OSDN Git Service

[WebAssembly] Add wasm symbol table support to llvm-objdump
[android-x86/external-llvm.git] / lib / Object / WasmObjectFile.cpp
1 //===- WasmObjectFile.cpp - Wasm object file implementation ---------------===//
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 #include "llvm/ADT/ArrayRef.h"
11 #include "llvm/ADT/STLExtras.h"
12 #include "llvm/ADT/StringRef.h"
13 #include "llvm/ADT/Triple.h"
14 #include "llvm/MC/SubtargetFeature.h"
15 #include "llvm/Object/Binary.h"
16 #include "llvm/Object/Error.h"
17 #include "llvm/Object/ObjectFile.h"
18 #include "llvm/Object/SymbolicFile.h"
19 #include "llvm/Object/Wasm.h"
20 #include "llvm/Support/Endian.h"
21 #include "llvm/Support/Error.h"
22 #include "llvm/Support/ErrorHandling.h"
23 #include "llvm/Support/LEB128.h"
24 #include "llvm/Support/Wasm.h"
25 #include <algorithm>
26 #include <cassert>
27 #include <cstdint>
28 #include <cstring>
29 #include <system_error>
30
31 using namespace llvm;
32 using namespace object;
33
34 Expected<std::unique_ptr<WasmObjectFile>>
35 ObjectFile::createWasmObjectFile(MemoryBufferRef Buffer) {
36   Error Err = Error::success();
37   auto ObjectFile = llvm::make_unique<WasmObjectFile>(Buffer, Err);
38   if (Err)
39     return std::move(Err);
40
41   return std::move(ObjectFile);
42 }
43
44 #define VARINT7_MAX ((1<<7)-1)
45 #define VARINT7_MIN (-(1<<7))
46 #define VARUINT7_MAX (1<<7)
47 #define VARUINT1_MAX (1)
48
49 static uint8_t readUint8(const uint8_t *&Ptr) { return *Ptr++; }
50
51 static uint32_t readUint32(const uint8_t *&Ptr) {
52   uint32_t Result = support::endian::read32le(Ptr);
53   Ptr += sizeof(Result);
54   return Result;
55 }
56
57 static int32_t readFloat32(const uint8_t *&Ptr) {
58   int32_t Result = 0;
59   memcpy(&Result, Ptr, sizeof(Result));
60   Ptr += sizeof(Result);
61   return Result;
62 }
63
64 static int64_t readFloat64(const uint8_t *&Ptr) {
65   int64_t Result = 0;
66   memcpy(&Result, Ptr, sizeof(Result));
67   Ptr += sizeof(Result);
68   return Result;
69 }
70
71 static uint64_t readULEB128(const uint8_t *&Ptr) {
72   unsigned Count;
73   uint64_t Result = decodeULEB128(Ptr, &Count);
74   Ptr += Count;
75   return Result;
76 }
77
78 static StringRef readString(const uint8_t *&Ptr) {
79   uint32_t StringLen = readULEB128(Ptr);
80   StringRef Return = StringRef(reinterpret_cast<const char *>(Ptr), StringLen);
81   Ptr += StringLen;
82   return Return;
83 }
84
85 static int64_t readLEB128(const uint8_t *&Ptr) {
86   unsigned Count;
87   uint64_t Result = decodeSLEB128(Ptr, &Count);
88   Ptr += Count;
89   return Result;
90 }
91
92 static uint8_t readVaruint1(const uint8_t *&Ptr) {
93   int64_t result = readLEB128(Ptr);
94   assert(result <= VARUINT1_MAX && result >= 0);
95   return result;
96 }
97
98 static int8_t readVarint7(const uint8_t *&Ptr) {
99   int64_t result = readLEB128(Ptr);
100   assert(result <= VARINT7_MAX && result >= VARINT7_MIN);
101   return result;
102 }
103
104 static uint8_t readVaruint7(const uint8_t *&Ptr) {
105   uint64_t result = readULEB128(Ptr);
106   assert(result <= VARUINT7_MAX);
107   return result;
108 }
109
110 static int32_t readVarint32(const uint8_t *&Ptr) {
111   int64_t result = readLEB128(Ptr);
112   assert(result <= INT32_MAX && result >= INT32_MIN);
113   return result;
114 }
115
116 static uint32_t readVaruint32(const uint8_t *&Ptr) {
117   uint64_t result = readULEB128(Ptr);
118   assert(result <= UINT32_MAX);
119   return result;
120 }
121
122 static int64_t readVarint64(const uint8_t *&Ptr) {
123   return readLEB128(Ptr);
124 }
125
126 static uint8_t readOpcode(const uint8_t *&Ptr) {
127   return readUint8(Ptr);
128 }
129
130 static Error readInitExpr(wasm::WasmInitExpr &Expr, const uint8_t *&Ptr) {
131   Expr.Opcode = readOpcode(Ptr);
132
133   switch (Expr.Opcode) {
134   case wasm::WASM_OPCODE_I32_CONST:
135     Expr.Value.Int32 = readVarint32(Ptr);
136     break;
137   case wasm::WASM_OPCODE_I64_CONST:
138     Expr.Value.Int64 = readVarint64(Ptr);
139     break;
140   case wasm::WASM_OPCODE_F32_CONST:
141     Expr.Value.Float32 = readFloat32(Ptr);
142     break;
143   case wasm::WASM_OPCODE_F64_CONST:
144     Expr.Value.Float64 = readFloat64(Ptr);
145     break;
146   case wasm::WASM_OPCODE_GET_GLOBAL:
147     Expr.Value.Global = readULEB128(Ptr);
148     break;
149   default:
150     return make_error<GenericBinaryError>("Invalid opcode in init_expr",
151                                           object_error::parse_failed);
152   }
153
154   uint8_t EndOpcode = readOpcode(Ptr);
155   if (EndOpcode != wasm::WASM_OPCODE_END) {
156     return make_error<GenericBinaryError>("Invalid init_expr",
157                                           object_error::parse_failed);
158   }
159   return Error::success();
160 }
161
162 static wasm::WasmLimits readLimits(const uint8_t *&Ptr) {
163   wasm::WasmLimits Result;
164   Result.Flags = readVaruint1(Ptr);
165   Result.Initial = readVaruint32(Ptr);
166   if (Result.Flags & wasm::WASM_LIMITS_FLAG_HAS_MAX)
167     Result.Maximum = readVaruint32(Ptr);
168   return Result;
169 }
170
171 static Error readSection(WasmSection &Section, const uint8_t *&Ptr,
172                          const uint8_t *Start) {
173   // TODO(sbc): Avoid reading past EOF in the case of malformed files.
174   Section.Offset = Ptr - Start;
175   Section.Type = readVaruint7(Ptr);
176   uint32_t Size = readVaruint32(Ptr);
177   if (Size == 0)
178     return make_error<StringError>("Zero length section",
179                                    object_error::parse_failed);
180   Section.Content = ArrayRef<uint8_t>(Ptr, Size);
181   Ptr += Size;
182   return Error::success();
183 }
184
185 WasmObjectFile::WasmObjectFile(MemoryBufferRef Buffer, Error &Err)
186     : ObjectFile(Binary::ID_Wasm, Buffer) {
187   ErrorAsOutParameter ErrAsOutParam(&Err);
188   Header.Magic = getData().substr(0, 4);
189   if (Header.Magic != StringRef("\0asm", 4)) {
190     Err = make_error<StringError>("Bad magic number",
191                                   object_error::parse_failed);
192     return;
193   }
194   const uint8_t *Ptr = getPtr(4);
195   Header.Version = readUint32(Ptr);
196   if (Header.Version != wasm::WasmVersion) {
197     Err = make_error<StringError>("Bad version number",
198                                   object_error::parse_failed);
199     return;
200   }
201
202   const uint8_t *Eof = getPtr(getData().size());
203   WasmSection Sec;
204   while (Ptr < Eof) {
205     if ((Err = readSection(Sec, Ptr, getPtr(0))))
206       return;
207     if ((Err = parseSection(Sec)))
208       return;
209
210     Sections.push_back(Sec);
211   }
212 }
213
214 Error WasmObjectFile::parseSection(WasmSection &Sec) {
215   const uint8_t* Start = Sec.Content.data();
216   const uint8_t* End = Start + Sec.Content.size();
217   switch (Sec.Type) {
218   case wasm::WASM_SEC_CUSTOM:
219     return parseCustomSection(Sec, Start, End);
220   case wasm::WASM_SEC_TYPE:
221     return parseTypeSection(Start, End);
222   case wasm::WASM_SEC_IMPORT:
223     return parseImportSection(Start, End);
224   case wasm::WASM_SEC_FUNCTION:
225     return parseFunctionSection(Start, End);
226   case wasm::WASM_SEC_TABLE:
227     return parseTableSection(Start, End);
228   case wasm::WASM_SEC_MEMORY:
229     return parseMemorySection(Start, End);
230   case wasm::WASM_SEC_GLOBAL:
231     return parseGlobalSection(Start, End);
232   case wasm::WASM_SEC_EXPORT:
233     return parseExportSection(Start, End);
234   case wasm::WASM_SEC_START:
235     return parseStartSection(Start, End);
236   case wasm::WASM_SEC_ELEM:
237     return parseElemSection(Start, End);
238   case wasm::WASM_SEC_CODE:
239     return parseCodeSection(Start, End);
240   case wasm::WASM_SEC_DATA:
241     return parseDataSection(Start, End);
242   default:
243     return make_error<GenericBinaryError>("Bad section type",
244                                           object_error::parse_failed);
245   }
246 }
247
248 Error WasmObjectFile::parseNameSection(const uint8_t *Ptr, const uint8_t *End) {
249   while (Ptr < End) {
250     uint8_t Type = readVarint7(Ptr);
251     uint32_t Size = readVaruint32(Ptr);
252     switch (Type) {
253     case wasm::WASM_NAMES_FUNCTION: {
254       uint32_t Count = readVaruint32(Ptr);
255       while (Count--) {
256         uint32_t Index = readVaruint32(Ptr);
257         StringRef Name = readString(Ptr);
258         if (!Name.empty())
259           Symbols.emplace_back(Name,
260                                WasmSymbol::SymbolType::DEBUG_FUNCTION_NAME,
261                                Sections.size(), Index);
262       }
263       break;
264     }
265     // Ignore local names for now
266     case wasm::WASM_NAMES_LOCAL:
267     default:
268       Ptr += Size;
269       break;
270     }
271   }
272
273   if (Ptr != End)
274     return make_error<GenericBinaryError>("Name section ended prematurely",
275                                           object_error::parse_failed);
276   return Error::success();
277 }
278
279 WasmSection* WasmObjectFile::findCustomSectionByName(StringRef Name) {
280   for (WasmSection& Section : Sections) {
281     if (Section.Type == wasm::WASM_SEC_CUSTOM && Section.Name == Name)
282       return &Section;
283   }
284   return nullptr;
285 }
286
287 WasmSection* WasmObjectFile::findSectionByType(uint32_t Type) {
288   assert(Type != wasm::WASM_SEC_CUSTOM);
289   for (WasmSection& Section : Sections) {
290     if (Section.Type == Type)
291       return &Section;
292   }
293   return nullptr;
294 }
295
296 Error WasmObjectFile::parseRelocSection(StringRef Name, const uint8_t *Ptr,
297                                         const uint8_t *End) {
298   uint8_t SectionCode = readVarint7(Ptr);
299   WasmSection* Section = nullptr;
300   if (SectionCode == wasm::WASM_SEC_CUSTOM) {
301     StringRef Name = readString(Ptr);
302     Section = findCustomSectionByName(Name);
303   } else {
304     Section = findSectionByType(SectionCode);
305   }
306   if (!Section)
307     return make_error<GenericBinaryError>("Invalid section code",
308                                           object_error::parse_failed);
309   uint32_t RelocCount = readVaruint32(Ptr);
310   while (RelocCount--) {
311     wasm::WasmRelocation Reloc;
312     memset(&Reloc, 0, sizeof(Reloc));
313     Reloc.Type = readVaruint32(Ptr);
314     Reloc.Offset = readVaruint32(Ptr);
315     Reloc.Index = readVaruint32(Ptr);
316     switch (Reloc.Type) {
317     case wasm::R_WEBASSEMBLY_FUNCTION_INDEX_LEB:
318     case wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB:
319     case wasm::R_WEBASSEMBLY_TABLE_INDEX_I32:
320     case wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB:
321       break;
322     case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_LEB:
323     case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_SLEB:
324     case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_I32:
325       Reloc.Addend = readVarint32(Ptr);
326       break;
327     default:
328       return make_error<GenericBinaryError>("Bad relocation type",
329                                             object_error::parse_failed);
330     }
331     Section->Relocations.push_back(Reloc);
332   }
333   if (Ptr != End)
334     return make_error<GenericBinaryError>("Reloc section ended prematurely",
335                                           object_error::parse_failed);
336   return Error::success();
337 }
338
339 Error WasmObjectFile::parseCustomSection(WasmSection &Sec,
340                                          const uint8_t *Ptr, const uint8_t *End) {
341   Sec.Name = readString(Ptr);
342   if (Sec.Name == "name") {
343     if (Error Err = parseNameSection(Ptr, End))
344       return Err;
345   } else if (Sec.Name.startswith("reloc.")) {
346     if (Error Err = parseRelocSection(Sec.Name, Ptr, End))
347       return Err;
348   }
349   return Error::success();
350 }
351
352 Error WasmObjectFile::parseTypeSection(const uint8_t *Ptr, const uint8_t *End) {
353   uint32_t Count = readVaruint32(Ptr);
354   Signatures.reserve(Count);
355   while (Count--) {
356     wasm::WasmSignature Sig;
357     Sig.ReturnType = wasm::WASM_TYPE_NORESULT;
358     int8_t Form = readVarint7(Ptr);
359     if (Form != wasm::WASM_TYPE_FUNC) {
360       return make_error<GenericBinaryError>("Invalid signature type",
361                                             object_error::parse_failed);
362     }
363     uint32_t ParamCount = readVaruint32(Ptr);
364     Sig.ParamTypes.reserve(ParamCount);
365     while (ParamCount--) {
366       uint32_t ParamType = readVarint7(Ptr);
367       Sig.ParamTypes.push_back(ParamType);
368     }
369     uint32_t ReturnCount = readVaruint32(Ptr);
370     if (ReturnCount) {
371       if (ReturnCount != 1) {
372         return make_error<GenericBinaryError>(
373             "Multiple return types not supported", object_error::parse_failed);
374       }
375       Sig.ReturnType = readVarint7(Ptr);
376     }
377     Signatures.push_back(Sig);
378   }
379   if (Ptr != End)
380     return make_error<GenericBinaryError>("Type section ended prematurely",
381                                           object_error::parse_failed);
382   return Error::success();
383 }
384
385 Error WasmObjectFile::parseImportSection(const uint8_t *Ptr, const uint8_t *End) {
386   uint32_t Count = readVaruint32(Ptr);
387   Imports.reserve(Count);
388   for (uint32_t i = 0; i < Count; i++) {
389     wasm::WasmImport Im;
390     Im.Module = readString(Ptr);
391     Im.Field = readString(Ptr);
392     Im.Kind = readUint8(Ptr);
393     switch (Im.Kind) {
394     case wasm::WASM_EXTERNAL_FUNCTION:
395       Im.SigIndex = readVaruint32(Ptr);
396       Symbols.emplace_back(Im.Field, WasmSymbol::SymbolType::FUNCTION_IMPORT,
397                            Sections.size(), i);
398       break;
399     case wasm::WASM_EXTERNAL_GLOBAL:
400       Im.GlobalType = readVarint7(Ptr);
401       Im.GlobalMutable = readVaruint1(Ptr);
402       Symbols.emplace_back(Im.Field, WasmSymbol::SymbolType::GLOBAL_IMPORT,
403                            Sections.size(), i);
404       break;
405     default:
406       // TODO(sbc): Handle other kinds of imports
407       return make_error<GenericBinaryError>(
408           "Unexpected import kind", object_error::parse_failed);
409     }
410     Imports.push_back(Im);
411   }
412   if (Ptr != End)
413     return make_error<GenericBinaryError>("Import section ended prematurely",
414                                           object_error::parse_failed);
415   return Error::success();
416 }
417
418 Error WasmObjectFile::parseFunctionSection(const uint8_t *Ptr, const uint8_t *End) {
419   uint32_t Count = readVaruint32(Ptr);
420   FunctionTypes.reserve(Count);
421   while (Count--) {
422     FunctionTypes.push_back(readVaruint32(Ptr));
423   }
424   if (Ptr != End)
425     return make_error<GenericBinaryError>("Function section ended prematurely",
426                                           object_error::parse_failed);
427   return Error::success();
428 }
429
430 Error WasmObjectFile::parseTableSection(const uint8_t *Ptr, const uint8_t *End) {
431   uint32_t Count = readVaruint32(Ptr);
432   Tables.reserve(Count);
433   while (Count--) {
434     wasm::WasmTable Table;
435     Table.ElemType = readVarint7(Ptr);
436     if (Table.ElemType != wasm::WASM_TYPE_ANYFUNC) {
437       return make_error<GenericBinaryError>("Invalid table element type",
438                                             object_error::parse_failed);
439     }
440     Table.Limits = readLimits(Ptr);
441     Tables.push_back(Table);
442   }
443   if (Ptr != End)
444     return make_error<GenericBinaryError>("Table section ended prematurely",
445                                           object_error::parse_failed);
446   return Error::success();
447 }
448
449 Error WasmObjectFile::parseMemorySection(const uint8_t *Ptr, const uint8_t *End) {
450   uint32_t Count = readVaruint32(Ptr);
451   Memories.reserve(Count);
452   while (Count--) {
453     Memories.push_back(readLimits(Ptr));
454   }
455   if (Ptr != End)
456     return make_error<GenericBinaryError>("Memory section ended prematurely",
457                                           object_error::parse_failed);
458   return Error::success();
459 }
460
461 Error WasmObjectFile::parseGlobalSection(const uint8_t *Ptr, const uint8_t *End) {
462   uint32_t Count = readVaruint32(Ptr);
463   Globals.reserve(Count);
464   while (Count--) {
465     wasm::WasmGlobal Global;
466     Global.Type = readVarint7(Ptr);
467     Global.Mutable = readVaruint1(Ptr);
468     if (Error Err = readInitExpr(Global.InitExpr, Ptr))
469       return Err;
470     Globals.push_back(Global);
471   }
472   if (Ptr != End)
473     return make_error<GenericBinaryError>("Global section ended prematurely",
474                                           object_error::parse_failed);
475   return Error::success();
476 }
477
478 Error WasmObjectFile::parseExportSection(const uint8_t *Ptr, const uint8_t *End) {
479   uint32_t Count = readVaruint32(Ptr);
480   Exports.reserve(Count);
481   for (uint32_t i = 0; i < Count; i++) {
482     wasm::WasmExport Ex;
483     Ex.Name = readString(Ptr);
484     Ex.Kind = readUint8(Ptr);
485     Ex.Index = readVaruint32(Ptr);
486     Exports.push_back(Ex);
487     switch (Ex.Kind) {
488     case wasm::WASM_EXTERNAL_FUNCTION:
489       Symbols.emplace_back(Ex.Name, WasmSymbol::SymbolType::FUNCTION_EXPORT,
490                            Sections.size(), i);
491       break;
492     case wasm::WASM_EXTERNAL_GLOBAL:
493       Symbols.emplace_back(Ex.Name, WasmSymbol::SymbolType::GLOBAL_EXPORT,
494                            Sections.size(), i);
495       break;
496     default:
497       // TODO(sbc): Handle other kinds of exports
498       return make_error<GenericBinaryError>(
499           "Unexpected export kind", object_error::parse_failed);
500     }
501   }
502   if (Ptr != End)
503     return make_error<GenericBinaryError>("Export section ended prematurely",
504                                           object_error::parse_failed);
505   return Error::success();
506 }
507
508 Error WasmObjectFile::parseStartSection(const uint8_t *Ptr, const uint8_t *End) {
509   StartFunction = readVaruint32(Ptr);
510   if (StartFunction < FunctionTypes.size())
511     return make_error<GenericBinaryError>("Invalid start function",
512                                           object_error::parse_failed);
513   return Error::success();
514 }
515
516 Error WasmObjectFile::parseCodeSection(const uint8_t *Ptr, const uint8_t *End) {
517   uint32_t FunctionCount = readVaruint32(Ptr);
518   if (FunctionCount != FunctionTypes.size()) {
519     return make_error<GenericBinaryError>("Invalid function count",
520                                           object_error::parse_failed);
521   }
522
523   CodeSection = ArrayRef<uint8_t>(Ptr, End - Ptr);
524
525   while (FunctionCount--) {
526     wasm::WasmFunction Function;
527     uint32_t FunctionSize = readVaruint32(Ptr);
528     const uint8_t *FunctionEnd = Ptr + FunctionSize;
529
530     uint32_t NumLocalDecls = readVaruint32(Ptr);
531     Function.Locals.reserve(NumLocalDecls);
532     while (NumLocalDecls--) {
533       wasm::WasmLocalDecl Decl;
534       Decl.Count = readVaruint32(Ptr);
535       Decl.Type = readVarint7(Ptr);
536       Function.Locals.push_back(Decl);
537     }
538
539     uint32_t BodySize = FunctionEnd - Ptr;
540     Function.Body = ArrayRef<uint8_t>(Ptr, BodySize);
541     Ptr += BodySize;
542     assert(Ptr == FunctionEnd);
543     Functions.push_back(Function);
544   }
545   if (Ptr != End)
546     return make_error<GenericBinaryError>("Code section ended prematurely",
547                                           object_error::parse_failed);
548   return Error::success();
549 }
550
551 Error WasmObjectFile::parseElemSection(const uint8_t *Ptr, const uint8_t *End) {
552   uint32_t Count = readVaruint32(Ptr);
553   ElemSegments.reserve(Count);
554   while (Count--) {
555     wasm::WasmElemSegment Segment;
556     Segment.TableIndex = readVaruint32(Ptr);
557     if (Segment.TableIndex != 0) {
558       return make_error<GenericBinaryError>("Invalid TableIndex",
559                                             object_error::parse_failed);
560     }
561     if (Error Err = readInitExpr(Segment.Offset, Ptr))
562       return Err;
563     uint32_t NumElems = readVaruint32(Ptr);
564     while (NumElems--) {
565       Segment.Functions.push_back(readVaruint32(Ptr));
566     }
567     ElemSegments.push_back(Segment);
568   }
569   if (Ptr != End)
570     return make_error<GenericBinaryError>("Elem section ended prematurely",
571                                           object_error::parse_failed);
572   return Error::success();
573 }
574
575 Error WasmObjectFile::parseDataSection(const uint8_t *Ptr, const uint8_t *End) {
576   uint32_t Count = readVaruint32(Ptr);
577   DataSegments.reserve(Count);
578   while (Count--) {
579     wasm::WasmDataSegment Segment;
580     Segment.Index = readVaruint32(Ptr);
581     if (Error Err = readInitExpr(Segment.Offset, Ptr))
582       return Err;
583     uint32_t Size = readVaruint32(Ptr);
584     Segment.Content = ArrayRef<uint8_t>(Ptr, Size);
585     Ptr += Size;
586     DataSegments.push_back(Segment);
587   }
588   if (Ptr != End)
589     return make_error<GenericBinaryError>("Data section ended prematurely",
590                                           object_error::parse_failed);
591   return Error::success();
592 }
593
594 const uint8_t *WasmObjectFile::getPtr(size_t Offset) const {
595   return reinterpret_cast<const uint8_t *>(getData().substr(Offset, 1).data());
596 }
597
598 const wasm::WasmObjectHeader &WasmObjectFile::getHeader() const {
599   return Header;
600 }
601
602 void WasmObjectFile::moveSymbolNext(DataRefImpl &Symb) const { Symb.d.a++; }
603
604 uint32_t WasmObjectFile::getSymbolFlags(DataRefImpl Symb) const {
605   uint32_t Result = SymbolRef::SF_None;
606   const WasmSymbol &Sym = getWasmSymbol(Symb);
607
608   switch (Sym.Type) {
609   case WasmSymbol::SymbolType::FUNCTION_IMPORT:
610     Result |= SymbolRef::SF_Undefined | SymbolRef::SF_Executable;
611     break;
612   case WasmSymbol::SymbolType::FUNCTION_EXPORT:
613     Result |= SymbolRef::SF_Global | SymbolRef::SF_Executable;
614     break;
615   case WasmSymbol::SymbolType::DEBUG_FUNCTION_NAME:
616     Result |= SymbolRef::SF_Executable;
617     break;
618   case WasmSymbol::SymbolType::GLOBAL_IMPORT:
619     Result |= SymbolRef::SF_Undefined;
620     break;
621   case WasmSymbol::SymbolType::GLOBAL_EXPORT:
622     Result |= SymbolRef::SF_Global;
623     break;
624   }
625
626   return Result;
627 }
628
629 basic_symbol_iterator WasmObjectFile::symbol_begin() const {
630   DataRefImpl Ref;
631   Ref.d.a = 0;
632   return BasicSymbolRef(Ref, this);
633 }
634
635 basic_symbol_iterator WasmObjectFile::symbol_end() const {
636   DataRefImpl Ref;
637   Ref.d.a = Symbols.size();
638   return BasicSymbolRef(Ref, this);
639 }
640
641 const WasmSymbol &WasmObjectFile::getWasmSymbol(DataRefImpl Symb) const {
642   return Symbols[Symb.d.a];
643 }
644
645 Expected<StringRef> WasmObjectFile::getSymbolName(DataRefImpl Symb) const {
646   const WasmSymbol &Sym = getWasmSymbol(Symb);
647   return Sym.Name;
648 }
649
650 Expected<uint64_t> WasmObjectFile::getSymbolAddress(DataRefImpl Symb) const {
651   return getSymbolValue(Symb);
652 }
653
654 uint64_t WasmObjectFile::getSymbolValueImpl(DataRefImpl Symb) const {
655   const WasmSymbol &Sym = getWasmSymbol(Symb);
656   return Sym.ElementIndex;
657 }
658
659 uint32_t WasmObjectFile::getSymbolAlignment(DataRefImpl Symb) const {
660   llvm_unreachable("not yet implemented");
661   return 0;
662 }
663
664 uint64_t WasmObjectFile::getCommonSymbolSizeImpl(DataRefImpl Symb) const {
665   llvm_unreachable("not yet implemented");
666   return 0;
667 }
668
669 Expected<SymbolRef::Type>
670 WasmObjectFile::getSymbolType(DataRefImpl Symb) const {
671   const WasmSymbol &Sym = getWasmSymbol(Symb);
672
673   switch (Sym.Type) {
674   case WasmSymbol::SymbolType::FUNCTION_IMPORT:
675   case WasmSymbol::SymbolType::FUNCTION_EXPORT:
676   case WasmSymbol::SymbolType::DEBUG_FUNCTION_NAME:
677     return SymbolRef::ST_Function;
678   case WasmSymbol::SymbolType::GLOBAL_IMPORT:
679   case WasmSymbol::SymbolType::GLOBAL_EXPORT:
680     return SymbolRef::ST_Data;
681   }
682
683   llvm_unreachable("Unknown WasmSymbol::SymbolType");
684   return SymbolRef::ST_Other;
685 }
686
687 Expected<section_iterator>
688 WasmObjectFile::getSymbolSection(DataRefImpl Symb) const {
689   DataRefImpl Ref;
690   Ref.d.a = getWasmSymbol(Symb).Section;
691   return section_iterator(SectionRef(Ref, this));
692 }
693
694 void WasmObjectFile::moveSectionNext(DataRefImpl &Sec) const { Sec.d.a++; }
695
696 std::error_code WasmObjectFile::getSectionName(DataRefImpl Sec,
697                                                StringRef &Res) const {
698   const WasmSection &S = Sections[Sec.d.a];
699 #define ECase(X)                                                               \
700   case wasm::WASM_SEC_##X:                                                     \
701     Res = #X;                                                                  \
702     break
703   switch (S.Type) {
704     ECase(TYPE);
705     ECase(IMPORT);
706     ECase(FUNCTION);
707     ECase(TABLE);
708     ECase(MEMORY);
709     ECase(GLOBAL);
710     ECase(EXPORT);
711     ECase(START);
712     ECase(ELEM);
713     ECase(CODE);
714     ECase(DATA);
715   case wasm::WASM_SEC_CUSTOM:
716     Res = S.Name;
717     break;
718   default:
719     return object_error::invalid_section_index;
720   }
721 #undef ECase
722   return std::error_code();
723 }
724
725 uint64_t WasmObjectFile::getSectionAddress(DataRefImpl Sec) const { return 0; }
726
727 uint64_t WasmObjectFile::getSectionSize(DataRefImpl Sec) const {
728   const WasmSection &S = Sections[Sec.d.a];
729   return S.Content.size();
730 }
731
732 std::error_code WasmObjectFile::getSectionContents(DataRefImpl Sec,
733                                                    StringRef &Res) const {
734   const WasmSection &S = Sections[Sec.d.a];
735   // This will never fail since wasm sections can never be empty (user-sections
736   // must have a name and non-user sections each have a defined structure).
737   Res = StringRef(reinterpret_cast<const char *>(S.Content.data()),
738                   S.Content.size());
739   return std::error_code();
740 }
741
742 uint64_t WasmObjectFile::getSectionAlignment(DataRefImpl Sec) const {
743   return 1;
744 }
745
746 bool WasmObjectFile::isSectionCompressed(DataRefImpl Sec) const {
747   return false;
748 }
749
750 bool WasmObjectFile::isSectionText(DataRefImpl Sec) const {
751   return getWasmSection(Sec).Type == wasm::WASM_SEC_CODE;
752 }
753
754 bool WasmObjectFile::isSectionData(DataRefImpl Sec) const {
755   return getWasmSection(Sec).Type == wasm::WASM_SEC_DATA;
756 }
757
758 bool WasmObjectFile::isSectionBSS(DataRefImpl Sec) const { return false; }
759
760 bool WasmObjectFile::isSectionVirtual(DataRefImpl Sec) const { return false; }
761
762 bool WasmObjectFile::isSectionBitcode(DataRefImpl Sec) const { return false; }
763
764 relocation_iterator WasmObjectFile::section_rel_begin(DataRefImpl Ref) const {
765   DataRefImpl RelocRef;
766   RelocRef.d.a = Ref.d.a;
767   RelocRef.d.b = 0;
768   return relocation_iterator(RelocationRef(RelocRef, this));
769 }
770
771 relocation_iterator WasmObjectFile::section_rel_end(DataRefImpl Ref) const {
772   const WasmSection &Sec = getWasmSection(Ref);
773   DataRefImpl RelocRef;
774   RelocRef.d.a = Ref.d.a;
775   RelocRef.d.b = Sec.Relocations.size();
776   return relocation_iterator(RelocationRef(RelocRef, this));
777 }
778
779 void WasmObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
780   Rel.d.b++;
781 }
782
783 uint64_t WasmObjectFile::getRelocationOffset(DataRefImpl Ref) const {
784   const wasm::WasmRelocation &Rel = getWasmRelocation(Ref);
785   return Rel.Offset;
786 }
787
788 symbol_iterator WasmObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
789   llvm_unreachable("not yet implemented");
790   SymbolRef Ref;
791   return symbol_iterator(Ref);
792 }
793
794 uint64_t WasmObjectFile::getRelocationType(DataRefImpl Ref) const {
795   const wasm::WasmRelocation &Rel = getWasmRelocation(Ref);
796   return Rel.Type;
797 }
798
799 void WasmObjectFile::getRelocationTypeName(
800     DataRefImpl Ref, SmallVectorImpl<char> &Result) const {
801   const wasm::WasmRelocation& Rel = getWasmRelocation(Ref);
802   StringRef Res = "Unknown";
803
804 #define WASM_RELOC(name, value)  \
805   case wasm::name:              \
806     Res = #name;               \
807     break;
808
809   switch (Rel.Type) {
810 #include "llvm/Support/WasmRelocs/WebAssembly.def"
811   }
812
813 #undef WASM_RELOC
814
815   Result.append(Res.begin(), Res.end());
816 }
817
818 section_iterator WasmObjectFile::section_begin() const {
819   DataRefImpl Ref;
820   Ref.d.a = 0;
821   return section_iterator(SectionRef(Ref, this));
822 }
823
824 section_iterator WasmObjectFile::section_end() const {
825   DataRefImpl Ref;
826   Ref.d.a = Sections.size();
827   return section_iterator(SectionRef(Ref, this));
828 }
829
830 uint8_t WasmObjectFile::getBytesInAddress() const { return 4; }
831
832 StringRef WasmObjectFile::getFileFormatName() const { return "WASM"; }
833
834 unsigned WasmObjectFile::getArch() const { return Triple::wasm32; }
835
836 SubtargetFeatures WasmObjectFile::getFeatures() const {
837   return SubtargetFeatures();
838 }
839
840 bool WasmObjectFile::isRelocatableObject() const { return false; }
841
842 const WasmSection &WasmObjectFile::getWasmSection(DataRefImpl Ref) const {
843   assert(Ref.d.a < Sections.size());
844   return Sections[Ref.d.a];
845 }
846
847 const WasmSection &
848 WasmObjectFile::getWasmSection(const SectionRef &Section) const {
849   return getWasmSection(Section.getRawDataRefImpl());
850 }
851
852 const wasm::WasmRelocation &
853 WasmObjectFile::getWasmRelocation(const RelocationRef &Ref) const {
854   return getWasmRelocation(Ref.getRawDataRefImpl());
855 }
856
857 const wasm::WasmRelocation &
858 WasmObjectFile::getWasmRelocation(DataRefImpl Ref) const {
859   assert(Ref.d.a < Sections.size());
860   const WasmSection& Sec = Sections[Ref.d.a];
861   assert(Ref.d.b < Sec.Relocations.size());
862   return Sec.Relocations[Ref.d.b];
863 }