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