1//===- SymbolTable.cpp ----------------------------------------------------===//
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#include "SymbolTable.h"
10#include "COFFLinkerContext.h"
11#include "Config.h"
12#include "Driver.h"
13#include "LTO.h"
14#include "PDB.h"
15#include "Symbols.h"
16#include "lld/Common/ErrorHandler.h"
17#include "lld/Common/Memory.h"
18#include "lld/Common/Timer.h"
19#include "llvm/DebugInfo/DIContext.h"
20#include "llvm/IR/LLVMContext.h"
21#include "llvm/LTO/LTO.h"
22#include "llvm/Support/Debug.h"
23#include "llvm/Support/raw_ostream.h"
24#include <utility>
25
26using namespace llvm;
27
28namespace lld::coff {
29
30StringRef ltrim1(StringRef s, const char *chars) {
31 if (!s.empty() && strchr(s: chars, c: s[0]))
32 return s.substr(Start: 1);
33 return s;
34}
35
36static bool compatibleMachineType(COFFLinkerContext &ctx, MachineTypes mt) {
37 if (mt == IMAGE_FILE_MACHINE_UNKNOWN)
38 return true;
39 switch (ctx.config.machine) {
40 case ARM64:
41 return mt == ARM64 || mt == ARM64X;
42 case ARM64EC:
43 return COFF::isArm64EC(Machine: mt) || mt == AMD64;
44 case ARM64X:
45 return COFF::isAnyArm64(Machine: mt) || mt == AMD64;
46 default:
47 return ctx.config.machine == mt;
48 }
49}
50
51void SymbolTable::addFile(InputFile *file) {
52 log(msg: "Reading " + toString(file));
53 if (file->lazy) {
54 if (auto *f = dyn_cast<BitcodeFile>(Val: file))
55 f->parseLazy();
56 else
57 cast<ObjFile>(Val: file)->parseLazy();
58 } else {
59 file->parse();
60 if (auto *f = dyn_cast<ObjFile>(Val: file)) {
61 ctx.objFileInstances.push_back(x: f);
62 } else if (auto *f = dyn_cast<BitcodeFile>(Val: file)) {
63 if (ltoCompilationDone) {
64 error(msg: "LTO object file " + toString(file) + " linked in after "
65 "doing LTO compilation.");
66 }
67 ctx.bitcodeFileInstances.push_back(x: f);
68 } else if (auto *f = dyn_cast<ImportFile>(Val: file)) {
69 ctx.importFileInstances.push_back(x: f);
70 }
71 }
72
73 MachineTypes mt = file->getMachineType();
74 if (ctx.config.machine == IMAGE_FILE_MACHINE_UNKNOWN) {
75 ctx.config.machine = mt;
76 ctx.driver.addWinSysRootLibSearchPaths();
77 } else if (!compatibleMachineType(ctx, mt)) {
78 error(msg: toString(file) + ": machine type " + machineToStr(MT: mt) +
79 " conflicts with " + machineToStr(MT: ctx.config.machine));
80 return;
81 }
82
83 ctx.driver.parseDirectives(file);
84}
85
86static void errorOrWarn(const Twine &s, bool forceUnresolved) {
87 if (forceUnresolved)
88 warn(msg: s);
89 else
90 error(msg: s);
91}
92
93// Causes the file associated with a lazy symbol to be linked in.
94static void forceLazy(Symbol *s) {
95 s->pendingArchiveLoad = true;
96 switch (s->kind()) {
97 case Symbol::Kind::LazyArchiveKind: {
98 auto *l = cast<LazyArchive>(Val: s);
99 l->file->addMember(sym: l->sym);
100 break;
101 }
102 case Symbol::Kind::LazyObjectKind: {
103 InputFile *file = cast<LazyObject>(Val: s)->file;
104 file->ctx.symtab.addFile(file);
105 break;
106 }
107 case Symbol::Kind::LazyDLLSymbolKind: {
108 auto *l = cast<LazyDLLSymbol>(Val: s);
109 l->file->makeImport(s: l->sym);
110 break;
111 }
112 default:
113 llvm_unreachable(
114 "symbol passed to forceLazy is not a LazyArchive or LazyObject");
115 }
116}
117
118// Returns the symbol in SC whose value is <= Addr that is closest to Addr.
119// This is generally the global variable or function whose definition contains
120// Addr.
121static Symbol *getSymbol(SectionChunk *sc, uint32_t addr) {
122 DefinedRegular *candidate = nullptr;
123
124 for (Symbol *s : sc->file->getSymbols()) {
125 auto *d = dyn_cast_or_null<DefinedRegular>(Val: s);
126 if (!d || !d->data || d->file != sc->file || d->getChunk() != sc ||
127 d->getValue() > addr ||
128 (candidate && d->getValue() < candidate->getValue()))
129 continue;
130
131 candidate = d;
132 }
133
134 return candidate;
135}
136
137static std::vector<std::string> getSymbolLocations(BitcodeFile *file) {
138 std::string res("\n>>> referenced by ");
139 StringRef source = file->obj->getSourceFileName();
140 if (!source.empty())
141 res += source.str() + "\n>>> ";
142 res += toString(file);
143 return {res};
144}
145
146static std::optional<std::pair<StringRef, uint32_t>>
147getFileLineDwarf(const SectionChunk *c, uint32_t addr) {
148 std::optional<DILineInfo> optionalLineInfo =
149 c->file->getDILineInfo(offset: addr, sectionIndex: c->getSectionNumber() - 1);
150 if (!optionalLineInfo)
151 return std::nullopt;
152 const DILineInfo &lineInfo = *optionalLineInfo;
153 if (lineInfo.FileName == DILineInfo::BadString)
154 return std::nullopt;
155 return std::make_pair(x: saver().save(S: lineInfo.FileName), y: lineInfo.Line);
156}
157
158static std::optional<std::pair<StringRef, uint32_t>>
159getFileLine(const SectionChunk *c, uint32_t addr) {
160 // MinGW can optionally use codeview, even if the default is dwarf.
161 std::optional<std::pair<StringRef, uint32_t>> fileLine =
162 getFileLineCodeView(c, addr);
163 // If codeview didn't yield any result, check dwarf in MinGW mode.
164 if (!fileLine && c->file->ctx.config.mingw)
165 fileLine = getFileLineDwarf(c, addr);
166 return fileLine;
167}
168
169// Given a file and the index of a symbol in that file, returns a description
170// of all references to that symbol from that file. If no debug information is
171// available, returns just the name of the file, else one string per actual
172// reference as described in the debug info.
173// Returns up to maxStrings string descriptions, along with the total number of
174// locations found.
175static std::pair<std::vector<std::string>, size_t>
176getSymbolLocations(ObjFile *file, uint32_t symIndex, size_t maxStrings) {
177 struct Location {
178 Symbol *sym;
179 std::pair<StringRef, uint32_t> fileLine;
180 };
181 std::vector<Location> locations;
182 size_t numLocations = 0;
183
184 for (Chunk *c : file->getChunks()) {
185 auto *sc = dyn_cast<SectionChunk>(Val: c);
186 if (!sc)
187 continue;
188 for (const coff_relocation &r : sc->getRelocs()) {
189 if (r.SymbolTableIndex != symIndex)
190 continue;
191 numLocations++;
192 if (locations.size() >= maxStrings)
193 continue;
194
195 std::optional<std::pair<StringRef, uint32_t>> fileLine =
196 getFileLine(c: sc, addr: r.VirtualAddress);
197 Symbol *sym = getSymbol(sc, addr: r.VirtualAddress);
198 if (fileLine)
199 locations.push_back(x: {.sym: sym, .fileLine: *fileLine});
200 else if (sym)
201 locations.push_back(x: {.sym: sym, .fileLine: {"", 0}});
202 }
203 }
204
205 if (maxStrings == 0)
206 return std::make_pair(x: std::vector<std::string>(), y&: numLocations);
207
208 if (numLocations == 0)
209 return std::make_pair(
210 x: std::vector<std::string>{"\n>>> referenced by " + toString(file)}, y: 1);
211
212 std::vector<std::string> symbolLocations(locations.size());
213 size_t i = 0;
214 for (Location loc : locations) {
215 llvm::raw_string_ostream os(symbolLocations[i++]);
216 os << "\n>>> referenced by ";
217 if (!loc.fileLine.first.empty())
218 os << loc.fileLine.first << ":" << loc.fileLine.second
219 << "\n>>> ";
220 os << toString(file);
221 if (loc.sym)
222 os << ":(" << toString(ctx: file->ctx, b&: *loc.sym) << ')';
223 }
224 return std::make_pair(x&: symbolLocations, y&: numLocations);
225}
226
227std::vector<std::string> getSymbolLocations(ObjFile *file, uint32_t symIndex) {
228 return getSymbolLocations(file, symIndex, SIZE_MAX).first;
229}
230
231static std::pair<std::vector<std::string>, size_t>
232getSymbolLocations(InputFile *file, uint32_t symIndex, size_t maxStrings) {
233 if (auto *o = dyn_cast<ObjFile>(Val: file))
234 return getSymbolLocations(file: o, symIndex, maxStrings);
235 if (auto *b = dyn_cast<BitcodeFile>(Val: file)) {
236 std::vector<std::string> symbolLocations = getSymbolLocations(file: b);
237 size_t numLocations = symbolLocations.size();
238 if (symbolLocations.size() > maxStrings)
239 symbolLocations.resize(new_size: maxStrings);
240 return std::make_pair(x&: symbolLocations, y&: numLocations);
241 }
242 llvm_unreachable("unsupported file type passed to getSymbolLocations");
243 return std::make_pair(x: std::vector<std::string>(), y: (size_t)0);
244}
245
246// For an undefined symbol, stores all files referencing it and the index of
247// the undefined symbol in each file.
248struct UndefinedDiag {
249 Symbol *sym;
250 struct File {
251 InputFile *file;
252 uint32_t symIndex;
253 };
254 std::vector<File> files;
255};
256
257static void reportUndefinedSymbol(const COFFLinkerContext &ctx,
258 const UndefinedDiag &undefDiag) {
259 std::string out;
260 llvm::raw_string_ostream os(out);
261 os << "undefined symbol: " << toString(ctx, b&: *undefDiag.sym);
262
263 const size_t maxUndefReferences = 3;
264 size_t numDisplayedRefs = 0, numRefs = 0;
265 for (const UndefinedDiag::File &ref : undefDiag.files) {
266 auto [symbolLocations, totalLocations] = getSymbolLocations(
267 file: ref.file, symIndex: ref.symIndex, maxStrings: maxUndefReferences - numDisplayedRefs);
268
269 numRefs += totalLocations;
270 numDisplayedRefs += symbolLocations.size();
271 for (const std::string &s : symbolLocations) {
272 os << s;
273 }
274 }
275 if (numDisplayedRefs < numRefs)
276 os << "\n>>> referenced " << numRefs - numDisplayedRefs << " more times";
277 errorOrWarn(s: os.str(), forceUnresolved: ctx.config.forceUnresolved);
278}
279
280void SymbolTable::loadMinGWSymbols() {
281 for (auto &i : symMap) {
282 Symbol *sym = i.second;
283 auto *undef = dyn_cast<Undefined>(Val: sym);
284 if (!undef)
285 continue;
286 if (undef->getWeakAlias())
287 continue;
288
289 StringRef name = undef->getName();
290
291 if (ctx.config.machine == I386 && ctx.config.stdcallFixup) {
292 // Check if we can resolve an undefined decorated symbol by finding
293 // the intended target as an undecorated symbol (only with a leading
294 // underscore).
295 StringRef origName = name;
296 StringRef baseName = name;
297 // Trim down stdcall/fastcall/vectorcall symbols to the base name.
298 baseName = ltrim1(s: baseName, chars: "_@");
299 baseName = baseName.substr(Start: 0, N: baseName.find(C: '@'));
300 // Add a leading underscore, as it would be in cdecl form.
301 std::string newName = ("_" + baseName).str();
302 Symbol *l;
303 if (newName != origName && (l = find(name: newName)) != nullptr) {
304 // If we found a symbol and it is lazy; load it.
305 if (l->isLazy() && !l->pendingArchiveLoad) {
306 log(msg: "Loading lazy " + l->getName() + " from " +
307 l->getFile()->getName() + " for stdcall fixup");
308 forceLazy(s: l);
309 }
310 // If it's lazy or already defined, hook it up as weak alias.
311 if (l->isLazy() || isa<Defined>(Val: l)) {
312 if (ctx.config.warnStdcallFixup)
313 warn(msg: "Resolving " + origName + " by linking to " + newName);
314 else
315 log(msg: "Resolving " + origName + " by linking to " + newName);
316 undef->weakAlias = l;
317 continue;
318 }
319 }
320 }
321
322 if (ctx.config.autoImport) {
323 if (name.starts_with(Prefix: "__imp_"))
324 continue;
325 // If we have an undefined symbol, but we have a lazy symbol we could
326 // load, load it.
327 Symbol *l = find(name: ("__imp_" + name).str());
328 if (!l || l->pendingArchiveLoad || !l->isLazy())
329 continue;
330
331 log(msg: "Loading lazy " + l->getName() + " from " + l->getFile()->getName() +
332 " for automatic import");
333 forceLazy(s: l);
334 }
335 }
336}
337
338Defined *SymbolTable::impSymbol(StringRef name) {
339 if (name.starts_with(Prefix: "__imp_"))
340 return nullptr;
341 return dyn_cast_or_null<Defined>(Val: find(name: ("__imp_" + name).str()));
342}
343
344bool SymbolTable::handleMinGWAutomaticImport(Symbol *sym, StringRef name) {
345 Defined *imp = impSymbol(name);
346 if (!imp)
347 return false;
348
349 // Replace the reference directly to a variable with a reference
350 // to the import address table instead. This obviously isn't right,
351 // but we mark the symbol as isRuntimePseudoReloc, and a later pass
352 // will add runtime pseudo relocations for every relocation against
353 // this Symbol. The runtime pseudo relocation framework expects the
354 // reference itself to point at the IAT entry.
355 size_t impSize = 0;
356 if (isa<DefinedImportData>(Val: imp)) {
357 log(msg: "Automatically importing " + name + " from " +
358 cast<DefinedImportData>(Val: imp)->getDLLName());
359 impSize = sizeof(DefinedImportData);
360 } else if (isa<DefinedRegular>(Val: imp)) {
361 log(msg: "Automatically importing " + name + " from " +
362 toString(file: cast<DefinedRegular>(Val: imp)->file));
363 impSize = sizeof(DefinedRegular);
364 } else {
365 warn(msg: "unable to automatically import " + name + " from " + imp->getName() +
366 " from " + toString(file: cast<DefinedRegular>(Val: imp)->file) +
367 "; unexpected symbol type");
368 return false;
369 }
370 sym->replaceKeepingName(other: imp, size: impSize);
371 sym->isRuntimePseudoReloc = true;
372
373 // There may exist symbols named .refptr.<name> which only consist
374 // of a single pointer to <name>. If it turns out <name> is
375 // automatically imported, we don't need to keep the .refptr.<name>
376 // pointer at all, but redirect all accesses to it to the IAT entry
377 // for __imp_<name> instead, and drop the whole .refptr.<name> chunk.
378 DefinedRegular *refptr =
379 dyn_cast_or_null<DefinedRegular>(Val: find(name: (".refptr." + name).str()));
380 if (refptr && refptr->getChunk()->getSize() == ctx.config.wordsize) {
381 SectionChunk *sc = dyn_cast_or_null<SectionChunk>(Val: refptr->getChunk());
382 if (sc && sc->getRelocs().size() == 1 && *sc->symbols().begin() == sym) {
383 log(msg: "Replacing .refptr." + name + " with " + imp->getName());
384 refptr->getChunk()->live = false;
385 refptr->replaceKeepingName(other: imp, size: impSize);
386 }
387 }
388 return true;
389}
390
391/// Helper function for reportUnresolvable and resolveRemainingUndefines.
392/// This function emits an "undefined symbol" diagnostic for each symbol in
393/// undefs. If localImports is not nullptr, it also emits a "locally
394/// defined symbol imported" diagnostic for symbols in localImports.
395/// objFiles and bitcodeFiles (if not nullptr) are used to report where
396/// undefined symbols are referenced.
397static void reportProblemSymbols(
398 const COFFLinkerContext &ctx, const SmallPtrSetImpl<Symbol *> &undefs,
399 const DenseMap<Symbol *, Symbol *> *localImports, bool needBitcodeFiles) {
400 // Return early if there is nothing to report (which should be
401 // the common case).
402 if (undefs.empty() && (!localImports || localImports->empty()))
403 return;
404
405 for (Symbol *b : ctx.config.gcroot) {
406 if (undefs.count(Ptr: b))
407 errorOrWarn(s: "<root>: undefined symbol: " + toString(ctx, b&: *b),
408 forceUnresolved: ctx.config.forceUnresolved);
409 if (localImports)
410 if (Symbol *imp = localImports->lookup(Val: b))
411 warn(msg: "<root>: locally defined symbol imported: " + toString(ctx, b&: *imp) +
412 " (defined in " + toString(file: imp->getFile()) + ") [LNK4217]");
413 }
414
415 std::vector<UndefinedDiag> undefDiags;
416 DenseMap<Symbol *, int> firstDiag;
417
418 auto processFile = [&](InputFile *file, ArrayRef<Symbol *> symbols) {
419 uint32_t symIndex = (uint32_t)-1;
420 for (Symbol *sym : symbols) {
421 ++symIndex;
422 if (!sym)
423 continue;
424 if (undefs.count(Ptr: sym)) {
425 auto it = firstDiag.find(Val: sym);
426 if (it == firstDiag.end()) {
427 firstDiag[sym] = undefDiags.size();
428 undefDiags.push_back(x: {.sym: sym, .files: {{.file: file, .symIndex: symIndex}}});
429 } else {
430 undefDiags[it->second].files.push_back(x: {.file: file, .symIndex: symIndex});
431 }
432 }
433 if (localImports)
434 if (Symbol *imp = localImports->lookup(Val: sym))
435 warn(msg: toString(file) +
436 ": locally defined symbol imported: " + toString(ctx, b&: *imp) +
437 " (defined in " + toString(file: imp->getFile()) + ") [LNK4217]");
438 }
439 };
440
441 for (ObjFile *file : ctx.objFileInstances)
442 processFile(file, file->getSymbols());
443
444 if (needBitcodeFiles)
445 for (BitcodeFile *file : ctx.bitcodeFileInstances)
446 processFile(file, file->getSymbols());
447
448 for (const UndefinedDiag &undefDiag : undefDiags)
449 reportUndefinedSymbol(ctx, undefDiag);
450}
451
452void SymbolTable::reportUnresolvable() {
453 SmallPtrSet<Symbol *, 8> undefs;
454 for (auto &i : symMap) {
455 Symbol *sym = i.second;
456 auto *undef = dyn_cast<Undefined>(Val: sym);
457 if (!undef || sym->deferUndefined)
458 continue;
459 if (undef->getWeakAlias())
460 continue;
461 StringRef name = undef->getName();
462 if (name.starts_with(Prefix: "__imp_")) {
463 Symbol *imp = find(name: name.substr(Start: strlen(s: "__imp_")));
464 if (Defined *def = dyn_cast_or_null<Defined>(Val: imp)) {
465 def->isUsedInRegularObj = true;
466 continue;
467 }
468 }
469 if (name.contains(Other: "_PchSym_"))
470 continue;
471 if (ctx.config.autoImport && impSymbol(name))
472 continue;
473 undefs.insert(Ptr: sym);
474 }
475
476 reportProblemSymbols(ctx, undefs,
477 /* localImports */ nullptr, needBitcodeFiles: true);
478}
479
480void SymbolTable::resolveRemainingUndefines() {
481 llvm::TimeTraceScope timeScope("Resolve remaining undefined symbols");
482 SmallPtrSet<Symbol *, 8> undefs;
483 DenseMap<Symbol *, Symbol *> localImports;
484
485 for (auto &i : symMap) {
486 Symbol *sym = i.second;
487 auto *undef = dyn_cast<Undefined>(Val: sym);
488 if (!undef)
489 continue;
490 if (!sym->isUsedInRegularObj)
491 continue;
492
493 StringRef name = undef->getName();
494
495 // A weak alias may have been resolved, so check for that.
496 if (Defined *d = undef->getWeakAlias()) {
497 // We want to replace Sym with D. However, we can't just blindly
498 // copy sizeof(SymbolUnion) bytes from D to Sym because D may be an
499 // internal symbol, and internal symbols are stored as "unparented"
500 // Symbols. For that reason we need to check which type of symbol we
501 // are dealing with and copy the correct number of bytes.
502 if (isa<DefinedRegular>(Val: d))
503 memcpy(dest: sym, src: d, n: sizeof(DefinedRegular));
504 else if (isa<DefinedAbsolute>(Val: d))
505 memcpy(dest: sym, src: d, n: sizeof(DefinedAbsolute));
506 else
507 memcpy(dest: sym, src: d, n: sizeof(SymbolUnion));
508 continue;
509 }
510
511 // If we can resolve a symbol by removing __imp_ prefix, do that.
512 // This odd rule is for compatibility with MSVC linker.
513 if (name.starts_with(Prefix: "__imp_")) {
514 Symbol *imp = find(name: name.substr(Start: strlen(s: "__imp_")));
515 if (imp && isa<Defined>(Val: imp)) {
516 auto *d = cast<Defined>(Val: imp);
517 replaceSymbol<DefinedLocalImport>(s: sym, arg&: ctx, arg&: name, arg&: d);
518 localImportChunks.push_back(x: cast<DefinedLocalImport>(Val: sym)->getChunk());
519 localImports[sym] = d;
520 continue;
521 }
522 }
523
524 // We don't want to report missing Microsoft precompiled headers symbols.
525 // A proper message will be emitted instead in PDBLinker::aquirePrecompObj
526 if (name.contains(Other: "_PchSym_"))
527 continue;
528
529 if (ctx.config.autoImport && handleMinGWAutomaticImport(sym, name))
530 continue;
531
532 // Remaining undefined symbols are not fatal if /force is specified.
533 // They are replaced with dummy defined symbols.
534 if (ctx.config.forceUnresolved)
535 replaceSymbol<DefinedAbsolute>(s: sym, arg&: ctx, arg&: name, arg: 0);
536 undefs.insert(Ptr: sym);
537 }
538
539 reportProblemSymbols(
540 ctx, undefs,
541 localImports: ctx.config.warnLocallyDefinedImported ? &localImports : nullptr, needBitcodeFiles: false);
542}
543
544std::pair<Symbol *, bool> SymbolTable::insert(StringRef name) {
545 bool inserted = false;
546 Symbol *&sym = symMap[CachedHashStringRef(name)];
547 if (!sym) {
548 sym = reinterpret_cast<Symbol *>(make<SymbolUnion>());
549 sym->isUsedInRegularObj = false;
550 sym->pendingArchiveLoad = false;
551 sym->canInline = true;
552 inserted = true;
553 }
554 return {sym, inserted};
555}
556
557std::pair<Symbol *, bool> SymbolTable::insert(StringRef name, InputFile *file) {
558 std::pair<Symbol *, bool> result = insert(name);
559 if (!file || !isa<BitcodeFile>(Val: file))
560 result.first->isUsedInRegularObj = true;
561 return result;
562}
563
564Symbol *SymbolTable::addUndefined(StringRef name, InputFile *f,
565 bool isWeakAlias) {
566 auto [s, wasInserted] = insert(name, file: f);
567 if (wasInserted || (s->isLazy() && isWeakAlias)) {
568 replaceSymbol<Undefined>(s, arg&: name);
569 return s;
570 }
571 if (s->isLazy())
572 forceLazy(s);
573 return s;
574}
575
576void SymbolTable::addLazyArchive(ArchiveFile *f, const Archive::Symbol &sym) {
577 StringRef name = sym.getName();
578 auto [s, wasInserted] = insert(name);
579 if (wasInserted) {
580 replaceSymbol<LazyArchive>(s, arg&: f, arg: sym);
581 return;
582 }
583 auto *u = dyn_cast<Undefined>(Val: s);
584 if (!u || u->weakAlias || s->pendingArchiveLoad)
585 return;
586 s->pendingArchiveLoad = true;
587 f->addMember(sym);
588}
589
590void SymbolTable::addLazyObject(InputFile *f, StringRef n) {
591 assert(f->lazy);
592 auto [s, wasInserted] = insert(name: n, file: f);
593 if (wasInserted) {
594 replaceSymbol<LazyObject>(s, arg&: f, arg&: n);
595 return;
596 }
597 auto *u = dyn_cast<Undefined>(Val: s);
598 if (!u || u->weakAlias || s->pendingArchiveLoad)
599 return;
600 s->pendingArchiveLoad = true;
601 f->lazy = false;
602 addFile(file: f);
603}
604
605void SymbolTable::addLazyDLLSymbol(DLLFile *f, DLLFile::Symbol *sym,
606 StringRef n) {
607 auto [s, wasInserted] = insert(name: n);
608 if (wasInserted) {
609 replaceSymbol<LazyDLLSymbol>(s, arg&: f, arg&: sym, arg&: n);
610 return;
611 }
612 auto *u = dyn_cast<Undefined>(Val: s);
613 if (!u || u->weakAlias || s->pendingArchiveLoad)
614 return;
615 s->pendingArchiveLoad = true;
616 f->makeImport(s: sym);
617}
618
619static std::string getSourceLocationBitcode(BitcodeFile *file) {
620 std::string res("\n>>> defined at ");
621 StringRef source = file->obj->getSourceFileName();
622 if (!source.empty())
623 res += source.str() + "\n>>> ";
624 res += toString(file);
625 return res;
626}
627
628static std::string getSourceLocationObj(ObjFile *file, SectionChunk *sc,
629 uint32_t offset, StringRef name) {
630 std::optional<std::pair<StringRef, uint32_t>> fileLine;
631 if (sc)
632 fileLine = getFileLine(c: sc, addr: offset);
633 if (!fileLine)
634 fileLine = file->getVariableLocation(var: name);
635
636 std::string res;
637 llvm::raw_string_ostream os(res);
638 os << "\n>>> defined at ";
639 if (fileLine)
640 os << fileLine->first << ":" << fileLine->second << "\n>>> ";
641 os << toString(file);
642 return os.str();
643}
644
645static std::string getSourceLocation(InputFile *file, SectionChunk *sc,
646 uint32_t offset, StringRef name) {
647 if (!file)
648 return "";
649 if (auto *o = dyn_cast<ObjFile>(Val: file))
650 return getSourceLocationObj(file: o, sc, offset, name);
651 if (auto *b = dyn_cast<BitcodeFile>(Val: file))
652 return getSourceLocationBitcode(file: b);
653 return "\n>>> defined at " + toString(file);
654}
655
656// Construct and print an error message in the form of:
657//
658// lld-link: error: duplicate symbol: foo
659// >>> defined at bar.c:30
660// >>> bar.o
661// >>> defined at baz.c:563
662// >>> baz.o
663void SymbolTable::reportDuplicate(Symbol *existing, InputFile *newFile,
664 SectionChunk *newSc,
665 uint32_t newSectionOffset) {
666 std::string msg;
667 llvm::raw_string_ostream os(msg);
668 os << "duplicate symbol: " << toString(ctx, b&: *existing);
669
670 DefinedRegular *d = dyn_cast<DefinedRegular>(Val: existing);
671 if (d && isa<ObjFile>(Val: d->getFile())) {
672 os << getSourceLocation(file: d->getFile(), sc: d->getChunk(), offset: d->getValue(),
673 name: existing->getName());
674 } else {
675 os << getSourceLocation(file: existing->getFile(), sc: nullptr, offset: 0, name: "");
676 }
677 os << getSourceLocation(file: newFile, sc: newSc, offset: newSectionOffset,
678 name: existing->getName());
679
680 if (ctx.config.forceMultiple)
681 warn(msg: os.str());
682 else
683 error(msg: os.str());
684}
685
686Symbol *SymbolTable::addAbsolute(StringRef n, COFFSymbolRef sym) {
687 auto [s, wasInserted] = insert(name: n, file: nullptr);
688 s->isUsedInRegularObj = true;
689 if (wasInserted || isa<Undefined>(Val: s) || s->isLazy())
690 replaceSymbol<DefinedAbsolute>(s, arg&: ctx, arg&: n, arg&: sym);
691 else if (auto *da = dyn_cast<DefinedAbsolute>(Val: s)) {
692 if (da->getVA() != sym.getValue())
693 reportDuplicate(existing: s, newFile: nullptr);
694 } else if (!isa<DefinedCOFF>(Val: s))
695 reportDuplicate(existing: s, newFile: nullptr);
696 return s;
697}
698
699Symbol *SymbolTable::addAbsolute(StringRef n, uint64_t va) {
700 auto [s, wasInserted] = insert(name: n, file: nullptr);
701 s->isUsedInRegularObj = true;
702 if (wasInserted || isa<Undefined>(Val: s) || s->isLazy())
703 replaceSymbol<DefinedAbsolute>(s, arg&: ctx, arg&: n, arg&: va);
704 else if (auto *da = dyn_cast<DefinedAbsolute>(Val: s)) {
705 if (da->getVA() != va)
706 reportDuplicate(existing: s, newFile: nullptr);
707 } else if (!isa<DefinedCOFF>(Val: s))
708 reportDuplicate(existing: s, newFile: nullptr);
709 return s;
710}
711
712Symbol *SymbolTable::addSynthetic(StringRef n, Chunk *c) {
713 auto [s, wasInserted] = insert(name: n, file: nullptr);
714 s->isUsedInRegularObj = true;
715 if (wasInserted || isa<Undefined>(Val: s) || s->isLazy())
716 replaceSymbol<DefinedSynthetic>(s, arg&: n, arg&: c);
717 else if (!isa<DefinedCOFF>(Val: s))
718 reportDuplicate(existing: s, newFile: nullptr);
719 return s;
720}
721
722Symbol *SymbolTable::addRegular(InputFile *f, StringRef n,
723 const coff_symbol_generic *sym, SectionChunk *c,
724 uint32_t sectionOffset, bool isWeak) {
725 auto [s, wasInserted] = insert(name: n, file: f);
726 if (wasInserted || !isa<DefinedRegular>(Val: s) || s->isWeak)
727 replaceSymbol<DefinedRegular>(s, arg&: f, arg&: n, /*IsCOMDAT*/ arg: false,
728 /*IsExternal*/ arg: true, arg&: sym, arg&: c, arg&: isWeak);
729 else if (!isWeak)
730 reportDuplicate(existing: s, newFile: f, newSc: c, newSectionOffset: sectionOffset);
731 return s;
732}
733
734std::pair<DefinedRegular *, bool>
735SymbolTable::addComdat(InputFile *f, StringRef n,
736 const coff_symbol_generic *sym) {
737 auto [s, wasInserted] = insert(name: n, file: f);
738 if (wasInserted || !isa<DefinedRegular>(Val: s)) {
739 replaceSymbol<DefinedRegular>(s, arg&: f, arg&: n, /*IsCOMDAT*/ arg: true,
740 /*IsExternal*/ arg: true, arg&: sym, arg: nullptr);
741 return {cast<DefinedRegular>(Val: s), true};
742 }
743 auto *existingSymbol = cast<DefinedRegular>(Val: s);
744 if (!existingSymbol->isCOMDAT)
745 reportDuplicate(existing: s, newFile: f);
746 return {existingSymbol, false};
747}
748
749Symbol *SymbolTable::addCommon(InputFile *f, StringRef n, uint64_t size,
750 const coff_symbol_generic *sym, CommonChunk *c) {
751 auto [s, wasInserted] = insert(name: n, file: f);
752 if (wasInserted || !isa<DefinedCOFF>(Val: s))
753 replaceSymbol<DefinedCommon>(s, arg&: f, arg&: n, arg&: size, arg&: sym, arg&: c);
754 else if (auto *dc = dyn_cast<DefinedCommon>(Val: s))
755 if (size > dc->getSize())
756 replaceSymbol<DefinedCommon>(s, arg&: f, arg&: n, arg&: size, arg&: sym, arg&: c);
757 return s;
758}
759
760Symbol *SymbolTable::addImportData(StringRef n, ImportFile *f) {
761 auto [s, wasInserted] = insert(name: n, file: nullptr);
762 s->isUsedInRegularObj = true;
763 if (wasInserted || isa<Undefined>(Val: s) || s->isLazy()) {
764 replaceSymbol<DefinedImportData>(s, arg&: n, arg&: f);
765 return s;
766 }
767
768 reportDuplicate(existing: s, newFile: f);
769 return nullptr;
770}
771
772Symbol *SymbolTable::addImportThunk(StringRef name, DefinedImportData *id,
773 uint16_t machine) {
774 auto [s, wasInserted] = insert(name, file: nullptr);
775 s->isUsedInRegularObj = true;
776 if (wasInserted || isa<Undefined>(Val: s) || s->isLazy()) {
777 replaceSymbol<DefinedImportThunk>(s, arg&: ctx, arg&: name, arg&: id, arg&: machine);
778 return s;
779 }
780
781 reportDuplicate(existing: s, newFile: id->file);
782 return nullptr;
783}
784
785void SymbolTable::addLibcall(StringRef name) {
786 Symbol *sym = findUnderscore(name);
787 if (!sym)
788 return;
789
790 if (auto *l = dyn_cast<LazyArchive>(Val: sym)) {
791 MemoryBufferRef mb = l->getMemberBuffer();
792 if (isBitcode(mb))
793 addUndefined(name: sym->getName());
794 } else if (LazyObject *o = dyn_cast<LazyObject>(Val: sym)) {
795 if (isBitcode(mb: o->file->mb))
796 addUndefined(name: sym->getName());
797 }
798}
799
800std::vector<Chunk *> SymbolTable::getChunks() const {
801 std::vector<Chunk *> res;
802 for (ObjFile *file : ctx.objFileInstances) {
803 ArrayRef<Chunk *> v = file->getChunks();
804 res.insert(position: res.end(), first: v.begin(), last: v.end());
805 }
806 return res;
807}
808
809Symbol *SymbolTable::find(StringRef name) const {
810 return symMap.lookup(Val: CachedHashStringRef(name));
811}
812
813Symbol *SymbolTable::findUnderscore(StringRef name) const {
814 if (ctx.config.machine == I386)
815 return find(name: ("_" + name).str());
816 return find(name);
817}
818
819// Return all symbols that start with Prefix, possibly ignoring the first
820// character of Prefix or the first character symbol.
821std::vector<Symbol *> SymbolTable::getSymsWithPrefix(StringRef prefix) {
822 std::vector<Symbol *> syms;
823 for (auto pair : symMap) {
824 StringRef name = pair.first.val();
825 if (name.starts_with(Prefix: prefix) || name.starts_with(Prefix: prefix.drop_front()) ||
826 name.drop_front().starts_with(Prefix: prefix) ||
827 name.drop_front().starts_with(Prefix: prefix.drop_front())) {
828 syms.push_back(x: pair.second);
829 }
830 }
831 return syms;
832}
833
834Symbol *SymbolTable::findMangle(StringRef name) {
835 if (Symbol *sym = find(name)) {
836 if (auto *u = dyn_cast<Undefined>(Val: sym)) {
837 // We're specifically looking for weak aliases that ultimately resolve to
838 // defined symbols, hence the call to getWeakAlias() instead of just using
839 // the weakAlias member variable. This matches link.exe's behavior.
840 if (Symbol *weakAlias = u->getWeakAlias())
841 return weakAlias;
842 } else {
843 return sym;
844 }
845 }
846
847 // Efficient fuzzy string lookup is impossible with a hash table, so iterate
848 // the symbol table once and collect all possibly matching symbols into this
849 // vector. Then compare each possibly matching symbol with each possible
850 // mangling.
851 std::vector<Symbol *> syms = getSymsWithPrefix(prefix: name);
852 auto findByPrefix = [&syms](const Twine &t) -> Symbol * {
853 std::string prefix = t.str();
854 for (auto *s : syms)
855 if (s->getName().starts_with(Prefix: prefix))
856 return s;
857 return nullptr;
858 };
859
860 // For non-x86, just look for C++ functions.
861 if (ctx.config.machine != I386)
862 return findByPrefix("?" + name + "@@Y");
863
864 if (!name.starts_with(Prefix: "_"))
865 return nullptr;
866 // Search for x86 stdcall function.
867 if (Symbol *s = findByPrefix(name + "@"))
868 return s;
869 // Search for x86 fastcall function.
870 if (Symbol *s = findByPrefix("@" + name.substr(Start: 1) + "@"))
871 return s;
872 // Search for x86 vectorcall function.
873 if (Symbol *s = findByPrefix(name.substr(Start: 1) + "@@"))
874 return s;
875 // Search for x86 C++ non-member function.
876 return findByPrefix("?" + name.substr(Start: 1) + "@@Y");
877}
878
879Symbol *SymbolTable::addUndefined(StringRef name) {
880 return addUndefined(name, f: nullptr, isWeakAlias: false);
881}
882
883void SymbolTable::compileBitcodeFiles() {
884 ltoCompilationDone = true;
885 if (ctx.bitcodeFileInstances.empty())
886 return;
887
888 llvm::TimeTraceScope timeScope("Compile bitcode");
889 ScopedTimer t(ctx.ltoTimer);
890 lto.reset(p: new BitcodeCompiler(ctx));
891 for (BitcodeFile *f : ctx.bitcodeFileInstances)
892 lto->add(f&: *f);
893 for (InputFile *newObj : lto->compile()) {
894 ObjFile *obj = cast<ObjFile>(Val: newObj);
895 obj->parse();
896 ctx.objFileInstances.push_back(x: obj);
897 }
898}
899
900} // namespace lld::coff
901

source code of lld/COFF/SymbolTable.cpp