xref: /llvm-project-15.0.7/lld/wasm/Writer.cpp (revision fcd549a7)
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 createInitMemoryFunction();
58   void createApplyRelocationsFunction();
59   void createCallCtorsFunction();
60   void createInitTLSFunction();
61 
62   void assignIndexes();
63   void populateSymtab();
64   void populateProducers();
65   void populateTargetFeatures();
66   void calculateInitFunctions();
67   void calculateImports();
68   void calculateExports();
69   void calculateCustomSections();
70   void calculateTypes();
71   void createOutputSegments();
72   void layoutMemory();
73   void createHeader();
74 
75   void addSection(OutputSection *sec);
76 
77   void addSections();
78 
79   void createCustomSections();
80   void createSyntheticSections();
81   void finalizeSections();
82 
83   // Custom sections
84   void createRelocSections();
85 
86   void writeHeader();
87   void writeSections();
88 
89   uint64_t fileSize = 0;
90   uint32_t tableBase = 0;
91 
92   std::vector<WasmInitEntry> initFunctions;
93   llvm::StringMap<std::vector<InputSection *>> customSectionMapping;
94 
95   // Elements that are used to construct the final output
96   std::string header;
97   std::vector<OutputSection *> outputSections;
98 
99   std::unique_ptr<FileOutputBuffer> buffer;
100 
101   std::vector<OutputSegment *> segments;
102   llvm::SmallDenseMap<StringRef, OutputSegment *> segmentMap;
103 };
104 
105 } // anonymous namespace
106 
107 void Writer::calculateCustomSections() {
108   log("calculateCustomSections");
109   bool stripDebug = config->stripDebug || config->stripAll;
110   for (ObjFile *file : symtab->objectFiles) {
111     for (InputSection *section : file->customSections) {
112       StringRef name = section->getName();
113       // These custom sections are known the linker and synthesized rather than
114       // blindly copied
115       if (name == "linking" || name == "name" || name == "producers" ||
116           name == "target_features" || name.startswith("reloc."))
117         continue;
118       // .. or it is a debug section
119       if (stripDebug && name.startswith(".debug_"))
120         continue;
121       customSectionMapping[name].push_back(section);
122     }
123   }
124 }
125 
126 void Writer::createCustomSections() {
127   log("createCustomSections");
128   for (auto &pair : customSectionMapping) {
129     StringRef name = pair.first();
130     LLVM_DEBUG(dbgs() << "createCustomSection: " << name << "\n");
131 
132     OutputSection *sec = make<CustomSection>(name, pair.second);
133     if (config->relocatable || config->emitRelocs) {
134       auto *sym = make<OutputSectionSymbol>(sec);
135       out.linkingSec->addToSymtab(sym);
136       sec->sectionSym = sym;
137     }
138     addSection(sec);
139   }
140 }
141 
142 // Create relocations sections in the final output.
143 // These are only created when relocatable output is requested.
144 void Writer::createRelocSections() {
145   log("createRelocSections");
146   // Don't use iterator here since we are adding to OutputSection
147   size_t origSize = outputSections.size();
148   for (size_t i = 0; i < origSize; i++) {
149     LLVM_DEBUG(dbgs() << "check section " << i << "\n");
150     OutputSection *sec = outputSections[i];
151 
152     // Count the number of needed sections.
153     uint32_t count = sec->getNumRelocations();
154     if (!count)
155       continue;
156 
157     StringRef name;
158     if (sec->type == WASM_SEC_DATA)
159       name = "reloc.DATA";
160     else if (sec->type == WASM_SEC_CODE)
161       name = "reloc.CODE";
162     else if (sec->type == WASM_SEC_CUSTOM)
163       name = saver.save("reloc." + sec->name);
164     else
165       llvm_unreachable(
166           "relocations only supported for code, data, or custom sections");
167 
168     addSection(make<RelocSection>(name, sec));
169   }
170 }
171 
172 void Writer::populateProducers() {
173   for (ObjFile *file : symtab->objectFiles) {
174     const WasmProducerInfo &info = file->getWasmObj()->getProducerInfo();
175     out.producersSec->addInfo(info);
176   }
177 }
178 
179 void Writer::writeHeader() {
180   memcpy(buffer->getBufferStart(), header.data(), header.size());
181 }
182 
183 void Writer::writeSections() {
184   uint8_t *buf = buffer->getBufferStart();
185   parallelForEach(outputSections, [buf](OutputSection *s) {
186     assert(s->isNeeded());
187     s->writeTo(buf);
188   });
189 }
190 
191 // Fix the memory layout of the output binary.  This assigns memory offsets
192 // to each of the input data sections as well as the explicit stack region.
193 // The default memory layout is as follows, from low to high.
194 //
195 //  - initialized data (starting at Config->globalBase)
196 //  - BSS data (not currently implemented in llvm)
197 //  - explicit stack (Config->ZStackSize)
198 //  - heap start / unallocated
199 //
200 // The --stack-first option means that stack is placed before any static data.
201 // This can be useful since it means that stack overflow traps immediately
202 // rather than overwriting global data, but also increases code size since all
203 // static data loads and stores requires larger offsets.
204 void Writer::layoutMemory() {
205   uint32_t memoryPtr = 0;
206 
207   auto placeStack = [&]() {
208     if (config->relocatable || config->isPic)
209       return;
210     memoryPtr = alignTo(memoryPtr, stackAlignment);
211     if (config->zStackSize != alignTo(config->zStackSize, stackAlignment))
212       error("stack size must be " + Twine(stackAlignment) + "-byte aligned");
213     log("mem: stack size  = " + Twine(config->zStackSize));
214     log("mem: stack base  = " + Twine(memoryPtr));
215     memoryPtr += config->zStackSize;
216     auto *sp = cast<DefinedGlobal>(WasmSym::stackPointer);
217     sp->global->global.InitExpr.Value.Int32 = memoryPtr;
218     log("mem: stack top   = " + Twine(memoryPtr));
219   };
220 
221   if (config->stackFirst) {
222     placeStack();
223   } else {
224     memoryPtr = config->globalBase;
225     log("mem: global base = " + Twine(config->globalBase));
226   }
227 
228   if (WasmSym::globalBase)
229     WasmSym::globalBase->setVirtualAddress(config->globalBase);
230 
231   uint32_t dataStart = memoryPtr;
232 
233   // Arbitrarily set __dso_handle handle to point to the start of the data
234   // segments.
235   if (WasmSym::dsoHandle)
236     WasmSym::dsoHandle->setVirtualAddress(dataStart);
237 
238   out.dylinkSec->memAlign = 0;
239   for (OutputSegment *seg : segments) {
240     out.dylinkSec->memAlign = std::max(out.dylinkSec->memAlign, seg->alignment);
241     memoryPtr = alignTo(memoryPtr, 1ULL << seg->alignment);
242     seg->startVA = memoryPtr;
243     log(formatv("mem: {0,-15} offset={1,-8} size={2,-8} align={3}", seg->name,
244                 memoryPtr, seg->size, seg->alignment));
245     memoryPtr += seg->size;
246 
247     if (WasmSym::tlsSize && seg->name == ".tdata") {
248       auto *tlsSize = cast<DefinedGlobal>(WasmSym::tlsSize);
249       tlsSize->global->global.InitExpr.Value.Int32 = seg->size;
250 
251       auto *tlsAlign = cast<DefinedGlobal>(WasmSym::tlsAlign);
252       tlsAlign->global->global.InitExpr.Value.Int32 = 1U << seg->alignment;
253     }
254   }
255 
256   // TODO: Add .bss space here.
257   if (WasmSym::dataEnd)
258     WasmSym::dataEnd->setVirtualAddress(memoryPtr);
259 
260   log("mem: static data = " + Twine(memoryPtr - dataStart));
261 
262   if (config->shared) {
263     out.dylinkSec->memSize = memoryPtr;
264     return;
265   }
266 
267   if (!config->stackFirst)
268     placeStack();
269 
270   // Set `__heap_base` to directly follow the end of the stack or global data.
271   // The fact that this comes last means that a malloc/brk implementation
272   // can grow the heap at runtime.
273   log("mem: heap base   = " + Twine(memoryPtr));
274   if (WasmSym::heapBase)
275     WasmSym::heapBase->setVirtualAddress(memoryPtr);
276 
277   if (config->initialMemory != 0) {
278     if (config->initialMemory != alignTo(config->initialMemory, WasmPageSize))
279       error("initial memory must be " + Twine(WasmPageSize) + "-byte aligned");
280     if (memoryPtr > config->initialMemory)
281       error("initial memory too small, " + Twine(memoryPtr) + " bytes needed");
282     else
283       memoryPtr = config->initialMemory;
284   }
285   out.dylinkSec->memSize = memoryPtr;
286   out.memorySec->numMemoryPages =
287       alignTo(memoryPtr, WasmPageSize) / WasmPageSize;
288   log("mem: total pages = " + Twine(out.memorySec->numMemoryPages));
289 
290   // Check max if explicitly supplied or required by shared memory
291   if (config->maxMemory != 0 || config->sharedMemory) {
292     if (config->maxMemory != alignTo(config->maxMemory, WasmPageSize))
293       error("maximum memory must be " + Twine(WasmPageSize) + "-byte aligned");
294     if (memoryPtr > config->maxMemory)
295       error("maximum memory too small, " + Twine(memoryPtr) + " bytes needed");
296     out.memorySec->maxMemoryPages = config->maxMemory / WasmPageSize;
297     log("mem: max pages   = " + Twine(out.memorySec->maxMemoryPages));
298   }
299 }
300 
301 void Writer::addSection(OutputSection *sec) {
302   if (!sec->isNeeded())
303     return;
304   log("addSection: " + toString(*sec));
305   sec->sectionIndex = outputSections.size();
306   outputSections.push_back(sec);
307 }
308 
309 // If a section name is valid as a C identifier (which is rare because of
310 // the leading '.'), linkers are expected to define __start_<secname> and
311 // __stop_<secname> symbols. They are at beginning and end of the section,
312 // respectively. This is not requested by the ELF standard, but GNU ld and
313 // gold provide the feature, and used by many programs.
314 static void addStartStopSymbols(const OutputSegment *seg) {
315   StringRef name = seg->name;
316   if (!isValidCIdentifier(name))
317     return;
318   LLVM_DEBUG(dbgs() << "addStartStopSymbols: " << name << "\n");
319   uint32_t start = seg->startVA;
320   uint32_t stop = start + seg->size;
321   symtab->addOptionalDataSymbol(saver.save("__start_" + name), start);
322   symtab->addOptionalDataSymbol(saver.save("__stop_" + name), stop);
323 }
324 
325 void Writer::addSections() {
326   addSection(out.dylinkSec);
327   addSection(out.typeSec);
328   addSection(out.importSec);
329   addSection(out.functionSec);
330   addSection(out.tableSec);
331   addSection(out.memorySec);
332   addSection(out.globalSec);
333   addSection(out.eventSec);
334   addSection(out.exportSec);
335   addSection(out.elemSec);
336   addSection(out.dataCountSec);
337 
338   addSection(make<CodeSection>(out.functionSec->inputFunctions));
339   addSection(make<DataSection>(segments));
340 
341   createCustomSections();
342 
343   addSection(out.linkingSec);
344   if (config->emitRelocs || config->relocatable) {
345     createRelocSections();
346   }
347 
348   addSection(out.nameSec);
349   addSection(out.producersSec);
350   addSection(out.targetFeaturesSec);
351 }
352 
353 void Writer::finalizeSections() {
354   for (OutputSection *s : outputSections) {
355     s->setOffset(fileSize);
356     s->finalizeContents();
357     fileSize += s->getSize();
358   }
359 }
360 
361 void Writer::populateTargetFeatures() {
362   StringMap<std::string> used;
363   StringMap<std::string> required;
364   StringMap<std::string> disallowed;
365   bool tlsUsed = false;
366 
367   // Only infer used features if user did not specify features
368   bool inferFeatures = !config->features.hasValue();
369 
370   if (!inferFeatures) {
371     for (auto &feature : config->features.getValue())
372       out.targetFeaturesSec->features.insert(feature);
373     // No need to read or check features
374     if (!config->checkFeatures)
375       return;
376   }
377 
378   // Find the sets of used, required, and disallowed features
379   for (ObjFile *file : symtab->objectFiles) {
380     StringRef fileName(file->getName());
381     for (auto &feature : file->getWasmObj()->getTargetFeatures()) {
382       switch (feature.Prefix) {
383       case WASM_FEATURE_PREFIX_USED:
384         used.insert({feature.Name, fileName});
385         break;
386       case WASM_FEATURE_PREFIX_REQUIRED:
387         used.insert({feature.Name, fileName});
388         required.insert({feature.Name, fileName});
389         break;
390       case WASM_FEATURE_PREFIX_DISALLOWED:
391         disallowed.insert({feature.Name, fileName});
392         break;
393       default:
394         error("Unrecognized feature policy prefix " +
395               std::to_string(feature.Prefix));
396       }
397     }
398 
399     for (InputSegment *segment : file->segments) {
400       if (!segment->live)
401         continue;
402       StringRef name = segment->getName();
403       if (name.startswith(".tdata") || name.startswith(".tbss"))
404         tlsUsed = true;
405     }
406   }
407 
408   if (inferFeatures)
409     out.targetFeaturesSec->features.insert(used.keys().begin(),
410                                            used.keys().end());
411 
412   if (out.targetFeaturesSec->features.count("atomics") &&
413       !config->sharedMemory) {
414     if (inferFeatures)
415       error(Twine("'atomics' feature is used by ") + used["atomics"] +
416             ", so --shared-memory must be used");
417     else
418       error("'atomics' feature is used, so --shared-memory must be used");
419   }
420 
421   if (!config->checkFeatures)
422     return;
423 
424   if (disallowed.count("atomics") && config->sharedMemory)
425     error("'atomics' feature is disallowed by " + disallowed["atomics"] +
426           ", so --shared-memory must not be used");
427 
428   if (!used.count("bulk-memory") && config->passiveSegments)
429     error("'bulk-memory' feature must be used in order to emit passive "
430           "segments");
431 
432   if (!used.count("bulk-memory") && tlsUsed)
433     error("'bulk-memory' feature must be used in order to use thread-local "
434           "storage");
435 
436   // Validate that used features are allowed in output
437   if (!inferFeatures) {
438     for (auto &feature : used.keys()) {
439       if (!out.targetFeaturesSec->features.count(feature))
440         error(Twine("Target feature '") + feature + "' used by " +
441               used[feature] + " is not allowed.");
442     }
443   }
444 
445   // Validate the required and disallowed constraints for each file
446   for (ObjFile *file : symtab->objectFiles) {
447     StringRef fileName(file->getName());
448     SmallSet<std::string, 8> objectFeatures;
449     for (auto &feature : file->getWasmObj()->getTargetFeatures()) {
450       if (feature.Prefix == WASM_FEATURE_PREFIX_DISALLOWED)
451         continue;
452       objectFeatures.insert(feature.Name);
453       if (disallowed.count(feature.Name))
454         error(Twine("Target feature '") + feature.Name + "' used in " +
455               fileName + " is disallowed by " + disallowed[feature.Name] +
456               ". Use --no-check-features to suppress.");
457     }
458     for (auto &feature : required.keys()) {
459       if (!objectFeatures.count(feature))
460         error(Twine("Missing target feature '") + feature + "' in " + fileName +
461               ", required by " + required[feature] +
462               ". Use --no-check-features to suppress.");
463     }
464   }
465 }
466 
467 void Writer::calculateImports() {
468   for (Symbol *sym : symtab->getSymbols()) {
469     if (!sym->isUndefined())
470       continue;
471     if (sym->isWeak() && !config->relocatable)
472       continue;
473     if (!sym->isLive())
474       continue;
475     if (!sym->isUsedInRegularObj)
476       continue;
477     // We don't generate imports for data symbols. They however can be imported
478     // as GOT entries.
479     if (isa<DataSymbol>(sym))
480       continue;
481 
482     LLVM_DEBUG(dbgs() << "import: " << sym->getName() << "\n");
483     out.importSec->addImport(sym);
484   }
485 }
486 
487 void Writer::calculateExports() {
488   if (config->relocatable)
489     return;
490 
491   if (!config->relocatable && !config->importMemory)
492     out.exportSec->exports.push_back(
493         WasmExport{"memory", WASM_EXTERNAL_MEMORY, 0});
494 
495   if (!config->relocatable && config->exportTable)
496     out.exportSec->exports.push_back(
497         WasmExport{functionTableName, WASM_EXTERNAL_TABLE, 0});
498 
499   unsigned fakeGlobalIndex = out.importSec->getNumImportedGlobals() +
500                              out.globalSec->inputGlobals.size();
501 
502   for (Symbol *sym : symtab->getSymbols()) {
503     if (!sym->isExported())
504       continue;
505     if (!sym->isLive())
506       continue;
507 
508     StringRef name = sym->getName();
509     WasmExport export_;
510     if (auto *f = dyn_cast<DefinedFunction>(sym)) {
511       export_ = {name, WASM_EXTERNAL_FUNCTION, f->getFunctionIndex()};
512     } else if (auto *g = dyn_cast<DefinedGlobal>(sym)) {
513       // TODO(sbc): Remove this check once to mutable global proposal is
514       // implement in all major browsers.
515       // See: https://github.com/WebAssembly/mutable-global
516       if (g->getGlobalType()->Mutable) {
517         // Only __stack_pointer and __tls_base should ever be create as mutable.
518         assert(g == WasmSym::stackPointer || g == WasmSym::tlsBase);
519         continue;
520       }
521       export_ = {name, WASM_EXTERNAL_GLOBAL, g->getGlobalIndex()};
522     } else if (auto *e = dyn_cast<DefinedEvent>(sym)) {
523       export_ = {name, WASM_EXTERNAL_EVENT, e->getEventIndex()};
524     } else {
525       auto *d = cast<DefinedData>(sym);
526       out.globalSec->definedFakeGlobals.emplace_back(d);
527       export_ = {name, WASM_EXTERNAL_GLOBAL, fakeGlobalIndex++};
528     }
529 
530     LLVM_DEBUG(dbgs() << "Export: " << name << "\n");
531     out.exportSec->exports.push_back(export_);
532   }
533 }
534 
535 void Writer::populateSymtab() {
536   if (!config->relocatable && !config->emitRelocs)
537     return;
538 
539   for (Symbol *sym : symtab->getSymbols())
540     if (sym->isUsedInRegularObj && sym->isLive())
541       out.linkingSec->addToSymtab(sym);
542 
543   for (ObjFile *file : symtab->objectFiles) {
544     LLVM_DEBUG(dbgs() << "Local symtab entries: " << file->getName() << "\n");
545     for (Symbol *sym : file->getSymbols())
546       if (sym->isLocal() && !isa<SectionSymbol>(sym) && sym->isLive())
547         out.linkingSec->addToSymtab(sym);
548   }
549 }
550 
551 void Writer::calculateTypes() {
552   // The output type section is the union of the following sets:
553   // 1. Any signature used in the TYPE relocation
554   // 2. The signatures of all imported functions
555   // 3. The signatures of all defined functions
556   // 4. The signatures of all imported events
557   // 5. The signatures of all defined events
558 
559   for (ObjFile *file : symtab->objectFiles) {
560     ArrayRef<WasmSignature> types = file->getWasmObj()->types();
561     for (uint32_t i = 0; i < types.size(); i++)
562       if (file->typeIsUsed[i])
563         file->typeMap[i] = out.typeSec->registerType(types[i]);
564   }
565 
566   for (const Symbol *sym : out.importSec->importedSymbols) {
567     if (auto *f = dyn_cast<FunctionSymbol>(sym))
568       out.typeSec->registerType(*f->signature);
569     else if (auto *e = dyn_cast<EventSymbol>(sym))
570       out.typeSec->registerType(*e->signature);
571   }
572 
573   for (const InputFunction *f : out.functionSec->inputFunctions)
574     out.typeSec->registerType(f->signature);
575 
576   for (const InputEvent *e : out.eventSec->inputEvents)
577     out.typeSec->registerType(e->signature);
578 }
579 
580 static void scanRelocations() {
581   for (ObjFile *file : symtab->objectFiles) {
582     LLVM_DEBUG(dbgs() << "scanRelocations: " << file->getName() << "\n");
583     for (InputChunk *chunk : file->functions)
584       scanRelocations(chunk);
585     for (InputChunk *chunk : file->segments)
586       scanRelocations(chunk);
587     for (auto &p : file->customSections)
588       scanRelocations(p);
589   }
590 }
591 
592 void Writer::assignIndexes() {
593   // Seal the import section, since other index spaces such as function and
594   // global are effected by the number of imports.
595   out.importSec->seal();
596 
597   for (InputFunction *func : symtab->syntheticFunctions)
598     out.functionSec->addFunction(func);
599 
600   for (ObjFile *file : symtab->objectFiles) {
601     LLVM_DEBUG(dbgs() << "Functions: " << file->getName() << "\n");
602     for (InputFunction *func : file->functions)
603       out.functionSec->addFunction(func);
604   }
605 
606   for (InputGlobal *global : symtab->syntheticGlobals)
607     out.globalSec->addGlobal(global);
608 
609   for (ObjFile *file : symtab->objectFiles) {
610     LLVM_DEBUG(dbgs() << "Globals: " << file->getName() << "\n");
611     for (InputGlobal *global : file->globals)
612       out.globalSec->addGlobal(global);
613   }
614 
615   for (ObjFile *file : symtab->objectFiles) {
616     LLVM_DEBUG(dbgs() << "Events: " << file->getName() << "\n");
617     for (InputEvent *event : file->events)
618       out.eventSec->addEvent(event);
619   }
620 }
621 
622 static StringRef getOutputDataSegmentName(StringRef name) {
623   // With PIC code we currently only support a single data segment since
624   // we only have a single __memory_base to use as our base address.
625   if (config->isPic)
626     return ".data";
627   // We only support one thread-local segment, so we must merge the segments
628   // despite --no-merge-data-segments.
629   // We also need to merge .tbss into .tdata so they share the same offsets.
630   if (name.startswith(".tdata") || name.startswith(".tbss"))
631     return ".tdata";
632   if (!config->mergeDataSegments)
633     return name;
634   if (name.startswith(".text."))
635     return ".text";
636   if (name.startswith(".data."))
637     return ".data";
638   if (name.startswith(".bss."))
639     return ".bss";
640   if (name.startswith(".rodata."))
641     return ".rodata";
642   return name;
643 }
644 
645 void Writer::createOutputSegments() {
646   for (ObjFile *file : symtab->objectFiles) {
647     for (InputSegment *segment : file->segments) {
648       if (!segment->live)
649         continue;
650       StringRef name = getOutputDataSegmentName(segment->getName());
651       OutputSegment *&s = segmentMap[name];
652       if (s == nullptr) {
653         LLVM_DEBUG(dbgs() << "new segment: " << name << "\n");
654         s = make<OutputSegment>(name, segments.size());
655         if (config->passiveSegments || name == ".tdata")
656           s->initFlags = WASM_SEGMENT_IS_PASSIVE;
657         segments.push_back(s);
658       }
659       s->addInputSegment(segment);
660       LLVM_DEBUG(dbgs() << "added data: " << name << ": " << s->size << "\n");
661     }
662   }
663 }
664 
665 static void createFunction(DefinedFunction *func, StringRef bodyContent) {
666   std::string functionBody;
667   {
668     raw_string_ostream os(functionBody);
669     writeUleb128(os, bodyContent.size(), "function size");
670     os << bodyContent;
671   }
672   ArrayRef<uint8_t> body = arrayRefFromStringRef(saver.save(functionBody));
673   cast<SyntheticFunction>(func->function)->setBody(body);
674 }
675 
676 void Writer::createInitMemoryFunction() {
677   LLVM_DEBUG(dbgs() << "createInitMemoryFunction\n");
678   std::string bodyContent;
679   {
680     raw_string_ostream os(bodyContent);
681     writeUleb128(os, 0, "num locals");
682 
683     // initialize passive data segments
684     for (const OutputSegment *s : segments) {
685       if (s->initFlags & WASM_SEGMENT_IS_PASSIVE && s->name != ".tdata") {
686         // destination address
687         writeU8(os, WASM_OPCODE_I32_CONST, "i32.const");
688         writeSleb128(os, s->startVA, "destination address");
689         // source segment offset
690         writeU8(os, WASM_OPCODE_I32_CONST, "i32.const");
691         writeSleb128(os, 0, "segment offset");
692         // memory region size
693         writeU8(os, WASM_OPCODE_I32_CONST, "i32.const");
694         writeSleb128(os, s->size, "memory region size");
695         // memory.init instruction
696         writeU8(os, WASM_OPCODE_MISC_PREFIX, "bulk-memory prefix");
697         writeUleb128(os, WASM_OPCODE_MEMORY_INIT, "MEMORY.INIT");
698         writeUleb128(os, s->index, "segment index immediate");
699         writeU8(os, 0, "memory index immediate");
700         // data.drop instruction
701         writeU8(os, WASM_OPCODE_MISC_PREFIX, "bulk-memory prefix");
702         writeUleb128(os, WASM_OPCODE_DATA_DROP, "DATA.DROP");
703         writeUleb128(os, s->index, "segment index immediate");
704       }
705     }
706     writeU8(os, WASM_OPCODE_END, "END");
707   }
708 
709   createFunction(WasmSym::initMemory, bodyContent);
710 }
711 
712 // For -shared (PIC) output, we create create a synthetic function which will
713 // apply any relocations to the data segments on startup.  This function is
714 // called __wasm_apply_relocs and is added at the beginning of __wasm_call_ctors
715 // before any of the constructors run.
716 void Writer::createApplyRelocationsFunction() {
717   LLVM_DEBUG(dbgs() << "createApplyRelocationsFunction\n");
718   // First write the body's contents to a string.
719   std::string bodyContent;
720   {
721     raw_string_ostream os(bodyContent);
722     writeUleb128(os, 0, "num locals");
723     for (const OutputSegment *seg : segments)
724       for (const InputSegment *inSeg : seg->inputSegments)
725         inSeg->generateRelocationCode(os);
726     writeU8(os, WASM_OPCODE_END, "END");
727   }
728 
729   createFunction(WasmSym::applyRelocs, bodyContent);
730 }
731 
732 // Create synthetic "__wasm_call_ctors" function based on ctor functions
733 // in input object.
734 void Writer::createCallCtorsFunction() {
735   if (!WasmSym::callCtors->isLive())
736     return;
737 
738   // First write the body's contents to a string.
739   std::string bodyContent;
740   {
741     raw_string_ostream os(bodyContent);
742     writeUleb128(os, 0, "num locals");
743 
744     if (config->passiveSegments) {
745       writeU8(os, WASM_OPCODE_CALL, "CALL");
746       writeUleb128(os, WasmSym::initMemory->getFunctionIndex(),
747                    "function index");
748     }
749 
750     if (config->isPic) {
751       writeU8(os, WASM_OPCODE_CALL, "CALL");
752       writeUleb128(os, WasmSym::applyRelocs->getFunctionIndex(),
753                    "function index");
754     }
755 
756     // Call constructors
757     for (const WasmInitEntry &f : initFunctions) {
758       writeU8(os, WASM_OPCODE_CALL, "CALL");
759       writeUleb128(os, f.sym->getFunctionIndex(), "function index");
760     }
761     writeU8(os, WASM_OPCODE_END, "END");
762   }
763 
764   createFunction(WasmSym::callCtors, bodyContent);
765 }
766 
767 void Writer::createInitTLSFunction() {
768   if (!WasmSym::initTLS->isLive())
769     return;
770 
771   std::string bodyContent;
772   {
773     raw_string_ostream os(bodyContent);
774 
775     OutputSegment *tlsSeg = nullptr;
776     for (auto *seg : segments) {
777       if (seg->name == ".tdata") {
778         tlsSeg = seg;
779         break;
780       }
781     }
782 
783     writeUleb128(os, 0, "num locals");
784     if (tlsSeg) {
785       writeU8(os, WASM_OPCODE_LOCAL_GET, "local.get");
786       writeUleb128(os, 0, "local index");
787 
788       writeU8(os, WASM_OPCODE_GLOBAL_SET, "global.set");
789       writeUleb128(os, WasmSym::tlsBase->getGlobalIndex(), "global index");
790 
791       writeU8(os, WASM_OPCODE_LOCAL_GET, "local.get");
792       writeUleb128(os, 0, "local index");
793 
794       writeU8(os, WASM_OPCODE_I32_CONST, "i32.const");
795       writeSleb128(os, 0, "segment offset");
796 
797       writeU8(os, WASM_OPCODE_I32_CONST, "i32.const");
798       writeSleb128(os, tlsSeg->size, "memory region size");
799 
800       writeU8(os, WASM_OPCODE_MISC_PREFIX, "bulk-memory prefix");
801       writeUleb128(os, WASM_OPCODE_MEMORY_INIT, "MEMORY.INIT");
802       writeUleb128(os, tlsSeg->index, "segment index immediate");
803       writeU8(os, 0, "memory index immediate");
804     }
805     writeU8(os, WASM_OPCODE_END, "end function");
806   }
807 
808   createFunction(WasmSym::initTLS, bodyContent);
809 }
810 
811 // Populate InitFunctions vector with init functions from all input objects.
812 // This is then used either when creating the output linking section or to
813 // synthesize the "__wasm_call_ctors" function.
814 void Writer::calculateInitFunctions() {
815   if (!config->relocatable && !WasmSym::callCtors->isLive())
816     return;
817 
818   for (ObjFile *file : symtab->objectFiles) {
819     const WasmLinkingData &l = file->getWasmObj()->linkingData();
820     for (const WasmInitFunc &f : l.InitFunctions) {
821       FunctionSymbol *sym = file->getFunctionSymbol(f.Symbol);
822       // comdat exclusions can cause init functions be discarded.
823       if (sym->isDiscarded())
824         continue;
825       assert(sym->isLive());
826       if (*sym->signature != WasmSignature{{}, {}})
827         error("invalid signature for init func: " + toString(*sym));
828       LLVM_DEBUG(dbgs() << "initFunctions: " << toString(*sym) << "\n");
829       initFunctions.emplace_back(WasmInitEntry{sym, f.Priority});
830     }
831   }
832 
833   // Sort in order of priority (lowest first) so that they are called
834   // in the correct order.
835   llvm::stable_sort(initFunctions,
836                     [](const WasmInitEntry &l, const WasmInitEntry &r) {
837                       return l.priority < r.priority;
838                     });
839 }
840 
841 void Writer::createSyntheticSections() {
842   out.dylinkSec = make<DylinkSection>();
843   out.typeSec = make<TypeSection>();
844   out.importSec = make<ImportSection>();
845   out.functionSec = make<FunctionSection>();
846   out.tableSec = make<TableSection>();
847   out.memorySec = make<MemorySection>();
848   out.globalSec = make<GlobalSection>();
849   out.eventSec = make<EventSection>();
850   out.exportSec = make<ExportSection>();
851   out.elemSec = make<ElemSection>(tableBase);
852   out.dataCountSec = make<DataCountSection>(segments.size());
853   out.linkingSec = make<LinkingSection>(initFunctions, segments);
854   out.nameSec = make<NameSection>();
855   out.producersSec = make<ProducersSection>();
856   out.targetFeaturesSec = make<TargetFeaturesSection>();
857 }
858 
859 void Writer::run() {
860   if (config->relocatable || config->isPic)
861     config->globalBase = 0;
862 
863   // For PIC code the table base is assigned dynamically by the loader.
864   // For non-PIC, we start at 1 so that accessing table index 0 always traps.
865   if (!config->isPic)
866     tableBase = 1;
867 
868   log("-- createOutputSegments");
869   createOutputSegments();
870   log("-- createSyntheticSections");
871   createSyntheticSections();
872   log("-- populateProducers");
873   populateProducers();
874   log("-- populateTargetFeatures");
875   populateTargetFeatures();
876   log("-- calculateImports");
877   calculateImports();
878   log("-- layoutMemory");
879   layoutMemory();
880 
881   if (!config->relocatable) {
882     // Create linker synthesized __start_SECNAME/__stop_SECNAME symbols
883     // This has to be done after memory layout is performed.
884     for (const OutputSegment *seg : segments)
885       addStartStopSymbols(seg);
886   }
887 
888   log("-- scanRelocations");
889   scanRelocations();
890   log("-- assignIndexes");
891   assignIndexes();
892   log("-- calculateInitFunctions");
893   calculateInitFunctions();
894 
895   if (!config->relocatable) {
896     // Create linker synthesized functions
897     if (config->passiveSegments)
898       createInitMemoryFunction();
899     if (config->isPic)
900       createApplyRelocationsFunction();
901     createCallCtorsFunction();
902   }
903 
904   if (config->sharedMemory && !config->shared)
905     createInitTLSFunction();
906 
907   if (errorCount())
908     return;
909 
910   log("-- calculateTypes");
911   calculateTypes();
912   log("-- calculateExports");
913   calculateExports();
914   log("-- calculateCustomSections");
915   calculateCustomSections();
916   log("-- populateSymtab");
917   populateSymtab();
918   log("-- addSections");
919   addSections();
920 
921   if (errorHandler().verbose) {
922     log("Defined Functions: " + Twine(out.functionSec->inputFunctions.size()));
923     log("Defined Globals  : " + Twine(out.globalSec->inputGlobals.size()));
924     log("Defined Events   : " + Twine(out.eventSec->inputEvents.size()));
925     log("Function Imports : " +
926         Twine(out.importSec->getNumImportedFunctions()));
927     log("Global Imports   : " + Twine(out.importSec->getNumImportedGlobals()));
928     log("Event Imports    : " + Twine(out.importSec->getNumImportedEvents()));
929     for (ObjFile *file : symtab->objectFiles)
930       file->dumpInfo();
931   }
932 
933   createHeader();
934   log("-- finalizeSections");
935   finalizeSections();
936 
937   log("-- openFile");
938   openFile();
939   if (errorCount())
940     return;
941 
942   writeHeader();
943 
944   log("-- writeSections");
945   writeSections();
946   if (errorCount())
947     return;
948 
949   if (Error e = buffer->commit())
950     fatal("failed to write the output file: " + toString(std::move(e)));
951 }
952 
953 // Open a result file.
954 void Writer::openFile() {
955   log("writing: " + config->outputFile);
956 
957   Expected<std::unique_ptr<FileOutputBuffer>> bufferOrErr =
958       FileOutputBuffer::create(config->outputFile, fileSize,
959                                FileOutputBuffer::F_executable);
960 
961   if (!bufferOrErr)
962     error("failed to open " + config->outputFile + ": " +
963           toString(bufferOrErr.takeError()));
964   else
965     buffer = std::move(*bufferOrErr);
966 }
967 
968 void Writer::createHeader() {
969   raw_string_ostream os(header);
970   writeBytes(os, WasmMagic, sizeof(WasmMagic), "wasm magic");
971   writeU32(os, WasmVersion, "wasm version");
972   os.flush();
973   fileSize += header.size();
974 }
975 
976 void lld::wasm::writeResult() { Writer().run(); }
977