• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===- WasmObjectFile.h - Wasm object file implementation -------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file declares the WasmObjectFile class, which implements the ObjectFile
11 // interface for Wasm files.
12 //
13 // See: https://github.com/WebAssembly/design/blob/master/BinaryEncoding.md
14 //
15 //===----------------------------------------------------------------------===//
16 
17 #ifndef LLVM_OBJECT_WASM_H
18 #define LLVM_OBJECT_WASM_H
19 
20 #include "llvm/ADT/ArrayRef.h"
21 #include "llvm/ADT/StringRef.h"
22 #include "llvm/ADT/StringMap.h"
23 #include "llvm/BinaryFormat/Wasm.h"
24 #include "llvm/Config/llvm-config.h"
25 #include "llvm/Object/Binary.h"
26 #include "llvm/Object/ObjectFile.h"
27 #include "llvm/Support/Error.h"
28 #include "llvm/Support/MemoryBuffer.h"
29 #include <cstddef>
30 #include <cstdint>
31 #include <vector>
32 
33 namespace llvm {
34 namespace object {
35 
36 class WasmSymbol {
37 public:
WasmSymbol(const wasm::WasmSymbolInfo & Info,const wasm::WasmSignature * FunctionType,const wasm::WasmGlobalType * GlobalType)38   WasmSymbol(const wasm::WasmSymbolInfo &Info,
39              const wasm::WasmSignature *FunctionType,
40              const wasm::WasmGlobalType *GlobalType)
41       : Info(Info), FunctionType(FunctionType), GlobalType(GlobalType) {}
42 
43   const wasm::WasmSymbolInfo &Info;
44   const wasm::WasmSignature *FunctionType;
45   const wasm::WasmGlobalType *GlobalType;
46 
isTypeFunction()47   bool isTypeFunction() const {
48     return Info.Kind == wasm::WASM_SYMBOL_TYPE_FUNCTION;
49   }
50 
isTypeData()51   bool isTypeData() const { return Info.Kind == wasm::WASM_SYMBOL_TYPE_DATA; }
52 
isTypeGlobal()53   bool isTypeGlobal() const {
54     return Info.Kind == wasm::WASM_SYMBOL_TYPE_GLOBAL;
55   }
56 
isTypeSection()57   bool isTypeSection() const {
58     return Info.Kind == wasm::WASM_SYMBOL_TYPE_SECTION;
59   }
60 
isDefined()61   bool isDefined() const { return !isUndefined(); }
62 
isUndefined()63   bool isUndefined() const {
64     return (Info.Flags & wasm::WASM_SYMBOL_UNDEFINED) != 0;
65   }
66 
isBindingWeak()67   bool isBindingWeak() const {
68     return getBinding() == wasm::WASM_SYMBOL_BINDING_WEAK;
69   }
70 
isBindingGlobal()71   bool isBindingGlobal() const {
72     return getBinding() == wasm::WASM_SYMBOL_BINDING_GLOBAL;
73   }
74 
isBindingLocal()75   bool isBindingLocal() const {
76     return getBinding() == wasm::WASM_SYMBOL_BINDING_LOCAL;
77   }
78 
getBinding()79   unsigned getBinding() const {
80     return Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK;
81   }
82 
isHidden()83   bool isHidden() const {
84     return getVisibility() == wasm::WASM_SYMBOL_VISIBILITY_HIDDEN;
85   }
86 
getVisibility()87   unsigned getVisibility() const {
88     return Info.Flags & wasm::WASM_SYMBOL_VISIBILITY_MASK;
89   }
90 
91   void print(raw_ostream &Out) const;
92 
93 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
94   LLVM_DUMP_METHOD void dump() const;
95 #endif
96 };
97 
98 struct WasmSection {
99   WasmSection() = default;
100 
101   uint32_t Type = 0; // Section type (See below)
102   uint32_t Offset = 0; // Offset with in the file
103   StringRef Name; // Section name (User-defined sections only)
104   ArrayRef<uint8_t> Content; // Section content
105   std::vector<wasm::WasmRelocation> Relocations; // Relocations for this section
106 };
107 
108 struct WasmSegment {
109   uint32_t SectionOffset;
110   wasm::WasmDataSegment Data;
111 };
112 
113 class WasmObjectFile : public ObjectFile {
114 
115 public:
116   WasmObjectFile(MemoryBufferRef Object, Error &Err);
117 
118   const wasm::WasmObjectHeader &getHeader() const;
119   const WasmSymbol &getWasmSymbol(const DataRefImpl &Symb) const;
120   const WasmSymbol &getWasmSymbol(const SymbolRef &Symbol) const;
121   const WasmSection &getWasmSection(const SectionRef &Section) const;
122   const wasm::WasmRelocation &getWasmRelocation(const RelocationRef& Ref) const;
123 
classof(const Binary * v)124   static bool classof(const Binary *v) { return v->isWasm(); }
125 
types()126   ArrayRef<wasm::WasmSignature> types() const { return Signatures; }
functionTypes()127   ArrayRef<uint32_t> functionTypes() const { return FunctionTypes; }
imports()128   ArrayRef<wasm::WasmImport> imports() const { return Imports; }
tables()129   ArrayRef<wasm::WasmTable> tables() const { return Tables; }
memories()130   ArrayRef<wasm::WasmLimits> memories() const { return Memories; }
globals()131   ArrayRef<wasm::WasmGlobal> globals() const { return Globals; }
exports()132   ArrayRef<wasm::WasmExport> exports() const { return Exports; }
syms()133   ArrayRef<WasmSymbol> syms() const { return Symbols; }
linkingData()134   const wasm::WasmLinkingData& linkingData() const { return LinkingData; }
getNumberOfSymbols()135   uint32_t getNumberOfSymbols() const { return Symbols.size(); }
elements()136   ArrayRef<wasm::WasmElemSegment> elements() const { return ElemSegments; }
dataSegments()137   ArrayRef<WasmSegment> dataSegments() const { return DataSegments; }
functions()138   ArrayRef<wasm::WasmFunction> functions() const { return Functions; }
debugNames()139   ArrayRef<wasm::WasmFunctionName> debugNames() const { return DebugNames; }
startFunction()140   uint32_t startFunction() const { return StartFunction; }
getNumImportedGlobals()141   uint32_t getNumImportedGlobals() const { return NumImportedGlobals; }
getNumImportedFunctions()142   uint32_t getNumImportedFunctions() const { return NumImportedFunctions; }
143 
144   void moveSymbolNext(DataRefImpl &Symb) const override;
145 
146   uint32_t getSymbolFlags(DataRefImpl Symb) const override;
147 
148   basic_symbol_iterator symbol_begin() const override;
149 
150   basic_symbol_iterator symbol_end() const override;
151   Expected<StringRef> getSymbolName(DataRefImpl Symb) const override;
152 
153   Expected<uint64_t> getSymbolAddress(DataRefImpl Symb) const override;
154   uint64_t getWasmSymbolValue(const WasmSymbol& Sym) const;
155   uint64_t getSymbolValueImpl(DataRefImpl Symb) const override;
156   uint32_t getSymbolAlignment(DataRefImpl Symb) const override;
157   uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb) const override;
158   Expected<SymbolRef::Type> getSymbolType(DataRefImpl Symb) const override;
159   Expected<section_iterator> getSymbolSection(DataRefImpl Symb) const override;
160 
161   // Overrides from SectionRef.
162   void moveSectionNext(DataRefImpl &Sec) const override;
163   std::error_code getSectionName(DataRefImpl Sec,
164                                  StringRef &Res) const override;
165   uint64_t getSectionAddress(DataRefImpl Sec) const override;
166   uint64_t getSectionIndex(DataRefImpl Sec) const override;
167   uint64_t getSectionSize(DataRefImpl Sec) const override;
168   std::error_code getSectionContents(DataRefImpl Sec,
169                                      StringRef &Res) const override;
170   uint64_t getSectionAlignment(DataRefImpl Sec) const override;
171   bool isSectionCompressed(DataRefImpl Sec) const override;
172   bool isSectionText(DataRefImpl Sec) const override;
173   bool isSectionData(DataRefImpl Sec) const override;
174   bool isSectionBSS(DataRefImpl Sec) const override;
175   bool isSectionVirtual(DataRefImpl Sec) const override;
176   bool isSectionBitcode(DataRefImpl Sec) const override;
177   relocation_iterator section_rel_begin(DataRefImpl Sec) const override;
178   relocation_iterator section_rel_end(DataRefImpl Sec) const override;
179 
180   // Overrides from RelocationRef.
181   void moveRelocationNext(DataRefImpl &Rel) const override;
182   uint64_t getRelocationOffset(DataRefImpl Rel) const override;
183   symbol_iterator getRelocationSymbol(DataRefImpl Rel) const override;
184   uint64_t getRelocationType(DataRefImpl Rel) const override;
185   void getRelocationTypeName(DataRefImpl Rel,
186                              SmallVectorImpl<char> &Result) const override;
187 
188   section_iterator section_begin() const override;
189   section_iterator section_end() const override;
190   uint8_t getBytesInAddress() const override;
191   StringRef getFileFormatName() const override;
192   Triple::ArchType getArch() const override;
193   SubtargetFeatures getFeatures() const override;
194   bool isRelocatableObject() const override;
195 
196   struct ReadContext {
197     const uint8_t *Start;
198     const uint8_t *Ptr;
199     const uint8_t *End;
200   };
201 
202 private:
203   bool isValidFunctionIndex(uint32_t Index) const;
204   bool isDefinedFunctionIndex(uint32_t Index) const;
205   bool isValidGlobalIndex(uint32_t Index) const;
206   bool isDefinedGlobalIndex(uint32_t Index) const;
207   bool isValidFunctionSymbol(uint32_t Index) const;
208   bool isValidGlobalSymbol(uint32_t Index) const;
209   bool isValidDataSymbol(uint32_t Index) const;
210   bool isValidSectionSymbol(uint32_t Index) const;
211   wasm::WasmFunction &getDefinedFunction(uint32_t Index);
212   wasm::WasmGlobal &getDefinedGlobal(uint32_t Index);
213 
214   const WasmSection &getWasmSection(DataRefImpl Ref) const;
215   const wasm::WasmRelocation &getWasmRelocation(DataRefImpl Ref) const;
216 
217   const uint8_t *getPtr(size_t Offset) const;
218   Error parseSection(WasmSection &Sec);
219   Error parseCustomSection(WasmSection &Sec, ReadContext &Ctx);
220 
221   // Standard section types
222   Error parseTypeSection(ReadContext &Ctx);
223   Error parseImportSection(ReadContext &Ctx);
224   Error parseFunctionSection(ReadContext &Ctx);
225   Error parseTableSection(ReadContext &Ctx);
226   Error parseMemorySection(ReadContext &Ctx);
227   Error parseGlobalSection(ReadContext &Ctx);
228   Error parseExportSection(ReadContext &Ctx);
229   Error parseStartSection(ReadContext &Ctx);
230   Error parseElemSection(ReadContext &Ctx);
231   Error parseCodeSection(ReadContext &Ctx);
232   Error parseDataSection(ReadContext &Ctx);
233 
234   // Custom section types
235   Error parseNameSection(ReadContext &Ctx);
236   Error parseLinkingSection(ReadContext &Ctx);
237   Error parseLinkingSectionSymtab(ReadContext &Ctx);
238   Error parseLinkingSectionComdat(ReadContext &Ctx);
239   Error parseRelocSection(StringRef Name, ReadContext &Ctx);
240 
241   wasm::WasmObjectHeader Header;
242   std::vector<WasmSection> Sections;
243   std::vector<wasm::WasmSignature> Signatures;
244   std::vector<uint32_t> FunctionTypes;
245   std::vector<wasm::WasmTable> Tables;
246   std::vector<wasm::WasmLimits> Memories;
247   std::vector<wasm::WasmGlobal> Globals;
248   std::vector<wasm::WasmImport> Imports;
249   std::vector<wasm::WasmExport> Exports;
250   std::vector<wasm::WasmElemSegment> ElemSegments;
251   std::vector<WasmSegment> DataSegments;
252   std::vector<wasm::WasmFunction> Functions;
253   std::vector<WasmSymbol> Symbols;
254   std::vector<wasm::WasmFunctionName> DebugNames;
255   uint32_t StartFunction = -1;
256   bool HasLinkingSection = false;
257   wasm::WasmLinkingData LinkingData;
258   uint32_t NumImportedGlobals = 0;
259   uint32_t NumImportedFunctions = 0;
260   uint32_t CodeSection = 0;
261   uint32_t DataSection = 0;
262   uint32_t GlobalSection = 0;
263 };
264 
265 } // end namespace object
266 
267 inline raw_ostream &operator<<(raw_ostream &OS,
268                                const object::WasmSymbol &Sym) {
269   Sym.print(OS);
270   return OS;
271 }
272 
273 } // end namespace llvm
274 
275 #endif // LLVM_OBJECT_WASM_H
276