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:
parent
4b18a510a2
commit
3f5d634c73
|
@ -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:
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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())
|
||||
|
|
Loading…
Reference in New Issue