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