[lld] r247858 - Start adding support for Elf_Rel.
Rafael Espindola via llvm-commits
llvm-commits at lists.llvm.org
Wed Sep 16 14:57:07 PDT 2015
Author: rafael
Date: Wed Sep 16 16:57:07 2015
New Revision: 247858
URL: http://llvm.org/viewvc/llvm-project?rev=247858&view=rev
Log:
Start adding support for Elf_Rel.
I don't intend to add full i686 support right now, just make sure we have all
the infrastructure in place for it.
Added:
lld/trunk/test/elf2/relocation-i686.s
Modified:
lld/trunk/ELF/Writer.cpp
Modified: lld/trunk/ELF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp?rev=247858&r1=247857&r2=247858&view=diff
==============================================================================
--- lld/trunk/ELF/Writer.cpp (original)
+++ lld/trunk/ELF/Writer.cpp Wed Sep 16 16:57:07 2015
@@ -147,6 +147,7 @@ class lld::elf2::OutputSection final
public:
typedef typename OutputSectionBase<ELFT::Is64Bits>::uintX_t uintX_t;
typedef typename ELFFile<ELFT>::Elf_Shdr Elf_Shdr;
+ typedef typename ELFFile<ELFT>::Elf_Rel Elf_Rel;
typedef typename ELFFile<ELFT>::Elf_Rela Elf_Rela;
OutputSection(StringRef Name, uint32_t sh_type, uintX_t sh_flags,
RelocationSection<ELFT> &RelaDynSec)
@@ -156,6 +157,16 @@ public:
void addChunk(SectionChunk<ELFT> *C);
void writeTo(uint8_t *Buf) override;
+ template <bool isRela>
+ void relocate(uint8_t *Buf,
+ iterator_range<const Elf_Rel_Impl<ELFT, isRela> *> Rels,
+ const ObjectFile<ELFT> &File, uintX_t BaseAddr);
+
+ void relocateOne(uint8_t *Buf, const Elf_Rela &Rel, uint32_t Type,
+ uintX_t BaseAddr, uintX_t SymVA);
+ void relocateOne(uint8_t *Buf, const Elf_Rel &Rel, uint32_t Type,
+ uintX_t BaseAddr, uintX_t SymVA);
+
private:
std::vector<SectionChunk<ELFT> *> Chunks;
RelocationSection<ELFT> &RelaDynSec;
@@ -540,61 +551,93 @@ getSymVA(const DefinedRegular<ELFT> *DR)
return OS->getVA() + SC->getOutputSectionOff() + DR->Sym.st_value;
}
+template <class ELFT>
+void OutputSection<ELFT>::relocateOne(uint8_t *Buf, const Elf_Rel &Rel,
+ uint32_t Type, uintX_t BaseAddr,
+ uintX_t SymVA) {
+ uintX_t Offset = Rel.r_offset;
+ uint8_t *Location = Buf + Offset;
+ switch (Type) {
+ case R_386_32:
+ support::endian::write32le(Location, SymVA);
+ break;
+ default:
+ llvm::errs() << Twine("unrecognized reloc ") + Twine(Type) << '\n';
+ break;
+ }
+}
+
+template <class ELFT>
+void OutputSection<ELFT>::relocateOne(uint8_t *Buf, const Elf_Rela &Rel,
+ uint32_t Type, uintX_t BaseAddr,
+ uintX_t SymVA) {
+ uintX_t Offset = Rel.r_offset;
+ uint8_t *Location = Buf + Offset;
+ switch (Type) {
+ case R_X86_64_PC32:
+ support::endian::write32le(Location,
+ SymVA + (Rel.r_addend - (BaseAddr + Offset)));
+ break;
+ case R_X86_64_64:
+ support::endian::write64le(Location, SymVA + Rel.r_addend);
+ break;
+ case R_X86_64_32: {
+ case R_X86_64_32S:
+ uint64_t VA = SymVA + Rel.r_addend;
+ if (Type == R_X86_64_32 && !isUInt<32>(VA))
+ error("R_X86_64_32 out of range");
+ else if (!isInt<32>(VA))
+ error("R_X86_64_32S out of range");
+
+ support::endian::write32le(Location, VA);
+ break;
+ }
+ default:
+ llvm::errs() << Twine("unrecognized reloc ") + Twine(Type) << '\n';
+ break;
+ }
+}
+
+template <class ELFT>
+template <bool isRela>
+void OutputSection<ELFT>::relocate(
+ uint8_t *Buf, iterator_range<const Elf_Rel_Impl<ELFT, isRela> *> Rels,
+ const ObjectFile<ELFT> &File, uintX_t BaseAddr) {
+ typedef Elf_Rel_Impl<ELFT, isRela> RelType;
+ bool IsMips64EL = File.getObj()->isMips64EL();
+ for (const RelType &RI : Rels) {
+ uint32_t SymIndex = RI.getSymbol(IsMips64EL);
+ const SymbolBody *Body = File.getSymbolBody(SymIndex);
+ if (!Body)
+ continue;
+
+ uintX_t SymVA;
+ if (auto *DR = dyn_cast<DefinedRegular<ELFT>>(Body))
+ SymVA = getSymVA<ELFT>(DR);
+ else if (auto *DA = dyn_cast<DefinedAbsolute<ELFT>>(Body))
+ SymVA = DA->Sym.st_value;
+ else
+ // Skip unsupported for now.
+ continue;
+
+ uint32_t Type = RI.getType(IsMips64EL);
+ relocateOne(Buf, RI, Type, BaseAddr, SymVA);
+ }
+}
+
template <class ELFT> void OutputSection<ELFT>::writeTo(uint8_t *Buf) {
for (SectionChunk<ELFT> *C : Chunks) {
C->writeTo(Buf);
const ObjectFile<ELFT> *File = C->getFile();
ELFFile<ELFT> *EObj = File->getObj();
uint8_t *Base = Buf + C->getOutputSectionOff();
-
+ uintX_t BaseAddr = this->getVA() + C->getOutputSectionOff();
// Iterate over all relocation sections that apply to this section.
for (const Elf_Shdr *RelSec : C->RelocSections) {
- // Only support RELA for now.
- if (RelSec->sh_type != SHT_RELA)
- continue;
- for (const Elf_Rela &RI : EObj->relas(RelSec)) {
- uint32_t SymIndex = RI.getSymbol(EObj->isMips64EL());
- const SymbolBody *Body = File->getSymbolBody(SymIndex);
- if (!Body)
- continue;
-
- uintX_t SymVA;
- if (auto *DR = dyn_cast<DefinedRegular<ELFT>>(Body))
- SymVA = getSymVA<ELFT>(DR);
- else if (auto *DA = dyn_cast<DefinedAbsolute<ELFT>>(Body))
- SymVA = DA->Sym.st_value;
- else
- // Skip unsupported for now.
- continue;
-
- uintX_t Offset = RI.r_offset;
- uint32_t Type = RI.getType(EObj->isMips64EL());
- uintX_t P = this->getVA() + C->getOutputSectionOff();
- uint8_t *Location = Base + Offset;
- switch (Type) {
- case llvm::ELF::R_X86_64_PC32:
- support::endian::write32le(Location,
- SymVA + (RI.r_addend - (P + Offset)));
- break;
- case llvm::ELF::R_X86_64_64:
- support::endian::write64le(Location, SymVA + RI.r_addend);
- break;
- case llvm::ELF::R_X86_64_32: {
- case llvm::ELF::R_X86_64_32S:
- uint64_t VA = SymVA + RI.r_addend;
- if (Type == llvm::ELF::R_X86_64_32 && !isUInt<32>(VA))
- error("R_X86_64_32 out of range");
- else if (!isInt<32>(VA))
- error("R_X86_64_32S out of range");
-
- support::endian::write32le(Location, VA);
- break;
- }
- default:
- llvm::errs() << Twine("unrecognized reloc ") + Twine(Type) << '\n';
- break;
- }
- }
+ if (RelSec->sh_type == SHT_RELA)
+ relocate(Base, EObj->relas(RelSec), *File, BaseAddr);
+ else
+ relocate(Base, EObj->rels(RelSec), *File, BaseAddr);
}
}
}
Added: lld/trunk/test/elf2/relocation-i686.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf2/relocation-i686.s?rev=247858&view=auto
==============================================================================
--- lld/trunk/test/elf2/relocation-i686.s (added)
+++ lld/trunk/test/elf2/relocation-i686.s Wed Sep 16 16:57:07 2015
@@ -0,0 +1,16 @@
+// RUN: llvm-mc -filetype=obj -triple=i686-pc-linux %s -o %t
+// RUN: lld -flavor gnu2 %t -o %t2
+// RUN: llvm-objdump -d %t2 | FileCheck %s
+// REQUIRES: x86
+
+.global _start
+_start:
+
+.section .R_386_32,"ax", at progbits
+.global R_386_32
+R_386_32:
+ movl $R_386_32, %edx
+
+// CHECK: Disassembly of section .R_386_32:
+// CHECK-NEXT: R_386_32:
+// CHECK-NEXT: 11000: {{.*}} movl $69632, %edx
More information about the llvm-commits
mailing list