[SandboxIR] Avoid repeated hash lookups (NFC) (#125337)
[llvm-project.git] / lld / wasm / SyntheticSections.cpp
blob7fb44b9f0c00913e0af9351dc023e0f0e2eb431a
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.
11 //===----------------------------------------------------------------------===//
13 #include "SyntheticSections.h"
15 #include "InputChunks.h"
16 #include "InputElement.h"
17 #include "OutputSegment.h"
18 #include "SymbolTable.h"
19 #include "llvm/Support/Path.h"
20 #include <optional>
22 using namespace llvm;
23 using namespace llvm::wasm;
25 namespace lld::wasm {
27 OutStruct out;
29 namespace {
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) {}
40 void writeTo(raw_ostream &to) {
41 writeUleb128(to, type, "subsection type");
42 writeUleb128(to, body.size(), "subsection size");
43 to.write(body.data(), body.size());
46 private:
47 uint32_t type;
48 std::string body;
50 public:
51 raw_string_ostream os{body};
54 } // namespace
56 bool DylinkSection::isNeeded() const {
57 return ctx.isPic ||
58 ctx.arg.unresolvedSymbols == UnresolvedPolicy::ImportDynamic ||
59 !ctx.sharedFiles.empty();
62 void DylinkSection::writeBody() {
63 raw_ostream &os = bodyOutputStream;
66 SubSection sub(WASM_DYLINK_MEM_INFO);
67 writeUleb128(sub.os, memSize, "MemSize");
68 writeUleb128(sub.os, memAlign, "MemAlign");
69 writeUleb128(sub.os, out.elemSec->numEntries(), "TableSize");
70 writeUleb128(sub.os, 0, "TableAlign");
71 sub.writeTo(os);
74 if (ctx.sharedFiles.size()) {
75 SubSection sub(WASM_DYLINK_NEEDED);
76 writeUleb128(sub.os, ctx.sharedFiles.size(), "Needed");
77 for (auto *so : ctx.sharedFiles)
78 writeStr(sub.os, llvm::sys::path::filename(so->getName()), "so name");
79 sub.writeTo(os);
82 // Under certain circumstances we need to include extra information about our
83 // exports and/or imports to the dynamic linker.
84 // For exports we need to notify the linker when an export is TLS since the
85 // exported value is relative to __tls_base rather than __memory_base.
86 // For imports we need to notify the dynamic linker when an import is weak
87 // so that knows not to report an error for such symbols.
88 std::vector<const Symbol *> importInfo;
89 std::vector<const Symbol *> exportInfo;
90 for (const Symbol *sym : symtab->symbols()) {
91 if (sym->isLive()) {
92 if (sym->isExported() && sym->isTLS() && isa<DefinedData>(sym)) {
93 exportInfo.push_back(sym);
95 if (sym->isUndefWeak()) {
96 importInfo.push_back(sym);
101 if (!exportInfo.empty()) {
102 SubSection sub(WASM_DYLINK_EXPORT_INFO);
103 writeUleb128(sub.os, exportInfo.size(), "num exports");
105 for (const Symbol *sym : exportInfo) {
106 LLVM_DEBUG(llvm::dbgs() << "export info: " << toString(*sym) << "\n");
107 StringRef name = sym->getName();
108 if (auto *f = dyn_cast<DefinedFunction>(sym)) {
109 if (std::optional<StringRef> exportName =
110 f->function->getExportName()) {
111 name = *exportName;
114 writeStr(sub.os, name, "sym name");
115 writeUleb128(sub.os, sym->flags, "sym flags");
118 sub.writeTo(os);
121 if (!importInfo.empty()) {
122 SubSection sub(WASM_DYLINK_IMPORT_INFO);
123 writeUleb128(sub.os, importInfo.size(), "num imports");
125 for (const Symbol *sym : importInfo) {
126 LLVM_DEBUG(llvm::dbgs() << "imports info: " << toString(*sym) << "\n");
127 StringRef module = sym->importModule.value_or(defaultModule);
128 StringRef name = sym->importName.value_or(sym->getName());
129 writeStr(sub.os, module, "import module");
130 writeStr(sub.os, name, "import name");
131 writeUleb128(sub.os, sym->flags, "sym flags");
134 sub.writeTo(os);
138 uint32_t TypeSection::registerType(const WasmSignature &sig) {
139 auto pair = typeIndices.insert(std::make_pair(sig, types.size()));
140 if (pair.second) {
141 LLVM_DEBUG(llvm::dbgs() << "registerType " << toString(sig) << "\n");
142 types.push_back(&sig);
144 return pair.first->second;
147 uint32_t TypeSection::lookupType(const WasmSignature &sig) {
148 auto it = typeIndices.find(sig);
149 if (it == typeIndices.end()) {
150 error("type not found: " + toString(sig));
151 return 0;
153 return it->second;
156 void TypeSection::writeBody() {
157 writeUleb128(bodyOutputStream, types.size(), "type count");
158 for (const WasmSignature *sig : types)
159 writeSig(bodyOutputStream, *sig);
162 uint32_t ImportSection::getNumImports() const {
163 assert(isSealed);
164 uint32_t numImports = importedSymbols.size() + gotSymbols.size();
165 if (ctx.arg.memoryImport.has_value())
166 ++numImports;
167 return numImports;
170 void ImportSection::addGOTEntry(Symbol *sym) {
171 assert(!isSealed);
172 if (sym->hasGOTIndex())
173 return;
174 LLVM_DEBUG(dbgs() << "addGOTEntry: " << toString(*sym) << "\n");
175 sym->setGOTIndex(numImportedGlobals++);
176 if (ctx.isPic) {
177 // Any symbol that is assigned an normal GOT entry must be exported
178 // otherwise the dynamic linker won't be able create the entry that contains
179 // it.
180 sym->forceExport = true;
182 gotSymbols.push_back(sym);
185 void ImportSection::addImport(Symbol *sym) {
186 assert(!isSealed);
187 StringRef module = sym->importModule.value_or(defaultModule);
188 StringRef name = sym->importName.value_or(sym->getName());
189 if (auto *f = dyn_cast<FunctionSymbol>(sym)) {
190 ImportKey<WasmSignature> key(*(f->getSignature()), module, name);
191 auto entry = importedFunctions.try_emplace(key, numImportedFunctions);
192 if (entry.second) {
193 importedSymbols.emplace_back(sym);
194 f->setFunctionIndex(numImportedFunctions++);
195 } else {
196 f->setFunctionIndex(entry.first->second);
198 } else if (auto *g = dyn_cast<GlobalSymbol>(sym)) {
199 ImportKey<WasmGlobalType> key(*(g->getGlobalType()), module, name);
200 auto entry = importedGlobals.try_emplace(key, numImportedGlobals);
201 if (entry.second) {
202 importedSymbols.emplace_back(sym);
203 g->setGlobalIndex(numImportedGlobals++);
204 } else {
205 g->setGlobalIndex(entry.first->second);
207 } else if (auto *t = dyn_cast<TagSymbol>(sym)) {
208 ImportKey<WasmSignature> key(*(t->getSignature()), module, name);
209 auto entry = importedTags.try_emplace(key, numImportedTags);
210 if (entry.second) {
211 importedSymbols.emplace_back(sym);
212 t->setTagIndex(numImportedTags++);
213 } else {
214 t->setTagIndex(entry.first->second);
216 } else {
217 assert(TableSymbol::classof(sym));
218 auto *table = cast<TableSymbol>(sym);
219 ImportKey<WasmTableType> key(*(table->getTableType()), module, name);
220 auto entry = importedTables.try_emplace(key, numImportedTables);
221 if (entry.second) {
222 importedSymbols.emplace_back(sym);
223 table->setTableNumber(numImportedTables++);
224 } else {
225 table->setTableNumber(entry.first->second);
230 void ImportSection::writeBody() {
231 raw_ostream &os = bodyOutputStream;
233 writeUleb128(os, getNumImports(), "import count");
235 bool is64 = ctx.arg.is64.value_or(false);
237 if (ctx.arg.memoryImport) {
238 WasmImport import;
239 import.Module = ctx.arg.memoryImport->first;
240 import.Field = ctx.arg.memoryImport->second;
241 import.Kind = WASM_EXTERNAL_MEMORY;
242 import.Memory.Flags = 0;
243 import.Memory.Minimum = out.memorySec->numMemoryPages;
244 if (out.memorySec->maxMemoryPages != 0 || ctx.arg.sharedMemory) {
245 import.Memory.Flags |= WASM_LIMITS_FLAG_HAS_MAX;
246 import.Memory.Maximum = out.memorySec->maxMemoryPages;
248 if (ctx.arg.sharedMemory)
249 import.Memory.Flags |= WASM_LIMITS_FLAG_IS_SHARED;
250 if (is64)
251 import.Memory.Flags |= WASM_LIMITS_FLAG_IS_64;
252 writeImport(os, import);
255 for (const Symbol *sym : importedSymbols) {
256 WasmImport import;
257 import.Field = sym->importName.value_or(sym->getName());
258 import.Module = sym->importModule.value_or(defaultModule);
260 if (auto *functionSym = dyn_cast<FunctionSymbol>(sym)) {
261 import.Kind = WASM_EXTERNAL_FUNCTION;
262 import.SigIndex = out.typeSec->lookupType(*functionSym->signature);
263 } else if (auto *globalSym = dyn_cast<GlobalSymbol>(sym)) {
264 import.Kind = WASM_EXTERNAL_GLOBAL;
265 import.Global = *globalSym->getGlobalType();
266 } else if (auto *tagSym = dyn_cast<TagSymbol>(sym)) {
267 import.Kind = WASM_EXTERNAL_TAG;
268 import.SigIndex = out.typeSec->lookupType(*tagSym->signature);
269 } else {
270 auto *tableSym = cast<TableSymbol>(sym);
271 import.Kind = WASM_EXTERNAL_TABLE;
272 import.Table = *tableSym->getTableType();
274 writeImport(os, import);
277 for (const Symbol *sym : gotSymbols) {
278 WasmImport import;
279 import.Kind = WASM_EXTERNAL_GLOBAL;
280 auto ptrType = is64 ? WASM_TYPE_I64 : WASM_TYPE_I32;
281 import.Global = {static_cast<uint8_t>(ptrType), true};
282 if (isa<DataSymbol>(sym))
283 import.Module = "GOT.mem";
284 else
285 import.Module = "GOT.func";
286 import.Field = sym->getName();
287 writeImport(os, import);
291 void FunctionSection::writeBody() {
292 raw_ostream &os = bodyOutputStream;
294 writeUleb128(os, inputFunctions.size(), "function count");
295 for (const InputFunction *func : inputFunctions)
296 writeUleb128(os, out.typeSec->lookupType(func->signature), "sig index");
299 void FunctionSection::addFunction(InputFunction *func) {
300 if (!func->live)
301 return;
302 uint32_t functionIndex =
303 out.importSec->getNumImportedFunctions() + inputFunctions.size();
304 inputFunctions.emplace_back(func);
305 func->setFunctionIndex(functionIndex);
308 void TableSection::writeBody() {
309 raw_ostream &os = bodyOutputStream;
311 writeUleb128(os, inputTables.size(), "table count");
312 for (const InputTable *table : inputTables)
313 writeTableType(os, table->getType());
316 void TableSection::addTable(InputTable *table) {
317 if (!table->live)
318 return;
319 // Some inputs require that the indirect function table be assigned to table
320 // number 0.
321 if (ctx.legacyFunctionTable &&
322 isa<DefinedTable>(WasmSym::indirectFunctionTable) &&
323 cast<DefinedTable>(WasmSym::indirectFunctionTable)->table == table) {
324 if (out.importSec->getNumImportedTables()) {
325 // Alack! Some other input imported a table, meaning that we are unable
326 // to assign table number 0 to the indirect function table.
327 for (const auto *culprit : out.importSec->importedSymbols) {
328 if (isa<UndefinedTable>(culprit)) {
329 error("object file not built with 'reference-types' or "
330 "'call-indirect-overlong' feature conflicts with import of "
331 "table " +
332 culprit->getName() + " by file " +
333 toString(culprit->getFile()));
334 return;
337 llvm_unreachable("failed to find conflicting table import");
339 inputTables.insert(inputTables.begin(), table);
340 return;
342 inputTables.push_back(table);
345 void TableSection::assignIndexes() {
346 uint32_t tableNumber = out.importSec->getNumImportedTables();
347 for (InputTable *t : inputTables)
348 t->assignIndex(tableNumber++);
351 void MemorySection::writeBody() {
352 raw_ostream &os = bodyOutputStream;
354 bool hasMax = maxMemoryPages != 0 || ctx.arg.sharedMemory;
355 writeUleb128(os, 1, "memory count");
356 unsigned flags = 0;
357 if (hasMax)
358 flags |= WASM_LIMITS_FLAG_HAS_MAX;
359 if (ctx.arg.sharedMemory)
360 flags |= WASM_LIMITS_FLAG_IS_SHARED;
361 if (ctx.arg.is64.value_or(false))
362 flags |= WASM_LIMITS_FLAG_IS_64;
363 writeUleb128(os, flags, "memory limits flags");
364 writeUleb128(os, numMemoryPages, "initial pages");
365 if (hasMax)
366 writeUleb128(os, maxMemoryPages, "max pages");
369 void TagSection::writeBody() {
370 raw_ostream &os = bodyOutputStream;
372 writeUleb128(os, inputTags.size(), "tag count");
373 for (InputTag *t : inputTags) {
374 writeUleb128(os, 0, "tag attribute"); // Reserved "attribute" field
375 writeUleb128(os, out.typeSec->lookupType(t->signature), "sig index");
379 void TagSection::addTag(InputTag *tag) {
380 if (!tag->live)
381 return;
382 uint32_t tagIndex = out.importSec->getNumImportedTags() + inputTags.size();
383 LLVM_DEBUG(dbgs() << "addTag: " << tagIndex << "\n");
384 tag->assignIndex(tagIndex);
385 inputTags.push_back(tag);
388 void GlobalSection::assignIndexes() {
389 uint32_t globalIndex = out.importSec->getNumImportedGlobals();
390 for (InputGlobal *g : inputGlobals)
391 g->assignIndex(globalIndex++);
392 for (Symbol *sym : internalGotSymbols)
393 sym->setGOTIndex(globalIndex++);
394 isSealed = true;
397 static void ensureIndirectFunctionTable() {
398 if (!WasmSym::indirectFunctionTable)
399 WasmSym::indirectFunctionTable =
400 symtab->resolveIndirectFunctionTable(/*required =*/true);
403 void GlobalSection::addInternalGOTEntry(Symbol *sym) {
404 assert(!isSealed);
405 if (sym->requiresGOT)
406 return;
407 LLVM_DEBUG(dbgs() << "addInternalGOTEntry: " << sym->getName() << " "
408 << toString(sym->kind()) << "\n");
409 sym->requiresGOT = true;
410 if (auto *F = dyn_cast<FunctionSymbol>(sym)) {
411 ensureIndirectFunctionTable();
412 out.elemSec->addEntry(F);
414 internalGotSymbols.push_back(sym);
417 void GlobalSection::generateRelocationCode(raw_ostream &os, bool TLS) const {
418 assert(!ctx.arg.extendedConst);
419 bool is64 = ctx.arg.is64.value_or(false);
420 unsigned opcode_ptr_const = is64 ? WASM_OPCODE_I64_CONST
421 : WASM_OPCODE_I32_CONST;
422 unsigned opcode_ptr_add = is64 ? WASM_OPCODE_I64_ADD
423 : WASM_OPCODE_I32_ADD;
425 for (const Symbol *sym : internalGotSymbols) {
426 if (TLS != sym->isTLS())
427 continue;
429 if (auto *d = dyn_cast<DefinedData>(sym)) {
430 // Get __memory_base
431 writeU8(os, WASM_OPCODE_GLOBAL_GET, "GLOBAL_GET");
432 if (sym->isTLS())
433 writeUleb128(os, WasmSym::tlsBase->getGlobalIndex(), "__tls_base");
434 else
435 writeUleb128(os, WasmSym::memoryBase->getGlobalIndex(),
436 "__memory_base");
438 // Add the virtual address of the data symbol
439 writeU8(os, opcode_ptr_const, "CONST");
440 writeSleb128(os, d->getVA(), "offset");
441 } else if (auto *f = dyn_cast<FunctionSymbol>(sym)) {
442 if (f->isStub)
443 continue;
444 // Get __table_base
445 writeU8(os, WASM_OPCODE_GLOBAL_GET, "GLOBAL_GET");
446 writeUleb128(os, WasmSym::tableBase->getGlobalIndex(), "__table_base");
448 // Add the table index to __table_base
449 writeU8(os, opcode_ptr_const, "CONST");
450 writeSleb128(os, f->getTableIndex(), "offset");
451 } else {
452 assert(isa<UndefinedData>(sym) || isa<SharedData>(sym));
453 continue;
455 writeU8(os, opcode_ptr_add, "ADD");
456 writeU8(os, WASM_OPCODE_GLOBAL_SET, "GLOBAL_SET");
457 writeUleb128(os, sym->getGOTIndex(), "got_entry");
461 void GlobalSection::writeBody() {
462 raw_ostream &os = bodyOutputStream;
464 writeUleb128(os, numGlobals(), "global count");
465 for (InputGlobal *g : inputGlobals) {
466 writeGlobalType(os, g->getType());
467 writeInitExpr(os, g->getInitExpr());
469 bool is64 = ctx.arg.is64.value_or(false);
470 uint8_t itype = is64 ? WASM_TYPE_I64 : WASM_TYPE_I32;
471 for (const Symbol *sym : internalGotSymbols) {
472 bool mutable_ = false;
473 if (!sym->isStub) {
474 // In the case of dynamic linking, unless we have 'extended-const'
475 // available, these global must to be mutable since they get updated to
476 // the correct runtime value during `__wasm_apply_global_relocs`.
477 if (!ctx.arg.extendedConst && ctx.isPic && !sym->isTLS())
478 mutable_ = true;
479 // With multi-theadeding any TLS globals must be mutable since they get
480 // set during `__wasm_apply_global_tls_relocs`
481 if (ctx.arg.sharedMemory && sym->isTLS())
482 mutable_ = true;
484 WasmGlobalType type{itype, mutable_};
485 writeGlobalType(os, type);
487 bool useExtendedConst = false;
488 uint32_t globalIdx;
489 int64_t offset;
490 if (ctx.arg.extendedConst && ctx.isPic) {
491 if (auto *d = dyn_cast<DefinedData>(sym)) {
492 if (!sym->isTLS()) {
493 globalIdx = WasmSym::memoryBase->getGlobalIndex();
494 offset = d->getVA();
495 useExtendedConst = true;
497 } else if (auto *f = dyn_cast<FunctionSymbol>(sym)) {
498 if (!sym->isStub) {
499 globalIdx = WasmSym::tableBase->getGlobalIndex();
500 offset = f->getTableIndex();
501 useExtendedConst = true;
505 if (useExtendedConst) {
506 // We can use an extended init expression to add a constant
507 // offset of __memory_base/__table_base.
508 writeU8(os, WASM_OPCODE_GLOBAL_GET, "global get");
509 writeUleb128(os, globalIdx, "literal (global index)");
510 if (offset) {
511 writePtrConst(os, offset, is64, "offset");
512 writeU8(os, is64 ? WASM_OPCODE_I64_ADD : WASM_OPCODE_I32_ADD, "add");
514 writeU8(os, WASM_OPCODE_END, "opcode:end");
515 } else {
516 WasmInitExpr initExpr;
517 if (auto *d = dyn_cast<DefinedData>(sym))
518 // In the sharedMemory case TLS globals are set during
519 // `__wasm_apply_global_tls_relocs`, but in the non-shared case
520 // we know the absolute value at link time.
521 initExpr = intConst(d->getVA(/*absolute=*/!ctx.arg.sharedMemory), is64);
522 else if (auto *f = dyn_cast<FunctionSymbol>(sym))
523 initExpr = intConst(f->isStub ? 0 : f->getTableIndex(), is64);
524 else {
525 assert(isa<UndefinedData>(sym) || isa<SharedData>(sym));
526 initExpr = intConst(0, is64);
528 writeInitExpr(os, initExpr);
531 for (const DefinedData *sym : dataAddressGlobals) {
532 WasmGlobalType type{itype, false};
533 writeGlobalType(os, type);
534 writeInitExpr(os, intConst(sym->getVA(), is64));
538 void GlobalSection::addGlobal(InputGlobal *global) {
539 assert(!isSealed);
540 if (!global->live)
541 return;
542 inputGlobals.push_back(global);
545 void ExportSection::writeBody() {
546 raw_ostream &os = bodyOutputStream;
548 writeUleb128(os, exports.size(), "export count");
549 for (const WasmExport &export_ : exports)
550 writeExport(os, export_);
553 bool StartSection::isNeeded() const {
554 return WasmSym::startFunction != nullptr;
557 void StartSection::writeBody() {
558 raw_ostream &os = bodyOutputStream;
559 writeUleb128(os, WasmSym::startFunction->getFunctionIndex(),
560 "function index");
563 void ElemSection::addEntry(FunctionSymbol *sym) {
564 // Don't add stub functions to the wasm table. The address of all stub
565 // functions should be zero and they should they don't appear in the table.
566 // They only exist so that the calls to missing functions can validate.
567 if (sym->hasTableIndex() || sym->isStub)
568 return;
569 sym->setTableIndex(ctx.arg.tableBase + indirectFunctions.size());
570 indirectFunctions.emplace_back(sym);
573 void ElemSection::writeBody() {
574 raw_ostream &os = bodyOutputStream;
576 assert(WasmSym::indirectFunctionTable);
577 writeUleb128(os, 1, "segment count");
578 uint32_t tableNumber = WasmSym::indirectFunctionTable->getTableNumber();
579 uint32_t flags = 0;
580 if (tableNumber)
581 flags |= WASM_ELEM_SEGMENT_HAS_TABLE_NUMBER;
582 writeUleb128(os, flags, "elem segment flags");
583 if (flags & WASM_ELEM_SEGMENT_HAS_TABLE_NUMBER)
584 writeUleb128(os, tableNumber, "table number");
586 WasmInitExpr initExpr;
587 initExpr.Extended = false;
588 if (ctx.isPic) {
589 initExpr.Inst.Opcode = WASM_OPCODE_GLOBAL_GET;
590 initExpr.Inst.Value.Global = WasmSym::tableBase->getGlobalIndex();
591 } else {
592 bool is64 = ctx.arg.is64.value_or(false);
593 initExpr = intConst(ctx.arg.tableBase, is64);
595 writeInitExpr(os, initExpr);
597 if (flags & WASM_ELEM_SEGMENT_MASK_HAS_ELEM_DESC) {
598 // We only write active function table initializers, for which the elem kind
599 // is specified to be written as 0x00 and interpreted to mean "funcref".
600 const uint8_t elemKind = 0;
601 writeU8(os, elemKind, "elem kind");
604 writeUleb128(os, indirectFunctions.size(), "elem count");
605 uint32_t tableIndex = ctx.arg.tableBase;
606 for (const FunctionSymbol *sym : indirectFunctions) {
607 assert(sym->getTableIndex() == tableIndex);
608 (void) tableIndex;
609 writeUleb128(os, sym->getFunctionIndex(), "function index");
610 ++tableIndex;
614 DataCountSection::DataCountSection(ArrayRef<OutputSegment *> segments)
615 : SyntheticSection(llvm::wasm::WASM_SEC_DATACOUNT),
616 numSegments(llvm::count_if(segments, [](OutputSegment *const segment) {
617 return segment->requiredInBinary();
618 })) {}
620 void DataCountSection::writeBody() {
621 writeUleb128(bodyOutputStream, numSegments, "data count");
624 bool DataCountSection::isNeeded() const {
625 return numSegments && ctx.arg.sharedMemory;
628 void LinkingSection::writeBody() {
629 raw_ostream &os = bodyOutputStream;
631 writeUleb128(os, WasmMetadataVersion, "Version");
633 if (!symtabEntries.empty()) {
634 SubSection sub(WASM_SYMBOL_TABLE);
635 writeUleb128(sub.os, symtabEntries.size(), "num symbols");
637 for (const Symbol *sym : symtabEntries) {
638 assert(sym->isDefined() || sym->isUndefined());
639 WasmSymbolType kind = sym->getWasmType();
640 uint32_t flags = sym->flags;
642 writeU8(sub.os, kind, "sym kind");
643 writeUleb128(sub.os, flags, "sym flags");
645 if (auto *f = dyn_cast<FunctionSymbol>(sym)) {
646 if (auto *d = dyn_cast<DefinedFunction>(sym)) {
647 writeUleb128(sub.os, d->getExportedFunctionIndex(), "index");
648 } else {
649 writeUleb128(sub.os, f->getFunctionIndex(), "index");
651 if (sym->isDefined() || (flags & WASM_SYMBOL_EXPLICIT_NAME) != 0)
652 writeStr(sub.os, sym->getName(), "sym name");
653 } else if (auto *g = dyn_cast<GlobalSymbol>(sym)) {
654 writeUleb128(sub.os, g->getGlobalIndex(), "index");
655 if (sym->isDefined() || (flags & WASM_SYMBOL_EXPLICIT_NAME) != 0)
656 writeStr(sub.os, sym->getName(), "sym name");
657 } else if (auto *t = dyn_cast<TagSymbol>(sym)) {
658 writeUleb128(sub.os, t->getTagIndex(), "index");
659 if (sym->isDefined() || (flags & WASM_SYMBOL_EXPLICIT_NAME) != 0)
660 writeStr(sub.os, sym->getName(), "sym name");
661 } else if (auto *t = dyn_cast<TableSymbol>(sym)) {
662 writeUleb128(sub.os, t->getTableNumber(), "table number");
663 if (sym->isDefined() || (flags & WASM_SYMBOL_EXPLICIT_NAME) != 0)
664 writeStr(sub.os, sym->getName(), "sym name");
665 } else if (isa<DataSymbol>(sym)) {
666 writeStr(sub.os, sym->getName(), "sym name");
667 if (auto *dataSym = dyn_cast<DefinedData>(sym)) {
668 if (dataSym->segment) {
669 writeUleb128(sub.os, dataSym->getOutputSegmentIndex(), "index");
670 writeUleb128(sub.os, dataSym->getOutputSegmentOffset(),
671 "data offset");
672 } else {
673 writeUleb128(sub.os, 0, "index");
674 writeUleb128(sub.os, dataSym->getVA(), "data offset");
676 writeUleb128(sub.os, dataSym->getSize(), "data size");
678 } else {
679 auto *s = cast<OutputSectionSymbol>(sym);
680 writeUleb128(sub.os, s->section->sectionIndex, "sym section index");
684 sub.writeTo(os);
687 if (dataSegments.size()) {
688 SubSection sub(WASM_SEGMENT_INFO);
689 writeUleb128(sub.os, dataSegments.size(), "num data segments");
690 for (const OutputSegment *s : dataSegments) {
691 writeStr(sub.os, s->name, "segment name");
692 writeUleb128(sub.os, s->alignment, "alignment");
693 writeUleb128(sub.os, s->linkingFlags, "flags");
695 sub.writeTo(os);
698 if (!initFunctions.empty()) {
699 SubSection sub(WASM_INIT_FUNCS);
700 writeUleb128(sub.os, initFunctions.size(), "num init functions");
701 for (const WasmInitEntry &f : initFunctions) {
702 writeUleb128(sub.os, f.priority, "priority");
703 writeUleb128(sub.os, f.sym->getOutputSymbolIndex(), "function index");
705 sub.writeTo(os);
708 struct ComdatEntry {
709 unsigned kind;
710 uint32_t index;
712 std::map<StringRef, std::vector<ComdatEntry>> comdats;
714 for (const InputFunction *f : out.functionSec->inputFunctions) {
715 StringRef comdat = f->getComdatName();
716 if (!comdat.empty())
717 comdats[comdat].emplace_back(
718 ComdatEntry{WASM_COMDAT_FUNCTION, f->getFunctionIndex()});
720 for (uint32_t i = 0; i < dataSegments.size(); ++i) {
721 const auto &inputSegments = dataSegments[i]->inputSegments;
722 if (inputSegments.empty())
723 continue;
724 StringRef comdat = inputSegments[0]->getComdatName();
725 #ifndef NDEBUG
726 for (const InputChunk *isec : inputSegments)
727 assert(isec->getComdatName() == comdat);
728 #endif
729 if (!comdat.empty())
730 comdats[comdat].emplace_back(ComdatEntry{WASM_COMDAT_DATA, i});
733 if (!comdats.empty()) {
734 SubSection sub(WASM_COMDAT_INFO);
735 writeUleb128(sub.os, comdats.size(), "num comdats");
736 for (const auto &c : comdats) {
737 writeStr(sub.os, c.first, "comdat name");
738 writeUleb128(sub.os, 0, "comdat flags"); // flags for future use
739 writeUleb128(sub.os, c.second.size(), "num entries");
740 for (const ComdatEntry &entry : c.second) {
741 writeU8(sub.os, entry.kind, "entry kind");
742 writeUleb128(sub.os, entry.index, "entry index");
745 sub.writeTo(os);
749 void LinkingSection::addToSymtab(Symbol *sym) {
750 sym->setOutputSymbolIndex(symtabEntries.size());
751 symtabEntries.emplace_back(sym);
754 unsigned NameSection::numNamedFunctions() const {
755 unsigned numNames = out.importSec->getNumImportedFunctions();
757 for (const InputFunction *f : out.functionSec->inputFunctions)
758 if (!f->name.empty() || !f->debugName.empty())
759 ++numNames;
761 return numNames;
764 unsigned NameSection::numNamedGlobals() const {
765 unsigned numNames = out.importSec->getNumImportedGlobals();
767 for (const InputGlobal *g : out.globalSec->inputGlobals)
768 if (!g->getName().empty())
769 ++numNames;
771 numNames += out.globalSec->internalGotSymbols.size();
772 return numNames;
775 unsigned NameSection::numNamedDataSegments() const {
776 unsigned numNames = 0;
778 for (const OutputSegment *s : segments)
779 if (!s->name.empty() && s->requiredInBinary())
780 ++numNames;
782 return numNames;
785 // Create the custom "name" section containing debug symbol names.
786 void NameSection::writeBody() {
788 SubSection sub(WASM_NAMES_MODULE);
789 StringRef moduleName = ctx.arg.soName;
790 if (ctx.arg.soName.empty())
791 moduleName = llvm::sys::path::filename(ctx.arg.outputFile);
792 writeStr(sub.os, moduleName, "module name");
793 sub.writeTo(bodyOutputStream);
796 unsigned count = numNamedFunctions();
797 if (count) {
798 SubSection sub(WASM_NAMES_FUNCTION);
799 writeUleb128(sub.os, count, "name count");
801 // Function names appear in function index order. As it happens
802 // importedSymbols and inputFunctions are numbered in order with imported
803 // functions coming first.
804 for (const Symbol *s : out.importSec->importedSymbols) {
805 if (auto *f = dyn_cast<FunctionSymbol>(s)) {
806 writeUleb128(sub.os, f->getFunctionIndex(), "func index");
807 writeStr(sub.os, toString(*s), "symbol name");
810 for (const InputFunction *f : out.functionSec->inputFunctions) {
811 if (!f->name.empty()) {
812 writeUleb128(sub.os, f->getFunctionIndex(), "func index");
813 if (!f->debugName.empty()) {
814 writeStr(sub.os, f->debugName, "symbol name");
815 } else {
816 writeStr(sub.os, maybeDemangleSymbol(f->name), "symbol name");
820 sub.writeTo(bodyOutputStream);
823 count = numNamedGlobals();
824 if (count) {
825 SubSection sub(WASM_NAMES_GLOBAL);
826 writeUleb128(sub.os, count, "name count");
828 for (const Symbol *s : out.importSec->importedSymbols) {
829 if (auto *g = dyn_cast<GlobalSymbol>(s)) {
830 writeUleb128(sub.os, g->getGlobalIndex(), "global index");
831 writeStr(sub.os, toString(*s), "symbol name");
834 for (const Symbol *s : out.importSec->gotSymbols) {
835 writeUleb128(sub.os, s->getGOTIndex(), "global index");
836 writeStr(sub.os, toString(*s), "symbol name");
838 for (const InputGlobal *g : out.globalSec->inputGlobals) {
839 if (!g->getName().empty()) {
840 writeUleb128(sub.os, g->getAssignedIndex(), "global index");
841 writeStr(sub.os, maybeDemangleSymbol(g->getName()), "symbol name");
844 for (Symbol *s : out.globalSec->internalGotSymbols) {
845 writeUleb128(sub.os, s->getGOTIndex(), "global index");
846 if (isa<FunctionSymbol>(s))
847 writeStr(sub.os, "GOT.func.internal." + toString(*s), "symbol name");
848 else
849 writeStr(sub.os, "GOT.data.internal." + toString(*s), "symbol name");
852 sub.writeTo(bodyOutputStream);
855 count = numNamedDataSegments();
856 if (count) {
857 SubSection sub(WASM_NAMES_DATA_SEGMENT);
858 writeUleb128(sub.os, count, "name count");
860 for (OutputSegment *s : segments) {
861 if (!s->name.empty() && s->requiredInBinary()) {
862 writeUleb128(sub.os, s->index, "global index");
863 writeStr(sub.os, s->name, "segment name");
867 sub.writeTo(bodyOutputStream);
871 void ProducersSection::addInfo(const WasmProducerInfo &info) {
872 for (auto &producers :
873 {std::make_pair(&info.Languages, &languages),
874 std::make_pair(&info.Tools, &tools), std::make_pair(&info.SDKs, &sDKs)})
875 for (auto &producer : *producers.first)
876 if (llvm::none_of(*producers.second,
877 [&](std::pair<std::string, std::string> seen) {
878 return seen.first == producer.first;
880 producers.second->push_back(producer);
883 void ProducersSection::writeBody() {
884 auto &os = bodyOutputStream;
885 writeUleb128(os, fieldCount(), "field count");
886 for (auto &field :
887 {std::make_pair("language", languages),
888 std::make_pair("processed-by", tools), std::make_pair("sdk", sDKs)}) {
889 if (field.second.empty())
890 continue;
891 writeStr(os, field.first, "field name");
892 writeUleb128(os, field.second.size(), "number of entries");
893 for (auto &entry : field.second) {
894 writeStr(os, entry.first, "producer name");
895 writeStr(os, entry.second, "producer version");
900 void TargetFeaturesSection::writeBody() {
901 SmallVector<std::string, 8> emitted(features.begin(), features.end());
902 llvm::sort(emitted);
903 auto &os = bodyOutputStream;
904 writeUleb128(os, emitted.size(), "feature count");
905 for (auto &feature : emitted) {
906 writeU8(os, WASM_FEATURE_PREFIX_USED, "feature used prefix");
907 writeStr(os, feature, "feature name");
911 void RelocSection::writeBody() {
912 uint32_t count = sec->getNumRelocations();
913 assert(sec->sectionIndex != UINT32_MAX);
914 writeUleb128(bodyOutputStream, sec->sectionIndex, "reloc section");
915 writeUleb128(bodyOutputStream, count, "reloc count");
916 sec->writeRelocations(bodyOutputStream);
919 static size_t getHashSize() {
920 switch (ctx.arg.buildId) {
921 case BuildIdKind::Fast:
922 case BuildIdKind::Uuid:
923 return 16;
924 case BuildIdKind::Sha1:
925 return 20;
926 case BuildIdKind::Hexstring:
927 return ctx.arg.buildIdVector.size();
928 case BuildIdKind::None:
929 return 0;
931 llvm_unreachable("build id kind not implemented");
934 BuildIdSection::BuildIdSection()
935 : SyntheticSection(llvm::wasm::WASM_SEC_CUSTOM, buildIdSectionName),
936 hashSize(getHashSize()) {}
938 void BuildIdSection::writeBody() {
939 LLVM_DEBUG(llvm::dbgs() << "BuildId writebody\n");
940 // Write hash size
941 auto &os = bodyOutputStream;
942 writeUleb128(os, hashSize, "build id size");
943 writeBytes(os, std::vector<char>(hashSize, ' ').data(), hashSize,
944 "placeholder");
947 void BuildIdSection::writeBuildId(llvm::ArrayRef<uint8_t> buf) {
948 assert(buf.size() == hashSize);
949 LLVM_DEBUG(dbgs() << "buildid write " << buf.size() << " "
950 << hashPlaceholderPtr << '\n');
951 memcpy(hashPlaceholderPtr, buf.data(), hashSize);
954 } // namespace wasm::lld