diff options
| author | Denis Protivensky <dprotivensky@accesssoftek.com> | 2015-03-27 16:29:08 +0000 |
|---|---|---|
| committer | Denis Protivensky <dprotivensky@accesssoftek.com> | 2015-03-27 16:29:08 +0000 |
| commit | 7eda0225214097f2ca8628dfdbb52213843bb8da (patch) | |
| tree | 4ba70dafeacf5da51efd2d6a7d76b588a3da2103 /lld/lib/ReaderWriter/ELF/ARM/ARMRelocationHandler.cpp | |
| parent | bfbc7b9c41ae8befab24acd9c05c3f9f27e594b6 (diff) | |
| download | bcm5719-llvm-7eda0225214097f2ca8628dfdbb52213843bb8da.tar.gz bcm5719-llvm-7eda0225214097f2ca8628dfdbb52213843bb8da.zip | |
[ARM] Handle GOT relocations
This includes relocs needed to link against glibc:
R_ARM_BASE_PREL
R_ARM_GOT_BREL
Every reloc is accompanied with a test case.
llvm-svn: 233383
Diffstat (limited to 'lld/lib/ReaderWriter/ELF/ARM/ARMRelocationHandler.cpp')
| -rw-r--r-- | lld/lib/ReaderWriter/ELF/ARM/ARMRelocationHandler.cpp | 42 |
1 files changed, 42 insertions, 0 deletions
diff --git a/lld/lib/ReaderWriter/ELF/ARM/ARMRelocationHandler.cpp b/lld/lib/ReaderWriter/ELF/ARM/ARMRelocationHandler.cpp index 4f436727094..9a96a93f040 100644 --- a/lld/lib/ReaderWriter/ELF/ARM/ARMRelocationHandler.cpp +++ b/lld/lib/ReaderWriter/ELF/ARM/ARMRelocationHandler.cpp @@ -82,6 +82,8 @@ static Reference::Addend readAddend(const uint8_t *location, switch (kindValue) { case R_ARM_ABS32: case R_ARM_REL32: + case R_ARM_GOT_BREL: + case R_ARM_BASE_PREL: case R_ARM_TLS_IE32: case R_ARM_TLS_LE32: return (int32_t)read32le(location); @@ -257,6 +259,32 @@ static void relocR_ARM_THM_JUMP11(uint8_t *location, uint64_t P, uint64_t S, applyThumb16Reloc(location, result, 0x7FF); } +/// \brief R_ARM_BASE_PREL - B(S) + A - P => S + A - P +static void relocR_ARM_BASE_PREL(uint8_t *location, uint64_t P, uint64_t S, + int64_t A) { + uint32_t result = (uint32_t)(S + A - P); + DEBUG_WITH_TYPE( + "ARM", llvm::dbgs() << "\t\tHandle " << LLVM_FUNCTION_NAME << " -"; + llvm::dbgs() << " S: 0x" << Twine::utohexstr(S); + llvm::dbgs() << " A: 0x" << Twine::utohexstr(A); + llvm::dbgs() << " P: 0x" << Twine::utohexstr(P); + llvm::dbgs() << " result: 0x" << Twine::utohexstr(result) << "\n"); + applyArmReloc(location, result); +} + +/// \brief R_ARM_GOT_BREL - GOT(S) + A - GOT_ORG => S + A - GOT_ORG +static void relocR_ARM_GOT_BREL(uint8_t *location, uint64_t P, uint64_t S, + int64_t A, uint64_t GOT_ORG) { + uint32_t result = (uint32_t)(S + A - GOT_ORG); + DEBUG_WITH_TYPE( + "ARM", llvm::dbgs() << "\t\tHandle " << LLVM_FUNCTION_NAME << " -"; + llvm::dbgs() << " S: 0x" << Twine::utohexstr(S); + llvm::dbgs() << " A: 0x" << Twine::utohexstr(A); + llvm::dbgs() << " P: 0x" << Twine::utohexstr(P); + llvm::dbgs() << " result: 0x" << Twine::utohexstr(result) << "\n"); + applyArmReloc(location, result); +} + /// \brief R_ARM_CALL - ((S + A) | T) - P static void relocR_ARM_CALL(uint8_t *location, uint64_t P, uint64_t S, int64_t A, bool addressesThumb) { @@ -561,6 +589,20 @@ std::error_code ARMTargetRelocationHandler::applyRelocation( relocR_ARM_TLS_LE32(location, relocVAddress, targetVAddress, addend, _armLayout.getTPOffset()); break; + case R_ARM_GOT_BREL: + relocR_ARM_GOT_BREL(location, relocVAddress, targetVAddress, addend, + _armLayout.getGOTSymAddr()); + break; + case R_ARM_BASE_PREL: + // GOT origin is used for NULL symbol and when explicitly specified + if (!targetVAddress || + ref.target()->name().equals("_GLOBAL_OFFSET_TABLE_")) { + targetVAddress = _armLayout.getGOTSymAddr(); + } else { + llvm_unreachable("Segment-base relative addressing is not supported"); + } + relocR_ARM_BASE_PREL(location, relocVAddress, targetVAddress, addend); + break; case R_ARM_ALU_PC_G0_NC: relocR_ARM_ALU_PC_G0_NC(location, relocVAddress, targetVAddress, addend); break; |

