/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 |