Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 17 Jun 2017 19:00:12 +0000 (UTC)
From:      Ed Maste <emaste@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org
Subject:   svn commit: r320060 - stable/11/contrib/llvm/tools/lld/ELF
Message-ID:  <201706171900.v5HJ0CLR006202@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: emaste
Date: Sat Jun 17 19:00:12 2017
New Revision: 320060
URL: https://svnweb.freebsd.org/changeset/base/320060

Log:
  lld: Fix weak symbols on arm and aarch64
  
  MFC r319955: lld: sort relocations
  
  No functional change; applied to facilitate merge of later LLD commit.
  
  MFC r319956: lld: Fix weak symbols on arm and aarch64
  
  Given
  
  .weak target
   .global _start
  _start:
   b target
  
  The intention is that the branch goes to the instruction after the
  branch, effectively turning it on a nop. The branch adds the runtime
  PC, but we were adding it statically too.
  
  I noticed the oddity by inspection, but llvm-objdump seems to agree,
  since it now prints things like:
  
  b #-4 <_start+0x4>
  
  Obtained from:	LLD r298797, r305212
  Approved by:	re (gjb)
  Sponsored by:	The FreeBSD Foundation

Modified:
  stable/11/contrib/llvm/tools/lld/ELF/InputSection.cpp
  stable/11/contrib/llvm/tools/lld/ELF/Relocations.h
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/contrib/llvm/tools/lld/ELF/InputSection.cpp
==============================================================================
--- stable/11/contrib/llvm/tools/lld/ELF/InputSection.cpp	Sat Jun 17 17:42:52 2017	(r320059)
+++ stable/11/contrib/llvm/tools/lld/ELF/InputSection.cpp	Sat Jun 17 19:00:12 2017	(r320060)
@@ -255,7 +255,7 @@ static uint32_t getARMUndefinedRelativeWeakVA(uint32_t
                                               uint32_t P) {
   switch (Type) {
   case R_ARM_THM_JUMP11:
-    return P + 2;
+    return P + 2 + A;
   case R_ARM_CALL:
   case R_ARM_JUMP24:
   case R_ARM_PC24:
@@ -263,12 +263,12 @@ static uint32_t getARMUndefinedRelativeWeakVA(uint32_t
   case R_ARM_PREL31:
   case R_ARM_THM_JUMP19:
   case R_ARM_THM_JUMP24:
-    return P + 4;
+    return P + 4 + A;
   case R_ARM_THM_CALL:
     // We don't want an interworking BLX to ARM
-    return P + 5;
+    return P + 5 + A;
   default:
-    return A;
+    return P + A;
   }
 }
 
@@ -279,9 +279,9 @@ static uint64_t getAArch64UndefinedRelativeWeakVA(uint
   case R_AARCH64_CONDBR19:
   case R_AARCH64_JUMP26:
   case R_AARCH64_TSTBR14:
-    return P + 4;
+    return P + 4 + A;
   default:
-    return A;
+    return P + A;
   }
 }
 
