Mercurial > hg > CbC > CbC_llvm
diff lld/ELF/SymbolTable.h @ 150:1d019706d866
LLVM10
author | anatofuz |
---|---|
date | Thu, 13 Feb 2020 15:10:13 +0900 |
parents | |
children | c4bab56944e8 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lld/ELF/SymbolTable.h Thu Feb 13 15:10:13 2020 +0900 @@ -0,0 +1,97 @@ +//===- SymbolTable.h --------------------------------------------*- C++ -*-===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#ifndef LLD_ELF_SYMBOL_TABLE_H +#define LLD_ELF_SYMBOL_TABLE_H + +#include "InputFiles.h" +#include "Symbols.h" +#include "lld/Common/Strings.h" +#include "llvm/ADT/CachedHashString.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/STLExtras.h" + +namespace lld { +namespace elf { + +// SymbolTable is a bucket of all known symbols, including defined, +// undefined, or lazy symbols (the last one is symbols in archive +// files whose archive members are not yet loaded). +// +// We put all symbols of all files to a SymbolTable, and the +// SymbolTable selects the "best" symbols if there are name +// conflicts. For example, obviously, a defined symbol is better than +// an undefined symbol. Or, if there's a conflict between a lazy and a +// undefined, it'll read an archive member to read a real definition +// to replace the lazy symbol. The logic is implemented in the +// add*() functions, which are called by input files as they are parsed. There +// is one add* function per symbol type. +class SymbolTable { + struct FilterOutPlaceholder { + bool operator()(Symbol *S) const { return !S->isPlaceholder(); } + }; + using iterator = llvm::filter_iterator<std::vector<Symbol *>::const_iterator, + FilterOutPlaceholder>; + +public: + llvm::iterator_range<iterator> symbols() const { + return llvm::make_filter_range(symVector, FilterOutPlaceholder()); + } + + void wrap(Symbol *sym, Symbol *real, Symbol *wrap); + + Symbol *insert(StringRef name); + + Symbol *addSymbol(const Symbol &newSym); + + void scanVersionScript(); + + Symbol *find(StringRef name); + + void handleDynamicList(); + + // Set of .so files to not link the same shared object file more than once. + llvm::DenseMap<StringRef, SharedFile *> soNames; + + // Comdat groups define "link once" sections. If two comdat groups have the + // same name, only one of them is linked, and the other is ignored. This map + // is used to uniquify them. + llvm::DenseMap<llvm::CachedHashStringRef, const InputFile *> comdatGroups; + +private: + std::vector<Symbol *> findByVersion(SymbolVersion ver); + std::vector<Symbol *> findAllByVersion(SymbolVersion ver); + + llvm::StringMap<std::vector<Symbol *>> &getDemangledSyms(); + void assignExactVersion(SymbolVersion ver, uint16_t versionId, + StringRef versionName); + void assignWildcardVersion(SymbolVersion ver, uint16_t versionId); + + // The order the global symbols are in is not defined. We can use an arbitrary + // order, but it has to be reproducible. That is true even when cross linking. + // The default hashing of StringRef produces different results on 32 and 64 + // bit systems so we use a map to a vector. That is arbitrary, deterministic + // but a bit inefficient. + // FIXME: Experiment with passing in a custom hashing or sorting the symbols + // once symbol resolution is finished. + llvm::DenseMap<llvm::CachedHashStringRef, int> symMap; + std::vector<Symbol *> symVector; + + // A map from demangled symbol names to their symbol objects. + // This mapping is 1:N because two symbols with different versions + // can have the same name. We use this map to handle "extern C++ {}" + // directive in version scripts. + llvm::Optional<llvm::StringMap<std::vector<Symbol *>>> demangledSyms; +}; + +extern SymbolTable *symtab; + +} // namespace elf +} // namespace lld + +#endif