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.Minimum = 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 " + 234 toString(culprit->getFile())); 235 return; 236 } 237 } 238 llvm_unreachable("failed to find conflicting table import"); 239 } 240 inputTables.insert(inputTables.begin(), table); 241 return; 242 } 243 inputTables.push_back(table); 244 } 245 246 void TableSection::assignIndexes() { 247 uint32_t tableNumber = out.importSec->getNumImportedTables(); 248 for (InputTable *t : inputTables) 249 t->assignIndex(tableNumber++); 250 } 251 252 void MemorySection::writeBody() { 253 raw_ostream &os = bodyOutputStream; 254 255 bool hasMax = maxMemoryPages != 0 || config->sharedMemory; 256 writeUleb128(os, 1, "memory count"); 257 unsigned flags = 0; 258 if (hasMax) 259 flags |= WASM_LIMITS_FLAG_HAS_MAX; 260 if (config->sharedMemory) 261 flags |= WASM_LIMITS_FLAG_IS_SHARED; 262 if (config->is64.getValueOr(false)) 263 flags |= WASM_LIMITS_FLAG_IS_64; 264 writeUleb128(os, flags, "memory limits flags"); 265 writeUleb128(os, numMemoryPages, "initial pages"); 266 if (hasMax) 267 writeUleb128(os, maxMemoryPages, "max pages"); 268 } 269 270 void EventSection::writeBody() { 271 raw_ostream &os = bodyOutputStream; 272 273 writeUleb128(os, inputEvents.size(), "event count"); 274 for (InputEvent *e : inputEvents) { 275 WasmEventType type = e->getType(); 276 type.SigIndex = out.typeSec->lookupType(e->signature); 277 writeEventType(os, type); 278 } 279 } 280 281 void EventSection::addEvent(InputEvent *event) { 282 if (!event->live) 283 return; 284 uint32_t eventIndex = 285 out.importSec->getNumImportedEvents() + inputEvents.size(); 286 LLVM_DEBUG(dbgs() << "addEvent: " << eventIndex << "\n"); 287 event->assignIndex(eventIndex); 288 inputEvents.push_back(event); 289 } 290 291 void GlobalSection::assignIndexes() { 292 uint32_t globalIndex = out.importSec->getNumImportedGlobals(); 293 for (InputGlobal *g : inputGlobals) 294 g->assignIndex(globalIndex++); 295 for (Symbol *sym : internalGotSymbols) 296 sym->setGOTIndex(globalIndex++); 297 isSealed = true; 298 } 299 300 static void ensureIndirectFunctionTable() { 301 if (!WasmSym::indirectFunctionTable) 302 WasmSym::indirectFunctionTable = 303 symtab->resolveIndirectFunctionTable(/*required =*/true); 304 } 305 306 void GlobalSection::addInternalGOTEntry(Symbol *sym) { 307 assert(!isSealed); 308 if (sym->requiresGOT) 309 return; 310 LLVM_DEBUG(dbgs() << "addInternalGOTEntry: " << sym->getName() << " " 311 << toString(sym->kind()) << "\n"); 312 sym->requiresGOT = true; 313 if (auto *F = dyn_cast<FunctionSymbol>(sym)) { 314 ensureIndirectFunctionTable(); 315 out.elemSec->addEntry(F); 316 } 317 internalGotSymbols.push_back(sym); 318 } 319 320 void GlobalSection::generateRelocationCode(raw_ostream &os) const { 321 unsigned opcode_ptr_const = config->is64.getValueOr(false) 322 ? WASM_OPCODE_I64_CONST 323 : WASM_OPCODE_I32_CONST; 324 unsigned opcode_ptr_add = config->is64.getValueOr(false) 325 ? WASM_OPCODE_I64_ADD 326 : WASM_OPCODE_I32_ADD; 327 328 for (const Symbol *sym : internalGotSymbols) { 329 if (auto *d = dyn_cast<DefinedData>(sym)) { 330 // Get __memory_base 331 writeU8(os, WASM_OPCODE_GLOBAL_GET, "GLOBAL_GET"); 332 writeUleb128(os, WasmSym::memoryBase->getGlobalIndex(), "__memory_base"); 333 334 // Add the virtual address of the data symbol 335 writeU8(os, opcode_ptr_const, "CONST"); 336 writeSleb128(os, d->getVA(), "offset"); 337 } else if (auto *f = dyn_cast<FunctionSymbol>(sym)) { 338 if (f->isStub) 339 continue; 340 // Get __table_base 341 writeU8(os, WASM_OPCODE_GLOBAL_GET, "GLOBAL_GET"); 342 writeUleb128(os, WasmSym::tableBase->getGlobalIndex(), "__table_base"); 343 344 // Add the table index to __table_base 345 writeU8(os, opcode_ptr_const, "CONST"); 346 writeSleb128(os, f->getTableIndex(), "offset"); 347 } else { 348 assert(isa<UndefinedData>(sym)); 349 continue; 350 } 351 writeU8(os, opcode_ptr_add, "ADD"); 352 writeU8(os, WASM_OPCODE_GLOBAL_SET, "GLOBAL_SET"); 353 writeUleb128(os, sym->getGOTIndex(), "got_entry"); 354 } 355 } 356 357 void GlobalSection::writeBody() { 358 raw_ostream &os = bodyOutputStream; 359 360 writeUleb128(os, numGlobals(), "global count"); 361 for (InputGlobal *g : inputGlobals) { 362 writeGlobalType(os, g->getType()); 363 writeInitExpr(os, g->getInitExpr()); 364 } 365 // TODO(wvo): when do these need I64_CONST? 366 for (const Symbol *sym : internalGotSymbols) { 367 // In the case of dynamic linking, internal GOT entries 368 // need to be mutable since they get updated to the correct 369 // runtime value during `__wasm_apply_global_relocs`. 370 bool mutable_ = config->isPic & !sym->isStub; 371 WasmGlobalType type{WASM_TYPE_I32, mutable_}; 372 WasmInitExpr initExpr; 373 initExpr.Opcode = WASM_OPCODE_I32_CONST; 374 if (auto *d = dyn_cast<DefinedData>(sym)) 375 initExpr.Value.Int32 = d->getVA(); 376 else if (auto *f = dyn_cast<FunctionSymbol>(sym)) 377 initExpr.Value.Int32 = f->isStub ? 0 : f->getTableIndex(); 378 else { 379 assert(isa<UndefinedData>(sym)); 380 initExpr.Value.Int32 = 0; 381 } 382 writeGlobalType(os, type); 383 writeInitExpr(os, initExpr); 384 } 385 for (const DefinedData *sym : dataAddressGlobals) { 386 WasmGlobalType type{WASM_TYPE_I32, false}; 387 WasmInitExpr initExpr; 388 initExpr.Opcode = WASM_OPCODE_I32_CONST; 389 initExpr.Value.Int32 = sym->getVA(); 390 writeGlobalType(os, type); 391 writeInitExpr(os, initExpr); 392 } 393 } 394 395 void GlobalSection::addGlobal(InputGlobal *global) { 396 assert(!isSealed); 397 if (!global->live) 398 return; 399 inputGlobals.push_back(global); 400 } 401 402 void ExportSection::writeBody() { 403 raw_ostream &os = bodyOutputStream; 404 405 writeUleb128(os, exports.size(), "export count"); 406 for (const WasmExport &export_ : exports) 407 writeExport(os, export_); 408 } 409 410 bool StartSection::isNeeded() const { 411 return WasmSym::startFunction != nullptr; 412 } 413 414 void StartSection::writeBody() { 415 raw_ostream &os = bodyOutputStream; 416 writeUleb128(os, WasmSym::startFunction->getFunctionIndex(), 417 "function index"); 418 } 419 420 void ElemSection::addEntry(FunctionSymbol *sym) { 421 // Don't add stub functions to the wasm table. The address of all stub 422 // functions should be zero and they should they don't appear in the table. 423 // They only exist so that the calls to missing functions can validate. 424 if (sym->hasTableIndex() || sym->isStub) 425 return; 426 sym->setTableIndex(config->tableBase + indirectFunctions.size()); 427 indirectFunctions.emplace_back(sym); 428 } 429 430 void ElemSection::writeBody() { 431 raw_ostream &os = bodyOutputStream; 432 433 assert(WasmSym::indirectFunctionTable); 434 writeUleb128(os, 1, "segment count"); 435 uint32_t tableNumber = WasmSym::indirectFunctionTable->getTableNumber(); 436 uint32_t flags = 0; 437 if (tableNumber) 438 flags |= WASM_ELEM_SEGMENT_HAS_TABLE_NUMBER; 439 writeUleb128(os, flags, "elem segment flags"); 440 if (flags & WASM_ELEM_SEGMENT_HAS_TABLE_NUMBER) 441 writeUleb128(os, tableNumber, "table number"); 442 443 WasmInitExpr initExpr; 444 if (config->isPic) { 445 initExpr.Opcode = WASM_OPCODE_GLOBAL_GET; 446 initExpr.Value.Global = WasmSym::tableBase->getGlobalIndex(); 447 } else { 448 initExpr.Opcode = WASM_OPCODE_I32_CONST; 449 initExpr.Value.Int32 = config->tableBase; 450 } 451 writeInitExpr(os, initExpr); 452 453 if (flags & WASM_ELEM_SEGMENT_MASK_HAS_ELEM_KIND) { 454 // We only write active function table initializers, for which the elem kind 455 // is specified to be written as 0x00 and interpreted to mean "funcref". 456 const uint8_t elemKind = 0; 457 writeU8(os, elemKind, "elem kind"); 458 } 459 460 writeUleb128(os, indirectFunctions.size(), "elem count"); 461 uint32_t tableIndex = config->tableBase; 462 for (const FunctionSymbol *sym : indirectFunctions) { 463 assert(sym->getTableIndex() == tableIndex); 464 writeUleb128(os, sym->getFunctionIndex(), "function index"); 465 ++tableIndex; 466 } 467 } 468 469 DataCountSection::DataCountSection(ArrayRef<OutputSegment *> segments) 470 : SyntheticSection(llvm::wasm::WASM_SEC_DATACOUNT), 471 numSegments(std::count_if( 472 segments.begin(), segments.end(), 473 [](OutputSegment *const segment) { return !segment->isBss; })) {} 474 475 void DataCountSection::writeBody() { 476 writeUleb128(bodyOutputStream, numSegments, "data count"); 477 } 478 479 bool DataCountSection::isNeeded() const { 480 return numSegments && config->sharedMemory; 481 } 482 483 void LinkingSection::writeBody() { 484 raw_ostream &os = bodyOutputStream; 485 486 writeUleb128(os, WasmMetadataVersion, "Version"); 487 488 if (!symtabEntries.empty()) { 489 SubSection sub(WASM_SYMBOL_TABLE); 490 writeUleb128(sub.os, symtabEntries.size(), "num symbols"); 491 492 for (const Symbol *sym : symtabEntries) { 493 assert(sym->isDefined() || sym->isUndefined()); 494 WasmSymbolType kind = sym->getWasmType(); 495 uint32_t flags = sym->flags; 496 497 writeU8(sub.os, kind, "sym kind"); 498 writeUleb128(sub.os, flags, "sym flags"); 499 500 if (auto *f = dyn_cast<FunctionSymbol>(sym)) { 501 writeUleb128(sub.os, f->getFunctionIndex(), "index"); 502 if (sym->isDefined() || (flags & WASM_SYMBOL_EXPLICIT_NAME) != 0) 503 writeStr(sub.os, sym->getName(), "sym name"); 504 } else if (auto *g = dyn_cast<GlobalSymbol>(sym)) { 505 writeUleb128(sub.os, g->getGlobalIndex(), "index"); 506 if (sym->isDefined() || (flags & WASM_SYMBOL_EXPLICIT_NAME) != 0) 507 writeStr(sub.os, sym->getName(), "sym name"); 508 } else if (auto *e = dyn_cast<EventSymbol>(sym)) { 509 writeUleb128(sub.os, e->getEventIndex(), "index"); 510 if (sym->isDefined() || (flags & WASM_SYMBOL_EXPLICIT_NAME) != 0) 511 writeStr(sub.os, sym->getName(), "sym name"); 512 } else if (auto *t = dyn_cast<TableSymbol>(sym)) { 513 writeUleb128(sub.os, t->getTableNumber(), "table number"); 514 if (sym->isDefined() || (flags & WASM_SYMBOL_EXPLICIT_NAME) != 0) 515 writeStr(sub.os, sym->getName(), "sym name"); 516 } else if (isa<DataSymbol>(sym)) { 517 writeStr(sub.os, sym->getName(), "sym name"); 518 if (auto *dataSym = dyn_cast<DefinedData>(sym)) { 519 writeUleb128(sub.os, dataSym->getOutputSegmentIndex(), "index"); 520 writeUleb128(sub.os, dataSym->getOutputSegmentOffset(), 521 "data offset"); 522 writeUleb128(sub.os, dataSym->getSize(), "data size"); 523 } 524 } else { 525 auto *s = cast<OutputSectionSymbol>(sym); 526 writeUleb128(sub.os, s->section->sectionIndex, "sym section index"); 527 } 528 } 529 530 sub.writeTo(os); 531 } 532 533 if (dataSegments.size()) { 534 SubSection sub(WASM_SEGMENT_INFO); 535 writeUleb128(sub.os, dataSegments.size(), "num data segments"); 536 for (const OutputSegment *s : dataSegments) { 537 writeStr(sub.os, s->name, "segment name"); 538 writeUleb128(sub.os, s->alignment, "alignment"); 539 writeUleb128(sub.os, 0, "flags"); 540 } 541 sub.writeTo(os); 542 } 543 544 if (!initFunctions.empty()) { 545 SubSection sub(WASM_INIT_FUNCS); 546 writeUleb128(sub.os, initFunctions.size(), "num init functions"); 547 for (const WasmInitEntry &f : initFunctions) { 548 writeUleb128(sub.os, f.priority, "priority"); 549 writeUleb128(sub.os, f.sym->getOutputSymbolIndex(), "function index"); 550 } 551 sub.writeTo(os); 552 } 553 554 struct ComdatEntry { 555 unsigned kind; 556 uint32_t index; 557 }; 558 std::map<StringRef, std::vector<ComdatEntry>> comdats; 559 560 for (const InputFunction *f : out.functionSec->inputFunctions) { 561 StringRef comdat = f->getComdatName(); 562 if (!comdat.empty()) 563 comdats[comdat].emplace_back( 564 ComdatEntry{WASM_COMDAT_FUNCTION, f->getFunctionIndex()}); 565 } 566 for (uint32_t i = 0; i < dataSegments.size(); ++i) { 567 const auto &inputSegments = dataSegments[i]->inputSegments; 568 if (inputSegments.empty()) 569 continue; 570 StringRef comdat = inputSegments[0]->getComdatName(); 571 #ifndef NDEBUG 572 for (const InputSegment *isec : inputSegments) 573 assert(isec->getComdatName() == comdat); 574 #endif 575 if (!comdat.empty()) 576 comdats[comdat].emplace_back(ComdatEntry{WASM_COMDAT_DATA, i}); 577 } 578 579 if (!comdats.empty()) { 580 SubSection sub(WASM_COMDAT_INFO); 581 writeUleb128(sub.os, comdats.size(), "num comdats"); 582 for (const auto &c : comdats) { 583 writeStr(sub.os, c.first, "comdat name"); 584 writeUleb128(sub.os, 0, "comdat flags"); // flags for future use 585 writeUleb128(sub.os, c.second.size(), "num entries"); 586 for (const ComdatEntry &entry : c.second) { 587 writeU8(sub.os, entry.kind, "entry kind"); 588 writeUleb128(sub.os, entry.index, "entry index"); 589 } 590 } 591 sub.writeTo(os); 592 } 593 } 594 595 void LinkingSection::addToSymtab(Symbol *sym) { 596 sym->setOutputSymbolIndex(symtabEntries.size()); 597 symtabEntries.emplace_back(sym); 598 } 599 600 unsigned NameSection::numNamedFunctions() const { 601 unsigned numNames = out.importSec->getNumImportedFunctions(); 602 603 for (const InputFunction *f : out.functionSec->inputFunctions) 604 if (!f->getName().empty() || !f->getDebugName().empty()) 605 ++numNames; 606 607 return numNames; 608 } 609 610 unsigned NameSection::numNamedGlobals() const { 611 unsigned numNames = out.importSec->getNumImportedGlobals(); 612 613 for (const InputGlobal *g : out.globalSec->inputGlobals) 614 if (!g->getName().empty()) 615 ++numNames; 616 617 numNames += out.globalSec->internalGotSymbols.size(); 618 return numNames; 619 } 620 621 unsigned NameSection::numNamedDataSegments() const { 622 unsigned numNames = 0; 623 624 for (const OutputSegment *s : segments) 625 if (!s->name.empty() && !s->isBss) 626 ++numNames; 627 628 return numNames; 629 } 630 631 // Create the custom "name" section containing debug symbol names. 632 void NameSection::writeBody() { 633 unsigned count = numNamedFunctions(); 634 if (count) { 635 SubSection sub(WASM_NAMES_FUNCTION); 636 writeUleb128(sub.os, count, "name count"); 637 638 // Function names appear in function index order. As it happens 639 // importedSymbols and inputFunctions are numbered in order with imported 640 // functions coming first. 641 for (const Symbol *s : out.importSec->importedSymbols) { 642 if (auto *f = dyn_cast<FunctionSymbol>(s)) { 643 writeUleb128(sub.os, f->getFunctionIndex(), "func index"); 644 writeStr(sub.os, toString(*s), "symbol name"); 645 } 646 } 647 for (const InputFunction *f : out.functionSec->inputFunctions) { 648 if (!f->getName().empty()) { 649 writeUleb128(sub.os, f->getFunctionIndex(), "func index"); 650 if (!f->getDebugName().empty()) { 651 writeStr(sub.os, f->getDebugName(), "symbol name"); 652 } else { 653 writeStr(sub.os, maybeDemangleSymbol(f->getName()), "symbol name"); 654 } 655 } 656 } 657 sub.writeTo(bodyOutputStream); 658 } 659 660 count = numNamedGlobals(); 661 if (count) { 662 SubSection sub(WASM_NAMES_GLOBAL); 663 writeUleb128(sub.os, count, "name count"); 664 665 for (const Symbol *s : out.importSec->importedSymbols) { 666 if (auto *g = dyn_cast<GlobalSymbol>(s)) { 667 writeUleb128(sub.os, g->getGlobalIndex(), "global index"); 668 writeStr(sub.os, toString(*s), "symbol name"); 669 } 670 } 671 for (const Symbol *s : out.importSec->gotSymbols) { 672 writeUleb128(sub.os, s->getGOTIndex(), "global index"); 673 writeStr(sub.os, toString(*s), "symbol name"); 674 } 675 for (const InputGlobal *g : out.globalSec->inputGlobals) { 676 if (!g->getName().empty()) { 677 writeUleb128(sub.os, g->getAssignedIndex(), "global index"); 678 writeStr(sub.os, maybeDemangleSymbol(g->getName()), "symbol name"); 679 } 680 } 681 for (Symbol *s : out.globalSec->internalGotSymbols) { 682 writeUleb128(sub.os, s->getGOTIndex(), "global index"); 683 if (isa<FunctionSymbol>(s)) 684 writeStr(sub.os, "GOT.func.internal." + toString(*s), "symbol name"); 685 else 686 writeStr(sub.os, "GOT.data.internal." + toString(*s), "symbol name"); 687 } 688 689 sub.writeTo(bodyOutputStream); 690 } 691 692 count = numNamedDataSegments(); 693 if (count) { 694 SubSection sub(WASM_NAMES_DATA_SEGMENT); 695 writeUleb128(sub.os, count, "name count"); 696 697 for (OutputSegment *s : segments) { 698 if (!s->name.empty() && !s->isBss) { 699 writeUleb128(sub.os, s->index, "global index"); 700 writeStr(sub.os, s->name, "segment name"); 701 } 702 } 703 704 sub.writeTo(bodyOutputStream); 705 } 706 } 707 708 void ProducersSection::addInfo(const WasmProducerInfo &info) { 709 for (auto &producers : 710 {std::make_pair(&info.Languages, &languages), 711 std::make_pair(&info.Tools, &tools), std::make_pair(&info.SDKs, &sDKs)}) 712 for (auto &producer : *producers.first) 713 if (producers.second->end() == 714 llvm::find_if(*producers.second, 715 [&](std::pair<std::string, std::string> seen) { 716 return seen.first == producer.first; 717 })) 718 producers.second->push_back(producer); 719 } 720 721 void ProducersSection::writeBody() { 722 auto &os = bodyOutputStream; 723 writeUleb128(os, fieldCount(), "field count"); 724 for (auto &field : 725 {std::make_pair("language", languages), 726 std::make_pair("processed-by", tools), std::make_pair("sdk", sDKs)}) { 727 if (field.second.empty()) 728 continue; 729 writeStr(os, field.first, "field name"); 730 writeUleb128(os, field.second.size(), "number of entries"); 731 for (auto &entry : field.second) { 732 writeStr(os, entry.first, "producer name"); 733 writeStr(os, entry.second, "producer version"); 734 } 735 } 736 } 737 738 void TargetFeaturesSection::writeBody() { 739 SmallVector<std::string, 8> emitted(features.begin(), features.end()); 740 llvm::sort(emitted); 741 auto &os = bodyOutputStream; 742 writeUleb128(os, emitted.size(), "feature count"); 743 for (auto &feature : emitted) { 744 writeU8(os, WASM_FEATURE_PREFIX_USED, "feature used prefix"); 745 writeStr(os, feature, "feature name"); 746 } 747 } 748 749 void RelocSection::writeBody() { 750 uint32_t count = sec->getNumRelocations(); 751 assert(sec->sectionIndex != UINT32_MAX); 752 writeUleb128(bodyOutputStream, sec->sectionIndex, "reloc section"); 753 writeUleb128(bodyOutputStream, count, "reloc count"); 754 sec->writeRelocations(bodyOutputStream); 755 } 756 757 } // namespace wasm 758 } // namespace lld 759