diff options
-rw-r--r-- | bolt/include/bolt/Core/DebugData.h | 64 | ||||
-rw-r--r-- | bolt/include/bolt/Rewrite/DWARFRewriter.h | 15 | ||||
-rw-r--r-- | bolt/lib/Core/DebugData.cpp | 100 | ||||
-rw-r--r-- | bolt/lib/Rewrite/DWARFRewriter.cpp | 97 | ||||
-rw-r--r-- | bolt/test/X86/dwarf5-addr-section-reuse.s | 6 |
5 files changed, 165 insertions, 117 deletions
diff --git a/bolt/include/bolt/Core/DebugData.h b/bolt/include/bolt/Core/DebugData.h index 2324e57..5935ffa 100644 --- a/bolt/include/bolt/Core/DebugData.h +++ b/bolt/include/bolt/Core/DebugData.h @@ -256,7 +256,7 @@ public: }; virtual ~DebugRangeListsSectionWriter(){}; - static void setAddressWriter(DebugAddrWriter *AddrW) { AddrWriter = AddrW; } + void setAddressWriter(DebugAddrWriter *AddrW) { AddrWriter = AddrW; } /// Add ranges with caching. uint64_t addRanges( @@ -284,7 +284,7 @@ public: } private: - static DebugAddrWriter *AddrWriter; + DebugAddrWriter *AddrWriter = nullptr; /// Used to find unique CU ID. DWARFUnit *CU; /// Current relative offset of range list entry within this CUs rangelist @@ -336,21 +336,36 @@ using AddressSectionBuffer = SmallVector<char, 4>; class DebugAddrWriter { public: DebugAddrWriter() = delete; - DebugAddrWriter(BinaryContext *BC_); + DebugAddrWriter(BinaryContext *BC_) : DebugAddrWriter(BC_, UCHAR_MAX) {}; + DebugAddrWriter(BinaryContext *BC_, uint8_t AddressByteSize); virtual ~DebugAddrWriter(){}; /// Given an address returns an index in .debug_addr. /// Adds Address to map. uint32_t getIndexFromAddress(uint64_t Address, DWARFUnit &CU); /// Write out entries in to .debug_addr section for CUs. - virtual void update(DIEBuilder &DIEBlder, DWARFUnit &CUs); + virtual std::optional<uint64_t> finalize(const size_t BufferSize); /// Return buffer with all the entries in .debug_addr already writen out using /// update(...). - virtual AddressSectionBuffer &finalize() { return *Buffer; } + virtual std::unique_ptr<AddressSectionBuffer> releaseBuffer() { + return std::move(Buffer); + } + + /// Returns buffer size. + virtual size_t getBufferSize() const { return Buffer->size(); } + + /// Returns True if Buffer is not empty. + bool isInitialized() const { return !Buffer->empty(); } - /// Returns False if .debug_addr section was created.. - bool isInitialized() const { return !AddressMaps.empty(); } + /// Updates address base with the given Offset. + virtual void updateAddrBase(DIEBuilder &DIEBlder, DWARFUnit &CU, + const uint64_t Offset); + + /// Appends an AddressSectionBuffer to the address writer's buffer. + void appendToAddressBuffer(const AddressSectionBuffer &Buffer) { + *AddressStream << Buffer; + } protected: class AddressForDWOCU { @@ -407,23 +422,32 @@ protected: } BinaryContext *BC; - /// Maps DWOID to AddressForDWOCU. - std::unordered_map<uint64_t, AddressForDWOCU> AddressMaps; + /// Address for the DWO CU associated with the address writer. + AddressForDWOCU Map; + uint8_t AddressByteSize; /// Mutex used for parallel processing of debug info. std::mutex WriterMutex; std::unique_ptr<AddressSectionBuffer> Buffer; std::unique_ptr<raw_svector_ostream> AddressStream; /// Used to track sections that were not modified so that they can be re-used. - DenseMap<uint64_t, uint64_t> UnmodifiedAddressOffsets; + static DenseMap<uint64_t, uint64_t> UnmodifiedAddressOffsets; }; class DebugAddrWriterDwarf5 : public DebugAddrWriter { public: DebugAddrWriterDwarf5() = delete; DebugAddrWriterDwarf5(BinaryContext *BC) : DebugAddrWriter(BC) {} + DebugAddrWriterDwarf5(BinaryContext *BC, uint8_t AddressByteSize, + std::optional<uint64_t> AddrOffsetSectionBase) + : DebugAddrWriter(BC, AddressByteSize), + AddrOffsetSectionBase(AddrOffsetSectionBase) {} /// Write out entries in to .debug_addr section for CUs. - virtual void update(DIEBuilder &DIEBlder, DWARFUnit &CUs) override; + virtual std::optional<uint64_t> finalize(const size_t BufferSize) override; + + /// Updates address base with the given Offset. + virtual void updateAddrBase(DIEBuilder &DIEBlder, DWARFUnit &CU, + const uint64_t Offset) override; protected: /// Given DWARFUnit \p Unit returns either DWO ID or it's offset within @@ -435,6 +459,10 @@ protected: } return Unit.getOffset(); } + +private: + std::optional<uint64_t> AddrOffsetSectionBase = std::nullopt; + static constexpr uint32_t HeaderSize = 8; }; /// This class is NOT thread safe. @@ -583,12 +611,10 @@ class DebugLoclistWriter : public DebugLocWriter { public: ~DebugLoclistWriter() {} DebugLoclistWriter() = delete; - DebugLoclistWriter(DWARFUnit &Unit, uint8_t DV, bool SD) - : DebugLocWriter(DV, LocWriterKind::DebugLoclistWriter), CU(Unit), - IsSplitDwarf(SD) { - assert(DebugLoclistWriter::AddrWriter && - "Please use SetAddressWriter to initialize " - "DebugAddrWriter before instantiation."); + DebugLoclistWriter(DWARFUnit &Unit, uint8_t DV, bool SD, + DebugAddrWriter &AddrW) + : DebugLocWriter(DV, LocWriterKind::DebugLoclistWriter), + AddrWriter(AddrW), CU(Unit), IsSplitDwarf(SD) { if (DwarfVersion >= 5) { LocBodyBuffer = std::make_unique<DebugBufferVector>(); LocBodyStream = std::make_unique<raw_svector_ostream>(*LocBodyBuffer); @@ -600,8 +626,6 @@ public: } } - static void setAddressWriter(DebugAddrWriter *AddrW) { AddrWriter = AddrW; } - /// Stores location lists internally to be written out during finalize phase. virtual void addList(DIEBuilder &DIEBldr, DIE &Die, DIEValue &AttrInfo, DebugLocationsVector &LocList) override; @@ -630,7 +654,7 @@ private: /// Writes out locations in to a local buffer and applies debug info patches. void finalizeDWARF5(DIEBuilder &DIEBldr, DIE &Die); - static DebugAddrWriter *AddrWriter; + DebugAddrWriter &AddrWriter; DWARFUnit &CU; bool IsSplitDwarf{false}; // Used for DWARF5 to store location lists before being finalized. diff --git a/bolt/include/bolt/Rewrite/DWARFRewriter.h b/bolt/include/bolt/Rewrite/DWARFRewriter.h index 4f576eaa..abd18b5 100644 --- a/bolt/include/bolt/Rewrite/DWARFRewriter.h +++ b/bolt/include/bolt/Rewrite/DWARFRewriter.h @@ -66,10 +66,6 @@ private: /// .debug_aranges DWARF section. std::unique_ptr<DebugARangesSectionWriter> ARangesSectionWriter; - /// Stores and serializes information that will be put into the - /// .debug_addr DWARF section. - std::unique_ptr<DebugAddrWriter> AddrWriter; - /// Stores and serializes information that will be put in to the /// .debug_addr DWARF section. /// Does not do de-duplication. @@ -93,6 +89,10 @@ private: std::unordered_map<uint64_t, std::unique_ptr<DebugRangesSectionWriter>> LegacyRangesWritersByCU; + /// Stores address writer for each CU. + std::unordered_map<uint64_t, std::unique_ptr<DebugAddrWriter>> + AddressWritersByCU; + std::mutex LocListDebugInfoPatchesMutex; /// Dwo id specific its RangesBase. @@ -115,6 +115,7 @@ private: void updateUnitDebugInfo(DWARFUnit &Unit, DIEBuilder &DIEBldr, DebugLocWriter &DebugLocWriter, DebugRangesSectionWriter &RangesSectionWriter, + DebugAddrWriter &AddressWriter, std::optional<uint64_t> RangesBase = std::nullopt); /// Patches the binary for an object's address ranges to be updated. @@ -141,13 +142,15 @@ private: /// Process and write out CUs that are passsed in. void finalizeCompileUnits(DIEBuilder &DIEBlder, DIEStreamer &Streamer, CUOffsetMap &CUMap, - const std::list<DWARFUnit *> &CUs); + const std::list<DWARFUnit *> &CUs, + DebugAddrWriter &FinalAddrWriter); /// Finalize debug sections in the main binary. void finalizeDebugSections(DIEBuilder &DIEBlder, DWARF5AcceleratorTable &DebugNamesTable, DIEStreamer &Streamer, raw_svector_ostream &ObjOS, - CUOffsetMap &CUMap); + CUOffsetMap &CUMap, + DebugAddrWriter &FinalAddrWriter); /// Patches the binary for DWARF address ranges (e.g. in functions and lexical /// blocks) to be updated. diff --git a/bolt/lib/Core/DebugData.cpp b/bolt/lib/Core/DebugData.cpp index 76c3545..002f58c 100644 --- a/bolt/lib/Core/DebugData.cpp +++ b/bolt/lib/Core/DebugData.cpp @@ -184,8 +184,6 @@ void DebugRangesSectionWriter::appendToRangeBuffer( *RangesStream << CUBuffer; } -DebugAddrWriter *DebugRangeListsSectionWriter::AddrWriter = nullptr; - uint64_t DebugRangeListsSectionWriter::addRanges( DebugAddressRangesVector &&Ranges, std::map<DebugAddressRangesVector, uint64_t> &CachedRanges) { @@ -390,7 +388,9 @@ void DebugARangesSectionWriter::writeARangesSection( } } -DebugAddrWriter::DebugAddrWriter(BinaryContext *BC) : BC(BC) { +DebugAddrWriter::DebugAddrWriter(BinaryContext *BC, + const uint8_t AddressByteSize) + : BC(BC), AddressByteSize(AddressByteSize) { Buffer = std::make_unique<AddressSectionBuffer>(); AddressStream = std::make_unique<raw_svector_ostream>(*Buffer); } @@ -405,11 +405,6 @@ void DebugAddrWriter::AddressForDWOCU::dump() { } uint32_t DebugAddrWriter::getIndexFromAddress(uint64_t Address, DWARFUnit &CU) { std::lock_guard<std::mutex> Lock(WriterMutex); - const uint64_t CUID = getCUID(CU); - if (!AddressMaps.count(CUID)) - AddressMaps[CUID] = AddressForDWOCU(); - - AddressForDWOCU &Map = AddressMaps[CUID]; auto Entry = Map.find(Address); if (Entry == Map.end()) { auto Index = Map.getNextIndex(); @@ -449,29 +444,23 @@ static void updateAddressBase(DIEBuilder &DIEBlder, DebugAddrWriter &AddrWriter, } } -void DebugAddrWriter::update(DIEBuilder &DIEBlder, DWARFUnit &CU) { - // Handling the case where debug information is a mix of Debug fission and - // monolithic. - if (!CU.getDWOId()) - return; - const uint64_t CUID = getCUID(CU); - auto AM = AddressMaps.find(CUID); - // Adding to map even if it did not contribute to .debug_addr. - // The Skeleton CU might still have DW_AT_GNU_addr_base. - uint64_t Offset = Buffer->size(); - // If does not exist this CUs DWO section didn't contribute to .debug_addr. - if (AM == AddressMaps.end()) - return; - std::vector<IndexAddressPair> SortedMap(AM->second.indexToAddressBegin(), - AM->second.indexToAdddessEnd()); +void DebugAddrWriter::updateAddrBase(DIEBuilder &DIEBlder, DWARFUnit &CU, + const uint64_t Offset) { + updateAddressBase(DIEBlder, *this, CU, Offset); +} + +std::optional<uint64_t> DebugAddrWriter::finalize(const size_t BufferSize) { + if (Map.begin() == Map.end()) + return std::nullopt; + std::vector<IndexAddressPair> SortedMap(Map.indexToAddressBegin(), + Map.indexToAdddessEnd()); // Sorting address in increasing order of indices. llvm::sort(SortedMap, llvm::less_first()); - uint8_t AddrSize = CU.getAddressByteSize(); uint32_t Counter = 0; auto WriteAddress = [&](uint64_t Address) -> void { ++Counter; - switch (AddrSize) { + switch (AddressByteSize) { default: assert(false && "Address Size is invalid."); break; @@ -490,10 +479,19 @@ void DebugAddrWriter::update(DIEBuilder &DIEBlder, DWARFUnit &CU) { WriteAddress(0); WriteAddress(Val.second); } - updateAddressBase(DIEBlder, *this, CU, Offset); + return std::nullopt; +} + +void DebugAddrWriterDwarf5::updateAddrBase(DIEBuilder &DIEBlder, DWARFUnit &CU, + const uint64_t Offset) { + /// Header for DWARF5 has size 8, so we add it to the offset. + updateAddressBase(DIEBlder, *this, CU, Offset + HeaderSize); } -void DebugAddrWriterDwarf5::update(DIEBuilder &DIEBlder, DWARFUnit &CU) { +DenseMap<uint64_t, uint64_t> DebugAddrWriter::UnmodifiedAddressOffsets; + +std::optional<uint64_t> +DebugAddrWriterDwarf5::finalize(const size_t BufferSize) { // Need to layout all sections within .debug_addr // Within each section sort Address by index. const endianness Endian = BC->DwCtx->isLittleEndian() @@ -504,55 +502,44 @@ void DebugAddrWriterDwarf5::update(DIEBuilder &DIEBlder, DWARFUnit &CU) { Endian == llvm::endianness::little, 0); DWARFDebugAddrTable AddrTable; DIDumpOptions DumpOpts; - constexpr uint32_t HeaderSize = 8; - const uint64_t CUID = getCUID(CU); - const uint8_t AddrSize = CU.getAddressByteSize(); - auto AMIter = AddressMaps.find(CUID); // A case where CU has entry in .debug_addr, but we don't modify addresses // for it. - if (AMIter == AddressMaps.end()) { - AMIter = AddressMaps.insert({CUID, AddressForDWOCU()}).first; - std::optional<uint64_t> BaseOffset = CU.getAddrOffsetSectionBase(); - if (!BaseOffset) - return; + if (Map.begin() == Map.end()) { + if (!AddrOffsetSectionBase) + return std::nullopt; // Address base offset is to the first entry. // The size of header is 8 bytes. - uint64_t Offset = *BaseOffset - HeaderSize; + uint64_t Offset = *AddrOffsetSectionBase - HeaderSize; auto Iter = UnmodifiedAddressOffsets.find(Offset); - if (Iter != UnmodifiedAddressOffsets.end()) { - updateAddressBase(DIEBlder, *this, CU, Iter->getSecond()); - return; - } - UnmodifiedAddressOffsets[Offset] = Buffer->size() + HeaderSize; - if (Error Err = AddrTable.extract(AddrData, &Offset, 5, AddrSize, + if (Iter != UnmodifiedAddressOffsets.end()) + return Iter->second; + UnmodifiedAddressOffsets[Offset] = BufferSize; + if (Error Err = AddrTable.extract(AddrData, &Offset, 5, AddressByteSize, DumpOpts.WarningHandler)) { DumpOpts.RecoverableErrorHandler(std::move(Err)); - return; + return std::nullopt; } - uint32_t Index = 0; for (uint64_t Addr : AddrTable.getAddressEntries()) - AMIter->second.insert(Addr, Index++); + Map.insert(Addr, Index++); } - updateAddressBase(DIEBlder, *this, CU, Buffer->size() + HeaderSize); - - std::vector<IndexAddressPair> SortedMap(AMIter->second.indexToAddressBegin(), - AMIter->second.indexToAdddessEnd()); + std::vector<IndexAddressPair> SortedMap(Map.indexToAddressBegin(), + Map.indexToAdddessEnd()); // Sorting address in increasing order of indices. llvm::sort(SortedMap, llvm::less_first()); // Writing out Header - const uint32_t Length = SortedMap.size() * AddrSize + 4; + const uint32_t Length = SortedMap.size() * AddressByteSize + 4; support::endian::write(*AddressStream, Length, Endian); support::endian::write(*AddressStream, static_cast<uint16_t>(5), Endian); - support::endian::write(*AddressStream, static_cast<uint8_t>(AddrSize), + support::endian::write(*AddressStream, static_cast<uint8_t>(AddressByteSize), Endian); support::endian::write(*AddressStream, static_cast<uint8_t>(0), Endian); uint32_t Counter = 0; auto writeAddress = [&](uint64_t Address) -> void { ++Counter; - switch (AddrSize) { + switch (AddressByteSize) { default: llvm_unreachable("Address Size is invalid."); break; @@ -571,6 +558,7 @@ void DebugAddrWriterDwarf5::update(DIEBuilder &DIEBlder, DWARFUnit &CU) { writeAddress(0); writeAddress(Val.second); } + return std::nullopt; } void DebugLocWriter::init() { @@ -723,11 +711,11 @@ void DebugLoclistWriter::addList(DIEBuilder &DIEBldr, DIE &Die, DIEValue &AttrInfo, DebugLocationsVector &LocList) { if (DwarfVersion < 5) - writeLegacyLocList(AttrInfo, LocList, DIEBldr, Die, *AddrWriter, *LocBuffer, + writeLegacyLocList(AttrInfo, LocList, DIEBldr, Die, AddrWriter, *LocBuffer, CU, *LocStream); else writeDWARF5LocList(NumberOfEntries, AttrInfo, LocList, Die, DIEBldr, - *AddrWriter, *LocBodyBuffer, RelativeLocListOffsets, CU, + AddrWriter, *LocBodyBuffer, RelativeLocListOffsets, CU, *LocBodyStream); } @@ -789,8 +777,6 @@ void DebugLoclistWriter::finalize(DIEBuilder &DIEBldr, DIE &Die) { finalizeDWARF5(DIEBldr, Die); } -DebugAddrWriter *DebugLoclistWriter::AddrWriter = nullptr; - static std::string encodeLE(size_t ByteSize, uint64_t NewValue) { std::string LE64(ByteSize, 0); for (size_t I = 0; I < ByteSize; ++I) { diff --git a/bolt/lib/Rewrite/DWARFRewriter.cpp b/bolt/lib/Rewrite/DWARFRewriter.cpp index 89168b4..042c39a 100644 --- a/bolt/lib/Rewrite/DWARFRewriter.cpp +++ b/bolt/lib/Rewrite/DWARFRewriter.cpp @@ -612,12 +612,15 @@ void DWARFRewriter::updateDebugInfo() { errs() << "BOLT-WARNING: --deterministic-debuginfo is being deprecated\n"; } + /// Stores and serializes information that will be put into the + /// .debug_addr DWARF section. + std::unique_ptr<DebugAddrWriter> FinalAddrWriter; + if (BC.isDWARF5Used()) { - AddrWriter = std::make_unique<DebugAddrWriterDwarf5>(&BC); + FinalAddrWriter = std::make_unique<DebugAddrWriterDwarf5>(&BC); RangeListsSectionWriter = std::make_unique<DebugRangeListsSectionWriter>(); - DebugRangeListsSectionWriter::setAddressWriter(AddrWriter.get()); } else { - AddrWriter = std::make_unique<DebugAddrWriter>(&BC); + FinalAddrWriter = std::make_unique<DebugAddrWriter>(&BC); } if (BC.isDWARFLegacyUsed()) { @@ -625,34 +628,42 @@ void DWARFRewriter::updateDebugInfo() { LegacyRangesSectionWriter->initSection(); } - DebugLoclistWriter::setAddressWriter(AddrWriter.get()); - uint32_t CUIndex = 0; std::mutex AccessMutex; // Needs to be invoked in the same order as CUs are processed. - auto createRangeLocList = [&](DWARFUnit &CU) -> DebugLocWriter * { + auto createRangeLocListAddressWriters = + [&](DWARFUnit &CU) -> DebugLocWriter * { std::lock_guard<std::mutex> Lock(AccessMutex); const uint16_t DwarfVersion = CU.getVersion(); if (DwarfVersion >= 5) { + auto AddrW = std::make_unique<DebugAddrWriterDwarf5>( + &BC, CU.getAddressByteSize(), CU.getAddrOffsetSectionBase()); + RangeListsSectionWriter->setAddressWriter(AddrW.get()); LocListWritersByCU[CUIndex] = - std::make_unique<DebugLoclistWriter>(CU, DwarfVersion, false); + std::make_unique<DebugLoclistWriter>(CU, DwarfVersion, false, *AddrW); if (std::optional<uint64_t> DWOId = CU.getDWOId()) { assert(RangeListsWritersByCU.count(*DWOId) == 0 && "RangeLists writer for DWO unit already exists."); - auto RangeListsSectionWriter = + auto DWORangeListsSectionWriter = std::make_unique<DebugRangeListsSectionWriter>(); - RangeListsSectionWriter->initSection(CU); - RangeListsWritersByCU[*DWOId] = std::move(RangeListsSectionWriter); + DWORangeListsSectionWriter->initSection(CU); + DWORangeListsSectionWriter->setAddressWriter(AddrW.get()); + RangeListsWritersByCU[*DWOId] = std::move(DWORangeListsSectionWriter); } + AddressWritersByCU[CU.getOffset()] = std::move(AddrW); } else { + auto AddrW = + std::make_unique<DebugAddrWriter>(&BC, CU.getAddressByteSize()); + AddressWritersByCU[CU.getOffset()] = std::move(AddrW); LocListWritersByCU[CUIndex] = std::make_unique<DebugLocWriter>(); if (std::optional<uint64_t> DWOId = CU.getDWOId()) { assert(LegacyRangesWritersByCU.count(*DWOId) == 0 && "LegacyRangeLists writer for DWO unit already exists."); auto LegacyRangesSectionWriterByCU = std::make_unique<DebugRangesSectionWriter>(); + LegacyRangesSectionWriterByCU->initSection(CU); LegacyRangesWritersByCU[*DWOId] = std::move(LegacyRangesSectionWriterByCU); } @@ -674,10 +685,12 @@ void DWARFRewriter::updateDebugInfo() { std::optional<uint64_t> DWOId = Unit->getDWOId(); if (DWOId) SplitCU = BC.getDWOCU(*DWOId); - DebugLocWriter *DebugLocWriter = createRangeLocList(*Unit); + DebugLocWriter *DebugLocWriter = createRangeLocListAddressWriters(*Unit); DebugRangesSectionWriter *RangesSectionWriter = Unit->getVersion() >= 5 ? RangeListsSectionWriter.get() : LegacyRangesSectionWriter.get(); + DebugAddrWriter *AddressWriter = + AddressWritersByCU[Unit->getOffset()].get(); // Skipping CUs that failed to load. if (SplitCU) { DIEBuilder DWODIEBuilder(BC, &(*SplitCU)->getContext(), DebugNamesTable, @@ -698,7 +711,8 @@ void DWARFRewriter::updateDebugInfo() { DWODIEBuilder.updateDWONameCompDirForTypes(DWOStrOffstsWriter, DWOStrWriter, **SplitCU, DwarfOutputPath, DWOName); - DebugLoclistWriter DebugLocDWoWriter(*Unit, Unit->getVersion(), true); + DebugLoclistWriter DebugLocDWoWriter(*Unit, Unit->getVersion(), true, + *AddressWriter); DebugRangesSectionWriter *TempRangesSectionWriter = RangesSectionWriter; if (Unit->getVersion() >= 5) { TempRangesSectionWriter = RangeListsWritersByCU[*DWOId].get(); @@ -709,7 +723,7 @@ void DWARFRewriter::updateDebugInfo() { } updateUnitDebugInfo(*(*SplitCU), DWODIEBuilder, DebugLocDWoWriter, - *TempRangesSectionWriter); + *TempRangesSectionWriter, *AddressWriter); DebugLocDWoWriter.finalize(DWODIEBuilder, *DWODIEBuilder.getUnitDIEbyUnit(**SplitCU)); if (Unit->getVersion() >= 5) @@ -728,11 +742,10 @@ void DWARFRewriter::updateDebugInfo() { } updateUnitDebugInfo(*Unit, *DIEBlder, *DebugLocWriter, *RangesSectionWriter, - RangesBase); + *AddressWriter, RangesBase); DebugLocWriter->finalize(*DIEBlder, *DIEBlder->getUnitDIEbyUnit(*Unit)); if (Unit->getVersion() >= 5) RangesSectionWriter->finalizeSection(); - AddrWriter->update(*DIEBlder, *Unit); }; DIEBuilder DIEBlder(BC, BC.DwCtx.get(), DebugNamesTable); @@ -758,7 +771,7 @@ void DWARFRewriter::updateDebugInfo() { for (DWARFUnit *CU : DIEBlder.getProcessedCUs()) processUnitDIE(CU, &DIEBlder); finalizeCompileUnits(DIEBlder, *Streamer, OffsetMap, - DIEBlder.getProcessedCUs()); + DIEBlder.getProcessedCUs(), *FinalAddrWriter); } } else { // Update unit debug info in parallel @@ -773,8 +786,8 @@ void DWARFRewriter::updateDebugInfo() { if (opts::WriteDWP) finalizeDWP(State); - finalizeDebugSections(DIEBlder, DebugNamesTable, *Streamer, *ObjOS, - OffsetMap); + finalizeDebugSections(DIEBlder, DebugNamesTable, *Streamer, *ObjOS, OffsetMap, + *FinalAddrWriter); GDBIndexSection.updateGdbIndexSection(OffsetMap, CUIndex, *ARangesSectionWriter); } @@ -782,7 +795,7 @@ void DWARFRewriter::updateDebugInfo() { void DWARFRewriter::updateUnitDebugInfo( DWARFUnit &Unit, DIEBuilder &DIEBldr, DebugLocWriter &DebugLocWriter, DebugRangesSectionWriter &RangesSectionWriter, - std::optional<uint64_t> RangesBase) { + DebugAddrWriter &AddressWriter, std::optional<uint64_t> RangesBase) { // Cache debug ranges so that the offset for identical ranges could be reused. std::map<DebugAddressRangesVector, uint64_t> CachedRanges; @@ -816,7 +829,7 @@ void DWARFRewriter::updateUnitDebugInfo( if (FormLowPC == dwarf::DW_FORM_addrx || FormLowPC == dwarf::DW_FORM_GNU_addr_index) - LowPC = AddrWriter->getIndexFromAddress(LowPC, Unit); + LowPC = AddressWriter.getIndexFromAddress(LowPC, Unit); if (LowPCVal) DIEBldr.replaceValue(Die, AttrLowPC, FormLowPC, DIEInteger(LowPC)); @@ -980,7 +993,7 @@ void DWARFRewriter::updateUnitDebugInfo( if (AttrVal.getForm() == dwarf::DW_FORM_addrx) { const uint32_t Index = - AddrWriter->getIndexFromAddress(UpdatedAddress, Unit); + AddressWriter.getIndexFromAddress(UpdatedAddress, Unit); DIEBldr.replaceValue(Die, AttrVal.getAttribute(), AttrVal.getForm(), DIEInteger(Index)); } else if (AttrVal.getForm() == dwarf::DW_FORM_addr) { @@ -1197,7 +1210,7 @@ void DWARFRewriter::updateUnitDebugInfo( assert(EntryAddress && "Address is not found."); assert(Index <= std::numeric_limits<uint32_t>::max() && "Invalid Operand Index."); - const uint32_t AddrIndex = AddrWriter->getIndexFromAddress( + const uint32_t AddrIndex = AddressWriter.getIndexFromAddress( EntryAddress->Address, Unit); // update Index into .debug_address section for DW_AT_location. // The Size field is not stored in IR, we need to minus 1 in @@ -1249,7 +1262,7 @@ void DWARFRewriter::updateUnitDebugInfo( std::lock_guard<std::mutex> Lock(DWARFRewriterMutex); if (Form == dwarf::DW_FORM_addrx || Form == dwarf::DW_FORM_GNU_addr_index) { - const uint32_t Index = AddrWriter->getIndexFromAddress( + const uint32_t Index = AddressWriter.getIndexFromAddress( NewAddress ? NewAddress : Address, Unit); DIEBldr.replaceValue(Die, LowPCAttrInfo.getAttribute(), LowPCAttrInfo.getForm(), DIEInteger(Index)); @@ -1512,7 +1525,8 @@ CUOffsetMap DWARFRewriter::finalizeTypeSections(DIEBuilder &DIEBlder, void DWARFRewriter::finalizeDebugSections( DIEBuilder &DIEBlder, DWARF5AcceleratorTable &DebugNamesTable, - DIEStreamer &Streamer, raw_svector_ostream &ObjOS, CUOffsetMap &CUMap) { + DIEStreamer &Streamer, raw_svector_ostream &ObjOS, CUOffsetMap &CUMap, + DebugAddrWriter &FinalAddrWriter) { if (StrWriter->isInitialized()) { RewriteInstance::addToDebugSectionsToOverwrite(".debug_str"); std::unique_ptr<DebugStrBufferVector> DebugStrSectionContents = @@ -1565,13 +1579,12 @@ void DWARFRewriter::finalizeDebugSections( LocationListSectionContents->size()); } - // AddrWriter should be finalized after debug_loc since more addresses can be - // added there. - if (AddrWriter->isInitialized()) { - AddressSectionBuffer AddressSectionContents = AddrWriter->finalize(); + if (FinalAddrWriter.isInitialized()) { + std::unique_ptr<AddressSectionBuffer> AddressSectionContents = + FinalAddrWriter.releaseBuffer(); BC.registerOrUpdateNoteSection(".debug_addr", - copyByteArray(AddressSectionContents), - AddressSectionContents.size()); + copyByteArray(*AddressSectionContents), + AddressSectionContents->size()); } Streamer.emitAbbrevs(DIEBlder.getAbbrevs(), BC.DwCtx->getMaxVersion()); @@ -1624,8 +1637,26 @@ void DWARFRewriter::finalizeDebugSections( void DWARFRewriter::finalizeCompileUnits(DIEBuilder &DIEBlder, DIEStreamer &Streamer, CUOffsetMap &CUMap, - const std::list<DWARFUnit *> &CUs) { + const std::list<DWARFUnit *> &CUs, + DebugAddrWriter &FinalAddrWriter) { for (DWARFUnit *CU : CUs) { + auto AddressWriterIterator = AddressWritersByCU.find(CU->getOffset()); + assert(AddressWriterIterator != AddressWritersByCU.end() && + "AddressWriter does not exist for CU"); + DebugAddrWriter *AddressWriter = AddressWriterIterator->second.get(); + const size_t BufferOffset = FinalAddrWriter.getBufferSize(); + std::optional<uint64_t> Offset = AddressWriter->finalize(BufferOffset); + /// If Offset already exists in UnmodifiedAddressOffsets, then update with + /// Offset, else update with BufferOffset. + if (Offset) + AddressWriter->updateAddrBase(DIEBlder, *CU, *Offset); + else if (AddressWriter->isInitialized()) + AddressWriter->updateAddrBase(DIEBlder, *CU, BufferOffset); + if (AddressWriter->isInitialized()) { + std::unique_ptr<AddressSectionBuffer> AddressSectionContents = + AddressWriter->releaseBuffer(); + FinalAddrWriter.appendToAddressBuffer(*AddressSectionContents); + } if (CU->getVersion() != 4) continue; std::optional<uint64_t> DWOId = CU->getDWOId(); @@ -2155,6 +2186,10 @@ void DWARFRewriter::convertToRangesPatchDebugInfo( // when it's absent. if (IsUnitDie) { if (LowForm == dwarf::DW_FORM_addrx) { + auto AddrWriterIterator = AddressWritersByCU.find(Unit.getOffset()); + assert(AddrWriterIterator != AddressWritersByCU.end() && + "AddressWriter does not exist for CU"); + DebugAddrWriter *AddrWriter = AddrWriterIterator->second.get(); const uint32_t Index = AddrWriter->getIndexFromAddress(0, Unit); DIEBldr.replaceValue(&Die, LowPCAttrInfo.getAttribute(), LowPCAttrInfo.getForm(), DIEInteger(Index)); diff --git a/bolt/test/X86/dwarf5-addr-section-reuse.s b/bolt/test/X86/dwarf5-addr-section-reuse.s index 6b00ce0..cf511d6 100644 --- a/bolt/test/X86/dwarf5-addr-section-reuse.s +++ b/bolt/test/X86/dwarf5-addr-section-reuse.s @@ -1,7 +1,7 @@ # RUN: llvm-mc -dwarf-version=5 -filetype=obj -triple x86_64-unknown-linux %p/Inputs/dwarf5-main-addr-section-reuse.s -o %tmain.o # RUN: llvm-mc -dwarf-version=5 -filetype=obj -triple x86_64-unknown-linux %p/Inputs/dwarf5-helper1-addr-section-reuse.s -o %thelper1.o # RUN: llvm-mc -dwarf-version=5 -filetype=obj -triple x86_64-unknown-linux %p/Inputs/dwarf5-helper2-addr-section-reuse.s -o %thelper2.o -# RUN: %clang %cflags -dwarf-5 %tmain.o %thelper1.o %thelper2.o -o %t.exe -Wl,-q +# RUN: %clang %cflags -dwarf-5 %thelper1.o %tmain.o %thelper2.o -o %t.exe -Wl,-q # RUN: llvm-dwarfdump --debug-info %t.exe | FileCheck --check-prefix=PRECHECK %s # RUN: llvm-bolt %t.exe -o %t.exe.bolt --update-debug-sections # RUN: llvm-dwarfdump --debug-info %t.exe.bolt | FileCheck --check-prefix=POSTCHECK %s @@ -14,5 +14,5 @@ # PRECHECK: DW_AT_addr_base (0x00000008) # POSTCHECK: DW_AT_addr_base (0x00000008) -# POSTCHECK: DW_AT_addr_base (0x00000020) -# POSTCHECK: DW_AT_addr_base (0x00000020) +# POSTCHECK: DW_AT_addr_base (0x00000018) +# POSTCHECK: DW_AT_addr_base (0x00000008) |