}
/// \brief gp register value stored in the .reginfo section.
- int64_t getGP0() const { return *_gp0; }
+ int64_t getGP0() const { return _gp0 ? *_gp0 : 0; }
/// \brief .tdata section address plus fixed offset.
uint64_t getTPOffset() const { return *_tpOff; }
return readAddend(ap, 0x3ffffff, false) << 2;
case llvm::ELF::R_MIPS_HI16:
case llvm::ELF::R_MIPS_LO16:
+ case llvm::ELF::R_MIPS_GPREL16:
case llvm::ELF::R_MIPS_GOT16:
case llvm::ELF::R_MIPS_TLS_DTPREL_HI16:
case llvm::ELF::R_MIPS_TLS_DTPREL_LO16:
applyReloc(ins, G, 0xffff);
}
+/// \brief R_MIPS_GPREL16
+/// local: sign-extend(A) + S + GP0 - GP
+/// external: sign-extend(A) + S - GP
+static void relocGPRel16(uint32_t &ins, uint64_t S, int64_t A, uint64_t GP) {
+ // We added GP0 to addendum for a local symbol during a Relocation pass.
+ int32_t result = signExtend<16>(A) + S - GP;
+ applyReloc(ins, result, 0xffff);
+}
+
/// \brief R_MIPS_GPREL32
/// local: rel32 A + S + GP0 - GP (truncate)
static void relocGPRel32(uint32_t &ins, uint64_t P, uint64_t S, int64_t A,
case R_MICROMIPS_TLS_TPREL_LO16:
relocLo16(ins, 0, targetVAddress, ref.addend(), false, true);
break;
+ case R_MIPS_GPREL16:
+ relocGPRel16(ins, targetVAddress, ref.addend(), gpAddr);
+ break;
case R_MIPS_GPREL32:
relocGPRel32(ins, relocVAddress, targetVAddress, ref.addend(), gpAddr);
break;
void handlePlain(const MipsELFDefinedAtom<ELFT> &atom, Reference &ref);
void handle26(const MipsELFDefinedAtom<ELFT> &atom, Reference &ref);
void handleGOT(Reference &ref);
- void handleGPRel(const MipsELFDefinedAtom<ELFT> &atom, Reference &ref);
const GOTAtom *getLocalGOTEntry(const Reference &ref);
const GOTAtom *getGlobalGOTEntry(const Atom *a);
case R_MICROMIPS_CALL16:
handleGOT(ref);
break;
+ case R_MIPS_GPREL16:
+ if (isLocal(ref.target()))
+ ref.setAddend(ref.addend() + atom.file().getGP0());
+ break;
case R_MIPS_GPREL32:
- handleGPRel(atom, ref);
+ ref.setAddend(ref.addend() + atom.file().getGP0());
break;
case R_MIPS_TLS_DTPREL_HI16:
case R_MIPS_TLS_DTPREL_LO16:
case R_MIPS_NONE:
case R_MIPS_JALR:
case R_MICROMIPS_JALR:
+ case R_MIPS_GPREL16:
case R_MIPS_GPREL32:
return false;
default:
}
template <typename ELFT>
-void RelocationPass<ELFT>::handleGPRel(const MipsELFDefinedAtom<ELFT> &atom,
- Reference &ref) {
- assert(ref.kindValue() == R_MIPS_GPREL32);
- ref.setAddend(ref.addend() + atom.file().getGP0());
-}
-
-template <typename ELFT>
bool RelocationPass<ELFT>::isLocalCall(const Atom *a) const {
Atom::Scope scope;
if (auto *da = dyn_cast<DefinedAtom>(a))
--- /dev/null
+# Check R_MIPS_GPREL16 relocation handling.
+#
+# RUN: yaml2obj -format=elf %s > %t-obj
+# RUN: lld -flavor gnu -target mipsel -e G1 -shared -o %t.so %t-obj
+# RUN: llvm-readobj -symbols %t.so | FileCheck -check-prefix=SYM %s
+# RUN: llvm-objdump -s %t.so | FileCheck -check-prefix=SEC %s
+
+# SYM: Name: L1 (1)
+# SYM-NEXT: Value: 0xCC
+# SYM-NEXT: Size: 4
+# SYM-NEXT: Binding: Local (0x0)
+# SYM-NEXT: Type: Function (0x2)
+# SYM-NEXT: Other: 0
+# SYM-NEXT: Section: .text (0x4)
+
+# SYM: Name: G1 (4)
+# SYM-NEXT: Value: 0xD0
+# SYM-NEXT: Size: 4
+# SYM-NEXT: Binding: Global (0x1)
+# SYM-NEXT: Type: Function (0x2)
+# SYM-NEXT: Other: 0
+# SYM-NEXT: Section: .text (0x4)
+
+# SYM: Name: _gp (34)
+# SYM-NEXT: Value: 0x8FF0
+# SYM-NEXT: Size: 0
+# SYM-NEXT: Binding: Global (0x1)
+# SYM-NEXT: Type: Object (0x1)
+# SYM-NEXT: Other: 0
+# SYM-NEXT: Section: Absolute (0xFFF1)
+
+# 0x160db == 0xffff (addend) + 0x00cc (L1) + 0x01f000 (GP0) - 0x8ff0 (_gp)
+# SEC: Contents of section .rodata:
+# SEC-NEXT: 00d4 db600008 00000000 00000000 00000000 .`..............
+
+!ELF
+FileHeader:
+ Class: ELFCLASS32
+ Data: ELFDATA2LSB
+ Type: ET_REL
+ Machine: EM_MIPS
+ Flags: [ EF_MIPS_NOREORDER, EF_MIPS_PIC, EF_MIPS_CPIC,
+ EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R2 ]
+Sections:
+- Type: SHT_PROGBITS
+ Name: .text
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
+ AddressAlign: 0x04
+ Size: 0x08
+
+- Type: SHT_REL
+ Name: .rel.text
+ Type: SHT_REL
+ Link: .symtab
+ Info: .text
+ AddressAlign: 0x04
+ Relocations:
+ - Offset: 0
+ Symbol: .rodata
+ Type: R_MIPS_GOT16
+ - Offset: 4
+ Symbol: .rodata
+ Type: R_MIPS_LO16
+
+- Type: SHT_PROGBITS
+ Name: .rodata
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC ]
+ AddressAlign: 0x04
+ Content: ffff0008000000000000000000000000
+
+- Type: SHT_REL
+ Name: .rel.rodata
+ Type: SHT_REL
+ Link: .symtab
+ Info: .rodata
+ AddressAlign: 0x04
+ Relocations:
+ - Offset: 0
+ Symbol: L1
+ Type: R_MIPS_GPREL16
+
+- Type: SHT_MIPS_REGINFO
+ Name: .reginfo
+ Type: SHT_MIPS_REGINFO
+ Flags: [ SHF_ALLOC ]
+ AddressAlign: 0x01
+ Content: 000000000000000000000000000000000000000000f00100
+
+Symbols:
+ Local:
+ - Name: L1
+ Section: .text
+ Value: 0x00
+ Size: 0x04
+ - Name: .rodata
+ Type: STT_SECTION
+ Section: .rodata
+ Global:
+ - Name: G1
+ Section: .text
+ Value: 0x04
+ Size: 0x04