Update stmt_list value to point to new .debug_line offset.

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)
This commit is contained in:
Maksim Panchenko 2016-03-09 16:06:41 -08:00
parent 9212a9ad69
commit f2df1a8d97
3 changed files with 79 additions and 24 deletions

View file

@ -65,6 +65,9 @@ public:
// 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;

View file

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

View file

@ -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)
@ -89,9 +99,9 @@ public:
/*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; }
@ -223,6 +233,9 @@ private:
/// 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};