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