diff options
author | Reid Kleckner <rnk@google.com> | 2018-06-22 23:53:22 +0000 |
---|---|---|
committer | Reid Kleckner <rnk@google.com> | 2018-06-22 23:53:22 +0000 |
commit | 330f65b3e8eb308c2501c381de37f9bd715d99eb (patch) | |
tree | 892282af7d73d9012481b910334d5c68c662fdd7 /llvm/lib/ExecutionEngine/RuntimeDyld | |
parent | ef115de6290d10922f5f82d2e004532a337f2ec6 (diff) | |
download | bcm5719-llvm-330f65b3e8eb308c2501c381de37f9bd715d99eb.tar.gz bcm5719-llvm-330f65b3e8eb308c2501c381de37f9bd715d99eb.zip |
[RuntimeDyld] Implement the ELF PIC large code model relocations
Prerequisite for https://reviews.llvm.org/D47211 which improves our ELF
large PIC codegen.
llvm-svn: 335402
Diffstat (limited to 'llvm/lib/ExecutionEngine/RuntimeDyld')
-rw-r--r-- | llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp | 43 |
1 files changed, 43 insertions, 0 deletions
diff --git a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp index 91fd129224b..cc6729d2132 100644 --- a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp +++ b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp @@ -312,6 +312,22 @@ void RuntimeDyldELF::resolveX86_64Relocation(const SectionEntry &Section, int64_t RealOffset = Value + Addend - FinalAddress; support::ulittle64_t::ref(Section.getAddressWithOffset(Offset)) = RealOffset; + LLVM_DEBUG(dbgs() << "Writing " << format("%p", RealOffset) << " at " + << format("%p\n", FinalAddress)); + break; + } + case ELF::R_X86_64_GOTOFF64: { + // Compute Value - GOTBase. + uint64_t GOTBase = 0; + for (const auto &Section : Sections) { + if (Section.getName() == ".got") { + GOTBase = Section.getLoadAddressWithOffset(0); + break; + } + } + assert(GOTBase != 0 && "missing GOT"); + int64_t GOTOffset = Value - GOTBase + Addend; + support::ulittle64_t::ref(Section.getAddressWithOffset(Offset)) = GOTOffset; break; } } @@ -1700,6 +1716,29 @@ RuntimeDyldELF::processRelocationRef( addRelocationForSymbol(RE, Value.SymbolName); else addRelocationForSection(RE, Value.SectionID); + } else if (RelType == ELF::R_X86_64_GOT64) { + // Fill in a 64-bit GOT offset. + uint64_t GOTOffset = allocateGOTEntries(1); + resolveRelocation(Sections[SectionID], Offset, GOTOffset, + ELF::R_X86_64_64, 0); + + // Fill in the value of the symbol we're targeting into the GOT + RelocationEntry RE = + computeGOTOffsetRE(GOTOffset, Value.Offset, ELF::R_X86_64_64); + if (Value.SymbolName) + addRelocationForSymbol(RE, Value.SymbolName); + else + addRelocationForSection(RE, Value.SectionID); + } else if (RelType == ELF::R_X86_64_GOTPC64) { + // Materialize the address of the base of the GOT relative to the PC. + // This doesn't create a GOT entry, but it does mean we need a GOT + // section. + (void)allocateGOTEntries(0); + resolveGOTOffsetRelocation(SectionID, Offset, Addend, ELF::R_X86_64_PC64); + } else if (RelType == ELF::R_X86_64_GOTOFF64) { + // GOTOFF relocations ultimately require a section difference relocation. + (void)allocateGOTEntries(0); + processSimpleRelocation(SectionID, Offset, RelType, Value); } else if (RelType == ELF::R_X86_64_PC32) { Value.Addend += support::ulittle32_t::ref(computePlaceholderAddress(SectionID, Offset)); processSimpleRelocation(SectionID, Offset, RelType, Value); @@ -1871,6 +1910,7 @@ bool RuntimeDyldELF::relocationNeedsGot(const RelocationRef &R) const { if (Arch == Triple::x86_64) return RelTy == ELF::R_X86_64_GOTPCREL || RelTy == ELF::R_X86_64_GOTPCRELX || + RelTy == ELF::R_X86_64_GOT64 || RelTy == ELF::R_X86_64_REX_GOTPCRELX; return false; } @@ -1887,6 +1927,9 @@ bool RuntimeDyldELF::relocationNeedsStub(const RelocationRef &R) const { case ELF::R_X86_64_GOTPCREL: case ELF::R_X86_64_GOTPCRELX: case ELF::R_X86_64_REX_GOTPCRELX: + case ELF::R_X86_64_GOTPC64: + case ELF::R_X86_64_GOT64: + case ELF::R_X86_64_GOTOFF64: case ELF::R_X86_64_PC32: case ELF::R_X86_64_PC64: case ELF::R_X86_64_64: |