xref: /freebsd/contrib/llvm-project/lld/COFF/SymbolTable.cpp (revision 85868e8a1daeaae7a0e48effb2ea2310ae3b02c6)
10b57cec5SDimitry Andric //===- SymbolTable.cpp ----------------------------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "SymbolTable.h"
100b57cec5SDimitry Andric #include "Config.h"
110b57cec5SDimitry Andric #include "Driver.h"
120b57cec5SDimitry Andric #include "LTO.h"
130b57cec5SDimitry Andric #include "PDB.h"
140b57cec5SDimitry Andric #include "Symbols.h"
150b57cec5SDimitry Andric #include "lld/Common/ErrorHandler.h"
160b57cec5SDimitry Andric #include "lld/Common/Memory.h"
170b57cec5SDimitry Andric #include "lld/Common/Timer.h"
18*85868e8aSDimitry Andric #include "llvm/DebugInfo/Symbolize/Symbolize.h"
190b57cec5SDimitry Andric #include "llvm/IR/LLVMContext.h"
200b57cec5SDimitry Andric #include "llvm/Object/WindowsMachineFlag.h"
210b57cec5SDimitry Andric #include "llvm/Support/Debug.h"
220b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
230b57cec5SDimitry Andric #include <utility>
240b57cec5SDimitry Andric 
250b57cec5SDimitry Andric using namespace llvm;
260b57cec5SDimitry Andric 
270b57cec5SDimitry Andric namespace lld {
280b57cec5SDimitry Andric namespace coff {
290b57cec5SDimitry Andric 
300b57cec5SDimitry Andric static Timer ltoTimer("LTO", Timer::root());
310b57cec5SDimitry Andric 
320b57cec5SDimitry Andric SymbolTable *symtab;
330b57cec5SDimitry Andric 
340b57cec5SDimitry Andric void SymbolTable::addFile(InputFile *file) {
350b57cec5SDimitry Andric   log("Reading " + toString(file));
360b57cec5SDimitry Andric   file->parse();
370b57cec5SDimitry Andric 
380b57cec5SDimitry Andric   MachineTypes mt = file->getMachineType();
390b57cec5SDimitry Andric   if (config->machine == IMAGE_FILE_MACHINE_UNKNOWN) {
400b57cec5SDimitry Andric     config->machine = mt;
410b57cec5SDimitry Andric   } else if (mt != IMAGE_FILE_MACHINE_UNKNOWN && config->machine != mt) {
420b57cec5SDimitry Andric     error(toString(file) + ": machine type " + machineToStr(mt) +
430b57cec5SDimitry Andric           " conflicts with " + machineToStr(config->machine));
440b57cec5SDimitry Andric     return;
450b57cec5SDimitry Andric   }
460b57cec5SDimitry Andric 
470b57cec5SDimitry Andric   if (auto *f = dyn_cast<ObjFile>(file)) {
480b57cec5SDimitry Andric     ObjFile::instances.push_back(f);
490b57cec5SDimitry Andric   } else if (auto *f = dyn_cast<BitcodeFile>(file)) {
500b57cec5SDimitry Andric     BitcodeFile::instances.push_back(f);
510b57cec5SDimitry Andric   } else if (auto *f = dyn_cast<ImportFile>(file)) {
520b57cec5SDimitry Andric     ImportFile::instances.push_back(f);
530b57cec5SDimitry Andric   }
540b57cec5SDimitry Andric 
550b57cec5SDimitry Andric   driver->parseDirectives(file);
560b57cec5SDimitry Andric }
570b57cec5SDimitry Andric 
580b57cec5SDimitry Andric static void errorOrWarn(const Twine &s) {
590b57cec5SDimitry Andric   if (config->forceUnresolved)
600b57cec5SDimitry Andric     warn(s);
610b57cec5SDimitry Andric   else
620b57cec5SDimitry Andric     error(s);
630b57cec5SDimitry Andric }
640b57cec5SDimitry Andric 
65*85868e8aSDimitry Andric // Causes the file associated with a lazy symbol to be linked in.
66*85868e8aSDimitry Andric static void forceLazy(Symbol *s) {
67*85868e8aSDimitry Andric   s->pendingArchiveLoad = true;
68*85868e8aSDimitry Andric   switch (s->kind()) {
69*85868e8aSDimitry Andric   case Symbol::Kind::LazyArchiveKind: {
70*85868e8aSDimitry Andric     auto *l = cast<LazyArchive>(s);
71*85868e8aSDimitry Andric     l->file->addMember(l->sym);
72*85868e8aSDimitry Andric     break;
73*85868e8aSDimitry Andric   }
74*85868e8aSDimitry Andric   case Symbol::Kind::LazyObjectKind:
75*85868e8aSDimitry Andric     cast<LazyObject>(s)->file->fetch();
76*85868e8aSDimitry Andric     break;
77*85868e8aSDimitry Andric   default:
78*85868e8aSDimitry Andric     llvm_unreachable(
79*85868e8aSDimitry Andric         "symbol passed to forceLazy is not a LazyArchive or LazyObject");
80*85868e8aSDimitry Andric   }
81*85868e8aSDimitry Andric }
82*85868e8aSDimitry Andric 
830b57cec5SDimitry Andric // Returns the symbol in SC whose value is <= Addr that is closest to Addr.
840b57cec5SDimitry Andric // This is generally the global variable or function whose definition contains
850b57cec5SDimitry Andric // Addr.
860b57cec5SDimitry Andric static Symbol *getSymbol(SectionChunk *sc, uint32_t addr) {
870b57cec5SDimitry Andric   DefinedRegular *candidate = nullptr;
880b57cec5SDimitry Andric 
890b57cec5SDimitry Andric   for (Symbol *s : sc->file->getSymbols()) {
900b57cec5SDimitry Andric     auto *d = dyn_cast_or_null<DefinedRegular>(s);
91*85868e8aSDimitry Andric     if (!d || !d->data || d->file != sc->file || d->getChunk() != sc ||
92*85868e8aSDimitry Andric         d->getValue() > addr ||
930b57cec5SDimitry Andric         (candidate && d->getValue() < candidate->getValue()))
940b57cec5SDimitry Andric       continue;
950b57cec5SDimitry Andric 
960b57cec5SDimitry Andric     candidate = d;
970b57cec5SDimitry Andric   }
980b57cec5SDimitry Andric 
990b57cec5SDimitry Andric   return candidate;
1000b57cec5SDimitry Andric }
1010b57cec5SDimitry Andric 
102*85868e8aSDimitry Andric static std::vector<std::string> getSymbolLocations(BitcodeFile *file) {
103*85868e8aSDimitry Andric   std::string res("\n>>> referenced by ");
104*85868e8aSDimitry Andric   StringRef source = file->obj->getSourceFileName();
105*85868e8aSDimitry Andric   if (!source.empty())
106*85868e8aSDimitry Andric     res += source.str() + "\n>>>               ";
107*85868e8aSDimitry Andric   res += toString(file);
108*85868e8aSDimitry Andric   return {res};
109*85868e8aSDimitry Andric }
110*85868e8aSDimitry Andric 
111*85868e8aSDimitry Andric static Optional<std::pair<StringRef, uint32_t>>
112*85868e8aSDimitry Andric getFileLineDwarf(const SectionChunk *c, uint32_t addr) {
113*85868e8aSDimitry Andric   Optional<DILineInfo> optionalLineInfo =
114*85868e8aSDimitry Andric       c->file->getDILineInfo(addr, c->getSectionNumber() - 1);
115*85868e8aSDimitry Andric   if (!optionalLineInfo)
116*85868e8aSDimitry Andric     return None;
117*85868e8aSDimitry Andric   const DILineInfo &lineInfo = *optionalLineInfo;
118*85868e8aSDimitry Andric   if (lineInfo.FileName == DILineInfo::BadString)
119*85868e8aSDimitry Andric     return None;
120*85868e8aSDimitry Andric   return std::make_pair(saver.save(lineInfo.FileName), lineInfo.Line);
121*85868e8aSDimitry Andric }
122*85868e8aSDimitry Andric 
123*85868e8aSDimitry Andric static Optional<std::pair<StringRef, uint32_t>>
124*85868e8aSDimitry Andric getFileLine(const SectionChunk *c, uint32_t addr) {
125*85868e8aSDimitry Andric   // MinGW can optionally use codeview, even if the default is dwarf.
126*85868e8aSDimitry Andric   Optional<std::pair<StringRef, uint32_t>> fileLine =
127*85868e8aSDimitry Andric       getFileLineCodeView(c, addr);
128*85868e8aSDimitry Andric   // If codeview didn't yield any result, check dwarf in MinGW mode.
129*85868e8aSDimitry Andric   if (!fileLine && config->mingw)
130*85868e8aSDimitry Andric     fileLine = getFileLineDwarf(c, addr);
131*85868e8aSDimitry Andric   return fileLine;
132*85868e8aSDimitry Andric }
133*85868e8aSDimitry Andric 
1340b57cec5SDimitry Andric // Given a file and the index of a symbol in that file, returns a description
1350b57cec5SDimitry Andric // of all references to that symbol from that file. If no debug information is
1360b57cec5SDimitry Andric // available, returns just the name of the file, else one string per actual
1370b57cec5SDimitry Andric // reference as described in the debug info.
1380b57cec5SDimitry Andric std::vector<std::string> getSymbolLocations(ObjFile *file, uint32_t symIndex) {
1390b57cec5SDimitry Andric   struct Location {
1400b57cec5SDimitry Andric     Symbol *sym;
1410b57cec5SDimitry Andric     std::pair<StringRef, uint32_t> fileLine;
1420b57cec5SDimitry Andric   };
1430b57cec5SDimitry Andric   std::vector<Location> locations;
1440b57cec5SDimitry Andric 
1450b57cec5SDimitry Andric   for (Chunk *c : file->getChunks()) {
1460b57cec5SDimitry Andric     auto *sc = dyn_cast<SectionChunk>(c);
1470b57cec5SDimitry Andric     if (!sc)
1480b57cec5SDimitry Andric       continue;
1490b57cec5SDimitry Andric     for (const coff_relocation &r : sc->getRelocs()) {
1500b57cec5SDimitry Andric       if (r.SymbolTableIndex != symIndex)
1510b57cec5SDimitry Andric         continue;
152*85868e8aSDimitry Andric       Optional<std::pair<StringRef, uint32_t>> fileLine =
1530b57cec5SDimitry Andric           getFileLine(sc, r.VirtualAddress);
1540b57cec5SDimitry Andric       Symbol *sym = getSymbol(sc, r.VirtualAddress);
155*85868e8aSDimitry Andric       if (fileLine)
156*85868e8aSDimitry Andric         locations.push_back({sym, *fileLine});
157*85868e8aSDimitry Andric       else if (sym)
158*85868e8aSDimitry Andric         locations.push_back({sym, {"", 0}});
1590b57cec5SDimitry Andric     }
1600b57cec5SDimitry Andric   }
1610b57cec5SDimitry Andric 
1620b57cec5SDimitry Andric   if (locations.empty())
1630b57cec5SDimitry Andric     return std::vector<std::string>({"\n>>> referenced by " + toString(file)});
1640b57cec5SDimitry Andric 
1650b57cec5SDimitry Andric   std::vector<std::string> symbolLocations(locations.size());
1660b57cec5SDimitry Andric   size_t i = 0;
1670b57cec5SDimitry Andric   for (Location loc : locations) {
1680b57cec5SDimitry Andric     llvm::raw_string_ostream os(symbolLocations[i++]);
1690b57cec5SDimitry Andric     os << "\n>>> referenced by ";
1700b57cec5SDimitry Andric     if (!loc.fileLine.first.empty())
1710b57cec5SDimitry Andric       os << loc.fileLine.first << ":" << loc.fileLine.second
1720b57cec5SDimitry Andric          << "\n>>>               ";
1730b57cec5SDimitry Andric     os << toString(file);
1740b57cec5SDimitry Andric     if (loc.sym)
1750b57cec5SDimitry Andric       os << ":(" << toString(*loc.sym) << ')';
1760b57cec5SDimitry Andric   }
1770b57cec5SDimitry Andric   return symbolLocations;
1780b57cec5SDimitry Andric }
1790b57cec5SDimitry Andric 
180*85868e8aSDimitry Andric std::vector<std::string> getSymbolLocations(InputFile *file,
181*85868e8aSDimitry Andric                                             uint32_t symIndex) {
182*85868e8aSDimitry Andric   if (auto *o = dyn_cast<ObjFile>(file))
183*85868e8aSDimitry Andric     return getSymbolLocations(o, symIndex);
184*85868e8aSDimitry Andric   if (auto *b = dyn_cast<BitcodeFile>(file))
185*85868e8aSDimitry Andric     return getSymbolLocations(b);
186*85868e8aSDimitry Andric   llvm_unreachable("unsupported file type passed to getSymbolLocations");
187*85868e8aSDimitry Andric   return {};
188*85868e8aSDimitry Andric }
189*85868e8aSDimitry Andric 
1900b57cec5SDimitry Andric // For an undefined symbol, stores all files referencing it and the index of
1910b57cec5SDimitry Andric // the undefined symbol in each file.
1920b57cec5SDimitry Andric struct UndefinedDiag {
1930b57cec5SDimitry Andric   Symbol *sym;
1940b57cec5SDimitry Andric   struct File {
195*85868e8aSDimitry Andric     InputFile *file;
196*85868e8aSDimitry Andric     uint32_t symIndex;
1970b57cec5SDimitry Andric   };
1980b57cec5SDimitry Andric   std::vector<File> files;
1990b57cec5SDimitry Andric };
2000b57cec5SDimitry Andric 
2010b57cec5SDimitry Andric static void reportUndefinedSymbol(const UndefinedDiag &undefDiag) {
2020b57cec5SDimitry Andric   std::string out;
2030b57cec5SDimitry Andric   llvm::raw_string_ostream os(out);
2040b57cec5SDimitry Andric   os << "undefined symbol: " << toString(*undefDiag.sym);
2050b57cec5SDimitry Andric 
2060b57cec5SDimitry Andric   const size_t maxUndefReferences = 10;
2070b57cec5SDimitry Andric   size_t i = 0, numRefs = 0;
2080b57cec5SDimitry Andric   for (const UndefinedDiag::File &ref : undefDiag.files) {
2090b57cec5SDimitry Andric     std::vector<std::string> symbolLocations =
210*85868e8aSDimitry Andric         getSymbolLocations(ref.file, ref.symIndex);
2110b57cec5SDimitry Andric     numRefs += symbolLocations.size();
2120b57cec5SDimitry Andric     for (const std::string &s : symbolLocations) {
2130b57cec5SDimitry Andric       if (i >= maxUndefReferences)
2140b57cec5SDimitry Andric         break;
2150b57cec5SDimitry Andric       os << s;
2160b57cec5SDimitry Andric       i++;
2170b57cec5SDimitry Andric     }
2180b57cec5SDimitry Andric   }
2190b57cec5SDimitry Andric   if (i < numRefs)
2200b57cec5SDimitry Andric     os << "\n>>> referenced " << numRefs - i << " more times";
2210b57cec5SDimitry Andric   errorOrWarn(os.str());
2220b57cec5SDimitry Andric }
2230b57cec5SDimitry Andric 
2240b57cec5SDimitry Andric void SymbolTable::loadMinGWAutomaticImports() {
2250b57cec5SDimitry Andric   for (auto &i : symMap) {
2260b57cec5SDimitry Andric     Symbol *sym = i.second;
2270b57cec5SDimitry Andric     auto *undef = dyn_cast<Undefined>(sym);
2280b57cec5SDimitry Andric     if (!undef)
2290b57cec5SDimitry Andric       continue;
2300b57cec5SDimitry Andric     if (!sym->isUsedInRegularObj)
2310b57cec5SDimitry Andric       continue;
232*85868e8aSDimitry Andric     if (undef->getWeakAlias())
233*85868e8aSDimitry Andric       continue;
2340b57cec5SDimitry Andric 
2350b57cec5SDimitry Andric     StringRef name = undef->getName();
2360b57cec5SDimitry Andric 
2370b57cec5SDimitry Andric     if (name.startswith("__imp_"))
2380b57cec5SDimitry Andric       continue;
239*85868e8aSDimitry Andric     // If we have an undefined symbol, but we have a lazy symbol we could
240*85868e8aSDimitry Andric     // load, load it.
241*85868e8aSDimitry Andric     Symbol *l = find(("__imp_" + name).str());
242*85868e8aSDimitry Andric     if (!l || l->pendingArchiveLoad || !l->isLazy())
2430b57cec5SDimitry Andric       continue;
2440b57cec5SDimitry Andric 
245*85868e8aSDimitry Andric     log("Loading lazy " + l->getName() + " from " + l->getFile()->getName() +
2460b57cec5SDimitry Andric         " for automatic import");
247*85868e8aSDimitry Andric     forceLazy(l);
2480b57cec5SDimitry Andric   }
2490b57cec5SDimitry Andric }
2500b57cec5SDimitry Andric 
251*85868e8aSDimitry Andric Defined *SymbolTable::impSymbol(StringRef name) {
252*85868e8aSDimitry Andric   if (name.startswith("__imp_"))
253*85868e8aSDimitry Andric     return nullptr;
254*85868e8aSDimitry Andric   return dyn_cast_or_null<Defined>(find(("__imp_" + name).str()));
255*85868e8aSDimitry Andric }
256*85868e8aSDimitry Andric 
2570b57cec5SDimitry Andric bool SymbolTable::handleMinGWAutomaticImport(Symbol *sym, StringRef name) {
258*85868e8aSDimitry Andric   Defined *imp = impSymbol(name);
2590b57cec5SDimitry Andric   if (!imp)
2600b57cec5SDimitry Andric     return false;
2610b57cec5SDimitry Andric 
2620b57cec5SDimitry Andric   // Replace the reference directly to a variable with a reference
2630b57cec5SDimitry Andric   // to the import address table instead. This obviously isn't right,
2640b57cec5SDimitry Andric   // but we mark the symbol as isRuntimePseudoReloc, and a later pass
2650b57cec5SDimitry Andric   // will add runtime pseudo relocations for every relocation against
2660b57cec5SDimitry Andric   // this Symbol. The runtime pseudo relocation framework expects the
2670b57cec5SDimitry Andric   // reference itself to point at the IAT entry.
2680b57cec5SDimitry Andric   size_t impSize = 0;
2690b57cec5SDimitry Andric   if (isa<DefinedImportData>(imp)) {
2700b57cec5SDimitry Andric     log("Automatically importing " + name + " from " +
2710b57cec5SDimitry Andric         cast<DefinedImportData>(imp)->getDLLName());
2720b57cec5SDimitry Andric     impSize = sizeof(DefinedImportData);
2730b57cec5SDimitry Andric   } else if (isa<DefinedRegular>(imp)) {
2740b57cec5SDimitry Andric     log("Automatically importing " + name + " from " +
2750b57cec5SDimitry Andric         toString(cast<DefinedRegular>(imp)->file));
2760b57cec5SDimitry Andric     impSize = sizeof(DefinedRegular);
2770b57cec5SDimitry Andric   } else {
2780b57cec5SDimitry Andric     warn("unable to automatically import " + name + " from " + imp->getName() +
2790b57cec5SDimitry Andric          " from " + toString(cast<DefinedRegular>(imp)->file) +
2800b57cec5SDimitry Andric          "; unexpected symbol type");
2810b57cec5SDimitry Andric     return false;
2820b57cec5SDimitry Andric   }
2830b57cec5SDimitry Andric   sym->replaceKeepingName(imp, impSize);
2840b57cec5SDimitry Andric   sym->isRuntimePseudoReloc = true;
2850b57cec5SDimitry Andric 
2860b57cec5SDimitry Andric   // There may exist symbols named .refptr.<name> which only consist
2870b57cec5SDimitry Andric   // of a single pointer to <name>. If it turns out <name> is
2880b57cec5SDimitry Andric   // automatically imported, we don't need to keep the .refptr.<name>
2890b57cec5SDimitry Andric   // pointer at all, but redirect all accesses to it to the IAT entry
2900b57cec5SDimitry Andric   // for __imp_<name> instead, and drop the whole .refptr.<name> chunk.
2910b57cec5SDimitry Andric   DefinedRegular *refptr =
2920b57cec5SDimitry Andric       dyn_cast_or_null<DefinedRegular>(find((".refptr." + name).str()));
2930b57cec5SDimitry Andric   if (refptr && refptr->getChunk()->getSize() == config->wordsize) {
2940b57cec5SDimitry Andric     SectionChunk *sc = dyn_cast_or_null<SectionChunk>(refptr->getChunk());
2950b57cec5SDimitry Andric     if (sc && sc->getRelocs().size() == 1 && *sc->symbols().begin() == sym) {
2960b57cec5SDimitry Andric       log("Replacing .refptr." + name + " with " + imp->getName());
2970b57cec5SDimitry Andric       refptr->getChunk()->live = false;
2980b57cec5SDimitry Andric       refptr->replaceKeepingName(imp, impSize);
2990b57cec5SDimitry Andric     }
3000b57cec5SDimitry Andric   }
3010b57cec5SDimitry Andric   return true;
3020b57cec5SDimitry Andric }
3030b57cec5SDimitry Andric 
304*85868e8aSDimitry Andric /// Helper function for reportUnresolvable and resolveRemainingUndefines.
305*85868e8aSDimitry Andric /// This function emits an "undefined symbol" diagnostic for each symbol in
306*85868e8aSDimitry Andric /// undefs. If localImports is not nullptr, it also emits a "locally
307*85868e8aSDimitry Andric /// defined symbol imported" diagnostic for symbols in localImports.
308*85868e8aSDimitry Andric /// objFiles and bitcodeFiles (if not nullptr) are used to report where
309*85868e8aSDimitry Andric /// undefined symbols are referenced.
310*85868e8aSDimitry Andric static void
311*85868e8aSDimitry Andric reportProblemSymbols(const SmallPtrSetImpl<Symbol *> &undefs,
312*85868e8aSDimitry Andric                      const DenseMap<Symbol *, Symbol *> *localImports,
313*85868e8aSDimitry Andric                      const std::vector<ObjFile *> objFiles,
314*85868e8aSDimitry Andric                      const std::vector<BitcodeFile *> *bitcodeFiles) {
315*85868e8aSDimitry Andric 
316*85868e8aSDimitry Andric   // Return early if there is nothing to report (which should be
317*85868e8aSDimitry Andric   // the common case).
318*85868e8aSDimitry Andric   if (undefs.empty() && (!localImports || localImports->empty()))
319*85868e8aSDimitry Andric     return;
320*85868e8aSDimitry Andric 
321*85868e8aSDimitry Andric   for (Symbol *b : config->gcroot) {
322*85868e8aSDimitry Andric     if (undefs.count(b))
323*85868e8aSDimitry Andric       errorOrWarn("<root>: undefined symbol: " + toString(*b));
324*85868e8aSDimitry Andric     if (localImports)
325*85868e8aSDimitry Andric       if (Symbol *imp = localImports->lookup(b))
326*85868e8aSDimitry Andric         warn("<root>: locally defined symbol imported: " + toString(*imp) +
327*85868e8aSDimitry Andric              " (defined in " + toString(imp->getFile()) + ") [LNK4217]");
328*85868e8aSDimitry Andric   }
329*85868e8aSDimitry Andric 
330*85868e8aSDimitry Andric   std::vector<UndefinedDiag> undefDiags;
331*85868e8aSDimitry Andric   DenseMap<Symbol *, int> firstDiag;
332*85868e8aSDimitry Andric 
333*85868e8aSDimitry Andric   auto processFile = [&](InputFile *file, ArrayRef<Symbol *> symbols) {
334*85868e8aSDimitry Andric     uint32_t symIndex = (uint32_t)-1;
335*85868e8aSDimitry Andric     for (Symbol *sym : symbols) {
336*85868e8aSDimitry Andric       ++symIndex;
337*85868e8aSDimitry Andric       if (!sym)
338*85868e8aSDimitry Andric         continue;
339*85868e8aSDimitry Andric       if (undefs.count(sym)) {
340*85868e8aSDimitry Andric         auto it = firstDiag.find(sym);
341*85868e8aSDimitry Andric         if (it == firstDiag.end()) {
342*85868e8aSDimitry Andric           firstDiag[sym] = undefDiags.size();
343*85868e8aSDimitry Andric           undefDiags.push_back({sym, {{file, symIndex}}});
344*85868e8aSDimitry Andric         } else {
345*85868e8aSDimitry Andric           undefDiags[it->second].files.push_back({file, symIndex});
346*85868e8aSDimitry Andric         }
347*85868e8aSDimitry Andric       }
348*85868e8aSDimitry Andric       if (localImports)
349*85868e8aSDimitry Andric         if (Symbol *imp = localImports->lookup(sym))
350*85868e8aSDimitry Andric           warn(toString(file) +
351*85868e8aSDimitry Andric                ": locally defined symbol imported: " + toString(*imp) +
352*85868e8aSDimitry Andric                " (defined in " + toString(imp->getFile()) + ") [LNK4217]");
353*85868e8aSDimitry Andric     }
354*85868e8aSDimitry Andric   };
355*85868e8aSDimitry Andric 
356*85868e8aSDimitry Andric   for (ObjFile *file : objFiles)
357*85868e8aSDimitry Andric     processFile(file, file->getSymbols());
358*85868e8aSDimitry Andric 
359*85868e8aSDimitry Andric   if (bitcodeFiles)
360*85868e8aSDimitry Andric     for (BitcodeFile *file : *bitcodeFiles)
361*85868e8aSDimitry Andric       processFile(file, file->getSymbols());
362*85868e8aSDimitry Andric 
363*85868e8aSDimitry Andric   for (const UndefinedDiag &undefDiag : undefDiags)
364*85868e8aSDimitry Andric     reportUndefinedSymbol(undefDiag);
365*85868e8aSDimitry Andric }
366*85868e8aSDimitry Andric 
367*85868e8aSDimitry Andric void SymbolTable::reportUnresolvable() {
368*85868e8aSDimitry Andric   SmallPtrSet<Symbol *, 8> undefs;
369*85868e8aSDimitry Andric   for (auto &i : symMap) {
370*85868e8aSDimitry Andric     Symbol *sym = i.second;
371*85868e8aSDimitry Andric     auto *undef = dyn_cast<Undefined>(sym);
372*85868e8aSDimitry Andric     if (!undef)
373*85868e8aSDimitry Andric       continue;
374*85868e8aSDimitry Andric     if (undef->getWeakAlias())
375*85868e8aSDimitry Andric       continue;
376*85868e8aSDimitry Andric     StringRef name = undef->getName();
377*85868e8aSDimitry Andric     if (name.startswith("__imp_")) {
378*85868e8aSDimitry Andric       Symbol *imp = find(name.substr(strlen("__imp_")));
379*85868e8aSDimitry Andric       if (imp && isa<Defined>(imp))
380*85868e8aSDimitry Andric         continue;
381*85868e8aSDimitry Andric     }
382*85868e8aSDimitry Andric     if (name.contains("_PchSym_"))
383*85868e8aSDimitry Andric       continue;
384*85868e8aSDimitry Andric     if (config->mingw && impSymbol(name))
385*85868e8aSDimitry Andric       continue;
386*85868e8aSDimitry Andric     undefs.insert(sym);
387*85868e8aSDimitry Andric   }
388*85868e8aSDimitry Andric 
389*85868e8aSDimitry Andric   reportProblemSymbols(undefs,
390*85868e8aSDimitry Andric                        /* localImports */ nullptr, ObjFile::instances,
391*85868e8aSDimitry Andric                        &BitcodeFile::instances);
392*85868e8aSDimitry Andric }
393*85868e8aSDimitry Andric 
394*85868e8aSDimitry Andric void SymbolTable::resolveRemainingUndefines() {
3950b57cec5SDimitry Andric   SmallPtrSet<Symbol *, 8> undefs;
3960b57cec5SDimitry Andric   DenseMap<Symbol *, Symbol *> localImports;
3970b57cec5SDimitry Andric 
3980b57cec5SDimitry Andric   for (auto &i : symMap) {
3990b57cec5SDimitry Andric     Symbol *sym = i.second;
4000b57cec5SDimitry Andric     auto *undef = dyn_cast<Undefined>(sym);
4010b57cec5SDimitry Andric     if (!undef)
4020b57cec5SDimitry Andric       continue;
4030b57cec5SDimitry Andric     if (!sym->isUsedInRegularObj)
4040b57cec5SDimitry Andric       continue;
4050b57cec5SDimitry Andric 
4060b57cec5SDimitry Andric     StringRef name = undef->getName();
4070b57cec5SDimitry Andric 
4080b57cec5SDimitry Andric     // A weak alias may have been resolved, so check for that.
4090b57cec5SDimitry Andric     if (Defined *d = undef->getWeakAlias()) {
4100b57cec5SDimitry Andric       // We want to replace Sym with D. However, we can't just blindly
4110b57cec5SDimitry Andric       // copy sizeof(SymbolUnion) bytes from D to Sym because D may be an
4120b57cec5SDimitry Andric       // internal symbol, and internal symbols are stored as "unparented"
4130b57cec5SDimitry Andric       // Symbols. For that reason we need to check which type of symbol we
4140b57cec5SDimitry Andric       // are dealing with and copy the correct number of bytes.
4150b57cec5SDimitry Andric       if (isa<DefinedRegular>(d))
4160b57cec5SDimitry Andric         memcpy(sym, d, sizeof(DefinedRegular));
4170b57cec5SDimitry Andric       else if (isa<DefinedAbsolute>(d))
4180b57cec5SDimitry Andric         memcpy(sym, d, sizeof(DefinedAbsolute));
4190b57cec5SDimitry Andric       else
4200b57cec5SDimitry Andric         memcpy(sym, d, sizeof(SymbolUnion));
4210b57cec5SDimitry Andric       continue;
4220b57cec5SDimitry Andric     }
4230b57cec5SDimitry Andric 
4240b57cec5SDimitry Andric     // If we can resolve a symbol by removing __imp_ prefix, do that.
4250b57cec5SDimitry Andric     // This odd rule is for compatibility with MSVC linker.
4260b57cec5SDimitry Andric     if (name.startswith("__imp_")) {
4270b57cec5SDimitry Andric       Symbol *imp = find(name.substr(strlen("__imp_")));
4280b57cec5SDimitry Andric       if (imp && isa<Defined>(imp)) {
4290b57cec5SDimitry Andric         auto *d = cast<Defined>(imp);
4300b57cec5SDimitry Andric         replaceSymbol<DefinedLocalImport>(sym, name, d);
4310b57cec5SDimitry Andric         localImportChunks.push_back(cast<DefinedLocalImport>(sym)->getChunk());
4320b57cec5SDimitry Andric         localImports[sym] = d;
4330b57cec5SDimitry Andric         continue;
4340b57cec5SDimitry Andric       }
4350b57cec5SDimitry Andric     }
4360b57cec5SDimitry Andric 
4370b57cec5SDimitry Andric     // We don't want to report missing Microsoft precompiled headers symbols.
4380b57cec5SDimitry Andric     // A proper message will be emitted instead in PDBLinker::aquirePrecompObj
4390b57cec5SDimitry Andric     if (name.contains("_PchSym_"))
4400b57cec5SDimitry Andric       continue;
4410b57cec5SDimitry Andric 
4420b57cec5SDimitry Andric     if (config->mingw && handleMinGWAutomaticImport(sym, name))
4430b57cec5SDimitry Andric       continue;
4440b57cec5SDimitry Andric 
4450b57cec5SDimitry Andric     // Remaining undefined symbols are not fatal if /force is specified.
4460b57cec5SDimitry Andric     // They are replaced with dummy defined symbols.
4470b57cec5SDimitry Andric     if (config->forceUnresolved)
4480b57cec5SDimitry Andric       replaceSymbol<DefinedAbsolute>(sym, name, 0);
4490b57cec5SDimitry Andric     undefs.insert(sym);
4500b57cec5SDimitry Andric   }
4510b57cec5SDimitry Andric 
452*85868e8aSDimitry Andric   reportProblemSymbols(
453*85868e8aSDimitry Andric       undefs, config->warnLocallyDefinedImported ? &localImports : nullptr,
454*85868e8aSDimitry Andric       ObjFile::instances, /* bitcode files no longer needed */ nullptr);
4550b57cec5SDimitry Andric }
4560b57cec5SDimitry Andric 
4570b57cec5SDimitry Andric std::pair<Symbol *, bool> SymbolTable::insert(StringRef name) {
4580b57cec5SDimitry Andric   bool inserted = false;
4590b57cec5SDimitry Andric   Symbol *&sym = symMap[CachedHashStringRef(name)];
4600b57cec5SDimitry Andric   if (!sym) {
4610b57cec5SDimitry Andric     sym = reinterpret_cast<Symbol *>(make<SymbolUnion>());
4620b57cec5SDimitry Andric     sym->isUsedInRegularObj = false;
4630b57cec5SDimitry Andric     sym->pendingArchiveLoad = false;
4640b57cec5SDimitry Andric     inserted = true;
4650b57cec5SDimitry Andric   }
4660b57cec5SDimitry Andric   return {sym, inserted};
4670b57cec5SDimitry Andric }
4680b57cec5SDimitry Andric 
4690b57cec5SDimitry Andric std::pair<Symbol *, bool> SymbolTable::insert(StringRef name, InputFile *file) {
4700b57cec5SDimitry Andric   std::pair<Symbol *, bool> result = insert(name);
4710b57cec5SDimitry Andric   if (!file || !isa<BitcodeFile>(file))
4720b57cec5SDimitry Andric     result.first->isUsedInRegularObj = true;
4730b57cec5SDimitry Andric   return result;
4740b57cec5SDimitry Andric }
4750b57cec5SDimitry Andric 
4760b57cec5SDimitry Andric Symbol *SymbolTable::addUndefined(StringRef name, InputFile *f,
4770b57cec5SDimitry Andric                                   bool isWeakAlias) {
4780b57cec5SDimitry Andric   Symbol *s;
4790b57cec5SDimitry Andric   bool wasInserted;
4800b57cec5SDimitry Andric   std::tie(s, wasInserted) = insert(name, f);
481*85868e8aSDimitry Andric   if (wasInserted || (s->isLazy() && isWeakAlias)) {
4820b57cec5SDimitry Andric     replaceSymbol<Undefined>(s, name);
4830b57cec5SDimitry Andric     return s;
4840b57cec5SDimitry Andric   }
485*85868e8aSDimitry Andric   if (s->isLazy())
486*85868e8aSDimitry Andric     forceLazy(s);
4870b57cec5SDimitry Andric   return s;
4880b57cec5SDimitry Andric }
4890b57cec5SDimitry Andric 
490*85868e8aSDimitry Andric void SymbolTable::addLazyArchive(ArchiveFile *f, const Archive::Symbol &sym) {
4910b57cec5SDimitry Andric   StringRef name = sym.getName();
4920b57cec5SDimitry Andric   Symbol *s;
4930b57cec5SDimitry Andric   bool wasInserted;
4940b57cec5SDimitry Andric   std::tie(s, wasInserted) = insert(name);
4950b57cec5SDimitry Andric   if (wasInserted) {
496*85868e8aSDimitry Andric     replaceSymbol<LazyArchive>(s, f, sym);
4970b57cec5SDimitry Andric     return;
4980b57cec5SDimitry Andric   }
4990b57cec5SDimitry Andric   auto *u = dyn_cast<Undefined>(s);
5000b57cec5SDimitry Andric   if (!u || u->weakAlias || s->pendingArchiveLoad)
5010b57cec5SDimitry Andric     return;
5020b57cec5SDimitry Andric   s->pendingArchiveLoad = true;
5030b57cec5SDimitry Andric   f->addMember(sym);
5040b57cec5SDimitry Andric }
5050b57cec5SDimitry Andric 
506*85868e8aSDimitry Andric void SymbolTable::addLazyObject(LazyObjFile *f, StringRef n) {
507*85868e8aSDimitry Andric   Symbol *s;
508*85868e8aSDimitry Andric   bool wasInserted;
509*85868e8aSDimitry Andric   std::tie(s, wasInserted) = insert(n, f);
510*85868e8aSDimitry Andric   if (wasInserted) {
511*85868e8aSDimitry Andric     replaceSymbol<LazyObject>(s, f, n);
512*85868e8aSDimitry Andric     return;
513*85868e8aSDimitry Andric   }
514*85868e8aSDimitry Andric   auto *u = dyn_cast<Undefined>(s);
515*85868e8aSDimitry Andric   if (!u || u->weakAlias || s->pendingArchiveLoad)
516*85868e8aSDimitry Andric     return;
517*85868e8aSDimitry Andric   s->pendingArchiveLoad = true;
518*85868e8aSDimitry Andric   f->fetch();
519*85868e8aSDimitry Andric }
520*85868e8aSDimitry Andric 
521*85868e8aSDimitry Andric static std::string getSourceLocationBitcode(BitcodeFile *file) {
522*85868e8aSDimitry Andric   std::string res("\n>>> defined at ");
523*85868e8aSDimitry Andric   StringRef source = file->obj->getSourceFileName();
524*85868e8aSDimitry Andric   if (!source.empty())
525*85868e8aSDimitry Andric     res += source.str() + "\n>>>            ";
526*85868e8aSDimitry Andric   res += toString(file);
527*85868e8aSDimitry Andric   return res;
528*85868e8aSDimitry Andric }
529*85868e8aSDimitry Andric 
530*85868e8aSDimitry Andric static std::string getSourceLocationObj(ObjFile *file, SectionChunk *sc,
531*85868e8aSDimitry Andric                                         uint32_t offset, StringRef name) {
532*85868e8aSDimitry Andric   Optional<std::pair<StringRef, uint32_t>> fileLine;
533*85868e8aSDimitry Andric   if (sc)
534*85868e8aSDimitry Andric     fileLine = getFileLine(sc, offset);
535*85868e8aSDimitry Andric   if (!fileLine)
536*85868e8aSDimitry Andric     fileLine = file->getVariableLocation(name);
537*85868e8aSDimitry Andric 
538*85868e8aSDimitry Andric   std::string res;
539*85868e8aSDimitry Andric   llvm::raw_string_ostream os(res);
540*85868e8aSDimitry Andric   os << "\n>>> defined at ";
541*85868e8aSDimitry Andric   if (fileLine)
542*85868e8aSDimitry Andric     os << fileLine->first << ":" << fileLine->second << "\n>>>            ";
543*85868e8aSDimitry Andric   os << toString(file);
544*85868e8aSDimitry Andric   return os.str();
545*85868e8aSDimitry Andric }
546*85868e8aSDimitry Andric 
547*85868e8aSDimitry Andric static std::string getSourceLocation(InputFile *file, SectionChunk *sc,
548*85868e8aSDimitry Andric                                      uint32_t offset, StringRef name) {
549*85868e8aSDimitry Andric   if (auto *o = dyn_cast<ObjFile>(file))
550*85868e8aSDimitry Andric     return getSourceLocationObj(o, sc, offset, name);
551*85868e8aSDimitry Andric   if (auto *b = dyn_cast<BitcodeFile>(file))
552*85868e8aSDimitry Andric     return getSourceLocationBitcode(b);
553*85868e8aSDimitry Andric   return "\n>>> defined at " + toString(file);
554*85868e8aSDimitry Andric }
555*85868e8aSDimitry Andric 
556*85868e8aSDimitry Andric // Construct and print an error message in the form of:
557*85868e8aSDimitry Andric //
558*85868e8aSDimitry Andric //   lld-link: error: duplicate symbol: foo
559*85868e8aSDimitry Andric //   >>> defined at bar.c:30
560*85868e8aSDimitry Andric //   >>>            bar.o
561*85868e8aSDimitry Andric //   >>> defined at baz.c:563
562*85868e8aSDimitry Andric //   >>>            baz.o
563*85868e8aSDimitry Andric void SymbolTable::reportDuplicate(Symbol *existing, InputFile *newFile,
564*85868e8aSDimitry Andric                                   SectionChunk *newSc,
565*85868e8aSDimitry Andric                                   uint32_t newSectionOffset) {
566*85868e8aSDimitry Andric   std::string msg;
567*85868e8aSDimitry Andric   llvm::raw_string_ostream os(msg);
568*85868e8aSDimitry Andric   os << "duplicate symbol: " << toString(*existing);
569*85868e8aSDimitry Andric 
570*85868e8aSDimitry Andric   DefinedRegular *d = cast<DefinedRegular>(existing);
571*85868e8aSDimitry Andric   if (d && isa<ObjFile>(d->getFile())) {
572*85868e8aSDimitry Andric     os << getSourceLocation(d->getFile(), d->getChunk(), d->getValue(),
573*85868e8aSDimitry Andric                             existing->getName());
574*85868e8aSDimitry Andric   } else {
575*85868e8aSDimitry Andric     os << getSourceLocation(existing->getFile(), nullptr, 0, "");
576*85868e8aSDimitry Andric   }
577*85868e8aSDimitry Andric   os << getSourceLocation(newFile, newSc, newSectionOffset,
578*85868e8aSDimitry Andric                           existing->getName());
5790b57cec5SDimitry Andric 
5800b57cec5SDimitry Andric   if (config->forceMultiple)
581*85868e8aSDimitry Andric     warn(os.str());
5820b57cec5SDimitry Andric   else
583*85868e8aSDimitry Andric     error(os.str());
5840b57cec5SDimitry Andric }
5850b57cec5SDimitry Andric 
5860b57cec5SDimitry Andric Symbol *SymbolTable::addAbsolute(StringRef n, COFFSymbolRef sym) {
5870b57cec5SDimitry Andric   Symbol *s;
5880b57cec5SDimitry Andric   bool wasInserted;
5890b57cec5SDimitry Andric   std::tie(s, wasInserted) = insert(n, nullptr);
5900b57cec5SDimitry Andric   s->isUsedInRegularObj = true;
591*85868e8aSDimitry Andric   if (wasInserted || isa<Undefined>(s) || s->isLazy())
5920b57cec5SDimitry Andric     replaceSymbol<DefinedAbsolute>(s, n, sym);
5930b57cec5SDimitry Andric   else if (!isa<DefinedCOFF>(s))
5940b57cec5SDimitry Andric     reportDuplicate(s, nullptr);
5950b57cec5SDimitry Andric   return s;
5960b57cec5SDimitry Andric }
5970b57cec5SDimitry Andric 
5980b57cec5SDimitry Andric Symbol *SymbolTable::addAbsolute(StringRef n, uint64_t va) {
5990b57cec5SDimitry Andric   Symbol *s;
6000b57cec5SDimitry Andric   bool wasInserted;
6010b57cec5SDimitry Andric   std::tie(s, wasInserted) = insert(n, nullptr);
6020b57cec5SDimitry Andric   s->isUsedInRegularObj = true;
603*85868e8aSDimitry Andric   if (wasInserted || isa<Undefined>(s) || s->isLazy())
6040b57cec5SDimitry Andric     replaceSymbol<DefinedAbsolute>(s, n, va);
6050b57cec5SDimitry Andric   else if (!isa<DefinedCOFF>(s))
6060b57cec5SDimitry Andric     reportDuplicate(s, nullptr);
6070b57cec5SDimitry Andric   return s;
6080b57cec5SDimitry Andric }
6090b57cec5SDimitry Andric 
6100b57cec5SDimitry Andric Symbol *SymbolTable::addSynthetic(StringRef n, Chunk *c) {
6110b57cec5SDimitry Andric   Symbol *s;
6120b57cec5SDimitry Andric   bool wasInserted;
6130b57cec5SDimitry Andric   std::tie(s, wasInserted) = insert(n, nullptr);
6140b57cec5SDimitry Andric   s->isUsedInRegularObj = true;
615*85868e8aSDimitry Andric   if (wasInserted || isa<Undefined>(s) || s->isLazy())
6160b57cec5SDimitry Andric     replaceSymbol<DefinedSynthetic>(s, n, c);
6170b57cec5SDimitry Andric   else if (!isa<DefinedCOFF>(s))
6180b57cec5SDimitry Andric     reportDuplicate(s, nullptr);
6190b57cec5SDimitry Andric   return s;
6200b57cec5SDimitry Andric }
6210b57cec5SDimitry Andric 
6220b57cec5SDimitry Andric Symbol *SymbolTable::addRegular(InputFile *f, StringRef n,
623*85868e8aSDimitry Andric                                 const coff_symbol_generic *sym, SectionChunk *c,
624*85868e8aSDimitry Andric                                 uint32_t sectionOffset) {
6250b57cec5SDimitry Andric   Symbol *s;
6260b57cec5SDimitry Andric   bool wasInserted;
6270b57cec5SDimitry Andric   std::tie(s, wasInserted) = insert(n, f);
6280b57cec5SDimitry Andric   if (wasInserted || !isa<DefinedRegular>(s))
6290b57cec5SDimitry Andric     replaceSymbol<DefinedRegular>(s, f, n, /*IsCOMDAT*/ false,
6300b57cec5SDimitry Andric                                   /*IsExternal*/ true, sym, c);
6310b57cec5SDimitry Andric   else
632*85868e8aSDimitry Andric     reportDuplicate(s, f, c, sectionOffset);
6330b57cec5SDimitry Andric   return s;
6340b57cec5SDimitry Andric }
6350b57cec5SDimitry Andric 
6360b57cec5SDimitry Andric std::pair<DefinedRegular *, bool>
6370b57cec5SDimitry Andric SymbolTable::addComdat(InputFile *f, StringRef n,
6380b57cec5SDimitry Andric                        const coff_symbol_generic *sym) {
6390b57cec5SDimitry Andric   Symbol *s;
6400b57cec5SDimitry Andric   bool wasInserted;
6410b57cec5SDimitry Andric   std::tie(s, wasInserted) = insert(n, f);
6420b57cec5SDimitry Andric   if (wasInserted || !isa<DefinedRegular>(s)) {
6430b57cec5SDimitry Andric     replaceSymbol<DefinedRegular>(s, f, n, /*IsCOMDAT*/ true,
6440b57cec5SDimitry Andric                                   /*IsExternal*/ true, sym, nullptr);
6450b57cec5SDimitry Andric     return {cast<DefinedRegular>(s), true};
6460b57cec5SDimitry Andric   }
6470b57cec5SDimitry Andric   auto *existingSymbol = cast<DefinedRegular>(s);
6480b57cec5SDimitry Andric   if (!existingSymbol->isCOMDAT)
6490b57cec5SDimitry Andric     reportDuplicate(s, f);
6500b57cec5SDimitry Andric   return {existingSymbol, false};
6510b57cec5SDimitry Andric }
6520b57cec5SDimitry Andric 
6530b57cec5SDimitry Andric Symbol *SymbolTable::addCommon(InputFile *f, StringRef n, uint64_t size,
6540b57cec5SDimitry Andric                                const coff_symbol_generic *sym, CommonChunk *c) {
6550b57cec5SDimitry Andric   Symbol *s;
6560b57cec5SDimitry Andric   bool wasInserted;
6570b57cec5SDimitry Andric   std::tie(s, wasInserted) = insert(n, f);
6580b57cec5SDimitry Andric   if (wasInserted || !isa<DefinedCOFF>(s))
6590b57cec5SDimitry Andric     replaceSymbol<DefinedCommon>(s, f, n, size, sym, c);
6600b57cec5SDimitry Andric   else if (auto *dc = dyn_cast<DefinedCommon>(s))
6610b57cec5SDimitry Andric     if (size > dc->getSize())
6620b57cec5SDimitry Andric       replaceSymbol<DefinedCommon>(s, f, n, size, sym, c);
6630b57cec5SDimitry Andric   return s;
6640b57cec5SDimitry Andric }
6650b57cec5SDimitry Andric 
6660b57cec5SDimitry Andric Symbol *SymbolTable::addImportData(StringRef n, ImportFile *f) {
6670b57cec5SDimitry Andric   Symbol *s;
6680b57cec5SDimitry Andric   bool wasInserted;
6690b57cec5SDimitry Andric   std::tie(s, wasInserted) = insert(n, nullptr);
6700b57cec5SDimitry Andric   s->isUsedInRegularObj = true;
671*85868e8aSDimitry Andric   if (wasInserted || isa<Undefined>(s) || s->isLazy()) {
6720b57cec5SDimitry Andric     replaceSymbol<DefinedImportData>(s, n, f);
6730b57cec5SDimitry Andric     return s;
6740b57cec5SDimitry Andric   }
6750b57cec5SDimitry Andric 
6760b57cec5SDimitry Andric   reportDuplicate(s, f);
6770b57cec5SDimitry Andric   return nullptr;
6780b57cec5SDimitry Andric }
6790b57cec5SDimitry Andric 
6800b57cec5SDimitry Andric Symbol *SymbolTable::addImportThunk(StringRef name, DefinedImportData *id,
6810b57cec5SDimitry Andric                                     uint16_t machine) {
6820b57cec5SDimitry Andric   Symbol *s;
6830b57cec5SDimitry Andric   bool wasInserted;
6840b57cec5SDimitry Andric   std::tie(s, wasInserted) = insert(name, nullptr);
6850b57cec5SDimitry Andric   s->isUsedInRegularObj = true;
686*85868e8aSDimitry Andric   if (wasInserted || isa<Undefined>(s) || s->isLazy()) {
6870b57cec5SDimitry Andric     replaceSymbol<DefinedImportThunk>(s, name, id, machine);
6880b57cec5SDimitry Andric     return s;
6890b57cec5SDimitry Andric   }
6900b57cec5SDimitry Andric 
6910b57cec5SDimitry Andric   reportDuplicate(s, id->file);
6920b57cec5SDimitry Andric   return nullptr;
6930b57cec5SDimitry Andric }
6940b57cec5SDimitry Andric 
6950b57cec5SDimitry Andric void SymbolTable::addLibcall(StringRef name) {
6960b57cec5SDimitry Andric   Symbol *sym = findUnderscore(name);
6970b57cec5SDimitry Andric   if (!sym)
6980b57cec5SDimitry Andric     return;
6990b57cec5SDimitry Andric 
700*85868e8aSDimitry Andric   if (auto *l = dyn_cast<LazyArchive>(sym)) {
7010b57cec5SDimitry Andric     MemoryBufferRef mb = l->getMemberBuffer();
702*85868e8aSDimitry Andric     if (isBitcode(mb))
703*85868e8aSDimitry Andric       addUndefined(sym->getName());
704*85868e8aSDimitry Andric   } else if (LazyObject *o = dyn_cast<LazyObject>(sym)) {
705*85868e8aSDimitry Andric     if (isBitcode(o->file->mb))
7060b57cec5SDimitry Andric       addUndefined(sym->getName());
7070b57cec5SDimitry Andric   }
7080b57cec5SDimitry Andric }
7090b57cec5SDimitry Andric 
7100b57cec5SDimitry Andric std::vector<Chunk *> SymbolTable::getChunks() {
7110b57cec5SDimitry Andric   std::vector<Chunk *> res;
7120b57cec5SDimitry Andric   for (ObjFile *file : ObjFile::instances) {
7130b57cec5SDimitry Andric     ArrayRef<Chunk *> v = file->getChunks();
7140b57cec5SDimitry Andric     res.insert(res.end(), v.begin(), v.end());
7150b57cec5SDimitry Andric   }
7160b57cec5SDimitry Andric   return res;
7170b57cec5SDimitry Andric }
7180b57cec5SDimitry Andric 
7190b57cec5SDimitry Andric Symbol *SymbolTable::find(StringRef name) {
7200b57cec5SDimitry Andric   return symMap.lookup(CachedHashStringRef(name));
7210b57cec5SDimitry Andric }
7220b57cec5SDimitry Andric 
7230b57cec5SDimitry Andric Symbol *SymbolTable::findUnderscore(StringRef name) {
7240b57cec5SDimitry Andric   if (config->machine == I386)
7250b57cec5SDimitry Andric     return find(("_" + name).str());
7260b57cec5SDimitry Andric   return find(name);
7270b57cec5SDimitry Andric }
7280b57cec5SDimitry Andric 
7290b57cec5SDimitry Andric // Return all symbols that start with Prefix, possibly ignoring the first
7300b57cec5SDimitry Andric // character of Prefix or the first character symbol.
7310b57cec5SDimitry Andric std::vector<Symbol *> SymbolTable::getSymsWithPrefix(StringRef prefix) {
7320b57cec5SDimitry Andric   std::vector<Symbol *> syms;
7330b57cec5SDimitry Andric   for (auto pair : symMap) {
7340b57cec5SDimitry Andric     StringRef name = pair.first.val();
7350b57cec5SDimitry Andric     if (name.startswith(prefix) || name.startswith(prefix.drop_front()) ||
7360b57cec5SDimitry Andric         name.drop_front().startswith(prefix) ||
7370b57cec5SDimitry Andric         name.drop_front().startswith(prefix.drop_front())) {
7380b57cec5SDimitry Andric       syms.push_back(pair.second);
7390b57cec5SDimitry Andric     }
7400b57cec5SDimitry Andric   }
7410b57cec5SDimitry Andric   return syms;
7420b57cec5SDimitry Andric }
7430b57cec5SDimitry Andric 
7440b57cec5SDimitry Andric Symbol *SymbolTable::findMangle(StringRef name) {
7450b57cec5SDimitry Andric   if (Symbol *sym = find(name))
7460b57cec5SDimitry Andric     if (!isa<Undefined>(sym))
7470b57cec5SDimitry Andric       return sym;
7480b57cec5SDimitry Andric 
7490b57cec5SDimitry Andric   // Efficient fuzzy string lookup is impossible with a hash table, so iterate
7500b57cec5SDimitry Andric   // the symbol table once and collect all possibly matching symbols into this
7510b57cec5SDimitry Andric   // vector. Then compare each possibly matching symbol with each possible
7520b57cec5SDimitry Andric   // mangling.
7530b57cec5SDimitry Andric   std::vector<Symbol *> syms = getSymsWithPrefix(name);
7540b57cec5SDimitry Andric   auto findByPrefix = [&syms](const Twine &t) -> Symbol * {
7550b57cec5SDimitry Andric     std::string prefix = t.str();
7560b57cec5SDimitry Andric     for (auto *s : syms)
7570b57cec5SDimitry Andric       if (s->getName().startswith(prefix))
7580b57cec5SDimitry Andric         return s;
7590b57cec5SDimitry Andric     return nullptr;
7600b57cec5SDimitry Andric   };
7610b57cec5SDimitry Andric 
7620b57cec5SDimitry Andric   // For non-x86, just look for C++ functions.
7630b57cec5SDimitry Andric   if (config->machine != I386)
7640b57cec5SDimitry Andric     return findByPrefix("?" + name + "@@Y");
7650b57cec5SDimitry Andric 
7660b57cec5SDimitry Andric   if (!name.startswith("_"))
7670b57cec5SDimitry Andric     return nullptr;
7680b57cec5SDimitry Andric   // Search for x86 stdcall function.
7690b57cec5SDimitry Andric   if (Symbol *s = findByPrefix(name + "@"))
7700b57cec5SDimitry Andric     return s;
7710b57cec5SDimitry Andric   // Search for x86 fastcall function.
7720b57cec5SDimitry Andric   if (Symbol *s = findByPrefix("@" + name.substr(1) + "@"))
7730b57cec5SDimitry Andric     return s;
7740b57cec5SDimitry Andric   // Search for x86 vectorcall function.
7750b57cec5SDimitry Andric   if (Symbol *s = findByPrefix(name.substr(1) + "@@"))
7760b57cec5SDimitry Andric     return s;
7770b57cec5SDimitry Andric   // Search for x86 C++ non-member function.
7780b57cec5SDimitry Andric   return findByPrefix("?" + name.substr(1) + "@@Y");
7790b57cec5SDimitry Andric }
7800b57cec5SDimitry Andric 
7810b57cec5SDimitry Andric Symbol *SymbolTable::addUndefined(StringRef name) {
7820b57cec5SDimitry Andric   return addUndefined(name, nullptr, false);
7830b57cec5SDimitry Andric }
7840b57cec5SDimitry Andric 
7850b57cec5SDimitry Andric std::vector<StringRef> SymbolTable::compileBitcodeFiles() {
7860b57cec5SDimitry Andric   lto.reset(new BitcodeCompiler);
7870b57cec5SDimitry Andric   for (BitcodeFile *f : BitcodeFile::instances)
7880b57cec5SDimitry Andric     lto->add(*f);
7890b57cec5SDimitry Andric   return lto->compile();
7900b57cec5SDimitry Andric }
7910b57cec5SDimitry Andric 
7920b57cec5SDimitry Andric void SymbolTable::addCombinedLTOObjects() {
7930b57cec5SDimitry Andric   if (BitcodeFile::instances.empty())
7940b57cec5SDimitry Andric     return;
7950b57cec5SDimitry Andric 
7960b57cec5SDimitry Andric   ScopedTimer t(ltoTimer);
7970b57cec5SDimitry Andric   for (StringRef object : compileBitcodeFiles()) {
7980b57cec5SDimitry Andric     auto *obj = make<ObjFile>(MemoryBufferRef(object, "lto.tmp"));
7990b57cec5SDimitry Andric     obj->parse();
8000b57cec5SDimitry Andric     ObjFile::instances.push_back(obj);
8010b57cec5SDimitry Andric   }
8020b57cec5SDimitry Andric }
8030b57cec5SDimitry Andric 
8040b57cec5SDimitry Andric } // namespace coff
8050b57cec5SDimitry Andric } // namespace lld
806