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;
|
2020-05-15 13:18:58 +08:00
|
|
|
using namespace lld;
|
|
|
|
using namespace lld::elf;
|
2015-07-25 05:03:07 +08:00
|
|
|
|
2021-12-23 06:36:14 +08:00
|
|
|
std::unique_ptr<SymbolTable> elf::symtab;
|
2017-07-27 02:42:48 +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) {
|
2021-10-26 03:52:06 +08:00
|
|
|
// Redirect __real_foo to the original foo and foo to the original __wrap_foo.
|
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
|
|
|
|
2020-06-02 13:57:43 +08:00
|
|
|
if (real->exportDynamic)
|
|
|
|
sym->exportDynamic = true;
|
2021-04-17 15:29:51 +08:00
|
|
|
if (!real->isUsedInRegularObj && sym->isUndefined())
|
2020-08-09 09:17:38 +08:00
|
|
|
sym->isUsedInRegularObj = false;
|
2020-06-02 13:57:43 +08:00
|
|
|
|
2020-05-28 07:18:55 +08:00
|
|
|
// 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.
|
2020-06-02 13:57:43 +08:00
|
|
|
memcpy(real, sym, sizeof(SymbolUnion));
|
2020-05-28 07:18:55 +08:00
|
|
|
real->isUsedInRegularObj = false;
|
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).
|
2021-12-16 07:19:35 +08:00
|
|
|
StringRef stem = name;
|
2017-09-26 12:17:13 +08:00
|
|
|
size_t pos = name.find('@');
|
|
|
|
if (pos != StringRef::npos && pos + 1 < name.size() && name[pos + 1] == '@')
|
2021-12-16 07:19:35 +08:00
|
|
|
stem = name.take_front(pos);
|
[Coding style change] Rename variables so that they start with a lowercase letter
This patch is mechanically generated by clang-llvm-rename tool that I wrote
using Clang Refactoring Engine just for creating this patch. You can see the
source code of the tool at https://reviews.llvm.org/D64123. There's no manual
post-processing; you can generate the same patch by re-running the tool against
lld's code base.
Here is the main discussion thread to change the LLVM coding style:
https://lists.llvm.org/pipermail/llvm-dev/2019-February/130083.html
In the discussion thread, I proposed we use lld as a testbed for variable
naming scheme change, and this patch does that.
I chose to rename variables so that they are in camelCase, just because that
is a minimal change to make variables to start with a lowercase letter.
Note to downstream patch maintainers: if you are maintaining a downstream lld
repo, just rebasing ahead of this commit would cause massive merge conflicts
because this patch essentially changes every line in the lld subdirectory. But
there's a remedy.
clang-llvm-rename tool is a batch tool, so you can rename variables in your
downstream repo with the tool. Given that, here is how to rebase your repo to
a commit after the mass renaming:
1. rebase to the commit just before the mass variable renaming,
2. apply the tool to your downstream repo to mass-rename variables locally, and
3. rebase again to the head.
Most changes made by the tool should be identical for a downstream repo and
for the head, so at the step 3, almost all changes should be merged and
disappear. I'd expect that there would be some lines that you need to merge by
hand, but that shouldn't be too many.
Differential Revision: https://reviews.llvm.org/D64121
llvm-svn: 365595
2019-07-10 13:00:37 +08:00
|
|
|
|
2021-12-16 07:19:35 +08:00
|
|
|
auto p = symMap.insert({CachedHashStringRef(stem), (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;
|
[Coding style change] Rename variables so that they start with a lowercase letter
This patch is mechanically generated by clang-llvm-rename tool that I wrote
using Clang Refactoring Engine just for creating this patch. You can see the
source code of the tool at https://reviews.llvm.org/D64123. There's no manual
post-processing; you can generate the same patch by re-running the tool against
lld's code base.
Here is the main discussion thread to change the LLVM coding style:
https://lists.llvm.org/pipermail/llvm-dev/2019-February/130083.html
In the discussion thread, I proposed we use lld as a testbed for variable
naming scheme change, and this patch does that.
I chose to rename variables so that they are in camelCase, just because that
is a minimal change to make variables to start with a lowercase letter.
Note to downstream patch maintainers: if you are maintaining a downstream lld
repo, just rebasing ahead of this commit would cause massive merge conflicts
because this patch essentially changes every line in the lld subdirectory. But
there's a remedy.
clang-llvm-rename tool is a batch tool, so you can rename variables in your
downstream repo with the tool. Given that, here is how to rebase your repo to
a commit after the mass renaming:
1. rebase to the commit just before the mass variable renaming,
2. apply the tool to your downstream repo to mass-rename variables locally, and
3. rebase again to the head.
Most changes made by the tool should be identical for a downstream repo and
for the head, so at the step 3, almost all changes should be merged and
disappear. I'd expect that there would be some lines that you need to merge by
hand, but that shouldn't be too many.
Differential Revision: https://reviews.llvm.org/D64121
llvm-svn: 365595
2019-07-10 13:00:37 +08:00
|
|
|
|
2021-12-16 07:19:35 +08:00
|
|
|
if (!isNew) {
|
|
|
|
Symbol *sym = symVector[symIndex];
|
|
|
|
if (stem.size() != name.size())
|
|
|
|
sym->setName(name);
|
|
|
|
return sym;
|
|
|
|
}
|
[Coding style change] Rename variables so that they start with a lowercase letter
This patch is mechanically generated by clang-llvm-rename tool that I wrote
using Clang Refactoring Engine just for creating this patch. You can see the
source code of the tool at https://reviews.llvm.org/D64123. There's no manual
post-processing; you can generate the same patch by re-running the tool against
lld's code base.
Here is the main discussion thread to change the LLVM coding style:
https://lists.llvm.org/pipermail/llvm-dev/2019-February/130083.html
In the discussion thread, I proposed we use lld as a testbed for variable
naming scheme change, and this patch does that.
I chose to rename variables so that they are in camelCase, just because that
is a minimal change to make variables to start with a lowercase letter.
Note to downstream patch maintainers: if you are maintaining a downstream lld
repo, just rebasing ahead of this commit would cause massive merge conflicts
because this patch essentially changes every line in the lld subdirectory. But
there's a remedy.
clang-llvm-rename tool is a batch tool, so you can rename variables in your
downstream repo with the tool. Given that, here is how to rebase your repo to
a commit after the mass renaming:
1. rebase to the commit just before the mass variable renaming,
2. apply the tool to your downstream repo to mass-rename variables locally, and
3. rebase again to the head.
Most changes made by the tool should be identical for a downstream repo and
for the head, so at the step 3, almost all changes should be merged and
disappear. I'd expect that there would be some lines that you need to merge by
hand, but that shouldn't be too many.
Differential Revision: https://reviews.llvm.org/D64121
llvm-svn: 365595
2019-07-10 13:00:37 +08:00
|
|
|
|
2019-05-17 09:55:20 +08:00
|
|
|
Symbol *sym = reinterpret_cast<Symbol *>(make<SymbolUnion>());
|
|
|
|
symVector.push_back(sym);
|
[Coding style change] Rename variables so that they start with a lowercase letter
This patch is mechanically generated by clang-llvm-rename tool that I wrote
using Clang Refactoring Engine just for creating this patch. You can see the
source code of the tool at https://reviews.llvm.org/D64123. There's no manual
post-processing; you can generate the same patch by re-running the tool against
lld's code base.
Here is the main discussion thread to change the LLVM coding style:
https://lists.llvm.org/pipermail/llvm-dev/2019-February/130083.html
In the discussion thread, I proposed we use lld as a testbed for variable
naming scheme change, and this patch does that.
I chose to rename variables so that they are in camelCase, just because that
is a minimal change to make variables to start with a lowercase letter.
Note to downstream patch maintainers: if you are maintaining a downstream lld
repo, just rebasing ahead of this commit would cause massive merge conflicts
because this patch essentially changes every line in the lld subdirectory. But
there's a remedy.
clang-llvm-rename tool is a batch tool, so you can rename variables in your
downstream repo with the tool. Given that, here is how to rebase your repo to
a commit after the mass renaming:
1. rebase to the commit just before the mass variable renaming,
2. apply the tool to your downstream repo to mass-rename variables locally, and
3. rebase again to the head.
Most changes made by the tool should be identical for a downstream repo and
for the head, so at the step 3, almost all changes should be merged and
disappear. I'd expect that there would be some lines that you need to merge by
hand, but that shouldn't be too many.
Differential Revision: https://reviews.llvm.org/D64121
llvm-svn: 365595
2019-07-10 13:00:37 +08:00
|
|
|
|
2019-08-14 09:52:47 +08:00
|
|
|
// *sym was not initialized by a constructor. Fields that may get referenced
|
|
|
|
// when it is a placeholder must be initialized here.
|
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;
|
2019-08-05 22:31:39 +08:00
|
|
|
sym->versionId = VER_NDX_GLOBAL;
|
2019-05-17 09:55:20 +08:00
|
|
|
sym->visibility = STV_DEFAULT;
|
|
|
|
sym->isUsedInRegularObj = false;
|
|
|
|
sym->exportDynamic = false;
|
2019-08-13 17:12:52 +08:00
|
|
|
sym->inDynamicList = false;
|
2019-05-17 09:55:20 +08:00
|
|
|
sym->canInline = true;
|
2019-08-14 09:52:47 +08:00
|
|
|
sym->referenced = false;
|
|
|
|
sym->traced = false;
|
2019-05-17 09:55:20 +08:00
|
|
|
sym->scriptDefined = false;
|
2019-05-29 11:55:20 +08:00
|
|
|
sym->partition = 1;
|
2019-05-17 09:55:20 +08:00
|
|
|
return sym;
|
2019-05-16 11:29:03 +08:00
|
|
|
}
|
|
|
|
|
2019-08-13 14:19:39 +08:00
|
|
|
Symbol *SymbolTable::addSymbol(const Symbol &newSym) {
|
2020-07-07 03:00:29 +08:00
|
|
|
Symbol *sym = insert(newSym.getName());
|
2019-08-13 14:19:39 +08:00
|
|
|
sym->resolve(newSym);
|
2019-05-23 17:58:08 +08:00
|
|
|
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;
|
2021-12-15 14:41:52 +08:00
|
|
|
return symVector[it->second];
|
2015-10-14 00:34:14 +08:00
|
|
|
}
|
|
|
|
|
2020-04-02 07:11:31 +08:00
|
|
|
// A version script/dynamic list is only meaningful for a Defined symbol.
|
|
|
|
// A CommonSymbol will be converted to a Defined in replaceCommonSymbols().
|
2021-11-27 02:58:50 +08:00
|
|
|
// A lazy symbol may be made Defined if an LTO libcall extracts it.
|
2020-04-02 07:11:31 +08:00
|
|
|
static bool canBeVersioned(const Symbol &sym) {
|
|
|
|
return sym.isDefined() || sym.isCommon() || sym.isLazy();
|
|
|
|
}
|
|
|
|
|
2019-07-16 13:50:45 +08:00
|
|
|
// Initialize demangledSyms with a map from demangled symbols to symbol
|
2016-11-16 02:41:52 +08:00
|
|
|
// 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();
|
2021-08-05 14:52:55 +08:00
|
|
|
std::string demangled;
|
2020-04-02 07:11:31 +08:00
|
|
|
for (Symbol *sym : symVector)
|
2021-08-05 14:52:55 +08:00
|
|
|
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);
|
|
|
|
}
|
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);
|
2020-04-02 07:11:31 +08:00
|
|
|
if (Symbol *sym = find(ver.name))
|
|
|
|
if (canBeVersioned(*sym))
|
|
|
|
return {sym};
|
2016-12-22 17:54:32 +08:00
|
|
|
return {};
|
2016-12-08 23:56:33 +08:00
|
|
|
}
|
|
|
|
|
2021-08-05 14:52:55 +08:00
|
|
|
std::vector<Symbol *> SymbolTable::findAllByVersion(SymbolVersion ver,
|
|
|
|
bool includeNonDefault) {
|
2017-11-04 05:21:47 +08:00
|
|
|
std::vector<Symbol *> res;
|
[lld/ELF] PR44498: Support input filename in double quote
Summary:
Linker scripts allow filenames to be put in double quotes to prevent
characters in filenames that are part of the linker script syntax from
having their special meaning. Case in point the * wildcard character.
Availability of double quoting filenames also allows to fix a failure in
ELF/linkerscript/filename-spec.s when the path contain a @ which the
lexer consider as a special characters and thus break up a filename
containing it. This may happens under Jenkins which createspath such as
pipeline@2.
To avoid the need for escaping GlobPattern metacharacters in filename
in double quotes, GlobPattern::create is augmented with a new parameter
to request literal matching instead of relying on the presence of a
wildcard character in the pattern.
Reviewers: jhenderson, MaskRay, evgeny777, espindola, alexshap
Reviewed By: MaskRay
Subscribers: peter.smith, grimar, ruiu, emaste, arichardson, hiraditya, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D72517
2020-01-11 00:56:07 +08:00
|
|
|
SingleStringMatcher m(ver.name);
|
2021-08-05 14:52:55 +08:00
|
|
|
auto check = [&](StringRef name) {
|
|
|
|
size_t pos = name.find('@');
|
|
|
|
if (!includeNonDefault)
|
|
|
|
return pos == StringRef::npos;
|
|
|
|
return !(pos + 1 < name.size() && name[pos + 1] == '@');
|
|
|
|
};
|
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()))
|
2021-08-05 14:52:55 +08:00
|
|
|
for (Symbol *sym : p.second)
|
|
|
|
if (check(sym->getName()))
|
|
|
|
res.push_back(sym);
|
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)
|
2021-08-05 14:52:55 +08:00
|
|
|
if (canBeVersioned(*sym) && check(sym->getName()) &&
|
|
|
|
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
|
|
|
}
|
|
|
|
|
2017-09-09 02:16:59 +08:00
|
|
|
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)
|
2021-08-05 14:52:55 +08:00
|
|
|
syms = findAllByVersion(ver, /*includeNonDefault=*/true);
|
2017-12-06 08:14:04 +08:00
|
|
|
else
|
|
|
|
syms = findByVersion(ver);
|
2017-09-09 02:16:59 +08:00
|
|
|
|
2019-08-13 17:12:52 +08:00
|
|
|
for (Symbol *sym : syms)
|
|
|
|
sym->inDynamicList = true;
|
2017-09-09 02:16:59 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-08-05 14:52:55 +08:00
|
|
|
// 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) {
|
2016-11-17 10:09:42 +08:00
|
|
|
// 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-11-17 10:09:42 +08:00
|
|
|
|
2019-07-11 19:16:44 +08:00
|
|
|
auto getName = [](uint16_t ver) -> std::string {
|
|
|
|
if (ver == VER_NDX_LOCAL)
|
|
|
|
return "VER_NDX_LOCAL";
|
|
|
|
if (ver == VER_NDX_GLOBAL)
|
|
|
|
return "VER_NDX_GLOBAL";
|
2019-08-05 22:31:39 +08:00
|
|
|
return ("version '" + config->versionDefinitions[ver].name + "'").str();
|
2019-07-11 19:16:44 +08:00
|
|
|
};
|
|
|
|
|
2016-11-17 10:09:42 +08:00
|
|
|
// Assign the version.
|
2017-11-04 05:21:47 +08:00
|
|
|
for (Symbol *sym : syms) {
|
2021-08-05 14:52:55 +08:00
|
|
|
// 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('@'))
|
2017-07-12 21:54:42 +08:00
|
|
|
continue;
|
|
|
|
|
2019-08-05 22:31:39 +08:00
|
|
|
// If the version has not been assigned, verdefIndex is -1. Use an arbitrary
|
|
|
|
// number (0) to indicate the version has been assigned.
|
2021-12-16 09:59:30 +08:00
|
|
|
if (sym->verdefIndex == uint16_t(-1)) {
|
2019-08-05 22:31:39 +08:00
|
|
|
sym->verdefIndex = 0;
|
2019-07-11 19:16:44 +08:00
|
|
|
sym->versionId = versionId;
|
2019-08-05 22:31:39 +08:00
|
|
|
}
|
2019-07-11 19:16:44 +08:00
|
|
|
if (sym->versionId == versionId)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
warn("attempt to reassign symbol '" + ver.name + "' of " +
|
|
|
|
getName(sym->versionId) + " to " + getName(versionId));
|
2016-11-17 10:09:42 +08:00
|
|
|
}
|
2021-08-05 14:52:55 +08:00
|
|
|
return !syms.empty();
|
2016-11-17 10:09:42 +08:00
|
|
|
}
|
|
|
|
|
2021-08-05 14:52:55 +08:00
|
|
|
void SymbolTable::assignWildcardVersion(SymbolVersion ver, uint16_t versionId,
|
|
|
|
bool includeNonDefault) {
|
2019-10-29 09:41:38 +08:00
|
|
|
// Exact matching takes precedence over fuzzy matching,
|
2016-11-16 02:41:52 +08:00
|
|
|
// so we set a version to a symbol only if no version has been assigned
|
|
|
|
// to the symbol. This behavior is compatible with GNU.
|
2021-08-05 14:52:55 +08:00
|
|
|
for (Symbol *sym : findAllByVersion(ver, includeNonDefault))
|
2021-12-16 09:59:30 +08:00
|
|
|
if (sym->verdefIndex == uint16_t(-1)) {
|
2019-08-05 22:31:39 +08:00
|
|
|
sym->verdefIndex = 0;
|
|
|
|
sym->versionId = versionId;
|
|
|
|
}
|
2016-11-16 02:41:52 +08:00
|
|
|
}
|
|
|
|
|
2019-07-16 13:50:45 +08:00
|
|
|
// This function processes version scripts by updating the versionId
|
2016-09-03 06:15:08 +08:00
|
|
|
// member of symbols.
|
2019-07-11 19:16:51 +08:00
|
|
|
// If there's only one anonymous version definition in a version
|
|
|
|
// script file, the script does not actually define any symbol version,
|
|
|
|
// but just specifies symbols visibilities.
|
2017-07-27 02:42:48 +08:00
|
|
|
void SymbolTable::scanVersionScript() {
|
2021-08-05 14:52:55 +08:00
|
|
|
SmallString<128> buf;
|
2016-09-03 06:15:08 +08:00
|
|
|
// First, we assign versions to exact matching symbols,
|
|
|
|
// i.e. version definitions not containing any glob meta-characters.
|
2021-08-05 14:52:55 +08:00
|
|
|
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");
|
|
|
|
}
|
2019-08-05 22:31:39 +08:00
|
|
|
|
|
|
|
// 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.
|
2021-08-05 14:52:55 +08:00
|
|
|
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)
|
2019-08-05 22:31:39 +08:00
|
|
|
if (pat.hasWildcard && pat.name != "*")
|
2021-08-05 14:52:55 +08:00
|
|
|
assignWildcard(pat, v.id, v.name);
|
|
|
|
for (SymbolVersion &pat : v.localPatterns)
|
|
|
|
if (pat.hasWildcard && pat.name != "*")
|
|
|
|
assignWildcard(pat, VER_NDX_LOCAL, v.name);
|
|
|
|
}
|
2019-08-05 22:31:39 +08:00
|
|
|
|
|
|
|
// Then, assign versions to "*". In GNU linkers they have lower priority than
|
|
|
|
// other wildcards.
|
2021-08-05 14:52:55 +08:00
|
|
|
for (VersionDefinition &v : config->versionDefinitions) {
|
|
|
|
for (SymbolVersion &pat : v.nonLocalPatterns)
|
2019-08-05 22:31:39 +08:00
|
|
|
if (pat.hasWildcard && pat.name == "*")
|
2021-08-05 14:52:55 +08:00
|
|
|
assignWildcard(pat, v.id, v.name);
|
|
|
|
for (SymbolVersion &pat : v.localPatterns)
|
|
|
|
if (pat.hasWildcard && pat.name == "*")
|
|
|
|
assignWildcard(pat, VER_NDX_LOCAL, v.name);
|
|
|
|
}
|
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();
|
2019-07-11 19:16:51 +08:00
|
|
|
|
|
|
|
// isPreemptible is false at this point. To correctly compute the binding of a
|
|
|
|
// Defined (which is used by includeInDynsym()), we need to know if it is
|
2019-08-05 22:31:39 +08:00
|
|
|
// VER_NDX_LOCAL or not. Compute symbol versions before handling
|
|
|
|
// --dynamic-list.
|
2019-07-11 19:16:51 +08:00
|
|
|
handleDynamicList();
|
2016-04-23 04:21:26 +08:00
|
|
|
}
|