Coverage Report

Created: 2019-07-24 05:18

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/tools/lld/wasm/SyntheticSections.h
Line
Count
Source (jump to first uncovered line)
1
//===- SyntheticSection.h ---------------------------------------*- C++ -*-===//
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
// Synthetic sections represent chunks of linker-created data. If you
10
// need to create a chunk of data that to be included in some section
11
// in the result, you probably want to create that as a synthetic section.
12
//
13
//===----------------------------------------------------------------------===//
14
15
#ifndef LLD_WASM_SYNTHETIC_SECTIONS_H
16
#define LLD_WASM_SYNTHETIC_SECTIONS_H
17
18
#include "OutputSections.h"
19
20
#include "llvm/ADT/SmallSet.h"
21
#include "llvm/ADT/StringMap.h"
22
#include "llvm/Object/WasmTraits.h"
23
24
#define DEBUG_TYPE "lld"
25
26
namespace lld {
27
namespace wasm {
28
29
// An init entry to be written to either the synthetic init func or the
30
// linking metadata.
31
struct WasmInitEntry {
32
  const FunctionSymbol *sym;
33
  uint32_t priority;
34
};
35
36
class SyntheticSection : public OutputSection {
37
public:
38
  SyntheticSection(uint32_t type, std::string name = "")
39
2.91k
      : OutputSection(type, name), bodyOutputStream(body) {
40
2.91k
    if (!name.empty())
41
982
      writeStr(bodyOutputStream, name, "section name");
42
2.91k
  }
43
44
1.21k
  void writeTo(uint8_t *buf) override {
45
1.21k
    assert(offset);
46
1.21k
    log("writing " + toString(*this));
47
1.21k
    memcpy(buf + offset, header.data(), header.size());
48
1.21k
    memcpy(buf + offset + header.size(), body.data(), body.size());
49
1.21k
  }
50
51
2.42k
  size_t getSize() const override { return header.size() + body.size(); }
52
53
0
  virtual void writeBody() {}
54
55
1.21k
  void finalizeContents() override {
56
1.21k
    writeBody();
57
1.21k
    bodyOutputStream.flush();
58
1.21k
    createHeader(body.size());
59
1.21k
  }
60
61
0
  raw_ostream &getStream() { return bodyOutputStream; }
62
63
  std::string body;
64
65
protected:
66
  llvm::raw_string_ostream bodyOutputStream;
67
};
68
69
// Create the custom "dylink" section containing information for the dynamic
70
// linker.
71
// See
72
// https://github.com/WebAssembly/tool-conventions/blob/master/DynamicLinking.md
73
class DylinkSection : public SyntheticSection {
74
public:
75
193
  DylinkSection() : SyntheticSection(llvm::wasm::WASM_SEC_CUSTOM, "dylink") {}
76
172
  bool isNeeded() const override { return config->isPic; }
77
  void writeBody() override;
78
79
  uint32_t memAlign = 0;
80
  uint32_t memSize = 0;
81
};
82
83
class TypeSection : public SyntheticSection {
84
public:
85
193
  TypeSection() : SyntheticSection(llvm::wasm::WASM_SEC_TYPE) {}
86
87
172
  bool isNeeded() const override { return types.size() > 0; };
88
  void writeBody() override;
89
  uint32_t registerType(const WasmSignature &sig);
90
  uint32_t lookupType(const WasmSignature &sig);
91
92
protected:
93
  std::vector<const WasmSignature *> types;
94
  llvm::DenseMap<WasmSignature, int32_t> typeIndices;
95
};
96
97
class ImportSection : public SyntheticSection {
98
public:
99
193
  ImportSection() : SyntheticSection(llvm::wasm::WASM_SEC_IMPORT) {}
100
172
  bool isNeeded() const override { return getNumImports() > 0; }
101
  void writeBody() override;
102
  void addImport(Symbol *sym);
103
  void addGOTEntry(Symbol *sym);
104
193
  void seal() { isSealed = true; }
105
  uint32_t getNumImports() const;
106
352
  uint32_t getNumImportedGlobals() const {
107
352
    assert(isSealed);
108
352
    return numImportedGlobals;
109
352
  }
110
858
  uint32_t getNumImportedFunctions() const {
111
858
    assert(isSealed);
112
858
    return numImportedFunctions;
113
858
  }
114
1
  uint32_t getNumImportedEvents() const {
115
1
    assert(isSealed);
116
1
    return numImportedEvents;
117
1
  }
118
119
  std::vector<const Symbol *> importedSymbols;
120
121
protected:
122
  bool isSealed = false;
123
  unsigned numImportedGlobals = 0;
124
  unsigned numImportedFunctions = 0;
125
  unsigned numImportedEvents = 0;
126
  std::vector<const Symbol *> gotSymbols;
127
};
128
129
class FunctionSection : public SyntheticSection {
130
public:
131
193
  FunctionSection() : SyntheticSection(llvm::wasm::WASM_SEC_FUNCTION) {}
132
133
172
  bool isNeeded() const override { return inputFunctions.size() > 0; };
134
  void writeBody() override;
135
  void addFunction(InputFunction *func);
136
137
  std::vector<InputFunction *> inputFunctions;
138
139
protected:
140
};
141
142
class MemorySection : public SyntheticSection {
143
public:
144
193
  MemorySection() : SyntheticSection(llvm::wasm::WASM_SEC_MEMORY) {}
145
146
172
  bool isNeeded() const override { return !config->importMemory; }
147
  void writeBody() override;
148
149
  uint32_t numMemoryPages = 0;
150
  uint32_t maxMemoryPages = 0;
151
};
152
153
class TableSection : public SyntheticSection {
154
public:
155
193
  TableSection() : SyntheticSection(llvm::wasm::WASM_SEC_TABLE) {}
156
157
172
  bool isNeeded() const override {
158
172
    // Always output a table section (or table import), even if there are no
159
172
    // indirect calls.  There are two reasons for this:
160
172
    //  1. For executables it is useful to have an empty table slot at 0
161
172
    //     which can be filled with a null function call handler.
162
172
    //  2. If we don't do this, any program that contains a call_indirect but
163
172
    //     no address-taken function will fail at validation time since it is
164
172
    //     a validation error to include a call_indirect instruction if there
165
172
    //     is not table.
166
172
    return !config->importTable;
167
172
  }
168
169
  void writeBody() override;
170
};
171
172
class GlobalSection : public SyntheticSection {
173
public:
174
193
  GlobalSection() : SyntheticSection(llvm::wasm::WASM_SEC_GLOBAL) {}
175
323
  uint32_t numGlobals() const {
176
323
    return inputGlobals.size() + definedFakeGlobals.size();
177
323
  }
178
172
  bool isNeeded() const override { return numGlobals() > 0; }
179
  void writeBody() override;
180
  void addGlobal(InputGlobal *global);
181
182
  std::vector<const DefinedData *> definedFakeGlobals;
183
  std::vector<InputGlobal *> inputGlobals;
184
};
185
186
// The event section contains a list of declared wasm events associated with the
187
// module. Currently the only supported event kind is exceptions. A single event
188
// entry represents a single event with an event tag. All C++ exceptions are
189
// represented by a single event. An event entry in this section contains
190
// information on what kind of event it is (e.g. exception) and the type of
191
// values contained in a single event object. (In wasm, an event can contain
192
// multiple values of primitive types. But for C++ exceptions, we just throw a
193
// pointer which is an i32 value (for wasm32 architecture), so the signature of
194
// C++ exception is (i32)->(void), because all event types are assumed to have
195
// void return type to share WasmSignature with functions.)
196
class EventSection : public SyntheticSection {
197
public:
198
193
  EventSection() : SyntheticSection(llvm::wasm::WASM_SEC_EVENT) {}
199
  void writeBody() override;
200
172
  bool isNeeded() const override { return inputEvents.size() > 0; }
201
  void addEvent(InputEvent *event);
202
203
  std::vector<InputEvent *> inputEvents;
204
};
205
206
class ExportSection : public SyntheticSection {
207
public:
208
193
  ExportSection() : SyntheticSection(llvm::wasm::WASM_SEC_EXPORT) {}
209
172
  bool isNeeded() const override { return exports.size() > 0; }
210
  void writeBody() override;
211
212
  std::vector<llvm::wasm::WasmExport> exports;
213
};
214
215
class ElemSection : public SyntheticSection {
216
public:
217
  ElemSection(uint32_t offset)
218
193
      : SyntheticSection(llvm::wasm::WASM_SEC_ELEM), elemOffset(offset) {}
219
172
  bool isNeeded() const override { return indirectFunctions.size() > 0; };
220
  void writeBody() override;
221
  void addEntry(FunctionSymbol *sym);
222
177
  uint32_t numEntries() const { return indirectFunctions.size(); }
223
  uint32_t elemOffset;
224
225
protected:
226
  std::vector<const FunctionSymbol *> indirectFunctions;
227
};
228
229
class DataCountSection : public SyntheticSection {
230
public:
231
  DataCountSection(uint32_t numSegments)
232
      : SyntheticSection(llvm::wasm::WASM_SEC_DATACOUNT),
233
193
        numSegments(numSegments) {}
234
  bool isNeeded() const override;
235
  void writeBody() override;
236
237
protected:
238
  uint32_t numSegments;
239
};
240
241
// Create the custom "linking" section containing linker metadata.
242
// This is only created when relocatable output is requested.
243
class LinkingSection : public SyntheticSection {
244
public:
245
  LinkingSection(const std::vector<WasmInitEntry> &initFunctions,
246
                 const std::vector<OutputSegment *> &dataSegments)
247
      : SyntheticSection(llvm::wasm::WASM_SEC_CUSTOM, "linking"),
248
193
        initFunctions(initFunctions), dataSegments(dataSegments) {}
249
172
  bool isNeeded() const override {
250
172
    return config->relocatable || 
config->emitRelocs152
;
251
172
  }
252
  void writeBody() override;
253
  void addToSymtab(Symbol *sym);
254
255
protected:
256
  std::vector<const Symbol *> symtabEntries;
257
  llvm::StringMap<uint32_t> sectionSymbolIndices;
258
  const std::vector<WasmInitEntry> &initFunctions;
259
  const std::vector<OutputSegment *> &dataSegments;
260
};
261
262
// Create the custom "name" section containing debug symbol names.
263
class NameSection : public SyntheticSection {
264
public:
265
193
  NameSection() : SyntheticSection(llvm::wasm::WASM_SEC_CUSTOM, "name") {}
266
172
  bool isNeeded() const override {
267
172
    return !config->stripDebug && 
!config->stripAll168
&&
numNames() > 0166
;
268
172
  }
269
  void writeBody() override;
270
  unsigned numNames() const;
271
};
272
273
class ProducersSection : public SyntheticSection {
274
public:
275
  ProducersSection()
276
193
      : SyntheticSection(llvm::wasm::WASM_SEC_CUSTOM, "producers") {}
277
172
  bool isNeeded() const override {
278
172
    return !config->stripAll && 
fieldCount() > 0170
;
279
172
  }
280
  void writeBody() override;
281
  void addInfo(const llvm::wasm::WasmProducerInfo &info);
282
283
protected:
284
172
  int fieldCount() const {
285
172
    return int(!languages.empty()) + int(!tools.empty()) + int(!sDKs.empty());
286
172
  }
287
  SmallVector<std::pair<std::string, std::string>, 8> languages;
288
  SmallVector<std::pair<std::string, std::string>, 8> tools;
289
  SmallVector<std::pair<std::string, std::string>, 8> sDKs;
290
};
291
292
class TargetFeaturesSection : public SyntheticSection {
293
public:
294
  TargetFeaturesSection()
295
193
      : SyntheticSection(llvm::wasm::WASM_SEC_CUSTOM, "target_features") {}
296
172
  bool isNeeded() const override {
297
172
    return !config->stripAll && 
features.size() > 0170
;
298
172
  }
299
  void writeBody() override;
300
301
  llvm::SmallSet<std::string, 8> features;
302
};
303
304
class RelocSection : public SyntheticSection {
305
public:
306
  RelocSection(StringRef name, OutputSection *sec)
307
17
      : SyntheticSection(llvm::wasm::WASM_SEC_CUSTOM, name), sec(sec) {}
308
  void writeBody() override;
309
17
  bool isNeeded() const override { return sec->getNumRelocations() > 0; };
310
311
protected:
312
  OutputSection *sec;
313
};
314
315
// Linker generated output sections
316
struct OutStruct {
317
  DylinkSection *dylinkSec;
318
  TypeSection *typeSec;
319
  FunctionSection *functionSec;
320
  ImportSection *importSec;
321
  TableSection *tableSec;
322
  MemorySection *memorySec;
323
  GlobalSection *globalSec;
324
  EventSection *eventSec;
325
  ExportSection *exportSec;
326
  ElemSection *elemSec;
327
  DataCountSection *dataCountSec;
328
  LinkingSection *linkingSec;
329
  NameSection *nameSec;
330
  ProducersSection *producersSec;
331
  TargetFeaturesSection *targetFeaturesSec;
332
};
333
334
extern OutStruct out;
335
336
} // namespace wasm
337
} // namespace lld
338
339
#endif