mirror of
https://github.com/intel/llvm.git
synced 2026-02-08 17:28:30 +08:00
[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
This commit is contained in:
@@ -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 @@ public:
|
||||
/// 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 @@ private:
|
||||
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 @@ private:
|
||||
/// 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 @@ private:
|
||||
/// .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.
|
||||
|
||||
@@ -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 @@ public:
|
||||
|
||||
/// 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 @@ private:
|
||||
/// @}
|
||||
|
||||
/// 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*
|
||||
|
||||
@@ -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 @@ public:
|
||||
/// 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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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] =
|
||||
|
||||
BIN
llvm/test/tools/dsymutil/Inputs/dwarf5-dw-op-addrx.o
Normal file
BIN
llvm/test/tools/dsymutil/Inputs/dwarf5-dw-op-addrx.o
Normal file
Binary file not shown.
47
llvm/test/tools/dsymutil/X86/dwarf5-dw-op-addrx.test
Normal file
47
llvm/test/tools/dsymutil/X86/dwarf5-dw-op-addrx.test
Normal file
@@ -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 }
|
||||
@@ -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")
|
||||
|
||||
@@ -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
|
||||
...
|
||||
@@ -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();
|
||||
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;
|
||||
}
|
||||
|
||||
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());
|
||||
|
||||
// FIXME: Support relocations debug_addr.
|
||||
return hasValidRelocationAt(ValidDebugInfoRelocs, LocationOffset,
|
||||
LocationEndOffset);
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<int64_t>
|
||||
|
||||
@@ -177,8 +177,9 @@ private:
|
||||
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;
|
||||
|
||||
|
||||
@@ -88,38 +88,33 @@ public:
|
||||
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;
|
||||
|
||||
Reference in New Issue
Block a user