1 //===- Wasm.h - Wasm object file implementation -----------------*- 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 // This file declares the WasmObjectFile class, which implements the ObjectFile
10 // interface for Wasm files.
11 //
12 // See: https://github.com/WebAssembly/design/blob/master/BinaryEncoding.md
13 //
14 //===----------------------------------------------------------------------===//
15 
16 #ifndef LLVM_OBJECT_WASM_H
17 #define LLVM_OBJECT_WASM_H
18 
19 #include "llvm/ADT/ArrayRef.h"
20 #include "llvm/ADT/StringRef.h"
21 #include "llvm/BinaryFormat/Wasm.h"
22 #include "llvm/Config/llvm-config.h"
23 #include "llvm/MC/MCSymbolWasm.h"
24 #include "llvm/Object/Binary.h"
25 #include "llvm/Object/ObjectFile.h"
26 #include "llvm/Support/Error.h"
27 #include "llvm/Support/MemoryBuffer.h"
28 #include <cstddef>
29 #include <cstdint>
30 #include <vector>
31 
32 namespace llvm {
33 namespace object {
34 
35 class WasmSymbol {
36 public:
37   WasmSymbol(const wasm::WasmSymbolInfo &Info,
38              const wasm::WasmGlobalType *GlobalType,
39              const wasm::WasmEventType *EventType,
40              const wasm::WasmSignature *Signature)
41       : Info(Info), GlobalType(GlobalType), EventType(EventType),
42         Signature(Signature) {}
43 
44   const wasm::WasmSymbolInfo &Info;
45   const wasm::WasmGlobalType *GlobalType;
46   const wasm::WasmEventType *EventType;
47   const wasm::WasmSignature *Signature;
48 
49   bool isTypeFunction() const {
50     return Info.Kind == wasm::WASM_SYMBOL_TYPE_FUNCTION;
51   }
52 
53   bool isTypeData() const { return Info.Kind == wasm::WASM_SYMBOL_TYPE_DATA; }
54 
55   bool isTypeGlobal() const {
56     return Info.Kind == wasm::WASM_SYMBOL_TYPE_GLOBAL;
57   }
58 
59   bool isTypeSection() const {
60     return Info.Kind == wasm::WASM_SYMBOL_TYPE_SECTION;
61   }
62 
63   bool isTypeEvent() const { return Info.Kind == wasm::WASM_SYMBOL_TYPE_EVENT; }
64 
65   bool isDefined() const { return !isUndefined(); }
66 
67   bool isUndefined() const {
68     return (Info.Flags & wasm::WASM_SYMBOL_UNDEFINED) != 0;
69   }
70 
71   bool isBindingWeak() const {
72     return getBinding() == wasm::WASM_SYMBOL_BINDING_WEAK;
73   }
74 
75   bool isBindingGlobal() const {
76     return getBinding() == wasm::WASM_SYMBOL_BINDING_GLOBAL;
77   }
78 
79   bool isBindingLocal() const {
80     return getBinding() == wasm::WASM_SYMBOL_BINDING_LOCAL;
81   }
82 
83   unsigned getBinding() const {
84     return Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK;
85   }
86 
87   bool isHidden() const {
88     return getVisibility() == wasm::WASM_SYMBOL_VISIBILITY_HIDDEN;
89   }
90 
91   unsigned getVisibility() const {
92     return Info.Flags & wasm::WASM_SYMBOL_VISIBILITY_MASK;
93   }
94 
95   void print(raw_ostream &Out) const;
96 
97 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
98   LLVM_DUMP_METHOD void dump() const;
99 #endif
100 };
101 
102 struct WasmSection {
103   WasmSection() = default;
104 
105   uint32_t Type = 0;         // Section type (See below)
106   uint32_t Offset = 0;       // Offset with in the file
107   StringRef Name;            // Section name (User-defined sections only)
108   ArrayRef<uint8_t> Content; // Section content
109   std::vector<wasm::WasmRelocation> Relocations; // Relocations for this section
110 };
111 
112 struct WasmSegment {
113   uint32_t SectionOffset;
114   wasm::WasmDataSegment Data;
115 };
116 
117 class WasmObjectFile : public ObjectFile {
118 
119 public:
120   WasmObjectFile(MemoryBufferRef Object, Error &Err);
121 
122   const wasm::WasmObjectHeader &getHeader() const;
123   const WasmSymbol &getWasmSymbol(const DataRefImpl &Symb) const;
124   const WasmSymbol &getWasmSymbol(const SymbolRef &Symbol) const;
125   const WasmSection &getWasmSection(const SectionRef &Section) const;
126   const wasm::WasmRelocation &getWasmRelocation(const RelocationRef &Ref) const;
127 
128   static bool classof(const Binary *v) { return v->isWasm(); }
129 
130   const wasm::WasmDylinkInfo &dylinkInfo() const { return DylinkInfo; }
131   const wasm::WasmProducerInfo &getProducerInfo() const { return ProducerInfo; }
132   ArrayRef<wasm::WasmFeatureEntry> getTargetFeatures() const {
133     return TargetFeatures;
134   }
135   ArrayRef<wasm::WasmSignature> types() const { return Signatures; }
136   ArrayRef<uint32_t> functionTypes() const { return FunctionTypes; }
137   ArrayRef<wasm::WasmImport> imports() const { return Imports; }
138   ArrayRef<wasm::WasmTable> tables() const { return Tables; }
139   ArrayRef<wasm::WasmLimits> memories() const { return Memories; }
140   ArrayRef<wasm::WasmGlobal> globals() const { return Globals; }
141   ArrayRef<wasm::WasmEvent> events() const { return Events; }
142   ArrayRef<wasm::WasmExport> exports() const { return Exports; }
143   ArrayRef<WasmSymbol> syms() const { return Symbols; }
144   const wasm::WasmLinkingData &linkingData() const { return LinkingData; }
145   uint32_t getNumberOfSymbols() const { return Symbols.size(); }
146   ArrayRef<wasm::WasmElemSegment> elements() const { return ElemSegments; }
147   ArrayRef<WasmSegment> dataSegments() const { return DataSegments; }
148   ArrayRef<wasm::WasmFunction> functions() const { return Functions; }
149   ArrayRef<wasm::WasmFunctionName> debugNames() const { return DebugNames; }
150   uint32_t startFunction() const { return StartFunction; }
151   uint32_t getNumImportedGlobals() const { return NumImportedGlobals; }
152   uint32_t getNumImportedFunctions() const { return NumImportedFunctions; }
153   uint32_t getNumImportedEvents() const { return NumImportedEvents; }
154   uint32_t getNumSections() const { return Sections.size(); }
155   void moveSymbolNext(DataRefImpl &Symb) const override;
156 
157   Expected<uint32_t> getSymbolFlags(DataRefImpl Symb) const override;
158 
159   basic_symbol_iterator symbol_begin() const override;
160 
161   basic_symbol_iterator symbol_end() const override;
162   Expected<StringRef> getSymbolName(DataRefImpl Symb) const override;
163 
164   Expected<uint64_t> getSymbolAddress(DataRefImpl Symb) const override;
165   uint64_t getWasmSymbolValue(const WasmSymbol &Sym) const;
166   uint64_t getSymbolValueImpl(DataRefImpl Symb) const override;
167   uint32_t getSymbolAlignment(DataRefImpl Symb) const override;
168   uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb) const override;
169   Expected<SymbolRef::Type> getSymbolType(DataRefImpl Symb) const override;
170   Expected<section_iterator> getSymbolSection(DataRefImpl Symb) const override;
171   uint32_t getSymbolSectionId(SymbolRef Sym) const;
172 
173   // Overrides from SectionRef.
174   void moveSectionNext(DataRefImpl &Sec) const override;
175   Expected<StringRef> getSectionName(DataRefImpl Sec) const override;
176   uint64_t getSectionAddress(DataRefImpl Sec) const override;
177   uint64_t getSectionIndex(DataRefImpl Sec) const override;
178   uint64_t getSectionSize(DataRefImpl Sec) const override;
179   Expected<ArrayRef<uint8_t>>
180   getSectionContents(DataRefImpl Sec) const override;
181   uint64_t getSectionAlignment(DataRefImpl Sec) const override;
182   bool isSectionCompressed(DataRefImpl Sec) const override;
183   bool isSectionText(DataRefImpl Sec) const override;
184   bool isSectionData(DataRefImpl Sec) const override;
185   bool isSectionBSS(DataRefImpl Sec) const override;
186   bool isSectionVirtual(DataRefImpl Sec) const override;
187   relocation_iterator section_rel_begin(DataRefImpl Sec) const override;
188   relocation_iterator section_rel_end(DataRefImpl Sec) const override;
189 
190   // Overrides from RelocationRef.
191   void moveRelocationNext(DataRefImpl &Rel) const override;
192   uint64_t getRelocationOffset(DataRefImpl Rel) const override;
193   symbol_iterator getRelocationSymbol(DataRefImpl Rel) const override;
194   uint64_t getRelocationType(DataRefImpl Rel) const override;
195   void getRelocationTypeName(DataRefImpl Rel,
196                              SmallVectorImpl<char> &Result) const override;
197 
198   section_iterator section_begin() const override;
199   section_iterator section_end() const override;
200   uint8_t getBytesInAddress() const override;
201   StringRef getFileFormatName() const override;
202   Triple::ArchType getArch() const override;
203   SubtargetFeatures getFeatures() const override;
204   bool isRelocatableObject() const override;
205   bool isSharedObject() const;
206 
207   struct ReadContext {
208     const uint8_t *Start;
209     const uint8_t *Ptr;
210     const uint8_t *End;
211   };
212 
213 private:
214   bool isValidFunctionIndex(uint32_t Index) const;
215   bool isDefinedFunctionIndex(uint32_t Index) const;
216   bool isValidGlobalIndex(uint32_t Index) const;
217   bool isDefinedGlobalIndex(uint32_t Index) const;
218   bool isValidEventIndex(uint32_t Index) const;
219   bool isDefinedEventIndex(uint32_t Index) const;
220   bool isValidFunctionSymbol(uint32_t Index) const;
221   bool isValidGlobalSymbol(uint32_t Index) const;
222   bool isValidEventSymbol(uint32_t Index) const;
223   bool isValidDataSymbol(uint32_t Index) const;
224   bool isValidSectionSymbol(uint32_t Index) const;
225   wasm::WasmFunction &getDefinedFunction(uint32_t Index);
226   const wasm::WasmFunction &getDefinedFunction(uint32_t Index) const;
227   wasm::WasmGlobal &getDefinedGlobal(uint32_t Index);
228   wasm::WasmEvent &getDefinedEvent(uint32_t Index);
229 
230   const WasmSection &getWasmSection(DataRefImpl Ref) const;
231   const wasm::WasmRelocation &getWasmRelocation(DataRefImpl Ref) const;
232   uint32_t getSymbolSectionIdImpl(const WasmSymbol &Symb) const;
233 
234   Error parseSection(WasmSection &Sec);
235   Error parseCustomSection(WasmSection &Sec, ReadContext &Ctx);
236 
237   // Standard section types
238   Error parseTypeSection(ReadContext &Ctx);
239   Error parseImportSection(ReadContext &Ctx);
240   Error parseFunctionSection(ReadContext &Ctx);
241   Error parseTableSection(ReadContext &Ctx);
242   Error parseMemorySection(ReadContext &Ctx);
243   Error parseEventSection(ReadContext &Ctx);
244   Error parseGlobalSection(ReadContext &Ctx);
245   Error parseExportSection(ReadContext &Ctx);
246   Error parseStartSection(ReadContext &Ctx);
247   Error parseElemSection(ReadContext &Ctx);
248   Error parseCodeSection(ReadContext &Ctx);
249   Error parseDataSection(ReadContext &Ctx);
250   Error parseDataCountSection(ReadContext &Ctx);
251 
252   // Custom section types
253   Error parseDylinkSection(ReadContext &Ctx);
254   Error parseNameSection(ReadContext &Ctx);
255   Error parseLinkingSection(ReadContext &Ctx);
256   Error parseLinkingSectionSymtab(ReadContext &Ctx);
257   Error parseLinkingSectionComdat(ReadContext &Ctx);
258   Error parseProducersSection(ReadContext &Ctx);
259   Error parseTargetFeaturesSection(ReadContext &Ctx);
260   Error parseRelocSection(StringRef Name, ReadContext &Ctx);
261 
262   wasm::WasmObjectHeader Header;
263   std::vector<WasmSection> Sections;
264   wasm::WasmDylinkInfo DylinkInfo;
265   wasm::WasmProducerInfo ProducerInfo;
266   std::vector<wasm::WasmFeatureEntry> TargetFeatures;
267   std::vector<wasm::WasmSignature> Signatures;
268   std::vector<uint32_t> FunctionTypes;
269   std::vector<wasm::WasmTable> Tables;
270   std::vector<wasm::WasmLimits> Memories;
271   std::vector<wasm::WasmGlobal> Globals;
272   std::vector<wasm::WasmEvent> Events;
273   std::vector<wasm::WasmImport> Imports;
274   std::vector<wasm::WasmExport> Exports;
275   std::vector<wasm::WasmElemSegment> ElemSegments;
276   std::vector<WasmSegment> DataSegments;
277   llvm::Optional<size_t> DataCount;
278   std::vector<wasm::WasmFunction> Functions;
279   std::vector<WasmSymbol> Symbols;
280   std::vector<wasm::WasmFunctionName> DebugNames;
281   uint32_t StartFunction = -1;
282   bool HasLinkingSection = false;
283   bool HasDylinkSection = false;
284   bool SeenCodeSection = false;
285   wasm::WasmLinkingData LinkingData;
286   uint32_t NumImportedGlobals = 0;
287   uint32_t NumImportedFunctions = 0;
288   uint32_t NumImportedEvents = 0;
289   uint32_t CodeSection = 0;
290   uint32_t DataSection = 0;
291   uint32_t EventSection = 0;
292   uint32_t GlobalSection = 0;
293 };
294 
295 class WasmSectionOrderChecker {
296 public:
297   // We define orders for all core wasm sections and known custom sections.
298   enum : int {
299     // Sentinel, must be zero
300     WASM_SEC_ORDER_NONE = 0,
301 
302     // Core sections
303     WASM_SEC_ORDER_TYPE,
304     WASM_SEC_ORDER_IMPORT,
305     WASM_SEC_ORDER_FUNCTION,
306     WASM_SEC_ORDER_TABLE,
307     WASM_SEC_ORDER_MEMORY,
308     WASM_SEC_ORDER_EVENT,
309     WASM_SEC_ORDER_GLOBAL,
310     WASM_SEC_ORDER_EXPORT,
311     WASM_SEC_ORDER_START,
312     WASM_SEC_ORDER_ELEM,
313     WASM_SEC_ORDER_DATACOUNT,
314     WASM_SEC_ORDER_CODE,
315     WASM_SEC_ORDER_DATA,
316 
317     // Custom sections
318     // "dylink" should be the very first section in the module
319     WASM_SEC_ORDER_DYLINK,
320     // "linking" section requires DATA section in order to validate data symbols
321     WASM_SEC_ORDER_LINKING,
322     // Must come after "linking" section in order to validate reloc indexes.
323     WASM_SEC_ORDER_RELOC,
324     // "name" section must appear after DATA. Comes after "linking" to allow
325     // symbol table to set default function name.
326     WASM_SEC_ORDER_NAME,
327     // "producers" section must appear after "name" section.
328     WASM_SEC_ORDER_PRODUCERS,
329     // "target_features" section must appear after producers section
330     WASM_SEC_ORDER_TARGET_FEATURES,
331 
332     // Must be last
333     WASM_NUM_SEC_ORDERS
334 
335   };
336 
337   // Sections that may or may not be present, but cannot be predecessors
338   static int DisallowedPredecessors[WASM_NUM_SEC_ORDERS][WASM_NUM_SEC_ORDERS];
339 
340   bool isValidSectionOrder(unsigned ID, StringRef CustomSectionName = "");
341 
342 private:
343   bool Seen[WASM_NUM_SEC_ORDERS] = {}; // Sections that have been seen already
344 
345   // Returns -1 for unknown sections.
346   int getSectionOrder(unsigned ID, StringRef CustomSectionName = "");
347 };
348 
349 } // end namespace object
350 
351 inline raw_ostream &operator<<(raw_ostream &OS, const object::WasmSymbol &Sym) {
352   Sym.print(OS);
353   return OS;
354 }
355 
356 } // end namespace llvm
357 
358 #endif // LLVM_OBJECT_WASM_H
359