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