[lld] r331772 - [ELF][MIPS] Fix calculation of GP relative relocations in case of relocatable output

Simon Atanasyan via llvm-commits llvm-commits at lists.llvm.org
Tue May 8 08:34:06 PDT 2018


Author: atanasyan
Date: Tue May  8 08:34:06 2018
New Revision: 331772

URL: http://llvm.org/viewvc/llvm-project?rev=331772&view=rev
Log:
[ELF][MIPS] Fix calculation of GP relative relocations in case of relocatable output

Some MIPS relocations depend on "gp" value. By default, this value has
0x7ff0 offset from a .got section. But relocatable files produced by a
compiler or a linker might redefine this default value and we have to
use it for a calculation of the relocation result. When we generate EXE
or DSO it's trivial. Generating a relocatable output is more difficult
case because the linker does calculate relocations in this case and
cannot store individual "gp" values used by each input object file.
As a workaround we add the "gp" value to the relocation addend.

This fixes https://llvm.org/pr31149

Differential revision: https://reviews.llvm.org/D45972

Added:
    lld/trunk/test/ELF/Inputs/mips-micro-gp0-non-zero.o
    lld/trunk/test/ELF/Inputs/mips-n64-gp0-non-zero.o
    lld/trunk/test/ELF/mips-non-zero-gp0.s
Modified:
    lld/trunk/ELF/InputSection.cpp
    lld/trunk/ELF/SyntheticSections.cpp
    lld/trunk/test/ELF/mips-gprel32-relocs-gp0.s

Modified: lld/trunk/ELF/InputSection.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputSection.cpp?rev=331772&r1=331771&r2=331772&view=diff
==============================================================================
--- lld/trunk/ELF/InputSection.cpp (original)
+++ lld/trunk/ELF/InputSection.cpp Tue May  8 08:34:06 2018
@@ -376,17 +376,32 @@ void InputSection::copyRelocations(uint8
         continue;
       }
 
-      if (RelTy::IsRela) {
-        P->r_addend =
-            Sym.getVA(getAddend<ELFT>(Rel)) - Section->getOutputSection()->Addr;
-      } else if (Config->Relocatable) {
-        const uint8_t *BufLoc = Sec->Data.begin() + Rel.r_offset;
-        Sec->Relocations.push_back({R_ABS, Type, Rel.r_offset,
-                                    Target->getImplicitAddend(BufLoc, Type),
-                                    &Sym});
+      int64_t Addend = getAddend<ELFT>(Rel);
+      const uint8_t *BufLoc = Sec->Data.begin() + Rel.r_offset;
+      if (!RelTy::IsRela)
+        Addend = Target->getImplicitAddend(BufLoc, Type);
+
+      if (Config->EMachine == EM_MIPS && Config->Relocatable &&
+          Target->getRelExpr(Type, Sym, BufLoc) == R_MIPS_GOTREL) {
+        // Some MIPS relocations depend on "gp" value. By default,
+        // this value has 0x7ff0 offset from a .got section. But
+        // relocatable files produced by a complier or a linker
+        // might redefine this default value and we must use it
+        // for a calculation of the relocation result. When we
+        // generate EXE or DSO it's trivial. Generating a relocatable
+        // output is more difficult case because the linker does
+        // not calculate relocations in this mode and loses
+        // individual "gp" values used by each input object file.
+        // As a workaround we add the "gp" value to the relocation
+        // addend and save it back to the file.
+        Addend += Sec->getFile<ELFT>()->MipsGp0;
       }
-    }
 
+      if (RelTy::IsRela)
+        P->r_addend = Sym.getVA(Addend) - Section->getOutputSection()->Addr;
+      else if (Config->Relocatable)
+        Sec->Relocations.push_back({R_ABS, Type, Rel.r_offset, Addend, &Sym});
+    }
   }
 }
 

