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