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
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 archive
49// files whose archive members are not yet loaded).
50//
51// We put all symbols of all files to a SymbolTable, and the
52// SymbolTable selects the "best" symbols if there are name
53// conflicts. For example, obviously, a defined symbol is better than
54// an undefined symbol. Or, if there's a conflict between a lazy and a
55// undefined, it'll read an archive member to read a real definition
56// to replace the lazy symbol. The logic is implemented in the
57// 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 table
69 // accordingly, then print an error message for any remaining undefined
70 // 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 for
77 // 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 its
88 // mangled symbol. This function tries to find a mangled name
89 // for U from the symbol table, and if found, set the symbol as
90 // 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 to
101 // choose the right one depending on which "main" function is defined.
102 // This function looks up the symbol table and resolve corresponding
103 // entry point name.
104 StringRef findDefaultEntry();
105 WindowsSubsystem inferSubsystem();
106
107 // Build a set of COFF objects representing the combined contents of
108 // BitcodeFiles and add them to the symbol table. Called after all files are
109 // 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 symbol
208 /// 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 void
224 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::coff
235
236#endif
237