xref: /freebsd/contrib/llvm-project/lld/ELF/SymbolTable.h (revision 0b57cec536236d46e3dba9bd041533462f33dbb7)
1*0b57cec5SDimitry Andric //===- SymbolTable.h --------------------------------------------*- C++ -*-===//
2*0b57cec5SDimitry Andric //
3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*0b57cec5SDimitry Andric //
7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
8*0b57cec5SDimitry Andric 
9*0b57cec5SDimitry Andric #ifndef LLD_ELF_SYMBOL_TABLE_H
10*0b57cec5SDimitry Andric #define LLD_ELF_SYMBOL_TABLE_H
11*0b57cec5SDimitry Andric 
12*0b57cec5SDimitry Andric #include "InputFiles.h"
13*0b57cec5SDimitry Andric #include "Symbols.h"
14*0b57cec5SDimitry Andric #include "lld/Common/Strings.h"
15*0b57cec5SDimitry Andric #include "llvm/ADT/CachedHashString.h"
16*0b57cec5SDimitry Andric #include "llvm/ADT/DenseMap.h"
17*0b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h"
18*0b57cec5SDimitry Andric 
19*0b57cec5SDimitry Andric namespace lld {
20*0b57cec5SDimitry Andric namespace elf {
21*0b57cec5SDimitry Andric 
22*0b57cec5SDimitry Andric // SymbolTable is a bucket of all known symbols, including defined,
23*0b57cec5SDimitry Andric // undefined, or lazy symbols (the last one is symbols in archive
24*0b57cec5SDimitry Andric // files whose archive members are not yet loaded).
25*0b57cec5SDimitry Andric //
26*0b57cec5SDimitry Andric // We put all symbols of all files to a SymbolTable, and the
27*0b57cec5SDimitry Andric // SymbolTable selects the "best" symbols if there are name
28*0b57cec5SDimitry Andric // conflicts. For example, obviously, a defined symbol is better than
29*0b57cec5SDimitry Andric // an undefined symbol. Or, if there's a conflict between a lazy and a
30*0b57cec5SDimitry Andric // undefined, it'll read an archive member to read a real definition
31*0b57cec5SDimitry Andric // to replace the lazy symbol. The logic is implemented in the
32*0b57cec5SDimitry Andric // add*() functions, which are called by input files as they are parsed. There
33*0b57cec5SDimitry Andric // is one add* function per symbol type.
34*0b57cec5SDimitry Andric class SymbolTable {
35*0b57cec5SDimitry Andric public:
36*0b57cec5SDimitry Andric   void wrap(Symbol *sym, Symbol *real, Symbol *wrap);
37*0b57cec5SDimitry Andric 
38*0b57cec5SDimitry Andric   void forEachSymbol(llvm::function_ref<void(Symbol *)> fn) {
39*0b57cec5SDimitry Andric     for (Symbol *sym : symVector)
40*0b57cec5SDimitry Andric       if (!sym->isPlaceholder())
41*0b57cec5SDimitry Andric         fn(sym);
42*0b57cec5SDimitry Andric   }
43*0b57cec5SDimitry Andric 
44*0b57cec5SDimitry Andric   Symbol *insert(StringRef name);
45*0b57cec5SDimitry Andric 
46*0b57cec5SDimitry Andric   Symbol *addSymbol(const Symbol &New);
47*0b57cec5SDimitry Andric 
48*0b57cec5SDimitry Andric   void scanVersionScript();
49*0b57cec5SDimitry Andric 
50*0b57cec5SDimitry Andric   Symbol *find(StringRef name);
51*0b57cec5SDimitry Andric 
52*0b57cec5SDimitry Andric   void handleDynamicList();
53*0b57cec5SDimitry Andric 
54*0b57cec5SDimitry Andric   // Set of .so files to not link the same shared object file more than once.
55*0b57cec5SDimitry Andric   llvm::DenseMap<StringRef, SharedFile *> soNames;
56*0b57cec5SDimitry Andric 
57*0b57cec5SDimitry Andric   // Comdat groups define "link once" sections. If two comdat groups have the
58*0b57cec5SDimitry Andric   // same name, only one of them is linked, and the other is ignored. This map
59*0b57cec5SDimitry Andric   // is used to uniquify them.
60*0b57cec5SDimitry Andric   llvm::DenseMap<llvm::CachedHashStringRef, const InputFile *> comdatGroups;
61*0b57cec5SDimitry Andric 
62*0b57cec5SDimitry Andric private:
63*0b57cec5SDimitry Andric   std::vector<Symbol *> findByVersion(SymbolVersion ver);
64*0b57cec5SDimitry Andric   std::vector<Symbol *> findAllByVersion(SymbolVersion ver);
65*0b57cec5SDimitry Andric 
66*0b57cec5SDimitry Andric   llvm::StringMap<std::vector<Symbol *>> &getDemangledSyms();
67*0b57cec5SDimitry Andric   void assignExactVersion(SymbolVersion ver, uint16_t versionId,
68*0b57cec5SDimitry Andric                           StringRef versionName);
69*0b57cec5SDimitry Andric   void assignWildcardVersion(SymbolVersion ver, uint16_t versionId);
70*0b57cec5SDimitry Andric 
71*0b57cec5SDimitry Andric   // The order the global symbols are in is not defined. We can use an arbitrary
72*0b57cec5SDimitry Andric   // order, but it has to be reproducible. That is true even when cross linking.
73*0b57cec5SDimitry Andric   // The default hashing of StringRef produces different results on 32 and 64
74*0b57cec5SDimitry Andric   // bit systems so we use a map to a vector. That is arbitrary, deterministic
75*0b57cec5SDimitry Andric   // but a bit inefficient.
76*0b57cec5SDimitry Andric   // FIXME: Experiment with passing in a custom hashing or sorting the symbols
77*0b57cec5SDimitry Andric   // once symbol resolution is finished.
78*0b57cec5SDimitry Andric   llvm::DenseMap<llvm::CachedHashStringRef, int> symMap;
79*0b57cec5SDimitry Andric   std::vector<Symbol *> symVector;
80*0b57cec5SDimitry Andric 
81*0b57cec5SDimitry Andric   // A map from demangled symbol names to their symbol objects.
82*0b57cec5SDimitry Andric   // This mapping is 1:N because two symbols with different versions
83*0b57cec5SDimitry Andric   // can have the same name. We use this map to handle "extern C++ {}"
84*0b57cec5SDimitry Andric   // directive in version scripts.
85*0b57cec5SDimitry Andric   llvm::Optional<llvm::StringMap<std::vector<Symbol *>>> demangledSyms;
86*0b57cec5SDimitry Andric };
87*0b57cec5SDimitry Andric 
88*0b57cec5SDimitry Andric extern SymbolTable *symtab;
89*0b57cec5SDimitry Andric 
90*0b57cec5SDimitry Andric } // namespace elf
91*0b57cec5SDimitry Andric } // namespace lld
92*0b57cec5SDimitry Andric 
93*0b57cec5SDimitry Andric #endif
94