237 lines · c
1//===- SymbolTable.h --------------------------------------------*- C++ -*-===//2//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-exception6//7//===----------------------------------------------------------------------===//8 9#ifndef LLD_COFF_SYMBOL_TABLE_H10#define LLD_COFF_SYMBOL_TABLE_H11 12#include "InputFiles.h"13#include "LTO.h"14#include "llvm/ADT/CachedHashString.h"15#include "llvm/ADT/DenseMap.h"16#include "llvm/ADT/DenseMapInfo.h"17#include "llvm/ADT/SmallPtrSet.h"18#include "llvm/Support/raw_ostream.h"19 20namespace llvm {21struct LTOCodeGenerator;22}23 24namespace lld::coff {25 26class Chunk;27class CommonChunk;28class COFFLinkerContext;29class Defined;30class DefinedAbsolute;31class DefinedRegular;32class ImportThunkChunk;33class LazyArchive;34class SameAddressThunkARM64EC;35class SectionChunk;36class Symbol;37 38// This data structure is instantiated for each -wrap option.39struct WrappedSymbol {40 Symbol *sym;41 Symbol *real;42 Symbol *wrap;43};44 45struct UndefinedDiag;46 47// SymbolTable is a bucket of all known symbols, including defined,48// undefined, or lazy symbols (the last one is symbols in archive49// files whose archive members are not yet loaded).50//51// We put all symbols of all files to a SymbolTable, and the52// SymbolTable selects the "best" symbols if there are name53// conflicts. For example, obviously, a defined symbol is better than54// an undefined symbol. Or, if there's a conflict between a lazy and a55// undefined, it'll read an archive member to read a real definition56// to replace the lazy symbol. The logic is implemented in the57// add*() functions, which are called by input files as they are parsed.58// There is one add* function per symbol type.59class SymbolTable {60public:61 SymbolTable(COFFLinkerContext &c,62 llvm::COFF::MachineTypes machine = IMAGE_FILE_MACHINE_UNKNOWN)63 : ctx(c), machine(machine) {}64 65 // Emit errors for symbols that cannot be resolved.66 void reportUnresolvable();67 68 // Try to resolve any undefined symbols and update the symbol table69 // accordingly, then print an error message for any remaining undefined70 // symbols and warn about imported local symbols.71 void resolveRemainingUndefines(std::vector<Undefined *> &aliases);72 73 // Try to resolve undefined symbols with alternate names.74 void resolveAlternateNames();75 76 // Load lazy objects that are needed for MinGW automatic import and for77 // doing stdcall fixups.78 void loadMinGWSymbols();79 bool handleMinGWAutomaticImport(Symbol *sym, StringRef name);80 81 // Returns a symbol for a given name. Returns a nullptr if not found.82 Symbol *find(StringRef name) const;83 Symbol *findUnderscore(StringRef name) const;84 85 void addUndefinedGlob(StringRef arg);86 87 // Occasionally we have to resolve an undefined symbol to its88 // mangled symbol. This function tries to find a mangled name89 // for U from the symbol table, and if found, set the symbol as90 // a weak alias for U.91 Symbol *findMangle(StringRef name);92 StringRef mangleMaybe(Symbol *s);93 94 // Symbol names are mangled by prepending "_" on x86.95 StringRef mangle(StringRef sym);96 97 // Windows specific -- "main" is not the only main function in Windows.98 // You can choose one from these four -- {w,}{WinMain,main}.99 // There are four different entry point functions for them,100 // {w,}{WinMain,main}CRTStartup, respectively. The linker needs to101 // choose the right one depending on which "main" function is defined.102 // This function looks up the symbol table and resolve corresponding103 // entry point name.104 StringRef findDefaultEntry();105 WindowsSubsystem inferSubsystem();106 107 // Build a set of COFF objects representing the combined contents of108 // BitcodeFiles and add them to the symbol table. Called after all files are109 // added and before the writer writes results to a file.110 void compileBitcodeFiles();111 112 // Creates an Undefined symbol and marks it as live.113 Symbol *addGCRoot(StringRef sym, bool aliasEC = false);114 115 // Creates an Undefined symbol for a given name.116 Symbol *addUndefined(StringRef name);117 118 Symbol *addSynthetic(StringRef n, Chunk *c);119 Symbol *addAbsolute(StringRef n, uint64_t va);120 121 Symbol *addUndefined(StringRef name, InputFile *f, bool overrideLazy);122 void addLazyArchive(ArchiveFile *f, const Archive::Symbol &sym);123 void addLazyObject(InputFile *f, StringRef n);124 void addLazyDLLSymbol(DLLFile *f, DLLFile::Symbol *sym, StringRef n);125 Symbol *addAbsolute(StringRef n, COFFSymbolRef s);126 Symbol *addRegular(InputFile *f, StringRef n,127 const llvm::object::coff_symbol_generic *s = nullptr,128 SectionChunk *c = nullptr, uint32_t sectionOffset = 0,129 bool isWeak = false);130 std::pair<DefinedRegular *, bool>131 addComdat(InputFile *f, StringRef n,132 const llvm::object::coff_symbol_generic *s = nullptr);133 Symbol *addCommon(InputFile *f, StringRef n, uint64_t size,134 const llvm::object::coff_symbol_generic *s = nullptr,135 CommonChunk *c = nullptr);136 DefinedImportData *addImportData(StringRef n, ImportFile *f,137 Chunk *&location);138 Defined *addImportThunk(StringRef name, DefinedImportData *s,139 ImportThunkChunk *chunk);140 void addLibcall(StringRef name);141 void addEntryThunk(Symbol *from, Symbol *to);142 void addExitThunk(Symbol *from, Symbol *to);143 void initializeECThunks();144 void initializeSameAddressThunks();145 146 void reportDuplicate(Symbol *existing, InputFile *newFile,147 SectionChunk *newSc = nullptr,148 uint32_t newSectionOffset = 0);149 150 COFFLinkerContext &ctx;151 llvm::COFF::MachineTypes machine;152 153 bool isEC() const { return machine == ARM64EC; }154 155 // An entry point symbol.156 Symbol *entry = nullptr;157 158 // A list of chunks which to be added to .rdata.159 std::vector<Chunk *> localImportChunks;160 161 // A list of EC EXP+ symbols.162 std::vector<Symbol *> expSymbols;163 164 std::vector<SameAddressThunkARM64EC *> sameAddressThunks;165 166 // A list of DLL exports.167 std::vector<Export> exports;168 llvm::DenseSet<StringRef> directivesExports;169 bool hadExplicitExports;170 171 Chunk *edataStart = nullptr;172 Chunk *edataEnd = nullptr;173 174 Symbol *delayLoadHelper = nullptr;175 Chunk *tailMergeUnwindInfoChunk = nullptr;176 177 // A list of wrapped symbols.178 std::vector<WrappedSymbol> wrapped;179 180 // Used for /alternatename.181 std::map<StringRef, StringRef> alternateNames;182 183 // Used for /aligncomm.184 std::map<std::string, int> alignComm;185 186 void fixupExports();187 void assignExportOrdinals();188 void parseModuleDefs(StringRef path);189 void parseAlternateName(StringRef);190 void parseAligncomm(StringRef);191 192 // Iterates symbols in non-determinstic hash table order.193 template <typename T> void forEachSymbol(T callback) {194 for (auto &pair : symMap)195 callback(pair.second);196 }197 198 std::vector<BitcodeFile *> bitcodeFileInstances;199 200 DefinedRegular *loadConfigSym = nullptr;201 uint32_t loadConfigSize = 0;202 void initializeLoadConfig();203 204 std::string printSymbol(Symbol *sym) const;205 206private:207 /// Given a name without "__imp_" prefix, returns a defined symbol208 /// with the "__imp_" prefix, if it exists.209 Defined *impSymbol(StringRef name);210 /// Inserts symbol if not already present.211 std::pair<Symbol *, bool> insert(StringRef name);212 /// Same as insert(Name), but also sets isUsedInRegularObj.213 std::pair<Symbol *, bool> insert(StringRef name, InputFile *f);214 215 bool findUnderscoreMangle(StringRef sym);216 std::vector<Symbol *> getSymsWithPrefix(StringRef prefix);217 218 llvm::DenseMap<llvm::CachedHashStringRef, Symbol *> symMap;219 std::unique_ptr<BitcodeCompiler> lto;220 std::vector<std::pair<Symbol *, Symbol *>> entryThunks;221 llvm::DenseMap<Symbol *, Symbol *> exitThunks;222 223 void224 reportProblemSymbols(const llvm::SmallPtrSetImpl<Symbol *> &undefs,225 const llvm::DenseMap<Symbol *, Symbol *> *localImports,226 bool needBitcodeFiles);227 void reportUndefinedSymbol(const UndefinedDiag &undefDiag);228};229 230std::vector<std::string> getSymbolLocations(ObjFile *file, uint32_t symIndex);231 232StringRef ltrim1(StringRef s, const char *chars);233 234} // namespace lld::coff235 236#endif237