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