1c94d393aSSam Clegg //===- SymbolTable.cpp ----------------------------------------------------===//
2c94d393aSSam Clegg //
3c94d393aSSam Clegg //                             The LLVM Linker
4c94d393aSSam Clegg //
5c94d393aSSam Clegg // This file is distributed under the University of Illinois Open Source
6c94d393aSSam Clegg // License. See LICENSE.TXT for details.
7c94d393aSSam Clegg //
8c94d393aSSam Clegg //===----------------------------------------------------------------------===//
9c94d393aSSam Clegg 
10c94d393aSSam Clegg #include "SymbolTable.h"
11c94d393aSSam Clegg #include "Config.h"
125fa274beSSam Clegg #include "InputChunks.h"
13*93102974SSam Clegg #include "InputGlobal.h"
14b8621596SSam Clegg #include "WriterUtils.h"
15c94d393aSSam Clegg #include "lld/Common/ErrorHandler.h"
162017d52bSRui Ueyama #include "lld/Common/Memory.h"
177d67dd11SRui Ueyama #include "llvm/ADT/SetVector.h"
18c94d393aSSam Clegg 
19c94d393aSSam Clegg #define DEBUG_TYPE "lld"
20c94d393aSSam Clegg 
21c94d393aSSam Clegg using namespace llvm;
2220db381bSSam Clegg using namespace llvm::wasm;
23c94d393aSSam Clegg using namespace lld;
24c94d393aSSam Clegg using namespace lld::wasm;
25c94d393aSSam Clegg 
26c94d393aSSam Clegg SymbolTable *lld::wasm::Symtab;
27c94d393aSSam Clegg 
28c94d393aSSam Clegg void SymbolTable::addFile(InputFile *File) {
29c94d393aSSam Clegg   log("Processing: " + toString(File));
30c94d393aSSam Clegg   File->parse();
31c94d393aSSam Clegg 
32c94d393aSSam Clegg   if (auto *F = dyn_cast<ObjFile>(File))
33c94d393aSSam Clegg     ObjectFiles.push_back(F);
34c94d393aSSam Clegg }
35c94d393aSSam Clegg 
36c94d393aSSam Clegg void SymbolTable::reportRemainingUndefines() {
377d67dd11SRui Ueyama   SetVector<Symbol *> Undefs;
3874fe0ba1SSam Clegg   for (Symbol *Sym : SymVector) {
39c94d393aSSam Clegg     if (Sym->isUndefined() && !Sym->isWeak() &&
40c94d393aSSam Clegg         Config->AllowUndefinedSymbols.count(Sym->getName()) == 0) {
41c94d393aSSam Clegg       Undefs.insert(Sym);
42c94d393aSSam Clegg     }
43c94d393aSSam Clegg   }
44c94d393aSSam Clegg 
45c94d393aSSam Clegg   if (Undefs.empty())
46c94d393aSSam Clegg     return;
47c94d393aSSam Clegg 
48c94d393aSSam Clegg   for (ObjFile *File : ObjectFiles)
49c94d393aSSam Clegg     for (Symbol *Sym : File->getSymbols())
50c94d393aSSam Clegg       if (Undefs.count(Sym))
51c94d393aSSam Clegg         error(toString(File) + ": undefined symbol: " + toString(*Sym));
52c94d393aSSam Clegg 
53c94d393aSSam Clegg   for (Symbol *Sym : Undefs)
54c94d393aSSam Clegg     if (!Sym->getFile())
55c94d393aSSam Clegg       error("undefined symbol: " + toString(*Sym));
56c94d393aSSam Clegg }
57c94d393aSSam Clegg 
58c94d393aSSam Clegg Symbol *SymbolTable::find(StringRef Name) {
59a80d94d5SSam Clegg   auto It = SymMap.find(CachedHashStringRef(Name));
60a80d94d5SSam Clegg   if (It == SymMap.end())
61c94d393aSSam Clegg     return nullptr;
62c94d393aSSam Clegg   return It->second;
63c94d393aSSam Clegg }
64c94d393aSSam Clegg 
65c94d393aSSam Clegg std::pair<Symbol *, bool> SymbolTable::insert(StringRef Name) {
66a80d94d5SSam Clegg   Symbol *&Sym = SymMap[CachedHashStringRef(Name)];
67c94d393aSSam Clegg   if (Sym)
68c94d393aSSam Clegg     return {Sym, false};
69dfb0b2c7SSam Clegg   Sym = reinterpret_cast<Symbol *>(make<SymbolUnion>());
7074fe0ba1SSam Clegg   SymVector.emplace_back(Sym);
71c94d393aSSam Clegg   return {Sym, true};
72c94d393aSSam Clegg }
73c94d393aSSam Clegg 
74b8621596SSam Clegg // Check the type of new symbol matches that of the symbol is replacing.
75b8621596SSam Clegg // For functions this can also involve verifying that the signatures match.
76b8621596SSam Clegg static void checkSymbolTypes(const Symbol &Existing, const InputFile &F,
77*93102974SSam Clegg                              WasmSymbolType NewType,
78*93102974SSam Clegg                              const WasmSignature *NewFunctionSig,
79*93102974SSam Clegg                              const WasmGlobalType *NewGlobalType) {
80b8621596SSam Clegg   if (Existing.isLazy())
81c94d393aSSam Clegg     return;
82c94d393aSSam Clegg 
83*93102974SSam Clegg   WasmSymbolType ExistingType = Existing.getWasmType();
84*93102974SSam Clegg 
85b8621596SSam Clegg   // First check the symbol types match (i.e. either both are function
86b8621596SSam Clegg   // symbols or both are data symbols).
87*93102974SSam Clegg   if (NewType != ExistingType) {
8820db381bSSam Clegg     error("symbol type mismatch: " + Existing.getName() + "\n>>> defined as " +
89*93102974SSam Clegg           toString(ExistingType) + " in " + toString(Existing.getFile()) +
90*93102974SSam Clegg           "\n>>> defined as " + toString(NewType) + " in " + F.getName());
91b8621596SSam Clegg     return;
92b8621596SSam Clegg   }
93b8621596SSam Clegg 
94*93102974SSam Clegg   // For function/global symbols, optionally check the type matches too.
95*93102974SSam Clegg   if (NewType == WASM_SYMBOL_TYPE_DATA || !Config->CheckSignatures)
96c94d393aSSam Clegg     return;
97dfb0b2c7SSam Clegg 
98*93102974SSam Clegg   DEBUG(dbgs() << "checkSymbolTypes: " << Existing.getName() << "\n");
993f8db988SSam Clegg 
100*93102974SSam Clegg   auto ReportError = [&](const Twine &Old, const Twine &New) {
101*93102974SSam Clegg     error(toString(NewType) + " type mismatch: " + Existing.getName() +
102*93102974SSam Clegg           "\n>>> defined as " + Old + " in " + toString(Existing.getFile()) +
103*93102974SSam Clegg           "\n>>> defined as " + New + " in " + F.getName());
104*93102974SSam Clegg   };
105*93102974SSam Clegg 
106*93102974SSam Clegg   if (NewType == WASM_SYMBOL_TYPE_FUNCTION) {
10731de2f0cSSam Clegg     // Skip the signature check if the existing function has no signature (e.g.
10831de2f0cSSam Clegg     // if it is an undefined symbol generated by --undefined command line flag).
109*93102974SSam Clegg     auto &Sym = cast<FunctionSymbol>(Existing);
110*93102974SSam Clegg     const WasmSignature *OldSig = Sym.getFunctionType();
111*93102974SSam Clegg     if (!OldSig)
11231de2f0cSSam Clegg       return;
113c94d393aSSam Clegg 
114*93102974SSam Clegg     assert(NewFunctionSig);
115*93102974SSam Clegg     if (*NewFunctionSig == *OldSig)
116b8621596SSam Clegg       return;
117b8621596SSam Clegg 
118*93102974SSam Clegg     ReportError(toString(*OldSig), toString(*NewFunctionSig));
119*93102974SSam Clegg   } else {
120*93102974SSam Clegg     auto &Sym = cast<GlobalSymbol>(Existing);
121*93102974SSam Clegg 
122*93102974SSam Clegg     assert(NewGlobalType != nullptr);
123*93102974SSam Clegg     const WasmGlobalType *OldType = Sym.getGlobalType();
124*93102974SSam Clegg     if (*NewGlobalType == *OldType)
125*93102974SSam Clegg       return;
126*93102974SSam Clegg 
127*93102974SSam Clegg     ReportError(toString(*OldType), toString(*NewGlobalType));
128c94d393aSSam Clegg   }
12924b3dcd4SSam Clegg }
13024b3dcd4SSam Clegg 
131dfb0b2c7SSam Clegg DefinedFunction *SymbolTable::addSyntheticFunction(StringRef Name,
13250686856SSam Clegg                                                    const WasmSignature *Type,
13350686856SSam Clegg                                                    uint32_t Flags) {
134a189230bSSam Clegg   DEBUG(dbgs() << "addSyntheticFunction: " << Name << "\n");
13550686856SSam Clegg   Symbol *S;
13650686856SSam Clegg   bool WasInserted;
13750686856SSam Clegg   std::tie(S, WasInserted) = insert(Name);
138a189230bSSam Clegg   assert(WasInserted);
139dfb0b2c7SSam Clegg   return replaceSymbol<DefinedFunction>(S, Name, Flags, Type);
14050686856SSam Clegg }
14150686856SSam Clegg 
14200245539SSam Clegg DefinedData *SymbolTable::addSyntheticDataSymbol(StringRef Name,
14300245539SSam Clegg                                                  uint32_t Flags) {
14400245539SSam Clegg   DEBUG(dbgs() << "addSyntheticDataSymbol: " << Name << "\n");
145c94d393aSSam Clegg   Symbol *S;
146c94d393aSSam Clegg   bool WasInserted;
147c94d393aSSam Clegg   std::tie(S, WasInserted) = insert(Name);
148a189230bSSam Clegg   assert(WasInserted);
14900245539SSam Clegg   return replaceSymbol<DefinedData>(S, Name, Flags);
150c94d393aSSam Clegg }
151c94d393aSSam Clegg 
152*93102974SSam Clegg DefinedGlobal *SymbolTable::addSyntheticGlobal(StringRef Name, uint32_t Flags,
153*93102974SSam Clegg                                                InputGlobal *Global) {
154*93102974SSam Clegg   DEBUG(dbgs() << "addSyntheticGlobal: " << Name << " -> " << Global << "\n");
155*93102974SSam Clegg   Symbol *S;
156*93102974SSam Clegg   bool WasInserted;
157*93102974SSam Clegg   std::tie(S, WasInserted) = insert(Name);
158*93102974SSam Clegg   assert(WasInserted);
159*93102974SSam Clegg   return replaceSymbol<DefinedGlobal>(S, Name, Flags, nullptr, Global);
160*93102974SSam Clegg }
161*93102974SSam Clegg 
162f60b0d5cSSam Clegg static bool shouldReplace(const Symbol &Existing, InputFile *NewFile,
163*93102974SSam Clegg                           WasmSymbolType NewType, uint32_t NewFlags,
164*93102974SSam Clegg                           const WasmSignature *NewFuncType = nullptr,
165*93102974SSam Clegg                           const WasmGlobalType *NewGlobalType = nullptr) {
166*93102974SSam Clegg 
167c03c9040SRui Ueyama   // If existing symbol is lazy, replace it without checking types since
168b8621596SSam Clegg   // lazy symbols don't have any type information.
169c03c9040SRui Ueyama   if (Existing.isLazy()) {
17093e559b1SSam Clegg     DEBUG(dbgs() << "replacing existing lazy symbol: " << Existing.getName()
17193e559b1SSam Clegg                  << "\n");
172c03c9040SRui Ueyama     return true;
173c94d393aSSam Clegg   }
174c94d393aSSam Clegg 
175c03c9040SRui Ueyama   // Now we have two wasm symbols, and all wasm symbols that have the same
176c03c9040SRui Ueyama   // symbol name must have the same type, even if they are undefined. This
177c03c9040SRui Ueyama   // is different from ELF because symbol types are not that significant
178c03c9040SRui Ueyama   // in ELF, and undefined symbols in ELF don't have type in the first place.
179*93102974SSam Clegg   checkSymbolTypes(Existing, *NewFile, NewType, NewFuncType, NewGlobalType);
18093e559b1SSam Clegg 
181c03c9040SRui Ueyama   // If existing symbol is undefined, replace it.
182c03c9040SRui Ueyama   if (!Existing.isDefined()) {
183c03c9040SRui Ueyama     DEBUG(dbgs() << "resolving existing undefined symbol: "
184c03c9040SRui Ueyama                  << Existing.getName() << "\n");
185c03c9040SRui Ueyama     return true;
186c03c9040SRui Ueyama   }
187c03c9040SRui Ueyama 
188c03c9040SRui Ueyama   // Now we have two defined symbols. If the new one is weak, we can ignore it.
189c03c9040SRui Ueyama   if ((NewFlags & WASM_SYMBOL_BINDING_MASK) == WASM_SYMBOL_BINDING_WEAK) {
190c03c9040SRui Ueyama     DEBUG(dbgs() << "existing symbol takes precedence\n");
191c03c9040SRui Ueyama     return false;
192c03c9040SRui Ueyama   }
193c03c9040SRui Ueyama 
194c03c9040SRui Ueyama   // If the existing symbol is weak, we should replace it.
195c03c9040SRui Ueyama   if (Existing.isWeak()) {
196c03c9040SRui Ueyama     DEBUG(dbgs() << "replacing existing weak symbol\n");
197c03c9040SRui Ueyama     return true;
198c03c9040SRui Ueyama   }
199c03c9040SRui Ueyama 
200c03c9040SRui Ueyama   // Neither symbol is week. They conflict.
201c03c9040SRui Ueyama   error("duplicate symbol: " + toString(Existing) + "\n>>> defined in " +
202c03c9040SRui Ueyama         toString(Existing.getFile()) + "\n>>> defined in " + toString(NewFile));
203c03c9040SRui Ueyama   return true;
204b8621596SSam Clegg }
20593e559b1SSam Clegg 
20693e559b1SSam Clegg Symbol *SymbolTable::addDefinedFunction(StringRef Name, uint32_t Flags,
20793e559b1SSam Clegg                                         InputFile *F, InputFunction *Function) {
20893e559b1SSam Clegg   DEBUG(dbgs() << "addDefinedFunction: " << Name << "\n");
20993e559b1SSam Clegg   Symbol *S;
21093e559b1SSam Clegg   bool WasInserted;
21193e559b1SSam Clegg   std::tie(S, WasInserted) = insert(Name);
212*93102974SSam Clegg   if (WasInserted || shouldReplace(*S, F, WASM_SYMBOL_TYPE_FUNCTION, Flags,
213*93102974SSam Clegg                                    &Function->Signature))
21493e559b1SSam Clegg     replaceSymbol<DefinedFunction>(S, Name, Flags, F, Function);
21593e559b1SSam Clegg   return S;
21693e559b1SSam Clegg }
21793e559b1SSam Clegg 
21800245539SSam Clegg Symbol *SymbolTable::addDefinedData(StringRef Name, uint32_t Flags,
21993e559b1SSam Clegg                                     InputFile *F, InputSegment *Segment,
220*93102974SSam Clegg                                     uint32_t Address, uint32_t Size) {
22100245539SSam Clegg   DEBUG(dbgs() << "addDefinedData:" << Name << " addr:" << Address << "\n");
22293e559b1SSam Clegg   Symbol *S;
22393e559b1SSam Clegg   bool WasInserted;
22493e559b1SSam Clegg   std::tie(S, WasInserted) = insert(Name);
225*93102974SSam Clegg   if (WasInserted || shouldReplace(*S, F, WASM_SYMBOL_TYPE_DATA, Flags))
226*93102974SSam Clegg     replaceSymbol<DefinedData>(S, Name, Flags, F, Segment, Address, Size);
227c94d393aSSam Clegg   return S;
228c94d393aSSam Clegg }
229c94d393aSSam Clegg 
230*93102974SSam Clegg Symbol *SymbolTable::addDefinedGlobal(StringRef Name, uint32_t Flags,
231*93102974SSam Clegg                                       InputFile *F, InputGlobal *Global) {
232*93102974SSam Clegg   DEBUG(dbgs() << "addDefinedGlobal:" << Name << "\n");
233*93102974SSam Clegg   Symbol *S;
234*93102974SSam Clegg   bool WasInserted;
235*93102974SSam Clegg   std::tie(S, WasInserted) = insert(Name);
236*93102974SSam Clegg   if (WasInserted || shouldReplace(*S, F, WASM_SYMBOL_TYPE_GLOBAL, Flags,
237*93102974SSam Clegg                                    nullptr, &Global->getType()))
238*93102974SSam Clegg     replaceSymbol<DefinedGlobal>(S, Name, Flags, F, Global);
239*93102974SSam Clegg   return S;
240*93102974SSam Clegg }
241*93102974SSam Clegg 
242*93102974SSam Clegg Symbol *SymbolTable::addUndefined(StringRef Name, WasmSymbolType Type,
24320db381bSSam Clegg                                   uint32_t Flags, InputFile *F,
244*93102974SSam Clegg                                   const WasmSignature *FunctionType,
245*93102974SSam Clegg                                   const WasmGlobalType *GlobalType) {
246*93102974SSam Clegg   DEBUG(dbgs() << "addUndefined type=" << Type << ": " << Name << "\n");
247c03c9040SRui Ueyama 
248c94d393aSSam Clegg   Symbol *S;
249c94d393aSSam Clegg   bool WasInserted;
25020db381bSSam Clegg   std::tie(S, WasInserted) = insert(Name);
251c03c9040SRui Ueyama 
252c94d393aSSam Clegg   if (WasInserted) {
253*93102974SSam Clegg     switch (Type) {
254*93102974SSam Clegg     case WASM_SYMBOL_TYPE_FUNCTION:
255*93102974SSam Clegg       replaceSymbol<UndefinedFunction>(S, Name, Flags, F, FunctionType);
256*93102974SSam Clegg       break;
257*93102974SSam Clegg     case WASM_SYMBOL_TYPE_GLOBAL:
258*93102974SSam Clegg       replaceSymbol<UndefinedGlobal>(S, Name, Flags, F, GlobalType);
259*93102974SSam Clegg       break;
260*93102974SSam Clegg     case WASM_SYMBOL_TYPE_DATA:
26100245539SSam Clegg       replaceSymbol<UndefinedData>(S, Name, Flags, F);
262*93102974SSam Clegg       break;
263*93102974SSam Clegg     }
264c03c9040SRui Ueyama     return S;
265c03c9040SRui Ueyama   }
266c03c9040SRui Ueyama 
267c03c9040SRui Ueyama   if (auto *Lazy = dyn_cast<LazySymbol>(S)) {
268c94d393aSSam Clegg     DEBUG(dbgs() << "resolved by existing lazy\n");
269c03c9040SRui Ueyama     cast<ArchiveFile>(Lazy->getFile())->addMember(&Lazy->getArchiveSymbol());
270c03c9040SRui Ueyama     return S;
271c03c9040SRui Ueyama   }
272c03c9040SRui Ueyama 
273c03c9040SRui Ueyama   if (S->isDefined()) {
274c94d393aSSam Clegg     DEBUG(dbgs() << "resolved by existing\n");
275*93102974SSam Clegg     checkSymbolTypes(*S, *F, Type, FunctionType, GlobalType);
276c94d393aSSam Clegg   }
277*93102974SSam Clegg 
278c94d393aSSam Clegg   return S;
279c94d393aSSam Clegg }
280c94d393aSSam Clegg 
281c94d393aSSam Clegg void SymbolTable::addLazy(ArchiveFile *F, const Archive::Symbol *Sym) {
282a681a116SSam Clegg   DEBUG(dbgs() << "addLazy: " << Sym->getName() << "\n");
283c94d393aSSam Clegg   StringRef Name = Sym->getName();
284c03c9040SRui Ueyama 
285c94d393aSSam Clegg   Symbol *S;
286c94d393aSSam Clegg   bool WasInserted;
287c94d393aSSam Clegg   std::tie(S, WasInserted) = insert(Name);
288c03c9040SRui Ueyama 
289c94d393aSSam Clegg   if (WasInserted) {
290dfb0b2c7SSam Clegg     replaceSymbol<LazySymbol>(S, Name, F, *Sym);
291c03c9040SRui Ueyama     return;
292c03c9040SRui Ueyama   }
293c03c9040SRui Ueyama 
294c03c9040SRui Ueyama   // If there is an existing undefined symbol, load a new one from the archive.
295c03c9040SRui Ueyama   if (S->isUndefined()) {
296c94d393aSSam Clegg     DEBUG(dbgs() << "replacing existing undefined\n");
297c94d393aSSam Clegg     F->addMember(Sym);
298c94d393aSSam Clegg   }
299c94d393aSSam Clegg }
300e0f6fcd0SSam Clegg 
301e0f6fcd0SSam Clegg bool SymbolTable::addComdat(StringRef Name, ObjFile *F) {
302e0f6fcd0SSam Clegg   DEBUG(dbgs() << "addComdat: " << Name << "\n");
303e0f6fcd0SSam Clegg   ObjFile *&File = ComdatMap[CachedHashStringRef(Name)];
304e0f6fcd0SSam Clegg   if (File) {
305e0f6fcd0SSam Clegg     DEBUG(dbgs() << "COMDAT already defined\n");
306e0f6fcd0SSam Clegg     return false;
307e0f6fcd0SSam Clegg   }
308e0f6fcd0SSam Clegg   File = F;
309e0f6fcd0SSam Clegg   return true;
310e0f6fcd0SSam Clegg }
311e0f6fcd0SSam Clegg 
312e0f6fcd0SSam Clegg ObjFile *SymbolTable::findComdat(StringRef Name) const {
313e0f6fcd0SSam Clegg   auto It = ComdatMap.find(CachedHashStringRef(Name));
314e0f6fcd0SSam Clegg   return It == ComdatMap.end() ? nullptr : It->second;
315e0f6fcd0SSam Clegg }
316