[llvm-dwarfdump] - Add the support of parsing .debug_loclists.
This teaches llvm-dwarfdump to dump the content of .debug_loclists sections.
It converts the DWARFDebugLocDWO class to DWARFDebugLoclists,
teaches llvm-dwarfdump about .debug_loclists section and
adds the implementation for parsing the DW_LLE_offset_pair entries.
Differential revision: https://reviews.llvm.org/D53364
llvm-svn: 344895
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp b/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp
index 18ec847..1f37538 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp
@@ -292,6 +292,27 @@
}
}
+static void dumpLoclistsSection(raw_ostream &OS, DIDumpOptions DumpOpts,
+ DWARFDataExtractor Data,
+ const MCRegisterInfo *MRI,
+ Optional<uint64_t> DumpOffset) {
+ uint32_t Offset = 0;
+ DWARFDebugLoclists Loclists;
+
+ DWARFListTableHeader Header(".debug_loclists", "locations");
+ if (Error E = Header.extract(Data, &Offset)) {
+ WithColor::error() << toString(std::move(E)) << '\n';
+ return;
+ }
+
+ Header.dump(OS, DumpOpts);
+ DataExtractor LocData(Data.getData().drop_front(Offset),
+ Data.isLittleEndian(), Header.getAddrSize());
+
+ Loclists.parse(LocData);
+ Loclists.dump(OS, 0, MRI, DumpOffset);
+}
+
void DWARFContext::dump(
raw_ostream &OS, DIDumpOptions DumpOpts,
std::array<Optional<uint64_t>, DIDT_ID_Count> DumpOffsets) {
@@ -366,9 +387,15 @@
DObj->getLocSection().Data)) {
getDebugLoc()->dump(OS, getRegisterInfo(), DumpOffset);
}
+ if (shouldDump(Explicit, ".debug_loclists", DIDT_ID_DebugLoclists,
+ DObj->getLoclistsSection().Data)) {
+ DWARFDataExtractor Data(*DObj, DObj->getLoclistsSection(), isLittleEndian(),
+ 0);
+ dumpLoclistsSection(OS, DumpOpts, Data, getRegisterInfo(), DumpOffset);
+ }
if (shouldDump(ExplicitDWO, ".debug_loc.dwo", DIDT_ID_DebugLoc,
DObj->getLocDWOSection().Data)) {
- getDebugLocDWO()->dump(OS, getRegisterInfo(), DumpOffset);
+ getDebugLocDWO()->dump(OS, 0, getRegisterInfo(), DumpOffset);
}
if (shouldDump(Explicit, ".debug_frame", DIDT_ID_DebugFrame,
@@ -696,11 +723,11 @@
return Loc.get();
}
-const DWARFDebugLocDWO *DWARFContext::getDebugLocDWO() {
+const DWARFDebugLoclists *DWARFContext::getDebugLocDWO() {
if (LocDWO)
return LocDWO.get();
- LocDWO.reset(new DWARFDebugLocDWO());
+ LocDWO.reset(new DWARFDebugLoclists());
// Assume all compile units have the same address byte size.
// FIXME: We don't need AddressSize for split DWARF since relocatable
// addresses cannot appear there. At the moment DWARFExpression requires it.
@@ -1213,6 +1240,7 @@
DWARFSectionMap InfoSection;
DWARFSectionMap LocSection;
+ DWARFSectionMap LocListsSection;
DWARFSectionMap LineSection;
DWARFSectionMap RangeSection;
DWARFSectionMap RnglistsSection;
@@ -1234,6 +1262,7 @@
return StringSwitch<DWARFSectionMap *>(Name)
.Case("debug_info", &InfoSection)
.Case("debug_loc", &LocSection)
+ .Case("debug_loclists", &LocListsSection)
.Case("debug_line", &LineSection)
.Case("debug_str_offsets", &StringOffsetSection)
.Case("debug_ranges", &RangeSection)
@@ -1529,6 +1558,7 @@
StringRef getAbbrevSection() const override { return AbbrevSection; }
const DWARFSection &getLocSection() const override { return LocSection; }
+ const DWARFSection &getLoclistsSection() const override { return LocListsSection; }
StringRef getARangeSection() const override { return ARangeSection; }
StringRef getDebugFrameSection() const override { return DebugFrameSection; }
StringRef getEHFrameSection() const override { return EHFrameSection; }
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp
index 617b914..bfcf799 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp
@@ -144,24 +144,39 @@
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) {
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);
+ E.Value1 = Data.getU32(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);
@@ -174,7 +189,7 @@
return LL;
}
-void DWARFDebugLocDWO::parse(DataExtractor data) {
+void DWARFDebugLoclists::parse(DataExtractor data) {
IsLittleEndian = data.isLittleEndian();
AddressSize = data.getAddressSize();
@@ -187,8 +202,8 @@
}
}
-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 +212,46 @@
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%8.8x, 0x%8.8x): ", E.Value0, E.Value0 + E.Value1);
+ break;
+ case dwarf::DW_LLE_offset_pair:
+ OS << '\n';
+ OS.indent(Indent);
+ OS << format("[0x%8.8x, 0x%8.8x): ", BaseAddr + E.Value0,
+ 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";
};
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp
index b441365..76430b4 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp
@@ -102,7 +102,7 @@
FormValue.dump(OS, DumpOpts);
if (FormValue.isFormClass(DWARFFormValue::FC_SectionOffset)) {
uint32_t Offset = *FormValue.getAsSectionOffset();
- if (!U->isDWOUnit()) {
+ if (!U->isDWOUnit() && !U->getLocSection()->Data.empty()) {
DWARFDebugLoc DebugLoc;
DWARFDataExtractor Data(Obj, *U->getLocSection(), Ctx.isLittleEndian(),
Obj.getAddressSize());
@@ -115,11 +115,23 @@
Indent);
} else
OS << "error extracting location list.";
- } else {
- DataExtractor Data(U->getLocSectionData(), Ctx.isLittleEndian(), 0);
- auto LL = DWARFDebugLocDWO::parseOneLocationList(Data, &Offset);
+ return;
+ }
+
+ StringRef LoclistsSectionData =
+ U->isDWOUnit() ? U->getLocSectionData() : Obj.getLoclistsSection().Data;
+ if (!LoclistsSectionData.empty()) {
+ DataExtractor Data(LoclistsSectionData, Ctx.isLittleEndian(),
+ Obj.getAddressSize());
+ auto LL = DWARFDebugLoclists::parseOneLocationList(Data, &Offset);
+
+ uint64_t BaseAddr = 0;
+ if (Optional<SectionedAddress> BA = U->getBaseAddress())
+ BaseAddr = BA->Address;
+
if (LL)
- LL->dump(OS, Ctx.isLittleEndian(), Obj.getAddressSize(), MRI, Indent);
+ LL->dump(OS, BaseAddr, Ctx.isLittleEndian(), Obj.getAddressSize(), MRI,
+ Indent);
else
OS << "error extracting location list.";
}