1 //===- Symbols.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 "Symbols.h"
10 #include "Config.h"
11 #include "InputChunks.h"
12 #include "InputEvent.h"
13 #include "InputFiles.h"
14 #include "InputGlobal.h"
15 #include "OutputSections.h"
16 #include "OutputSegment.h"
17 #include "lld/Common/ErrorHandler.h"
18 #include "lld/Common/Strings.h"
19
20 #define DEBUG_TYPE "lld"
21
22 using namespace llvm;
23 using namespace llvm::object;
24 using namespace llvm::wasm;
25
26 namespace lld {
toString(const wasm::Symbol & sym)27 std::string toString(const wasm::Symbol &sym) {
28 return maybeDemangleSymbol(sym.getName());
29 }
30
maybeDemangleSymbol(StringRef name)31 std::string maybeDemangleSymbol(StringRef name) {
32 if (wasm::config->demangle)
33 return demangleItanium(name);
34 return name;
35 }
36
toString(wasm::Symbol::Kind kind)37 std::string toString(wasm::Symbol::Kind kind) {
38 switch (kind) {
39 case wasm::Symbol::DefinedFunctionKind:
40 return "DefinedFunction";
41 case wasm::Symbol::DefinedDataKind:
42 return "DefinedData";
43 case wasm::Symbol::DefinedGlobalKind:
44 return "DefinedGlobal";
45 case wasm::Symbol::DefinedEventKind:
46 return "DefinedEvent";
47 case wasm::Symbol::UndefinedFunctionKind:
48 return "UndefinedFunction";
49 case wasm::Symbol::UndefinedDataKind:
50 return "UndefinedData";
51 case wasm::Symbol::UndefinedGlobalKind:
52 return "UndefinedGlobal";
53 case wasm::Symbol::LazyKind:
54 return "LazyKind";
55 case wasm::Symbol::SectionKind:
56 return "SectionKind";
57 case wasm::Symbol::OutputSectionKind:
58 return "OutputSectionKind";
59 }
60 llvm_unreachable("invalid symbol kind");
61 }
62
63 namespace wasm {
64 DefinedFunction *WasmSym::callCtors;
65 DefinedFunction *WasmSym::initMemory;
66 DefinedFunction *WasmSym::applyRelocs;
67 DefinedFunction *WasmSym::initTLS;
68 DefinedData *WasmSym::dsoHandle;
69 DefinedData *WasmSym::dataEnd;
70 DefinedData *WasmSym::globalBase;
71 DefinedData *WasmSym::heapBase;
72 DefinedData *WasmSym::initMemoryFlag;
73 GlobalSymbol *WasmSym::stackPointer;
74 GlobalSymbol *WasmSym::tlsBase;
75 GlobalSymbol *WasmSym::tlsSize;
76 GlobalSymbol *WasmSym::tlsAlign;
77 UndefinedGlobal *WasmSym::tableBase;
78 DefinedData *WasmSym::definedTableBase;
79 UndefinedGlobal *WasmSym::memoryBase;
80 DefinedData *WasmSym::definedMemoryBase;
81
getWasmType() const82 WasmSymbolType Symbol::getWasmType() const {
83 if (isa<FunctionSymbol>(this))
84 return WASM_SYMBOL_TYPE_FUNCTION;
85 if (isa<DataSymbol>(this))
86 return WASM_SYMBOL_TYPE_DATA;
87 if (isa<GlobalSymbol>(this))
88 return WASM_SYMBOL_TYPE_GLOBAL;
89 if (isa<EventSymbol>(this))
90 return WASM_SYMBOL_TYPE_EVENT;
91 if (isa<SectionSymbol>(this) || isa<OutputSectionSymbol>(this))
92 return WASM_SYMBOL_TYPE_SECTION;
93 llvm_unreachable("invalid symbol kind");
94 }
95
getSignature() const96 const WasmSignature *Symbol::getSignature() const {
97 if (auto* f = dyn_cast<FunctionSymbol>(this))
98 return f->signature;
99 if (auto *l = dyn_cast<LazySymbol>(this))
100 return l->signature;
101 return nullptr;
102 }
103
getChunk() const104 InputChunk *Symbol::getChunk() const {
105 if (auto *f = dyn_cast<DefinedFunction>(this))
106 return f->function;
107 if (auto *d = dyn_cast<DefinedData>(this))
108 return d->segment;
109 return nullptr;
110 }
111
isDiscarded() const112 bool Symbol::isDiscarded() const {
113 if (InputChunk *c = getChunk())
114 return c->discarded;
115 return false;
116 }
117
isLive() const118 bool Symbol::isLive() const {
119 if (auto *g = dyn_cast<DefinedGlobal>(this))
120 return g->global->live;
121 if (auto *e = dyn_cast<DefinedEvent>(this))
122 return e->event->live;
123 if (InputChunk *c = getChunk())
124 return c->live;
125 return referenced;
126 }
127
markLive()128 void Symbol::markLive() {
129 assert(!isDiscarded());
130 if (auto *g = dyn_cast<DefinedGlobal>(this))
131 g->global->live = true;
132 if (auto *e = dyn_cast<DefinedEvent>(this))
133 e->event->live = true;
134 if (InputChunk *c = getChunk())
135 c->live = true;
136 referenced = true;
137 }
138
getOutputSymbolIndex() const139 uint32_t Symbol::getOutputSymbolIndex() const {
140 assert(outputSymbolIndex != INVALID_INDEX);
141 return outputSymbolIndex;
142 }
143
setOutputSymbolIndex(uint32_t index)144 void Symbol::setOutputSymbolIndex(uint32_t index) {
145 LLVM_DEBUG(dbgs() << "setOutputSymbolIndex " << name << " -> " << index
146 << "\n");
147 assert(outputSymbolIndex == INVALID_INDEX);
148 outputSymbolIndex = index;
149 }
150
setGOTIndex(uint32_t index)151 void Symbol::setGOTIndex(uint32_t index) {
152 LLVM_DEBUG(dbgs() << "setGOTIndex " << name << " -> " << index << "\n");
153 assert(gotIndex == INVALID_INDEX);
154 if (config->isPic) {
155 // Any symbol that is assigned a GOT entry must be exported othewise the
156 // dynamic linker won't be able create the entry that contains it.
157 forceExport = true;
158 }
159 gotIndex = index;
160 }
161
isWeak() const162 bool Symbol::isWeak() const {
163 return (flags & WASM_SYMBOL_BINDING_MASK) == WASM_SYMBOL_BINDING_WEAK;
164 }
165
isLocal() const166 bool Symbol::isLocal() const {
167 return (flags & WASM_SYMBOL_BINDING_MASK) == WASM_SYMBOL_BINDING_LOCAL;
168 }
169
isHidden() const170 bool Symbol::isHidden() const {
171 return (flags & WASM_SYMBOL_VISIBILITY_MASK) == WASM_SYMBOL_VISIBILITY_HIDDEN;
172 }
173
setHidden(bool isHidden)174 void Symbol::setHidden(bool isHidden) {
175 LLVM_DEBUG(dbgs() << "setHidden: " << name << " -> " << isHidden << "\n");
176 flags &= ~WASM_SYMBOL_VISIBILITY_MASK;
177 if (isHidden)
178 flags |= WASM_SYMBOL_VISIBILITY_HIDDEN;
179 else
180 flags |= WASM_SYMBOL_VISIBILITY_DEFAULT;
181 }
182
isExported() const183 bool Symbol::isExported() const {
184 if (!isDefined() || isLocal())
185 return false;
186
187 if (forceExport || config->exportAll)
188 return true;
189
190 if (config->exportDynamic && !isHidden())
191 return true;
192
193 return flags & WASM_SYMBOL_EXPORTED;
194 }
195
isNoStrip() const196 bool Symbol::isNoStrip() const {
197 return flags & WASM_SYMBOL_NO_STRIP;
198 }
199
getFunctionIndex() const200 uint32_t FunctionSymbol::getFunctionIndex() const {
201 if (auto *f = dyn_cast<DefinedFunction>(this))
202 return f->function->getFunctionIndex();
203 assert(functionIndex != INVALID_INDEX);
204 return functionIndex;
205 }
206
setFunctionIndex(uint32_t index)207 void FunctionSymbol::setFunctionIndex(uint32_t index) {
208 LLVM_DEBUG(dbgs() << "setFunctionIndex " << name << " -> " << index << "\n");
209 assert(functionIndex == INVALID_INDEX);
210 functionIndex = index;
211 }
212
hasFunctionIndex() const213 bool FunctionSymbol::hasFunctionIndex() const {
214 if (auto *f = dyn_cast<DefinedFunction>(this))
215 return f->function->hasFunctionIndex();
216 return functionIndex != INVALID_INDEX;
217 }
218
getTableIndex() const219 uint32_t FunctionSymbol::getTableIndex() const {
220 if (auto *f = dyn_cast<DefinedFunction>(this))
221 return f->function->getTableIndex();
222 assert(tableIndex != INVALID_INDEX);
223 return tableIndex;
224 }
225
hasTableIndex() const226 bool FunctionSymbol::hasTableIndex() const {
227 if (auto *f = dyn_cast<DefinedFunction>(this))
228 return f->function->hasTableIndex();
229 return tableIndex != INVALID_INDEX;
230 }
231
setTableIndex(uint32_t index)232 void FunctionSymbol::setTableIndex(uint32_t index) {
233 // For imports, we set the table index here on the Symbol; for defined
234 // functions we set the index on the InputFunction so that we don't export
235 // the same thing twice (keeps the table size down).
236 if (auto *f = dyn_cast<DefinedFunction>(this)) {
237 f->function->setTableIndex(index);
238 return;
239 }
240 LLVM_DEBUG(dbgs() << "setTableIndex " << name << " -> " << index << "\n");
241 assert(tableIndex == INVALID_INDEX);
242 tableIndex = index;
243 }
244
DefinedFunction(StringRef name,uint32_t flags,InputFile * f,InputFunction * function)245 DefinedFunction::DefinedFunction(StringRef name, uint32_t flags, InputFile *f,
246 InputFunction *function)
247 : FunctionSymbol(name, DefinedFunctionKind, flags, f,
248 function ? &function->signature : nullptr),
249 function(function) {}
250
getVirtualAddress() const251 uint32_t DefinedData::getVirtualAddress() const {
252 LLVM_DEBUG(dbgs() << "getVirtualAddress: " << getName() << "\n");
253 if (segment) {
254 // For thread local data, the symbol location is relative to the start of
255 // the .tdata section, since they are used as offsets from __tls_base.
256 // Hence, we do not add in segment->outputSeg->startVA.
257 if (segment->outputSeg->name == ".tdata")
258 return segment->outputSegmentOffset + offset;
259 return segment->outputSeg->startVA + segment->outputSegmentOffset + offset;
260 }
261 return offset;
262 }
263
setVirtualAddress(uint32_t value)264 void DefinedData::setVirtualAddress(uint32_t value) {
265 LLVM_DEBUG(dbgs() << "setVirtualAddress " << name << " -> " << value << "\n");
266 assert(!segment);
267 offset = value;
268 }
269
getOutputSegmentOffset() const270 uint32_t DefinedData::getOutputSegmentOffset() const {
271 LLVM_DEBUG(dbgs() << "getOutputSegmentOffset: " << getName() << "\n");
272 return segment->outputSegmentOffset + offset;
273 }
274
getOutputSegmentIndex() const275 uint32_t DefinedData::getOutputSegmentIndex() const {
276 LLVM_DEBUG(dbgs() << "getOutputSegmentIndex: " << getName() << "\n");
277 return segment->outputSeg->index;
278 }
279
getGlobalIndex() const280 uint32_t GlobalSymbol::getGlobalIndex() const {
281 if (auto *f = dyn_cast<DefinedGlobal>(this))
282 return f->global->getGlobalIndex();
283 assert(globalIndex != INVALID_INDEX);
284 return globalIndex;
285 }
286
setGlobalIndex(uint32_t index)287 void GlobalSymbol::setGlobalIndex(uint32_t index) {
288 LLVM_DEBUG(dbgs() << "setGlobalIndex " << name << " -> " << index << "\n");
289 assert(globalIndex == INVALID_INDEX);
290 globalIndex = index;
291 }
292
hasGlobalIndex() const293 bool GlobalSymbol::hasGlobalIndex() const {
294 if (auto *f = dyn_cast<DefinedGlobal>(this))
295 return f->global->hasGlobalIndex();
296 return globalIndex != INVALID_INDEX;
297 }
298
DefinedGlobal(StringRef name,uint32_t flags,InputFile * file,InputGlobal * global)299 DefinedGlobal::DefinedGlobal(StringRef name, uint32_t flags, InputFile *file,
300 InputGlobal *global)
301 : GlobalSymbol(name, DefinedGlobalKind, flags, file,
302 global ? &global->getType() : nullptr),
303 global(global) {}
304
getEventIndex() const305 uint32_t EventSymbol::getEventIndex() const {
306 if (auto *f = dyn_cast<DefinedEvent>(this))
307 return f->event->getEventIndex();
308 assert(eventIndex != INVALID_INDEX);
309 return eventIndex;
310 }
311
setEventIndex(uint32_t index)312 void EventSymbol::setEventIndex(uint32_t index) {
313 LLVM_DEBUG(dbgs() << "setEventIndex " << name << " -> " << index << "\n");
314 assert(eventIndex == INVALID_INDEX);
315 eventIndex = index;
316 }
317
hasEventIndex() const318 bool EventSymbol::hasEventIndex() const {
319 if (auto *f = dyn_cast<DefinedEvent>(this))
320 return f->event->hasEventIndex();
321 return eventIndex != INVALID_INDEX;
322 }
323
DefinedEvent(StringRef name,uint32_t flags,InputFile * file,InputEvent * event)324 DefinedEvent::DefinedEvent(StringRef name, uint32_t flags, InputFile *file,
325 InputEvent *event)
326 : EventSymbol(name, DefinedEventKind, flags, file,
327 event ? &event->getType() : nullptr,
328 event ? &event->signature : nullptr),
329 event(event) {}
330
getOutputSectionSymbol() const331 const OutputSectionSymbol *SectionSymbol::getOutputSectionSymbol() const {
332 assert(section->outputSec && section->outputSec->sectionSym);
333 return section->outputSec->sectionSym;
334 }
335
fetch()336 void LazySymbol::fetch() { cast<ArchiveFile>(file)->addMember(&archiveSymbol); }
337
getMemberBuffer()338 MemoryBufferRef LazySymbol::getMemberBuffer() {
339 Archive::Child c =
340 CHECK(archiveSymbol.getMember(),
341 "could not get the member for symbol " + toString(*this));
342
343 return CHECK(c.getMemoryBufferRef(),
344 "could not get the buffer for the member defining symbol " +
345 toString(*this));
346 }
347
printTraceSymbolUndefined(StringRef name,const InputFile * file)348 void printTraceSymbolUndefined(StringRef name, const InputFile* file) {
349 message(toString(file) + ": reference to " + name);
350 }
351
352 // Print out a log message for --trace-symbol.
printTraceSymbol(Symbol * sym)353 void printTraceSymbol(Symbol *sym) {
354 // Undefined symbols are traced via printTraceSymbolUndefined
355 if (sym->isUndefined())
356 return;
357
358 std::string s;
359 if (sym->isLazy())
360 s = ": lazy definition of ";
361 else
362 s = ": definition of ";
363
364 message(toString(sym->getFile()) + s + sym->getName());
365 }
366
367 const char *defaultModule = "env";
368 const char *functionTableName = "__indirect_function_table";
369
370 } // namespace wasm
371 } // namespace lld
372