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