blob: a32e1bde8c5484c019741f119eb58ec3e6acbf64 [file] [log] [blame]
Sam Cleggc94d3932017-11-17 18:14:09 +00001//===- 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"
Sam Cleggc94d3932017-11-17 18:14:09 +000013#include "OutputSections.h"
14#include "OutputSegment.h"
15#include "SymbolTable.h"
16#include "WriterUtils.h"
17#include "lld/Common/ErrorHandler.h"
Rui Ueyama2017d522017-11-28 20:39:17 +000018#include "lld/Common/Memory.h"
Sam Cleggc94d3932017-11-17 18:14:09 +000019#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
29using namespace llvm;
30using namespace llvm::wasm;
31using namespace lld;
32using namespace lld::wasm;
33
34static constexpr int kStackAlignment = 16;
35
36namespace {
37
Sam Cleggc94d3932017-11-17 18:14:09 +000038// Traits for using WasmSignature in a DenseMap.
39struct 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.
63class Writer {
64public:
65 void run();
66
67private:
68 void openFile();
69
Sam Cleggb8621592017-11-30 01:40:08 +000070 uint32_t getTypeIndex(const WasmSignature &Sig);
Sam Cleggc94d3932017-11-17 18:14:09 +000071 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;
Sam Cleggc94d3932017-11-17 18:14:09 +0000106 uint32_t NumMemoryPages = 0;
Sam Cleggc94d3932017-11-17 18:14:09 +0000107 uint32_t InitialTableOffset = 0;
108
109 std::vector<const WasmSignature *> Types;
110 DenseMap<WasmSignature, int32_t, WasmSignatureDenseMapInfo> TypeIndices;
Sam Clegg74fe0ba2017-12-07 01:51:24 +0000111 std::vector<const Symbol *> FunctionImports;
112 std::vector<const Symbol *> GlobalImports;
113 std::vector<const Symbol *> DefinedGlobals;
Sam Cleggfc1a9122017-12-11 22:00:56 +0000114 std::vector<const Symbol *> IndirectFunctions;
Sam Cleggc94d3932017-11-17 18:14:09 +0000115
116 // Elements that are used to construct the final output
117 std::string Header;
118 std::vector<OutputSection *> OutputSections;
119
120 std::unique_ptr<FileOutputBuffer> Buffer;
121
122 std::vector<OutputSegment *> Segments;
123 llvm::SmallDenseMap<StringRef, OutputSegment *> SegmentMap;
124};
125
126} // anonymous namespace
127
128static void debugPrint(const char *fmt, ...) {
129 if (!errorHandler().Verbose)
130 return;
131 fprintf(stderr, "lld: ");
132 va_list ap;
133 va_start(ap, fmt);
134 vfprintf(stderr, fmt, ap);
135 va_end(ap);
136}
137
138void Writer::createImportSection() {
139 uint32_t NumImports = FunctionImports.size() + GlobalImports.size();
140 if (Config->ImportMemory)
141 ++NumImports;
142
143 if (NumImports == 0)
144 return;
145
146 SyntheticSection *Section = createSyntheticSection(WASM_SEC_IMPORT);
147 raw_ostream &OS = Section->getStream();
148
149 writeUleb128(OS, NumImports, "import count");
150
Sam Clegg4eedcfc2017-12-05 19:05:45 +0000151 for (const Symbol *Sym : FunctionImports) {
Sam Cleggc94d3932017-11-17 18:14:09 +0000152 WasmImport Import;
153 Import.Module = "env";
154 Import.Field = Sym->getName();
155 Import.Kind = WASM_EXTERNAL_FUNCTION;
Sam Cleggb8621592017-11-30 01:40:08 +0000156 assert(TypeIndices.count(Sym->getFunctionType()) > 0);
157 Import.SigIndex = TypeIndices.lookup(Sym->getFunctionType());
Sam Cleggc94d3932017-11-17 18:14:09 +0000158 writeImport(OS, Import);
159 }
160
161 if (Config->ImportMemory) {
162 WasmImport Import;
163 Import.Module = "env";
164 Import.Field = "memory";
165 Import.Kind = WASM_EXTERNAL_MEMORY;
166 Import.Memory.Flags = 0;
167 Import.Memory.Initial = NumMemoryPages;
168 writeImport(OS, Import);
169 }
170
Sam Clegg4eedcfc2017-12-05 19:05:45 +0000171 for (const Symbol *Sym : GlobalImports) {
Sam Cleggc94d3932017-11-17 18:14:09 +0000172 WasmImport Import;
173 Import.Module = "env";
174 Import.Field = Sym->getName();
175 Import.Kind = WASM_EXTERNAL_GLOBAL;
176 Import.Global.Mutable = false;
Sam Cleggd451da12017-12-19 19:56:27 +0000177 Import.Global.Type = WASM_TYPE_I32;
Sam Cleggc94d3932017-11-17 18:14:09 +0000178 writeImport(OS, Import);
179 }
180}
181
182void Writer::createTypeSection() {
183 SyntheticSection *Section = createSyntheticSection(WASM_SEC_TYPE);
184 raw_ostream &OS = Section->getStream();
185 writeUleb128(OS, Types.size(), "type count");
Sam Cleggd451da12017-12-19 19:56:27 +0000186 for (const WasmSignature *Sig : Types)
Sam Cleggc94d3932017-11-17 18:14:09 +0000187 writeSig(OS, *Sig);
Sam Cleggc94d3932017-11-17 18:14:09 +0000188}
189
190void Writer::createFunctionSection() {
191 if (!NumFunctions)
192 return;
193
194 SyntheticSection *Section = createSyntheticSection(WASM_SEC_FUNCTION);
195 raw_ostream &OS = Section->getStream();
196
197 writeUleb128(OS, NumFunctions, "function count");
Sam Cleggd451da12017-12-19 19:56:27 +0000198 for (ObjFile *File : Symtab->ObjectFiles)
199 for (uint32_t Sig : File->getWasmObj()->functionTypes())
Sam Cleggc94d3932017-11-17 18:14:09 +0000200 writeUleb128(OS, File->relocateTypeIndex(Sig), "sig index");
Sam Cleggc94d3932017-11-17 18:14:09 +0000201}
202
203void Writer::createMemorySection() {
204 if (Config->ImportMemory)
205 return;
206
207 SyntheticSection *Section = createSyntheticSection(WASM_SEC_MEMORY);
208 raw_ostream &OS = Section->getStream();
209
210 writeUleb128(OS, 1, "memory count");
211 writeUleb128(OS, 0, "memory limits flags");
212 writeUleb128(OS, NumMemoryPages, "initial pages");
213}
214
215void Writer::createGlobalSection() {
Sam Clegg74fe0ba2017-12-07 01:51:24 +0000216 if (DefinedGlobals.empty())
217 return;
218
Sam Cleggc94d3932017-11-17 18:14:09 +0000219 SyntheticSection *Section = createSyntheticSection(WASM_SEC_GLOBAL);
220 raw_ostream &OS = Section->getStream();
221
Sam Clegg74fe0ba2017-12-07 01:51:24 +0000222 writeUleb128(OS, DefinedGlobals.size(), "global count");
223 for (const Symbol *Sym : DefinedGlobals) {
Sam Clegg4eedcfc2017-12-05 19:05:45 +0000224 WasmGlobal Global;
225 Global.Type = WASM_TYPE_I32;
226 Global.Mutable = Sym == Config->StackPointerSymbol;
227 Global.InitExpr.Opcode = WASM_OPCODE_I32_CONST;
228 Global.InitExpr.Value.Int32 = Sym->getVirtualAddress();
Sam Cleggc94d3932017-11-17 18:14:09 +0000229 writeGlobal(OS, Global);
230 }
Sam Cleggc94d3932017-11-17 18:14:09 +0000231}
232
233void Writer::createTableSection() {
Sam Cleggfc1a9122017-12-11 22:00:56 +0000234 // Always output a table section, even if there are no indirect calls.
235 // There are two reasons for this:
236 // 1. For executables it is useful to have an empty table slot at 0
237 // which can be filled with a null function call handler.
238 // 2. If we don't do this, any program that contains a call_indirect but
239 // no address-taken function will fail at validation time since it is
240 // a validation error to include a call_indirect instruction if there
241 // is not table.
242 uint32_t TableSize = InitialTableOffset + IndirectFunctions.size();
243
Sam Cleggc94d3932017-11-17 18:14:09 +0000244 SyntheticSection *Section = createSyntheticSection(WASM_SEC_TABLE);
245 raw_ostream &OS = Section->getStream();
246
247 writeUleb128(OS, 1, "table count");
248 writeSleb128(OS, WASM_TYPE_ANYFUNC, "table type");
249 writeUleb128(OS, WASM_LIMITS_FLAG_HAS_MAX, "table flags");
Sam Cleggfc1a9122017-12-11 22:00:56 +0000250 writeUleb128(OS, TableSize, "table initial size");
251 writeUleb128(OS, TableSize, "table max size");
Sam Cleggc94d3932017-11-17 18:14:09 +0000252}
253
254void Writer::createExportSection() {
Sam Cleggc94d3932017-11-17 18:14:09 +0000255 bool ExportMemory = !Config->Relocatable && !Config->ImportMemory;
Sam Clegg4b27c052017-12-03 02:38:04 +0000256 Symbol *EntrySym = Symtab->find(Config->Entry);
257 bool ExportEntry = !Config->Relocatable && EntrySym && EntrySym->isDefined();
Sam Clegg74fe0ba2017-12-07 01:51:24 +0000258 bool ExportHidden = Config->EmitRelocs;
Sam Cleggc94d3932017-11-17 18:14:09 +0000259
Sam Clegg74fe0ba2017-12-07 01:51:24 +0000260 uint32_t NumExports = ExportMemory ? 1 : 0;
Sam Cleggc94d3932017-11-17 18:14:09 +0000261
Sam Clegg74fe0ba2017-12-07 01:51:24 +0000262 std::vector<const Symbol *> SymbolExports;
Sam Clegg4b27c052017-12-03 02:38:04 +0000263 if (ExportEntry)
Sam Clegg74fe0ba2017-12-07 01:51:24 +0000264 SymbolExports.emplace_back(EntrySym);
Sam Cleggc94d3932017-11-17 18:14:09 +0000265
Sam Clegg74fe0ba2017-12-07 01:51:24 +0000266 for (const Symbol *Sym : Symtab->getSymbols()) {
267 if (Sym->isUndefined() || Sym->isGlobal())
268 continue;
269 if (Sym->isHidden() && !ExportHidden)
270 continue;
271 if (ExportEntry && Sym == EntrySym)
272 continue;
273 SymbolExports.emplace_back(Sym);
Sam Cleggc94d3932017-11-17 18:14:09 +0000274 }
275
Sam Clegg74fe0ba2017-12-07 01:51:24 +0000276 for (const Symbol *Sym : DefinedGlobals) {
277 // Can't export the SP right now because it mutable and mutable globals
278 // connot be exported.
279 if (Sym == Config->StackPointerSymbol)
280 continue;
281 SymbolExports.emplace_back(Sym);
282 }
283
284 NumExports += SymbolExports.size();
Sam Cleggc94d3932017-11-17 18:14:09 +0000285 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
Sam Clegg74fe0ba2017-12-07 01:51:24 +0000301 for (const Symbol *Sym : SymbolExports) {
302 log("Export: " + Sym->getName());
303 WasmExport Export;
304 Export.Name = Sym->getName();
305 Export.Index = Sym->getOutputIndex();
306 if (Sym->isFunction())
307 Export.Kind = WASM_EXTERNAL_FUNCTION;
308 else
309 Export.Kind = WASM_EXTERNAL_GLOBAL;
310 writeExport(OS, Export);
Sam Cleggc94d3932017-11-17 18:14:09 +0000311 }
312}
313
314void Writer::createStartSection() {}
315
316void Writer::createElemSection() {
Sam Cleggfc1a9122017-12-11 22:00:56 +0000317 if (IndirectFunctions.empty())
Sam Cleggc94d3932017-11-17 18:14:09 +0000318 return;
319
320 SyntheticSection *Section = createSyntheticSection(WASM_SEC_ELEM);
321 raw_ostream &OS = Section->getStream();
322
323 writeUleb128(OS, 1, "segment count");
324 writeUleb128(OS, 0, "table index");
325 WasmInitExpr InitExpr;
326 InitExpr.Opcode = WASM_OPCODE_I32_CONST;
327 InitExpr.Value.Int32 = InitialTableOffset;
328 writeInitExpr(OS, InitExpr);
Sam Cleggfc1a9122017-12-11 22:00:56 +0000329 writeUleb128(OS, IndirectFunctions.size(), "elem count");
Sam Cleggc94d3932017-11-17 18:14:09 +0000330
Sam Cleggfc1a9122017-12-11 22:00:56 +0000331 uint32_t TableIndex = InitialTableOffset;
332 for (const Symbol *Sym : IndirectFunctions) {
333 assert(Sym->getTableIndex() == TableIndex);
334 writeUleb128(OS, Sym->getOutputIndex(), "function index");
335 ++TableIndex;
336 }
Sam Cleggc94d3932017-11-17 18:14:09 +0000337}
338
339void Writer::createCodeSection() {
340 if (!NumFunctions)
341 return;
342
343 log("createCodeSection");
344
345 auto Section = make<CodeSection>(NumFunctions, Symtab->ObjectFiles);
346 OutputSections.push_back(Section);
347}
348
349void Writer::createDataSection() {
350 if (!Segments.size())
351 return;
352
353 log("createDataSection");
354 auto Section = make<DataSection>(Segments);
355 OutputSections.push_back(Section);
356}
357
Sam Cleggd451da12017-12-19 19:56:27 +0000358// Create relocations sections in the final output.
Sam Cleggc94d3932017-11-17 18:14:09 +0000359// These are only created when relocatable output is requested.
360void Writer::createRelocSections() {
361 log("createRelocSections");
362 // Don't use iterator here since we are adding to OutputSection
363 size_t OrigSize = OutputSections.size();
364 for (size_t i = 0; i < OrigSize; i++) {
365 OutputSection *S = OutputSections[i];
366 const char *name;
367 uint32_t Count = S->numRelocations();
368 if (!Count)
369 continue;
370
371 if (S->Type == WASM_SEC_DATA)
372 name = "reloc.DATA";
373 else if (S->Type == WASM_SEC_CODE)
374 name = "reloc.CODE";
375 else
Sam Cleggd451da12017-12-19 19:56:27 +0000376 llvm_unreachable("relocations only supported for code and data");
Sam Cleggc94d3932017-11-17 18:14:09 +0000377
378 SyntheticSection *Section = createSyntheticSection(WASM_SEC_CUSTOM, name);
379 raw_ostream &OS = Section->getStream();
380 writeUleb128(OS, S->Type, "reloc section");
381 writeUleb128(OS, Count, "reloc count");
382 S->writeRelocations(OS);
383 }
384}
385
Sam Clegg49ed9262017-12-01 00:53:21 +0000386// Create the custom "linking" section containing linker metadata.
Sam Cleggc94d3932017-11-17 18:14:09 +0000387// This is only created when relocatable output is requested.
388void Writer::createLinkingSection() {
389 SyntheticSection *Section =
390 createSyntheticSection(WASM_SEC_CUSTOM, "linking");
391 raw_ostream &OS = Section->getStream();
392
393 SubSection DataSizeSubSection(WASM_DATA_SIZE);
394 writeUleb128(DataSizeSubSection.getStream(), DataSize, "data size");
395 DataSizeSubSection.finalizeContents();
396 DataSizeSubSection.writeToStream(OS);
397
Sam Clegg0d0dd392017-12-19 17:09:45 +0000398 if (!Config->Relocatable)
399 return;
400
401 if (Segments.size()) {
Sam Cleggc94d3932017-11-17 18:14:09 +0000402 SubSection SubSection(WASM_SEGMENT_INFO);
403 writeUleb128(SubSection.getStream(), Segments.size(), "num data segments");
404 for (const OutputSegment *S : Segments) {
405 writeStr(SubSection.getStream(), S->Name, "segment name");
406 writeUleb128(SubSection.getStream(), S->Alignment, "alignment");
407 writeUleb128(SubSection.getStream(), 0, "flags");
408 }
409 SubSection.finalizeContents();
410 SubSection.writeToStream(OS);
411 }
Sam Clegg0d0dd392017-12-19 17:09:45 +0000412
413 std::vector<WasmInitFunc> InitFunctions;
414 for (ObjFile *File : Symtab->ObjectFiles) {
415 const WasmLinkingData &L = File->getWasmObj()->linkingData();
416 InitFunctions.reserve(InitFunctions.size() + L.InitFunctions.size());
Sam Cleggd451da12017-12-19 19:56:27 +0000417 for (const WasmInitFunc &F : L.InitFunctions)
Sam Clegg0d0dd392017-12-19 17:09:45 +0000418 InitFunctions.emplace_back(WasmInitFunc{
419 F.Priority, File->relocateFunctionIndex(F.FunctionIndex)});
Sam Clegg0d0dd392017-12-19 17:09:45 +0000420 }
421
422 if (!InitFunctions.empty()) {
423 SubSection SubSection(WASM_INIT_FUNCS);
424 writeUleb128(SubSection.getStream(), InitFunctions.size(),
425 "num init functionsw");
426 for (const WasmInitFunc &F : InitFunctions) {
427 writeUleb128(SubSection.getStream(), F.Priority, "priority");
428 writeUleb128(SubSection.getStream(), F.FunctionIndex, "function index");
429 }
430 SubSection.finalizeContents();
431 SubSection.writeToStream(OS);
432 }
Sam Cleggc94d3932017-11-17 18:14:09 +0000433}
434
435// Create the custom "name" section containing debug symbol names.
436void Writer::createNameSection() {
437 // Create an array of all function sorted by function index space
438 std::vector<const Symbol *> Names;
439
440 for (ObjFile *File : Symtab->ObjectFiles) {
441 Names.reserve(Names.size() + File->getSymbols().size());
442 for (Symbol *S : File->getSymbols()) {
443 if (!S->isFunction() || S->isWeak() || S->WrittenToNameSec)
444 continue;
445 S->WrittenToNameSec = true;
446 Names.emplace_back(S);
447 }
448 }
449
450 SyntheticSection *Section = createSyntheticSection(WASM_SEC_CUSTOM, "name");
451
452 std::sort(Names.begin(), Names.end(), [](const Symbol *A, const Symbol *B) {
453 return A->getOutputIndex() < B->getOutputIndex();
454 });
455
456 SubSection FunctionSubsection(WASM_NAMES_FUNCTION);
457 raw_ostream &OS = FunctionSubsection.getStream();
458 writeUleb128(OS, Names.size(), "name count");
459
460 // We have to iterate through the inputs twice so that all the imports
461 // appear first before any of the local function names.
462 for (const Symbol *S : Names) {
463 writeUleb128(OS, S->getOutputIndex(), "func index");
464 writeStr(OS, S->getName(), "symbol name");
465 }
466
467 FunctionSubsection.finalizeContents();
468 FunctionSubsection.writeToStream(Section->getStream());
469}
470
471void Writer::writeHeader() {
472 memcpy(Buffer->getBufferStart(), Header.data(), Header.size());
473}
474
475void Writer::writeSections() {
476 uint8_t *Buf = Buffer->getBufferStart();
477 parallelForEach(OutputSections, [Buf](OutputSection *S) { S->writeTo(Buf); });
478}
479
480// Fix the memory layout of the output binary. This assigns memory offsets
Sam Clegg49ed9262017-12-01 00:53:21 +0000481// to each of the input data sections as well as the explicit stack region.
Sam Cleggc94d3932017-11-17 18:14:09 +0000482void Writer::layoutMemory() {
483 uint32_t MemoryPtr = 0;
484 if (!Config->Relocatable) {
485 MemoryPtr = Config->GlobalBase;
486 debugPrint("mem: global base = %d\n", Config->GlobalBase);
487 }
488
489 createOutputSegments();
490
491 // Static data comes first
492 for (OutputSegment *Seg : Segments) {
493 MemoryPtr = alignTo(MemoryPtr, Seg->Alignment);
494 Seg->StartVA = MemoryPtr;
495 debugPrint("mem: %-10s offset=%-8d size=%-4d align=%d\n",
496 Seg->Name.str().c_str(), MemoryPtr, Seg->Size, Seg->Alignment);
497 MemoryPtr += Seg->Size;
498 }
499
500 DataSize = MemoryPtr;
501 if (!Config->Relocatable)
502 DataSize -= Config->GlobalBase;
503 debugPrint("mem: static data = %d\n", DataSize);
504
505 // Stack comes after static data
506 if (!Config->Relocatable) {
507 MemoryPtr = alignTo(MemoryPtr, kStackAlignment);
508 if (Config->ZStackSize != alignTo(Config->ZStackSize, kStackAlignment))
509 error("stack size must be " + Twine(kStackAlignment) + "-byte aligned");
510 debugPrint("mem: stack size = %d\n", Config->ZStackSize);
511 debugPrint("mem: stack base = %d\n", MemoryPtr);
512 MemoryPtr += Config->ZStackSize;
Sam Clegg4eedcfc2017-12-05 19:05:45 +0000513 Config->StackPointerSymbol->setVirtualAddress(MemoryPtr);
Sam Cleggc94d3932017-11-17 18:14:09 +0000514 debugPrint("mem: stack top = %d\n", MemoryPtr);
515 }
516
517 uint32_t MemSize = alignTo(MemoryPtr, WasmPageSize);
518 NumMemoryPages = MemSize / WasmPageSize;
519 debugPrint("mem: total pages = %d\n", NumMemoryPages);
520}
521
522SyntheticSection *Writer::createSyntheticSection(uint32_t Type,
523 std::string Name) {
524 auto Sec = make<SyntheticSection>(Type, Name);
525 log("createSection: " + toString(Sec));
526 OutputSections.push_back(Sec);
527 return Sec;
528}
529
530void Writer::createSections() {
531 // Known sections
532 createTypeSection();
533 createImportSection();
534 createFunctionSection();
535 createTableSection();
536 createMemorySection();
537 createGlobalSection();
538 createExportSection();
539 createStartSection();
540 createElemSection();
541 createCodeSection();
542 createDataSection();
543
544 // Custom sections
Sam Clegg22cfe522017-12-05 16:53:25 +0000545 if (Config->EmitRelocs)
Sam Cleggc94d3932017-11-17 18:14:09 +0000546 createRelocSections();
547 createLinkingSection();
548 if (!Config->StripDebug && !Config->StripAll)
549 createNameSection();
550
551 for (OutputSection *S : OutputSections) {
552 S->setOffset(FileSize);
553 S->finalizeContents();
554 FileSize += S->getSize();
555 }
556}
557
558void Writer::calculateOffsets() {
Sam Cleggc94d3932017-11-17 18:14:09 +0000559 for (ObjFile *File : Symtab->ObjectFiles) {
560 const WasmObjectFile *WasmFile = File->getWasmObj();
561
562 // Function Index
563 File->FunctionIndexOffset =
564 FunctionImports.size() - File->NumFunctionImports() + NumFunctions;
565 NumFunctions += WasmFile->functions().size();
566
Sam Cleggc94d3932017-11-17 18:14:09 +0000567 // Memory
Sam Cleggfc1a9122017-12-11 22:00:56 +0000568 if (WasmFile->memories().size() > 1)
569 fatal(File->getName() + ": contains more than one memory");
Sam Cleggc94d3932017-11-17 18:14:09 +0000570 }
571}
572
573void Writer::calculateImports() {
Sam Clegg574d7ce2017-12-15 19:23:49 +0000574 for (Symbol *Sym : Symtab->getSymbols()) {
Sam Cleggc0181152017-12-15 22:17:15 +0000575 if (!Sym->isUndefined() || Sym->isWeak())
Sam Clegg574d7ce2017-12-15 19:23:49 +0000576 continue;
Sam Cleggc94d3932017-11-17 18:14:09 +0000577
Sam Clegg574d7ce2017-12-15 19:23:49 +0000578 if (Sym->isFunction()) {
579 Sym->setOutputIndex(FunctionImports.size());
580 FunctionImports.push_back(Sym);
581 } else {
582 Sym->setOutputIndex(GlobalImports.size());
583 GlobalImports.push_back(Sym);
Sam Cleggc94d3932017-11-17 18:14:09 +0000584 }
585 }
586}
587
Sam Cleggb8621592017-11-30 01:40:08 +0000588uint32_t Writer::getTypeIndex(const WasmSignature &Sig) {
589 auto Pair = TypeIndices.insert(std::make_pair(Sig, Types.size()));
590 if (Pair.second)
591 Types.push_back(&Sig);
592 return Pair.first->second;
593}
594
Sam Cleggc94d3932017-11-17 18:14:09 +0000595void Writer::calculateTypes() {
596 for (ObjFile *File : Symtab->ObjectFiles) {
597 File->TypeMap.reserve(File->getWasmObj()->types().size());
Sam Cleggb8621592017-11-30 01:40:08 +0000598 for (const WasmSignature &Sig : File->getWasmObj()->types())
599 File->TypeMap.push_back(getTypeIndex(Sig));
Sam Cleggc94d3932017-11-17 18:14:09 +0000600 }
601}
602
603void Writer::assignSymbolIndexes() {
Sam Clegg74fe0ba2017-12-07 01:51:24 +0000604 uint32_t GlobalIndex = GlobalImports.size();
605
606 if (Config->StackPointerSymbol) {
607 DefinedGlobals.emplace_back(Config->StackPointerSymbol);
608 Config->StackPointerSymbol->setOutputIndex(GlobalIndex++);
609 }
610
611 if (Config->EmitRelocs)
612 DefinedGlobals.reserve(Symtab->getSymbols().size());
613
Sam Cleggfc1a9122017-12-11 22:00:56 +0000614 uint32_t TableIndex = InitialTableOffset;
615
Sam Cleggc94d3932017-11-17 18:14:09 +0000616 for (ObjFile *File : Symtab->ObjectFiles) {
617 DEBUG(dbgs() << "assignSymbolIndexes: " << File->getName() << "\n");
Sam Cleggfc1a9122017-12-11 22:00:56 +0000618
Sam Cleggc94d3932017-11-17 18:14:09 +0000619 for (Symbol *Sym : File->getSymbols()) {
Sam Clegg3f1fb882017-12-11 21:52:21 +0000620 // Assign indexes for symbols defined with this file.
621 if (!Sym->isDefined() || File != Sym->getFile())
Sam Cleggc94d3932017-11-17 18:14:09 +0000622 continue;
Sam Clegg74fe0ba2017-12-07 01:51:24 +0000623 if (Sym->isFunction()) {
Sam Clegg3f1fb882017-12-11 21:52:21 +0000624 auto *Obj = cast<ObjFile>(Sym->getFile());
625 Sym->setOutputIndex(Obj->FunctionIndexOffset +
626 Sym->getFunctionIndex());
Sam Clegg74fe0ba2017-12-07 01:51:24 +0000627 } else if (Config->EmitRelocs) {
628 DefinedGlobals.emplace_back(Sym);
629 Sym->setOutputIndex(GlobalIndex++);
Sam Cleggc94d3932017-11-17 18:14:09 +0000630 }
631 }
Sam Cleggfc1a9122017-12-11 22:00:56 +0000632
633 for (Symbol *Sym : File->getTableSymbols()) {
634 if (!Sym->hasTableIndex()) {
635 Sym->setTableIndex(TableIndex++);
636 IndirectFunctions.emplace_back(Sym);
637 }
638 }
Sam Cleggc94d3932017-11-17 18:14:09 +0000639 }
640}
641
642static StringRef getOutputDataSegmentName(StringRef Name) {
643 if (Config->Relocatable)
644 return Name;
645
646 for (StringRef V :
647 {".text.", ".rodata.", ".data.rel.ro.", ".data.", ".bss.rel.ro.",
648 ".bss.", ".init_array.", ".fini_array.", ".ctors.", ".dtors.", ".tbss.",
649 ".gcc_except_table.", ".tdata.", ".ARM.exidx.", ".ARM.extab."}) {
650 StringRef Prefix = V.drop_back();
651 if (Name.startswith(V) || Name == Prefix)
652 return Prefix;
653 }
654
655 return Name;
656}
657
658void Writer::createOutputSegments() {
659 for (ObjFile *File : Symtab->ObjectFiles) {
660 for (InputSegment *Segment : File->Segments) {
661 StringRef Name = getOutputDataSegmentName(Segment->getName());
662 OutputSegment *&S = SegmentMap[Name];
663 if (S == nullptr) {
664 DEBUG(dbgs() << "new segment: " << Name << "\n");
665 S = make<OutputSegment>(Name);
666 Segments.push_back(S);
667 }
668 S->addInputSegment(Segment);
669 DEBUG(dbgs() << "added data: " << Name << ": " << S->Size << "\n");
Sam Cleggc94d3932017-11-17 18:14:09 +0000670 }
671 }
672}
673
674void Writer::run() {
675 if (!Config->Relocatable)
676 InitialTableOffset = 1;
677
678 log("-- calculateTypes");
679 calculateTypes();
680 log("-- calculateImports");
681 calculateImports();
682 log("-- calculateOffsets");
683 calculateOffsets();
684
685 if (errorHandler().Verbose) {
Sam Cleggfc1a9122017-12-11 22:00:56 +0000686 log("Defined Functions: " + Twine(NumFunctions));
687 log("Defined Globals : " + Twine(DefinedGlobals.size()));
688 log("Function Imports : " + Twine(FunctionImports.size()));
689 log("Global Imports : " + Twine(GlobalImports.size()));
690 log("Total Imports : " +
Sam Cleggc94d3932017-11-17 18:14:09 +0000691 Twine(FunctionImports.size() + GlobalImports.size()));
Sam Cleggc94d3932017-11-17 18:14:09 +0000692 for (ObjFile *File : Symtab->ObjectFiles)
693 File->dumpInfo();
694 }
695
696 log("-- assignSymbolIndexes");
697 assignSymbolIndexes();
698 log("-- layoutMemory");
699 layoutMemory();
700
701 createHeader();
702 log("-- createSections");
703 createSections();
704
705 log("-- openFile");
706 openFile();
707 if (errorCount())
708 return;
709
710 writeHeader();
711
712 log("-- writeSections");
713 writeSections();
714 if (errorCount())
715 return;
716
717 if (Error E = Buffer->commit())
718 fatal("failed to write the output file: " + toString(std::move(E)));
719}
720
721// Open a result file.
722void Writer::openFile() {
723 log("writing: " + Config->OutputFile);
724 ::remove(Config->OutputFile.str().c_str());
725
726 Expected<std::unique_ptr<FileOutputBuffer>> BufferOrErr =
727 FileOutputBuffer::create(Config->OutputFile, FileSize,
728 FileOutputBuffer::F_executable);
729
730 if (!BufferOrErr)
731 error("failed to open " + Config->OutputFile + ": " +
732 toString(BufferOrErr.takeError()));
733 else
734 Buffer = std::move(*BufferOrErr);
735}
736
737void Writer::createHeader() {
738 raw_string_ostream OS(Header);
739 writeBytes(OS, WasmMagic, sizeof(WasmMagic), "wasm magic");
740 writeU32(OS, WasmVersion, "wasm version");
741 OS.flush();
742 FileSize += Header.size();
743}
744
745void lld::wasm::writeResult() { Writer().run(); }