diff options
-rw-r--r-- | lld/ELF/Target.cpp | 11 | ||||
-rw-r--r-- | lld/test/ELF/mips-call16.s | 40 |
2 files changed, 49 insertions, 2 deletions
diff --git a/lld/ELF/Target.cpp b/lld/ELF/Target.cpp index 6c0a2224cd5..5e3de699af6 100644 --- a/lld/ELF/Target.cpp +++ b/lld/ELF/Target.cpp @@ -116,6 +116,7 @@ public: template <class ELFT> class MipsTargetInfo final : public TargetInfo { public: MipsTargetInfo(); + unsigned getGotRefReloc(unsigned Type) const override; void writeGotHeaderEntries(uint8_t *Buf) const override; void writeGotPltEntry(uint8_t *Buf, uint64_t Plt) const override; void writePltZeroEntry(uint8_t *Buf, uint64_t GotEntryAddr, @@ -876,6 +877,11 @@ template <class ELFT> MipsTargetInfo<ELFT>::MipsTargetInfo() { } template <class ELFT> +unsigned MipsTargetInfo<ELFT>::getGotRefReloc(unsigned Type) const { + return Type; +} + +template <class ELFT> void MipsTargetInfo<ELFT>::writeGotHeaderEntries(uint8_t *Buf) const { typedef typename llvm::object::ELFFile<ELFT>::Elf_Off Elf_Off; auto *P = reinterpret_cast<Elf_Off *>(Buf); @@ -895,7 +901,7 @@ void MipsTargetInfo<ELFT>::writePltEntry(uint8_t *Buf, uint64_t GotEntryAddr, template <class ELFT> bool MipsTargetInfo<ELFT>::relocNeedsGot(uint32_t Type, const SymbolBody &S) const { - return Type == R_MIPS_GOT16; + return Type == R_MIPS_GOT16 || Type == R_MIPS_CALL16; } template <class ELFT> @@ -913,9 +919,10 @@ void MipsTargetInfo<ELFT>::relocateOne(uint8_t *Loc, uint8_t *BufEnd, case R_MIPS_32: add32<E>(Loc, SA); break; + case R_MIPS_CALL16: case R_MIPS_GOT16: { int64_t V = SA - getMipsGpAddr<ELFT>(); - if (!isInt<16>(V)) + if (Type == R_MIPS_GOT16 && !isInt<16>(V)) error("Relocation R_MIPS_GOT16 out of range"); write32<E>(Loc, (read32<E>(Loc) & 0xffff0000) | (V & 0xffff)); break; diff --git a/lld/test/ELF/mips-call16.s b/lld/test/ELF/mips-call16.s new file mode 100644 index 00000000000..4a5d0bf3f87 --- /dev/null +++ b/lld/test/ELF/mips-call16.s @@ -0,0 +1,40 @@ +# Check R_MIPS_CALL16 relocation calculation. + +# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %s -o %t.o +# RUN: ld.lld %t.o -shared -o %t.exe +# RUN: llvm-objdump -d %t.exe | FileCheck %s +# RUN: llvm-readobj -mips-plt-got -symbols %t.exe \ +# RUN: | FileCheck -check-prefix=GOT %s + +# REQUIRES: mips + + .text + .globl __start +__start: + lw $t0,%call16(g1)($gp) + + .globl g1 + .type g1,@function +g1: + nop + +# CHECK: Disassembly of section .text: +# CHECK-NEXT: __start: +# CHECK-NEXT: 10000: 8f 88 80 18 lw $8, -32744 + +# GOT: Name: g1 +# GOT-NEXT: Value: 0x[[ADDR:[0-9A-F]+]] + +# GOT: Local entries [ +# GOT-NEXT: ] +# GOT-NEXT: Global entries [ +# GOT-NEXT: Entry { +# GOT-NEXT: Address: +# GOT-NEXT: Access: -32744 +# GOT-NEXT: Initial: 0x[[ADDR]] +# GOT-NEXT: Value: 0x[[ADDR]] +# GOT-NEXT: Type: Function +# GOT-NEXT: Section: .text +# GOT-NEXT: Name: g1 +# GOT-NEXT: } +# GOT-NEXT: ] |