lld: sort relocations

No functional change; applied to facilitate merge of later LLD commit.

Reviewed by:	dim, Rafael Espíndola
Obtained from:	LLD r298797
MFC after:	3 days
Differential Revision:	https://reviews.freebsd.org/D11190
This commit is contained in:
emaste 2017-06-14 18:53:33 +00:00
parent d6d4022784
commit 858d15e96f
2 changed files with 88 additions and 87 deletions

View File

@ -290,82 +290,37 @@ static typename ELFT::uint
getRelocTargetVA(uint32_t Type, typename ELFT::uint A, typename ELFT::uint P, getRelocTargetVA(uint32_t Type, typename ELFT::uint A, typename ELFT::uint P,
const SymbolBody &Body, RelExpr Expr) { const SymbolBody &Body, RelExpr Expr) {
switch (Expr) { switch (Expr) {
case R_HINT: case R_ABS:
case R_TLSDESC_CALL: case R_RELAX_GOT_PC_NOPIC:
llvm_unreachable("cannot relocate hint relocs"); return Body.getVA<ELFT>(A);
case R_TLSLD: case R_GOT:
return In<ELFT>::Got->getTlsIndexOff() + A - In<ELFT>::Got->getSize(); case R_RELAX_TLS_GD_TO_IE_ABS:
case R_TLSLD_PC: return Body.getGotVA<ELFT>() + A;
return In<ELFT>::Got->getTlsIndexVA() + A - P; case R_GOTONLY_PC:
case R_THUNK_ABS: return In<ELFT>::Got->getVA() + A - P;
return Body.getThunkVA<ELFT>() + A; case R_GOTONLY_PC_FROM_END:
case R_THUNK_PC: return In<ELFT>::Got->getVA() + A - P + In<ELFT>::Got->getSize();
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_GOTREL: case R_GOTREL:
return Body.getVA<ELFT>(A) - In<ELFT>::Got->getVA(); return Body.getVA<ELFT>(A) - In<ELFT>::Got->getVA();
case R_GOTREL_FROM_END: case R_GOTREL_FROM_END:
return Body.getVA<ELFT>(A) - In<ELFT>::Got->getVA() - return Body.getVA<ELFT>(A) - In<ELFT>::Got->getVA() -
In<ELFT>::Got->getSize(); In<ELFT>::Got->getSize();
case R_RELAX_TLS_GD_TO_IE_END:
case R_GOT_FROM_END: case R_GOT_FROM_END:
case R_RELAX_TLS_GD_TO_IE_END:
return Body.getGotOffset<ELFT>() + A - In<ELFT>::Got->getSize(); 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_PAGE_PC:
return getAArch64Page(Body.getGotVA<ELFT>() + A) - getAArch64Page(P);
case R_RELAX_TLS_GD_TO_IE:
case R_GOT_PC:
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: case R_GOT_OFF:
return Body.getGotOffset<ELFT>() + A; 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_GOT_PC:
case R_RELAX_TLS_GD_TO_IE:
return Body.getGotVA<ELFT>() + A - P;
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: case R_MIPS_GOT_LOCAL_PAGE:
// If relocation against MIPS local symbol requires GOT entry, this entry // If relocation against MIPS local symbol requires GOT entry, this entry
// should be initialized by 'page address'. This address is high 16-bits // should be initialized by 'page address'. This address is high 16-bits
@ -381,8 +336,6 @@ getRelocTargetVA(uint32_t Type, typename ELFT::uint A, typename ELFT::uint P,
return In<ELFT>::MipsGot->getVA() + return In<ELFT>::MipsGot->getVA() +
In<ELFT>::MipsGot->getBodyEntryOffset(Body, A) - In<ELFT>::MipsGot->getBodyEntryOffset(Body, A) -
In<ELFT>::MipsGot->getGp(); In<ELFT>::MipsGot->getGp();
case R_MIPS_GOTREL:
return Body.getVA<ELFT>(A) - In<ELFT>::MipsGot->getGp();
case R_MIPS_TLSGD: case R_MIPS_TLSGD:
return In<ELFT>::MipsGot->getVA() + In<ELFT>::MipsGot->getTlsOffset() + return In<ELFT>::MipsGot->getVA() + In<ELFT>::MipsGot->getTlsOffset() +
In<ELFT>::MipsGot->getGlobalDynOffset(Body) - In<ELFT>::MipsGot->getGlobalDynOffset(Body) -
@ -390,6 +343,26 @@ getRelocTargetVA(uint32_t Type, typename ELFT::uint A, typename ELFT::uint P,
case R_MIPS_TLSLD: case R_MIPS_TLSLD:
return In<ELFT>::MipsGot->getVA() + In<ELFT>::MipsGot->getTlsOffset() + return In<ELFT>::MipsGot->getVA() + In<ELFT>::MipsGot->getTlsOffset() +
In<ELFT>::MipsGot->getTlsIndexOff() - In<ELFT>::MipsGot->getGp(); In<ELFT>::MipsGot->getTlsIndexOff() - In<ELFT>::MipsGot->getGp();
case R_PAGE_PC:
case R_PLT_PAGE_PC:
if (Body.isUndefined() && !Body.isLocal() && Body.symbol()->isWeak())
return getAArch64Page(A);
return getAArch64Page(Body.getVA<ELFT>(A)) - getAArch64Page(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);
}
return Body.getVA<ELFT>(A) - 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: { case R_PPC_OPD: {
uint64_t SymVA = Body.getVA<ELFT>(A); uint64_t SymVA = Body.getVA<ELFT>(A);
// If we have an undefined weak symbol, we might get here with a symbol // If we have an undefined weak symbol, we might get here with a symbol
@ -408,22 +381,50 @@ getRelocTargetVA(uint32_t Type, typename ELFT::uint A, typename ELFT::uint P,
} }
return SymVA - P; return SymVA - P;
} }
case R_PC: case R_PPC_TOC:
if (Body.isUndefined() && !Body.isLocal() && Body.symbol()->isWeak()) { return getPPC64TocBase() + A;
// 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_RELAX_GOT_PC: case R_RELAX_GOT_PC:
return Body.getVA<ELFT>(A) - P; return Body.getVA<ELFT>(A) - P;
case R_PLT_PAGE_PC: case R_RELAX_TLS_GD_TO_LE:
case R_PAGE_PC: case R_RELAX_TLS_IE_TO_LE:
if (Body.isUndefined() && !Body.isLocal() && Body.symbol()->isWeak()) case R_RELAX_TLS_LD_TO_LE:
return getAArch64Page(A); case R_TLS:
return getAArch64Page(Body.getVA<ELFT>(A)) - getAArch64Page(P); // 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"); llvm_unreachable("Invalid expression");
} }

View File

@ -34,26 +34,26 @@ enum RelExpr {
R_GOT_PAGE_PC, R_GOT_PAGE_PC,
R_GOT_PC, R_GOT_PC,
R_HINT, R_HINT,
R_MIPS_GOTREL,
R_MIPS_GOT_LOCAL_PAGE, R_MIPS_GOT_LOCAL_PAGE,
R_MIPS_GOT_OFF, R_MIPS_GOT_OFF,
R_MIPS_GOT_OFF32, R_MIPS_GOT_OFF32,
R_MIPS_GOTREL,
R_MIPS_TLSGD, R_MIPS_TLSGD,
R_MIPS_TLSLD, R_MIPS_TLSLD,
R_NEG_TLS, R_NEG_TLS,
R_PAGE_PC, R_PAGE_PC,
R_PC, R_PC,
R_PLT, R_PLT,
R_PLT_PC,
R_PLT_PAGE_PC, R_PLT_PAGE_PC,
R_PLT_PC,
R_PPC_OPD, R_PPC_OPD,
R_PPC_PLT_OPD, R_PPC_PLT_OPD,
R_PPC_TOC, R_PPC_TOC,
R_RELAX_GOT_PC, R_RELAX_GOT_PC,
R_RELAX_GOT_PC_NOPIC, R_RELAX_GOT_PC_NOPIC,
R_RELAX_TLS_GD_TO_IE, 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_ABS,
R_RELAX_TLS_GD_TO_IE_END,
R_RELAX_TLS_GD_TO_IE_PAGE_PC, R_RELAX_TLS_GD_TO_IE_PAGE_PC,
R_RELAX_TLS_GD_TO_LE, R_RELAX_TLS_GD_TO_LE,
R_RELAX_TLS_GD_TO_LE_NEG, R_RELAX_TLS_GD_TO_LE_NEG,
@ -65,8 +65,8 @@ enum RelExpr {
R_THUNK_PLT_PC, R_THUNK_PLT_PC,
R_TLS, R_TLS,
R_TLSDESC, R_TLSDESC,
R_TLSDESC_PAGE,
R_TLSDESC_CALL, R_TLSDESC_CALL,
R_TLSDESC_PAGE,
R_TLSGD, R_TLSGD,
R_TLSGD_PC, R_TLSGD_PC,
R_TLSLD, R_TLSLD,