Have getRelExpr handle all cases on x86.

This requires adding a few more expression types, but is already a small
simplification. Having Writer.cpp know the exact expression will also
allow further simplifications.

llvm-svn: 266604
This commit is contained in:
Rafael Espindola 2016-04-18 12:07:13 +00:00
parent 4b18a510a2
commit 3f5d634c73
4 changed files with 37 additions and 40 deletions

View File

@ -159,9 +159,11 @@ static typename ELFT::uint
getSymVA(uint32_t Type, typename ELFT::uint A, typename ELFT::uint P,
const SymbolBody &Body, uint8_t *BufLoc,
const elf::ObjectFile<ELFT> &File, RelExpr Expr) {
typedef typename ELFT::uint uintX_t;
switch (Expr) {
case R_TLSLD:
return Out<ELFT>::Got->getTlsIndexVA() + A;
return Out<ELFT>::Got->getTlsIndexOff() + A -
Out<ELFT>::Got->getNumEntries() * sizeof(uintX_t);
case R_TLSLD_PC:
return Out<ELFT>::Got->getTlsIndexVA() + A - P;
case R_THUNK:
@ -169,7 +171,8 @@ getSymVA(uint32_t Type, typename ELFT::uint A, typename ELFT::uint P,
case R_PPC_TOC:
return getPPC64TocBase() + A;
case R_TLSGD:
return Out<ELFT>::Got->getGlobalDynAddr(Body) + A;
return Out<ELFT>::Got->getGlobalDynOffset(Body) + A -
Out<ELFT>::Got->getNumEntries() * sizeof(uintX_t);
case R_TLSGD_PC:
return Out<ELFT>::Got->getGlobalDynAddr(Body) + A - P;
case R_PLT:
@ -179,6 +182,11 @@ getSymVA(uint32_t Type, typename ELFT::uint A, typename ELFT::uint P,
return Body.getPltVA<ELFT>() + A - P;
case R_SIZE:
return Body.getSize<ELFT>() + A;
case R_GOTREL:
return Body.getVA<ELFT>(A) - Out<ELFT>::Got->getVA();
case R_GOT_FROM_END:
return Body.getGotOffset<ELFT>() + A -
Out<ELFT>::Got->getNumEntries() * sizeof(uintX_t);
case R_GOT:
case R_RELAX_TLS_GD_TO_IE:
return Body.getGotVA<ELFT>() + A;
@ -187,6 +195,12 @@ getSymVA(uint32_t Type, typename ELFT::uint A, typename ELFT::uint P,
case R_GOT_PC:
case R_RELAX_TLS_GD_TO_IE_PC:
return Body.getGotVA<ELFT>() + A - P;
case R_GOTONLY_PC:
return Out<ELFT>::Got->getVA() + A - P;
case R_TLS:
return Body.getVA<ELFT>(A) - Out<ELF32LE>::TlsPhdr->p_memsz;
case R_NEG_TLS:
return Out<ELF32LE>::TlsPhdr->p_memsz - Body.getVA<ELFT>(A);
case R_ABS:
case R_RELAX_TLS_GD_TO_LE:
case R_RELAX_TLS_IE_TO_LE:

View File

@ -29,11 +29,15 @@ template <class ELFT> class OutputSectionBase;
enum RelExpr {
R_ABS,
R_GOT,
R_GOTONLY_PC,
R_GOTREL,
R_GOT_FROM_END,
R_GOT_PAGE_PC,
R_GOT_PC,
R_MIPS_GOT,
R_MIPS_GOT_LOCAL,
R_MIPS_GP0,
R_NEG_TLS,
R_PAGE_PC,
R_PC,
R_PLT,
@ -48,6 +52,7 @@ enum RelExpr {
R_RELAX_TLS_LD_TO_LE,
R_SIZE,
R_THUNK,
R_TLS,
R_TLSGD,
R_TLSGD_PC,
R_TLSLD,

View File

@ -372,12 +372,20 @@ RelExpr X86TargetInfo::getRelExpr(uint32_t Type, const SymbolBody &S) const {
return R_TLSLD;
case R_386_PLT32:
case R_386_PC32:
case R_386_GOTPC:
return R_PC;
case R_386_GOT32:
case R_386_TLS_GOTIE:
case R_386_GOTPC:
return R_GOTONLY_PC;
case R_386_TLS_IE:
return R_GOT;
case R_386_GOT32:
case R_386_TLS_GOTIE:
return R_GOT_FROM_END;
case R_386_GOTOFF:
return R_GOTREL;
case R_386_TLS_LE:
return R_TLS;
case R_386_TLS_LE_32:
return R_NEG_TLS;
}
}
@ -507,38 +515,8 @@ uint64_t X86TargetInfo::getImplicitAddend(const uint8_t *Buf,
void X86TargetInfo::relocateOne(uint8_t *Loc, uint32_t Type,
uint64_t Val) const {
switch (Type) {
case R_386_32:
case R_386_PC32:
case R_386_PLT32:
case R_386_TLS_IE:
case R_386_TLS_LDO_32:
write32le(Loc, Val);
break;
case R_386_GOTOFF:
write32le(Loc, Val - Out<ELF32LE>::Got->getVA());
break;
case R_386_GOTPC:
write32le(Loc, Val + Out<ELF32LE>::Got->getVA());
break;
case R_386_GOT32:
case R_386_TLS_GD:
case R_386_TLS_LDM: {
uint64_t V = Val - Out<ELF32LE>::Got->getVA() -
Out<ELF32LE>::Got->getNumEntries() * 4;
checkInt<32>(V, Type);
write32le(Loc, V);
break;
}
case R_386_TLS_LE:
write32le(Loc, Val - Out<ELF32LE>::TlsPhdr->p_memsz);
break;
case R_386_TLS_LE_32:
write32le(Loc, Out<ELF32LE>::TlsPhdr->p_memsz - Val);
break;
default:
fatal("unrecognized reloc " + Twine(Type));
}
checkInt<32>(Val, Type);
write32le(Loc, Val);
}
bool X86TargetInfo::needsDynRelative(uint32_t Type) const {
@ -623,13 +601,13 @@ void X86TargetInfo::relaxTlsIeToLe(uint8_t *Loc, uint32_t Type,
else
*Op = 0x80 | Reg | (Reg << 3);
}
relocateOne(Loc, R_386_TLS_LE, Val);
relocateOne(Loc, R_386_TLS_LE, Val - Out<ELF32LE>::TlsPhdr->p_memsz);
}
void X86TargetInfo::relaxTlsLdToLe(uint8_t *Loc, uint32_t Type,
uint64_t Val) const {
if (Type == R_386_TLS_LDO_32) {
relocateOne(Loc, R_386_TLS_LE, Val);
relocateOne(Loc, R_386_TLS_LE, Val - Out<ELF32LE>::TlsPhdr->p_memsz);
return;
}

View File

@ -563,7 +563,7 @@ void Writer<ELFT>::scanRelocs(InputSectionBase<ELFT> &C, ArrayRef<RelTy> Rels) {
// If a relocation needs GOT, we create a GOT slot for the symbol.
if (Expr == R_GOT || Expr == R_MIPS_GOT || Expr == R_MIPS_GOT_LOCAL ||
Expr == R_GOT_PAGE_PC || Expr == R_GOT_PC) {
Expr == R_GOT_PAGE_PC || Expr == R_GOT_PC || Expr == R_GOT_FROM_END) {
uint32_t T = Body.isTls() ? Target->getTlsGotRel(Type) : Type;
C.Relocations.push_back({Expr, T, Offset, Addend, &Body});
if (Body.isInGot())