summaryrefslogtreecommitdiff
path: root/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2019-01-19 10:01:25 +0000
committerDimitry Andric <dim@FreeBSD.org>2019-01-19 10:01:25 +0000
commitd8e91e46262bc44006913e6796843909f1ac7bcd (patch)
tree7d0c143d9b38190e0fa0180805389da22cd834c5 /lib/DebugInfo/DWARF/DWARFDebugLoc.cpp
parentb7eb8e35e481a74962664b63dfb09483b200209a (diff)
Notes
Diffstat (limited to 'lib/DebugInfo/DWARF/DWARFDebugLoc.cpp')
-rw-r--r--lib/DebugInfo/DWARF/DWARFDebugLoc.cpp105
1 files changed, 77 insertions, 28 deletions
diff --git a/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp b/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp
index 617b914ecce9..f8b5ff6ec8fb 100644
--- a/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp
+++ b/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp
@@ -124,7 +124,7 @@ DWARFDebugLoc::parseOneLocationList(DWARFDataExtractor Data, unsigned *Offset) {
StringRef str = Data.getData().substr(*Offset, Bytes);
*Offset += Bytes;
E.Loc.reserve(str.size());
- std::copy(str.begin(), str.end(), std::back_inserter(E.Loc));
+ llvm::copy(str, std::back_inserter(E.Loc));
LL.Entries.push_back(std::move(E));
}
}
@@ -144,51 +144,74 @@ void DWARFDebugLoc::parse(const DWARFDataExtractor &data) {
WithColor::error() << "failed to consume entire .debug_loc section\n";
}
-Optional<DWARFDebugLocDWO::LocationList>
-DWARFDebugLocDWO::parseOneLocationList(DataExtractor Data, unsigned *Offset) {
+Optional<DWARFDebugLoclists::LocationList>
+DWARFDebugLoclists::parseOneLocationList(DataExtractor Data, unsigned *Offset,
+ unsigned Version) {
LocationList LL;
LL.Offset = *Offset;
// dwarf::DW_LLE_end_of_list_entry is 0 and indicates the end of the list.
while (auto Kind =
static_cast<dwarf::LocationListEntry>(Data.getU8(Offset))) {
- if (Kind != dwarf::DW_LLE_startx_length) {
+
+ Entry E;
+ E.Kind = Kind;
+ switch (Kind) {
+ case dwarf::DW_LLE_startx_length:
+ E.Value0 = Data.getULEB128(Offset);
+ // Pre-DWARF 5 has different interpretation of the length field. We have
+ // to support both pre- and standartized styles for the compatibility.
+ if (Version < 5)
+ E.Value1 = Data.getU32(Offset);
+ else
+ E.Value1 = Data.getULEB128(Offset);
+ break;
+ case dwarf::DW_LLE_start_length:
+ E.Value0 = Data.getAddress(Offset);
+ E.Value1 = Data.getULEB128(Offset);
+ break;
+ case dwarf::DW_LLE_offset_pair:
+ E.Value0 = Data.getULEB128(Offset);
+ E.Value1 = Data.getULEB128(Offset);
+ break;
+ case dwarf::DW_LLE_base_address:
+ E.Value0 = Data.getAddress(Offset);
+ break;
+ default:
WithColor::error() << "dumping support for LLE of kind " << (int)Kind
<< " not implemented\n";
return None;
}
- Entry E;
- E.Start = Data.getULEB128(Offset);
- E.Length = Data.getU32(Offset);
-
- unsigned Bytes = Data.getU16(Offset);
- // A single location description describing the location of the object...
- StringRef str = Data.getData().substr(*Offset, Bytes);
- *Offset += Bytes;
- E.Loc.resize(str.size());
- std::copy(str.begin(), str.end(), E.Loc.begin());
+ if (Kind != dwarf::DW_LLE_base_address) {
+ unsigned Bytes = Data.getU16(Offset);
+ // A single location description describing the location of the object...
+ StringRef str = Data.getData().substr(*Offset, Bytes);
+ *Offset += Bytes;
+ E.Loc.resize(str.size());
+ llvm::copy(str, E.Loc.begin());
+ }
LL.Entries.push_back(std::move(E));
}
return LL;
}
-void DWARFDebugLocDWO::parse(DataExtractor data) {
+void DWARFDebugLoclists::parse(DataExtractor data, unsigned Version) {
IsLittleEndian = data.isLittleEndian();
AddressSize = data.getAddressSize();
uint32_t Offset = 0;
while (data.isValidOffset(Offset)) {
- if (auto LL = parseOneLocationList(data, &Offset))
+ if (auto LL = parseOneLocationList(data, &Offset, Version))
Locations.push_back(std::move(*LL));
else
return;
}
}
-DWARFDebugLocDWO::LocationList const *
-DWARFDebugLocDWO::getLocationListAtOffset(uint64_t Offset) const {
+DWARFDebugLoclists::LocationList const *
+DWARFDebugLoclists::getLocationListAtOffset(uint64_t Offset) const {
auto It = std::lower_bound(
Locations.begin(), Locations.end(), Offset,
[](const LocationList &L, uint64_t Offset) { return L.Offset < Offset; });
@@ -197,23 +220,49 @@ DWARFDebugLocDWO::getLocationListAtOffset(uint64_t Offset) const {
return nullptr;
}
-void DWARFDebugLocDWO::LocationList::dump(raw_ostream &OS, bool IsLittleEndian,
- unsigned AddressSize,
- const MCRegisterInfo *MRI,
- unsigned Indent) const {
+void DWARFDebugLoclists::LocationList::dump(raw_ostream &OS, uint64_t BaseAddr,
+ bool IsLittleEndian,
+ unsigned AddressSize,
+ const MCRegisterInfo *MRI,
+ unsigned Indent) const {
for (const Entry &E : Entries) {
- OS << '\n';
- OS.indent(Indent);
- OS << "Addr idx " << E.Start << " (w/ length " << E.Length << "): ";
+ switch (E.Kind) {
+ case dwarf::DW_LLE_startx_length:
+ OS << '\n';
+ OS.indent(Indent);
+ OS << "Addr idx " << E.Value0 << " (w/ length " << E.Value1 << "): ";
+ break;
+ case dwarf::DW_LLE_start_length:
+ OS << '\n';
+ OS.indent(Indent);
+ OS << format("[0x%*.*" PRIx64 ", 0x%*.*" PRIx64 "): ", AddressSize * 2,
+ AddressSize * 2, E.Value0, AddressSize * 2, AddressSize * 2,
+ E.Value0 + E.Value1);
+ break;
+ case dwarf::DW_LLE_offset_pair:
+ OS << '\n';
+ OS.indent(Indent);
+ OS << format("[0x%*.*" PRIx64 ", 0x%*.*" PRIx64 "): ", AddressSize * 2,
+ AddressSize * 2, BaseAddr + E.Value0, AddressSize * 2,
+ AddressSize * 2, BaseAddr + E.Value1);
+ break;
+ case dwarf::DW_LLE_base_address:
+ BaseAddr = E.Value0;
+ break;
+ default:
+ llvm_unreachable("unreachable locations list kind");
+ }
+
dumpExpression(OS, E.Loc, IsLittleEndian, AddressSize, MRI);
}
}
-void DWARFDebugLocDWO::dump(raw_ostream &OS, const MCRegisterInfo *MRI,
- Optional<uint64_t> Offset) const {
+void DWARFDebugLoclists::dump(raw_ostream &OS, uint64_t BaseAddr,
+ const MCRegisterInfo *MRI,
+ Optional<uint64_t> Offset) const {
auto DumpLocationList = [&](const LocationList &L) {
OS << format("0x%8.8x: ", L.Offset);
- L.dump(OS, IsLittleEndian, AddressSize, MRI, /*Indent=*/12);
+ L.dump(OS, BaseAddr, IsLittleEndian, AddressSize, MRI, /*Indent=*/12);
OS << "\n\n";
};