diff options
author | Patrick Wildt <patrick@cvs.openbsd.org> | 2020-08-03 14:32:30 +0000 |
---|---|---|
committer | Patrick Wildt <patrick@cvs.openbsd.org> | 2020-08-03 14:32:30 +0000 |
commit | 0ae31cf61a8a8bc7e7556fa97855cac9260e8ae9 (patch) | |
tree | 9deb45a29a7cd4db25f436b6fe8679bcb5410fa7 /gnu | |
parent | 72fb4976593ffa23596d6ecf134ccbc8f1a44b05 (diff) |
Import LLVM 10.0.0 release including clang, lld and lldb.
ok hackroom
tested by plenty
Diffstat (limited to 'gnu')
-rw-r--r-- | gnu/llvm/lld/ELF/InputFiles.h | 71 | ||||
-rw-r--r-- | gnu/llvm/lld/ELF/SymbolTable.cpp | 166 |
2 files changed, 75 insertions, 162 deletions
diff --git a/gnu/llvm/lld/ELF/InputFiles.h b/gnu/llvm/lld/ELF/InputFiles.h index bd72cfcdd05..a310ba551bd 100644 --- a/gnu/llvm/lld/ELF/InputFiles.h +++ b/gnu/llvm/lld/ELF/InputFiles.h @@ -38,6 +38,8 @@ class DWARFCache; std::string toString(const elf::InputFile *f); namespace elf { +class InputFile; +class InputSectionBase; using llvm::object::Archive; @@ -92,11 +94,9 @@ public: return symbols; } - // Get filename to use for linker script processing. - StringRef getNameForScript() const; - - // If not empty, this stores the name of the archive containing this file. - // We use this string for creating error messages. + // Filename of .a which contained this file. If this file was + // not in an archive file, it is the empty string. We use this + // string for creating error messages. std::string archiveName; // If this is an architecture-specific file, the following members @@ -130,10 +130,6 @@ public: // [.got, .got + 0xFFFC]. bool ppc64SmallCodeModelTocRelocs = false; - // True if the file has TLSGD/TLSLD GOT relocations without R_PPC64_TLSGD or - // R_PPC64_TLSLD. Disable TLS relaxation to avoid bad code generation. - bool ppc64DisableTLSRelax = false; - // groupId is used for --warn-backrefs which is an optional error // checking feature. All files within the same --{start,end}-group or // --{start,end}-lib get the same group ID. Otherwise, each file gets a new @@ -153,9 +149,6 @@ protected: private: const Kind fileKind; - - // Cache for getNameForScript(). - mutable std::string nameForScriptCache; }; class ELFFileBase : public InputFile { @@ -189,7 +182,12 @@ protected: // .o file. template <class ELFT> class ObjFile : public ELFFileBase { - LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) + using Elf_Rel = typename ELFT::Rel; + using Elf_Rela = typename ELFT::Rela; + using Elf_Sym = typename ELFT::Sym; + using Elf_Shdr = typename ELFT::Shdr; + using Elf_Word = typename ELFT::Word; + using Elf_CGProfile = typename ELFT::CGProfile; public: static bool classof(const InputFile *f) { return f->kind() == ObjKind; } @@ -202,7 +200,7 @@ public: ArrayRef<Symbol *> getGlobalSymbols(); ObjFile(MemoryBufferRef m, StringRef archiveName) : ELFFileBase(ObjKind, m) { - this->archiveName = std::string(archiveName); + this->archiveName = archiveName; } void parse(bool ignoreComdats = false); @@ -249,17 +247,14 @@ public: // Pointer to this input file's .llvm_addrsig section, if it has one. const Elf_Shdr *addrsigSec = nullptr; - // SHT_LLVM_CALL_GRAPH_PROFILE section index. - uint32_t cgProfileSectionIndex = 0; - - // Get cached DWARF information. - DWARFCache *getDwarf(); + // SHT_LLVM_CALL_GRAPH_PROFILE table + ArrayRef<Elf_CGProfile> cgProfile; private: void initializeSections(bool ignoreComdats); void initializeSymbols(); void initializeJustSymbols(); - + void initializeDwarf(); InputSectionBase *getRelocTarget(const Elf_Shdr &sec); InputSectionBase *createInputSection(const Elf_Shdr &sec); StringRef getSectionName(const Elf_Shdr &sec); @@ -287,8 +282,8 @@ private: // reporting. Linker may find reasonable number of errors in a // single object file, so we cache debugging information in order to // parse it only once for each object file we link. - std::unique_ptr<DWARFCache> dwarf; - llvm::once_flag initDwarf; + DWARFCache *dwarf; + llvm::once_flag initDwarfLine; }; // LazyObjFile is analogous to ArchiveFile in the sense that @@ -303,7 +298,7 @@ public: LazyObjFile(MemoryBufferRef m, StringRef archiveName, uint64_t offsetInArchive) : InputFile(LazyObjKind, m), offsetInArchive(offsetInArchive) { - this->archiveName = std::string(archiveName); + this->archiveName = archiveName; } static bool classof(const InputFile *f) { return f->kind() == LazyObjKind; } @@ -311,12 +306,6 @@ public: template <class ELFT> void parse(); void fetch(); - // Check if a non-common symbol should be fetched to override a common - // definition. - bool shouldFetchForCommon(const StringRef &name); - - bool fetched = false; - private: uint64_t offsetInArchive; }; @@ -334,15 +323,6 @@ public: // more than once.) void fetch(const Archive::Symbol &sym); - // Check if a non-common symbol should be fetched to override a common - // definition. - bool shouldFetchForCommon(const Archive::Symbol &sym); - - size_t getMemberCount() const; - size_t getFetchedMemberCount() const { return seen.size(); } - - bool parsed = false; - private: std::unique_ptr<Archive> file; llvm::DenseSet<uint64_t> seen; @@ -361,7 +341,7 @@ public: class SharedFile : public ELFFileBase { public: SharedFile(MemoryBufferRef m, StringRef defaultSoName) - : ELFFileBase(SharedKind, m), soName(std::string(defaultSoName)), + : ELFFileBase(SharedKind, m), soName(defaultSoName), isNeeded(!config->asNeeded) {} // This is actually a vector of Elf_Verdef pointers. @@ -381,17 +361,11 @@ public: template <typename ELFT> void parse(); + // Used for --no-allow-shlib-undefined. + bool allNeededIsKnown; + // Used for --as-needed bool isNeeded; - - // Non-weak undefined symbols which are not yet resolved when the SO is - // parsed. Only filled for `--no-allow-shlib-undefined`. - std::vector<Symbol *> requiredSymbols; - -private: - template <typename ELFT> - std::vector<uint32_t> parseVerneed(const llvm::object::ELFFile<ELFT> &obj, - const typename ELFT::Shdr *sec); }; class BinaryFile : public InputFile { @@ -410,7 +384,6 @@ inline bool isBitcode(MemoryBufferRef mb) { std::string replaceThinLTOSuffix(StringRef path); -extern std::vector<ArchiveFile *> archiveFiles; extern std::vector<BinaryFile *> binaryFiles; extern std::vector<BitcodeFile *> bitcodeFiles; extern std::vector<LazyObjFile *> lazyObjFiles; diff --git a/gnu/llvm/lld/ELF/SymbolTable.cpp b/gnu/llvm/lld/ELF/SymbolTable.cpp index 22e6b4f9289..f7a8a99cf8f 100644 --- a/gnu/llvm/lld/ELF/SymbolTable.cpp +++ b/gnu/llvm/lld/ELF/SymbolTable.cpp @@ -26,10 +26,10 @@ using namespace llvm; using namespace llvm::object; using namespace llvm::ELF; -using namespace lld; -using namespace lld::elf; -SymbolTable *elf::symtab; +namespace lld { +namespace elf { +SymbolTable *symtab; void SymbolTable::wrap(Symbol *sym, Symbol *real, Symbol *wrap) { // Swap symbols as instructed by -wrap. @@ -40,20 +40,12 @@ void SymbolTable::wrap(Symbol *sym, Symbol *real, Symbol *wrap) { idx2 = idx1; idx1 = idx3; - if (real->exportDynamic) - sym->exportDynamic = true; - if (!real->isUsedInRegularObj && sym->isUndefined()) - sym->isUsedInRegularObj = false; - - // Now renaming is complete, and no one refers to real. We drop real from - // .symtab and .dynsym. If real is undefined, it is important that we don't - // leave it in .dynsym, because otherwise it might lead to an undefined symbol - // error in a subsequent link. If real is defined, we could emit real as an - // alias for sym, but that could degrade the user experience of some tools - // that can print out only one symbol for each location: sym is a preferred - // name than real, but they might print out real instead. + // Now renaming is complete. No one refers Real symbol. We could leave + // Real as-is, but if Real is written to the symbol table, that may + // contain irrelevant values. So, we copy all values from Sym to Real. + StringRef s = real->getName(); memcpy(real, sym, sizeof(SymbolUnion)); - real->isUsedInRegularObj = false; + real->setName(s); } // Find an existing symbol or create a new one. @@ -96,7 +88,7 @@ Symbol *SymbolTable::insert(StringRef name) { } Symbol *SymbolTable::addSymbol(const Symbol &newSym) { - Symbol *sym = insert(newSym.getName()); + Symbol *sym = symtab->insert(newSym.getName()); sym->resolve(newSym); return sym; } @@ -111,13 +103,6 @@ Symbol *SymbolTable::find(StringRef name) { return sym; } -// A version script/dynamic list is only meaningful for a Defined symbol. -// A CommonSymbol will be converted to a Defined in replaceCommonSymbols(). -// A lazy symbol may be made Defined if an LTO libcall fetches it. -static bool canBeVersioned(const Symbol &sym) { - return sym.isDefined() || sym.isCommon() || sym.isLazy(); -} - // Initialize demangledSyms with a map from demangled symbols to symbol // objects. Used to handle "extern C++" directive in version scripts. // @@ -134,20 +119,11 @@ static bool canBeVersioned(const Symbol &sym) { StringMap<std::vector<Symbol *>> &SymbolTable::getDemangledSyms() { if (!demangledSyms) { demangledSyms.emplace(); - std::string demangled; - for (Symbol *sym : symVector) - if (canBeVersioned(*sym)) { - StringRef name = sym->getName(); - size_t pos = name.find('@'); - if (pos == std::string::npos) - demangled = demangleItanium(name); - else if (pos + 1 == name.size() || name[pos + 1] == '@') - demangled = demangleItanium(name.substr(0, pos)); - else - demangled = - (demangleItanium(name.substr(0, pos)) + name.substr(pos)).str(); - (*demangledSyms)[demangled].push_back(sym); - } + for (Symbol *sym : symVector) { + if (!sym->isDefined() && !sym->isCommon()) + continue; + (*demangledSyms)[demangleItanium(sym->getName())].push_back(sym); + } } return *demangledSyms; } @@ -155,35 +131,25 @@ StringMap<std::vector<Symbol *>> &SymbolTable::getDemangledSyms() { std::vector<Symbol *> SymbolTable::findByVersion(SymbolVersion ver) { if (ver.isExternCpp) return getDemangledSyms().lookup(ver.name); - if (Symbol *sym = find(ver.name)) - if (canBeVersioned(*sym)) - return {sym}; + if (Symbol *b = find(ver.name)) + if (b->isDefined() || b->isCommon()) + return {b}; return {}; } -std::vector<Symbol *> SymbolTable::findAllByVersion(SymbolVersion ver, - bool includeNonDefault) { +std::vector<Symbol *> SymbolTable::findAllByVersion(SymbolVersion ver) { std::vector<Symbol *> res; - SingleStringMatcher m(ver.name); - auto check = [&](StringRef name) { - size_t pos = name.find('@'); - if (!includeNonDefault) - return pos == StringRef::npos; - return !(pos + 1 < name.size() && name[pos + 1] == '@'); - }; + StringMatcher m(ver.name); if (ver.isExternCpp) { for (auto &p : getDemangledSyms()) if (m.match(p.first())) - for (Symbol *sym : p.second) - if (check(sym->getName())) - res.push_back(sym); + res.insert(res.end(), p.second.begin(), p.second.end()); return res; } for (Symbol *sym : symVector) - if (canBeVersioned(*sym) && check(sym->getName()) && - m.match(sym->getName())) + if ((sym->isDefined() || sym->isCommon()) && m.match(sym->getName())) res.push_back(sym); return res; } @@ -193,7 +159,7 @@ void SymbolTable::handleDynamicList() { for (SymbolVersion &ver : config->dynamicList) { std::vector<Symbol *> syms; if (ver.hasWildcard) - syms = findAllByVersion(ver, /*includeNonDefault=*/true); + syms = findAllByVersion(ver); else syms = findByVersion(ver); @@ -202,13 +168,21 @@ void SymbolTable::handleDynamicList() { } } -// Set symbol versions to symbols. This function handles patterns containing no -// wildcard characters. Return false if no symbol definition matches ver. -bool SymbolTable::assignExactVersion(SymbolVersion ver, uint16_t versionId, - StringRef versionName, - bool includeNonDefault) { +// Set symbol versions to symbols. This function handles patterns +// containing no wildcard characters. +void SymbolTable::assignExactVersion(SymbolVersion ver, uint16_t versionId, + StringRef versionName) { + if (ver.hasWildcard) + return; + // Get a list of symbols which we need to assign the version to. std::vector<Symbol *> syms = findByVersion(ver); + if (syms.empty()) { + if (!config->undefinedVersion) + error("version script assignment of '" + versionName + "' to symbol '" + + ver.name + "' failed: symbol not defined"); + return; + } auto getName = [](uint16_t ver) -> std::string { if (ver == VER_NDX_LOCAL) @@ -220,11 +194,10 @@ bool SymbolTable::assignExactVersion(SymbolVersion ver, uint16_t versionId, // Assign the version. for (Symbol *sym : syms) { - // For a non-local versionId, skip symbols containing version info because - // symbol versions specified by symbol names take precedence over version - // scripts. See parseSymbolVersion(). - if (!includeNonDefault && versionId != VER_NDX_LOCAL && - sym->getName().contains('@')) + // Skip symbols containing version info because symbol versions + // specified by symbol names take precedence over version scripts. + // See parseSymbolVersion(). + if (sym->getName().contains('@')) continue; // If the version has not been assigned, verdefIndex is -1. Use an arbitrary @@ -239,15 +212,13 @@ bool SymbolTable::assignExactVersion(SymbolVersion ver, uint16_t versionId, warn("attempt to reassign symbol '" + ver.name + "' of " + getName(sym->versionId) + " to " + getName(versionId)); } - return !syms.empty(); } -void SymbolTable::assignWildcardVersion(SymbolVersion ver, uint16_t versionId, - bool includeNonDefault) { +void SymbolTable::assignWildcardVersion(SymbolVersion ver, uint16_t versionId) { // Exact matching takes precedence over fuzzy matching, // so we set a version to a symbol only if no version has been assigned // to the symbol. This behavior is compatible with GNU. - for (Symbol *sym : findAllByVersion(ver, includeNonDefault)) + for (Symbol *sym : findAllByVersion(ver)) if (sym->verdefIndex == UINT32_C(-1)) { sym->verdefIndex = 0; sym->versionId = versionId; @@ -260,60 +231,26 @@ void SymbolTable::assignWildcardVersion(SymbolVersion ver, uint16_t versionId, // script file, the script does not actually define any symbol version, // but just specifies symbols visibilities. void SymbolTable::scanVersionScript() { - SmallString<128> buf; // First, we assign versions to exact matching symbols, // i.e. version definitions not containing any glob meta-characters. - std::vector<Symbol *> syms; - for (VersionDefinition &v : config->versionDefinitions) { - auto assignExact = [&](SymbolVersion pat, uint16_t id, StringRef ver) { - bool found = - assignExactVersion(pat, id, ver, /*includeNonDefault=*/false); - buf.clear(); - found |= assignExactVersion({(pat.name + "@" + v.name).toStringRef(buf), - pat.isExternCpp, /*hasWildCard=*/false}, - id, ver, /*includeNonDefault=*/true); - if (!found && !config->undefinedVersion) - errorOrWarn("version script assignment of '" + ver + "' to symbol '" + - pat.name + "' failed: symbol not defined"); - }; - for (SymbolVersion &pat : v.nonLocalPatterns) - if (!pat.hasWildcard) - assignExact(pat, v.id, v.name); - for (SymbolVersion pat : v.localPatterns) - if (!pat.hasWildcard) - assignExact(pat, VER_NDX_LOCAL, "local"); - } + for (VersionDefinition &v : config->versionDefinitions) + for (SymbolVersion &pat : v.patterns) + assignExactVersion(pat, v.id, v.name); // Next, assign versions to wildcards that are not "*". Note that because the // last match takes precedence over previous matches, we iterate over the // definitions in the reverse order. - auto assignWildcard = [&](SymbolVersion pat, uint16_t id, StringRef ver) { - assignWildcardVersion(pat, id, /*includeNonDefault=*/false); - buf.clear(); - assignWildcardVersion({(pat.name + "@" + ver).toStringRef(buf), - pat.isExternCpp, /*hasWildCard=*/true}, - id, - /*includeNonDefault=*/true); - }; - for (VersionDefinition &v : llvm::reverse(config->versionDefinitions)) { - for (SymbolVersion &pat : v.nonLocalPatterns) - if (pat.hasWildcard && pat.name != "*") - assignWildcard(pat, v.id, v.name); - for (SymbolVersion &pat : v.localPatterns) + for (VersionDefinition &v : llvm::reverse(config->versionDefinitions)) + for (SymbolVersion &pat : v.patterns) if (pat.hasWildcard && pat.name != "*") - assignWildcard(pat, VER_NDX_LOCAL, v.name); - } + assignWildcardVersion(pat, v.id); // Then, assign versions to "*". In GNU linkers they have lower priority than // other wildcards. - for (VersionDefinition &v : config->versionDefinitions) { - for (SymbolVersion &pat : v.nonLocalPatterns) + for (VersionDefinition &v : config->versionDefinitions) + for (SymbolVersion &pat : v.patterns) if (pat.hasWildcard && pat.name == "*") - assignWildcard(pat, v.id, v.name); - for (SymbolVersion &pat : v.localPatterns) - if (pat.hasWildcard && pat.name == "*") - assignWildcard(pat, VER_NDX_LOCAL, v.name); - } + assignWildcardVersion(pat, v.id); // Symbol themselves might know their versions because symbols // can contain versions in the form of <name>@<version>. @@ -327,3 +264,6 @@ void SymbolTable::scanVersionScript() { // --dynamic-list. handleDynamicList(); } + +} // namespace elf +} // namespace lld |