xref: /llvm-project-15.0.7/lld/wasm/Writer.cpp (revision a7ac2cb6)
1 //===- Writer.cpp ---------------------------------------------------------===//
2 //
3 //                             The LLVM Linker
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "Writer.h"
11 
12 #include "Config.h"
13 #include "OutputSections.h"
14 #include "OutputSegment.h"
15 #include "SymbolTable.h"
16 #include "WriterUtils.h"
17 #include "lld/Common/ErrorHandler.h"
18 #include "lld/Common/Memory.h"
19 #include "lld/Common/Threads.h"
20 #include "llvm/Support/FileOutputBuffer.h"
21 #include "llvm/Support/Format.h"
22 #include "llvm/Support/FormatVariadic.h"
23 #include "llvm/Support/LEB128.h"
24 
25 #include <cstdarg>
26 
27 #define DEBUG_TYPE "lld"
28 
29 using namespace llvm;
30 using namespace llvm::wasm;
31 using namespace lld;
32 using namespace lld::wasm;
33 
34 static constexpr int kStackAlignment = 16;
35 
36 namespace {
37 
38 // Traits for using WasmSignature in a DenseMap.
39 struct WasmSignatureDenseMapInfo {
40   static WasmSignature getEmptyKey() {
41     WasmSignature Sig;
42     Sig.ReturnType = 1;
43     return Sig;
44   }
45   static WasmSignature getTombstoneKey() {
46     WasmSignature Sig;
47     Sig.ReturnType = 2;
48     return Sig;
49   }
50   static unsigned getHashValue(const WasmSignature &Sig) {
51     uintptr_t Value = 0;
52     Value += DenseMapInfo<int32_t>::getHashValue(Sig.ReturnType);
53     for (int32_t Param : Sig.ParamTypes)
54       Value += DenseMapInfo<int32_t>::getHashValue(Param);
55     return Value;
56   }
57   static bool isEqual(const WasmSignature &LHS, const WasmSignature &RHS) {
58     return LHS == RHS;
59   }
60 };
61 
62 // The writer writes a SymbolTable result to a file.
63 class Writer {
64 public:
65   void run();
66 
67 private:
68   void openFile();
69 
70   uint32_t getTypeIndex(const WasmSignature &Sig);
71   void assignSymbolIndexes();
72   void calculateImports();
73   void calculateOffsets();
74   void calculateTypes();
75   void createOutputSegments();
76   void layoutMemory();
77   void createHeader();
78   void createSections();
79   SyntheticSection *createSyntheticSection(uint32_t Type,
80                                            std::string Name = "");
81 
82   // Builtin sections
83   void createTypeSection();
84   void createFunctionSection();
85   void createTableSection();
86   void createGlobalSection();
87   void createExportSection();
88   void createImportSection();
89   void createMemorySection();
90   void createElemSection();
91   void createStartSection();
92   void createCodeSection();
93   void createDataSection();
94 
95   // Custom sections
96   void createRelocSections();
97   void createLinkingSection();
98   void createNameSection();
99 
100   void writeHeader();
101   void writeSections();
102 
103   uint64_t FileSize = 0;
104   uint32_t DataSize = 0;
105   uint32_t NumFunctions = 0;
106   uint32_t NumGlobals = 0;
107   uint32_t NumMemoryPages = 0;
108   uint32_t NumTableElems = 0;
109   uint32_t NumElements = 0;
110   uint32_t InitialTableOffset = 0;
111 
112   std::vector<const WasmSignature *> Types;
113   DenseMap<WasmSignature, int32_t, WasmSignatureDenseMapInfo> TypeIndices;
114   std::vector<Symbol *> FunctionImports;
115   std::vector<Symbol *> GlobalImports;
116 
117   // Elements that are used to construct the final output
118   std::string Header;
119   std::vector<OutputSection *> OutputSections;
120 
121   std::unique_ptr<FileOutputBuffer> Buffer;
122 
123   std::vector<OutputSegment *> Segments;
124   llvm::SmallDenseMap<StringRef, OutputSegment *> SegmentMap;
125 };
126 
127 } // anonymous namespace
128 
129 static void debugPrint(const char *fmt, ...) {
130   if (!errorHandler().Verbose)
131     return;
132   fprintf(stderr, "lld: ");
133   va_list ap;
134   va_start(ap, fmt);
135   vfprintf(stderr, fmt, ap);
136   va_end(ap);
137 }
138 
139 void Writer::createImportSection() {
140   uint32_t NumImports = FunctionImports.size() + GlobalImports.size();
141   if (Config->ImportMemory)
142     ++NumImports;
143 
144   if (NumImports == 0)
145     return;
146 
147   SyntheticSection *Section = createSyntheticSection(WASM_SEC_IMPORT);
148   raw_ostream &OS = Section->getStream();
149 
150   writeUleb128(OS, NumImports, "import count");
151 
152   for (Symbol *Sym : FunctionImports) {
153     WasmImport Import;
154     Import.Module = "env";
155     Import.Field = Sym->getName();
156     Import.Kind = WASM_EXTERNAL_FUNCTION;
157     assert(TypeIndices.count(Sym->getFunctionType()) > 0);
158     Import.SigIndex = TypeIndices.lookup(Sym->getFunctionType());
159     writeImport(OS, Import);
160   }
161 
162   if (Config->ImportMemory) {
163     WasmImport Import;
164     Import.Module = "env";
165     Import.Field = "memory";
166     Import.Kind = WASM_EXTERNAL_MEMORY;
167     Import.Memory.Flags = 0;
168     Import.Memory.Initial = NumMemoryPages;
169     writeImport(OS, Import);
170   }
171 
172   for (Symbol *Sym : GlobalImports) {
173     WasmImport Import;
174     Import.Module = "env";
175     Import.Field = Sym->getName();
176     Import.Kind = WASM_EXTERNAL_GLOBAL;
177     Import.Global.Mutable = false;
178     Import.Global.Type = WASM_TYPE_I32; // Sym->getGlobalType();
179     writeImport(OS, Import);
180   }
181 }
182 
183 void Writer::createTypeSection() {
184   SyntheticSection *Section = createSyntheticSection(WASM_SEC_TYPE);
185   raw_ostream &OS = Section->getStream();
186   writeUleb128(OS, Types.size(), "type count");
187   for (const WasmSignature *Sig : Types) {
188     writeSig(OS, *Sig);
189   }
190 }
191 
192 void Writer::createFunctionSection() {
193   if (!NumFunctions)
194     return;
195 
196   SyntheticSection *Section = createSyntheticSection(WASM_SEC_FUNCTION);
197   raw_ostream &OS = Section->getStream();
198 
199   writeUleb128(OS, NumFunctions, "function count");
200   for (ObjFile *File : Symtab->ObjectFiles) {
201     for (uint32_t Sig : File->getWasmObj()->functionTypes()) {
202       writeUleb128(OS, File->relocateTypeIndex(Sig), "sig index");
203     }
204   }
205 }
206 
207 void Writer::createMemorySection() {
208   if (Config->ImportMemory)
209     return;
210 
211   SyntheticSection *Section = createSyntheticSection(WASM_SEC_MEMORY);
212   raw_ostream &OS = Section->getStream();
213 
214   writeUleb128(OS, 1, "memory count");
215   writeUleb128(OS, 0, "memory limits flags");
216   writeUleb128(OS, NumMemoryPages, "initial pages");
217 }
218 
219 void Writer::createGlobalSection() {
220   SyntheticSection *Section = createSyntheticSection(WASM_SEC_GLOBAL);
221   raw_ostream &OS = Section->getStream();
222 
223   writeUleb128(OS, NumGlobals, "global count");
224   for (auto &Pair : Config->SyntheticGlobals) {
225     WasmGlobal &Global = Pair.second;
226     writeGlobal(OS, Global);
227   }
228 
229   if (Config->Relocatable || Config->EmitRelocs) {
230     for (ObjFile *File : Symtab->ObjectFiles) {
231       uint32_t GlobalIndex = File->NumGlobalImports();
232       for (const WasmGlobal &Global : File->getWasmObj()->globals()) {
233         WasmGlobal RelocatedGlobal(Global);
234         if (Global.Type != WASM_TYPE_I32)
235           fatal("unsupported global type: " + Twine(Global.Type));
236         if (Global.InitExpr.Opcode != WASM_OPCODE_I32_CONST)
237           fatal("unsupported global init opcode: " +
238                 Twine(Global.InitExpr.Opcode));
239         RelocatedGlobal.InitExpr.Value.Int32 =
240             File->getRelocatedAddress(GlobalIndex);
241         writeGlobal(OS, RelocatedGlobal);
242         ++GlobalIndex;
243       }
244     }
245   }
246 }
247 
248 void Writer::createTableSection() {
249   SyntheticSection *Section = createSyntheticSection(WASM_SEC_TABLE);
250   raw_ostream &OS = Section->getStream();
251 
252   writeUleb128(OS, 1, "table count");
253   writeSleb128(OS, WASM_TYPE_ANYFUNC, "table type");
254   writeUleb128(OS, WASM_LIMITS_FLAG_HAS_MAX, "table flags");
255   writeUleb128(OS, NumTableElems, "table initial size");
256   writeUleb128(OS, NumTableElems, "table max size");
257 }
258 
259 void Writer::createExportSection() {
260   // Memory is and main function are exported for executables.
261   bool ExportMemory = !Config->Relocatable && !Config->ImportMemory;
262   bool ExportMain = !Config->Relocatable;
263   bool ExportOther = true; // Config->Relocatable;
264 
265   uint32_t NumExports = 0;
266 
267   if (ExportMemory)
268     ++NumExports;
269 
270   if (ExportMain && !ExportOther)
271     ++NumExports;
272 
273   if (ExportOther) {
274     for (ObjFile *File : Symtab->ObjectFiles) {
275       for (Symbol *Sym : File->getSymbols()) {
276         if (!Sym->isFunction() || Sym->isLocal() || Sym->isUndefined() ||
277             Sym->WrittenToSymtab)
278           continue;
279         Sym->WrittenToSymtab = true;
280         ++NumExports;
281       }
282     }
283   }
284 
285   if (!NumExports)
286     return;
287 
288   SyntheticSection *Section = createSyntheticSection(WASM_SEC_EXPORT);
289   raw_ostream &OS = Section->getStream();
290 
291   writeUleb128(OS, NumExports, "export count");
292 
293   if (ExportMemory) {
294     WasmExport MemoryExport;
295     MemoryExport.Name = "memory";
296     MemoryExport.Kind = WASM_EXTERNAL_MEMORY;
297     MemoryExport.Index = 0;
298     writeExport(OS, MemoryExport);
299   }
300 
301   if (ExportMain) {
302     Symbol *Sym = Symtab->find(Config->Entry);
303     if (Sym->isDefined()) {
304       if (!Sym->isFunction())
305         fatal("entry point is not a function: " + Sym->getName());
306 
307       if (!ExportOther) {
308         WasmExport MainExport;
309         MainExport.Name = Config->Entry;
310         MainExport.Kind = WASM_EXTERNAL_FUNCTION;
311         MainExport.Index = Sym->getOutputIndex();
312         writeExport(OS, MainExport);
313       }
314     }
315   }
316 
317   if (ExportOther) {
318     for (ObjFile *File : Symtab->ObjectFiles) {
319       for (Symbol *Sym : File->getSymbols()) {
320         if (!Sym->isFunction() || Sym->isLocal() | Sym->isUndefined() ||
321             !Sym->WrittenToSymtab)
322           continue;
323         Sym->WrittenToSymtab = false;
324         log("Export: " + Sym->getName());
325         WasmExport Export;
326         Export.Name = Sym->getName();
327         Export.Index = Sym->getOutputIndex();
328         if (Sym->isFunction())
329           Export.Kind = WASM_EXTERNAL_FUNCTION;
330         else
331           Export.Kind = WASM_EXTERNAL_GLOBAL;
332         writeExport(OS, Export);
333       }
334     }
335 
336     // TODO(sbc): Export local symbols too, Even though they are not part
337     // of the symbol table?
338   }
339 }
340 
341 void Writer::createStartSection() {}
342 
343 void Writer::createElemSection() {
344   if (!NumElements)
345     return;
346 
347   SyntheticSection *Section = createSyntheticSection(WASM_SEC_ELEM);
348   raw_ostream &OS = Section->getStream();
349 
350   writeUleb128(OS, 1, "segment count");
351   writeUleb128(OS, 0, "table index");
352   WasmInitExpr InitExpr;
353   InitExpr.Opcode = WASM_OPCODE_I32_CONST;
354   InitExpr.Value.Int32 = InitialTableOffset;
355   writeInitExpr(OS, InitExpr);
356   writeUleb128(OS, NumElements, "elem count");
357 
358   for (ObjFile *File : Symtab->ObjectFiles)
359     for (const WasmElemSegment &Segment : File->getWasmObj()->elements())
360       for (uint64_t FunctionIndex : Segment.Functions)
361         writeUleb128(OS, File->relocateFunctionIndex(FunctionIndex),
362                      "function index");
363 }
364 
365 void Writer::createCodeSection() {
366   if (!NumFunctions)
367     return;
368 
369   log("createCodeSection");
370 
371   auto Section = make<CodeSection>(NumFunctions, Symtab->ObjectFiles);
372   OutputSections.push_back(Section);
373 }
374 
375 void Writer::createDataSection() {
376   if (!Segments.size())
377     return;
378 
379   log("createDataSection");
380   auto Section = make<DataSection>(Segments);
381   OutputSections.push_back(Section);
382 }
383 
384 // Create reloctions sections in the final output.
385 // These are only created when relocatable output is requested.
386 void Writer::createRelocSections() {
387   log("createRelocSections");
388   // Don't use iterator here since we are adding to OutputSection
389   size_t OrigSize = OutputSections.size();
390   for (size_t i = 0; i < OrigSize; i++) {
391     OutputSection *S = OutputSections[i];
392     const char *name;
393     uint32_t Count = S->numRelocations();
394     if (!Count)
395       continue;
396 
397     if (S->Type == WASM_SEC_DATA)
398       name = "reloc.DATA";
399     else if (S->Type == WASM_SEC_CODE)
400       name = "reloc.CODE";
401     else
402       llvm_unreachable("relocations only support for code and data");
403 
404     SyntheticSection *Section = createSyntheticSection(WASM_SEC_CUSTOM, name);
405     raw_ostream &OS = Section->getStream();
406     writeUleb128(OS, S->Type, "reloc section");
407     writeUleb128(OS, Count, "reloc count");
408     S->writeRelocations(OS);
409   }
410 }
411 
412 // Create the custome "linking" section containing linker metadata.
413 // This is only created when relocatable output is requested.
414 void Writer::createLinkingSection() {
415   SyntheticSection *Section =
416       createSyntheticSection(WASM_SEC_CUSTOM, "linking");
417   raw_ostream &OS = Section->getStream();
418 
419   SubSection DataSizeSubSection(WASM_DATA_SIZE);
420   writeUleb128(DataSizeSubSection.getStream(), DataSize, "data size");
421   DataSizeSubSection.finalizeContents();
422   DataSizeSubSection.writeToStream(OS);
423 
424   if (Segments.size() && Config->Relocatable) {
425     SubSection SubSection(WASM_SEGMENT_INFO);
426     writeUleb128(SubSection.getStream(), Segments.size(), "num data segments");
427     for (const OutputSegment *S : Segments) {
428       writeStr(SubSection.getStream(), S->Name, "segment name");
429       writeUleb128(SubSection.getStream(), S->Alignment, "alignment");
430       writeUleb128(SubSection.getStream(), 0, "flags");
431     }
432     SubSection.finalizeContents();
433     SubSection.writeToStream(OS);
434   }
435 }
436 
437 // Create the custom "name" section containing debug symbol names.
438 void Writer::createNameSection() {
439   // Create an array of all function sorted by function index space
440   std::vector<const Symbol *> Names;
441 
442   for (ObjFile *File : Symtab->ObjectFiles) {
443     Names.reserve(Names.size() + File->getSymbols().size());
444     for (Symbol *S : File->getSymbols()) {
445       if (!S->isFunction() || S->isWeak() || S->WrittenToNameSec)
446         continue;
447       S->WrittenToNameSec = true;
448       Names.emplace_back(S);
449     }
450   }
451 
452   SyntheticSection *Section = createSyntheticSection(WASM_SEC_CUSTOM, "name");
453 
454   std::sort(Names.begin(), Names.end(), [](const Symbol *A, const Symbol *B) {
455     return A->getOutputIndex() < B->getOutputIndex();
456   });
457 
458   SubSection FunctionSubsection(WASM_NAMES_FUNCTION);
459   raw_ostream &OS = FunctionSubsection.getStream();
460   writeUleb128(OS, Names.size(), "name count");
461 
462   // We have to iterate through the inputs twice so that all the imports
463   // appear first before any of the local function names.
464   for (const Symbol *S : Names) {
465     writeUleb128(OS, S->getOutputIndex(), "func index");
466     writeStr(OS, S->getName(), "symbol name");
467   }
468 
469   FunctionSubsection.finalizeContents();
470   FunctionSubsection.writeToStream(Section->getStream());
471 }
472 
473 void Writer::writeHeader() {
474   memcpy(Buffer->getBufferStart(), Header.data(), Header.size());
475 }
476 
477 void Writer::writeSections() {
478   uint8_t *Buf = Buffer->getBufferStart();
479   parallelForEach(OutputSections, [Buf](OutputSection *S) { S->writeTo(Buf); });
480 }
481 
482 // Fix the memory layout of the output binary.  This assigns memory offsets
483 // to each of the intput data sections as well as the explicit stack region.
484 void Writer::layoutMemory() {
485   uint32_t MemoryPtr = 0;
486   if (!Config->Relocatable) {
487     MemoryPtr = Config->GlobalBase;
488     debugPrint("mem: global base = %d\n", Config->GlobalBase);
489   }
490 
491   createOutputSegments();
492 
493   // Static data comes first
494   for (OutputSegment *Seg : Segments) {
495     MemoryPtr = alignTo(MemoryPtr, Seg->Alignment);
496     Seg->StartVA = MemoryPtr;
497     debugPrint("mem: %-10s offset=%-8d size=%-4d align=%d\n",
498                Seg->Name.str().c_str(), MemoryPtr, Seg->Size, Seg->Alignment);
499     MemoryPtr += Seg->Size;
500   }
501 
502   DataSize = MemoryPtr;
503   if (!Config->Relocatable)
504     DataSize -= Config->GlobalBase;
505   debugPrint("mem: static data = %d\n", DataSize);
506 
507   // Stack comes after static data
508   if (!Config->Relocatable) {
509     MemoryPtr = alignTo(MemoryPtr, kStackAlignment);
510     if (Config->ZStackSize != alignTo(Config->ZStackSize, kStackAlignment))
511       error("stack size must be " + Twine(kStackAlignment) + "-byte aligned");
512     debugPrint("mem: stack size  = %d\n", Config->ZStackSize);
513     debugPrint("mem: stack base  = %d\n", MemoryPtr);
514     MemoryPtr += Config->ZStackSize;
515     Config->SyntheticGlobals[0].second.InitExpr.Value.Int32 = MemoryPtr;
516     debugPrint("mem: stack top   = %d\n", MemoryPtr);
517   }
518 
519   uint32_t MemSize = alignTo(MemoryPtr, WasmPageSize);
520   NumMemoryPages = MemSize / WasmPageSize;
521   debugPrint("mem: total pages = %d\n", NumMemoryPages);
522 }
523 
524 SyntheticSection *Writer::createSyntheticSection(uint32_t Type,
525                                                  std::string Name) {
526   auto Sec = make<SyntheticSection>(Type, Name);
527   log("createSection: " + toString(Sec));
528   OutputSections.push_back(Sec);
529   return Sec;
530 }
531 
532 void Writer::createSections() {
533   // Known sections
534   createTypeSection();
535   createImportSection();
536   createFunctionSection();
537   createTableSection();
538   createMemorySection();
539   createGlobalSection();
540   createExportSection();
541   createStartSection();
542   createElemSection();
543   createCodeSection();
544   createDataSection();
545 
546   // Custom sections
547   if (Config->EmitRelocs || Config->Relocatable)
548     createRelocSections();
549   createLinkingSection();
550   if (!Config->StripDebug && !Config->StripAll)
551     createNameSection();
552 
553   for (OutputSection *S : OutputSections) {
554     S->setOffset(FileSize);
555     S->finalizeContents();
556     FileSize += S->getSize();
557   }
558 }
559 
560 void Writer::calculateOffsets() {
561   NumGlobals = Config->SyntheticGlobals.size();
562   NumTableElems = InitialTableOffset;
563 
564   for (ObjFile *File : Symtab->ObjectFiles) {
565     const WasmObjectFile *WasmFile = File->getWasmObj();
566 
567     // Function Index
568     File->FunctionIndexOffset =
569         FunctionImports.size() - File->NumFunctionImports() + NumFunctions;
570     NumFunctions += WasmFile->functions().size();
571 
572     // Global Index
573     if (Config->Relocatable || Config->EmitRelocs) {
574       File->GlobalIndexOffset =
575           GlobalImports.size() - File->NumGlobalImports() + NumGlobals;
576       NumGlobals += WasmFile->globals().size();
577     }
578 
579     // Memory
580     if (WasmFile->memories().size()) {
581       if (WasmFile->memories().size() > 1) {
582         fatal(File->getName() + ": contains more than one memory");
583       }
584     }
585 
586     // Table
587     uint32_t TableCount = WasmFile->tables().size();
588     if (TableCount) {
589       if (TableCount > 1)
590         fatal(File->getName() + ": contains more than one table");
591       File->TableIndexOffset = NumTableElems;
592       NumTableElems += WasmFile->tables()[0].Limits.Initial;
593     }
594 
595     // Elem
596     uint32_t SegmentCount = WasmFile->elements().size();
597     if (SegmentCount) {
598       if (SegmentCount > 1)
599         fatal(File->getName() + ": contains more than element segment");
600 
601       const WasmElemSegment &Segment = WasmFile->elements()[0];
602       if (Segment.TableIndex != 0)
603         fatal(File->getName() + ": unsupported table index");
604       if (Segment.Offset.Value.Int32 != 0)
605         fatal(File->getName() + ": unsupported segment offset");
606       NumElements += Segment.Functions.size();
607     }
608   }
609 }
610 
611 void Writer::calculateImports() {
612   for (ObjFile *File : Symtab->ObjectFiles) {
613     for (Symbol *Sym : File->getSymbols()) {
614       if (Sym->hasOutputIndex() || Sym->isDefined() || Sym->isWeak())
615         continue;
616 
617       if (Sym->isFunction()) {
618         Sym->setOutputIndex(FunctionImports.size());
619         FunctionImports.push_back(Sym);
620       } else {
621         Sym->setOutputIndex(GlobalImports.size());
622         GlobalImports.push_back(Sym);
623       }
624     }
625   }
626 }
627 
628 uint32_t Writer::getTypeIndex(const WasmSignature &Sig) {
629   auto Pair = TypeIndices.insert(std::make_pair(Sig, Types.size()));
630   if (Pair.second)
631     Types.push_back(&Sig);
632   return Pair.first->second;
633 }
634 
635 void Writer::calculateTypes() {
636   for (ObjFile *File : Symtab->ObjectFiles) {
637     File->TypeMap.reserve(File->getWasmObj()->types().size());
638     for (const WasmSignature &Sig : File->getWasmObj()->types())
639       File->TypeMap.push_back(getTypeIndex(Sig));
640   }
641 }
642 
643 void Writer::assignSymbolIndexes() {
644   for (ObjFile *File : Symtab->ObjectFiles) {
645     DEBUG(dbgs() << "assignSymbolIndexes: " << File->getName() << "\n");
646     for (Symbol *Sym : File->getSymbols()) {
647       if (Sym->hasOutputIndex() || !Sym->isDefined())
648         continue;
649 
650       if (Sym->getFile() && isa<ObjFile>(Sym->getFile())) {
651         auto *Obj = cast<ObjFile>(Sym->getFile());
652         if (Sym->isFunction())
653           Sym->setOutputIndex(Obj->FunctionIndexOffset +
654                               Sym->getFunctionIndex());
655         else
656           Sym->setOutputIndex(Obj->GlobalIndexOffset + Sym->getGlobalIndex());
657       }
658     }
659   }
660 }
661 
662 static StringRef getOutputDataSegmentName(StringRef Name) {
663   if (Config->Relocatable)
664     return Name;
665 
666   for (StringRef V :
667        {".text.", ".rodata.", ".data.rel.ro.", ".data.", ".bss.rel.ro.",
668         ".bss.", ".init_array.", ".fini_array.", ".ctors.", ".dtors.", ".tbss.",
669         ".gcc_except_table.", ".tdata.", ".ARM.exidx.", ".ARM.extab."}) {
670     StringRef Prefix = V.drop_back();
671     if (Name.startswith(V) || Name == Prefix)
672       return Prefix;
673   }
674 
675   return Name;
676 }
677 
678 void Writer::createOutputSegments() {
679   for (ObjFile *File : Symtab->ObjectFiles) {
680     for (InputSegment *Segment : File->Segments) {
681       StringRef Name = getOutputDataSegmentName(Segment->getName());
682       OutputSegment *&S = SegmentMap[Name];
683       if (S == nullptr) {
684         DEBUG(dbgs() << "new segment: " << Name << "\n");
685         S = make<OutputSegment>(Name);
686         Segments.push_back(S);
687       }
688       S->addInputSegment(Segment);
689       DEBUG(dbgs() << "added data: " << Name << ": " << S->Size << "\n");
690       for (const WasmRelocation &R : File->DataSection->Relocations) {
691         if (R.Offset >= Segment->getInputSectionOffset() &&
692             R.Offset < Segment->getInputSectionOffset() + Segment->getSize()) {
693           Segment->Relocations.push_back(R);
694         }
695       }
696     }
697   }
698 }
699 
700 void Writer::run() {
701   if (!Config->Relocatable)
702     InitialTableOffset = 1;
703 
704   log("-- calculateTypes");
705   calculateTypes();
706   log("-- calculateImports");
707   calculateImports();
708   log("-- calculateOffsets");
709   calculateOffsets();
710 
711   if (errorHandler().Verbose) {
712     log("NumFunctions    : " + Twine(NumFunctions));
713     log("NumGlobals      : " + Twine(NumGlobals));
714     log("NumImports      : " +
715         Twine(FunctionImports.size() + GlobalImports.size()));
716     log("FunctionImports : " + Twine(FunctionImports.size()));
717     log("GlobalImports   : " + Twine(GlobalImports.size()));
718     for (ObjFile *File : Symtab->ObjectFiles)
719       File->dumpInfo();
720   }
721 
722   log("-- assignSymbolIndexes");
723   assignSymbolIndexes();
724   log("-- layoutMemory");
725   layoutMemory();
726 
727   createHeader();
728   log("-- createSections");
729   createSections();
730 
731   log("-- openFile");
732   openFile();
733   if (errorCount())
734     return;
735 
736   writeHeader();
737 
738   log("-- writeSections");
739   writeSections();
740   if (errorCount())
741     return;
742 
743   if (Error E = Buffer->commit())
744     fatal("failed to write the output file: " + toString(std::move(E)));
745 }
746 
747 // Open a result file.
748 void Writer::openFile() {
749   log("writing: " + Config->OutputFile);
750   ::remove(Config->OutputFile.str().c_str());
751 
752   Expected<std::unique_ptr<FileOutputBuffer>> BufferOrErr =
753       FileOutputBuffer::create(Config->OutputFile, FileSize,
754                                FileOutputBuffer::F_executable);
755 
756   if (!BufferOrErr)
757     error("failed to open " + Config->OutputFile + ": " +
758           toString(BufferOrErr.takeError()));
759   else
760     Buffer = std::move(*BufferOrErr);
761 }
762 
763 void Writer::createHeader() {
764   raw_string_ostream OS(Header);
765   writeBytes(OS, WasmMagic, sizeof(WasmMagic), "wasm magic");
766   writeU32(OS, WasmVersion, "wasm version");
767   OS.flush();
768   FileSize += Header.size();
769 }
770 
771 void lld::wasm::writeResult() { Writer().run(); }
772