@@ -290,82 +290,37 @@ static typename ELFT::uint
 getRelocTargetVA(uint32_t Type, typename ELFT::uint A, typename ELFT::uint P,
                  const SymbolBody &Body, RelExpr Expr) {
   switch (Expr) {
-  case R_HINT:
-  case R_TLSDESC_CALL:
-    llvm_unreachable("cannot relocate hint relocs");
-  case R_TLSLD:
-    return In<ELFT>::Got->getTlsIndexOff() + A - In<ELFT>::Got->getSize();
-  case R_TLSLD_PC:
-    return In<ELFT>::Got->getTlsIndexVA() + A - P;
-  case R_THUNK_ABS:
-    return Body.getThunkVA<ELFT>() + A;
-  case R_THUNK_PC:
-  case R_THUNK_PLT_PC:
-    return Body.getThunkVA<ELFT>() + A - P;
-  case R_PPC_TOC:
-    return getPPC64TocBase() + A;
-  case R_TLSGD:
-    return In<ELFT>::Got->getGlobalDynOffset(Body) + A -
-           In<ELFT>::Got->getSize();
-  case R_TLSGD_PC:
-    return In<ELFT>::Got->getGlobalDynAddr(Body) + A - P;
-  case R_TLSDESC:
-    return In<ELFT>::Got->getGlobalDynAddr(Body) + A;
-  case R_TLSDESC_PAGE:
-    return getAArch64Page(In<ELFT>::Got->getGlobalDynAddr(Body) + A) -
-           getAArch64Page(P);
-  case R_PLT:
-    return Body.getPltVA<ELFT>() + A;
-  case R_PLT_PC:
-  case R_PPC_PLT_OPD:
-    return Body.getPltVA<ELFT>() + A - P;
-  case R_SIZE:
-    return Body.getSize<ELFT>() + A;
+  case R_ABS:
+  case R_RELAX_GOT_PC_NOPIC:
+    return Body.getVA<ELFT>(A);
+  case R_GOT:
+  case R_RELAX_TLS_GD_TO_IE_ABS:
+    return Body.getGotVA<ELFT>() + A;
+  case R_GOTONLY_PC:
+    return In<ELFT>::Got->getVA() + A - P;
+  case R_GOTONLY_PC_FROM_END:
+    return In<ELFT>::Got->getVA() + A - P + In<ELFT>::Got->getSize();
   case R_GOTREL:
     return Body.getVA<ELFT>(A) - In<ELFT>::Got->getVA();
   case R_GOTREL_FROM_END:
     return Body.getVA<ELFT>(A) - In<ELFT>::Got->getVA() -
            In<ELFT>::Got->getSize();
-  case R_RELAX_TLS_GD_TO_IE_END:
   case R_GOT_FROM_END:
+  case R_RELAX_TLS_GD_TO_IE_END:
     return Body.getGotOffset<ELFT>() + A - In<ELFT>::Got->getSize();
-  case R_RELAX_TLS_GD_TO_IE_ABS:
-  case R_GOT:
-    return Body.getGotVA<ELFT>() + A;
-  case R_RELAX_TLS_GD_TO_IE_PAGE_PC:
+  case R_GOT_OFF:
+    return Body.getGotOffset<ELFT>() + A;
   case R_GOT_PAGE_PC:
+  case R_RELAX_TLS_GD_TO_IE_PAGE_PC:
     return getAArch64Page(Body.getGotVA<ELFT>() + A) - getAArch64Page(P);
-  case R_RELAX_TLS_GD_TO_IE:
   case R_GOT_PC:
+  case R_RELAX_TLS_GD_TO_IE:
     return Body.getGotVA<ELFT>() + A - P;
-  case R_GOTONLY_PC:
-    return In<ELFT>::Got->getVA() + A - P;
-  case R_GOTONLY_PC_FROM_END:
-    return In<ELFT>::Got->getVA() + A - P + In<ELFT>::Got->getSize();
-  case R_RELAX_TLS_LD_TO_LE:
-  case R_RELAX_TLS_IE_TO_LE:
-  case R_RELAX_TLS_GD_TO_LE:
-  case R_TLS:
-    // A weak undefined TLS symbol resolves to the base of the TLS
-    // block, i.e. gets a value of zero. If we pass --gc-sections to
-    // lld and .tbss is not referenced, it gets reclaimed and we don't
-    // create a TLS program header. Therefore, we resolve this
-    // statically to zero.
-    if (Body.isTls() && (Body.isLazy() || Body.isUndefined()) &&
-        Body.symbol()->isWeak())
-      return 0;
-    if (Target->TcbSize)
-      return Body.getVA<ELFT>(A) +
-             alignTo(Target->TcbSize, Out<ELFT>::TlsPhdr->p_align);
-    return Body.getVA<ELFT>(A) - Out<ELFT>::TlsPhdr->p_memsz;
-  case R_RELAX_TLS_GD_TO_LE_NEG:
-  case R_NEG_TLS:
-    return Out<ELF32LE>::TlsPhdr->p_memsz - Body.getVA<ELFT>(A);
-  case R_ABS:
-  case R_RELAX_GOT_PC_NOPIC:
-    return Body.getVA<ELFT>(A);
-  case R_GOT_OFF:
-    return Body.getGotOffset<ELFT>() + A;
+  case R_HINT:
+  case R_TLSDESC_CALL:
+    llvm_unreachable("cannot relocate hint relocs");
+  case R_MIPS_GOTREL:
+    return Body.getVA<ELFT>(A) - In<ELFT>::MipsGot->getGp();
   case R_MIPS_GOT_LOCAL_PAGE:
     // If relocation against MIPS local symbol requires GOT entry, this entry
     // should be initialized by 'page address'. This address is high 16-bits
@@ -381,8 +336,6 @@ getRelocTargetVA(uint32_t Type, typename ELFT::uint A,
     return In<ELFT>::MipsGot->getVA() +
            In<ELFT>::MipsGot->getBodyEntryOffset(Body, A) -
            In<ELFT>::MipsGot->getGp();
-  case R_MIPS_GOTREL:
-    return Body.getVA<ELFT>(A) - In<ELFT>::MipsGot->getGp();
   case R_MIPS_TLSGD:
     return In<ELFT>::MipsGot->getVA() + In<ELFT>::MipsGot->getTlsOffset() +
            In<ELFT>::MipsGot->getGlobalDynOffset(Body) -
@@ -390,6 +343,36 @@ getRelocTargetVA(uint32_t Type, typename ELFT::uint A,
   case R_MIPS_TLSLD:
     return In<ELFT>::MipsGot->getVA() + In<ELFT>::MipsGot->getTlsOffset() +
            In<ELFT>::MipsGot->getTlsIndexOff() - In<ELFT>::MipsGot->getGp();
+  case R_PAGE_PC:
+  case R_PLT_PAGE_PC: {
+    uint64_t Dest;
+    if (Body.isUndefined() && !Body.isLocal() && Body.symbol()->isWeak())
+      Dest = getAArch64Page(A);
+    else
+      Dest = getAArch64Page(Body.getVA<ELFT>(A));
+    return Dest - getAArch64Page(P);
+  }
+  case R_PC: {
+    uint64_t Dest;
+    if (Body.isUndefined() && !Body.isLocal() && Body.symbol()->isWeak()) {
+      // On ARM and AArch64 a branch to an undefined weak resolves to the
+      // next instruction, otherwise the place.
+      if (Config->EMachine == EM_ARM)
+        Dest = getARMUndefinedRelativeWeakVA(Type, A, P);
+      else if (Config->EMachine == EM_AARCH64)
+        Dest = getAArch64UndefinedRelativeWeakVA(Type, A, P);
+      else
+        Dest = Body.getVA<ELFT>(A);
+    } else {
+      Dest = Body.getVA<ELFT>(A);
+    }
+    return Dest - P;
+  }
+  case R_PLT:
+    return Body.getPltVA<ELFT>() + A;
+  case R_PLT_PC:
+  case R_PPC_PLT_OPD:
+    return Body.getPltVA<ELFT>() + A - P;
   case R_PPC_OPD: {
     uint64_t SymVA = Body.getVA<ELFT>(A);
     // If we have an undefined weak symbol, we might get here with a symbol
@@ -408,22 +391,50 @@ getRelocTargetVA(uint32_t Type, typename ELFT::uint A,
     }
     return SymVA - P;
   }
-  case R_PC:
-    if (Body.isUndefined() && !Body.isLocal() && Body.symbol()->isWeak()) {
-      // On ARM and AArch64 a branch to an undefined weak resolves to the
-      // next instruction, otherwise the place.
-      if (Config->EMachine == EM_ARM)
-        return getARMUndefinedRelativeWeakVA(Type, A, P);
-      if (Config->EMachine == EM_AARCH64)
-        return getAArch64UndefinedRelativeWeakVA(Type, A, P);
-    }
+  case R_PPC_TOC:
+    return getPPC64TocBase() + A;
   case R_RELAX_GOT_PC:
     return Body.getVA<ELFT>(A) - P;
-  case R_PLT_PAGE_PC:
-  case R_PAGE_PC:
-    if (Body.isUndefined() && !Body.isLocal() && Body.symbol()->isWeak())
-      return getAArch64Page(A);
-    return getAArch64Page(Body.getVA<ELFT>(A)) - getAArch64Page(P);
+  case R_RELAX_TLS_GD_TO_LE:
+  case R_RELAX_TLS_IE_TO_LE:
+  case R_RELAX_TLS_LD_TO_LE:
+  case R_TLS:
+    // A weak undefined TLS symbol resolves to the base of the TLS
+    // block, i.e. gets a value of zero. If we pass --gc-sections to
+    // lld and .tbss is not referenced, it gets reclaimed and we don't
+    // create a TLS program header. Therefore, we resolve this
+    // statically to zero.
+    if (Body.isTls() && (Body.isLazy() || Body.isUndefined()) &&
+        Body.symbol()->isWeak())
+      return 0;
+    if (Target->TcbSize)
+      return Body.getVA<ELFT>(A) +
+             alignTo(Target->TcbSize, Out<ELFT>::TlsPhdr->p_align);
+    return Body.getVA<ELFT>(A) - Out<ELFT>::TlsPhdr->p_memsz;
+  case R_RELAX_TLS_GD_TO_LE_NEG:
+  case R_NEG_TLS:
+    return Out<ELF32LE>::TlsPhdr->p_memsz - Body.getVA<ELFT>(A);
+  case R_SIZE:
+    return Body.getSize<ELFT>() + A;
+  case R_THUNK_ABS:
+    return Body.getThunkVA<ELFT>() + A;
+  case R_THUNK_PC:
+  case R_THUNK_PLT_PC:
+    return Body.getThunkVA<ELFT>() + A - P;
+  case R_TLSDESC:
+    return In<ELFT>::Got->getGlobalDynAddr(Body) + A;
+  case R_TLSDESC_PAGE:
+    return getAArch64Page(In<ELFT>::Got->getGlobalDynAddr(Body) + A) -
+           getAArch64Page(P);
+  case R_TLSGD:
+    return In<ELFT>::Got->getGlobalDynOffset(Body) + A -
+           In<ELFT>::Got->getSize();
+  case R_TLSGD_PC:
+    return In<ELFT>::Got->getGlobalDynAddr(Body) + A - P;
+  case R_TLSLD:
+    return In<ELFT>::Got->getTlsIndexOff() + A - In<ELFT>::Got->getSize();
+  case R_TLSLD_PC:
+    return In<ELFT>::Got->getTlsIndexVA() + A - P;
   }
   llvm_unreachable("Invalid expression");
 }

Modified: stable/11/contrib/llvm/tools/lld/ELF/Relocations.h
==============================================================================
--- stable/11/contrib/llvm/tools/lld/ELF/Relocations.h	Sat Jun 17 17:42:52 2017	(r320059)
+++ stable/11/contrib/llvm/tools/lld/ELF/Relocations.h	Sat Jun 17 19:00:12 2017	(r320060)
@@ -34,26 +34,26 @@ enum RelExpr {
   R_GOT_PAGE_PC,
   R_GOT_PC,
   R_HINT,
+  R_MIPS_GOTREL,
   R_MIPS_GOT_LOCAL_PAGE,
   R_MIPS_GOT_OFF,
   R_MIPS_GOT_OFF32,
-  R_MIPS_GOTREL,
   R_MIPS_TLSGD,
   R_MIPS_TLSLD,
   R_NEG_TLS,
   R_PAGE_PC,
   R_PC,
   R_PLT,
-  R_PLT_PC,
   R_PLT_PAGE_PC,
+  R_PLT_PC,
   R_PPC_OPD,
   R_PPC_PLT_OPD,
   R_PPC_TOC,
   R_RELAX_GOT_PC,
   R_RELAX_GOT_PC_NOPIC,
   R_RELAX_TLS_GD_TO_IE,
-  R_RELAX_TLS_GD_TO_IE_END,
   R_RELAX_TLS_GD_TO_IE_ABS,
+  R_RELAX_TLS_GD_TO_IE_END,
   R_RELAX_TLS_GD_TO_IE_PAGE_PC,
   R_RELAX_TLS_GD_TO_LE,
   R_RELAX_TLS_GD_TO_LE_NEG,
@@ -65,8 +65,8 @@ enum RelExpr {
   R_THUNK_PLT_PC,
   R_TLS,
   R_TLSDESC,
-  R_TLSDESC_PAGE,
   R_TLSDESC_CALL,
+  R_TLSDESC_PAGE,
   R_TLSGD,
   R_TLSGD_PC,
   R_TLSLD,



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201706171900.v5HJ0CLR006202>