summaryrefslogtreecommitdiffstats
path: root/lld/lib/ReaderWriter/ELF/ARM
diff options
context:
space:
mode:
authorDenis Protivensky <dprotivensky@accesssoftek.com>2015-03-17 09:18:24 +0000
committerDenis Protivensky <dprotivensky@accesssoftek.com>2015-03-17 09:18:24 +0000
commite458ab45774966c263817fdd63613faf28cf843c (patch)
tree1ffa4e4fc2d53deffa07bdf599fbb650df8ef34e /lld/lib/ReaderWriter/ELF/ARM
parentb326765175f7be0a8b8aebf6d17ba769793e5c67 (diff)
downloadbcm5719-llvm-e458ab45774966c263817fdd63613faf28cf843c.tar.gz
bcm5719-llvm-e458ab45774966c263817fdd63613faf28cf843c.zip
[ARM] Implement relocations: R_ARM_REL32, R_ARM_THM_JUMP11, R_ARM_PREL31
Test case for every relocation is added. Differential Revision: http://reviews.llvm.org/D7565 llvm-svn: 232464
Diffstat (limited to 'lld/lib/ReaderWriter/ELF/ARM')
-rw-r--r--lld/lib/ReaderWriter/ELF/ARM/ARMRelocationHandler.cpp82
1 files changed, 81 insertions, 1 deletions
diff --git a/lld/lib/ReaderWriter/ELF/ARM/ARMRelocationHandler.cpp b/lld/lib/ReaderWriter/ELF/ARM/ARMRelocationHandler.cpp
index 938210f8f49..c99015275b6 100644
--- a/lld/lib/ReaderWriter/ELF/ARM/ARMRelocationHandler.cpp
+++ b/lld/lib/ReaderWriter/ELF/ARM/ARMRelocationHandler.cpp
@@ -70,6 +70,13 @@ static Reference::Addend readAddend_ARM_CALL(const uint8_t *location) {
return llvm::SignExtend64<26>(result);
}
+static Reference::Addend readAddend_THM_JUMP11(const uint8_t *location) {
+ const auto value = read16le(location);
+ const uint16_t imm11 = value & 0x7FF;
+
+ return llvm::SignExtend32<12>(imm11 << 1);
+}
+
static Reference::Addend readAddend(const uint8_t *location,
Reference::KindValue kindValue) {
switch (kindValue) {
@@ -78,6 +85,8 @@ static Reference::Addend readAddend(const uint8_t *location,
case R_ARM_THM_CALL:
case R_ARM_THM_JUMP24:
return readAddend_THM_CALL(location);
+ case R_ARM_THM_JUMP11:
+ return readAddend_THM_JUMP11(location);
case R_ARM_CALL:
case R_ARM_JUMP24:
return readAddend_ARM_CALL(location);
@@ -107,6 +116,12 @@ static inline void applyThmReloc(uint8_t *location, uint16_t resHi,
write16le(location, (read16le(location) & ~maskLo) | (resLo & maskLo));
}
+static inline void applyThumb16Reloc(uint8_t *location, uint16_t result,
+ uint16_t mask = 0xFFFF) {
+ assert(!(result & ~mask));
+ write16le(location, (read16le(location) & ~mask) | (result & mask));
+}
+
/// \brief R_ARM_ABS32 - (S + A) | T
static void relocR_ARM_ABS32(uint8_t *location, uint64_t P, uint64_t S,
int64_t A, bool addressesThumb) {
@@ -123,6 +138,42 @@ static void relocR_ARM_ABS32(uint8_t *location, uint64_t P, uint64_t S,
applyArmReloc(location, result);
}
+/// \brief R_ARM_REL32 - ((S + A) | T) - P
+static void relocR_ARM_REL32(uint8_t *location, uint64_t P, uint64_t S,
+ int64_t A, bool addressesThumb) {
+ uint64_t T = addressesThumb;
+ uint32_t result = (uint32_t)(((S + A) | T) - 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() << " T: 0x" << Twine::utohexstr(T);
+ llvm::dbgs() << " result: 0x" << Twine::utohexstr(result) << "\n");
+ applyArmReloc(location, result);
+}
+
+/// \brief R_ARM_PREL31 - ((S + A) | T) - P
+static void relocR_ARM_PREL31(uint8_t *location, uint64_t P, uint64_t S,
+ int64_t A, bool addressesThumb) {
+ uint64_t T = addressesThumb;
+ uint32_t result = (uint32_t)(((S + A) | T) - P);
+ const uint32_t mask = 0x7FFFFFFF;
+ uint32_t rel31 = result & mask;
+
+ 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() << " T: 0x" << Twine::utohexstr(T);
+ llvm::dbgs() << " result: 0x" << Twine::utohexstr(result);
+ llvm::dbgs() << " rel31: 0x" << Twine::utohexstr(rel31) << "\n");
+
+ applyArmReloc(location, rel31, mask);
+}
+
/// \brief Relocate B/BL instructions. useJs defines whether J1 & J2 are used
static void relocR_ARM_THM_B_L(uint8_t *location, uint32_t result, bool useJs) {
result = (result & 0x01FFFFFE) >> 1;
@@ -183,6 +234,24 @@ static void relocR_ARM_THM_JUMP24(uint8_t *location, uint64_t P, uint64_t S,
relocR_ARM_THM_B_L(location, result, true);
}
+/// \brief R_ARM_THM_JUMP11 - S + A - P
+static void relocR_ARM_THM_JUMP11(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");
+
+ //we cut off first bit because it is always 1 according to p. 4.5.3
+ result = (result & 0x0FFE) >> 1;
+
+ applyThumb16Reloc(location, result, 0x7FF);
+}
+
/// \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) {
@@ -274,7 +343,7 @@ static void relocR_ARM_THM_MOV(uint8_t *location, uint32_t result) {
const uint16_t bitI = (result >> 11) & 0x1;
const uint16_t resHi = (bitI << 10) | imm4;
- applyThmReloc(location, resHi, resLo, 0x40F, 0x70FF);
+ applyThmReloc(location, resHi, resLo, 0x40F, 0x70FF);
}
/// \brief R_ARM_THM_MOVW_ABS_NC - (S + A) | T
@@ -340,6 +409,10 @@ std::error_code ARMTargetRelocationHandler::applyRelocation(
relocR_ARM_ABS32(location, relocVAddress, targetVAddress, addend,
addressesThumb);
break;
+ case R_ARM_REL32:
+ relocR_ARM_REL32(location, relocVAddress, targetVAddress, addend,
+ addressesThumb);
+ break;
case R_ARM_THM_CALL:
// TODO: consider adding bool variable to disable J1 & J2 for archs
// before ARMv6
@@ -358,6 +431,9 @@ std::error_code ARMTargetRelocationHandler::applyRelocation(
relocR_ARM_THM_JUMP24(location, relocVAddress, targetVAddress, addend,
addressesThumb);
break;
+ case R_ARM_THM_JUMP11:
+ relocR_ARM_THM_JUMP11(location, relocVAddress, targetVAddress, addend);
+ break;
case R_ARM_MOVW_ABS_NC:
relocR_ARM_MOVW_ABS_NC(location, relocVAddress, targetVAddress, addend,
addressesThumb);
@@ -372,6 +448,10 @@ std::error_code ARMTargetRelocationHandler::applyRelocation(
case R_ARM_THM_MOVT_ABS:
relocR_ARM_THM_MOVT_ABS(location, relocVAddress, targetVAddress, addend);
break;
+ case R_ARM_PREL31:
+ relocR_ARM_PREL31(location, relocVAddress, targetVAddress, addend,
+ addressesThumb);
+ break;
default:
return make_unhandled_reloc_error();
}
OpenPOWER on IntegriCloud