[PATCH] D45972: [ELF][MIPS] Fix calculation of GP relative relocations in case of relocatable output

Simon Atanasyan via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Mon Apr 23 09:54:36 PDT 2018


atanasyan created this revision.
atanasyan added reviewers: ruiu, espindola, grimar.
atanasyan added a project: lld.
Herald added subscribers: MaskRay, arichardson, sdardis, emaste.

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


Repository:
  rLLD LLVM Linker

https://reviews.llvm.org/D45972

Files:
  ELF/InputSection.cpp
  ELF/SyntheticSections.cpp
  test/ELF/mips-gprel32-relocs-gp0.s


Index: test/ELF/mips-gprel32-relocs-gp0.s
===================================================================
--- test/ELF/mips-gprel32-relocs-gp0.s
+++ test/ELF/mips-gprel32-relocs-gp0.s
@@ -12,8 +12,9 @@
 # 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
+# RUN: ld.lld -r -o %t.r %S/Inputs/mips-gp0-non-zero.o
+# RUN: llvm-readobj -mips-reginfo %t.r | FileCheck --check-prefix=REL %s
+# RUN: llvm-objdump -s -t %t.r | FileCheck --check-prefix=ADDEND %s
 
 # REQUIRES: mips
 
@@ -31,7 +32,9 @@
 # DUMP: 00010004         .text          00000000 foo
 # DUMP: 00027ff0         .got           00000000 .hidden _gp
 
-# ERR: error: {{.*}}mips-gp0-non-zero.o: unsupported non-zero ri_gp_value
+# ADDEND:      Contents of section .rodata:
+# ADDEND-NEXT:  0000 00007ff4 00007ff8
+#                    ^ 4+GP0  ^ 8+GP0
 
   .text
   .global  __start
Index: ELF/SyntheticSections.cpp
===================================================================
--- ELF/SyntheticSections.cpp
+++ ELF/SyntheticSections.cpp
@@ -184,8 +184,6 @@
 
       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 @@
       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;
   };
Index: ELF/InputSection.cpp
===================================================================
--- ELF/InputSection.cpp
+++ ELF/InputSection.cpp
@@ -376,14 +376,32 @@
         continue;
       }
 
+      int64_t AddendAdjustment = 0;
+      if (Config->EMachine == EM_MIPS && Config->Relocatable) {
+        // 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.
+        if (Type == R_MIPS_GPREL32 || Type == R_MIPS_GPREL16 ||
+            R_MICROMIPS_GPREL16 || R_MICROMIPS_GPREL7_S2)
+          AddendAdjustment = Sec->getFile<ELFT>()->MipsGp0;
+      }
+
       if (RelTy::IsRela) {
-        P->r_addend =
-            Sym.getVA(getAddend<ELFT>(Rel)) - Section->getOutputSection()->Addr;
+        P->r_addend = Sym.getVA(getAddend<ELFT>(Rel) + AddendAdjustment) -
+                      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});
+        Sec->Relocations.push_back(
+            {R_ABS, Type, Rel.r_offset,
+             Target->getImplicitAddend(BufLoc, Type) + AddendAdjustment, &Sym});
       }
     }
 


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D45972.143585.patch
Type: text/x-patch
Size: 4081 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20180423/e2f56851/attachment.bin>


More information about the llvm-commits mailing list