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