mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-12-14 11:39:35 +00:00
ELF: Redefine canBeDefined as a member function of SymbolBody.
We want to make SymbolBody the central place to query symbol information. This patch also renames canBePreempted to isPreemptible because I feel that the latter is slightly better (the former is three words and the latter is two words.) llvm-svn: 263386
This commit is contained in:
parent
22b5d1f901
commit
c4466605d8
@ -209,7 +209,7 @@ static uintX_t getMipsGotVA(const SymbolBody &Body, uintX_t SymVA,
|
||||
AHL += SignExtend64<16>(read32<E>(PairedLoc));
|
||||
return Out<ELFT>::Got->getMipsLocalPageAddr(SymVA + AHL);
|
||||
}
|
||||
if (!canBePreempted(Body))
|
||||
if (!Body.isPreemptible())
|
||||
// For non-local symbols GOT entries should contain their full
|
||||
// addresses. But if such symbol cannot be preempted, we do not
|
||||
// have to put them into the "global" part of GOT and use dynamic
|
||||
@ -274,7 +274,6 @@ void InputSectionBase<ELFT>::relocate(uint8_t *Buf, uint8_t *BufEnd,
|
||||
}
|
||||
|
||||
uintX_t SymVA = Body.getVA<ELFT>(A);
|
||||
bool CBP = canBePreempted(Body);
|
||||
uint8_t *PairedLoc = nullptr;
|
||||
if (Config->EMachine == EM_MIPS)
|
||||
PairedLoc = findMipsPairedReloc(Buf, &RI, Rels.end());
|
||||
@ -288,7 +287,7 @@ void InputSectionBase<ELFT>::relocate(uint8_t *Buf, uint8_t *BufEnd,
|
||||
SymVA = Body.getGotVA<ELFT>() + A;
|
||||
if (Body.IsTls)
|
||||
Type = Target->getTlsGotRel(Type);
|
||||
} else if (Target->isSizeRel(Type) && CBP) {
|
||||
} else if (Target->isSizeRel(Type) && Body.isPreemptible()) {
|
||||
// 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.
|
||||
// If that's the case, we leave the field alone rather than filling it
|
||||
@ -296,7 +295,8 @@ void InputSectionBase<ELFT>::relocate(uint8_t *Buf, uint8_t *BufEnd,
|
||||
continue;
|
||||
} else if (Config->EMachine == EM_MIPS) {
|
||||
SymVA = adjustMipsSymVA<ELFT>(Type, *File, Body, AddrLoc, SymVA) + A;
|
||||
} else if (!Target->needsCopyRel<ELFT>(Type, Body) && CBP) {
|
||||
} else if (!Target->needsCopyRel<ELFT>(Type, Body) &&
|
||||
Body.isPreemptible()) {
|
||||
continue;
|
||||
}
|
||||
uintX_t Size = Body.getSize<ELFT>();
|
||||
|
@ -182,7 +182,7 @@ template <class ELFT> void GotSection<ELFT>::writeTo(uint8_t *Buf) {
|
||||
// for detailed description:
|
||||
// ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf
|
||||
// As the first approach, we can just store addresses for all symbols.
|
||||
if (Config->EMachine != EM_MIPS && canBePreempted(*B))
|
||||
if (Config->EMachine != EM_MIPS && B->isPreemptible())
|
||||
continue; // The dynamic linker will take care of it.
|
||||
uintX_t VA = B->getVA<ELFT>();
|
||||
write<uintX_t, ELFT::TargetEndianness, sizeof(uintX_t)>(Entry, VA);
|
||||
@ -882,37 +882,6 @@ template <class ELFT> void OutputSection<ELFT>::sortCtorsDtors() {
|
||||
reassignOffsets();
|
||||
}
|
||||
|
||||
// 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.
|
||||
bool elf::canBePreempted(const SymbolBody &Body) {
|
||||
if (Body.isLocal())
|
||||
return false;
|
||||
|
||||
if (Body.isShared())
|
||||
return true;
|
||||
|
||||
if (Body.isUndefined()) {
|
||||
if (!Body.isWeak())
|
||||
return true;
|
||||
|
||||
// Ideally the static linker should see a definition for every symbol, but
|
||||
// shared object are normally allowed to have undefined references that the
|
||||
// static linker never sees a definition for.
|
||||
if (Config->Shared)
|
||||
return true;
|
||||
|
||||
// Otherwise, just resolve to 0.
|
||||
return false;
|
||||
}
|
||||
if (!Config->Shared)
|
||||
return false;
|
||||
if (Body.getVisibility() != STV_DEFAULT)
|
||||
return false;
|
||||
if (Config->Bsymbolic || (Config->BsymbolicFunctions && Body.IsFunc))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static void fill(uint8_t *Buf, size_t Size, ArrayRef<uint8_t> A) {
|
||||
size_t I = 0;
|
||||
for (; I + A.size() < Size; I += A.size())
|
||||
|
@ -47,8 +47,6 @@ getAddend(const typename llvm::object::ELFFile<ELFT>::Elf_Rela &Rel) {
|
||||
return Rel.r_addend;
|
||||
}
|
||||
|
||||
bool canBePreempted(const SymbolBody &Body);
|
||||
|
||||
bool isValidCIdentifier(StringRef S);
|
||||
|
||||
// This represents a section in an output file.
|
||||
|
@ -81,6 +81,38 @@ getSymVA(const SymbolBody &Body, typename ELFFile<ELFT>::uintX_t &Addend) {
|
||||
llvm_unreachable("invalid symbol kind");
|
||||
}
|
||||
|
||||
// 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.
|
||||
bool SymbolBody::isPreemptible() const {
|
||||
if (isLocal())
|
||||
return false;
|
||||
|
||||
if (isShared())
|
||||
return true;
|
||||
|
||||
if (isUndefined()) {
|
||||
if (!isWeak())
|
||||
return true;
|
||||
|
||||
// Ideally the static linker should see a definition for every symbol, but
|
||||
// shared object are normally allowed to have undefined references that the
|
||||
// static linker never sees a definition for.
|
||||
if (Config->Shared)
|
||||
return true;
|
||||
|
||||
// Otherwise, just resolve to 0.
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!Config->Shared)
|
||||
return false;
|
||||
if (getVisibility() != STV_DEFAULT)
|
||||
return false;
|
||||
if (Config->Bsymbolic || (Config->BsymbolicFunctions && IsFunc))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class ELFT> bool SymbolBody::isGnuIfunc() const {
|
||||
if (auto *D = dyn_cast<DefinedElf<ELFT>>(this))
|
||||
return D->Sym.getType() == STT_GNU_IFUNC;
|
||||
|
@ -75,7 +75,7 @@ public:
|
||||
bool isShared() const { return SymbolKind == SharedKind; }
|
||||
bool isLocal() const { return IsLocal; }
|
||||
bool isUsedInRegularObj() const { return IsUsedInRegularObj; }
|
||||
|
||||
bool isPreemptible() const;
|
||||
template <class ELFT> bool isGnuIfunc() const;
|
||||
|
||||
// Returns the symbol name.
|
||||
|
@ -272,7 +272,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
|
||||
// defined.
|
||||
if (isTlsInitialExecRel(Type))
|
||||
return !canBePreempted(*S);
|
||||
return !S->isPreemptible();
|
||||
|
||||
return false;
|
||||
}
|
||||
@ -311,7 +311,7 @@ TargetInfo::PltNeed TargetInfo::needsPlt(uint32_t Type,
|
||||
const SymbolBody &S) const {
|
||||
if (S.isGnuIfunc<ELFT>())
|
||||
return Plt_Explicit;
|
||||
if (canBePreempted(S) && needsPltImpl(Type))
|
||||
if (S.isPreemptible() && needsPltImpl(Type))
|
||||
return Plt_Explicit;
|
||||
|
||||
// This handles a non PIC program call to function in a shared library.
|
||||
@ -464,7 +464,7 @@ bool X86TargetInfo::needsCopyRelImpl(uint32_t Type) const {
|
||||
|
||||
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) && S.isPreemptible();
|
||||
if (Type == R_386_TLS_GOTIE || Type == R_386_TLS_IE)
|
||||
return !canRelaxTls(Type, &S);
|
||||
return Type == R_386_GOT32 || needsPlt<ELF32LE>(Type, S);
|
||||
@ -542,7 +542,7 @@ size_t X86TargetInfo::relaxTls(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type,
|
||||
const SymbolBody &S) const {
|
||||
switch (Type) {
|
||||
case R_386_TLS_GD:
|
||||
if (canBePreempted(S))
|
||||
if (S.isPreemptible())
|
||||
relocateTlsGdToIe(Loc, BufEnd, P, SA);
|
||||
else
|
||||
relocateTlsGdToLe(Loc, BufEnd, P, SA);
|
||||
@ -726,7 +726,7 @@ bool X86_64TargetInfo::refersToGotEntry(uint32_t Type) const {
|
||||
|
||||
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) && S.isPreemptible();
|
||||
if (Type == R_X86_64_GOTTPOFF)
|
||||
return !canRelaxTls(Type, &S);
|
||||
return refersToGotEntry(Type) || needsPlt<ELF64LE>(Type, S);
|
||||
@ -896,7 +896,7 @@ size_t X86_64TargetInfo::relaxTls(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type,
|
||||
relocateTlsIeToLe(Loc, BufEnd, P, SA);
|
||||
return 0;
|
||||
case R_X86_64_TLSGD: {
|
||||
if (canBePreempted(S))
|
||||
if (S.isPreemptible())
|
||||
relocateTlsGdToIe(Loc, BufEnd, P, SA);
|
||||
else
|
||||
relocateTlsGdToLe(Loc, BufEnd, P, SA);
|
||||
@ -1463,7 +1463,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_ADD_LO12_NC:
|
||||
case R_AARCH64_TLSDESC_CALL: {
|
||||
if (canBePreempted(S))
|
||||
if (S.isPreemptible())
|
||||
fatal("unsupported TLS optimization");
|
||||
uint64_t X = S.getVA<ELF64LE>();
|
||||
relocateTlsGdToLe(Type, Loc, BufEnd, P, X);
|
||||
|
@ -290,7 +290,7 @@ static bool handleTlsRelocation(uint32_t Type, SymbolBody &Body,
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (!canBePreempted(Body))
|
||||
if (!Body.isPreemptible())
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -332,7 +332,7 @@ void Writer<ELFT>::scanRelocs(InputSectionBase<ELFT> &C,
|
||||
if (auto *S = dyn_cast<SharedSymbol<ELFT>>(&Body))
|
||||
S->File->IsUsed = true;
|
||||
|
||||
bool CBP = canBePreempted(Body);
|
||||
bool Preemptible = Body.isPreemptible();
|
||||
if (handleTlsRelocation<ELFT>(Type, Body, C, RI))
|
||||
continue;
|
||||
|
||||
@ -341,7 +341,7 @@ void Writer<ELFT>::scanRelocs(InputSectionBase<ELFT> &C,
|
||||
&Body, getAddend<ELFT>(RI)});
|
||||
|
||||
// MIPS has a special rule to create GOTs for local symbols.
|
||||
if (Config->EMachine == EM_MIPS && !CBP &&
|
||||
if (Config->EMachine == EM_MIPS && !Preemptible &&
|
||||
(Type == R_MIPS_GOT16 || Type == R_MIPS_CALL16)) {
|
||||
// FIXME (simon): Do not add so many redundant entries.
|
||||
Out<ELFT>::Got->addMipsLocalEntry();
|
||||
@ -371,13 +371,13 @@ void Writer<ELFT>::scanRelocs(InputSectionBase<ELFT> &C,
|
||||
if (Target->UseLazyBinding) {
|
||||
Out<ELFT>::GotPlt->addEntry(Body);
|
||||
Out<ELFT>::RelaPlt->addReloc(
|
||||
{CBP ? Target->PltRel : Target->IRelativeRel,
|
||||
DynamicReloc<ELFT>::Off_GotPlt, !CBP, &Body});
|
||||
{Preemptible ? Target->PltRel : Target->IRelativeRel,
|
||||
DynamicReloc<ELFT>::Off_GotPlt, !Preemptible, &Body});
|
||||
} else {
|
||||
Out<ELFT>::Got->addEntry(Body);
|
||||
Out<ELFT>::RelaDyn->addReloc(
|
||||
{CBP ? Target->PltRel : Target->IRelativeRel,
|
||||
DynamicReloc<ELFT>::Off_Got, !CBP, &Body});
|
||||
{Preemptible ? Target->PltRel : Target->IRelativeRel,
|
||||
DynamicReloc<ELFT>::Off_Got, !Preemptible, &Body});
|
||||
}
|
||||
continue;
|
||||
}
|
||||
@ -424,16 +424,16 @@ void Writer<ELFT>::scanRelocs(InputSectionBase<ELFT> &C,
|
||||
|
||||
bool Dynrel = Config->Shared && !Target->isRelRelative(Type) &&
|
||||
!Target->isSizeRel(Type);
|
||||
if (CBP || Dynrel) {
|
||||
if (Preemptible || Dynrel) {
|
||||
uint32_t DynType;
|
||||
if (Body.IsTls)
|
||||
DynType = Target->TlsGotRel;
|
||||
else if (CBP)
|
||||
else if (Preemptible)
|
||||
DynType = Target->GotRel;
|
||||
else
|
||||
DynType = Target->RelativeRel;
|
||||
Out<ELFT>::RelaDyn->addReloc(
|
||||
{DynType, DynamicReloc<ELFT>::Off_Got, !CBP, &Body});
|
||||
{DynType, DynamicReloc<ELFT>::Off_Got, !Preemptible, &Body});
|
||||
}
|
||||
continue;
|
||||
}
|
||||
@ -456,7 +456,7 @@ void Writer<ELFT>::scanRelocs(InputSectionBase<ELFT> &C,
|
||||
continue;
|
||||
}
|
||||
|
||||
if (CBP) {
|
||||
if (Preemptible) {
|
||||
// We don't know anything about the finaly symbol. Just ask the dynamic
|
||||
// linker to handle the relocation for us.
|
||||
Out<ELFT>::RelaDyn->addReloc({Target->getDynRel(Type), &C, RI.r_offset,
|
||||
|
Loading…
Reference in New Issue
Block a user