llvm.org GIT mirror llvm / 349a48f
[WebAssembly] Improve support for WebAssembly binary format Mostly this change adds support converting to and from YAML which will allow us to write more test cases for the WebAssembly MC and lld ports. Better support for objdump, readelf, and nm will be in followup CLs. I had to update the two wasm test binaries because they used the old style 'name' section which is no longer supported. Differential Revision: https://reviews.llvm.org/D31099 Patch by Sam Clegg git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@299101 91177308-0d34-0410-b5e6-96231b3b80d8 Derek Schuff 2 years ago
35 changed file(s) with 2448 addition(s) and 91 deletion(s). Raw diff Collapse all Expand all
2828 namespace llvm {
2929 namespace object {
3030
31 class WasmSymbol {
32 public:
33 enum class SymbolType {
34 FUNCTION_IMPORT,
35 FUNCTION_EXPORT,
36 GLOBAL_IMPORT,
37 GLOBAL_EXPORT,
38 DEBUG_FUNCTION_NAME,
39 };
40
41 WasmSymbol(StringRef Name, SymbolType Type) : Name(Name), Type(Type) {}
42
43 StringRef Name;
44 SymbolType Type;
45 };
46
47 class WasmSection {
48 public:
49 WasmSection() : Type(0), Offset(0) {}
50
51 uint32_t Type; // Section type (See below)
52 uint32_t Offset; // Offset with in the file
53 StringRef Name; // Section name (User-defined sections only)
54 ArrayRef Content; // Section content
55 std::vector Relocations; // Relocations for this section
56 };
57
3158 class WasmObjectFile : public ObjectFile {
3259 public:
3360 WasmObjectFile(MemoryBufferRef Object, Error &Err);
3461
3562 const wasm::WasmObjectHeader &getHeader() const;
36 const wasm::WasmSection *getWasmSection(const SectionRef &Section) const;
63 const WasmSymbol &getWasmSymbol(DataRefImpl Symb) const;
64 const WasmSection &getWasmSection(const SectionRef &Section) const;
65 const wasm::WasmRelocation &getWasmRelocation(const RelocationRef& Ref) const;
3766
3867 static bool classof(const Binary *v) { return v->isWasm(); }
3968
69 const std::vector& types() const { return Signatures; }
70 const std::vector& functionTypes() const { return FunctionTypes; }
71 const std::vector& imports() const { return Imports; }
72 const std::vector& tables() const { return Tables; }
73 const std::vector& memories() const { return Memories; }
74 const std::vector& globals() const { return Globals; }
75 const std::vector& exports() const { return Exports; }
76 const std::vector& elements() const {
77 return ElemSegments;
78 }
79 const std::vector& dataSegments() const {
80 return DataSegments;
81 }
82 const std::vector& functions() const { return Functions; }
83 const ArrayRef& code() const { return CodeSection; }
84 uint32_t startFunction() const { return StartFunction; }
85
4086 protected:
4187 void moveSymbolNext(DataRefImpl &Symb) const override;
42
43 std::error_code printSymbolName(raw_ostream &OS,
44 DataRefImpl Symb) const override;
4588
4689 uint32_t getSymbolFlags(DataRefImpl Symb) const override;
4790
74117 bool isSectionBitcode(DataRefImpl Sec) const override;
75118 relocation_iterator section_rel_begin(DataRefImpl Sec) const override;
76119 relocation_iterator section_rel_end(DataRefImpl Sec) const override;
77 section_iterator getRelocatedSection(DataRefImpl Sec) const override;
78120
79121 // Overrides from RelocationRef.
80122 void moveRelocationNext(DataRefImpl &Rel) const override;
93135 bool isRelocatableObject() const override;
94136
95137 private:
138 const WasmSection &getWasmSection(DataRefImpl Ref) const;
139 const wasm::WasmRelocation &getWasmRelocation(DataRefImpl Ref) const;
140
141 WasmSection* findCustomSectionByName(StringRef Name);
142 WasmSection* findSectionByType(uint32_t Type);
143
96144 const uint8_t *getPtr(size_t Offset) const;
97 Error parseCustomSection(wasm::WasmSection &Sec, const uint8_t *Ptr,
98 size_t Length);
145 Error parseSection(WasmSection &Sec);
146 Error parseCustomSection(WasmSection &Sec, const uint8_t *Ptr,
147 const uint8_t *End);
148
149 // Standard section types
150 Error parseTypeSection(const uint8_t *Ptr, const uint8_t *End);
151 Error parseImportSection(const uint8_t *Ptr, const uint8_t *End);
152 Error parseFunctionSection(const uint8_t *Ptr, const uint8_t *End);
153 Error parseTableSection(const uint8_t *Ptr, const uint8_t *End);
154 Error parseMemorySection(const uint8_t *Ptr, const uint8_t *End);
155 Error parseGlobalSection(const uint8_t *Ptr, const uint8_t *End);
156 Error parseExportSection(const uint8_t *Ptr, const uint8_t *End);
157 Error parseStartSection(const uint8_t *Ptr, const uint8_t *End);
158 Error parseElemSection(const uint8_t *Ptr, const uint8_t *End);
159 Error parseCodeSection(const uint8_t *Ptr, const uint8_t *End);
160 Error parseDataSection(const uint8_t *Ptr, const uint8_t *End);
161
162 // Custom section types
163 Error parseNameSection(const uint8_t *Ptr, const uint8_t *End);
164 Error parseRelocSection(StringRef Name, const uint8_t *Ptr,
165 const uint8_t *End);
99166
100167 wasm::WasmObjectHeader Header;
101 std::vector<wasm::WasmSection> Sections;
168 std::vector<WasmSection> Sections;
169 std::vector Signatures;
170 std::vector FunctionTypes;
171 std::vector Tables;
172 std::vector Memories;
173 std::vector Globals;
174 std::vector Imports;
175 std::vector Exports;
176 std::vector ElemSegments;
177 std::vector DataSegments;
178 std::vector Symbols;
179 std::vector Functions;
180 ArrayRef CodeSection;
181 uint32_t StartFunction;
102182 };
103183
104184 } // end namespace object
99 #ifndef LLVM_OBJECTYAML_OBJECTYAML_H
1010 #define LLVM_OBJECTYAML_OBJECTYAML_H
1111
12 #include "llvm/ObjectYAML/COFFYAML.h"
13 #include "llvm/ObjectYAML/ELFYAML.h"
14 #include "llvm/ObjectYAML/MachOYAML.h"
15 #include "llvm/ObjectYAML/WasmYAML.h"
1216 #include "llvm/Support/YAMLTraits.h"
13 #include "llvm/ObjectYAML/ELFYAML.h"
14 #include "llvm/ObjectYAML/COFFYAML.h"
15 #include "llvm/ObjectYAML/MachOYAML.h"
1617
1718 namespace llvm {
1819 namespace yaml {
2223 std::unique_ptr Coff;
2324 std::unique_ptr MachO;
2425 std::unique_ptr FatMachO;
26 std::unique_ptr Wasm;
2527 };
2628
2729 template <> struct MappingTraits {
0 //===- WasmYAML.h - Wasm YAMLIO implementation ------------------*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 ///
9 /// \file
10 /// \brief This file declares classes for handling the YAML representation
11 /// of wasm binaries.
12 ///
13 //===----------------------------------------------------------------------===//
14
15 #ifndef LLVM_OBJECTYAML_WASMYAML_H
16 #define LLVM_OBJECTYAML_WASMYAML_H
17
18 #include "llvm/ObjectYAML/YAML.h"
19 #include "llvm/Support/Wasm.h"
20
21 namespace llvm {
22 namespace WasmYAML {
23
24 LLVM_YAML_STRONG_TYPEDEF(uint32_t, SectionType)
25 LLVM_YAML_STRONG_TYPEDEF(int32_t, ValueType)
26 LLVM_YAML_STRONG_TYPEDEF(int32_t, TableType)
27 LLVM_YAML_STRONG_TYPEDEF(int32_t, SignatureForm)
28 LLVM_YAML_STRONG_TYPEDEF(uint32_t, ExportKind)
29 LLVM_YAML_STRONG_TYPEDEF(uint32_t, Opcode)
30 LLVM_YAML_STRONG_TYPEDEF(uint32_t, RelocType)
31
32 struct FileHeader {
33 yaml::Hex32 Version;
34 };
35
36 struct Import {
37 StringRef Module;
38 StringRef Field;
39 ExportKind Kind;
40 union {
41 uint32_t SigIndex;
42 ValueType GlobalType;
43 };
44 bool GlobalMutable;
45 };
46
47 struct Limits {
48 yaml::Hex32 Flags;
49 yaml::Hex32 Initial;
50 yaml::Hex32 Maximum;
51 };
52
53 struct Table {
54 TableType ElemType;
55 Limits TableLimits;
56 };
57
58 struct Export {
59 StringRef Name;
60 ExportKind Kind;
61 uint32_t Index;
62 };
63
64 struct ElemSegment {
65 uint32_t TableIndex;
66 wasm::WasmInitExpr Offset;
67 std::vector Functions;
68 };
69
70 struct Global {
71 ValueType Type;
72 bool Mutable;
73 wasm::WasmInitExpr InitExpr;
74 };
75
76 struct LocalDecl {
77 ValueType Type;
78 uint32_t Count;
79 };
80
81 struct Function {
82 std::vector Locals;
83 yaml::BinaryRef Body;
84 };
85
86 struct Relocation {
87 RelocType Type;
88 uint32_t Index;
89 yaml::Hex32 Offset;
90 yaml::Hex32 Addend;
91 };
92
93 struct DataSegment {
94 uint32_t Index;
95 wasm::WasmInitExpr Offset;
96 yaml::BinaryRef Content;
97 };
98
99 struct Signature {
100 Signature() : Form(wasm::WASM_TYPE_FUNC) {}
101
102 uint32_t Index;
103 SignatureForm Form;
104 std::vector ParamTypes;
105 ValueType ReturnType;
106 };
107
108 struct Section {
109 Section(SectionType SecType) : Type(SecType) {}
110
111 SectionType Type;
112 std::vector Relocations;
113 };
114
115 struct CustomSection : Section {
116 CustomSection() : Section(wasm::WASM_SEC_CUSTOM) {}
117 static bool classof(const Section *S) {
118 return S->Type == wasm::WASM_SEC_CUSTOM;
119 }
120
121 StringRef Name;
122 yaml::BinaryRef Payload;
123 };
124
125 struct TypeSection : Section {
126 TypeSection() : Section(wasm::WASM_SEC_TYPE) {}
127 static bool classof(const Section *S) {
128 return S->Type == wasm::WASM_SEC_TYPE;
129 }
130
131 std::vector Signatures;
132 };
133
134 struct ImportSection : Section {
135 ImportSection() : Section(wasm::WASM_SEC_IMPORT) {}
136 static bool classof(const Section *S) {
137 return S->Type == wasm::WASM_SEC_IMPORT;
138 }
139
140 std::vector Imports;
141 };
142
143 struct FunctionSection : Section {
144 FunctionSection() : Section(wasm::WASM_SEC_FUNCTION) {}
145 static bool classof(const Section *S) {
146 return S->Type == wasm::WASM_SEC_FUNCTION;
147 }
148
149 std::vector FunctionTypes;
150 };
151
152 struct TableSection : Section {
153 TableSection() : Section(wasm::WASM_SEC_TABLE) {}
154 static bool classof(const Section *S) {
155 return S->Type == wasm::WASM_SEC_TABLE;
156 }
157
158 std::vector Tables;
159 };
160
161 struct MemorySection : Section {
162 MemorySection() : Section(wasm::WASM_SEC_MEMORY) {}
163 static bool classof(const Section *S) {
164 return S->Type == wasm::WASM_SEC_MEMORY;
165 }
166
167 std::vector Memories;
168 };
169
170 struct GlobalSection : Section {
171 GlobalSection() : Section(wasm::WASM_SEC_GLOBAL) {}
172 static bool classof(const Section *S) {
173 return S->Type == wasm::WASM_SEC_GLOBAL;
174 }
175
176 std::vector Globals;
177 };
178
179 struct ExportSection : Section {
180 ExportSection() : Section(wasm::WASM_SEC_EXPORT) {}
181 static bool classof(const Section *S) {
182 return S->Type == wasm::WASM_SEC_EXPORT;
183 }
184
185 std::vector Exports;
186 };
187
188 struct StartSection : Section {
189 StartSection() : Section(wasm::WASM_SEC_START) {}
190 static bool classof(const Section *S) {
191 return S->Type == wasm::WASM_SEC_START;
192 }
193
194 uint32_t StartFunction;
195 };
196
197 struct ElemSection : Section {
198 ElemSection() : Section(wasm::WASM_SEC_ELEM) {}
199 static bool classof(const Section *S) {
200 return S->Type == wasm::WASM_SEC_ELEM;
201 }
202
203 std::vector Segments;
204 };
205
206 struct CodeSection : Section {
207 CodeSection() : Section(wasm::WASM_SEC_CODE) {}
208 static bool classof(const Section *S) {
209 return S->Type == wasm::WASM_SEC_CODE;
210 }
211
212 std::vector Functions;
213 };
214
215 struct DataSection : Section {
216 DataSection() : Section(wasm::WASM_SEC_DATA) {}
217 static bool classof(const Section *S) {
218 return S->Type == wasm::WASM_SEC_DATA;
219 }
220
221 std::vector Segments;
222 };
223
224 struct Object {
225 FileHeader Header;
226 std::vector> Sections;
227 };
228
229 } // end namespace WasmYAML
230 } // end namespace llvm
231
232 LLVM_YAML_IS_SEQUENCE_VECTOR(std::unique_ptr)
233 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::Signature)
234 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::ValueType)
235 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::Table)
236 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::Import)
237 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::Export)
238 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::ElemSegment)
239 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::Limits)
240 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::DataSegment)
241 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::Global)
242 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::Function)
243 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::LocalDecl)
244 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::Relocation)
245 LLVM_YAML_IS_SEQUENCE_VECTOR(uint32_t)
246
247 namespace llvm {
248 namespace yaml {
249
250 template <> struct MappingTraits {
251 static void mapping(IO &IO, WasmYAML::FileHeader &FileHdr);
252 };
253
254 template <> struct MappingTraits> {
255 static void mapping(IO &IO, std::unique_ptr &Section);
256 };
257
258 template <> struct MappingTraits {
259 static void mapping(IO &IO, WasmYAML::Object &Object);
260 };
261
262 template <> struct MappingTraits {
263 static void mapping(IO &IO, WasmYAML::Import &Import);
264 };
265
266 template <> struct MappingTraits {
267 static void mapping(IO &IO, WasmYAML::Export &Export);
268 };
269
270 template <> struct MappingTraits {
271 static void mapping(IO &IO, WasmYAML::Global &Global);
272 };
273
274 template <> struct ScalarEnumerationTraits {
275 static void enumeration(IO &IO, WasmYAML::SectionType &Type);
276 };
277
278 template <> struct MappingTraits {
279 static void mapping(IO &IO, WasmYAML::Signature &Signature);
280 };
281
282 template <> struct MappingTraits {
283 static void mapping(IO &IO, WasmYAML::Table &Table);
284 };
285
286 template <> struct MappingTraits {
287 static void mapping(IO &IO, WasmYAML::Limits &Limits);
288 };
289
290 template <> struct MappingTraits {
291 static void mapping(IO &IO, WasmYAML::Function &Function);
292 };
293
294 template <> struct MappingTraits {
295 static void mapping(IO &IO, WasmYAML::Relocation &Relocation);
296 };
297
298 template <> struct MappingTraits {
299 static void mapping(IO &IO, WasmYAML::LocalDecl &LocalDecl);
300 };
301
302 template <> struct MappingTraits {
303 static void mapping(IO &IO, wasm::WasmInitExpr &Expr);
304 };
305
306 template <> struct MappingTraits {
307 static void mapping(IO &IO, WasmYAML::DataSegment &Segment);
308 };
309
310 template <> struct MappingTraits {
311 static void mapping(IO &IO, WasmYAML::ElemSegment &Segment);
312 };
313
314 template <> struct ScalarEnumerationTraits {
315 static void enumeration(IO &IO, WasmYAML::ValueType &Type);
316 };
317
318 template <> struct ScalarEnumerationTraits {
319 static void enumeration(IO &IO, WasmYAML::ExportKind &Kind);
320 };
321
322 template <> struct ScalarEnumerationTraits {
323 static void enumeration(IO &IO, WasmYAML::TableType &Type);
324 };
325
326 template <> struct ScalarEnumerationTraits {
327 static void enumeration(IO &IO, WasmYAML::Opcode &Opcode);
328 };
329
330 template <> struct ScalarEnumerationTraits {
331 static void enumeration(IO &IO, WasmYAML::RelocType &Kind);
332 };
333
334 } // end namespace yaml
335 } // end namespace llvm
336
337 #endif
2929 uint32_t Version;
3030 };
3131
32 struct WasmSection {
33 uint32_t Type; // Section type (See below)
34 uint32_t Offset; // Offset with in the file
35 StringRef Name; // Section name (User-defined sections only)
36 ArrayRef Content; // Section content
32 struct WasmSignature {
33 std::vector ParamTypes;
34 int32_t ReturnType;
35 };
36
37 struct WasmImport {
38 StringRef Module;
39 StringRef Field;
40 uint32_t Kind;
41 union {
42 uint32_t SigIndex;
43 int32_t GlobalType;
44 };
45 bool GlobalMutable;
46 };
47
48 struct WasmExport {
49 StringRef Name;
50 uint32_t Kind;
51 uint32_t Index;
52 };
53
54 struct WasmLimits {
55 uint32_t Flags;
56 uint32_t Initial;
57 uint32_t Maximum;
58 };
59
60 struct WasmTable {
61 int32_t ElemType;
62 WasmLimits Limits;
63 };
64
65 struct WasmInitExpr {
66 uint8_t Opcode;
67 union {
68 int32_t Int32;
69 int64_t Int64;
70 int32_t Float32;
71 int64_t Float64;
72 uint32_t Global;
73 } Value;
74 };
75
76 struct WasmGlobal {
77 int32_t Type;
78 bool Mutable;
79 WasmInitExpr InitExpr;
80 };
81
82 struct WasmLocalDecl {
83 int32_t Type;
84 uint32_t Count;
85 };
86
87 struct WasmFunction {
88 std::vector Locals;
89 ArrayRef Body;
90 };
91
92 struct WasmDataSegment {
93 uint32_t Index;
94 WasmInitExpr Offset;
95 ArrayRef Content;
96 };
97
98 struct WasmElemSegment {
99 uint32_t TableIndex;
100 WasmInitExpr Offset;
101 std::vector Functions;
102 };
103
104 struct WasmRelocation {
105 uint32_t Type; // The type of the relocation.
106 int32_t Index; // Index into function to global index space.
107 uint64_t Offset; // Offset from the start of the section.
108 uint64_t Addend; // A value to add to the symbol.
37109 };
38110
39111 enum : unsigned {
85157 WASM_NAMES_LOCAL = 0x2,
86158 };
87159
160 enum : unsigned {
161 WASM_LIMITS_FLAG_HAS_MAX = 0x1,
162 };
163
88164 // Subset of types that a value can have
89165 enum class ValType {
90166 I32 = WASM_TYPE_I32,
99175 #include "WasmRelocs/WebAssembly.def"
100176 };
101177
178 #undef WASM_RELOC
179
102180 } // end namespace wasm
103181 } // end namespace llvm
104182
3737 return std::move(ObjectFile);
3838 }
3939
40 #define VARINT7_MAX ((1<<7)-1)
41 #define VARINT7_MIN (-(1<<7))
42 #define VARUINT7_MAX (1<<7)
43 #define VARUINT1_MAX (1)
44
45 static uint8_t readUint8(const uint8_t *&Ptr) { return *Ptr++; }
46
4047 static uint32_t readUint32(const uint8_t *&Ptr) {
4148 uint32_t Result = support::endian::read32le(Ptr);
49 Ptr += sizeof(Result);
50 return Result;
51 }
52
53 static int32_t readFloat32(const uint8_t *&Ptr) {
54 int32_t Result = 0;
55 memcpy(&Result, Ptr, sizeof(Result));
56 Ptr += sizeof(Result);
57 return Result;
58 }
59
60 static int64_t readFloat64(const uint8_t *&Ptr) {
61 int64_t Result = 0;
62 memcpy(&Result, Ptr, sizeof(Result));
4263 Ptr += sizeof(Result);
4364 return Result;
4465 }
5778 return Return;
5879 }
5980
60 static Error readSection(wasm::WasmSection &Section, const uint8_t *&Ptr,
81 static int64_t readLEB128(const uint8_t *&Ptr) {
82 unsigned Count;
83 uint64_t Result = decodeSLEB128(Ptr, &Count);
84 Ptr += Count;
85 return Result;
86 }
87
88 static uint8_t readVaruint1(const uint8_t *&Ptr) {
89 int64_t result = readLEB128(Ptr);
90 assert(result <= VARUINT1_MAX && result >= 0);
91 return result;
92 }
93
94 static int8_t readVarint7(const uint8_t *&Ptr) {
95 int64_t result = readLEB128(Ptr);
96 assert(result <= VARINT7_MAX && result >= VARINT7_MIN);
97 return result;
98 }
99
100 static uint8_t readVaruint7(const uint8_t *&Ptr) {
101 uint64_t result = readULEB128(Ptr);
102 assert(result <= VARUINT7_MAX && result >= 0);
103 return result;
104 }
105
106 static int32_t readVarint32(const uint8_t *&Ptr) {
107 int64_t result = readLEB128(Ptr);
108 assert(result <= INT32_MAX && result >= INT32_MIN);
109 return result;
110 }
111
112 static uint32_t readVaruint32(const uint8_t *&Ptr) {
113 uint64_t result = readULEB128(Ptr);
114 assert(result <= UINT32_MAX && result >= 0);
115 return result;
116 }
117
118 static int64_t readVarint64(const uint8_t *&Ptr) {
119 return readLEB128(Ptr);
120 }
121
122 static uint8_t readOpcode(const uint8_t *&Ptr) {
123 return readUint8(Ptr);
124 }
125
126 static Error readInitExpr(wasm::WasmInitExpr &Expr, const uint8_t *&Ptr) {
127 Expr.Opcode = readOpcode(Ptr);
128
129 switch (Expr.Opcode) {
130 case wasm::WASM_OPCODE_I32_CONST:
131 Expr.Value.Int32 = readVarint32(Ptr);
132 break;
133 case wasm::WASM_OPCODE_I64_CONST:
134 Expr.Value.Int64 = readVarint64(Ptr);
135 break;
136 case wasm::WASM_OPCODE_F32_CONST:
137 Expr.Value.Float32 = readFloat32(Ptr);
138 break;
139 case wasm::WASM_OPCODE_F64_CONST:
140 Expr.Value.Float64 = readFloat64(Ptr);
141 break;
142 case wasm::WASM_OPCODE_GET_GLOBAL:
143 Expr.Value.Global = readUint32(Ptr);
144 break;
145 default:
146 return make_error("Invalid opcode in init_expr",
147 object_error::parse_failed);
148 }
149
150 uint8_t EndOpcode = readOpcode(Ptr);
151 if (EndOpcode != wasm::WASM_OPCODE_END) {
152 return make_error("Invalid init_expr",
153 object_error::parse_failed);
154 }
155 return Error::success();
156 }
157
158 static wasm::WasmLimits readLimits(const uint8_t *&Ptr) {
159 wasm::WasmLimits Result;
160 Result.Flags = readVaruint1(Ptr);
161 Result.Initial = readVaruint32(Ptr);
162 if (Result.Flags & wasm::WASM_LIMITS_FLAG_HAS_MAX)
163 Result.Maximum = readVaruint32(Ptr);
164 return Result;
165 }
166
167 static Error readSection(WasmSection &Section, const uint8_t *&Ptr,
61168 const uint8_t *Start) {
62169 // TODO(sbc): Avoid reading past EOF in the case of malformed files.
63170 Section.Offset = Ptr - Start;
64 Section.Type = readULEB128(Ptr);
65 uint32_t Size = readULEB128(Ptr);
171 Section.Type = readVaruint7(Ptr);
172 uint32_t Size = readVaruint32(Ptr);
66173 if (Size == 0)
67174 return make_error("Zero length section",
68175 object_error::parse_failed);
72179 }
73180
74181 WasmObjectFile::WasmObjectFile(MemoryBufferRef Buffer, Error &Err)
75 : ObjectFile(Binary::ID_Wasm, Buffer) {
182 : ObjectFile(Binary::ID_Wasm, Buffer), StartFunction(-1) {
76183 ErrorAsOutParameter ErrAsOutParam(&Err);
77184 Header.Magic = getData().substr(0, 4);
78185 if (Header.Magic != StringRef("\0asm", 4)) {
89196 }
90197
91198 const uint8_t *Eof = getPtr(getData().size());
92 wasm::WasmSection Sec;
199 WasmSection Sec;
93200 while (Ptr < Eof) {
94201 if ((Err = readSection(Sec, Ptr, getPtr(0))))
95202 return;
96 if (Sec.Type == wasm::WASM_SEC_CUSTOM) {
97 if ((Err =
98 parseCustomSection(Sec, Sec.Content.data(), Sec.Content.size())))
99 return;
100 }
203 if ((Err = parseSection(Sec)))
204 return;
205
101206 Sections.push_back(Sec);
102207 }
103208 }
104209
105 Error WasmObjectFile::parseCustomSection(wasm::WasmSection &Sec,
106 const uint8_t *Ptr, size_t Length) {
210 Error WasmObjectFile::parseSection(WasmSection &Sec) {
211 const uint8_t* Start = Sec.Content.data();
212 const uint8_t* End = Start + Sec.Content.size();
213 switch (Sec.Type) {
214 case wasm::WASM_SEC_CUSTOM:
215 return parseCustomSection(Sec, Start, End);
216 case wasm::WASM_SEC_TYPE:
217 return parseTypeSection(Start, End);
218 case wasm::WASM_SEC_IMPORT:
219 return parseImportSection(Start, End);
220 case wasm::WASM_SEC_FUNCTION:
221 return parseFunctionSection(Start, End);
222 case wasm::WASM_SEC_TABLE:
223 return parseTableSection(Start, End);
224 case wasm::WASM_SEC_MEMORY:
225 return parseMemorySection(Start, End);
226 case wasm::WASM_SEC_GLOBAL:
227 return parseGlobalSection(Start, End);
228 case wasm::WASM_SEC_EXPORT:
229 return parseExportSection(Start, End);
230 case wasm::WASM_SEC_START:
231 return parseStartSection(Start, End);
232 case wasm::WASM_SEC_ELEM:
233 return parseElemSection(Start, End);
234 case wasm::WASM_SEC_CODE:
235 return parseCodeSection(Start, End);
236 case wasm::WASM_SEC_DATA:
237 return parseDataSection(Start, End);
238 default:
239 return make_error("Bad section type",
240 object_error::parse_failed);
241 }
242 }
243
244 Error WasmObjectFile::parseNameSection(const uint8_t *Ptr, const uint8_t *End) {
245 while (Ptr < End) {
246 uint8_t Type = readVarint7(Ptr);
247 uint32_t Size = readVaruint32(Ptr);
248 switch (Type) {
249 case wasm::WASM_NAMES_FUNCTION: {
250 uint32_t Count = readVaruint32(Ptr);
251 while (Count--) {
252 /*uint32_t Index =*/readVaruint32(Ptr);
253 StringRef Name = readString(Ptr);
254 if (Name.size())
255 Symbols.emplace_back(Name,
256 WasmSymbol::SymbolType::DEBUG_FUNCTION_NAME);
257 }
258 break;
259 }
260 // Ignore local names for now
261 case wasm::WASM_NAMES_LOCAL:
262 default:
263 Ptr += Size;
264 break;
265 }
266 }
267
268 if (Ptr != End)
269 return make_error("Name section ended prematurely",
270 object_error::parse_failed);
271 return Error::success();
272 }
273
274 WasmSection* WasmObjectFile::findCustomSectionByName(StringRef Name) {
275 for (WasmSection& Section : Sections) {
276 if (Section.Type == wasm::WASM_SEC_CUSTOM && Section.Name == Name)
277 return &Section;
278 }
279 return nullptr;
280 }
281
282 WasmSection* WasmObjectFile::findSectionByType(uint32_t Type) {
283 assert(Type != wasm::WASM_SEC_CUSTOM);
284 for (WasmSection& Section : Sections) {
285 if (Section.Type == Type)
286 return &Section;
287 }
288 return nullptr;
289 }
290
291 Error WasmObjectFile::parseRelocSection(StringRef Name, const uint8_t *Ptr,
292 const uint8_t *End) {
293 uint8_t SectionCode = readVarint7(Ptr);
294 WasmSection* Section = nullptr;
295 if (SectionCode == wasm::WASM_SEC_CUSTOM) {
296 StringRef Name = readString(Ptr);
297 Section = findCustomSectionByName(Name);
298 } else {
299 Section = findSectionByType(SectionCode);
300 }
301 if (!Section)
302 return make_error("Invalid section code",
303 object_error::parse_failed);
304 uint32_t RelocCount = readVaruint32(Ptr);
305 while (RelocCount--) {
306 wasm::WasmRelocation Reloc;
307 memset(&Reloc, 0, sizeof(Reloc));
308 Reloc.Type = readVaruint32(Ptr);
309 Reloc.Offset = readVaruint32(Ptr);
310 Reloc.Index = readVaruint32(Ptr);
311 switch (Reloc.Type) {
312 case wasm::R_WEBASSEMBLY_FUNCTION_INDEX_LEB:
313 case wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB:
314 case wasm::R_WEBASSEMBLY_TABLE_INDEX_I32:
315 break;
316 case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_LEB:
317 case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_SLEB:
318 case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_I32:
319 Reloc.Addend = readVaruint32(Ptr);
320 break;
321 default:
322 return make_error("Bad relocation type",
323 object_error::parse_failed);
324 }
325 Section->Relocations.push_back(Reloc);
326 }
327 if (Ptr != End)
328 return make_error("Reloc section ended prematurely",
329 object_error::parse_failed);
330 return Error::success();
331 }
332
333 Error WasmObjectFile::parseCustomSection(WasmSection &Sec,
334 const uint8_t *Ptr, const uint8_t *End) {
107335 Sec.Name = readString(Ptr);
336 if (Sec.Name == "name") {
337 if (Error Err = parseNameSection(Ptr, End))
338 return Err;
339 } else if (Sec.Name.startswith("reloc.")) {
340 if (Error Err = parseRelocSection(Sec.Name, Ptr, End))
341 return Err;
342 }
343 return Error::success();
344 }
345
346 Error WasmObjectFile::parseTypeSection(const uint8_t *Ptr, const uint8_t *End) {
347 uint32_t Count = readVaruint32(Ptr);
348 Signatures.reserve(Count);
349 while (Count--) {
350 wasm::WasmSignature Sig;
351 Sig.ReturnType = wasm::WASM_TYPE_NORESULT;
352 int8_t Form = readVarint7(Ptr);
353 if (Form != wasm::WASM_TYPE_FUNC) {
354 return make_error("Invalid signature type",
355 object_error::parse_failed);
356 }
357 uint32_t ParamCount = readVaruint32(Ptr);
358 Sig.ParamTypes.reserve(ParamCount);
359 while (ParamCount--) {
360 uint32_t ParamType = readVarint7(Ptr);
361 Sig.ParamTypes.push_back(ParamType);
362 }
363 uint32_t ReturnCount = readVaruint32(Ptr);
364 if (ReturnCount) {
365 if (ReturnCount != 1) {
366 return make_error(
367 "Multiple return types not supported", object_error::parse_failed);
368 }
369 Sig.ReturnType = readVarint7(Ptr);
370 }
371 Signatures.push_back(Sig);
372 }
373 if (Ptr != End)
374 return make_error("Type section ended prematurely",
375 object_error::parse_failed);
376 return Error::success();
377 }
378
379 Error WasmObjectFile::parseImportSection(const uint8_t *Ptr, const uint8_t *End) {
380 uint32_t Count = readVaruint32(Ptr);
381 Imports.reserve(Count);
382 while (Count--) {
383 wasm::WasmImport Im;
384 Im.Module = readString(Ptr);
385 Im.Field = readString(Ptr);
386 Im.Kind = readUint8(Ptr);
387 switch (Im.Kind) {
388 case wasm::WASM_EXTERNAL_FUNCTION:
389 Im.SigIndex = readVaruint32(Ptr);
390 Symbols.emplace_back(Im.Field, WasmSymbol::SymbolType::FUNCTION_IMPORT);
391 break;
392 case wasm::WASM_EXTERNAL_GLOBAL:
393 Im.GlobalType = readVarint7(Ptr);
394 Im.GlobalMutable = readVaruint1(Ptr);
395 Symbols.emplace_back(Im.Field, WasmSymbol::SymbolType::GLOBAL_IMPORT);
396 break;
397 default:
398 // TODO(sbc): Handle other kinds of imports
399 return make_error(
400 "Unexpected import kind", object_error::parse_failed);
401 }
402 Imports.push_back(Im);
403 }
404 if (Ptr != End)
405 return make_error("Import section ended prematurely",
406 object_error::parse_failed);
407 return Error::success();
408 }
409
410 Error WasmObjectFile::parseFunctionSection(const uint8_t *Ptr, const uint8_t *End) {
411 uint32_t Count = readVaruint32(Ptr);
412 FunctionTypes.reserve(Count);
413 while (Count--) {
414 FunctionTypes.push_back(readVaruint32(Ptr));
415 }
416 if (Ptr != End)
417 return make_error("Function section ended prematurely",
418 object_error::parse_failed);
419 return Error::success();
420 }
421
422 Error WasmObjectFile::parseTableSection(const uint8_t *Ptr, const uint8_t *End) {
423 uint32_t Count = readVaruint32(Ptr);
424 Tables.reserve(Count);
425 while (Count--) {
426 wasm::WasmTable Table;
427 Table.ElemType = readVarint7(Ptr);
428 if (Table.ElemType != wasm::WASM_TYPE_ANYFUNC) {
429 return make_error("Invalid table element type",
430 object_error::parse_failed);
431 }
432 Table.Limits = readLimits(Ptr);
433 Tables.push_back(Table);
434 }
435 if (Ptr != End)
436 return make_error("Table section ended prematurely",
437 object_error::parse_failed);
438 return Error::success();
439 }
440
441 Error WasmObjectFile::parseMemorySection(const uint8_t *Ptr, const uint8_t *End) {
442 uint32_t Count = readVaruint32(Ptr);
443 Memories.reserve(Count);
444 while (Count--) {
445 Memories.push_back(readLimits(Ptr));
446 }
447 if (Ptr != End)
448 return make_error("Memory section ended prematurely",
449 object_error::parse_failed);
450 return Error::success();
451 }
452
453 Error WasmObjectFile::parseGlobalSection(const uint8_t *Ptr, const uint8_t *End) {
454 uint32_t Count = readVaruint32(Ptr);
455 Globals.reserve(Count);
456 while (Count--) {
457 wasm::WasmGlobal Global;
458 Global.Type = readVarint7(Ptr);
459 Global.Mutable = readVaruint1(Ptr);
460 size_t offset = Ptr - getPtr(0);
461 if (Error Err = readInitExpr(Global.InitExpr, Ptr)) {
462 offset = Ptr - getPtr(0);
463 return Err;
464 }
465 Globals.push_back(Global);
466 }
467 if (Ptr != End)
468 return make_error("Global section ended prematurely",
469 object_error::parse_failed);
470 return Error::success();
471 }
472
473 Error WasmObjectFile::parseExportSection(const uint8_t *Ptr, const uint8_t *End) {
474 uint32_t Count = readVaruint32(Ptr);
475 Exports.reserve(Count);
476 while (Count--) {
477 wasm::WasmExport Ex;
478 Ex.Name = readString(Ptr);
479 Ex.Kind = readUint8(Ptr);
480 Ex.Index = readVaruint32(Ptr);
481 Exports.push_back(Ex);
482 switch (Ex.Kind) {
483 case wasm::WASM_EXTERNAL_FUNCTION:
484 Symbols.emplace_back(Ex.Name, WasmSymbol::SymbolType::FUNCTION_EXPORT);
485 break;
486 case wasm::WASM_EXTERNAL_GLOBAL:
487 Symbols.emplace_back(Ex.Name, WasmSymbol::SymbolType::GLOBAL_EXPORT);
488 break;
489 default:
490 // TODO(sbc): Handle other kinds of exports
491 return make_error(
492 "Unexpected export kind", object_error::parse_failed);
493 }
494 }
495 if (Ptr != End)
496 return make_error("Export section ended prematurely",
497 object_error::parse_failed);
498 return Error::success();
499 }
500
501 Error WasmObjectFile::parseStartSection(const uint8_t *Ptr, const uint8_t *End) {
502 StartFunction = readVaruint32(Ptr);
503 if (StartFunction < FunctionTypes.size())
504 return make_error("Invalid start function",
505 object_error::parse_failed);
506 return Error::success();
507 }
508
509 Error WasmObjectFile::parseCodeSection(const uint8_t *Ptr, const uint8_t *End) {
510 uint32_t FunctionCount = readVaruint32(Ptr);
511 if (FunctionCount != FunctionTypes.size()) {
512 return make_error("Invalid function count",
513 object_error::parse_failed);
514 }
515
516 CodeSection = ArrayRef(Ptr, End - Ptr);
517
518 while (FunctionCount--) {
519 wasm::WasmFunction Function;
520 uint32_t FunctionSize = readVaruint32(Ptr);
521 const uint8_t *FunctionEnd = Ptr + FunctionSize;
522
523 uint32_t NumLocalDecls = readVaruint32(Ptr);
524 Function.Locals.reserve(NumLocalDecls);
525 while (NumLocalDecls--) {
526 wasm::WasmLocalDecl Decl;
527 Decl.Count = readVaruint32(Ptr);
528 Decl.Type = readVarint7(Ptr);
529 Function.Locals.push_back(Decl);
530 }
531
532 uint32_t BodySize = FunctionEnd - Ptr;
533 Function.Body = ArrayRef(Ptr, BodySize);
534 Ptr += BodySize;
535 assert(Ptr == FunctionEnd);
536 Functions.push_back(Function);
537 }
538 if (Ptr != End)
539 return make_error("Code section ended prematurely",
540 object_error::parse_failed);
541 return Error::success();
542 }
543
544 Error WasmObjectFile::parseElemSection(const uint8_t *Ptr, const uint8_t *End) {
545 uint32_t Count = readVaruint32(Ptr);
546 ElemSegments.reserve(Count);
547 while (Count--) {
548 wasm::WasmElemSegment Segment;
549 Segment.TableIndex = readVaruint32(Ptr);
550 if (Segment.TableIndex != 0) {
551 return make_error("Invalid TableIndex",
552 object_error::parse_failed);
553 }
554 if (Error Err = readInitExpr(Segment.Offset, Ptr))
555 return Err;
556 uint32_t NumElems = readVaruint32(Ptr);
557 while (NumElems--) {
558 Segment.Functions.push_back(readVaruint32(Ptr));
559 }
560 ElemSegments.push_back(Segment);
561 }
562 if (Ptr != End)
563 return make_error("Elem section ended prematurely",
564 object_error::parse_failed);
565 return Error::success();
566 }
567
568 Error WasmObjectFile::parseDataSection(const uint8_t *Ptr, const uint8_t *End) {
569 uint32_t Count = readVaruint32(Ptr);
570 DataSegments.reserve(Count);
571 while (Count--) {
572 wasm::WasmDataSegment Segment;
573 Segment.Index = readVaruint32(Ptr);
574 if (Error Err = readInitExpr(Segment.Offset, Ptr))
575 return Err;
576 uint32_t Size = readVaruint32(Ptr);
577 Segment.Content = ArrayRef(Ptr, Size);
578 Ptr += Size;
579 DataSegments.push_back(Segment);
580 }
581 if (Ptr != End)
582 return make_error("Data section ended prematurely",
583 object_error::parse_failed);
108584 return Error::success();
109585 }
110586
116592 return Header;
117593 }
118594
119 void WasmObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
120 llvm_unreachable("not yet implemented");
121 }
122
123 std::error_code WasmObjectFile::printSymbolName(raw_ostream &OS,
124 DataRefImpl Symb) const {
125 llvm_unreachable("not yet implemented");
126 return object_error::invalid_symbol_index;
127 }
595 void WasmObjectFile::moveSymbolNext(DataRefImpl &Symb) const { Symb.d.a++; }
128596
129597 uint32_t WasmObjectFile::getSymbolFlags(DataRefImpl Symb) const {
130 llvm_unreachable("not yet implemented");
131 return 0;
598 const WasmSymbol &Sym = getWasmSymbol(Symb);
599 switch (Sym.Type) {
600 case WasmSymbol::SymbolType::FUNCTION_IMPORT:
601 return object::SymbolRef::SF_Undefined | SymbolRef::SF_Executable;
602 case WasmSymbol::SymbolType::FUNCTION_EXPORT:
603 return object::SymbolRef::SF_Global | SymbolRef::SF_Executable;
604 case WasmSymbol::SymbolType::DEBUG_FUNCTION_NAME:
605 return object::SymbolRef::SF_Executable;
606 case WasmSymbol::SymbolType::GLOBAL_IMPORT:
607 return object::SymbolRef::SF_Undefined;
608 case WasmSymbol::SymbolType::GLOBAL_EXPORT:
609 return object::SymbolRef::SF_Global;
610 }
132611 }
133612
134613 basic_symbol_iterator WasmObjectFile::symbol_begin() const {
135 return BasicSymbolRef(DataRefImpl(), this);
614 DataRefImpl Ref;
615 Ref.d.a = 0;
616 return BasicSymbolRef(Ref, this);
136617 }
137618
138619 basic_symbol_iterator WasmObjectFile::symbol_end() const {
139 return BasicSymbolRef(DataRefImpl(), this);
620 DataRefImpl Ref;
621 Ref.d.a = Symbols.size();
622 return BasicSymbolRef(Ref, this);
623 }
624
625 const WasmSymbol &WasmObjectFile::getWasmSymbol(DataRefImpl Symb) const {
626 return Symbols[Symb.d.a];
140627 }
141628
142629 Expected WasmObjectFile::getSymbolName(DataRefImpl Symb) const {
143 llvm_unreachable("not yet implemented");
144 return errorCodeToError(object_error::invalid_symbol_index);
630 const WasmSymbol &Sym = getWasmSymbol(Symb);
631 return Sym.Name;
145632 }
146633
147634 Expected WasmObjectFile::getSymbolAddress(DataRefImpl Symb) const {
148 llvm_unreachable("not yet implemented");
149 return errorCodeToError(object_error::invalid_symbol_index);
635 return (uint64_t)Symb.d.a;
150636 }
151637
152638 uint64_t WasmObjectFile::getSymbolValueImpl(DataRefImpl Symb) const {
180666
181667 std::error_code WasmObjectFile::getSectionName(DataRefImpl Sec,
182668 StringRef &Res) const {
183 const wasm::WasmSection &S = Sections[Sec.d.a];
669 const WasmSection &S = Sections[Sec.d.a];
184670 #define ECase(X) \
185671 case wasm::WASM_SEC_##X: \
186672 Res = #X; \
210696 uint64_t WasmObjectFile::getSectionAddress(DataRefImpl Sec) const { return 0; }
211697
212698 uint64_t WasmObjectFile::getSectionSize(DataRefImpl Sec) const {
213 const wasm::WasmSection &S = Sections[Sec.d.a];
699 const WasmSection &S = Sections[Sec.d.a];
214700 return S.Content.size();
215701 }
216702
217703 std::error_code WasmObjectFile::getSectionContents(DataRefImpl Sec,
218704 StringRef &Res) const {
219 const wasm::WasmSection &S = Sections[Sec.d.a];
705 const WasmSection &S = Sections[Sec.d.a];
220706 // This will never fail since wasm sections can never be empty (user-sections
221707 // must have a name and non-user sections each have a defined structure).
222708 Res = StringRef(reinterpret_cast(S.Content.data()),
233719 }
234720
235721 bool WasmObjectFile::isSectionText(DataRefImpl Sec) const {
236 const wasm::WasmSection &S = Sections[Sec.d.a];
237 return S.Type == wasm::WASM_SEC_CODE;
722 return getWasmSection(Sec).Type == wasm::WASM_SEC_CODE;
238723 }
239724
240725 bool WasmObjectFile::isSectionData(DataRefImpl Sec) const {
241 const wasm::WasmSection &S = Sections[Sec.d.a];
242 return S.Type == wasm::WASM_SEC_DATA;
726 return getWasmSection(Sec).Type == wasm::WASM_SEC_DATA;
243727 }
244728
245729 bool WasmObjectFile::isSectionBSS(DataRefImpl Sec) const { return false; }
248732
249733 bool WasmObjectFile::isSectionBitcode(DataRefImpl Sec) const { return false; }
250734
251 relocation_iterator WasmObjectFile::section_rel_begin(DataRefImpl Sec) const {
252 llvm_unreachable("not yet implemented");
253 RelocationRef Rel;
254 return relocation_iterator(Rel);
255 }
256
257 relocation_iterator WasmObjectFile::section_rel_end(DataRefImpl Sec) const {
258 llvm_unreachable("not yet implemented");
259 RelocationRef Rel;
260 return relocation_iterator(Rel);
261 }
262
263 section_iterator WasmObjectFile::getRelocatedSection(DataRefImpl Sec) const {
264 llvm_unreachable("not yet implemented");
265 SectionRef Ref;
266 return section_iterator(Ref);
735 relocation_iterator WasmObjectFile::section_rel_begin(DataRefImpl Ref) const {
736 DataRefImpl RelocRef;
737 RelocRef.d.a = Ref.d.a;
738 RelocRef.d.b = 0;
739 return relocation_iterator(RelocationRef(RelocRef, this));
740 }
741
742 relocation_iterator WasmObjectFile::section_rel_end(DataRefImpl Ref) const {
743 const WasmSection &Sec = getWasmSection(Ref);
744 DataRefImpl RelocRef;
745 RelocRef.d.a = Ref.d.a;
746 RelocRef.d.b = Sec.Relocations.size();
747 return relocation_iterator(RelocationRef(RelocRef, this));
267748 }
268749
269750 void WasmObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
270 llvm_unreachable("not yet implemented");
271 }
272
273 uint64_t WasmObjectFile::getRelocationOffset(DataRefImpl Rel) const {
274 llvm_unreachable("not yet implemented");
275 return 0;
751 Rel.d.b++;
752 }
753
754 uint64_t WasmObjectFile::getRelocationOffset(DataRefImpl Ref) const {
755 const wasm::WasmRelocation &Rel = getWasmRelocation(Ref);
756 return Rel.Offset;
276757 }
277758
278759 symbol_iterator WasmObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
281762 return symbol_iterator(Ref);
282763 }
283764
284 uint64_t WasmObjectFile::getRelocationType(DataRefImpl Rel) const {
285 llvm_unreachable("not yet implemented");
286 return 0;
765 uint64_t WasmObjectFile::getRelocationType(DataRefImpl Ref) const {
766 const wasm::WasmRelocation &Rel = getWasmRelocation(Ref);
767 return Rel.Type;
287768 }
288769
289770 void WasmObjectFile::getRelocationTypeName(
290 DataRefImpl Rel, SmallVectorImpl &Result) const {
291 llvm_unreachable("not yet implemented");
771 DataRefImpl Ref, SmallVectorImpl &Result) const {
772 const wasm::WasmRelocation& Rel = getWasmRelocation(Ref);
773 StringRef Res = "Unknown";
774
775 #define WASM_RELOC(name, value) \
776 case wasm::name: \
777 Res = #name; \
778 break;
779
780 switch (Rel.Type) {
781 #include "llvm/Support/WasmRelocs/WebAssembly.def"
782 }
783
784 #undef WASM_RELOC
785
786 Result.append(Res.begin(), Res.end());
292787 }
293788
294789 section_iterator WasmObjectFile::section_begin() const {
315810
316811 bool WasmObjectFile::isRelocatableObject() const { return false; }
317812
318 const wasm::WasmSection *
813 const WasmSection &WasmObjectFile::getWasmSection(DataRefImpl Ref) const {
814 assert(Ref.d.a >= 0 && Ref.d.a < Sections.size());
815 return Sections[Ref.d.a];
816 }
817
818 const WasmSection &
319819 WasmObjectFile::getWasmSection(const SectionRef &Section) const {
320 return &Sections[Section.getRawDataRefImpl().d.a];
321 }
820 return getWasmSection(Section.getRawDataRefImpl());
821 }
822
823 const wasm::WasmRelocation &
824 WasmObjectFile::getWasmRelocation(const RelocationRef &Ref) const {
825 return getWasmRelocation(Ref.getRawDataRefImpl());
826 }
827
828 const wasm::WasmRelocation &
829 WasmObjectFile::getWasmRelocation(DataRefImpl Ref) const {
830 assert(Ref.d.a >= 0 && Ref.d.a < Sections.size());
831 const WasmSection& Sec = Sections[Ref.d.a];
832 assert(Ref.d.b >= 0 && Ref.d.b < Sec.Relocations.size());
833 return Sec.Relocations[Ref.d.b];
834 }
55 ELFYAML.cpp
66 MachOYAML.cpp
77 ObjectYAML.cpp
8 WasmYAML.cpp
89 YAML.cpp
910 )
4242 ObjectFile.FatMachO.reset(new MachOYAML::UniversalBinary());
4343 MappingTraits::mapping(IO,
4444 *ObjectFile.FatMachO);
45 } else if (IO.mapTag("!WASM")) {
46 ObjectFile.Wasm.reset(new WasmYAML::Object());
47 MappingTraits::mapping(IO, *ObjectFile.Wasm);
4548 } else {
4649 Input &In = (Input &)IO;
4750 std::string Tag = In.getCurrentNode()->getRawTag();
0 //===- WasmYAML.cpp - Wasm YAMLIO implementation --------------------------===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file defines classes for handling the YAML representation of wasm.
10 //
11 //===----------------------------------------------------------------------===//
12
13 #include "llvm/ObjectYAML/WasmYAML.h"
14 #include "llvm/Object/Wasm.h"
15 #include "llvm/Support/Casting.h"
16 #include "llvm/Support/MipsABIFlags.h"
17
18 namespace llvm {
19 namespace yaml {
20
21 void MappingTraits::mapping(
22 IO &IO, WasmYAML::FileHeader &FileHdr) {
23 IO.mapRequired("Version", FileHdr.Version);
24 }
25
26 void MappingTraits::mapping(IO &IO,
27 WasmYAML::Object &Object) {
28 IO.setContext(&Object);
29 IO.mapTag("!WASM", true);
30 IO.mapRequired("FileHeader", Object.Header);
31 IO.mapOptional("Sections", Object.Sections);
32 IO.setContext(nullptr);
33 }
34
35 static void commonSectionMapping(IO &IO, WasmYAML::Section &Section) {
36 IO.mapRequired("Type", Section.Type);
37 IO.mapOptional("Relocations", Section.Relocations);
38 }
39
40 static void sectionMapping(IO &IO, WasmYAML::CustomSection &Section) {
41 commonSectionMapping(IO, Section);
42 IO.mapRequired("Name", Section.Name);
43 IO.mapRequired("Payload", Section.Payload);
44 }
45
46 static void sectionMapping(IO &IO, WasmYAML::TypeSection &Section) {
47 commonSectionMapping(IO, Section);
48 IO.mapOptional("Signatures", Section.Signatures);
49 }
50
51 static void sectionMapping(IO &IO, WasmYAML::ImportSection &Section) {
52 commonSectionMapping(IO, Section);
53 IO.mapOptional("Imports", Section.Imports);
54 }
55
56 static void sectionMapping(IO &IO, WasmYAML::FunctionSection &Section) {
57 commonSectionMapping(IO, Section);
58 IO.mapOptional("FunctionTypes", Section.FunctionTypes);
59 }
60
61 static void sectionMapping(IO &IO, WasmYAML::TableSection &Section) {
62 commonSectionMapping(IO, Section);
63 IO.mapOptional("Tables", Section.Tables);
64 }
65
66 static void sectionMapping(IO &IO, WasmYAML::MemorySection &Section) {
67 commonSectionMapping(IO, Section);
68 IO.mapOptional("Memories", Section.Memories);
69 }
70
71 static void sectionMapping(IO &IO, WasmYAML::GlobalSection &Section) {
72 commonSectionMapping(IO, Section);
73 IO.mapOptional("Globals", Section.Globals);
74 }
75
76 static void sectionMapping(IO &IO, WasmYAML::ExportSection &Section) {
77 commonSectionMapping(IO, Section);
78 IO.mapOptional("Exports", Section.Exports);
79 }
80
81 static void sectionMapping(IO &IO, WasmYAML::StartSection &Section) {
82 commonSectionMapping(IO, Section);
83 IO.mapOptional("StartFunction", Section.StartFunction);
84 }
85
86 static void sectionMapping(IO &IO, WasmYAML::ElemSection &Section) {
87 commonSectionMapping(IO, Section);
88 IO.mapOptional("Segments", Section.Segments);
89 }
90
91 static void sectionMapping(IO &IO, WasmYAML::CodeSection &Section) {
92 commonSectionMapping(IO, Section);
93 IO.mapRequired("Functions", Section.Functions);
94 }
95
96 static void sectionMapping(IO &IO, WasmYAML::DataSection &Section) {
97 commonSectionMapping(IO, Section);
98 IO.mapRequired("Segments", Section.Segments);
99 }
100
101 void MappingTraits>::mapping(
102 IO &IO, std::unique_ptr &Section) {
103 WasmYAML::SectionType SectionType;
104 if (IO.outputting())
105 SectionType = Section->Type;
106 else
107 IO.mapRequired("Type", SectionType);
108
109 switch (SectionType) {
110 case wasm::WASM_SEC_CUSTOM:
111 if (!IO.outputting())
112 Section.reset(new WasmYAML::CustomSection());
113 sectionMapping(IO, *cast(Section.get()));
114 break;
115 case wasm::WASM_SEC_TYPE:
116 if (!IO.outputting())
117 Section.reset(new WasmYAML::TypeSection());
118 sectionMapping(IO, *cast(Section.get()));
119 break;
120 case wasm::WASM_SEC_IMPORT:
121 if (!IO.outputting())
122 Section.reset(new WasmYAML::ImportSection());
123 sectionMapping(IO, *cast(Section.get()));
124 break;
125 case wasm::WASM_SEC_FUNCTION:
126 if (!IO.outputting())
127 Section.reset(new WasmYAML::FunctionSection());
128 sectionMapping(IO, *cast(Section.get()));
129 break;
130 case wasm::WASM_SEC_TABLE:
131 if (!IO.outputting())
132 Section.reset(new WasmYAML::TableSection());
133 sectionMapping(IO, *cast(Section.get()));
134 break;
135 case wasm::WASM_SEC_MEMORY:
136 if (!IO.outputting())
137 Section.reset(new WasmYAML::MemorySection());
138 sectionMapping(IO, *cast(Section.get()));
139 break;
140 case wasm::WASM_SEC_GLOBAL:
141 if (!IO.outputting())
142 Section.reset(new WasmYAML::GlobalSection());
143 sectionMapping(IO, *cast(Section.get()));
144 break;
145 case wasm::WASM_SEC_EXPORT:
146 if (!IO.outputting())
147 Section.reset(new WasmYAML::ExportSection());
148 sectionMapping(IO, *cast(Section.get()));
149 break;
150 case wasm::WASM_SEC_START:
151 if (!IO.outputting())
152 Section.reset(new WasmYAML::StartSection());
153 sectionMapping(IO, *cast(Section.get()));
154 break;
155 case wasm::WASM_SEC_ELEM:
156 if (!IO.outputting())
157 Section.reset(new WasmYAML::ElemSection());
158 sectionMapping(IO, *cast(Section.get()));
159 break;
160 case wasm::WASM_SEC_CODE:
161 if (!IO.outputting())
162 Section.reset(new WasmYAML::CodeSection());
163 sectionMapping(IO, *cast(Section.get()));
164 break;
165 case wasm::WASM_SEC_DATA:
166 if (!IO.outputting())
167 Section.reset(new WasmYAML::DataSection());
168 sectionMapping(IO, *cast(Section.get()));
169 break;
170 default:
171 llvm_unreachable("Unknown section type");
172 }
173 }
174
175 void ScalarEnumerationTraits::enumeration(
176 IO &IO, WasmYAML::SectionType &Type) {
177 #define ECase(X) IO.enumCase(Type, #X, wasm::WASM_SEC_##X);
178 ECase(CUSTOM);
179 ECase(TYPE);
180 ECase(IMPORT);
181 ECase(FUNCTION);
182 ECase(TABLE);
183 ECase(MEMORY);
184 ECase(GLOBAL);
185 ECase(EXPORT);
186 ECase(START);
187 ECase(ELEM);
188 ECase(CODE);
189 ECase(DATA);
190 #undef ECase
191 }
192
193 void MappingTraits::mapping(
194 IO &IO, WasmYAML::Signature &Signature) {
195 IO.mapOptional("Index", Signature.Index);
196 IO.mapRequired("ReturnType", Signature.ReturnType);
197 IO.mapRequired("ParamTypes", Signature.ParamTypes);
198 }
199
200 void MappingTraits::mapping(IO &IO, WasmYAML::Table &Table) {
201 IO.mapRequired("ElemType", Table.ElemType);
202 IO.mapRequired("Limits", Table.TableLimits);
203 }
204
205 void MappingTraits::mapping(IO &IO,
206 WasmYAML::Function &Function) {
207 IO.mapRequired("Locals", Function.Locals);
208 IO.mapRequired("Body", Function.Body);
209 }
210
211 void MappingTraits::mapping(
212 IO &IO, WasmYAML::Relocation &Relocation) {
213 IO.mapRequired("Type", Relocation.Type);
214 IO.mapRequired("Index", Relocation.Index);
215 IO.mapRequired("Offset", Relocation.Offset);
216 IO.mapRequired("Addend", Relocation.Addend);
217 }
218
219 void MappingTraits::mapping(
220 IO &IO, WasmYAML::LocalDecl &LocalDecl) {
221 IO.mapRequired("Type", LocalDecl.Type);
222 IO.mapRequired("Count", LocalDecl.Count);
223 }
224
225 void MappingTraits::mapping(IO &IO,
226 WasmYAML::Limits &Limits) {
227 if (!IO.outputting() || Limits.Flags)
228 IO.mapOptional("Flags", Limits.Flags);
229 IO.mapRequired("Initial", Limits.Initial);
230 if (!IO.outputting() || Limits.Flags & wasm::WASM_LIMITS_FLAG_HAS_MAX)
231 IO.mapOptional("Maximum", Limits.Maximum);
232 }
233
234 void MappingTraits::mapping(
235 IO &IO, WasmYAML::ElemSegment &Segment) {
236 IO.mapRequired("Offset", Segment.Offset);
237 IO.mapRequired("Functions", Segment.Functions);
238 }
239
240 void MappingTraits::mapping(IO &IO,
241 WasmYAML::Import &Import) {
242 IO.mapRequired("Module", Import.Module);
243 IO.mapRequired("Field", Import.Field);
244 IO.mapRequired("Kind", Import.Kind);
245 if (Import.Kind == wasm::WASM_EXTERNAL_FUNCTION) {
246 IO.mapRequired("SigIndex", Import.SigIndex);
247 } else if (Import.Kind == wasm::WASM_EXTERNAL_GLOBAL) {
248 IO.mapRequired("GlobalType", Import.GlobalType);
249 IO.mapRequired("GlobalMutable", Import.GlobalMutable);
250 } else {
251 llvm_unreachable("unhandled import type");
252 }
253 }
254
255 void MappingTraits::mapping(IO &IO,
256 WasmYAML::Export &Export) {
257 IO.mapRequired("Name", Export.Name);
258 IO.mapRequired("Kind", Export.Kind);
259 IO.mapRequired("Index", Export.Index);
260 }
261
262 void MappingTraits::mapping(IO &IO,
263 WasmYAML::Global &Global) {
264 IO.mapRequired("Type", Global.Type);
265 IO.mapRequired("Mutable", Global.Mutable);
266 IO.mapRequired("InitExpr", Global.InitExpr);
267 }
268
269 void MappingTraits::mapping(IO &IO,
270 wasm::WasmInitExpr &Expr) {
271 WasmYAML::Opcode Op = Expr.Opcode;
272 IO.mapRequired("Opcode", Op);
273 Expr.Opcode = Op;
274 switch (Expr.Opcode) {
275 case wasm::WASM_OPCODE_I32_CONST:
276 IO.mapRequired("Value", Expr.Value.Int32);
277 break;
278 case wasm::WASM_OPCODE_I64_CONST:
279 IO.mapRequired("Value", Expr.Value.Int64);
280 break;
281 case wasm::WASM_OPCODE_F32_CONST:
282 IO.mapRequired("Value", Expr.Value.Float32);
283 break;
284 case wasm::WASM_OPCODE_F64_CONST:
285 IO.mapRequired("Value", Expr.Value.Float64);
286 break;
287 }
288 }
289
290 void MappingTraits::mapping(
291 IO &IO, WasmYAML::DataSegment &Segment) {
292 IO.mapRequired("Index", Segment.Index);
293 IO.mapRequired("Offset", Segment.Offset);
294 IO.mapRequired("Content", Segment.Content);
295 }
296
297 void ScalarEnumerationTraits::enumeration(
298 IO &IO, WasmYAML::ValueType &Type) {
299 #define ECase(X) IO.enumCase(Type, #X, wasm::WASM_TYPE_##X);
300 ECase(I32);
301 ECase(I64);
302 ECase(F32);
303 ECase(F64);
304 ECase(ANYFUNC);
305 ECase(FUNC);
306 ECase(NORESULT);
307 #undef ECase
308 }
309
310 void ScalarEnumerationTraits::enumeration(
311 IO &IO, WasmYAML::ExportKind &Kind) {
312 #define ECase(X) IO.enumCase(Kind, #X, wasm::WASM_EXTERNAL_##X);
313 ECase(FUNCTION);
314 ECase(TABLE);
315 ECase(MEMORY);
316 ECase(GLOBAL);
317 #undef ECase
318 }
319
320 void ScalarEnumerationTraits::enumeration(
321 IO &IO, WasmYAML::Opcode &Code) {
322 #define ECase(X) IO.enumCase(Code, #X, wasm::WASM_OPCODE_##X);
323 ECase(END);
324 ECase(I32_CONST);
325 ECase(I64_CONST);
326 ECase(F64_CONST);
327 ECase(F32_CONST);
328 ECase(GET_GLOBAL);
329 #undef ECase
330 }
331
332 void ScalarEnumerationTraits::enumeration(
333 IO &IO, WasmYAML::TableType &Type) {
334 #define ECase(X) IO.enumCase(Type, #X, wasm::WASM_TYPE_##X);
335 ECase(ANYFUNC);
336 #undef ECase
337 }
338
339 void ScalarEnumerationTraits::enumeration(
340 IO &IO, WasmYAML::RelocType &Type) {
341 #define WASM_RELOC(name, value) IO.enumCase(Type, #name, wasm::name);
342 #include "llvm/Support/WasmRelocs/WebAssembly.def"
343 #undef WASM_RELOC
344 }
345
346 } // end namespace yaml
347 } // end namespace llvm
0 # RUN: yaml2obj %s | obj2yaml | FileCheck %s
1 --- !WASM
2 FileHeader:
3 Version: 0x00000001
4 Sections:
5 - Type: TYPE
6 Signatures:
7 - ReturnType: F32
8 ParamTypes:
9 - I32
10 - ReturnType: NORESULT
11 ParamTypes:
12 - I32
13 - I64
14 - Type: FUNCTION
15 FunctionTypes:
16 - 0
17 - 1
18 - Type: CODE
19 Relocations:
20 - Type: R_WEBASSEMBLY_TABLE_INDEX_SLEB
21 Index: 0
22 Offset: 0x00000006
23 Addend: 0x00000000
24 - Type: R_WEBASSEMBLY_FUNCTION_INDEX_LEB
25 Index: 1
26 Offset: 0x00000025
27 Addend: 0x00000000
28 Functions:
29 - Locals:
30 - Type: I32
31 Count: 3
32 Body: 418080808000210020002101200111808080800000210220020F0B
33 - Locals:
34 - Type: I32
35 Count: 1
36 Body: 108180808000210020000F0B
37 ...
38 # CHECK: --- !WASM
39 # CHECK: FileHeader:
40 # CHECK: Version: 0x00000001
41 # CHECK: Sections:
42 # CHECK: - Type: TYPE
43 # CHECK: Signatures:
44 # CHECK: - Index: 0
45 # CHECK: ReturnType: F32
46 # CHECK: ParamTypes:
47 # CHECK: - I32
48 # CHECK: - Index: 1
49 # CHECK: ReturnType: NORESULT
50 # CHECK: ParamTypes:
51 # CHECK: - I32
52 # CHECK: - I64
53 # CHECK: - Type: CODE
54 # CHECK: Relocations:
55 # CHECK: - Type: R_WEBASSEMBLY_TABLE_INDEX_SLEB
56 # CHECK: Index: 0
57 # CHECK: Offset: 0x00000006
58 # CHECK: Addend: 0x00000000
59 # CHECK: - Type: R_WEBASSEMBLY_FUNCTION_INDEX_LEB
60 # CHECK: Index: 1
61 # CHECK: Offset: 0x00000025
62 # CHECK: Addend: 0x00000000
63 # CHECK: Functions:
64 # CHECK: - Locals:
65 # CHECK: - Type: I32
66 # CHECK: Count: 3
67 # CHECK: Body: 418080808000210020002101200111808080800000210220020F0B
68 # CHECK: - Locals:
69 # CHECK: - Type: I32
70 # CHECK: Count: 1
71 # CHECK: Body: 108180808000210020000F0B
0 # RUN: yaml2obj %s | obj2yaml | FileCheck %s
1 --- !WASM
2 FileHeader:
3 Version: 0x00000001
4 Sections:
5 - Type: CUSTOM
6 Name: foo
7 Payload: 03666F6F0401020304
8 ...
9 # CHECK: --- !WASM
10 # CHECK: FileHeader:
11 # CHECK: Version: 0x00000001
12 # CHECK: Sections:
13 # CHECK: - Type: CUSTOM
14 # CHECK: Name: foo
15 # CHECK: Payload: 03666F6F0401020304
16 # CHECK: ...
0 # RUN: yaml2obj %s | obj2yaml | FileCheck %s
1 --- !WASM
2 FileHeader:
3 Version: 0x00000001
4 Sections:
5 - Type: MEMORY
6 Memories:
7 - Initial: 0x00000003
8 - Type: DATA
9 Segments:
10 - Index: 0
11 Offset:
12 Opcode: I32_CONST
13 Value: 4
14 Content: '10001000'
15 ...
16 # CHECK: --- !WASM
17 # CHECK: FileHeader:
18 # CHECK: Version: 0x00000001
19 # CHECK: Sections:
20 # CHECK: - Type: DATA
21 # CHECK: Segments:
22 # CHECK: - Index: 0
23 # CHECK: Offset:
24 # CHECK: Opcode: I32_CONST
25 # CHECK: Value: 4
26 # CHECK: Content: '10001000'
27 # CHECK: ...
0 # RUN: yaml2obj %s | obj2yaml | FileCheck %s
1 --- !WASM
2 FileHeader:
3 Version: 0x00000001
4 Sections:
5 - Type: TABLE
6 Tables:
7 - ElemType: ANYFUNC
8 Limits:
9 Flags: 0x00000001
10 Initial: 0x00000010
11 Maximum: 0x00000011
12 - Type: ELEM
13 Segments:
14 - Offset:
15 Opcode: I32_CONST
16 Value: 3
17 Functions:
18 - 1
19 - Offset:
20 Opcode: I32_CONST
21 Value: 5
22 Functions:
23 - 4
24 ...
25 # CHECK: --- !WASM
26 # CHECK: FileHeader:
27 # CHECK: Version: 0x00000001
28 # CHECK: Sections:
29 # CHECK: - Type: ELEM
30 # CHECK: Segments:
31 # CHECK: - Offset:
32 # CHECK: Opcode: I32_CONST
33 # CHECK: Value: 3
34 # CHECK: Functions:
35 # CHECK: - 1
36 # CHECK: - Offset:
37 # CHECK: Opcode: I32_CONST
38 # CHECK: Value: 5
39 # CHECK: Functions:
40 # CHECK: - 4
41 # CHECK: ...
0 # RUN: yaml2obj %s | obj2yaml | FileCheck %s
1 --- !WASM
2 FileHeader:
3 Version: 0x00000001
4 Sections:
5 - Type: EXPORT
6 Exports:
7 - Name: foo
8 Kind: FUNCTION
9 Index: 0
10 - Name: bar
11 Kind: FUNCTION
12 Index: 1
13 ...
14 # CHECK: --- !WASM
15 # CHECK: FileHeader:
16 # CHECK: Version: 0x00000001
17 # CHECK: Sections:
18 # CHECK: - Type: EXPORT
19 # CHECK: Exports:
20 # CHECK: - Name: foo
21 # CHECK: Kind: FUNCTION
22 # CHECK: Index: 0
23 # CHECK: - Name: bar
24 # CHECK: Kind: FUNCTION
25 # CHECK: Index: 1
26 # CHECK: ...
0 # RUN: yaml2obj %s | obj2yaml | FileCheck %s
1 --- !WASM
2 FileHeader:
3 Version: 0x00000001
4 Sections:
5 - Type: FUNCTION
6 FunctionTypes:
7 - 1
8 - 0
9 ...
10 # CHECK: --- !WASM
11 # CHECK: FileHeader:
12 # CHECK: Version: 0x00000001
13 # CHECK: Sections:
14 # CHECK: - Type: FUNCTION
15 # CHECK: FunctionTypes:
16 # CHECK: - 1
17 # CHECK: - 0
18 # CHECK: ...
0 # RUN: yaml2obj %s | obj2yaml | FileCheck %s
1 --- !WASM
2 FileHeader:
3 Version: 0x00000001
4 Sections:
5 - Type: GLOBAL
6 Globals:
7 - Type: I32
8 Mutable: false
9 InitExpr:
10 Opcode: I64_CONST
11 Value: -5
12 ...
13 # CHECK: --- !WASM
14 # CHECK: FileHeader:
15 # CHECK: Version: 0x00000001
16 # CHECK: Sections:
17 # CHECK: - Type: GLOBAL
18 # CHECK: Globals:
19 # CHECK: - Type: I32
20 # CHECK: Mutable: false
21 # CHECK: InitExpr:
22 # CHECK: Opcode: I64_CONST
23 # CHECK: Value: -5
24 # CHECK: ...
0 # RUN: yaml2obj %s | obj2yaml | FileCheck %s
1 --- !WASM
2 FileHeader:
3 Version: 0x00000001
4 ...
5 # CHECK: --- !WASM
6 # CHECK: FileHeader:
7 # CHECK: Version: 0x00000001
8 # CHECK: ...
0 # RUN: yaml2obj %s | not obj2yaml 2>&1 | FileCheck %s
1
2 --- !WASM
3 FileHeader:
4 Version: 0x00000002
5 ...
6
7 # CHECK: Error: 'Invalid data was encountered while parsing the file'
0 # RUN: yaml2obj %s | obj2yaml | FileCheck %s
1 --- !WASM
2 FileHeader:
3 Version: 0x00000001
4 Sections:
5 - Type: TYPE
6 Signatures:
7 - ReturnType: I32
8 ParamTypes:
9 - I32
10 - Type: IMPORT
11 Imports:
12 - Module: foo
13 Field: bar
14 Kind: FUNCTION
15 SigIndex: 0
16 - Module: fiz
17 Field: baz
18 Kind: GLOBAL
19 GlobalType: I32
20 GlobalMutable: false
21 - Type: FUNCTION
22 FunctionTypes:
23 - 0
24 ...
25 # CHECK: --- !WASM
26 # CHECK: FileHeader:
27 # CHECK: Version: 0x00000001
28 # CHECK: Sections:
29 # CHECK: - Type: IMPORT
30 # CHECK: Imports:
31 # CHECK: - Module: foo
32 # CHECK: Field: bar
33 # CHECK: Kind: FUNCTION
34 # CHECK: SigIndex: 0
35 # CHECK: - Module: fiz
36 # CHECK: Field: baz
37 # CHECK: Kind: GLOBAL
38 # CHECK: GlobalType: I32
39 # CHECK: GlobalMutable: false
40 # CHECK: ...
0 # RUN: yaml2obj %s | obj2yaml | FileCheck %s
1 --- !WASM
2 FileHeader:
3 Version: 0x00000001
4 Sections:
5 - Type: MEMORY
6 Memories:
7 - Flags: 0x00000001
8 Initial: 0x00000002
9 Maximum: 0x000000FF
10 - Initial: 0x00000003
11 ...
12 # CHECK: --- !WASM
13 # CHECK: FileHeader:
14 # CHECK: Version: 0x00000001
15 # CHECK: Sections:
16 # CHECK: - Type: MEMORY
17 # CHECK: Memories:
18 # CHECK: - Flags: 0x00000001
19 # CHECK: Initial: 0x00000002
20 # CHECK: Maximum: 0x000000FF
21 # CHECK: - Initial: 0x00000003
22 # CHECK: ...
0 # RUN: yaml2obj %s | obj2yaml | FileCheck %s
1 --- !WASM
2 FileHeader:
3 Version: 0x00000001
4 Sections:
5 - Type: START
6 StartFunction: 1
7 ...
8 # CHECK: --- !WASM
9 # CHECK: FileHeader:
10 # CHECK: Version: 0x00000001
11 # CHECK: Sections:
12 # CHECK: - Type: START
13 # CHECK: StartFunction: 1
14 # CHECK: ...
0 # RUN: yaml2obj %s | obj2yaml | FileCheck %s
1 --- !WASM
2 FileHeader:
3 Version: 0x00000001
4 Sections:
5 - Type: TABLE
6 Tables:
7 - ElemType: ANYFUNC
8 Limits:
9 Flags: 0x00000001
10 Initial: 0x00000010
11 Maximum: 0x00000011
12 ...
13 # CHECK: --- !WASM
14 # CHECK: FileHeader:
15 # CHECK: Version: 0x00000001
16 # CHECK: Sections:
17 # CHECK: - Type: TABLE
18 # CHECK: Tables:
19 # CHECK: - ElemType: ANYFUNC
20 # CHECK: Limits:
21 # CHECK: Flags: 0x00000001
22 # CHECK: Initial: 0x00000010
23 # CHECK: Maximum: 0x00000011
24 # CHECK: ...
0 # RUN: yaml2obj %s | obj2yaml | FileCheck %s
1 --- !WASM
2 FileHeader:
3 Version: 0x00000001
4 Sections:
5 - Type: TYPE
6 Signatures:
7 - ReturnType: I32
8 ParamTypes:
9 - F32
10 - F32
11 - ReturnType: I64
12 ParamTypes:
13 - F64
14 - F64
15 ...
16 # CHECK: --- !WASM
17 # CHECK: FileHeader:
18 # CHECK: Version: 0x00000001
19 # CHECK: Sections:
20 # CHECK: - Type: TYPE
21 # CHECK: Signatures:
22 # CHECK: - Index: 0
23 # CHECK: ReturnType: I32
24 # CHECK: ParamTypes:
25 # CHECK: - F32
26 # CHECK: - F32
27 # CHECK: - Index: 1
28 # CHECK: ReturnType: I64
29 # CHECK: ParamTypes:
30 # CHECK: - F64
31 # CHECK: - F64
32 # CHECK: ...
88 # CHECK: 4 EXPORT 0000000e 0000000000000000
99 # CHECK: 5 ELEM 00000007 0000000000000000
1010 # CHECK: 6 CODE 0000002a 0000000000000000 TEXT
11 # CHECK: 7 name 0000002c 0000000000000000
11 # CHECK: 7 name 0000003c 0000000000000000
1212
1313 # RUN: llvm-objdump -p %p/Inputs/test.wasm | FileCheck %s -check-prefix CHECK-HEADER
1414
530530 WASM-NEXT: }
531531 WASM-NEXT: Section {
532532 WASM-NEXT: Type: CUSTOM (0x0)
533 WASM-NEXT: Size: 44
533 WASM-NEXT: Size: 60
534534 WASM-NEXT: Offset: 119
535535 WASM-NEXT: Name: name
536536 WASM-NEXT: }
5454 void printSections() override {
5555 ListScope Group(W, "Sections");
5656 for (const SectionRef &Section : Obj->sections()) {
57 const wasm::WasmSection *WasmSec = Obj->getWasmSection(Section);
57 const WasmSection &WasmSec = Obj->getWasmSection(Section);
5858 DictScope SectionD(W, "Section");
59 const char *Type = wasmSectionTypeToString(WasmSec->Type);
60 W.printHex("Type", Type, WasmSec->Type);
61 W.printNumber("Size", (uint64_t)WasmSec->Content.size());
62 W.printNumber("Offset", WasmSec->Offset);
63 if (WasmSec->Type == wasm::WASM_SEC_CUSTOM) {
64 W.printString("Name", WasmSec->Name);
59 const char *Type = wasmSectionTypeToString(WasmSec.Type);
60 W.printHex("Type", Type, WasmSec.Type);
61 W.printNumber("Size", (uint64_t)WasmSec.Content.size());
62 W.printNumber("Offset", WasmSec.Offset);
63 if (WasmSec.Type == wasm::WASM_SEC_CUSTOM) {
64 W.printString("Name", WasmSec.Name);
6565 }
6666 }
6767 }
1010 dwarf2yaml.cpp
1111 elf2yaml.cpp
1212 macho2yaml.cpp
13 wasm2yaml.cpp
1314 Error.cpp
1415 )
2323 return coff2yaml(outs(), cast(Obj));
2424 if (Obj.isELF())
2525 return elf2yaml(outs(), Obj);
26 if (Obj.isWasm())
27 return wasm2yaml(outs(), cast(Obj));
2628
2729 return obj2yaml_error::unsupported_obj_file_format;
2830 }
1313 #define LLVM_TOOLS_OBJ2YAML_OBJ2YAML_H
1414
1515 #include "llvm/Object/COFF.h"
16 #include "llvm/Object/Wasm.h"
1617 #include "llvm/Support/raw_ostream.h"
1718 #include
1819
2223 const llvm::object::ObjectFile &Obj);
2324 std::error_code macho2yaml(llvm::raw_ostream &Out,
2425 const llvm::object::Binary &Obj);
26 std::error_code wasm2yaml(llvm::raw_ostream &Out,
27 const llvm::object::WasmObjectFile &Obj);
2528
2629 // Forward decls for dwarf2yaml
2730 namespace llvm {
0 //===------ utils/wasm2yaml.cpp - obj2yaml conversion tool ------*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8
9 #include "obj2yaml.h"
10 #include "llvm/Object/COFF.h"
11 #include "llvm/ObjectYAML/WasmYAML.h"
12 #include "llvm/Support/ErrorHandling.h"
13 #include "llvm/Support/YAMLTraits.h"
14
15 using namespace llvm;
16
17 namespace {
18
19 class WasmDumper {
20 const object::WasmObjectFile &Obj;
21
22 public:
23 WasmDumper(const object::WasmObjectFile &O) : Obj(O) {}
24 ErrorOr dump();
25 };
26
27 ErrorOr WasmDumper::dump() {
28 auto Y = make_unique();
29
30 // Dump header
31 Y->Header.Version = Obj.getHeader().Version;
32
33 // Dump sections
34 for (const auto &Sec : Obj.sections()) {
35 const object::WasmSection &WasmSec = Obj.getWasmSection(Sec);
36 std::unique_ptr S;
37 switch (WasmSec.Type) {
38 case wasm::WASM_SEC_CUSTOM: {
39 if (WasmSec.Name.startswith("reloc.")) {
40 // Relocations are attached the sections they apply to rather than
41 // being represented as a custom section in the YAML output.
42 continue;
43 }
44 auto CustomSec = make_unique();
45 CustomSec->Name = WasmSec.Name;
46 CustomSec->Payload = yaml::BinaryRef(WasmSec.Content);
47 S = std::move(CustomSec);
48 break;
49 }
50 case wasm::WASM_SEC_TYPE: {
51 auto TypeSec = make_unique();
52 uint32_t Index = 0;
53 for (const auto &FunctionSig : Obj.types()) {
54 WasmYAML::Signature Sig;
55 Sig.Index = Index++;
56 Sig.ReturnType = FunctionSig.ReturnType;
57 for (const auto &ParamType : FunctionSig.ParamTypes)
58 Sig.ParamTypes.push_back(ParamType);
59 TypeSec->Signatures.push_back(Sig);
60 }
61 S = std::move(TypeSec);
62 break;
63 }
64 case wasm::WASM_SEC_IMPORT: {
65 auto ImportSec = make_unique();
66 for (auto &Import : Obj.imports()) {
67 WasmYAML::Import Ex;
68 Ex.Module = Import.Module;
69 Ex.Field = Import.Field;
70 Ex.Kind = Import.Kind;
71 if (Ex.Kind == wasm::WASM_EXTERNAL_FUNCTION) {
72 Ex.SigIndex = Import.SigIndex;
73 } else if (Ex.Kind == wasm::WASM_EXTERNAL_GLOBAL) {
74 Ex.GlobalType = Import.GlobalType;
75 Ex.GlobalMutable = Import.GlobalMutable;
76 }
77 ImportSec->Imports.push_back(Ex);
78 }
79 S = std::move(ImportSec);
80 break;
81 }
82 case wasm::WASM_SEC_FUNCTION: {
83 auto FuncSec = make_unique();
84 for (const auto &Func : Obj.functionTypes()) {
85 FuncSec->FunctionTypes.push_back(Func);
86 }
87 S = std::move(FuncSec);
88 break;
89 }
90 case wasm::WASM_SEC_TABLE: {
91 auto TableSec = make_unique();
92 for (auto &Table : Obj.tables()) {
93 WasmYAML::Table T;
94 T.ElemType = Table.ElemType;
95 T.TableLimits.Flags = Table.Limits.Flags;
96 T.TableLimits.Initial = Table.Limits.Initial;
97 T.TableLimits.Maximum = Table.Limits.Maximum;
98 TableSec->Tables.push_back(T);
99 }
100 S = std::move(TableSec);
101 break;
102 }
103 case wasm::WASM_SEC_MEMORY: {
104 auto MemorySec = make_unique();
105 for (auto &Memory : Obj.memories()) {
106 WasmYAML::Limits L;
107 L.Flags = Memory.Flags;
108 L.Initial = Memory.Initial;
109 L.Maximum = Memory.Maximum;
110 MemorySec->Memories.push_back(L);
111 }
112 S = std::move(MemorySec);
113 break;
114 }
115 case wasm::WASM_SEC_GLOBAL: {
116 auto GlobalSec = make_unique();
117 for (auto &Global : Obj.globals()) {
118 WasmYAML::Global G;
119 G.Type = Global.Type;
120 G.Mutable = Global.Mutable;
121 G.InitExpr = Global.InitExpr;
122 GlobalSec->Globals.push_back(G);
123 }
124 S = std::move(GlobalSec);
125 break;
126 }
127 case wasm::WASM_SEC_START: {
128 auto StartSec = make_unique();
129 StartSec->StartFunction = Obj.startFunction();
130 S = std::move(StartSec);
131 break;
132 }
133 case wasm::WASM_SEC_EXPORT: {
134 auto ExportSec = make_unique();
135 for (auto &Export : Obj.exports()) {
136 WasmYAML::Export Ex;
137 Ex.Name = Export.Name;
138 Ex.Kind = Export.Kind;
139 Ex.Index = Export.Index;
140 ExportSec->Exports.push_back(Ex);
141 }
142 S = std::move(ExportSec);
143 break;
144 }
145 case wasm::WASM_SEC_ELEM: {
146 auto ElemSec = make_unique();
147 for (auto &Segment : Obj.elements()) {
148 WasmYAML::ElemSegment Seg;
149 Seg.TableIndex = Segment.TableIndex;
150 Seg.Offset = Segment.Offset;
151 for (auto &Func : Segment.Functions) {
152 Seg.Functions.push_back(Func);
153 }
154 ElemSec->Segments.push_back(Seg);
155 }
156 S = std::move(ElemSec);
157 break;
158 }
159 case wasm::WASM_SEC_CODE: {
160 auto CodeSec = make_unique();
161 for (auto &Func : Obj.functions()) {
162 WasmYAML::Function Function;
163 for (auto &Local : Func.Locals) {
164 WasmYAML::LocalDecl LocalDecl;
165 LocalDecl.Type = Local.Type;
166 LocalDecl.Count = Local.Count;
167 Function.Locals.push_back(LocalDecl);
168 }
169 Function.Body = yaml::BinaryRef(Func.Body);
170 CodeSec->Functions.push_back(Function);
171 }
172 S = std::move(CodeSec);
173 break;
174 }
175 case wasm::WASM_SEC_DATA: {
176 auto DataSec = make_unique();
177 for (auto &Segment : Obj.dataSegments()) {
178 WasmYAML::DataSegment Seg;
179 Seg.Index = Segment.Index;
180 Seg.Offset = Segment.Offset;
181 Seg.Content = yaml::BinaryRef(Segment.Content);
182 DataSec->Segments.push_back(Seg);
183 }
184 S = std::move(DataSec);
185 break;
186 }
187 default:
188 llvm_unreachable("Unknown section type");
189 break;
190 }
191 for (const wasm::WasmRelocation &Reloc: WasmSec.Relocations) {
192 WasmYAML::Relocation R;
193 R.Type = Reloc.Type;
194 R.Index = Reloc.Index;
195 R.Offset = Reloc.Offset;
196 R.Addend = Reloc.Addend;
197 S->Relocations.push_back(R);
198 }
199 Y->Sections.push_back(std::move(S));
200 }
201
202 return Y.release();
203 }
204
205 } // namespace
206
207 std::error_code wasm2yaml(raw_ostream &Out, const object::WasmObjectFile &Obj) {
208 WasmDumper Dumper(Obj);
209 ErrorOr YAMLOrErr = Dumper.dump();
210 if (std::error_code EC = YAMLOrErr.getError())
211 return EC;
212
213 std::unique_ptr YAML(YAMLOrErr.get());
214 yaml::Output Yout(Out);
215 Yout << *YAML;
216
217 return std::error_code();
218 }
99 yaml2coff.cpp
1010 yaml2elf.cpp
1111 yaml2macho.cpp
12 yaml2wasm.cpp
1213 )
5656 return yaml2coff(*Doc.Coff, Out);
5757 if (Doc.MachO || Doc.FatMachO)
5858 return yaml2macho(Doc, Out);
59 if (Doc.Wasm)
60 return yaml2wasm(*Doc.Wasm, Out);
5961 errs() << "yaml2obj: Unknown document type!\n";
6062 return 1;
6163 }
2222 struct Object;
2323 }
2424
25 namespace WasmYAML {
26 struct Object;
27 }
28
2529 namespace yaml {
2630 class Input;
2731 struct YamlObjectFile;
3135 int yaml2coff(llvm::COFFYAML::Object &Doc, llvm::raw_ostream &Out);
3236 int yaml2elf(llvm::ELFYAML::Object &Doc, llvm::raw_ostream &Out);
3337 int yaml2macho(llvm::yaml::YamlObjectFile &Doc, llvm::raw_ostream &Out);
38 int yaml2wasm(llvm::WasmYAML::Object &Doc, llvm::raw_ostream &Out);
3439
3540 #endif
0 //===- yaml2wasm - Convert YAML to a Wasm object file --------------------===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 ///
9 /// \file
10 /// \brief The Wasm component of yaml2obj.
11 ///
12 //===----------------------------------------------------------------------===//
13 //
14 #include "yaml2obj.h"
15 #include "llvm/Object/Wasm.h"
16 #include "llvm/ObjectYAML/ObjectYAML.h"
17 #include "llvm/Support/Endian.h"
18 #include "llvm/Support/LEB128.h"
19
20 using namespace llvm;
21
22 /// This parses a yaml stream that represents a Wasm object file.
23 /// See docs/yaml2obj for the yaml scheema.
24 class WasmWriter {
25 public:
26 WasmWriter(WasmYAML::Object &Obj) : Obj(Obj) {}
27 int writeWasm(raw_ostream &OS);
28 int writeRelocSection(raw_ostream &OS, WasmYAML::Section &Sec);
29 int writeSectionContent(raw_ostream &OS, WasmYAML::CustomSection &Section);
30 int writeSectionContent(raw_ostream &OS, WasmYAML::TypeSection &Section);
31 int writeSectionContent(raw_ostream &OS, WasmYAML::ImportSection &Section);
32 int writeSectionContent(raw_ostream &OS, WasmYAML::FunctionSection &Section);
33 int writeSectionContent(raw_ostream &OS, WasmYAML::TableSection &Section);
34 int writeSectionContent(raw_ostream &OS, WasmYAML::MemorySection &Section);
35 int writeSectionContent(raw_ostream &OS, WasmYAML::GlobalSection &Section);
36 int writeSectionContent(raw_ostream &OS, WasmYAML::ExportSection &Section);
37 int writeSectionContent(raw_ostream &OS, WasmYAML::StartSection &Section);
38 int writeSectionContent(raw_ostream &OS, WasmYAML::ElemSection &Section);
39 int writeSectionContent(raw_ostream &OS, WasmYAML::CodeSection &Section);
40 int writeSectionContent(raw_ostream &OS, WasmYAML::DataSection &Section);
41
42 private:
43 WasmYAML::Object &Obj;
44 };
45
46 static int writeUint64(raw_ostream &OS, uint64_t Value) {
47 char Data[sizeof(Value)];
48 support::endian::write64le(Data, Value);
49 OS.write(Data, sizeof(Data));
50 return 0;
51 }
52
53 static int writeUint32(raw_ostream &OS, uint32_t Value) {
54 char Data[sizeof(Value)];
55 support::endian::write32le(Data, Value);
56 OS.write(Data, sizeof(Data));
57 return 0;
58 }
59
60 static int writeUint8(raw_ostream &OS, uint8_t Value) {
61 char Data[sizeof(Value)];
62 memcpy(Data, &Value, sizeof(Data));
63 OS.write(Data, sizeof(Data));
64 return 0;
65 }
66
67 static int writeStringRef(StringRef &Str, raw_ostream &OS) {
68 encodeULEB128(Str.size(), OS);
69 OS << Str;
70 return 0;
71 }
72
73 static int writeLimits(WasmYAML::Limits Lim, raw_ostream &OS) {
74 encodeULEB128(Lim.Flags, OS);
75 encodeULEB128(Lim.Initial, OS);
76 if (Lim.Flags & wasm::WASM_LIMITS_FLAG_HAS_MAX)
77 encodeULEB128(Lim.Maximum, OS);
78 return 0;
79 }
80
81 static int writeInitExpr(wasm::WasmInitExpr InitExpr, raw_ostream &OS) {
82 writeUint8(OS, InitExpr.Opcode);
83 switch (InitExpr.Opcode) {
84 case wasm::WASM_OPCODE_I32_CONST:
85 encodeSLEB128(InitExpr.Value.Int32, OS);
86 break;
87 case wasm::WASM_OPCODE_I64_CONST:
88 encodeSLEB128(InitExpr.Value.Int64, OS);
89 break;
90 case wasm::WASM_OPCODE_F32_CONST:
91 writeUint32(OS, InitExpr.Value.Float32);
92 break;
93 case wasm::WASM_OPCODE_F64_CONST:
94 writeUint64(OS, InitExpr.Value.Float64);
95 break;
96 case wasm::WASM_OPCODE_GET_GLOBAL:
97 encodeULEB128(InitExpr.Value.Global, OS);
98 break;
99 default:
100 errs() << "Unknown opcode in init_expr: " << InitExpr.Opcode;
101 return 1;
102 }
103 writeUint8(OS, wasm::WASM_OPCODE_END);
104 return 0;
105 }
106
107 int WasmWriter::writeSectionContent(raw_ostream &OS,
108 WasmYAML::CustomSection &Section) {
109 // writeStringRef(Section.Name, OS);
110 // encodeULEB128(Section.Payload.binary_size(), OS);
111 Section.Payload.writeAsBinary(OS);
112 return 0;
113 }
114
115 int WasmWriter::writeSectionContent(raw_ostream &OS,
116 WasmYAML::TypeSection &Section) {
117 encodeULEB128(Section.Signatures.size(), OS);
118 for (auto &Sig : Section.Signatures) {
119 encodeSLEB128(Sig.Form, OS);
120 encodeULEB128(Sig.ParamTypes.size(), OS);
121 for (auto ParamType : Sig.ParamTypes)
122 encodeSLEB128(ParamType, OS);
123 if (Sig.ReturnType == wasm::WASM_TYPE_NORESULT) {
124 encodeSLEB128(0, OS);
125 } else {
126 encodeULEB128(1, OS);
127 encodeSLEB128(Sig.ReturnType, OS);
128 }
129 }
130 return 0;
131 }
132
133 int WasmWriter::writeSectionContent(raw_ostream &OS,
134 WasmYAML::ImportSection &Section) {
135 encodeULEB128(Section.Imports.size(), OS);
136 for (auto &Import : Section.Imports) {
137 writeStringRef(Import.Module, OS);
138 writeStringRef(Import.Field, OS);
139 encodeULEB128(Import.Kind, OS);
140 switch (Import.Kind) {
141 case wasm::WASM_EXTERNAL_FUNCTION:
142 encodeULEB128(Import.SigIndex, OS);
143 break;
144 case wasm::WASM_EXTERNAL_GLOBAL:
145 encodeSLEB128(Import.GlobalType, OS);
146 writeUint8(OS, Import.GlobalMutable);
147 break;
148 default:
149 errs() << "Unknown import type: " << Import.Kind;
150 return 1;
151 }
152 }
153 return 0;
154 }
155
156 int WasmWriter::writeSectionContent(raw_ostream &OS,
157 WasmYAML::FunctionSection &Section) {
158 encodeULEB128(Section.FunctionTypes.size(), OS);
159 for (uint32_t FuncType : Section.FunctionTypes) {
160 encodeULEB128(FuncType, OS);
161 }
162 return 0;
163 }
164
165 int WasmWriter::writeSectionContent(raw_ostream &OS,
166 WasmYAML::ExportSection &Section) {
167 encodeULEB128(Section.Exports.size(), OS);
168 for (auto &Export : Section.Exports) {
169 writeStringRef(Export.Name, OS);
170 encodeULEB128(Export.Kind, OS);
171 encodeULEB128(Export.Index, OS);
172 }
173 return 0;
174 }
175
176 int WasmWriter::writeSectionContent(raw_ostream &OS,
177 WasmYAML::StartSection &Section) {
178 encodeULEB128(Section.StartFunction, OS);
179 return 0;
180 }
181
182 int WasmWriter::writeSectionContent(raw_ostream &OS,
183 WasmYAML::TableSection &Section) {
184 encodeULEB128(Section.Tables.size(), OS);
185 for (auto &Table : Section.Tables) {
186 encodeSLEB128(Table.ElemType, OS);
187 writeLimits(Table.TableLimits, OS);
188 }
189 return 0;
190 }
191
192 int WasmWriter::writeSectionContent(raw_ostream &OS,
193 WasmYAML::MemorySection &Section) {
194 encodeULEB128(Section.Memories.size(), OS);
195 for (auto &Mem : Section.Memories) {
196 writeLimits(Mem, OS);
197 }
198 return 0;
199 }
200
201 int WasmWriter::writeSectionContent(raw_ostream &OS,
202 WasmYAML::GlobalSection &Section) {
203 encodeULEB128(Section.Globals.size(), OS);
204 for (auto &Global : Section.Globals) {
205 encodeSLEB128(Global.Type, OS);
206 writeUint8(OS, Global.Mutable);
207 writeInitExpr(Global.InitExpr, OS);
208 }
209 return 0;
210 }
211
212 int WasmWriter::writeSectionContent(raw_ostream &OS,
213 WasmYAML::ElemSection &Section) {
214 encodeULEB128(Section.Segments.size(), OS);
215 for (auto &Segment : Section.Segments) {
216 encodeULEB128(Segment.TableIndex, OS);
217 writeInitExpr(Segment.Offset, OS);
218
219 encodeULEB128(Segment.Functions.size(), OS);
220 for (auto &Function : Segment.Functions) {
221 encodeULEB128(Function, OS);
222 }
223 }
224 return 0;
225 }
226
227 int WasmWriter::writeSectionContent(raw_ostream &OS,
228 WasmYAML::CodeSection &Section) {
229 encodeULEB128(Section.Functions.size(), OS);
230 for (auto &Func : Section.Functions) {
231 std::string OutString;
232 raw_string_ostream StringStream(OutString);
233
234 encodeULEB128(Func.Locals.size(), StringStream);
235 for (auto &LocalDecl : Func.Locals) {
236 encodeULEB128(LocalDecl.Count, StringStream);
237 encodeSLEB128(LocalDecl.Type, StringStream);
238 }
239
240 Func.Body.writeAsBinary(StringStream);
241
242 // Write the section size followed by the content
243 StringStream.flush();
244 encodeULEB128(OutString.size(), OS);
245 OS << OutString;
246 }
247 return 0;
248 }
249
250 int WasmWriter::writeSectionContent(raw_ostream &OS,
251 WasmYAML::DataSection &Section) {
252 encodeULEB128(Section.Segments.size(), OS);
253 for (auto &Segment : Section.Segments) {
254 encodeULEB128(Segment.Index, OS);
255 writeInitExpr(Segment.Offset, OS);
256 encodeULEB128(Segment.Content.binary_size(), OS);
257 Segment.Content.writeAsBinary(OS);
258 }
259 return 0;
260 }
261
262 int WasmWriter::writeRelocSection(raw_ostream &OS,
263 WasmYAML::Section &Sec) {
264 StringRef Name;
265 switch (Sec.Type) {
266 case wasm::WASM_SEC_CODE:
267 Name = "reloc.CODE";
268 break;
269 case wasm::WASM_SEC_DATA:
270 Name = "reloc.DATA";
271 break;
272 default:
273 llvm_unreachable("not yet implemented");
274 return 1;
275 }
276
277 writeStringRef(Name, OS);
278 encodeULEB128(Sec.Type, OS);
279 encodeULEB128(Sec.Relocations.size(), OS);
280
281 for (auto Reloc: Sec.Relocations) {
282 encodeULEB128(Reloc.Type, OS);
283 encodeULEB128(Reloc.Offset, OS);
284 encodeULEB128(Reloc.Index, OS);
285 switch (Reloc.Type) {
286 case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_LEB:
287 case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_SLEB:
288 case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_I32:
289 encodeULEB128(Reloc.Addend, OS);
290 }
291 }
292 return 0;
293 }
294
295
296 int WasmWriter::writeWasm(raw_ostream &OS) {
297 // Write headers
298 OS.write(wasm::WasmMagic, sizeof(wasm::WasmMagic));
299 writeUint32(OS, Obj.Header.Version);
300
301 // Write each section
302 for (const std::unique_ptr &Sec : Obj.Sections) {
303 encodeULEB128(Sec->Type, OS);
304
305 std::string OutString;
306 raw_string_ostream StringStream(OutString);
307 if (auto S = dyn_cast(Sec.get())) {
308 if (auto Err = writeSectionContent(StringStream, *S))
309 return Err;
310 } else if (auto S = dyn_cast(Sec.get())) {
311 if (auto Err = writeSectionContent(StringStream, *S))
312 return Err;
313 } else if (auto S = dyn_cast(Sec.get())) {
314 if (auto Err = writeSectionContent(StringStream, *S))
315 return Err;
316 } else if (auto S = dyn_cast(Sec.get())) {
317 if (auto Err = writeSectionContent(StringStream, *S))
318 return Err;
319 } else if (auto S = dyn_cast(Sec.get())) {
320 if (auto Err = writeSectionContent(StringStream, *S))
321 return Err;
322 } else if (auto S = dyn_cast(Sec.get())) {
323 if (auto Err = writeSectionContent(StringStream, *S))
324 return Err;
325 } else if (auto S = dyn_cast(Sec.get())) {
326 if (auto Err = writeSectionContent(StringStream, *S))
327 return Err;
328 } else if (auto S = dyn_cast(Sec.get())) {
329 if (auto Err = writeSectionContent(StringStream, *S))
330 return Err;
331 } else if (auto S = dyn_cast(Sec.get())) {
332 if (auto Err = writeSectionContent(StringStream, *S))
333 return Err;
334 } else if (auto S = dyn_cast(Sec.get())) {
335 if (auto Err = writeSectionContent(StringStream, *S))
336 return Err;
337 } else if (auto S = dyn_cast(Sec.get())) {
338 if (auto Err = writeSectionContent(StringStream, *S))
339 return Err;
340 } else if (auto S = dyn_cast(Sec.get())) {
341 if (auto Err = writeSectionContent(StringStream, *S))
342 return Err;
343 } else {
344 errs() << "Unknown section type: " << Sec->Type << "\n";
345 return 1;
346 }
347 StringStream.flush();
348
349 // Write the section size followed by the content
350 encodeULEB128(OutString.size(), OS);
351 OS << OutString;
352 }
353
354 // write reloc sections for any section that have relocations
355 for (const std::unique_ptr &Sec : Obj.Sections) {
356 if (Sec->Relocations.empty())
357 continue;
358
359 encodeULEB128(wasm::WASM_SEC_CUSTOM, OS);
360 std::string OutString;
361 raw_string_ostream StringStream(OutString);
362 writeRelocSection(StringStream, *Sec);
363 StringStream.flush();
364
365 encodeULEB128(OutString.size(), OS);
366 OS << OutString;
367 }
368
369 return 0;
370 }
371
372 int yaml2wasm(llvm::WasmYAML::Object &Doc, raw_ostream &Out) {
373 WasmWriter Writer(Doc);
374
375 return Writer.writeWasm(Out);
376 }