mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-01-05 15:42:24 +00:00
Delete isTlsDynRel.
It was a badly specified hack for when a tls relocation should be propagated to the dynamic relocation table. This replaces it with a not as bad hack of saying that a local dynamic tls relocation is never preempted. I will try to remove even that second hack in the next patch. llvm-svn: 262955
This commit is contained in:
parent
715b04eda6
commit
1f04c44885
@ -271,7 +271,7 @@ void InputSectionBase<ELFT>::relocate(uint8_t *Buf, uint8_t *BufEnd,
|
|||||||
}
|
}
|
||||||
|
|
||||||
uintX_t SymVA = Body->getVA<ELFT>();
|
uintX_t SymVA = Body->getVA<ELFT>();
|
||||||
bool CBP = canBePreempted(Body);
|
bool CBP = canBePreempted(Body, Type);
|
||||||
if (Target->needsPlt<ELFT>(Type, *Body)) {
|
if (Target->needsPlt<ELFT>(Type, *Body)) {
|
||||||
SymVA = Body->getPltVA<ELFT>();
|
SymVA = Body->getPltVA<ELFT>();
|
||||||
} else if (Target->needsGot(Type, *Body)) {
|
} else if (Target->needsGot(Type, *Body)) {
|
||||||
@ -284,11 +284,6 @@ void InputSectionBase<ELFT>::relocate(uint8_t *Buf, uint8_t *BufEnd,
|
|||||||
SymVA = Body->getGotVA<ELFT>();
|
SymVA = Body->getGotVA<ELFT>();
|
||||||
if (Body->IsTls)
|
if (Body->IsTls)
|
||||||
Type = Target->getTlsGotRel(Type);
|
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) {
|
} else if (Target->isSizeRel(Type) && CBP) {
|
||||||
// A SIZE relocation is supposed to set a symbol size, but if a symbol
|
// 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.
|
// can be preempted, the size at runtime may be different than link time.
|
||||||
@ -302,6 +297,8 @@ void InputSectionBase<ELFT>::relocate(uint8_t *Buf, uint8_t *BufEnd,
|
|||||||
SymVA = getMipsGpAddr<ELFT>() - AddrLoc + 4;
|
SymVA = getMipsGpAddr<ELFT>() - AddrLoc + 4;
|
||||||
else if (Body == Config->MipsLocalGp)
|
else if (Body == Config->MipsLocalGp)
|
||||||
SymVA = getMipsGpAddr<ELFT>();
|
SymVA = getMipsGpAddr<ELFT>();
|
||||||
|
} else if (!Target->needsCopyRel<ELFT>(Type, *Body) && CBP) {
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
uintX_t Size = Body->getSize<ELFT>();
|
uintX_t Size = Body->getSize<ELFT>();
|
||||||
Target->relocateOne(BufLoc, BufEnd, Type, AddrLoc, SymVA + A, Size + A,
|
Target->relocateOne(BufLoc, BufEnd, Type, AddrLoc, SymVA + A, Size + A,
|
||||||
|
@ -176,7 +176,7 @@ template <class ELFT> void GotSection<ELFT>::writeTo(uint8_t *Buf) {
|
|||||||
// for detailed description:
|
// for detailed description:
|
||||||
// ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf
|
// ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf
|
||||||
// As the first approach, we can just store addresses for all symbols.
|
// As the first approach, we can just store addresses for all symbols.
|
||||||
if (Config->EMachine != EM_MIPS && canBePreempted(B))
|
if (Config->EMachine != EM_MIPS && canBePreempted(B, 0))
|
||||||
continue; // The dynamic linker will take care of it.
|
continue; // The dynamic linker will take care of it.
|
||||||
uintX_t VA = B->getVA<ELFT>();
|
uintX_t VA = B->getVA<ELFT>();
|
||||||
write<uintX_t, ELFT::TargetEndianness, sizeof(uintX_t)>(Entry, VA);
|
write<uintX_t, ELFT::TargetEndianness, sizeof(uintX_t)>(Entry, VA);
|
||||||
@ -932,9 +932,16 @@ elf::getLocalRelTarget(const ObjectFile<ELFT> &File,
|
|||||||
|
|
||||||
// Returns true if a symbol can be replaced at load-time by a symbol
|
// Returns true if a symbol can be replaced at load-time by a symbol
|
||||||
// with the same name defined in other ELF executable or DSO.
|
// with the same name defined in other ELF executable or DSO.
|
||||||
bool elf::canBePreempted(const SymbolBody *Body) {
|
bool elf::canBePreempted(const SymbolBody *Body, unsigned Type) {
|
||||||
if (!Body)
|
if (!Body)
|
||||||
return false; // Body is a local symbol.
|
return false; // Body is a local symbol.
|
||||||
|
|
||||||
|
// FIXME: Both gold and bfd consider that a local dynamic tls relocation to
|
||||||
|
// a symbol will not be preempted. Is that actually relevant? The compiler
|
||||||
|
// should not use it if the symbol can be preempted.
|
||||||
|
if (Target->isTlsLocalDynamicRel(Type))
|
||||||
|
return false;
|
||||||
|
|
||||||
if (Body->isShared())
|
if (Body->isShared())
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
@ -53,7 +53,7 @@ getLocalRelTarget(const ObjectFile<ELFT> &File,
|
|||||||
const llvm::object::Elf_Rel_Impl<ELFT, IsRela> &Rel,
|
const llvm::object::Elf_Rel_Impl<ELFT, IsRela> &Rel,
|
||||||
typename llvm::object::ELFFile<ELFT>::uintX_t Addend);
|
typename llvm::object::ELFFile<ELFT>::uintX_t Addend);
|
||||||
|
|
||||||
bool canBePreempted(const SymbolBody *Body);
|
bool canBePreempted(const SymbolBody *Body, unsigned Type);
|
||||||
|
|
||||||
bool isValidCIdentifier(StringRef S);
|
bool isValidCIdentifier(StringRef S);
|
||||||
|
|
||||||
|
@ -87,7 +87,6 @@ public:
|
|||||||
bool isTlsLocalDynamicRel(uint32_t Type) const override;
|
bool isTlsLocalDynamicRel(uint32_t Type) const override;
|
||||||
bool isTlsGlobalDynamicRel(uint32_t Type) const override;
|
bool isTlsGlobalDynamicRel(uint32_t Type) const override;
|
||||||
bool isTlsInitialExecRel(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 writeGotPlt(uint8_t *Buf, uint64_t Plt) const override;
|
||||||
void writePltZero(uint8_t *Buf) const override;
|
void writePltZero(uint8_t *Buf) const override;
|
||||||
void writePlt(uint8_t *Buf, uint64_t GotEntryAddr, uint64_t PltEntryAddr,
|
void writePlt(uint8_t *Buf, uint64_t GotEntryAddr, uint64_t PltEntryAddr,
|
||||||
@ -123,7 +122,6 @@ public:
|
|||||||
bool isTlsLocalDynamicRel(uint32_t Type) const override;
|
bool isTlsLocalDynamicRel(uint32_t Type) const override;
|
||||||
bool isTlsGlobalDynamicRel(uint32_t Type) const override;
|
bool isTlsGlobalDynamicRel(uint32_t Type) const override;
|
||||||
bool isTlsInitialExecRel(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 writeGotPltHeader(uint8_t *Buf) const override;
|
||||||
void writeGotPlt(uint8_t *Buf, uint64_t Plt) const override;
|
void writeGotPlt(uint8_t *Buf, uint64_t Plt) const override;
|
||||||
void writePltZero(uint8_t *Buf) const override;
|
void writePltZero(uint8_t *Buf) const override;
|
||||||
@ -185,7 +183,6 @@ public:
|
|||||||
void writePlt(uint8_t *Buf, uint64_t GotEntryAddr, uint64_t PltEntryAddr,
|
void writePlt(uint8_t *Buf, uint64_t GotEntryAddr, uint64_t PltEntryAddr,
|
||||||
int32_t Index, unsigned RelOff) const override;
|
int32_t Index, unsigned RelOff) const override;
|
||||||
uint32_t getTlsGotRel(uint32_t Type) 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 isRelRelative(uint32_t Type) const override;
|
||||||
bool needsCopyRelImpl(uint32_t Type) const override;
|
bool needsCopyRelImpl(uint32_t Type) const override;
|
||||||
bool needsGot(uint32_t Type, SymbolBody &S) const override;
|
bool needsGot(uint32_t Type, SymbolBody &S) const override;
|
||||||
@ -281,7 +278,7 @@ bool TargetInfo::canRelaxTls(uint32_t Type, const SymbolBody *S) const {
|
|||||||
// Initial-Exec relocs can be relaxed to Local-Exec if the symbol is locally
|
// Initial-Exec relocs can be relaxed to Local-Exec if the symbol is locally
|
||||||
// defined.
|
// defined.
|
||||||
if (isTlsInitialExecRel(Type))
|
if (isTlsInitialExecRel(Type))
|
||||||
return !canBePreempted(S);
|
return !canBePreempted(S, Type);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -304,10 +301,6 @@ bool TargetInfo::needsCopyRel(uint32_t Type, const SymbolBody &S) const {
|
|||||||
return mayNeedCopy<ELFT>(S) && needsCopyRelImpl(Type);
|
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::isGotRelative(uint32_t Type) const { return false; }
|
||||||
bool TargetInfo::isHintRel(uint32_t Type) const { return false; }
|
bool TargetInfo::isHintRel(uint32_t Type) const { return false; }
|
||||||
bool TargetInfo::isRelRelative(uint32_t Type) const { return true; }
|
bool TargetInfo::isRelRelative(uint32_t Type) const { return true; }
|
||||||
@ -324,7 +317,7 @@ TargetInfo::PltNeed TargetInfo::needsPlt(uint32_t Type,
|
|||||||
const SymbolBody &S) const {
|
const SymbolBody &S) const {
|
||||||
if (isGnuIFunc<ELFT>(S))
|
if (isGnuIFunc<ELFT>(S))
|
||||||
return Plt_Explicit;
|
return Plt_Explicit;
|
||||||
if (canBePreempted(&S) && needsPltImpl(Type))
|
if (canBePreempted(&S, Type) && needsPltImpl(Type))
|
||||||
return Plt_Explicit;
|
return Plt_Explicit;
|
||||||
|
|
||||||
// This handles a non PIC program call to function in a shared library.
|
// This handles a non PIC program call to function in a shared library.
|
||||||
@ -428,15 +421,6 @@ bool X86TargetInfo::isTlsInitialExecRel(uint32_t Type) const {
|
|||||||
return Type == R_386_TLS_IE || Type == R_386_TLS_GOTIE;
|
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 {
|
void X86TargetInfo::writePltZero(uint8_t *Buf) const {
|
||||||
// Executable files and shared object files have
|
// Executable files and shared object files have
|
||||||
// separate procedure linkage tables.
|
// separate procedure linkage tables.
|
||||||
@ -486,7 +470,7 @@ bool X86TargetInfo::needsCopyRelImpl(uint32_t Type) const {
|
|||||||
|
|
||||||
bool X86TargetInfo::needsGot(uint32_t Type, SymbolBody &S) const {
|
bool X86TargetInfo::needsGot(uint32_t Type, SymbolBody &S) const {
|
||||||
if (S.IsTls && Type == R_386_TLS_GD)
|
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)
|
if (Type == R_386_TLS_GOTIE || Type == R_386_TLS_IE)
|
||||||
return !canRelaxTls(Type, &S);
|
return !canRelaxTls(Type, &S);
|
||||||
return Type == R_386_GOT32 || needsPlt<ELF32LE>(Type, S);
|
return Type == R_386_GOT32 || needsPlt<ELF32LE>(Type, S);
|
||||||
@ -564,7 +548,7 @@ size_t X86TargetInfo::relaxTls(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type,
|
|||||||
const SymbolBody *S) const {
|
const SymbolBody *S) const {
|
||||||
switch (Type) {
|
switch (Type) {
|
||||||
case R_386_TLS_GD:
|
case R_386_TLS_GD:
|
||||||
if (canBePreempted(S))
|
if (canBePreempted(S, Type))
|
||||||
relocateTlsGdToIe(Loc, BufEnd, P, SA);
|
relocateTlsGdToIe(Loc, BufEnd, P, SA);
|
||||||
else
|
else
|
||||||
relocateTlsGdToLe(Loc, BufEnd, P, SA);
|
relocateTlsGdToLe(Loc, BufEnd, P, SA);
|
||||||
@ -748,7 +732,7 @@ bool X86_64TargetInfo::refersToGotEntry(uint32_t Type) const {
|
|||||||
|
|
||||||
bool X86_64TargetInfo::needsGot(uint32_t Type, SymbolBody &S) const {
|
bool X86_64TargetInfo::needsGot(uint32_t Type, SymbolBody &S) const {
|
||||||
if (Type == R_X86_64_TLSGD)
|
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)
|
if (Type == R_X86_64_GOTTPOFF)
|
||||||
return !canRelaxTls(Type, &S);
|
return !canRelaxTls(Type, &S);
|
||||||
return refersToGotEntry(Type) || needsPlt<ELF64LE>(Type, S);
|
return refersToGotEntry(Type) || needsPlt<ELF64LE>(Type, S);
|
||||||
@ -774,11 +758,8 @@ bool X86_64TargetInfo::pointsToLocalDynamicGotEntry(uint32_t Type) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool X86_64TargetInfo::isTlsLocalDynamicRel(uint32_t Type) const {
|
bool X86_64TargetInfo::isTlsLocalDynamicRel(uint32_t Type) const {
|
||||||
return Type == R_X86_64_DTPOFF32 || Type == R_X86_64_TLSLD;
|
return Type == R_X86_64_DTPOFF32 || Type == R_X86_64_DTPOFF64 ||
|
||||||
}
|
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool X86_64TargetInfo::needsPltImpl(uint32_t Type) const {
|
bool X86_64TargetInfo::needsPltImpl(uint32_t Type) const {
|
||||||
@ -918,7 +899,7 @@ size_t X86_64TargetInfo::relaxTls(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type,
|
|||||||
relocateTlsIeToLe(Loc, BufEnd, P, SA);
|
relocateTlsIeToLe(Loc, BufEnd, P, SA);
|
||||||
return 0;
|
return 0;
|
||||||
case R_X86_64_TLSGD: {
|
case R_X86_64_TLSGD: {
|
||||||
if (canBePreempted(S))
|
if (canBePreempted(S, Type))
|
||||||
relocateTlsGdToIe(Loc, BufEnd, P, SA);
|
relocateTlsGdToIe(Loc, BufEnd, P, SA);
|
||||||
else
|
else
|
||||||
relocateTlsGdToLe(Loc, BufEnd, P, SA);
|
relocateTlsGdToLe(Loc, BufEnd, P, SA);
|
||||||
@ -1309,15 +1290,6 @@ uint32_t AArch64TargetInfo::getTlsGotRel(uint32_t Type) const {
|
|||||||
return Type;
|
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 {
|
bool AArch64TargetInfo::needsCopyRelImpl(uint32_t Type) const {
|
||||||
switch (Type) {
|
switch (Type) {
|
||||||
default:
|
default:
|
||||||
@ -1494,7 +1466,7 @@ size_t AArch64TargetInfo::relaxTls(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type,
|
|||||||
case R_AARCH64_TLSDESC_LD64_LO12_NC:
|
case R_AARCH64_TLSDESC_LD64_LO12_NC:
|
||||||
case R_AARCH64_TLSDESC_ADD_LO12_NC:
|
case R_AARCH64_TLSDESC_ADD_LO12_NC:
|
||||||
case R_AARCH64_TLSDESC_CALL: {
|
case R_AARCH64_TLSDESC_CALL: {
|
||||||
if (canBePreempted(S))
|
if (canBePreempted(S, Type))
|
||||||
fatal("Unsupported TLS optimization");
|
fatal("Unsupported TLS optimization");
|
||||||
uint64_t X = S ? S->getVA<ELF64LE>() : SA;
|
uint64_t X = S ? S->getVA<ELF64LE>() : SA;
|
||||||
relocateTlsGdToLe(Type, Loc, BufEnd, P, X);
|
relocateTlsGdToLe(Type, Loc, BufEnd, P, X);
|
||||||
|
@ -27,7 +27,6 @@ public:
|
|||||||
virtual bool isTlsLocalDynamicRel(uint32_t Type) const;
|
virtual bool isTlsLocalDynamicRel(uint32_t Type) const;
|
||||||
virtual bool isTlsGlobalDynamicRel(uint32_t Type) const;
|
virtual bool isTlsGlobalDynamicRel(uint32_t Type) const;
|
||||||
virtual uint32_t getDynRel(uint32_t Type) const { return Type; }
|
virtual uint32_t getDynRel(uint32_t Type) const { return Type; }
|
||||||
virtual bool isTlsDynRel(uint32_t Type, const SymbolBody &S) const;
|
|
||||||
virtual uint32_t getTlsGotRel(uint32_t Type) const { return TlsGotRel; }
|
virtual uint32_t getTlsGotRel(uint32_t Type) const { return TlsGotRel; }
|
||||||
virtual void writeGotHeader(uint8_t *Buf) const {}
|
virtual void writeGotHeader(uint8_t *Buf) const {}
|
||||||
virtual void writeGotPltHeader(uint8_t *Buf) const {}
|
virtual void writeGotPltHeader(uint8_t *Buf) const {}
|
||||||
|
@ -281,10 +281,10 @@ static bool handleTlsRelocation(uint32_t Type, SymbolBody *Body,
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (!canBePreempted(Body))
|
if (!canBePreempted(Body, Type))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return !Target->isTlsDynRel(Type, *Body);
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The reason we have to do this early scan is as follows
|
// The reason we have to do this early scan is as follows
|
||||||
@ -327,7 +327,7 @@ void Writer<ELFT>::scanRelocs(
|
|||||||
if (Body)
|
if (Body)
|
||||||
Body = Body->repl();
|
Body = Body->repl();
|
||||||
|
|
||||||
bool CBP = canBePreempted(Body);
|
bool CBP = canBePreempted(Body, Type);
|
||||||
if (handleTlsRelocation<ELFT>(Type, Body, C, RI))
|
if (handleTlsRelocation<ELFT>(Type, Body, C, RI))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
# CHECK: Disassembly of section .text:
|
# CHECK: Disassembly of section .text:
|
||||||
# CHECK-NEXT: _start
|
# CHECK-NEXT: _start
|
||||||
# CHECK-NEXT: 11000: e8 fb ef fe ff callq -69637
|
# CHECK-NEXT: 11000: e8 00 00 00 00 callq 0
|
||||||
|
|
||||||
# next code will not link without noinhibit-exec flag
|
# next code will not link without noinhibit-exec flag
|
||||||
# because of undefined symbol _bar
|
# because of undefined symbol _bar
|
||||||
|
Loading…
Reference in New Issue
Block a user