[BOLT][DWARF] Remove caching of ranges/abbrevs

Removing caching of ranges/abbrevs to simplify the code.
Before we were doing it to get around a gdb limitation.
FBD34015613

Reviewed By: Amir, maksfb

Differential Revision: https://reviews.llvm.org/D119276
This commit is contained in:
Alexander Yermolovich 2022-02-08 15:24:29 -08:00
parent 5af0f097ba
commit 0d9921daad
4 changed files with 36 additions and 159 deletions

View File

@ -108,9 +108,6 @@ class DWARFRewriter {
/// Output .dwp files.
void writeDWP(std::unordered_map<uint64_t, std::string> &DWOIdToName);
/// Abbreviations that were converted to use DW_AT_ranges.
std::set<const DWARFAbbreviationDeclaration *> ConvertedRangesAbbrevs;
/// DWARFDie contains a pointer to a DIE and hence gets invalidated once the
/// embedded DIE is destroyed. This wrapper class stores a DIE internally and
/// could be cast to a DWARFDie that is valid even after the initial DIE is
@ -135,8 +132,6 @@ class DWARFRewriter {
const DWARFAbbreviationDeclaration *,
std::vector<std::pair<DWARFDieWrapper, DebugAddressRange>>>;
PendingRangesType PendingRanges;
/// Convert \p Abbrev from using a simple DW_AT_(low|high)_pc range to
/// DW_AT_ranges with optional \p RangesBase.
void convertToRangesPatchAbbrev(const DWARFUnit &Unit,
@ -151,30 +146,10 @@ class DWARFRewriter {
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,
SimpleBinaryPatcher &DebugInfoPatcher);
/// Patch DW_AT_(low|high)_pc values for the \p DIE based on \p Range.
void patchLowHigh(DWARFDie DIE, DebugAddressRange Range,
SimpleBinaryPatcher &DebugInfoPatcher);
/// Convert pending ranges associated with the given \p Abbrev.
void convertPending(const DWARFUnit &Unit,
const DWARFAbbreviationDeclaration *Abbrev,
SimpleBinaryPatcher &DebugInfoPatcher,
DebugAbbrevWriter &AbbrevWriter);
/// Adds to Pending Ranges.
/// For Debug Fission also adding to .debug_addr to take care of a case where
/// some entries are not converted to ranges and left as
/// DW_AT_low_pc/DW_AT_high_pc.
void addToPendingRanges(const DWARFAbbreviationDeclaration *Abbrev,
DWARFDie DIE, DebugAddressRangesVector &Ranges,
Optional<uint64_t> DWOId);
/// Once all DIEs were seen, update DW_AT_(low|high)_pc values.
void flushPendingRanges(SimpleBinaryPatcher &DebugInfoPatcher);
SimpleBinaryPatcher &DebugInfoPatcher,
Optional<uint64_t> DWOId);
/// Helper function for creating and returning per-DWO patchers/writers.
template <class T, class Patcher>

View File

@ -321,8 +321,6 @@ void DWARFRewriter::updateDebugInfo() {
}
DebugInfoPatcher->clearDestinationLabels();
flushPendingRanges(*DebugInfoPatcher);
CUOffsetMap OffsetMap = finalizeDebugSections(*DebugInfoPatcher);
if (opts::WriteDWP)
@ -384,7 +382,6 @@ void DWARFRewriter::updateUnitDebugInfo(
}
case dwarf::DW_TAG_subprogram: {
// Get function address either from ranges or [LowPC, HighPC) pair.
bool UsesRanges = false;
uint64_t Address;
uint64_t SectionIndex, HighPC;
if (!DIE.getLowAndHighPC(Address, HighPC, SectionIndex)) {
@ -400,7 +397,6 @@ void DWARFRewriter::updateUnitDebugInfo(
break;
Address = Ranges.front().LowPC;
UsesRanges = true;
}
// Clear cached ranges as the new function will have its own set.
@ -410,37 +406,14 @@ void DWARFRewriter::updateUnitDebugInfo(
if (const BinaryFunction *Function =
BC.getBinaryFunctionAtAddress(Address))
FunctionRanges = Function->getOutputAddressRanges();
// Update ranges.
if (UsesRanges) {
updateDWARFObjectAddressRanges(
DIE, RangesSectionWriter->addRanges(FunctionRanges),
DebugInfoPatcher, AbbrevWriter);
} else {
// Delay conversion of [LowPC, HighPC) into DW_AT_ranges if possible.
const DWARFAbbreviationDeclaration *Abbrev =
DIE.getAbbreviationDeclarationPtr();
assert(Abbrev && "abbrev expected");
// Create a critical section.
static std::shared_timed_mutex CriticalSectionMutex;
std::unique_lock<std::shared_timed_mutex> Lock(CriticalSectionMutex);
if (FunctionRanges.empty())
FunctionRanges.push_back({0, 0});
updateDWARFObjectAddressRanges(
DIE, RangesSectionWriter->addRanges(FunctionRanges), DebugInfoPatcher,
AbbrevWriter);
if (FunctionRanges.size() > 1) {
convertPending(Unit, Abbrev, DebugInfoPatcher, AbbrevWriter);
// Exit critical section early.
Lock.unlock();
convertToRanges(DIE, FunctionRanges, DebugInfoPatcher);
} else if (ConvertedRangesAbbrevs.find(Abbrev) !=
ConvertedRangesAbbrevs.end()) {
// Exit critical section early.
Lock.unlock();
convertToRanges(DIE, FunctionRanges, DebugInfoPatcher);
} else {
if (FunctionRanges.empty())
FunctionRanges.emplace_back(DebugAddressRange());
addToPendingRanges(Abbrev, DIE, FunctionRanges, Unit.getDWOId());
}
}
break;
}
case dwarf::DW_TAG_lexical_block:
@ -1358,67 +1331,6 @@ void DWARFRewriter::updateGdbIndexSection(CUOffsetMap &CUMap) {
NewGdbIndexSize);
}
void DWARFRewriter::convertToRanges(DWARFDie DIE,
const DebugAddressRangesVector &Ranges,
SimpleBinaryPatcher &DebugInfoPatcher) {
uint64_t RangesSectionOffset;
if (Ranges.empty())
RangesSectionOffset = RangesSectionWriter->getEmptyRangesOffset();
else
RangesSectionOffset = RangesSectionWriter->addRanges(Ranges);
convertToRangesPatchDebugInfo(DIE, RangesSectionOffset, DebugInfoPatcher);
}
void DWARFRewriter::convertPending(const DWARFUnit &Unit,
const DWARFAbbreviationDeclaration *Abbrev,
SimpleBinaryPatcher &DebugInfoPatcher,
DebugAbbrevWriter &AbbrevWriter) {
if (ConvertedRangesAbbrevs.count(Abbrev))
return;
convertToRangesPatchAbbrev(Unit, Abbrev, AbbrevWriter);
auto I = PendingRanges.find(Abbrev);
if (I != PendingRanges.end()) {
for (std::pair<DWARFDieWrapper, DebugAddressRange> &Pair : I->second)
convertToRanges(Pair.first, {Pair.second}, DebugInfoPatcher);
PendingRanges.erase(I);
}
ConvertedRangesAbbrevs.emplace(Abbrev);
}
void DWARFRewriter::addToPendingRanges(
const DWARFAbbreviationDeclaration *Abbrev, DWARFDie DIE,
DebugAddressRangesVector &FunctionRanges, Optional<uint64_t> DWOId) {
Optional<DWARFFormValue> LowPcValue = DIE.find(dwarf::DW_AT_low_pc);
Optional<DWARFFormValue> HighPcValue = DIE.find(dwarf::DW_AT_high_pc);
if (LowPcValue &&
LowPcValue->getForm() == dwarf::Form::DW_FORM_GNU_addr_index) {
assert(DWOId && "Invalid DWO ID.");
(void)DWOId;
assert(HighPcValue && "Low PC exists, but not High PC.");
(void)HighPcValue;
uint64_t IndexL = LowPcValue->getRawUValue();
uint64_t IndexH = HighPcValue->getRawUValue();
for (auto Address : FunctionRanges) {
AddrWriter->addIndexAddress(Address.LowPC, IndexL, *DWOId);
// 2.17.2
// If the value of the DW_AT_high_pc is of class address, it is the
// relocated address of the first location past the last instruction
// associated with the entity; if it is of class constant, the value is
// an unsigned integer offset which when added to the low PC gives the
// address of the first location past the last instruction associated
// with the entity.
if (!HighPcValue->isFormClass(DWARFFormValue::FC_Constant))
AddrWriter->addIndexAddress(Address.HighPC, IndexH, *DWOId);
}
}
PendingRanges[Abbrev].emplace_back(
std::make_pair(DWARFDieWrapper(DIE), FunctionRanges.front()));
}
std::unique_ptr<DebugBufferVector>
DWARFRewriter::makeFinalLocListsSection(SimpleBinaryPatcher &DebugInfoPatcher) {
auto LocBuffer = std::make_unique<DebugBufferVector>();
@ -1452,15 +1364,6 @@ DWARFRewriter::makeFinalLocListsSection(SimpleBinaryPatcher &DebugInfoPatcher) {
return LocBuffer;
}
void DWARFRewriter::flushPendingRanges(SimpleBinaryPatcher &DebugInfoPatcher) {
for (std::pair<const DWARFAbbreviationDeclaration *const,
std::vector<std::pair<DWARFDieWrapper, DebugAddressRange>>>
&I : PendingRanges)
for (std::pair<DWARFDieWrapper, DebugAddressRange> &RangePair : I.second)
patchLowHigh(RangePair.first, RangePair.second, DebugInfoPatcher);
clearList(PendingRanges);
}
namespace {
void getRangeAttrData(DWARFDie DIE, Optional<AttrInfo> &LowPCVal,
@ -1499,7 +1402,8 @@ void getRangeAttrData(DWARFDie DIE, Optional<AttrInfo> &LowPCVal,
} // namespace
void DWARFRewriter::patchLowHigh(DWARFDie DIE, DebugAddressRange Range,
SimpleBinaryPatcher &DebugInfoPatcher) {
SimpleBinaryPatcher &DebugInfoPatcher,
Optional<uint64_t> DWOId) {
Optional<AttrInfo> LowPCVal = None;
Optional<AttrInfo> HighPCVal = None;
getRangeAttrData(DIE, LowPCVal, HighPCVal);
@ -1507,14 +1411,22 @@ void DWARFRewriter::patchLowHigh(DWARFDie DIE, DebugAddressRange Range,
uint64_t HighPCOffset = HighPCVal->Offset;
auto *TempDebugPatcher = &DebugInfoPatcher;
if (LowPCVal->V.getForm() == dwarf::DW_FORM_GNU_addr_index) {
DWARFUnit *Unit = DIE.getDwarfUnit();
assert(Unit->isDWOUnit() && "DW_FORM_GNU_addr_index not part of DWO.");
uint32_t AddressIndex =
AddrWriter->getIndexFromAddress(Range.LowPC, *Unit->getDWOId());
TempDebugPatcher = getBinaryDWODebugInfoPatcher(*Unit->getDWOId());
TempDebugPatcher->addUDataPatch(LowPCOffset, AddressIndex,
std::abs(int(HighPCOffset - LowPCOffset)));
// TODO: In DWARF5 support ULEB128 for high_pc
AddrWriter->getIndexFromAddress(Range.LowPC, *DWOId);
TempDebugPatcher = getBinaryDWODebugInfoPatcher(*DWOId);
TempDebugPatcher->addUDataPatch(LowPCOffset, AddressIndex, LowPCVal->Size);
// 2.17.2
// If the value of the DW_AT_high_pc is of class address, it is the
// relocated address of the first location past the last instruction
// associated with the entity; if it is of class constant, the value is
// an unsigned integer offset which when added to the low PC gives the
// address of the first location past the last instruction associated
// with the entity.
if (!HighPCVal->V.isFormClass(DWARFFormValue::FC_Constant)) {
AddressIndex = AddrWriter->getIndexFromAddress(Range.HighPC, *DWOId);
TempDebugPatcher->addUDataPatch(HighPCOffset, AddressIndex,
HighPCVal->Size);
}
} else {
TempDebugPatcher->addLE64Patch(LowPCOffset, Range.LowPC);
}

View File

@ -19,33 +19,23 @@
# RUN: --update-debug-sections \
# RUN: --dwarf-output-path=%T \
# RUN: -o %t.bolt.1.exe 2>&1 | FileCheck %s
# RUN: llvm-dwarfdump --show-form --verbose \
# RUN: --debug-info \
# RUN: %T/debug-fission-simple.dwo0.dwo \
# RUN: | grep DW_FORM_GNU_addr_index \
# RUN: | FileCheck %s --check-prefix=CHECK-ADDR-INDEX
# RUN: llvm-dwarfdump --show-form --verbose \
# RUN: --debug-addr \
# RUN: %t.bolt.1.exe \
# RUN: | FileCheck %s --check-prefix=CHECK-ADDR-SEC
# RUN: not llvm-dwarfdump --show-form --verbose --debug-info %T/debug-fission-simple.dwo0.dwo -o %tAddrIndexTest 2> /dev/null
# RUN: cat %tAddrIndexTest | grep DW_FORM_GNU_addr_index | FileCheck %s --check-prefix=CHECK-ADDR-INDEX
# RUN: llvm-dwarfdump --show-form --verbose --debug-addr %t.bolt.1.exe | FileCheck %s --check-prefix=CHECK-ADDR-SEC
# CHECK-NOT: warning: DWARF unit from offset {{.*}} incl. to offset {{.*}} excl. tries to read DIEs at offset {{.*}}
# CHECK-ADDR-INDEX: DW_AT_low_pc [DW_FORM_GNU_addr_index] (indexed (00000001)
# CHECK-ADDR-INDEX: DW_AT_low_pc [DW_FORM_GNU_addr_index] (indexed (00000002)
# CHECK-ADDR-INDEX: DW_AT_low_pc [DW_FORM_GNU_addr_index] (indexed (00000003)
# CHECK-ADDR-INDEX: DW_AT_low_pc [DW_FORM_GNU_addr_index] (indexed (00000000)
# CHECK-ADDR-INDEX: DW_AT_low_pc [DW_FORM_GNU_addr_index] (indexed (00000000)
# CHECK-ADDR-INDEX: DW_AT_low_pc [DW_FORM_GNU_addr_index] (indexed (00000000)
# CHECK-ADDR-SEC: .debug_addr contents:
# CHECK-ADDR-SEC: 0x00000000: Addrs: [
# CHECK-ADDR-SEC: 0x0000000000601000
# CHECK-ADDR-SEC: 0x0000000000a00000
# CHECK-ADDR-SEC: 0x0000000000000000
# CHECK-ADDR-SEC: 0x0000000000a00040
# RUN: llvm-bolt %t.exe --reorder-blocks=reverse -update-debug-sections \
# RUN: -dwarf-output-path=%T -o %t.bolt.2.exe --write-dwp=true
# RUN: llvm-dwarfdump --show-form --verbose --debug-info %t.bolt.2.exe.dwp \
# RUN: | FileCheck %s --check-prefix=CHECK-DWP-DEBUG
# RUN: llvm-bolt %t.exe --reorder-blocks=reverse -update-debug-sections -dwarf-output-path=%T -o %t.bolt.2.exe --write-dwp=true
# RUN: not llvm-dwarfdump --show-form --verbose --debug-info %t.bolt.2.exe.dwp -o %tAddrIndexTestDwp 2> /dev/null
# RUN: cat %tAddrIndexTestDwp | FileCheck %s --check-prefix=CHECK-DWP-DEBUG
# CHECK-DWP-DEBUG: DW_TAG_compile_unit [1] *
# CHECK-DWP-DEBUG: DW_AT_producer [DW_FORM_GNU_str_index] (indexed (0000000a) string = "clang version 13.0.0")

View File

@ -18,8 +18,8 @@ RUN: llvm-dwarfdump -gdb-index %tfile.exe.bolt | FileCheck %s
; CHECK: Version = 7
; CHECK: CU list offset = 0x18, has 2 entries:
; CHECK-NEXT: 0: Offset = 0x0, Length = 0x4f
; CHECK-NEXT: 1: Offset = 0x4f, Length = 0x53
; CHECK-NEXT: 0: Offset = 0x0, Length = 0x4b
; CHECK-NEXT: 1: Offset = 0x4b, Length = 0x4f
; CHECK: Types CU list offset = 0x38, has 0 entries: