Index: src/IceELFObjectWriter.cpp |
diff --git a/src/IceELFObjectWriter.cpp b/src/IceELFObjectWriter.cpp |
index 7eebfa9ee0627b2b2c5845c6b116592330a7c802..f1b698b434a2058cdd7b7b8ea93ed205933a04f8 100644 |
--- a/src/IceELFObjectWriter.cpp |
+++ b/src/IceELFObjectWriter.cpp |
@@ -11,6 +11,7 @@ |
// |
//===----------------------------------------------------------------------===// |
+#include "assembler.h" |
#include "IceDefs.h" |
#include "IceELFObjectWriter.h" |
#include "IceELFSection.h" |
@@ -114,7 +115,7 @@ void ELFObjectWriter::assignRelSectionNumInPairs(SizeT &CurSectionNumber, |
UserSection->setNameStrIndex(ShStrTab->getIndex(UserSection->getName())); |
AllSections.push_back(UserSection); |
if (RelIt != RelE) { |
- ELFRelocationSectionBase *RelSection = *RelIt; |
+ ELFRelocationSection *RelSection = *RelIt; |
if (RelSection->getRelatedSection() == UserSection) { |
RelSection->setInfoNum(UserSection->getNumber()); |
RelSection->setNumber(CurSectionNumber++); |
@@ -131,7 +132,7 @@ void ELFObjectWriter::assignRelSectionNumInPairs(SizeT &CurSectionNumber, |
void ELFObjectWriter::assignRelLinkNum(SizeT SymTabNumber, |
RelSectionList &RelSections) { |
- for (ELFRelocationSectionBase *S : RelSections) { |
+ for (ELFRelocationSection *S : RelSections) { |
S->setLinkNum(SymTabNumber); |
} |
} |
@@ -187,12 +188,11 @@ Elf64_Off ELFObjectWriter::alignFileOffset(Elf64_Xword Align) { |
} |
void ELFObjectWriter::writeFunctionCode(const IceString &FuncName, |
- bool IsInternal, |
- const llvm::StringRef Data) { |
+ bool IsInternal, const Assembler *Asm) { |
assert(!SectionNumbersAssigned); |
+ ELFTextSection *Section = nullptr; |
// TODO(jvoung): handle ffunction-sections. |
IceString SectionName = ".text"; |
- ELFTextSection *Section = nullptr; |
if (TextSections.size() == 0) { |
const Elf64_Xword ShFlags = SHF_ALLOC | SHF_EXECINSTR; |
// TODO(jvoung): Should be bundle size. Grab it from that target? |
@@ -209,7 +209,7 @@ void ELFObjectWriter::writeFunctionCode(const IceString &FuncName, |
// Function symbols are set to 0 size in the symbol table, |
// in contrast to data symbols which have a proper size. |
SizeT SymbolSize = 0; |
- Section->appendData(Str, Data); |
+ Section->appendData(Str, Asm->getBufferView()); |
uint8_t SymbolType; |
uint8_t SymbolBinding; |
if (IsInternal) { |
@@ -222,6 +222,38 @@ void ELFObjectWriter::writeFunctionCode(const IceString &FuncName, |
SymTab->createDefinedSym(FuncName, SymbolType, SymbolBinding, Section, |
OffsetInSection, SymbolSize); |
StrTab->add(FuncName); |
+ |
+ // Create a relocation section for the text section if needed, and copy the |
+ // fixup information from per-function Assembler memory to the object |
+ // writer's memory, for writing later. |
+ if (!Asm->fixups().empty()) { |
+ bool IsELF64 = isELF64(Ctx.getTargetArch()); |
+ IceString RelSectionName = IsELF64 ? ".rela" : ".rel"; |
+ RelSectionName += SectionName; |
+ ELFRelocationSection *RelSection = nullptr; |
+ // TODO(jvoung): Make this more efficient if -ffunction-sections |
+ // efficiency becomes a problem. |
+ auto RSI = |
+ std::find_if(RelTextSections.begin(), RelTextSections.end(), |
+ [&RelSectionName](const ELFRelocationSection *S) |
+ -> bool { return S->getName() == RelSectionName; }); |
+ if (RSI != RelTextSections.end()) { |
+ RelSection = *RSI; |
+ } else { |
+ const Elf64_Word ShType = IsELF64 ? SHT_RELA : SHT_REL; |
+ const Elf64_Xword ShAlign = IsELF64 ? 8 : 4; |
+ const Elf64_Xword ShEntSize = |
+ IsELF64 ? sizeof(Elf64_Rela) : sizeof(Elf32_Rel); |
+ static_assert(sizeof(Elf64_Rela) == 24 && sizeof(Elf32_Rel) == 8, |
+ "Elf_Rel/Rela sizes cannot be derived from sizeof"); |
+ const Elf64_Xword ShFlags = 0; |
+ RelSection = createSection<ELFRelocationSection>( |
+ RelSectionName, ShType, ShFlags, ShAlign, ShEntSize); |
+ RelSection->setRelatedSection(Section); |
+ RelTextSections.push_back(RelSection); |
+ } |
+ RelSection->addRelocations(OffsetInSection, Asm->fixups()); |
+ } |
} |
void ELFObjectWriter::writeDataInitializer(const IceString &VarName, |
@@ -347,6 +379,26 @@ template void ELFObjectWriter::writeConstantPool<ConstantFloat>(Type Ty); |
template void ELFObjectWriter::writeConstantPool<ConstantDouble>(Type Ty); |
+void ELFObjectWriter::writeAllRelocationSections(bool IsELF64) { |
+ writeRelocationSections(IsELF64, RelTextSections); |
+ writeRelocationSections(IsELF64, RelDataSections); |
+ writeRelocationSections(IsELF64, RelRoDataSections); |
+} |
+ |
+void ELFObjectWriter::writeRelocationSections(bool IsELF64, |
+ RelSectionList &RelSections) { |
+ for (ELFRelocationSection *RelSec : RelSections) { |
+ Elf64_Off Offset = alignFileOffset(RelSec->getSectionAlign()); |
+ RelSec->setFileOffset(Offset); |
+ RelSec->setSize(RelSec->getSectionDataSize(Ctx, SymTab)); |
+ if (IsELF64) { |
+ RelSec->writeData<true>(Ctx, Str, SymTab); |
+ } else { |
+ RelSec->writeData<false>(Ctx, Str, SymTab); |
+ } |
+ } |
+} |
+ |
void ELFObjectWriter::writeNonUserSections() { |
bool IsELF64 = isELF64(Ctx.getTargetArch()); |
@@ -375,9 +427,7 @@ void ELFObjectWriter::writeNonUserSections() { |
StrTab->setFileOffset(StrTabOffset); |
Str.writeBytes(StrTab->getSectionData()); |
- // TODO: Write out the relocation sections. |
- // May also be able to seek around the file and resolve function calls |
- // that are for functions within the same section. |
+ writeAllRelocationSections(IsELF64); |
// Write out the section headers. |
const size_t ShdrAlign = IsELF64 ? 8 : 4; |