• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/BinaryFormat/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 = "")
OutputSection(type,name)39       : OutputSection(type, name), bodyOutputStream(body) {
40     if (!name.empty())
41       writeStr(bodyOutputStream, name, "section name");
42   }
43 
writeTo(uint8_t * buf)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 
getSize()51   size_t getSize() const override { return header.size() + body.size(); }
52 
writeBody()53   virtual void writeBody() {}
54 
assignIndexes()55   virtual void assignIndexes() {}
56 
finalizeContents()57   void finalizeContents() override {
58     writeBody();
59     bodyOutputStream.flush();
60     createHeader(body.size());
61   }
62 
getStream()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:
DylinkSection()77   DylinkSection() : SyntheticSection(llvm::wasm::WASM_SEC_CUSTOM, "dylink") {}
isNeeded()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:
TypeSection()87   TypeSection() : SyntheticSection(llvm::wasm::WASM_SEC_TYPE) {}
88 
isNeeded()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:
ImportSection()101   ImportSection() : SyntheticSection(llvm::wasm::WASM_SEC_IMPORT) {}
isNeeded()102   bool isNeeded() const override { return getNumImports() > 0; }
103   void writeBody() override;
104   void addImport(Symbol *sym);
105   void addGOTEntry(Symbol *sym);
seal()106   void seal() { isSealed = true; }
107   uint32_t getNumImports() const;
getNumImportedGlobals()108   uint32_t getNumImportedGlobals() const {
109     assert(isSealed);
110     return numImportedGlobals;
111   }
getNumImportedFunctions()112   uint32_t getNumImportedFunctions() const {
113     assert(isSealed);
114     return numImportedFunctions;
115   }
getNumImportedEvents()116   uint32_t getNumImportedEvents() const {
117     assert(isSealed);
118     return numImportedEvents;
119   }
120 
121   std::vector<const Symbol *> importedSymbols;
122   std::vector<const Symbol *> gotSymbols;
123 
124 protected:
125   bool isSealed = false;
126   unsigned numImportedGlobals = 0;
127   unsigned numImportedFunctions = 0;
128   unsigned numImportedEvents = 0;
129 };
130 
131 class FunctionSection : public SyntheticSection {
132 public:
FunctionSection()133   FunctionSection() : SyntheticSection(llvm::wasm::WASM_SEC_FUNCTION) {}
134 
isNeeded()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:
TableSection()146   TableSection() : SyntheticSection(llvm::wasm::WASM_SEC_TABLE) {}
147 
isNeeded()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:
MemorySection()165   MemorySection() : SyntheticSection(llvm::wasm::WASM_SEC_MEMORY) {}
166 
isNeeded()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:
EventSection()186   EventSection() : SyntheticSection(llvm::wasm::WASM_SEC_EVENT) {}
187   void writeBody() override;
isNeeded()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:
GlobalSection()196   GlobalSection() : SyntheticSection(llvm::wasm::WASM_SEC_GLOBAL) {}
numGlobals()197   uint32_t numGlobals() const {
198     assert(isSealed);
199     return inputGlobals.size() + dataAddressGlobals.size() +
200            internalGotSymbols.size();
201   }
isNeeded()202   bool isNeeded() const override { return numGlobals() > 0; }
203   void assignIndexes() override;
204   void writeBody() override;
205   void addGlobal(InputGlobal *global);
206 
207   // Add an internal GOT entry global that corresponds to the given symbol.
208   // Normally GOT entries are imported and assigned by the external dynamic
209   // linker.  However, when linking PIC code statically or when linking with
210   // -Bsymbolic we can internalize GOT entries by declaring globals the hold
211   // symbol addresses.
212   //
213   // For the static linking case these internal globals can be completely
214   // eliminated by a post-link optimizer such as wasm-opt.
215   //
216   // TODO(sbc): Another approach to optimizing these away could be to use
217   // specific relocation types combined with linker relaxation which could
218   // transform a `global.get` to an `i32.const`.
219   void addInternalGOTEntry(Symbol *sym);
220   void generateRelocationCode(raw_ostream &os) const;
221 
222   std::vector<const DefinedData *> dataAddressGlobals;
223   std::vector<InputGlobal *> inputGlobals;
224   std::vector<Symbol *> internalGotSymbols;
225 
226 protected:
227   bool isSealed = false;
228 };
229 
230 class ExportSection : public SyntheticSection {
231 public:
ExportSection()232   ExportSection() : SyntheticSection(llvm::wasm::WASM_SEC_EXPORT) {}
isNeeded()233   bool isNeeded() const override { return exports.size() > 0; }
234   void writeBody() override;
235 
236   std::vector<llvm::wasm::WasmExport> exports;
237   std::vector<const Symbol *> exportedSymbols;
238 };
239 
240 class StartSection : public SyntheticSection {
241 public:
StartSection(bool hasInitializedSegments)242   StartSection(bool hasInitializedSegments)
243       : SyntheticSection(llvm::wasm::WASM_SEC_START),
244         hasInitializedSegments(hasInitializedSegments) {}
245   bool isNeeded() const override;
246   void writeBody() override;
247 
248 protected:
249   bool hasInitializedSegments;
250 };
251 
252 class ElemSection : public SyntheticSection {
253 public:
ElemSection()254   ElemSection()
255       : SyntheticSection(llvm::wasm::WASM_SEC_ELEM) {}
isNeeded()256   bool isNeeded() const override { return indirectFunctions.size() > 0; };
257   void writeBody() override;
258   void addEntry(FunctionSymbol *sym);
numEntries()259   uint32_t numEntries() const { return indirectFunctions.size(); }
260 
261 protected:
262   std::vector<const FunctionSymbol *> indirectFunctions;
263 };
264 
265 class DataCountSection : public SyntheticSection {
266 public:
267   DataCountSection(ArrayRef<OutputSegment *> segments);
268   bool isNeeded() const override;
269   void writeBody() override;
270 
271 protected:
272   uint32_t numSegments;
273 };
274 
275 // Create the custom "linking" section containing linker metadata.
276 // This is only created when relocatable output is requested.
277 class LinkingSection : public SyntheticSection {
278 public:
LinkingSection(const std::vector<WasmInitEntry> & initFunctions,const std::vector<OutputSegment * > & dataSegments)279   LinkingSection(const std::vector<WasmInitEntry> &initFunctions,
280                  const std::vector<OutputSegment *> &dataSegments)
281       : SyntheticSection(llvm::wasm::WASM_SEC_CUSTOM, "linking"),
282         initFunctions(initFunctions), dataSegments(dataSegments) {}
isNeeded()283   bool isNeeded() const override {
284     return config->relocatable || config->emitRelocs;
285   }
286   void writeBody() override;
287   void addToSymtab(Symbol *sym);
288 
289 protected:
290   std::vector<const Symbol *> symtabEntries;
291   llvm::StringMap<uint32_t> sectionSymbolIndices;
292   const std::vector<WasmInitEntry> &initFunctions;
293   const std::vector<OutputSegment *> &dataSegments;
294 };
295 
296 // Create the custom "name" section containing debug symbol names.
297 class NameSection : public SyntheticSection {
298 public:
NameSection()299   NameSection() : SyntheticSection(llvm::wasm::WASM_SEC_CUSTOM, "name") {}
isNeeded()300   bool isNeeded() const override {
301     return !config->stripDebug && !config->stripAll && numNames() > 0;
302   }
303   void writeBody() override;
numNames()304   unsigned numNames() const { return numNamedGlobals() + numNamedFunctions(); }
305   unsigned numNamedGlobals() const;
306   unsigned numNamedFunctions() const;
307 };
308 
309 class ProducersSection : public SyntheticSection {
310 public:
ProducersSection()311   ProducersSection()
312       : SyntheticSection(llvm::wasm::WASM_SEC_CUSTOM, "producers") {}
isNeeded()313   bool isNeeded() const override {
314     return !config->stripAll && fieldCount() > 0;
315   }
316   void writeBody() override;
317   void addInfo(const llvm::wasm::WasmProducerInfo &info);
318 
319 protected:
fieldCount()320   int fieldCount() const {
321     return int(!languages.empty()) + int(!tools.empty()) + int(!sDKs.empty());
322   }
323   SmallVector<std::pair<std::string, std::string>, 8> languages;
324   SmallVector<std::pair<std::string, std::string>, 8> tools;
325   SmallVector<std::pair<std::string, std::string>, 8> sDKs;
326 };
327 
328 class TargetFeaturesSection : public SyntheticSection {
329 public:
TargetFeaturesSection()330   TargetFeaturesSection()
331       : SyntheticSection(llvm::wasm::WASM_SEC_CUSTOM, "target_features") {}
isNeeded()332   bool isNeeded() const override {
333     return !config->stripAll && features.size() > 0;
334   }
335   void writeBody() override;
336 
337   llvm::SmallSet<std::string, 8> features;
338 };
339 
340 class RelocSection : public SyntheticSection {
341 public:
RelocSection(StringRef name,OutputSection * sec)342   RelocSection(StringRef name, OutputSection *sec)
343       : SyntheticSection(llvm::wasm::WASM_SEC_CUSTOM, std::string(name)),
344         sec(sec) {}
345   void writeBody() override;
isNeeded()346   bool isNeeded() const override { return sec->getNumRelocations() > 0; };
347 
348 protected:
349   OutputSection *sec;
350 };
351 
352 // Linker generated output sections
353 struct OutStruct {
354   DylinkSection *dylinkSec;
355   TypeSection *typeSec;
356   FunctionSection *functionSec;
357   ImportSection *importSec;
358   TableSection *tableSec;
359   MemorySection *memorySec;
360   GlobalSection *globalSec;
361   EventSection *eventSec;
362   ExportSection *exportSec;
363   StartSection *startSec;
364   ElemSection *elemSec;
365   DataCountSection *dataCountSec;
366   LinkingSection *linkingSec;
367   NameSection *nameSec;
368   ProducersSection *producersSec;
369   TargetFeaturesSection *targetFeaturesSec;
370 };
371 
372 extern OutStruct out;
373 
374 } // namespace wasm
375 } // namespace lld
376 
377 #endif
378