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