summaryrefslogtreecommitdiffstats
path: root/lld/ELF/Writer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lld/ELF/Writer.cpp')
-rw-r--r--lld/ELF/Writer.cpp36
1 files changed, 36 insertions, 0 deletions
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