summaryrefslogtreecommitdiffstats
path: root/lld/lib/ReaderWriter/ELF/ARM/ARMRelocationHandler.cpp
diff options
context:
space:
mode:
authorDenis Protivensky <dprotivensky@accesssoftek.com>2015-03-27 16:29:08 +0000
committerDenis Protivensky <dprotivensky@accesssoftek.com>2015-03-27 16:29:08 +0000
commit7eda0225214097f2ca8628dfdbb52213843bb8da (patch)
tree4ba70dafeacf5da51efd2d6a7d76b588a3da2103 /lld/lib/ReaderWriter/ELF/ARM/ARMRelocationHandler.cpp
parentbfbc7b9c41ae8befab24acd9c05c3f9f27e594b6 (diff)
downloadbcm5719-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.cpp42
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;
OpenPOWER on IntegriCloud