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