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