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