1 //===- SymbolTable.cpp ----------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "SymbolTable.h"
10 #include "Config.h"
11 #include "InputChunks.h"
12 #include "InputEvent.h"
13 #include "InputGlobal.h"
14 #include "WriterUtils.h"
15 #include "lld/Common/ErrorHandler.h"
16 #include "lld/Common/Memory.h"
17 #include "llvm/ADT/SetVector.h"
18 
19 #define DEBUG_TYPE "lld"
20 
21 using namespace llvm;
22 using namespace llvm::wasm;
23 using namespace llvm::object;
24 using namespace lld;
25 using namespace lld::wasm;
26 
27 SymbolTable *lld::wasm::Symtab;
28 
29 void SymbolTable::addFile(InputFile *File) {
30   log("Processing: " + toString(File));
31 
32   // .a file
33   if (auto *F = dyn_cast<ArchiveFile>(File)) {
34     F->parse();
35     return;
36   }
37 
38   // .so file
39   if (auto *F = dyn_cast<SharedFile>(File)) {
40     SharedFiles.push_back(F);
41     return;
42   }
43 
44   if (Config->Trace)
45     message(toString(File));
46 
47   // LLVM bitcode file
48   if (auto *F = dyn_cast<BitcodeFile>(File)) {
49     F->parse();
50     BitcodeFiles.push_back(F);
51     return;
52   }
53 
54   // Regular object file
55   auto *F = cast<ObjFile>(File);
56   F->parse(false);
57   ObjectFiles.push_back(F);
58 }
59 
60 // This function is where all the optimizations of link-time
61 // optimization happens. When LTO is in use, some input files are
62 // not in native object file format but in the LLVM bitcode format.
63 // This function compiles bitcode files into a few big native files
64 // using LLVM functions and replaces bitcode symbols with the results.
65 // Because all bitcode files that the program consists of are passed
66 // to the compiler at once, it can do whole-program optimization.
67 void SymbolTable::addCombinedLTOObject() {
68   if (BitcodeFiles.empty())
69     return;
70 
71   // Compile bitcode files and replace bitcode symbols.
72   LTO.reset(new BitcodeCompiler);
73   for (BitcodeFile *F : BitcodeFiles)
74     LTO->add(*F);
75 
76   for (StringRef Filename : LTO->compile()) {
77     auto *Obj = make<ObjFile>(MemoryBufferRef(Filename, "lto.tmp"), "");
78     Obj->parse(true);
79     ObjectFiles.push_back(Obj);
80   }
81 }
82 
83 void SymbolTable::reportRemainingUndefines() {
84   for (const auto& Pair : SymMap) {
85     const Symbol *Sym = SymVector[Pair.second];
86     if (!Sym->isUndefined() || Sym->isWeak())
87       continue;
88     if (Config->AllowUndefinedSymbols.count(Sym->getName()) != 0)
89       continue;
90     if (!Sym->IsUsedInRegularObj)
91       continue;
92     error(toString(Sym->getFile()) + ": undefined symbol: " + toString(*Sym));
93   }
94 }
95 
96 Symbol *SymbolTable::find(StringRef Name) {
97   auto It = SymMap.find(CachedHashStringRef(Name));
98   if (It == SymMap.end() || It->second == -1)
99     return nullptr;
100   return SymVector[It->second];
101 }
102 
103 void SymbolTable::replace(StringRef Name, Symbol* Sym) {
104   auto It = SymMap.find(CachedHashStringRef(Name));
105   SymVector[It->second] = Sym;
106 }
107 
108 std::pair<Symbol *, bool> SymbolTable::insertName(StringRef Name) {
109   bool Trace = false;
110   auto P = SymMap.insert({CachedHashStringRef(Name), (int)SymVector.size()});
111   int &SymIndex = P.first->second;
112   bool IsNew = P.second;
113   if (SymIndex == -1) {
114     SymIndex = SymVector.size();
115     Trace = true;
116     IsNew = true;
117   }
118 
119   if (!IsNew)
120     return {SymVector[SymIndex], false};
121 
122   Symbol *Sym = reinterpret_cast<Symbol *>(make<SymbolUnion>());
123   Sym->IsUsedInRegularObj = false;
124   Sym->CanInline = true;
125   Sym->Traced = Trace;
126   SymVector.emplace_back(Sym);
127   return {Sym, true};
128 }
129 
130 std::pair<Symbol *, bool> SymbolTable::insert(StringRef Name,
131                                               const InputFile *File) {
132   Symbol *S;
133   bool WasInserted;
134   std::tie(S, WasInserted) = insertName(Name);
135 
136   if (!File || File->kind() == InputFile::ObjectKind)
137     S->IsUsedInRegularObj = true;
138 
139   return {S, WasInserted};
140 }
141 
142 static void reportTypeError(const Symbol *Existing, const InputFile *File,
143                             llvm::wasm::WasmSymbolType Type) {
144   error("symbol type mismatch: " + toString(*Existing) + "\n>>> defined as " +
145         toString(Existing->getWasmType()) + " in " +
146         toString(Existing->getFile()) + "\n>>> defined as " + toString(Type) +
147         " in " + toString(File));
148 }
149 
150 // Check the type of new symbol matches that of the symbol is replacing.
151 // Returns true if the function types match, false is there is a singature
152 // mismatch.
153 static bool signatureMatches(FunctionSymbol *Existing,
154                              const WasmSignature *NewSig) {
155   const WasmSignature *OldSig = Existing->Signature;
156 
157   // If either function is missing a signature (this happend for bitcode
158   // symbols) then assume they match.  Any mismatch will be reported later
159   // when the LTO objects are added.
160   if (!NewSig || !OldSig)
161     return true;
162 
163   return *NewSig == *OldSig;
164 }
165 
166 static void checkGlobalType(const Symbol *Existing, const InputFile *File,
167                             const WasmGlobalType *NewType) {
168   if (!isa<GlobalSymbol>(Existing)) {
169     reportTypeError(Existing, File, WASM_SYMBOL_TYPE_GLOBAL);
170     return;
171   }
172 
173   const WasmGlobalType *OldType = cast<GlobalSymbol>(Existing)->getGlobalType();
174   if (*NewType != *OldType) {
175     error("Global type mismatch: " + Existing->getName() + "\n>>> defined as " +
176           toString(*OldType) + " in " + toString(Existing->getFile()) +
177           "\n>>> defined as " + toString(*NewType) + " in " + toString(File));
178   }
179 }
180 
181 static void checkEventType(const Symbol *Existing, const InputFile *File,
182                            const WasmEventType *NewType,
183                            const WasmSignature *NewSig) {
184   auto ExistingEvent = dyn_cast<EventSymbol>(Existing);
185   if (!isa<EventSymbol>(Existing)) {
186     reportTypeError(Existing, File, WASM_SYMBOL_TYPE_EVENT);
187     return;
188   }
189 
190   const WasmEventType *OldType = cast<EventSymbol>(Existing)->getEventType();
191   const WasmSignature *OldSig = ExistingEvent->Signature;
192   if (NewType->Attribute != OldType->Attribute)
193     error("Event type mismatch: " + Existing->getName() + "\n>>> defined as " +
194           toString(*OldType) + " in " + toString(Existing->getFile()) +
195           "\n>>> defined as " + toString(*NewType) + " in " + toString(File));
196   if (*NewSig != *OldSig)
197     warn("Event signature mismatch: " + Existing->getName() +
198          "\n>>> defined as " + toString(*OldSig) + " in " +
199          toString(Existing->getFile()) + "\n>>> defined as " +
200          toString(*NewSig) + " in " + toString(File));
201 }
202 
203 static void checkDataType(const Symbol *Existing, const InputFile *File) {
204   if (!isa<DataSymbol>(Existing))
205     reportTypeError(Existing, File, WASM_SYMBOL_TYPE_DATA);
206 }
207 
208 DefinedFunction *SymbolTable::addSyntheticFunction(StringRef Name,
209                                                    uint32_t Flags,
210                                                    InputFunction *Function) {
211   LLVM_DEBUG(dbgs() << "addSyntheticFunction: " << Name << "\n");
212   assert(!find(Name));
213   SyntheticFunctions.emplace_back(Function);
214   return replaceSymbol<DefinedFunction>(insertName(Name).first, Name,
215                                         Flags, nullptr, Function);
216 }
217 
218 // Adds an optional, linker generated, data symbols.  The symbol will only be
219 // added if there is an undefine reference to it, or if it is explictly exported
220 // via the --export flag.  Otherwise we don't add the symbol and return nullptr.
221 DefinedData *SymbolTable::addOptionalDataSymbol(StringRef Name, uint32_t Value,
222                                                 uint32_t Flags) {
223   Symbol *S = find(Name);
224   if (!S && (Config->ExportAll || Config->ExportedSymbols.count(Name) != 0))
225     S = insertName(Name).first;
226   else if (!S || S->isDefined())
227     return nullptr;
228   LLVM_DEBUG(dbgs() << "addOptionalDataSymbol: " << Name << "\n");
229   auto *rtn = replaceSymbol<DefinedData>(S, Name, Flags);
230   rtn->setVirtualAddress(Value);
231   return rtn;
232 }
233 
234 DefinedData *SymbolTable::addSyntheticDataSymbol(StringRef Name,
235                                                  uint32_t Flags) {
236   LLVM_DEBUG(dbgs() << "addSyntheticDataSymbol: " << Name << "\n");
237   assert(!find(Name));
238   return replaceSymbol<DefinedData>(insertName(Name).first, Name, Flags);
239 }
240 
241 DefinedGlobal *SymbolTable::addSyntheticGlobal(StringRef Name, uint32_t Flags,
242                                                InputGlobal *Global) {
243   LLVM_DEBUG(dbgs() << "addSyntheticGlobal: " << Name << " -> " << Global
244                     << "\n");
245   assert(!find(Name));
246   SyntheticGlobals.emplace_back(Global);
247   return replaceSymbol<DefinedGlobal>(insertName(Name).first, Name, Flags,
248                                       nullptr, Global);
249 }
250 
251 static bool shouldReplace(const Symbol *Existing, InputFile *NewFile,
252                           uint32_t NewFlags) {
253   // If existing symbol is undefined, replace it.
254   if (!Existing->isDefined()) {
255     LLVM_DEBUG(dbgs() << "resolving existing undefined symbol: "
256                       << Existing->getName() << "\n");
257     return true;
258   }
259 
260   // Now we have two defined symbols. If the new one is weak, we can ignore it.
261   if ((NewFlags & WASM_SYMBOL_BINDING_MASK) == WASM_SYMBOL_BINDING_WEAK) {
262     LLVM_DEBUG(dbgs() << "existing symbol takes precedence\n");
263     return false;
264   }
265 
266   // If the existing symbol is weak, we should replace it.
267   if (Existing->isWeak()) {
268     LLVM_DEBUG(dbgs() << "replacing existing weak symbol\n");
269     return true;
270   }
271 
272   // Neither symbol is week. They conflict.
273   error("duplicate symbol: " + toString(*Existing) + "\n>>> defined in " +
274         toString(Existing->getFile()) + "\n>>> defined in " +
275         toString(NewFile));
276   return true;
277 }
278 
279 Symbol *SymbolTable::addDefinedFunction(StringRef Name, uint32_t Flags,
280                                         InputFile *File,
281                                         InputFunction *Function) {
282   LLVM_DEBUG(dbgs() << "addDefinedFunction: " << Name << " ["
283                     << (Function ? toString(Function->Signature) : "none")
284                     << "]\n");
285   Symbol *S;
286   bool WasInserted;
287   std::tie(S, WasInserted) = insert(Name, File);
288 
289   auto Replace = [&](Symbol* Sym) {
290     // If the new defined function doesn't have signture (i.e. bitcode
291     // functions) but the old symbol does, then preserve the old signature
292     const WasmSignature *OldSig = S->getSignature();
293     auto* NewSym = replaceSymbol<DefinedFunction>(Sym, Name, Flags, File, Function);
294     if (!NewSym->Signature)
295       NewSym->Signature = OldSig;
296   };
297 
298   if (WasInserted || S->isLazy()) {
299     Replace(S);
300     return S;
301   }
302 
303   auto ExistingFunction = dyn_cast<FunctionSymbol>(S);
304   if (!ExistingFunction) {
305     reportTypeError(S, File, WASM_SYMBOL_TYPE_FUNCTION);
306     return S;
307   }
308 
309   bool CheckSig = true;
310   if (auto UD = dyn_cast<UndefinedFunction>(ExistingFunction))
311     CheckSig = UD->IsCalledDirectly;
312 
313   if (CheckSig && Function && !signatureMatches(ExistingFunction, &Function->Signature)) {
314     Symbol* Variant;
315     if (getFunctionVariant(S, &Function->Signature, File, &Variant))
316       // New variant, always replace
317       Replace(Variant);
318     else if (shouldReplace(S, File, Flags))
319       // Variant already exists, replace it after checking shouldReplace
320       Replace(Variant);
321 
322     // This variant we found take the place in the symbol table as the primary
323     // variant.
324     replace(Name, Variant);
325     return Variant;
326   }
327 
328   // Existing function with matching signature.
329   if (shouldReplace(S, File, Flags))
330     Replace(S);
331 
332   return S;
333 }
334 
335 Symbol *SymbolTable::addDefinedData(StringRef Name, uint32_t Flags,
336                                     InputFile *File, InputSegment *Segment,
337                                     uint32_t Address, uint32_t Size) {
338   LLVM_DEBUG(dbgs() << "addDefinedData:" << Name << " addr:" << Address
339                     << "\n");
340   Symbol *S;
341   bool WasInserted;
342   std::tie(S, WasInserted) = insert(Name, File);
343 
344   auto Replace = [&]() {
345     replaceSymbol<DefinedData>(S, Name, Flags, File, Segment, Address, Size);
346   };
347 
348   if (WasInserted || S->isLazy()) {
349     Replace();
350     return S;
351   }
352 
353   checkDataType(S, File);
354 
355   if (shouldReplace(S, File, Flags))
356     Replace();
357   return S;
358 }
359 
360 Symbol *SymbolTable::addDefinedGlobal(StringRef Name, uint32_t Flags,
361                                       InputFile *File, InputGlobal *Global) {
362   LLVM_DEBUG(dbgs() << "addDefinedGlobal:" << Name << "\n");
363 
364   Symbol *S;
365   bool WasInserted;
366   std::tie(S, WasInserted) = insert(Name, File);
367 
368   auto Replace = [&]() {
369     replaceSymbol<DefinedGlobal>(S, Name, Flags, File, Global);
370   };
371 
372   if (WasInserted || S->isLazy()) {
373     Replace();
374     return S;
375   }
376 
377   checkGlobalType(S, File, &Global->getType());
378 
379   if (shouldReplace(S, File, Flags))
380     Replace();
381   return S;
382 }
383 
384 Symbol *SymbolTable::addDefinedEvent(StringRef Name, uint32_t Flags,
385                                      InputFile *File, InputEvent *Event) {
386   LLVM_DEBUG(dbgs() << "addDefinedEvent:" << Name << "\n");
387 
388   Symbol *S;
389   bool WasInserted;
390   std::tie(S, WasInserted) = insert(Name, File);
391 
392   auto Replace = [&]() {
393     replaceSymbol<DefinedEvent>(S, Name, Flags, File, Event);
394   };
395 
396   if (WasInserted || S->isLazy()) {
397     Replace();
398     return S;
399   }
400 
401   checkEventType(S, File, &Event->getType(), &Event->Signature);
402 
403   if (shouldReplace(S, File, Flags))
404     Replace();
405   return S;
406 }
407 
408 Symbol *SymbolTable::addUndefinedFunction(StringRef Name, StringRef ImportName,
409                                           StringRef ImportModule,
410                                           uint32_t Flags, InputFile *File,
411                                           const WasmSignature *Sig,
412                                           bool IsCalledDirectly) {
413   LLVM_DEBUG(dbgs() << "addUndefinedFunction: " << Name << " ["
414                     << (Sig ? toString(*Sig) : "none")
415                     << "] IsCalledDirectly:" << IsCalledDirectly << "\n");
416 
417   Symbol *S;
418   bool WasInserted;
419   std::tie(S, WasInserted) = insert(Name, File);
420   if (S->Traced)
421     printTraceSymbolUndefined(Name, File);
422 
423   auto Replace = [&]() {
424     replaceSymbol<UndefinedFunction>(S, Name, ImportName, ImportModule, Flags,
425                                      File, Sig, IsCalledDirectly);
426   };
427 
428   if (WasInserted)
429     Replace();
430   else if (auto *Lazy = dyn_cast<LazySymbol>(S))
431     Lazy->fetch();
432   else {
433     auto ExistingFunction = dyn_cast<FunctionSymbol>(S);
434     if (!ExistingFunction) {
435       reportTypeError(S, File, WASM_SYMBOL_TYPE_FUNCTION);
436       return S;
437     }
438     if (!ExistingFunction->Signature && Sig)
439       ExistingFunction->Signature = Sig;
440     if (IsCalledDirectly && !signatureMatches(ExistingFunction, Sig))
441       if (getFunctionVariant(S, Sig, File, &S))
442         Replace();
443   }
444 
445   return S;
446 }
447 
448 Symbol *SymbolTable::addUndefinedData(StringRef Name, uint32_t Flags,
449                                       InputFile *File) {
450   LLVM_DEBUG(dbgs() << "addUndefinedData: " << Name << "\n");
451 
452   Symbol *S;
453   bool WasInserted;
454   std::tie(S, WasInserted) = insert(Name, File);
455   if (S->Traced)
456     printTraceSymbolUndefined(Name, File);
457 
458   if (WasInserted)
459     replaceSymbol<UndefinedData>(S, Name, Flags, File);
460   else if (auto *Lazy = dyn_cast<LazySymbol>(S))
461     Lazy->fetch();
462   else if (S->isDefined())
463     checkDataType(S, File);
464   return S;
465 }
466 
467 Symbol *SymbolTable::addUndefinedGlobal(StringRef Name, StringRef ImportName,
468                                         StringRef ImportModule, uint32_t Flags,
469                                         InputFile *File,
470                                         const WasmGlobalType *Type) {
471   LLVM_DEBUG(dbgs() << "addUndefinedGlobal: " << Name << "\n");
472 
473   Symbol *S;
474   bool WasInserted;
475   std::tie(S, WasInserted) = insert(Name, File);
476   if (S->Traced)
477     printTraceSymbolUndefined(Name, File);
478 
479   if (WasInserted)
480     replaceSymbol<UndefinedGlobal>(S, Name, ImportName, ImportModule, Flags,
481                                    File, Type);
482   else if (auto *Lazy = dyn_cast<LazySymbol>(S))
483     Lazy->fetch();
484   else if (S->isDefined())
485     checkGlobalType(S, File, Type);
486   return S;
487 }
488 
489 void SymbolTable::addLazy(ArchiveFile *File, const Archive::Symbol *Sym) {
490   LLVM_DEBUG(dbgs() << "addLazy: " << Sym->getName() << "\n");
491   StringRef Name = Sym->getName();
492 
493   Symbol *S;
494   bool WasInserted;
495   std::tie(S, WasInserted) = insertName(Name);
496 
497   if (WasInserted) {
498     replaceSymbol<LazySymbol>(S, Name, 0, File, *Sym);
499     return;
500   }
501 
502   if (!S->isUndefined())
503     return;
504 
505   // The existing symbol is undefined, load a new one from the archive,
506   // unless the the existing symbol is weak in which case replace the undefined
507   // symbols with a LazySymbol.
508   if (S->isWeak()) {
509     const WasmSignature *OldSig = nullptr;
510     // In the case of an UndefinedFunction we need to preserve the expected
511     // signature.
512     if (auto *F = dyn_cast<UndefinedFunction>(S))
513       OldSig = F->Signature;
514     LLVM_DEBUG(dbgs() << "replacing existing weak undefined symbol\n");
515     auto NewSym = replaceSymbol<LazySymbol>(S, Name, WASM_SYMBOL_BINDING_WEAK,
516                                             File, *Sym);
517     NewSym->Signature = OldSig;
518     return;
519   }
520 
521   LLVM_DEBUG(dbgs() << "replacing existing undefined\n");
522   File->addMember(Sym);
523 }
524 
525 bool SymbolTable::addComdat(StringRef Name) {
526   return ComdatGroups.insert(CachedHashStringRef(Name)).second;
527 }
528 
529 // The new signature doesn't match.  Create a variant to the symbol with the
530 // signature encoded in the name and return that instead.  These symbols are
531 // then unified later in handleSymbolVariants.
532 bool SymbolTable::getFunctionVariant(Symbol* Sym, const WasmSignature *Sig,
533                                      const InputFile *File, Symbol **Out) {
534   LLVM_DEBUG(dbgs() << "getFunctionVariant: " << Sym->getName() << " -> "
535                     << " " << toString(*Sig) << "\n");
536   Symbol *Variant = nullptr;
537 
538   // Linear search through symbol variants.  Should never be more than two
539   // or three entries here.
540   auto &Variants = SymVariants[CachedHashStringRef(Sym->getName())];
541   if (Variants.empty())
542     Variants.push_back(Sym);
543 
544   for (Symbol* V : Variants) {
545     if (*V->getSignature() == *Sig) {
546       Variant = V;
547       break;
548     }
549   }
550 
551   bool WasAdded = !Variant;
552   if (WasAdded) {
553     // Create a new variant;
554     LLVM_DEBUG(dbgs() << "added new variant\n");
555     Variant = reinterpret_cast<Symbol *>(make<SymbolUnion>());
556     Variants.push_back(Variant);
557   } else {
558     LLVM_DEBUG(dbgs() << "variant already exists: " << toString(*Variant) << "\n");
559     assert(*Variant->getSignature() == *Sig);
560   }
561 
562   *Out = Variant;
563   return WasAdded;
564 }
565 
566 // Set a flag for --trace-symbol so that we can print out a log message
567 // if a new symbol with the same name is inserted into the symbol table.
568 void SymbolTable::trace(StringRef Name) {
569   SymMap.insert({CachedHashStringRef(Name), -1});
570 }
571 
572 void SymbolTable::wrap(Symbol *Sym, Symbol *Real, Symbol *Wrap) {
573   // Swap symbols as instructed by -wrap.
574   int &OrigIdx = SymMap[CachedHashStringRef(Sym->getName())];
575   int &RealIdx= SymMap[CachedHashStringRef(Real->getName())];
576   int &WrapIdx = SymMap[CachedHashStringRef(Wrap->getName())];
577   LLVM_DEBUG(dbgs() << "wrap: " << Sym->getName() << "\n");
578 
579   // Anyone looking up __real symbols should get the original
580   RealIdx = OrigIdx;
581   // Anyone looking up the original should get the __wrap symbol
582   OrigIdx = WrapIdx;
583 }
584 
585 static const uint8_t UnreachableFn[] = {
586     0x03 /* ULEB length */, 0x00 /* ULEB num locals */,
587     0x00 /* opcode unreachable */, 0x0b /* opcode end */
588 };
589 
590 // Replace the given symbol body with an unreachable function.
591 // This is used by handleWeakUndefines in order to generate a callable
592 // equivalent of an undefined function and also handleSymbolVariants for
593 // undefined functions that don't match the signature of the definition.
594 InputFunction *SymbolTable::replaceWithUnreachable(Symbol *Sym,
595                                                    const WasmSignature &Sig,
596                                                    StringRef DebugName) {
597   auto *Func = make<SyntheticFunction>(Sig, Sym->getName(), DebugName);
598   Func->setBody(UnreachableFn);
599   SyntheticFunctions.emplace_back(Func);
600   replaceSymbol<DefinedFunction>(Sym, Sym->getName(), Sym->getFlags(), nullptr,
601                                  Func);
602   return Func;
603 }
604 
605 // For weak undefined functions, there may be "call" instructions that reference
606 // the symbol. In this case, we need to synthesise a dummy/stub function that
607 // will abort at runtime, so that relocations can still provided an operand to
608 // the call instruction that passes Wasm validation.
609 void SymbolTable::handleWeakUndefines() {
610   for (Symbol *Sym : getSymbols()) {
611     if (!Sym->isUndefWeak())
612       continue;
613 
614     const WasmSignature *Sig = Sym->getSignature();
615     if (!Sig) {
616       // It is possible for undefined functions not to have a signature (eg. if
617       // added via "--undefined"), but weak undefined ones do have a signature.
618       // Lazy symbols may not be functions and therefore Sig can still be null
619       // in some circumstantce.
620       assert(!isa<FunctionSymbol>(Sym));
621       continue;
622     }
623 
624     // Add a synthetic dummy for weak undefined functions.  These dummies will
625     // be GC'd if not used as the target of any "call" instructions.
626     StringRef DebugName = Saver.save("undefined:" + toString(*Sym));
627     InputFunction* Func = replaceWithUnreachable(Sym, *Sig, DebugName);
628     // Ensure it compares equal to the null pointer, and so that table relocs
629     // don't pull in the stub body (only call-operand relocs should do that).
630     Func->setTableIndex(0);
631     // Hide our dummy to prevent export.
632     Sym->setHidden(true);
633   }
634 }
635 
636 static void reportFunctionSignatureMismatch(StringRef SymName,
637                                             FunctionSymbol *A,
638                                             FunctionSymbol *B, bool Error) {
639   std::string msg = ("function signature mismatch: " + SymName +
640                      "\n>>> defined as " + toString(*A->Signature) + " in " +
641                      toString(A->getFile()) + "\n>>> defined as " +
642                      toString(*B->Signature) + " in " + toString(B->getFile()))
643                         .str();
644   if (Error)
645     error(msg);
646   else
647     warn(msg);
648 }
649 
650 // Remove any variant symbols that were created due to function signature
651 // mismatches.
652 void SymbolTable::handleSymbolVariants() {
653   for (auto Pair : SymVariants) {
654     // Push the initial symbol onto the list of variants.
655     StringRef SymName = Pair.first.val();
656     std::vector<Symbol *> &Variants = Pair.second;
657 
658 #ifndef NDEBUG
659     LLVM_DEBUG(dbgs() << "symbol with (" << Variants.size()
660                       << ") variants: " << SymName << "\n");
661     for (auto *S: Variants) {
662       auto *F = cast<FunctionSymbol>(S);
663       LLVM_DEBUG(dbgs() << " variant: " + F->getName() << " "
664                         << toString(*F->Signature) << "\n");
665     }
666 #endif
667 
668     // Find the one definition.
669     DefinedFunction *Defined = nullptr;
670     for (auto *Symbol : Variants) {
671       if (auto F = dyn_cast<DefinedFunction>(Symbol)) {
672         Defined = F;
673         break;
674       }
675     }
676 
677     // If there are no definitions, and the undefined symbols disagree on
678     // the signature, there is not we can do since we don't know which one
679     // to use as the signature on the import.
680     if (!Defined) {
681       reportFunctionSignatureMismatch(SymName,
682                                       cast<FunctionSymbol>(Variants[0]),
683                                       cast<FunctionSymbol>(Variants[1]), true);
684       return;
685     }
686 
687     for (auto *Symbol : Variants) {
688       if (Symbol != Defined) {
689         auto *F = cast<FunctionSymbol>(Symbol);
690         reportFunctionSignatureMismatch(SymName, F, Defined, false);
691         StringRef DebugName = Saver.save("unreachable:" + toString(*F));
692         replaceWithUnreachable(F, *F->Signature, DebugName);
693       }
694     }
695   }
696 }
697