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