• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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   // WebAssembly requires caller and callee signatures to match, so we mangle
33   // `main` in the case where we need to pass it arguments.
34   if (name == "__main_argc_argv")
35     return "main";
36   if (wasm::config->demangle)
37     return demangleItanium(name);
38   return std::string(name);
39 }
40 
toString(wasm::Symbol::Kind kind)41 std::string toString(wasm::Symbol::Kind kind) {
42   switch (kind) {
43   case wasm::Symbol::DefinedFunctionKind:
44     return "DefinedFunction";
45   case wasm::Symbol::DefinedDataKind:
46     return "DefinedData";
47   case wasm::Symbol::DefinedGlobalKind:
48     return "DefinedGlobal";
49   case wasm::Symbol::DefinedEventKind:
50     return "DefinedEvent";
51   case wasm::Symbol::UndefinedFunctionKind:
52     return "UndefinedFunction";
53   case wasm::Symbol::UndefinedDataKind:
54     return "UndefinedData";
55   case wasm::Symbol::UndefinedGlobalKind:
56     return "UndefinedGlobal";
57   case wasm::Symbol::LazyKind:
58     return "LazyKind";
59   case wasm::Symbol::SectionKind:
60     return "SectionKind";
61   case wasm::Symbol::OutputSectionKind:
62     return "OutputSectionKind";
63   }
64   llvm_unreachable("invalid symbol kind");
65 }
66 
67 namespace wasm {
68 DefinedFunction *WasmSym::callCtors;
69 DefinedFunction *WasmSym::callDtors;
70 DefinedFunction *WasmSym::initMemory;
71 DefinedFunction *WasmSym::applyRelocs;
72 DefinedFunction *WasmSym::initTLS;
73 DefinedData *WasmSym::dsoHandle;
74 DefinedData *WasmSym::dataEnd;
75 DefinedData *WasmSym::globalBase;
76 DefinedData *WasmSym::heapBase;
77 DefinedData *WasmSym::initMemoryFlag;
78 GlobalSymbol *WasmSym::stackPointer;
79 GlobalSymbol *WasmSym::tlsBase;
80 GlobalSymbol *WasmSym::tlsSize;
81 GlobalSymbol *WasmSym::tlsAlign;
82 UndefinedGlobal *WasmSym::tableBase;
83 DefinedData *WasmSym::definedTableBase;
84 UndefinedGlobal *WasmSym::memoryBase;
85 DefinedData *WasmSym::definedMemoryBase;
86 
getWasmType() const87 WasmSymbolType Symbol::getWasmType() const {
88   if (isa<FunctionSymbol>(this))
89     return WASM_SYMBOL_TYPE_FUNCTION;
90   if (isa<DataSymbol>(this))
91     return WASM_SYMBOL_TYPE_DATA;
92   if (isa<GlobalSymbol>(this))
93     return WASM_SYMBOL_TYPE_GLOBAL;
94   if (isa<EventSymbol>(this))
95     return WASM_SYMBOL_TYPE_EVENT;
96   if (isa<SectionSymbol>(this) || isa<OutputSectionSymbol>(this))
97     return WASM_SYMBOL_TYPE_SECTION;
98   llvm_unreachable("invalid symbol kind");
99 }
100 
getSignature() const101 const WasmSignature *Symbol::getSignature() const {
102   if (auto* f = dyn_cast<FunctionSymbol>(this))
103     return f->signature;
104   if (auto *l = dyn_cast<LazySymbol>(this))
105     return l->signature;
106   return nullptr;
107 }
108 
getChunk() const109 InputChunk *Symbol::getChunk() const {
110   if (auto *f = dyn_cast<DefinedFunction>(this))
111     return f->function;
112   if (auto *f = dyn_cast<UndefinedFunction>(this))
113     if (f->stubFunction)
114       return f->stubFunction->function;
115   if (auto *d = dyn_cast<DefinedData>(this))
116     return d->segment;
117   return nullptr;
118 }
119 
isDiscarded() const120 bool Symbol::isDiscarded() const {
121   if (InputChunk *c = getChunk())
122     return c->discarded;
123   return false;
124 }
125 
isLive() const126 bool Symbol::isLive() const {
127   if (auto *g = dyn_cast<DefinedGlobal>(this))
128     return g->global->live;
129   if (auto *e = dyn_cast<DefinedEvent>(this))
130     return e->event->live;
131   if (InputChunk *c = getChunk())
132     return c->live;
133   return referenced;
134 }
135 
markLive()136 void Symbol::markLive() {
137   assert(!isDiscarded());
138   if (file != NULL)
139     file->markLive();
140   if (auto *g = dyn_cast<DefinedGlobal>(this))
141     g->global->live = true;
142   if (auto *e = dyn_cast<DefinedEvent>(this))
143     e->event->live = true;
144   if (InputChunk *c = getChunk())
145     c->live = true;
146   referenced = true;
147 }
148 
getOutputSymbolIndex() const149 uint32_t Symbol::getOutputSymbolIndex() const {
150   assert(outputSymbolIndex != INVALID_INDEX);
151   return outputSymbolIndex;
152 }
153 
setOutputSymbolIndex(uint32_t index)154 void Symbol::setOutputSymbolIndex(uint32_t index) {
155   LLVM_DEBUG(dbgs() << "setOutputSymbolIndex " << name << " -> " << index
156                     << "\n");
157   assert(outputSymbolIndex == INVALID_INDEX);
158   outputSymbolIndex = index;
159 }
160 
setGOTIndex(uint32_t index)161 void Symbol::setGOTIndex(uint32_t index) {
162   LLVM_DEBUG(dbgs() << "setGOTIndex " << name << " -> " << index << "\n");
163   assert(gotIndex == INVALID_INDEX);
164   if (config->isPic) {
165     // Any symbol that is assigned a GOT entry must be exported otherwise the
166     // dynamic linker won't be able create the entry that contains it.
167     forceExport = true;
168   }
169   gotIndex = index;
170 }
171 
isWeak() const172 bool Symbol::isWeak() const {
173   return (flags & WASM_SYMBOL_BINDING_MASK) == WASM_SYMBOL_BINDING_WEAK;
174 }
175 
isLocal() const176 bool Symbol::isLocal() const {
177   return (flags & WASM_SYMBOL_BINDING_MASK) == WASM_SYMBOL_BINDING_LOCAL;
178 }
179 
isHidden() const180 bool Symbol::isHidden() const {
181   return (flags & WASM_SYMBOL_VISIBILITY_MASK) == WASM_SYMBOL_VISIBILITY_HIDDEN;
182 }
183 
setHidden(bool isHidden)184 void Symbol::setHidden(bool isHidden) {
185   LLVM_DEBUG(dbgs() << "setHidden: " << name << " -> " << isHidden << "\n");
186   flags &= ~WASM_SYMBOL_VISIBILITY_MASK;
187   if (isHidden)
188     flags |= WASM_SYMBOL_VISIBILITY_HIDDEN;
189   else
190     flags |= WASM_SYMBOL_VISIBILITY_DEFAULT;
191 }
192 
isExported() const193 bool Symbol::isExported() const {
194   if (!isDefined() || isLocal())
195     return false;
196 
197   if (forceExport || config->exportAll)
198     return true;
199 
200   if (config->exportDynamic && !isHidden())
201     return true;
202 
203   return flags & WASM_SYMBOL_EXPORTED;
204 }
205 
isNoStrip() const206 bool Symbol::isNoStrip() const {
207   return flags & WASM_SYMBOL_NO_STRIP;
208 }
209 
getFunctionIndex() const210 uint32_t FunctionSymbol::getFunctionIndex() const {
211   if (auto *f = dyn_cast<DefinedFunction>(this))
212     return f->function->getFunctionIndex();
213   if (const auto *u = dyn_cast<UndefinedFunction>(this)) {
214     if (u->stubFunction) {
215       return u->stubFunction->getFunctionIndex();
216     }
217   }
218   assert(functionIndex != INVALID_INDEX);
219   return functionIndex;
220 }
221 
setFunctionIndex(uint32_t index)222 void FunctionSymbol::setFunctionIndex(uint32_t index) {
223   LLVM_DEBUG(dbgs() << "setFunctionIndex " << name << " -> " << index << "\n");
224   assert(functionIndex == INVALID_INDEX);
225   functionIndex = index;
226 }
227 
hasFunctionIndex() const228 bool FunctionSymbol::hasFunctionIndex() const {
229   if (auto *f = dyn_cast<DefinedFunction>(this))
230     return f->function->hasFunctionIndex();
231   return functionIndex != INVALID_INDEX;
232 }
233 
getTableIndex() const234 uint32_t FunctionSymbol::getTableIndex() const {
235   if (auto *f = dyn_cast<DefinedFunction>(this))
236     return f->function->getTableIndex();
237   assert(tableIndex != INVALID_INDEX);
238   return tableIndex;
239 }
240 
hasTableIndex() const241 bool FunctionSymbol::hasTableIndex() const {
242   if (auto *f = dyn_cast<DefinedFunction>(this))
243     return f->function->hasTableIndex();
244   return tableIndex != INVALID_INDEX;
245 }
246 
setTableIndex(uint32_t index)247 void FunctionSymbol::setTableIndex(uint32_t index) {
248   // For imports, we set the table index here on the Symbol; for defined
249   // functions we set the index on the InputFunction so that we don't export
250   // the same thing twice (keeps the table size down).
251   if (auto *f = dyn_cast<DefinedFunction>(this)) {
252     f->function->setTableIndex(index);
253     return;
254   }
255   LLVM_DEBUG(dbgs() << "setTableIndex " << name << " -> " << index << "\n");
256   assert(tableIndex == INVALID_INDEX);
257   tableIndex = index;
258 }
259 
DefinedFunction(StringRef name,uint32_t flags,InputFile * f,InputFunction * function)260 DefinedFunction::DefinedFunction(StringRef name, uint32_t flags, InputFile *f,
261                                  InputFunction *function)
262     : FunctionSymbol(name, DefinedFunctionKind, flags, f,
263                      function ? &function->signature : nullptr),
264       function(function) {}
265 
getVirtualAddress() const266 uint64_t DefinedData::getVirtualAddress() const {
267   LLVM_DEBUG(dbgs() << "getVirtualAddress: " << getName() << "\n");
268   if (segment)
269     return segment->outputSeg->startVA + segment->outputSegmentOffset + offset;
270   return offset;
271 }
272 
setVirtualAddress(uint64_t value)273 void DefinedData::setVirtualAddress(uint64_t value) {
274   LLVM_DEBUG(dbgs() << "setVirtualAddress " << name << " -> " << value << "\n");
275   assert(!segment);
276   offset = value;
277 }
278 
getOutputSegmentOffset() const279 uint64_t DefinedData::getOutputSegmentOffset() const {
280   LLVM_DEBUG(dbgs() << "getOutputSegmentOffset: " << getName() << "\n");
281   return segment->outputSegmentOffset + offset;
282 }
283 
getOutputSegmentIndex() const284 uint64_t DefinedData::getOutputSegmentIndex() const {
285   LLVM_DEBUG(dbgs() << "getOutputSegmentIndex: " << getName() << "\n");
286   return segment->outputSeg->index;
287 }
288 
getGlobalIndex() const289 uint32_t GlobalSymbol::getGlobalIndex() const {
290   if (auto *f = dyn_cast<DefinedGlobal>(this))
291     return f->global->getGlobalIndex();
292   assert(globalIndex != INVALID_INDEX);
293   return globalIndex;
294 }
295 
setGlobalIndex(uint32_t index)296 void GlobalSymbol::setGlobalIndex(uint32_t index) {
297   LLVM_DEBUG(dbgs() << "setGlobalIndex " << name << " -> " << index << "\n");
298   assert(globalIndex == INVALID_INDEX);
299   globalIndex = index;
300 }
301 
hasGlobalIndex() const302 bool GlobalSymbol::hasGlobalIndex() const {
303   if (auto *f = dyn_cast<DefinedGlobal>(this))
304     return f->global->hasGlobalIndex();
305   return globalIndex != INVALID_INDEX;
306 }
307 
DefinedGlobal(StringRef name,uint32_t flags,InputFile * file,InputGlobal * global)308 DefinedGlobal::DefinedGlobal(StringRef name, uint32_t flags, InputFile *file,
309                              InputGlobal *global)
310     : GlobalSymbol(name, DefinedGlobalKind, flags, file,
311                    global ? &global->getType() : nullptr),
312       global(global) {}
313 
getEventIndex() const314 uint32_t EventSymbol::getEventIndex() const {
315   if (auto *f = dyn_cast<DefinedEvent>(this))
316     return f->event->getEventIndex();
317   assert(eventIndex != INVALID_INDEX);
318   return eventIndex;
319 }
320 
setEventIndex(uint32_t index)321 void EventSymbol::setEventIndex(uint32_t index) {
322   LLVM_DEBUG(dbgs() << "setEventIndex " << name << " -> " << index << "\n");
323   assert(eventIndex == INVALID_INDEX);
324   eventIndex = index;
325 }
326 
hasEventIndex() const327 bool EventSymbol::hasEventIndex() const {
328   if (auto *f = dyn_cast<DefinedEvent>(this))
329     return f->event->hasEventIndex();
330   return eventIndex != INVALID_INDEX;
331 }
332 
DefinedEvent(StringRef name,uint32_t flags,InputFile * file,InputEvent * event)333 DefinedEvent::DefinedEvent(StringRef name, uint32_t flags, InputFile *file,
334                            InputEvent *event)
335     : EventSymbol(name, DefinedEventKind, flags, file,
336                   event ? &event->getType() : nullptr,
337                   event ? &event->signature : nullptr),
338       event(event) {}
339 
getOutputSectionSymbol() const340 const OutputSectionSymbol *SectionSymbol::getOutputSectionSymbol() const {
341   assert(section->outputSec && section->outputSec->sectionSym);
342   return section->outputSec->sectionSym;
343 }
344 
fetch()345 void LazySymbol::fetch() { cast<ArchiveFile>(file)->addMember(&archiveSymbol); }
346 
setWeak()347 void LazySymbol::setWeak() {
348   flags |= (flags & ~WASM_SYMBOL_BINDING_MASK) | WASM_SYMBOL_BINDING_WEAK;
349 }
350 
getMemberBuffer()351 MemoryBufferRef LazySymbol::getMemberBuffer() {
352   Archive::Child c =
353       CHECK(archiveSymbol.getMember(),
354             "could not get the member for symbol " + toString(*this));
355 
356   return CHECK(c.getMemoryBufferRef(),
357                "could not get the buffer for the member defining symbol " +
358                    toString(*this));
359 }
360 
printTraceSymbolUndefined(StringRef name,const InputFile * file)361 void printTraceSymbolUndefined(StringRef name, const InputFile* file) {
362   message(toString(file) + ": reference to " + name);
363 }
364 
365 // Print out a log message for --trace-symbol.
printTraceSymbol(Symbol * sym)366 void printTraceSymbol(Symbol *sym) {
367   // Undefined symbols are traced via printTraceSymbolUndefined
368   if (sym->isUndefined())
369     return;
370 
371   std::string s;
372   if (sym->isLazy())
373     s = ": lazy definition of ";
374   else
375     s = ": definition of ";
376 
377   message(toString(sym->getFile()) + s + sym->getName());
378 }
379 
380 const char *defaultModule = "env";
381 const char *functionTableName = "__indirect_function_table";
382 
383 } // namespace wasm
384 } // namespace lld
385