diff options
| author | Simon Atanasyan <simon@atanasyan.com> | 2014-02-26 19:17:14 +0000 |
|---|---|---|
| committer | Simon Atanasyan <simon@atanasyan.com> | 2014-02-26 19:17:14 +0000 |
| commit | 2043ee167ced6fc6a85d2266da141bc9ffa8a6ba (patch) | |
| tree | 0e96130c6a3f09e195d193fa6b6a8430f1b04eec | |
| parent | a444eae5ce05d7c27803f8d537be100a57dc31f6 (diff) | |
| download | bcm5719-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.cpp | 23 | ||||
| -rw-r--r-- | lld/test/elf/Mips/r26.test | 2 |
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: |

