[llvm] bd0dd27 - [DWARFLinker][DWARFv5] Add handling of DW_OP_addrx and DW_OP_constx expression operands.
Alexey Lapshin via llvm-commits
llvm-commits at lists.llvm.org
Tue May 16 10:27:58 PDT 2023
Author: Alexey Lapshin
Date: 2023-05-16T19:27:16+02:00
New Revision: bd0dd27bb5be0fbf60c1b2a4ce15188812388574
URL: https://github.com/llvm/llvm-project/commit/bd0dd27bb5be0fbf60c1b2a4ce15188812388574
DIFF: https://github.com/llvm/llvm-project/commit/bd0dd27bb5be0fbf60c1b2a4ce15188812388574.diff
LOG: [DWARFLinker][DWARFv5] Add handling of DW_OP_addrx and DW_OP_constx expression operands.
This patch adds handling of DW_OP_addrx and DW_OP_constx expression operands.
In --update case these operands are preserved as is. Otherwise they are
converted into the DW_OP_addr and DW_OP_const[*]u correspondingly.
Differential Revision: https://reviews.llvm.org/D147066
Added:
llvm/test/tools/dsymutil/Inputs/dwarf5-dw-op-addrx.o
llvm/test/tools/dsymutil/X86/dwarf5-dw-op-addrx.test
llvm/test/tools/llvm-dwarfutil/ELF/X86/dwarf5-addresses.test
Modified:
llvm/include/llvm/DWARFLinker/DWARFLinker.h
llvm/include/llvm/DWARFLinker/DWARFLinkerCompileUnit.h
llvm/include/llvm/DWARFLinkerParallel/AddressesMap.h
llvm/lib/DWARFLinker/DWARFLinker.cpp
llvm/lib/DWARFLinker/DWARFLinkerCompileUnit.cpp
llvm/lib/DebugInfo/DWARF/DWARFExpression.cpp
llvm/test/tools/dsymutil/X86/op-convert-offset.test
llvm/tools/dsymutil/DwarfLinkerForBinary.cpp
llvm/tools/dsymutil/DwarfLinkerForBinary.h
llvm/tools/llvm-dwarfutil/DebugInfoLinker.cpp
Removed:
llvm/test/tools/llvm-dwarfutil/ELF/X86/dwarf5-addrx.test
################################################################################
diff --git a/llvm/include/llvm/DWARFLinker/DWARFLinker.h b/llvm/include/llvm/DWARFLinker/DWARFLinker.h
index 4d519479fab6e..d94e31d5e6cd4 100644
--- a/llvm/include/llvm/DWARFLinker/DWARFLinker.h
+++ b/llvm/include/llvm/DWARFLinker/DWARFLinker.h
@@ -17,6 +17,7 @@
#include "llvm/DebugInfo/DWARF/DWARFDebugLine.h"
#include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h"
#include "llvm/DebugInfo/DWARF/DWARFDie.h"
+#include "llvm/DebugInfo/DWARF/DWARFExpression.h"
#include <map>
namespace llvm {
@@ -48,14 +49,16 @@ class AddressesMap {
/// section.
virtual bool hasValidRelocs() = 0;
- /// Checks that the specified variable \p DIE references the live code
- /// section and returns the relocation adjustment value (to get the linked
- /// address this value might be added to the source variable address).
- /// Allowed kinds of input DIE: DW_TAG_variable, DW_TAG_constant.
+ /// Checks that the specified DWARF expression operand \p Op references live
+ /// code section and returns the relocation adjustment value (to get the
+ /// linked address this value might be added to the source expression operand
+ /// address).
/// \returns relocation adjustment value or std::nullopt if there is no
/// corresponding live address.
virtual std::optional<int64_t>
- getVariableRelocAdjustment(const DWARFDie &DIE) = 0;
+ getExprOpAddressRelocAdjustment(DWARFUnit &U,
+ const DWARFExpression::Operation &Op,
+ uint64_t StartOffset, uint64_t EndOffset) = 0;
/// Checks that the specified subprogram \p DIE references the live code
/// section and returns the relocation adjustment value (to get the linked
@@ -572,6 +575,12 @@ class DWARFLinker {
CompileUnit &Unit, CompileUnit::DIEInfo &MyInfo,
unsigned Flags);
+ /// This function checks whether variable has DWARF expression containing
+ /// operation referencing live address(f.e. DW_OP_addr, DW_OP_addrx...).
+ /// \returns relocation adjustment value if live address is referenced.
+ std::optional<int64_t> getVariableRelocAdjustment(AddressesMap &RelocMgr,
+ const DWARFDie &DIE);
+
/// Check if a variable describing DIE should be kept.
/// \returns updated TraversalFlags.
unsigned shouldKeepVariableDIE(AddressesMap &RelocMgr, const DWARFDie &DIE,
@@ -703,14 +712,16 @@ class DWARFLinker {
/// Clone a DWARF expression that may be referencing another DIE.
void cloneExpression(DataExtractor &Data, DWARFExpression Expression,
const DWARFFile &File, CompileUnit &Unit,
- SmallVectorImpl<uint8_t> &OutputBuffer);
+ SmallVectorImpl<uint8_t> &OutputBuffer,
+ int64_t AddrRelocAdjustment);
/// Clone an attribute referencing another DIE and add
/// it to \p Die.
/// \returns the size of the new attribute.
- unsigned cloneBlockAttribute(DIE &Die, const DWARFFile &File,
- CompileUnit &Unit, AttributeSpec AttrSpec,
- const DWARFFormValue &Val, unsigned AttrSize,
+ unsigned cloneBlockAttribute(DIE &Die, const DWARFDie &InputDIE,
+ const DWARFFile &File, CompileUnit &Unit,
+ AttributeSpec AttrSpec,
+ const DWARFFormValue &Val,
bool IsLittleEndian);
/// Clone an attribute referencing another DIE and add
@@ -761,8 +772,9 @@ class DWARFLinker {
/// .debug_rnglists) for \p Unit, patch the attributes referencing it.
void generateUnitRanges(CompileUnit &Unit, const DWARFFile &File) const;
- using ExpressionHandlerRef = function_ref<void(SmallVectorImpl<uint8_t> &,
- SmallVectorImpl<uint8_t> &)>;
+ using ExpressionHandlerRef =
+ function_ref<void(SmallVectorImpl<uint8_t> &, SmallVectorImpl<uint8_t> &,
+ int64_t AddrRelocAdjustment)>;
/// Compute and emit debug locations (.debug_loc, .debug_loclists)
/// for \p Unit, patch the attributes referencing it.
diff --git a/llvm/include/llvm/DWARFLinker/DWARFLinkerCompileUnit.h b/llvm/include/llvm/DWARFLinker/DWARFLinkerCompileUnit.h
index cfbd13414f703..3736033f3a046 100644
--- a/llvm/include/llvm/DWARFLinker/DWARFLinkerCompileUnit.h
+++ b/llvm/include/llvm/DWARFLinker/DWARFLinkerCompileUnit.h
@@ -23,12 +23,22 @@ class DeclContext;
/// linked address.
using RangesTy = AddressRangesMap;
-// FIXME: Delete this structure.
+// This structure keeps patch for the attribute and, optionally,
+// the value of relocation which should be applied. Currently,
+// only location attribute needs to have relocation: either to the
+// function ranges if location attribute is of type 'loclist',
+// either to the operand of DW_OP_addr/DW_OP_addrx if location attribute
+// is of type 'exprloc'.
+// ASSUMPTION: Location attributes of 'loclist' type containing 'exprloc'
+// with address expression operands are not supported yet.
struct PatchLocation {
DIE::value_iterator I;
+ int64_t RelocAdjustment = 0;
PatchLocation() = default;
PatchLocation(DIE::value_iterator I) : I(I) {}
+ PatchLocation(DIE::value_iterator I, int64_t Reloc)
+ : I(I), RelocAdjustment(Reloc) {}
void set(uint64_t New) const {
assert(I);
@@ -44,7 +54,7 @@ struct PatchLocation {
};
using RngListAttributesTy = SmallVector<PatchLocation>;
-using LocListAttributesTy = SmallVector<std::pair<PatchLocation, int64_t>>;
+using LocListAttributesTy = SmallVector<PatchLocation>;
/// Stores all information relating to a compile unit, be it in its original
/// instance in the object file to its brand new cloned and generated DIE tree.
@@ -191,7 +201,7 @@ class CompileUnit {
/// Keep track of a location attribute pointing to a location list in the
/// debug_loc section.
- void noteLocationAttribute(PatchLocation Attr, int64_t PcOffset);
+ void noteLocationAttribute(PatchLocation Attr);
/// Add a name accelerator entry for \a Die with \a Name.
void addNamespaceAccelerator(const DIE *Die, DwarfStringPoolEntryRef Name);
@@ -286,9 +296,10 @@ class CompileUnit {
/// @}
/// Location attributes that need to be transferred from the
- /// original debug_loc section to the liked one. They are stored
+ /// original debug_loc section to the linked one. They are stored
/// along with the PC offset that is to be applied to their
- /// function's address.
+ /// function's address or to be applied to address operands of
+ /// location expression.
LocListAttributesTy LocationAttributes;
/// Accelerator entries for the unit, both for the pub*
diff --git a/llvm/include/llvm/DWARFLinkerParallel/AddressesMap.h b/llvm/include/llvm/DWARFLinkerParallel/AddressesMap.h
index eadd7120f70c7..5386f9ca68674 100644
--- a/llvm/include/llvm/DWARFLinkerParallel/AddressesMap.h
+++ b/llvm/include/llvm/DWARFLinkerParallel/AddressesMap.h
@@ -11,6 +11,7 @@
#include "llvm/ADT/AddressRanges.h"
#include "llvm/DebugInfo/DWARF/DWARFDie.h"
+#include "llvm/DebugInfo/DWARF/DWARFExpression.h"
#include <cstdint>
namespace llvm {
@@ -32,14 +33,16 @@ class AddressesMap {
/// section.
virtual bool hasValidRelocs() = 0;
- /// Checks that the specified variable \p DIE references the live code
- /// section and returns the relocation adjustment value (to get the linked
- /// address this value might be added to the source variable address).
- /// Allowed kinds of input DIE: DW_TAG_variable, DW_TAG_constant.
+ /// Checks that the specified DWARF expression operand \p Op references live
+ /// code section and returns the relocation adjustment value (to get the
+ /// linked address this value might be added to the source expression operand
+ /// address).
/// \returns relocation adjustment value or std::nullopt if there is no
/// corresponding live address.
virtual std::optional<int64_t>
- getVariableRelocAdjustment(const DWARFDie &DIE) = 0;
+ getExprOpAddressRelocAdjustment(DWARFUnit &U,
+ const DWARFExpression::Operation &Op,
+ uint64_t StartOffset, uint64_t EndOffset) = 0;
/// Checks that the specified subprogram \p DIE references the live code
/// section and returns the relocation adjustment value (to get the linked
diff --git a/llvm/lib/DWARFLinker/DWARFLinker.cpp b/llvm/lib/DWARFLinker/DWARFLinker.cpp
index 3307f5384158f..93c03a10cf91b 100644
--- a/llvm/lib/DWARFLinker/DWARFLinker.cpp
+++ b/llvm/lib/DWARFLinker/DWARFLinker.cpp
@@ -419,6 +419,94 @@ void DWARFLinker::cleanupAuxiliarryData(LinkContext &Context) {
DIEAlloc.Reset();
}
+std::optional<int64_t>
+DWARFLinker::getVariableRelocAdjustment(AddressesMap &RelocMgr,
+ const DWARFDie &DIE) {
+ assert((DIE.getTag() == dwarf::DW_TAG_variable ||
+ DIE.getTag() == dwarf::DW_TAG_constant) &&
+ "Wrong type of input die");
+
+ const auto *Abbrev = DIE.getAbbreviationDeclarationPtr();
+
+ // Check if DIE has DW_AT_location attribute.
+ DWARFUnit *U = DIE.getDwarfUnit();
+ std::optional<uint32_t> LocationIdx =
+ Abbrev->findAttributeIndex(dwarf::DW_AT_location);
+ if (!LocationIdx)
+ return std::nullopt;
+
+ // Get offset to the DW_AT_location attribute.
+ uint64_t AttrOffset =
+ Abbrev->getAttributeOffsetFromIndex(*LocationIdx, DIE.getOffset(), *U);
+
+ // Get value of the DW_AT_location attribute.
+ std::optional<DWARFFormValue> LocationValue =
+ Abbrev->getAttributeValueFromOffset(*LocationIdx, AttrOffset, *U);
+ if (!LocationValue)
+ return std::nullopt;
+
+ // Check that DW_AT_location attribute is of 'exprloc' class.
+ // Handling value of location expressions for attributes of 'loclist'
+ // class is not implemented yet.
+ std::optional<ArrayRef<uint8_t>> Expr = LocationValue->getAsBlock();
+ if (!Expr)
+ return std::nullopt;
+
+ // Parse 'exprloc' expression.
+ DataExtractor Data(toStringRef(*Expr), U->getContext().isLittleEndian(),
+ U->getAddressByteSize());
+ DWARFExpression Expression(Data, U->getAddressByteSize(),
+ U->getFormParams().Format);
+
+ uint64_t CurExprOffset = 0;
+ for (DWARFExpression::iterator It = Expression.begin();
+ It != Expression.end(); ++It) {
+ DWARFExpression::iterator NextIt = It;
+ ++NextIt;
+
+ const DWARFExpression::Operation &Op = *It;
+ switch (Op.getCode()) {
+ case dwarf::DW_OP_const4u:
+ case dwarf::DW_OP_const8u:
+ case dwarf::DW_OP_const4s:
+ case dwarf::DW_OP_const8s:
+ if (NextIt == Expression.end() ||
+ NextIt->getCode() != dwarf::DW_OP_form_tls_address)
+ break;
+ [[fallthrough]];
+ case dwarf::DW_OP_addr: {
+ // Check relocation for the address.
+ if (std::optional<int64_t> RelocAdjustment =
+ RelocMgr.getExprOpAddressRelocAdjustment(
+ *U, Op, AttrOffset + CurExprOffset,
+ AttrOffset + Op.getEndOffset()))
+ return *RelocAdjustment;
+ } break;
+ case dwarf::DW_OP_constx:
+ case dwarf::DW_OP_addrx: {
+ if (std::optional<uint64_t> AddrOffsetSectionBase =
+ DIE.getDwarfUnit()->getAddrOffsetSectionBase()) {
+ uint64_t StartOffset = *AddrOffsetSectionBase + Op.getRawOperand(0);
+ uint64_t EndOffset =
+ StartOffset + DIE.getDwarfUnit()->getAddressByteSize();
+
+ // Check relocation for the address.
+ if (std::optional<int64_t> RelocAdjustment =
+ RelocMgr.getExprOpAddressRelocAdjustment(*U, Op, StartOffset,
+ EndOffset))
+ return *RelocAdjustment;
+ }
+ } break;
+ default: {
+ // Nothing to do.
+ } break;
+ }
+ CurExprOffset = Op.getEndOffset();
+ }
+
+ return std::nullopt;
+}
+
/// Check if a variable describing DIE should be kept.
/// \returns updated TraversalFlags.
unsigned DWARFLinker::shouldKeepVariableDIE(AddressesMap &RelocMgr,
@@ -440,7 +528,7 @@ unsigned DWARFLinker::shouldKeepVariableDIE(AddressesMap &RelocMgr,
// However, we don't want a static variable in a function to force us to keep
// the enclosing function, unless requested explicitly.
std::optional<int64_t> RelocAdjustment =
- RelocMgr.getVariableRelocAdjustment(DIE);
+ getVariableRelocAdjustment(RelocMgr, DIE);
if (RelocAdjustment) {
MyInfo.AddrAdjust = *RelocAdjustment;
@@ -1053,9 +1141,12 @@ unsigned DWARFLinker::DIECloner::cloneDieReferenceAttribute(
void DWARFLinker::DIECloner::cloneExpression(
DataExtractor &Data, DWARFExpression Expression, const DWARFFile &File,
- CompileUnit &Unit, SmallVectorImpl<uint8_t> &OutputBuffer) {
+ CompileUnit &Unit, SmallVectorImpl<uint8_t> &OutputBuffer,
+ int64_t AddrRelocAdjustment) {
using Encoding = DWARFExpression::Operation::Encoding;
+ uint8_t OrigAddressByteSize = Unit.getOrigUnit().getAddressByteSize();
+
uint64_t OpOffset = 0;
for (auto &Op : Expression) {
auto Description = Op.getDescription();
@@ -1107,6 +1198,55 @@ void DWARFLinker::DIECloner::cloneExpression(
assert(RealSize == ULEBsize && "padding failed");
ArrayRef<uint8_t> ULEBbytes(ULEB, ULEBsize);
OutputBuffer.append(ULEBbytes.begin(), ULEBbytes.end());
+ } else if (!Linker.Options.Update && Op.getCode() == dwarf::DW_OP_addrx) {
+ if (std::optional<object::SectionedAddress> SA =
+ Unit.getOrigUnit().getAddrOffsetSectionItem(
+ Op.getRawOperand(0))) {
+ // DWARFLinker does not use addrx forms since it generates relocated
+ // addresses. Replace DW_OP_addrx with DW_OP_addr here.
+ // Argument of DW_OP_addrx should be relocated here as it is not
+ // processed by applyValidRelocs.
+ OutputBuffer.push_back(dwarf::DW_OP_addr);
+ uint64_t LinkedAddress = SA->Address + AddrRelocAdjustment;
+ ArrayRef<uint8_t> AddressBytes(
+ reinterpret_cast<const uint8_t *>(&LinkedAddress),
+ OrigAddressByteSize);
+ OutputBuffer.append(AddressBytes.begin(), AddressBytes.end());
+ } else
+ Linker.reportWarning("cannot read DW_OP_addrx operand.", File);
+ } else if (!Linker.Options.Update && Op.getCode() == dwarf::DW_OP_constx) {
+ if (std::optional<object::SectionedAddress> SA =
+ Unit.getOrigUnit().getAddrOffsetSectionItem(
+ Op.getRawOperand(0))) {
+ // DWARFLinker does not use constx forms since it generates relocated
+ // addresses. Replace DW_OP_constx with DW_OP_const[*]u here.
+ // Argument of DW_OP_constx should be relocated here as it is not
+ // processed by applyValidRelocs.
+ std::optional<uint8_t> OutOperandKind;
+ switch (OrigAddressByteSize) {
+ case 4:
+ OutOperandKind = dwarf::DW_OP_const4u;
+ break;
+ case 8:
+ OutOperandKind = dwarf::DW_OP_const8u;
+ break;
+ default:
+ Linker.reportWarning(
+ formatv(("unsupported address size: {0}."), OrigAddressByteSize),
+ File);
+ break;
+ }
+
+ if (OutOperandKind) {
+ OutputBuffer.push_back(*OutOperandKind);
+ uint64_t LinkedAddress = SA->Address + AddrRelocAdjustment;
+ ArrayRef<uint8_t> AddressBytes(
+ reinterpret_cast<const uint8_t *>(&LinkedAddress),
+ OrigAddressByteSize);
+ OutputBuffer.append(AddressBytes.begin(), AddressBytes.end());
+ }
+ } else
+ Linker.reportWarning("cannot read DW_OP_constx operand.", File);
} else {
// Copy over everything else unmodified.
StringRef Bytes = Data.getData().slice(OpOffset, Op.getEndOffset());
@@ -1117,8 +1257,9 @@ void DWARFLinker::DIECloner::cloneExpression(
}
unsigned DWARFLinker::DIECloner::cloneBlockAttribute(
- DIE &Die, const DWARFFile &File, CompileUnit &Unit, AttributeSpec AttrSpec,
- const DWARFFormValue &Val, unsigned AttrSize, bool IsLittleEndian) {
+ DIE &Die, const DWARFDie &InputDIE, const DWARFFile &File,
+ CompileUnit &Unit, AttributeSpec AttrSpec, const DWARFFormValue &Val,
+ bool IsLittleEndian) {
DIEValueList *Attr;
DIEValue Value;
DIELoc *Loc = nullptr;
@@ -1152,7 +1293,8 @@ unsigned DWARFLinker::DIECloner::cloneBlockAttribute(
IsLittleEndian, OrigUnit.getAddressByteSize());
DWARFExpression Expr(Data, OrigUnit.getAddressByteSize(),
OrigUnit.getFormParams().Format);
- cloneExpression(Data, Expr, File, Unit, Buffer);
+ cloneExpression(Data, Expr, File, Unit, Buffer,
+ Unit.getInfo(InputDIE).AddrAdjust);
Bytes = Buffer;
}
for (auto Byte : Bytes)
@@ -1168,7 +1310,7 @@ unsigned DWARFLinker::DIECloner::cloneBlockAttribute(
Block->setSize(Bytes.size());
Die.addValue(DIEAlloc, Value);
- return AttrSize;
+ return getULEB128Size(Bytes.size()) + Bytes.size();
}
unsigned DWARFLinker::DIECloner::cloneAddressAttribute(
@@ -1355,7 +1497,7 @@ unsigned DWARFLinker::DIECloner::cloneScalarAttribute(
return 0;
}
- PatchLocation Patch =
+ DIE::value_iterator Patch =
Die.addValue(DIEAlloc, dwarf::Attribute(AttrSpec.Attr),
dwarf::Form(AttrSpec.Form), DIEInteger(Value));
if (AttrSpec.Attr == dwarf::DW_AT_ranges ||
@@ -1366,7 +1508,11 @@ unsigned DWARFLinker::DIECloner::cloneScalarAttribute(
dwarf::doesFormBelongToClass(AttrSpec.Form,
DWARFFormValue::FC_SectionOffset,
Unit.getOrigUnit().getVersion())) {
- Unit.noteLocationAttribute(Patch, Info.PCOffset);
+
+ CompileUnit::DIEInfo &LocationDieInfo = Unit.getInfo(InputDIE);
+ Unit.noteLocationAttribute({Patch, LocationDieInfo.InDebugMap
+ ? LocationDieInfo.AddrAdjust
+ : Info.PCOffset});
} else if (AttrSpec.Attr == dwarf::DW_AT_declaration && Value)
Info.IsDeclaration = true;
@@ -1408,7 +1554,7 @@ unsigned DWARFLinker::DIECloner::cloneAttribute(
case dwarf::DW_FORM_block2:
case dwarf::DW_FORM_block4:
case dwarf::DW_FORM_exprloc:
- return cloneBlockAttribute(Die, File, Unit, AttrSpec, Val, AttrSize,
+ return cloneBlockAttribute(Die, InputDIE, File, Unit, AttrSpec, Val,
IsLittleEndian);
case dwarf::DW_FORM_addr:
case dwarf::DW_FORM_addrx:
@@ -1803,7 +1949,7 @@ void DWARFLinker::generateUnitLocations(
// Get location expressions vector corresponding to the current attribute
// from the source DWARF.
Expected<DWARFLocationExpressionsVector> OriginalLocations =
- Unit.getOrigUnit().findLoclistFromOffset((CurLocAttr.first).get());
+ Unit.getOrigUnit().findLoclistFromOffset(CurLocAttr.get());
if (!OriginalLocations) {
llvm::consumeError(OriginalLocations.takeError());
@@ -1813,26 +1959,26 @@ void DWARFLinker::generateUnitLocations(
DWARFLocationExpressionsVector LinkedLocationExpressions;
for (DWARFLocationExpression &CurExpression : *OriginalLocations) {
-
DWARFLocationExpression LinkedExpression;
if (CurExpression.Range) {
// Relocate address range.
LinkedExpression.Range = {
- CurExpression.Range->LowPC + CurLocAttr.second,
- CurExpression.Range->HighPC + CurLocAttr.second};
+ CurExpression.Range->LowPC + CurLocAttr.RelocAdjustment,
+ CurExpression.Range->HighPC + CurLocAttr.RelocAdjustment};
}
// Clone expression.
LinkedExpression.Expr.reserve(CurExpression.Expr.size());
- ExprHandler(CurExpression.Expr, LinkedExpression.Expr);
+ ExprHandler(CurExpression.Expr, LinkedExpression.Expr,
+ CurLocAttr.RelocAdjustment);
LinkedLocationExpressions.push_back(LinkedExpression);
}
// Emit locations list table fragment corresponding to the CurLocAttr.
TheDwarfEmitter->emitDwarfDebugLocListFragment(
- Unit, LinkedLocationExpressions, CurLocAttr.first);
+ Unit, LinkedLocationExpressions, CurLocAttr);
}
// Emit locations list table footer.
@@ -2399,14 +2545,15 @@ uint64_t DWARFLinker::DIECloner::cloneAllCompileUnits(
Linker.generateUnitRanges(*CurrentUnit, File);
auto ProcessExpr = [&](SmallVectorImpl<uint8_t> &SrcBytes,
- SmallVectorImpl<uint8_t> &OutBytes) {
+ SmallVectorImpl<uint8_t> &OutBytes,
+ int64_t RelocAdjustment) {
DWARFUnit &OrigUnit = CurrentUnit->getOrigUnit();
DataExtractor Data(SrcBytes, IsLittleEndian,
OrigUnit.getAddressByteSize());
cloneExpression(Data,
DWARFExpression(Data, OrigUnit.getAddressByteSize(),
OrigUnit.getFormParams().Format),
- File, *CurrentUnit, OutBytes);
+ File, *CurrentUnit, OutBytes, RelocAdjustment);
};
Linker.generateUnitLocations(*CurrentUnit, File, ProcessExpr);
}
diff --git a/llvm/lib/DWARFLinker/DWARFLinkerCompileUnit.cpp b/llvm/lib/DWARFLinker/DWARFLinkerCompileUnit.cpp
index 870a841951e0f..4aa6f33c2908b 100644
--- a/llvm/lib/DWARFLinker/DWARFLinkerCompileUnit.cpp
+++ b/llvm/lib/DWARFLinker/DWARFLinkerCompileUnit.cpp
@@ -8,6 +8,8 @@
#include "llvm/DWARFLinker/DWARFLinkerCompileUnit.h"
#include "llvm/DWARFLinker/DWARFLinkerDeclContext.h"
+#include "llvm/DebugInfo/DWARF/DWARFContext.h"
+#include "llvm/DebugInfo/DWARF/DWARFExpression.h"
#include "llvm/Support/FormatVariadic.h"
namespace llvm {
@@ -63,6 +65,7 @@ void CompileUnit::markEverythingAsKept() {
// Mark everything that wasn't explicit marked for pruning.
I.Keep = !I.Prune;
auto DIE = OrigUnit.getDIEAtIndex(Idx++);
+ DWARFUnit *U = DIE.getDwarfUnit();
// Try to guess which DIEs must go to the accelerator tables. We do that
// just for variables, because functions will be handled depending on
@@ -78,10 +81,39 @@ void CompileUnit::markEverythingAsKept() {
I.InDebugMap = true;
continue;
}
- if (auto Block = Value->getAsBlock()) {
- if (Block->size() > OrigUnit.getAddressByteSize() &&
- (*Block)[0] == dwarf::DW_OP_addr)
- I.InDebugMap = true;
+
+ if (auto ExprLockBlock = Value->getAsBlock()) {
+ // Parse 'exprloc' expression.
+ DataExtractor Data(toStringRef(*ExprLockBlock),
+ U->getContext().isLittleEndian(),
+ U->getAddressByteSize());
+ DWARFExpression Expression(Data, U->getAddressByteSize(),
+ U->getFormParams().Format);
+
+ for (DWARFExpression::iterator It = Expression.begin();
+ (It != Expression.end()) && !I.InDebugMap; ++It) {
+ DWARFExpression::iterator NextIt = It;
+ ++NextIt;
+
+ switch (It->getCode()) {
+ case dwarf::DW_OP_const4u:
+ case dwarf::DW_OP_const8u:
+ case dwarf::DW_OP_const4s:
+ case dwarf::DW_OP_const8s:
+ if (NextIt == Expression.end() ||
+ NextIt->getCode() != dwarf::DW_OP_form_tls_address)
+ break;
+ [[fallthrough]];
+ case dwarf::DW_OP_constx:
+ case dwarf::DW_OP_addr:
+ case dwarf::DW_OP_addrx:
+ I.InDebugMap = true;
+ break;
+ default:
+ // Nothing to do.
+ break;
+ }
+ }
}
}
}
@@ -143,8 +175,8 @@ void CompileUnit::noteRangeAttribute(const DIE &Die, PatchLocation Attr) {
RangeAttributes.emplace_back(Attr);
}
-void CompileUnit::noteLocationAttribute(PatchLocation Attr, int64_t PcOffset) {
- LocationAttributes.emplace_back(Attr, PcOffset);
+void CompileUnit::noteLocationAttribute(PatchLocation Attr) {
+ LocationAttributes.emplace_back(Attr);
}
void CompileUnit::addNamespaceAccelerator(const DIE *Die,
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFExpression.cpp b/llvm/lib/DebugInfo/DWARF/DWARFExpression.cpp
index 3adc6c7bcbe56..109731e73c71d 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFExpression.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFExpression.cpp
@@ -94,11 +94,12 @@ static DescVector getDescriptions() {
Descriptions[DW_OP_WASM_location] =
Desc(Op::Dwarf4, Op::SizeLEB, Op::WasmLocationArg);
Descriptions[DW_OP_GNU_push_tls_address] = Desc(Op::Dwarf3);
- Descriptions[DW_OP_addrx] = Desc(Op::Dwarf4, Op::SizeLEB);
Descriptions[DW_OP_GNU_addr_index] = Desc(Op::Dwarf4, Op::SizeLEB);
Descriptions[DW_OP_GNU_const_index] = Desc(Op::Dwarf4, Op::SizeLEB);
Descriptions[DW_OP_GNU_entry_value] = Desc(Op::Dwarf4, Op::SizeLEB);
+ Descriptions[DW_OP_addrx] = Desc(Op::Dwarf5, Op::SizeLEB);
+ Descriptions[DW_OP_constx] = Desc(Op::Dwarf5, Op::SizeLEB);
Descriptions[DW_OP_convert] = Desc(Op::Dwarf5, Op::BaseTypeRef);
Descriptions[DW_OP_entry_value] = Desc(Op::Dwarf5, Op::SizeLEB);
Descriptions[DW_OP_regval_type] =
diff --git a/llvm/test/tools/dsymutil/Inputs/dwarf5-dw-op-addrx.o b/llvm/test/tools/dsymutil/Inputs/dwarf5-dw-op-addrx.o
new file mode 100644
index 0000000000000..fb2a6d3242ec5
Binary files /dev/null and b/llvm/test/tools/dsymutil/Inputs/dwarf5-dw-op-addrx.o
diff er
diff --git a/llvm/test/tools/dsymutil/X86/dwarf5-dw-op-addrx.test b/llvm/test/tools/dsymutil/X86/dwarf5-dw-op-addrx.test
new file mode 100644
index 0000000000000..8951470f4c5b6
--- /dev/null
+++ b/llvm/test/tools/dsymutil/X86/dwarf5-dw-op-addrx.test
@@ -0,0 +1,47 @@
+## This test checks that DW_OP_addrx expression operand
+## is correctly recognized and converted into the DW_OP_addr
+## operand or just preserved in case --update.
+
+## cat dwarf5-dw-op-addrx.c
+
+## $ clang -gdwarf-5 dwarf5-dw-op-addrx.c -c -O2 -o dwarf5-dw-op-addrx.o
+
+#RUN: dsymutil -oso-prepend-path %p/../Inputs -y %s -o %t.dSYM
+#RUN: llvm-dwarfdump --verify %t.dSYM | FileCheck %s
+#RUN: llvm-dwarfdump -a --verbose %t.dSYM | FileCheck %s --check-prefix DWARF-CHECK
+
+#RUN: dsymutil --update -oso-prepend-path %p/../Inputs -y %s -o %t.dSYM
+#RUN: llvm-dwarfdump --verify %t.dSYM | FileCheck %s
+#RUN: llvm-dwarfdump -a --verbose %t.dSYM | FileCheck %s --check-prefix UPD-DWARF-CHECK
+
+#CHECK: No errors.
+
+#DWARF-CHECK: DW_TAG_compile_unit
+#DWARF-CHECK: DW_AT_name {{.*}}"dwarf5-dw-op-addrx.c"
+#DWARF-CHECK: DW_AT_low_pc {{.*}}0x0000000100000fb0
+#DWARF-CHECK: DW_TAG_variable
+#DWARF-CHECK: DW_AT_name {{.*}}"arr"
+#DWARF-CHECK: DW_AT_location {{.*}}(DW_OP_addr 0x100002000)
+#DWARF-CHECK-NOT: .debug_addr
+
+#UPD-DWARF-CHECK: DW_TAG_compile_unit
+#UPD-DWARF-CHECK: DW_AT_name {{.*}}"dwarf5-dw-op-addrx.c"
+#UPD-DWARF-CHECK: DW_AT_low_pc [DW_FORM_addrx] (indexed (00000001) address = 0x0000000000000000)
+#UPD-DWARF-CHECK: DW_AT_high_pc [DW_FORM_data4] (0x00000008)
+#UPD-DWARF-CHECK: DW_AT_addr_base [DW_FORM_sec_offset] (0x00000008)
+#UPD-DWARF-CHECK: DW_TAG_variable
+#UPD-DWARF-CHECK: DW_AT_name {{.*}}"arr"
+#UPD-DWARF-CHECK: DW_AT_location [DW_FORM_exprloc] (DW_OP_addrx 0x0)
+#UPD-DWARF-CHECK: .debug_addr contents:
+#UPD-DWARF-CHECK: 0x00000000: Address table header: length = 0x00000014, format = DWARF32, version = 0x0005, addr_size = 0x08, seg_size = 0x00
+#UPD-DWARF-CHECK: 0x0000000000000000
+#UPD-DWARF-CHECK: 0x0000000000000000
+
+---
+triple: 'x86_64-apple-darwin'
+objects:
+ - filename: 'dwarf5-dw-op-addrx.o'
+ timestamp: 1676048242
+ symbols:
+ - { sym: _main, objAddr: 0x0000000000000000, binAddr: 0x0000000100000FB0, size: 0x00000008 }
+ - { sym: _arr, binAddr: 0x0000000100002000, size: 0x00000000 }
diff --git a/llvm/test/tools/dsymutil/X86/op-convert-offset.test b/llvm/test/tools/dsymutil/X86/op-convert-offset.test
index 5694535322810..8cf378c114a39 100644
--- a/llvm/test/tools/dsymutil/X86/op-convert-offset.test
+++ b/llvm/test/tools/dsymutil/X86/op-convert-offset.test
@@ -34,12 +34,12 @@ OBJ: DW_AT_location (DW_OP_breg2 RCX+0, DW_OP_constu 0x
OBJ: DW_AT_name ("b")
OBJ: DW_AT_type (0x000000af "_Bool")
-DSYM: 0x0000008d: DW_TAG_base_type
+DSYM: 0x000000ae: DW_TAG_base_type
DSYM: DW_AT_name ("DW_ATE_unsigned_1")
DSYM: DW_AT_encoding (DW_ATE_unsigned)
DSYM: DW_AT_byte_size (0x01)
-DSYM: 0x000000b4: DW_TAG_formal_parameter
-DSYM: DW_AT_location (DW_OP_breg2 RCX+0, DW_OP_constu 0xff, DW_OP_and, DW_OP_convert (0x0000008d) "DW_ATE_unsigned_1", DW_OP_convert (0x00000094) "DW_ATE_unsigned_8", DW_OP_stack_value)
+DSYM: 0x000000d5: DW_TAG_formal_parameter
+DSYM: DW_AT_location (DW_OP_breg2 RCX+0, DW_OP_constu 0xff, DW_OP_and, DW_OP_convert (0x000000ae) "DW_ATE_unsigned_1", DW_OP_convert (0x000000b5) "DW_ATE_unsigned_8", DW_OP_stack_value)
DSYM: DW_AT_name ("b")
-DSYM: DW_AT_type (0x000000d2 "_Bool")
+DSYM: DW_AT_type (0x000000f3 "_Bool")
diff --git a/llvm/test/tools/llvm-dwarfutil/ELF/X86/dwarf5-addrx.test b/llvm/test/tools/llvm-dwarfutil/ELF/X86/dwarf5-addresses.test
similarity index 71%
rename from llvm/test/tools/llvm-dwarfutil/ELF/X86/dwarf5-addrx.test
rename to llvm/test/tools/llvm-dwarfutil/ELF/X86/dwarf5-addresses.test
index bf52bac1237c1..3a3bf54c61d7d 100644
--- a/llvm/test/tools/llvm-dwarfutil/ELF/X86/dwarf5-addrx.test
+++ b/llvm/test/tools/llvm-dwarfutil/ELF/X86/dwarf5-addresses.test
@@ -1,6 +1,11 @@
-## Test that DWARFv5 DW_FORM_addrx is correctly recognized
-## and converted into the DW_FORM_addr in --garbage-collection
-## case or correctly preserved in --no-garbage-collection case.
+## Test that DWARFv5 address attributes and address expression operands
+## are handled correctly, specifically:
+## 1. DW_FORM_addrx is correctly recognized and converted into the DW_FORM_addr
+## in --garbage-collection case or correctly preserved in --no-garbage-collection case.
+## 2. DW_OP_addrx is correctly recognized and converted into the DW_OP_addr
+## in --garbage-collection case or correctly preserved in --no-garbage-collection case.
+## 3. DW_OP_constx is correctly recognized and converted into the DW_OP_const[*]u
+## in --garbage-collection case or correctly preserved in --no-garbage-collection case.
# RUN: yaml2obj %s -o %t.o
@@ -46,6 +51,18 @@
#DWARF-CHECK: DW_AT_name [DW_FORM_strp] {{.*}} "foo6"
#DWARF-CHECK: DW_AT_low_pc [DW_FORM_addr] (0x0000000000001180)
#DWARF-CHECK: DW_AT_high_pc [DW_FORM_data8] (0x0000000000000010)
+#DWARF-CHECK: DW_TAG_variable
+#DWARF-CHECK: DW_AT_name [DW_FORM_strp] {{.*}} "var1"
+#DWARF-CHECK: DW_AT_location [DW_FORM_exprloc] (DW_OP_addr 0x2000)
+#DWARF-CHECK: DW_TAG_variable
+#DWARF-CHECK: DW_AT_name [DW_FORM_strp] {{.*}} "var2"
+#DWARF-CHECK: DW_AT_location [DW_FORM_exprloc] (DW_OP_addr 0x2000)
+#DWARF-CHECK: DW_TAG_variable
+#DWARF-CHECK: DW_AT_name [DW_FORM_strp] {{.*}} "var3"
+#DWARF-CHECK: DW_AT_location [DW_FORM_exprloc] (DW_OP_const8u 0x2000, DW_OP_form_tls_address)
+#DWARF-CHECK: DW_TAG_variable
+#DWARF-CHECK: DW_AT_name [DW_FORM_strp] {{.*}} "var4"
+#DWARF-CHECK: DW_AT_location [DW_FORM_exprloc] (DW_OP_const8u 0x2000, DW_OP_form_tls_address)
#DWARF-CHECK=NOT: .debug_addr contents:
#UPD-DWARF-CHECK: DW_TAG_compile_unit
@@ -76,8 +93,20 @@
#UPD-DWARF-CHECK: DW_AT_name {{.*}}"foo6"
#UPD-DWARF-CHECK: DW_AT_low_pc [DW_FORM_addrx4] (indexed (00000005) address = 0x0000000000001180)
#UPD-DWARF-CHECK: DW_AT_high_pc [DW_FORM_data8] (0x0000000000000010)
+#UPD-DWARF-CHECK: DW_TAG_variable
+#UPD-DWARF-CHECK: DW_AT_name {{.*}}"var1"
+#UPD-DWARF-CHECK: DW_AT_location [DW_FORM_exprloc] (DW_OP_addrx 0x6)
+#UPD-DWARF-CHECK: DW_TAG_variable
+#UPD-DWARF-CHECK: DW_AT_name {{.*}}"var2"
+#UPD-DWARF-CHECK: DW_AT_location [DW_FORM_exprloc] (DW_OP_addr 0x2000)
+#UPD-DWARF-CHECK: DW_TAG_variable
+#UPD-DWARF-CHECK: DW_AT_name {{.*}}"var3"
+#UPD-DWARF-CHECK: DW_AT_location [DW_FORM_exprloc] (DW_OP_constx 0x6, DW_OP_form_tls_address)
+#UPD-DWARF-CHECK: DW_TAG_variable
+#UPD-DWARF-CHECK: DW_AT_name {{.*}}"var4"
+#UPD-DWARF-CHECK: DW_AT_location [DW_FORM_exprloc] (DW_OP_const8u 0x2000, DW_OP_form_tls_address)
#UPD-DWARF-CHECK: .debug_addr contents:
-#UPD-DWARF-CHECK: 0x00000000: Address table header: length = 0x00000034, format = DWARF32, version = 0x0005, addr_size = 0x08, seg_size = 0x00
+#UPD-DWARF-CHECK: 0x00000000: Address table header: length = 0x0000003c, format = DWARF32, version = 0x0005, addr_size = 0x08, seg_size = 0x00
#UPD-DWARF-CHECK: Addrs: [
#UPD-DWARF-CHECK: 0x0000000000001130
#UPD-DWARF-CHECK: 0x0000000000001140
@@ -85,6 +114,7 @@
#UPD-DWARF-CHECK: 0x0000000000001160
#UPD-DWARF-CHECK: 0x0000000000001170
#UPD-DWARF-CHECK: 0x0000000000001180
+#UPD-DWARF-CHECK: 0x0000000000002000
#UPD-DWARF-CHECK: ]
--- !ELF
@@ -98,7 +128,7 @@ Sections:
Type: SHT_PROGBITS
Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
Address: 0x1130
- Size: 0x60
+ Size: 0x1000
DWARF:
debug_abbrev:
- Table:
@@ -166,6 +196,15 @@ DWARF:
Attributes:
- Attribute: DW_AT_name
Form: DW_FORM_string
+ - Tag: DW_TAG_variable
+ Children: DW_CHILDREN_no
+ Attributes:
+ - Attribute: DW_AT_name
+ Form: DW_FORM_string
+ - Attribute: DW_AT_type
+ Form: DW_FORM_ref4
+ - Attribute: DW_AT_location
+ Form: DW_FORM_exprloc
debug_info:
- Version: 5
UnitType: DW_UT_compile
@@ -223,6 +262,50 @@ DWARF:
- AbbrCode: 6
Values:
- CStr: int
+ - AbbrCode: 7
+ Values:
+ - CStr: var1
+ - Value: 0xa4
+ - BlockData:
+ - 0xa1
+ - 0x6
+ - AbbrCode: 7
+ Values:
+ - CStr: var2
+ - Value: 0xa4
+ - BlockData:
+ - 0x03
+ - 0x00
+ - 0x20
+ - 0x00
+ - 0x00
+ - 0x00
+ - 0x00
+ - 0x00
+ - 0x00
+ - AbbrCode: 7
+ Values:
+ - CStr: var3
+ - Value: 0xa4
+ - BlockData:
+ - 0xa2
+ - 0x6
+ - 0x9b
+ - AbbrCode: 7
+ Values:
+ - CStr: var4
+ - Value: 0xa4
+ - BlockData:
+ - 0x0e
+ - 0x00
+ - 0x20
+ - 0x00
+ - 0x00
+ - 0x00
+ - 0x00
+ - 0x00
+ - 0x00
+ - 0x9b
- AbbrCode: 0
debug_addr:
- Version: 5
@@ -234,4 +317,5 @@ DWARF:
- Address: 0x1160
- Address: 0x1170
- Address: 0x1180
+ - Address: 0x2000
...
diff --git a/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp b/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp
index 62251162e7b33..efa490ebbb40f 100644
--- a/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp
+++ b/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp
@@ -40,6 +40,7 @@
#include "llvm/DebugInfo/DWARF/DWARFDebugLine.h"
#include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h"
#include "llvm/DebugInfo/DWARF/DWARFDie.h"
+#include "llvm/DebugInfo/DWARF/DWARFExpression.h"
#include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
#include "llvm/DebugInfo/DWARF/DWARFSection.h"
#include "llvm/DebugInfo/DWARF/DWARFUnit.h"
@@ -985,23 +986,27 @@ getAttributeOffsets(const DWARFAbbreviationDeclaration *Abbrev, unsigned Idx,
}
std::optional<int64_t>
-DwarfLinkerForBinary::AddressManager::getVariableRelocAdjustment(
- const DWARFDie &DIE) {
- const auto *Abbrev = DIE.getAbbreviationDeclarationPtr();
-
- std::optional<uint32_t> LocationIdx =
- Abbrev->findAttributeIndex(dwarf::DW_AT_location);
- if (!LocationIdx)
- return std::nullopt;
-
- uint64_t Offset = DIE.getOffset() + getULEB128Size(Abbrev->getCode());
- uint64_t LocationOffset, LocationEndOffset;
- std::tie(LocationOffset, LocationEndOffset) =
- getAttributeOffsets(Abbrev, *LocationIdx, Offset, *DIE.getDwarfUnit());
+DwarfLinkerForBinary::AddressManager::getExprOpAddressRelocAdjustment(
+ DWARFUnit &U, const DWARFExpression::Operation &Op, uint64_t StartOffset,
+ uint64_t EndOffset) {
+ switch (Op.getCode()) {
+ default: {
+ assert(false && "Specified operation does not have address operand");
+ } break;
+ case dwarf::DW_OP_const4u:
+ case dwarf::DW_OP_const8u:
+ case dwarf::DW_OP_const4s:
+ case dwarf::DW_OP_const8s:
+ case dwarf::DW_OP_addr: {
+ return hasValidRelocationAt(ValidDebugInfoRelocs, StartOffset, EndOffset);
+ } break;
+ case dwarf::DW_OP_constx:
+ case dwarf::DW_OP_addrx: {
+ return hasValidRelocationAt(ValidDebugAddrRelocs, StartOffset, EndOffset);
+ } break;
+ }
- // FIXME: Support relocations debug_addr.
- return hasValidRelocationAt(ValidDebugInfoRelocs, LocationOffset,
- LocationEndOffset);
+ return std::nullopt;
}
std::optional<int64_t>
diff --git a/llvm/tools/dsymutil/DwarfLinkerForBinary.h b/llvm/tools/dsymutil/DwarfLinkerForBinary.h
index ec54265bdd77b..8b967f9f418e2 100644
--- a/llvm/tools/dsymutil/DwarfLinkerForBinary.h
+++ b/llvm/tools/dsymutil/DwarfLinkerForBinary.h
@@ -177,8 +177,9 @@ class DwarfLinkerForBinary {
hasValidRelocationAt(const std::vector<ValidReloc> &Relocs,
uint64_t StartOffset, uint64_t EndOffset);
- std::optional<int64_t>
- getVariableRelocAdjustment(const DWARFDie &DIE) override;
+ std::optional<int64_t> getExprOpAddressRelocAdjustment(
+ DWARFUnit &U, const DWARFExpression::Operation &Op,
+ uint64_t StartOffset, uint64_t EndOffset) override;
std::optional<int64_t>
getSubprogramRelocAdjustment(const DWARFDie &DIE) override;
diff --git a/llvm/tools/llvm-dwarfutil/DebugInfoLinker.cpp b/llvm/tools/llvm-dwarfutil/DebugInfoLinker.cpp
index 534a56a4f7d04..b36c57a737098 100644
--- a/llvm/tools/llvm-dwarfutil/DebugInfoLinker.cpp
+++ b/llvm/tools/llvm-dwarfutil/DebugInfoLinker.cpp
@@ -88,38 +88,33 @@ class ObjFileAddressMap : public AddressesMap {
return std::nullopt;
}
- std::optional<int64_t>
- getVariableRelocAdjustment(const DWARFDie &DIE) override {
- assert((DIE.getTag() == dwarf::DW_TAG_variable ||
- DIE.getTag() == dwarf::DW_TAG_constant) &&
- "Wrong type of input die");
-
- if (Expected<DWARFLocationExpressionsVector> Loc =
- DIE.getLocations(dwarf::DW_AT_location)) {
- DWARFUnit *U = DIE.getDwarfUnit();
- for (const auto &Entry : *Loc) {
- DataExtractor Data(toStringRef(Entry.Expr),
- U->getContext().isLittleEndian(), 0);
- DWARFExpression Expression(Data, U->getAddressByteSize(),
- U->getFormParams().Format);
- bool HasLiveAddresses =
- any_of(Expression, [&](const DWARFExpression::Operation &Op) {
- // TODO: add handling of dwarf::DW_OP_addrx
- return !Op.isError() &&
- (Op.getCode() == dwarf::DW_OP_addr &&
- !isDeadAddress(Op.getRawOperand(0), U->getVersion(),
- Opts.Tombstone,
- DIE.getDwarfUnit()->getAddressByteSize()));
- });
-
- if (HasLiveAddresses)
+ std::optional<int64_t> getExprOpAddressRelocAdjustment(
+ DWARFUnit &U, const DWARFExpression::Operation &Op, uint64_t StartOffset,
+ uint64_t EndOffset) override {
+ switch (Op.getCode()) {
+ default: {
+ assert(false && "Specified operation does not have address operand");
+ } break;
+ case dwarf::DW_OP_const4u:
+ case dwarf::DW_OP_const8u:
+ case dwarf::DW_OP_const4s:
+ case dwarf::DW_OP_const8s:
+ case dwarf::DW_OP_addr: {
+ if (!isDeadAddress(Op.getRawOperand(0), U.getVersion(), Opts.Tombstone,
+ U.getAddressByteSize()))
+ // Relocation value for the linked binary is 0.
+ return 0;
+ } break;
+ case dwarf::DW_OP_constx:
+ case dwarf::DW_OP_addrx: {
+ if (std::optional<object::SectionedAddress> Address =
+ U.getAddrOffsetSectionItem(Op.getRawOperand(0))) {
+ if (!isDeadAddress(Address->Address, U.getVersion(), Opts.Tombstone,
+ U.getAddressByteSize()))
// Relocation value for the linked binary is 0.
return 0;
}
- } else {
- // FIXME: missing DW_AT_location is OK here, but other errors should be
- // reported to the user.
- consumeError(Loc.takeError());
+ } break;
}
return std::nullopt;
More information about the llvm-commits
mailing list