]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lld/COFF/SymbolTable.cpp
MFV r339640,339641,339644:
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / lld / COFF / SymbolTable.cpp
1 //===- SymbolTable.cpp ----------------------------------------------------===//
2 //
3 //                             The LLVM Linker
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #include "SymbolTable.h"
11 #include "Config.h"
12 #include "Driver.h"
13 #include "LTO.h"
14 #include "Symbols.h"
15 #include "lld/Common/ErrorHandler.h"
16 #include "lld/Common/Memory.h"
17 #include "llvm/IR/LLVMContext.h"
18 #include "llvm/Support/Debug.h"
19 #include "llvm/Support/raw_ostream.h"
20 #include <utility>
21
22 using namespace llvm;
23
24 namespace lld {
25 namespace coff {
26
27 SymbolTable *Symtab;
28
29 void SymbolTable::addFile(InputFile *File) {
30   log("Reading " + toString(File));
31   File->parse();
32
33   MachineTypes MT = File->getMachineType();
34   if (Config->Machine == IMAGE_FILE_MACHINE_UNKNOWN) {
35     Config->Machine = MT;
36   } else if (MT != IMAGE_FILE_MACHINE_UNKNOWN && Config->Machine != MT) {
37     fatal(toString(File) + ": machine type " + machineToStr(MT) +
38           " conflicts with " + machineToStr(Config->Machine));
39   }
40
41   if (auto *F = dyn_cast<ObjFile>(File)) {
42     ObjFile::Instances.push_back(F);
43   } else if (auto *F = dyn_cast<BitcodeFile>(File)) {
44     BitcodeFile::Instances.push_back(F);
45   } else if (auto *F = dyn_cast<ImportFile>(File)) {
46     ImportFile::Instances.push_back(F);
47   }
48
49   StringRef S = File->getDirectives();
50   if (S.empty())
51     return;
52
53   log("Directives: " + toString(File) + ": " + S);
54   Driver->parseDirectives(S);
55 }
56
57 static void errorOrWarn(const Twine &S) {
58   if (Config->Force)
59     warn(S);
60   else
61     error(S);
62 }
63
64 void SymbolTable::reportRemainingUndefines() {
65   SmallPtrSet<Symbol *, 8> Undefs;
66   DenseMap<Symbol *, Symbol *> LocalImports;
67
68   for (auto &I : SymMap) {
69     Symbol *Sym = I.second;
70     auto *Undef = dyn_cast<Undefined>(Sym);
71     if (!Undef)
72       continue;
73     if (!Sym->IsUsedInRegularObj)
74       continue;
75
76     StringRef Name = Undef->getName();
77
78     // A weak alias may have been resolved, so check for that.
79     if (Defined *D = Undef->getWeakAlias()) {
80       // We want to replace Sym with D. However, we can't just blindly
81       // copy sizeof(SymbolUnion) bytes from D to Sym because D may be an
82       // internal symbol, and internal symbols are stored as "unparented"
83       // Symbols. For that reason we need to check which type of symbol we
84       // are dealing with and copy the correct number of bytes.
85       if (isa<DefinedRegular>(D))
86         memcpy(Sym, D, sizeof(DefinedRegular));
87       else if (isa<DefinedAbsolute>(D))
88         memcpy(Sym, D, sizeof(DefinedAbsolute));
89       else
90         memcpy(Sym, D, sizeof(SymbolUnion));
91       continue;
92     }
93
94     // If we can resolve a symbol by removing __imp_ prefix, do that.
95     // This odd rule is for compatibility with MSVC linker.
96     if (Name.startswith("__imp_")) {
97       Symbol *Imp = find(Name.substr(strlen("__imp_")));
98       if (Imp && isa<Defined>(Imp)) {
99         auto *D = cast<Defined>(Imp);
100         replaceSymbol<DefinedLocalImport>(Sym, Name, D);
101         LocalImportChunks.push_back(cast<DefinedLocalImport>(Sym)->getChunk());
102         LocalImports[Sym] = D;
103         continue;
104       }
105     }
106
107     // Remaining undefined symbols are not fatal if /force is specified.
108     // They are replaced with dummy defined symbols.
109     if (Config->Force)
110       replaceSymbol<DefinedAbsolute>(Sym, Name, 0);
111     Undefs.insert(Sym);
112   }
113
114   if (Undefs.empty() && LocalImports.empty())
115     return;
116
117   for (Symbol *B : Config->GCRoot) {
118     if (Undefs.count(B))
119       errorOrWarn("<root>: undefined symbol: " + B->getName());
120     if (Config->WarnLocallyDefinedImported)
121       if (Symbol *Imp = LocalImports.lookup(B))
122         warn("<root>: locally defined symbol imported: " + Imp->getName() +
123              " (defined in " + toString(Imp->getFile()) + ")");
124   }
125
126   for (ObjFile *File : ObjFile::Instances) {
127     for (Symbol *Sym : File->getSymbols()) {
128       if (!Sym)
129         continue;
130       if (Undefs.count(Sym))
131         errorOrWarn(toString(File) + ": undefined symbol: " + Sym->getName());
132       if (Config->WarnLocallyDefinedImported)
133         if (Symbol *Imp = LocalImports.lookup(Sym))
134           warn(toString(File) + ": locally defined symbol imported: " +
135                Imp->getName() + " (defined in " + toString(Imp->getFile()) +
136                ")");
137     }
138   }
139 }
140
141 std::pair<Symbol *, bool> SymbolTable::insert(StringRef Name) {
142   Symbol *&Sym = SymMap[CachedHashStringRef(Name)];
143   if (Sym)
144     return {Sym, false};
145   Sym = (Symbol *)make<SymbolUnion>();
146   Sym->IsUsedInRegularObj = false;
147   Sym->PendingArchiveLoad = false;
148   return {Sym, true};
149 }
150
151 Symbol *SymbolTable::addUndefined(StringRef Name, InputFile *F,
152                                   bool IsWeakAlias) {
153   Symbol *S;
154   bool WasInserted;
155   std::tie(S, WasInserted) = insert(Name);
156   if (!F || !isa<BitcodeFile>(F))
157     S->IsUsedInRegularObj = true;
158   if (WasInserted || (isa<Lazy>(S) && IsWeakAlias)) {
159     replaceSymbol<Undefined>(S, Name);
160     return S;
161   }
162   if (auto *L = dyn_cast<Lazy>(S)) {
163     if (!S->PendingArchiveLoad) {
164       S->PendingArchiveLoad = true;
165       L->File->addMember(&L->Sym);
166     }
167   }
168   return S;
169 }
170
171 void SymbolTable::addLazy(ArchiveFile *F, const Archive::Symbol Sym) {
172   StringRef Name = Sym.getName();
173   Symbol *S;
174   bool WasInserted;
175   std::tie(S, WasInserted) = insert(Name);
176   if (WasInserted) {
177     replaceSymbol<Lazy>(S, F, Sym);
178     return;
179   }
180   auto *U = dyn_cast<Undefined>(S);
181   if (!U || U->WeakAlias || S->PendingArchiveLoad)
182     return;
183   S->PendingArchiveLoad = true;
184   F->addMember(&Sym);
185 }
186
187 void SymbolTable::reportDuplicate(Symbol *Existing, InputFile *NewFile) {
188   error("duplicate symbol: " + toString(*Existing) + " in " +
189         toString(Existing->getFile()) + " and in " + toString(NewFile));
190 }
191
192 Symbol *SymbolTable::addAbsolute(StringRef N, COFFSymbolRef Sym) {
193   Symbol *S;
194   bool WasInserted;
195   std::tie(S, WasInserted) = insert(N);
196   S->IsUsedInRegularObj = true;
197   if (WasInserted || isa<Undefined>(S) || isa<Lazy>(S))
198     replaceSymbol<DefinedAbsolute>(S, N, Sym);
199   else if (!isa<DefinedCOFF>(S))
200     reportDuplicate(S, nullptr);
201   return S;
202 }
203
204 Symbol *SymbolTable::addAbsolute(StringRef N, uint64_t VA) {
205   Symbol *S;
206   bool WasInserted;
207   std::tie(S, WasInserted) = insert(N);
208   S->IsUsedInRegularObj = true;
209   if (WasInserted || isa<Undefined>(S) || isa<Lazy>(S))
210     replaceSymbol<DefinedAbsolute>(S, N, VA);
211   else if (!isa<DefinedCOFF>(S))
212     reportDuplicate(S, nullptr);
213   return S;
214 }
215
216 Symbol *SymbolTable::addSynthetic(StringRef N, Chunk *C) {
217   Symbol *S;
218   bool WasInserted;
219   std::tie(S, WasInserted) = insert(N);
220   S->IsUsedInRegularObj = true;
221   if (WasInserted || isa<Undefined>(S) || isa<Lazy>(S))
222     replaceSymbol<DefinedSynthetic>(S, N, C);
223   else if (!isa<DefinedCOFF>(S))
224     reportDuplicate(S, nullptr);
225   return S;
226 }
227
228 Symbol *SymbolTable::addRegular(InputFile *F, StringRef N,
229                                 const coff_symbol_generic *Sym,
230                                 SectionChunk *C) {
231   Symbol *S;
232   bool WasInserted;
233   std::tie(S, WasInserted) = insert(N);
234   if (!isa<BitcodeFile>(F))
235     S->IsUsedInRegularObj = true;
236   if (WasInserted || !isa<DefinedRegular>(S))
237     replaceSymbol<DefinedRegular>(S, F, N, /*IsCOMDAT*/ false,
238                                   /*IsExternal*/ true, Sym, C);
239   else
240     reportDuplicate(S, F);
241   return S;
242 }
243
244 std::pair<Symbol *, bool>
245 SymbolTable::addComdat(InputFile *F, StringRef N,
246                        const coff_symbol_generic *Sym) {
247   Symbol *S;
248   bool WasInserted;
249   std::tie(S, WasInserted) = insert(N);
250   if (!isa<BitcodeFile>(F))
251     S->IsUsedInRegularObj = true;
252   if (WasInserted || !isa<DefinedRegular>(S)) {
253     replaceSymbol<DefinedRegular>(S, F, N, /*IsCOMDAT*/ true,
254                                   /*IsExternal*/ true, Sym, nullptr);
255     return {S, true};
256   }
257   if (!cast<DefinedRegular>(S)->isCOMDAT())
258     reportDuplicate(S, F);
259   return {S, false};
260 }
261
262 Symbol *SymbolTable::addCommon(InputFile *F, StringRef N, uint64_t Size,
263                                const coff_symbol_generic *Sym, CommonChunk *C) {
264   Symbol *S;
265   bool WasInserted;
266   std::tie(S, WasInserted) = insert(N);
267   if (!isa<BitcodeFile>(F))
268     S->IsUsedInRegularObj = true;
269   if (WasInserted || !isa<DefinedCOFF>(S))
270     replaceSymbol<DefinedCommon>(S, F, N, Size, Sym, C);
271   else if (auto *DC = dyn_cast<DefinedCommon>(S))
272     if (Size > DC->getSize())
273       replaceSymbol<DefinedCommon>(S, F, N, Size, Sym, C);
274   return S;
275 }
276
277 DefinedImportData *SymbolTable::addImportData(StringRef N, ImportFile *F) {
278   Symbol *S;
279   bool WasInserted;
280   std::tie(S, WasInserted) = insert(N);
281   S->IsUsedInRegularObj = true;
282   if (WasInserted || isa<Undefined>(S) || isa<Lazy>(S)) {
283     replaceSymbol<DefinedImportData>(S, N, F);
284     return cast<DefinedImportData>(S);
285   }
286
287   reportDuplicate(S, F);
288   return nullptr;
289 }
290
291 DefinedImportThunk *SymbolTable::addImportThunk(StringRef Name,
292                                                DefinedImportData *ID,
293                                                uint16_t Machine) {
294   Symbol *S;
295   bool WasInserted;
296   std::tie(S, WasInserted) = insert(Name);
297   S->IsUsedInRegularObj = true;
298   if (WasInserted || isa<Undefined>(S) || isa<Lazy>(S)) {
299     replaceSymbol<DefinedImportThunk>(S, Name, ID, Machine);
300     return cast<DefinedImportThunk>(S);
301   }
302
303   reportDuplicate(S, ID->File);
304   return nullptr;
305 }
306
307 std::vector<Chunk *> SymbolTable::getChunks() {
308   std::vector<Chunk *> Res;
309   for (ObjFile *File : ObjFile::Instances) {
310     ArrayRef<Chunk *> V = File->getChunks();
311     Res.insert(Res.end(), V.begin(), V.end());
312   }
313   return Res;
314 }
315
316 Symbol *SymbolTable::find(StringRef Name) {
317   auto It = SymMap.find(CachedHashStringRef(Name));
318   if (It == SymMap.end())
319     return nullptr;
320   return It->second;
321 }
322
323 Symbol *SymbolTable::findUnderscore(StringRef Name) {
324   if (Config->Machine == I386)
325     return find(("_" + Name).str());
326   return find(Name);
327 }
328
329 StringRef SymbolTable::findByPrefix(StringRef Prefix) {
330   for (auto Pair : SymMap) {
331     StringRef Name = Pair.first.val();
332     if (Name.startswith(Prefix))
333       return Name;
334   }
335   return "";
336 }
337
338 StringRef SymbolTable::findMangle(StringRef Name) {
339   if (Symbol *Sym = find(Name))
340     if (!isa<Undefined>(Sym))
341       return Name;
342   if (Config->Machine != I386)
343     return findByPrefix(("?" + Name + "@@Y").str());
344   if (!Name.startswith("_"))
345     return "";
346   // Search for x86 stdcall function.
347   StringRef S = findByPrefix((Name + "@").str());
348   if (!S.empty())
349     return S;
350   // Search for x86 fastcall function.
351   S = findByPrefix(("@" + Name.substr(1) + "@").str());
352   if (!S.empty())
353     return S;
354   // Search for x86 vectorcall function.
355   S = findByPrefix((Name.substr(1) + "@@").str());
356   if (!S.empty())
357     return S;
358   // Search for x86 C++ non-member function.
359   return findByPrefix(("?" + Name.substr(1) + "@@Y").str());
360 }
361
362 void SymbolTable::mangleMaybe(Symbol *B) {
363   auto *U = dyn_cast<Undefined>(B);
364   if (!U || U->WeakAlias)
365     return;
366   StringRef Alias = findMangle(U->getName());
367   if (!Alias.empty()) {
368     log(U->getName() + " aliased to " + Alias);
369     U->WeakAlias = addUndefined(Alias);
370   }
371 }
372
373 Symbol *SymbolTable::addUndefined(StringRef Name) {
374   return addUndefined(Name, nullptr, false);
375 }
376
377 std::vector<StringRef> SymbolTable::compileBitcodeFiles() {
378   LTO.reset(new BitcodeCompiler);
379   for (BitcodeFile *F : BitcodeFile::Instances)
380     LTO->add(*F);
381   return LTO->compile();
382 }
383
384 void SymbolTable::addCombinedLTOObjects() {
385   if (BitcodeFile::Instances.empty())
386     return;
387   for (StringRef Object : compileBitcodeFiles()) {
388     auto *Obj = make<ObjFile>(MemoryBufferRef(Object, "lto.tmp"));
389     Obj->parse();
390     ObjFile::Instances.push_back(Obj);
391   }
392 }
393
394 } // namespace coff
395 } // namespace lld