summaryrefslogtreecommitdiffstats
path: root/llvm/lib/DebugInfo
diff options
context:
space:
mode:
authorPavel Labath <pavel@labath.sk>2019-11-08 15:24:11 +0100
committerPavel Labath <pavel@labath.sk>2019-11-20 16:24:11 +0100
commita03435ec8e219e236331780626351c74a95f1b6e (patch)
tree074adab5e4f138b92959ca31c408cbf4661254d4 /llvm/lib/DebugInfo
parentb80033ef6528ed868294ba0c1e18bfcf74597a1b (diff)
downloadbcm5719-llvm-a03435ec8e219e236331780626351c74a95f1b6e.tar.gz
bcm5719-llvm-a03435ec8e219e236331780626351c74a95f1b6e.zip
Recommit "[DWARF] Add an api to get "interpreted" location lists"
This recommits 089c0f581492cd6e2a3d2927be3fbf60ea2d7e62, which was reverted due to failing tests on big endian machines. It includes a fix which I believe (I don't have BE machine) should fix this issue. The fix consists of correcting the invocation DWARFYAML::EmitDebugSections, which was missing one (default) function arguments, and so didn't actually force the little-endian mode. The original commit message follows. 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')
-rw-r--r--llvm/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp15
-rw-r--r--llvm/lib/DebugInfo/DWARF/DWARFDie.cpp21
-rw-r--r--llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp24
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();
OpenPOWER on IntegriCloud