[ELF2] - Basic implementation of -r/--relocatable
-r, -relocatable - Generate relocatable output
Currently does not have support for files containing
relocation sections with entries that refer to local
symbols (like rel[a].eh_frame which refer to sections
and not to symbols)
Differential revision: http://reviews.llvm.org/D14382
llvm-svn: 261838
diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp
index 231d9f1..e902e00 100644
--- a/lld/ELF/InputSection.cpp
+++ b/lld/ELF/InputSection.cpp
@@ -105,6 +105,43 @@
}
template <class ELFT>
+InputSectionBase<ELFT> *InputSection<ELFT>::getRelocatedSection() {
+ assert(this->Header->sh_type == SHT_RELA || this->Header->sh_type == SHT_REL);
+ ArrayRef<InputSectionBase<ELFT> *> Sections = this->File->getSections();
+ return Sections[this->Header->sh_info];
+}
+
+// This is used for -r. We can't use memcpy to copy relocations because we need
+// to update symbol table offset and section index for each relocation. So we
+// copy relocations one by one.
+template <class ELFT>
+template <bool isRela>
+void InputSection<ELFT>::copyRelocations(uint8_t *Buf,
+ RelIteratorRange<isRela> Rels) {
+ typedef Elf_Rel_Impl<ELFT, isRela> RelType;
+ InputSectionBase<ELFT> *RelocatedSection = getRelocatedSection();
+
+ for (const RelType &Rel : Rels) {
+ uint32_t SymIndex = Rel.getSymbol(Config->Mips64EL);
+ uint32_t Type = Rel.getType(Config->Mips64EL);
+ const Elf_Shdr *SymTab = this->File->getSymbolTable();
+
+ RelType *P = reinterpret_cast<RelType *>(Buf);
+ Buf += sizeof(RelType);
+
+ // Relocation for local symbol here means that it is probably
+ // rel[a].eh_frame section which has references to
+ // sections in r_info field. Also needs fix for addend.
+ if (SymIndex < SymTab->sh_info)
+ fatal("Relocation against local symbols is not supported yet");
+
+ SymbolBody *Body = this->File->getSymbolBody(SymIndex)->repl();
+ P->r_offset = RelocatedSection->getOffset(Rel.r_offset);
+ P->setSymbolAndType(Body->DynsymIndex, Type, Config->Mips64EL);
+ }
+}
+
+template <class ELFT>
template <bool isRela>
uint8_t *
InputSectionBase<ELFT>::findMipsPairedReloc(uint8_t *Buf, uint32_t SymIndex,
@@ -256,9 +293,21 @@
return;
// Copy section contents from source object file to output file.
ArrayRef<uint8_t> Data = this->getSectionData();
+ ELFFile<ELFT> &EObj = this->File->getObj();
+
+ // That happens with -r. In that case we need fix the relocation position and
+ // target. No relocations are applied.
+ if (this->Header->sh_type == SHT_RELA) {
+ this->copyRelocations(Buf + OutSecOff, EObj.relas(this->Header));
+ return;
+ }
+ if (this->Header->sh_type == SHT_REL) {
+ this->copyRelocations(Buf + OutSecOff, EObj.rels(this->Header));
+ return;
+ }
+
memcpy(Buf + OutSecOff, Data.data(), Data.size());
- ELFFile<ELFT> &EObj = this->File->getObj();
uint8_t *BufEnd = Buf + OutSecOff + Data.size();
// Iterate over all relocation sections that apply to this section.
for (const Elf_Shdr *RelSec : this->RelocSections) {