forked from OSchip/llvm-project
[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:
parent
5af0f097ba
commit
0d9921daad
|
@ -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>
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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:
|
||||
|
||||
|
|
Loading…
Reference in New Issue