forked from OSchip/llvm-project
Refactor existing debugging code.
Summary: Almost NFC. Isolate code for updating debug info. (cherry picked from FBD3051536)
This commit is contained in:
parent
dc7cc1fb18
commit
d01172ffa8
|
@ -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
|
||||
|
|
|
@ -114,8 +114,7 @@ public:
|
|||
std::unique_ptr<const MCInstrAnalysis> MIA,
|
||||
std::unique_ptr<const MCRegisterInfo> MRI,
|
||||
std::unique_ptr<MCDisassembler> 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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -402,34 +402,7 @@ static std::unique_ptr<BinaryContext> 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<const void*>(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<char, 16> 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();
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue