Refactor existing debugging code.

Summary: Almost NFC. Isolate code for updating debug info.

(cherry picked from FBD3051536)
This commit is contained in:
Maksim Panchenko 2016-03-14 18:48:05 -07:00
parent dc7cc1fb18
commit d01172ffa8
5 changed files with 88 additions and 77 deletions

View File

@ -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

View File

@ -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

View File

@ -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,

View File

@ -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();
}

View File

@ -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;