diff options
-rw-r--r-- | lld/ELF/Target.cpp | 25 | ||||
-rw-r--r-- | lld/test/ELF/mips-pc-relocs.s | 9 |
2 files changed, 23 insertions, 11 deletions
diff --git a/lld/ELF/Target.cpp b/lld/ELF/Target.cpp index 7782c0fefcc..2b1e9f7308d 100644 --- a/lld/ELF/Target.cpp +++ b/lld/ELF/Target.cpp @@ -1437,16 +1437,17 @@ bool MipsTargetInfo<ELFT>::needsPlt(uint32_t Type, const SymbolBody &S) const { static uint16_t mipsHigh(uint64_t V) { return (V + 0x8000) >> 16; } -template <endianness E, uint8_t BSIZE> +template <endianness E, uint8_t BSIZE, uint8_t SHIFT> static void applyMipsPcReloc(uint8_t *Loc, uint32_t Type, uint64_t P, uint64_t SA) { - uint32_t Mask = ~(0xffffffff << BSIZE); + uint32_t Mask = 0xffffffff >> (32 - BSIZE); uint32_t Instr = read32<E>(Loc); - int64_t A = SignExtend64<BSIZE + 2>((Instr & Mask) << 2); - checkAlignment<4>(SA + A, Type); + int64_t A = SignExtend64<BSIZE + SHIFT>((Instr & Mask) << SHIFT); + if (SHIFT > 0) + checkAlignment<(1 << SHIFT)>(SA + A, Type); int64_t V = SA + A - P; - checkInt<BSIZE + 2>(V, Type); - write32<E>(Loc, (Instr & ~Mask) | ((V >> 2) & Mask)); + checkInt<BSIZE + SHIFT>(V, Type); + write32<E>(Loc, (Instr & ~Mask) | ((V >> SHIFT) & Mask)); } template <class ELFT> @@ -1498,16 +1499,19 @@ void MipsTargetInfo<ELFT>::relocateOne(uint8_t *Loc, uint8_t *BufEnd, break; } case R_MIPS_PC16: - applyMipsPcReloc<E, 16>(Loc, Type, P, SA); + applyMipsPcReloc<E, 16, 2>(Loc, Type, P, SA); break; case R_MIPS_PC19_S2: - applyMipsPcReloc<E, 19>(Loc, Type, P, SA); + applyMipsPcReloc<E, 19, 2>(Loc, Type, P, SA); break; case R_MIPS_PC21_S2: - applyMipsPcReloc<E, 21>(Loc, Type, P, SA); + applyMipsPcReloc<E, 21, 2>(Loc, Type, P, SA); break; case R_MIPS_PC26_S2: - applyMipsPcReloc<E, 26>(Loc, Type, P, SA); + applyMipsPcReloc<E, 26, 2>(Loc, Type, P, SA); + break; + case R_MIPS_PC32: + applyMipsPcReloc<E, 32, 0>(Loc, Type, P, SA); break; case R_MIPS_PCHI16: { uint32_t Instr = read32<E>(Loc); @@ -1546,6 +1550,7 @@ bool MipsTargetInfo<ELFT>::isRelRelative(uint32_t Type) const { case R_MIPS_PC19_S2: case R_MIPS_PC21_S2: case R_MIPS_PC26_S2: + case R_MIPS_PC32: case R_MIPS_PCHI16: case R_MIPS_PCLO16: return true; diff --git a/lld/test/ELF/mips-pc-relocs.s b/lld/test/ELF/mips-pc-relocs.s index 631dd433925..b659b9c6fcc 100644 --- a/lld/test/ELF/mips-pc-relocs.s +++ b/lld/test/ELF/mips-pc-relocs.s @@ -5,7 +5,7 @@ # RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux \ # RUN: -mcpu=mips32r6 %S/Inputs/mips-dynamic.s -o %t2.o # RUN: ld.lld %t1.o %t2.o -o %t.exe -# RUN: llvm-objdump -mcpu=mips32r6 -d -t %t.exe | FileCheck %s +# RUN: llvm-objdump -mcpu=mips32r6 -d -t -s %t.exe | FileCheck %s # REQUIRES: mips @@ -19,6 +19,9 @@ __start: aluipc $2, %pcrel_hi(_foo) # R_MIPS_PCHI16 addiu $2, $2, %pcrel_lo(_foo) # R_MIPS_PCLO16 + .data + .word _foo+8-. # R_MIPS_PC32 + # CHECK: Disassembly of section .text: # CHECK-NEXT: __start: # CHECK-NEXT: 20000: ec c8 00 08 lwpc $6, 32 @@ -34,5 +37,9 @@ __start: # CHECK-NEXT: 20014: 24 42 00 0c addiu $2, $2, 12 # ^-- %lo(0x20020-0x20014) +# CHECK: Contents of section .data: +# CHECK-NEXT: 30000 ffff0028 00000000 00000000 00000000 +# ^-- 0x20020 + 8 - 0x30000 + # CHECK: 00020000 .text 00000000 __start # CHECK: 00020020 .text 00000000 _foo |