Wasm.h revision 321369
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/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
32namespace llvm {
33namespace object {
34
35class WasmSymbol {
36public:
37  enum class SymbolType {
38    FUNCTION_IMPORT,
39    FUNCTION_EXPORT,
40    GLOBAL_IMPORT,
41    GLOBAL_EXPORT,
42    DEBUG_FUNCTION_NAME,
43  };
44
45  WasmSymbol(StringRef Name, SymbolType Type, uint32_t Section,
46             uint32_t ElementIndex)
47      : Name(Name), Type(Type), Section(Section), ElementIndex(ElementIndex) {}
48
49  StringRef Name;
50  SymbolType Type;
51  uint32_t Section;
52  uint32_t Flags = 0;
53
54  // Index into the imports, exports or functions array of the object depending
55  // on the type
56  uint32_t ElementIndex;
57
58  bool isWeak() const {
59    return Flags & wasm::WASM_SYMBOL_FLAG_WEAK;
60  }
61
62  void print(raw_ostream &Out) const {
63    Out << "Name=" << Name << ", Type=" << static_cast<int>(Type)
64        << ", Flags=" << Flags << " ElemIndex=" << ElementIndex;
65  }
66
67#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
68  LLVM_DUMP_METHOD void dump() const { print(dbgs()); }
69#endif
70};
71
72struct WasmSection {
73  WasmSection() = default;
74
75  uint32_t Type = 0; // Section type (See below)
76  uint32_t Offset = 0; // Offset with in the file
77  StringRef Name; // Section name (User-defined sections only)
78  ArrayRef<uint8_t> Content; // Section content
79  std::vector<wasm::WasmRelocation> Relocations; // Relocations for this section
80};
81
82struct WasmSegment {
83  uint32_t SectionOffset;
84  wasm::WasmDataSegment Data;
85};
86
87class WasmObjectFile : public ObjectFile {
88
89public:
90  WasmObjectFile(MemoryBufferRef Object, Error &Err);
91
92  const wasm::WasmObjectHeader &getHeader() const;
93  const WasmSymbol &getWasmSymbol(const DataRefImpl &Symb) const;
94  const WasmSymbol &getWasmSymbol(const SymbolRef &Symbol) const;
95  const WasmSection &getWasmSection(const SectionRef &Section) const;
96  const wasm::WasmRelocation &getWasmRelocation(const RelocationRef& Ref) const;
97
98  static bool classof(const Binary *v) { return v->isWasm(); }
99
100  const std::vector<wasm::WasmSignature>& types() const { return Signatures; }
101  const std::vector<uint32_t>& functionTypes() const { return FunctionTypes; }
102  const std::vector<wasm::WasmImport>& imports() const { return Imports; }
103  const std::vector<wasm::WasmTable>& tables() const { return Tables; }
104  const std::vector<wasm::WasmLimits>& memories() const { return Memories; }
105  const std::vector<wasm::WasmGlobal>& globals() const { return Globals; }
106  const std::vector<wasm::WasmExport>& exports() const { return Exports; }
107  const wasm::WasmLinkingData& linkingData() const { return LinkingData; }
108
109  uint32_t getNumberOfSymbols() const {
110    return Symbols.size();
111  }
112
113  const std::vector<wasm::WasmElemSegment>& elements() const {
114    return ElemSegments;
115  }
116
117  const std::vector<WasmSegment>& dataSegments() const {
118    return DataSegments;
119  }
120
121  const std::vector<wasm::WasmFunction>& functions() const { return Functions; }
122  const ArrayRef<uint8_t>& code() const { return CodeSection; }
123  uint32_t startFunction() const { return StartFunction; }
124
125  void moveSymbolNext(DataRefImpl &Symb) const override;
126
127  uint32_t getSymbolFlags(DataRefImpl Symb) const override;
128
129  basic_symbol_iterator symbol_begin() const override;
130
131  basic_symbol_iterator symbol_end() const override;
132  Expected<StringRef> getSymbolName(DataRefImpl Symb) const override;
133
134  Expected<uint64_t> getSymbolAddress(DataRefImpl Symb) const override;
135  uint64_t getSymbolValueImpl(DataRefImpl Symb) const override;
136  uint32_t getSymbolAlignment(DataRefImpl Symb) const override;
137  uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb) const override;
138  Expected<SymbolRef::Type> getSymbolType(DataRefImpl Symb) const override;
139  Expected<section_iterator> getSymbolSection(DataRefImpl Symb) const override;
140
141  // Overrides from SectionRef.
142  void moveSectionNext(DataRefImpl &Sec) const override;
143  std::error_code getSectionName(DataRefImpl Sec,
144                                 StringRef &Res) const override;
145  uint64_t getSectionAddress(DataRefImpl Sec) const override;
146  uint64_t getSectionIndex(DataRefImpl Sec) const override;
147  uint64_t getSectionSize(DataRefImpl Sec) const override;
148  std::error_code getSectionContents(DataRefImpl Sec,
149                                     StringRef &Res) const override;
150  uint64_t getSectionAlignment(DataRefImpl Sec) const override;
151  bool isSectionCompressed(DataRefImpl Sec) const override;
152  bool isSectionText(DataRefImpl Sec) const override;
153  bool isSectionData(DataRefImpl Sec) const override;
154  bool isSectionBSS(DataRefImpl Sec) const override;
155  bool isSectionVirtual(DataRefImpl Sec) const override;
156  bool isSectionBitcode(DataRefImpl Sec) const override;
157  relocation_iterator section_rel_begin(DataRefImpl Sec) const override;
158  relocation_iterator section_rel_end(DataRefImpl Sec) const override;
159
160  // Overrides from RelocationRef.
161  void moveRelocationNext(DataRefImpl &Rel) const override;
162  uint64_t getRelocationOffset(DataRefImpl Rel) const override;
163  symbol_iterator getRelocationSymbol(DataRefImpl Rel) const override;
164  uint64_t getRelocationType(DataRefImpl Rel) const override;
165  void getRelocationTypeName(DataRefImpl Rel,
166                             SmallVectorImpl<char> &Result) const override;
167
168  section_iterator section_begin() const override;
169  section_iterator section_end() const override;
170  uint8_t getBytesInAddress() const override;
171  StringRef getFileFormatName() const override;
172  unsigned getArch() const override;
173  SubtargetFeatures getFeatures() const override;
174  bool isRelocatableObject() const override;
175
176private:
177  const WasmSection &getWasmSection(DataRefImpl Ref) const;
178  const wasm::WasmRelocation &getWasmRelocation(DataRefImpl Ref) const;
179
180  WasmSection* findCustomSectionByName(StringRef Name);
181  WasmSection* findSectionByType(uint32_t Type);
182
183  const uint8_t *getPtr(size_t Offset) const;
184  Error parseSection(WasmSection &Sec);
185  Error parseCustomSection(WasmSection &Sec, const uint8_t *Ptr,
186                           const uint8_t *End);
187
188  // Standard section types
189  Error parseTypeSection(const uint8_t *Ptr, const uint8_t *End);
190  Error parseImportSection(const uint8_t *Ptr, const uint8_t *End);
191  Error parseFunctionSection(const uint8_t *Ptr, const uint8_t *End);
192  Error parseTableSection(const uint8_t *Ptr, const uint8_t *End);
193  Error parseMemorySection(const uint8_t *Ptr, const uint8_t *End);
194  Error parseGlobalSection(const uint8_t *Ptr, const uint8_t *End);
195  Error parseExportSection(const uint8_t *Ptr, const uint8_t *End);
196  Error parseStartSection(const uint8_t *Ptr, const uint8_t *End);
197  Error parseElemSection(const uint8_t *Ptr, const uint8_t *End);
198  Error parseCodeSection(const uint8_t *Ptr, const uint8_t *End);
199  Error parseDataSection(const uint8_t *Ptr, const uint8_t *End);
200
201  // Custom section types
202  Error parseNameSection(const uint8_t *Ptr, const uint8_t *End);
203  Error parseLinkingSection(const uint8_t *Ptr, const uint8_t *End);
204  Error parseRelocSection(StringRef Name, const uint8_t *Ptr,
205                          const uint8_t *End);
206
207  wasm::WasmObjectHeader Header;
208  std::vector<WasmSection> Sections;
209  std::vector<wasm::WasmSignature> Signatures;
210  std::vector<uint32_t> FunctionTypes;
211  std::vector<wasm::WasmTable> Tables;
212  std::vector<wasm::WasmLimits> Memories;
213  std::vector<wasm::WasmGlobal> Globals;
214  std::vector<wasm::WasmImport> Imports;
215  std::vector<wasm::WasmExport> Exports;
216  std::vector<wasm::WasmElemSegment> ElemSegments;
217  std::vector<WasmSegment> DataSegments;
218  std::vector<wasm::WasmFunction> Functions;
219  std::vector<WasmSymbol> Symbols;
220  ArrayRef<uint8_t> CodeSection;
221  uint32_t StartFunction = -1;
222  bool HasLinkingSection = false;
223  wasm::WasmLinkingData LinkingData;
224
225  StringMap<uint32_t> SymbolMap;
226};
227
228} // end namespace object
229
230inline raw_ostream &operator<<(raw_ostream &OS,
231                               const object::WasmSymbol &Sym) {
232  Sym.print(OS);
233  return OS;
234}
235
236} // end namespace llvm
237
238#endif // LLVM_OBJECT_WASM_H
239