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:
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
writeBody()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
registerType(const WasmSignature & sig)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
lookupType(const WasmSignature & sig)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
writeBody()88 void TypeSection::writeBody() {
89 writeUleb128(bodyOutputStream, types.size(), "type count");
90 for (const WasmSignature *sig : types)
91 writeSig(bodyOutputStream, *sig);
92 }
93
getNumImports() const94 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
addGOTEntry(Symbol * sym)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
addImport(Symbol * sym)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
writeBody()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
writeBody()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
addFunction(InputFunction * func)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
writeBody()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
writeBody()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
writeBody()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
addEvent(InputEvent * event)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
assignIndexes()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
addInternalGOTEntry(Symbol * sym)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
generateRelocationCode(raw_ostream & os) const288 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 if (f->isStub)
307 continue;
308 // Get __table_base
309 writeU8(os, WASM_OPCODE_GLOBAL_GET, "GLOBAL_GET");
310 writeUleb128(os, WasmSym::tableBase->getGlobalIndex(), "__table_base");
311
312 // Add the table index to __table_base
313 writeU8(os, opcode_ptr_const, "CONST");
314 writeSleb128(os, f->getTableIndex(), "offset");
315 } else {
316 assert(isa<UndefinedData>(sym));
317 continue;
318 }
319 writeU8(os, opcode_ptr_add, "ADD");
320 writeU8(os, WASM_OPCODE_GLOBAL_SET, "GLOBAL_SET");
321 writeUleb128(os, sym->getGOTIndex(), "got_entry");
322 }
323 }
324
writeBody()325 void GlobalSection::writeBody() {
326 raw_ostream &os = bodyOutputStream;
327
328 writeUleb128(os, numGlobals(), "global count");
329 for (InputGlobal *g : inputGlobals)
330 writeGlobal(os, g->global);
331 // TODO(wvo): when do these need I64_CONST?
332 for (const Symbol *sym : internalGotSymbols) {
333 WasmGlobal global;
334 // In the case of dynamic linking, internal GOT entries
335 // need to be mutable since they get updated to the correct
336 // runtime value during `__wasm_apply_relocs`.
337 bool mutable_ = config->isPic & !sym->isStub;
338 global.Type = {WASM_TYPE_I32, mutable_};
339 global.InitExpr.Opcode = WASM_OPCODE_I32_CONST;
340 if (auto *d = dyn_cast<DefinedData>(sym))
341 global.InitExpr.Value.Int32 = d->getVirtualAddress();
342 else if (auto *f = dyn_cast<FunctionSymbol>(sym))
343 global.InitExpr.Value.Int32 = f->isStub ? 0 : f->getTableIndex();
344 else {
345 assert(isa<UndefinedData>(sym));
346 global.InitExpr.Value.Int32 = 0;
347 }
348 writeGlobal(os, global);
349 }
350 for (const DefinedData *sym : dataAddressGlobals) {
351 WasmGlobal global;
352 global.Type = {WASM_TYPE_I32, false};
353 global.InitExpr.Opcode = WASM_OPCODE_I32_CONST;
354 global.InitExpr.Value.Int32 = sym->getVirtualAddress();
355 writeGlobal(os, global);
356 }
357 }
358
addGlobal(InputGlobal * global)359 void GlobalSection::addGlobal(InputGlobal *global) {
360 assert(!isSealed);
361 if (!global->live)
362 return;
363 inputGlobals.push_back(global);
364 }
365
writeBody()366 void ExportSection::writeBody() {
367 raw_ostream &os = bodyOutputStream;
368
369 writeUleb128(os, exports.size(), "export count");
370 for (const WasmExport &export_ : exports)
371 writeExport(os, export_);
372 }
373
isNeeded() const374 bool StartSection::isNeeded() const {
375 return WasmSym::initMemory != nullptr;
376 }
377
writeBody()378 void StartSection::writeBody() {
379 raw_ostream &os = bodyOutputStream;
380 writeUleb128(os, WasmSym::initMemory->getFunctionIndex(), "function index");
381 }
382
addEntry(FunctionSymbol * sym)383 void ElemSection::addEntry(FunctionSymbol *sym) {
384 // Don't add stub functions to the wasm table. The address of all stub
385 // functions should be zero and they should they don't appear in the table.
386 // They only exist so that the calls to missing functions can validate.
387 if (sym->hasTableIndex() || sym->isStub)
388 return;
389 sym->setTableIndex(config->tableBase + indirectFunctions.size());
390 indirectFunctions.emplace_back(sym);
391 }
392
writeBody()393 void ElemSection::writeBody() {
394 raw_ostream &os = bodyOutputStream;
395
396 writeUleb128(os, 1, "segment count");
397 writeUleb128(os, 0, "table index");
398 WasmInitExpr initExpr;
399 if (config->isPic) {
400 initExpr.Opcode = WASM_OPCODE_GLOBAL_GET;
401 initExpr.Value.Global = WasmSym::tableBase->getGlobalIndex();
402 } else {
403 initExpr.Opcode = WASM_OPCODE_I32_CONST;
404 initExpr.Value.Int32 = config->tableBase;
405 }
406 writeInitExpr(os, initExpr);
407 writeUleb128(os, indirectFunctions.size(), "elem count");
408
409 uint32_t tableIndex = config->tableBase;
410 for (const FunctionSymbol *sym : indirectFunctions) {
411 assert(sym->getTableIndex() == tableIndex);
412 writeUleb128(os, sym->getFunctionIndex(), "function index");
413 ++tableIndex;
414 }
415 }
416
DataCountSection(ArrayRef<OutputSegment * > segments)417 DataCountSection::DataCountSection(ArrayRef<OutputSegment *> segments)
418 : SyntheticSection(llvm::wasm::WASM_SEC_DATACOUNT),
419 numSegments(std::count_if(
420 segments.begin(), segments.end(),
421 [](OutputSegment *const segment) { return !segment->isBss; })) {}
422
writeBody()423 void DataCountSection::writeBody() {
424 writeUleb128(bodyOutputStream, numSegments, "data count");
425 }
426
isNeeded() const427 bool DataCountSection::isNeeded() const {
428 return numSegments && config->sharedMemory;
429 }
430
writeBody()431 void LinkingSection::writeBody() {
432 raw_ostream &os = bodyOutputStream;
433
434 writeUleb128(os, WasmMetadataVersion, "Version");
435
436 if (!symtabEntries.empty()) {
437 SubSection sub(WASM_SYMBOL_TABLE);
438 writeUleb128(sub.os, symtabEntries.size(), "num symbols");
439
440 for (const Symbol *sym : symtabEntries) {
441 assert(sym->isDefined() || sym->isUndefined());
442 WasmSymbolType kind = sym->getWasmType();
443 uint32_t flags = sym->flags;
444
445 writeU8(sub.os, kind, "sym kind");
446 writeUleb128(sub.os, flags, "sym flags");
447
448 if (auto *f = dyn_cast<FunctionSymbol>(sym)) {
449 writeUleb128(sub.os, f->getFunctionIndex(), "index");
450 if (sym->isDefined() || (flags & WASM_SYMBOL_EXPLICIT_NAME) != 0)
451 writeStr(sub.os, sym->getName(), "sym name");
452 } else if (auto *g = dyn_cast<GlobalSymbol>(sym)) {
453 writeUleb128(sub.os, g->getGlobalIndex(), "index");
454 if (sym->isDefined() || (flags & WASM_SYMBOL_EXPLICIT_NAME) != 0)
455 writeStr(sub.os, sym->getName(), "sym name");
456 } else if (auto *e = dyn_cast<EventSymbol>(sym)) {
457 writeUleb128(sub.os, e->getEventIndex(), "index");
458 if (sym->isDefined() || (flags & WASM_SYMBOL_EXPLICIT_NAME) != 0)
459 writeStr(sub.os, sym->getName(), "sym name");
460 } else if (isa<DataSymbol>(sym)) {
461 writeStr(sub.os, sym->getName(), "sym name");
462 if (auto *dataSym = dyn_cast<DefinedData>(sym)) {
463 writeUleb128(sub.os, dataSym->getOutputSegmentIndex(), "index");
464 writeUleb128(sub.os, dataSym->getOutputSegmentOffset(),
465 "data offset");
466 writeUleb128(sub.os, dataSym->getSize(), "data size");
467 }
468 } else {
469 auto *s = cast<OutputSectionSymbol>(sym);
470 writeUleb128(sub.os, s->section->sectionIndex, "sym section index");
471 }
472 }
473
474 sub.writeTo(os);
475 }
476
477 if (dataSegments.size()) {
478 SubSection sub(WASM_SEGMENT_INFO);
479 writeUleb128(sub.os, dataSegments.size(), "num data segments");
480 for (const OutputSegment *s : dataSegments) {
481 writeStr(sub.os, s->name, "segment name");
482 writeUleb128(sub.os, s->alignment, "alignment");
483 writeUleb128(sub.os, 0, "flags");
484 }
485 sub.writeTo(os);
486 }
487
488 if (!initFunctions.empty()) {
489 SubSection sub(WASM_INIT_FUNCS);
490 writeUleb128(sub.os, initFunctions.size(), "num init functions");
491 for (const WasmInitEntry &f : initFunctions) {
492 writeUleb128(sub.os, f.priority, "priority");
493 writeUleb128(sub.os, f.sym->getOutputSymbolIndex(), "function index");
494 }
495 sub.writeTo(os);
496 }
497
498 struct ComdatEntry {
499 unsigned kind;
500 uint32_t index;
501 };
502 std::map<StringRef, std::vector<ComdatEntry>> comdats;
503
504 for (const InputFunction *f : out.functionSec->inputFunctions) {
505 StringRef comdat = f->getComdatName();
506 if (!comdat.empty())
507 comdats[comdat].emplace_back(
508 ComdatEntry{WASM_COMDAT_FUNCTION, f->getFunctionIndex()});
509 }
510 for (uint32_t i = 0; i < dataSegments.size(); ++i) {
511 const auto &inputSegments = dataSegments[i]->inputSegments;
512 if (inputSegments.empty())
513 continue;
514 StringRef comdat = inputSegments[0]->getComdatName();
515 #ifndef NDEBUG
516 for (const InputSegment *isec : inputSegments)
517 assert(isec->getComdatName() == comdat);
518 #endif
519 if (!comdat.empty())
520 comdats[comdat].emplace_back(ComdatEntry{WASM_COMDAT_DATA, i});
521 }
522
523 if (!comdats.empty()) {
524 SubSection sub(WASM_COMDAT_INFO);
525 writeUleb128(sub.os, comdats.size(), "num comdats");
526 for (const auto &c : comdats) {
527 writeStr(sub.os, c.first, "comdat name");
528 writeUleb128(sub.os, 0, "comdat flags"); // flags for future use
529 writeUleb128(sub.os, c.second.size(), "num entries");
530 for (const ComdatEntry &entry : c.second) {
531 writeU8(sub.os, entry.kind, "entry kind");
532 writeUleb128(sub.os, entry.index, "entry index");
533 }
534 }
535 sub.writeTo(os);
536 }
537 }
538
addToSymtab(Symbol * sym)539 void LinkingSection::addToSymtab(Symbol *sym) {
540 sym->setOutputSymbolIndex(symtabEntries.size());
541 symtabEntries.emplace_back(sym);
542 }
543
numNamedFunctions() const544 unsigned NameSection::numNamedFunctions() const {
545 unsigned numNames = out.importSec->getNumImportedFunctions();
546
547 for (const InputFunction *f : out.functionSec->inputFunctions)
548 if (!f->getName().empty() || !f->getDebugName().empty())
549 ++numNames;
550
551 return numNames;
552 }
553
numNamedGlobals() const554 unsigned NameSection::numNamedGlobals() const {
555 unsigned numNames = out.importSec->getNumImportedGlobals();
556
557 for (const InputGlobal *g : out.globalSec->inputGlobals)
558 if (!g->getName().empty())
559 ++numNames;
560
561 numNames += out.globalSec->internalGotSymbols.size();
562 return numNames;
563 }
564
565 // Create the custom "name" section containing debug symbol names.
writeBody()566 void NameSection::writeBody() {
567 unsigned count = numNamedFunctions();
568 if (count) {
569 SubSection sub(WASM_NAMES_FUNCTION);
570 writeUleb128(sub.os, count, "name count");
571
572 // Function names appear in function index order. As it happens
573 // importedSymbols and inputFunctions are numbered in order with imported
574 // functions coming first.
575 for (const Symbol *s : out.importSec->importedSymbols) {
576 if (auto *f = dyn_cast<FunctionSymbol>(s)) {
577 writeUleb128(sub.os, f->getFunctionIndex(), "func index");
578 writeStr(sub.os, toString(*s), "symbol name");
579 }
580 }
581 for (const InputFunction *f : out.functionSec->inputFunctions) {
582 if (!f->getName().empty()) {
583 writeUleb128(sub.os, f->getFunctionIndex(), "func index");
584 if (!f->getDebugName().empty()) {
585 writeStr(sub.os, f->getDebugName(), "symbol name");
586 } else {
587 writeStr(sub.os, maybeDemangleSymbol(f->getName()), "symbol name");
588 }
589 }
590 }
591 sub.writeTo(bodyOutputStream);
592 }
593
594 count = numNamedGlobals();
595 if (count) {
596 SubSection sub(WASM_NAMES_GLOBAL);
597 writeUleb128(sub.os, count, "name count");
598
599 for (const Symbol *s : out.importSec->importedSymbols) {
600 if (auto *g = dyn_cast<GlobalSymbol>(s)) {
601 writeUleb128(sub.os, g->getGlobalIndex(), "global index");
602 writeStr(sub.os, toString(*s), "symbol name");
603 }
604 }
605 for (const Symbol *s : out.importSec->gotSymbols) {
606 writeUleb128(sub.os, s->getGOTIndex(), "global index");
607 writeStr(sub.os, toString(*s), "symbol name");
608 }
609 for (const InputGlobal *g : out.globalSec->inputGlobals) {
610 if (!g->getName().empty()) {
611 writeUleb128(sub.os, g->getGlobalIndex(), "global index");
612 writeStr(sub.os, maybeDemangleSymbol(g->getName()), "symbol name");
613 }
614 }
615 for (Symbol *s : out.globalSec->internalGotSymbols) {
616 writeUleb128(sub.os, s->getGOTIndex(), "global index");
617 writeStr(sub.os, toString(*s), "symbol name");
618 }
619
620 sub.writeTo(bodyOutputStream);
621 }
622 }
623
addInfo(const WasmProducerInfo & info)624 void ProducersSection::addInfo(const WasmProducerInfo &info) {
625 for (auto &producers :
626 {std::make_pair(&info.Languages, &languages),
627 std::make_pair(&info.Tools, &tools), std::make_pair(&info.SDKs, &sDKs)})
628 for (auto &producer : *producers.first)
629 if (producers.second->end() ==
630 llvm::find_if(*producers.second,
631 [&](std::pair<std::string, std::string> seen) {
632 return seen.first == producer.first;
633 }))
634 producers.second->push_back(producer);
635 }
636
writeBody()637 void ProducersSection::writeBody() {
638 auto &os = bodyOutputStream;
639 writeUleb128(os, fieldCount(), "field count");
640 for (auto &field :
641 {std::make_pair("language", languages),
642 std::make_pair("processed-by", tools), std::make_pair("sdk", sDKs)}) {
643 if (field.second.empty())
644 continue;
645 writeStr(os, field.first, "field name");
646 writeUleb128(os, field.second.size(), "number of entries");
647 for (auto &entry : field.second) {
648 writeStr(os, entry.first, "producer name");
649 writeStr(os, entry.second, "producer version");
650 }
651 }
652 }
653
writeBody()654 void TargetFeaturesSection::writeBody() {
655 SmallVector<std::string, 8> emitted(features.begin(), features.end());
656 llvm::sort(emitted);
657 auto &os = bodyOutputStream;
658 writeUleb128(os, emitted.size(), "feature count");
659 for (auto &feature : emitted) {
660 writeU8(os, WASM_FEATURE_PREFIX_USED, "feature used prefix");
661 writeStr(os, feature, "feature name");
662 }
663 }
664
writeBody()665 void RelocSection::writeBody() {
666 uint32_t count = sec->getNumRelocations();
667 assert(sec->sectionIndex != UINT32_MAX);
668 writeUleb128(bodyOutputStream, sec->sectionIndex, "reloc section");
669 writeUleb128(bodyOutputStream, count, "reloc count");
670 sec->writeRelocations(bodyOutputStream);
671 }
672
673 } // namespace wasm
674 } // namespace lld
675