2015-07-25 05:03:07 +08:00
|
|
|
//===- SymbolTable.cpp ----------------------------------------------------===//
|
|
|
|
//
|
2019-01-19 16:50:56 +08:00
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
2015-07-25 05:03:07 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
2015-10-14 03:51:57 +08:00
|
|
|
//
|
|
|
|
// Symbol table is a bag of all known symbols. We put all symbols of
|
2016-01-06 04:47:37 +08:00
|
|
|
// all input files to the symbol table. The symbol table is basically
|
2015-10-14 03:51:57 +08:00
|
|
|
// a hash table with the logic to resolve symbol name conflicts using
|
|
|
|
// the symbol types.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
2015-07-25 05:03:07 +08:00
|
|
|
|
|
|
|
#include "SymbolTable.h"
|
2015-09-12 06:42:45 +08:00
|
|
|
#include "Config.h"
|
2016-06-29 10:46:51 +08:00
|
|
|
#include "LinkerScript.h"
|
2015-07-25 05:03:07 +08:00
|
|
|
#include "Symbols.h"
|
2017-11-06 12:33:58 +08:00
|
|
|
#include "SyntheticSections.h"
|
[lld] unified COFF and ELF error handling on new Common/ErrorHandler
Summary:
The COFF linker and the ELF linker have long had similar but separate
Error.h and Error.cpp files to implement error handling. This change
introduces new error handling code in Common/ErrorHandler.h, changes the
COFF and ELF linkers to use it, and removes the old, separate
implementations.
Reviewers: ruiu
Reviewed By: ruiu
Subscribers: smeenai, jyknight, emaste, sdardis, nemanjai, nhaehnle, mgorny, javed.absar, kbarton, fedor.sergeev, llvm-commits
Differential Revision: https://reviews.llvm.org/D39259
llvm-svn: 316624
2017-10-26 06:28:38 +08:00
|
|
|
#include "lld/Common/ErrorHandler.h"
|
2017-11-29 04:39:17 +08:00
|
|
|
#include "lld/Common/Memory.h"
|
2017-11-28 10:15:26 +08:00
|
|
|
#include "lld/Common/Strings.h"
|
2016-11-18 03:57:43 +08:00
|
|
|
#include "llvm/ADT/STLExtras.h"
|
2015-07-25 05:03:07 +08:00
|
|
|
|
|
|
|
using namespace llvm;
|
2015-08-31 09:16:19 +08:00
|
|
|
using namespace llvm::object;
|
2015-09-23 02:19:46 +08:00
|
|
|
using namespace llvm::ELF;
|
2015-07-25 05:03:07 +08:00
|
|
|
|
|
|
|
using namespace lld;
|
2016-02-28 08:25:54 +08:00
|
|
|
using namespace lld::elf;
|
2015-07-25 05:03:07 +08:00
|
|
|
|
2017-07-27 02:42:48 +08:00
|
|
|
SymbolTable *elf::Symtab;
|
|
|
|
|
2016-07-18 01:50:09 +08:00
|
|
|
// Set a flag for --trace-symbol so that we can print out a log message
|
|
|
|
// if a new symbol with the same name is inserted into the symbol table.
|
2017-07-27 02:42:48 +08:00
|
|
|
void SymbolTable::trace(StringRef Name) {
|
2017-11-28 07:16:06 +08:00
|
|
|
SymMap.insert({CachedHashStringRef(Name), -1});
|
2016-07-18 01:50:09 +08:00
|
|
|
}
|
|
|
|
|
Change how we handle -wrap.
We have an issue with -wrap that the option doesn't work well when
renamed symbols get PLT entries. I'll explain what is the issue and
how this patch solves it.
For one -wrap option, we have three symbols: foo, wrap_foo and real_foo.
Currently, we use memcpy to overwrite wrapped symbols so that they get
the same contents. This works in most cases but doesn't when the relocation
processor sets some flags in the symbol. memcpy'ed symbols are just
aliases, so they always have to have the same contents, but the
relocation processor breaks that assumption.
r336609 is an attempt to fix the issue by memcpy'ing again after
processing relocations, so that symbols that are out of sync get the
same contents again. That works in most cases as well, but it breaks
ASan build in a mysterious way.
We could probably fix the issue by choosing symbol attributes that need
to be copied after they are updated. But it feels too complicated to me.
So, in this patch, I fixed it once and for all. With this patch, we no
longer memcpy symbols. All references to renamed symbols point to new
symbols after wrapSymbols() is done.
Differential Revision: https://reviews.llvm.org/D50569
llvm-svn: 340387
2018-08-22 15:02:26 +08:00
|
|
|
void SymbolTable::wrap(Symbol *Sym, Symbol *Real, Symbol *Wrap) {
|
|
|
|
// Swap symbols as instructed by -wrap.
|
2018-10-10 04:22:18 +08:00
|
|
|
int &Idx1 = SymMap[CachedHashStringRef(Sym->getName())];
|
|
|
|
int &Idx2 = SymMap[CachedHashStringRef(Real->getName())];
|
|
|
|
int &Idx3 = SymMap[CachedHashStringRef(Wrap->getName())];
|
2016-01-08 01:20:07 +08:00
|
|
|
|
Change how we handle -wrap.
We have an issue with -wrap that the option doesn't work well when
renamed symbols get PLT entries. I'll explain what is the issue and
how this patch solves it.
For one -wrap option, we have three symbols: foo, wrap_foo and real_foo.
Currently, we use memcpy to overwrite wrapped symbols so that they get
the same contents. This works in most cases but doesn't when the relocation
processor sets some flags in the symbol. memcpy'ed symbols are just
aliases, so they always have to have the same contents, but the
relocation processor breaks that assumption.
r336609 is an attempt to fix the issue by memcpy'ing again after
processing relocations, so that symbols that are out of sync get the
same contents again. That works in most cases as well, but it breaks
ASan build in a mysterious way.
We could probably fix the issue by choosing symbol attributes that need
to be copied after they are updated. But it feels too complicated to me.
So, in this patch, I fixed it once and for all. With this patch, we no
longer memcpy symbols. All references to renamed symbols point to new
symbols after wrapSymbols() is done.
Differential Revision: https://reviews.llvm.org/D50569
llvm-svn: 340387
2018-08-22 15:02:26 +08:00
|
|
|
Idx2 = Idx1;
|
|
|
|
Idx1 = Idx3;
|
2017-11-05 07:09:43 +08:00
|
|
|
|
Change how we handle -wrap.
We have an issue with -wrap that the option doesn't work well when
renamed symbols get PLT entries. I'll explain what is the issue and
how this patch solves it.
For one -wrap option, we have three symbols: foo, wrap_foo and real_foo.
Currently, we use memcpy to overwrite wrapped symbols so that they get
the same contents. This works in most cases but doesn't when the relocation
processor sets some flags in the symbol. memcpy'ed symbols are just
aliases, so they always have to have the same contents, but the
relocation processor breaks that assumption.
r336609 is an attempt to fix the issue by memcpy'ing again after
processing relocations, so that symbols that are out of sync get the
same contents again. That works in most cases as well, but it breaks
ASan build in a mysterious way.
We could probably fix the issue by choosing symbol attributes that need
to be copied after they are updated. But it feels too complicated to me.
So, in this patch, I fixed it once and for all. With this patch, we no
longer memcpy symbols. All references to renamed symbols point to new
symbols after wrapSymbols() is done.
Differential Revision: https://reviews.llvm.org/D50569
llvm-svn: 340387
2018-08-22 15:02:26 +08:00
|
|
|
// 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->setName(S);
|
2017-04-26 18:40:02 +08:00
|
|
|
}
|
|
|
|
|
2019-05-17 09:55:20 +08:00
|
|
|
// Find an existing symbol or create a new one.
|
|
|
|
Symbol *SymbolTable::insert(StringRef Name) {
|
2017-07-20 00:45:05 +08:00
|
|
|
// <name>@@<version> means the symbol is the default version. In that
|
|
|
|
// case <name>@@<version> will be used to resolve references to <name>.
|
2017-09-26 12:17:13 +08:00
|
|
|
//
|
|
|
|
// Since this is a hot path, the following string search code is
|
|
|
|
// optimized for speed. StringRef::find(char) is much faster than
|
|
|
|
// StringRef::find(StringRef).
|
|
|
|
size_t Pos = Name.find('@');
|
|
|
|
if (Pos != StringRef::npos && Pos + 1 < Name.size() && Name[Pos + 1] == '@')
|
2017-07-20 00:45:05 +08:00
|
|
|
Name = Name.take_front(Pos);
|
|
|
|
|
2017-11-28 07:16:06 +08:00
|
|
|
auto P = SymMap.insert({CachedHashStringRef(Name), (int)SymVector.size()});
|
2017-11-06 12:58:04 +08:00
|
|
|
int &SymIndex = P.first->second;
|
2016-07-18 01:50:09 +08:00
|
|
|
bool IsNew = P.second;
|
2017-11-06 12:58:04 +08:00
|
|
|
bool Traced = false;
|
2016-07-18 01:50:09 +08:00
|
|
|
|
2017-11-06 12:58:04 +08:00
|
|
|
if (SymIndex == -1) {
|
|
|
|
SymIndex = SymVector.size();
|
2018-10-10 06:44:42 +08:00
|
|
|
IsNew = true;
|
|
|
|
Traced = true;
|
2016-07-18 09:35:00 +08:00
|
|
|
}
|
|
|
|
|
2019-05-17 09:55:20 +08:00
|
|
|
if (!IsNew)
|
|
|
|
return SymVector[SymIndex];
|
|
|
|
|
|
|
|
Symbol *Sym = reinterpret_cast<Symbol *>(make<SymbolUnion>());
|
|
|
|
SymVector.push_back(Sym);
|
|
|
|
|
Speed up --start-lib and --end-lib.
--{start,end}-lib give files grouped by the options the archive file
semantics. That is, each object file between them acts as if it were
in an archive file whose sole member is the file.
Therefore, files between --{start,end}-lib are linked to the final
output only if they are needed to resolve some undefined symbols.
Previously, the feature was implemented this way:
1. We read a symbol table and insert defined symbols to the symbol
table as lazy symbols.
2. If an undefind symbol is resolved to a lazy symbol, that lazy
symbol instantiate ObjFile class for that symbol, which re-insert
all defined symbols to the symbol table.
So, if an ObjFile is instantiated, defined symbols are inserted to the
symbol table twice. Since inserting long symbol names is not cheap,
there's a room to optimize here.
This patch optimzies it. Now, LazyObjFile remembers symbol handles and
passed them over to a new ObjFile instance, so that the ObjFile
doesn't insert the same strings.
Here is a quick benchmark to link clang. "Original" is the original
lld with unmodified command line options. For "Case 1" and "Case 2", I
extracted all files from archive files and replace .a's in a command
line with .o's wrapped with --{start,end}-lib. I used the original lld
for Case 1" and use this patch for Case 2.
Original: 5.892
Case 1: 6.001 (+1.8%)
Case 2: 5.701 (-3.2%)
So, interestingly, --{start,end}-lib are now faster than the regular
linking scheme with archive files. That's perhaps not too surprising,
though, because for regular archive files, we look up the symbol table
with the same string twice.
Differential Revision: https://reviews.llvm.org/D62188
llvm-svn: 361473
2019-05-23 17:53:30 +08:00
|
|
|
Sym->setName(Name);
|
2019-05-17 09:55:20 +08:00
|
|
|
Sym->SymbolKind = Symbol::PlaceholderKind;
|
|
|
|
Sym->VersionId = Config->DefaultSymbolVersion;
|
|
|
|
Sym->Visibility = STV_DEFAULT;
|
|
|
|
Sym->IsUsedInRegularObj = false;
|
|
|
|
Sym->ExportDynamic = false;
|
|
|
|
Sym->CanInline = true;
|
|
|
|
Sym->Traced = Traced;
|
|
|
|
Sym->ScriptDefined = false;
|
|
|
|
return Sym;
|
2019-05-16 11:29:03 +08:00
|
|
|
}
|
|
|
|
|
2019-05-17 09:55:20 +08:00
|
|
|
Symbol *SymbolTable::addSymbol(const Symbol &New) {
|
2019-05-23 17:58:08 +08:00
|
|
|
Symbol *Sym = Symtab->insert(New.getName());
|
|
|
|
Sym->resolve(New);
|
|
|
|
return Sym;
|
ELF: New symbol table design.
This patch implements a new design for the symbol table that stores
SymbolBodies within a memory region of the Symbol object. Symbols are mutated
by constructing SymbolBodies in place over existing SymbolBodies, rather
than by mutating pointers. As mentioned in the initial proposal [1], this
memory layout helps reduce the cache miss rate by improving memory locality.
Performance numbers:
old(s) new(s)
Without debug info:
chrome 7.178 6.432 (-11.5%)
LLVMgold.so 0.505 0.502 (-0.5%)
clang 0.954 0.827 (-15.4%)
llvm-as 0.052 0.045 (-15.5%)
With debug info:
scylla 5.695 5.613 (-1.5%)
clang 14.396 14.143 (-1.8%)
Performance counter results show that the fewer required indirections is
indeed the cause of the improved performance. For example, when linking
chrome, stalled cycles decreases from 14,556,444,002 to 12,959,238,310, and
instructions per cycle increases from 0.78 to 0.83. We are also executing
many fewer instructions (15,516,401,933 down to 15,002,434,310), probably
because we spend less time allocating SymbolBodies.
The new mechanism by which symbols are added to the symbol table is by calling
add* functions on the SymbolTable.
In this patch, I handle local symbols by storing them inside "unparented"
SymbolBodies. This is suboptimal, but if we do want to try to avoid allocating
these SymbolBodies, we can probably do that separately.
I also removed a few members from the SymbolBody class that were only being
used to pass information from the input file to the symbol table.
This patch implements the new design for the ELF linker only. I intend to
prepare a similar patch for the COFF linker.
[1] http://lists.llvm.org/pipermail/llvm-dev/2016-April/098832.html
Differential Revision: http://reviews.llvm.org/D19752
llvm-svn: 268178
2016-05-01 12:55:03 +08:00
|
|
|
}
|
|
|
|
|
2017-11-04 05:21:47 +08:00
|
|
|
Symbol *SymbolTable::find(StringRef Name) {
|
2017-11-28 07:16:06 +08:00
|
|
|
auto It = SymMap.find(CachedHashStringRef(Name));
|
|
|
|
if (It == SymMap.end())
|
2015-10-14 00:34:14 +08:00
|
|
|
return nullptr;
|
2017-11-06 12:58:04 +08:00
|
|
|
if (It->second == -1)
|
2016-07-18 09:35:00 +08:00
|
|
|
return nullptr;
|
2017-11-06 12:58:04 +08:00
|
|
|
return SymVector[It->second];
|
2015-10-14 00:34:14 +08:00
|
|
|
}
|
|
|
|
|
2016-11-16 02:41:52 +08:00
|
|
|
// Initialize DemangledSyms with a map from demangled symbols to symbol
|
|
|
|
// objects. Used to handle "extern C++" directive in version scripts.
|
|
|
|
//
|
|
|
|
// The map will contain all demangled symbols. That can be very large,
|
|
|
|
// and in LLD we generally want to avoid do anything for each symbol.
|
|
|
|
// Then, why are we doing this? Here's why.
|
|
|
|
//
|
|
|
|
// Users can use "extern C++ {}" directive to match against demangled
|
|
|
|
// C++ symbols. For example, you can write a pattern such as
|
|
|
|
// "llvm::*::foo(int, ?)". Obviously, there's no way to handle this
|
|
|
|
// other than trying to match a pattern against all demangled symbols.
|
|
|
|
// So, if "extern C++" feature is used, we need to demangle all known
|
|
|
|
// symbols.
|
2017-11-04 05:21:47 +08:00
|
|
|
StringMap<std::vector<Symbol *>> &SymbolTable::getDemangledSyms() {
|
2016-12-22 13:31:52 +08:00
|
|
|
if (!DemangledSyms) {
|
|
|
|
DemangledSyms.emplace();
|
2017-11-04 05:21:47 +08:00
|
|
|
for (Symbol *Sym : SymVector) {
|
2019-05-16 11:29:03 +08:00
|
|
|
if (!Sym->isDefined() && !Sym->isCommon())
|
2016-12-22 17:54:32 +08:00
|
|
|
continue;
|
2017-11-28 10:15:26 +08:00
|
|
|
if (Optional<std::string> S = demangleItanium(Sym->getName()))
|
2017-11-01 00:07:41 +08:00
|
|
|
(*DemangledSyms)[*S].push_back(Sym);
|
2016-12-22 13:31:52 +08:00
|
|
|
else
|
2017-11-01 00:07:41 +08:00
|
|
|
(*DemangledSyms)[Sym->getName()].push_back(Sym);
|
2016-12-22 13:31:52 +08:00
|
|
|
}
|
2016-07-18 09:34:57 +08:00
|
|
|
}
|
2016-12-22 13:31:52 +08:00
|
|
|
return *DemangledSyms;
|
2016-07-16 20:26:39 +08:00
|
|
|
}
|
|
|
|
|
2017-11-04 05:21:47 +08:00
|
|
|
std::vector<Symbol *> SymbolTable::findByVersion(SymbolVersion Ver) {
|
2016-12-22 13:31:52 +08:00
|
|
|
if (Ver.IsExternCpp)
|
|
|
|
return getDemangledSyms().lookup(Ver.Name);
|
2017-11-04 05:21:47 +08:00
|
|
|
if (Symbol *B = find(Ver.Name))
|
2019-05-16 11:29:03 +08:00
|
|
|
if (B->isDefined() || B->isCommon())
|
2016-12-22 17:54:32 +08:00
|
|
|
return {B};
|
|
|
|
return {};
|
2016-12-08 23:56:33 +08:00
|
|
|
}
|
|
|
|
|
2017-11-04 05:21:47 +08:00
|
|
|
std::vector<Symbol *> SymbolTable::findAllByVersion(SymbolVersion Ver) {
|
|
|
|
std::vector<Symbol *> Res;
|
2016-12-21 10:27:14 +08:00
|
|
|
StringMatcher M(Ver.Name);
|
2016-12-09 00:26:20 +08:00
|
|
|
|
2016-12-09 00:02:48 +08:00
|
|
|
if (Ver.IsExternCpp) {
|
2016-12-22 13:31:52 +08:00
|
|
|
for (auto &P : getDemangledSyms())
|
2016-12-09 00:02:48 +08:00
|
|
|
if (M.match(P.first()))
|
2016-12-22 17:54:32 +08:00
|
|
|
Res.insert(Res.end(), P.second.begin(), P.second.end());
|
2016-12-09 00:02:48 +08:00
|
|
|
return Res;
|
|
|
|
}
|
2016-12-09 00:26:20 +08:00
|
|
|
|
2017-11-04 05:21:47 +08:00
|
|
|
for (Symbol *Sym : SymVector)
|
2019-05-16 11:29:03 +08:00
|
|
|
if ((Sym->isDefined() || Sym->isCommon()) && M.match(Sym->getName()))
|
2017-11-01 00:07:41 +08:00
|
|
|
Res.push_back(Sym);
|
2016-12-09 00:26:20 +08:00
|
|
|
return Res;
|
2016-12-08 23:56:33 +08:00
|
|
|
}
|
|
|
|
|
2016-09-14 04:51:30 +08:00
|
|
|
// If there's only one anonymous version definition in a version
|
2016-11-14 17:56:35 +08:00
|
|
|
// script file, the script does not actually define any symbol version,
|
2017-01-11 00:37:24 +08:00
|
|
|
// but just specifies symbols visibilities.
|
2017-07-27 02:42:48 +08:00
|
|
|
void SymbolTable::handleAnonymousVersion() {
|
2017-01-11 00:37:24 +08:00
|
|
|
for (SymbolVersion &Ver : Config->VersionScriptGlobals)
|
|
|
|
assignExactVersion(Ver, VER_NDX_GLOBAL, "global");
|
|
|
|
for (SymbolVersion &Ver : Config->VersionScriptGlobals)
|
|
|
|
assignWildcardVersion(Ver, VER_NDX_GLOBAL);
|
|
|
|
for (SymbolVersion &Ver : Config->VersionScriptLocals)
|
|
|
|
assignExactVersion(Ver, VER_NDX_LOCAL, "local");
|
|
|
|
for (SymbolVersion &Ver : Config->VersionScriptLocals)
|
|
|
|
assignWildcardVersion(Ver, VER_NDX_LOCAL);
|
2016-09-14 04:51:30 +08:00
|
|
|
}
|
|
|
|
|
2017-09-09 02:16:59 +08:00
|
|
|
// Handles -dynamic-list.
|
|
|
|
void SymbolTable::handleDynamicList() {
|
|
|
|
for (SymbolVersion &Ver : Config->DynamicList) {
|
2017-11-04 05:21:47 +08:00
|
|
|
std::vector<Symbol *> Syms;
|
2017-09-09 02:16:59 +08:00
|
|
|
if (Ver.HasWildcard)
|
|
|
|
Syms = findAllByVersion(Ver);
|
2017-12-06 08:14:04 +08:00
|
|
|
else
|
|
|
|
Syms = findByVersion(Ver);
|
2017-09-09 02:16:59 +08:00
|
|
|
|
2017-11-04 05:21:47 +08:00
|
|
|
for (Symbol *B : Syms) {
|
2017-09-09 02:16:59 +08:00
|
|
|
if (!Config->Shared)
|
2017-11-01 00:07:41 +08:00
|
|
|
B->ExportDynamic = true;
|
|
|
|
else if (B->includeInDynsym())
|
2017-09-09 02:16:59 +08:00
|
|
|
B->IsPreemptible = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-11-17 10:09:42 +08:00
|
|
|
// Set symbol versions to symbols. This function handles patterns
|
|
|
|
// containing no wildcard characters.
|
2017-07-27 02:42:48 +08:00
|
|
|
void SymbolTable::assignExactVersion(SymbolVersion Ver, uint16_t VersionId,
|
|
|
|
StringRef VersionName) {
|
2016-11-18 14:30:08 +08:00
|
|
|
if (Ver.HasWildcard)
|
2016-11-17 10:09:42 +08:00
|
|
|
return;
|
|
|
|
|
|
|
|
// Get a list of symbols which we need to assign the version to.
|
2017-11-04 05:21:47 +08:00
|
|
|
std::vector<Symbol *> Syms = findByVersion(Ver);
|
2016-12-22 17:54:32 +08:00
|
|
|
if (Syms.empty()) {
|
2018-02-03 05:44:06 +08:00
|
|
|
if (!Config->UndefinedVersion)
|
2016-12-22 17:54:32 +08:00
|
|
|
error("version script assignment of '" + VersionName + "' to symbol '" +
|
|
|
|
Ver.Name + "' failed: symbol not defined");
|
|
|
|
return;
|
|
|
|
}
|
2016-11-17 10:09:42 +08:00
|
|
|
|
|
|
|
// Assign the version.
|
2017-11-04 05:21:47 +08:00
|
|
|
for (Symbol *Sym : Syms) {
|
2017-07-12 21:54:42 +08:00
|
|
|
// Skip symbols containing version info because symbol versions
|
|
|
|
// specified by symbol names take precedence over version scripts.
|
|
|
|
// See parseSymbolVersion().
|
2017-11-01 00:07:41 +08:00
|
|
|
if (Sym->getName().contains('@'))
|
2017-07-12 21:54:42 +08:00
|
|
|
continue;
|
|
|
|
|
2018-03-07 01:05:12 +08:00
|
|
|
if (Sym->VersionId != Config->DefaultSymbolVersion &&
|
|
|
|
Sym->VersionId != VersionId)
|
|
|
|
error("duplicate symbol '" + Ver.Name + "' in version script");
|
2016-12-10 06:40:49 +08:00
|
|
|
Sym->VersionId = VersionId;
|
2016-11-17 10:09:42 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-07-27 02:42:48 +08:00
|
|
|
void SymbolTable::assignWildcardVersion(SymbolVersion Ver, uint16_t VersionId) {
|
2016-11-18 14:30:08 +08:00
|
|
|
if (!Ver.HasWildcard)
|
2016-11-16 02:41:52 +08:00
|
|
|
return;
|
|
|
|
|
|
|
|
// Exact matching takes precendence 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.
|
2017-11-04 05:21:47 +08:00
|
|
|
for (Symbol *B : findAllByVersion(Ver))
|
2017-11-01 00:07:41 +08:00
|
|
|
if (B->VersionId == Config->DefaultSymbolVersion)
|
|
|
|
B->VersionId = VersionId;
|
2016-11-16 02:41:52 +08:00
|
|
|
}
|
|
|
|
|
2016-09-03 06:15:08 +08:00
|
|
|
// This function processes version scripts by updating VersionId
|
|
|
|
// member of symbols.
|
2017-07-27 02:42:48 +08:00
|
|
|
void SymbolTable::scanVersionScript() {
|
2016-09-14 04:51:30 +08:00
|
|
|
// Handle edge cases first.
|
2017-01-11 00:37:24 +08:00
|
|
|
handleAnonymousVersion();
|
2017-09-09 02:16:59 +08:00
|
|
|
handleDynamicList();
|
2016-06-20 19:55:12 +08:00
|
|
|
|
2016-09-03 06:15:08 +08:00
|
|
|
// Now we have version definitions, so we need to set version ids to symbols.
|
|
|
|
// Each version definition has a glob pattern, and all symbols that match
|
|
|
|
// with the pattern get that version.
|
|
|
|
|
|
|
|
// First, we assign versions to exact matching symbols,
|
|
|
|
// i.e. version definitions not containing any glob meta-characters.
|
2016-11-17 02:46:23 +08:00
|
|
|
for (VersionDefinition &V : Config->VersionDefinitions)
|
2016-11-18 03:57:45 +08:00
|
|
|
for (SymbolVersion &Ver : V.Globals)
|
|
|
|
assignExactVersion(Ver, V.Id, V.Name);
|
[ELF] - Fixed incorrect logic of version assignments when mixing wildcards with values matching.
Previously we had incorrect logic here. Imagine we would have the next script:
LIBSAMPLE_1.0
{
global:
a_2;
local:
*;
};
LIBSAMPLE_2.0
{
global:
a*;
};
According to previous logic it would assign version 1 to a_2 and then
would try to reassign it to version 2 because of applying wildcard a*.
And show a warning about that.
Generally Ian Lance Tailor wrote about next rules that should be applied:
(http://www.airs.com/blog/archives/300)
Here are the current rules for gold:
"If there is an exact match for the mangled name, we use it. If there is more than one exact match, we give a warning, and we use the first tag in the script which matches. If a symbol has an exact match as both global and local for the same version tag, we give an error.
Otherwise, we look for an extern C++ or an extern Java exact match. If we find an exact match, we use it. If there is more than one exact match, we give a warning, and we use the first tag in the script which matches. If a symbol has an exact match as both global and local for the same version tag, we give an error.
Otherwise, we look through the wildcard patterns, ignoring “*” patterns. We look through the version tags in reverse order. For each version tag, we look through the global patterns and then the local patterns. We use the first match we find (i.e., the last matching version tag in the file).
Otherwise, we use the “*” pattern if there is one. We give a warning if there are multiple “*” patterns."
Patch makes wildcard matching to be in revered order and to follow after the regular naming matching.
Differential revision: http://reviews.llvm.org/D21894
llvm-svn: 274739
2016-07-07 15:45:27 +08:00
|
|
|
|
2016-09-03 06:15:08 +08:00
|
|
|
// Next, we assign versions to fuzzy matching symbols,
|
|
|
|
// i.e. version definitions containing glob meta-characters.
|
|
|
|
// Note that because the last match takes precedence over previous matches,
|
|
|
|
// we iterate over the definitions in the reverse order.
|
2016-11-18 03:57:43 +08:00
|
|
|
for (VersionDefinition &V : llvm::reverse(Config->VersionDefinitions))
|
|
|
|
for (SymbolVersion &Ver : V.Globals)
|
|
|
|
assignWildcardVersion(Ver, V.Id);
|
2017-07-12 21:54:42 +08:00
|
|
|
|
|
|
|
// Symbol themselves might know their versions because symbols
|
|
|
|
// can contain versions in the form of <name>@<version>.
|
|
|
|
// Let them parse and update their names to exclude version suffix.
|
2017-11-04 05:21:47 +08:00
|
|
|
for (Symbol *Sym : SymVector)
|
2017-11-01 00:07:41 +08:00
|
|
|
Sym->parseSymbolVersion();
|
2016-04-23 04:21:26 +08:00
|
|
|
}
|