Coverage Report

Created: 2018-01-17 17:22

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/tools/lld/wasm/Writer.cpp
Line
Count
Source (jump to first uncovered line)
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 "llvm/ADT/DenseSet.h"
13
#include "Config.h"
14
#include "InputChunks.h"
15
#include "OutputSections.h"
16
#include "OutputSegment.h"
17
#include "SymbolTable.h"
18
#include "WriterUtils.h"
19
#include "lld/Common/ErrorHandler.h"
20
#include "lld/Common/Memory.h"
21
#include "lld/Common/Threads.h"
22
#include "llvm/Support/FileOutputBuffer.h"
23
#include "llvm/Support/Format.h"
24
#include "llvm/Support/FormatVariadic.h"
25
#include "llvm/Support/LEB128.h"
26
27
#include <cstdarg>
28
#include <map>
29
30
#define DEBUG_TYPE "lld"
31
32
using namespace llvm;
33
using namespace llvm::wasm;
34
using namespace lld;
35
using namespace lld::wasm;
36
37
static constexpr int kStackAlignment = 16;
38
39
namespace {
40
41
// Traits for using WasmSignature in a DenseMap.
42
struct WasmSignatureDenseMapInfo {
43
0
  static WasmSignature getEmptyKey() {
44
0
    WasmSignature Sig;
45
0
    Sig.ReturnType = 1;
46
0
    return Sig;
47
0
  }
48
0
  static WasmSignature getTombstoneKey() {
49
0
    WasmSignature Sig;
50
0
    Sig.ReturnType = 2;
51
0
    return Sig;
52
0
  }
53
0
  static unsigned getHashValue(const WasmSignature &Sig) {
54
0
    uintptr_t Value = 0;
55
0
    Value += DenseMapInfo<int32_t>::getHashValue(Sig.ReturnType);
56
0
    for (int32_t Param : Sig.ParamTypes)
57
0
      Value += DenseMapInfo<int32_t>::getHashValue(Param);
58
0
    return Value;
59
0
  }
60
0
  static bool isEqual(const WasmSignature &LHS, const WasmSignature &RHS) {
61
0
    return LHS == RHS;
62
0
  }
63
};
64
65
// The writer writes a SymbolTable result to a file.
66
class Writer {
67
public:
68
  void run();
69
70
private:
71
  void openFile();
72
73
  uint32_t lookupType(const WasmSignature &Sig);
74
  uint32_t registerType(const WasmSignature &Sig);
75
  void createCtorFunction();
76
  void calculateInitFunctions();
77
  void assignIndexes();
78
  void calculateImports();
79
  void calculateTypes();
80
  void createOutputSegments();
81
  void layoutMemory();
82
  void createHeader();
83
  void createSections();
84
  SyntheticSection *createSyntheticSection(uint32_t Type,
85
                                           StringRef Name = "");
86
87
  // Builtin sections
88
  void createTypeSection();
89
  void createFunctionSection();
90
  void createTableSection();
91
  void createGlobalSection();
92
  void createExportSection();
93
  void createImportSection();
94
  void createMemorySection();
95
  void createElemSection();
96
  void createStartSection();
97
  void createCodeSection();
98
  void createDataSection();
99
100
  // Custom sections
101
  void createRelocSections();
102
  void createLinkingSection();
103
  void createNameSection();
104
105
  void writeHeader();
106
  void writeSections();
107
108
  uint64_t FileSize = 0;
109
  uint32_t DataSize = 0;
110
  uint32_t NumMemoryPages = 0;
111
  uint32_t InitialTableOffset = 0;
112
113
  std::vector<const WasmSignature *> Types;
114
  DenseMap<WasmSignature, int32_t, WasmSignatureDenseMapInfo> TypeIndices;
115
  std::vector<const Symbol *> ImportedFunctions;
116
  std::vector<const Symbol *> ImportedGlobals;
117
  std::vector<const Symbol *> DefinedGlobals;
118
  std::vector<InputFunction *> DefinedFunctions;
119
  std::vector<const Symbol *> IndirectFunctions;
120
  std::vector<WasmInitFunc> InitFunctions;
121
122
  // Elements that are used to construct the final output
123
  std::string Header;
124
  std::vector<OutputSection *> OutputSections;
125
126
  std::unique_ptr<FileOutputBuffer> Buffer;
127
  std::unique_ptr<SyntheticFunction> CtorFunction;
128
  std::string CtorFunctionBody;
129
130
  std::vector<OutputSegment *> Segments;
131
  llvm::SmallDenseMap<StringRef, OutputSegment *> SegmentMap;
132
};
133
134
} // anonymous namespace
135
136
0
static void debugPrint(const char *fmt, ...) {
137
0
  if (!errorHandler().Verbose)
138
0
    return;
139
0
  fprintf(stderr, "lld: ");
140
0
  va_list ap;
141
0
  va_start(ap, fmt);
142
0
  vfprintf(stderr, fmt, ap);
143
0
  va_end(ap);
144
0
}
145
146
0
void Writer::createImportSection() {
147
0
  uint32_t NumImports = ImportedFunctions.size() + ImportedGlobals.size();
148
0
  if (Config->ImportMemory)
149
0
    ++NumImports;
150
0
151
0
  if (NumImports == 0)
152
0
    return;
153
0
154
0
  SyntheticSection *Section = createSyntheticSection(WASM_SEC_IMPORT);
155
0
  raw_ostream &OS = Section->getStream();
156
0
157
0
  writeUleb128(OS, NumImports, "import count");
158
0
159
0
  for (const Symbol *Sym : ImportedFunctions) {
160
0
    WasmImport Import;
161
0
    Import.Module = "env";
162
0
    Import.Field = Sym->getName();
163
0
    Import.Kind = WASM_EXTERNAL_FUNCTION;
164
0
    Import.SigIndex = lookupType(Sym->getFunctionType());
165
0
    writeImport(OS, Import);
166
0
  }
167
0
168
0
  if (Config->ImportMemory) {
169
0
    WasmImport Import;
170
0
    Import.Module = "env";
171
0
    Import.Field = "memory";
172
0
    Import.Kind = WASM_EXTERNAL_MEMORY;
173
0
    Import.Memory.Flags = 0;
174
0
    Import.Memory.Initial = NumMemoryPages;
175
0
    writeImport(OS, Import);
176
0
  }
177
0
178
0
  for (const Symbol *Sym : ImportedGlobals) {
179
0
    WasmImport Import;
180
0
    Import.Module = "env";
181
0
    Import.Field = Sym->getName();
182
0
    Import.Kind = WASM_EXTERNAL_GLOBAL;
183
0
    Import.Global.Mutable = false;
184
0
    Import.Global.Type = WASM_TYPE_I32;
185
0
    writeImport(OS, Import);
186
0
  }
187
0
}
188
189
0
void Writer::createTypeSection() {
190
0
  SyntheticSection *Section = createSyntheticSection(WASM_SEC_TYPE);
191
0
  raw_ostream &OS = Section->getStream();
192
0
  writeUleb128(OS, Types.size(), "type count");
193
0
  for (const WasmSignature *Sig : Types)
194
0
    writeSig(OS, *Sig);
195
0
}
196
197
0
void Writer::createFunctionSection() {
198
0
  if (DefinedFunctions.empty())
199
0
    return;
200
0
201
0
  SyntheticSection *Section = createSyntheticSection(WASM_SEC_FUNCTION);
202
0
  raw_ostream &OS = Section->getStream();
203
0
204
0
  writeUleb128(OS, DefinedFunctions.size(), "function count");
205
0
  for (const InputFunction *Func : DefinedFunctions)
206
0
    writeUleb128(OS, lookupType(Func->Signature), "sig index");
207
0
}
208
209
0
void Writer::createMemorySection() {
210
0
  if (Config->ImportMemory)
211
0
    return;
212
0
213
0
  SyntheticSection *Section = createSyntheticSection(WASM_SEC_MEMORY);
214
0
  raw_ostream &OS = Section->getStream();
215
0
216
0
  writeUleb128(OS, 1, "memory count");
217
0
  writeUleb128(OS, 0, "memory limits flags");
218
0
  writeUleb128(OS, NumMemoryPages, "initial pages");
219
0
}
220
221
0
void Writer::createGlobalSection() {
222
0
  if (DefinedGlobals.empty())
223
0
    return;
224
0
225
0
  SyntheticSection *Section = createSyntheticSection(WASM_SEC_GLOBAL);
226
0
  raw_ostream &OS = Section->getStream();
227
0
228
0
  writeUleb128(OS, DefinedGlobals.size(), "global count");
229
0
  for (const Symbol *Sym : DefinedGlobals) {
230
0
    WasmGlobal Global;
231
0
    Global.Type = WASM_TYPE_I32;
232
0
    Global.Mutable = Sym == Config->StackPointerSymbol;
233
0
    Global.InitExpr.Opcode = WASM_OPCODE_I32_CONST;
234
0
    Global.InitExpr.Value.Int32 = Sym->getVirtualAddress();
235
0
    writeGlobal(OS, Global);
236
0
  }
237
0
}
238
239
0
void Writer::createTableSection() {
240
0
  // Always output a table section, even if there are no indirect calls.
241
0
  // There are two reasons for this:
242
0
  //  1. For executables it is useful to have an empty table slot at 0
243
0
  //     which can be filled with a null function call handler.
244
0
  //  2. If we don't do this, any program that contains a call_indirect but
245
0
  //     no address-taken function will fail at validation time since it is
246
0
  //     a validation error to include a call_indirect instruction if there
247
0
  //     is not table.
248
0
  uint32_t TableSize = InitialTableOffset + IndirectFunctions.size();
249
0
250
0
  SyntheticSection *Section = createSyntheticSection(WASM_SEC_TABLE);
251
0
  raw_ostream &OS = Section->getStream();
252
0
253
0
  writeUleb128(OS, 1, "table count");
254
0
  writeSleb128(OS, WASM_TYPE_ANYFUNC, "table type");
255
0
  writeUleb128(OS, WASM_LIMITS_FLAG_HAS_MAX, "table flags");
256
0
  writeUleb128(OS, TableSize, "table initial size");
257
0
  writeUleb128(OS, TableSize, "table max size");
258
0
}
259
260
0
void Writer::createExportSection() {
261
0
  bool ExportMemory = !Config->Relocatable && !Config->ImportMemory;
262
0
  Symbol *EntrySym = Symtab->find(Config->Entry);
263
0
  bool ExportEntry = !Config->Relocatable && EntrySym && EntrySym->isDefined();
264
0
  bool ExportHidden = Config->EmitRelocs;
265
0
266
0
  uint32_t NumExports = ExportMemory ? 1 : 0;
267
0
268
0
  std::vector<const Symbol *> SymbolExports;
269
0
  if (ExportEntry)
270
0
    SymbolExports.emplace_back(EntrySym);
271
0
272
0
  for (const Symbol *Sym : Symtab->getSymbols()) {
273
0
    if (Sym->isUndefined() || Sym->isGlobal())
274
0
      continue;
275
0
    if (Sym->isHidden() && !ExportHidden)
276
0
      continue;
277
0
    if (ExportEntry && Sym == EntrySym)
278
0
      continue;
279
0
    SymbolExports.emplace_back(Sym);
280
0
  }
281
0
282
0
  for (const Symbol *Sym : DefinedGlobals) {
283
0
    // Can't export the SP right now because it mutable and mutable globals
284
0
    // connot be exported.
285
0
    if (Sym == Config->StackPointerSymbol)
286
0
      continue;
287
0
    SymbolExports.emplace_back(Sym);
288
0
  }
289
0
290
0
  NumExports += SymbolExports.size();
291
0
  if (!NumExports)
292
0
    return;
293
0
294
0
  SyntheticSection *Section = createSyntheticSection(WASM_SEC_EXPORT);
295
0
  raw_ostream &OS = Section->getStream();
296
0
297
0
  writeUleb128(OS, NumExports, "export count");
298
0
299
0
  if (ExportMemory) {
300
0
    WasmExport MemoryExport;
301
0
    MemoryExport.Name = "memory";
302
0
    MemoryExport.Kind = WASM_EXTERNAL_MEMORY;
303
0
    MemoryExport.Index = 0;
304
0
    writeExport(OS, MemoryExport);
305
0
  }
306
0
307
0
  for (const Symbol *Sym : SymbolExports) {
308
0
    DEBUG(dbgs() << "Export: " << Sym->getName() << "\n");
309
0
    WasmExport Export;
310
0
    Export.Name = Sym->getName();
311
0
    Export.Index = Sym->getOutputIndex();
312
0
    if (Sym->isFunction())
313
0
      Export.Kind = WASM_EXTERNAL_FUNCTION;
314
0
    else
315
0
      Export.Kind = WASM_EXTERNAL_GLOBAL;
316
0
    writeExport(OS, Export);
317
0
  }
318
0
}
319
320
0
void Writer::createStartSection() {}
321
322
0
void Writer::createElemSection() {
323
0
  if (IndirectFunctions.empty())
324
0
    return;
325
0
326
0
  SyntheticSection *Section = createSyntheticSection(WASM_SEC_ELEM);
327
0
  raw_ostream &OS = Section->getStream();
328
0
329
0
  writeUleb128(OS, 1, "segment count");
330
0
  writeUleb128(OS, 0, "table index");
331
0
  WasmInitExpr InitExpr;
332
0
  InitExpr.Opcode = WASM_OPCODE_I32_CONST;
333
0
  InitExpr.Value.Int32 = InitialTableOffset;
334
0
  writeInitExpr(OS, InitExpr);
335
0
  writeUleb128(OS, IndirectFunctions.size(), "elem count");
336
0
337
0
  uint32_t TableIndex = InitialTableOffset;
338
0
  for (const Symbol *Sym : IndirectFunctions) {
339
0
    assert(Sym->getTableIndex() == TableIndex);
340
0
    writeUleb128(OS, Sym->getOutputIndex(), "function index");
341
0
    ++TableIndex;
342
0
  }
343
0
}
344
345
0
void Writer::createCodeSection() {
346
0
  if (DefinedFunctions.empty())
347
0
    return;
348
0
349
0
  log("createCodeSection");
350
0
351
0
  auto Section = make<CodeSection>(DefinedFunctions);
352
0
  OutputSections.push_back(Section);
353
0
}
354
355
0
void Writer::createDataSection() {
356
0
  if (!Segments.size())
357
0
    return;
358
0
359
0
  log("createDataSection");
360
0
  auto Section = make<DataSection>(Segments);
361
0
  OutputSections.push_back(Section);
362
0
}
363
364
// Create relocations sections in the final output.
365
// These are only created when relocatable output is requested.
366
0
void Writer::createRelocSections() {
367
0
  log("createRelocSections");
368
0
  // Don't use iterator here since we are adding to OutputSection
369
0
  size_t OrigSize = OutputSections.size();
370
0
  for (size_t i = 0; i < OrigSize; i++) {
371
0
    OutputSection *S = OutputSections[i];
372
0
    const char *name;
373
0
    uint32_t Count = S->numRelocations();
374
0
    if (!Count)
375
0
      continue;
376
0
377
0
    if (S->Type == WASM_SEC_DATA)
378
0
      name = "reloc.DATA";
379
0
    else if (S->Type == WASM_SEC_CODE)
380
0
      name = "reloc.CODE";
381
0
    else
382
0
      llvm_unreachable("relocations only supported for code and data");
383
0
384
0
    SyntheticSection *Section = createSyntheticSection(WASM_SEC_CUSTOM, name);
385
0
    raw_ostream &OS = Section->getStream();
386
0
    writeUleb128(OS, S->Type, "reloc section");
387
0
    writeUleb128(OS, Count, "reloc count");
388
0
    S->writeRelocations(OS);
389
0
  }
390
0
}
391
392
// Create the custom "linking" section containing linker metadata.
393
// This is only created when relocatable output is requested.
394
0
void Writer::createLinkingSection() {
395
0
  SyntheticSection *Section =
396
0
      createSyntheticSection(WASM_SEC_CUSTOM, "linking");
397
0
  raw_ostream &OS = Section->getStream();
398
0
399
0
  SubSection DataSizeSubSection(WASM_DATA_SIZE);
400
0
  writeUleb128(DataSizeSubSection.getStream(), DataSize, "data size");
401
0
  DataSizeSubSection.finalizeContents();
402
0
  DataSizeSubSection.writeToStream(OS);
403
0
404
0
  if (!Config->Relocatable)
405
0
    return;
406
0
407
0
  if (Segments.size()) {
408
0
    SubSection SubSection(WASM_SEGMENT_INFO);
409
0
    writeUleb128(SubSection.getStream(), Segments.size(), "num data segments");
410
0
    for (const OutputSegment *S : Segments) {
411
0
      writeStr(SubSection.getStream(), S->Name, "segment name");
412
0
      writeUleb128(SubSection.getStream(), S->Alignment, "alignment");
413
0
      writeUleb128(SubSection.getStream(), 0, "flags");
414
0
    }
415
0
    SubSection.finalizeContents();
416
0
    SubSection.writeToStream(OS);
417
0
  }
418
0
419
0
  if (!InitFunctions.empty()) {
420
0
    SubSection SubSection(WASM_INIT_FUNCS);
421
0
    writeUleb128(SubSection.getStream(), InitFunctions.size(),
422
0
                 "num init functions");
423
0
    for (const WasmInitFunc &F : InitFunctions) {
424
0
      writeUleb128(SubSection.getStream(), F.Priority, "priority");
425
0
      writeUleb128(SubSection.getStream(), F.FunctionIndex, "function index");
426
0
    }
427
0
    SubSection.finalizeContents();
428
0
    SubSection.writeToStream(OS);
429
0
  }
430
0
431
0
  struct ComdatEntry { unsigned Kind; uint32_t Index; };
432
0
  std::map<StringRef,std::vector<ComdatEntry>> Comdats;
433
0
434
0
  for (const InputFunction *F : DefinedFunctions) {
435
0
    StringRef Comdat = F->getComdat();
436
0
    if (!Comdat.empty())
437
0
      Comdats[Comdat].emplace_back(
438
0
          ComdatEntry{WASM_COMDAT_FUNCTION, F->getOutputIndex()});
439
0
  }
440
0
  for (uint32_t I = 0; I < Segments.size(); ++I) {
441
0
    const auto &InputSegments = Segments[I]->InputSegments;
442
0
    if (InputSegments.empty())
443
0
      continue;
444
0
    StringRef Comdat = InputSegments[0]->getComdat();
445
#ifndef NDEBUG
446
    for (const InputSegment *IS : InputSegments)
447
      assert(IS->getComdat() == Comdat);
448
#endif
449
0
    if (!Comdat.empty())
450
0
      Comdats[Comdat].emplace_back(ComdatEntry{WASM_COMDAT_DATA, I});
451
0
  }
452
0
453
0
  if (!Comdats.empty()) {
454
0
    SubSection SubSection(WASM_COMDAT_INFO);
455
0
    writeUleb128(SubSection.getStream(), Comdats.size(), "num comdats");
456
0
    for (const auto &C : Comdats) {
457
0
      writeStr(SubSection.getStream(), C.first, "comdat name");
458
0
      writeUleb128(SubSection.getStream(), 0, "comdat flags"); // flags for future use
459
0
      writeUleb128(SubSection.getStream(), C.second.size(), "num entries");
460
0
      for (const ComdatEntry &Entry : C.second) {
461
0
        writeUleb128(SubSection.getStream(), Entry.Kind, "entry kind");
462
0
        writeUleb128(SubSection.getStream(), Entry.Index, "entry index");
463
0
      }
464
0
    }
465
0
    SubSection.finalizeContents();
466
0
    SubSection.writeToStream(OS);
467
0
  }
468
0
}
469
470
// Create the custom "name" section containing debug symbol names.
471
0
void Writer::createNameSection() {
472
0
  unsigned NumNames = ImportedFunctions.size();
473
0
  for (const InputFunction *F : DefinedFunctions)
474
0
    if (!F->getName().empty())
475
0
      ++NumNames;
476
0
477
0
  if (NumNames == 0)
478
0
    return;
479
0
480
0
  SyntheticSection *Section = createSyntheticSection(WASM_SEC_CUSTOM, "name");
481
0
482
0
  SubSection FunctionSubsection(WASM_NAMES_FUNCTION);
483
0
  raw_ostream &OS = FunctionSubsection.getStream();
484
0
  writeUleb128(OS, NumNames, "name count");
485
0
486
0
  // Names must appear in function index order.  As it happens ImportedFunctions
487
0
  // and DefinedFunctions are numbers in order with imported functions coming
488
0
  // first.
489
0
  for (const Symbol *S : ImportedFunctions) {
490
0
    writeUleb128(OS, S->getOutputIndex(), "import index");
491
0
    writeStr(OS, S->getName(), "symbol name");
492
0
  }
493
0
  for (const InputFunction *F : DefinedFunctions) {
494
0
    if (!F->getName().empty()) {
495
0
      writeUleb128(OS, F->getOutputIndex(), "func index");
496
0
      writeStr(OS, F->getName(), "symbol name");
497
0
    }
498
0
  }
499
0
500
0
  FunctionSubsection.finalizeContents();
501
0
  FunctionSubsection.writeToStream(Section->getStream());
502
0
}
503
504
0
void Writer::writeHeader() {
505
0
  memcpy(Buffer->getBufferStart(), Header.data(), Header.size());
506
0
}
507
508
void Writer::writeSections() {
509
  uint8_t *Buf = Buffer->getBufferStart();
510
0
  parallelForEach(OutputSections, [Buf](OutputSection *S) { S->writeTo(Buf); });
511
}
512
513
// Fix the memory layout of the output binary.  This assigns memory offsets
514
// to each of the input data sections as well as the explicit stack region.
515
0
void Writer::layoutMemory() {
516
0
  uint32_t MemoryPtr = 0;
517
0
  if (!Config->Relocatable) {
518
0
    MemoryPtr = Config->GlobalBase;
519
0
    debugPrint("mem: global base = %d\n", Config->GlobalBase);
520
0
  }
521
0
522
0
  createOutputSegments();
523
0
524
0
  // Static data comes first
525
0
  for (OutputSegment *Seg : Segments) {
526
0
    MemoryPtr = alignTo(MemoryPtr, Seg->Alignment);
527
0
    Seg->StartVA = MemoryPtr;
528
0
    debugPrint("mem: %-15s offset=%-8d size=%-8d align=%d\n",
529
0
               Seg->Name.str().c_str(), MemoryPtr, Seg->Size, Seg->Alignment);
530
0
    MemoryPtr += Seg->Size;
531
0
  }
532
0
533
0
  DataSize = MemoryPtr;
534
0
  if (!Config->Relocatable)
535
0
    DataSize -= Config->GlobalBase;
536
0
  debugPrint("mem: static data = %d\n", DataSize);
537
0
538
0
  // Stack comes after static data
539
0
  if (!Config->Relocatable) {
540
0
    MemoryPtr = alignTo(MemoryPtr, kStackAlignment);
541
0
    if (Config->ZStackSize != alignTo(Config->ZStackSize, kStackAlignment))
542
0
      error("stack size must be " + Twine(kStackAlignment) + "-byte aligned");
543
0
    debugPrint("mem: stack size  = %d\n", Config->ZStackSize);
544
0
    debugPrint("mem: stack base  = %d\n", MemoryPtr);
545
0
    MemoryPtr += Config->ZStackSize;
546
0
    Config->StackPointerSymbol->setVirtualAddress(MemoryPtr);
547
0
    debugPrint("mem: stack top   = %d\n", MemoryPtr);
548
0
    // Set `__heap_base` to directly follow the end of the stack.  We don't
549
0
    // allocate any heap memory up front, but instead really on the malloc/brk
550
0
    // implementation growing the memory at runtime.
551
0
    Config->HeapBaseSymbol->setVirtualAddress(MemoryPtr);
552
0
    debugPrint("mem: heap base   = %d\n", MemoryPtr);
553
0
  }
554
0
555
0
  uint32_t MemSize = alignTo(MemoryPtr, WasmPageSize);
556
0
  NumMemoryPages = MemSize / WasmPageSize;
557
0
  debugPrint("mem: total pages = %d\n", NumMemoryPages);
558
0
}
559
560
SyntheticSection *Writer::createSyntheticSection(uint32_t Type,
561
0
                                                 StringRef Name) {
562
0
  auto Sec = make<SyntheticSection>(Type, Name);
563
0
  log("createSection: " + toString(*Sec));
564
0
  OutputSections.push_back(Sec);
565
0
  return Sec;
566
0
}
567
568
void Writer::createSections() {
569
  // Known sections
570
  createTypeSection();
571
  createImportSection();
572
  createFunctionSection();
573
  createTableSection();
574
  createMemorySection();
575
  createGlobalSection();
576
  createExportSection();
577
  createStartSection();
578
  createElemSection();
579
  createCodeSection();
580
  createDataSection();
581
582
  // Custom sections
583
  if (Config->EmitRelocs)
584
    createRelocSections();
585
  createLinkingSection();
586
  if (!Config->StripDebug && !Config->StripAll)
587
    createNameSection();
588
589
  for (OutputSection *S : OutputSections) {
590
    S->setOffset(FileSize);
591
    S->finalizeContents();
592
    FileSize += S->getSize();
593
  }
594
}
595
596
0
void Writer::calculateImports() {
597
0
  for (Symbol *Sym : Symtab->getSymbols()) {
598
0
    if (!Sym->isUndefined() || Sym->isWeak())
599
0
      continue;
600
0
601
0
    if (Sym->isFunction()) {
602
0
      Sym->setOutputIndex(ImportedFunctions.size());
603
0
      ImportedFunctions.push_back(Sym);
604
0
    } else {
605
0
      Sym->setOutputIndex(ImportedGlobals.size());
606
0
      ImportedGlobals.push_back(Sym);
607
0
    }
608
0
  }
609
0
}
610
611
0
uint32_t Writer::lookupType(const WasmSignature &Sig) {
612
0
  auto It = TypeIndices.find(Sig);
613
0
  if (It == TypeIndices.end()) {
614
0
    error("type not found: " + toString(Sig));
615
0
    return 0;
616
0
  }
617
0
  return It->second;
618
0
}
619
620
0
uint32_t Writer::registerType(const WasmSignature &Sig) {
621
0
  auto Pair = TypeIndices.insert(std::make_pair(Sig, Types.size()));
622
0
  if (Pair.second) {
623
0
    DEBUG(dbgs() << "type " << toString(Sig) << "\n");
624
0
    Types.push_back(&Sig);
625
0
  }
626
0
  return Pair.first->second;
627
0
}
628
629
0
void Writer::calculateTypes() {
630
0
  for (ObjFile *File : Symtab->ObjectFiles) {
631
0
    File->TypeMap.reserve(File->getWasmObj()->types().size());
632
0
    for (const WasmSignature &Sig : File->getWasmObj()->types())
633
0
      File->TypeMap.push_back(registerType(Sig));
634
0
  }
635
0
636
0
  for (Symbol *Sym : Symtab->getSymbols())
637
0
    if (Sym->isFunction())
638
0
      registerType(Sym->getFunctionType());
639
0
}
640
641
0
void Writer::assignIndexes() {
642
0
  uint32_t GlobalIndex = ImportedGlobals.size() + DefinedGlobals.size();
643
0
  uint32_t FunctionIndex = ImportedFunctions.size() + DefinedFunctions.size();
644
0
645
0
  if (Config->StackPointerSymbol) {
646
0
    DefinedGlobals.emplace_back(Config->StackPointerSymbol);
647
0
    Config->StackPointerSymbol->setOutputIndex(GlobalIndex++);
648
0
  }
649
0
650
0
  if (Config->HeapBaseSymbol) {
651
0
    DefinedGlobals.emplace_back(Config->HeapBaseSymbol);
652
0
    Config->HeapBaseSymbol->setOutputIndex(GlobalIndex++);
653
0
  }
654
0
655
0
  if (Config->EmitRelocs)
656
0
    DefinedGlobals.reserve(Symtab->getSymbols().size());
657
0
658
0
  uint32_t TableIndex = InitialTableOffset;
659
0
660
0
  for (ObjFile *File : Symtab->ObjectFiles) {
661
0
    if (Config->EmitRelocs) {
662
0
      DEBUG(dbgs() << "Globals: " << File->getName() << "\n");
663
0
      for (Symbol *Sym : File->getSymbols()) {
664
0
        // Create wasm globals for data symbols defined in this file
665
0
        if (!Sym->isDefined() || File != Sym->getFile())
666
0
          continue;
667
0
        if (Sym->isFunction())
668
0
          continue;
669
0
670
0
        DefinedGlobals.emplace_back(Sym);
671
0
        Sym->setOutputIndex(GlobalIndex++);
672
0
      }
673
0
    }
674
0
  }
675
0
676
0
  for (ObjFile *File : Symtab->ObjectFiles) {
677
0
    DEBUG(dbgs() << "Functions: " << File->getName() << "\n");
678
0
    for (InputFunction *Func : File->Functions) {
679
0
      if (Func->Discarded)
680
0
        continue;
681
0
      DefinedFunctions.emplace_back(Func);
682
0
      Func->setOutputIndex(FunctionIndex++);
683
0
    }
684
0
  }
685
0
686
0
  for (ObjFile *File : Symtab->ObjectFiles) {
687
0
    DEBUG(dbgs() << "Table Indexes: " << File->getName() << "\n");
688
0
    for (Symbol *Sym : File->getTableSymbols()) {
689
0
      if (Sym->hasTableIndex() || !Sym->hasOutputIndex())
690
0
        continue;
691
0
      Sym->setTableIndex(TableIndex++);
692
0
      IndirectFunctions.emplace_back(Sym);
693
0
    }
694
0
  }
695
0
}
696
697
0
static StringRef getOutputDataSegmentName(StringRef Name) {
698
0
  if (Config->Relocatable)
699
0
    return Name;
700
0
701
0
  for (StringRef V :
702
0
       {".text.", ".rodata.", ".data.rel.ro.", ".data.", ".bss.rel.ro.",
703
0
        ".bss.", ".init_array.", ".fini_array.", ".ctors.", ".dtors.", ".tbss.",
704
0
        ".gcc_except_table.", ".tdata.", ".ARM.exidx.", ".ARM.extab."}) {
705
0
    StringRef Prefix = V.drop_back();
706
0
    if (Name.startswith(V) || Name == Prefix)
707
0
      return Prefix;
708
0
  }
709
0
710
0
  return Name;
711
0
}
712
713
0
void Writer::createOutputSegments() {
714
0
  for (ObjFile *File : Symtab->ObjectFiles) {
715
0
    for (InputSegment *Segment : File->Segments) {
716
0
      if (Segment->Discarded)
717
0
        continue;
718
0
      StringRef Name = getOutputDataSegmentName(Segment->getName());
719
0
      OutputSegment *&S = SegmentMap[Name];
720
0
      if (S == nullptr) {
721
0
        DEBUG(dbgs() << "new segment: " << Name << "\n");
722
0
        S = make<OutputSegment>(Name);
723
0
        Segments.push_back(S);
724
0
      }
725
0
      S->addInputSegment(Segment);
726
0
      DEBUG(dbgs() << "added data: " << Name << ": " << S->Size << "\n");
727
0
    }
728
0
  }
729
0
}
730
731
static const int OPCODE_CALL = 0x10;
732
static const int OPCODE_END = 0xb;
733
734
// Create synthetic "__wasm_call_ctors" function based on ctor functions
735
// in input object.
736
0
void Writer::createCtorFunction() {
737
0
  uint32_t FunctionIndex = ImportedFunctions.size() + DefinedFunctions.size();
738
0
  Config->CtorSymbol->setOutputIndex(FunctionIndex);
739
0
740
0
  // First write the body bytes to a string.
741
0
  std::string FunctionBody;
742
0
  static WasmSignature Signature = {{}, WASM_TYPE_NORESULT};
743
0
  {
744
0
    raw_string_ostream OS(FunctionBody);
745
0
    writeUleb128(OS, 0, "num locals");
746
0
    for (const WasmInitFunc &F : InitFunctions) {
747
0
      writeU8(OS, OPCODE_CALL, "CALL");
748
0
      writeUleb128(OS, F.FunctionIndex, "function index");
749
0
    }
750
0
    writeU8(OS, OPCODE_END, "END");
751
0
  }
752
0
753
0
  // Once we know the size of the body we can create the final function body
754
0
  raw_string_ostream OS(CtorFunctionBody);
755
0
  writeUleb128(OS, FunctionBody.size(), "function size");
756
0
  OS.flush();
757
0
  CtorFunctionBody += FunctionBody;
758
0
  ArrayRef<uint8_t> BodyArray(
759
0
      reinterpret_cast<const uint8_t *>(CtorFunctionBody.data()),
760
0
      CtorFunctionBody.size());
761
0
  CtorFunction = llvm::make_unique<SyntheticFunction>(
762
0
      Signature, BodyArray, Config->CtorSymbol->getName());
763
0
  CtorFunction->setOutputIndex(FunctionIndex);
764
0
  DefinedFunctions.emplace_back(CtorFunction.get());
765
0
}
766
767
// Populate InitFunctions vector with init functions from all input objects.
768
// This is then used either when creating the output linking section or to
769
// synthesize the "__wasm_call_ctors" function.
770
0
void Writer::calculateInitFunctions() {
771
0
  for (ObjFile *File : Symtab->ObjectFiles) {
772
0
    const WasmLinkingData &L = File->getWasmObj()->linkingData();
773
0
    InitFunctions.reserve(InitFunctions.size() + L.InitFunctions.size());
774
0
    for (const WasmInitFunc &F : L.InitFunctions)
775
0
      InitFunctions.emplace_back(WasmInitFunc{
776
0
          F.Priority, File->relocateFunctionIndex(F.FunctionIndex)});
777
0
  }
778
0
  // Sort in order of priority (lowest first) so that they are called
779
0
  // in the correct order.
780
0
  std::sort(InitFunctions.begin(), InitFunctions.end(),
781
0
            [](const WasmInitFunc &L, const WasmInitFunc &R) {
782
0
              return L.Priority < R.Priority;
783
0
            });
784
0
}
785
786
void Writer::run() {
787
  if (!Config->Relocatable)
788
    InitialTableOffset = 1;
789
790
  log("-- calculateTypes");
791
  calculateTypes();
792
  log("-- calculateImports");
793
  calculateImports();
794
  log("-- assignIndexes");
795
  assignIndexes();
796
  log("-- calculateInitFunctions");
797
  calculateInitFunctions();
798
  if (!Config->Relocatable)
799
    createCtorFunction();
800
801
  if (errorHandler().Verbose) {
802
    log("Defined Functions: " + Twine(DefinedFunctions.size()));
803
    log("Defined Globals  : " + Twine(DefinedGlobals.size()));
804
    log("Function Imports : " + Twine(ImportedFunctions.size()));
805
    log("Global Imports   : " + Twine(ImportedGlobals.size()));
806
    log("Total Imports    : " +
807
        Twine(ImportedFunctions.size() + ImportedGlobals.size()));
808
    for (ObjFile *File : Symtab->ObjectFiles)
809
      File->dumpInfo();
810
  }
811
812
  log("-- layoutMemory");
813
  layoutMemory();
814
815
  createHeader();
816
  log("-- createSections");
817
  createSections();
818
819
  log("-- openFile");
820
  openFile();
821
  if (errorCount())
822
    return;
823
824
  writeHeader();
825
826
  log("-- writeSections");
827
  writeSections();
828
  if (errorCount())
829
    return;
830
831
  if (Error E = Buffer->commit())
832
    fatal("failed to write the output file: " + toString(std::move(E)));
833
}
834
835
// Open a result file.
836
0
void Writer::openFile() {
837
0
  log("writing: " + Config->OutputFile);
838
0
  ::remove(Config->OutputFile.str().c_str());
839
0
840
0
  Expected<std::unique_ptr<FileOutputBuffer>> BufferOrErr =
841
0
      FileOutputBuffer::create(Config->OutputFile, FileSize,
842
0
                               FileOutputBuffer::F_executable);
843
0
844
0
  if (!BufferOrErr)
845
0
    error("failed to open " + Config->OutputFile + ": " +
846
0
          toString(BufferOrErr.takeError()));
847
0
  else
848
0
    Buffer = std::move(*BufferOrErr);
849
0
}
850
851
0
void Writer::createHeader() {
852
0
  raw_string_ostream OS(Header);
853
0
  writeBytes(OS, WasmMagic, sizeof(WasmMagic), "wasm magic");
854
0
  writeU32(OS, WasmVersion, "wasm version");
855
0
  OS.flush();
856
0
  FileSize += Header.size();
857
0
}
858
859
0
void lld::wasm::writeResult() { Writer().run(); }