// same size seen in the input binary, in case this section is a copy
// of the original one seen in the binary.
BC->EFMM.reset(new ExecutableFileMemoryManager(*BC, /*AllowStubs*/ false));
+ BC->EFMM->setNewSecPrefix(getNewSecPrefix());
+ BC->EFMM->setOrgSecPrefix(getOrgSecPrefix());
auto ELF64LEFile = dyn_cast<ELF64LEObjectFile>(InputFile);
const ELFFile<ELF64LE> &Obj = ELF64LEFile->getELFFile();
if (opts::DiffOnly)
return Error::success();
+ preregisterSections();
+
runOptimizationPasses();
emitAndLink();
}
void RewriteInstance::relocateEHFrameSection() {
- assert(EHFrameSection && "non-empty .eh_frame section expected");
+ assert(EHFrameSection && "Non-empty .eh_frame section expected.");
+ BinarySection *RelocatedEHFrameSection =
+ getSection(".relocated" + getEHFrameSectionName());
+ assert(RelocatedEHFrameSection &&
+ "Relocated eh_frame section should be preregistered.");
DWARFDataExtractor DE(EHFrameSection->getContents(),
BC->AsmInfo->isLittleEndian(),
BC->AsmInfo->getCodePointerSize());
// Create a relocation against an absolute value since the goal is to
// preserve the contents of the section independent of the new values
// of referenced symbols.
- EHFrameSection->addRelocation(Offset, nullptr, RelType, Value);
+ RelocatedEHFrameSection->addRelocation(Offset, nullptr, RelType, Value);
};
Error E = EHFrameParser::parse(DE, EHFrameSection->getAddress(), createReloc);
check_error(SectionNameOrErr.takeError(), "cannot get section name");
StringRef SectionName = *SectionNameOrErr;
- // Only register sections with names.
- if (!SectionName.empty()) {
- if (Error E = Section.getContents().takeError())
- return E;
- BC->registerSection(Section);
- LLVM_DEBUG(
- dbgs() << "BOLT-DEBUG: registering section " << SectionName << " @ 0x"
- << Twine::utohexstr(Section.getAddress()) << ":0x"
- << Twine::utohexstr(Section.getAddress() + Section.getSize())
- << "\n");
- if (isDebugSection(SectionName))
- HasDebugInfo = true;
- if (isKSymtabSection(SectionName))
- opts::LinuxKernelMode = true;
- }
+ if (Error E = Section.getContents().takeError())
+ return E;
+ BC->registerSection(Section);
+ LLVM_DEBUG(
+ dbgs() << "BOLT-DEBUG: registering section " << SectionName << " @ 0x"
+ << Twine::utohexstr(Section.getAddress()) << ":0x"
+ << Twine::utohexstr(Section.getAddress() + Section.getSize())
+ << "\n");
+ if (isDebugSection(SectionName))
+ HasDebugInfo = true;
+ if (isKSymtabSection(SectionName))
+ opts::LinuxKernelMode = true;
}
if (HasDebugInfo && !opts::UpdateDebugSections && !opts::AggregateOnly) {
} // anonymous namespace
+void RewriteInstance::preregisterSections() {
+ // Preregister sections before emission to set their order in the output.
+ const unsigned ROFlags = BinarySection::getFlags(/*IsReadOnly*/ true,
+ /*IsText*/ false,
+ /*IsAllocatable*/ true);
+ if (BinarySection *EHFrameSection = getSection(getEHFrameSectionName())) {
+ // New .eh_frame.
+ BC->registerOrUpdateSection(getNewSecPrefix() + getEHFrameSectionName(),
+ ELF::SHT_PROGBITS, ROFlags);
+ // Fully register a relocatable copy of the original .eh_frame.
+ BC->registerSection(".relocated.eh_frame", *EHFrameSection);
+ }
+ BC->registerOrUpdateSection(getNewSecPrefix() + ".gcc_except_table",
+ ELF::SHT_PROGBITS, ROFlags);
+ BC->registerOrUpdateSection(getNewSecPrefix() + ".rodata", ELF::SHT_PROGBITS,
+ ROFlags);
+ BC->registerOrUpdateSection(getNewSecPrefix() + ".rodata.cold",
+ ELF::SHT_PROGBITS, ROFlags);
+}
+
void RewriteInstance::emitAndLink() {
NamedRegionTimer T("emitAndLink", "emit and link", TimerGroupName,
TimerGroupDesc, opts::TimeRewrite);
exit(1);
}
+ ErrorOr<BinarySection &> TextSection =
+ BC->getUniqueSectionByName(BC->getMainCodeSectionName());
+ if (BC->HasRelocations && TextSection)
+ BC->renameSection(*TextSection, getOrgSecPrefix() + ".text");
+
//////////////////////////////////////////////////////////////////////////////
// Assign addresses to new sections.
//////////////////////////////////////////////////////////////////////////////
if (RuntimeLibrary *RtLibrary = BC->getRuntimeLibrary())
RtLibrary->link(*BC, ToolPath, *RTDyld, [this](RuntimeDyld &R) {
- this->mapExtraSections(*RTDyld);
+ // Map newly registered sections.
+ this->mapAllocatableSections(*RTDyld);
});
// Once the code is emitted, we can rename function sections to actual
}
void RewriteInstance::mapFileSections(RuntimeDyld &RTDyld) {
+ BC->deregisterUnusedSections();
+
+ // If no new .eh_frame was written, remove relocated original .eh_frame.
+ BinarySection *RelocatedEHFrameSection =
+ getSection(".relocated" + getEHFrameSectionName());
+ if (RelocatedEHFrameSection && RelocatedEHFrameSection->hasValidSectionID()) {
+ BinarySection *NewEHFrameSection =
+ getSection(getNewSecPrefix() + getEHFrameSectionName());
+ if (!NewEHFrameSection || !NewEHFrameSection->isFinalized()) {
+ // RTDyld will still have to process relocations for the section, hence
+ // we need to assign it the address that wouldn't result in relocation
+ // processing failure.
+ RTDyld.reassignSectionAddress(RelocatedEHFrameSection->getSectionID(),
+ NextAvailableAddress);
+ BC->deregisterSection(*RelocatedEHFrameSection);
+ }
+ }
+
mapCodeSections(RTDyld);
- mapDataSections(RTDyld);
+
+ // Map the rest of the sections.
+ mapAllocatableSections(RTDyld);
}
std::vector<BinarySection *> RewriteInstance::getCodeSections() {
BinarySection &Section = JT->getOutputSection();
Section.setOutputAddress(JT->getAddress());
Section.setOutputFileOffset(getFileOffsetForAddress(JT->getAddress()));
- LLVM_DEBUG(dbgs() << "BOLT-DEBUG: mapping " << Section.getName()
+ LLVM_DEBUG(dbgs() << "BOLT-DEBUG: mapping JT " << Section.getName()
<< " to 0x" << Twine::utohexstr(JT->getAddress())
<< '\n');
RTDyld.reassignSectionAddress(Section.getSectionID(), JT->getAddress());
FF.setImageAddress(0);
FF.setImageSize(0);
FF.setFileOffset(0);
+ BC->deregisterSection(*ColdSection);
} else {
FF.setAddress(NextAvailableAddress);
FF.setImageAddress(ColdSection->getAllocAddress());
}
}
-void RewriteInstance::mapDataSections(RuntimeDyld &RTDyld) {
- // Map special sections to their addresses in the output image.
- // These are the sections that we generate via MCStreamer.
- // The order is important.
- std::vector<std::string> Sections = {
- ".eh_frame", Twine(getOrgSecPrefix(), ".eh_frame").str(),
- ".gcc_except_table", ".rodata", ".rodata.cold"};
- if (RuntimeLibrary *RtLibrary = BC->getRuntimeLibrary())
- RtLibrary->addRuntimeLibSections(Sections);
-
- if (!EHFrameSection || !EHFrameSection->isFinalized()) {
- ErrorOr<BinarySection &> OldEHFrameSection =
- BC->getUniqueSectionByName(Twine(getOrgSecPrefix(), ".eh_frame").str());
- if (OldEHFrameSection) {
- RTDyld.reassignSectionAddress(OldEHFrameSection->getSectionID(),
- NextAvailableAddress);
- BC->deregisterSection(*OldEHFrameSection);
- }
- }
-
- for (std::string &SectionName : Sections) {
- ErrorOr<BinarySection &> Section = BC->getUniqueSectionByName(SectionName);
- if (!Section || !Section->isAllocatable() || !Section->isFinalized())
- continue;
- NextAvailableAddress =
- alignTo(NextAvailableAddress, Section->getAlignment());
- LLVM_DEBUG(dbgs() << "BOLT: mapping section " << SectionName << " (0x"
- << Twine::utohexstr(Section->getAllocAddress())
- << ") to 0x" << Twine::utohexstr(NextAvailableAddress)
- << ":0x"
- << Twine::utohexstr(NextAvailableAddress +
- Section->getOutputSize())
- << '\n');
+void RewriteInstance::mapAllocatableSections(RuntimeDyld &RTDyld) {
+ // Allocate read-only sections first, then writable sections.
+ enum : uint8_t { ST_READONLY, ST_READWRITE };
+ for (uint8_t SType = ST_READONLY; SType <= ST_READWRITE; ++SType) {
+ for (BinarySection &Section : BC->allocatableSections()) {
+ if (!Section.hasValidSectionID())
+ continue;
- RTDyld.reassignSectionAddress(Section->getSectionID(),
- NextAvailableAddress);
- Section->setOutputAddress(NextAvailableAddress);
- Section->setOutputFileOffset(getFileOffsetForAddress(NextAvailableAddress));
+ if (Section.isReadOnly() != (SType == ST_READONLY))
+ continue;
- NextAvailableAddress += Section->getOutputSize();
- }
+ if (Section.getOutputAddress()) {
+ LLVM_DEBUG({
+ dbgs() << "BOLT-DEBUG: section " << Section.getName()
+ << " is already mapped at 0x"
+ << Twine::utohexstr(Section.getOutputAddress()) << '\n';
+ });
+ continue;
+ }
- // Handling for sections with relocations.
- for (BinarySection &Section : BC->sections()) {
- if (!Section.hasSectionRef())
- continue;
+ if (Section.hasSectionRef()) {
+ LLVM_DEBUG({
+ dbgs() << "BOLT-DEBUG: mapping original section " << Section.getName()
+ << " to 0x" << Twine::utohexstr(Section.getAddress()) << '\n';
+ });
+ Section.setOutputAddress(Section.getAddress());
+ Section.setOutputFileOffset(Section.getInputFileOffset());
+ RTDyld.reassignSectionAddress(Section.getSectionID(),
+ Section.getAddress());
+ } else {
+ NextAvailableAddress =
+ alignTo(NextAvailableAddress, Section.getAlignment());
+ LLVM_DEBUG({
+ dbgs() << "BOLT: mapping section " << Section.getName() << " (0x"
+ << Twine::utohexstr(Section.getAllocAddress()) << ") to 0x"
+ << Twine::utohexstr(NextAvailableAddress) << ":0x"
+ << Twine::utohexstr(NextAvailableAddress +
+ Section.getOutputSize())
+ << '\n';
+ });
- StringRef SectionName = Section.getName();
- ErrorOr<BinarySection &> OrgSection =
- BC->getUniqueSectionByName((getOrgSecPrefix() + SectionName).str());
- if (!OrgSection ||
- !OrgSection->isAllocatable() ||
- !OrgSection->isFinalized() ||
- !OrgSection->hasValidSectionID())
- continue;
+ RTDyld.reassignSectionAddress(Section.getSectionID(),
+ NextAvailableAddress);
+ Section.setOutputAddress(NextAvailableAddress);
+ Section.setOutputFileOffset(
+ getFileOffsetForAddress(NextAvailableAddress));
- if (OrgSection->getOutputAddress()) {
- LLVM_DEBUG(dbgs() << "BOLT-DEBUG: section " << SectionName
- << " is already mapped at 0x"
- << Twine::utohexstr(OrgSection->getOutputAddress())
- << '\n');
- continue;
+ NextAvailableAddress += Section.getOutputSize();
+ }
}
- LLVM_DEBUG(
- dbgs() << "BOLT: mapping original section " << SectionName << " (0x"
- << Twine::utohexstr(OrgSection->getAllocAddress()) << ") to 0x"
- << Twine::utohexstr(Section.getAddress()) << '\n');
-
- RTDyld.reassignSectionAddress(OrgSection->getSectionID(),
- Section.getAddress());
-
- OrgSection->setOutputAddress(Section.getAddress());
- OrgSection->setOutputFileOffset(Section.getContents().data() -
- InputFile->getData().data());
- }
-}
-
-void RewriteInstance::mapExtraSections(RuntimeDyld &RTDyld) {
- for (BinarySection &Section : BC->allocatableSections()) {
- if (Section.getOutputAddress() || !Section.hasValidSectionID())
- continue;
- NextAvailableAddress =
- alignTo(NextAvailableAddress, Section.getAlignment());
- Section.setOutputAddress(NextAvailableAddress);
- NextAvailableAddress += Section.getOutputSize();
-
- LLVM_DEBUG(dbgs() << "BOLT: (extra) mapping " << Section.getName()
- << " at 0x" << Twine::utohexstr(Section.getAllocAddress())
- << " to 0x"
- << Twine::utohexstr(Section.getOutputAddress()) << '\n');
-
- RTDyld.reassignSectionAddress(Section.getSectionID(),
- Section.getOutputAddress());
- Section.setOutputFileOffset(
- getFileOffsetForAddress(Section.getOutputAddress()));
}
}
NewPhdr.p_memsz = sizeof(NewPhdr) * Phnum;
} else if (Phdr.p_type == ELF::PT_GNU_EH_FRAME) {
ErrorOr<BinarySection &> EHFrameHdrSec =
- BC->getUniqueSectionByName(".eh_frame_hdr");
+ BC->getUniqueSectionByName(getNewSecPrefix() + ".eh_frame_hdr");
if (EHFrameHdrSec && EHFrameHdrSec->isAllocatable() &&
EHFrameHdrSec->isFinalized()) {
NewPhdr.p_offset = EHFrameHdrSec->getOutputFileOffset();
if (Section.sh_flags & ELF::SHF_ALLOC)
continue;
+ SectionRef SecRef = ELF64LEFile->toSectionRef(&Section);
+ BinarySection *BSec = BC->getSectionForSectionRef(SecRef);
+ assert(BSec && !BSec->isAllocatable() &&
+ "Matching non-allocatable BinarySection should exist.");
+
StringRef SectionName =
cantFail(Obj.getSectionName(Section), "cannot get section name");
- ErrorOr<BinarySection &> BSec = BC->getUniqueSectionByName(SectionName);
-
if (shouldStrip(Section, SectionName))
continue;
Size = Section.sh_size;
StringRef Dataref = InputFile->getData().substr(Section.sh_offset, Size);
std::string Data;
- if (BSec && BSec->getPatcher()) {
+ if (BSec->getPatcher()) {
Data = BSec->getPatcher()->patchBinary(Dataref);
Dataref = StringRef(Data);
}
// Section was expanded, so need to treat it as overwrite.
if (Size != Dataref.size()) {
- BSec = BC->registerOrUpdateNoteSection(
+ BSec = &BC->registerOrUpdateNoteSection(
SectionName, copyByteArray(Dataref), Dataref.size());
Size = 0;
} else {
}
// Perform section post-processing.
- if (BSec && !BSec->isAllocatable()) {
- assert(BSec->getAlignment() <= Section.sh_addralign &&
- "alignment exceeds value in file");
-
- if (BSec->getAllocAddress()) {
- assert(!DataWritten && "Writing section twice.");
- (void)DataWritten;
- SectionData = BSec->getOutputData();
-
- LLVM_DEBUG(dbgs() << "BOLT-DEBUG: " << (Size ? "appending" : "writing")
- << " contents to section " << SectionName << '\n');
- OS.write(reinterpret_cast<char *>(SectionData), BSec->getOutputSize());
- Size += BSec->getOutputSize();
- }
-
- BSec->setOutputFileOffset(NextAvailableOffset);
- BSec->flushPendingRelocations(OS,
- [this] (const MCSymbol *S) {
- return getNewValueForSymbol(S->getName());
- });
+ assert(BSec->getAlignment() <= Section.sh_addralign &&
+ "alignment exceeds value in file");
+
+ if (BSec->getAllocAddress()) {
+ assert(!DataWritten && "Writing section twice.");
+ (void)DataWritten;
+ SectionData = BSec->getOutputData();
+
+ LLVM_DEBUG(dbgs() << "BOLT-DEBUG: " << (Size ? "appending" : "writing")
+ << " contents to section " << SectionName << '\n');
+ OS.write(reinterpret_cast<char *>(SectionData), BSec->getOutputSize());
+ Size += BSec->getOutputSize();
}
+ BSec->setOutputFileOffset(NextAvailableOffset);
+ BSec->flushPendingRelocations(OS, [this](const MCSymbol *S) {
+ return getNewValueForSymbol(S->getName());
+ });
+
// Set/modify section info.
- BinarySection &NewSection =
- BC->registerOrUpdateNoteSection(SectionName,
- SectionData,
- Size,
- Section.sh_addralign,
- BSec ? BSec->isReadOnly() : false,
- BSec ? BSec->getELFType()
- : ELF::SHT_PROGBITS);
+ BinarySection &NewSection = BC->registerOrUpdateNoteSection(
+ SectionName, SectionData, Size, Section.sh_addralign,
+ BSec->isReadOnly(), BSec->getELFType());
NewSection.setOutputAddress(0);
NewSection.setOutputFileOffset(NextAvailableOffset);
template <typename ELFT>
void RewriteInstance::finalizeSectionStringTable(ELFObjectFile<ELFT> *File) {
- using ELFShdrTy = typename ELFT::Shdr;
- const ELFFile<ELFT> &Obj = File->getELFFile();
-
// Pre-populate section header string table.
- for (const ELFShdrTy &Section : cantFail(Obj.sections())) {
- StringRef SectionName =
- cantFail(Obj.getSectionName(Section), "cannot get section name");
- SHStrTab.add(SectionName);
- std::string OutputSectionName = getOutputSectionName(Obj, Section);
- if (OutputSectionName != SectionName)
- SHStrTabPool.emplace_back(std::move(OutputSectionName));
- }
- for (const std::string &Str : SHStrTabPool)
- SHStrTab.add(Str);
for (const BinarySection &Section : BC->sections())
- SHStrTab.add(Section.getName());
+ if (!Section.isAnonymous())
+ SHStrTab.add(Section.getOutputName());
SHStrTab.finalize();
const size_t SHStrTabSize = SHStrTab.getSize();
/*IsReadOnly=*/true, ELF::SHT_NOTE);
}
-template <typename ELFObjType, typename ELFShdrTy>
-std::string RewriteInstance::getOutputSectionName(const ELFObjType &Obj,
- const ELFShdrTy &Section) {
- if (Section.sh_type == ELF::SHT_NULL)
- return "";
-
- StringRef SectionName =
- cantFail(Obj.getSectionName(Section), "cannot get section name");
-
- if ((Section.sh_flags & ELF::SHF_ALLOC) && willOverwriteSection(SectionName))
- return (getOrgSecPrefix() + SectionName).str();
-
- return std::string(SectionName);
-}
-
template <typename ELFShdrTy>
bool RewriteInstance::shouldStrip(const ELFShdrTy &Section,
StringRef SectionName) {
const ELFFile<ELFT> &Obj = File->getELFFile();
typename ELFT::ShdrRange Sections = cantFail(Obj.sections());
- // Keep track of section header entries together with their name.
- std::vector<std::pair<std::string, ELFShdrTy>> OutputSections;
- auto addSection = [&](const std::string &Name, const ELFShdrTy &Section) {
+ // Keep track of section header entries attached to the corresponding section.
+ std::vector<std::pair<BinarySection *, ELFShdrTy>> OutputSections;
+ auto addSection = [&](const ELFShdrTy &Section, BinarySection *BinSec) {
ELFShdrTy NewSection = Section;
- NewSection.sh_name = SHStrTab.getOffset(Name);
- OutputSections.emplace_back(Name, std::move(NewSection));
+ NewSection.sh_name = SHStrTab.getOffset(BinSec->getOutputName());
+ OutputSections.emplace_back(BinSec, std::move(NewSection));
};
// Copy over entries for original allocatable sections using modified name.
for (const ELFShdrTy &Section : Sections) {
// Always ignore this section.
if (Section.sh_type == ELF::SHT_NULL) {
- OutputSections.emplace_back("", Section);
+ OutputSections.emplace_back(nullptr, Section);
continue;
}
if (!(Section.sh_flags & ELF::SHF_ALLOC))
continue;
- addSection(getOutputSectionName(Obj, Section), Section);
+ SectionRef SecRef = File->toSectionRef(&Section);
+ BinarySection *BinSec = BC->getSectionForSectionRef(SecRef);
+ assert(BinSec && "Matching BinarySection should exist.");
+
+ addSection(Section, BinSec);
}
- for (const BinarySection &Section : BC->allocatableSections()) {
+ for (BinarySection &Section : BC->allocatableSections()) {
if (!Section.isFinalized())
continue;
- if (Section.getName().startswith(getOrgSecPrefix()) ||
- Section.isAnonymous()) {
+ if (Section.hasSectionRef() || Section.isAnonymous()) {
if (opts::Verbosity)
outs() << "BOLT-INFO: not writing section header for section "
- << Section.getName() << '\n';
+ << Section.getOutputName() << '\n';
continue;
}
if (opts::Verbosity >= 1)
- outs() << "BOLT-INFO: writing section header for " << Section.getName()
- << '\n';
+ outs() << "BOLT-INFO: writing section header for "
+ << Section.getOutputName() << '\n';
ELFShdrTy NewSection;
NewSection.sh_type = ELF::SHT_PROGBITS;
NewSection.sh_addr = Section.getOutputAddress();
NewSection.sh_link = 0;
NewSection.sh_info = 0;
NewSection.sh_addralign = Section.getAlignment();
- addSection(std::string(Section.getName()), NewSection);
+ addSection(NewSection, &Section);
}
// Sort all allocatable sections by their offset.
- llvm::stable_sort(OutputSections,
- [](const std::pair<std::string, ELFShdrTy> &A,
- const std::pair<std::string, ELFShdrTy> &B) {
- return A.second.sh_offset < B.second.sh_offset;
- });
+ llvm::stable_sort(OutputSections, [](const auto &A, const auto &B) {
+ return A.second.sh_offset < B.second.sh_offset;
+ });
// Fix section sizes to prevent overlapping.
ELFShdrTy *PrevSection = nullptr;
- StringRef PrevSectionName;
+ BinarySection *PrevBinSec = nullptr;
for (auto &SectionKV : OutputSections) {
ELFShdrTy &Section = SectionKV.second;
if (PrevSection &&
PrevSection->sh_addr + PrevSection->sh_size > Section.sh_addr) {
if (opts::Verbosity > 1)
- outs() << "BOLT-INFO: adjusting size for section " << PrevSectionName
- << '\n';
+ outs() << "BOLT-INFO: adjusting size for section "
+ << PrevBinSec->getOutputName() << '\n';
PrevSection->sh_size = Section.sh_addr > PrevSection->sh_addr
? Section.sh_addr - PrevSection->sh_addr
: 0;
}
PrevSection = &Section;
- PrevSectionName = SectionKV.first;
+ PrevBinSec = SectionKV.first;
}
uint64_t LastFileOffset = 0;
if (shouldStrip(Section, SectionName))
continue;
- ErrorOr<BinarySection &> BSec = BC->getUniqueSectionByName(SectionName);
- assert(BSec && "missing section info for non-allocatable section");
+ SectionRef SecRef = File->toSectionRef(&Section);
+ BinarySection *BinSec = BC->getSectionForSectionRef(SecRef);
+ assert(BinSec && "Matching BinarySection should exist.");
ELFShdrTy NewSection = Section;
- NewSection.sh_offset = BSec->getOutputFileOffset();
- NewSection.sh_size = BSec->getOutputSize();
+ NewSection.sh_offset = BinSec->getOutputFileOffset();
+ NewSection.sh_size = BinSec->getOutputSize();
if (NewSection.sh_type == ELF::SHT_SYMTAB)
NewSection.sh_info = NumLocalSymbols;
- addSection(std::string(SectionName), NewSection);
+ addSection(NewSection, BinSec);
- LastFileOffset = BSec->getOutputFileOffset();
+ LastFileOffset = BinSec->getOutputFileOffset();
}
// Create entries for new non-allocatable sections.
continue;
if (opts::Verbosity >= 1)
- outs() << "BOLT-INFO: writing section header for " << Section.getName()
- << '\n';
+ outs() << "BOLT-INFO: writing section header for "
+ << Section.getOutputName() << '\n';
ELFShdrTy NewSection;
NewSection.sh_type = Section.getELFType();
NewSection.sh_info = 0;
NewSection.sh_addralign = Section.getAlignment();
- addSection(std::string(Section.getName()), NewSection);
+ addSection(NewSection, &Section);
}
// Assign indices to sections.
std::unordered_map<std::string, uint64_t> NameToIndex;
- for (uint32_t Index = 1; Index < OutputSections.size(); ++Index) {
- const std::string &SectionName = OutputSections[Index].first;
- NameToIndex[SectionName] = Index;
- if (ErrorOr<BinarySection &> Section =
- BC->getUniqueSectionByName(SectionName))
- Section->setIndex(Index);
- }
+ for (uint32_t Index = 1; Index < OutputSections.size(); ++Index)
+ OutputSections[Index].first->setIndex(Index);
// Update section index mapping
NewSectionIndex.clear();
continue;
size_t OrgIndex = std::distance(Sections.begin(), &Section);
- std::string SectionName = getOutputSectionName(Obj, Section);
+
+ SectionRef SecRef = File->toSectionRef(&Section);
+ BinarySection *BinSec = BC->getSectionForSectionRef(SecRef);
+ assert(BinSec && "BinarySection should exist for an input section.");
// Some sections are stripped
- if (!NameToIndex.count(SectionName))
+ if (!BinSec->hasValidIndex())
continue;
- NewSectionIndex[OrgIndex] = NameToIndex[SectionName];
+ NewSectionIndex[OrgIndex] = BinSec->getIndex();
}
std::vector<ELFShdrTy> SectionsOnly(OutputSections.size());
llvm::transform(OutputSections, SectionsOnly.begin(),
- [](std::pair<std::string, ELFShdrTy> &SectionInfo) {
- return SectionInfo.second;
- });
+ [](auto &SectionInfo) { return SectionInfo.second; });
return SectionsOnly;
}
});
// If .eh_frame is present create .eh_frame_hdr.
- if (EHFrameSection && EHFrameSection->isFinalized())
+ if (EHFrameSection)
writeEHFrameHeader();
// Add BOLT Addresses Translation maps to allow profile collection to
}
void RewriteInstance::writeEHFrameHeader() {
+ BinarySection *NewEHFrameSection =
+ getSection(getNewSecPrefix() + getEHFrameSectionName());
+
+ // No need to update the header if no new .eh_frame was created.
+ if (!NewEHFrameSection)
+ return;
+
DWARFDebugFrame NewEHFrame(BC->TheTriple->getArch(), true,
- EHFrameSection->getOutputAddress());
+ NewEHFrameSection->getOutputAddress());
Error E = NewEHFrame.parse(DWARFDataExtractor(
- EHFrameSection->getOutputContents(), BC->AsmInfo->isLittleEndian(),
+ NewEHFrameSection->getOutputContents(), BC->AsmInfo->isLittleEndian(),
BC->AsmInfo->getCodePointerSize()));
check_error(std::move(E), "failed to parse EH frame");
- uint64_t OldEHFrameAddress = 0;
- StringRef OldEHFrameContents;
- ErrorOr<BinarySection &> OldEHFrameSection =
- BC->getUniqueSectionByName(Twine(getOrgSecPrefix(), ".eh_frame").str());
- if (OldEHFrameSection) {
- OldEHFrameAddress = OldEHFrameSection->getOutputAddress();
- OldEHFrameContents = OldEHFrameSection->getOutputContents();
- }
- DWARFDebugFrame OldEHFrame(BC->TheTriple->getArch(), true, OldEHFrameAddress);
- Error Er = OldEHFrame.parse(
- DWARFDataExtractor(OldEHFrameContents, BC->AsmInfo->isLittleEndian(),
- BC->AsmInfo->getCodePointerSize()));
+ uint64_t RelocatedEHFrameAddress = 0;
+ StringRef RelocatedEHFrameContents;
+ BinarySection *RelocatedEHFrameSection =
+ getSection(".relocated" + getEHFrameSectionName());
+ if (RelocatedEHFrameSection) {
+ RelocatedEHFrameAddress = RelocatedEHFrameSection->getOutputAddress();
+ RelocatedEHFrameContents = RelocatedEHFrameSection->getOutputContents();
+ }
+ DWARFDebugFrame RelocatedEHFrame(BC->TheTriple->getArch(), true,
+ RelocatedEHFrameAddress);
+ Error Er = RelocatedEHFrame.parse(DWARFDataExtractor(
+ RelocatedEHFrameContents, BC->AsmInfo->isLittleEndian(),
+ BC->AsmInfo->getCodePointerSize()));
check_error(std::move(Er), "failed to parse EH frame");
LLVM_DEBUG(dbgs() << "BOLT: writing a new .eh_frame_hdr\n");
getFileOffsetForAddress(NextAvailableAddress);
std::vector<char> NewEHFrameHdr = CFIRdWrt->generateEHFrameHeader(
- OldEHFrame, NewEHFrame, EHFrameHdrOutputAddress, FailedAddresses);
+ RelocatedEHFrame, NewEHFrame, EHFrameHdrOutputAddress, FailedAddresses);
assert(Out->os().tell() == EHFrameHdrFileOffset && "offset mismatch");
Out->os().write(NewEHFrameHdr.data(), NewEHFrameHdr.size());
const unsigned Flags = BinarySection::getFlags(/*IsReadOnly=*/true,
/*IsText=*/false,
/*IsAllocatable=*/true);
+ BinarySection *OldEHFrameHdrSection = getSection(".eh_frame_hdr");
+ if (OldEHFrameHdrSection)
+ OldEHFrameHdrSection->setOutputName(getOrgSecPrefix() + ".eh_frame_hdr");
+
BinarySection &EHFrameHdrSec = BC->registerOrUpdateSection(
- ".eh_frame_hdr", ELF::SHT_PROGBITS, Flags, nullptr, NewEHFrameHdr.size(),
- /*Alignment=*/1);
+ getNewSecPrefix() + ".eh_frame_hdr", ELF::SHT_PROGBITS, Flags, nullptr,
+ NewEHFrameHdr.size(), /*Alignment=*/1);
EHFrameHdrSec.setOutputFileOffset(EHFrameHdrFileOffset);
EHFrameHdrSec.setOutputAddress(EHFrameHdrOutputAddress);
+ EHFrameHdrSec.setOutputName(".eh_frame_hdr");
NextAvailableAddress += EHFrameHdrSec.getOutputSize();
- // Merge new .eh_frame with original so that gdb can locate all FDEs.
- if (OldEHFrameSection) {
- const uint64_t EHFrameSectionSize = (OldEHFrameSection->getOutputAddress() +
- OldEHFrameSection->getOutputSize() -
- EHFrameSection->getOutputAddress());
- EHFrameSection =
- BC->registerOrUpdateSection(".eh_frame",
- EHFrameSection->getELFType(),
- EHFrameSection->getELFFlags(),
- EHFrameSection->getOutputData(),
- EHFrameSectionSize,
- EHFrameSection->getAlignment());
- BC->deregisterSection(*OldEHFrameSection);
+ // Merge new .eh_frame with the relocated original so that gdb can locate all
+ // FDEs.
+ if (RelocatedEHFrameSection) {
+ const uint64_t NewEHFrameSectionSize =
+ RelocatedEHFrameSection->getOutputAddress() +
+ RelocatedEHFrameSection->getOutputSize() -
+ NewEHFrameSection->getOutputAddress();
+ NewEHFrameSection->updateContents(NewEHFrameSection->getOutputData(),
+ NewEHFrameSectionSize);
+ BC->deregisterSection(*RelocatedEHFrameSection);
}
LLVM_DEBUG(dbgs() << "BOLT-DEBUG: size of .eh_frame after merge is "
- << EHFrameSection->getOutputSize() << '\n');
+ << NewEHFrameSection->getOutputSize() << '\n');
}
uint64_t RewriteInstance::getNewValueForSymbol(const StringRef Name) {