From d01172ffa8ef88c20aab47b9a3571a88e409ebe9 Mon Sep 17 00:00:00 2001 From: Maksim Panchenko Date: Mon, 14 Mar 2016 18:48:05 -0700 Subject: [PATCH] Refactor existing debugging code. Summary: Almost NFC. Isolate code for updating debug info. (cherry picked from FBD3051536) --- bolt/BinaryContext.cpp | 25 +++++++++- bolt/BinaryContext.h | 16 ++----- bolt/BinaryFunction.h | 5 ++ bolt/RewriteInstance.cpp | 101 ++++++++++++++++----------------------- bolt/RewriteInstance.h | 18 +++++-- 5 files changed, 88 insertions(+), 77 deletions(-) diff --git a/bolt/BinaryContext.cpp b/bolt/BinaryContext.cpp index 46ef7b046109..77f1afe49d41 100644 --- a/bolt/BinaryContext.cpp +++ b/bolt/BinaryContext.cpp @@ -43,11 +43,32 @@ MCSymbol *BinaryContext::getOrCreateGlobalSymbol(uint64_t Address, return Symbol; } - -void BinaryContext::buildOffsetToDWARFCompileUnitMap() { +void BinaryContext::preprocessDebugInfo() { + // Iterate over all DWARF compilation units and map their offset in the + // binary to themselves in OffsetDwarfCUMap for (const auto &CU : DwCtx->compile_units()) { OffsetToDwarfCU[CU->getOffset()] = CU.get(); } + + // Populate MCContext with DWARF files. + for (const auto &CU : DwCtx->compile_units()) { + const auto CUID = CU->getOffset(); + auto LineTable = DwCtx->getLineTableForUnit(CU.get()); + const auto &FileNames = LineTable->Prologue.FileNames; + for (size_t I = 0, Size = FileNames.size(); I != Size; ++I) { + // Dir indexes start at 1, as DWARF file numbers, and a dir index 0 + // means empty dir. + const char *Dir = FileNames[I].DirIdx ? + LineTable->Prologue.IncludeDirectories[FileNames[I].DirIdx - 1] : + ""; + Ctx->getDwarfFile(Dir, FileNames[I].Name, I + 1, CUID); + } + + auto LineTableOffset = + DwCtx->getAttrFieldOffsetForUnit(CU.get(), dwarf::DW_AT_stmt_list); + if (LineTableOffset) + LineTableOffsetCUMap[CUID] = LineTableOffset; + } } } // namespace bolt diff --git a/bolt/BinaryContext.h b/bolt/BinaryContext.h index 27e66ca625b3..612cf132e243 100644 --- a/bolt/BinaryContext.h +++ b/bolt/BinaryContext.h @@ -114,8 +114,7 @@ public: std::unique_ptr MIA, std::unique_ptr MRI, std::unique_ptr DisAsm, - const DataReader &DR, - bool LoadDebugContext) : + const DataReader &DR) : Ctx(std::move(Ctx)), DwCtx(std::move(DwCtx)), TheTriple(std::move(TheTriple)), @@ -130,11 +129,7 @@ public: MIA(std::move(MIA)), MRI(std::move(MRI)), DisAsm(std::move(DisAsm)), - DR(DR) { - if (LoadDebugContext) { - buildOffsetToDWARFCompileUnitMap(); - } - } + DR(DR) {} ~BinaryContext() {} @@ -144,10 +139,9 @@ public: /// return the first one. MCSymbol *getOrCreateGlobalSymbol(uint64_t Address, Twine Prefix); -private: - // Iterates over all DWARF compilation units and maps their offset in the - // binary to themselves in OffsetDwarfCUMap - void buildOffsetToDWARFCompileUnitMap(); + /// Populate some internal data structures with debug info. + void preprocessDebugInfo(); + }; } // namespace bolt diff --git a/bolt/BinaryFunction.h b/bolt/BinaryFunction.h index 2069c262923c..95cff6662aa5 100644 --- a/bolt/BinaryFunction.h +++ b/bolt/BinaryFunction.h @@ -726,16 +726,19 @@ public: /// Info for fragmented functions. class FragmentInfo { private: + uint64_t Address{0}; uint64_t ImageAddress{0}; uint64_t ImageSize{0}; uint64_t FileOffset{0}; const MCSymbol *OutputSymbol{nullptr}; public: + uint64_t getAddress() const { return Address; } uint64_t getImageAddress() const { return ImageAddress; } uint64_t getImageSize() const { return ImageSize; } uint64_t getFileOffset() const { return FileOffset; } const MCSymbol *getOutputSymbol() const { return OutputSymbol; } + void setAddress(uint64_t VAddress) { Address = VAddress; } void setImageAddress(uint64_t Address) { ImageAddress = Address; } void setImageSize(uint64_t Size) { ImageSize = Size; } void setFileOffset(uint64_t Offset) { FileOffset = Offset; } @@ -746,6 +749,8 @@ public: FragmentInfo ColdFragment; FragmentInfo &cold() { return ColdFragment; } + + const FragmentInfo &cold() const { return ColdFragment; } }; inline raw_ostream &operator<<(raw_ostream &OS, diff --git a/bolt/RewriteInstance.cpp b/bolt/RewriteInstance.cpp index b19d8ec699dc..ab84d52910b2 100644 --- a/bolt/RewriteInstance.cpp +++ b/bolt/RewriteInstance.cpp @@ -402,34 +402,7 @@ static std::unique_ptr CreateBinaryContext( std::move(MIA), std::move(MRI), std::move(DisAsm), - DR, - opts::UpdateDebugSections); - - if (opts::UpdateDebugSections) { - // Populate MCContext with DWARF files. - for (const auto &CU : BC->DwCtx->compile_units()) { - const auto CUID = CU->getOffset(); - auto LineTable = BC->DwCtx->getLineTableForUnit(CU.get()); - auto LineTableOffset = - BC->DwCtx->getAttrFieldOffsetForUnit(CU.get(), dwarf::DW_AT_stmt_list); - const auto &FileNames = LineTable->Prologue.FileNames; - for (size_t I = 0, Size = FileNames.size(); I != Size; ++I) { - // Dir indexes start at 1, as DWARF file numbers, and a dir index 0 - // means empty dir. - const char *Dir = FileNames[I].DirIdx ? - LineTable->Prologue.IncludeDirectories[FileNames[I].DirIdx - 1] : - ""; - BC->Ctx->getDwarfFile( - Dir, - FileNames[I].Name, - I + 1, - CUID); - } - if (LineTableOffset) { - BC->LineTableOffsetCUMap[CUID] = LineTableOffset; - } - } - } + DR); return BC; } @@ -543,10 +516,12 @@ void RewriteInstance::run() { // Main "loop". discoverStorage(); readSpecialSections(); + readDebugInfo(); discoverFileObjects(); disassembleFunctions(); runOptimizationPasses(); emitFunctions(); + updateDebugInfo(); // Copy allocatable part of the input. std::error_code EC; @@ -738,6 +713,13 @@ void RewriteInstance::readSpecialSections() { } } +void RewriteInstance::readDebugInfo() { + if (!opts::UpdateDebugSections) + return; + + BC->preprocessDebugInfo(); +} + void RewriteInstance::disassembleFunctions() { // Disassemble every function and build it's control flow graph. TotalScore = 0; @@ -1282,11 +1264,6 @@ void RewriteInstance::emitFunctions() { Function.getAddress()); Function.setImageAddress(SMII->second.AllocAddress); Function.setImageSize(SMII->second.Size); - - if (opts::UpdateDebugSections) { - addDebugArangesEntry(Function.getAddress(), Function.getAddress(), - Function.getSize()); - } } else { errs() << "BOLT: cannot remap function " << Function.getName() << "\n"; FailedAddresses.emplace_back(Function.getAddress()); @@ -1308,15 +1285,11 @@ void RewriteInstance::emitFunctions() { OLT.mapSectionAddress(ObjectsHandle, reinterpret_cast(SMII->second.AllocAddress), NextAvailableAddress); + Function.cold().setAddress(NextAvailableAddress); Function.cold().setImageAddress(SMII->second.AllocAddress); Function.cold().setImageSize(SMII->second.Size); Function.cold().setFileOffset(getFileOffsetFor(NextAvailableAddress)); - if (opts::UpdateDebugSections) { - addDebugArangesEntry(Function.getAddress(), NextAvailableAddress, - Function.cold().getImageSize()); - } - NextAvailableAddress += SMII->second.Size; } else { errs() << "BOLT: cannot remap function " << Function.getName() << "\n"; @@ -1324,10 +1297,6 @@ void RewriteInstance::emitFunctions() { } } - // After collecting rewritten function addresses, generate the contents of - // .debug_aranges. - generateDebugAranges(); - // Add the new text section aggregating all existing code sections. auto NewTextSectionSize = NextAvailableAddress - NewTextSectionStartAddress; if (NewTextSectionSize) { @@ -1375,28 +1344,33 @@ void RewriteInstance::emitFunctions() { TempOut->keep(); } -void RewriteInstance::addDebugArangesEntry(uint64_t OriginalFunctionAddress, - uint64_t RangeBegin, - uint64_t RangeSize) { - if (auto DebugAranges = BC->DwCtx->getDebugAranges()) { - uint32_t CUOffset = DebugAranges->findAddress(OriginalFunctionAddress); - if (CUOffset != -1U) { - ArangesWriter.AddRange(CUOffset, RangeBegin, RangeSize); +void RewriteInstance::updateFunctionRanges() { + auto addDebugArangesEntry = [&](uint64_t OriginalFunctionAddress, + uint64_t RangeBegin, + uint64_t RangeSize) { + if (auto DebugAranges = BC->DwCtx->getDebugAranges()) { + uint32_t CUOffset = DebugAranges->findAddress(OriginalFunctionAddress); + if (CUOffset != -1U) + ArangesWriter.AddRange(CUOffset, RangeBegin, RangeSize); + } + }; + + for (const auto &BFI : BinaryFunctions) { + const auto &Function = BFI.second; + // Use either new (image) or original size for the function range. + addDebugArangesEntry(Function.getAddress(), + Function.getAddress(), + Function.isSimple() ? Function.getImageSize() + : Function.getSize()); + if (Function.isSimple() && Function.cold().getImageSize()) { + addDebugArangesEntry(Function.getAddress(), + Function.cold().getAddress(), + Function.cold().getImageSize()); } } } void RewriteInstance::generateDebugAranges() { - // Get the address of all non-simple functions and add them intact to aranges. - // Simple functions are rewritten and have their .debug_aranges entries added - // during rewriting. - for (const auto &BFI : BinaryFunctions) { - const auto &Function = BFI.second; - if (!Function.isSimple()) { - addDebugArangesEntry(Function.getAddress(), Function.getAddress(), - Function.getSize()); - } - } SmallVector ArangesBuffer; raw_svector_ostream OS(ArangesBuffer); @@ -1945,3 +1919,12 @@ void RewriteInstance::computeLineTableOffsets() { << " has line table at " << Offset << "\n"); } } + +void RewriteInstance::updateDebugInfo() { + if (!opts::UpdateDebugSections) + return; + + updateFunctionRanges(); + + generateDebugAranges(); +} diff --git a/bolt/RewriteInstance.h b/bolt/RewriteInstance.h index 7a452994dda7..32bf3a377c4b 100644 --- a/bolt/RewriteInstance.h +++ b/bolt/RewriteInstance.h @@ -134,6 +134,9 @@ public: /// and stack unwinding information. void readSpecialSections(); + /// Read information from debug sections. + void readDebugInfo(); + /// Disassemble each function in the binary and associate it with a /// BinaryFunction object, preparing all information necessary for binary /// optimization. @@ -147,6 +150,9 @@ public: /// performing final relaxation. void emitFunctions(); + /// Update debug information in the file for re-written code. + void updateDebugInfo(); + /// Rewrite back all functions (hopefully optimized) that fit in the original /// memory footprint for that function. If the function is now larger and does /// not fit in the binary, reject it and preserve the original version of the @@ -175,14 +181,17 @@ private: /// stores them into BinaryContext::CompileUnitLineTableOffset. void computeLineTableOffsets(); - /// Adds an entry to be saved in the .debug_aranges section. + /// Adds an entry to be saved in the .debug_aranges/.debug_ranges section. /// \p OriginalFunctionAddress function's address in the original binary, /// used for compile unit lookup. /// \p RangeBegin first address of the address range being added. /// \p RangeSie size in bytes of the address range. - void addDebugArangesEntry(uint64_t OriginalFunctionAddress, - uint64_t RangeBegin, - uint64_t RangeSize); + void addDebugRangesEntry(uint64_t OriginalFunctionAddress, + uint64_t RangeBegin, + uint64_t RangeSize); + + /// Update internal function ranges after functions have been written. + void updateFunctionRanges(); /// Generate the contents of the output .debug_aranges section based on the /// added entries. @@ -195,7 +204,6 @@ private: return Address - NewTextSegmentAddress + NewTextSegmentOffset; } - private: /// An instance of the input binary we are processing, externally owned. llvm::object::ELFObjectFileBase *InputFile;