Skip to content

Commit

Permalink
Update stmt_list value to point to new .debug_line offset.
Browse files Browse the repository at this point in the history
Summary:
After we add new line number information we have to update stmt_list
offsets in .debug_info. For this I had to add a primitive relocations
support for non-allocatable sections we are copying from input file.

Also enabled functionality to process relocations in non-allocatable
sections that LLVM is generating, such as .debug_line. I thought
we already had it, but apparently it didn't work, at least not
for ELF binaries.

(cherry picked from FBD3037903)
  • Loading branch information
maksfb committed Mar 10, 2016
1 parent 9212a9a commit f2df1a8
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 24 deletions.
3 changes: 3 additions & 0 deletions bolt/BinaryContext.h
Expand Up @@ -65,6 +65,9 @@ class BinaryContext {
// output file.
std::map<const DWARFCompileUnit *, uint32_t> CompileUnitLineTableOffset;

/// Maps DWARF CUID to offset of stmt_list attribute in .debug_info.
std::map<unsigned, uint32_t> LineTableOffsetCUMap;

std::unique_ptr<MCContext> Ctx;

std::unique_ptr<DWARFContext> DwCtx;
Expand Down
81 changes: 60 additions & 21 deletions bolt/RewriteInstance.cpp
Expand Up @@ -257,7 +257,7 @@ uint8_t *ExecutableFileMemoryManager::allocateSection(intptr_t Size,
return ret;
}

void ExecutableFileMemoryManager::recordNoteSection(
uint8_t *ExecutableFileMemoryManager::recordNoteSection(
const uint8_t *Data,
uintptr_t Size,
unsigned Alignment,
Expand All @@ -271,13 +271,19 @@ void ExecutableFileMemoryManager::recordNoteSection(
if (SectionName == ".debug_line") {
// We need to make a copy of the section contents if we'll need it for
// a future reference.
uint8_t *p = new uint8_t[Size];
memcpy(p, Data, Size);
NoteSectionInfo[SectionName] = SectionInfo(reinterpret_cast<uint64_t>(p),
Size,
Alignment,
/*IsCode=*/false,
/*IsReadOnly*/true);
uint8_t *DataCopy = new uint8_t[Size];
memcpy(DataCopy, Data, Size);
NoteSectionInfo[SectionName] =
SectionInfo(reinterpret_cast<uint64_t>(DataCopy),
Size,
Alignment,
/*IsCode=*/false,
/*IsReadOnly*/true);
return DataCopy;
} else {
DEBUG(dbgs() << "BOLT-DEBUG: ignoring section " << SectionName
<< " in recordNoteSection()\n");
return nullptr;
}
}

Expand Down Expand Up @@ -404,6 +410,8 @@ static std::unique_ptr<BinaryContext> CreateBinaryContext(
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
Expand All @@ -417,6 +425,9 @@ static std::unique_ptr<BinaryContext> CreateBinaryContext(
I + 1,
CUID);
}
if (LineTableOffset) {
BC->LineTableOffsetCUMap[CUID] = LineTableOffset;
}
}
}

Expand Down Expand Up @@ -668,11 +679,12 @@ void RewriteInstance::readSpecialSections() {
if (SectionName == ".gcc_except_table") {
LSDAData = SectionData;
LSDAAddress = Section.getAddress();
}
if (SectionName == ".eh_frame_hdr") {
} else if (SectionName == ".eh_frame_hdr") {
FrameHdrAddress = Section.getAddress();
FrameHdrContents = SectionContents;
FrameHdrAlign = Section.getAlignment();
} else if (SectionName == ".debug_line") {
DebugLineSize = Section.getSize();
}
}

Expand Down Expand Up @@ -1171,6 +1183,9 @@ void RewriteInstance::emitFunctions() {
// Assign addresses to new functions/sections.
//////////////////////////////////////////////////////////////////////////////

auto EFMM = new ExecutableFileMemoryManager();
SectionMM.reset(EFMM);

if (opts::UpdateDebugSections) {
// Compute offsets of tables in .debug_line for each compile unit.
computeLineTableOffsets();
Expand All @@ -1183,10 +1198,6 @@ void RewriteInstance::emitFunctions() {
object::ObjectFile::createObjectFile(ObjectMemBuffer->getMemBufferRef());
check_error(ObjOrErr.getError(), "error creating in-memory object");

auto EFMM = new ExecutableFileMemoryManager();
SectionMM.reset(EFMM);


// Run ObjectLinkingLayer() with custom memory manager and symbol resolver.
orc::ObjectLinkingLayer<> OLT;

Expand Down Expand Up @@ -1431,20 +1442,40 @@ void RewriteInstance::rewriteNoteSections() {
// Address of extension to the section.
uint64_t Address{0};

// Append new section contents if available.
// Perform section post-processing.
ErrorOr<StringRef> SectionName = Obj->getSectionName(&Section);
check_error(SectionName.getError(), "cannot get section name");

auto SII = SectionMM->NoteSectionInfo.find(*SectionName);
if (SII != SectionMM->NoteSectionInfo.end()) {
auto &SI = SII->second;
assert(SI.Alignment <= Section.sh_addralign &&
"alignment exceeds value in file");
outs() << "BOLT: appending contents to section " << *SectionName << '\n';

// Write section extension.
Address = SI.AllocAddress;
OS.write(reinterpret_cast<const char *>(Address), SI.Size);
Size += SI.Size;
if (Address) {
DEBUG(dbgs() << "BOLT: appending contents to section "
<< *SectionName << '\n');
OS.write(reinterpret_cast<const char *>(Address), SI.Size);
Size += SI.Size;
}

if (!SI.PendingRelocs.empty()) {
DEBUG(dbgs() << "BOLT-DEBUG: processing relocs for section "
<< *SectionName << '\n');
for (auto &Reloc : SI.PendingRelocs) {
DEBUG(dbgs() << "BOLT-DEBUG: writing value "
<< Twine::utohexstr(Reloc.Value)
<< " of size " << (unsigned)Reloc.Size
<< " at offset "
<< Twine::utohexstr(Reloc.Offset) << '\n');
assert(Reloc.Size == 4 &&
"only relocations of size 4 are supported at the moment");
OS.pwrite(reinterpret_cast<const char*>(&Reloc.Value),
Reloc.Size,
NextAvailableOffset + Reloc.Offset);
}
}
}

// Set/modify section info.
Expand Down Expand Up @@ -1794,7 +1825,15 @@ void RewriteInstance::computeLineTableOffsets() {
auto CompileUnit = BC->OffsetToDwarfCU[CUIDLineTablePair.first];
BC->CompileUnitLineTableOffset[CompileUnit] = Offset;

DEBUG(errs() << "BOLT-DEBUG: CU " << CUIDLineTablePair.first
<< " has line table at " << Offset << "\n");
auto LTOI = BC->LineTableOffsetCUMap.find(CUIDLineTablePair.first);
if (LTOI != BC->LineTableOffsetCUMap.end()) {
DEBUG(dbgs() << "BOLT-DEBUG: adding relocation for stmt_list "
<< "in .debug_info\n");
auto &SI = SectionMM->NoteSectionInfo[".debug_info"];
SI.PendingRelocs.emplace_back(
SectionInfo::Reloc{LTOI->second, 4, 0, Offset + DebugLineSize});
}
DEBUG(dbgs() << "BOLT-DEBUG: CU " << CUIDLineTablePair.first
<< " has line table at " << Offset << "\n");
}
}
19 changes: 16 additions & 3 deletions bolt/RewriteInstance.h
Expand Up @@ -45,6 +45,16 @@ struct SectionInfo {
uint64_t FileOffset{0}; /// Offset in the output file.
uint64_t ShName{0}; /// Name offset in section header string table.

struct Reloc {
uint32_t Offset;
uint8_t Size;
uint8_t Type; // unused atm
uint32_t Value;
};

/// Pending relocations for the section.
std::vector<Reloc> PendingRelocs;

SectionInfo(uint64_t Address = 0, uint64_t Size = 0, unsigned Alignment = 0,
bool IsCode = false, bool IsReadOnly = false,
uint64_t FileAddress = 0, uint64_t FileOffset = 0)
Expand Down Expand Up @@ -89,9 +99,9 @@ class ExecutableFileMemoryManager : public SectionMemoryManager {
/*IsCode=*/false, IsReadOnly);
}

void recordNoteSection(const uint8_t *Data, uintptr_t Size,
unsigned Alignment, unsigned SectionID,
StringRef SectionName) override;
uint8_t *recordNoteSection(const uint8_t *Data, uintptr_t Size,
unsigned Alignment, unsigned SectionID,
StringRef SectionName) override;

// Tell EE that we guarantee we don't need stubs.
bool allowStubAllocation() const override { return false; }
Expand Down Expand Up @@ -223,6 +233,9 @@ class RewriteInstance {
/// rewriting CFI info for these functions.
std::vector<uint64_t> FailedAddresses;

/// Size of the .debug_line section on input.
uint32_t DebugLineSize{0};

/// Total hotness score according to profiling data for this binary.
uint64_t TotalScore{0};

Expand Down

0 comments on commit f2df1a8

Please sign in to comment.