1 //===- SyntheticSections.cpp ----------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file contains linker-synthesized sections. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "SyntheticSections.h" 14 15 #include "InputChunks.h" 16 #include "InputElement.h" 17 #include "OutputSegment.h" 18 #include "SymbolTable.h" 19 #include "llvm/Support/Path.h" 20 #include <optional> 21 22 using namespace llvm; 23 using namespace llvm::wasm; 24 25 namespace lld::wasm { 26 27 OutStruct out; 28 29 namespace { 30 31 // Some synthetic sections (e.g. "name" and "linking") have subsections. 32 // Just like the synthetic sections themselves these need to be created before 33 // they can be written out (since they are preceded by their length). This 34 // class is used to create subsections and then write them into the stream 35 // of the parent section. 36 class SubSection { 37 public: 38 explicit SubSection(uint32_t type) : type(type) {} 39 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()); 44 } 45 46 private: 47 uint32_t type; 48 std::string body; 49 50 public: 51 raw_string_ostream os{body}; 52 }; 53 54 } // namespace 55 56 bool DylinkSection::isNeeded() const { 57 return ctx.isPic || 58 ctx.arg.unresolvedSymbols == UnresolvedPolicy::ImportDynamic || 59 !ctx.sharedFiles.empty(); 60 } 61 62 void DylinkSection::writeBody() { 63 raw_ostream &os = bodyOutputStream; 64 65 { 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); 72 } 73 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); 80 } 81 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); 94 } 95 if (sym->isUndefWeak()) { 96 importInfo.push_back(sym); 97 } 98 } 99 } 100 101 if (!exportInfo.empty()) { 102 SubSection sub(WASM_DYLINK_EXPORT_INFO); 103 writeUleb128(sub.os, exportInfo.size(), "num exports"); 104 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; 112 } 113 } 114 writeStr(sub.os, name, "sym name"); 115 writeUleb128(sub.os, sym->flags, "sym flags"); 116 } 117 118 sub.writeTo(os); 119 } 120 121 if (!importInfo.empty()) { 122 SubSection sub(WASM_DYLINK_IMPORT_INFO); 123 writeUleb128(sub.os, importInfo.size(), "num imports"); 124 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"); 132 } 133 134 sub.writeTo(os); 135 } 136 } 137 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); 143 } 144 return pair.first->second; 145 } 146 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; 152 } 153 return it->second; 154 } 155 156 void TypeSection::writeBody() { 157 writeUleb128(bodyOutputStream, types.size(), "type count"); 158 for (const WasmSignature *sig : types) 159 writeSig(bodyOutputStream, *sig); 160 } 161 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; 168 } 169 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; 181 } 182 gotSymbols.push_back(sym); 183 } 184 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); 197 } 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); 206 } 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); 215 } 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); 226 } 227 } 228 } 229 230 void ImportSection::writeBody() { 231 raw_ostream &os = bodyOutputStream; 232 233 writeUleb128(os, getNumImports(), "import count"); 234 235 bool is64 = ctx.arg.is64.value_or(false); 236 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; 247 } 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); 253 } 254 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); 259 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(); 273 } 274 writeImport(os, import); 275 } 276 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); 288 } 289 } 290 291 void FunctionSection::writeBody() { 292 raw_ostream &os = bodyOutputStream; 293 294 writeUleb128(os, inputFunctions.size(), "function count"); 295 for (const InputFunction *func : inputFunctions) 296 writeUleb128(os, out.typeSec->lookupType(func->signature), "sig index"); 297 } 298 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); 306 } 307 308 void TableSection::writeBody() { 309 raw_ostream &os = bodyOutputStream; 310 311 writeUleb128(os, inputTables.size(), "table count"); 312 for (const InputTable *table : inputTables) 313 writeTableType(os, table->getType()); 314 } 315 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; 335 } 336 } 337 llvm_unreachable("failed to find conflicting table import"); 338 } 339 inputTables.insert(inputTables.begin(), table); 340 return; 341 } 342 inputTables.push_back(table); 343 } 344 345 void TableSection::assignIndexes() { 346 uint32_t tableNumber = out.importSec->getNumImportedTables(); 347 for (InputTable *t : inputTables) 348 t->assignIndex(tableNumber++); 349 } 350 351 void MemorySection::writeBody() { 352 raw_ostream &os = bodyOutputStream; 353 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"); 367 } 368 369 void TagSection::writeBody() { 370 raw_ostream &os = bodyOutputStream; 371 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"); 376 } 377 } 378 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); 386 } 387 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; 395 } 396 397 static void ensureIndirectFunctionTable() { 398 if (!WasmSym::indirectFunctionTable) 399 WasmSym::indirectFunctionTable = 400 symtab->resolveIndirectFunctionTable(/*required =*/true); 401 } 402 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); 413 } 414 internalGotSymbols.push_back(sym); 415 } 416 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; 424 425 for (const Symbol *sym : internalGotSymbols) { 426 if (TLS != sym->isTLS()) 427 continue; 428 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"); 437 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"); 447 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; 454 } 455 writeU8(os, opcode_ptr_add, "ADD"); 456 writeU8(os, WASM_OPCODE_GLOBAL_SET, "GLOBAL_SET"); 457 writeUleb128(os, sym->getGOTIndex(), "got_entry"); 458 } 459 } 460 461 void GlobalSection::writeBody() { 462 raw_ostream &os = bodyOutputStream; 463 464 writeUleb128(os, numGlobals(), "global count"); 465 for (InputGlobal *g : inputGlobals) { 466 writeGlobalType(os, g->getType()); 467 writeInitExpr(os, g->getInitExpr()); 468 } 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; 483 } 484 WasmGlobalType type{itype, mutable_}; 485 writeGlobalType(os, type); 486 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; 496 } 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; 502 } 503 } 504 } 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"); 513 } 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); 527 } 528 writeInitExpr(os, initExpr); 529 } 530 } 531 for (const DefinedData *sym : dataAddressGlobals) { 532 WasmGlobalType type{itype, false}; 533 writeGlobalType(os, type); 534 writeInitExpr(os, intConst(sym->getVA(), is64)); 535 } 536 } 537 538 void GlobalSection::addGlobal(InputGlobal *global) { 539 assert(!isSealed); 540 if (!global->live) 541 return; 542 inputGlobals.push_back(global); 543 } 544 545 void ExportSection::writeBody() { 546 raw_ostream &os = bodyOutputStream; 547 548 writeUleb128(os, exports.size(), "export count"); 549 for (const WasmExport &export_ : exports) 550 writeExport(os, export_); 551 } 552 553 bool StartSection::isNeeded() const { 554 return WasmSym::startFunction != nullptr; 555 } 556 557 void StartSection::writeBody() { 558 raw_ostream &os = bodyOutputStream; 559 writeUleb128(os, WasmSym::startFunction->getFunctionIndex(), 560 "function index"); 561 } 562 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); 571 } 572 573 void ElemSection::writeBody() { 574 raw_ostream &os = bodyOutputStream; 575 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"); 585 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); 594 } 595 writeInitExpr(os, initExpr); 596 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"); 602 } 603 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; 611 } 612 } 613 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 })) {} 619 620 void DataCountSection::writeBody() { 621 writeUleb128(bodyOutputStream, numSegments, "data count"); 622 } 623 624 bool DataCountSection::isNeeded() const { 625 return numSegments && ctx.arg.sharedMemory; 626 } 627 628 void LinkingSection::writeBody() { 629 raw_ostream &os = bodyOutputStream; 630 631 writeUleb128(os, WasmMetadataVersion, "Version"); 632 633 if (!symtabEntries.empty()) { 634 SubSection sub(WASM_SYMBOL_TABLE); 635 writeUleb128(sub.os, symtabEntries.size(), "num symbols"); 636 637 for (const Symbol *sym : symtabEntries) { 638 assert(sym->isDefined() || sym->isUndefined()); 639 WasmSymbolType kind = sym->getWasmType(); 640 uint32_t flags = sym->flags; 641 642 writeU8(sub.os, kind, "sym kind"); 643 writeUleb128(sub.os, flags, "sym flags"); 644 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"); 650 } 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"); 675 } 676 writeUleb128(sub.os, dataSym->getSize(), "data size"); 677 } 678 } else { 679 auto *s = cast<OutputSectionSymbol>(sym); 680 writeUleb128(sub.os, s->section->sectionIndex, "sym section index"); 681 } 682 } 683 684 sub.writeTo(os); 685 } 686 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"); 694 } 695 sub.writeTo(os); 696 } 697 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"); 704 } 705 sub.writeTo(os); 706 } 707 708 struct ComdatEntry { 709 unsigned kind; 710 uint32_t index; 711 }; 712 std::map<StringRef, std::vector<ComdatEntry>> comdats; 713 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()}); 719 } 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}); 731 } 732 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"); 743 } 744 } 745 sub.writeTo(os); 746 } 747 } 748 749 void LinkingSection::addToSymtab(Symbol *sym) { 750 sym->setOutputSymbolIndex(symtabEntries.size()); 751 symtabEntries.emplace_back(sym); 752 } 753 754 unsigned NameSection::numNamedFunctions() const { 755 unsigned numNames = out.importSec->getNumImportedFunctions(); 756 757 for (const InputFunction *f : out.functionSec->inputFunctions) 758 if (!f->name.empty() || !f->debugName.empty()) 759 ++numNames; 760 761 return numNames; 762 } 763 764 unsigned NameSection::numNamedGlobals() const { 765 unsigned numNames = out.importSec->getNumImportedGlobals(); 766 767 for (const InputGlobal *g : out.globalSec->inputGlobals) 768 if (!g->getName().empty()) 769 ++numNames; 770 771 numNames += out.globalSec->internalGotSymbols.size(); 772 return numNames; 773 } 774 775 unsigned NameSection::numNamedDataSegments() const { 776 unsigned numNames = 0; 777 778 for (const OutputSegment *s : segments) 779 if (!s->name.empty() && s->requiredInBinary()) 780 ++numNames; 781 782 return numNames; 783 } 784 785 // Create the custom "name" section containing debug symbol names. 786 void NameSection::writeBody() { 787 { 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); 794 } 795 796 unsigned count = numNamedFunctions(); 797 if (count) { 798 SubSection sub(WASM_NAMES_FUNCTION); 799 writeUleb128(sub.os, count, "name count"); 800 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"); 808 } 809 } 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"); 817 } 818 } 819 } 820 sub.writeTo(bodyOutputStream); 821 } 822 823 count = numNamedGlobals(); 824 if (count) { 825 SubSection sub(WASM_NAMES_GLOBAL); 826 writeUleb128(sub.os, count, "name count"); 827 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"); 832 } 833 } 834 for (const Symbol *s : out.importSec->gotSymbols) { 835 writeUleb128(sub.os, s->getGOTIndex(), "global index"); 836 writeStr(sub.os, toString(*s), "symbol name"); 837 } 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"); 842 } 843 } 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"); 850 } 851 852 sub.writeTo(bodyOutputStream); 853 } 854 855 count = numNamedDataSegments(); 856 if (count) { 857 SubSection sub(WASM_NAMES_DATA_SEGMENT); 858 writeUleb128(sub.os, count, "name count"); 859 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"); 864 } 865 } 866 867 sub.writeTo(bodyOutputStream); 868 } 869 } 870 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; 879 })) 880 producers.second->push_back(producer); 881 } 882 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"); 896 } 897 } 898 } 899 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"); 908 } 909 } 910 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); 917 } 918 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; 930 } 931 llvm_unreachable("build id kind not implemented"); 932 } 933 934 BuildIdSection::BuildIdSection() 935 : SyntheticSection(llvm::wasm::WASM_SEC_CUSTOM, buildIdSectionName), 936 hashSize(getHashSize()) {} 937 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"); 945 } 946 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); 952 } 953 954 } // namespace wasm::lld 955