[BOLT][DWARF] Change convertToRanges to not use indirect

Summary:
Now that we are re-writing .debug_info we are not longer restricted to have same size patches.
Simplifying logic to use direct forms.

(cherry picked from FBD32971159)
This commit is contained in:
Alexander Yermolovich 2021-12-07 17:35:12 -08:00 committed by Maksim Panchenko
parent 6bb26fcb20
commit 9bf7a73787
2 changed files with 28 additions and 60 deletions

View File

@ -139,17 +139,17 @@ class DWARFRewriter {
/// Convert \p Abbrev from using a simple DW_AT_(low|high)_pc range to
/// DW_AT_ranges with optional \p RangesBase.
void convertToRanges(const DWARFUnit &Unit,
const DWARFAbbreviationDeclaration *Abbrev,
DebugAbbrevWriter &AbbrevWriter,
Optional<uint64_t> RangesBase = None);
void convertToRangesPatchAbbrev(const DWARFUnit &Unit,
const DWARFAbbreviationDeclaration *Abbrev,
DebugAbbrevWriter &AbbrevWriter,
Optional<uint64_t> RangesBase = None);
/// Update \p DIE that was using DW_AT_(low|high)_pc with DW_AT_ranges offset.
/// Updates to the DIE should be synced with abbreviation updates using the
/// function above.
void convertToRanges(DWARFDie DIE, uint64_t RangesSectionOffset,
SimpleBinaryPatcher &DebugInfoPatcher,
Optional<uint64_t> RangesBase = None);
void convertToRangesPatchDebugInfo(DWARFDie DIE, uint64_t RangesSectionOffset,
SimpleBinaryPatcher &DebugInfoPatcher,
Optional<uint64_t> RangesBase = None);
/// Same as above, but takes a vector of \p Ranges as a parameter.
void convertToRanges(DWARFDie DIE, const DebugAddressRangesVector &Ranges,

View File

@ -710,9 +710,10 @@ void DWARFRewriter::updateDWARFObjectAddressRanges(
// to back. Replace with new attributes and patch the DIE.
if (AbbreviationDecl->findAttributeIndex(dwarf::DW_AT_low_pc) &&
AbbreviationDecl->findAttributeIndex(dwarf::DW_AT_high_pc)) {
convertToRanges(*DIE.getDwarfUnit(), AbbreviationDecl, AbbrevWriter,
RangesBase);
convertToRanges(DIE, DebugRangesOffset, DebugInfoPatcher, RangesBase);
convertToRangesPatchAbbrev(*DIE.getDwarfUnit(), AbbreviationDecl,
AbbrevWriter, RangesBase);
convertToRangesPatchDebugInfo(DIE, DebugRangesOffset, DebugInfoPatcher,
RangesBase);
} else {
if (opts::Verbosity >= 1)
errs() << "BOLT-ERROR: cannot update ranges for DIE at offset 0x"
@ -1332,7 +1333,7 @@ void DWARFRewriter::convertToRanges(DWARFDie DIE,
else
RangesSectionOffset = RangesSectionWriter->addRanges(Ranges);
convertToRanges(DIE, RangesSectionOffset, DebugInfoPatcher);
convertToRangesPatchDebugInfo(DIE, RangesSectionOffset, DebugInfoPatcher);
}
void DWARFRewriter::convertPending(const DWARFUnit &Unit,
@ -1342,7 +1343,7 @@ void DWARFRewriter::convertPending(const DWARFUnit &Unit,
if (ConvertedRangesAbbrevs.count(Abbrev))
return;
convertToRanges(Unit, Abbrev, AbbrevWriter);
convertToRangesPatchAbbrev(Unit, Abbrev, AbbrevWriter);
auto I = PendingRanges.find(Abbrev);
if (I != PendingRanges.end()) {
@ -1485,33 +1486,23 @@ void DWARFRewriter::patchLowHigh(DWARFDie DIE, DebugAddressRange Range,
HighPCVal->Size);
}
void DWARFRewriter::convertToRanges(const DWARFUnit &Unit,
const DWARFAbbreviationDeclaration *Abbrev,
DebugAbbrevWriter &AbbrevWriter,
Optional<uint64_t> RangesBase) {
void DWARFRewriter::convertToRangesPatchAbbrev(
const DWARFUnit &Unit, const DWARFAbbreviationDeclaration *Abbrev,
DebugAbbrevWriter &AbbrevWriter, Optional<uint64_t> RangesBase) {
auto getAttributeForm = [&Abbrev](const dwarf::Attribute Attr) {
Optional<uint32_t> Index = Abbrev->findAttributeIndex(Attr);
assert(Index && "attribute not found");
return Abbrev->getFormByIndex(*Index);
};
dwarf::Form HighPCForm = getAttributeForm(dwarf::DW_AT_high_pc);
dwarf::Form LowPCForm = getAttributeForm(dwarf::DW_AT_low_pc);
// DW_FORM_GNU_addr_index is already variable encoding so nothing to do
// there. If HighForm is 8 bytes need to change low_pc to be variable
// encoding to consume extra bytes from high_pc, since DW_FORM_sec_offset is
// 4 bytes for DWARF32.
// FIXME: update comments
// there.
if (RangesBase) {
assert(LowPCForm != dwarf::DW_FORM_GNU_addr_index);
AbbrevWriter.addAttributePatch(Unit, Abbrev, dwarf::DW_AT_low_pc,
dwarf::DW_AT_GNU_ranges_base,
dwarf::DW_FORM_indirect);
} else if (LowPCForm != dwarf::DW_FORM_GNU_addr_index &&
isHighPcFormEightBytes(HighPCForm)) {
AbbrevWriter.addAttributePatch(Unit, Abbrev, dwarf::DW_AT_low_pc,
dwarf::DW_AT_low_pc,
dwarf::DW_FORM_indirect);
dwarf::DW_FORM_sec_offset);
}
AbbrevWriter.addAttributePatch(Unit, Abbrev, dwarf::DW_AT_high_pc,
@ -1519,53 +1510,30 @@ void DWARFRewriter::convertToRanges(const DWARFUnit &Unit,
dwarf::DW_FORM_sec_offset);
}
void DWARFRewriter::convertToRanges(DWARFDie DIE, uint64_t RangesSectionOffset,
SimpleBinaryPatcher &DebugInfoPatcher,
Optional<uint64_t> RangesBase) {
void DWARFRewriter::convertToRangesPatchDebugInfo(
DWARFDie DIE, uint64_t RangesSectionOffset,
SimpleBinaryPatcher &DebugInfoPatcher, Optional<uint64_t> RangesBase) {
Optional<AttrInfo> LowPCVal = None;
Optional<AttrInfo> HighPCVal = None;
getRangeAttrData(DIE, LowPCVal, HighPCVal);
uint64_t LowPCOffset = LowPCVal->Offset;
uint64_t HighPCOffset = HighPCVal->Offset;
// Size to fill with the first field (DW_AT_low_pc or DW_AT_GNU_ranges_base).
unsigned NumBytesToFill = 0;
assert(DIE.getDwarfUnit()->getAddressByteSize() == 8);
if (isHighPcFormEightBytes(HighPCVal->V.getForm())) {
NumBytesToFill = 12;
} else if (HighPCVal->V.getForm() == dwarf::DW_FORM_data4) {
NumBytesToFill = 8;
} else {
llvm_unreachable("unexpected DW_AT_high_pc form");
}
std::lock_guard<std::mutex> Lock(DebugInfoPatcherMutex);
uint32_t BaseOffset = 0;
if (LowPCVal->V.getForm() == dwarf::DW_FORM_GNU_addr_index) {
// Use ULEB128 for the value.
DebugInfoPatcher.addUDataPatch(LowPCOffset, 0,
std::abs(int(HighPCOffset - LowPCOffset)) +
NumBytesToFill - 8);
std::abs(int(HighPCOffset - LowPCOffset)));
// Ranges are relative to DW_AT_GNU_ranges_base.
BaseOffset = DebugInfoPatcher.getRangeBase();
} else {
if (RangesBase) {
assert(NumBytesToFill == LowPCVal->Size &&
"Bytes to fill not equal to LocPCVal Size");
DebugInfoPatcher.addUDataPatch(LowPCOffset, dwarf::DW_FORM_udata, 1);
DebugInfoPatcher.addUDataPatch(LowPCOffset + 1, *RangesBase,
LowPCVal->Size - 1);
} else if (NumBytesToFill == 12) {
// Creatively encoding dwarf::DW_FORM_addr in to 4 bytes.
// Write an indirect 0 value for DW_AT_low_pc so that we can fill
// 12 bytes of space.
DebugInfoPatcher.addUDataPatch(LowPCOffset, dwarf::DW_FORM_addr, 4);
DebugInfoPatcher.addLE64Patch(LowPCOffset + 4, 0);
} else {
// NumBytesToFill == 8
// If case DW_AT_low_pc was converted into DW_AT_GNU_ranges_base
if (RangesBase)
DebugInfoPatcher.addLE32Patch(LowPCOffset, *RangesBase, 8);
else
DebugInfoPatcher.addLE64Patch(LowPCOffset, 0);
}
}
DebugInfoPatcher.addLE32Patch(HighPCOffset + NumBytesToFill - 8,
RangesSectionOffset - BaseOffset);
DebugInfoPatcher.addLE32Patch(HighPCOffset, RangesSectionOffset - BaseOffset,
HighPCVal->Size);
}