forked from OSchip/llvm-project
[BOLT] Update addresses for DW_TAG_GNU_call_site and DW_TAG_label.
Summary: Some DWARF tags (such as GNU_call_site and label) reference instruction addresses in the input binary. When we update debug info we need to update these tags too with new addresses. Also fix base address used for calculation of output addresses in relocation mode. (cherry picked from FBD5155814)
This commit is contained in:
parent
35d2530a40
commit
6c32079d57
|
@ -3772,6 +3772,30 @@ DWARFAddressRangesVector BinaryFunction::getOutputAddressRanges() const {
|
|||
return OutputRanges;
|
||||
}
|
||||
|
||||
uint64_t BinaryFunction::translateInputToOutputAddress(uint64_t Address) const {
|
||||
// If the function hasn't changed return the same address.
|
||||
if (!isEmitted() && !opts::Relocs)
|
||||
return Address;
|
||||
|
||||
if (Address < getAddress())
|
||||
return 0;
|
||||
|
||||
// FIXME: #18950828 - we rely on relative offsets inside basic blocks to stay
|
||||
// intact. Instead we can use pseudo instructions and/or annotations.
|
||||
const auto Offset = Address - getAddress();
|
||||
const auto *BB = getBasicBlockContainingOffset(Offset);
|
||||
if (!BB) {
|
||||
// Special case for address immediately past the end of the function.
|
||||
if (Offset == getSize())
|
||||
return getOutputAddress() + getOutputSize();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
return std::min(BB->getOutputAddressRange().first + Offset - BB->getOffset(),
|
||||
BB->getOutputAddressRange().second);
|
||||
}
|
||||
|
||||
DWARFAddressRangesVector BinaryFunction::translateInputToOutputRanges(
|
||||
const DWARFAddressRangesVector &InputRanges) const {
|
||||
// If the function hasn't changed return the same ranges.
|
||||
|
|
|
@ -1823,6 +1823,13 @@ public:
|
|||
/// Return output address ranges for a function.
|
||||
DWARFAddressRangesVector getOutputAddressRanges() const;
|
||||
|
||||
/// Given an address corresponding to an instruction in the input binary,
|
||||
/// return an address of this instruction in output binary.
|
||||
///
|
||||
/// Return 0 if no matching address could be found or the instruction was
|
||||
/// removed.
|
||||
uint64_t translateInputToOutputAddress(uint64_t Address) const;
|
||||
|
||||
/// Take address ranges corresponding to the input binary and translate
|
||||
/// them to address ranges in the output binary.
|
||||
DWARFAddressRangesVector translateInputToOutputRanges(
|
||||
|
|
|
@ -151,13 +151,13 @@ void RewriteInstance::updateUnitDebugInfo(
|
|||
// Handle any tag that can have DW_AT_location attribute.
|
||||
DWARFFormValue Value;
|
||||
uint32_t AttrOffset;
|
||||
const BinaryFunction *Function =
|
||||
FunctionStack.empty() ? nullptr : FunctionStack.back();
|
||||
if (DIE->getAttributeValue(Unit, dwarf::DW_AT_location, Value,
|
||||
&AttrOffset)) {
|
||||
if (Value.isFormClass(DWARFFormValue::FC_Constant) ||
|
||||
Value.isFormClass(DWARFFormValue::FC_SectionOffset)) {
|
||||
auto LocListSectionOffset = LocationListWriter->getEmptyListOffset();
|
||||
const BinaryFunction *Function =
|
||||
FunctionStack.empty() ? nullptr : FunctionStack.back();
|
||||
if (Function) {
|
||||
// Limit parsing to a single list to save memory.
|
||||
DWARFDebugLoc::LocationList LL;
|
||||
|
@ -172,8 +172,8 @@ void RewriteInstance::updateUnitDebugInfo(
|
|||
->translateInputToOutputLocationList(LL, Unit->getBaseAddress());
|
||||
DEBUG(
|
||||
if (OutputLL.Entries.empty()) {
|
||||
dbgs() << "BOLT-DEBUG: location list translated to an empty one "
|
||||
"at 0x"
|
||||
dbgs() << "BOLT-DEBUG: location list translated to an empty "
|
||||
"one at 0x"
|
||||
<< Twine::utohexstr(DIE->getOffset()) << " in CU at 0x"
|
||||
<< Twine::utohexstr(Unit->getOffset()) << '\n';
|
||||
}
|
||||
|
@ -191,6 +191,27 @@ void RewriteInstance::updateUnitDebugInfo(
|
|||
Value.isFormClass(DWARFFormValue::FC_Block)) &&
|
||||
"unexpected DW_AT_location form");
|
||||
}
|
||||
} else if (DIE->getAttributeValue(Unit, dwarf::DW_AT_low_pc, Value,
|
||||
&AttrOffset)) {
|
||||
const auto Result = Value.getAsAddress(Unit);
|
||||
if (Result.hasValue()) {
|
||||
uint64_t NewAddress = 0;
|
||||
if (Function) {
|
||||
const auto Address = Result.getValue();
|
||||
NewAddress = Function->translateInputToOutputAddress(Address);
|
||||
DEBUG(dbgs() << "BOLT-DEBUG: Fixing low_pc 0x"
|
||||
<< Twine::utohexstr(Address)
|
||||
<< " for DIE with tag " << DIE->getTag()
|
||||
<< " to 0x" << Twine::utohexstr(NewAddress) << '\n');
|
||||
}
|
||||
auto DebugInfoPatcher =
|
||||
static_cast<SimpleBinaryPatcher *>(
|
||||
SectionPatchers[".debug_info"].get());
|
||||
DebugInfoPatcher->addLE64Patch(AttrOffset, NewAddress);
|
||||
} else if (opts::Verbosity >= 1) {
|
||||
errs() << "BOLT-WARNING: unexpected form value for attribute at 0x"
|
||||
<< Twine::utohexstr(AttrOffset);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2410,7 +2410,7 @@ void RewriteInstance::updateOutputValues(const MCAsmLayout &Layout) {
|
|||
continue;
|
||||
|
||||
// Output ranges should match the input if the body hasn't changed.
|
||||
if (!Function.isSimple())
|
||||
if (!Function.isSimple() && !opts::Relocs)
|
||||
continue;
|
||||
|
||||
BinaryBasicBlock *PrevBB = nullptr;
|
||||
|
@ -2418,8 +2418,13 @@ void RewriteInstance::updateOutputValues(const MCAsmLayout &Layout) {
|
|||
BBI != BBE; ++BBI) {
|
||||
auto *BB = *BBI;
|
||||
assert(BB->getLabel()->isDefined(false) && "symbol should be defined");
|
||||
uint64_t BaseAddress = BB->isCold() ? Function.cold().getAddress()
|
||||
: Function.getOutputAddress();
|
||||
uint64_t BaseAddress;
|
||||
if (opts::Relocs) {
|
||||
BaseAddress = NewTextSectionStartAddress;
|
||||
} else {
|
||||
BaseAddress = BB->isCold() ? Function.cold().getAddress()
|
||||
: Function.getOutputAddress();
|
||||
}
|
||||
uint64_t Address = BaseAddress + Layout.getSymbolOffset(*BB->getLabel());
|
||||
BB->setOutputStartAddress(Address);
|
||||
|
||||
|
|
Loading…
Reference in New Issue