Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for SHT_RELA in LGC ElfLinker #2856

Merged
merged 1 commit into from
Nov 29, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 39 additions & 10 deletions lgc/elfLinker/ElfLinker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ class OutputSection {

// Add a relocation to the output elf
void addRelocation(object::ELFRelocationRef relocRef, StringRef id, unsigned int relocSectionOffset,
unsigned int targetSectionOffset);
unsigned int targetSectionOffset, unsigned sectType);

// Get the output file offset of a particular input section in the output section
uint64_t getOutputOffset(unsigned inputIdx) { return m_offset + m_inputSections[inputIdx].offset; }
Expand Down Expand Up @@ -180,6 +180,7 @@ class ElfLinkerImpl final : public ElfLinker {
StringRef getStrings() { return m_strings; }
SmallVectorImpl<ELF::Elf64_Sym> &getSymbols() { return m_symbols; }
SmallVectorImpl<ELF::Elf64_Rel> &getRelocations() { return m_relocations; }
SmallVectorImpl<ELF::Elf64_Rela> &getRelocationsA() { return m_relocationsA; }
void setStringTableIndex(unsigned index) { m_ehdr.e_shstrndx = index; }
StringRef getNotes() { return m_notes; }

Expand Down Expand Up @@ -229,6 +230,7 @@ class ElfLinkerImpl final : public ElfLinker {
SmallVector<OutputSection, 4> m_outputSections; // Output sections
SmallVector<ELF::Elf64_Sym, 8> m_symbols; // Symbol table
SmallVector<ELF::Elf64_Rel, 8> m_relocations; // Relocations
SmallVector<ELF::Elf64_Rela, 8> m_relocationsA; // Relocations with explicit addend
StringMap<unsigned> m_symbolMap; // Map from name to symbol index
std::string m_strings; // Strings for string table
StringMap<unsigned> m_stringMap; // Map from string to string table index
Expand Down Expand Up @@ -447,16 +449,22 @@ bool ElfLinkerImpl::link(raw_pwrite_stream &outStream) {
// The creation of the relocation section is delayed below so we can create it only if there is at least one
// relocation.
bool relSectionCreated = false;
bool relaSectionCreated = false;

// Allocate input sections to output sections.
for (auto &elfInput : m_elfInputs) {
for (const object::SectionRef &section : elfInput.objectFile->sections()) {
unsigned sectType = object::ELFSectionRef(section).getType();
if (sectType == ELF::SHT_REL || sectType == ELF::SHT_RELA) {
if (!relSectionCreated && section.relocation_begin() != section.relocation_end()) {
if (sectType == ELF::SHT_REL) {
if (!relSectionCreated && !section.relocations().empty()) {
m_outputSections.push_back(OutputSection(this, ".rel.text", ELF::SHT_REL));
relSectionCreated = true;
}
} else if (sectType == ELF::SHT_RELA) {
if (!relaSectionCreated && !section.relocations().empty()) {
m_outputSections.push_back(OutputSection(this, ".rela.text", ELF::SHT_RELA));
relaSectionCreated = true;
}
} else if (sectType == ELF::SHT_PROGBITS) {
// Put same-named sections together (excluding symbol table, string table, reloc sections).
StringRef name = cantFail(section.getName());
Expand Down Expand Up @@ -547,15 +555,15 @@ bool ElfLinkerImpl::link(raw_pwrite_stream &outStream) {
if (targetSectionIdx != UINT_MAX) {
(void)(textSectionIdx);
assert(targetSectionIdx == textSectionIdx && "We assume all relocations are applied to the text section");
assert(sectType == ELF::SHT_REL && "We do not output a RELA section yet");
object::SectionRef relocSection = *cantFail(reloc.getSymbol()->getSection());
unsigned relocSectionId = UINT_MAX;
unsigned relocIdxInSection = UINT_MAX;
std::tie(relocSectionId, relocIdxInSection) = findInputSection(elfInput, relocSection);
uint64_t relocSectionOffset = m_outputSections[relocSectionId].getOutputOffset(relocIdxInSection);
uint64_t targetSectionOffset = m_outputSections[targetSectionIdx].getOutputOffset(targetIdxInSection);
StringRef id = sys::path::filename(elfInput.objectFile->getFileName());
m_outputSections[relocSectionId].addRelocation(reloc, id, relocSectionOffset, targetSectionOffset);
m_outputSections[relocSectionId].addRelocation(reloc, id, relocSectionOffset, targetSectionOffset,
sectType);
}
}
}
Expand Down Expand Up @@ -965,8 +973,7 @@ void OutputSection::addSymbol(const object::ELFSymbolRef &elfSymRef, unsigned in

// Add a relocation to the output elf
void OutputSection::addRelocation(object::ELFRelocationRef relocRef, StringRef id, unsigned int relocSectionOffset,
unsigned int targetSectionOffset) {
ELF::Elf64_Rel newReloc = {};
unsigned int targetSectionOffset, unsigned sectType) {
object::ELFSymbolRef relocSymRef(*relocRef.getSymbol());
std::string rodataSymName = cantFail(relocSymRef.getName()).str();
rodataSymName += ".";
Expand All @@ -984,9 +991,19 @@ void OutputSection::addRelocation(object::ELFRelocationRef relocRef, StringRef i
rodataSymIdx = m_linker->getSymbols().size();
m_linker->getSymbols().push_back(newSym);
}
newReloc.setSymbolAndType(rodataSymIdx, relocRef.getType());
newReloc.r_offset = targetSectionOffset + relocRef.getOffset();
m_linker->getRelocations().push_back(newReloc);
if (sectType == ELF::SHT_REL) {
ELF::Elf64_Rel newReloc = {};
newReloc.setSymbolAndType(rodataSymIdx, relocRef.getType());
newReloc.r_offset = targetSectionOffset + relocRef.getOffset();
m_linker->getRelocations().push_back(newReloc);
} else {
assert(sectType == ELF::SHT_RELA);
ELF::Elf64_Rela newReloc = {};
newReloc.setSymbolAndType(rodataSymIdx, relocRef.getType());
newReloc.r_offset = targetSectionOffset + relocRef.getOffset();
newReloc.r_addend = cantFail(relocRef.getAddend());
m_linker->getRelocationsA().push_back(newReloc);
}
}

// =====================================================================================================================
Expand Down Expand Up @@ -1037,6 +1054,18 @@ void OutputSection::write(raw_pwrite_stream &outStream, ELF::Elf64_Shdr *shdr) {
return;
}

if (m_type == ELF::SHT_RELA) {
ArrayRef<ELF::Elf64_Rela> relocations = m_linker->getRelocationsA();
shdr->sh_type = m_type;
shdr->sh_size = relocations.size() * sizeof(ELF::Elf64_Rela);
shdr->sh_entsize = sizeof(ELF::Elf64_Rela);
shdr->sh_link = 2; // Section index of symbol table
shdr->sh_info = 3; // Section index of the .text section
outStream << StringRef(reinterpret_cast<const char *>(relocations.data()),
relocations.size() * sizeof(ELF::Elf64_Rela));
return;
}

if (m_inputSections.empty())
return;

Expand Down
Loading