blob: 722d5a0da1637d07dcc33accbe139919091bc459 [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;
Sam Clegga80d94d2017-11-27 23:16:06 +000037 for (auto &I : SymMap) {
Sam Cleggc94d3932017-11-17 18:14:09 +000038 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) {
Sam Clegga80d94d2017-11-27 23:16:06 +000059 auto It = SymMap.find(CachedHashStringRef(Name));
60 if (It == SymMap.end())
Sam Cleggc94d3932017-11-17 18:14:09 +000061 return nullptr;
62 return It->second;
63}
64
65std::pair<Symbol *, bool> SymbolTable::insert(StringRef Name) {
Sam Clegga80d94d2017-11-27 23:16:06 +000066 Symbol *&Sym = SymMap[CachedHashStringRef(Name)];
Sam Cleggc94d3932017-11-17 18:14:09 +000067 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 " +
Sam Clegge2ed0922017-11-27 22:49:16 +000076 toString(NewFile));
Sam Cleggc94d3932017-11-17 18:14:09 +000077}
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
Sam Cleggc94d3932017-11-17 18:14:09 +000089 error("symbol type mismatch: " + New->Name + "\n>>> defined as " +
Sam Clegge2ed0922017-11-27 22:49:16 +000090 (Existing->isFunction() ? "Function" : "Global") + " in " +
91 toString(Existing->getFile()) + "\n>>> defined as " +
92 (NewIsFunction ? "Function" : "Global") + " in " + F->getName());
Sam Cleggc94d3932017-11-17 18:14:09 +000093}
94
95Symbol *SymbolTable::addDefinedGlobal(StringRef Name) {
96 DEBUG(dbgs() << "addDefinedGlobal: " << Name << "\n");
97 Symbol *S;
98 bool WasInserted;
99 std::tie(S, WasInserted) = insert(Name);
100 if (WasInserted)
101 S->update(Symbol::DefinedGlobalKind);
102 else if (!S->isGlobal())
103 error("symbol type mismatch: " + Name);
104 return S;
105}
106
107Symbol *SymbolTable::addDefined(InputFile *F, const WasmSymbol *Sym,
108 const InputSegment *Segment) {
109 DEBUG(dbgs() << "addDefined: " << Sym->Name << "\n");
110 Symbol *S;
111 bool WasInserted;
112 Symbol::Kind Kind = Symbol::DefinedFunctionKind;
113 if (Sym->Type == WasmSymbol::SymbolType::GLOBAL_EXPORT)
114 Kind = Symbol::DefinedGlobalKind;
115
116 std::tie(S, WasInserted) = insert(Sym->Name);
117 if (WasInserted) {
118 S->update(Kind, F, Sym, Segment);
119 } else if (!S->isDefined()) {
120 // The existing symbol table entry is undefined. The new symbol replaces
121 // it
122 DEBUG(dbgs() << "resolving existing undefined symbol: " << Sym->Name
123 << "\n");
124 checkSymbolTypes(S, F, Sym);
125 S->update(Kind, F, Sym, Segment);
126 } else if (Sym->isWeak()) {
127 // the new symbol is weak we can ignore it
128 DEBUG(dbgs() << "existing symbol takes precensence\n");
129 } else if (S->isWeak()) {
130 // the new symbol is not weak and the existing symbol is, so we replace
131 // it
132 DEBUG(dbgs() << "replacing existing weak symbol\n");
133 S->update(Kind, F, Sym, Segment);
134 } else {
135 // niether symbol is week. They conflict.
136 reportDuplicate(S, F);
137 }
138 return S;
139}
140
141Symbol *SymbolTable::addUndefinedFunction(StringRef Name) {
142 Symbol *S;
143 bool WasInserted;
144 std::tie(S, WasInserted) = insert(Name);
145 if (WasInserted)
146 S->update(Symbol::UndefinedFunctionKind);
147 else if (!S->isFunction())
148 error("symbol type mismatch: " + Name);
149 return S;
150}
151
152Symbol *SymbolTable::addUndefined(InputFile *F, const WasmSymbol *Sym) {
153 DEBUG(dbgs() << "addUndefined: " << displayName(Sym->Name) << "\n");
154 Symbol *S;
155 bool WasInserted;
156 Symbol::Kind Kind = Symbol::UndefinedFunctionKind;
157 if (Sym->Type == WasmSymbol::SymbolType::GLOBAL_IMPORT)
158 Kind = Symbol::UndefinedGlobalKind;
159 std::tie(S, WasInserted) = insert(Sym->Name);
160 if (WasInserted) {
161 S->update(Kind, F, Sym);
162 } else if (S->isLazy()) {
163 DEBUG(dbgs() << "resolved by existing lazy\n");
164 auto *AF = cast<ArchiveFile>(S->getFile());
165 AF->addMember(&S->getArchiveSymbol());
166 } else if (S->isDefined()) {
167 DEBUG(dbgs() << "resolved by existing\n");
168 checkSymbolTypes(S, F, Sym);
169 }
170 return S;
171}
172
173void SymbolTable::addLazy(ArchiveFile *F, const Archive::Symbol *Sym) {
174 DEBUG(dbgs() << "addLazy: " << displayName(Sym->getName()) << "\n");
175 StringRef Name = Sym->getName();
176 Symbol *S;
177 bool WasInserted;
178 std::tie(S, WasInserted) = insert(Name);
179 if (WasInserted) {
180 S->update(Symbol::LazyKind, F);
181 S->setArchiveSymbol(*Sym);
182 } else if (S->isUndefined()) {
183 // There is an existing undefined symbol. The can load from the
184 // archive.
185 DEBUG(dbgs() << "replacing existing undefined\n");
186 F->addMember(Sym);
187 }
188}