diff options
author | Pavel Labath <pavel@labath.sk> | 2019-11-08 15:24:11 +0100 |
---|---|---|
committer | Pavel Labath <pavel@labath.sk> | 2019-11-20 13:25:18 +0100 |
commit | 089c0f581492cd6e2a3d2927be3fbf60ea2d7e62 (patch) | |
tree | c99b6523359271ad380b5b039af76805b7dab1dc /llvm/lib/DebugInfo/DWARF | |
parent | 979592a6f735a7111ba2c3a19e5ef3e8d336e01a (diff) | |
download | bcm5719-llvm-089c0f581492cd6e2a3d2927be3fbf60ea2d7e62.tar.gz bcm5719-llvm-089c0f581492cd6e2a3d2927be3fbf60ea2d7e62.zip |
[DWARF] Add an api to get "interpreted" location lists
Summary:
This patch adds DWARFDie::getLocations, which returns the location
expressions for a given attribute (typically DW_AT_location). It handles
both "inline" locations and references to the external location list
sections (currently only of the DW_FORM_sec_offset type). It is
implemented on top of DWARFUnit::findLoclistFromOffset, which is also
added in this patch. I tried to make their signatures similar to the
equivalent range list functionality.
The actual location list interpretation logic is in
DWARFLocationTable::visitAbsoluteLocationList. This part is not
equivalent to the range list code, but this deviation is motivated by a
desire to reuse the same location list parsing code within lldb.
The functionality is tested via a c++ unit test of the DWARFDie API.
Reviewers: dblaikie, JDevlieghere, SouraVX
Subscribers: mgorny, hiraditya, cmtice, probinson, llvm-commits, aprantl
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D70394
Diffstat (limited to 'llvm/lib/DebugInfo/DWARF')
-rw-r--r-- | llvm/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp | 15 | ||||
-rw-r--r-- | llvm/lib/DebugInfo/DWARF/DWARFDie.cpp | 21 | ||||
-rw-r--r-- | llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp | 24 |
3 files changed, 60 insertions, 0 deletions
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp index 1af51a85d18..8b84822914d 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp @@ -151,6 +151,21 @@ bool DWARFLocationTable::dumpLocationList(uint64_t *Offset, raw_ostream &OS, return true; } +Error DWARFLocationTable::visitAbsoluteLocationList( + uint64_t Offset, Optional<SectionedAddress> BaseAddr, + std::function<Optional<SectionedAddress>(uint32_t)> LookupAddr, + function_ref<bool(Expected<DWARFLocationExpression>)> Callback) const { + DWARFLocationInterpreter Interp(BaseAddr, std::move(LookupAddr)); + return visitLocationList(&Offset, [&](const DWARFLocationEntry &E) { + Expected<Optional<DWARFLocationExpression>> Loc = Interp.Interpret(E); + if (!Loc) + return Callback(Loc.takeError()); + if (*Loc) + return Callback(**Loc); + return true; + }); +} + DWARFDebugLoc::LocationList const * DWARFDebugLoc::getLocationListAtOffset(uint64_t Offset) const { auto It = partition_point( diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp index a11865e048c..6cf30270539 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp @@ -486,6 +486,27 @@ bool DWARFDie::addressRangeContainsAddress(const uint64_t Address) const { return false; } +Expected<DWARFLocationExpressionsVector> +DWARFDie::getLocations(dwarf::Attribute Attr) const { + Optional<DWARFFormValue> Location = find(Attr); + if (!Location) + return createStringError(inconvertibleErrorCode(), "No %s", + dwarf::AttributeString(Attr).data()); + + if (Optional<uint64_t> Off = Location->getAsSectionOffset()) + return U->findLoclistFromOffset(*Off); + + if (Optional<ArrayRef<uint8_t>> Expr = Location->getAsBlock()) { + return DWARFLocationExpressionsVector{ + DWARFLocationExpression{None, to_vector<4>(*Expr)}}; + } + + return createStringError( + inconvertibleErrorCode(), "Unsupported %s encoding: %s", + dwarf::AttributeString(Attr).data(), + dwarf::FormEncodingString(Location->getForm()).data()); +} + const char *DWARFDie::getSubroutineName(DINameKind Kind) const { if (!isSubroutineDIE()) return nullptr; diff --git a/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp b/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp index 2eb7d2f945a..e5d33e13644 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp @@ -637,6 +637,30 @@ Expected<DWARFAddressRangesVector> DWARFUnit::collectAddressRanges() { return *CUDIERangesOrError; } +Expected<DWARFLocationExpressionsVector> +DWARFUnit::findLoclistFromOffset(uint64_t Offset) { + DWARFLocationExpressionsVector Result; + + Error InterpretationError = Error::success(); + + Error ParseError = getLocationTable().visitAbsoluteLocationList( + Offset, getBaseAddress(), + [this](uint32_t Index) { return getAddrOffsetSectionItem(Index); }, + [&](Expected<DWARFLocationExpression> L) { + if (L) + Result.push_back(std::move(*L)); + else + InterpretationError = + joinErrors(L.takeError(), std::move(InterpretationError)); + return !InterpretationError; + }); + + if (ParseError || InterpretationError) + return joinErrors(std::move(ParseError), std::move(InterpretationError)); + + return Result; +} + void DWARFUnit::updateAddressDieMap(DWARFDie Die) { if (Die.isSubroutineDIE()) { auto DIERangesOrError = Die.getAddressRanges(); |