[lld] r271100 - [ELF][MIPS] Always resolve MIPS GP-relative relocations to 'local' definitions

Simon Atanasyan via llvm-commits llvm-commits at lists.llvm.org
Fri May 27 21:49:58 PDT 2016


Author: atanasyan
Date: Fri May 27 23:49:57 2016
New Revision: 271100

URL: http://llvm.org/viewvc/llvm-project?rev=271100&view=rev
Log:
[ELF][MIPS] Always resolve MIPS GP-relative relocations to 'local' definitions

In case of MIPS, GP-relative relocations always resolve to a definition
in a regular input file, ignoring the one-definition rule. Such
relocations are used to setup GP relative offsets in a function's
prologue. So we, for example, should not attempt to create a dynamic
relocation even if the target symbol is preemptible.

Fixes bug 27880.

Differential Revision: http://reviews.llvm.org/D20664

Added:
    lld/trunk/test/ELF/mips-64-gprel-so.s
Modified:
    lld/trunk/ELF/Relocations.cpp

Modified: lld/trunk/ELF/Relocations.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Relocations.cpp?rev=271100&r1=271099&r2=271100&view=diff
==============================================================================
--- lld/trunk/ELF/Relocations.cpp (original)
+++ lld/trunk/ELF/Relocations.cpp Fri May 27 23:49:57 2016
@@ -65,6 +65,22 @@ static bool refersToGotEntry(RelExpr Exp
          Expr == R_TLSGD_PC;
 }
 
+static bool isPreemptible(const SymbolBody &Body, uint32_t Type) {
+  // In case of MIPS GP-relative relocations always resolve to a definition
+  // in a regular input file, ignoring the one-definition rule. So we,
+  // for example, should not attempt to create a dynamic relocation even
+  // if the target symbol is preemptible. There are two two MIPS GP-relative
+  // relocations R_MIPS_GPREL16 and R_MIPS_GPREL32. But only R_MIPS_GPREL16
+  // can be against a preemptible symbol.
+  // To get MIPS relocation type we apply 0xf mask. In case of O32 ABI all
+  // relocation types occupy eight bit. In case of N64 ABI we extract first
+  // relocation from 3-in-1 packet because only the first relocation can
+  // be against a real symbol.
+  if (Config->EMachine == EM_MIPS && (Type & 0xf) == R_MIPS_GPREL16)
+    return false;
+  return Body.isPreemptible();
+}
+
 // Returns the number of relocations processed.
 template <class ELFT>
 static unsigned handleTlsRelocation(uint32_t Type, SymbolBody &Body,
@@ -116,7 +132,7 @@ static unsigned handleTlsRelocation(uint
 
     // Global-Dynamic relocs can be relaxed to Initial-Exec or Local-Exec
     // depending on the symbol being locally defined or not.
-    if (Body.isPreemptible()) {
+    if (isPreemptible(Body, Type)) {
       C.Relocations.push_back(
           {R_RELAX_TLS_GD_TO_IE, Type, Offset, Addend, &Body});
       if (!Body.isInGot()) {
@@ -135,7 +151,7 @@ static unsigned handleTlsRelocation(uint
   // Initial-Exec relocs can be relaxed to Local-Exec if the symbol is locally
   // defined.
   if (Target->isTlsInitialExecRel(Type) && !Config->Shared &&
-      !Body.isPreemptible()) {
+      !isPreemptible(Body, Type)) {
     C.Relocations.push_back(
         {R_RELAX_TLS_IE_TO_LE, Type, Offset, Addend, &Body});
     return 1;
@@ -246,7 +262,7 @@ static bool isStaticLinkTimeConstant(Rel
   if (E == R_GOT || E == R_PLT)
     return Target->usesOnlyLowPageBits(Type) || !Config->Pic;
 
-  if (Body.isPreemptible())
+  if (isPreemptible(Body, Type))
     return false;
 
   if (!Config->Pic)
@@ -348,7 +364,7 @@ static RelExpr adjustExpr(const elf::Obj
                           const uint8_t *Data, typename ELFT::uint Offset) {
   if (Target->needsThunk(Type, File, Body))
     return R_THUNK;
-  bool Preemptible = Body.isPreemptible();
+  bool Preemptible = isPreemptible(Body, Type);
   if (Body.isGnuIFunc()) {
     Expr = toPlt(Expr);
   } else if (!Preemptible) {
@@ -485,7 +501,7 @@ static void scanRelocs(InputSectionBase<
     if (Offset == (uintX_t)-1)
       continue;
 
-    bool Preemptible = Body.isPreemptible();
+    bool Preemptible = isPreemptible(Body, Type);
     Expr = adjustExpr(File, Body, IsWrite, Expr, Type, Buf, Offset);
     if (HasError)
       continue;
@@ -504,7 +520,7 @@ static void scanRelocs(InputSectionBase<
     }
 
     if (needsPlt(Expr) || Expr == R_THUNK || refersToGotEntry(Expr) ||
-        !Body.isPreemptible()) {
+        !isPreemptible(Body, Type)) {
       // If the relocation points to something in the file, we can process it.
       bool Constant = isStaticLinkTimeConstant<ELFT>(Expr, Type, Body);
 

Added: lld/trunk/test/ELF/mips-64-gprel-so.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/mips-64-gprel-so.s?rev=271100&view=auto
==============================================================================
--- lld/trunk/test/ELF/mips-64-gprel-so.s (added)
+++ lld/trunk/test/ELF/mips-64-gprel-so.s Fri May 27 23:49:57 2016
@@ -0,0 +1,23 @@
+# Check setup of GP relative offsets in a function's prologue.
+
+# RUN: llvm-mc -filetype=obj -triple=mips64-unknown-linux %s -o %t.o
+# RUN: ld.lld %t.o -shared -o %t.so
+# RUN: llvm-objdump -d -t %t.so | FileCheck %s
+
+# REQUIRES: mips
+
+# CHECK:      Disassembly of section .text:
+# CHECK-NEXT: foo:
+# CHECK-NEXT:    10000:    3c 1c 00 01    lui     $gp, 1
+# CHECK-NEXT:    10004:    03 99 e0 2d    daddu   $gp, $gp, $25
+# CHECK-NEXT:    10008:    67 9c 7f f0    daddiu  $gp, $gp, 32752
+
+# CHECK: 0000000000027ff0   .got    00000000 .hidden _gp
+# CHECK: 0000000000010000   .text   00000000 foo
+
+  .text
+  .global foo
+foo:
+  lui     $gp,%hi(%neg(%gp_rel(foo)))
+  daddu   $gp,$gp,$t9
+  daddiu  $gp,$gp,%lo(%neg(%gp_rel(foo)))




More information about the llvm-commits mailing list