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