summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lld/ELF/Writer.cpp12
-rw-r--r--lld/test/ELF/mips-gp-lowest.s44
2 files changed, 54 insertions, 2 deletions
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index c63b8834bd9..d1c1ecd2cc7 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -1490,8 +1490,16 @@ template <class ELFT> void Writer<ELFT>::fixAbsoluteSymbols() {
// Setup MIPS _gp_disp/__gnu_local_gp symbols which should
// be equal to the _gp symbol's value.
if (Config->EMachine == EM_MIPS) {
- if (!ElfSym<ELFT>::MipsGp->Value)
- ElfSym<ELFT>::MipsGp->Value = In<ELFT>::MipsGot->getVA() + 0x7ff0;
+ if (!ElfSym<ELFT>::MipsGp->Value) {
+ // Find GP-relative section with the lowest address
+ // and use this address to calculate default _gp value.
+ uintX_t Gp = -1;
+ for (const OutputSectionBase * OS : OutputSections)
+ if ((OS->Flags & SHF_MIPS_GPREL) && OS->Addr < Gp)
+ Gp = OS->Addr;
+ if (Gp != (uintX_t)-1)
+ ElfSym<ELFT>::MipsGp->Value = Gp + 0x7ff0;
+ }
if (ElfSym<ELFT>::MipsGpDisp)
ElfSym<ELFT>::MipsGpDisp->Value = ElfSym<ELFT>::MipsGp->Value;
if (ElfSym<ELFT>::MipsLocalGp)
diff --git a/lld/test/ELF/mips-gp-lowest.s b/lld/test/ELF/mips-gp-lowest.s
new file mode 100644
index 00000000000..b3d30aa3590
--- /dev/null
+++ b/lld/test/ELF/mips-gp-lowest.s
@@ -0,0 +1,44 @@
+# Check that default _gp value is calculated relative
+# to the GP-relative section with the lowest address.
+
+# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %s -o %t.o
+# RUN: echo "SECTIONS { \
+# RUN: .sdata : { *(.sdata) } \
+# RUN: .got : { *(.got) } }" > %t.rel.script
+# RUN: ld.lld %t.o --script %t.rel.script -shared -o %t.so
+# RUN: llvm-readobj -s -t %t.so | FileCheck %s
+
+# REQUIRES: mips
+
+ .text
+ .global foo
+foo:
+ lui $gp, %call16(foo)
+
+ .sdata
+ .word 0
+
+# CHECK: Section {
+# CHECK: Name: .sdata
+# CHECK-NEXT: Type: SHT_PROGBITS
+# CHECK-NEXT: Flags [
+# CHECK-NEXT: SHF_ALLOC
+# CHECK-NEXT: SHF_MIPS_GPREL
+# CHECK-NEXT: SHF_WRITE
+# CHECK-NEXT: ]
+# CHECK-NEXT: Address: 0xDD
+# CHECK: }
+# CHECK: Section {
+# CHECK: Name: .got
+# CHECK-NEXT: Type: SHT_PROGBITS
+# CHECK-NEXT: Flags [
+# CHECK-NEXT: SHF_ALLOC
+# CHECK-NEXT: SHF_MIPS_GPREL
+# CHECK-NEXT: SHF_WRITE
+# CHECK-NEXT: ]
+# CHECK-NEXT: Address: 0xE4
+# CHECK: }
+
+# CHECK: Name: _gp (5)
+# CHECK-NEXT: Value: 0x80CD
+# ^-- 0xDD + 0x7ff0
OpenPOWER on IntegriCloud