summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lld/ELF/Relocations.cpp4
-rw-r--r--lld/ELF/Symbols.cpp38
-rw-r--r--lld/ELF/Symbols.h4
-rw-r--r--lld/ELF/Writer.cpp36
4 files changed, 44 insertions, 38 deletions
diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp
index c22f0d8e436..f9cdb405c70 100644
--- a/lld/ELF/Relocations.cpp
+++ b/lld/ELF/Relocations.cpp
@@ -149,7 +149,7 @@ static unsigned handleARMTlsRelocation(uint32_t Type, SymbolBody &Body,
InputSectionBase &C, uint64_t Offset,
int64_t Addend, RelExpr Expr) {
// The Dynamic TLS Module Index Relocation for a symbol defined in an
- // executable is always 1. If the target Symbol is not preemtible then
+ // executable is always 1. If the target Symbol is not preemptible then
// we know the offset into the TLS block at static link time.
bool NeedDynId = Body.isPreemptible() || Config->Shared;
bool NeedDynOff = Body.isPreemptible();
@@ -527,6 +527,7 @@ template <class ELFT> static void addCopyRelSymbol(SharedSymbol *SS) {
// interpose any aliases.
for (SharedSymbol *Sym : getSymbolsAt<ELFT>(SS)) {
Sym->CopyRelSec = Sec;
+ Sym->IsPreemptible = false;
Sym->CopyRelSecOff = Off;
Sym->symbol()->IsUsedInRegularObj = true;
}
@@ -612,6 +613,7 @@ static RelExpr adjustExpr(SymbolBody &Body, RelExpr Expr, uint32_t Type,
// plt. That is identified by special relocation types (R_X86_64_JUMP_SLOT,
// R_386_JMP_SLOT, etc).
Body.NeedsPltAddr = true;
+ Body.IsPreemptible = false;
return toPlt(Expr);
}
diff --git a/lld/ELF/Symbols.cpp b/lld/ELF/Symbols.cpp
index 3d99ef3baaa..5f1e69b2601 100644
--- a/lld/ELF/Symbols.cpp
+++ b/lld/ELF/Symbols.cpp
@@ -127,7 +127,8 @@ SymbolBody::SymbolBody(Kind K, StringRefZ Name, bool IsLocal, uint8_t StOther,
uint8_t Type)
: SymbolKind(K), NeedsPltAddr(false), IsLocal(IsLocal),
IsInGlobalMipsGot(false), Is32BitMipsGot(false), IsInIplt(false),
- IsInIgot(false), Type(Type), StOther(StOther), Name(Name) {}
+ IsInIgot(false), IsPreemptible(false), Type(Type), StOther(StOther),
+ Name(Name) {}
InputFile *SymbolBody::getFile() const {
if (isLocal())
@@ -135,41 +136,6 @@ InputFile *SymbolBody::getFile() const {
return symbol()->File;
}
-// 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;
-
- // Shared symbols resolve to the definition in the DSO. The exceptions are
- // symbols with copy relocations (which resolve to .bss) or preempt plt
- // entries (which resolve to that plt entry).
- if (auto *SS = dyn_cast<SharedSymbol>(this))
- return !SS->CopyRelSec && !NeedsPltAddr;
-
- // Only symbols that appear in dynsym can be preempted.
- if (!symbol()->includeInDynsym())
- return false;
-
- // Only default visibility symbols can be preempted.
- if (symbol()->Visibility != STV_DEFAULT)
- return false;
-
- // Undefined symbols in non-DSOs are usually just an error, so it
- // doesn't matter whether we return true or false here. However, if
- // -unresolved-symbols=ignore-all is specified, undefined symbols in
- // executables are automatically exported so that the runtime linker
- // can try to resolve them. In that case, they is preemptible. So, we
- // return true for an undefined symbol in case the option is specified.
- if (!Config->Shared)
- return isUndefined();
-
- // -Bsymbolic means that definitions are not preempted.
- if (Config->Bsymbolic || (Config->BsymbolicFunctions && isFunc()))
- return !isDefined();
- return true;
-}
-
// Overwrites all attributes with Other's so that this symbol becomes
// an alias to Other. This is useful for handling some options such as
// --wrap.
diff --git a/lld/ELF/Symbols.h b/lld/ELF/Symbols.h
index 0e6bd406d1f..02855c5ff9f 100644
--- a/lld/ELF/Symbols.h
+++ b/lld/ELF/Symbols.h
@@ -70,7 +70,7 @@ public:
}
bool isLocal() const { return IsLocal; }
InputFile *getFile() const;
- bool isPreemptible() const;
+ bool isPreemptible() const { return IsPreemptible; }
StringRef getName() const { return Name; }
uint8_t getVisibility() const { return StOther & 0x3; }
void parseSymbolVersion();
@@ -121,6 +121,8 @@ public:
// True if this symbol is in the Igot sub-section of the .got.plt or .got.
unsigned IsInIgot : 1;
+ unsigned IsPreemptible : 1;
+
// The following fields have the same meaning as the ELF symbol attributes.
uint8_t Type; // symbol type
uint8_t StOther; // st_other field value
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index e82be4f86f2..83d5739ff0e 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -1149,6 +1149,39 @@ static void removeUnusedSyntheticSections() {
}
}
+// 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.
+static bool computeIsPreemptible(const SymbolBody &B) {
+ assert(!B.isLocal());
+ // Shared symbols resolve to the definition in the DSO. The exceptions are
+ // symbols with copy relocations (which resolve to .bss) or preempt plt
+ // entries (which resolve to that plt entry).
+ if (auto *SS = dyn_cast<SharedSymbol>(&B))
+ return !SS->CopyRelSec && !SS->NeedsPltAddr;
+
+ // Only symbols that appear in dynsym can be preempted.
+ if (!B.symbol()->includeInDynsym())
+ return false;
+
+ // Only default visibility symbols can be preempted.
+ if (B.symbol()->Visibility != STV_DEFAULT)
+ return false;
+
+ // Undefined symbols in non-DSOs are usually just an error, so it
+ // doesn't matter whether we return true or false here. However, if
+ // -unresolved-symbols=ignore-all is specified, undefined symbols in
+ // executables are automatically exported so that the runtime linker
+ // can try to resolve them. In that case, they is preemptible. So, we
+ // return true for an undefined symbol in case the option is specified.
+ if (!Config->Shared)
+ return B.isUndefined();
+
+ // -Bsymbolic means that definitions are not preempted.
+ if (Config->Bsymbolic || (Config->BsymbolicFunctions && B.isFunc()))
+ return !B.isDefined();
+ return true;
+}
+
// Create output section objects and add them to OutputSections.
template <class ELFT> void Writer<ELFT>::finalizeSections() {
Out::DebugInfo = findSection(".debug_info");
@@ -1182,6 +1215,9 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
applySynthetic({In<ELFT>::EhFrame},
[](SyntheticSection *SS) { SS->finalizeContents(); });
+ for (Symbol *S : Symtab->getSymbols())
+ S->body()->IsPreemptible = computeIsPreemptible(*S->body());
+
// Scan relocations. This must be done after every symbol is declared so that
// we can correctly decide if a dynamic relocation is needed.
forEachRelSec(scanRelocations<ELFT>);
OpenPOWER on IntegriCloud