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