aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2022-07-04 19:20:19 +0000
committerDimitry Andric <dim@FreeBSD.org>2023-02-08 19:02:26 +0000
commit81ad626541db97eb356e2c1d4a20eb2a26a766ab (patch)
tree311b6a8987c32b1e1dcbab65c54cfac3fdb56175 /contrib/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp
parent5fff09660e06a66bed6482da9c70df328e16bbb6 (diff)
parent145449b1e420787bb99721a429341fa6be3adfb6 (diff)
Diffstat (limited to 'contrib/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp')
-rw-r--r--contrib/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp119
1 files changed, 115 insertions, 4 deletions
diff --git a/contrib/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp b/contrib/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp
index eed0a60ec75e..74667fcb92bc 100644
--- a/contrib/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp
+++ b/contrib/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp
@@ -9,15 +9,23 @@
#include "llvm/DebugInfo/DWARF/DWARFUnit.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/BinaryFormat/Dwarf.h"
#include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h"
#include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h"
#include "llvm/DebugInfo/DWARF/DWARFContext.h"
#include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h"
#include "llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h"
+#include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h"
+#include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h"
#include "llvm/DebugInfo/DWARF/DWARFDebugRnglists.h"
#include "llvm/DebugInfo/DWARF/DWARFDie.h"
+#include "llvm/DebugInfo/DWARF/DWARFExpression.h"
#include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
+#include "llvm/DebugInfo/DWARF/DWARFListTable.h"
+#include "llvm/DebugInfo/DWARF/DWARFObject.h"
+#include "llvm/DebugInfo/DWARF/DWARFSection.h"
#include "llvm/DebugInfo/DWARF/DWARFTypeUnit.h"
+#include "llvm/Object/ObjectFile.h"
#include "llvm/Support/DataExtractor.h"
#include "llvm/Support/Errc.h"
#include "llvm/Support/Path.h"
@@ -25,7 +33,6 @@
#include <cassert>
#include <cstddef>
#include <cstdint>
-#include <cstdio>
#include <utility>
#include <vector>
@@ -79,7 +86,14 @@ void DWARFUnitVector::addUnitsImpl(
if (!IndexEntry && IsDWO) {
const DWARFUnitIndex &Index = getDWARFUnitIndex(
Context, Header.isTypeUnit() ? DW_SECT_EXT_TYPES : DW_SECT_INFO);
- IndexEntry = Index.getFromOffset(Header.getOffset());
+ if (Index) {
+ if (Header.isTypeUnit())
+ IndexEntry = Index.getFromHash(Header.getTypeHash());
+ else if (auto DWOId = Header.getDWOId())
+ IndexEntry = Index.getFromHash(*DWOId);
+ }
+ if (!IndexEntry)
+ IndexEntry = Index.getFromOffset(Header.getOffset());
}
if (IndexEntry && !Header.applyIndexEntry(IndexEntry))
return nullptr;
@@ -366,6 +380,9 @@ void DWARFUnit::clear() {
AddrOffsetSectionBase = None;
SU = nullptr;
clearDIEs(false);
+ AddrDieMap.clear();
+ if (DWO)
+ DWO->clear();
DWO.reset();
}
@@ -407,7 +424,7 @@ void DWARFUnit::extractDIEsToVector(
assert((Parents.back() == UINT32_MAX || Parents.back() <= Dies.size()) &&
"Wrong parent index");
- // Extract die. Stop if any error occured.
+ // Extract die. Stop if any error occurred.
if (!DIE.extractFast(*this, &DIEOffset, DebugInfoData, NextCUOffset,
Parents.back()))
break;
@@ -607,7 +624,7 @@ bool DWARFUnit::parseDWO() {
DWO->setAddrOffsetSection(AddrOffsetSection, *AddrOffsetSectionBase);
if (getVersion() == 4) {
auto DWORangesBase = UnitDie.getRangesBaseAttribute();
- DWO->setRangesSection(RangeSection, DWORangesBase.getValueOr(0));
+ DWO->setRangesSection(RangeSection, DWORangesBase.value_or(0));
}
return true;
@@ -735,6 +752,100 @@ DWARFDie DWARFUnit::getSubroutineForAddress(uint64_t Address) {
return R->second.second;
}
+void DWARFUnit::updateVariableDieMap(DWARFDie Die) {
+ for (DWARFDie Child : Die) {
+ if (isType(Child.getTag()))
+ continue;
+ updateVariableDieMap(Child);
+ }
+
+ if (Die.getTag() != DW_TAG_variable)
+ return;
+
+ Expected<DWARFLocationExpressionsVector> Locations =
+ Die.getLocations(DW_AT_location);
+ if (!Locations) {
+ // Missing DW_AT_location is fine here.
+ consumeError(Locations.takeError());
+ return;
+ }
+
+ uint64_t Address = UINT64_MAX;
+
+ for (const DWARFLocationExpression &Location : *Locations) {
+ uint8_t AddressSize = getAddressByteSize();
+ DataExtractor Data(Location.Expr, /*IsLittleEndian=*/true, AddressSize);
+ DWARFExpression Expr(Data, AddressSize);
+ auto It = Expr.begin();
+ if (It == Expr.end())
+ continue;
+
+ // Match exactly the main sequence used to describe global variables:
+ // `DW_OP_addr[x] [+ DW_OP_plus_uconst]`. Currently, this is the sequence
+ // that LLVM produces for DILocalVariables and DIGlobalVariables. If, in
+ // future, the DWARF producer (`DwarfCompileUnit::addLocationAttribute()` is
+ // a good starting point) is extended to use further expressions, this code
+ // needs to be updated.
+ uint64_t LocationAddr;
+ if (It->getCode() == dwarf::DW_OP_addr) {
+ LocationAddr = It->getRawOperand(0);
+ } else if (It->getCode() == dwarf::DW_OP_addrx) {
+ uint64_t DebugAddrOffset = It->getRawOperand(0);
+ if (auto Pointer = getAddrOffsetSectionItem(DebugAddrOffset)) {
+ LocationAddr = Pointer->Address;
+ }
+ } else {
+ continue;
+ }
+
+ // Read the optional 2nd operand, a DW_OP_plus_uconst.
+ if (++It != Expr.end()) {
+ if (It->getCode() != dwarf::DW_OP_plus_uconst)
+ continue;
+
+ LocationAddr += It->getRawOperand(0);
+
+ // Probe for a 3rd operand, if it exists, bail.
+ if (++It != Expr.end())
+ continue;
+ }
+
+ Address = LocationAddr;
+ break;
+ }
+
+ // Get the size of the global variable. If all else fails (i.e. the global has
+ // no type), then we use a size of one to still allow symbolization of the
+ // exact address.
+ uint64_t GVSize = 1;
+ if (DWARFDie BaseType = Die.getAttributeValueAsReferencedDie(DW_AT_type))
+ if (Optional<uint64_t> Size = Die.getTypeSize(getAddressByteSize()))
+ GVSize = *Size;
+
+ if (Address != UINT64_MAX)
+ VariableDieMap[Address] = {Address + GVSize, Die};
+}
+
+DWARFDie DWARFUnit::getVariableForAddress(uint64_t Address) {
+ extractDIEsIfNeeded(false);
+
+ auto RootDie = getUnitDIE();
+
+ auto RootLookup = RootsParsedForVariables.insert(RootDie.getOffset());
+ if (RootLookup.second)
+ updateVariableDieMap(RootDie);
+
+ auto R = VariableDieMap.upper_bound(Address);
+ if (R == VariableDieMap.begin())
+ return DWARFDie();
+
+ // upper_bound's previous item contains Address.
+ --R;
+ if (Address >= R->second.first)
+ return DWARFDie();
+ return R->second.second;
+}
+
void
DWARFUnit::getInlinedChainForAddress(uint64_t Address,
SmallVectorImpl<DWARFDie> &InlinedChain) {