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