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