[PATCH] D19115: [ELF][MIPS] Make R_MIPS_LO16 a relative relocation if it references _gp_disp symbol

Simon Atanasyan via llvm-commits llvm-commits at lists.llvm.org
Thu Apr 14 08:03:09 PDT 2016


atanasyan created this revision.
atanasyan added a reviewer: rafael.
atanasyan added a subscriber: llvm-commits.
atanasyan set the repository for this revision to rL LLVM.
atanasyan added a project: lld.
Herald added a subscriber: sdardis.

The _gp_disp symbol designates offset between start of function and 'gp' pointer into GOT. The following code is a typical MIPS function preamble used to setup $gp register:
```
lui    $gp, %hi(_gp_disp)
addi   $gp, $gp, %lo(_gp_disp)
```
To calculate R_MIPS_HI16 / R_MIPS_LO16 relocations results we use the following formulas:
```
%hi(_gp - P + A)
%lo(_gp - P + A + 4),
```
where _gp is a value of _gp symbol, A is addend, and P current address.

The R_MIPS_LO16 relocation references _gp_disp symbol is always the second instruction. That is why we need four byte adjustments. The patch assigns R_PC type for R_MIPS_LO16 relocation and adjusts its addend by 4. That fix R_MIPS_LO16 calculation.

For details see p. 4-19 at ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf

Repository:
  rL LLVM

http://reviews.llvm.org/D19115

Files:
  ELF/Target.cpp
  ELF/Writer.cpp
  test/ELF/mips-hilo-gp-disp.s

Index: test/ELF/mips-hilo-gp-disp.s
===================================================================
--- test/ELF/mips-hilo-gp-disp.s
+++ test/ELF/mips-hilo-gp-disp.s
@@ -16,27 +16,40 @@
   lui    $t0,%hi(_gp_disp)
   addi   $t0,$t0,%lo(_gp_disp)
   lw     $v0,%call16(_foo)($gp)
+bar:
+  lui    $t0,%hi(_gp_disp)
+  addi   $t0,$t0,%lo(_gp_disp)
 
 # 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:      bar:
+# EXE-NEXT:  2000c:   3c 08 00 01   lui    $8, 1
+#                                              ^-- %hi(0x37ff0-0x2000c)
+# EXE-NEXT:  20010:   21 08 7f e4   addi   $8, $8, 32740
+#                                                  ^-- %lo(0x37ff0-0x20010+4)
 
 # EXE: SYMBOL TABLE:
+# EXE: 0002000c     .text   00000000 bar
 # EXE: 00037ff0     .got    00000000 .hidden _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:       bar:
+# SO-NEXT:   1000c:   3c 08 00 01   lui    $8, 1
+#                                              ^-- %hi(0x27ff0-0x1000c)
+# SO-NEXT:   10010:   21 08 7f e4   addi   $8, $8, 32740
+#                                                  ^-- %lo(0x27ff0-0x10010+4)
 
 # SO: SYMBOL TABLE:
+# SO: 0001000c     .text   00000000 bar
 # SO: 00027ff0     .got    00000000 .hidden _gp
 # SO: 00010000     .text   00000000 __start
-# SO: 00010010     .text   00000000 _foo
Index: ELF/Writer.cpp
===================================================================
--- ELF/Writer.cpp
+++ ELF/Writer.cpp
@@ -468,8 +468,16 @@
     const uint8_t *BufLoc = Buf + RI.r_offset;
     if (!RelTy::IsRela)
       Addend += Target->getImplicitAddend(BufLoc, Type);
-    if (Config->EMachine == EM_MIPS)
+    if (Config->EMachine == EM_MIPS) {
       Addend += findMipsPairedAddend<ELFT>(Buf, BufLoc, Body, &RI, E);
+      if (Type == R_MIPS_LO16 && Expr == R_PC)
+        // R_MIPS_LO16 expression has R_PC type iif the target is _gp_disp
+        // symbol. In that case we should use the following formula for
+        // calculation "AHL + GP – P + 4". Let's add 4 right here.
+        // For details see p. 4-19 at
+        // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf
+        Addend += 4;
+    }
 
     bool Preemptible = Body.isPreemptible();
     if (unsigned Processed =
Index: ELF/Target.cpp
===================================================================
--- ELF/Target.cpp
+++ ELF/Target.cpp
@@ -1589,6 +1589,7 @@
   default:
     return R_ABS;
   case R_MIPS_HI16:
+  case R_MIPS_LO16:
     // MIPS _gp_disp designates offset between start of function and 'gp'
     // pointer into GOT. __gnu_local_gp is equal to the current value of
     // the 'gp'. Therefore any relocations against them do not require


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D19115.53722.patch
Type: text/x-patch
Size: 3317 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20160414/8b35dbed/attachment.bin>


More information about the llvm-commits mailing list