mirror of
https://github.com/intel/llvm.git
synced 2026-01-22 07:01:03 +08:00
Relocate old .eh_frame section next to the new one.
Summary: In order to improve gdb experience with BOLT we have to make sure the output file has a single .eh_frame section. Otherwise gdb will use either old or new section for unwinding purposes. This diff relocates the original .eh_frame section next to the new one generated by LLVM. Later we merge two sections into one and make sure only the newly created section has .eh_frame name. (cherry picked from FBD4203943)
This commit is contained in:
@@ -67,7 +67,8 @@ public:
|
||||
std::multimap<uint64_t, std::string> GlobalAddresses;
|
||||
|
||||
/// [MCSymbol] -> [BinaryFunction]
|
||||
std::unordered_map<const MCSymbol *, const BinaryFunction *> SymbolToFunctionMap;
|
||||
std::unordered_map<const MCSymbol *,
|
||||
const BinaryFunction *> SymbolToFunctionMap;
|
||||
|
||||
/// Map virtual address to a section.
|
||||
std::map<uint64_t, SectionRef> AllocatableSections;
|
||||
|
||||
@@ -3391,5 +3391,56 @@ void DynoStats::operator+=(const DynoStats &Other) {
|
||||
}
|
||||
}
|
||||
|
||||
size_t Relocation::getSizeForType(uint64_t Type) {
|
||||
switch (Type) {
|
||||
default:
|
||||
llvm_unreachable("unsupported relocation type");
|
||||
case ELF::R_X86_64_PC8:
|
||||
return 1;
|
||||
case ELF::R_X86_64_PLT32:
|
||||
case ELF::R_X86_64_PC32:
|
||||
case ELF::R_X86_64_32S:
|
||||
case ELF::R_X86_64_32:
|
||||
case ELF::R_X86_64_GOTPCREL:
|
||||
case ELF::R_X86_64_GOTTPOFF:
|
||||
case ELF::R_X86_64_TPOFF32:
|
||||
return 4;
|
||||
case ELF::R_X86_64_PC64:
|
||||
case ELF::R_X86_64_64:
|
||||
return 8;
|
||||
}
|
||||
}
|
||||
|
||||
size_t Relocation::emitTo(MCStreamer *Streamer) {
|
||||
const auto Size = getSizeForType(Type);
|
||||
auto &Ctx = Streamer->getContext();
|
||||
switch (Type) {
|
||||
default:
|
||||
llvm_unreachable("unsupported relocation type");
|
||||
case ELF::R_X86_64_PC8:
|
||||
case ELF::R_X86_64_PC32: {
|
||||
auto *TempLabel = Ctx.createTempSymbol();
|
||||
Streamer->EmitLabel(TempLabel);
|
||||
auto Value =
|
||||
MCBinaryExpr::createSub(MCSymbolRefExpr::create(Symbol, Ctx),
|
||||
MCSymbolRefExpr::create(TempLabel, Ctx),
|
||||
Ctx);
|
||||
if (Addend) {
|
||||
Value = MCBinaryExpr::createAdd(Value,
|
||||
MCConstantExpr::create(Addend, Ctx),
|
||||
Ctx);
|
||||
}
|
||||
Streamer->EmitValue(Value, Size);
|
||||
break;
|
||||
}
|
||||
case ELF::R_X86_64_64:
|
||||
case ELF::R_X86_64_32:
|
||||
case ELF::R_X86_64_32S:
|
||||
Streamer->EmitSymbolValue(Symbol, Size);
|
||||
break;
|
||||
}
|
||||
return Size;
|
||||
}
|
||||
|
||||
} // namespace bolt
|
||||
} // namespace llvm
|
||||
|
||||
@@ -143,6 +143,26 @@ inline raw_ostream &operator<<(raw_ostream &OS, const DynoStats &Stats) {
|
||||
|
||||
DynoStats operator+(const DynoStats &A, const DynoStats &B);
|
||||
|
||||
/// Relocation class.
|
||||
struct Relocation {
|
||||
uint64_t Offset;
|
||||
MCSymbol *Symbol;
|
||||
uint64_t Type;
|
||||
uint64_t Addend;
|
||||
|
||||
/// Return size of the given relocation \p Type.
|
||||
static size_t getSizeForType(uint64_t Type);
|
||||
|
||||
/// Emit relocation at a current \p Streamer' position. The caller is
|
||||
/// responsible for setting the position correctly.
|
||||
size_t emitTo(MCStreamer *Streamer);
|
||||
};
|
||||
|
||||
/// Relocation ordering by offset.
|
||||
inline bool operator<(const Relocation &A, const Relocation &B) {
|
||||
return A.Offset < B.Offset;
|
||||
}
|
||||
|
||||
/// BinaryFunction is a representation of machine-level function.
|
||||
///
|
||||
/// We use the term "Binary" as "Machine" was already taken.
|
||||
|
||||
@@ -693,28 +693,24 @@ bool CFIReaderWriter::fillCFIInfoFor(BinaryFunction &Function) const {
|
||||
}
|
||||
|
||||
std::vector<char> CFIReaderWriter::generateEHFrameHeader(
|
||||
const DWARFFrame &OldEHFrame,
|
||||
const DWARFFrame &NewEHFrame,
|
||||
uint64_t EHFrameHeaderAddress,
|
||||
std::vector<uint64_t> &FailedAddresses) const {
|
||||
// Common PC -> FDE map to be written into the new .eh_frame_hdr.
|
||||
// Common PC -> FDE map to be written into .eh_frame_hdr.
|
||||
std::map<uint64_t, uint64_t> PCToFDE;
|
||||
|
||||
// Presort array for binary search.
|
||||
std::sort(FailedAddresses.begin(), FailedAddresses.end());
|
||||
|
||||
// Initialize PCToFDE using NewEHFrame.
|
||||
for (const auto &NewEntry : NewEHFrame.Entries) {
|
||||
const auto *NewFDE = dyn_cast<dwarf::FDE>(NewEntry.get());
|
||||
// Ignore CIE entries.
|
||||
if (!NewFDE) {
|
||||
continue;
|
||||
}
|
||||
const auto FuncAddress = NewFDE->getInitialLocation();
|
||||
const auto FDEAddress = NewEHFrame.EHFrameAddress + NewFDE->getOffset();
|
||||
NewEHFrame.for_each_FDE([&](const dwarf::FDE *FDE) {
|
||||
const auto FuncAddress = FDE->getInitialLocation();
|
||||
const auto FDEAddress = NewEHFrame.EHFrameAddress + FDE->getOffset();
|
||||
|
||||
// Ignore FDEs pointing to zero.
|
||||
// Ignore unused FDEs.
|
||||
if (FuncAddress == 0)
|
||||
continue;
|
||||
return;
|
||||
|
||||
// Add the address to the map unless we failed to write it.
|
||||
if (!std::binary_search(FailedAddresses.begin(), FailedAddresses.end(),
|
||||
@@ -724,17 +720,17 @@ std::vector<char> CFIReaderWriter::generateEHFrameHeader(
|
||||
<< Twine::utohexstr(FDEAddress) << '\n');
|
||||
PCToFDE[FuncAddress] = FDEAddress;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
DEBUG(dbgs() << "BOLT-DEBUG: new .eh_frame contains "
|
||||
<< NewEHFrame.Entries.size() << " entries\n");
|
||||
|
||||
// Add entries from the original .eh_frame corresponding to the functions
|
||||
// that we did not update.
|
||||
for (const auto &FDEI : getFDEs()) {
|
||||
const auto *OldFDE = FDEI.second;
|
||||
const auto FuncAddress = OldFDE->getInitialLocation();
|
||||
const auto FDEAddress = EHFrame.EHFrameAddress + OldFDE->getOffset();
|
||||
OldEHFrame.for_each_FDE([&](const dwarf::FDE *FDE) {
|
||||
const auto FuncAddress = FDE->getInitialLocation();
|
||||
const auto FDEAddress = OldEHFrame.EHFrameAddress + FDE->getOffset();
|
||||
|
||||
// Add the address if we failed to write it.
|
||||
if (PCToFDE.count(FuncAddress) == 0) {
|
||||
DEBUG(dbgs() << "BOLT-DEBUG: old FDE for function at 0x"
|
||||
@@ -742,10 +738,10 @@ std::vector<char> CFIReaderWriter::generateEHFrameHeader(
|
||||
<< Twine::utohexstr(FDEAddress) << '\n');
|
||||
PCToFDE[FuncAddress] = FDEAddress;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
DEBUG(dbgs() << "BOLT-DEBUG: old .eh_frame contains "
|
||||
<< EHFrame.Entries.size() << " entries\n");
|
||||
<< OldEHFrame.Entries.size() << " entries\n");
|
||||
|
||||
// Generate a new .eh_frame_hdr based on the new map.
|
||||
|
||||
|
||||
@@ -44,11 +44,12 @@ public:
|
||||
///
|
||||
/// Take FDEs from the \p NewEHFrame unless their initial_pc is listed
|
||||
/// in \p FailedAddresses. All other entries are taken from the
|
||||
/// original .eh_frame.
|
||||
/// \p OldEHFrame.
|
||||
///
|
||||
/// \p EHFrameHeaderAddress specifies location of the .eh_frame_hdr,
|
||||
/// and is required to be set for relative addressing.
|
||||
/// \p EHFrameHeaderAddress specifies location of .eh_frame_hdr,
|
||||
/// and is required for relative addressing used in the section.
|
||||
std::vector<char> generateEHFrameHeader(
|
||||
const DWARFFrame &OldEHFrame,
|
||||
const DWARFFrame &NewEHFrame,
|
||||
uint64_t EHFrameHeaderAddress,
|
||||
std::vector<uint64_t> &FailedAddresses) const;
|
||||
|
||||
@@ -44,6 +44,7 @@
|
||||
#include "llvm/Object/SymbolicFile.h"
|
||||
#include "llvm/Support/Casting.h"
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
#include "llvm/Support/Dwarf.h"
|
||||
#include "llvm/Support/Errc.h"
|
||||
#include "llvm/Support/ManagedStatic.h"
|
||||
#include "llvm/Support/TargetSelect.h"
|
||||
@@ -481,6 +482,7 @@ void RewriteInstance::reset() {
|
||||
EHFrame = nullptr;
|
||||
FailedAddresses.clear();
|
||||
RangesSectionsWriter.reset();
|
||||
SectionRelocations.clear();
|
||||
TotalScore = 0;
|
||||
}
|
||||
|
||||
@@ -994,6 +996,65 @@ void RewriteInstance::adjustFunctionBoundaries() {
|
||||
}
|
||||
}
|
||||
|
||||
void RewriteInstance::relocateEHFrameSection() {
|
||||
assert(EHFrameSection.getObject() != nullptr &&
|
||||
"non-empty .eh_frame section expected");
|
||||
|
||||
DWARFFrame EHFrame(EHFrameSection.getAddress());
|
||||
StringRef EHFrameSectionContents;
|
||||
EHFrameSection.getContents(EHFrameSectionContents);
|
||||
DataExtractor DE(EHFrameSectionContents,
|
||||
BC->AsmInfo->isLittleEndian(),
|
||||
BC->AsmInfo->getPointerSize());
|
||||
auto createReloc = [&](uint64_t Value, uint64_t Offset, uint64_t DwarfType) {
|
||||
if (DwarfType == dwarf::DW_EH_PE_omit)
|
||||
return;
|
||||
|
||||
if (!(DwarfType & dwarf::DW_EH_PE_pcrel) &&
|
||||
!(DwarfType & dwarf::DW_EH_PE_textrel) &&
|
||||
!(DwarfType & dwarf::DW_EH_PE_funcrel) &&
|
||||
!(DwarfType & dwarf::DW_EH_PE_datarel)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(DwarfType & dwarf::DW_EH_PE_sdata4))
|
||||
return;
|
||||
|
||||
uint64_t RelType;
|
||||
switch (DwarfType & 0x0f) {
|
||||
default:
|
||||
llvm_unreachable("unsupported DWARF encoding type");
|
||||
case dwarf::DW_EH_PE_sdata4:
|
||||
case dwarf::DW_EH_PE_udata4:
|
||||
RelType = ELF::R_X86_64_PC32;
|
||||
break;
|
||||
case dwarf::DW_EH_PE_sdata8:
|
||||
case dwarf::DW_EH_PE_udata8:
|
||||
RelType = ELF::R_X86_64_PC64;
|
||||
break;
|
||||
}
|
||||
|
||||
DEBUG(dbgs() << "BOLT-DEBUG: adding DWARF reference\n");
|
||||
|
||||
auto *Symbol = BC->getGlobalSymbolAtAddress(Value);
|
||||
if (!Symbol) {
|
||||
DEBUG(dbgs() << "BOLT-DEBUG: creating symbol for DWARF reference at 0x"
|
||||
<< Twine::utohexstr(Value) << '\n');
|
||||
Symbol = BC->getOrCreateGlobalSymbol(Value, "FUNCat");
|
||||
}
|
||||
|
||||
addSectionRelocation(EHFrameSection, Offset, Symbol, RelType);
|
||||
};
|
||||
|
||||
EHFrame.parse(DE, createReloc);
|
||||
|
||||
if (!EHFrame.ParseError.empty()) {
|
||||
errs() << "BOLT-ERROR: EHFrame reader failed with message \""
|
||||
<< EHFrame.ParseError << '\n';
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
BinaryFunction *RewriteInstance::createBinaryFunction(
|
||||
const std::string &Name, SectionRef Section, uint64_t Address,
|
||||
uint64_t Size, bool IsSimple) {
|
||||
@@ -1022,6 +1083,8 @@ void RewriteInstance::readSpecialSections() {
|
||||
LSDAAddress = Section.getAddress();
|
||||
} else if (SectionName == ".debug_loc") {
|
||||
DebugLocSize = Section.getSize();
|
||||
} else if (SectionName == ".eh_frame") {
|
||||
EHFrameSection = Section;
|
||||
}
|
||||
|
||||
// Ignore zero-size allocatable sections as they present no interest to us.
|
||||
@@ -1353,8 +1416,8 @@ void emitFunction(MCStreamer &Streamer, BinaryFunction &Function,
|
||||
// from that. We also update the current CU debug info with the
|
||||
// filename of the inlined function.
|
||||
if (RowReference.DwCompileUnitIndex != OrigUnitID) {
|
||||
Unit =
|
||||
BC.DwCtx->getCompileUnitForOffset(RowReference.DwCompileUnitIndex);
|
||||
Unit = BC.DwCtx->
|
||||
getCompileUnitForOffset(RowReference.DwCompileUnitIndex);
|
||||
OriginalLineTable = BC.DwCtx->getLineTableForUnit(Unit);
|
||||
const auto Filenum =
|
||||
OriginalLineTable->Rows[RowReference.RowIndex - 1].File;
|
||||
@@ -1485,6 +1548,12 @@ void RewriteInstance::emitFunctions() {
|
||||
if (opts::UpdateDebugSections)
|
||||
updateDebugLineInfoForNonSimpleFunctions();
|
||||
|
||||
// Relocate .eh_frame to .eh_frame_old.
|
||||
if (EHFrameSection.getObject() != nullptr) {
|
||||
relocateEHFrameSection();
|
||||
emitDataSection(Streamer.get(), EHFrameSection, ".eh_frame_old");
|
||||
}
|
||||
|
||||
Streamer->Finish();
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
@@ -1605,7 +1674,9 @@ void RewriteInstance::emitFunctions() {
|
||||
}
|
||||
|
||||
// Map special sections to their addresses in the output image.
|
||||
std::vector<std::string> Sections = { ".eh_frame", ".gcc_except_table",
|
||||
// The order is important here.
|
||||
std::vector<std::string> Sections = { ".eh_frame", ".eh_frame_old",
|
||||
".gcc_except_table",
|
||||
".rodata", ".rodata.cold" };
|
||||
for (auto &SectionName : Sections) {
|
||||
auto SMII = EFMM->SectionMapInfo.find(SectionName);
|
||||
@@ -1656,6 +1727,55 @@ void RewriteInstance::emitFunctions() {
|
||||
TempOut->keep();
|
||||
}
|
||||
|
||||
void RewriteInstance::emitDataSection(MCStreamer *Streamer, SectionRef Section,
|
||||
std::string Name) {
|
||||
StringRef SectionName;
|
||||
if (!Name.empty())
|
||||
SectionName = Name;
|
||||
else
|
||||
Section.getName(SectionName);
|
||||
auto *ELFSection = BC->Ctx->getELFSection(SectionName,
|
||||
ELF::SHT_PROGBITS,
|
||||
ELF::SHF_WRITE | ELF::SHF_ALLOC);
|
||||
StringRef SectionContents;
|
||||
Section.getContents(SectionContents);
|
||||
|
||||
Streamer->SwitchSection(ELFSection);
|
||||
Streamer->EmitValueToAlignment(Section.getAlignment());
|
||||
|
||||
DEBUG(dbgs() << "BOLT-DEBUG: emitting section " << SectionName << '\n');
|
||||
|
||||
auto SRI = SectionRelocations.find(Section);
|
||||
if (SRI == SectionRelocations.end()) {
|
||||
Streamer->EmitBytes(SectionContents);
|
||||
return;
|
||||
}
|
||||
|
||||
auto &Relocations = SRI->second;
|
||||
uint64_t SectionOffset = 0;
|
||||
std::sort(Relocations.begin(), Relocations.end());
|
||||
for (auto &Relocation : Relocations) {
|
||||
assert(Relocation.Offset < Section.getSize() && "overflow detected");
|
||||
if (SectionOffset < Relocation.Offset) {
|
||||
Streamer->EmitBytes(
|
||||
SectionContents.substr(SectionOffset,
|
||||
Relocation.Offset - SectionOffset));
|
||||
SectionOffset = Relocation.Offset;
|
||||
}
|
||||
DEBUG(dbgs() << "BOLT-DEBUG: emitting relocation for symbol "
|
||||
<< Relocation.Symbol->getName() << " at offset 0x"
|
||||
<< Twine::utohexstr(Relocation.Offset)
|
||||
<< " with size "
|
||||
<< Relocation::getSizeForType(Relocation.Type) << '\n');
|
||||
auto RelocationSize = Relocation.emitTo(Streamer);
|
||||
SectionOffset += RelocationSize;
|
||||
}
|
||||
assert(SectionOffset <= SectionContents.size() && "overflow error");
|
||||
if (SectionOffset < SectionContents.size()) {
|
||||
Streamer->EmitBytes(SectionContents.substr(SectionOffset));
|
||||
}
|
||||
}
|
||||
|
||||
bool RewriteInstance::checkLargeFunctions() {
|
||||
LargeFunctions.clear();
|
||||
for (auto &BFI : BinaryFunctions) {
|
||||
@@ -1799,7 +1919,7 @@ void RewriteInstance::rewriteNoteSections() {
|
||||
// New section size.
|
||||
uint64_t Size = 0;
|
||||
|
||||
// Copy over section contents unless it's one of the sections we ovewrite.
|
||||
// Copy over section contents unless it's one of the sections we overwrite.
|
||||
if (!shouldOverwriteSection(*SectionName)) {
|
||||
Size = Section.sh_size;
|
||||
std::string Data = InputFile->getData().substr(Section.sh_offset, Size);
|
||||
@@ -1916,6 +2036,7 @@ void RewriteInstance::patchELFSectionHeaderTable(ELFObjectFile<ELFT> *File) {
|
||||
if (SMII != SectionMM->SectionMapInfo.end()) {
|
||||
auto &SecInfo = SMII->second;
|
||||
SecInfo.ShName = Section.sh_name;
|
||||
NewSection.sh_name = 0;
|
||||
}
|
||||
|
||||
OS.write(reinterpret_cast<const char *>(&NewSection), sizeof(NewSection));
|
||||
@@ -2116,47 +2237,10 @@ void RewriteInstance::rewriteFile() {
|
||||
SI.FileOffset);
|
||||
}
|
||||
|
||||
// If .eh_frame is present it requires special handling.
|
||||
// If .eh_frame is present create .eh_frame_hdr.
|
||||
auto SMII = SectionMM->SectionMapInfo.find(".eh_frame");
|
||||
if (SMII != SectionMM->SectionMapInfo.end()) {
|
||||
auto &EHFrameSecInfo = SMII->second;
|
||||
DEBUG(dbgs() << "BOLT: writing a new .eh_frame_hdr\n");
|
||||
|
||||
auto PaddingSize = OffsetToAlignment(NextAvailableAddress, EHFrameHdrAlign);
|
||||
writePadding(Out->os(), PaddingSize);
|
||||
NextAvailableAddress += PaddingSize;
|
||||
|
||||
SectionInfo EHFrameHdrSecInfo;
|
||||
EHFrameHdrSecInfo.FileAddress = NextAvailableAddress;
|
||||
EHFrameHdrSecInfo.FileOffset = getFileOffsetFor(NextAvailableAddress);
|
||||
|
||||
DWARFFrame NewEHFrame(EHFrameSecInfo.FileAddress);
|
||||
NewEHFrame.parse(
|
||||
DataExtractor(StringRef(reinterpret_cast<const char *>(
|
||||
EHFrameSecInfo.AllocAddress),
|
||||
EHFrameSecInfo.Size),
|
||||
BC->AsmInfo->isLittleEndian(),
|
||||
BC->AsmInfo->getPointerSize()));
|
||||
if (!NewEHFrame.ParseError.empty()) {
|
||||
errs() << "BOLT-ERROR: EHFrame reader failed with message \""
|
||||
<< NewEHFrame.ParseError << '\n';
|
||||
exit(1);
|
||||
}
|
||||
|
||||
auto NewEHFrameHdr =
|
||||
CFIRdWrt->generateEHFrameHeader(NewEHFrame,
|
||||
EHFrameHdrSecInfo.FileAddress,
|
||||
FailedAddresses);
|
||||
|
||||
EHFrameHdrSecInfo.Size = NewEHFrameHdr.size();
|
||||
|
||||
assert(Out->os().tell() == EHFrameHdrSecInfo.FileOffset &&
|
||||
"offset mismatch");
|
||||
Out->os().write(NewEHFrameHdr.data(), EHFrameHdrSecInfo.Size);
|
||||
|
||||
SectionMM->SectionMapInfo[".eh_frame_hdr"] = EHFrameHdrSecInfo;
|
||||
|
||||
NextAvailableAddress += EHFrameHdrSecInfo.Size;
|
||||
writeEHFrameHeader(SMII->second);
|
||||
}
|
||||
|
||||
// Patch program header table.
|
||||
@@ -2188,6 +2272,71 @@ void RewriteInstance::rewriteFile() {
|
||||
}
|
||||
}
|
||||
|
||||
void RewriteInstance::writeEHFrameHeader(SectionInfo &EHFrameSecInfo) {
|
||||
DWARFFrame NewEHFrame(EHFrameSecInfo.FileAddress);
|
||||
NewEHFrame.parse(
|
||||
DataExtractor(StringRef(reinterpret_cast<const char *>(
|
||||
EHFrameSecInfo.AllocAddress),
|
||||
EHFrameSecInfo.Size),
|
||||
BC->AsmInfo->isLittleEndian(),
|
||||
BC->AsmInfo->getPointerSize()));
|
||||
if (!NewEHFrame.ParseError.empty()) {
|
||||
errs() << "BOLT-ERROR: EHFrame reader failed with message \""
|
||||
<< NewEHFrame.ParseError << '\n';
|
||||
exit(1);
|
||||
}
|
||||
|
||||
auto OldSMII = SectionMM->SectionMapInfo.find(".eh_frame_old");
|
||||
assert(OldSMII != SectionMM->SectionMapInfo.end() &&
|
||||
"expected .eh_frame_old to be present");
|
||||
auto &OldEHFrameSecInfo = OldSMII->second;
|
||||
DWARFFrame OldEHFrame(OldEHFrameSecInfo.FileAddress);
|
||||
OldEHFrame.parse(
|
||||
DataExtractor(StringRef(reinterpret_cast<const char *>(
|
||||
OldEHFrameSecInfo.AllocAddress),
|
||||
OldEHFrameSecInfo.Size),
|
||||
BC->AsmInfo->isLittleEndian(),
|
||||
BC->AsmInfo->getPointerSize()));
|
||||
if (!OldEHFrame.ParseError.empty()) {
|
||||
errs() << "BOLT-ERROR: EHFrame reader failed with message \""
|
||||
<< OldEHFrame.ParseError << '\n';
|
||||
exit(1);
|
||||
}
|
||||
|
||||
DEBUG(dbgs() << "BOLT: writing a new .eh_frame_hdr\n");
|
||||
|
||||
auto PaddingSize = OffsetToAlignment(NextAvailableAddress, EHFrameHdrAlign);
|
||||
writePadding(Out->os(), PaddingSize);
|
||||
NextAvailableAddress += PaddingSize;
|
||||
|
||||
SectionInfo EHFrameHdrSecInfo;
|
||||
EHFrameHdrSecInfo.FileAddress = NextAvailableAddress;
|
||||
EHFrameHdrSecInfo.FileOffset = getFileOffsetFor(NextAvailableAddress);
|
||||
|
||||
auto NewEHFrameHdr =
|
||||
CFIRdWrt->generateEHFrameHeader(OldEHFrame,
|
||||
NewEHFrame,
|
||||
EHFrameHdrSecInfo.FileAddress,
|
||||
FailedAddresses);
|
||||
|
||||
EHFrameHdrSecInfo.Size = NewEHFrameHdr.size();
|
||||
|
||||
assert(Out->os().tell() == EHFrameHdrSecInfo.FileOffset &&
|
||||
"offset mismatch");
|
||||
Out->os().write(NewEHFrameHdr.data(), EHFrameHdrSecInfo.Size);
|
||||
|
||||
SectionMM->SectionMapInfo[".eh_frame_hdr"] = EHFrameHdrSecInfo;
|
||||
|
||||
NextAvailableAddress += EHFrameHdrSecInfo.Size;
|
||||
|
||||
// Merge .eh_frame and .eh_frame_old so that gdb can locate all FDEs.
|
||||
EHFrameSecInfo.Size = OldEHFrameSecInfo.FileAddress + OldEHFrameSecInfo.Size
|
||||
- EHFrameSecInfo.FileAddress;
|
||||
SectionMM->SectionMapInfo.erase(OldSMII);
|
||||
DEBUG(dbgs() << "BOLT-DEBUG: size of .eh_frame after merge is "
|
||||
<< EHFrameSecInfo.Size << '\n');
|
||||
}
|
||||
|
||||
bool RewriteInstance::shouldOverwriteSection(StringRef SectionName) {
|
||||
if (opts::UpdateDebugSections) {
|
||||
for (auto &OverwriteName : DebugSectionsToOverwrite) {
|
||||
|
||||
@@ -156,6 +156,11 @@ public:
|
||||
/// performing final relaxation.
|
||||
void emitFunctions();
|
||||
|
||||
/// Emit data \p Section, possibly with relocations. Use name \p Name if
|
||||
/// non-empty.
|
||||
void emitDataSection(MCStreamer *Streamer, SectionRef Section,
|
||||
std::string Name = "");
|
||||
|
||||
/// Update debug information in the file for re-written code.
|
||||
void updateDebugInfo();
|
||||
|
||||
@@ -170,6 +175,19 @@ public:
|
||||
/// rewritten.
|
||||
void updateDebugLineInfoForNonSimpleFunctions();
|
||||
|
||||
/// Add section relocation.
|
||||
void addSectionRelocation(SectionRef Section, uint64_t Address,
|
||||
MCSymbol *Symbol, uint64_t Type,
|
||||
uint64_t Addend = 0) {
|
||||
auto RI = SectionRelocations.find(Section);
|
||||
if (RI == SectionRelocations.end()) {
|
||||
auto Result =
|
||||
SectionRelocations.emplace(Section, std::vector<Relocation>());
|
||||
RI = Result.first;
|
||||
}
|
||||
RI->second.emplace_back(Relocation{Address, Symbol, Type, Addend});
|
||||
}
|
||||
|
||||
/// 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
|
||||
@@ -187,9 +205,15 @@ private:
|
||||
/// symbol table has been processed.
|
||||
void adjustFunctionBoundaries();
|
||||
|
||||
/// Make .eh_frame section relocatable.
|
||||
void relocateEHFrameSection();
|
||||
|
||||
/// Rewrite non-allocatable sections with modifications.
|
||||
void rewriteNoteSections();
|
||||
|
||||
/// Write .eh_frame_hdr.
|
||||
void writeEHFrameHeader(SectionInfo &EHFrameSecInfo);
|
||||
|
||||
/// Patch ELF book-keeping info.
|
||||
void patchELF();
|
||||
void patchELFPHDRTable();
|
||||
@@ -313,12 +337,9 @@ private:
|
||||
uint64_t NewTextSegmentOffset{0};
|
||||
uint64_t NewTextSegmentSize{0};
|
||||
|
||||
/// Track next available address in the new text segment.
|
||||
/// Track next available address for new allocatable sections.
|
||||
uint64_t NextAvailableAddress{0};
|
||||
|
||||
/// Information on sections to re-write in the binary.
|
||||
std::map<std::string, SectionInfo> SectionsToRewrite;
|
||||
|
||||
/// Store all non-zero symbols in this map for a quick address lookup.
|
||||
std::map<uint64_t, llvm::object::SymbolRef> FileSymRefs;
|
||||
|
||||
@@ -337,6 +358,7 @@ private:
|
||||
ArrayRef<uint8_t> LSDAData;
|
||||
uint64_t LSDAAddress{0};
|
||||
const llvm::DWARFFrame *EHFrame{nullptr};
|
||||
SectionRef EHFrameSection;
|
||||
|
||||
/// Keep track of functions we fail to write in the binary. We need to avoid
|
||||
/// rewriting CFI info for these functions.
|
||||
@@ -352,6 +374,9 @@ private:
|
||||
/// Total hotness score according to profiling data for this binary.
|
||||
uint64_t TotalScore{0};
|
||||
|
||||
/// Section relocations.
|
||||
std::map<SectionRef, std::vector<Relocation>> SectionRelocations;
|
||||
|
||||
/// Construct BinaryFunction object and add it to internal maps.
|
||||
BinaryFunction *createBinaryFunction(const std::string &Name,
|
||||
object::SectionRef Section,
|
||||
|
||||
Reference in New Issue
Block a user