[PATCH] D15480: [ELF][MIPS] Handle R_MIPS_HI16/LO16 relocations against _gp_disp symbol

Simon Atanasyan via llvm-commits llvm-commits at lists.llvm.org
Sat Dec 12 22:54:38 PST 2015


atanasyan created this revision.
atanasyan added reviewers: ruiu, rafael.
atanasyan added a subscriber: llvm-commits.
atanasyan set the repository for this revision to rL LLVM.
atanasyan added a project: lld.

The `_gp_disp` is a magic symbol designates offset between start of function and gp pointer into GOT. Only `R_MIPS_HI16` and `R_MIPS_LO16` relocations are permitted with `_gp_disp`. The patch adds the `_gp_disp` as an ignored symbol and adjusts symbol value before call the `relocateOne` for `R_MIPS_HI16/LO16` relocations.

I put code which adjust symbol value in case of `R_MIPS_HI16/LO16` relocations into the `InputSectionBase<ELFT>::relocate` routine to escape passing `SymboBody` to each `relocateOne` methods while it is necessary for MIPS target only.

It is possible to optimize the current solution a bit. We can save a reference to the `SymbolBody` instance created by the `addIgnoredSym` call and replace "_gp_disp" string comparison by comparison of `SymbolBody` references. But I cannot find a good place to keep the reference to the "_gp_disp" `SymbolBody`.

Repository:
  rL LLVM

http://reviews.llvm.org/D15480

Files:
  ELF/Driver.cpp
  ELF/InputSection.cpp
  test/ELF/mips-hilo-gp-disp.s

Index: test/ELF/mips-hilo-gp-disp.s
===================================================================
--- /dev/null
+++ test/ELF/mips-hilo-gp-disp.s
@@ -0,0 +1,42 @@
+# Check R_MIPS_HI16 / LO16 relocations calculation against _gp_disp.
+
+# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %s -o %t1.o
+# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux \
+# RUN:         %S/Inputs/mips-dynamic.s -o %t2.o
+# RUN: ld.lld %t1.o %t2.o -o %t.exe
+# RUN: llvm-objdump -d -t %t.exe | FileCheck -check-prefix=EXE %s
+# RUN: ld.lld %t1.o %t2.o -shared -o %t.so
+# RUN: llvm-objdump -d -t %t.so | FileCheck -check-prefix=SO %s
+
+# REQUIRES: mips
+
+  .text
+  .globl  __start
+__start:
+  lui    $t0,%hi(_gp_disp)
+  addi   $t0,$t0,%lo(_gp_disp)
+  lw     $v0,%call16(_foo)($gp)
+
+# EXE:      Disassembly of section .text:
+# EXE-NEXT: __start:
+# EXE-NEXT:  20000:   3c 08 00 01   lui    $8, 1
+#                                              ^-- %hi(0x37ff0-0x20000)
+# EXE-NEXT:  20004:   21 08 7f f0   addi   $8, $8, 32752
+#                                                  ^-- %lo(0x37ff0-0x20004+4)
+
+# EXE: SYMBOL TABLE:
+# EXE: 00037ff0     *ABS*   00000000 _gp
+# EXE: 00020000     .text   00000000 __start
+# EXE: 00020010     .text   00000000 _foo
+
+# SO:      Disassembly of section .text:
+# SO-NEXT: __start:
+# SO-NEXT:  10000:   3c 08 00 01   lui    $8, 1
+#                                             ^-- %hi(0x27ff0-0x10000)
+# SO-NEXT:  10004:   21 08 7f f0   addi   $8, $8, 32752
+#                                                 ^-- %lo(0x27ff0-0x10004+4)
+
+# SO: SYMBOL TABLE:
+# SO: 00027ff0     *ABS*   00000000 _gp
+# SO: 00010000     .text   00000000 __start
+# SO: 00010010     .text   00000000 _foo
Index: ELF/InputSection.cpp
===================================================================
--- ELF/InputSection.cpp
+++ ELF/InputSection.cpp
@@ -205,6 +205,11 @@
     } else if (Target->isTlsDynReloc(Type) ||
                Target->isSizeDynReloc(Type, Body)) {
       continue;
+    } else if (Config->EMachine == EM_MIPS) {
+      if (Type == R_MIPS_HI16 && Body.getName() == "_gp_disp")
+        SymVA = getMipsGpAddr<ELFT>() - AddrLoc;
+      else if (Type == R_MIPS_LO16 && Body.getName() == "_gp_disp")
+        SymVA = getMipsGpAddr<ELFT>() - AddrLoc + 4;
     }
     uintX_t A = getAddend<ELFT>(RI);
     uintX_t Size = getSymSize<ELFT>(Body);
Index: ELF/Driver.cpp
===================================================================
--- ELF/Driver.cpp
+++ ELF/Driver.cpp
@@ -263,6 +263,11 @@
     Symtab.addIgnoredSym("_GLOBAL_OFFSET_TABLE_");
   }
 
+  // On MIPS O32 ABI _gp_disp is a magic symbol designates offset between
+  // start of function and gp pointer into GOT.
+  if (Config->EMachine == EM_MIPS)
+    Symtab.addIgnoredSym("_gp_disp");
+
   if (!Config->Entry.empty()) {
     // Set either EntryAddr (if S is a number) or EntrySym (otherwise).
     StringRef S = Config->Entry;


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D15480.42650.patch
Type: text/x-patch
Size: 2945 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20151213/d71acc0d/attachment.bin>


More information about the llvm-commits mailing list