xref: /openbsd-src/gnu/llvm/lld/wasm/SyntheticSections.h (revision 1a8dbaac879b9f3335ad7fb25429ce63ac1d6bac)
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 MemorySection : public SyntheticSection {
145 public:
146   MemorySection() : SyntheticSection(llvm::wasm::WASM_SEC_MEMORY) {}
147 
148   bool isNeeded() const override { return !config->importMemory; }
149   void writeBody() override;
150 
151   uint32_t numMemoryPages = 0;
152   uint32_t maxMemoryPages = 0;
153 };
154 
155 class TableSection : public SyntheticSection {
156 public:
157   TableSection() : SyntheticSection(llvm::wasm::WASM_SEC_TABLE) {}
158 
159   bool isNeeded() const override {
160     // Always output a table section (or table import), even if there are no
161     // indirect calls.  There are two reasons for this:
162     //  1. For executables it is useful to have an empty table slot at 0
163     //     which can be filled with a null function call handler.
164     //  2. If we don't do this, any program that contains a call_indirect but
165     //     no address-taken function will fail at validation time since it is
166     //     a validation error to include a call_indirect instruction if there
167     //     is not table.
168     return !config->importTable;
169   }
170 
171   void writeBody() override;
172 };
173 
174 class GlobalSection : public SyntheticSection {
175 public:
176   GlobalSection() : SyntheticSection(llvm::wasm::WASM_SEC_GLOBAL) {}
177   uint32_t numGlobals() const {
178     assert(isSealed);
179     return inputGlobals.size() + dataAddressGlobals.size() +
180            staticGotSymbols.size();
181   }
182   bool isNeeded() const override { return numGlobals() > 0; }
183   void assignIndexes() override;
184   void writeBody() override;
185   void addGlobal(InputGlobal *global);
186   void addDataAddressGlobal(DefinedData *global);
187   void addStaticGOTEntry(Symbol *sym);
188 
189   std::vector<const DefinedData *> dataAddressGlobals;
190 
191 protected:
192   bool isSealed = false;
193   std::vector<InputGlobal *> inputGlobals;
194   std::vector<Symbol *> staticGotSymbols;
195 };
196 
197 // The event section contains a list of declared wasm events associated with the
198 // module. Currently the only supported event kind is exceptions. A single event
199 // entry represents a single event with an event tag. All C++ exceptions are
200 // represented by a single event. An event entry in this section contains
201 // information on what kind of event it is (e.g. exception) and the type of
202 // values contained in a single event object. (In wasm, an event can contain
203 // multiple values of primitive types. But for C++ exceptions, we just throw a
204 // pointer which is an i32 value (for wasm32 architecture), so the signature of
205 // C++ exception is (i32)->(void), because all event types are assumed to have
206 // void return type to share WasmSignature with functions.)
207 class EventSection : public SyntheticSection {
208 public:
209   EventSection() : SyntheticSection(llvm::wasm::WASM_SEC_EVENT) {}
210   void writeBody() override;
211   bool isNeeded() const override { return inputEvents.size() > 0; }
212   void addEvent(InputEvent *event);
213 
214   std::vector<InputEvent *> inputEvents;
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(uint32_t numSegments)
229       : SyntheticSection(llvm::wasm::WASM_SEC_START), numSegments(numSegments) {
230   }
231   bool isNeeded() const override;
232   void writeBody() override;
233 
234 protected:
235   uint32_t numSegments;
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, name), sec(sec) {}
328   void writeBody() override;
329   bool isNeeded() const override { return sec->getNumRelocations() > 0; };
330 
331 protected:
332   OutputSection *sec;
333 };
334 
335 // Linker generated output sections
336 struct OutStruct {
337   DylinkSection *dylinkSec;
338   TypeSection *typeSec;
339   FunctionSection *functionSec;
340   ImportSection *importSec;
341   TableSection *tableSec;
342   MemorySection *memorySec;
343   GlobalSection *globalSec;
344   EventSection *eventSec;
345   ExportSection *exportSec;
346   StartSection *startSec;
347   ElemSection *elemSec;
348   DataCountSection *dataCountSec;
349   LinkingSection *linkingSec;
350   NameSection *nameSec;
351   ProducersSection *producersSec;
352   TargetFeaturesSection *targetFeaturesSec;
353 };
354 
355 extern OutStruct out;
356 
357 } // namespace wasm
358 } // namespace lld
359 
360 #endif
361