diff options
| author | Pavel Labath <pavel@labath.sk> | 2019-11-05 14:46:54 +0100 |
|---|---|---|
| committer | Pavel Labath <pavel@labath.sk> | 2019-11-15 13:38:00 +0100 |
| commit | 0908093977b2b80d00baa12f0b2f1424dde096fb (patch) | |
| tree | fb4b665cad7f163289f1caa963afeb501a880406 /llvm/lib | |
| parent | c953e061b410163bc54771f186176a92aac04008 (diff) | |
| download | bcm5719-llvm-0908093977b2b80d00baa12f0b2f1424dde096fb.tar.gz bcm5719-llvm-0908093977b2b80d00baa12f0b2f1424dde096fb.zip | |
DWARFDebugLoc(v4): Add an incremental parsing function
Summary:
This adds a visitLocationList function to the DWARF v4 location lists,
similar to what already exists for DWARF v5. It follows the approach
outlined in previous patches (D69672), where the parsed form is always
stored in the DWARF v5 format, which makes it easier for generic code to
be built on top of that. v4 location lists are "upgraded" during
parsing, and then this upgrade is undone while dumping.
Both "inline" and section-based dumping is rewritten to reuse the
existing "generic" location list dumper. This means that the output
format is consistent for all location lists (the only thing one needs to
implement is the function which prints the "raw" form of a location
list), and that debug_loc dumping correctly processes base address
selection entries, etc.
The previous existing debug_loc functionality (e.g.,
parseOneLocationList) is rewritten on top of the new API, but it is not
removed as there is still code which uses them. This will be done in
follow-up patches, after I build the API to access the "interpreted"
location lists in a generic way (as that is what those users really
want).
Reviewers: dblaikie, probinson, JDevlieghere, aprantl, SouraVX
Subscribers: hiraditya, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D69847
Diffstat (limited to 'llvm/lib')
| -rw-r--r-- | llvm/lib/DebugInfo/DWARF/DWARFContext.cpp | 13 | ||||
| -rw-r--r-- | llvm/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp | 149 | ||||
| -rw-r--r-- | llvm/lib/DebugInfo/DWARF/DWARFDie.cpp | 29 | ||||
| -rw-r--r-- | llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp | 10 | ||||
| -rw-r--r-- | llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp | 2 |
5 files changed, 99 insertions, 104 deletions
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp b/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp index 5a1668442fc..3fad575ff40 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp @@ -734,13 +734,14 @@ const DWARFDebugLoc *DWARFContext::getDebugLoc() { if (Loc) return Loc.get(); - Loc.reset(new DWARFDebugLoc); // Assume all units have the same address byte size. - if (getNumCompileUnits()) { - DWARFDataExtractor LocData(*DObj, DObj->getLocSection(), isLittleEndian(), - getUnitAtIndex(0)->getAddressByteSize()); - Loc->parse(LocData); - } + auto LocData = + getNumCompileUnits() + ? DWARFDataExtractor(*DObj, DObj->getLocSection(), isLittleEndian(), + getUnitAtIndex(0)->getAddressByteSize()) + : DWARFDataExtractor("", isLittleEndian(), 0); + Loc.reset(new DWARFDebugLoc(std::move(LocData))); + Loc->parse(); return Loc.get(); } diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp index f84de263a78..218bf381567 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp @@ -145,25 +145,6 @@ bool DWARFLocationTable::dumpLocationList(uint64_t *Offset, raw_ostream &OS, return true; } -void DWARFDebugLoc::LocationList::dump(raw_ostream &OS, uint64_t BaseAddress, - bool IsLittleEndian, - unsigned AddressSize, - const MCRegisterInfo *MRI, DWARFUnit *U, - DIDumpOptions DumpOpts, - unsigned Indent) const { - for (const Entry &E : Entries) { - OS << '\n'; - OS.indent(Indent); - OS << format("[0x%*.*" PRIx64 ", ", AddressSize * 2, AddressSize * 2, - BaseAddress + E.Begin); - OS << format(" 0x%*.*" PRIx64 ")", AddressSize * 2, AddressSize * 2, - BaseAddress + E.End); - OS << ": "; - - dumpExpression(OS, E.Loc, IsLittleEndian, AddressSize, MRI, U); - } -} - DWARFDebugLoc::LocationList const * DWARFDebugLoc::getLocationListAtOffset(uint64_t Offset) const { auto It = partition_point( @@ -173,74 +154,84 @@ DWARFDebugLoc::getLocationListAtOffset(uint64_t Offset) const { return nullptr; } -void DWARFDebugLoc::dump(raw_ostream &OS, const MCRegisterInfo *MRI, DIDumpOptions DumpOpts, - Optional<uint64_t> Offset) const { - auto DumpLocationList = [&](const LocationList &L) { - OS << format("0x%8.8" PRIx64 ": ", L.Offset); - L.dump(OS, 0, IsLittleEndian, AddressSize, MRI, nullptr, DumpOpts, 12); - OS << "\n"; - }; - - if (Offset) { - if (auto *L = getLocationListAtOffset(*Offset)) - DumpLocationList(*L); - return; - } - - for (const LocationList &L : Locations) { - DumpLocationList(L); - if (&L != &Locations.back()) +void DWARFDebugLoc::dump(raw_ostream &OS, const MCRegisterInfo *MRI, + DIDumpOptions DumpOpts, + Optional<uint64_t> DumpOffset) const { + auto BaseAddr = None; + unsigned Indent = 12; + if (DumpOffset) { + dumpLocationList(&*DumpOffset, OS, BaseAddr, MRI, nullptr, DumpOpts, + Indent); + } else { + uint64_t Offset = 0; + StringRef Separator; + bool CanContinue = true; + while (CanContinue && Data.isValidOffset(Offset)) { + OS << Separator; + Separator = "\n"; + + CanContinue = dumpLocationList(&Offset, OS, BaseAddr, MRI, nullptr, + DumpOpts, Indent); OS << '\n'; + } } } -Expected<DWARFDebugLoc::LocationList> -DWARFDebugLoc::parseOneLocationList(const DWARFDataExtractor &Data, - uint64_t *Offset) { - LocationList LL; - LL.Offset = *Offset; - AddressSize = Data.getAddressSize(); +Error DWARFDebugLoc::visitLocationList( + uint64_t *Offset, + function_ref<bool(const DWARFLocationEntry &)> Callback) const { DataExtractor::Cursor C(*Offset); - - // 2.6.2 Location Lists - // A location list entry consists of: while (true) { - Entry E; - - // 1. A beginning address offset. ... - E.Begin = Data.getRelocatedAddress(C); - - // 2. An ending address offset. ... - E.End = Data.getRelocatedAddress(C); + uint64_t Value0 = Data.getRelocatedAddress(C); + uint64_t Value1 = Data.getRelocatedAddress(C); - if (Error Err = C.takeError()) - return std::move(Err); + DWARFLocationEntry E; // The end of any given location list is marked by an end of list entry, // which consists of a 0 for the beginning address offset and a 0 for the - // ending address offset. - if (E.Begin == 0 && E.End == 0) { - *Offset = C.tell(); - return LL; - } - - if (E.Begin != (AddressSize == 4 ? -1U : -1ULL)) { + // ending address offset. A beginning offset of 0xff...f marks the base + // address selection entry. + if (Value0 == 0 && Value1 == 0) { + E.Kind = dwarf::DW_LLE_end_of_list; + } else if (Value0 == (Data.getAddressSize() == 4 ? -1U : -1ULL)) { + E.Kind = dwarf::DW_LLE_base_address; + E.Value0 = Value1; + } else { + E.Kind = dwarf::DW_LLE_offset_pair; + E.Value0 = Value0; + E.Value1 = Value1; unsigned Bytes = Data.getU16(C); // A single location description describing the location of the object... Data.getU8(C, E.Loc, Bytes); } - LL.Entries.push_back(std::move(E)); + if (!C) + return C.takeError(); + if (!Callback(E) || E.Kind == dwarf::DW_LLE_end_of_list) + break; } + *Offset = C.tell(); + return Error::success(); } -void DWARFDebugLoc::parse(const DWARFDataExtractor &data) { - IsLittleEndian = data.isLittleEndian(); - AddressSize = data.getAddressSize(); +Expected<DWARFDebugLoc::LocationList> +DWARFDebugLoc::parseOneLocationList(uint64_t *Offset) { + LocationList LL; + LL.Offset = *Offset; + + Error E = visitLocationList(Offset, [&](const DWARFLocationEntry &E) { + LL.Entries.push_back(E); + return true; + }); + if (E) + return std::move(E); + return std::move(LL); +} +void DWARFDebugLoc::parse() { uint64_t Offset = 0; - while (Offset < data.getData().size()) { - if (auto LL = parseOneLocationList(data, &Offset)) + while (Offset < Data.getData().size()) { + if (auto LL = parseOneLocationList(&Offset)) Locations.push_back(std::move(*LL)); else { logAllUnhandledErrors(LL.takeError(), WithColor::error()); @@ -249,6 +240,30 @@ void DWARFDebugLoc::parse(const DWARFDataExtractor &data) { } } +void DWARFDebugLoc::dumpRawEntry(const DWARFLocationEntry &Entry, + raw_ostream &OS, unsigned Indent) const { + uint64_t Value0, Value1; + switch (Entry.Kind) { + case dwarf::DW_LLE_base_address: + Value0 = Data.getAddressSize() == 4 ? -1U : -1ULL; + Value1 = Entry.Value0; + break; + case dwarf::DW_LLE_offset_pair: + Value0 = Entry.Value0; + Value1 = Entry.Value1; + break; + case dwarf::DW_LLE_end_of_list: + Value0 = Value1 = 0; + return; + default: + llvm_unreachable("Not possible in DWARF4!"); + } + OS << '\n'; + OS.indent(Indent); + OS << '(' << format_hex(Value0, 2 + Data.getAddressSize() * 2) << ", " + << format_hex(Value1, 2 + Data.getAddressSize() * 2) << ')'; +} + Error DWARFDebugLoclists::visitLocationList( uint64_t *Offset, function_ref<bool(const DWARFLocationEntry &)> F) const { diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp index abe63f2716a..49a7f7dc2a5 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp @@ -79,7 +79,6 @@ static void dumpLocation(raw_ostream &OS, DWARFFormValue &FormValue, DWARFUnit *U, unsigned Indent, DIDumpOptions DumpOpts) { DWARFContext &Ctx = U->getContext(); - const DWARFObject &Obj = Ctx.getDWARFObj(); const MCRegisterInfo *MRI = Ctx.getRegisterInfo(); if (FormValue.isFormClass(DWARFFormValue::FC_Block) || FormValue.isFormClass(DWARFFormValue::FC_Exprloc)) { @@ -97,32 +96,8 @@ static void dumpLocation(raw_ostream &OS, DWARFFormValue &FormValue, uint64_t Offset = *FormValue.getAsSectionOffset(); - if (const DWARFLocationTable *LT = U->getLocationTable()) { - LT->dumpLocationList(&Offset, OS, U->getBaseAddress(), MRI, U, LLDumpOpts, - Indent); - return; - } - - DWARFDebugLoc DebugLoc; - DWARFDataExtractor Data(Obj, *U->getLocSection(), Ctx.isLittleEndian(), - Obj.getAddressSize()); - - FormValue.dump(OS, DumpOpts); - OS << ": "; - - if (Expected<DWARFDebugLoc::LocationList> LL = - DebugLoc.parseOneLocationList(Data, &Offset)) { - uint64_t BaseAddr = 0; - if (Optional<object::SectionedAddress> BA = U->getBaseAddress()) - BaseAddr = BA->Address; - LL->dump(OS, BaseAddr, Ctx.isLittleEndian(), Obj.getAddressSize(), MRI, U, - LLDumpOpts, Indent); - } else { - OS << '\n'; - OS.indent(Indent); - OS << formatv("error extracting location list: {0}", - fmt_consume(LL.takeError())); - } + U->getLocationTable().dumpLocationList(&Offset, OS, U->getBaseAddress(), + MRI, U, LLDumpOpts, Indent); return; } diff --git a/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp b/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp index 81c7959f646..7f0ee660cd0 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp @@ -175,9 +175,9 @@ DWARFUnit::DWARFUnit(DWARFContext &DC, const DWARFSection &Section, const DWARFSection *AOS, const DWARFSection &LS, bool LE, bool IsDWO, const DWARFUnitVector &UnitVector) : Context(DC), InfoSection(Section), Header(Header), Abbrev(DA), - RangeSection(RS), LocSection(LocSection), LineSection(LS), - StringSection(SS), StringOffsetSection(SOS), AddrOffsetSection(AOS), - isLittleEndian(LE), IsDWO(IsDWO), UnitVector(UnitVector) { + RangeSection(RS), LineSection(LS), StringSection(SS), + StringOffsetSection(SOS), AddrOffsetSection(AOS), isLittleEndian(LE), + IsDWO(IsDWO), UnitVector(UnitVector) { clear(); if (IsDWO) { // If we are reading a package file, we need to adjust the location list @@ -195,6 +195,10 @@ DWARFUnit::DWARFUnit(DWARFContext &DC, const DWARFSection &Section, Context.getDWARFObj().getLoclistsSection(), isLittleEndian, getAddressByteSize()), Header.getVersion()); + } else { + LocTable = std::make_unique<DWARFDebugLoc>( + DWARFDataExtractor(Context.getDWARFObj(), *LocSection, isLittleEndian, + getAddressByteSize())); } } diff --git a/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp b/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp index bf499b6ee09..357cdb299a2 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp @@ -1302,7 +1302,7 @@ static bool isVariableIndexable(const DWARFDie &Die, DWARFContext &DCtx) { if (const DWARFDebugLoc *DebugLoc = DCtx.getDebugLoc()) { if (const DWARFDebugLoc::LocationList *LocList = DebugLoc->getLocationListAtOffset(*Offset)) { - if (any_of(LocList->Entries, [&](const DWARFDebugLoc::Entry &E) { + if (any_of(LocList->Entries, [&](const DWARFLocationEntry &E) { return ContainsInterestingOperators(E.Loc); })) return true; |

