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