summaryrefslogtreecommitdiff
path: root/lld/ELF/Symbols.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lld/ELF/Symbols.cpp')
-rw-r--r--lld/ELF/Symbols.cpp75
1 files changed, 54 insertions, 21 deletions
diff --git a/lld/ELF/Symbols.cpp b/lld/ELF/Symbols.cpp
index c0cba21cfe8d..f0f6121009a5 100644
--- a/lld/ELF/Symbols.cpp
+++ b/lld/ELF/Symbols.cpp
@@ -162,15 +162,12 @@ uint64_t Symbol::getGotPltOffset() const {
return (pltIndex + target->gotPltHeaderEntriesNum) * config->wordsize;
}
-uint64_t Symbol::getPPC64LongBranchOffset() const {
- assert(ppc64BranchltIndex != 0xffff);
- return ppc64BranchltIndex * config->wordsize;
-}
-
uint64_t Symbol::getPltVA() const {
- PltSection *plt = isInIplt ? in.iplt : in.plt;
- uint64_t outVA =
- plt->getVA() + plt->headerSize + pltIndex * target->pltEntrySize;
+ uint64_t outVA = isInIplt
+ ? in.iplt->getVA() + pltIndex * target->ipltEntrySize
+ : in.plt->getVA() + in.plt->headerSize +
+ pltIndex * target->pltEntrySize;
+
// While linking microMIPS code PLT code are always microMIPS
// code. Set the less-significant bit to track that fact.
// See detailed comment in the `getSymVA` function.
@@ -179,12 +176,6 @@ uint64_t Symbol::getPltVA() const {
return outVA;
}
-uint64_t Symbol::getPPC64LongBranchTableVA() const {
- assert(ppc64BranchltIndex != 0xffff);
- return in.ppc64LongBranchTarget->getVA() +
- ppc64BranchltIndex * config->wordsize;
-}
-
uint64_t Symbol::getSize() const {
if (const auto *dr = dyn_cast<Defined>(this))
return dr->size;
@@ -286,13 +277,10 @@ bool Symbol::includeInDynsym() const {
return false;
if (computeBinding() == STB_LOCAL)
return false;
+ if (!isDefined() && !isCommon())
+ return true;
- // If a PIE binary was not linked against any shared libraries, then we can
- // safely drop weak undef symbols from .dynsym.
- if (isUndefWeak() && config->pie && sharedFiles.empty())
- return false;
-
- return isUndefined() || isShared() || exportDynamic || inDynamicList;
+ return exportDynamic || inDynamicList;
}
// Print out a log message for --trace-symbol.
@@ -342,6 +330,34 @@ void maybeWarnUnorderableSymbol(const Symbol *sym) {
report(": unable to order discarded 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.
+bool computeIsPreemptible(const Symbol &sym) {
+ assert(!sym.isLocal());
+
+ // Only symbols with default visibility that appear in dynsym can be
+ // preempted. Symbols with protected visibility cannot be preempted.
+ if (!sym.includeInDynsym() || sym.visibility != STV_DEFAULT)
+ return false;
+
+ // At this point copy relocations have not been created yet, so any
+ // symbol that is not defined locally is preemptible.
+ if (!sym.isDefined())
+ return true;
+
+ if (!config->shared)
+ return false;
+
+ // If the dynamic list is present, it specifies preemptable symbols in a DSO.
+ if (config->hasDynamicList)
+ return sym.inDynamicList;
+
+ // -Bsymbolic means that definitions are not preempted.
+ if (config->bsymbolic || (config->bsymbolicFunctions && sym.isFunc()))
+ return false;
+ return true;
+}
+
static uint8_t getMinVisibility(uint8_t va, uint8_t vb) {
if (va == STV_DEFAULT)
return vb;
@@ -603,7 +619,18 @@ void Symbol::resolveCommon(const CommonSymbol &other) {
return;
if (cmp > 0) {
- replace(other);
+ if (auto *s = dyn_cast<SharedSymbol>(this)) {
+ // Increase st_size if the shared symbol has a larger st_size. The shared
+ // symbol may be created from common symbols. The fact that some object
+ // files were linked into a shared object first should not change the
+ // regular rule that picks the largest st_size.
+ uint64_t size = s->size;
+ replace(other);
+ if (size > cast<CommonSymbol>(this)->size)
+ cast<CommonSymbol>(this)->size = size;
+ } else {
+ replace(other);
+ }
return;
}
@@ -644,6 +671,12 @@ template <class LazyT> void Symbol::resolveLazy(const LazyT &other) {
}
void Symbol::resolveShared(const SharedSymbol &other) {
+ if (isCommon()) {
+ // See the comment in resolveCommon() above.
+ if (other.size > cast<CommonSymbol>(this)->size)
+ cast<CommonSymbol>(this)->size = other.size;
+ return;
+ }
if (visibility == STV_DEFAULT && (isUndefined() || isLazy())) {
// An undefined symbol with non default visibility must be satisfied
// in the same DSO.