svn commit: r320060 - stable/11/contrib/llvm/tools/lld/ELF
Ed Maste
emaste at FreeBSD.org
Sat Jun 17 19:00:13 UTC 2017
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,
More information about the svn-src-stable
mailing list