Rafael Espindola | beee25e | 2015-08-14 14:12:54 +0000 | [diff] [blame] | 1 | //===- SymbolTable.h --------------------------------------------*- C++ -*-===// |
Michael J. Spencer | 84487f1 | 2015-07-24 21:03:07 +0000 | [diff] [blame] | 2 | // |
Chandler Carruth | 2946cd7 | 2019-01-19 08:50:56 +0000 | [diff] [blame] | 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| 4 | // See https://llvm.org/LICENSE.txt for license information. |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
Michael J. Spencer | 84487f1 | 2015-07-24 21:03:07 +0000 | [diff] [blame] | 6 | // |
| 7 | //===----------------------------------------------------------------------===// |
| 8 | |
| 9 | #ifndef LLD_ELF_SYMBOL_TABLE_H |
| 10 | #define LLD_ELF_SYMBOL_TABLE_H |
| 11 | |
| 12 | #include "InputFiles.h" |
Rui Ueyama | d8f8abb | 2019-05-28 06:33:06 +0000 | [diff] [blame] | 13 | #include "Symbols.h" |
Rui Ueyama | ee17371 | 2018-02-28 17:38:19 +0000 | [diff] [blame] | 14 | #include "lld/Common/Strings.h" |
Justin Lebar | 3c11e93 | 2016-10-18 17:50:36 +0000 | [diff] [blame] | 15 | #include "llvm/ADT/CachedHashString.h" |
Rafael Espindola | 7f0b727 | 2016-04-14 20:42:43 +0000 | [diff] [blame] | 16 | #include "llvm/ADT/DenseMap.h" |
Rui Ueyama | d8f8abb | 2019-05-28 06:33:06 +0000 | [diff] [blame] | 17 | #include "llvm/ADT/STLExtras.h" |
Michael J. Spencer | 84487f1 | 2015-07-24 21:03:07 +0000 | [diff] [blame] | 18 | |
| 19 | namespace lld { |
Rafael Espindola | e0df00b | 2016-02-28 00:25:54 +0000 | [diff] [blame] | 20 | namespace elf { |
Rui Ueyama | 7d47619 | 2019-05-16 02:14:00 +0000 | [diff] [blame] | 21 | |
Michael J. Spencer | 84487f1 | 2015-07-24 21:03:07 +0000 | [diff] [blame] | 22 | // SymbolTable is a bucket of all known symbols, including defined, |
| 23 | // undefined, or lazy symbols (the last one is symbols in archive |
| 24 | // files whose archive members are not yet loaded). |
| 25 | // |
| 26 | // We put all symbols of all files to a SymbolTable, and the |
| 27 | // SymbolTable selects the "best" symbols if there are name |
| 28 | // conflicts. For example, obviously, a defined symbol is better than |
| 29 | // an undefined symbol. Or, if there's a conflict between a lazy and a |
| 30 | // undefined, it'll read an archive member to read a real definition |
Peter Collingbourne | 4f95270 | 2016-05-01 04:55:03 +0000 | [diff] [blame] | 31 | // to replace the lazy symbol. The logic is implemented in the |
| 32 | // add*() functions, which are called by input files as they are parsed. There |
| 33 | // is one add* function per symbol type. |
Rafael Espindola | 244ef98 | 2017-07-26 18:42:48 +0000 | [diff] [blame] | 34 | class SymbolTable { |
Fangrui Song | a2fc964 | 2019-11-20 11:16:15 -0800 | [diff] [blame] | 35 | struct FilterOutPlaceholder { |
| 36 | bool operator()(Symbol *S) const { return !S->isPlaceholder(); } |
| 37 | }; |
| 38 | using iterator = llvm::filter_iterator<std::vector<Symbol *>::const_iterator, |
| 39 | FilterOutPlaceholder>; |
Michael J. Spencer | 84487f1 | 2015-07-24 21:03:07 +0000 | [diff] [blame] | 40 | |
Fangrui Song | a2fc964 | 2019-11-20 11:16:15 -0800 | [diff] [blame] | 41 | public: |
| 42 | llvm::iterator_range<iterator> symbols() const { |
| 43 | return llvm::make_filter_range(symVector, FilterOutPlaceholder()); |
Rui Ueyama | d8f8abb | 2019-05-28 06:33:06 +0000 | [diff] [blame] | 44 | } |
Rafael Espindola | 740fafe | 2015-09-08 19:43:27 +0000 | [diff] [blame] | 45 | |
Fangrui Song | a2fc964 | 2019-11-20 11:16:15 -0800 | [diff] [blame] | 46 | void wrap(Symbol *sym, Symbol *real, Symbol *wrap); |
| 47 | |
Rui Ueyama | 3837f42 | 2019-07-10 05:00:37 +0000 | [diff] [blame] | 48 | Symbol *insert(StringRef name); |
Rafael Espindola | 244ef98 | 2017-07-26 18:42:48 +0000 | [diff] [blame] | 49 | |
Fangrui Song | ab04ad6 | 2019-08-13 06:19:39 +0000 | [diff] [blame] | 50 | Symbol *addSymbol(const Symbol &newSym); |
Petr Hosek | 5e51f7d | 2017-02-21 22:32:51 +0000 | [diff] [blame] | 51 | |
Peter Collingbourne | 66ac1d6 | 2016-04-22 20:21:26 +0000 | [diff] [blame] | 52 | void scanVersionScript(); |
Rui Ueyama | d60dae8a | 2016-06-23 07:00:17 +0000 | [diff] [blame] | 53 | |
Rui Ueyama | 3837f42 | 2019-07-10 05:00:37 +0000 | [diff] [blame] | 54 | Symbol *find(StringRef name); |
Rui Ueyama | 69c778c | 2016-07-17 17:50:09 +0000 | [diff] [blame] | 55 | |
Rafael Espindola | d72d97b | 2017-09-08 18:16:59 +0000 | [diff] [blame] | 56 | void handleDynamicList(); |
| 57 | |
Fangrui Song | b4744d3 | 2019-02-01 02:25:05 +0000 | [diff] [blame] | 58 | // Set of .so files to not link the same shared object file more than once. |
Rui Ueyama | 3837f42 | 2019-07-10 05:00:37 +0000 | [diff] [blame] | 59 | llvm::DenseMap<StringRef, SharedFile *> soNames; |
Fangrui Song | b4744d3 | 2019-02-01 02:25:05 +0000 | [diff] [blame] | 60 | |
Fangrui Song | b72b091 | 2019-05-22 09:06:42 +0000 | [diff] [blame] | 61 | // Comdat groups define "link once" sections. If two comdat groups have the |
| 62 | // same name, only one of them is linked, and the other is ignored. This map |
| 63 | // is used to uniquify them. |
Rui Ueyama | 3837f42 | 2019-07-10 05:00:37 +0000 | [diff] [blame] | 64 | llvm::DenseMap<llvm::CachedHashStringRef, const InputFile *> comdatGroups; |
Fangrui Song | b72b091 | 2019-05-22 09:06:42 +0000 | [diff] [blame] | 65 | |
Michael J. Spencer | 84487f1 | 2015-07-24 21:03:07 +0000 | [diff] [blame] | 66 | private: |
Rui Ueyama | 3837f42 | 2019-07-10 05:00:37 +0000 | [diff] [blame] | 67 | std::vector<Symbol *> findByVersion(SymbolVersion ver); |
| 68 | std::vector<Symbol *> findAllByVersion(SymbolVersion ver); |
Rui Ueyama | 8249214 | 2016-11-15 18:41:52 +0000 | [diff] [blame] | 69 | |
Rui Ueyama | f52496e | 2017-11-03 21:21:47 +0000 | [diff] [blame] | 70 | llvm::StringMap<std::vector<Symbol *>> &getDemangledSyms(); |
Rui Ueyama | 3837f42 | 2019-07-10 05:00:37 +0000 | [diff] [blame] | 71 | void assignExactVersion(SymbolVersion ver, uint16_t versionId, |
| 72 | StringRef versionName); |
| 73 | void assignWildcardVersion(SymbolVersion ver, uint16_t versionId); |
George Rimar | 50dcece | 2016-07-16 12:26:39 +0000 | [diff] [blame] | 74 | |
Rafael Espindola | 40102eb | 2015-09-17 18:26:25 +0000 | [diff] [blame] | 75 | // The order the global symbols are in is not defined. We can use an arbitrary |
| 76 | // order, but it has to be reproducible. That is true even when cross linking. |
| 77 | // The default hashing of StringRef produces different results on 32 and 64 |
Rafael Espindola | 7f0b727 | 2016-04-14 20:42:43 +0000 | [diff] [blame] | 78 | // bit systems so we use a map to a vector. That is arbitrary, deterministic |
| 79 | // but a bit inefficient. |
Rafael Espindola | 40102eb | 2015-09-17 18:26:25 +0000 | [diff] [blame] | 80 | // FIXME: Experiment with passing in a custom hashing or sorting the symbols |
| 81 | // once symbol resolution is finished. |
Rui Ueyama | 3837f42 | 2019-07-10 05:00:37 +0000 | [diff] [blame] | 82 | llvm::DenseMap<llvm::CachedHashStringRef, int> symMap; |
| 83 | std::vector<Symbol *> symVector; |
Rafael Espindola | 222edc6 | 2015-09-03 18:56:20 +0000 | [diff] [blame] | 84 | |
Rui Ueyama | 8249214 | 2016-11-15 18:41:52 +0000 | [diff] [blame] | 85 | // A map from demangled symbol names to their symbol objects. |
| 86 | // This mapping is 1:N because two symbols with different versions |
| 87 | // can have the same name. We use this map to handle "extern C++ {}" |
| 88 | // directive in version scripts. |
Rui Ueyama | 3837f42 | 2019-07-10 05:00:37 +0000 | [diff] [blame] | 89 | llvm::Optional<llvm::StringMap<std::vector<Symbol *>>> demangledSyms; |
Michael J. Spencer | 84487f1 | 2015-07-24 21:03:07 +0000 | [diff] [blame] | 90 | }; |
| 91 | |
Rui Ueyama | 3837f42 | 2019-07-10 05:00:37 +0000 | [diff] [blame] | 92 | extern SymbolTable *symtab; |
Rui Ueyama | bbf154c | 2019-05-17 01:55:20 +0000 | [diff] [blame] | 93 | |
Rafael Espindola | e0df00b | 2016-02-28 00:25:54 +0000 | [diff] [blame] | 94 | } // namespace elf |
Michael J. Spencer | 84487f1 | 2015-07-24 21:03:07 +0000 | [diff] [blame] | 95 | } // namespace lld |
| 96 | |
| 97 | #endif |