1 //===- Writer.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 #include "Writer.h" 10 #include "Config.h" 11 #include "InputChunks.h" 12 #include "InputEvent.h" 13 #include "InputGlobal.h" 14 #include "OutputSections.h" 15 #include "OutputSegment.h" 16 #include "SymbolTable.h" 17 #include "WriterUtils.h" 18 #include "lld/Common/ErrorHandler.h" 19 #include "lld/Common/Memory.h" 20 #include "lld/Common/Strings.h" 21 #include "lld/Common/Threads.h" 22 #include "llvm/ADT/DenseSet.h" 23 #include "llvm/ADT/SmallVector.h" 24 #include "llvm/ADT/StringMap.h" 25 #include "llvm/BinaryFormat/Wasm.h" 26 #include "llvm/Object/WasmTraits.h" 27 #include "llvm/Support/FileOutputBuffer.h" 28 #include "llvm/Support/Format.h" 29 #include "llvm/Support/FormatVariadic.h" 30 #include "llvm/Support/LEB128.h" 31 32 #include <cstdarg> 33 #include <map> 34 35 #define DEBUG_TYPE "lld" 36 37 using namespace llvm; 38 using namespace llvm::wasm; 39 using namespace lld; 40 using namespace lld::wasm; 41 42 static constexpr int StackAlignment = 16; 43 static constexpr const char *FunctionTableName = "__indirect_function_table"; 44 const char *lld::wasm::DefaultModule = "env"; 45 46 namespace { 47 48 // An init entry to be written to either the synthetic init func or the 49 // linking metadata. 50 struct WasmInitEntry { 51 const FunctionSymbol *Sym; 52 uint32_t Priority; 53 }; 54 55 // The writer writes a SymbolTable result to a file. 56 class Writer { 57 public: 58 void run(); 59 60 private: 61 void openFile(); 62 63 uint32_t lookupType(const WasmSignature &Sig); 64 uint32_t registerType(const WasmSignature &Sig); 65 66 void createCtorFunction(); 67 void calculateInitFunctions(); 68 void assignIndexes(); 69 void calculateImports(); 70 void calculateExports(); 71 void calculateCustomSections(); 72 void assignSymtab(); 73 void calculateTypes(); 74 void createOutputSegments(); 75 void layoutMemory(); 76 void createHeader(); 77 void createSections(); 78 SyntheticSection *createSyntheticSection(uint32_t Type, StringRef Name = ""); 79 80 // Builtin sections 81 void createTypeSection(); 82 void createFunctionSection(); 83 void createTableSection(); 84 void createGlobalSection(); 85 void createEventSection(); 86 void createExportSection(); 87 void createImportSection(); 88 void createMemorySection(); 89 void createElemSection(); 90 void createCodeSection(); 91 void createDataSection(); 92 void createCustomSections(); 93 94 // Custom sections 95 void createDylinkSection(); 96 void createRelocSections(); 97 void createLinkingSection(); 98 void createNameSection(); 99 void createProducersSection(); 100 101 void writeHeader(); 102 void writeSections(); 103 104 uint64_t FileSize = 0; 105 uint32_t TableBase = 0; 106 uint32_t NumMemoryPages = 0; 107 uint32_t MaxMemoryPages = 0; 108 // Memory size and aligment. Written to the "dylink" section 109 // when build with -shared or -pie. 110 uint32_t MemAlign = 0; 111 uint32_t MemSize = 0; 112 113 std::vector<const WasmSignature *> Types; 114 DenseMap<WasmSignature, int32_t> TypeIndices; 115 std::vector<const Symbol *> ImportedSymbols; 116 unsigned NumImportedFunctions = 0; 117 unsigned NumImportedGlobals = 0; 118 unsigned NumImportedEvents = 0; 119 std::vector<WasmExport> Exports; 120 std::vector<const DefinedData *> DefinedFakeGlobals; 121 std::vector<InputGlobal *> InputGlobals; 122 std::vector<InputFunction *> InputFunctions; 123 std::vector<InputEvent *> InputEvents; 124 std::vector<const FunctionSymbol *> IndirectFunctions; 125 std::vector<const Symbol *> SymtabEntries; 126 std::vector<WasmInitEntry> InitFunctions; 127 128 llvm::StringMap<std::vector<InputSection *>> CustomSectionMapping; 129 llvm::StringMap<SectionSymbol *> CustomSectionSymbols; 130 131 // Elements that are used to construct the final output 132 std::string Header; 133 std::vector<OutputSection *> OutputSections; 134 135 std::unique_ptr<FileOutputBuffer> Buffer; 136 137 std::vector<OutputSegment *> Segments; 138 llvm::SmallDenseMap<StringRef, OutputSegment *> SegmentMap; 139 }; 140 141 } // anonymous namespace 142 143 void Writer::createImportSection() { 144 uint32_t NumImports = ImportedSymbols.size(); 145 if (Config->ImportMemory) 146 ++NumImports; 147 if (Config->ImportTable) 148 ++NumImports; 149 150 if (NumImports == 0) 151 return; 152 153 SyntheticSection *Section = createSyntheticSection(WASM_SEC_IMPORT); 154 raw_ostream &OS = Section->getStream(); 155 156 writeUleb128(OS, NumImports, "import count"); 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.Initial = NumMemoryPages; 165 if (MaxMemoryPages != 0) { 166 Import.Memory.Flags |= WASM_LIMITS_FLAG_HAS_MAX; 167 Import.Memory.Maximum = MaxMemoryPages; 168 } 169 if (Config->SharedMemory) 170 Import.Memory.Flags |= WASM_LIMITS_FLAG_IS_SHARED; 171 writeImport(OS, Import); 172 } 173 174 if (Config->ImportTable) { 175 uint32_t TableSize = TableBase + IndirectFunctions.size(); 176 WasmImport Import; 177 Import.Module = DefaultModule; 178 Import.Field = FunctionTableName; 179 Import.Kind = WASM_EXTERNAL_TABLE; 180 Import.Table.ElemType = WASM_TYPE_FUNCREF; 181 Import.Table.Limits = {0, TableSize, 0}; 182 writeImport(OS, Import); 183 } 184 185 for (const Symbol *Sym : ImportedSymbols) { 186 WasmImport Import; 187 if (auto *F = dyn_cast<UndefinedFunction>(Sym)) { 188 Import.Field = F->ImportName; 189 Import.Module = F->ImportModule; 190 } else if (auto *G = dyn_cast<UndefinedGlobal>(Sym)) { 191 Import.Field = G->ImportName; 192 Import.Module = G->ImportModule; 193 } else { 194 Import.Field = Sym->getName(); 195 Import.Module = DefaultModule; 196 } 197 198 if (auto *FunctionSym = dyn_cast<FunctionSymbol>(Sym)) { 199 Import.Kind = WASM_EXTERNAL_FUNCTION; 200 Import.SigIndex = lookupType(*FunctionSym->Signature); 201 } else if (auto *GlobalSym = dyn_cast<GlobalSymbol>(Sym)) { 202 Import.Kind = WASM_EXTERNAL_GLOBAL; 203 Import.Global = *GlobalSym->getGlobalType(); 204 } else { 205 auto *EventSym = cast<EventSymbol>(Sym); 206 Import.Kind = WASM_EXTERNAL_EVENT; 207 Import.Event.Attribute = EventSym->getEventType()->Attribute; 208 Import.Event.SigIndex = lookupType(*EventSym->Signature); 209 } 210 writeImport(OS, Import); 211 } 212 } 213 214 void Writer::createTypeSection() { 215 SyntheticSection *Section = createSyntheticSection(WASM_SEC_TYPE); 216 raw_ostream &OS = Section->getStream(); 217 writeUleb128(OS, Types.size(), "type count"); 218 for (const WasmSignature *Sig : Types) 219 writeSig(OS, *Sig); 220 } 221 222 void Writer::createFunctionSection() { 223 if (InputFunctions.empty()) 224 return; 225 226 SyntheticSection *Section = createSyntheticSection(WASM_SEC_FUNCTION); 227 raw_ostream &OS = Section->getStream(); 228 229 writeUleb128(OS, InputFunctions.size(), "function count"); 230 for (const InputFunction *Func : InputFunctions) 231 writeUleb128(OS, lookupType(Func->Signature), "sig index"); 232 } 233 234 void Writer::createMemorySection() { 235 if (Config->ImportMemory) 236 return; 237 238 SyntheticSection *Section = createSyntheticSection(WASM_SEC_MEMORY); 239 raw_ostream &OS = Section->getStream(); 240 241 bool HasMax = MaxMemoryPages != 0; 242 writeUleb128(OS, 1, "memory count"); 243 unsigned Flags = 0; 244 if (HasMax) 245 Flags |= WASM_LIMITS_FLAG_HAS_MAX; 246 if (Config->SharedMemory) 247 Flags |= WASM_LIMITS_FLAG_IS_SHARED; 248 writeUleb128(OS, Flags, "memory limits flags"); 249 writeUleb128(OS, NumMemoryPages, "initial pages"); 250 if (HasMax) 251 writeUleb128(OS, MaxMemoryPages, "max pages"); 252 } 253 254 void Writer::createGlobalSection() { 255 unsigned NumGlobals = InputGlobals.size() + DefinedFakeGlobals.size(); 256 if (NumGlobals == 0) 257 return; 258 259 SyntheticSection *Section = createSyntheticSection(WASM_SEC_GLOBAL); 260 raw_ostream &OS = Section->getStream(); 261 262 writeUleb128(OS, NumGlobals, "global count"); 263 for (const InputGlobal *G : InputGlobals) 264 writeGlobal(OS, G->Global); 265 for (const DefinedData *Sym : DefinedFakeGlobals) { 266 WasmGlobal Global; 267 Global.Type = {WASM_TYPE_I32, false}; 268 Global.InitExpr.Opcode = WASM_OPCODE_I32_CONST; 269 Global.InitExpr.Value.Int32 = Sym->getVirtualAddress(); 270 writeGlobal(OS, Global); 271 } 272 } 273 274 // The event section contains a list of declared wasm events associated with the 275 // module. Currently the only supported event kind is exceptions. A single event 276 // entry represents a single event with an event tag. All C++ exceptions are 277 // represented by a single event. An event entry in this section contains 278 // information on what kind of event it is (e.g. exception) and the type of 279 // values contained in a single event object. (In wasm, an event can contain 280 // multiple values of primitive types. But for C++ exceptions, we just throw a 281 // pointer which is an i32 value (for wasm32 architecture), so the signature of 282 // C++ exception is (i32)->(void), because all event types are assumed to have 283 // void return type to share WasmSignature with functions.) 284 void Writer::createEventSection() { 285 unsigned NumEvents = InputEvents.size(); 286 if (NumEvents == 0) 287 return; 288 289 SyntheticSection *Section = createSyntheticSection(WASM_SEC_EVENT); 290 raw_ostream &OS = Section->getStream(); 291 292 writeUleb128(OS, NumEvents, "event count"); 293 for (InputEvent *E : InputEvents) { 294 E->Event.Type.SigIndex = lookupType(E->Signature); 295 writeEvent(OS, E->Event); 296 } 297 } 298 299 void Writer::createTableSection() { 300 if (Config->ImportTable) 301 return; 302 303 // Always output a table section (or table import), even if there are no 304 // indirect calls. There are two reasons for this: 305 // 1. For executables it is useful to have an empty table slot at 0 306 // which can be filled with a null function call handler. 307 // 2. If we don't do this, any program that contains a call_indirect but 308 // no address-taken function will fail at validation time since it is 309 // a validation error to include a call_indirect instruction if there 310 // is not table. 311 uint32_t TableSize = TableBase + IndirectFunctions.size(); 312 313 SyntheticSection *Section = createSyntheticSection(WASM_SEC_TABLE); 314 raw_ostream &OS = Section->getStream(); 315 316 writeUleb128(OS, 1, "table count"); 317 WasmLimits Limits = {WASM_LIMITS_FLAG_HAS_MAX, TableSize, TableSize}; 318 writeTableType(OS, WasmTable{WASM_TYPE_FUNCREF, Limits}); 319 } 320 321 void Writer::createExportSection() { 322 if (!Exports.size()) 323 return; 324 325 SyntheticSection *Section = createSyntheticSection(WASM_SEC_EXPORT); 326 raw_ostream &OS = Section->getStream(); 327 328 writeUleb128(OS, Exports.size(), "export count"); 329 for (const WasmExport &Export : Exports) 330 writeExport(OS, Export); 331 } 332 333 void Writer::calculateCustomSections() { 334 log("calculateCustomSections"); 335 bool StripDebug = Config->StripDebug || Config->StripAll; 336 for (ObjFile *File : Symtab->ObjectFiles) { 337 for (InputSection *Section : File->CustomSections) { 338 StringRef Name = Section->getName(); 339 // These custom sections are known the linker and synthesized rather than 340 // blindly copied 341 if (Name == "linking" || Name == "name" || Name == "producers" || 342 Name.startswith("reloc.")) 343 continue; 344 // .. or it is a debug section 345 if (StripDebug && Name.startswith(".debug_")) 346 continue; 347 CustomSectionMapping[Name].push_back(Section); 348 } 349 } 350 } 351 352 void Writer::createCustomSections() { 353 log("createCustomSections"); 354 for (auto &Pair : CustomSectionMapping) { 355 StringRef Name = Pair.first(); 356 357 auto P = CustomSectionSymbols.find(Name); 358 if (P != CustomSectionSymbols.end()) { 359 uint32_t SectionIndex = OutputSections.size(); 360 P->second->setOutputSectionIndex(SectionIndex); 361 } 362 363 LLVM_DEBUG(dbgs() << "createCustomSection: " << Name << "\n"); 364 OutputSections.push_back(make<CustomSection>(Name, Pair.second)); 365 } 366 } 367 368 void Writer::createElemSection() { 369 if (IndirectFunctions.empty()) 370 return; 371 372 SyntheticSection *Section = createSyntheticSection(WASM_SEC_ELEM); 373 raw_ostream &OS = Section->getStream(); 374 375 writeUleb128(OS, 1, "segment count"); 376 writeUleb128(OS, 0, "table index"); 377 WasmInitExpr InitExpr; 378 if (Config->Pic) { 379 InitExpr.Opcode = WASM_OPCODE_GLOBAL_GET; 380 InitExpr.Value.Global = WasmSym::TableBase->getGlobalIndex(); 381 } else { 382 InitExpr.Opcode = WASM_OPCODE_I32_CONST; 383 InitExpr.Value.Int32 = TableBase; 384 } 385 writeInitExpr(OS, InitExpr); 386 writeUleb128(OS, IndirectFunctions.size(), "elem count"); 387 388 uint32_t TableIndex = TableBase; 389 for (const FunctionSymbol *Sym : IndirectFunctions) { 390 assert(Sym->getTableIndex() == TableIndex); 391 writeUleb128(OS, Sym->getFunctionIndex(), "function index"); 392 ++TableIndex; 393 } 394 } 395 396 void Writer::createCodeSection() { 397 if (InputFunctions.empty()) 398 return; 399 400 log("createCodeSection"); 401 402 auto Section = make<CodeSection>(InputFunctions); 403 OutputSections.push_back(Section); 404 } 405 406 void Writer::createDataSection() { 407 if (!Segments.size()) 408 return; 409 410 log("createDataSection"); 411 auto Section = make<DataSection>(Segments); 412 OutputSections.push_back(Section); 413 } 414 415 // Create relocations sections in the final output. 416 // These are only created when relocatable output is requested. 417 void Writer::createRelocSections() { 418 log("createRelocSections"); 419 // Don't use iterator here since we are adding to OutputSection 420 size_t OrigSize = OutputSections.size(); 421 for (size_t I = 0; I < OrigSize; I++) { 422 OutputSection *OSec = OutputSections[I]; 423 uint32_t Count = OSec->numRelocations(); 424 if (!Count) 425 continue; 426 427 StringRef Name; 428 if (OSec->Type == WASM_SEC_DATA) 429 Name = "reloc.DATA"; 430 else if (OSec->Type == WASM_SEC_CODE) 431 Name = "reloc.CODE"; 432 else if (OSec->Type == WASM_SEC_CUSTOM) 433 Name = Saver.save("reloc." + OSec->Name); 434 else 435 llvm_unreachable( 436 "relocations only supported for code, data, or custom sections"); 437 438 SyntheticSection *Section = createSyntheticSection(WASM_SEC_CUSTOM, Name); 439 raw_ostream &OS = Section->getStream(); 440 writeUleb128(OS, I, "reloc section"); 441 writeUleb128(OS, Count, "reloc count"); 442 OSec->writeRelocations(OS); 443 } 444 } 445 446 static uint32_t getWasmFlags(const Symbol *Sym) { 447 uint32_t Flags = 0; 448 if (Sym->isLocal()) 449 Flags |= WASM_SYMBOL_BINDING_LOCAL; 450 if (Sym->isWeak()) 451 Flags |= WASM_SYMBOL_BINDING_WEAK; 452 if (Sym->isHidden()) 453 Flags |= WASM_SYMBOL_VISIBILITY_HIDDEN; 454 if (Sym->isUndefined()) 455 Flags |= WASM_SYMBOL_UNDEFINED; 456 if (auto *F = dyn_cast<UndefinedFunction>(Sym)) { 457 if (F->getName() != F->ImportName) 458 Flags |= WASM_SYMBOL_EXPLICIT_NAME; 459 } else if (auto *G = dyn_cast<UndefinedGlobal>(Sym)) { 460 if (G->getName() != G->ImportName) 461 Flags |= WASM_SYMBOL_EXPLICIT_NAME; 462 } 463 return Flags; 464 } 465 466 // Some synthetic sections (e.g. "name" and "linking") have subsections. 467 // Just like the synthetic sections themselves these need to be created before 468 // they can be written out (since they are preceded by their length). This 469 // class is used to create subsections and then write them into the stream 470 // of the parent section. 471 class SubSection { 472 public: 473 explicit SubSection(uint32_t Type) : Type(Type) {} 474 475 void writeTo(raw_ostream &To) { 476 OS.flush(); 477 writeUleb128(To, Type, "subsection type"); 478 writeUleb128(To, Body.size(), "subsection size"); 479 To.write(Body.data(), Body.size()); 480 } 481 482 private: 483 uint32_t Type; 484 std::string Body; 485 486 public: 487 raw_string_ostream OS{Body}; 488 }; 489 490 // Create the custom "dylink" section containing information for the dynamic 491 // linker. 492 // See 493 // https://github.com/WebAssembly/tool-conventions/blob/master/DynamicLinking.md 494 void Writer::createDylinkSection() { 495 SyntheticSection *Section = createSyntheticSection(WASM_SEC_CUSTOM, "dylink"); 496 raw_ostream &OS = Section->getStream(); 497 498 writeUleb128(OS, MemSize, "MemSize"); 499 writeUleb128(OS, MemAlign, "MemAlign"); 500 writeUleb128(OS, IndirectFunctions.size(), "TableSize"); 501 writeUleb128(OS, 0, "TableAlign"); 502 writeUleb128(OS, 0, "Needed"); // TODO: Support "needed" shared libraries 503 } 504 505 // Create the custom "linking" section containing linker metadata. 506 // This is only created when relocatable output is requested. 507 void Writer::createLinkingSection() { 508 SyntheticSection *Section = 509 createSyntheticSection(WASM_SEC_CUSTOM, "linking"); 510 raw_ostream &OS = Section->getStream(); 511 512 writeUleb128(OS, WasmMetadataVersion, "Version"); 513 514 if (!SymtabEntries.empty()) { 515 SubSection Sub(WASM_SYMBOL_TABLE); 516 writeUleb128(Sub.OS, SymtabEntries.size(), "num symbols"); 517 518 for (const Symbol *Sym : SymtabEntries) { 519 assert(Sym->isDefined() || Sym->isUndefined()); 520 WasmSymbolType Kind = Sym->getWasmType(); 521 uint32_t Flags = getWasmFlags(Sym); 522 523 writeU8(Sub.OS, Kind, "sym kind"); 524 writeUleb128(Sub.OS, Flags, "sym flags"); 525 526 if (auto *F = dyn_cast<FunctionSymbol>(Sym)) { 527 writeUleb128(Sub.OS, F->getFunctionIndex(), "index"); 528 if (Sym->isDefined() || 529 (Flags & WASM_SYMBOL_EXPLICIT_NAME) != 0) 530 writeStr(Sub.OS, Sym->getName(), "sym name"); 531 } else if (auto *G = dyn_cast<GlobalSymbol>(Sym)) { 532 writeUleb128(Sub.OS, G->getGlobalIndex(), "index"); 533 if (Sym->isDefined() || 534 (Flags & WASM_SYMBOL_EXPLICIT_NAME) != 0) 535 writeStr(Sub.OS, Sym->getName(), "sym name"); 536 } else if (auto *E = dyn_cast<EventSymbol>(Sym)) { 537 writeUleb128(Sub.OS, E->getEventIndex(), "index"); 538 if (Sym->isDefined() || 539 (Flags & WASM_SYMBOL_EXPLICIT_NAME) != 0) 540 writeStr(Sub.OS, Sym->getName(), "sym name"); 541 } else if (isa<DataSymbol>(Sym)) { 542 writeStr(Sub.OS, Sym->getName(), "sym name"); 543 if (auto *DataSym = dyn_cast<DefinedData>(Sym)) { 544 writeUleb128(Sub.OS, DataSym->getOutputSegmentIndex(), "index"); 545 writeUleb128(Sub.OS, DataSym->getOutputSegmentOffset(), 546 "data offset"); 547 writeUleb128(Sub.OS, DataSym->getSize(), "data size"); 548 } 549 } else { 550 auto *S = cast<SectionSymbol>(Sym); 551 writeUleb128(Sub.OS, S->getOutputSectionIndex(), "sym section index"); 552 } 553 } 554 555 Sub.writeTo(OS); 556 } 557 558 if (Segments.size()) { 559 SubSection Sub(WASM_SEGMENT_INFO); 560 writeUleb128(Sub.OS, Segments.size(), "num data segments"); 561 for (const OutputSegment *S : Segments) { 562 writeStr(Sub.OS, S->Name, "segment name"); 563 writeUleb128(Sub.OS, S->Alignment, "alignment"); 564 writeUleb128(Sub.OS, 0, "flags"); 565 } 566 Sub.writeTo(OS); 567 } 568 569 if (!InitFunctions.empty()) { 570 SubSection Sub(WASM_INIT_FUNCS); 571 writeUleb128(Sub.OS, InitFunctions.size(), "num init functions"); 572 for (const WasmInitEntry &F : InitFunctions) { 573 writeUleb128(Sub.OS, F.Priority, "priority"); 574 writeUleb128(Sub.OS, F.Sym->getOutputSymbolIndex(), "function index"); 575 } 576 Sub.writeTo(OS); 577 } 578 579 struct ComdatEntry { 580 unsigned Kind; 581 uint32_t Index; 582 }; 583 std::map<StringRef, std::vector<ComdatEntry>> Comdats; 584 585 for (const InputFunction *F : InputFunctions) { 586 StringRef Comdat = F->getComdatName(); 587 if (!Comdat.empty()) 588 Comdats[Comdat].emplace_back( 589 ComdatEntry{WASM_COMDAT_FUNCTION, F->getFunctionIndex()}); 590 } 591 for (uint32_t I = 0; I < Segments.size(); ++I) { 592 const auto &InputSegments = Segments[I]->InputSegments; 593 if (InputSegments.empty()) 594 continue; 595 StringRef Comdat = InputSegments[0]->getComdatName(); 596 #ifndef NDEBUG 597 for (const InputSegment *IS : InputSegments) 598 assert(IS->getComdatName() == Comdat); 599 #endif 600 if (!Comdat.empty()) 601 Comdats[Comdat].emplace_back(ComdatEntry{WASM_COMDAT_DATA, I}); 602 } 603 604 if (!Comdats.empty()) { 605 SubSection Sub(WASM_COMDAT_INFO); 606 writeUleb128(Sub.OS, Comdats.size(), "num comdats"); 607 for (const auto &C : Comdats) { 608 writeStr(Sub.OS, C.first, "comdat name"); 609 writeUleb128(Sub.OS, 0, "comdat flags"); // flags for future use 610 writeUleb128(Sub.OS, C.second.size(), "num entries"); 611 for (const ComdatEntry &Entry : C.second) { 612 writeU8(Sub.OS, Entry.Kind, "entry kind"); 613 writeUleb128(Sub.OS, Entry.Index, "entry index"); 614 } 615 } 616 Sub.writeTo(OS); 617 } 618 } 619 620 // Create the custom "name" section containing debug symbol names. 621 void Writer::createNameSection() { 622 unsigned NumNames = NumImportedFunctions; 623 for (const InputFunction *F : InputFunctions) 624 if (!F->getName().empty() || !F->getDebugName().empty()) 625 ++NumNames; 626 627 if (NumNames == 0) 628 return; 629 630 SyntheticSection *Section = createSyntheticSection(WASM_SEC_CUSTOM, "name"); 631 632 SubSection Sub(WASM_NAMES_FUNCTION); 633 writeUleb128(Sub.OS, NumNames, "name count"); 634 635 // Names must appear in function index order. As it happens ImportedSymbols 636 // and InputFunctions are numbered in order with imported functions coming 637 // first. 638 for (const Symbol *S : ImportedSymbols) { 639 if (auto *F = dyn_cast<FunctionSymbol>(S)) { 640 writeUleb128(Sub.OS, F->getFunctionIndex(), "func index"); 641 writeStr(Sub.OS, toString(*S), "symbol name"); 642 } 643 } 644 for (const InputFunction *F : InputFunctions) { 645 if (!F->getName().empty()) { 646 writeUleb128(Sub.OS, F->getFunctionIndex(), "func index"); 647 if (!F->getDebugName().empty()) { 648 writeStr(Sub.OS, F->getDebugName(), "symbol name"); 649 } else { 650 writeStr(Sub.OS, maybeDemangleSymbol(F->getName()), "symbol name"); 651 } 652 } 653 } 654 655 Sub.writeTo(Section->getStream()); 656 } 657 658 void Writer::createProducersSection() { 659 SmallVector<std::pair<std::string, std::string>, 8> Languages; 660 SmallVector<std::pair<std::string, std::string>, 8> Tools; 661 SmallVector<std::pair<std::string, std::string>, 8> SDKs; 662 for (ObjFile *File : Symtab->ObjectFiles) { 663 const WasmProducerInfo &Info = File->getWasmObj()->getProducerInfo(); 664 for (auto &Producers : {std::make_pair(&Info.Languages, &Languages), 665 std::make_pair(&Info.Tools, &Tools), 666 std::make_pair(&Info.SDKs, &SDKs)}) 667 for (auto &Producer : *Producers.first) 668 if (Producers.second->end() == 669 std::find_if(Producers.second->begin(), Producers.second->end(), 670 [&](std::pair<std::string, std::string> Seen) { 671 return Seen.first == Producer.first; 672 })) 673 Producers.second->push_back(Producer); 674 } 675 int FieldCount = 676 int(!Languages.empty()) + int(!Tools.empty()) + int(!SDKs.empty()); 677 if (FieldCount == 0) 678 return; 679 SyntheticSection *Section = 680 createSyntheticSection(WASM_SEC_CUSTOM, "producers"); 681 auto &OS = Section->getStream(); 682 writeUleb128(OS, FieldCount, "field count"); 683 for (auto &Field : 684 {std::make_pair("language", Languages), 685 std::make_pair("processed-by", Tools), std::make_pair("sdk", SDKs)}) { 686 if (Field.second.empty()) 687 continue; 688 writeStr(OS, Field.first, "field name"); 689 writeUleb128(OS, Field.second.size(), "number of entries"); 690 for (auto &Entry : Field.second) { 691 writeStr(OS, Entry.first, "producer name"); 692 writeStr(OS, Entry.second, "producer version"); 693 } 694 } 695 } 696 697 void Writer::writeHeader() { 698 memcpy(Buffer->getBufferStart(), Header.data(), Header.size()); 699 } 700 701 void Writer::writeSections() { 702 uint8_t *Buf = Buffer->getBufferStart(); 703 parallelForEach(OutputSections, [Buf](OutputSection *S) { S->writeTo(Buf); }); 704 } 705 706 // Fix the memory layout of the output binary. This assigns memory offsets 707 // to each of the input data sections as well as the explicit stack region. 708 // The default memory layout is as follows, from low to high. 709 // 710 // - initialized data (starting at Config->GlobalBase) 711 // - BSS data (not currently implemented in llvm) 712 // - explicit stack (Config->ZStackSize) 713 // - heap start / unallocated 714 // 715 // The --stack-first option means that stack is placed before any static data. 716 // This can be useful since it means that stack overflow traps immediately 717 // rather than overwriting global data, but also increases code size since all 718 // static data loads and stores requires larger offsets. 719 void Writer::layoutMemory() { 720 createOutputSegments(); 721 722 uint32_t MemoryPtr = 0; 723 724 auto PlaceStack = [&]() { 725 if (Config->Relocatable || Config->Shared) 726 return; 727 MemoryPtr = alignTo(MemoryPtr, StackAlignment); 728 if (Config->ZStackSize != alignTo(Config->ZStackSize, StackAlignment)) 729 error("stack size must be " + Twine(StackAlignment) + "-byte aligned"); 730 log("mem: stack size = " + Twine(Config->ZStackSize)); 731 log("mem: stack base = " + Twine(MemoryPtr)); 732 MemoryPtr += Config->ZStackSize; 733 auto *SP = cast<DefinedGlobal>(WasmSym::StackPointer); 734 SP->Global->Global.InitExpr.Value.Int32 = MemoryPtr; 735 log("mem: stack top = " + Twine(MemoryPtr)); 736 }; 737 738 if (Config->StackFirst) { 739 PlaceStack(); 740 } else { 741 MemoryPtr = Config->GlobalBase; 742 log("mem: global base = " + Twine(Config->GlobalBase)); 743 } 744 745 uint32_t DataStart = MemoryPtr; 746 747 // Arbitrarily set __dso_handle handle to point to the start of the data 748 // segments. 749 if (WasmSym::DsoHandle) 750 WasmSym::DsoHandle->setVirtualAddress(DataStart); 751 752 MemAlign = 0; 753 for (OutputSegment *Seg : Segments) { 754 MemAlign = std::max(MemAlign, Seg->Alignment); 755 MemoryPtr = alignTo(MemoryPtr, 1ULL << Seg->Alignment); 756 Seg->StartVA = MemoryPtr; 757 log(formatv("mem: {0,-15} offset={1,-8} size={2,-8} align={3}", Seg->Name, 758 MemoryPtr, Seg->Size, Seg->Alignment)); 759 MemoryPtr += Seg->Size; 760 } 761 762 // TODO: Add .bss space here. 763 if (WasmSym::DataEnd) 764 WasmSym::DataEnd->setVirtualAddress(MemoryPtr); 765 766 log("mem: static data = " + Twine(MemoryPtr - DataStart)); 767 768 if (Config->Shared) { 769 MemSize = MemoryPtr; 770 return; 771 } 772 773 if (!Config->StackFirst) 774 PlaceStack(); 775 776 // Set `__heap_base` to directly follow the end of the stack or global data. 777 // The fact that this comes last means that a malloc/brk implementation 778 // can grow the heap at runtime. 779 if (!Config->Relocatable) { 780 WasmSym::HeapBase->setVirtualAddress(MemoryPtr); 781 log("mem: heap base = " + Twine(MemoryPtr)); 782 } 783 784 if (Config->InitialMemory != 0) { 785 if (Config->InitialMemory != alignTo(Config->InitialMemory, WasmPageSize)) 786 error("initial memory must be " + Twine(WasmPageSize) + "-byte aligned"); 787 if (MemoryPtr > Config->InitialMemory) 788 error("initial memory too small, " + Twine(MemoryPtr) + " bytes needed"); 789 else 790 MemoryPtr = Config->InitialMemory; 791 } 792 MemSize = MemoryPtr; 793 NumMemoryPages = alignTo(MemoryPtr, WasmPageSize) / WasmPageSize; 794 log("mem: total pages = " + Twine(NumMemoryPages)); 795 796 if (Config->MaxMemory != 0) { 797 if (Config->MaxMemory != alignTo(Config->MaxMemory, WasmPageSize)) 798 error("maximum memory must be " + Twine(WasmPageSize) + "-byte aligned"); 799 if (MemoryPtr > Config->MaxMemory) 800 error("maximum memory too small, " + Twine(MemoryPtr) + " bytes needed"); 801 MaxMemoryPages = Config->MaxMemory / WasmPageSize; 802 log("mem: max pages = " + Twine(MaxMemoryPages)); 803 } 804 } 805 806 SyntheticSection *Writer::createSyntheticSection(uint32_t Type, 807 StringRef Name) { 808 auto Sec = make<SyntheticSection>(Type, Name); 809 log("createSection: " + toString(*Sec)); 810 OutputSections.push_back(Sec); 811 return Sec; 812 } 813 814 void Writer::createSections() { 815 // Known sections 816 if (Config->Pic) 817 createDylinkSection(); 818 createTypeSection(); 819 createImportSection(); 820 createFunctionSection(); 821 createTableSection(); 822 createMemorySection(); 823 createGlobalSection(); 824 createEventSection(); 825 createExportSection(); 826 createElemSection(); 827 createCodeSection(); 828 createDataSection(); 829 createCustomSections(); 830 831 // Custom sections 832 if (Config->Relocatable) { 833 createLinkingSection(); 834 createRelocSections(); 835 } 836 837 if (!Config->StripDebug && !Config->StripAll) 838 createNameSection(); 839 840 if (!Config->StripAll) 841 createProducersSection(); 842 843 for (OutputSection *S : OutputSections) { 844 S->setOffset(FileSize); 845 S->finalizeContents(); 846 FileSize += S->getSize(); 847 } 848 } 849 850 void Writer::calculateImports() { 851 for (Symbol *Sym : Symtab->getSymbols()) { 852 if (!Sym->isUndefined()) 853 continue; 854 if (isa<DataSymbol>(Sym)) 855 continue; 856 if (Sym->isWeak() && !Config->Relocatable) 857 continue; 858 if (!Sym->isLive()) 859 continue; 860 if (!Sym->IsUsedInRegularObj) 861 continue; 862 863 LLVM_DEBUG(dbgs() << "import: " << Sym->getName() << "\n"); 864 ImportedSymbols.emplace_back(Sym); 865 if (auto *F = dyn_cast<FunctionSymbol>(Sym)) 866 F->setFunctionIndex(NumImportedFunctions++); 867 else if (auto *G = dyn_cast<GlobalSymbol>(Sym)) 868 G->setGlobalIndex(NumImportedGlobals++); 869 else 870 cast<EventSymbol>(Sym)->setEventIndex(NumImportedEvents++); 871 } 872 } 873 874 void Writer::calculateExports() { 875 if (Config->Relocatable) 876 return; 877 878 if (!Config->Relocatable && !Config->ImportMemory) 879 Exports.push_back(WasmExport{"memory", WASM_EXTERNAL_MEMORY, 0}); 880 881 if (!Config->Relocatable && Config->ExportTable) 882 Exports.push_back(WasmExport{FunctionTableName, WASM_EXTERNAL_TABLE, 0}); 883 884 unsigned FakeGlobalIndex = NumImportedGlobals + InputGlobals.size(); 885 886 for (Symbol *Sym : Symtab->getSymbols()) { 887 if (!Sym->isExported()) 888 continue; 889 if (!Sym->isLive()) 890 continue; 891 892 StringRef Name = Sym->getName(); 893 WasmExport Export; 894 if (auto *F = dyn_cast<DefinedFunction>(Sym)) { 895 Export = {Name, WASM_EXTERNAL_FUNCTION, F->getFunctionIndex()}; 896 } else if (auto *G = dyn_cast<DefinedGlobal>(Sym)) { 897 // TODO(sbc): Remove this check once to mutable global proposal is 898 // implement in all major browsers. 899 // See: https://github.com/WebAssembly/mutable-global 900 if (G->getGlobalType()->Mutable) { 901 // Only the __stack_pointer should ever be create as mutable. 902 assert(G == WasmSym::StackPointer); 903 continue; 904 } 905 Export = {Name, WASM_EXTERNAL_GLOBAL, G->getGlobalIndex()}; 906 } else if (auto *E = dyn_cast<DefinedEvent>(Sym)) { 907 Export = {Name, WASM_EXTERNAL_EVENT, E->getEventIndex()}; 908 } else { 909 auto *D = cast<DefinedData>(Sym); 910 DefinedFakeGlobals.emplace_back(D); 911 Export = {Name, WASM_EXTERNAL_GLOBAL, FakeGlobalIndex++}; 912 } 913 914 LLVM_DEBUG(dbgs() << "Export: " << Name << "\n"); 915 Exports.push_back(Export); 916 } 917 } 918 919 void Writer::assignSymtab() { 920 if (!Config->Relocatable) 921 return; 922 923 StringMap<uint32_t> SectionSymbolIndices; 924 925 unsigned SymbolIndex = SymtabEntries.size(); 926 927 auto AddSymbol = [&](Symbol *Sym) { 928 if (auto *S = dyn_cast<SectionSymbol>(Sym)) { 929 StringRef Name = S->getName(); 930 if (CustomSectionMapping.count(Name) == 0) 931 return; 932 933 auto SSI = SectionSymbolIndices.find(Name); 934 if (SSI != SectionSymbolIndices.end()) { 935 Sym->setOutputSymbolIndex(SSI->second); 936 return; 937 } 938 939 SectionSymbolIndices[Name] = SymbolIndex; 940 CustomSectionSymbols[Name] = cast<SectionSymbol>(Sym); 941 942 Sym->markLive(); 943 } 944 945 // (Since this is relocatable output, GC is not performed so symbols must 946 // be live.) 947 assert(Sym->isLive()); 948 Sym->setOutputSymbolIndex(SymbolIndex++); 949 SymtabEntries.emplace_back(Sym); 950 }; 951 952 for (Symbol *Sym : Symtab->getSymbols()) 953 if (!Sym->isLazy()) 954 AddSymbol(Sym); 955 956 for (ObjFile *File : Symtab->ObjectFiles) { 957 LLVM_DEBUG(dbgs() << "Local symtab entries: " << File->getName() << "\n"); 958 for (Symbol *Sym : File->getSymbols()) 959 if (Sym->isLocal()) 960 AddSymbol(Sym); 961 } 962 } 963 964 uint32_t Writer::lookupType(const WasmSignature &Sig) { 965 auto It = TypeIndices.find(Sig); 966 if (It == TypeIndices.end()) { 967 error("type not found: " + toString(Sig)); 968 return 0; 969 } 970 return It->second; 971 } 972 973 uint32_t Writer::registerType(const WasmSignature &Sig) { 974 auto Pair = TypeIndices.insert(std::make_pair(Sig, Types.size())); 975 if (Pair.second) { 976 LLVM_DEBUG(dbgs() << "type " << toString(Sig) << "\n"); 977 Types.push_back(&Sig); 978 } 979 return Pair.first->second; 980 } 981 982 void Writer::calculateTypes() { 983 // The output type section is the union of the following sets: 984 // 1. Any signature used in the TYPE relocation 985 // 2. The signatures of all imported functions 986 // 3. The signatures of all defined functions 987 // 4. The signatures of all imported events 988 // 5. The signatures of all defined events 989 990 for (ObjFile *File : Symtab->ObjectFiles) { 991 ArrayRef<WasmSignature> Types = File->getWasmObj()->types(); 992 for (uint32_t I = 0; I < Types.size(); I++) 993 if (File->TypeIsUsed[I]) 994 File->TypeMap[I] = registerType(Types[I]); 995 } 996 997 for (const Symbol *Sym : ImportedSymbols) { 998 if (auto *F = dyn_cast<FunctionSymbol>(Sym)) 999 registerType(*F->Signature); 1000 else if (auto *E = dyn_cast<EventSymbol>(Sym)) 1001 registerType(*E->Signature); 1002 } 1003 1004 for (const InputFunction *F : InputFunctions) 1005 registerType(F->Signature); 1006 1007 for (const InputEvent *E : InputEvents) 1008 registerType(E->Signature); 1009 } 1010 1011 void Writer::assignIndexes() { 1012 assert(InputFunctions.empty()); 1013 uint32_t FunctionIndex = NumImportedFunctions; 1014 auto AddDefinedFunction = [&](InputFunction *Func) { 1015 if (!Func->Live) 1016 return; 1017 InputFunctions.emplace_back(Func); 1018 Func->setFunctionIndex(FunctionIndex++); 1019 }; 1020 1021 for (InputFunction *Func : Symtab->SyntheticFunctions) 1022 AddDefinedFunction(Func); 1023 1024 for (ObjFile *File : Symtab->ObjectFiles) { 1025 LLVM_DEBUG(dbgs() << "Functions: " << File->getName() << "\n"); 1026 for (InputFunction *Func : File->Functions) 1027 AddDefinedFunction(Func); 1028 } 1029 1030 uint32_t TableIndex = TableBase; 1031 auto HandleRelocs = [&](InputChunk *Chunk) { 1032 if (!Chunk->Live) 1033 return; 1034 ObjFile *File = Chunk->File; 1035 ArrayRef<WasmSignature> Types = File->getWasmObj()->types(); 1036 for (const WasmRelocation &Reloc : Chunk->getRelocations()) { 1037 if (Reloc.Type == R_WASM_TABLE_INDEX_I32 || 1038 Reloc.Type == R_WASM_TABLE_INDEX_SLEB) { 1039 FunctionSymbol *Sym = File->getFunctionSymbol(Reloc.Index); 1040 if (Sym->hasTableIndex() || !Sym->hasFunctionIndex()) 1041 continue; 1042 Sym->setTableIndex(TableIndex++); 1043 IndirectFunctions.emplace_back(Sym); 1044 } else if (Reloc.Type == R_WASM_TYPE_INDEX_LEB) { 1045 // Mark target type as live 1046 File->TypeMap[Reloc.Index] = registerType(Types[Reloc.Index]); 1047 File->TypeIsUsed[Reloc.Index] = true; 1048 } 1049 } 1050 }; 1051 1052 for (ObjFile *File : Symtab->ObjectFiles) { 1053 LLVM_DEBUG(dbgs() << "Handle relocs: " << File->getName() << "\n"); 1054 for (InputChunk *Chunk : File->Functions) 1055 HandleRelocs(Chunk); 1056 for (InputChunk *Chunk : File->Segments) 1057 HandleRelocs(Chunk); 1058 for (auto &P : File->CustomSections) 1059 HandleRelocs(P); 1060 } 1061 1062 assert(InputGlobals.empty()); 1063 uint32_t GlobalIndex = NumImportedGlobals; 1064 auto AddDefinedGlobal = [&](InputGlobal *Global) { 1065 if (Global->Live) { 1066 LLVM_DEBUG(dbgs() << "AddDefinedGlobal: " << GlobalIndex << "\n"); 1067 Global->setGlobalIndex(GlobalIndex++); 1068 InputGlobals.push_back(Global); 1069 } 1070 }; 1071 1072 for (InputGlobal *Global : Symtab->SyntheticGlobals) 1073 AddDefinedGlobal(Global); 1074 1075 for (ObjFile *File : Symtab->ObjectFiles) { 1076 LLVM_DEBUG(dbgs() << "Globals: " << File->getName() << "\n"); 1077 for (InputGlobal *Global : File->Globals) 1078 AddDefinedGlobal(Global); 1079 } 1080 1081 assert(InputEvents.empty()); 1082 uint32_t EventIndex = NumImportedEvents; 1083 auto AddDefinedEvent = [&](InputEvent *Event) { 1084 if (Event->Live) { 1085 LLVM_DEBUG(dbgs() << "AddDefinedEvent: " << EventIndex << "\n"); 1086 Event->setEventIndex(EventIndex++); 1087 InputEvents.push_back(Event); 1088 } 1089 }; 1090 1091 for (ObjFile *File : Symtab->ObjectFiles) { 1092 LLVM_DEBUG(dbgs() << "Events: " << File->getName() << "\n"); 1093 for (InputEvent *Event : File->Events) 1094 AddDefinedEvent(Event); 1095 } 1096 } 1097 1098 static StringRef getOutputDataSegmentName(StringRef Name) { 1099 // With PIC code we currently only support a single data segment since 1100 // we only have a single __memory_base to use as our base address. 1101 if (Config->Pic) 1102 return "data"; 1103 if (!Config->MergeDataSegments) 1104 return Name; 1105 if (Name.startswith(".text.")) 1106 return ".text"; 1107 if (Name.startswith(".data.")) 1108 return ".data"; 1109 if (Name.startswith(".bss.")) 1110 return ".bss"; 1111 if (Name.startswith(".rodata.")) 1112 return ".rodata"; 1113 return Name; 1114 } 1115 1116 void Writer::createOutputSegments() { 1117 for (ObjFile *File : Symtab->ObjectFiles) { 1118 for (InputSegment *Segment : File->Segments) { 1119 if (!Segment->Live) 1120 continue; 1121 StringRef Name = getOutputDataSegmentName(Segment->getName()); 1122 OutputSegment *&S = SegmentMap[Name]; 1123 if (S == nullptr) { 1124 LLVM_DEBUG(dbgs() << "new segment: " << Name << "\n"); 1125 S = make<OutputSegment>(Name, Segments.size()); 1126 Segments.push_back(S); 1127 } 1128 S->addInputSegment(Segment); 1129 LLVM_DEBUG(dbgs() << "added data: " << Name << ": " << S->Size << "\n"); 1130 } 1131 } 1132 } 1133 1134 static const int OPCODE_CALL = 0x10; 1135 static const int OPCODE_END = 0xb; 1136 1137 // Create synthetic "__wasm_call_ctors" function based on ctor functions 1138 // in input object. 1139 void Writer::createCtorFunction() { 1140 // First write the body's contents to a string. 1141 std::string BodyContent; 1142 { 1143 raw_string_ostream OS(BodyContent); 1144 writeUleb128(OS, 0, "num locals"); 1145 for (const WasmInitEntry &F : InitFunctions) { 1146 writeU8(OS, OPCODE_CALL, "CALL"); 1147 writeUleb128(OS, F.Sym->getFunctionIndex(), "function index"); 1148 } 1149 writeU8(OS, OPCODE_END, "END"); 1150 } 1151 1152 // Once we know the size of the body we can create the final function body 1153 std::string FunctionBody; 1154 { 1155 raw_string_ostream OS(FunctionBody); 1156 writeUleb128(OS, BodyContent.size(), "function size"); 1157 OS << BodyContent; 1158 } 1159 1160 ArrayRef<uint8_t> Body = arrayRefFromStringRef(Saver.save(FunctionBody)); 1161 cast<SyntheticFunction>(WasmSym::CallCtors->Function)->setBody(Body); 1162 } 1163 1164 // Populate InitFunctions vector with init functions from all input objects. 1165 // This is then used either when creating the output linking section or to 1166 // synthesize the "__wasm_call_ctors" function. 1167 void Writer::calculateInitFunctions() { 1168 for (ObjFile *File : Symtab->ObjectFiles) { 1169 const WasmLinkingData &L = File->getWasmObj()->linkingData(); 1170 for (const WasmInitFunc &F : L.InitFunctions) { 1171 FunctionSymbol *Sym = File->getFunctionSymbol(F.Symbol); 1172 if (*Sym->Signature != WasmSignature{{}, {}}) 1173 error("invalid signature for init func: " + toString(*Sym)); 1174 InitFunctions.emplace_back(WasmInitEntry{Sym, F.Priority}); 1175 } 1176 } 1177 1178 // Sort in order of priority (lowest first) so that they are called 1179 // in the correct order. 1180 std::stable_sort(InitFunctions.begin(), InitFunctions.end(), 1181 [](const WasmInitEntry &L, const WasmInitEntry &R) { 1182 return L.Priority < R.Priority; 1183 }); 1184 } 1185 1186 void Writer::run() { 1187 if (Config->Relocatable || Config->Pic) 1188 Config->GlobalBase = 0; 1189 1190 // For PIC code the table base is assigned dynamically by the loader. 1191 // For non-PIC, we start at 1 so that accessing table index 0 always traps. 1192 if (!Config->Pic) 1193 TableBase = 1; 1194 1195 log("-- calculateImports"); 1196 calculateImports(); 1197 log("-- assignIndexes"); 1198 assignIndexes(); 1199 log("-- calculateInitFunctions"); 1200 calculateInitFunctions(); 1201 if (!Config->Relocatable) 1202 createCtorFunction(); 1203 log("-- calculateTypes"); 1204 calculateTypes(); 1205 log("-- layoutMemory"); 1206 layoutMemory(); 1207 log("-- calculateExports"); 1208 calculateExports(); 1209 log("-- calculateCustomSections"); 1210 calculateCustomSections(); 1211 log("-- assignSymtab"); 1212 assignSymtab(); 1213 1214 if (errorHandler().Verbose) { 1215 log("Defined Functions: " + Twine(InputFunctions.size())); 1216 log("Defined Globals : " + Twine(InputGlobals.size())); 1217 log("Defined Events : " + Twine(InputEvents.size())); 1218 log("Function Imports : " + Twine(NumImportedFunctions)); 1219 log("Global Imports : " + Twine(NumImportedGlobals)); 1220 log("Event Imports : " + Twine(NumImportedEvents)); 1221 for (ObjFile *File : Symtab->ObjectFiles) 1222 File->dumpInfo(); 1223 } 1224 1225 createHeader(); 1226 log("-- createSections"); 1227 createSections(); 1228 1229 log("-- openFile"); 1230 openFile(); 1231 if (errorCount()) 1232 return; 1233 1234 writeHeader(); 1235 1236 log("-- writeSections"); 1237 writeSections(); 1238 if (errorCount()) 1239 return; 1240 1241 if (Error E = Buffer->commit()) 1242 fatal("failed to write the output file: " + toString(std::move(E))); 1243 } 1244 1245 // Open a result file. 1246 void Writer::openFile() { 1247 log("writing: " + Config->OutputFile); 1248 1249 Expected<std::unique_ptr<FileOutputBuffer>> BufferOrErr = 1250 FileOutputBuffer::create(Config->OutputFile, FileSize, 1251 FileOutputBuffer::F_executable); 1252 1253 if (!BufferOrErr) 1254 error("failed to open " + Config->OutputFile + ": " + 1255 toString(BufferOrErr.takeError())); 1256 else 1257 Buffer = std::move(*BufferOrErr); 1258 } 1259 1260 void Writer::createHeader() { 1261 raw_string_ostream OS(Header); 1262 writeBytes(OS, WasmMagic, sizeof(WasmMagic), "wasm magic"); 1263 writeU32(OS, WasmVersion, "wasm version"); 1264 OS.flush(); 1265 FileSize += Header.size(); 1266 } 1267 1268 void lld::wasm::writeResult() { Writer().run(); } 1269