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:
parent
9212a9ad69
commit
f2df1a8d97
|
@ -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;
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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};
|
||||
|
||||
|
|
Loading…
Reference in a new issue