brintos

brintos / llvm-project-archived public Read only

0
0
Text · 32.0 KiB · 5e7b9c2 Raw
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