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 "InputEvent.h" 17 #include "InputGlobal.h" 18 #include "OutputSegment.h" 19 #include "SymbolTable.h" 20 #include "llvm/Support/Path.h" 21 22 using namespace llvm; 23 using namespace llvm::wasm; 24 25 namespace lld { 26 namespace wasm { 27 28 OutStruct out; 29 30 namespace { 31 32 // Some synthetic sections (e.g. "name" and "linking") have subsections. 33 // Just like the synthetic sections themselves these need to be created before 34 // they can be written out (since they are preceded by their length). This 35 // class is used to create subsections and then write them into the stream 36 // of the parent section. 37 class SubSection { 38 public: 39 explicit SubSection(uint32_t type) : type(type) {} 40 41 void writeTo(raw_ostream &to) { 42 os.flush(); 43 writeUleb128(to, type, "subsection type"); 44 writeUleb128(to, body.size(), "subsection size"); 45 to.write(body.data(), body.size()); 46 } 47 48 private: 49 uint32_t type; 50 std::string body; 51 52 public: 53 raw_string_ostream os{body}; 54 }; 55 56 } // namespace 57 58 void DylinkSection::writeBody() { 59 raw_ostream &os = bodyOutputStream; 60 61 writeUleb128(os, memSize, "MemSize"); 62 writeUleb128(os, memAlign, "MemAlign"); 63 writeUleb128(os, out.elemSec->numEntries(), "TableSize"); 64 writeUleb128(os, 0, "TableAlign"); 65 writeUleb128(os, symtab->sharedFiles.size(), "Needed"); 66 for (auto *so : symtab->sharedFiles) 67 writeStr(os, llvm::sys::path::filename(so->getName()), "so name"); 68 } 69 70 uint32_t TypeSection::registerType(const WasmSignature &sig) { 71 auto pair = typeIndices.insert(std::make_pair(sig, types.size())); 72 if (pair.second) { 73 LLVM_DEBUG(llvm::dbgs() << "type " << toString(sig) << "\n"); 74 types.push_back(&sig); 75 } 76 return pair.first->second; 77 } 78 79 uint32_t TypeSection::lookupType(const WasmSignature &sig) { 80 auto it = typeIndices.find(sig); 81 if (it == typeIndices.end()) { 82 error("type not found: " + toString(sig)); 83 return 0; 84 } 85 return it->second; 86 } 87 88 void TypeSection::writeBody() { 89 writeUleb128(bodyOutputStream, types.size(), "type count"); 90 for (const WasmSignature *sig : types) 91 writeSig(bodyOutputStream, *sig); 92 } 93 94 uint32_t ImportSection::getNumImports() const { 95 assert(isSealed); 96 uint32_t numImports = importedSymbols.size() + gotSymbols.size(); 97 if (config->importMemory) 98 ++numImports; 99 if (config->importTable) 100 ++numImports; 101 return numImports; 102 } 103 104 void ImportSection::addGOTEntry(Symbol *sym) { 105 assert(!isSealed); 106 if (sym->hasGOTIndex()) 107 return; 108 LLVM_DEBUG(dbgs() << "addGOTEntry: " << toString(*sym) << "\n"); 109 sym->setGOTIndex(numImportedGlobals++); 110 gotSymbols.push_back(sym); 111 } 112 113 void ImportSection::addImport(Symbol *sym) { 114 assert(!isSealed); 115 importedSymbols.emplace_back(sym); 116 if (auto *f = dyn_cast<FunctionSymbol>(sym)) 117 f->setFunctionIndex(numImportedFunctions++); 118 else if (auto *g = dyn_cast<GlobalSymbol>(sym)) 119 g->setGlobalIndex(numImportedGlobals++); 120 else 121 cast<EventSymbol>(sym)->setEventIndex(numImportedEvents++); 122 } 123 124 void ImportSection::writeBody() { 125 raw_ostream &os = bodyOutputStream; 126 127 writeUleb128(os, getNumImports(), "import count"); 128 129 if (config->importMemory) { 130 WasmImport import; 131 import.Module = defaultModule; 132 import.Field = "memory"; 133 import.Kind = WASM_EXTERNAL_MEMORY; 134 import.Memory.Flags = 0; 135 import.Memory.Initial = out.memorySec->numMemoryPages; 136 if (out.memorySec->maxMemoryPages != 0 || config->sharedMemory) { 137 import.Memory.Flags |= WASM_LIMITS_FLAG_HAS_MAX; 138 import.Memory.Maximum = out.memorySec->maxMemoryPages; 139 } 140 if (config->sharedMemory) 141 import.Memory.Flags |= WASM_LIMITS_FLAG_IS_SHARED; 142 if (config->is64.getValueOr(false)) 143 import.Memory.Flags |= WASM_LIMITS_FLAG_IS_64; 144 writeImport(os, import); 145 } 146 147 if (config->importTable) { 148 uint32_t tableSize = config->tableBase + out.elemSec->numEntries(); 149 WasmImport import; 150 import.Module = defaultModule; 151 import.Field = functionTableName; 152 import.Kind = WASM_EXTERNAL_TABLE; 153 import.Table.ElemType = WASM_TYPE_FUNCREF; 154 import.Table.Limits = {0, tableSize, 0}; 155 writeImport(os, import); 156 } 157 158 for (const Symbol *sym : importedSymbols) { 159 WasmImport import; 160 if (auto *f = dyn_cast<UndefinedFunction>(sym)) { 161 import.Field = f->importName ? *f->importName : sym->getName(); 162 import.Module = f->importModule ? *f->importModule : defaultModule; 163 } else if (auto *g = dyn_cast<UndefinedGlobal>(sym)) { 164 import.Field = g->importName ? *g->importName : sym->getName(); 165 import.Module = g->importModule ? *g->importModule : defaultModule; 166 } else { 167 import.Field = sym->getName(); 168 import.Module = defaultModule; 169 } 170 171 if (auto *functionSym = dyn_cast<FunctionSymbol>(sym)) { 172 import.Kind = WASM_EXTERNAL_FUNCTION; 173 import.SigIndex = out.typeSec->lookupType(*functionSym->signature); 174 } else if (auto *globalSym = dyn_cast<GlobalSymbol>(sym)) { 175 import.Kind = WASM_EXTERNAL_GLOBAL; 176 import.Global = *globalSym->getGlobalType(); 177 } else { 178 auto *eventSym = cast<EventSymbol>(sym); 179 import.Kind = WASM_EXTERNAL_EVENT; 180 import.Event.Attribute = eventSym->getEventType()->Attribute; 181 import.Event.SigIndex = out.typeSec->lookupType(*eventSym->signature); 182 } 183 writeImport(os, import); 184 } 185 186 for (const Symbol *sym : gotSymbols) { 187 WasmImport import; 188 import.Kind = WASM_EXTERNAL_GLOBAL; 189 import.Global = {WASM_TYPE_I32, true}; 190 if (isa<DataSymbol>(sym)) 191 import.Module = "GOT.mem"; 192 else 193 import.Module = "GOT.func"; 194 import.Field = sym->getName(); 195 writeImport(os, import); 196 } 197 } 198 199 void FunctionSection::writeBody() { 200 raw_ostream &os = bodyOutputStream; 201 202 writeUleb128(os, inputFunctions.size(), "function count"); 203 for (const InputFunction *func : inputFunctions) 204 writeUleb128(os, out.typeSec->lookupType(func->signature), "sig index"); 205 } 206 207 void FunctionSection::addFunction(InputFunction *func) { 208 if (!func->live) 209 return; 210 uint32_t functionIndex = 211 out.importSec->getNumImportedFunctions() + inputFunctions.size(); 212 inputFunctions.emplace_back(func); 213 func->setFunctionIndex(functionIndex); 214 } 215 216 void TableSection::writeBody() { 217 uint32_t tableSize = config->tableBase + out.elemSec->numEntries(); 218 219 raw_ostream &os = bodyOutputStream; 220 writeUleb128(os, 1, "table count"); 221 WasmLimits limits; 222 if (config->growableTable) 223 limits = {0, tableSize, 0}; 224 else 225 limits = {WASM_LIMITS_FLAG_HAS_MAX, tableSize, tableSize}; 226 writeTableType(os, WasmTableType{WASM_TYPE_FUNCREF, limits}); 227 } 228 229 void MemorySection::writeBody() { 230 raw_ostream &os = bodyOutputStream; 231 232 bool hasMax = maxMemoryPages != 0 || config->sharedMemory; 233 writeUleb128(os, 1, "memory count"); 234 unsigned flags = 0; 235 if (hasMax) 236 flags |= WASM_LIMITS_FLAG_HAS_MAX; 237 if (config->sharedMemory) 238 flags |= WASM_LIMITS_FLAG_IS_SHARED; 239 if (config->is64.getValueOr(false)) 240 flags |= WASM_LIMITS_FLAG_IS_64; 241 writeUleb128(os, flags, "memory limits flags"); 242 writeUleb128(os, numMemoryPages, "initial pages"); 243 if (hasMax) 244 writeUleb128(os, maxMemoryPages, "max pages"); 245 } 246 247 void EventSection::writeBody() { 248 raw_ostream &os = bodyOutputStream; 249 250 writeUleb128(os, inputEvents.size(), "event count"); 251 for (InputEvent *e : inputEvents) { 252 e->event.Type.SigIndex = out.typeSec->lookupType(e->signature); 253 writeEvent(os, e->event); 254 } 255 } 256 257 void EventSection::addEvent(InputEvent *event) { 258 if (!event->live) 259 return; 260 uint32_t eventIndex = 261 out.importSec->getNumImportedEvents() + inputEvents.size(); 262 LLVM_DEBUG(dbgs() << "addEvent: " << eventIndex << "\n"); 263 event->setEventIndex(eventIndex); 264 inputEvents.push_back(event); 265 } 266 267 void GlobalSection::assignIndexes() { 268 uint32_t globalIndex = out.importSec->getNumImportedGlobals(); 269 for (InputGlobal *g : inputGlobals) 270 g->setGlobalIndex(globalIndex++); 271 for (Symbol *sym : internalGotSymbols) 272 sym->setGOTIndex(globalIndex++); 273 isSealed = true; 274 } 275 276 void GlobalSection::addInternalGOTEntry(Symbol *sym) { 277 assert(!isSealed); 278 if (sym->requiresGOT) 279 return; 280 LLVM_DEBUG(dbgs() << "addInternalGOTEntry: " << sym->getName() << " " 281 << toString(sym->kind()) << "\n"); 282 sym->requiresGOT = true; 283 if (auto *F = dyn_cast<FunctionSymbol>(sym)) 284 out.elemSec->addEntry(F); 285 internalGotSymbols.push_back(sym); 286 } 287 288 void GlobalSection::generateRelocationCode(raw_ostream &os) const { 289 unsigned opcode_ptr_const = config->is64.getValueOr(false) 290 ? WASM_OPCODE_I64_CONST 291 : WASM_OPCODE_I32_CONST; 292 unsigned opcode_ptr_add = config->is64.getValueOr(false) 293 ? WASM_OPCODE_I64_ADD 294 : WASM_OPCODE_I32_ADD; 295 296 for (const Symbol *sym : internalGotSymbols) { 297 if (auto *d = dyn_cast<DefinedData>(sym)) { 298 // Get __memory_base 299 writeU8(os, WASM_OPCODE_GLOBAL_GET, "GLOBAL_GET"); 300 writeUleb128(os, WasmSym::memoryBase->getGlobalIndex(), "__memory_base"); 301 302 // Add the virtual address of the data symbol 303 writeU8(os, opcode_ptr_const, "CONST"); 304 writeSleb128(os, d->getVirtualAddress(), "offset"); 305 } else if (auto *f = dyn_cast<FunctionSymbol>(sym)) { 306 // Get __table_base 307 writeU8(os, WASM_OPCODE_GLOBAL_GET, "GLOBAL_GET"); 308 writeUleb128(os, WasmSym::tableBase->getGlobalIndex(), "__table_base"); 309 310 // Add the table index to __table_base 311 writeU8(os, opcode_ptr_const, "CONST"); 312 writeSleb128(os, f->getTableIndex(), "offset"); 313 } else { 314 assert(isa<UndefinedData>(sym)); 315 continue; 316 } 317 writeU8(os, opcode_ptr_add, "ADD"); 318 writeU8(os, WASM_OPCODE_GLOBAL_SET, "GLOBAL_SET"); 319 writeUleb128(os, sym->getGOTIndex(), "got_entry"); 320 } 321 } 322 323 void GlobalSection::writeBody() { 324 raw_ostream &os = bodyOutputStream; 325 326 writeUleb128(os, numGlobals(), "global count"); 327 for (InputGlobal *g : inputGlobals) 328 writeGlobal(os, g->global); 329 // TODO(wvo): when do these need I64_CONST? 330 for (const Symbol *sym : internalGotSymbols) { 331 WasmGlobal global; 332 global.Type = {WASM_TYPE_I32, config->isPic}; 333 global.InitExpr.Opcode = WASM_OPCODE_I32_CONST; 334 if (auto *d = dyn_cast<DefinedData>(sym)) 335 global.InitExpr.Value.Int32 = d->getVirtualAddress(); 336 else if (auto *f = dyn_cast<FunctionSymbol>(sym)) 337 global.InitExpr.Value.Int32 = f->getTableIndex(); 338 else { 339 assert(isa<UndefinedData>(sym)); 340 global.InitExpr.Value.Int32 = 0; 341 } 342 writeGlobal(os, global); 343 } 344 for (const DefinedData *sym : dataAddressGlobals) { 345 WasmGlobal global; 346 global.Type = {WASM_TYPE_I32, false}; 347 global.InitExpr.Opcode = WASM_OPCODE_I32_CONST; 348 global.InitExpr.Value.Int32 = sym->getVirtualAddress(); 349 writeGlobal(os, global); 350 } 351 } 352 353 void GlobalSection::addGlobal(InputGlobal *global) { 354 assert(!isSealed); 355 if (!global->live) 356 return; 357 inputGlobals.push_back(global); 358 } 359 360 void ExportSection::writeBody() { 361 raw_ostream &os = bodyOutputStream; 362 363 writeUleb128(os, exports.size(), "export count"); 364 for (const WasmExport &export_ : exports) 365 writeExport(os, export_); 366 } 367 368 bool StartSection::isNeeded() const { 369 return !config->relocatable && hasInitializedSegments && config->sharedMemory; 370 } 371 372 void StartSection::writeBody() { 373 raw_ostream &os = bodyOutputStream; 374 writeUleb128(os, WasmSym::initMemory->getFunctionIndex(), "function index"); 375 } 376 377 void ElemSection::addEntry(FunctionSymbol *sym) { 378 if (sym->hasTableIndex()) 379 return; 380 sym->setTableIndex(config->tableBase + indirectFunctions.size()); 381 indirectFunctions.emplace_back(sym); 382 } 383 384 void ElemSection::writeBody() { 385 raw_ostream &os = bodyOutputStream; 386 387 writeUleb128(os, 1, "segment count"); 388 writeUleb128(os, 0, "table index"); 389 WasmInitExpr initExpr; 390 if (config->isPic) { 391 initExpr.Opcode = WASM_OPCODE_GLOBAL_GET; 392 initExpr.Value.Global = WasmSym::tableBase->getGlobalIndex(); 393 } else { 394 initExpr.Opcode = WASM_OPCODE_I32_CONST; 395 initExpr.Value.Int32 = config->tableBase; 396 } 397 writeInitExpr(os, initExpr); 398 writeUleb128(os, indirectFunctions.size(), "elem count"); 399 400 uint32_t tableIndex = config->tableBase; 401 for (const FunctionSymbol *sym : indirectFunctions) { 402 assert(sym->getTableIndex() == tableIndex); 403 writeUleb128(os, sym->getFunctionIndex(), "function index"); 404 ++tableIndex; 405 } 406 } 407 408 DataCountSection::DataCountSection(ArrayRef<OutputSegment *> segments) 409 : SyntheticSection(llvm::wasm::WASM_SEC_DATACOUNT), 410 numSegments(std::count_if( 411 segments.begin(), segments.end(), 412 [](OutputSegment *const segment) { return !segment->isBss; })) {} 413 414 void DataCountSection::writeBody() { 415 writeUleb128(bodyOutputStream, numSegments, "data count"); 416 } 417 418 bool DataCountSection::isNeeded() const { 419 return numSegments && config->sharedMemory; 420 } 421 422 void LinkingSection::writeBody() { 423 raw_ostream &os = bodyOutputStream; 424 425 writeUleb128(os, WasmMetadataVersion, "Version"); 426 427 if (!symtabEntries.empty()) { 428 SubSection sub(WASM_SYMBOL_TABLE); 429 writeUleb128(sub.os, symtabEntries.size(), "num symbols"); 430 431 for (const Symbol *sym : symtabEntries) { 432 assert(sym->isDefined() || sym->isUndefined()); 433 WasmSymbolType kind = sym->getWasmType(); 434 uint32_t flags = sym->flags; 435 436 writeU8(sub.os, kind, "sym kind"); 437 writeUleb128(sub.os, flags, "sym flags"); 438 439 if (auto *f = dyn_cast<FunctionSymbol>(sym)) { 440 writeUleb128(sub.os, f->getFunctionIndex(), "index"); 441 if (sym->isDefined() || (flags & WASM_SYMBOL_EXPLICIT_NAME) != 0) 442 writeStr(sub.os, sym->getName(), "sym name"); 443 } else if (auto *g = dyn_cast<GlobalSymbol>(sym)) { 444 writeUleb128(sub.os, g->getGlobalIndex(), "index"); 445 if (sym->isDefined() || (flags & WASM_SYMBOL_EXPLICIT_NAME) != 0) 446 writeStr(sub.os, sym->getName(), "sym name"); 447 } else if (auto *e = dyn_cast<EventSymbol>(sym)) { 448 writeUleb128(sub.os, e->getEventIndex(), "index"); 449 if (sym->isDefined() || (flags & WASM_SYMBOL_EXPLICIT_NAME) != 0) 450 writeStr(sub.os, sym->getName(), "sym name"); 451 } else if (isa<DataSymbol>(sym)) { 452 writeStr(sub.os, sym->getName(), "sym name"); 453 if (auto *dataSym = dyn_cast<DefinedData>(sym)) { 454 writeUleb128(sub.os, dataSym->getOutputSegmentIndex(), "index"); 455 writeUleb128(sub.os, dataSym->getOutputSegmentOffset(), 456 "data offset"); 457 writeUleb128(sub.os, dataSym->getSize(), "data size"); 458 } 459 } else { 460 auto *s = cast<OutputSectionSymbol>(sym); 461 writeUleb128(sub.os, s->section->sectionIndex, "sym section index"); 462 } 463 } 464 465 sub.writeTo(os); 466 } 467 468 if (dataSegments.size()) { 469 SubSection sub(WASM_SEGMENT_INFO); 470 writeUleb128(sub.os, dataSegments.size(), "num data segments"); 471 for (const OutputSegment *s : dataSegments) { 472 writeStr(sub.os, s->name, "segment name"); 473 writeUleb128(sub.os, s->alignment, "alignment"); 474 writeUleb128(sub.os, 0, "flags"); 475 } 476 sub.writeTo(os); 477 } 478 479 if (!initFunctions.empty()) { 480 SubSection sub(WASM_INIT_FUNCS); 481 writeUleb128(sub.os, initFunctions.size(), "num init functions"); 482 for (const WasmInitEntry &f : initFunctions) { 483 writeUleb128(sub.os, f.priority, "priority"); 484 writeUleb128(sub.os, f.sym->getOutputSymbolIndex(), "function index"); 485 } 486 sub.writeTo(os); 487 } 488 489 struct ComdatEntry { 490 unsigned kind; 491 uint32_t index; 492 }; 493 std::map<StringRef, std::vector<ComdatEntry>> comdats; 494 495 for (const InputFunction *f : out.functionSec->inputFunctions) { 496 StringRef comdat = f->getComdatName(); 497 if (!comdat.empty()) 498 comdats[comdat].emplace_back( 499 ComdatEntry{WASM_COMDAT_FUNCTION, f->getFunctionIndex()}); 500 } 501 for (uint32_t i = 0; i < dataSegments.size(); ++i) { 502 const auto &inputSegments = dataSegments[i]->inputSegments; 503 if (inputSegments.empty()) 504 continue; 505 StringRef comdat = inputSegments[0]->getComdatName(); 506 #ifndef NDEBUG 507 for (const InputSegment *isec : inputSegments) 508 assert(isec->getComdatName() == comdat); 509 #endif 510 if (!comdat.empty()) 511 comdats[comdat].emplace_back(ComdatEntry{WASM_COMDAT_DATA, i}); 512 } 513 514 if (!comdats.empty()) { 515 SubSection sub(WASM_COMDAT_INFO); 516 writeUleb128(sub.os, comdats.size(), "num comdats"); 517 for (const auto &c : comdats) { 518 writeStr(sub.os, c.first, "comdat name"); 519 writeUleb128(sub.os, 0, "comdat flags"); // flags for future use 520 writeUleb128(sub.os, c.second.size(), "num entries"); 521 for (const ComdatEntry &entry : c.second) { 522 writeU8(sub.os, entry.kind, "entry kind"); 523 writeUleb128(sub.os, entry.index, "entry index"); 524 } 525 } 526 sub.writeTo(os); 527 } 528 } 529 530 void LinkingSection::addToSymtab(Symbol *sym) { 531 sym->setOutputSymbolIndex(symtabEntries.size()); 532 symtabEntries.emplace_back(sym); 533 } 534 535 unsigned NameSection::numNamedFunctions() const { 536 unsigned numNames = out.importSec->getNumImportedFunctions(); 537 538 for (const InputFunction *f : out.functionSec->inputFunctions) 539 if (!f->getName().empty() || !f->getDebugName().empty()) 540 ++numNames; 541 542 return numNames; 543 } 544 545 unsigned NameSection::numNamedGlobals() const { 546 unsigned numNames = out.importSec->getNumImportedGlobals(); 547 548 for (const InputGlobal *g : out.globalSec->inputGlobals) 549 if (!g->getName().empty()) 550 ++numNames; 551 552 numNames += out.globalSec->internalGotSymbols.size(); 553 return numNames; 554 } 555 556 // Create the custom "name" section containing debug symbol names. 557 void NameSection::writeBody() { 558 unsigned count = numNamedFunctions(); 559 if (count) { 560 SubSection sub(WASM_NAMES_FUNCTION); 561 writeUleb128(sub.os, count, "name count"); 562 563 // Function names appear in function index order. As it happens 564 // importedSymbols and inputFunctions are numbered in order with imported 565 // functions coming first. 566 for (const Symbol *s : out.importSec->importedSymbols) { 567 if (auto *f = dyn_cast<FunctionSymbol>(s)) { 568 writeUleb128(sub.os, f->getFunctionIndex(), "func index"); 569 writeStr(sub.os, toString(*s), "symbol name"); 570 } 571 } 572 for (const InputFunction *f : out.functionSec->inputFunctions) { 573 if (!f->getName().empty()) { 574 writeUleb128(sub.os, f->getFunctionIndex(), "func index"); 575 if (!f->getDebugName().empty()) { 576 writeStr(sub.os, f->getDebugName(), "symbol name"); 577 } else { 578 writeStr(sub.os, maybeDemangleSymbol(f->getName()), "symbol name"); 579 } 580 } 581 } 582 sub.writeTo(bodyOutputStream); 583 } 584 585 count = numNamedGlobals(); 586 if (count) { 587 SubSection sub(WASM_NAMES_GLOBAL); 588 writeUleb128(sub.os, count, "name count"); 589 590 for (const Symbol *s : out.importSec->importedSymbols) { 591 if (auto *g = dyn_cast<GlobalSymbol>(s)) { 592 writeUleb128(sub.os, g->getGlobalIndex(), "global index"); 593 writeStr(sub.os, toString(*s), "symbol name"); 594 } 595 } 596 for (const Symbol *s : out.importSec->gotSymbols) { 597 writeUleb128(sub.os, s->getGOTIndex(), "global index"); 598 writeStr(sub.os, toString(*s), "symbol name"); 599 } 600 for (const InputGlobal *g : out.globalSec->inputGlobals) { 601 if (!g->getName().empty()) { 602 writeUleb128(sub.os, g->getGlobalIndex(), "global index"); 603 writeStr(sub.os, maybeDemangleSymbol(g->getName()), "symbol name"); 604 } 605 } 606 for (Symbol *s : out.globalSec->internalGotSymbols) { 607 writeUleb128(sub.os, s->getGOTIndex(), "global index"); 608 writeStr(sub.os, toString(*s), "symbol name"); 609 } 610 611 sub.writeTo(bodyOutputStream); 612 } 613 } 614 615 void ProducersSection::addInfo(const WasmProducerInfo &info) { 616 for (auto &producers : 617 {std::make_pair(&info.Languages, &languages), 618 std::make_pair(&info.Tools, &tools), std::make_pair(&info.SDKs, &sDKs)}) 619 for (auto &producer : *producers.first) 620 if (producers.second->end() == 621 llvm::find_if(*producers.second, 622 [&](std::pair<std::string, std::string> seen) { 623 return seen.first == producer.first; 624 })) 625 producers.second->push_back(producer); 626 } 627 628 void ProducersSection::writeBody() { 629 auto &os = bodyOutputStream; 630 writeUleb128(os, fieldCount(), "field count"); 631 for (auto &field : 632 {std::make_pair("language", languages), 633 std::make_pair("processed-by", tools), std::make_pair("sdk", sDKs)}) { 634 if (field.second.empty()) 635 continue; 636 writeStr(os, field.first, "field name"); 637 writeUleb128(os, field.second.size(), "number of entries"); 638 for (auto &entry : field.second) { 639 writeStr(os, entry.first, "producer name"); 640 writeStr(os, entry.second, "producer version"); 641 } 642 } 643 } 644 645 void TargetFeaturesSection::writeBody() { 646 SmallVector<std::string, 8> emitted(features.begin(), features.end()); 647 llvm::sort(emitted); 648 auto &os = bodyOutputStream; 649 writeUleb128(os, emitted.size(), "feature count"); 650 for (auto &feature : emitted) { 651 writeU8(os, WASM_FEATURE_PREFIX_USED, "feature used prefix"); 652 writeStr(os, feature, "feature name"); 653 } 654 } 655 656 void RelocSection::writeBody() { 657 uint32_t count = sec->getNumRelocations(); 658 assert(sec->sectionIndex != UINT32_MAX); 659 writeUleb128(bodyOutputStream, sec->sectionIndex, "reloc section"); 660 writeUleb128(bodyOutputStream, count, "reloc count"); 661 sec->writeRelocations(bodyOutputStream); 662 } 663 664 } // namespace wasm 665 } // namespace lld 666