1//===- SyntheticSections.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// This file contains linker-synthesized sections.
10//
11//===----------------------------------------------------------------------===//
12
13#include "SyntheticSections.h"
14
15#include "InputChunks.h"
16#include "InputElement.h"
17#include "OutputSegment.h"
18#include "SymbolTable.h"
19#include "llvm/Support/Path.h"
20#include <optional>
21
22using namespace llvm;
23using namespace llvm::wasm;
24
25namespace lld::wasm {
26
27OutStruct out;
28
29namespace {
30
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.
36class SubSection {
37public:
38 explicit SubSection(uint32_t type) : type(type) {}
39
40 void writeTo(raw_ostream &to) {
41 os.flush();
42 writeUleb128(os&: to, number: type, msg: "subsection type");
43 writeUleb128(os&: to, number: body.size(), msg: "subsection size");
44 to.write(Ptr: body.data(), Size: body.size());
45 }
46
47private:
48 uint32_t type;
49 std::string body;
50
51public:
52 raw_string_ostream os{body};
53};
54
55} // namespace
56
57bool DylinkSection::isNeeded() const {
58 return ctx.isPic ||
59 config->unresolvedSymbols == UnresolvedPolicy::ImportDynamic ||
60 !ctx.sharedFiles.empty();
61}
62
63void DylinkSection::writeBody() {
64 raw_ostream &os = bodyOutputStream;
65
66 {
67 SubSection sub(WASM_DYLINK_MEM_INFO);
68 writeUleb128(os&: sub.os, number: memSize, msg: "MemSize");
69 writeUleb128(os&: sub.os, number: memAlign, msg: "MemAlign");
70 writeUleb128(os&: sub.os, number: out.elemSec->numEntries(), msg: "TableSize");
71 writeUleb128(os&: sub.os, number: 0, msg: "TableAlign");
72 sub.writeTo(to&: os);
73 }
74
75 if (ctx.sharedFiles.size()) {
76 SubSection sub(WASM_DYLINK_NEEDED);
77 writeUleb128(os&: sub.os, number: ctx.sharedFiles.size(), msg: "Needed");
78 for (auto *so : ctx.sharedFiles)
79 writeStr(os&: sub.os, string: llvm::sys::path::filename(path: so->getName()), msg: "so name");
80 sub.writeTo(to&: os);
81 }
82
83 // Under certain circumstances we need to include extra information about our
84 // exports and/or imports to the dynamic linker.
85 // For exports we need to notify the linker when an export is TLS since the
86 // exported value is relative to __tls_base rather than __memory_base.
87 // For imports we need to notify the dynamic linker when an import is weak
88 // so that knows not to report an error for such symbols.
89 std::vector<const Symbol *> importInfo;
90 std::vector<const Symbol *> exportInfo;
91 for (const Symbol *sym : symtab->symbols()) {
92 if (sym->isLive()) {
93 if (sym->isExported() && sym->isTLS() && isa<DefinedData>(Val: sym)) {
94 exportInfo.push_back(x: sym);
95 }
96 if (sym->isUndefWeak()) {
97 importInfo.push_back(x: sym);
98 }
99 }
100 }
101
102 if (!exportInfo.empty()) {
103 SubSection sub(WASM_DYLINK_EXPORT_INFO);
104 writeUleb128(os&: sub.os, number: exportInfo.size(), msg: "num exports");
105
106 for (const Symbol *sym : exportInfo) {
107 LLVM_DEBUG(llvm::dbgs() << "export info: " << toString(*sym) << "\n");
108 StringRef name = sym->getName();
109 if (auto *f = dyn_cast<DefinedFunction>(Val: sym)) {
110 if (std::optional<StringRef> exportName =
111 f->function->getExportName()) {
112 name = *exportName;
113 }
114 }
115 writeStr(os&: sub.os, string: name, msg: "sym name");
116 writeUleb128(os&: sub.os, number: sym->flags, msg: "sym flags");
117 }
118
119 sub.writeTo(to&: os);
120 }
121
122 if (!importInfo.empty()) {
123 SubSection sub(WASM_DYLINK_IMPORT_INFO);
124 writeUleb128(os&: sub.os, number: importInfo.size(), msg: "num imports");
125
126 for (const Symbol *sym : importInfo) {
127 LLVM_DEBUG(llvm::dbgs() << "imports info: " << toString(*sym) << "\n");
128 StringRef module = sym->importModule.value_or(u&: defaultModule);
129 StringRef name = sym->importName.value_or(u: sym->getName());
130 writeStr(os&: sub.os, string: module, msg: "import module");
131 writeStr(os&: sub.os, string: name, msg: "import name");
132 writeUleb128(os&: sub.os, number: sym->flags, msg: "sym flags");
133 }
134
135 sub.writeTo(to&: os);
136 }
137}
138
139uint32_t TypeSection::registerType(const WasmSignature &sig) {
140 auto pair = typeIndices.insert(KV: std::make_pair(x: sig, y: types.size()));
141 if (pair.second) {
142 LLVM_DEBUG(llvm::dbgs() << "registerType " << toString(sig) << "\n");
143 types.push_back(x: &sig);
144 }
145 return pair.first->second;
146}
147
148uint32_t TypeSection::lookupType(const WasmSignature &sig) {
149 auto it = typeIndices.find(Val: sig);
150 if (it == typeIndices.end()) {
151 error(msg: "type not found: " + toString(sig));
152 return 0;
153 }
154 return it->second;
155}
156
157void TypeSection::writeBody() {
158 writeUleb128(os&: bodyOutputStream, number: types.size(), msg: "type count");
159 for (const WasmSignature *sig : types)
160 writeSig(os&: bodyOutputStream, sig: *sig);
161}
162
163uint32_t ImportSection::getNumImports() const {
164 assert(isSealed);
165 uint32_t numImports = importedSymbols.size() + gotSymbols.size();
166 if (config->memoryImport.has_value())
167 ++numImports;
168 return numImports;
169}
170
171void ImportSection::addGOTEntry(Symbol *sym) {
172 assert(!isSealed);
173 if (sym->hasGOTIndex())
174 return;
175 LLVM_DEBUG(dbgs() << "addGOTEntry: " << toString(*sym) << "\n");
176 sym->setGOTIndex(numImportedGlobals++);
177 if (ctx.isPic) {
178 // Any symbol that is assigned an normal GOT entry must be exported
179 // otherwise the dynamic linker won't be able create the entry that contains
180 // it.
181 sym->forceExport = true;
182 }
183 gotSymbols.push_back(x: sym);
184}
185
186void ImportSection::addImport(Symbol *sym) {
187 assert(!isSealed);
188 StringRef module = sym->importModule.value_or(u&: defaultModule);
189 StringRef name = sym->importName.value_or(u: sym->getName());
190 if (auto *f = dyn_cast<FunctionSymbol>(Val: sym)) {
191 ImportKey<WasmSignature> key(*(f->getSignature()), module, name);
192 auto entry = importedFunctions.try_emplace(Key: key, Args&: numImportedFunctions);
193 if (entry.second) {
194 importedSymbols.emplace_back(args&: sym);
195 f->setFunctionIndex(numImportedFunctions++);
196 } else {
197 f->setFunctionIndex(entry.first->second);
198 }
199 } else if (auto *g = dyn_cast<GlobalSymbol>(Val: sym)) {
200 ImportKey<WasmGlobalType> key(*(g->getGlobalType()), module, name);
201 auto entry = importedGlobals.try_emplace(Key: key, Args&: numImportedGlobals);
202 if (entry.second) {
203 importedSymbols.emplace_back(args&: sym);
204 g->setGlobalIndex(numImportedGlobals++);
205 } else {
206 g->setGlobalIndex(entry.first->second);
207 }
208 } else if (auto *t = dyn_cast<TagSymbol>(Val: sym)) {
209 ImportKey<WasmSignature> key(*(t->getSignature()), module, name);
210 auto entry = importedTags.try_emplace(Key: key, Args&: numImportedTags);
211 if (entry.second) {
212 importedSymbols.emplace_back(args&: sym);
213 t->setTagIndex(numImportedTags++);
214 } else {
215 t->setTagIndex(entry.first->second);
216 }
217 } else {
218 assert(TableSymbol::classof(sym));
219 auto *table = cast<TableSymbol>(Val: sym);
220 ImportKey<WasmTableType> key(*(table->getTableType()), module, name);
221 auto entry = importedTables.try_emplace(Key: key, Args&: numImportedTables);
222 if (entry.second) {
223 importedSymbols.emplace_back(args&: sym);
224 table->setTableNumber(numImportedTables++);
225 } else {
226 table->setTableNumber(entry.first->second);
227 }
228 }
229}
230
231void ImportSection::writeBody() {
232 raw_ostream &os = bodyOutputStream;
233
234 writeUleb128(os, number: getNumImports(), msg: "import count");
235
236 bool is64 = config->is64.value_or(u: false);
237
238 if (config->memoryImport) {
239 WasmImport import;
240 import.Module = config->memoryImport->first;
241 import.Field = config->memoryImport->second;
242 import.Kind = WASM_EXTERNAL_MEMORY;
243 import.Memory.Flags = 0;
244 import.Memory.Minimum = out.memorySec->numMemoryPages;
245 if (out.memorySec->maxMemoryPages != 0 || config->sharedMemory) {
246 import.Memory.Flags |= WASM_LIMITS_FLAG_HAS_MAX;
247 import.Memory.Maximum = out.memorySec->maxMemoryPages;
248 }
249 if (config->sharedMemory)
250 import.Memory.Flags |= WASM_LIMITS_FLAG_IS_SHARED;
251 if (is64)
252 import.Memory.Flags |= WASM_LIMITS_FLAG_IS_64;
253 writeImport(os, import);
254 }
255
256 for (const Symbol *sym : importedSymbols) {
257 WasmImport import;
258 import.Field = sym->importName.value_or(u: sym->getName());
259 import.Module = sym->importModule.value_or(u&: defaultModule);
260
261 if (auto *functionSym = dyn_cast<FunctionSymbol>(Val: sym)) {
262 import.Kind = WASM_EXTERNAL_FUNCTION;
263 import.SigIndex = out.typeSec->lookupType(sig: *functionSym->signature);
264 } else if (auto *globalSym = dyn_cast<GlobalSymbol>(Val: sym)) {
265 import.Kind = WASM_EXTERNAL_GLOBAL;
266 import.Global = *globalSym->getGlobalType();
267 } else if (auto *tagSym = dyn_cast<TagSymbol>(Val: sym)) {
268 import.Kind = WASM_EXTERNAL_TAG;
269 import.SigIndex = out.typeSec->lookupType(sig: *tagSym->signature);
270 } else {
271 auto *tableSym = cast<TableSymbol>(Val: sym);
272 import.Kind = WASM_EXTERNAL_TABLE;
273 import.Table = *tableSym->getTableType();
274 }
275 writeImport(os, import);
276 }
277
278 for (const Symbol *sym : gotSymbols) {
279 WasmImport import;
280 import.Kind = WASM_EXTERNAL_GLOBAL;
281 auto ptrType = is64 ? WASM_TYPE_I64 : WASM_TYPE_I32;
282 import.Global = {.Type: static_cast<uint8_t>(ptrType), .Mutable: true};
283 if (isa<DataSymbol>(Val: sym))
284 import.Module = "GOT.mem";
285 else
286 import.Module = "GOT.func";
287 import.Field = sym->getName();
288 writeImport(os, import);
289 }
290}
291
292void FunctionSection::writeBody() {
293 raw_ostream &os = bodyOutputStream;
294
295 writeUleb128(os, number: inputFunctions.size(), msg: "function count");
296 for (const InputFunction *func : inputFunctions)
297 writeUleb128(os, number: out.typeSec->lookupType(sig: func->signature), msg: "sig index");
298}
299
300void FunctionSection::addFunction(InputFunction *func) {
301 if (!func->live)
302 return;
303 uint32_t functionIndex =
304 out.importSec->getNumImportedFunctions() + inputFunctions.size();
305 inputFunctions.emplace_back(args&: func);
306 func->setFunctionIndex(functionIndex);
307}
308
309void TableSection::writeBody() {
310 raw_ostream &os = bodyOutputStream;
311
312 writeUleb128(os, number: inputTables.size(), msg: "table count");
313 for (const InputTable *table : inputTables)
314 writeTableType(os, type: table->getType());
315}
316
317void TableSection::addTable(InputTable *table) {
318 if (!table->live)
319 return;
320 // Some inputs require that the indirect function table be assigned to table
321 // number 0.
322 if (ctx.legacyFunctionTable &&
323 isa<DefinedTable>(Val: WasmSym::indirectFunctionTable) &&
324 cast<DefinedTable>(Val: WasmSym::indirectFunctionTable)->table == table) {
325 if (out.importSec->getNumImportedTables()) {
326 // Alack! Some other input imported a table, meaning that we are unable
327 // to assign table number 0 to the indirect function table.
328 for (const auto *culprit : out.importSec->importedSymbols) {
329 if (isa<UndefinedTable>(Val: culprit)) {
330 error(msg: "object file not built with 'reference-types' feature "
331 "conflicts with import of table " +
332 culprit->getName() + " by file " +
333 toString(file: culprit->getFile()));
334 return;
335 }
336 }
337 llvm_unreachable("failed to find conflicting table import");
338 }
339 inputTables.insert(position: inputTables.begin(), x: table);
340 return;
341 }
342 inputTables.push_back(x: table);
343}
344
345void TableSection::assignIndexes() {
346 uint32_t tableNumber = out.importSec->getNumImportedTables();
347 for (InputTable *t : inputTables)
348 t->assignIndex(index: tableNumber++);
349}
350
351void MemorySection::writeBody() {
352 raw_ostream &os = bodyOutputStream;
353
354 bool hasMax = maxMemoryPages != 0 || config->sharedMemory;
355 writeUleb128(os, number: 1, msg: "memory count");
356 unsigned flags = 0;
357 if (hasMax)
358 flags |= WASM_LIMITS_FLAG_HAS_MAX;
359 if (config->sharedMemory)
360 flags |= WASM_LIMITS_FLAG_IS_SHARED;
361 if (config->is64.value_or(u: false))
362 flags |= WASM_LIMITS_FLAG_IS_64;
363 writeUleb128(os, number: flags, msg: "memory limits flags");
364 writeUleb128(os, number: numMemoryPages, msg: "initial pages");
365 if (hasMax)
366 writeUleb128(os, number: maxMemoryPages, msg: "max pages");
367}
368
369void TagSection::writeBody() {
370 raw_ostream &os = bodyOutputStream;
371
372 writeUleb128(os, number: inputTags.size(), msg: "tag count");
373 for (InputTag *t : inputTags) {
374 writeUleb128(os, number: 0, msg: "tag attribute"); // Reserved "attribute" field
375 writeUleb128(os, number: out.typeSec->lookupType(sig: t->signature), msg: "sig index");
376 }
377}
378
379void TagSection::addTag(InputTag *tag) {
380 if (!tag->live)
381 return;
382 uint32_t tagIndex = out.importSec->getNumImportedTags() + inputTags.size();
383 LLVM_DEBUG(dbgs() << "addTag: " << tagIndex << "\n");
384 tag->assignIndex(index: tagIndex);
385 inputTags.push_back(x: tag);
386}
387
388void GlobalSection::assignIndexes() {
389 uint32_t globalIndex = out.importSec->getNumImportedGlobals();
390 for (InputGlobal *g : inputGlobals)
391 g->assignIndex(index: globalIndex++);
392 for (Symbol *sym : internalGotSymbols)
393 sym->setGOTIndex(globalIndex++);
394 isSealed = true;
395}
396
397static void ensureIndirectFunctionTable() {
398 if (!WasmSym::indirectFunctionTable)
399 WasmSym::indirectFunctionTable =
400 symtab->resolveIndirectFunctionTable(/*required =*/true);
401}
402
403void GlobalSection::addInternalGOTEntry(Symbol *sym) {
404 assert(!isSealed);
405 if (sym->requiresGOT)
406 return;
407 LLVM_DEBUG(dbgs() << "addInternalGOTEntry: " << sym->getName() << " "
408 << toString(sym->kind()) << "\n");
409 sym->requiresGOT = true;
410 if (auto *F = dyn_cast<FunctionSymbol>(Val: sym)) {
411 ensureIndirectFunctionTable();
412 out.elemSec->addEntry(sym: F);
413 }
414 internalGotSymbols.push_back(x: sym);
415}
416
417void GlobalSection::generateRelocationCode(raw_ostream &os, bool TLS) const {
418 assert(!config->extendedConst);
419 bool is64 = config->is64.value_or(u: 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;
424
425 for (const Symbol *sym : internalGotSymbols) {
426 if (TLS != sym->isTLS())
427 continue;
428
429 if (auto *d = dyn_cast<DefinedData>(Val: sym)) {
430 // Get __memory_base
431 writeU8(os, byte: WASM_OPCODE_GLOBAL_GET, msg: "GLOBAL_GET");
432 if (sym->isTLS())
433 writeUleb128(os, number: WasmSym::tlsBase->getGlobalIndex(), msg: "__tls_base");
434 else
435 writeUleb128(os, number: WasmSym::memoryBase->getGlobalIndex(),
436 msg: "__memory_base");
437
438 // Add the virtual address of the data symbol
439 writeU8(os, byte: opcode_ptr_const, msg: "CONST");
440 writeSleb128(os, number: d->getVA(), msg: "offset");
441 } else if (auto *f = dyn_cast<FunctionSymbol>(Val: sym)) {
442 if (f->isStub)
443 continue;
444 // Get __table_base
445 writeU8(os, byte: WASM_OPCODE_GLOBAL_GET, msg: "GLOBAL_GET");
446 writeUleb128(os, number: WasmSym::tableBase->getGlobalIndex(), msg: "__table_base");
447
448 // Add the table index to __table_base
449 writeU8(os, byte: opcode_ptr_const, msg: "CONST");
450 writeSleb128(os, number: f->getTableIndex(), msg: "offset");
451 } else {
452 assert(isa<UndefinedData>(sym) || isa<SharedData>(sym));
453 continue;
454 }
455 writeU8(os, byte: opcode_ptr_add, msg: "ADD");
456 writeU8(os, byte: WASM_OPCODE_GLOBAL_SET, msg: "GLOBAL_SET");
457 writeUleb128(os, number: sym->getGOTIndex(), msg: "got_entry");
458 }
459}
460
461void GlobalSection::writeBody() {
462 raw_ostream &os = bodyOutputStream;
463
464 writeUleb128(os, number: numGlobals(), msg: "global count");
465 for (InputGlobal *g : inputGlobals) {
466 writeGlobalType(os, type: g->getType());
467 writeInitExpr(os, initExpr: g->getInitExpr());
468 }
469 bool is64 = config->is64.value_or(u: false);
470 uint8_t itype = is64 ? WASM_TYPE_I64 : WASM_TYPE_I32;
471 for (const Symbol *sym : internalGotSymbols) {
472 bool mutable_ = false;
473 if (!sym->isStub) {
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 (!config->extendedConst && ctx.isPic && !sym->isTLS())
478 mutable_ = true;
479 // With multi-theadeding any TLS globals must be mutable since they get
480 // set during `__wasm_apply_global_tls_relocs`
481 if (config->sharedMemory && sym->isTLS())
482 mutable_ = true;
483 }
484 WasmGlobalType type{.Type: itype, .Mutable: mutable_};
485 writeGlobalType(os, type);
486
487 bool useExtendedConst = false;
488 uint32_t globalIdx;
489 int64_t offset;
490 if (config->extendedConst && ctx.isPic) {
491 if (auto *d = dyn_cast<DefinedData>(Val: sym)) {
492 if (!sym->isTLS()) {
493 globalIdx = WasmSym::memoryBase->getGlobalIndex();
494 offset = d->getVA();
495 useExtendedConst = true;
496 }
497 } else if (auto *f = dyn_cast<FunctionSymbol>(Val: sym)) {
498 if (!sym->isStub) {
499 globalIdx = WasmSym::tableBase->getGlobalIndex();
500 offset = f->getTableIndex();
501 useExtendedConst = true;
502 }
503 }
504 }
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, byte: WASM_OPCODE_GLOBAL_GET, msg: "global get");
509 writeUleb128(os, number: globalIdx, msg: "literal (global index)");
510 if (offset) {
511 writePtrConst(os, number: offset, is64, msg: "offset");
512 writeU8(os, byte: is64 ? WASM_OPCODE_I64_ADD : WASM_OPCODE_I32_ADD, msg: "add");
513 }
514 writeU8(os, byte: WASM_OPCODE_END, msg: "opcode:end");
515 } else {
516 WasmInitExpr initExpr;
517 if (auto *d = dyn_cast<DefinedData>(Val: sym))
518 initExpr = intConst(value: d->getVA(), is64);
519 else if (auto *f = dyn_cast<FunctionSymbol>(Val: sym))
520 initExpr = intConst(value: f->isStub ? 0 : f->getTableIndex(), is64);
521 else {
522 assert(isa<UndefinedData>(sym) || isa<SharedData>(sym));
523 initExpr = intConst(value: 0, is64);
524 }
525 writeInitExpr(os, initExpr);
526 }
527 }
528 for (const DefinedData *sym : dataAddressGlobals) {
529 WasmGlobalType type{.Type: itype, .Mutable: false};
530 writeGlobalType(os, type);
531 writeInitExpr(os, initExpr: intConst(value: sym->getVA(), is64));
532 }
533}
534
535void GlobalSection::addGlobal(InputGlobal *global) {
536 assert(!isSealed);
537 if (!global->live)
538 return;
539 inputGlobals.push_back(x: global);
540}
541
542void ExportSection::writeBody() {
543 raw_ostream &os = bodyOutputStream;
544
545 writeUleb128(os, number: exports.size(), msg: "export count");
546 for (const WasmExport &export_ : exports)
547 writeExport(os, export_);
548}
549
550bool StartSection::isNeeded() const {
551 return WasmSym::startFunction != nullptr;
552}
553
554void StartSection::writeBody() {
555 raw_ostream &os = bodyOutputStream;
556 writeUleb128(os, number: WasmSym::startFunction->getFunctionIndex(),
557 msg: "function index");
558}
559
560void ElemSection::addEntry(FunctionSymbol *sym) {
561 // Don't add stub functions to the wasm table. The address of all stub
562 // functions should be zero and they should they don't appear in the table.
563 // They only exist so that the calls to missing functions can validate.
564 if (sym->hasTableIndex() || sym->isStub)
565 return;
566 sym->setTableIndex(config->tableBase + indirectFunctions.size());
567 indirectFunctions.emplace_back(args&: sym);
568}
569
570void ElemSection::writeBody() {
571 raw_ostream &os = bodyOutputStream;
572
573 assert(WasmSym::indirectFunctionTable);
574 writeUleb128(os, number: 1, msg: "segment count");
575 uint32_t tableNumber = WasmSym::indirectFunctionTable->getTableNumber();
576 uint32_t flags = 0;
577 if (tableNumber)
578 flags |= WASM_ELEM_SEGMENT_HAS_TABLE_NUMBER;
579 writeUleb128(os, number: flags, msg: "elem segment flags");
580 if (flags & WASM_ELEM_SEGMENT_HAS_TABLE_NUMBER)
581 writeUleb128(os, number: tableNumber, msg: "table number");
582
583 WasmInitExpr initExpr;
584 initExpr.Extended = false;
585 if (ctx.isPic) {
586 initExpr.Inst.Opcode = WASM_OPCODE_GLOBAL_GET;
587 initExpr.Inst.Value.Global = WasmSym::tableBase->getGlobalIndex();
588 } else {
589 bool is64 = config->is64.value_or(u: false);
590 initExpr.Inst.Opcode = is64 ? WASM_OPCODE_I64_CONST : WASM_OPCODE_I32_CONST;
591 initExpr.Inst.Value.Int32 = config->tableBase;
592 }
593 writeInitExpr(os, initExpr);
594
595 if (flags & WASM_ELEM_SEGMENT_MASK_HAS_ELEM_KIND) {
596 // We only write active function table initializers, for which the elem kind
597 // is specified to be written as 0x00 and interpreted to mean "funcref".
598 const uint8_t elemKind = 0;
599 writeU8(os, byte: elemKind, msg: "elem kind");
600 }
601
602 writeUleb128(os, number: indirectFunctions.size(), msg: "elem count");
603 uint32_t tableIndex = config->tableBase;
604 for (const FunctionSymbol *sym : indirectFunctions) {
605 assert(sym->getTableIndex() == tableIndex);
606 (void) tableIndex;
607 writeUleb128(os, number: sym->getFunctionIndex(), msg: "function index");
608 ++tableIndex;
609 }
610}
611
612DataCountSection::DataCountSection(ArrayRef<OutputSegment *> segments)
613 : SyntheticSection(llvm::wasm::WASM_SEC_DATACOUNT),
614 numSegments(llvm::count_if(Range&: segments, P: [](OutputSegment *const segment) {
615 return segment->requiredInBinary();
616 })) {}
617
618void DataCountSection::writeBody() {
619 writeUleb128(os&: bodyOutputStream, number: numSegments, msg: "data count");
620}
621
622bool DataCountSection::isNeeded() const {
623 return numSegments && config->sharedMemory;
624}
625
626void LinkingSection::writeBody() {
627 raw_ostream &os = bodyOutputStream;
628
629 writeUleb128(os, number: WasmMetadataVersion, msg: "Version");
630
631 if (!symtabEntries.empty()) {
632 SubSection sub(WASM_SYMBOL_TABLE);
633 writeUleb128(os&: sub.os, number: symtabEntries.size(), msg: "num symbols");
634
635 for (const Symbol *sym : symtabEntries) {
636 assert(sym->isDefined() || sym->isUndefined());
637 WasmSymbolType kind = sym->getWasmType();
638 uint32_t flags = sym->flags;
639
640 writeU8(os&: sub.os, byte: kind, msg: "sym kind");
641 writeUleb128(os&: sub.os, number: flags, msg: "sym flags");
642
643 if (auto *f = dyn_cast<FunctionSymbol>(Val: sym)) {
644 if (auto *d = dyn_cast<DefinedFunction>(Val: sym)) {
645 writeUleb128(os&: sub.os, number: d->getExportedFunctionIndex(), msg: "index");
646 } else {
647 writeUleb128(os&: sub.os, number: f->getFunctionIndex(), msg: "index");
648 }
649 if (sym->isDefined() || (flags & WASM_SYMBOL_EXPLICIT_NAME) != 0)
650 writeStr(os&: sub.os, string: sym->getName(), msg: "sym name");
651 } else if (auto *g = dyn_cast<GlobalSymbol>(Val: sym)) {
652 writeUleb128(os&: sub.os, number: g->getGlobalIndex(), msg: "index");
653 if (sym->isDefined() || (flags & WASM_SYMBOL_EXPLICIT_NAME) != 0)
654 writeStr(os&: sub.os, string: sym->getName(), msg: "sym name");
655 } else if (auto *t = dyn_cast<TagSymbol>(Val: sym)) {
656 writeUleb128(os&: sub.os, number: t->getTagIndex(), msg: "index");
657 if (sym->isDefined() || (flags & WASM_SYMBOL_EXPLICIT_NAME) != 0)
658 writeStr(os&: sub.os, string: sym->getName(), msg: "sym name");
659 } else if (auto *t = dyn_cast<TableSymbol>(Val: sym)) {
660 writeUleb128(os&: sub.os, number: t->getTableNumber(), msg: "table number");
661 if (sym->isDefined() || (flags & WASM_SYMBOL_EXPLICIT_NAME) != 0)
662 writeStr(os&: sub.os, string: sym->getName(), msg: "sym name");
663 } else if (isa<DataSymbol>(Val: sym)) {
664 writeStr(os&: sub.os, string: sym->getName(), msg: "sym name");
665 if (auto *dataSym = dyn_cast<DefinedData>(Val: sym)) {
666 if (dataSym->segment) {
667 writeUleb128(os&: sub.os, number: dataSym->getOutputSegmentIndex(), msg: "index");
668 writeUleb128(os&: sub.os, number: dataSym->getOutputSegmentOffset(),
669 msg: "data offset");
670 } else {
671 writeUleb128(os&: sub.os, number: 0, msg: "index");
672 writeUleb128(os&: sub.os, number: dataSym->getVA(), msg: "data offset");
673 }
674 writeUleb128(os&: sub.os, number: dataSym->getSize(), msg: "data size");
675 }
676 } else {
677 auto *s = cast<OutputSectionSymbol>(Val: sym);
678 writeUleb128(os&: sub.os, number: s->section->sectionIndex, msg: "sym section index");
679 }
680 }
681
682 sub.writeTo(to&: os);
683 }
684
685 if (dataSegments.size()) {
686 SubSection sub(WASM_SEGMENT_INFO);
687 writeUleb128(os&: sub.os, number: dataSegments.size(), msg: "num data segments");
688 for (const OutputSegment *s : dataSegments) {
689 writeStr(os&: sub.os, string: s->name, msg: "segment name");
690 writeUleb128(os&: sub.os, number: s->alignment, msg: "alignment");
691 writeUleb128(os&: sub.os, number: s->linkingFlags, msg: "flags");
692 }
693 sub.writeTo(to&: os);
694 }
695
696 if (!initFunctions.empty()) {
697 SubSection sub(WASM_INIT_FUNCS);
698 writeUleb128(os&: sub.os, number: initFunctions.size(), msg: "num init functions");
699 for (const WasmInitEntry &f : initFunctions) {
700 writeUleb128(os&: sub.os, number: f.priority, msg: "priority");
701 writeUleb128(os&: sub.os, number: f.sym->getOutputSymbolIndex(), msg: "function index");
702 }
703 sub.writeTo(to&: os);
704 }
705
706 struct ComdatEntry {
707 unsigned kind;
708 uint32_t index;
709 };
710 std::map<StringRef, std::vector<ComdatEntry>> comdats;
711
712 for (const InputFunction *f : out.functionSec->inputFunctions) {
713 StringRef comdat = f->getComdatName();
714 if (!comdat.empty())
715 comdats[comdat].emplace_back(
716 args: ComdatEntry{.kind: WASM_COMDAT_FUNCTION, .index: f->getFunctionIndex()});
717 }
718 for (uint32_t i = 0; i < dataSegments.size(); ++i) {
719 const auto &inputSegments = dataSegments[i]->inputSegments;
720 if (inputSegments.empty())
721 continue;
722 StringRef comdat = inputSegments[0]->getComdatName();
723#ifndef NDEBUG
724 for (const InputChunk *isec : inputSegments)
725 assert(isec->getComdatName() == comdat);
726#endif
727 if (!comdat.empty())
728 comdats[comdat].emplace_back(args: ComdatEntry{.kind: WASM_COMDAT_DATA, .index: i});
729 }
730
731 if (!comdats.empty()) {
732 SubSection sub(WASM_COMDAT_INFO);
733 writeUleb128(os&: sub.os, number: comdats.size(), msg: "num comdats");
734 for (const auto &c : comdats) {
735 writeStr(os&: sub.os, string: c.first, msg: "comdat name");
736 writeUleb128(os&: sub.os, number: 0, msg: "comdat flags"); // flags for future use
737 writeUleb128(os&: sub.os, number: c.second.size(), msg: "num entries");
738 for (const ComdatEntry &entry : c.second) {
739 writeU8(os&: sub.os, byte: entry.kind, msg: "entry kind");
740 writeUleb128(os&: sub.os, number: entry.index, msg: "entry index");
741 }
742 }
743 sub.writeTo(to&: os);
744 }
745}
746
747void LinkingSection::addToSymtab(Symbol *sym) {
748 sym->setOutputSymbolIndex(symtabEntries.size());
749 symtabEntries.emplace_back(args&: sym);
750}
751
752unsigned NameSection::numNamedFunctions() const {
753 unsigned numNames = out.importSec->getNumImportedFunctions();
754
755 for (const InputFunction *f : out.functionSec->inputFunctions)
756 if (!f->name.empty() || !f->debugName.empty())
757 ++numNames;
758
759 return numNames;
760}
761
762unsigned NameSection::numNamedGlobals() const {
763 unsigned numNames = out.importSec->getNumImportedGlobals();
764
765 for (const InputGlobal *g : out.globalSec->inputGlobals)
766 if (!g->getName().empty())
767 ++numNames;
768
769 numNames += out.globalSec->internalGotSymbols.size();
770 return numNames;
771}
772
773unsigned NameSection::numNamedDataSegments() const {
774 unsigned numNames = 0;
775
776 for (const OutputSegment *s : segments)
777 if (!s->name.empty() && s->requiredInBinary())
778 ++numNames;
779
780 return numNames;
781}
782
783// Create the custom "name" section containing debug symbol names.
784void NameSection::writeBody() {
785 {
786 SubSection sub(WASM_NAMES_MODULE);
787 StringRef moduleName = config->soName;
788 if (config->soName.empty())
789 moduleName = llvm::sys::path::filename(path: config->outputFile);
790 writeStr(os&: sub.os, string: moduleName, msg: "module name");
791 sub.writeTo(to&: bodyOutputStream);
792 }
793
794 unsigned count = numNamedFunctions();
795 if (count) {
796 SubSection sub(WASM_NAMES_FUNCTION);
797 writeUleb128(os&: sub.os, number: count, msg: "name count");
798
799 // Function names appear in function index order. As it happens
800 // importedSymbols and inputFunctions are numbered in order with imported
801 // functions coming first.
802 for (const Symbol *s : out.importSec->importedSymbols) {
803 if (auto *f = dyn_cast<FunctionSymbol>(Val: s)) {
804 writeUleb128(os&: sub.os, number: f->getFunctionIndex(), msg: "func index");
805 writeStr(os&: sub.os, string: toString(sym: *s), msg: "symbol name");
806 }
807 }
808 for (const InputFunction *f : out.functionSec->inputFunctions) {
809 if (!f->name.empty()) {
810 writeUleb128(os&: sub.os, number: f->getFunctionIndex(), msg: "func index");
811 if (!f->debugName.empty()) {
812 writeStr(os&: sub.os, string: f->debugName, msg: "symbol name");
813 } else {
814 writeStr(os&: sub.os, string: maybeDemangleSymbol(name: f->name), msg: "symbol name");
815 }
816 }
817 }
818 sub.writeTo(to&: bodyOutputStream);
819 }
820
821 count = numNamedGlobals();
822 if (count) {
823 SubSection sub(WASM_NAMES_GLOBAL);
824 writeUleb128(os&: sub.os, number: count, msg: "name count");
825
826 for (const Symbol *s : out.importSec->importedSymbols) {
827 if (auto *g = dyn_cast<GlobalSymbol>(Val: s)) {
828 writeUleb128(os&: sub.os, number: g->getGlobalIndex(), msg: "global index");
829 writeStr(os&: sub.os, string: toString(sym: *s), msg: "symbol name");
830 }
831 }
832 for (const Symbol *s : out.importSec->gotSymbols) {
833 writeUleb128(os&: sub.os, number: s->getGOTIndex(), msg: "global index");
834 writeStr(os&: sub.os, string: toString(sym: *s), msg: "symbol name");
835 }
836 for (const InputGlobal *g : out.globalSec->inputGlobals) {
837 if (!g->getName().empty()) {
838 writeUleb128(os&: sub.os, number: g->getAssignedIndex(), msg: "global index");
839 writeStr(os&: sub.os, string: maybeDemangleSymbol(name: g->getName()), msg: "symbol name");
840 }
841 }
842 for (Symbol *s : out.globalSec->internalGotSymbols) {
843 writeUleb128(os&: sub.os, number: s->getGOTIndex(), msg: "global index");
844 if (isa<FunctionSymbol>(Val: s))
845 writeStr(os&: sub.os, string: "GOT.func.internal." + toString(sym: *s), msg: "symbol name");
846 else
847 writeStr(os&: sub.os, string: "GOT.data.internal." + toString(sym: *s), msg: "symbol name");
848 }
849
850 sub.writeTo(to&: bodyOutputStream);
851 }
852
853 count = numNamedDataSegments();
854 if (count) {
855 SubSection sub(WASM_NAMES_DATA_SEGMENT);
856 writeUleb128(os&: sub.os, number: count, msg: "name count");
857
858 for (OutputSegment *s : segments) {
859 if (!s->name.empty() && s->requiredInBinary()) {
860 writeUleb128(os&: sub.os, number: s->index, msg: "global index");
861 writeStr(os&: sub.os, string: s->name, msg: "segment name");
862 }
863 }
864
865 sub.writeTo(to&: bodyOutputStream);
866 }
867}
868
869void ProducersSection::addInfo(const WasmProducerInfo &info) {
870 for (auto &producers :
871 {std::make_pair(x: &info.Languages, y: &languages),
872 std::make_pair(x: &info.Tools, y: &tools), std::make_pair(x: &info.SDKs, y: &sDKs)})
873 for (auto &producer : *producers.first)
874 if (llvm::none_of(Range&: *producers.second,
875 P: [&](std::pair<std::string, std::string> seen) {
876 return seen.first == producer.first;
877 }))
878 producers.second->push_back(Elt: producer);
879}
880
881void ProducersSection::writeBody() {
882 auto &os = bodyOutputStream;
883 writeUleb128(os, number: fieldCount(), msg: "field count");
884 for (auto &field :
885 {std::make_pair(x: "language", y&: languages),
886 std::make_pair(x: "processed-by", y&: tools), std::make_pair(x: "sdk", y&: sDKs)}) {
887 if (field.second.empty())
888 continue;
889 writeStr(os, string: field.first, msg: "field name");
890 writeUleb128(os, number: field.second.size(), msg: "number of entries");
891 for (auto &entry : field.second) {
892 writeStr(os, string: entry.first, msg: "producer name");
893 writeStr(os, string: entry.second, msg: "producer version");
894 }
895 }
896}
897
898void TargetFeaturesSection::writeBody() {
899 SmallVector<std::string, 8> emitted(features.begin(), features.end());
900 llvm::sort(C&: emitted);
901 auto &os = bodyOutputStream;
902 writeUleb128(os, number: emitted.size(), msg: "feature count");
903 for (auto &feature : emitted) {
904 writeU8(os, byte: WASM_FEATURE_PREFIX_USED, msg: "feature used prefix");
905 writeStr(os, string: feature, msg: "feature name");
906 }
907}
908
909void RelocSection::writeBody() {
910 uint32_t count = sec->getNumRelocations();
911 assert(sec->sectionIndex != UINT32_MAX);
912 writeUleb128(os&: bodyOutputStream, number: sec->sectionIndex, msg: "reloc section");
913 writeUleb128(os&: bodyOutputStream, number: count, msg: "reloc count");
914 sec->writeRelocations(os&: bodyOutputStream);
915}
916
917static size_t getHashSize() {
918 switch (config->buildId) {
919 case BuildIdKind::Fast:
920 case BuildIdKind::Uuid:
921 return 16;
922 case BuildIdKind::Sha1:
923 return 20;
924 case BuildIdKind::Hexstring:
925 return config->buildIdVector.size();
926 case BuildIdKind::None:
927 return 0;
928 }
929 llvm_unreachable("build id kind not implemented");
930}
931
932BuildIdSection::BuildIdSection()
933 : SyntheticSection(llvm::wasm::WASM_SEC_CUSTOM, buildIdSectionName),
934 hashSize(getHashSize()) {}
935
936void BuildIdSection::writeBody() {
937 LLVM_DEBUG(llvm::dbgs() << "BuildId writebody\n");
938 // Write hash size
939 auto &os = bodyOutputStream;
940 writeUleb128(os, number: hashSize, msg: "build id size");
941 writeBytes(os, bytes: std::vector<char>(hashSize, ' ').data(), count: hashSize,
942 msg: "placeholder");
943}
944
945void BuildIdSection::writeBuildId(llvm::ArrayRef<uint8_t> buf) {
946 assert(buf.size() == hashSize);
947 LLVM_DEBUG(dbgs() << "buildid write " << buf.size() << " "
948 << hashPlaceholderPtr << '\n');
949 memcpy(dest: hashPlaceholderPtr, src: buf.data(), n: hashSize);
950}
951
952} // namespace wasm::lld
953