Skip to content

Commit

Permalink
Write updated .debug_line information to temp file
Browse files Browse the repository at this point in the history
Summary:
Writes .debug_line section by setting the state
in MCContext that LLVM needs to produce and output the
line tables. This basically consists of setting the
current location and compile unit offset. This makes LLVM
output .debug_line in the temporary file, but not yet in
the generated ELF file.

Also computes the line table offsets for each compile unit
and saves them into BinaryContext. Added an option to
print these offsets.

(cherry picked from FBD3004554)
  • Loading branch information
Gabriel Poesia authored and maksfb committed Mar 3, 2016
1 parent d68b1c7 commit 73c9f0a
Show file tree
Hide file tree
Showing 3 changed files with 113 additions and 0 deletions.
4 changes: 4 additions & 0 deletions bolt/BinaryContext.h
Expand Up @@ -61,6 +61,10 @@ class BinaryContext {
// DWARF Compilation Unit that starts at that offset.
std::map<uint32_t, DWARFCompileUnit *> OffsetToDwarfCU;

// Maps each compile unit to the offset of its .debug_line line table in the
// output file.
std::map<const DWARFCompileUnit *, uint32_t> CompileUnitLineTableOffset;

std::unique_ptr<MCContext> Ctx;

std::unique_ptr<DWARFContext> DwCtx;
Expand Down
105 changes: 105 additions & 0 deletions bolt/RewriteInstance.cpp
Expand Up @@ -14,17 +14,20 @@
#include "BinaryContext.h"
#include "BinaryFunction.h"
#include "DataReader.h"
#include "DebugLineTableRowRef.h"
#include "Exceptions.h"
#include "RewriteInstance.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/DebugInfo/DWARF/DWARFContext.h"
#include "llvm/DebugInfo/DWARF/DWARFDebugLine.h"
#include "llvm/ExecutionEngine/Orc/LambdaResolver.h"
#include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h"
#include "llvm/ExecutionEngine/RTDyldMemoryManager.h"
#include "llvm/MC/MCAsmBackend.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCDisassembler.h"
#include "llvm/MC/MCDwarf.h"
#include "llvm/MC/MCInstPrinter.h"
#include "llvm/MC/MCInstrAnalysis.h"
#include "llvm/MC/MCInstrInfo.h"
Expand Down Expand Up @@ -396,6 +399,27 @@ static std::unique_ptr<BinaryContext> CreateBinaryContext(
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());
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);
}
}
}

return BC;
}

Expand Down Expand Up @@ -959,6 +983,10 @@ void emitFunction(MCStreamer &Streamer, BinaryFunction &Function,
ELF::SHF_EXECINSTR | ELF::SHF_ALLOC);

MCSection *Section = FunctionSection;

Section->setHasInstructions(true);
BC.Ctx->addGenDwarfSection(Section);

Streamer.SwitchSection(Section);

Streamer.EmitCodeAlignment(Function.getAlignment());
Expand Down Expand Up @@ -1029,6 +1057,29 @@ void emitFunction(MCStreamer &Streamer, BinaryFunction &Function,
continue;
}
if (!BC.MIA->isCFI(Instr)) {
if (opts::UpdateDebugSections) {
auto RowReference = DebugLineTableRowRef::fromSMLoc(Instr.getLoc());
if (auto CompileUnit = BC.OffsetToDwarfCU[RowReference.DwCompileUnitIndex]) {

auto OriginalLineTable =
BC.DwCtx->getLineTableForUnit(
CompileUnit);
const auto &OriginalRow = OriginalLineTable->Rows[RowReference.RowIndex];

BC.Ctx->setCurrentDwarfLoc(
OriginalRow.File,
OriginalRow.Line,
OriginalRow.Column,
(DWARF2_FLAG_IS_STMT * OriginalRow.IsStmt) |
(DWARF2_FLAG_BASIC_BLOCK * OriginalRow.BasicBlock) |
(DWARF2_FLAG_PROLOGUE_END * OriginalRow.PrologueEnd) |
(DWARF2_FLAG_EPILOGUE_BEGIN * OriginalRow.EpilogueBegin),
OriginalRow.Isa,
OriginalRow.Discriminator);
BC.Ctx->setDwarfCompileUnitID(CompileUnit->getOffset());
}
}

Streamer.EmitInstruction(Instr, *BC.STI);
continue;
}
Expand Down Expand Up @@ -1120,6 +1171,11 @@ void RewriteInstance::emitFunctions() {
// Assign addresses to new functions/sections.
//////////////////////////////////////////////////////////////////////////////

if (opts::UpdateDebugSections) {
// Compute offsets of tables in .debug_line for each compile unit.
computeLineTableOffsets();
}

// Get output object as ObjectFile.
std::unique_ptr<MemoryBuffer> ObjectMemBuffer =
MemoryBuffer::getMemBuffer(BOS->str(), "in-memory object file", false);
Expand Down Expand Up @@ -1693,3 +1749,52 @@ void RewriteInstance::rewriteFile() {
// TODO: we should find a way to mark the binary as optimized by us.
Out->keep();
}

void RewriteInstance::computeLineTableOffsets() {
const auto LineSection =
BC->Ctx->getObjectFileInfo()->getDwarfLineSection();
auto CurrentFragment = LineSection->begin();
uint32_t CurrentOffset = 0;
uint32_t Offset = 0;

// Line tables are stored in MCContext in ascending order of offset in the
// output file, thus we can compute all table's offset by passing through
// each fragment at most once, continuing from the last CU's beginning
// instead of from the first fragment.
for (const auto &CUIDLineTablePair : BC->Ctx->getMCDwarfLineTables()) {
auto Label = CUIDLineTablePair.second.getLabel();

if (!Label)
continue;

auto Fragment = Label->getFragment();

while (&*CurrentFragment != Fragment) {
switch (CurrentFragment->getKind()) {
case MCFragment::FT_Dwarf:
Offset += cast<MCDwarfLineAddrFragment>(*CurrentFragment)
.getContents().size() - CurrentOffset;
break;
case MCFragment::FT_Data:
Offset += cast<MCDataFragment>(*CurrentFragment)
.getContents().size() - CurrentOffset;
break;
default:
llvm_unreachable(".debug_line section shouldn't contain other types "
"of fragments.");
}

++CurrentFragment;
CurrentOffset = 0;
}

Offset += Label->getOffset() - CurrentOffset;
CurrentOffset = Label->getOffset();

auto CompileUnit = BC->OffsetToDwarfCU[CUIDLineTablePair.first];
BC->CompileUnitLineTableOffset[CompileUnit] = Offset;

DEBUG(errs() << "BOLT-DEBUG: CU " << CUIDLineTablePair.first
<< " has line table at " << Offset << "\n");
}
}
4 changes: 4 additions & 0 deletions bolt/RewriteInstance.h
Expand Up @@ -160,6 +160,10 @@ class RewriteInstance {
void patchELFPHDRTable();
void patchELFSectionHeaderTable();

/// Computes output .debug_line line table offsets for each compile unit, and
/// stores them into BinaryContext::CompileUnitLineTableOffset.
void computeLineTableOffsets();

/// Return file offset corresponding to a given virtual address.
uint64_t getFileOffsetFor(uint64_t Address) {
assert(Address >= NewTextSegmentAddress &&
Expand Down

0 comments on commit 73c9f0a

Please sign in to comment.