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