[lld] r298306 - [ELF][MIPS] Calculate relocations agains _gp_disp / __gnu_local_gp using dedicated 'expressions'

Simon Atanasyan via llvm-commits llvm-commits at lists.llvm.org
Mon Mar 20 14:03:44 PDT 2017


Author: atanasyan
Date: Mon Mar 20 16:03:43 2017
New Revision: 298306

URL: http://llvm.org/viewvc/llvm-project?rev=298306&view=rev
Log:
[ELF][MIPS] Calculate relocations agains _gp_disp / __gnu_local_gp using dedicated 'expressions'

The patch introduces two new relocations expressions R_MIPS_GOT_GP and
R_MIPS_GOT_GP_PC. The first one represents a current value of `_gp`
pointer and used to calculate relocations against the `__gnu_local_gp`
symbol. The second one represents the offset between the beginning of
the function and the `_gp` pointer's value.

There are two motivations for introducing new expressions:
- It's better to keep all non-trivial relocation calculations in the
  single place - `getRelocTargetVA` function.
- Relocations against both `_gp_disp` and `__gnu_local_gp` symbols
  depend on the `_gp` value. It's a magical value points to the "middle"
  of GOT. Now all relocations use a common `_gp` value. But in fact,
  under some conditions each input file might require its own `_gp`
  value. I'm going to implement it in the future patches. So it's
  better to make `MipsGotSection` responsible for calculation of
  the `_gp` value.

Modified:
    lld/trunk/ELF/InputSection.cpp
    lld/trunk/ELF/Relocations.cpp
    lld/trunk/ELF/Relocations.h
    lld/trunk/ELF/Target.cpp
    lld/trunk/ELF/Writer.cpp
    lld/trunk/test/ELF/mips-gp-ext.s