Modified: lld/trunk/ELF/SyntheticSections.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SyntheticSections.cpp?rev=331772&r1=331771&r2=331772&view=diff
==============================================================================
--- lld/trunk/ELF/SyntheticSections.cpp (original)
+++ lld/trunk/ELF/SyntheticSections.cpp Tue May  8 08:34:06 2018
@@ -184,8 +184,6 @@ MipsOptionsSection<ELFT> *MipsOptionsSec
 
       auto *Opt = reinterpret_cast<const Elf_Mips_Options *>(D.data());
       if (Opt->kind == ODK_REGINFO) {
-        if (Config->Relocatable && Opt->getRegInfo().ri_gp_value)
-          error(Filename + ": unsupported non-zero ri_gp_value");
         Reginfo.ri_gprmask |= Opt->getRegInfo().ri_gprmask;
         Sec->getFile<ELFT>()->MipsGp0 = Opt->getRegInfo().ri_gp_value;
         break;
@@ -236,10 +234,8 @@ MipsReginfoSection<ELFT> *MipsReginfoSec
       error(toString(Sec->File) + ": invalid size of .reginfo section");
       return nullptr;
     }
-    auto *R = reinterpret_cast<const Elf_Mips_RegInfo *>(Sec->Data.data());
-    if (Config->Relocatable && R->ri_gp_value)
-      error(toString(Sec->File) + ": unsupported non-zero ri_gp_value");
 
+    auto *R = reinterpret_cast<const Elf_Mips_RegInfo *>(Sec->Data.data());
     Reginfo.ri_gprmask |= R->ri_gprmask;
     Sec->getFile<ELFT>()->MipsGp0 = R->ri_gp_value;
   };

Added: lld/trunk/test/ELF/Inputs/mips-micro-gp0-non-zero.o
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/Inputs/mips-micro-gp0-non-zero.o?rev=331772&view=auto
==============================================================================
Binary files lld/trunk/test/ELF/Inputs/mips-micro-gp0-non-zero.o (added) and lld/trunk/test/ELF/Inputs/mips-micro-gp0-non-zero.o Tue May  8 08:34:06 2018 differ

Added: lld/trunk/test/ELF/Inputs/mips-n64-gp0-non-zero.o
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/Inputs/mips-n64-gp0-non-zero.o?rev=331772&view=auto
==============================================================================
Binary files lld/trunk/test/ELF/Inputs/mips-n64-gp0-non-zero.o (added) and lld/trunk/test/ELF/Inputs/mips-n64-gp0-non-zero.o Tue May  8 08:34:06 2018 differ

Modified: lld/trunk/test/ELF/mips-gprel32-relocs-gp0.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/mips-gprel32-relocs-gp0.s?rev=331772&r1=331771&r2=331772&view=diff
==============================================================================
--- lld/trunk/test/ELF/mips-gprel32-relocs-gp0.s (original)
+++ lld/trunk/test/ELF/mips-gprel32-relocs-gp0.s Tue May  8 08:34:06 2018
@@ -1,8 +1,4 @@
 # Check that relocatable object produced by LLD has zero gp0 value.
-# Also check an error message if input object file has non-zero gp0 value
-# and the linker generates a relocatable object.
-# mips-gp0-non-zero.o is a relocatable object produced from the asm code
-# below and linked by GNU bfd linker.
 
 # RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %s -o %t.o
 # RUN: ld.lld -r -o %t-rel.o %t.o
@@ -12,9 +8,6 @@
 # RUN: llvm-readobj -mips-reginfo %t.so | FileCheck --check-prefix=DSO %s
 # RUN: llvm-objdump -s -t %t.so | FileCheck --check-prefix=DUMP %s
 
-# RUN: not ld.lld -r -o %t-rel.o %S/Inputs/mips-gp0-non-zero.o 2>&1 \
-# RUN:   | FileCheck --check-prefix=ERR %s
-
 # REQUIRES: mips
 
 # REL: GP: 0x0
@@ -31,8 +24,6 @@
 # DUMP: 00010004         .text          00000000 foo
 # DUMP: 00027ff0         .got           00000000 .hidden _gp
 
