summaryrefslogtreecommitdiff
path: root/gnu
diff options
context:
space:
mode:
authorPatrick Wildt <patrick@cvs.openbsd.org>2020-08-03 14:32:30 +0000
committerPatrick Wildt <patrick@cvs.openbsd.org>2020-08-03 14:32:30 +0000
commit0ae31cf61a8a8bc7e7556fa97855cac9260e8ae9 (patch)
tree9deb45a29a7cd4db25f436b6fe8679bcb5410fa7 /gnu
parent72fb4976593ffa23596d6ecf134ccbc8f1a44b05 (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.h71
-rw-r--r--gnu/llvm/lld/ELF/SymbolTable.cpp166
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