966 lines · cpp
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-exception6//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/BinaryFormat/Wasm.h"20#include "llvm/Support/Path.h"21#include <optional>22 23using namespace llvm;24using namespace llvm::wasm;25 26namespace lld::wasm {27 28OutStruct out;29 30namespace {31 32// Some synthetic sections (e.g. "name" and "linking") have subsections.33// Just like the synthetic sections themselves these need to be created before34// they can be written out (since they are preceded by their length). This35// class is used to create subsections and then write them into the stream36// of the parent section.37class SubSection {38public:39 explicit SubSection(uint32_t type) : type(type) {}40 41 void writeTo(raw_ostream &to) {42 writeUleb128(to, type, "subsection type");43 writeUleb128(to, body.size(), "subsection size");44 to.write(body.data(), body.size());45 }46 47private:48 uint32_t type;49 std::string body;50 51public:52 raw_string_ostream os{body};53};54 55} // namespace56 57bool DylinkSection::isNeeded() const {58 return ctx.isPic ||59 ctx.arg.unresolvedSymbols == UnresolvedPolicy::ImportDynamic ||60 !ctx.sharedFiles.empty();61}62 63void DylinkSection::writeBody() {64 raw_ostream &os = bodyOutputStream;65 66 {67 SubSection sub(WASM_DYLINK_MEM_INFO);68 writeUleb128(sub.os, memSize, "MemSize");69 writeUleb128(sub.os, memAlign, "MemAlign");70 writeUleb128(sub.os, out.elemSec->numEntries(), "TableSize");71 writeUleb128(sub.os, 0, "TableAlign");72 sub.writeTo(os);73 }74 75 if (ctx.sharedFiles.size()) {76 SubSection sub(WASM_DYLINK_NEEDED);77 writeUleb128(sub.os, ctx.sharedFiles.size(), "Needed");78 for (auto *so : ctx.sharedFiles)79 writeStr(sub.os, llvm::sys::path::filename(so->getName()), "so name");80 sub.writeTo(os);81 }82 83 // Under certain circumstances we need to include extra information about our84 // exports and/or imports to the dynamic linker.85 // For exports we need to notify the linker when an export is TLS since the86 // exported value is relative to __tls_base rather than __memory_base.87 // For imports we need to notify the dynamic linker when an import is weak88 // so that knows not to report an error for such symbols.89 std::vector<const Symbol *> importInfo;90 std::vector<const Symbol *> exportInfo;91 for (const Symbol *sym : symtab->symbols()) {92 if (sym->isLive()) {93 if (sym->isExported() && sym->isTLS() && isa<DefinedData>(sym)) {94 exportInfo.push_back(sym);95 }96 if (sym->isUndefWeak()) {97 importInfo.push_back(sym);98 }99 }100 }101 102 if (!exportInfo.empty()) {103 SubSection sub(WASM_DYLINK_EXPORT_INFO);104 writeUleb128(sub.os, exportInfo.size(), "num exports");105 106 for (const Symbol *sym : exportInfo) {107 LLVM_DEBUG(llvm::dbgs() << "export info: " << toString(*sym) << "\n");108 StringRef name = sym->getName();109 if (auto *f = dyn_cast<DefinedFunction>(sym)) {110 if (std::optional<StringRef> exportName =111 f->function->getExportName()) {112 name = *exportName;113 }114 }115 writeStr(sub.os, name, "sym name");116 writeUleb128(sub.os, sym->flags, "sym flags");117 }118 119 sub.writeTo(os);120 }121 122 if (!importInfo.empty()) {123 SubSection sub(WASM_DYLINK_IMPORT_INFO);124 writeUleb128(sub.os, importInfo.size(), "num imports");125 126 for (const Symbol *sym : importInfo) {127 LLVM_DEBUG(llvm::dbgs() << "imports info: " << toString(*sym) << "\n");128 StringRef module = sym->importModule.value_or(defaultModule);129 StringRef name = sym->importName.value_or(sym->getName());130 writeStr(sub.os, module, "import module");131 writeStr(sub.os, name, "import name");132 writeUleb128(sub.os, sym->flags, "sym flags");133 }134 135 sub.writeTo(os);136 }137 138 if (!ctx.arg.rpath.empty()) {139 SubSection sub(WASM_DYLINK_RUNTIME_PATH);140 writeUleb128(sub.os, ctx.arg.rpath.size(), "num rpath entries");141 for (const auto ref : ctx.arg.rpath)142 writeStr(sub.os, ref, "rpath entry");143 sub.writeTo(os);144 }145}146 147uint32_t TypeSection::registerType(const WasmSignature &sig) {148 auto pair = typeIndices.insert(std::make_pair(sig, types.size()));149 if (pair.second) {150 LLVM_DEBUG(llvm::dbgs() << "registerType " << toString(sig) << "\n");151 types.push_back(&sig);152 }153 return pair.first->second;154}155 156uint32_t TypeSection::lookupType(const WasmSignature &sig) {157 auto it = typeIndices.find(sig);158 if (it == typeIndices.end()) {159 error("type not found: " + toString(sig));160 return 0;161 }162 return it->second;163}164 165void TypeSection::writeBody() {166 writeUleb128(bodyOutputStream, types.size(), "type count");167 for (const WasmSignature *sig : types)168 writeSig(bodyOutputStream, *sig);169}170 171uint32_t ImportSection::getNumImports() const {172 assert(isSealed);173 uint32_t numImports = importedSymbols.size() + gotSymbols.size();174 if (ctx.arg.memoryImport.has_value())175 ++numImports;176 return numImports;177}178 179void ImportSection::addGOTEntry(Symbol *sym) {180 assert(!isSealed);181 if (sym->hasGOTIndex())182 return;183 LLVM_DEBUG(dbgs() << "addGOTEntry: " << toString(*sym) << "\n");184 sym->setGOTIndex(numImportedGlobals++);185 if (ctx.isPic) {186 // Any symbol that is assigned an normal GOT entry must be exported187 // otherwise the dynamic linker won't be able create the entry that contains188 // it.189 sym->forceExport = true;190 }191 gotSymbols.push_back(sym);192}193 194void ImportSection::addImport(Symbol *sym) {195 assert(!isSealed);196 StringRef module = sym->importModule.value_or(defaultModule);197 StringRef name = sym->importName.value_or(sym->getName());198 if (auto *f = dyn_cast<FunctionSymbol>(sym)) {199 const WasmSignature *sig = f->getSignature();200 assert(sig && "imported functions must have a signature");201 ImportKey<WasmSignature> key(*sig, module, name);202 auto entry = importedFunctions.try_emplace(key, numImportedFunctions);203 if (entry.second) {204 importedSymbols.emplace_back(sym);205 f->setFunctionIndex(numImportedFunctions++);206 } else {207 f->setFunctionIndex(entry.first->second);208 }209 } else if (auto *g = dyn_cast<GlobalSymbol>(sym)) {210 ImportKey<WasmGlobalType> key(*(g->getGlobalType()), module, name);211 auto entry = importedGlobals.try_emplace(key, numImportedGlobals);212 if (entry.second) {213 importedSymbols.emplace_back(sym);214 g->setGlobalIndex(numImportedGlobals++);215 } else {216 g->setGlobalIndex(entry.first->second);217 }218 } else if (auto *t = dyn_cast<TagSymbol>(sym)) {219 ImportKey<WasmSignature> key(*(t->getSignature()), module, name);220 auto entry = importedTags.try_emplace(key, numImportedTags);221 if (entry.second) {222 importedSymbols.emplace_back(sym);223 t->setTagIndex(numImportedTags++);224 } else {225 t->setTagIndex(entry.first->second);226 }227 } else {228 assert(TableSymbol::classof(sym));229 auto *table = cast<TableSymbol>(sym);230 ImportKey<WasmTableType> key(*(table->getTableType()), module, name);231 auto entry = importedTables.try_emplace(key, numImportedTables);232 if (entry.second) {233 importedSymbols.emplace_back(sym);234 table->setTableNumber(numImportedTables++);235 } else {236 table->setTableNumber(entry.first->second);237 }238 }239}240 241void ImportSection::writeBody() {242 raw_ostream &os = bodyOutputStream;243 244 writeUleb128(os, getNumImports(), "import count");245 246 bool is64 = ctx.arg.is64.value_or(false);247 248 if (ctx.arg.memoryImport) {249 WasmImport import;250 import.Module = ctx.arg.memoryImport->first;251 import.Field = ctx.arg.memoryImport->second;252 import.Kind = WASM_EXTERNAL_MEMORY;253 import.Memory.Flags = 0;254 import.Memory.Minimum = out.memorySec->numMemoryPages;255 if (out.memorySec->maxMemoryPages != 0 || ctx.arg.sharedMemory) {256 import.Memory.Flags |= WASM_LIMITS_FLAG_HAS_MAX;257 import.Memory.Maximum = out.memorySec->maxMemoryPages;258 }259 if (ctx.arg.sharedMemory)260 import.Memory.Flags |= WASM_LIMITS_FLAG_IS_SHARED;261 if (is64)262 import.Memory.Flags |= WASM_LIMITS_FLAG_IS_64;263 if (ctx.arg.pageSize != WasmDefaultPageSize) {264 import.Memory.Flags |= WASM_LIMITS_FLAG_HAS_PAGE_SIZE;265 import.Memory.PageSize = ctx.arg.pageSize;266 }267 writeImport(os, import);268 }269 270 for (const Symbol *sym : importedSymbols) {271 WasmImport import;272 import.Field = sym->importName.value_or(sym->getName());273 import.Module = sym->importModule.value_or(defaultModule);274 275 if (auto *functionSym = dyn_cast<FunctionSymbol>(sym)) {276 import.Kind = WASM_EXTERNAL_FUNCTION;277 import.SigIndex = out.typeSec->lookupType(*functionSym->signature);278 } else if (auto *globalSym = dyn_cast<GlobalSymbol>(sym)) {279 import.Kind = WASM_EXTERNAL_GLOBAL;280 import.Global = *globalSym->getGlobalType();281 } else if (auto *tagSym = dyn_cast<TagSymbol>(sym)) {282 import.Kind = WASM_EXTERNAL_TAG;283 import.SigIndex = out.typeSec->lookupType(*tagSym->signature);284 } else {285 auto *tableSym = cast<TableSymbol>(sym);286 import.Kind = WASM_EXTERNAL_TABLE;287 import.Table = *tableSym->getTableType();288 }289 writeImport(os, import);290 }291 292 for (const Symbol *sym : gotSymbols) {293 WasmImport import;294 import.Kind = WASM_EXTERNAL_GLOBAL;295 auto ptrType = is64 ? WASM_TYPE_I64 : WASM_TYPE_I32;296 import.Global = {static_cast<uint8_t>(ptrType), true};297 if (isa<DataSymbol>(sym))298 import.Module = "GOT.mem";299 else300 import.Module = "GOT.func";301 import.Field = sym->getName();302 writeImport(os, import);303 }304}305 306void FunctionSection::writeBody() {307 raw_ostream &os = bodyOutputStream;308 309 writeUleb128(os, inputFunctions.size(), "function count");310 for (const InputFunction *func : inputFunctions)311 writeUleb128(os, out.typeSec->lookupType(func->signature), "sig index");312}313 314void FunctionSection::addFunction(InputFunction *func) {315 if (!func->live)316 return;317 uint32_t functionIndex =318 out.importSec->getNumImportedFunctions() + inputFunctions.size();319 inputFunctions.emplace_back(func);320 func->setFunctionIndex(functionIndex);321}322 323void TableSection::writeBody() {324 raw_ostream &os = bodyOutputStream;325 326 writeUleb128(os, inputTables.size(), "table count");327 for (const InputTable *table : inputTables)328 writeTableType(os, table->getType());329}330 331void TableSection::addTable(InputTable *table) {332 if (!table->live)333 return;334 // Some inputs require that the indirect function table be assigned to table335 // number 0.336 if (ctx.legacyFunctionTable &&337 isa<DefinedTable>(ctx.sym.indirectFunctionTable) &&338 cast<DefinedTable>(ctx.sym.indirectFunctionTable)->table == table) {339 if (out.importSec->getNumImportedTables()) {340 // Alack! Some other input imported a table, meaning that we are unable341 // to assign table number 0 to the indirect function table.342 for (const auto *culprit : out.importSec->importedSymbols) {343 if (isa<UndefinedTable>(culprit)) {344 error("object file not built with 'reference-types' or "345 "'call-indirect-overlong' feature conflicts with import of "346 "table " +347 culprit->getName() + " by file " +348 toString(culprit->getFile()));349 return;350 }351 }352 llvm_unreachable("failed to find conflicting table import");353 }354 inputTables.insert(inputTables.begin(), table);355 return;356 }357 inputTables.push_back(table);358}359 360void TableSection::assignIndexes() {361 uint32_t tableNumber = out.importSec->getNumImportedTables();362 for (InputTable *t : inputTables)363 t->assignIndex(tableNumber++);364}365 366void MemorySection::writeBody() {367 raw_ostream &os = bodyOutputStream;368 369 bool hasMax = maxMemoryPages != 0 || ctx.arg.sharedMemory;370 writeUleb128(os, 1, "memory count");371 unsigned flags = 0;372 if (hasMax)373 flags |= WASM_LIMITS_FLAG_HAS_MAX;374 if (ctx.arg.sharedMemory)375 flags |= WASM_LIMITS_FLAG_IS_SHARED;376 if (ctx.arg.is64.value_or(false))377 flags |= WASM_LIMITS_FLAG_IS_64;378 if (ctx.arg.pageSize != WasmDefaultPageSize)379 flags |= WASM_LIMITS_FLAG_HAS_PAGE_SIZE;380 writeUleb128(os, flags, "memory limits flags");381 writeUleb128(os, numMemoryPages, "initial pages");382 if (hasMax)383 writeUleb128(os, maxMemoryPages, "max pages");384 if (ctx.arg.pageSize != WasmDefaultPageSize)385 writeUleb128(os, llvm::Log2_64(ctx.arg.pageSize), "page size");386}387 388void TagSection::writeBody() {389 raw_ostream &os = bodyOutputStream;390 391 writeUleb128(os, inputTags.size(), "tag count");392 for (InputTag *t : inputTags) {393 writeUleb128(os, 0, "tag attribute"); // Reserved "attribute" field394 writeUleb128(os, out.typeSec->lookupType(t->signature), "sig index");395 }396}397 398void TagSection::addTag(InputTag *tag) {399 if (!tag->live)400 return;401 uint32_t tagIndex = out.importSec->getNumImportedTags() + inputTags.size();402 LLVM_DEBUG(dbgs() << "addTag: " << tagIndex << "\n");403 tag->assignIndex(tagIndex);404 inputTags.push_back(tag);405}406 407void GlobalSection::assignIndexes() {408 uint32_t globalIndex = out.importSec->getNumImportedGlobals();409 for (InputGlobal *g : inputGlobals)410 g->assignIndex(globalIndex++);411 for (Symbol *sym : internalGotSymbols)412 sym->setGOTIndex(globalIndex++);413 isSealed = true;414}415 416static void ensureIndirectFunctionTable() {417 if (!ctx.sym.indirectFunctionTable)418 ctx.sym.indirectFunctionTable =419 symtab->resolveIndirectFunctionTable(/*required =*/true);420}421 422void GlobalSection::addInternalGOTEntry(Symbol *sym) {423 assert(!isSealed);424 if (sym->requiresGOT)425 return;426 LLVM_DEBUG(dbgs() << "addInternalGOTEntry: " << sym->getName() << " "427 << toString(sym->kind()) << "\n");428 sym->requiresGOT = true;429 if (auto *F = dyn_cast<FunctionSymbol>(sym)) {430 ensureIndirectFunctionTable();431 out.elemSec->addEntry(F);432 }433 internalGotSymbols.push_back(sym);434}435 436void GlobalSection::generateRelocationCode(raw_ostream &os, bool TLS) const {437 assert(!ctx.arg.extendedConst);438 bool is64 = ctx.arg.is64.value_or(false);439 unsigned opcode_ptr_add = is64 ? WASM_OPCODE_I64_ADD440 : WASM_OPCODE_I32_ADD;441 442 for (const Symbol *sym : internalGotSymbols) {443 if (TLS != sym->isTLS())444 continue;445 446 if (auto *d = dyn_cast<DefinedData>(sym)) {447 // Get __memory_base448 writeU8(os, WASM_OPCODE_GLOBAL_GET, "GLOBAL_GET");449 if (sym->isTLS())450 writeUleb128(os, ctx.sym.tlsBase->getGlobalIndex(), "__tls_base");451 else452 writeUleb128(os, ctx.sym.memoryBase->getGlobalIndex(), "__memory_base");453 454 // Add the virtual address of the data symbol455 writePtrConst(os, d->getVA(), is64, "offset");456 } else if (auto *f = dyn_cast<FunctionSymbol>(sym)) {457 if (f->isStub)458 continue;459 // Get __table_base460 writeU8(os, WASM_OPCODE_GLOBAL_GET, "GLOBAL_GET");461 writeUleb128(os, ctx.sym.tableBase->getGlobalIndex(), "__table_base");462 463 // Add the table index to __table_base464 writePtrConst(os, f->getTableIndex(), is64, "offset");465 } else {466 assert(isa<UndefinedData>(sym) || isa<SharedData>(sym));467 continue;468 }469 writeU8(os, opcode_ptr_add, "ADD");470 writeU8(os, WASM_OPCODE_GLOBAL_SET, "GLOBAL_SET");471 writeUleb128(os, sym->getGOTIndex(), "got_entry");472 }473}474 475void GlobalSection::writeBody() {476 raw_ostream &os = bodyOutputStream;477 478 writeUleb128(os, numGlobals(), "global count");479 for (InputGlobal *g : inputGlobals) {480 writeGlobalType(os, g->getType());481 writeInitExpr(os, g->getInitExpr());482 }483 bool is64 = ctx.arg.is64.value_or(false);484 uint8_t itype = is64 ? WASM_TYPE_I64 : WASM_TYPE_I32;485 for (const Symbol *sym : internalGotSymbols) {486 bool mutable_ = false;487 if (!sym->isStub) {488 // In the case of dynamic linking, unless we have 'extended-const'489 // available, these global must to be mutable since they get updated to490 // the correct runtime value during `__wasm_apply_global_relocs`.491 if (!ctx.arg.extendedConst && ctx.isPic && !sym->isTLS())492 mutable_ = true;493 // With multi-theadeding any TLS globals must be mutable since they get494 // set during `__wasm_apply_global_tls_relocs`495 if (ctx.arg.sharedMemory && sym->isTLS())496 mutable_ = true;497 }498 WasmGlobalType type{itype, mutable_};499 writeGlobalType(os, type);500 501 bool useExtendedConst = false;502 uint32_t globalIdx;503 int64_t offset;504 if (ctx.arg.extendedConst && ctx.isPic) {505 if (auto *d = dyn_cast<DefinedData>(sym)) {506 if (!sym->isTLS()) {507 globalIdx = ctx.sym.memoryBase->getGlobalIndex();508 offset = d->getVA();509 useExtendedConst = true;510 }511 } else if (auto *f = dyn_cast<FunctionSymbol>(sym)) {512 if (!sym->isStub) {513 globalIdx = ctx.sym.tableBase->getGlobalIndex();514 offset = f->getTableIndex();515 useExtendedConst = true;516 }517 }518 }519 if (useExtendedConst) {520 // We can use an extended init expression to add a constant521 // offset of __memory_base/__table_base.522 writeU8(os, WASM_OPCODE_GLOBAL_GET, "global get");523 writeUleb128(os, globalIdx, "literal (global index)");524 if (offset) {525 writePtrConst(os, offset, is64, "offset");526 writeU8(os, is64 ? WASM_OPCODE_I64_ADD : WASM_OPCODE_I32_ADD, "add");527 }528 writeU8(os, WASM_OPCODE_END, "opcode:end");529 } else {530 WasmInitExpr initExpr;531 if (auto *d = dyn_cast<DefinedData>(sym))532 // In the sharedMemory case TLS globals are set during533 // `__wasm_apply_global_tls_relocs`, but in the non-shared case534 // we know the absolute value at link time.535 initExpr = intConst(d->getVA(/*absolute=*/!ctx.arg.sharedMemory), is64);536 else if (auto *f = dyn_cast<FunctionSymbol>(sym))537 initExpr = intConst(f->isStub ? 0 : f->getTableIndex(), is64);538 else {539 assert(isa<UndefinedData>(sym) || isa<SharedData>(sym));540 initExpr = intConst(0, is64);541 }542 writeInitExpr(os, initExpr);543 }544 }545 for (const DefinedData *sym : dataAddressGlobals) {546 WasmGlobalType type{itype, false};547 writeGlobalType(os, type);548 writeInitExpr(os, intConst(sym->getVA(), is64));549 }550}551 552void GlobalSection::addGlobal(InputGlobal *global) {553 assert(!isSealed);554 if (!global->live)555 return;556 inputGlobals.push_back(global);557}558 559void ExportSection::writeBody() {560 raw_ostream &os = bodyOutputStream;561 562 writeUleb128(os, exports.size(), "export count");563 for (const WasmExport &export_ : exports)564 writeExport(os, export_);565}566 567bool StartSection::isNeeded() const { return ctx.sym.startFunction != nullptr; }568 569void StartSection::writeBody() {570 raw_ostream &os = bodyOutputStream;571 writeUleb128(os, ctx.sym.startFunction->getFunctionIndex(), "function index");572}573 574void ElemSection::addEntry(FunctionSymbol *sym) {575 // Don't add stub functions to the wasm table. The address of all stub576 // functions should be zero and they should they don't appear in the table.577 // They only exist so that the calls to missing functions can validate.578 if (sym->hasTableIndex() || sym->isStub)579 return;580 sym->setTableIndex(ctx.arg.tableBase + indirectFunctions.size());581 indirectFunctions.emplace_back(sym);582}583 584void ElemSection::writeBody() {585 raw_ostream &os = bodyOutputStream;586 587 assert(ctx.sym.indirectFunctionTable);588 writeUleb128(os, 1, "segment count");589 uint32_t tableNumber = ctx.sym.indirectFunctionTable->getTableNumber();590 uint32_t flags = 0;591 if (tableNumber)592 flags |= WASM_ELEM_SEGMENT_HAS_TABLE_NUMBER;593 writeUleb128(os, flags, "elem segment flags");594 if (flags & WASM_ELEM_SEGMENT_HAS_TABLE_NUMBER)595 writeUleb128(os, tableNumber, "table number");596 597 WasmInitExpr initExpr;598 initExpr.Extended = false;599 if (ctx.isPic) {600 initExpr.Inst.Opcode = WASM_OPCODE_GLOBAL_GET;601 initExpr.Inst.Value.Global = ctx.sym.tableBase->getGlobalIndex();602 } else {603 bool is64 = ctx.arg.is64.value_or(false);604 initExpr = intConst(ctx.arg.tableBase, is64);605 }606 writeInitExpr(os, initExpr);607 608 if (flags & WASM_ELEM_SEGMENT_MASK_HAS_ELEM_DESC) {609 // We only write active function table initializers, for which the elem kind610 // is specified to be written as 0x00 and interpreted to mean "funcref".611 const uint8_t elemKind = 0;612 writeU8(os, elemKind, "elem kind");613 }614 615 writeUleb128(os, indirectFunctions.size(), "elem count");616 uint32_t tableIndex = ctx.arg.tableBase;617 for (const FunctionSymbol *sym : indirectFunctions) {618 assert(sym->getTableIndex() == tableIndex);619 (void) tableIndex;620 writeUleb128(os, sym->getFunctionIndex(), "function index");621 ++tableIndex;622 }623}624 625DataCountSection::DataCountSection(ArrayRef<OutputSegment *> segments)626 : SyntheticSection(llvm::wasm::WASM_SEC_DATACOUNT),627 numSegments(llvm::count_if(segments, [](OutputSegment *const segment) {628 return segment->requiredInBinary();629 })) {}630 631void DataCountSection::writeBody() {632 writeUleb128(bodyOutputStream, numSegments, "data count");633}634 635bool DataCountSection::isNeeded() const {636 return numSegments && ctx.arg.sharedMemory;637}638 639void LinkingSection::writeBody() {640 raw_ostream &os = bodyOutputStream;641 642 writeUleb128(os, WasmMetadataVersion, "Version");643 644 if (!symtabEntries.empty()) {645 SubSection sub(WASM_SYMBOL_TABLE);646 writeUleb128(sub.os, symtabEntries.size(), "num symbols");647 648 for (const Symbol *sym : symtabEntries) {649 assert(sym->isDefined() || sym->isUndefined());650 WasmSymbolType kind = sym->getWasmType();651 uint32_t flags = sym->flags;652 653 writeU8(sub.os, kind, "sym kind");654 writeUleb128(sub.os, flags, "sym flags");655 656 if (auto *f = dyn_cast<FunctionSymbol>(sym)) {657 if (auto *d = dyn_cast<DefinedFunction>(sym)) {658 writeUleb128(sub.os, d->getExportedFunctionIndex(), "index");659 } else {660 writeUleb128(sub.os, f->getFunctionIndex(), "index");661 }662 if (sym->isDefined() || (flags & WASM_SYMBOL_EXPLICIT_NAME) != 0)663 writeStr(sub.os, sym->getName(), "sym name");664 } else if (auto *g = dyn_cast<GlobalSymbol>(sym)) {665 writeUleb128(sub.os, g->getGlobalIndex(), "index");666 if (sym->isDefined() || (flags & WASM_SYMBOL_EXPLICIT_NAME) != 0)667 writeStr(sub.os, sym->getName(), "sym name");668 } else if (auto *t = dyn_cast<TagSymbol>(sym)) {669 writeUleb128(sub.os, t->getTagIndex(), "index");670 if (sym->isDefined() || (flags & WASM_SYMBOL_EXPLICIT_NAME) != 0)671 writeStr(sub.os, sym->getName(), "sym name");672 } else if (auto *t = dyn_cast<TableSymbol>(sym)) {673 writeUleb128(sub.os, t->getTableNumber(), "table number");674 if (sym->isDefined() || (flags & WASM_SYMBOL_EXPLICIT_NAME) != 0)675 writeStr(sub.os, sym->getName(), "sym name");676 } else if (isa<DataSymbol>(sym)) {677 writeStr(sub.os, sym->getName(), "sym name");678 if (auto *dataSym = dyn_cast<DefinedData>(sym)) {679 if (dataSym->segment) {680 writeUleb128(sub.os, dataSym->getOutputSegmentIndex(), "index");681 writeUleb128(sub.os, dataSym->getOutputSegmentOffset(),682 "data offset");683 } else {684 writeUleb128(sub.os, 0, "index");685 writeUleb128(sub.os, dataSym->getVA(), "data offset");686 }687 writeUleb128(sub.os, dataSym->getSize(), "data size");688 }689 } else {690 auto *s = cast<OutputSectionSymbol>(sym);691 writeUleb128(sub.os, s->section->sectionIndex, "sym section index");692 }693 }694 695 sub.writeTo(os);696 }697 698 if (dataSegments.size()) {699 SubSection sub(WASM_SEGMENT_INFO);700 writeUleb128(sub.os, dataSegments.size(), "num data segments");701 for (const OutputSegment *s : dataSegments) {702 writeStr(sub.os, s->name, "segment name");703 writeUleb128(sub.os, s->alignment, "alignment");704 writeUleb128(sub.os, s->linkingFlags, "flags");705 }706 sub.writeTo(os);707 }708 709 if (!initFunctions.empty()) {710 SubSection sub(WASM_INIT_FUNCS);711 writeUleb128(sub.os, initFunctions.size(), "num init functions");712 for (const WasmInitEntry &f : initFunctions) {713 writeUleb128(sub.os, f.priority, "priority");714 writeUleb128(sub.os, f.sym->getOutputSymbolIndex(), "function index");715 }716 sub.writeTo(os);717 }718 719 struct ComdatEntry {720 unsigned kind;721 uint32_t index;722 };723 std::map<StringRef, std::vector<ComdatEntry>> comdats;724 725 for (const InputFunction *f : out.functionSec->inputFunctions) {726 StringRef comdat = f->getComdatName();727 if (!comdat.empty())728 comdats[comdat].emplace_back(729 ComdatEntry{WASM_COMDAT_FUNCTION, f->getFunctionIndex()});730 }731 for (uint32_t i = 0; i < dataSegments.size(); ++i) {732 const auto &inputSegments = dataSegments[i]->inputSegments;733 if (inputSegments.empty())734 continue;735 StringRef comdat = inputSegments[0]->getComdatName();736#ifndef NDEBUG737 for (const InputChunk *isec : inputSegments)738 assert(isec->getComdatName() == comdat);739#endif740 if (!comdat.empty())741 comdats[comdat].emplace_back(ComdatEntry{WASM_COMDAT_DATA, i});742 }743 744 if (!comdats.empty()) {745 SubSection sub(WASM_COMDAT_INFO);746 writeUleb128(sub.os, comdats.size(), "num comdats");747 for (const auto &c : comdats) {748 writeStr(sub.os, c.first, "comdat name");749 writeUleb128(sub.os, 0, "comdat flags"); // flags for future use750 writeUleb128(sub.os, c.second.size(), "num entries");751 for (const ComdatEntry &entry : c.second) {752 writeU8(sub.os, entry.kind, "entry kind");753 writeUleb128(sub.os, entry.index, "entry index");754 }755 }756 sub.writeTo(os);757 }758}759 760void LinkingSection::addToSymtab(Symbol *sym) {761 sym->setOutputSymbolIndex(symtabEntries.size());762 symtabEntries.emplace_back(sym);763}764 765unsigned NameSection::numNamedFunctions() const {766 unsigned numNames = out.importSec->getNumImportedFunctions();767 768 for (const InputFunction *f : out.functionSec->inputFunctions)769 if (!f->name.empty() || !f->debugName.empty())770 ++numNames;771 772 return numNames;773}774 775unsigned NameSection::numNamedGlobals() const {776 unsigned numNames = out.importSec->getNumImportedGlobals();777 778 for (const InputGlobal *g : out.globalSec->inputGlobals)779 if (!g->getName().empty())780 ++numNames;781 782 numNames += out.globalSec->internalGotSymbols.size();783 return numNames;784}785 786unsigned NameSection::numNamedDataSegments() const {787 unsigned numNames = 0;788 789 for (const OutputSegment *s : segments)790 if (!s->name.empty() && s->requiredInBinary())791 ++numNames;792 793 return numNames;794}795 796// Create the custom "name" section containing debug symbol names.797void NameSection::writeBody() {798 {799 SubSection sub(WASM_NAMES_MODULE);800 StringRef moduleName = ctx.arg.soName;801 if (ctx.arg.soName.empty())802 moduleName = llvm::sys::path::filename(ctx.arg.outputFile);803 writeStr(sub.os, moduleName, "module name");804 sub.writeTo(bodyOutputStream);805 }806 807 unsigned count = numNamedFunctions();808 if (count) {809 SubSection sub(WASM_NAMES_FUNCTION);810 writeUleb128(sub.os, count, "name count");811 812 // Function names appear in function index order. As it happens813 // importedSymbols and inputFunctions are numbered in order with imported814 // functions coming first.815 for (const Symbol *s : out.importSec->importedSymbols) {816 if (auto *f = dyn_cast<FunctionSymbol>(s)) {817 writeUleb128(sub.os, f->getFunctionIndex(), "func index");818 writeStr(sub.os, toString(*s), "symbol name");819 }820 }821 for (const InputFunction *f : out.functionSec->inputFunctions) {822 if (!f->name.empty()) {823 writeUleb128(sub.os, f->getFunctionIndex(), "func index");824 if (!f->debugName.empty()) {825 writeStr(sub.os, f->debugName, "symbol name");826 } else {827 writeStr(sub.os, maybeDemangleSymbol(f->name), "symbol name");828 }829 }830 }831 sub.writeTo(bodyOutputStream);832 }833 834 count = numNamedGlobals();835 if (count) {836 SubSection sub(WASM_NAMES_GLOBAL);837 writeUleb128(sub.os, count, "name count");838 839 for (const Symbol *s : out.importSec->importedSymbols) {840 if (auto *g = dyn_cast<GlobalSymbol>(s)) {841 writeUleb128(sub.os, g->getGlobalIndex(), "global index");842 writeStr(sub.os, toString(*s), "symbol name");843 }844 }845 for (const Symbol *s : out.importSec->gotSymbols) {846 writeUleb128(sub.os, s->getGOTIndex(), "global index");847 writeStr(sub.os, toString(*s), "symbol name");848 }849 for (const InputGlobal *g : out.globalSec->inputGlobals) {850 if (!g->getName().empty()) {851 writeUleb128(sub.os, g->getAssignedIndex(), "global index");852 writeStr(sub.os, maybeDemangleSymbol(g->getName()), "symbol name");853 }854 }855 for (Symbol *s : out.globalSec->internalGotSymbols) {856 writeUleb128(sub.os, s->getGOTIndex(), "global index");857 if (isa<FunctionSymbol>(s))858 writeStr(sub.os, "GOT.func.internal." + toString(*s), "symbol name");859 else860 writeStr(sub.os, "GOT.data.internal." + toString(*s), "symbol name");861 }862 863 sub.writeTo(bodyOutputStream);864 }865 866 count = numNamedDataSegments();867 if (count) {868 SubSection sub(WASM_NAMES_DATA_SEGMENT);869 writeUleb128(sub.os, count, "name count");870 871 for (OutputSegment *s : segments) {872 if (!s->name.empty() && s->requiredInBinary()) {873 writeUleb128(sub.os, s->index, "global index");874 writeStr(sub.os, s->name, "segment name");875 }876 }877 878 sub.writeTo(bodyOutputStream);879 }880}881 882void ProducersSection::addInfo(const WasmProducerInfo &info) {883 for (auto &producers :884 {std::make_pair(&info.Languages, &languages),885 std::make_pair(&info.Tools, &tools), std::make_pair(&info.SDKs, &sDKs)})886 for (auto &producer : *producers.first)887 if (llvm::none_of(*producers.second,888 [&](std::pair<std::string, std::string> seen) {889 return seen.first == producer.first;890 }))891 producers.second->push_back(producer);892}893 894void ProducersSection::writeBody() {895 auto &os = bodyOutputStream;896 writeUleb128(os, fieldCount(), "field count");897 for (auto &field :898 {std::make_pair("language", languages),899 std::make_pair("processed-by", tools), std::make_pair("sdk", sDKs)}) {900 if (field.second.empty())901 continue;902 writeStr(os, field.first, "field name");903 writeUleb128(os, field.second.size(), "number of entries");904 for (auto &entry : field.second) {905 writeStr(os, entry.first, "producer name");906 writeStr(os, entry.second, "producer version");907 }908 }909}910 911void TargetFeaturesSection::writeBody() {912 SmallVector<std::string, 8> emitted(features.begin(), features.end());913 llvm::sort(emitted);914 auto &os = bodyOutputStream;915 writeUleb128(os, emitted.size(), "feature count");916 for (auto &feature : emitted) {917 writeU8(os, WASM_FEATURE_PREFIX_USED, "feature used prefix");918 writeStr(os, feature, "feature name");919 }920}921 922void RelocSection::writeBody() {923 uint32_t count = sec->getNumRelocations();924 assert(sec->sectionIndex != UINT32_MAX);925 writeUleb128(bodyOutputStream, sec->sectionIndex, "reloc section");926 writeUleb128(bodyOutputStream, count, "reloc count");927 sec->writeRelocations(bodyOutputStream);928}929 930static size_t getHashSize() {931 switch (ctx.arg.buildId) {932 case BuildIdKind::Fast:933 case BuildIdKind::Uuid:934 return 16;935 case BuildIdKind::Sha1:936 return 20;937 case BuildIdKind::Hexstring:938 return ctx.arg.buildIdVector.size();939 case BuildIdKind::None:940 return 0;941 }942 llvm_unreachable("build id kind not implemented");943}944 945BuildIdSection::BuildIdSection()946 : SyntheticSection(llvm::wasm::WASM_SEC_CUSTOM, buildIdSectionName),947 hashSize(getHashSize()) {}948 949void BuildIdSection::writeBody() {950 LLVM_DEBUG(llvm::dbgs() << "BuildId writebody\n");951 // Write hash size952 auto &os = bodyOutputStream;953 writeUleb128(os, hashSize, "build id size");954 writeBytes(os, std::vector<char>(hashSize, ' ').data(), hashSize,955 "placeholder");956}957 958void BuildIdSection::writeBuildId(llvm::ArrayRef<uint8_t> buf) {959 assert(buf.size() == hashSize);960 LLVM_DEBUG(dbgs() << "buildid write " << buf.size() << " "961 << hashPlaceholderPtr << '\n');962 memcpy(hashPlaceholderPtr, buf.data(), hashSize);963}964 965} // namespace wasm::lld966