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