1 //===- Symbols.cpp --------------------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
11 #include "InputChunks.h"
12 #include "InputElement.h"
13 #include "InputFiles.h"
14 #include "OutputSections.h"
15 #include "OutputSegment.h"
16 #include "lld/Common/ErrorHandler.h"
17 #include "lld/Common/Memory.h"
18 #include "lld/Common/Strings.h"
20 #define DEBUG_TYPE "lld"
23 using namespace llvm::object
;
24 using namespace llvm::wasm
;
27 std::string
toString(const wasm::Symbol
&sym
) {
28 return maybeDemangleSymbol(sym
.getName());
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")
36 if (wasm::config
->demangle
)
37 return demangleItanium(name
);
38 return std::string(name
);
41 std::string
toString(wasm::Symbol::Kind kind
) {
43 case wasm::Symbol::DefinedFunctionKind
:
44 return "DefinedFunction";
45 case wasm::Symbol::DefinedDataKind
:
47 case wasm::Symbol::DefinedGlobalKind
:
48 return "DefinedGlobal";
49 case wasm::Symbol::DefinedTableKind
:
50 return "DefinedTable";
51 case wasm::Symbol::DefinedTagKind
:
53 case wasm::Symbol::UndefinedFunctionKind
:
54 return "UndefinedFunction";
55 case wasm::Symbol::UndefinedDataKind
:
56 return "UndefinedData";
57 case wasm::Symbol::UndefinedGlobalKind
:
58 return "UndefinedGlobal";
59 case wasm::Symbol::UndefinedTableKind
:
60 return "UndefinedTable";
61 case wasm::Symbol::LazyKind
:
63 case wasm::Symbol::SectionKind
:
65 case wasm::Symbol::OutputSectionKind
:
66 return "OutputSectionKind";
68 llvm_unreachable("invalid symbol kind");
72 DefinedFunction
*WasmSym::callCtors
;
73 DefinedFunction
*WasmSym::callDtors
;
74 DefinedFunction
*WasmSym::initMemory
;
75 DefinedFunction
*WasmSym::applyDataRelocs
;
76 DefinedFunction
*WasmSym::applyGlobalRelocs
;
77 DefinedFunction
*WasmSym::initTLS
;
78 DefinedFunction
*WasmSym::startFunction
;
79 DefinedData
*WasmSym::dsoHandle
;
80 DefinedData
*WasmSym::dataEnd
;
81 DefinedData
*WasmSym::globalBase
;
82 DefinedData
*WasmSym::heapBase
;
83 DefinedData
*WasmSym::initMemoryFlag
;
84 GlobalSymbol
*WasmSym::stackPointer
;
85 GlobalSymbol
*WasmSym::tlsBase
;
86 GlobalSymbol
*WasmSym::tlsSize
;
87 GlobalSymbol
*WasmSym::tlsAlign
;
88 UndefinedGlobal
*WasmSym::tableBase
;
89 DefinedData
*WasmSym::definedTableBase
;
90 UndefinedGlobal
*WasmSym::tableBase32
;
91 DefinedData
*WasmSym::definedTableBase32
;
92 UndefinedGlobal
*WasmSym::memoryBase
;
93 DefinedData
*WasmSym::definedMemoryBase
;
94 TableSymbol
*WasmSym::indirectFunctionTable
;
96 WasmSymbolType
Symbol::getWasmType() const {
97 if (isa
<FunctionSymbol
>(this))
98 return WASM_SYMBOL_TYPE_FUNCTION
;
99 if (isa
<DataSymbol
>(this))
100 return WASM_SYMBOL_TYPE_DATA
;
101 if (isa
<GlobalSymbol
>(this))
102 return WASM_SYMBOL_TYPE_GLOBAL
;
103 if (isa
<TagSymbol
>(this))
104 return WASM_SYMBOL_TYPE_TAG
;
105 if (isa
<TableSymbol
>(this))
106 return WASM_SYMBOL_TYPE_TABLE
;
107 if (isa
<SectionSymbol
>(this) || isa
<OutputSectionSymbol
>(this))
108 return WASM_SYMBOL_TYPE_SECTION
;
109 llvm_unreachable("invalid symbol kind");
112 const WasmSignature
*Symbol::getSignature() const {
113 if (auto* f
= dyn_cast
<FunctionSymbol
>(this))
115 if (auto *l
= dyn_cast
<LazySymbol
>(this))
120 InputChunk
*Symbol::getChunk() const {
121 if (auto *f
= dyn_cast
<DefinedFunction
>(this))
123 if (auto *f
= dyn_cast
<UndefinedFunction
>(this))
125 return f
->stubFunction
->function
;
126 if (auto *d
= dyn_cast
<DefinedData
>(this))
131 bool Symbol::isDiscarded() const {
132 if (InputChunk
*c
= getChunk())
137 bool Symbol::isLive() const {
138 if (auto *g
= dyn_cast
<DefinedGlobal
>(this))
139 return g
->global
->live
;
140 if (auto *t
= dyn_cast
<DefinedTag
>(this))
142 if (auto *t
= dyn_cast
<DefinedTable
>(this))
143 return t
->table
->live
;
144 if (InputChunk
*c
= getChunk())
149 void Symbol::markLive() {
150 assert(!isDiscarded());
152 if (file
!= NULL
&& isDefined())
154 if (auto *g
= dyn_cast
<DefinedGlobal
>(this))
155 g
->global
->live
= true;
156 if (auto *t
= dyn_cast
<DefinedTag
>(this))
158 if (auto *t
= dyn_cast
<DefinedTable
>(this))
159 t
->table
->live
= true;
160 if (InputChunk
*c
= getChunk()) {
161 // Usually, a whole chunk is marked as live or dead, but in mergeable
162 // (splittable) sections, each piece of data has independent liveness bit.
163 // So we explicitly tell it which offset is in use.
164 if (auto *d
= dyn_cast
<DefinedData
>(this)) {
165 if (auto *ms
= dyn_cast
<MergeInputChunk
>(c
)) {
166 ms
->getSectionPiece(d
->value
)->live
= true;
173 uint32_t Symbol::getOutputSymbolIndex() const {
174 assert(outputSymbolIndex
!= INVALID_INDEX
);
175 return outputSymbolIndex
;
178 void Symbol::setOutputSymbolIndex(uint32_t index
) {
179 LLVM_DEBUG(dbgs() << "setOutputSymbolIndex " << name
<< " -> " << index
181 assert(outputSymbolIndex
== INVALID_INDEX
);
182 outputSymbolIndex
= index
;
185 void Symbol::setGOTIndex(uint32_t index
) {
186 LLVM_DEBUG(dbgs() << "setGOTIndex " << name
<< " -> " << index
<< "\n");
187 assert(gotIndex
== INVALID_INDEX
);
189 // Any symbol that is assigned a GOT entry must be exported otherwise the
190 // dynamic linker won't be able create the entry that contains it.
196 bool Symbol::isWeak() const {
197 return (flags
& WASM_SYMBOL_BINDING_MASK
) == WASM_SYMBOL_BINDING_WEAK
;
200 bool Symbol::isLocal() const {
201 return (flags
& WASM_SYMBOL_BINDING_MASK
) == WASM_SYMBOL_BINDING_LOCAL
;
204 bool Symbol::isHidden() const {
205 return (flags
& WASM_SYMBOL_VISIBILITY_MASK
) == WASM_SYMBOL_VISIBILITY_HIDDEN
;
208 void Symbol::setHidden(bool isHidden
) {
209 LLVM_DEBUG(dbgs() << "setHidden: " << name
<< " -> " << isHidden
<< "\n");
210 flags
&= ~WASM_SYMBOL_VISIBILITY_MASK
;
212 flags
|= WASM_SYMBOL_VISIBILITY_HIDDEN
;
214 flags
|= WASM_SYMBOL_VISIBILITY_DEFAULT
;
217 bool Symbol::isExported() const {
218 // Shared libraries must export all weakly defined symbols
219 // in case they contain the version that will be chosed by
220 // the dynamic linker.
221 if (config
->shared
&& isLive() && isDefined() && isWeak())
224 if (!isDefined() || isLocal())
227 if (config
->exportAll
|| (config
->exportDynamic
&& !isHidden()))
230 return isExportedExplicit();
233 bool Symbol::isExportedExplicit() const {
234 return forceExport
|| flags
& WASM_SYMBOL_EXPORTED
;
237 bool Symbol::isNoStrip() const {
238 return flags
& WASM_SYMBOL_NO_STRIP
;
241 uint32_t FunctionSymbol::getFunctionIndex() const {
242 if (const auto *u
= dyn_cast
<UndefinedFunction
>(this))
244 return u
->stubFunction
->getFunctionIndex();
245 if (functionIndex
!= INVALID_INDEX
)
246 return functionIndex
;
247 auto *f
= cast
<DefinedFunction
>(this);
248 return f
->function
->getFunctionIndex();
251 void FunctionSymbol::setFunctionIndex(uint32_t index
) {
252 LLVM_DEBUG(dbgs() << "setFunctionIndex " << name
<< " -> " << index
<< "\n");
253 assert(functionIndex
== INVALID_INDEX
);
254 functionIndex
= index
;
257 bool FunctionSymbol::hasFunctionIndex() const {
258 if (auto *f
= dyn_cast
<DefinedFunction
>(this))
259 return f
->function
->hasFunctionIndex();
260 return functionIndex
!= INVALID_INDEX
;
263 uint32_t FunctionSymbol::getTableIndex() const {
264 if (auto *f
= dyn_cast
<DefinedFunction
>(this))
265 return f
->function
->getTableIndex();
266 assert(tableIndex
!= INVALID_INDEX
);
270 bool FunctionSymbol::hasTableIndex() const {
271 if (auto *f
= dyn_cast
<DefinedFunction
>(this))
272 return f
->function
->hasTableIndex();
273 return tableIndex
!= INVALID_INDEX
;
276 void FunctionSymbol::setTableIndex(uint32_t index
) {
277 // For imports, we set the table index here on the Symbol; for defined
278 // functions we set the index on the InputFunction so that we don't export
279 // the same thing twice (keeps the table size down).
280 if (auto *f
= dyn_cast
<DefinedFunction
>(this)) {
281 f
->function
->setTableIndex(index
);
284 LLVM_DEBUG(dbgs() << "setTableIndex " << name
<< " -> " << index
<< "\n");
285 assert(tableIndex
== INVALID_INDEX
);
289 DefinedFunction::DefinedFunction(StringRef name
, uint32_t flags
, InputFile
*f
,
290 InputFunction
*function
)
291 : FunctionSymbol(name
, DefinedFunctionKind
, flags
, f
,
292 function
? &function
->signature
: nullptr),
293 function(function
) {}
295 uint32_t DefinedFunction::getExportedFunctionIndex() const {
296 return function
->getFunctionIndex();
299 uint64_t DefinedData::getVA() const {
300 LLVM_DEBUG(dbgs() << "getVA: " << getName() << "\n");
302 return segment
->getVA(value
);
306 void DefinedData::setVA(uint64_t value_
) {
307 LLVM_DEBUG(dbgs() << "setVA " << name
<< " -> " << value_
<< "\n");
312 uint64_t DefinedData::getOutputSegmentOffset() const {
313 LLVM_DEBUG(dbgs() << "getOutputSegmentOffset: " << getName() << "\n");
314 return segment
->getChunkOffset(value
);
317 uint64_t DefinedData::getOutputSegmentIndex() const {
318 LLVM_DEBUG(dbgs() << "getOutputSegmentIndex: " << getName() << "\n");
319 return segment
->outputSeg
->index
;
322 uint32_t GlobalSymbol::getGlobalIndex() const {
323 if (auto *f
= dyn_cast
<DefinedGlobal
>(this))
324 return f
->global
->getAssignedIndex();
325 assert(globalIndex
!= INVALID_INDEX
);
329 void GlobalSymbol::setGlobalIndex(uint32_t index
) {
330 LLVM_DEBUG(dbgs() << "setGlobalIndex " << name
<< " -> " << index
<< "\n");
331 assert(globalIndex
== INVALID_INDEX
);
335 bool GlobalSymbol::hasGlobalIndex() const {
336 if (auto *f
= dyn_cast
<DefinedGlobal
>(this))
337 return f
->global
->hasAssignedIndex();
338 return globalIndex
!= INVALID_INDEX
;
341 DefinedGlobal::DefinedGlobal(StringRef name
, uint32_t flags
, InputFile
*file
,
343 : GlobalSymbol(name
, DefinedGlobalKind
, flags
, file
,
344 global
? &global
->getType() : nullptr),
347 uint32_t TagSymbol::getTagIndex() const {
348 if (auto *f
= dyn_cast
<DefinedTag
>(this))
349 return f
->tag
->getAssignedIndex();
350 assert(tagIndex
!= INVALID_INDEX
);
354 void TagSymbol::setTagIndex(uint32_t index
) {
355 LLVM_DEBUG(dbgs() << "setTagIndex " << name
<< " -> " << index
<< "\n");
356 assert(tagIndex
== INVALID_INDEX
);
360 bool TagSymbol::hasTagIndex() const {
361 if (auto *f
= dyn_cast
<DefinedTag
>(this))
362 return f
->tag
->hasAssignedIndex();
363 return tagIndex
!= INVALID_INDEX
;
366 DefinedTag::DefinedTag(StringRef name
, uint32_t flags
, InputFile
*file
,
368 : TagSymbol(name
, DefinedTagKind
, flags
, file
,
369 tag
? &tag
->getType() : nullptr,
370 tag
? &tag
->signature
: nullptr),
373 void TableSymbol::setLimits(const WasmLimits
&limits
) {
374 if (auto *t
= dyn_cast
<DefinedTable
>(this))
375 t
->table
->setLimits(limits
);
376 auto *newType
= make
<WasmTableType
>(*tableType
);
377 newType
->Limits
= limits
;
381 uint32_t TableSymbol::getTableNumber() const {
382 if (const auto *t
= dyn_cast
<DefinedTable
>(this))
383 return t
->table
->getAssignedIndex();
384 assert(tableNumber
!= INVALID_INDEX
);
388 void TableSymbol::setTableNumber(uint32_t number
) {
389 if (const auto *t
= dyn_cast
<DefinedTable
>(this))
390 return t
->table
->assignIndex(number
);
391 LLVM_DEBUG(dbgs() << "setTableNumber " << name
<< " -> " << number
<< "\n");
392 assert(tableNumber
== INVALID_INDEX
);
393 tableNumber
= number
;
396 bool TableSymbol::hasTableNumber() const {
397 if (const auto *t
= dyn_cast
<DefinedTable
>(this))
398 return t
->table
->hasAssignedIndex();
399 return tableNumber
!= INVALID_INDEX
;
402 DefinedTable::DefinedTable(StringRef name
, uint32_t flags
, InputFile
*file
,
404 : TableSymbol(name
, DefinedTableKind
, flags
, file
,
405 table
? &table
->getType() : nullptr),
408 const OutputSectionSymbol
*SectionSymbol::getOutputSectionSymbol() const {
409 assert(section
->outputSec
&& section
->outputSec
->sectionSym
);
410 return section
->outputSec
->sectionSym
;
413 void LazySymbol::fetch() { cast
<ArchiveFile
>(file
)->addMember(&archiveSymbol
); }
415 void LazySymbol::setWeak() {
416 flags
|= (flags
& ~WASM_SYMBOL_BINDING_MASK
) | WASM_SYMBOL_BINDING_WEAK
;
419 MemoryBufferRef
LazySymbol::getMemberBuffer() {
421 CHECK(archiveSymbol
.getMember(),
422 "could not get the member for symbol " + toString(*this));
424 return CHECK(c
.getMemoryBufferRef(),
425 "could not get the buffer for the member defining symbol " +
429 void printTraceSymbolUndefined(StringRef name
, const InputFile
* file
) {
430 message(toString(file
) + ": reference to " + name
);
433 // Print out a log message for --trace-symbol.
434 void printTraceSymbol(Symbol
*sym
) {
435 // Undefined symbols are traced via printTraceSymbolUndefined
436 if (sym
->isUndefined())
441 s
= ": lazy definition of ";
443 s
= ": definition of ";
445 message(toString(sym
->getFile()) + s
+ sym
->getName());
448 const char *defaultModule
= "env";
449 const char *functionTableName
= "__indirect_function_table";