}
uintX_t SymVA = Body->getVA<ELFT>();
- bool CBP = canBePreempted(Body);
+ bool CBP = canBePreempted(Body, Type);
if (Target->needsPlt<ELFT>(Type, *Body)) {
SymVA = Body->getPltVA<ELFT>();
} else if (Target->needsGot(Type, *Body)) {
SymVA = Body->getGotVA<ELFT>();
if (Body->IsTls)
Type = Target->getTlsGotRel(Type);
- } else if (!Target->needsCopyRel<ELFT>(Type, *Body) &&
- isa<SharedSymbol<ELFT>>(*Body)) {
- continue;
- } else if (Target->isTlsDynRel(Type, *Body)) {
- continue;
} else if (Target->isSizeRel(Type) && CBP) {
// A SIZE relocation is supposed to set a symbol size, but if a symbol
// can be preempted, the size at runtime may be different than link time.
SymVA = getMipsGpAddr<ELFT>() - AddrLoc + 4;
else if (Body == Config->MipsLocalGp)
SymVA = getMipsGpAddr<ELFT>();
+ } else if (!Target->needsCopyRel<ELFT>(Type, *Body) && CBP) {
+ continue;
}
uintX_t Size = Body->getSize<ELFT>();
Target->relocateOne(BufLoc, BufEnd, Type, AddrLoc, SymVA + A, Size + A,
bool isTlsLocalDynamicRel(uint32_t Type) const override;
bool isTlsGlobalDynamicRel(uint32_t Type) const override;
bool isTlsInitialExecRel(uint32_t Type) const override;
- bool isTlsDynRel(uint32_t Type, const SymbolBody &S) const override;
void writeGotPlt(uint8_t *Buf, uint64_t Plt) const override;
void writePltZero(uint8_t *Buf) const override;
void writePlt(uint8_t *Buf, uint64_t GotEntryAddr, uint64_t PltEntryAddr,
bool isTlsLocalDynamicRel(uint32_t Type) const override;
bool isTlsGlobalDynamicRel(uint32_t Type) const override;
bool isTlsInitialExecRel(uint32_t Type) const override;
- bool isTlsDynRel(uint32_t Type, const SymbolBody &S) const override;
void writeGotPltHeader(uint8_t *Buf) const override;
void writeGotPlt(uint8_t *Buf, uint64_t Plt) const override;
void writePltZero(uint8_t *Buf) const override;
void writePlt(uint8_t *Buf, uint64_t GotEntryAddr, uint64_t PltEntryAddr,
int32_t Index, unsigned RelOff) const override;
uint32_t getTlsGotRel(uint32_t Type) const override;
- bool isTlsDynRel(uint32_t Type, const SymbolBody &S) const override;
bool isRelRelative(uint32_t Type) const override;
bool needsCopyRelImpl(uint32_t Type) const override;
bool needsGot(uint32_t Type, SymbolBody &S) const override;
// Initial-Exec relocs can be relaxed to Local-Exec if the symbol is locally
// defined.
if (isTlsInitialExecRel(Type))
- return !canBePreempted(S);
+ return !canBePreempted(S, Type);
return false;
}
return mayNeedCopy<ELFT>(S) && needsCopyRelImpl(Type);
}
-bool TargetInfo::isTlsDynRel(uint32_t Type, const SymbolBody &S) const {
- return false;
-}
-
bool TargetInfo::isGotRelative(uint32_t Type) const { return false; }
bool TargetInfo::isHintRel(uint32_t Type) const { return false; }
bool TargetInfo::isRelRelative(uint32_t Type) const { return true; }
const SymbolBody &S) const {
if (isGnuIFunc<ELFT>(S))
return Plt_Explicit;
- if (canBePreempted(&S) && needsPltImpl(Type))
+ if (canBePreempted(&S, Type) && needsPltImpl(Type))
return Plt_Explicit;
// This handles a non PIC program call to function in a shared library.
return Type == R_386_TLS_IE || Type == R_386_TLS_GOTIE;
}
-bool X86TargetInfo::isTlsDynRel(uint32_t Type, const SymbolBody &S) const {
- if (Type == R_386_TLS_LE || Type == R_386_TLS_LE_32 ||
- Type == R_386_TLS_GOTIE)
- return Config->Shared;
- if (Type == R_386_TLS_IE)
- return canBePreempted(&S);
- return Type == R_386_TLS_GD;
-}
-
void X86TargetInfo::writePltZero(uint8_t *Buf) const {
// Executable files and shared object files have
// separate procedure linkage tables.
bool X86TargetInfo::needsGot(uint32_t Type, SymbolBody &S) const {
if (S.IsTls && Type == R_386_TLS_GD)
- return Target->canRelaxTls(Type, &S) && canBePreempted(&S);
+ return Target->canRelaxTls(Type, &S) && canBePreempted(&S, Type);
if (Type == R_386_TLS_GOTIE || Type == R_386_TLS_IE)
return !canRelaxTls(Type, &S);
return Type == R_386_GOT32 || needsPlt<ELF32LE>(Type, S);
const SymbolBody *S) const {
switch (Type) {
case R_386_TLS_GD:
- if (canBePreempted(S))
+ if (canBePreempted(S, Type))
relocateTlsGdToIe(Loc, BufEnd, P, SA);
else
relocateTlsGdToLe(Loc, BufEnd, P, SA);
bool X86_64TargetInfo::needsGot(uint32_t Type, SymbolBody &S) const {
if (Type == R_X86_64_TLSGD)
- return Target->canRelaxTls(Type, &S) && canBePreempted(&S);
+ return Target->canRelaxTls(Type, &S) && canBePreempted(&S, Type);
if (Type == R_X86_64_GOTTPOFF)
return !canRelaxTls(Type, &S);
return refersToGotEntry(Type) || needsPlt<ELF64LE>(Type, S);
}
bool X86_64TargetInfo::isTlsLocalDynamicRel(uint32_t Type) const {
- return Type == R_X86_64_DTPOFF32 || Type == R_X86_64_TLSLD;
-}
-
-bool X86_64TargetInfo::isTlsDynRel(uint32_t Type, const SymbolBody &S) const {
- return Type == R_X86_64_GOTTPOFF || Type == R_X86_64_TLSGD;
+ return Type == R_X86_64_DTPOFF32 || Type == R_X86_64_DTPOFF64 ||
+ Type == R_X86_64_TLSLD;
}
bool X86_64TargetInfo::needsPltImpl(uint32_t Type) const {
relocateTlsIeToLe(Loc, BufEnd, P, SA);
return 0;
case R_X86_64_TLSGD: {
- if (canBePreempted(S))
+ if (canBePreempted(S, Type))
relocateTlsGdToIe(Loc, BufEnd, P, SA);
else
relocateTlsGdToLe(Loc, BufEnd, P, SA);
return Type;
}
-bool AArch64TargetInfo::isTlsDynRel(uint32_t Type, const SymbolBody &S) const {
- return Type == R_AARCH64_TLSDESC_ADR_PAGE21 ||
- Type == R_AARCH64_TLSDESC_LD64_LO12_NC ||
- Type == R_AARCH64_TLSDESC_ADD_LO12_NC ||
- Type == R_AARCH64_TLSDESC_CALL ||
- Type == R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21 ||
- Type == R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC;
-}
-
bool AArch64TargetInfo::needsCopyRelImpl(uint32_t Type) const {
switch (Type) {
default:
case R_AARCH64_TLSDESC_LD64_LO12_NC:
case R_AARCH64_TLSDESC_ADD_LO12_NC:
case R_AARCH64_TLSDESC_CALL: {
- if (canBePreempted(S))
+ if (canBePreempted(S, Type))
fatal("Unsupported TLS optimization");
uint64_t X = S ? S->getVA<ELF64LE>() : SA;
relocateTlsGdToLe(Type, Loc, BufEnd, P, X);