diff --git a/bolt/include/bolt/Rewrite/DWARFRewriter.h b/bolt/include/bolt/Rewrite/DWARFRewriter.h --- a/bolt/include/bolt/Rewrite/DWARFRewriter.h +++ b/bolt/include/bolt/Rewrite/DWARFRewriter.h @@ -108,9 +108,6 @@ /// Output .dwp files. void writeDWP(std::unordered_map &DWOIdToName); - /// Abbreviations that were converted to use DW_AT_ranges. - std::set 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 @@ const DWARFAbbreviationDeclaration *, std::vector>>; - 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 @@ SimpleBinaryPatcher &DebugInfoPatcher, Optional 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 DWOId); - - /// Once all DIEs were seen, update DW_AT_(low|high)_pc values. - void flushPendingRanges(SimpleBinaryPatcher &DebugInfoPatcher); + SimpleBinaryPatcher &DebugInfoPatcher, + Optional DWOId); /// Helper function for creating and returning per-DWO patchers/writers. template diff --git a/bolt/lib/Rewrite/DWARFRewriter.cpp b/bolt/lib/Rewrite/DWARFRewriter.cpp --- a/bolt/lib/Rewrite/DWARFRewriter.cpp +++ b/bolt/lib/Rewrite/DWARFRewriter.cpp @@ -321,8 +321,6 @@ } DebugInfoPatcher->clearDestinationLabels(); - flushPendingRanges(*DebugInfoPatcher); - CUOffsetMap OffsetMap = finalizeDebugSections(*DebugInfoPatcher); if (opts::WriteDWP) @@ -384,7 +382,6 @@ } 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 @@ break; Address = Ranges.front().LowPC; - UsesRanges = true; } // Clear cached ranges as the new function will have its own set. @@ -410,37 +406,14 @@ 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 Lock(CriticalSectionMutex); - - 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()); - } - } + + if (FunctionRanges.empty()) + FunctionRanges.push_back({0, 0}); + + updateDWARFObjectAddressRanges( + DIE, RangesSectionWriter->addRanges(FunctionRanges), DebugInfoPatcher, + AbbrevWriter); + break; } case dwarf::DW_TAG_lexical_block: @@ -1358,67 +1331,6 @@ 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 &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 DWOId) { - Optional LowPcValue = DIE.find(dwarf::DW_AT_low_pc); - Optional 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 DWARFRewriter::makeFinalLocListsSection(SimpleBinaryPatcher &DebugInfoPatcher) { auto LocBuffer = std::make_unique(); @@ -1452,15 +1364,6 @@ return LocBuffer; } -void DWARFRewriter::flushPendingRanges(SimpleBinaryPatcher &DebugInfoPatcher) { - for (std::pair>> - &I : PendingRanges) - for (std::pair &RangePair : I.second) - patchLowHigh(RangePair.first, RangePair.second, DebugInfoPatcher); - clearList(PendingRanges); -} - namespace { void getRangeAttrData(DWARFDie DIE, Optional &LowPCVal, @@ -1499,7 +1402,8 @@ } // namespace void DWARFRewriter::patchLowHigh(DWARFDie DIE, DebugAddressRange Range, - SimpleBinaryPatcher &DebugInfoPatcher) { + SimpleBinaryPatcher &DebugInfoPatcher, + Optional DWOId) { Optional LowPCVal = None; Optional HighPCVal = None; getRangeAttrData(DIE, LowPCVal, HighPCVal); @@ -1507,14 +1411,22 @@ 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); } diff --git a/bolt/test/X86/debug-fission-single.s b/bolt/test/X86/debug-fission-single.s --- a/bolt/test/X86/debug-fission-single.s +++ b/bolt/test/X86/debug-fission-single.s @@ -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") diff --git a/bolt/test/X86/gdbindex.test b/bolt/test/X86/gdbindex.test --- a/bolt/test/X86/gdbindex.test +++ b/bolt/test/X86/gdbindex.test @@ -18,8 +18,8 @@ ; 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: