blob: 8706698df741ed6fd2559ad823b6d5908c685edf [file] [log] [blame]
Sam Cleggc94d3932017-11-17 18:14:09 +00001//===- SymbolTable.cpp ----------------------------------------------------===//
2//
3// The LLVM Linker
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "SymbolTable.h"
11
12#include "Config.h"
Sam Clegg5fa274b2018-01-10 01:13:34 +000013#include "InputChunks.h"
Sam Cleggb8621592017-11-30 01:40:08 +000014#include "WriterUtils.h"
Sam Cleggc94d3932017-11-17 18:14:09 +000015#include "lld/Common/ErrorHandler.h"
Rui Ueyama2017d522017-11-28 20:39:17 +000016#include "lld/Common/Memory.h"
Sam Cleggc94d3932017-11-17 18:14:09 +000017
18#include <unordered_set>
19
20#define DEBUG_TYPE "lld"
21
22using namespace llvm;
Sam Clegg20db3812018-01-10 00:52:20 +000023using namespace llvm::wasm;
Sam Cleggc94d3932017-11-17 18:14:09 +000024using namespace lld;
25using namespace lld::wasm;
26
27SymbolTable *lld::wasm::Symtab;
28
29void SymbolTable::addFile(InputFile *File) {
30 log("Processing: " + toString(File));
31 File->parse();
32
33 if (auto *F = dyn_cast<ObjFile>(File))
34 ObjectFiles.push_back(F);
35}
36
37void SymbolTable::reportRemainingUndefines() {
38 std::unordered_set<Symbol *> Undefs;
Sam Clegg74fe0ba2017-12-07 01:51:24 +000039 for (Symbol *Sym : SymVector) {
Sam Cleggc94d3932017-11-17 18:14:09 +000040 if (Sym->isUndefined() && !Sym->isWeak() &&
41 Config->AllowUndefinedSymbols.count(Sym->getName()) == 0) {
42 Undefs.insert(Sym);
43 }
44 }
45
46 if (Undefs.empty())
47 return;
48
49 for (ObjFile *File : ObjectFiles)
50 for (Symbol *Sym : File->getSymbols())
51 if (Undefs.count(Sym))
52 error(toString(File) + ": undefined symbol: " + toString(*Sym));
53
54 for (Symbol *Sym : Undefs)
55 if (!Sym->getFile())
56 error("undefined symbol: " + toString(*Sym));
57}
58
59Symbol *SymbolTable::find(StringRef Name) {
Sam Clegga80d94d2017-11-27 23:16:06 +000060 auto It = SymMap.find(CachedHashStringRef(Name));
61 if (It == SymMap.end())
Sam Cleggc94d3932017-11-17 18:14:09 +000062 return nullptr;
63 return It->second;
64}
65
66std::pair<Symbol *, bool> SymbolTable::insert(StringRef Name) {
Sam Clegga80d94d2017-11-27 23:16:06 +000067 Symbol *&Sym = SymMap[CachedHashStringRef(Name)];
Sam Cleggc94d3932017-11-17 18:14:09 +000068 if (Sym)
69 return {Sym, false};
70 Sym = make<Symbol>(Name, false);
Sam Clegg74fe0ba2017-12-07 01:51:24 +000071 SymVector.emplace_back(Sym);
Sam Cleggc94d3932017-11-17 18:14:09 +000072 return {Sym, true};
73}
74
75void SymbolTable::reportDuplicate(Symbol *Existing, InputFile *NewFile) {
76 error("duplicate symbol: " + toString(*Existing) + "\n>>> defined in " +
77 toString(Existing->getFile()) + "\n>>> defined in " +
Sam Clegge2ed0922017-11-27 22:49:16 +000078 toString(NewFile));
Sam Cleggc94d3932017-11-17 18:14:09 +000079}
80
Sam Cleggb8621592017-11-30 01:40:08 +000081// Check the type of new symbol matches that of the symbol is replacing.
82// For functions this can also involve verifying that the signatures match.
83static void checkSymbolTypes(const Symbol &Existing, const InputFile &F,
Sam Clegg20db3812018-01-10 00:52:20 +000084 Symbol::Kind Kind, const WasmSignature *NewSig) {
Sam Cleggb8621592017-11-30 01:40:08 +000085 if (Existing.isLazy())
Sam Cleggc94d3932017-11-17 18:14:09 +000086 return;
87
Sam Clegg20db3812018-01-10 00:52:20 +000088 bool NewIsFunction = Kind == Symbol::Kind::UndefinedFunctionKind ||
89 Kind == Symbol::Kind::DefinedFunctionKind;
Sam Cleggb8621592017-11-30 01:40:08 +000090
91 // First check the symbol types match (i.e. either both are function
92 // symbols or both are data symbols).
93 if (Existing.isFunction() != NewIsFunction) {
Sam Clegg20db3812018-01-10 00:52:20 +000094 error("symbol type mismatch: " + Existing.getName() + "\n>>> defined as " +
Sam Cleggb8621592017-11-30 01:40:08 +000095 (Existing.isFunction() ? "Function" : "Global") + " in " +
96 toString(Existing.getFile()) + "\n>>> defined as " +
97 (NewIsFunction ? "Function" : "Global") + " in " + F.getName());
98 return;
99 }
100
101 // For function symbols, optionally check the function signature matches too.
102 if (!NewIsFunction || !Config->CheckSignatures)
Sam Cleggc94d3932017-11-17 18:14:09 +0000103 return;
Sam Clegg31de2f02017-12-07 03:19:53 +0000104 // Skip the signature check if the existing function has no signature (e.g.
105 // if it is an undefined symbol generated by --undefined command line flag).
106 if (!Existing.hasFunctionType())
107 return;
Sam Cleggc94d3932017-11-17 18:14:09 +0000108
Sam Clegg20db3812018-01-10 00:52:20 +0000109 DEBUG(dbgs() << "checkSymbolTypes: " << Existing.getName() << "\n");
Sam Cleggb8621592017-11-30 01:40:08 +0000110 assert(NewSig);
111
112 const WasmSignature &OldSig = Existing.getFunctionType();
113 if (*NewSig == OldSig)
114 return;
115
Sam Clegg20db3812018-01-10 00:52:20 +0000116 error("function signature mismatch: " + Existing.getName() +
117 "\n>>> defined as " + toString(OldSig) + " in " +
118 toString(Existing.getFile()) + "\n>>> defined as " + toString(*NewSig) +
119 " in " + F.getName());
Sam Cleggc94d3932017-11-17 18:14:09 +0000120}
121
122Symbol *SymbolTable::addDefinedGlobal(StringRef Name) {
123 DEBUG(dbgs() << "addDefinedGlobal: " << Name << "\n");
124 Symbol *S;
125 bool WasInserted;
126 std::tie(S, WasInserted) = insert(Name);
127 if (WasInserted)
128 S->update(Symbol::DefinedGlobalKind);
129 else if (!S->isGlobal())
130 error("symbol type mismatch: " + Name);
131 return S;
132}
133
Sam Clegg20db3812018-01-10 00:52:20 +0000134Symbol *SymbolTable::addDefined(StringRef Name, Symbol::Kind Kind,
135 uint32_t Flags, InputFile *F,
Sam Clegg8d146bb2018-01-09 23:56:44 +0000136 const InputSegment *Segment,
Sam Clegg20db3812018-01-10 00:52:20 +0000137 InputFunction *Function, uint32_t Address) {
138 DEBUG(dbgs() << "addDefined: " << Name << " addr:" << Address << "\n");
Sam Cleggc94d3932017-11-17 18:14:09 +0000139 Symbol *S;
140 bool WasInserted;
Sam Cleggc94d3932017-11-17 18:14:09 +0000141
Sam Clegg20db3812018-01-10 00:52:20 +0000142 std::tie(S, WasInserted) = insert(Name);
Sam Cleggc94d3932017-11-17 18:14:09 +0000143 if (WasInserted) {
Sam Clegg20db3812018-01-10 00:52:20 +0000144 S->update(Kind, F, Flags, Segment, Function, Address);
Sam Cleggb8621592017-11-30 01:40:08 +0000145 } else if (S->isLazy()) {
146 // The existing symbol is lazy. Replace it without checking types since
147 // lazy symbols don't have any type information.
Sam Clegg20db3812018-01-10 00:52:20 +0000148 DEBUG(dbgs() << "replacing existing lazy symbol: " << Name << "\n");
149 S->update(Kind, F, Flags, Segment, Function, Address);
Sam Cleggc94d3932017-11-17 18:14:09 +0000150 } else if (!S->isDefined()) {
151 // The existing symbol table entry is undefined. The new symbol replaces
Sam Clegg49ed9262017-12-01 00:53:21 +0000152 // it, after checking the type matches
Sam Clegg20db3812018-01-10 00:52:20 +0000153 DEBUG(dbgs() << "resolving existing undefined symbol: " << Name << "\n");
154 checkSymbolTypes(*S, *F, Kind, Function ? &Function->Signature : nullptr);
155 S->update(Kind, F, Flags, Segment, Function, Address);
156 } else if ((Flags & WASM_SYMBOL_BINDING_MASK) == WASM_SYMBOL_BINDING_WEAK) {
Sam Cleggc94d3932017-11-17 18:14:09 +0000157 // the new symbol is weak we can ignore it
Sam Clegg49ed9262017-12-01 00:53:21 +0000158 DEBUG(dbgs() << "existing symbol takes precedence\n");
Sam Cleggc94d3932017-11-17 18:14:09 +0000159 } else if (S->isWeak()) {
160 // the new symbol is not weak and the existing symbol is, so we replace
161 // it
162 DEBUG(dbgs() << "replacing existing weak symbol\n");
Sam Clegg20db3812018-01-10 00:52:20 +0000163 checkSymbolTypes(*S, *F, Kind, Function ? &Function->Signature : nullptr);
164 S->update(Kind, F, Flags, Segment, Function, Address);
Sam Cleggc94d3932017-11-17 18:14:09 +0000165 } else {
Sam Clegg49ed9262017-12-01 00:53:21 +0000166 // neither symbol is week. They conflict.
Sam Cleggc94d3932017-11-17 18:14:09 +0000167 reportDuplicate(S, F);
168 }
169 return S;
170}
171
Sam Cleggb8621592017-11-30 01:40:08 +0000172Symbol *SymbolTable::addUndefinedFunction(StringRef Name,
173 const WasmSignature *Type) {
Sam Cleggc94d3932017-11-17 18:14:09 +0000174 Symbol *S;
175 bool WasInserted;
176 std::tie(S, WasInserted) = insert(Name);
Sam Cleggb8621592017-11-30 01:40:08 +0000177 if (WasInserted) {
Sam Clegg8d146bb2018-01-09 23:56:44 +0000178 S->update(Symbol::UndefinedFunctionKind);
179 S->setFunctionType(Type);
Sam Cleggb8621592017-11-30 01:40:08 +0000180 } else if (!S->isFunction()) {
Sam Cleggc94d3932017-11-17 18:14:09 +0000181 error("symbol type mismatch: " + Name);
Sam Cleggb8621592017-11-30 01:40:08 +0000182 }
Sam Cleggc94d3932017-11-17 18:14:09 +0000183 return S;
184}
185
Sam Clegg20db3812018-01-10 00:52:20 +0000186Symbol *SymbolTable::addUndefined(StringRef Name, Symbol::Kind Kind,
187 uint32_t Flags, InputFile *F,
Sam Clegg8d146bb2018-01-09 23:56:44 +0000188 const WasmSignature *Type) {
Sam Clegg20db3812018-01-10 00:52:20 +0000189 DEBUG(dbgs() << "addUndefined: " << Name << "\n");
Sam Cleggc94d3932017-11-17 18:14:09 +0000190 Symbol *S;
191 bool WasInserted;
Sam Clegg20db3812018-01-10 00:52:20 +0000192 std::tie(S, WasInserted) = insert(Name);
Sam Cleggc94d3932017-11-17 18:14:09 +0000193 if (WasInserted) {
Sam Clegg20db3812018-01-10 00:52:20 +0000194 S->update(Kind, F, Flags);
Sam Clegg8d146bb2018-01-09 23:56:44 +0000195 if (Type)
196 S->setFunctionType(Type);
Sam Cleggc94d3932017-11-17 18:14:09 +0000197 } else if (S->isLazy()) {
198 DEBUG(dbgs() << "resolved by existing lazy\n");
199 auto *AF = cast<ArchiveFile>(S->getFile());
200 AF->addMember(&S->getArchiveSymbol());
201 } else if (S->isDefined()) {
202 DEBUG(dbgs() << "resolved by existing\n");
Sam Clegg20db3812018-01-10 00:52:20 +0000203 checkSymbolTypes(*S, *F, Kind, Type);
Sam Cleggc94d3932017-11-17 18:14:09 +0000204 }
205 return S;
206}
207
208void SymbolTable::addLazy(ArchiveFile *F, const Archive::Symbol *Sym) {
Sam Clegga681a112017-12-06 03:10:39 +0000209 DEBUG(dbgs() << "addLazy: " << Sym->getName() << "\n");
Sam Cleggc94d3932017-11-17 18:14:09 +0000210 StringRef Name = Sym->getName();
211 Symbol *S;
212 bool WasInserted;
213 std::tie(S, WasInserted) = insert(Name);
214 if (WasInserted) {
215 S->update(Symbol::LazyKind, F);
216 S->setArchiveSymbol(*Sym);
217 } else if (S->isUndefined()) {
218 // There is an existing undefined symbol. The can load from the
219 // archive.
220 DEBUG(dbgs() << "replacing existing undefined\n");
221 F->addMember(Sym);
222 }
223}