blob: 492a809c42a62b1a0995c0d5df55fc22b42f35f0 [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"
13#include "Memory.h"
14#include "Strings.h"
15#include "lld/Common/ErrorHandler.h"
16
17#include <unordered_set>
18
19#define DEBUG_TYPE "lld"
20
21using namespace llvm;
22using namespace lld;
23using namespace lld::wasm;
24
25SymbolTable *lld::wasm::Symtab;
26
27void SymbolTable::addFile(InputFile *File) {
28 log("Processing: " + toString(File));
29 File->parse();
30
31 if (auto *F = dyn_cast<ObjFile>(File))
32 ObjectFiles.push_back(F);
33}
34
35void SymbolTable::reportRemainingUndefines() {
36 std::unordered_set<Symbol *> Undefs;
37 for (auto &I : Symtab) {
38 Symbol *Sym = I.second;
39 if (Sym->isUndefined() && !Sym->isWeak() &&
40 Config->AllowUndefinedSymbols.count(Sym->getName()) == 0) {
41 Undefs.insert(Sym);
42 }
43 }
44
45 if (Undefs.empty())
46 return;
47
48 for (ObjFile *File : ObjectFiles)
49 for (Symbol *Sym : File->getSymbols())
50 if (Undefs.count(Sym))
51 error(toString(File) + ": undefined symbol: " + toString(*Sym));
52
53 for (Symbol *Sym : Undefs)
54 if (!Sym->getFile())
55 error("undefined symbol: " + toString(*Sym));
56}
57
58Symbol *SymbolTable::find(StringRef Name) {
59 auto It = Symtab.find(CachedHashStringRef(Name));
60 if (It == Symtab.end())
61 return nullptr;
62 return It->second;
63}
64
65std::pair<Symbol *, bool> SymbolTable::insert(StringRef Name) {
66 Symbol *&Sym = Symtab[CachedHashStringRef(Name)];
67 if (Sym)
68 return {Sym, false};
69 Sym = make<Symbol>(Name, false);
70 return {Sym, true};
71}
72
73void SymbolTable::reportDuplicate(Symbol *Existing, InputFile *NewFile) {
74 error("duplicate symbol: " + toString(*Existing) + "\n>>> defined in " +
75 toString(Existing->getFile()) + "\n>>> defined in " +
76 (NewFile ? toString(NewFile) : "<internal>"));
77}
78
79static void checkSymbolTypes(Symbol *Existing, InputFile *F,
80 const WasmSymbol *New) {
81 if (Existing->isLazy())
82 return;
83
84 bool NewIsFunction = New->Type == WasmSymbol::SymbolType::FUNCTION_EXPORT ||
85 New->Type == WasmSymbol::SymbolType::FUNCTION_IMPORT;
86 if (Existing->isFunction() == NewIsFunction)
87 return;
88
89 std::string Filename = "<builtin>";
90 if (Existing->getFile())
91 Filename = toString(Existing->getFile());
92 error("symbol type mismatch: " + New->Name + "\n>>> defined as " +
93 (Existing->isFunction() ? "Function" : "Global") + " in " + Filename +
94 "\n>>> defined as " + (NewIsFunction ? "Function" : "Global") + " in " +
95 F->getName());
96}
97
98Symbol *SymbolTable::addDefinedGlobal(StringRef Name) {
99 DEBUG(dbgs() << "addDefinedGlobal: " << Name << "\n");
100 Symbol *S;
101 bool WasInserted;
102 std::tie(S, WasInserted) = insert(Name);
103 if (WasInserted)
104 S->update(Symbol::DefinedGlobalKind);
105 else if (!S->isGlobal())
106 error("symbol type mismatch: " + Name);
107 return S;
108}
109
110Symbol *SymbolTable::addDefined(InputFile *F, const WasmSymbol *Sym,
111 const InputSegment *Segment) {
112 DEBUG(dbgs() << "addDefined: " << Sym->Name << "\n");
113 Symbol *S;
114 bool WasInserted;
115 Symbol::Kind Kind = Symbol::DefinedFunctionKind;
116 if (Sym->Type == WasmSymbol::SymbolType::GLOBAL_EXPORT)
117 Kind = Symbol::DefinedGlobalKind;
118
119 std::tie(S, WasInserted) = insert(Sym->Name);
120 if (WasInserted) {
121 S->update(Kind, F, Sym, Segment);
122 } else if (!S->isDefined()) {
123 // The existing symbol table entry is undefined. The new symbol replaces
124 // it
125 DEBUG(dbgs() << "resolving existing undefined symbol: " << Sym->Name
126 << "\n");
127 checkSymbolTypes(S, F, Sym);
128 S->update(Kind, F, Sym, Segment);
129 } else if (Sym->isWeak()) {
130 // the new symbol is weak we can ignore it
131 DEBUG(dbgs() << "existing symbol takes precensence\n");
132 } else if (S->isWeak()) {
133 // the new symbol is not weak and the existing symbol is, so we replace
134 // it
135 DEBUG(dbgs() << "replacing existing weak symbol\n");
136 S->update(Kind, F, Sym, Segment);
137 } else {
138 // niether symbol is week. They conflict.
139 reportDuplicate(S, F);
140 }
141 return S;
142}
143
144Symbol *SymbolTable::addUndefinedFunction(StringRef Name) {
145 Symbol *S;
146 bool WasInserted;
147 std::tie(S, WasInserted) = insert(Name);
148 if (WasInserted)
149 S->update(Symbol::UndefinedFunctionKind);
150 else if (!S->isFunction())
151 error("symbol type mismatch: " + Name);
152 return S;
153}
154
155Symbol *SymbolTable::addUndefined(InputFile *F, const WasmSymbol *Sym) {
156 DEBUG(dbgs() << "addUndefined: " << displayName(Sym->Name) << "\n");
157 Symbol *S;
158 bool WasInserted;
159 Symbol::Kind Kind = Symbol::UndefinedFunctionKind;
160 if (Sym->Type == WasmSymbol::SymbolType::GLOBAL_IMPORT)
161 Kind = Symbol::UndefinedGlobalKind;
162 std::tie(S, WasInserted) = insert(Sym->Name);
163 if (WasInserted) {
164 S->update(Kind, F, Sym);
165 } else if (S->isLazy()) {
166 DEBUG(dbgs() << "resolved by existing lazy\n");
167 auto *AF = cast<ArchiveFile>(S->getFile());
168 AF->addMember(&S->getArchiveSymbol());
169 } else if (S->isDefined()) {
170 DEBUG(dbgs() << "resolved by existing\n");
171 checkSymbolTypes(S, F, Sym);
172 }
173 return S;
174}
175
176void SymbolTable::addLazy(ArchiveFile *F, const Archive::Symbol *Sym) {
177 DEBUG(dbgs() << "addLazy: " << displayName(Sym->getName()) << "\n");
178 StringRef Name = Sym->getName();
179 Symbol *S;
180 bool WasInserted;
181 std::tie(S, WasInserted) = insert(Name);
182 if (WasInserted) {
183 S->update(Symbol::LazyKind, F);
184 S->setArchiveSymbol(*Sym);
185 } else if (S->isUndefined()) {
186 // There is an existing undefined symbol. The can load from the
187 // archive.
188 DEBUG(dbgs() << "replacing existing undefined\n");
189 F->addMember(Sym);
190 }
191}