diff options
Diffstat (limited to 'lld/ELF/Symbols.cpp')
| -rw-r--r-- | lld/ELF/Symbols.cpp | 75 |
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. |
