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