-# ERR: error: {{.*}}mips-gp0-non-zero.o: unsupported non-zero ri_gp_value
-
   .text
   .global  __start
 __start:

Added: lld/trunk/test/ELF/mips-non-zero-gp0.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/mips-non-zero-gp0.s?rev=331772&view=auto
==============================================================================
--- lld/trunk/test/ELF/mips-non-zero-gp0.s (added)
+++ lld/trunk/test/ELF/mips-non-zero-gp0.s Tue May  8 08:34:06 2018
@@ -0,0 +1,66 @@
+# REQUIRES: mips
+
+# Check addend adjustment in case of generating a relocatable object
+# if some input files have non-zero GP0 value.
+
+# We have to use GNU as and ld.bfd 2.28 to generate relocatable object
+# files with non-zero GP0 value using the following command lines:
+#
+# as -mips32 -o test.o \
+#   && ld.bfd -m elf32btsmip -r test.o -o mips-gp0-non-zero.o
+# as -mips64 -mmicromips -o test.o \
+#   && ld.bfd -m elf64btsmip -r test.o -o mips-micro-gp0-non-zero.o
+# as -mips64 -o test.o \
+#   && ld.bfd -m elf64btsmip -r test.o -o mips-n64-gp0-non-zero.o
+
+# Source code for mips-gp0-non-zero.o:
+#   .text
+#   .global  __start
+# __start:
+#   lw      $t0,%call16(__start)($gp)
+# foo:
+#   nop
+# bar:
+#   nop
+#
+#   .section .rodata, "a"
+# v:
+#   .gpword foo
+#   .gpword bar
+
+# Source code for mips-n64-gp0-non-zero.o and mips-micro-gp0-non-zero.o:
+#   .text
+#   .global  __start
+# __start:
+# foo:
+#   lui     $gp,%hi(%neg(%gp_rel(foo)))
+
+# RUN: ld.lld -r -o %t-32.r %S/Inputs/mips-gp0-non-zero.o
+# RUN: llvm-readobj -mips-reginfo %t-32.r | FileCheck --check-prefix=GPVAL %s
+# RUN: llvm-objdump -s %t-32.r | FileCheck --check-prefix=ADDEND32 %s
+
+# RUN: ld.lld -r -o %t-64.r %S/Inputs/mips-n64-gp0-non-zero.o
+# RUN: llvm-readobj -mips-options %t-64.r | FileCheck --check-prefix=GPVAL %s
+# RUN: llvm-readobj -r %S/Inputs/mips-n64-gp0-non-zero.o %t-64.r \
+# RUN:   | FileCheck --check-prefix=ADDEND64 %s
+
+# RUN: ld.lld -r -o %t-micro.r %S/Inputs/mips-micro-gp0-non-zero.o
+# RUN: llvm-readobj -mips-options %t-micro.r | FileCheck --check-prefix=GPVAL %s
+# RUN: llvm-readobj -r %S/Inputs/mips-micro-gp0-non-zero.o %t-micro.r \
+# RUN:   | FileCheck --check-prefix=ADDENDMM %s
+
+# GPVAL: GP: 0x0
+
+# ADDEND32:      Contents of section .rodata:
+# ADDEND32-NEXT:  0000 00007ff4 00007ff8
+#                      ^ 4+GP0  ^ 8+GP0
+
+# ADDEND64: File: {{.*}}/Inputs/mips-n64-gp0-non-zero.o
+# ADDEND64: .text 0xFFFFFFFFFFFF8011
+# ADDEND64: File: {{.*}}/mips-non-zero-gp0.s.tmp-64.r
+# ADDEND64: .text 0x0
+
+# ADDENDMM: File: {{.*}}/Inputs/mips-micro-gp0-non-zero.o
+# ADDENDMM: .text 0xFFFFFFFFFFFF8012
+# ADDENDMM: File: {{.*}}/mips-non-zero-gp0.s.tmp-micro.r
+# ADDENDMM: .text 0x1




More information about the llvm-commits mailing list