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