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