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