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 "Relocations.h" 17 #include "SymbolTable.h" 18 #include "SyntheticSections.h" 19 #include "WriterUtils.h" 20 #include "lld/Common/ErrorHandler.h" 21 #include "lld/Common/Memory.h" 22 #include "lld/Common/Strings.h" 23 #include "lld/Common/Threads.h" 24 #include "llvm/ADT/DenseSet.h" 25 #include "llvm/ADT/SmallSet.h" 26 #include "llvm/ADT/SmallVector.h" 27 #include "llvm/ADT/StringMap.h" 28 #include "llvm/BinaryFormat/Wasm.h" 29 #include "llvm/Object/WasmTraits.h" 30 #include "llvm/Support/FileOutputBuffer.h" 31 #include "llvm/Support/Format.h" 32 #include "llvm/Support/FormatVariadic.h" 33 #include "llvm/Support/LEB128.h" 34 35 #include <cstdarg> 36 #include <map> 37 38 #define DEBUG_TYPE "lld" 39 40 using namespace llvm; 41 using namespace llvm::wasm; 42 using namespace lld; 43 using namespace lld::wasm; 44 45 static constexpr int StackAlignment = 16; 46 47 namespace { 48 49 // The writer writes a SymbolTable result to a file. 50 class Writer { 51 public: 52 void run(); 53 54 private: 55 void openFile(); 56 57 void createApplyRelocationsFunction(); 58 void createCallCtorsFunction(); 59 60 void assignIndexes(); 61 void populateSymtab(); 62 void populateProducers(); 63 void populateTargetFeatures(); 64 void calculateInitFunctions(); 65 void calculateImports(); 66 void calculateExports(); 67 void calculateCustomSections(); 68 void calculateTypes(); 69 void createOutputSegments(); 70 void layoutMemory(); 71 void createHeader(); 72 73 void addSection(OutputSection *Sec); 74 75 void addSections(); 76 void createCustomSections(); 77 void createSyntheticSections(); 78 void finalizeSections(); 79 80 // Custom sections 81 void createRelocSections(); 82 83 void writeHeader(); 84 void writeSections(); 85 86 uint64_t FileSize = 0; 87 uint32_t TableBase = 0; 88 89 std::vector<WasmInitEntry> InitFunctions; 90 llvm::StringMap<std::vector<InputSection *>> CustomSectionMapping; 91 92 // Elements that are used to construct the final output 93 std::string Header; 94 std::vector<OutputSection *> OutputSections; 95 96 std::unique_ptr<FileOutputBuffer> Buffer; 97 98 std::vector<OutputSegment *> Segments; 99 llvm::SmallDenseMap<StringRef, OutputSegment *> SegmentMap; 100 }; 101 102 } // anonymous namespace 103 104 void Writer::calculateCustomSections() { 105 log("calculateCustomSections"); 106 bool StripDebug = Config->StripDebug || Config->StripAll; 107 for (ObjFile *File : Symtab->ObjectFiles) { 108 for (InputSection *Section : File->CustomSections) { 109 StringRef Name = Section->getName(); 110 // These custom sections are known the linker and synthesized rather than 111 // blindly copied 112 if (Name == "linking" || Name == "name" || Name == "producers" || 113 Name == "target_features" || Name.startswith("reloc.")) 114 continue; 115 // .. or it is a debug section 116 if (StripDebug && Name.startswith(".debug_")) 117 continue; 118 CustomSectionMapping[Name].push_back(Section); 119 } 120 } 121 } 122 123 void Writer::createCustomSections() { 124 log("createCustomSections"); 125 for (auto &Pair : CustomSectionMapping) { 126 StringRef Name = Pair.first(); 127 LLVM_DEBUG(dbgs() << "createCustomSection: " << Name << "\n"); 128 129 OutputSection *Sec = make<CustomSection>(Name, Pair.second); 130 if (Config->Relocatable) { 131 auto *Sym = make<OutputSectionSymbol>(Sec); 132 Out.LinkingSec->addToSymtab(Sym); 133 Sec->SectionSym = Sym; 134 } 135 addSection(Sec); 136 } 137 } 138 139 // Create relocations sections in the final output. 140 // These are only created when relocatable output is requested. 141 void Writer::createRelocSections() { 142 log("createRelocSections"); 143 // Don't use iterator here since we are adding to OutputSection 144 size_t OrigSize = OutputSections.size(); 145 for (size_t I = 0; I < OrigSize; I++) { 146 LLVM_DEBUG(dbgs() << "check section " << I << "\n"); 147 OutputSection *Sec = OutputSections[I]; 148 149 // Count the number of needed sections. 150 uint32_t Count = Sec->numRelocations(); 151 if (!Count) 152 continue; 153 154 StringRef Name; 155 if (Sec->Type == WASM_SEC_DATA) 156 Name = "reloc.DATA"; 157 else if (Sec->Type == WASM_SEC_CODE) 158 Name = "reloc.CODE"; 159 else if (Sec->Type == WASM_SEC_CUSTOM) 160 Name = Saver.save("reloc." + Sec->Name); 161 else 162 llvm_unreachable( 163 "relocations only supported for code, data, or custom sections"); 164 165 addSection(make<RelocSection>(Name, Sec)); 166 } 167 } 168 169 void Writer::populateProducers() { 170 for (ObjFile *File : Symtab->ObjectFiles) { 171 const WasmProducerInfo &Info = File->getWasmObj()->getProducerInfo(); 172 Out.ProducersSec->addInfo(Info); 173 } 174 } 175 176 void Writer::writeHeader() { 177 memcpy(Buffer->getBufferStart(), Header.data(), Header.size()); 178 } 179 180 void Writer::writeSections() { 181 uint8_t *Buf = Buffer->getBufferStart(); 182 parallelForEach(OutputSections, [Buf](OutputSection *S) { 183 assert(S->isNeeded()); 184 S->writeTo(Buf); 185 }); 186 } 187 188 // Fix the memory layout of the output binary. This assigns memory offsets 189 // to each of the input data sections as well as the explicit stack region. 190 // The default memory layout is as follows, from low to high. 191 // 192 // - initialized data (starting at Config->GlobalBase) 193 // - BSS data (not currently implemented in llvm) 194 // - explicit stack (Config->ZStackSize) 195 // - heap start / unallocated 196 // 197 // The --stack-first option means that stack is placed before any static data. 198 // This can be useful since it means that stack overflow traps immediately 199 // rather than overwriting global data, but also increases code size since all 200 // static data loads and stores requires larger offsets. 201 void Writer::layoutMemory() { 202 uint32_t MemoryPtr = 0; 203 204 auto PlaceStack = [&]() { 205 if (Config->Relocatable || Config->Shared) 206 return; 207 MemoryPtr = alignTo(MemoryPtr, StackAlignment); 208 if (Config->ZStackSize != alignTo(Config->ZStackSize, StackAlignment)) 209 error("stack size must be " + Twine(StackAlignment) + "-byte aligned"); 210 log("mem: stack size = " + Twine(Config->ZStackSize)); 211 log("mem: stack base = " + Twine(MemoryPtr)); 212 MemoryPtr += Config->ZStackSize; 213 auto *SP = cast<DefinedGlobal>(WasmSym::StackPointer); 214 SP->Global->Global.InitExpr.Value.Int32 = MemoryPtr; 215 log("mem: stack top = " + Twine(MemoryPtr)); 216 }; 217 218 if (Config->StackFirst) { 219 PlaceStack(); 220 } else { 221 MemoryPtr = Config->GlobalBase; 222 log("mem: global base = " + Twine(Config->GlobalBase)); 223 } 224 225 uint32_t DataStart = MemoryPtr; 226 227 // Arbitrarily set __dso_handle handle to point to the start of the data 228 // segments. 229 if (WasmSym::DsoHandle) 230 WasmSym::DsoHandle->setVirtualAddress(DataStart); 231 232 Out.DylinkSec->MemAlign = 0; 233 for (OutputSegment *Seg : Segments) { 234 Out.DylinkSec->MemAlign = std::max(Out.DylinkSec->MemAlign, Seg->Alignment); 235 MemoryPtr = alignTo(MemoryPtr, 1ULL << Seg->Alignment); 236 Seg->StartVA = MemoryPtr; 237 log(formatv("mem: {0,-15} offset={1,-8} size={2,-8} align={3}", Seg->Name, 238 MemoryPtr, Seg->Size, Seg->Alignment)); 239 MemoryPtr += Seg->Size; 240 } 241 242 // TODO: Add .bss space here. 243 if (WasmSym::DataEnd) 244 WasmSym::DataEnd->setVirtualAddress(MemoryPtr); 245 246 log("mem: static data = " + Twine(MemoryPtr - DataStart)); 247 248 if (Config->Shared) { 249 Out.DylinkSec->MemSize = MemoryPtr; 250 return; 251 } 252 253 if (!Config->StackFirst) 254 PlaceStack(); 255 256 // Set `__heap_base` to directly follow the end of the stack or global data. 257 // The fact that this comes last means that a malloc/brk implementation 258 // can grow the heap at runtime. 259 if (!Config->Relocatable) { 260 WasmSym::HeapBase->setVirtualAddress(MemoryPtr); 261 log("mem: heap base = " + Twine(MemoryPtr)); 262 } 263 264 if (Config->InitialMemory != 0) { 265 if (Config->InitialMemory != alignTo(Config->InitialMemory, WasmPageSize)) 266 error("initial memory must be " + Twine(WasmPageSize) + "-byte aligned"); 267 if (MemoryPtr > Config->InitialMemory) 268 error("initial memory too small, " + Twine(MemoryPtr) + " bytes needed"); 269 else 270 MemoryPtr = Config->InitialMemory; 271 } 272 Out.DylinkSec->MemSize = MemoryPtr; 273 Out.MemorySec->NumMemoryPages = 274 alignTo(MemoryPtr, WasmPageSize) / WasmPageSize; 275 log("mem: total pages = " + Twine(Out.MemorySec->NumMemoryPages)); 276 277 // Check max if explicitly supplied or required by shared memory 278 if (Config->MaxMemory != 0 || Config->SharedMemory) { 279 if (Config->MaxMemory != alignTo(Config->MaxMemory, WasmPageSize)) 280 error("maximum memory must be " + Twine(WasmPageSize) + "-byte aligned"); 281 if (MemoryPtr > Config->MaxMemory) 282 error("maximum memory too small, " + Twine(MemoryPtr) + " bytes needed"); 283 Out.MemorySec->MaxMemoryPages = Config->MaxMemory / WasmPageSize; 284 log("mem: max pages = " + Twine(Out.MemorySec->MaxMemoryPages)); 285 } 286 } 287 288 void Writer::addSection(OutputSection *Sec) { 289 if (!Sec->isNeeded()) 290 return; 291 log("addSection: " + toString(*Sec)); 292 Sec->SectionIndex = OutputSections.size(); 293 OutputSections.push_back(Sec); 294 } 295 296 void Writer::addSections() { 297 addSection(Out.DylinkSec); 298 addSection(Out.TypeSec); 299 addSection(Out.ImportSec); 300 addSection(Out.FunctionSec); 301 addSection(Out.TableSec); 302 addSection(Out.MemorySec); 303 addSection(Out.GlobalSec); 304 addSection(Out.EventSec); 305 addSection(Out.ExportSec); 306 addSection(Out.ElemSec); 307 addSection(Out.DataCountSec); 308 309 addSection(make<CodeSection>(Out.FunctionSec->InputFunctions)); 310 addSection(make<DataSection>(Segments)); 311 312 createCustomSections(); 313 314 addSection(Out.LinkingSec); 315 if (Config->Relocatable) { 316 createRelocSections(); 317 } 318 319 addSection(Out.NameSec); 320 addSection(Out.ProducersSec); 321 addSection(Out.TargetFeaturesSec); 322 } 323 324 void Writer::finalizeSections() { 325 for (OutputSection *S : OutputSections) { 326 S->setOffset(FileSize); 327 S->finalizeContents(); 328 FileSize += S->getSize(); 329 } 330 } 331 332 void Writer::populateTargetFeatures() { 333 SmallSet<std::string, 8> Used; 334 SmallSet<std::string, 8> Required; 335 SmallSet<std::string, 8> Disallowed; 336 337 // Only infer used features if user did not specify features 338 bool InferFeatures = !Config->Features.hasValue(); 339 340 if (!InferFeatures) { 341 for (auto &Feature : Config->Features.getValue()) 342 Out.TargetFeaturesSec->Features.insert(Feature); 343 // No need to read or check features 344 if (!Config->CheckFeatures) 345 return; 346 } 347 348 // Find the sets of used, required, and disallowed features 349 for (ObjFile *File : Symtab->ObjectFiles) { 350 for (auto &Feature : File->getWasmObj()->getTargetFeatures()) { 351 switch (Feature.Prefix) { 352 case WASM_FEATURE_PREFIX_USED: 353 Used.insert(Feature.Name); 354 break; 355 case WASM_FEATURE_PREFIX_REQUIRED: 356 Used.insert(Feature.Name); 357 Required.insert(Feature.Name); 358 break; 359 case WASM_FEATURE_PREFIX_DISALLOWED: 360 Disallowed.insert(Feature.Name); 361 break; 362 default: 363 error("Unrecognized feature policy prefix " + 364 std::to_string(Feature.Prefix)); 365 } 366 } 367 } 368 369 if (InferFeatures) 370 Out.TargetFeaturesSec->Features.insert(Used.begin(), Used.end()); 371 372 if (Out.TargetFeaturesSec->Features.count("atomics") && !Config->SharedMemory) 373 error("'atomics' feature is used, so --shared-memory must be used"); 374 375 if (!Config->CheckFeatures) 376 return; 377 378 if (Disallowed.count("atomics") && Config->SharedMemory) 379 error( 380 "'atomics' feature is disallowed, so --shared-memory must not be used"); 381 382 // Validate that used features are allowed in output 383 if (!InferFeatures) { 384 for (auto &Feature : Used) { 385 if (!Out.TargetFeaturesSec->Features.count(Feature)) 386 error(Twine("Target feature '") + Feature + "' is not allowed."); 387 } 388 } 389 390 // Validate the required and disallowed constraints for each file 391 for (ObjFile *File : Symtab->ObjectFiles) { 392 SmallSet<std::string, 8> ObjectFeatures; 393 for (auto &Feature : File->getWasmObj()->getTargetFeatures()) { 394 if (Feature.Prefix == WASM_FEATURE_PREFIX_DISALLOWED) 395 continue; 396 ObjectFeatures.insert(Feature.Name); 397 if (Disallowed.count(Feature.Name)) 398 error(Twine("Target feature '") + Feature.Name + 399 "' is disallowed. Use --no-check-features to suppress."); 400 } 401 for (auto &Feature : Required) { 402 if (!ObjectFeatures.count(Feature)) 403 error(Twine("Missing required target feature '") + Feature + 404 "'. Use --no-check-features to suppress."); 405 } 406 } 407 } 408 409 void Writer::calculateImports() { 410 for (Symbol *Sym : Symtab->getSymbols()) { 411 if (!Sym->isUndefined()) 412 continue; 413 if (Sym->isWeak() && !Config->Relocatable) 414 continue; 415 if (!Sym->isLive()) 416 continue; 417 if (!Sym->IsUsedInRegularObj) 418 continue; 419 // We don't generate imports for data symbols. They however can be imported 420 // as GOT entries. 421 if (isa<DataSymbol>(Sym)) 422 continue; 423 424 LLVM_DEBUG(dbgs() << "import: " << Sym->getName() << "\n"); 425 Out.ImportSec->addImport(Sym); 426 } 427 } 428 429 void Writer::calculateExports() { 430 if (Config->Relocatable) 431 return; 432 433 if (!Config->Relocatable && !Config->ImportMemory) 434 Out.ExportSec->Exports.push_back( 435 WasmExport{"memory", WASM_EXTERNAL_MEMORY, 0}); 436 437 if (!Config->Relocatable && Config->ExportTable) 438 Out.ExportSec->Exports.push_back( 439 WasmExport{FunctionTableName, WASM_EXTERNAL_TABLE, 0}); 440 441 unsigned FakeGlobalIndex = 442 Out.ImportSec->NumImportedGlobals + Out.GlobalSec->InputGlobals.size(); 443 444 for (Symbol *Sym : Symtab->getSymbols()) { 445 if (!Sym->isExported()) 446 continue; 447 if (!Sym->isLive()) 448 continue; 449 450 StringRef Name = Sym->getName(); 451 WasmExport Export; 452 if (auto *F = dyn_cast<DefinedFunction>(Sym)) { 453 Export = {Name, WASM_EXTERNAL_FUNCTION, F->getFunctionIndex()}; 454 } else if (auto *G = dyn_cast<DefinedGlobal>(Sym)) { 455 // TODO(sbc): Remove this check once to mutable global proposal is 456 // implement in all major browsers. 457 // See: https://github.com/WebAssembly/mutable-global 458 if (G->getGlobalType()->Mutable) { 459 // Only the __stack_pointer should ever be create as mutable. 460 assert(G == WasmSym::StackPointer); 461 continue; 462 } 463 Export = {Name, WASM_EXTERNAL_GLOBAL, G->getGlobalIndex()}; 464 } else if (auto *E = dyn_cast<DefinedEvent>(Sym)) { 465 Export = {Name, WASM_EXTERNAL_EVENT, E->getEventIndex()}; 466 } else { 467 auto *D = cast<DefinedData>(Sym); 468 Out.GlobalSec->DefinedFakeGlobals.emplace_back(D); 469 Export = {Name, WASM_EXTERNAL_GLOBAL, FakeGlobalIndex++}; 470 } 471 472 LLVM_DEBUG(dbgs() << "Export: " << Name << "\n"); 473 Out.ExportSec->Exports.push_back(Export); 474 } 475 } 476 477 void Writer::populateSymtab() { 478 if (!Config->Relocatable) 479 return; 480 481 for (Symbol *Sym : Symtab->getSymbols()) 482 if (Sym->IsUsedInRegularObj) 483 Out.LinkingSec->addToSymtab(Sym); 484 485 for (ObjFile *File : Symtab->ObjectFiles) { 486 LLVM_DEBUG(dbgs() << "Local symtab entries: " << File->getName() << "\n"); 487 for (Symbol *Sym : File->getSymbols()) 488 if (Sym->isLocal() && !isa<SectionSymbol>(Sym)) 489 Out.LinkingSec->addToSymtab(Sym); 490 } 491 } 492 493 void Writer::calculateTypes() { 494 // The output type section is the union of the following sets: 495 // 1. Any signature used in the TYPE relocation 496 // 2. The signatures of all imported functions 497 // 3. The signatures of all defined functions 498 // 4. The signatures of all imported events 499 // 5. The signatures of all defined events 500 501 for (ObjFile *File : Symtab->ObjectFiles) { 502 ArrayRef<WasmSignature> Types = File->getWasmObj()->types(); 503 for (uint32_t I = 0; I < Types.size(); I++) 504 if (File->TypeIsUsed[I]) 505 File->TypeMap[I] = Out.TypeSec->registerType(Types[I]); 506 } 507 508 for (const Symbol *Sym : Out.ImportSec->ImportedSymbols) { 509 if (auto *F = dyn_cast<FunctionSymbol>(Sym)) 510 Out.TypeSec->registerType(*F->Signature); 511 else if (auto *E = dyn_cast<EventSymbol>(Sym)) 512 Out.TypeSec->registerType(*E->Signature); 513 } 514 515 for (const InputFunction *F : Out.FunctionSec->InputFunctions) 516 Out.TypeSec->registerType(F->Signature); 517 518 for (const InputEvent *E : Out.EventSec->InputEvents) 519 Out.TypeSec->registerType(E->Signature); 520 } 521 522 static void scanRelocations() { 523 for (ObjFile *File : Symtab->ObjectFiles) { 524 LLVM_DEBUG(dbgs() << "scanRelocations: " << File->getName() << "\n"); 525 for (InputChunk *Chunk : File->Functions) 526 scanRelocations(Chunk); 527 for (InputChunk *Chunk : File->Segments) 528 scanRelocations(Chunk); 529 for (auto &P : File->CustomSections) 530 scanRelocations(P); 531 } 532 } 533 534 void Writer::assignIndexes() { 535 assert(Out.FunctionSec->InputFunctions.empty()); 536 537 for (InputFunction *Func : Symtab->SyntheticFunctions) 538 Out.FunctionSec->addFunction(Func); 539 540 for (ObjFile *File : Symtab->ObjectFiles) { 541 LLVM_DEBUG(dbgs() << "Functions: " << File->getName() << "\n"); 542 for (InputFunction *Func : File->Functions) 543 Out.FunctionSec->addFunction(Func); 544 } 545 546 scanRelocations(); 547 548 for (InputGlobal *Global : Symtab->SyntheticGlobals) 549 Out.GlobalSec->addGlobal(Global); 550 551 for (ObjFile *File : Symtab->ObjectFiles) { 552 LLVM_DEBUG(dbgs() << "Globals: " << File->getName() << "\n"); 553 for (InputGlobal *Global : File->Globals) 554 Out.GlobalSec->addGlobal(Global); 555 } 556 557 for (ObjFile *File : Symtab->ObjectFiles) { 558 LLVM_DEBUG(dbgs() << "Events: " << File->getName() << "\n"); 559 for (InputEvent *Event : File->Events) 560 Out.EventSec->addEvent(Event); 561 } 562 } 563 564 static StringRef getOutputDataSegmentName(StringRef Name) { 565 // With PIC code we currently only support a single data segment since 566 // we only have a single __memory_base to use as our base address. 567 if (Config->Pic) 568 return "data"; 569 if (!Config->MergeDataSegments) 570 return Name; 571 if (Name.startswith(".text.")) 572 return ".text"; 573 if (Name.startswith(".data.")) 574 return ".data"; 575 if (Name.startswith(".bss.")) 576 return ".bss"; 577 if (Name.startswith(".rodata.")) 578 return ".rodata"; 579 return Name; 580 } 581 582 void Writer::createOutputSegments() { 583 for (ObjFile *File : Symtab->ObjectFiles) { 584 for (InputSegment *Segment : File->Segments) { 585 if (!Segment->Live) 586 continue; 587 StringRef Name = getOutputDataSegmentName(Segment->getName()); 588 OutputSegment *&S = SegmentMap[Name]; 589 if (S == nullptr) { 590 LLVM_DEBUG(dbgs() << "new segment: " << Name << "\n"); 591 S = make<OutputSegment>(Name, Segments.size()); 592 Segments.push_back(S); 593 } 594 S->addInputSegment(Segment); 595 LLVM_DEBUG(dbgs() << "added data: " << Name << ": " << S->Size << "\n"); 596 } 597 } 598 } 599 600 // For -shared (PIC) output, we create create a synthetic function which will 601 // apply any relocations to the data segments on startup. This function is 602 // called __wasm_apply_relocs and is added at the very beginning of 603 // __wasm_call_ctors before any of the constructors run. 604 void Writer::createApplyRelocationsFunction() { 605 LLVM_DEBUG(dbgs() << "createApplyRelocationsFunction\n"); 606 // First write the body's contents to a string. 607 std::string BodyContent; 608 { 609 raw_string_ostream OS(BodyContent); 610 writeUleb128(OS, 0, "num locals"); 611 for (const OutputSegment *Seg : Segments) 612 for (const InputSegment *InSeg : Seg->InputSegments) 613 InSeg->generateRelocationCode(OS); 614 writeU8(OS, WASM_OPCODE_END, "END"); 615 } 616 617 // Once we know the size of the body we can create the final function body 618 std::string FunctionBody; 619 { 620 raw_string_ostream OS(FunctionBody); 621 writeUleb128(OS, BodyContent.size(), "function size"); 622 OS << BodyContent; 623 } 624 625 ArrayRef<uint8_t> Body = arrayRefFromStringRef(Saver.save(FunctionBody)); 626 cast<SyntheticFunction>(WasmSym::ApplyRelocs->Function)->setBody(Body); 627 } 628 629 // Create synthetic "__wasm_call_ctors" function based on ctor functions 630 // in input object. 631 void Writer::createCallCtorsFunction() { 632 if (!WasmSym::CallCtors->isLive()) 633 return; 634 635 // First write the body's contents to a string. 636 std::string BodyContent; 637 { 638 raw_string_ostream OS(BodyContent); 639 writeUleb128(OS, 0, "num locals"); 640 if (Config->Pic) { 641 writeU8(OS, WASM_OPCODE_CALL, "CALL"); 642 writeUleb128(OS, WasmSym::ApplyRelocs->getFunctionIndex(), 643 "function index"); 644 } 645 for (const WasmInitEntry &F : InitFunctions) { 646 writeU8(OS, WASM_OPCODE_CALL, "CALL"); 647 writeUleb128(OS, F.Sym->getFunctionIndex(), "function index"); 648 } 649 writeU8(OS, WASM_OPCODE_END, "END"); 650 } 651 652 // Once we know the size of the body we can create the final function body 653 std::string FunctionBody; 654 { 655 raw_string_ostream OS(FunctionBody); 656 writeUleb128(OS, BodyContent.size(), "function size"); 657 OS << BodyContent; 658 } 659 660 ArrayRef<uint8_t> Body = arrayRefFromStringRef(Saver.save(FunctionBody)); 661 cast<SyntheticFunction>(WasmSym::CallCtors->Function)->setBody(Body); 662 } 663 664 // Populate InitFunctions vector with init functions from all input objects. 665 // This is then used either when creating the output linking section or to 666 // synthesize the "__wasm_call_ctors" function. 667 void Writer::calculateInitFunctions() { 668 if (!Config->Relocatable && !WasmSym::CallCtors->isLive()) 669 return; 670 671 for (ObjFile *File : Symtab->ObjectFiles) { 672 const WasmLinkingData &L = File->getWasmObj()->linkingData(); 673 for (const WasmInitFunc &F : L.InitFunctions) { 674 FunctionSymbol *Sym = File->getFunctionSymbol(F.Symbol); 675 assert(Sym->isLive()); 676 if (*Sym->Signature != WasmSignature{{}, {}}) 677 error("invalid signature for init func: " + toString(*Sym)); 678 InitFunctions.emplace_back(WasmInitEntry{Sym, F.Priority}); 679 } 680 } 681 682 // Sort in order of priority (lowest first) so that they are called 683 // in the correct order. 684 llvm::stable_sort(InitFunctions, 685 [](const WasmInitEntry &L, const WasmInitEntry &R) { 686 return L.Priority < R.Priority; 687 }); 688 } 689 690 void Writer::createSyntheticSections() { 691 Out.DylinkSec = make<DylinkSection>(); 692 Out.TypeSec = make<TypeSection>(); 693 Out.ImportSec = make<ImportSection>(); 694 Out.FunctionSec = make<FunctionSection>(); 695 Out.TableSec = make<TableSection>(); 696 Out.MemorySec = make<MemorySection>(); 697 Out.GlobalSec = make<GlobalSection>(); 698 Out.EventSec = make<EventSection>(); 699 Out.ExportSec = make<ExportSection>(); 700 Out.ElemSec = make<ElemSection>(TableBase); 701 Out.DataCountSec = make<DataCountSection>(Segments.size()); 702 Out.LinkingSec = make<LinkingSection>(InitFunctions, Segments); 703 Out.NameSec = make<NameSection>(); 704 Out.ProducersSec = make<ProducersSection>(); 705 Out.TargetFeaturesSec = make<TargetFeaturesSection>(); 706 } 707 708 void Writer::run() { 709 if (Config->Relocatable || Config->Pic) 710 Config->GlobalBase = 0; 711 712 // For PIC code the table base is assigned dynamically by the loader. 713 // For non-PIC, we start at 1 so that accessing table index 0 always traps. 714 if (!Config->Pic) 715 TableBase = 1; 716 717 log("-- createOutputSegments"); 718 createOutputSegments(); 719 log("-- createSyntheticSections"); 720 createSyntheticSections(); 721 log("-- populateProducers"); 722 populateProducers(); 723 log("-- populateTargetFeatures"); 724 populateTargetFeatures(); 725 log("-- calculateImports"); 726 calculateImports(); 727 log("-- assignIndexes"); 728 assignIndexes(); 729 log("-- calculateInitFunctions"); 730 calculateInitFunctions(); 731 log("-- calculateTypes"); 732 calculateTypes(); 733 log("-- layoutMemory"); 734 layoutMemory(); 735 if (!Config->Relocatable) { 736 if (Config->Pic) 737 createApplyRelocationsFunction(); 738 createCallCtorsFunction(); 739 } 740 log("-- calculateExports"); 741 calculateExports(); 742 log("-- calculateCustomSections"); 743 calculateCustomSections(); 744 log("-- populateSymtab"); 745 populateSymtab(); 746 log("-- addSections"); 747 addSections(); 748 749 if (errorHandler().Verbose) { 750 log("Defined Functions: " + Twine(Out.FunctionSec->InputFunctions.size())); 751 log("Defined Globals : " + Twine(Out.GlobalSec->InputGlobals.size())); 752 log("Defined Events : " + Twine(Out.EventSec->InputEvents.size())); 753 log("Function Imports : " + Twine(Out.ImportSec->NumImportedFunctions)); 754 log("Global Imports : " + Twine(Out.ImportSec->NumImportedGlobals)); 755 log("Event Imports : " + Twine(Out.ImportSec->NumImportedEvents)); 756 for (ObjFile *File : Symtab->ObjectFiles) 757 File->dumpInfo(); 758 } 759 760 createHeader(); 761 log("-- finalizeSections"); 762 finalizeSections(); 763 764 log("-- openFile"); 765 openFile(); 766 if (errorCount()) 767 return; 768 769 writeHeader(); 770 771 log("-- writeSections"); 772 writeSections(); 773 if (errorCount()) 774 return; 775 776 if (Error E = Buffer->commit()) 777 fatal("failed to write the output file: " + toString(std::move(E))); 778 } 779 780 // Open a result file. 781 void Writer::openFile() { 782 log("writing: " + Config->OutputFile); 783 784 Expected<std::unique_ptr<FileOutputBuffer>> BufferOrErr = 785 FileOutputBuffer::create(Config->OutputFile, FileSize, 786 FileOutputBuffer::F_executable); 787 788 if (!BufferOrErr) 789 error("failed to open " + Config->OutputFile + ": " + 790 toString(BufferOrErr.takeError())); 791 else 792 Buffer = std::move(*BufferOrErr); 793 } 794 795 void Writer::createHeader() { 796 raw_string_ostream OS(Header); 797 writeBytes(OS, WasmMagic, sizeof(WasmMagic), "wasm magic"); 798 writeU32(OS, WasmVersion, "wasm version"); 799 OS.flush(); 800 FileSize += Header.size(); 801 } 802 803 void lld::wasm::writeResult() { Writer().run(); } 804