1 //===- SyntheticSections.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 //===----------------------------------------------------------------------===//
9 // This file contains linker-synthesized sections.
11 //===----------------------------------------------------------------------===//
13 #include "SyntheticSections.h"
15 #include "InputChunks.h"
16 #include "InputElement.h"
17 #include "OutputSegment.h"
18 #include "SymbolTable.h"
19 #include "llvm/Support/Path.h"
23 using namespace llvm::wasm
;
31 // Some synthetic sections (e.g. "name" and "linking") have subsections.
32 // Just like the synthetic sections themselves these need to be created before
33 // they can be written out (since they are preceded by their length). This
34 // class is used to create subsections and then write them into the stream
35 // of the parent section.
38 explicit SubSection(uint32_t type
) : type(type
) {}
40 void writeTo(raw_ostream
&to
) {
41 writeUleb128(to
, type
, "subsection type");
42 writeUleb128(to
, body
.size(), "subsection size");
43 to
.write(body
.data(), body
.size());
51 raw_string_ostream os
{body
};
56 bool DylinkSection::isNeeded() const {
58 ctx
.arg
.unresolvedSymbols
== UnresolvedPolicy::ImportDynamic
||
59 !ctx
.sharedFiles
.empty();
62 void DylinkSection::writeBody() {
63 raw_ostream
&os
= bodyOutputStream
;
66 SubSection
sub(WASM_DYLINK_MEM_INFO
);
67 writeUleb128(sub
.os
, memSize
, "MemSize");
68 writeUleb128(sub
.os
, memAlign
, "MemAlign");
69 writeUleb128(sub
.os
, out
.elemSec
->numEntries(), "TableSize");
70 writeUleb128(sub
.os
, 0, "TableAlign");
74 if (ctx
.sharedFiles
.size()) {
75 SubSection
sub(WASM_DYLINK_NEEDED
);
76 writeUleb128(sub
.os
, ctx
.sharedFiles
.size(), "Needed");
77 for (auto *so
: ctx
.sharedFiles
)
78 writeStr(sub
.os
, llvm::sys::path::filename(so
->getName()), "so name");
82 // Under certain circumstances we need to include extra information about our
83 // exports and/or imports to the dynamic linker.
84 // For exports we need to notify the linker when an export is TLS since the
85 // exported value is relative to __tls_base rather than __memory_base.
86 // For imports we need to notify the dynamic linker when an import is weak
87 // so that knows not to report an error for such symbols.
88 std::vector
<const Symbol
*> importInfo
;
89 std::vector
<const Symbol
*> exportInfo
;
90 for (const Symbol
*sym
: symtab
->symbols()) {
92 if (sym
->isExported() && sym
->isTLS() && isa
<DefinedData
>(sym
)) {
93 exportInfo
.push_back(sym
);
95 if (sym
->isUndefWeak()) {
96 importInfo
.push_back(sym
);
101 if (!exportInfo
.empty()) {
102 SubSection
sub(WASM_DYLINK_EXPORT_INFO
);
103 writeUleb128(sub
.os
, exportInfo
.size(), "num exports");
105 for (const Symbol
*sym
: exportInfo
) {
106 LLVM_DEBUG(llvm::dbgs() << "export info: " << toString(*sym
) << "\n");
107 StringRef name
= sym
->getName();
108 if (auto *f
= dyn_cast
<DefinedFunction
>(sym
)) {
109 if (std::optional
<StringRef
> exportName
=
110 f
->function
->getExportName()) {
114 writeStr(sub
.os
, name
, "sym name");
115 writeUleb128(sub
.os
, sym
->flags
, "sym flags");
121 if (!importInfo
.empty()) {
122 SubSection
sub(WASM_DYLINK_IMPORT_INFO
);
123 writeUleb128(sub
.os
, importInfo
.size(), "num imports");
125 for (const Symbol
*sym
: importInfo
) {
126 LLVM_DEBUG(llvm::dbgs() << "imports info: " << toString(*sym
) << "\n");
127 StringRef module
= sym
->importModule
.value_or(defaultModule
);
128 StringRef name
= sym
->importName
.value_or(sym
->getName());
129 writeStr(sub
.os
, module
, "import module");
130 writeStr(sub
.os
, name
, "import name");
131 writeUleb128(sub
.os
, sym
->flags
, "sym flags");
138 uint32_t TypeSection::registerType(const WasmSignature
&sig
) {
139 auto pair
= typeIndices
.insert(std::make_pair(sig
, types
.size()));
141 LLVM_DEBUG(llvm::dbgs() << "registerType " << toString(sig
) << "\n");
142 types
.push_back(&sig
);
144 return pair
.first
->second
;
147 uint32_t TypeSection::lookupType(const WasmSignature
&sig
) {
148 auto it
= typeIndices
.find(sig
);
149 if (it
== typeIndices
.end()) {
150 error("type not found: " + toString(sig
));
156 void TypeSection::writeBody() {
157 writeUleb128(bodyOutputStream
, types
.size(), "type count");
158 for (const WasmSignature
*sig
: types
)
159 writeSig(bodyOutputStream
, *sig
);
162 uint32_t ImportSection::getNumImports() const {
164 uint32_t numImports
= importedSymbols
.size() + gotSymbols
.size();
165 if (ctx
.arg
.memoryImport
.has_value())
170 void ImportSection::addGOTEntry(Symbol
*sym
) {
172 if (sym
->hasGOTIndex())
174 LLVM_DEBUG(dbgs() << "addGOTEntry: " << toString(*sym
) << "\n");
175 sym
->setGOTIndex(numImportedGlobals
++);
177 // Any symbol that is assigned an normal GOT entry must be exported
178 // otherwise the dynamic linker won't be able create the entry that contains
180 sym
->forceExport
= true;
182 gotSymbols
.push_back(sym
);
185 void ImportSection::addImport(Symbol
*sym
) {
187 StringRef module
= sym
->importModule
.value_or(defaultModule
);
188 StringRef name
= sym
->importName
.value_or(sym
->getName());
189 if (auto *f
= dyn_cast
<FunctionSymbol
>(sym
)) {
190 ImportKey
<WasmSignature
> key(*(f
->getSignature()), module
, name
);
191 auto entry
= importedFunctions
.try_emplace(key
, numImportedFunctions
);
193 importedSymbols
.emplace_back(sym
);
194 f
->setFunctionIndex(numImportedFunctions
++);
196 f
->setFunctionIndex(entry
.first
->second
);
198 } else if (auto *g
= dyn_cast
<GlobalSymbol
>(sym
)) {
199 ImportKey
<WasmGlobalType
> key(*(g
->getGlobalType()), module
, name
);
200 auto entry
= importedGlobals
.try_emplace(key
, numImportedGlobals
);
202 importedSymbols
.emplace_back(sym
);
203 g
->setGlobalIndex(numImportedGlobals
++);
205 g
->setGlobalIndex(entry
.first
->second
);
207 } else if (auto *t
= dyn_cast
<TagSymbol
>(sym
)) {
208 ImportKey
<WasmSignature
> key(*(t
->getSignature()), module
, name
);
209 auto entry
= importedTags
.try_emplace(key
, numImportedTags
);
211 importedSymbols
.emplace_back(sym
);
212 t
->setTagIndex(numImportedTags
++);
214 t
->setTagIndex(entry
.first
->second
);
217 assert(TableSymbol::classof(sym
));
218 auto *table
= cast
<TableSymbol
>(sym
);
219 ImportKey
<WasmTableType
> key(*(table
->getTableType()), module
, name
);
220 auto entry
= importedTables
.try_emplace(key
, numImportedTables
);
222 importedSymbols
.emplace_back(sym
);
223 table
->setTableNumber(numImportedTables
++);
225 table
->setTableNumber(entry
.first
->second
);
230 void ImportSection::writeBody() {
231 raw_ostream
&os
= bodyOutputStream
;
233 writeUleb128(os
, getNumImports(), "import count");
235 bool is64
= ctx
.arg
.is64
.value_or(false);
237 if (ctx
.arg
.memoryImport
) {
239 import
.Module
= ctx
.arg
.memoryImport
->first
;
240 import
.Field
= ctx
.arg
.memoryImport
->second
;
241 import
.Kind
= WASM_EXTERNAL_MEMORY
;
242 import
.Memory
.Flags
= 0;
243 import
.Memory
.Minimum
= out
.memorySec
->numMemoryPages
;
244 if (out
.memorySec
->maxMemoryPages
!= 0 || ctx
.arg
.sharedMemory
) {
245 import
.Memory
.Flags
|= WASM_LIMITS_FLAG_HAS_MAX
;
246 import
.Memory
.Maximum
= out
.memorySec
->maxMemoryPages
;
248 if (ctx
.arg
.sharedMemory
)
249 import
.Memory
.Flags
|= WASM_LIMITS_FLAG_IS_SHARED
;
251 import
.Memory
.Flags
|= WASM_LIMITS_FLAG_IS_64
;
252 writeImport(os
, import
);
255 for (const Symbol
*sym
: importedSymbols
) {
257 import
.Field
= sym
->importName
.value_or(sym
->getName());
258 import
.Module
= sym
->importModule
.value_or(defaultModule
);
260 if (auto *functionSym
= dyn_cast
<FunctionSymbol
>(sym
)) {
261 import
.Kind
= WASM_EXTERNAL_FUNCTION
;
262 import
.SigIndex
= out
.typeSec
->lookupType(*functionSym
->signature
);
263 } else if (auto *globalSym
= dyn_cast
<GlobalSymbol
>(sym
)) {
264 import
.Kind
= WASM_EXTERNAL_GLOBAL
;
265 import
.Global
= *globalSym
->getGlobalType();
266 } else if (auto *tagSym
= dyn_cast
<TagSymbol
>(sym
)) {
267 import
.Kind
= WASM_EXTERNAL_TAG
;
268 import
.SigIndex
= out
.typeSec
->lookupType(*tagSym
->signature
);
270 auto *tableSym
= cast
<TableSymbol
>(sym
);
271 import
.Kind
= WASM_EXTERNAL_TABLE
;
272 import
.Table
= *tableSym
->getTableType();
274 writeImport(os
, import
);
277 for (const Symbol
*sym
: gotSymbols
) {
279 import
.Kind
= WASM_EXTERNAL_GLOBAL
;
280 auto ptrType
= is64
? WASM_TYPE_I64
: WASM_TYPE_I32
;
281 import
.Global
= {static_cast<uint8_t>(ptrType
), true};
282 if (isa
<DataSymbol
>(sym
))
283 import
.Module
= "GOT.mem";
285 import
.Module
= "GOT.func";
286 import
.Field
= sym
->getName();
287 writeImport(os
, import
);
291 void FunctionSection::writeBody() {
292 raw_ostream
&os
= bodyOutputStream
;
294 writeUleb128(os
, inputFunctions
.size(), "function count");
295 for (const InputFunction
*func
: inputFunctions
)
296 writeUleb128(os
, out
.typeSec
->lookupType(func
->signature
), "sig index");
299 void FunctionSection::addFunction(InputFunction
*func
) {
302 uint32_t functionIndex
=
303 out
.importSec
->getNumImportedFunctions() + inputFunctions
.size();
304 inputFunctions
.emplace_back(func
);
305 func
->setFunctionIndex(functionIndex
);
308 void TableSection::writeBody() {
309 raw_ostream
&os
= bodyOutputStream
;
311 writeUleb128(os
, inputTables
.size(), "table count");
312 for (const InputTable
*table
: inputTables
)
313 writeTableType(os
, table
->getType());
316 void TableSection::addTable(InputTable
*table
) {
319 // Some inputs require that the indirect function table be assigned to table
321 if (ctx
.legacyFunctionTable
&&
322 isa
<DefinedTable
>(WasmSym::indirectFunctionTable
) &&
323 cast
<DefinedTable
>(WasmSym::indirectFunctionTable
)->table
== table
) {
324 if (out
.importSec
->getNumImportedTables()) {
325 // Alack! Some other input imported a table, meaning that we are unable
326 // to assign table number 0 to the indirect function table.
327 for (const auto *culprit
: out
.importSec
->importedSymbols
) {
328 if (isa
<UndefinedTable
>(culprit
)) {
329 error("object file not built with 'reference-types' or "
330 "'call-indirect-overlong' feature conflicts with import of "
332 culprit
->getName() + " by file " +
333 toString(culprit
->getFile()));
337 llvm_unreachable("failed to find conflicting table import");
339 inputTables
.insert(inputTables
.begin(), table
);
342 inputTables
.push_back(table
);
345 void TableSection::assignIndexes() {
346 uint32_t tableNumber
= out
.importSec
->getNumImportedTables();
347 for (InputTable
*t
: inputTables
)
348 t
->assignIndex(tableNumber
++);
351 void MemorySection::writeBody() {
352 raw_ostream
&os
= bodyOutputStream
;
354 bool hasMax
= maxMemoryPages
!= 0 || ctx
.arg
.sharedMemory
;
355 writeUleb128(os
, 1, "memory count");
358 flags
|= WASM_LIMITS_FLAG_HAS_MAX
;
359 if (ctx
.arg
.sharedMemory
)
360 flags
|= WASM_LIMITS_FLAG_IS_SHARED
;
361 if (ctx
.arg
.is64
.value_or(false))
362 flags
|= WASM_LIMITS_FLAG_IS_64
;
363 writeUleb128(os
, flags
, "memory limits flags");
364 writeUleb128(os
, numMemoryPages
, "initial pages");
366 writeUleb128(os
, maxMemoryPages
, "max pages");
369 void TagSection::writeBody() {
370 raw_ostream
&os
= bodyOutputStream
;
372 writeUleb128(os
, inputTags
.size(), "tag count");
373 for (InputTag
*t
: inputTags
) {
374 writeUleb128(os
, 0, "tag attribute"); // Reserved "attribute" field
375 writeUleb128(os
, out
.typeSec
->lookupType(t
->signature
), "sig index");
379 void TagSection::addTag(InputTag
*tag
) {
382 uint32_t tagIndex
= out
.importSec
->getNumImportedTags() + inputTags
.size();
383 LLVM_DEBUG(dbgs() << "addTag: " << tagIndex
<< "\n");
384 tag
->assignIndex(tagIndex
);
385 inputTags
.push_back(tag
);
388 void GlobalSection::assignIndexes() {
389 uint32_t globalIndex
= out
.importSec
->getNumImportedGlobals();
390 for (InputGlobal
*g
: inputGlobals
)
391 g
->assignIndex(globalIndex
++);
392 for (Symbol
*sym
: internalGotSymbols
)
393 sym
->setGOTIndex(globalIndex
++);
397 static void ensureIndirectFunctionTable() {
398 if (!WasmSym::indirectFunctionTable
)
399 WasmSym::indirectFunctionTable
=
400 symtab
->resolveIndirectFunctionTable(/*required =*/true);
403 void GlobalSection::addInternalGOTEntry(Symbol
*sym
) {
405 if (sym
->requiresGOT
)
407 LLVM_DEBUG(dbgs() << "addInternalGOTEntry: " << sym
->getName() << " "
408 << toString(sym
->kind()) << "\n");
409 sym
->requiresGOT
= true;
410 if (auto *F
= dyn_cast
<FunctionSymbol
>(sym
)) {
411 ensureIndirectFunctionTable();
412 out
.elemSec
->addEntry(F
);
414 internalGotSymbols
.push_back(sym
);
417 void GlobalSection::generateRelocationCode(raw_ostream
&os
, bool TLS
) const {
418 assert(!ctx
.arg
.extendedConst
);
419 bool is64
= ctx
.arg
.is64
.value_or(false);
420 unsigned opcode_ptr_const
= is64
? WASM_OPCODE_I64_CONST
421 : WASM_OPCODE_I32_CONST
;
422 unsigned opcode_ptr_add
= is64
? WASM_OPCODE_I64_ADD
423 : WASM_OPCODE_I32_ADD
;
425 for (const Symbol
*sym
: internalGotSymbols
) {
426 if (TLS
!= sym
->isTLS())
429 if (auto *d
= dyn_cast
<DefinedData
>(sym
)) {
431 writeU8(os
, WASM_OPCODE_GLOBAL_GET
, "GLOBAL_GET");
433 writeUleb128(os
, WasmSym::tlsBase
->getGlobalIndex(), "__tls_base");
435 writeUleb128(os
, WasmSym::memoryBase
->getGlobalIndex(),
438 // Add the virtual address of the data symbol
439 writeU8(os
, opcode_ptr_const
, "CONST");
440 writeSleb128(os
, d
->getVA(), "offset");
441 } else if (auto *f
= dyn_cast
<FunctionSymbol
>(sym
)) {
445 writeU8(os
, WASM_OPCODE_GLOBAL_GET
, "GLOBAL_GET");
446 writeUleb128(os
, WasmSym::tableBase
->getGlobalIndex(), "__table_base");
448 // Add the table index to __table_base
449 writeU8(os
, opcode_ptr_const
, "CONST");
450 writeSleb128(os
, f
->getTableIndex(), "offset");
452 assert(isa
<UndefinedData
>(sym
) || isa
<SharedData
>(sym
));
455 writeU8(os
, opcode_ptr_add
, "ADD");
456 writeU8(os
, WASM_OPCODE_GLOBAL_SET
, "GLOBAL_SET");
457 writeUleb128(os
, sym
->getGOTIndex(), "got_entry");
461 void GlobalSection::writeBody() {
462 raw_ostream
&os
= bodyOutputStream
;
464 writeUleb128(os
, numGlobals(), "global count");
465 for (InputGlobal
*g
: inputGlobals
) {
466 writeGlobalType(os
, g
->getType());
467 writeInitExpr(os
, g
->getInitExpr());
469 bool is64
= ctx
.arg
.is64
.value_or(false);
470 uint8_t itype
= is64
? WASM_TYPE_I64
: WASM_TYPE_I32
;
471 for (const Symbol
*sym
: internalGotSymbols
) {
472 bool mutable_
= false;
474 // In the case of dynamic linking, unless we have 'extended-const'
475 // available, these global must to be mutable since they get updated to
476 // the correct runtime value during `__wasm_apply_global_relocs`.
477 if (!ctx
.arg
.extendedConst
&& ctx
.isPic
&& !sym
->isTLS())
479 // With multi-theadeding any TLS globals must be mutable since they get
480 // set during `__wasm_apply_global_tls_relocs`
481 if (ctx
.arg
.sharedMemory
&& sym
->isTLS())
484 WasmGlobalType type
{itype
, mutable_
};
485 writeGlobalType(os
, type
);
487 bool useExtendedConst
= false;
490 if (ctx
.arg
.extendedConst
&& ctx
.isPic
) {
491 if (auto *d
= dyn_cast
<DefinedData
>(sym
)) {
493 globalIdx
= WasmSym::memoryBase
->getGlobalIndex();
495 useExtendedConst
= true;
497 } else if (auto *f
= dyn_cast
<FunctionSymbol
>(sym
)) {
499 globalIdx
= WasmSym::tableBase
->getGlobalIndex();
500 offset
= f
->getTableIndex();
501 useExtendedConst
= true;
505 if (useExtendedConst
) {
506 // We can use an extended init expression to add a constant
507 // offset of __memory_base/__table_base.
508 writeU8(os
, WASM_OPCODE_GLOBAL_GET
, "global get");
509 writeUleb128(os
, globalIdx
, "literal (global index)");
511 writePtrConst(os
, offset
, is64
, "offset");
512 writeU8(os
, is64
? WASM_OPCODE_I64_ADD
: WASM_OPCODE_I32_ADD
, "add");
514 writeU8(os
, WASM_OPCODE_END
, "opcode:end");
516 WasmInitExpr initExpr
;
517 if (auto *d
= dyn_cast
<DefinedData
>(sym
))
518 // In the sharedMemory case TLS globals are set during
519 // `__wasm_apply_global_tls_relocs`, but in the non-shared case
520 // we know the absolute value at link time.
521 initExpr
= intConst(d
->getVA(/*absolute=*/!ctx
.arg
.sharedMemory
), is64
);
522 else if (auto *f
= dyn_cast
<FunctionSymbol
>(sym
))
523 initExpr
= intConst(f
->isStub
? 0 : f
->getTableIndex(), is64
);
525 assert(isa
<UndefinedData
>(sym
) || isa
<SharedData
>(sym
));
526 initExpr
= intConst(0, is64
);
528 writeInitExpr(os
, initExpr
);
531 for (const DefinedData
*sym
: dataAddressGlobals
) {
532 WasmGlobalType type
{itype
, false};
533 writeGlobalType(os
, type
);
534 writeInitExpr(os
, intConst(sym
->getVA(), is64
));
538 void GlobalSection::addGlobal(InputGlobal
*global
) {
542 inputGlobals
.push_back(global
);
545 void ExportSection::writeBody() {
546 raw_ostream
&os
= bodyOutputStream
;
548 writeUleb128(os
, exports
.size(), "export count");
549 for (const WasmExport
&export_
: exports
)
550 writeExport(os
, export_
);
553 bool StartSection::isNeeded() const {
554 return WasmSym::startFunction
!= nullptr;
557 void StartSection::writeBody() {
558 raw_ostream
&os
= bodyOutputStream
;
559 writeUleb128(os
, WasmSym::startFunction
->getFunctionIndex(),
563 void ElemSection::addEntry(FunctionSymbol
*sym
) {
564 // Don't add stub functions to the wasm table. The address of all stub
565 // functions should be zero and they should they don't appear in the table.
566 // They only exist so that the calls to missing functions can validate.
567 if (sym
->hasTableIndex() || sym
->isStub
)
569 sym
->setTableIndex(ctx
.arg
.tableBase
+ indirectFunctions
.size());
570 indirectFunctions
.emplace_back(sym
);
573 void ElemSection::writeBody() {
574 raw_ostream
&os
= bodyOutputStream
;
576 assert(WasmSym::indirectFunctionTable
);
577 writeUleb128(os
, 1, "segment count");
578 uint32_t tableNumber
= WasmSym::indirectFunctionTable
->getTableNumber();
581 flags
|= WASM_ELEM_SEGMENT_HAS_TABLE_NUMBER
;
582 writeUleb128(os
, flags
, "elem segment flags");
583 if (flags
& WASM_ELEM_SEGMENT_HAS_TABLE_NUMBER
)
584 writeUleb128(os
, tableNumber
, "table number");
586 WasmInitExpr initExpr
;
587 initExpr
.Extended
= false;
589 initExpr
.Inst
.Opcode
= WASM_OPCODE_GLOBAL_GET
;
590 initExpr
.Inst
.Value
.Global
= WasmSym::tableBase
->getGlobalIndex();
592 bool is64
= ctx
.arg
.is64
.value_or(false);
593 initExpr
= intConst(ctx
.arg
.tableBase
, is64
);
595 writeInitExpr(os
, initExpr
);
597 if (flags
& WASM_ELEM_SEGMENT_MASK_HAS_ELEM_DESC
) {
598 // We only write active function table initializers, for which the elem kind
599 // is specified to be written as 0x00 and interpreted to mean "funcref".
600 const uint8_t elemKind
= 0;
601 writeU8(os
, elemKind
, "elem kind");
604 writeUleb128(os
, indirectFunctions
.size(), "elem count");
605 uint32_t tableIndex
= ctx
.arg
.tableBase
;
606 for (const FunctionSymbol
*sym
: indirectFunctions
) {
607 assert(sym
->getTableIndex() == tableIndex
);
609 writeUleb128(os
, sym
->getFunctionIndex(), "function index");
614 DataCountSection::DataCountSection(ArrayRef
<OutputSegment
*> segments
)
615 : SyntheticSection(llvm::wasm::WASM_SEC_DATACOUNT
),
616 numSegments(llvm::count_if(segments
, [](OutputSegment
*const segment
) {
617 return segment
->requiredInBinary();
620 void DataCountSection::writeBody() {
621 writeUleb128(bodyOutputStream
, numSegments
, "data count");
624 bool DataCountSection::isNeeded() const {
625 return numSegments
&& ctx
.arg
.sharedMemory
;
628 void LinkingSection::writeBody() {
629 raw_ostream
&os
= bodyOutputStream
;
631 writeUleb128(os
, WasmMetadataVersion
, "Version");
633 if (!symtabEntries
.empty()) {
634 SubSection
sub(WASM_SYMBOL_TABLE
);
635 writeUleb128(sub
.os
, symtabEntries
.size(), "num symbols");
637 for (const Symbol
*sym
: symtabEntries
) {
638 assert(sym
->isDefined() || sym
->isUndefined());
639 WasmSymbolType kind
= sym
->getWasmType();
640 uint32_t flags
= sym
->flags
;
642 writeU8(sub
.os
, kind
, "sym kind");
643 writeUleb128(sub
.os
, flags
, "sym flags");
645 if (auto *f
= dyn_cast
<FunctionSymbol
>(sym
)) {
646 if (auto *d
= dyn_cast
<DefinedFunction
>(sym
)) {
647 writeUleb128(sub
.os
, d
->getExportedFunctionIndex(), "index");
649 writeUleb128(sub
.os
, f
->getFunctionIndex(), "index");
651 if (sym
->isDefined() || (flags
& WASM_SYMBOL_EXPLICIT_NAME
) != 0)
652 writeStr(sub
.os
, sym
->getName(), "sym name");
653 } else if (auto *g
= dyn_cast
<GlobalSymbol
>(sym
)) {
654 writeUleb128(sub
.os
, g
->getGlobalIndex(), "index");
655 if (sym
->isDefined() || (flags
& WASM_SYMBOL_EXPLICIT_NAME
) != 0)
656 writeStr(sub
.os
, sym
->getName(), "sym name");
657 } else if (auto *t
= dyn_cast
<TagSymbol
>(sym
)) {
658 writeUleb128(sub
.os
, t
->getTagIndex(), "index");
659 if (sym
->isDefined() || (flags
& WASM_SYMBOL_EXPLICIT_NAME
) != 0)
660 writeStr(sub
.os
, sym
->getName(), "sym name");
661 } else if (auto *t
= dyn_cast
<TableSymbol
>(sym
)) {
662 writeUleb128(sub
.os
, t
->getTableNumber(), "table number");
663 if (sym
->isDefined() || (flags
& WASM_SYMBOL_EXPLICIT_NAME
) != 0)
664 writeStr(sub
.os
, sym
->getName(), "sym name");
665 } else if (isa
<DataSymbol
>(sym
)) {
666 writeStr(sub
.os
, sym
->getName(), "sym name");
667 if (auto *dataSym
= dyn_cast
<DefinedData
>(sym
)) {
668 if (dataSym
->segment
) {
669 writeUleb128(sub
.os
, dataSym
->getOutputSegmentIndex(), "index");
670 writeUleb128(sub
.os
, dataSym
->getOutputSegmentOffset(),
673 writeUleb128(sub
.os
, 0, "index");
674 writeUleb128(sub
.os
, dataSym
->getVA(), "data offset");
676 writeUleb128(sub
.os
, dataSym
->getSize(), "data size");
679 auto *s
= cast
<OutputSectionSymbol
>(sym
);
680 writeUleb128(sub
.os
, s
->section
->sectionIndex
, "sym section index");
687 if (dataSegments
.size()) {
688 SubSection
sub(WASM_SEGMENT_INFO
);
689 writeUleb128(sub
.os
, dataSegments
.size(), "num data segments");
690 for (const OutputSegment
*s
: dataSegments
) {
691 writeStr(sub
.os
, s
->name
, "segment name");
692 writeUleb128(sub
.os
, s
->alignment
, "alignment");
693 writeUleb128(sub
.os
, s
->linkingFlags
, "flags");
698 if (!initFunctions
.empty()) {
699 SubSection
sub(WASM_INIT_FUNCS
);
700 writeUleb128(sub
.os
, initFunctions
.size(), "num init functions");
701 for (const WasmInitEntry
&f
: initFunctions
) {
702 writeUleb128(sub
.os
, f
.priority
, "priority");
703 writeUleb128(sub
.os
, f
.sym
->getOutputSymbolIndex(), "function index");
712 std::map
<StringRef
, std::vector
<ComdatEntry
>> comdats
;
714 for (const InputFunction
*f
: out
.functionSec
->inputFunctions
) {
715 StringRef comdat
= f
->getComdatName();
717 comdats
[comdat
].emplace_back(
718 ComdatEntry
{WASM_COMDAT_FUNCTION
, f
->getFunctionIndex()});
720 for (uint32_t i
= 0; i
< dataSegments
.size(); ++i
) {
721 const auto &inputSegments
= dataSegments
[i
]->inputSegments
;
722 if (inputSegments
.empty())
724 StringRef comdat
= inputSegments
[0]->getComdatName();
726 for (const InputChunk
*isec
: inputSegments
)
727 assert(isec
->getComdatName() == comdat
);
730 comdats
[comdat
].emplace_back(ComdatEntry
{WASM_COMDAT_DATA
, i
});
733 if (!comdats
.empty()) {
734 SubSection
sub(WASM_COMDAT_INFO
);
735 writeUleb128(sub
.os
, comdats
.size(), "num comdats");
736 for (const auto &c
: comdats
) {
737 writeStr(sub
.os
, c
.first
, "comdat name");
738 writeUleb128(sub
.os
, 0, "comdat flags"); // flags for future use
739 writeUleb128(sub
.os
, c
.second
.size(), "num entries");
740 for (const ComdatEntry
&entry
: c
.second
) {
741 writeU8(sub
.os
, entry
.kind
, "entry kind");
742 writeUleb128(sub
.os
, entry
.index
, "entry index");
749 void LinkingSection::addToSymtab(Symbol
*sym
) {
750 sym
->setOutputSymbolIndex(symtabEntries
.size());
751 symtabEntries
.emplace_back(sym
);
754 unsigned NameSection::numNamedFunctions() const {
755 unsigned numNames
= out
.importSec
->getNumImportedFunctions();
757 for (const InputFunction
*f
: out
.functionSec
->inputFunctions
)
758 if (!f
->name
.empty() || !f
->debugName
.empty())
764 unsigned NameSection::numNamedGlobals() const {
765 unsigned numNames
= out
.importSec
->getNumImportedGlobals();
767 for (const InputGlobal
*g
: out
.globalSec
->inputGlobals
)
768 if (!g
->getName().empty())
771 numNames
+= out
.globalSec
->internalGotSymbols
.size();
775 unsigned NameSection::numNamedDataSegments() const {
776 unsigned numNames
= 0;
778 for (const OutputSegment
*s
: segments
)
779 if (!s
->name
.empty() && s
->requiredInBinary())
785 // Create the custom "name" section containing debug symbol names.
786 void NameSection::writeBody() {
788 SubSection
sub(WASM_NAMES_MODULE
);
789 StringRef moduleName
= ctx
.arg
.soName
;
790 if (ctx
.arg
.soName
.empty())
791 moduleName
= llvm::sys::path::filename(ctx
.arg
.outputFile
);
792 writeStr(sub
.os
, moduleName
, "module name");
793 sub
.writeTo(bodyOutputStream
);
796 unsigned count
= numNamedFunctions();
798 SubSection
sub(WASM_NAMES_FUNCTION
);
799 writeUleb128(sub
.os
, count
, "name count");
801 // Function names appear in function index order. As it happens
802 // importedSymbols and inputFunctions are numbered in order with imported
803 // functions coming first.
804 for (const Symbol
*s
: out
.importSec
->importedSymbols
) {
805 if (auto *f
= dyn_cast
<FunctionSymbol
>(s
)) {
806 writeUleb128(sub
.os
, f
->getFunctionIndex(), "func index");
807 writeStr(sub
.os
, toString(*s
), "symbol name");
810 for (const InputFunction
*f
: out
.functionSec
->inputFunctions
) {
811 if (!f
->name
.empty()) {
812 writeUleb128(sub
.os
, f
->getFunctionIndex(), "func index");
813 if (!f
->debugName
.empty()) {
814 writeStr(sub
.os
, f
->debugName
, "symbol name");
816 writeStr(sub
.os
, maybeDemangleSymbol(f
->name
), "symbol name");
820 sub
.writeTo(bodyOutputStream
);
823 count
= numNamedGlobals();
825 SubSection
sub(WASM_NAMES_GLOBAL
);
826 writeUleb128(sub
.os
, count
, "name count");
828 for (const Symbol
*s
: out
.importSec
->importedSymbols
) {
829 if (auto *g
= dyn_cast
<GlobalSymbol
>(s
)) {
830 writeUleb128(sub
.os
, g
->getGlobalIndex(), "global index");
831 writeStr(sub
.os
, toString(*s
), "symbol name");
834 for (const Symbol
*s
: out
.importSec
->gotSymbols
) {
835 writeUleb128(sub
.os
, s
->getGOTIndex(), "global index");
836 writeStr(sub
.os
, toString(*s
), "symbol name");
838 for (const InputGlobal
*g
: out
.globalSec
->inputGlobals
) {
839 if (!g
->getName().empty()) {
840 writeUleb128(sub
.os
, g
->getAssignedIndex(), "global index");
841 writeStr(sub
.os
, maybeDemangleSymbol(g
->getName()), "symbol name");
844 for (Symbol
*s
: out
.globalSec
->internalGotSymbols
) {
845 writeUleb128(sub
.os
, s
->getGOTIndex(), "global index");
846 if (isa
<FunctionSymbol
>(s
))
847 writeStr(sub
.os
, "GOT.func.internal." + toString(*s
), "symbol name");
849 writeStr(sub
.os
, "GOT.data.internal." + toString(*s
), "symbol name");
852 sub
.writeTo(bodyOutputStream
);
855 count
= numNamedDataSegments();
857 SubSection
sub(WASM_NAMES_DATA_SEGMENT
);
858 writeUleb128(sub
.os
, count
, "name count");
860 for (OutputSegment
*s
: segments
) {
861 if (!s
->name
.empty() && s
->requiredInBinary()) {
862 writeUleb128(sub
.os
, s
->index
, "global index");
863 writeStr(sub
.os
, s
->name
, "segment name");
867 sub
.writeTo(bodyOutputStream
);
871 void ProducersSection::addInfo(const WasmProducerInfo
&info
) {
872 for (auto &producers
:
873 {std::make_pair(&info
.Languages
, &languages
),
874 std::make_pair(&info
.Tools
, &tools
), std::make_pair(&info
.SDKs
, &sDKs
)})
875 for (auto &producer
: *producers
.first
)
876 if (llvm::none_of(*producers
.second
,
877 [&](std::pair
<std::string
, std::string
> seen
) {
878 return seen
.first
== producer
.first
;
880 producers
.second
->push_back(producer
);
883 void ProducersSection::writeBody() {
884 auto &os
= bodyOutputStream
;
885 writeUleb128(os
, fieldCount(), "field count");
887 {std::make_pair("language", languages
),
888 std::make_pair("processed-by", tools
), std::make_pair("sdk", sDKs
)}) {
889 if (field
.second
.empty())
891 writeStr(os
, field
.first
, "field name");
892 writeUleb128(os
, field
.second
.size(), "number of entries");
893 for (auto &entry
: field
.second
) {
894 writeStr(os
, entry
.first
, "producer name");
895 writeStr(os
, entry
.second
, "producer version");
900 void TargetFeaturesSection::writeBody() {
901 SmallVector
<std::string
, 8> emitted(features
.begin(), features
.end());
903 auto &os
= bodyOutputStream
;
904 writeUleb128(os
, emitted
.size(), "feature count");
905 for (auto &feature
: emitted
) {
906 writeU8(os
, WASM_FEATURE_PREFIX_USED
, "feature used prefix");
907 writeStr(os
, feature
, "feature name");
911 void RelocSection::writeBody() {
912 uint32_t count
= sec
->getNumRelocations();
913 assert(sec
->sectionIndex
!= UINT32_MAX
);
914 writeUleb128(bodyOutputStream
, sec
->sectionIndex
, "reloc section");
915 writeUleb128(bodyOutputStream
, count
, "reloc count");
916 sec
->writeRelocations(bodyOutputStream
);
919 static size_t getHashSize() {
920 switch (ctx
.arg
.buildId
) {
921 case BuildIdKind::Fast
:
922 case BuildIdKind::Uuid
:
924 case BuildIdKind::Sha1
:
926 case BuildIdKind::Hexstring
:
927 return ctx
.arg
.buildIdVector
.size();
928 case BuildIdKind::None
:
931 llvm_unreachable("build id kind not implemented");
934 BuildIdSection::BuildIdSection()
935 : SyntheticSection(llvm::wasm::WASM_SEC_CUSTOM
, buildIdSectionName
),
936 hashSize(getHashSize()) {}
938 void BuildIdSection::writeBody() {
939 LLVM_DEBUG(llvm::dbgs() << "BuildId writebody\n");
941 auto &os
= bodyOutputStream
;
942 writeUleb128(os
, hashSize
, "build id size");
943 writeBytes(os
, std::vector
<char>(hashSize
, ' ').data(), hashSize
,
947 void BuildIdSection::writeBuildId(llvm::ArrayRef
<uint8_t> buf
) {
948 assert(buf
.size() == hashSize
);
949 LLVM_DEBUG(dbgs() << "buildid write " << buf
.size() << " "
950 << hashPlaceholderPtr
<< '\n');
951 memcpy(hashPlaceholderPtr
, buf
.data(), hashSize
);
954 } // namespace wasm::lld