Modified: lld/trunk/ELF/InputSection.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputSection.cpp?rev=298306&r1=298305&r2=298306&view=diff
==============================================================================
--- lld/trunk/ELF/InputSection.cpp (original)
+++ lld/trunk/ELF/InputSection.cpp Mon Mar 20 16:03:43 2017
@@ -410,6 +410,18 @@ getRelocTargetVA(uint32_t Type, int64_t
            In<ELFT>::MipsGot->getGp();
   case R_MIPS_GOTREL:
     return Body.getVA(A) - In<ELFT>::MipsGot->getGp();
+  case R_MIPS_GOT_GP:
+    return In<ELFT>::MipsGot->getGp() + A;
+  case R_MIPS_GOT_GP_PC: {
+    // R_MIPS_LO16 expression has R_MIPS_GOT_GP_PC type iif the target
+    // is _gp_disp symbol. In that case we should use the following
+    // formula for calculation "AHL + GP - P + 4". For details see p. 4-19 at
+    // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf
+    uint64_t V = In<ELFT>::MipsGot->getGp() + A - P;
+    if (Type == R_MIPS_LO16)
+      V += 4;
+    return V;
+  }
   case R_MIPS_TLSGD:
     return In<ELFT>::MipsGot->getVA() + In<ELFT>::MipsGot->getTlsOffset() +
            In<ELFT>::MipsGot->getGlobalDynOffset(Body) -

Modified: lld/trunk/ELF/Relocations.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Relocations.cpp?rev=298306&r1=298305&r2=298306&view=diff
==============================================================================
--- lld/trunk/ELF/Relocations.cpp (original)
+++ lld/trunk/ELF/Relocations.cpp Mon Mar 20 16:03:43 2017
@@ -317,9 +317,10 @@ isStaticLinkTimeConstant(RelExpr E, uint
                          InputSectionBase &S, typename ELFT::uint RelOff) {
   // These expressions always compute a constant
   if (isRelExprOneOf<R_SIZE, R_GOT_FROM_END, R_GOT_OFF, R_MIPS_GOT_LOCAL_PAGE,
-                     R_MIPS_GOT_OFF, R_MIPS_GOT_OFF32, R_MIPS_TLSGD,
-                     R_GOT_PAGE_PC, R_GOT_PC, R_PLT_PC, R_TLSGD_PC, R_TLSGD,
-                     R_PPC_PLT_OPD, R_TLSDESC_CALL, R_TLSDESC_PAGE, R_HINT>(E))
+                     R_MIPS_GOT_OFF, R_MIPS_GOT_OFF32, R_MIPS_GOT_GP_PC,
+                     R_MIPS_TLSGD, R_GOT_PAGE_PC, R_GOT_PC, R_PLT_PC,
+                     R_TLSGD_PC, R_TLSGD, R_PPC_PLT_OPD, R_TLSDESC_CALL,
+                     R_TLSDESC_PAGE, R_HINT>(E))
     return true;
 
   // These never do, except if the entire file is position dependent or if
@@ -351,8 +352,6 @@ isStaticLinkTimeConstant(RelExpr E, uint
   if (AbsVal && RelE) {
     if (Body.isUndefined() && !Body.isLocal() && Body.symbol()->isWeak())
       return true;
-    if (&Body == ElfSym::MipsGpDisp)
-      return true;
     error(S.getLocation<ELFT>(RelOff) + ": relocation " + toString(Type) +
           " cannot refer to absolute symbol '" + toString(Body) +
           "' defined in " + toString(Body.File));
@@ -582,13 +581,6 @@ static int64_t computeAddend(const elf::
     Addend += Target->getImplicitAddend(BufLoc, Type);
   if (Config->EMachine == EM_MIPS) {
     Addend += findMipsPairedAddend<ELFT>(SectionData, BufLoc, Body, &RI, End);
-    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;
     if (Expr == R_MIPS_GOTREL && Body.isLocal())
       Addend += File.MipsGp0;
   }

Modified: lld/trunk/ELF/Relocations.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Relocations.h?rev=298306&r1=298305&r2=298306&view=diff
==============================================================================
--- lld/trunk/ELF/Relocations.h (original)
+++ lld/trunk/ELF/Relocations.h Mon Mar 20 16:03:43 2017
@@ -38,6 +38,8 @@ enum RelExpr {
   R_MIPS_GOT_OFF,
   R_MIPS_GOT_OFF32,
   R_MIPS_GOTREL,
+  R_MIPS_GOT_GP,
+  R_MIPS_GOT_GP_PC,
   R_MIPS_TLSGD,
   R_MIPS_TLSLD,
   R_NEG_TLS,

Modified: lld/trunk/ELF/Target.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Target.cpp?rev=298306&r1=298305&r2=298306&view=diff
==============================================================================
--- lld/trunk/ELF/Target.cpp (original)
+++ lld/trunk/ELF/Target.cpp Mon Mar 20 16:03:43 2017
@@ -2083,13 +2083,16 @@ RelExpr MipsTargetInfo<ELFT>::getRelExpr
     return R_PLT;
   case R_MIPS_HI16:
   case R_MIPS_LO16:
-  case R_MIPS_GOT_OFST:
     // R_MIPS_HI16/R_MIPS_LO16 relocations against _gp_disp calculate
     // offset between start of function and 'gp' value which by default
     // equal to the start of .got section. In that case we consider these
     // relocations as relative.
     if (&S == ElfSym::MipsGpDisp)
-      return R_PC;
+      return R_MIPS_GOT_GP_PC;
+    if (&S == ElfSym::MipsLocalGp)
+      return R_MIPS_GOT_GP;
+    // fallthrough
+  case R_MIPS_GOT_OFST:
     return R_ABS;
   case R_MIPS_PC32:
   case R_MIPS_PC16:

Modified: lld/trunk/ELF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp?rev=298306&r1=298305&r2=298306&view=diff
==============================================================================
--- lld/trunk/ELF/Writer.cpp (original)
+++ lld/trunk/ELF/Writer.cpp Mon Mar 20 16:03:43 2017
@@ -802,9 +802,7 @@ template <class ELFT> void Writer<ELFT>:
     ElfSym::MipsGp = Symtab<ELFT>::X->addAbsolute("_gp", STV_HIDDEN, STB_LOCAL);
 
     // On MIPS O32 ABI, _gp_disp is a magic symbol designates offset between
-    // start of function and 'gp' pointer into GOT. To simplify relocation
-    // calculation we assign _gp value to it and calculate corresponding
-    // relocations as relative to this value.
+    // start of function and 'gp' pointer into GOT.
     if (Symtab<ELFT>::X->find("_gp_disp"))
       ElfSym::MipsGpDisp =
           Symtab<ELFT>::X->addAbsolute("_gp_disp", STV_HIDDEN, STB_LOCAL);
@@ -1692,10 +1690,6 @@ template <class ELFT> void Writer<ELFT>:
       if (Gp != (uintX_t)-1)
         ElfSym::MipsGp->Value = Gp + 0x7ff0;
     }
-    if (ElfSym::MipsGpDisp)
-      ElfSym::MipsGpDisp->Value = ElfSym::MipsGp->Value;
-    if (ElfSym::MipsLocalGp)
-      ElfSym::MipsLocalGp->Value = ElfSym::MipsGp->Value;
   }
 }
 

Modified: lld/trunk/test/ELF/mips-gp-ext.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/mips-gp-ext.s?rev=298306&r1=298305&r2=298306&view=diff
==============================================================================
--- lld/trunk/test/ELF/mips-gp-ext.s (original)
+++ lld/trunk/test/ELF/mips-gp-ext.s Mon Mar 20 16:03:43 2017
@@ -36,7 +36,7 @@
 #                 ^-- 0-0x10c
 
 # REL: 00000000         .text           00000000 foo
-# REL: 0000010c         *ABS*           00000000 .hidden _gp_disp
+# REL: 00000000         *ABS*           00000000 .hidden _gp_disp
 # REL: 0000010c         *ABS*           00000000 .hidden _gp
 
 # ABS:      Contents of section .text:
@@ -56,7 +56,7 @@
 #                 ^-- 0-0x200
 
 # ABS: 00000000         .text           00000000 foo
-# ABS: 00000200         *ABS*           00000000 .hidden _gp_disp
+# ABS: 00000000         *ABS*           00000000 .hidden _gp_disp
 # ABS: 00000200         *ABS*           00000000 .hidden _gp
 
   .text




More information about the llvm-commits mailing list