diff options
Diffstat (limited to 'lld/ELF/Symbols.cpp')
-rw-r--r-- | lld/ELF/Symbols.cpp | 67 |
1 files changed, 46 insertions, 21 deletions
diff --git a/lld/ELF/Symbols.cpp b/lld/ELF/Symbols.cpp index 8f2f55418df5..a54f68edf952 100644 --- a/lld/ELF/Symbols.cpp +++ b/lld/ELF/Symbols.cpp @@ -37,11 +37,9 @@ std::string lld::toString(const elf::Symbol &sym) { StringRef name = sym.getName(); std::string ret = demangle(name); - // If sym has a non-default version, its name may have been truncated at '@' - // by Symbol::parseSymbolVersion(). Add the trailing part. This check is safe - // because every symbol name ends with '\0'. - if (name.data()[name.size()] == '@') - ret += name.data() + name.size(); + const char *suffix = sym.getVersionSuffix(); + if (*suffix == '@') + ret += suffix; return ret; } @@ -64,7 +62,8 @@ Defined *ElfSym::relaIpltStart; Defined *ElfSym::relaIpltEnd; Defined *ElfSym::riscvGlobalPointer; Defined *ElfSym::tlsModuleBase; -DenseMap<const Symbol *, const InputFile *> elf::backwardReferences; +DenseMap<const Symbol *, std::pair<const InputFile *, const InputFile *>> + elf::backwardReferences; static uint64_t getSymVA(const Symbol &sym, int64_t &addend) { switch (sym.kind()) { @@ -376,8 +375,18 @@ bool elf::computeIsPreemptible(const Symbol &sym) { void elf::reportBackrefs() { for (auto &it : backwardReferences) { const Symbol &sym = *it.first; - warn("backward reference detected: " + sym.getName() + " in " + - toString(it.second) + " refers to " + toString(sym.file)); + std::string to = toString(it.second.second); + // Some libraries have known problems and can cause noise. Filter them out + // with --warn-backrefs-exclude=. to may look like *.o or *.a(*.o). + bool exclude = false; + for (const llvm::GlobPattern &pat : config->warnBackrefsExclude) + if (pat.match(to)) { + exclude = true; + break; + } + if (!exclude) + warn("backward reference detected: " + sym.getName() + " in " + + toString(it.second.first) + " refers to " + to); } } @@ -513,17 +522,6 @@ void Symbol::resolveUndefined(const Undefined &other) { // group assignment rule simulates the traditional linker's semantics. bool backref = config->warnBackrefs && other.file && file->groupId < other.file->groupId; - if (backref) { - // Some libraries have known problems and can cause noise. Filter them out - // with --warn-backrefs-exclude=. - StringRef name = - !file->archiveName.empty() ? file->archiveName : file->getName(); - for (const llvm::GlobPattern &pat : config->warnBackrefsExclude) - if (pat.match(name)) { - backref = false; - break; - } - } fetch(); // We don't report backward references to weak symbols as they can be @@ -532,9 +530,10 @@ void Symbol::resolveUndefined(const Undefined &other) { // A traditional linker does not error for -ldef1 -lref -ldef2 (linking // sandwich), where def2 may or may not be the same as def1. We don't want // to warn for this case, so dismiss the warning if we see a subsequent lazy - // definition. + // definition. this->file needs to be saved because in the case of LTO it + // may be reset to nullptr or be replaced with a file named lto.tmp. if (backref && !isWeak()) - backwardReferences.try_emplace(this, other.file); + backwardReferences.try_emplace(this, std::make_pair(other.file, file)); return; } @@ -690,7 +689,33 @@ void Symbol::resolveDefined(const Defined &other) { other.value); } +template <class LazyT> +static void replaceCommon(Symbol &oldSym, const LazyT &newSym) { + backwardReferences.erase(&oldSym); + oldSym.replace(newSym); + newSym.fetch(); +} + template <class LazyT> void Symbol::resolveLazy(const LazyT &other) { + // For common objects, we want to look for global or weak definitions that + // should be fetched as the cannonical definition instead. + if (isCommon() && elf::config->fortranCommon) { + if (auto *laSym = dyn_cast<LazyArchive>(&other)) { + ArchiveFile *archive = cast<ArchiveFile>(laSym->file); + const Archive::Symbol &archiveSym = laSym->sym; + if (archive->shouldFetchForCommon(archiveSym)) { + replaceCommon(*this, other); + return; + } + } else if (auto *loSym = dyn_cast<LazyObject>(&other)) { + LazyObjFile *obj = cast<LazyObjFile>(loSym->file); + if (obj->shouldFetchForCommon(loSym->getName())) { + replaceCommon(*this, other); + return; + } + } + } + if (!isUndefined()) { // See the comment in resolveUndefined(). if (isDefined()) |