summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimon Atanasyan <simon@atanasyan.com>2014-02-26 19:17:14 +0000
committerSimon Atanasyan <simon@atanasyan.com>2014-02-26 19:17:14 +0000
commit2043ee167ced6fc6a85d2266da141bc9ffa8a6ba (patch)
tree0e96130c6a3f09e195d193fa6b6a8430f1b04eec
parenta444eae5ce05d7c27803f8d537be100a57dc31f6 (diff)
downloadbcm5719-llvm-2043ee167ced6fc6a85d2266da141bc9ffa8a6ba.tar.gz
bcm5719-llvm-2043ee167ced6fc6a85d2266da141bc9ffa8a6ba.zip
[Mips] Use a correct number of bits when apply result of calculated relocation.
llvm-svn: 202288
-rw-r--r--lld/lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.cpp23
-rw-r--r--lld/test/elf/Mips/r26.test2
2 files changed, 13 insertions, 12 deletions
diff --git a/lld/lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.cpp b/lld/lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.cpp
index 343a956bc07..7ea9feac0a1 100644
--- a/lld/lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.cpp
+++ b/lld/lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.cpp
@@ -19,9 +19,10 @@ using namespace llvm::ELF;
namespace {
-inline void applyReloc(uint8_t *location, uint32_t result) {
- auto target = reinterpret_cast<llvm::support::ulittle32_t *>(location);
- *target = result | uint32_t(*target);
+inline
+void applyReloc(uint8_t *loc, uint32_t result, uint32_t mask) {
+ auto target = reinterpret_cast<llvm::support::ulittle32_t *>(loc);
+ *target = (uint32_t(*target) & ~mask) | (result & mask);
}
/// \brief Calculate AHL value combines addends from 'hi' and 'lo' relocations.
@@ -40,7 +41,7 @@ template <size_t BITS, class T> inline T signExtend(T val) {
/// \brief R_MIPS_32
/// local/external: word32 S + A (truncate)
void reloc32(uint8_t *location, uint64_t P, uint64_t S, int64_t A) {
- applyReloc(location, (S + A) & 0xffffffff);
+ applyReloc(location, S + A, 0xffffffff);
}
/// \brief R_MIPS_26
@@ -50,7 +51,7 @@ void reloc26(uint8_t *location, uint64_t P, uint64_t S, bool isLocal) {
int32_t A = (*(uint32_t*)location & 0x03FFFFFFU) << 2;
uint32_t result = isLocal ? (A | ((P + 4) & 0x3F000000)) : signExtend<28>(A);
result = (result + S) >> 2;
- applyReloc(location, result);
+ applyReloc(location, result, 0x03ffffff);
}
/// \brief R_MIPS_HI16
@@ -65,7 +66,7 @@ void relocHi16(uint8_t *location, uint64_t P, uint64_t S, int64_t AHL,
else
result = (AHL + S) - (int16_t)(AHL + S);
- applyReloc(location, (result >> 16) & 0xffff);
+ applyReloc(location, result >> 16, 0xffff);
}
/// \brief R_MIPS_LO16
@@ -80,7 +81,7 @@ void relocLo16(uint8_t *location, uint64_t P, uint64_t S, int64_t AHL,
else
result = AHL + S;
- applyReloc(location, result & 0xffff);
+ applyReloc(location, result, 0xffff);
}
/// \brief R_MIPS_GOT16
@@ -89,7 +90,7 @@ void relocGOT16(uint8_t *location, uint64_t P, uint64_t S, int64_t AHL,
uint64_t GP) {
// FIXME (simon): for local sym put high 16 bit of AHL to the GOT
int32_t G = (int32_t)(S - GP);
- applyReloc(location, G & 0xffff);
+ applyReloc(location, G, 0xffff);
}
/// \brief R_MIPS_CALL16
@@ -97,17 +98,17 @@ void relocGOT16(uint8_t *location, uint64_t P, uint64_t S, int64_t AHL,
void relocCall16(uint8_t *location, uint64_t P, uint64_t S, int64_t A,
uint64_t GP) {
int32_t G = (int32_t)(S - GP);
- applyReloc(location, G & 0xffff);
+ applyReloc(location, G, 0xffff);
}
/// \brief LLD_R_MIPS_HI16
void relocLldHi16(uint8_t *location, uint64_t S) {
- applyReloc(location, ((S + 0x8000) >> 16) & 0xffff);
+ applyReloc(location, (S + 0x8000) >> 16, 0xffff);
}
/// \brief LLD_R_MIPS_LO16
void relocLldLo16(uint8_t *location, uint64_t S) {
- applyReloc(location, S & 0xffff);
+ applyReloc(location, S, 0xffff);
}
} // end anon namespace
diff --git a/lld/test/elf/Mips/r26.test b/lld/test/elf/Mips/r26.test
index 09d72e3519b..c36fc34beff 100644
--- a/lld/test/elf/Mips/r26.test
+++ b/lld/test/elf/Mips/r26.test
@@ -43,7 +43,7 @@
# EXE-NEXT: 400194: 00 00 00 00 nop
#
# Jump to 'loc' label address
-# EXE-NEXT: 400198: 6c 00 10 0c jal 4194736
+# EXE-NEXT: 400198: 68 00 10 0c jal 4194720
# EXE-NEXT: 40019c: 00 00 00 00 nop
#
# EXE: loc:
OpenPOWER on IntegriCloud