xref: /llvm-project-15.0.7/lld/wasm/Writer.cpp (revision e3748b5a)
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