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/DenseSet.h"
12 #include "llvm/ADT/STLExtras.h"
13 #include "llvm/ADT/StringRef.h"
14 #include "llvm/ADT/StringSet.h"
15 #include "llvm/ADT/Triple.h"
16 #include "llvm/BinaryFormat/Wasm.h"
17 #include "llvm/MC/SubtargetFeature.h"
18 #include "llvm/Object/Binary.h"
19 #include "llvm/Object/Error.h"
20 #include "llvm/Object/ObjectFile.h"
21 #include "llvm/Object/SymbolicFile.h"
22 #include "llvm/Object/Wasm.h"
23 #include "llvm/Support/Endian.h"
24 #include "llvm/Support/Error.h"
25 #include "llvm/Support/ErrorHandling.h"
26 #include "llvm/Support/LEB128.h"
27 #include <algorithm>
28 #include <cassert>
29 #include <cstdint>
30 #include <cstring>
31 #include <system_error>
32 
33 #define DEBUG_TYPE "wasm-object"
34 
35 using namespace llvm;
36 using namespace object;
37 
38 Expected<std::unique_ptr<WasmObjectFile>>
39 ObjectFile::createWasmObjectFile(MemoryBufferRef Buffer) {
40   Error Err = Error::success();
41   auto ObjectFile = llvm::make_unique<WasmObjectFile>(Buffer, Err);
42   if (Err)
43     return std::move(Err);
44 
45   return std::move(ObjectFile);
46 }
47 
48 #define VARINT7_MAX ((1<<7)-1)
49 #define VARINT7_MIN (-(1<<7))
50 #define VARUINT7_MAX (1<<7)
51 #define VARUINT1_MAX (1)
52 
53 static uint8_t readUint8(const uint8_t *&Ptr) { return *Ptr++; }
54 
55 static uint32_t readUint32(const uint8_t *&Ptr) {
56   uint32_t Result = support::endian::read32le(Ptr);
57   Ptr += sizeof(Result);
58   return Result;
59 }
60 
61 static int32_t readFloat32(const uint8_t *&Ptr) {
62   int32_t Result = 0;
63   memcpy(&Result, Ptr, sizeof(Result));
64   Ptr += sizeof(Result);
65   return Result;
66 }
67 
68 static int64_t readFloat64(const uint8_t *&Ptr) {
69   int64_t Result = 0;
70   memcpy(&Result, Ptr, sizeof(Result));
71   Ptr += sizeof(Result);
72   return Result;
73 }
74 
75 static uint64_t readULEB128(const uint8_t *&Ptr) {
76   unsigned Count;
77   uint64_t Result = decodeULEB128(Ptr, &Count);
78   Ptr += Count;
79   return Result;
80 }
81 
82 static StringRef readString(const uint8_t *&Ptr) {
83   uint32_t StringLen = readULEB128(Ptr);
84   StringRef Return = StringRef(reinterpret_cast<const char *>(Ptr), StringLen);
85   Ptr += StringLen;
86   return Return;
87 }
88 
89 static int64_t readLEB128(const uint8_t *&Ptr) {
90   unsigned Count;
91   uint64_t Result = decodeSLEB128(Ptr, &Count);
92   Ptr += Count;
93   return Result;
94 }
95 
96 static uint8_t readVaruint1(const uint8_t *&Ptr) {
97   int64_t result = readLEB128(Ptr);
98   assert(result <= VARUINT1_MAX && result >= 0);
99   return result;
100 }
101 
102 static int8_t readVarint7(const uint8_t *&Ptr) {
103   int64_t result = readLEB128(Ptr);
104   assert(result <= VARINT7_MAX && result >= VARINT7_MIN);
105   return result;
106 }
107 
108 static uint8_t readVaruint7(const uint8_t *&Ptr) {
109   uint64_t result = readULEB128(Ptr);
110   assert(result <= VARUINT7_MAX);
111   return result;
112 }
113 
114 static int32_t readVarint32(const uint8_t *&Ptr) {
115   int64_t result = readLEB128(Ptr);
116   assert(result <= INT32_MAX && result >= INT32_MIN);
117   return result;
118 }
119 
120 static uint32_t readVaruint32(const uint8_t *&Ptr) {
121   uint64_t result = readULEB128(Ptr);
122   assert(result <= UINT32_MAX);
123   return result;
124 }
125 
126 static int64_t readVarint64(const uint8_t *&Ptr) {
127   return readLEB128(Ptr);
128 }
129 
130 static uint8_t readOpcode(const uint8_t *&Ptr) {
131   return readUint8(Ptr);
132 }
133 
134 static Error readInitExpr(wasm::WasmInitExpr &Expr, const uint8_t *&Ptr) {
135   Expr.Opcode = readOpcode(Ptr);
136 
137   switch (Expr.Opcode) {
138   case wasm::WASM_OPCODE_I32_CONST:
139     Expr.Value.Int32 = readVarint32(Ptr);
140     break;
141   case wasm::WASM_OPCODE_I64_CONST:
142     Expr.Value.Int64 = readVarint64(Ptr);
143     break;
144   case wasm::WASM_OPCODE_F32_CONST:
145     Expr.Value.Float32 = readFloat32(Ptr);
146     break;
147   case wasm::WASM_OPCODE_F64_CONST:
148     Expr.Value.Float64 = readFloat64(Ptr);
149     break;
150   case wasm::WASM_OPCODE_GET_GLOBAL:
151     Expr.Value.Global = readULEB128(Ptr);
152     break;
153   default:
154     return make_error<GenericBinaryError>("Invalid opcode in init_expr",
155                                           object_error::parse_failed);
156   }
157 
158   uint8_t EndOpcode = readOpcode(Ptr);
159   if (EndOpcode != wasm::WASM_OPCODE_END) {
160     return make_error<GenericBinaryError>("Invalid init_expr",
161                                           object_error::parse_failed);
162   }
163   return Error::success();
164 }
165 
166 static wasm::WasmLimits readLimits(const uint8_t *&Ptr) {
167   wasm::WasmLimits Result;
168   Result.Flags = readVaruint1(Ptr);
169   Result.Initial = readVaruint32(Ptr);
170   if (Result.Flags & wasm::WASM_LIMITS_FLAG_HAS_MAX)
171     Result.Maximum = readVaruint32(Ptr);
172   return Result;
173 }
174 
175 static wasm::WasmTable readTable(const uint8_t *&Ptr) {
176   wasm::WasmTable Table;
177   Table.ElemType = readVarint7(Ptr);
178   Table.Limits = readLimits(Ptr);
179   return Table;
180 }
181 
182 static Error readSection(WasmSection &Section, const uint8_t *&Ptr,
183                          const uint8_t *Start, const uint8_t *Eof) {
184   Section.Offset = Ptr - Start;
185   Section.Type = readVaruint7(Ptr);
186   uint32_t Size = readVaruint32(Ptr);
187   if (Size == 0)
188     return make_error<StringError>("Zero length section",
189                                    object_error::parse_failed);
190   if (Ptr + Size > Eof)
191     return make_error<StringError>("Section too large",
192                                    object_error::parse_failed);
193   Section.Content = ArrayRef<uint8_t>(Ptr, Size);
194   Ptr += Size;
195   return Error::success();
196 }
197 
198 WasmObjectFile::WasmObjectFile(MemoryBufferRef Buffer, Error &Err)
199     : ObjectFile(Binary::ID_Wasm, Buffer) {
200   LinkingData.DataSize = 0;
201 
202   ErrorAsOutParameter ErrAsOutParam(&Err);
203   Header.Magic = getData().substr(0, 4);
204   if (Header.Magic != StringRef("\0asm", 4)) {
205     Err = make_error<StringError>("Bad magic number",
206                                   object_error::parse_failed);
207     return;
208   }
209 
210   const uint8_t *Eof = getPtr(getData().size());
211   const uint8_t *Ptr = getPtr(4);
212 
213   if (Ptr + 4 > Eof) {
214     Err = make_error<StringError>("Missing version number",
215                                   object_error::parse_failed);
216     return;
217   }
218 
219   Header.Version = readUint32(Ptr);
220   if (Header.Version != wasm::WasmVersion) {
221     Err = make_error<StringError>("Bad version number",
222                                   object_error::parse_failed);
223     return;
224   }
225 
226   WasmSection Sec;
227   while (Ptr < Eof) {
228     if ((Err = readSection(Sec, Ptr, getPtr(0), Eof)))
229       return;
230     if ((Err = parseSection(Sec)))
231       return;
232 
233     Sections.push_back(Sec);
234   }
235 }
236 
237 Error WasmObjectFile::parseSection(WasmSection &Sec) {
238   const uint8_t* Start = Sec.Content.data();
239   const uint8_t* End = Start + Sec.Content.size();
240   switch (Sec.Type) {
241   case wasm::WASM_SEC_CUSTOM:
242     return parseCustomSection(Sec, Start, End);
243   case wasm::WASM_SEC_TYPE:
244     return parseTypeSection(Start, End);
245   case wasm::WASM_SEC_IMPORT:
246     return parseImportSection(Start, End);
247   case wasm::WASM_SEC_FUNCTION:
248     return parseFunctionSection(Start, End);
249   case wasm::WASM_SEC_TABLE:
250     return parseTableSection(Start, End);
251   case wasm::WASM_SEC_MEMORY:
252     return parseMemorySection(Start, End);
253   case wasm::WASM_SEC_GLOBAL:
254     return parseGlobalSection(Start, End);
255   case wasm::WASM_SEC_EXPORT:
256     return parseExportSection(Start, End);
257   case wasm::WASM_SEC_START:
258     return parseStartSection(Start, End);
259   case wasm::WASM_SEC_ELEM:
260     return parseElemSection(Start, End);
261   case wasm::WASM_SEC_CODE:
262     return parseCodeSection(Start, End);
263   case wasm::WASM_SEC_DATA:
264     return parseDataSection(Start, End);
265   default:
266     return make_error<GenericBinaryError>("Bad section type",
267                                           object_error::parse_failed);
268   }
269 }
270 
271 Error WasmObjectFile::parseNameSection(const uint8_t *Ptr, const uint8_t *End) {
272   llvm::DenseSet<uint64_t> Seen;
273 
274   while (Ptr < End) {
275     uint8_t Type = readVarint7(Ptr);
276     uint32_t Size = readVaruint32(Ptr);
277     const uint8_t *SubSectionEnd = Ptr + Size;
278     switch (Type) {
279     case wasm::WASM_NAMES_FUNCTION: {
280       uint32_t Count = readVaruint32(Ptr);
281       while (Count--) {
282         uint32_t Index = readVaruint32(Ptr);
283         if (!Seen.insert(Index).second)
284           return make_error<GenericBinaryError>("Function named more than once",
285                                                 object_error::parse_failed);
286         StringRef Name = readString(Ptr);
287         if (!Name.empty())
288           Symbols.emplace_back(Name,
289                                WasmSymbol::SymbolType::DEBUG_FUNCTION_NAME,
290                                Sections.size(), Index);
291       }
292       break;
293     }
294     // Ignore local names for now
295     case wasm::WASM_NAMES_LOCAL:
296     default:
297       Ptr += Size;
298       break;
299     }
300     if (Ptr != SubSectionEnd)
301       return make_error<GenericBinaryError>("Name sub-section ended prematurely",
302                                             object_error::parse_failed);
303   }
304 
305   if (Ptr != End)
306     return make_error<GenericBinaryError>("Name section ended prematurely",
307                                           object_error::parse_failed);
308   return Error::success();
309 }
310 
311 void WasmObjectFile::populateSymbolTable() {
312   // Add imports to symbol table
313   size_t GlobalIndex = 0;
314   size_t FunctionIndex = 0;
315   for (const wasm::WasmImport& Import : Imports) {
316     switch (Import.Kind) {
317     case wasm::WASM_EXTERNAL_GLOBAL:
318       assert(Import.Global.Type == wasm::WASM_TYPE_I32);
319       SymbolMap.try_emplace(Import.Field, Symbols.size());
320       Symbols.emplace_back(Import.Field, WasmSymbol::SymbolType::GLOBAL_IMPORT,
321                            ImportSection, GlobalIndex++);
322       DEBUG(dbgs() << "Adding import: " << Symbols.back()
323                    << " sym index:" << Symbols.size() << "\n");
324       break;
325     case wasm::WASM_EXTERNAL_FUNCTION:
326       SymbolMap.try_emplace(Import.Field, Symbols.size());
327       Symbols.emplace_back(Import.Field,
328                            WasmSymbol::SymbolType::FUNCTION_IMPORT,
329                            ImportSection, FunctionIndex++, Import.SigIndex);
330       DEBUG(dbgs() << "Adding import: " << Symbols.back()
331                    << " sym index:" << Symbols.size() << "\n");
332       break;
333     default:
334       break;
335     }
336   }
337 
338   // Add exports to symbol table
339   for (const wasm::WasmExport& Export : Exports) {
340     if (Export.Kind == wasm::WASM_EXTERNAL_FUNCTION ||
341         Export.Kind == wasm::WASM_EXTERNAL_GLOBAL) {
342       WasmSymbol::SymbolType ExportType =
343           Export.Kind == wasm::WASM_EXTERNAL_FUNCTION
344               ? WasmSymbol::SymbolType::FUNCTION_EXPORT
345               : WasmSymbol::SymbolType::GLOBAL_EXPORT;
346       auto Pair = SymbolMap.try_emplace(Export.Name, Symbols.size());
347       if (Pair.second) {
348         Symbols.emplace_back(Export.Name, ExportType,
349                              ExportSection, Export.Index);
350         DEBUG(dbgs() << "Adding export: " << Symbols.back()
351                      << " sym index:" << Symbols.size() << "\n");
352       } else {
353         uint32_t SymIndex = Pair.first->second;
354         const WasmSymbol &OldSym = Symbols[SymIndex];
355         WasmSymbol NewSym(Export.Name, ExportType, ExportSection, Export.Index);
356         NewSym.setAltIndex(OldSym.ElementIndex);
357         Symbols[SymIndex] = NewSym;
358 
359         DEBUG(dbgs() << "Replacing existing symbol:  " << NewSym
360                      << " sym index:" << SymIndex << "\n");
361       }
362     }
363   }
364 }
365 
366 Error WasmObjectFile::parseLinkingSection(const uint8_t *Ptr,
367                                           const uint8_t *End) {
368   HasLinkingSection = true;
369 
370   // Only populate the symbol table with imports and exports if the object
371   // has a linking section (i.e. its a relocatable object file). Otherwise
372   // the global might not represent symbols at all.
373   populateSymbolTable();
374 
375   while (Ptr < End) {
376     uint8_t Type = readVarint7(Ptr);
377     uint32_t Size = readVaruint32(Ptr);
378     const uint8_t *SubSectionEnd = Ptr + Size;
379     switch (Type) {
380     case wasm::WASM_SYMBOL_INFO: {
381       uint32_t Count = readVaruint32(Ptr);
382       while (Count--) {
383         StringRef Symbol = readString(Ptr);
384         uint32_t Flags = readVaruint32(Ptr);
385         auto iter = SymbolMap.find(Symbol);
386         if (iter == SymbolMap.end()) {
387           return make_error<GenericBinaryError>(
388               "Invalid symbol name in linking section: " + Symbol,
389               object_error::parse_failed);
390         }
391         uint32_t SymIndex = iter->second;
392         assert(SymIndex < Symbols.size());
393         Symbols[SymIndex].Flags = Flags;
394         DEBUG(dbgs() << "Set symbol flags index:"
395                      << SymIndex << " name:"
396                      << Symbols[SymIndex].Name << " expected:"
397                      << Symbol << " flags: " << Flags << "\n");
398       }
399       break;
400     }
401     case wasm::WASM_DATA_SIZE:
402       LinkingData.DataSize = readVaruint32(Ptr);
403       break;
404     case wasm::WASM_SEGMENT_INFO: {
405       uint32_t Count = readVaruint32(Ptr);
406       if (Count > DataSegments.size())
407         return make_error<GenericBinaryError>("Too many segment names",
408                                               object_error::parse_failed);
409       for (uint32_t i = 0; i < Count; i++) {
410         DataSegments[i].Data.Name = readString(Ptr);
411         DataSegments[i].Data.Alignment = readVaruint32(Ptr);
412         DataSegments[i].Data.Flags = readVaruint32(Ptr);
413       }
414       break;
415     }
416     case wasm::WASM_INIT_FUNCS: {
417       uint32_t Count = readVaruint32(Ptr);
418       LinkingData.InitFunctions.reserve(Count);
419       for (uint32_t i = 0; i < Count; i++) {
420         wasm::WasmInitFunc Init;
421         Init.Priority = readVaruint32(Ptr);
422         Init.FunctionIndex = readVaruint32(Ptr);
423         if (!isValidFunctionIndex(Init.FunctionIndex))
424           return make_error<GenericBinaryError>("Invalid function index: " +
425                                                     Twine(Init.FunctionIndex),
426                                                 object_error::parse_failed);
427         LinkingData.InitFunctions.emplace_back(Init);
428       }
429       break;
430     }
431     case wasm::WASM_COMDAT_INFO:
432       if (Error Err = parseLinkingSectionComdat(Ptr, SubSectionEnd))
433         return Err;
434       break;
435     default:
436       Ptr += Size;
437       break;
438     }
439     if (Ptr != SubSectionEnd)
440       return make_error<GenericBinaryError>(
441           "Linking sub-section ended prematurely", object_error::parse_failed);
442   }
443   if (Ptr != End)
444     return make_error<GenericBinaryError>("Linking section ended prematurely",
445                                           object_error::parse_failed);
446   return Error::success();
447 }
448 
449 Error WasmObjectFile::parseLinkingSectionComdat(const uint8_t *&Ptr,
450                                                 const uint8_t *End)
451 {
452   uint32_t ComdatCount = readVaruint32(Ptr);
453   StringSet<> ComdatSet;
454   while (ComdatCount--) {
455     StringRef Name = readString(Ptr);
456     if (Name.empty() || !ComdatSet.insert(Name).second)
457       return make_error<GenericBinaryError>("Bad/duplicate COMDAT name " + Twine(Name),
458                                             object_error::parse_failed);
459     Comdats.emplace_back(Name);
460     uint32_t Flags = readVaruint32(Ptr);
461     if (Flags != 0)
462       return make_error<GenericBinaryError>("Unsupported COMDAT flags",
463                                             object_error::parse_failed);
464 
465     uint32_t EntryCount = readVaruint32(Ptr);
466     while (EntryCount--) {
467       unsigned Kind = readVaruint32(Ptr);
468       unsigned Index = readVaruint32(Ptr);
469       switch (Kind) {
470       default:
471         return make_error<GenericBinaryError>("Invalid COMDAT entry type",
472                                               object_error::parse_failed);
473       case wasm::WASM_COMDAT_DATA:
474         if (Index >= DataSegments.size())
475           return make_error<GenericBinaryError>("COMDAT data index out of range",
476                                                 object_error::parse_failed);
477         if (!DataSegments[Index].Data.Comdat.empty())
478           return make_error<GenericBinaryError>("Data segment in two COMDATs",
479                                                 object_error::parse_failed);
480         DataSegments[Index].Data.Comdat = Name;
481         break;
482       case wasm::WASM_COMDAT_FUNCTION:
483         if (Index < NumImportedFunctions || !isValidFunctionIndex(Index))
484           return make_error<GenericBinaryError>("COMDAT function index out of range",
485                                                 object_error::parse_failed);
486         Index -= NumImportedFunctions;
487         if (!Functions[Index].Comdat.empty())
488           return make_error<GenericBinaryError>("Function in two COMDATs",
489                                                 object_error::parse_failed);
490         Functions[Index].Comdat = Name;
491         break;
492       }
493     }
494   }
495   return Error::success();
496 }
497 
498 WasmSection* WasmObjectFile::findCustomSectionByName(StringRef Name) {
499   for (WasmSection& Section : Sections) {
500     if (Section.Type == wasm::WASM_SEC_CUSTOM && Section.Name == Name)
501       return &Section;
502   }
503   return nullptr;
504 }
505 
506 WasmSection* WasmObjectFile::findSectionByType(uint32_t Type) {
507   assert(Type != wasm::WASM_SEC_CUSTOM);
508   for (WasmSection& Section : Sections) {
509     if (Section.Type == Type)
510       return &Section;
511   }
512   return nullptr;
513 }
514 
515 Error WasmObjectFile::parseRelocSection(StringRef Name, const uint8_t *Ptr,
516                                         const uint8_t *End) {
517   uint8_t SectionCode = readVarint7(Ptr);
518   WasmSection* Section = nullptr;
519   if (SectionCode == wasm::WASM_SEC_CUSTOM) {
520     StringRef Name = readString(Ptr);
521     Section = findCustomSectionByName(Name);
522   } else {
523     Section = findSectionByType(SectionCode);
524   }
525   if (!Section)
526     return make_error<GenericBinaryError>("Invalid section code",
527                                           object_error::parse_failed);
528   uint32_t RelocCount = readVaruint32(Ptr);
529   while (RelocCount--) {
530     wasm::WasmRelocation Reloc;
531     memset(&Reloc, 0, sizeof(Reloc));
532     Reloc.Type = readVaruint32(Ptr);
533     Reloc.Offset = readVaruint32(Ptr);
534     Reloc.Index = readVaruint32(Ptr);
535     switch (Reloc.Type) {
536     case wasm::R_WEBASSEMBLY_FUNCTION_INDEX_LEB:
537     case wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB:
538     case wasm::R_WEBASSEMBLY_TABLE_INDEX_I32:
539     case wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB:
540     case wasm::R_WEBASSEMBLY_GLOBAL_INDEX_LEB:
541       break;
542     case wasm::R_WEBASSEMBLY_MEMORY_ADDR_LEB:
543     case wasm::R_WEBASSEMBLY_MEMORY_ADDR_SLEB:
544     case wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32:
545       Reloc.Addend = readVarint32(Ptr);
546       break;
547     default:
548       return make_error<GenericBinaryError>("Bad relocation type: " +
549                                                 Twine(Reloc.Type),
550                                             object_error::parse_failed);
551     }
552     Section->Relocations.push_back(Reloc);
553   }
554   if (Ptr != End)
555     return make_error<GenericBinaryError>("Reloc section ended prematurely",
556                                           object_error::parse_failed);
557   return Error::success();
558 }
559 
560 Error WasmObjectFile::parseCustomSection(WasmSection &Sec,
561                                          const uint8_t *Ptr, const uint8_t *End) {
562   Sec.Name = readString(Ptr);
563   if (Sec.Name == "name") {
564     if (Error Err = parseNameSection(Ptr, End))
565       return Err;
566   } else if (Sec.Name == "linking") {
567     if (Error Err = parseLinkingSection(Ptr, End))
568       return Err;
569   } else if (Sec.Name.startswith("reloc.")) {
570     if (Error Err = parseRelocSection(Sec.Name, Ptr, End))
571       return Err;
572   }
573   return Error::success();
574 }
575 
576 Error WasmObjectFile::parseTypeSection(const uint8_t *Ptr, const uint8_t *End) {
577   uint32_t Count = readVaruint32(Ptr);
578   Signatures.reserve(Count);
579   while (Count--) {
580     wasm::WasmSignature Sig;
581     Sig.ReturnType = wasm::WASM_TYPE_NORESULT;
582     int8_t Form = readVarint7(Ptr);
583     if (Form != wasm::WASM_TYPE_FUNC) {
584       return make_error<GenericBinaryError>("Invalid signature type",
585                                             object_error::parse_failed);
586     }
587     uint32_t ParamCount = readVaruint32(Ptr);
588     Sig.ParamTypes.reserve(ParamCount);
589     while (ParamCount--) {
590       uint32_t ParamType = readVarint7(Ptr);
591       Sig.ParamTypes.push_back(ParamType);
592     }
593     uint32_t ReturnCount = readVaruint32(Ptr);
594     if (ReturnCount) {
595       if (ReturnCount != 1) {
596         return make_error<GenericBinaryError>(
597             "Multiple return types not supported", object_error::parse_failed);
598       }
599       Sig.ReturnType = readVarint7(Ptr);
600     }
601     Signatures.push_back(Sig);
602   }
603   if (Ptr != End)
604     return make_error<GenericBinaryError>("Type section ended prematurely",
605                                           object_error::parse_failed);
606   return Error::success();
607 }
608 
609 Error WasmObjectFile::parseImportSection(const uint8_t *Ptr, const uint8_t *End) {
610   ImportSection = Sections.size();
611   uint32_t Count = readVaruint32(Ptr);
612   Imports.reserve(Count);
613   for (uint32_t i = 0; i < Count; i++) {
614     wasm::WasmImport Im;
615     Im.Module = readString(Ptr);
616     Im.Field = readString(Ptr);
617     Im.Kind = readUint8(Ptr);
618     switch (Im.Kind) {
619     case wasm::WASM_EXTERNAL_FUNCTION:
620       NumImportedFunctions++;
621       Im.SigIndex = readVaruint32(Ptr);
622       break;
623     case wasm::WASM_EXTERNAL_GLOBAL:
624       NumImportedGlobals++;
625       Im.Global.Type = readVarint7(Ptr);
626       Im.Global.Mutable = readVaruint1(Ptr);
627       break;
628     case wasm::WASM_EXTERNAL_MEMORY:
629       Im.Memory = readLimits(Ptr);
630       break;
631     case wasm::WASM_EXTERNAL_TABLE:
632       Im.Table = readTable(Ptr);
633       if (Im.Table.ElemType != wasm::WASM_TYPE_ANYFUNC)
634         return make_error<GenericBinaryError>("Invalid table element type",
635                                               object_error::parse_failed);
636       break;
637     default:
638       return make_error<GenericBinaryError>(
639           "Unexpected import kind", object_error::parse_failed);
640     }
641     Imports.push_back(Im);
642   }
643   if (Ptr != End)
644     return make_error<GenericBinaryError>("Import section ended prematurely",
645                                           object_error::parse_failed);
646   return Error::success();
647 }
648 
649 Error WasmObjectFile::parseFunctionSection(const uint8_t *Ptr, const uint8_t *End) {
650   uint32_t Count = readVaruint32(Ptr);
651   FunctionTypes.reserve(Count);
652   while (Count--) {
653     FunctionTypes.push_back(readVaruint32(Ptr));
654   }
655   if (Ptr != End)
656     return make_error<GenericBinaryError>("Function section ended prematurely",
657                                           object_error::parse_failed);
658   return Error::success();
659 }
660 
661 Error WasmObjectFile::parseTableSection(const uint8_t *Ptr, const uint8_t *End) {
662   uint32_t Count = readVaruint32(Ptr);
663   Tables.reserve(Count);
664   while (Count--) {
665     Tables.push_back(readTable(Ptr));
666     if (Tables.back().ElemType != wasm::WASM_TYPE_ANYFUNC) {
667       return make_error<GenericBinaryError>("Invalid table element type",
668                                             object_error::parse_failed);
669     }
670   }
671   if (Ptr != End)
672     return make_error<GenericBinaryError>("Table section ended prematurely",
673                                           object_error::parse_failed);
674   return Error::success();
675 }
676 
677 Error WasmObjectFile::parseMemorySection(const uint8_t *Ptr, const uint8_t *End) {
678   uint32_t Count = readVaruint32(Ptr);
679   Memories.reserve(Count);
680   while (Count--) {
681     Memories.push_back(readLimits(Ptr));
682   }
683   if (Ptr != End)
684     return make_error<GenericBinaryError>("Memory section ended prematurely",
685                                           object_error::parse_failed);
686   return Error::success();
687 }
688 
689 Error WasmObjectFile::parseGlobalSection(const uint8_t *Ptr, const uint8_t *End) {
690   uint32_t Count = readVaruint32(Ptr);
691   Globals.reserve(Count);
692   while (Count--) {
693     wasm::WasmGlobal Global;
694     Global.Index = NumImportedGlobals + Globals.size();
695     Global.Type = readVarint7(Ptr);
696     Global.Mutable = readVaruint1(Ptr);
697     if (Error Err = readInitExpr(Global.InitExpr, Ptr))
698       return Err;
699     Globals.push_back(Global);
700   }
701   if (Ptr != End)
702     return make_error<GenericBinaryError>("Global section ended prematurely",
703                                           object_error::parse_failed);
704   return Error::success();
705 }
706 
707 Error WasmObjectFile::parseExportSection(const uint8_t *Ptr, const uint8_t *End) {
708   ExportSection = Sections.size();
709   uint32_t Count = readVaruint32(Ptr);
710   Exports.reserve(Count);
711   for (uint32_t i = 0; i < Count; i++) {
712     wasm::WasmExport Ex;
713     Ex.Name = readString(Ptr);
714     Ex.Kind = readUint8(Ptr);
715     Ex.Index = readVaruint32(Ptr);
716     switch (Ex.Kind) {
717     case wasm::WASM_EXTERNAL_FUNCTION:
718       if (Ex.Index >= FunctionTypes.size() + NumImportedFunctions)
719         return make_error<GenericBinaryError>("Invalid function export",
720                                               object_error::parse_failed);
721       break;
722     case wasm::WASM_EXTERNAL_GLOBAL: {
723       if (Ex.Index >= Globals.size() + NumImportedGlobals)
724         return make_error<GenericBinaryError>("Invalid global export",
725                                               object_error::parse_failed);
726       break;
727     }
728     case wasm::WASM_EXTERNAL_MEMORY:
729     case wasm::WASM_EXTERNAL_TABLE:
730       break;
731     default:
732       return make_error<GenericBinaryError>(
733           "Unexpected export kind", object_error::parse_failed);
734     }
735     Exports.push_back(Ex);
736   }
737   if (Ptr != End)
738     return make_error<GenericBinaryError>("Export section ended prematurely",
739                                           object_error::parse_failed);
740   return Error::success();
741 }
742 
743 bool WasmObjectFile::isValidFunctionIndex(uint32_t Index) const {
744   return Index < FunctionTypes.size() + NumImportedFunctions;
745 }
746 
747 Error WasmObjectFile::parseStartSection(const uint8_t *Ptr, const uint8_t *End) {
748   StartFunction = readVaruint32(Ptr);
749   if (!isValidFunctionIndex(StartFunction))
750     return make_error<GenericBinaryError>("Invalid start function",
751                                           object_error::parse_failed);
752   return Error::success();
753 }
754 
755 Error WasmObjectFile::parseCodeSection(const uint8_t *Ptr, const uint8_t *End) {
756   const uint8_t *CodeSectionStart = Ptr;
757   uint32_t FunctionCount = readVaruint32(Ptr);
758   if (FunctionCount != FunctionTypes.size()) {
759     return make_error<GenericBinaryError>("Invalid function count",
760                                           object_error::parse_failed);
761   }
762 
763   while (FunctionCount--) {
764     wasm::WasmFunction Function;
765     const uint8_t *FunctionStart = Ptr;
766     uint32_t Size = readVaruint32(Ptr);
767     const uint8_t *FunctionEnd = Ptr + Size;
768 
769     Function.Index = NumImportedFunctions + Functions.size();
770     Function.CodeSectionOffset = FunctionStart - CodeSectionStart;
771     Function.Size = FunctionEnd - FunctionStart;
772 
773     uint32_t NumLocalDecls = readVaruint32(Ptr);
774     Function.Locals.reserve(NumLocalDecls);
775     while (NumLocalDecls--) {
776       wasm::WasmLocalDecl Decl;
777       Decl.Count = readVaruint32(Ptr);
778       Decl.Type = readVarint7(Ptr);
779       Function.Locals.push_back(Decl);
780     }
781 
782     uint32_t BodySize = FunctionEnd - Ptr;
783     Function.Body = ArrayRef<uint8_t>(Ptr, BodySize);
784     Ptr += BodySize;
785     assert(Ptr == FunctionEnd);
786     Functions.push_back(Function);
787   }
788   if (Ptr != End)
789     return make_error<GenericBinaryError>("Code section ended prematurely",
790                                           object_error::parse_failed);
791   return Error::success();
792 }
793 
794 Error WasmObjectFile::parseElemSection(const uint8_t *Ptr, const uint8_t *End) {
795   uint32_t Count = readVaruint32(Ptr);
796   ElemSegments.reserve(Count);
797   while (Count--) {
798     wasm::WasmElemSegment Segment;
799     Segment.TableIndex = readVaruint32(Ptr);
800     if (Segment.TableIndex != 0) {
801       return make_error<GenericBinaryError>("Invalid TableIndex",
802                                             object_error::parse_failed);
803     }
804     if (Error Err = readInitExpr(Segment.Offset, Ptr))
805       return Err;
806     uint32_t NumElems = readVaruint32(Ptr);
807     while (NumElems--) {
808       Segment.Functions.push_back(readVaruint32(Ptr));
809     }
810     ElemSegments.push_back(Segment);
811   }
812   if (Ptr != End)
813     return make_error<GenericBinaryError>("Elem section ended prematurely",
814                                           object_error::parse_failed);
815   return Error::success();
816 }
817 
818 Error WasmObjectFile::parseDataSection(const uint8_t *Ptr, const uint8_t *End) {
819   const uint8_t *Start = Ptr;
820   uint32_t Count = readVaruint32(Ptr);
821   DataSegments.reserve(Count);
822   while (Count--) {
823     WasmSegment Segment;
824     Segment.Data.MemoryIndex = readVaruint32(Ptr);
825     if (Error Err = readInitExpr(Segment.Data.Offset, Ptr))
826       return Err;
827     uint32_t Size = readVaruint32(Ptr);
828     Segment.Data.Content = ArrayRef<uint8_t>(Ptr, Size);
829     Segment.Data.Alignment = 0;
830     Segment.Data.Flags = 0;
831     Segment.SectionOffset = Ptr - Start;
832     Ptr += Size;
833     DataSegments.push_back(Segment);
834   }
835   if (Ptr != End)
836     return make_error<GenericBinaryError>("Data section ended prematurely",
837                                           object_error::parse_failed);
838   return Error::success();
839 }
840 
841 const uint8_t *WasmObjectFile::getPtr(size_t Offset) const {
842   return reinterpret_cast<const uint8_t *>(getData().substr(Offset, 1).data());
843 }
844 
845 const wasm::WasmObjectHeader &WasmObjectFile::getHeader() const {
846   return Header;
847 }
848 
849 void WasmObjectFile::moveSymbolNext(DataRefImpl &Symb) const { Symb.d.a++; }
850 
851 uint32_t WasmObjectFile::getSymbolFlags(DataRefImpl Symb) const {
852   uint32_t Result = SymbolRef::SF_None;
853   const WasmSymbol &Sym = getWasmSymbol(Symb);
854 
855   DEBUG(dbgs() << "getSymbolFlags: ptr=" << &Sym << " " << Sym << "\n");
856   if (Sym.isWeak())
857     Result |= SymbolRef::SF_Weak;
858   if (!Sym.isLocal())
859     Result |= SymbolRef::SF_Global;
860   if (Sym.isHidden())
861     Result |= SymbolRef::SF_Hidden;
862 
863   switch (Sym.Type) {
864   case WasmSymbol::SymbolType::FUNCTION_IMPORT:
865     Result |= SymbolRef::SF_Undefined | SymbolRef::SF_Executable;
866     break;
867   case WasmSymbol::SymbolType::FUNCTION_EXPORT:
868     Result |= SymbolRef::SF_Executable;
869     break;
870   case WasmSymbol::SymbolType::DEBUG_FUNCTION_NAME:
871     Result |= SymbolRef::SF_Executable;
872     Result |= SymbolRef::SF_FormatSpecific;
873     break;
874   case WasmSymbol::SymbolType::GLOBAL_IMPORT:
875     Result |= SymbolRef::SF_Undefined;
876     break;
877   case WasmSymbol::SymbolType::GLOBAL_EXPORT:
878     break;
879   }
880 
881   return Result;
882 }
883 
884 basic_symbol_iterator WasmObjectFile::symbol_begin() const {
885   DataRefImpl Ref;
886   Ref.d.a = 0;
887   return BasicSymbolRef(Ref, this);
888 }
889 
890 basic_symbol_iterator WasmObjectFile::symbol_end() const {
891   DataRefImpl Ref;
892   Ref.d.a = Symbols.size();
893   return BasicSymbolRef(Ref, this);
894 }
895 
896 const WasmSymbol &WasmObjectFile::getWasmSymbol(const DataRefImpl &Symb) const {
897   return Symbols[Symb.d.a];
898 }
899 
900 const WasmSymbol &WasmObjectFile::getWasmSymbol(const SymbolRef &Symb) const {
901   return getWasmSymbol(Symb.getRawDataRefImpl());
902 }
903 
904 Expected<StringRef> WasmObjectFile::getSymbolName(DataRefImpl Symb) const {
905   return getWasmSymbol(Symb).Name;
906 }
907 
908 Expected<uint64_t> WasmObjectFile::getSymbolAddress(DataRefImpl Symb) const {
909   return getSymbolValue(Symb);
910 }
911 
912 uint64_t WasmObjectFile::getWasmSymbolValue(const WasmSymbol& Sym) const {
913   switch (Sym.Type) {
914   case WasmSymbol::SymbolType::FUNCTION_IMPORT:
915   case WasmSymbol::SymbolType::GLOBAL_IMPORT:
916   case WasmSymbol::SymbolType::FUNCTION_EXPORT:
917   case WasmSymbol::SymbolType::DEBUG_FUNCTION_NAME:
918     return Sym.ElementIndex;
919   case WasmSymbol::SymbolType::GLOBAL_EXPORT: {
920     uint32_t GlobalIndex = Sym.ElementIndex - NumImportedGlobals;
921     assert(GlobalIndex < Globals.size());
922     const wasm::WasmGlobal &Global = Globals[GlobalIndex];
923     // WasmSymbols correspond only to I32_CONST globals
924     assert(Global.InitExpr.Opcode == wasm::WASM_OPCODE_I32_CONST);
925     return Global.InitExpr.Value.Int32;
926   }
927   }
928   llvm_unreachable("invalid symbol type");
929 }
930 
931 uint64_t WasmObjectFile::getSymbolValueImpl(DataRefImpl Symb) const {
932   return getWasmSymbolValue(getWasmSymbol(Symb));
933 }
934 
935 uint32_t WasmObjectFile::getSymbolAlignment(DataRefImpl Symb) const {
936   llvm_unreachable("not yet implemented");
937   return 0;
938 }
939 
940 uint64_t WasmObjectFile::getCommonSymbolSizeImpl(DataRefImpl Symb) const {
941   llvm_unreachable("not yet implemented");
942   return 0;
943 }
944 
945 Expected<SymbolRef::Type>
946 WasmObjectFile::getSymbolType(DataRefImpl Symb) const {
947   const WasmSymbol &Sym = getWasmSymbol(Symb);
948 
949   switch (Sym.Type) {
950   case WasmSymbol::SymbolType::FUNCTION_IMPORT:
951   case WasmSymbol::SymbolType::FUNCTION_EXPORT:
952   case WasmSymbol::SymbolType::DEBUG_FUNCTION_NAME:
953     return SymbolRef::ST_Function;
954   case WasmSymbol::SymbolType::GLOBAL_IMPORT:
955   case WasmSymbol::SymbolType::GLOBAL_EXPORT:
956     return SymbolRef::ST_Data;
957   }
958 
959   llvm_unreachable("Unknown WasmSymbol::SymbolType");
960   return SymbolRef::ST_Other;
961 }
962 
963 Expected<section_iterator>
964 WasmObjectFile::getSymbolSection(DataRefImpl Symb) const {
965   DataRefImpl Ref;
966   Ref.d.a = getWasmSymbol(Symb).Section;
967   return section_iterator(SectionRef(Ref, this));
968 }
969 
970 void WasmObjectFile::moveSectionNext(DataRefImpl &Sec) const { Sec.d.a++; }
971 
972 std::error_code WasmObjectFile::getSectionName(DataRefImpl Sec,
973                                                StringRef &Res) const {
974   const WasmSection &S = Sections[Sec.d.a];
975 #define ECase(X)                                                               \
976   case wasm::WASM_SEC_##X:                                                     \
977     Res = #X;                                                                  \
978     break
979   switch (S.Type) {
980     ECase(TYPE);
981     ECase(IMPORT);
982     ECase(FUNCTION);
983     ECase(TABLE);
984     ECase(MEMORY);
985     ECase(GLOBAL);
986     ECase(EXPORT);
987     ECase(START);
988     ECase(ELEM);
989     ECase(CODE);
990     ECase(DATA);
991   case wasm::WASM_SEC_CUSTOM:
992     Res = S.Name;
993     break;
994   default:
995     return object_error::invalid_section_index;
996   }
997 #undef ECase
998   return std::error_code();
999 }
1000 
1001 uint64_t WasmObjectFile::getSectionAddress(DataRefImpl Sec) const { return 0; }
1002 
1003 uint64_t WasmObjectFile::getSectionIndex(DataRefImpl Sec) const {
1004   return Sec.d.a;
1005 }
1006 
1007 uint64_t WasmObjectFile::getSectionSize(DataRefImpl Sec) const {
1008   const WasmSection &S = Sections[Sec.d.a];
1009   return S.Content.size();
1010 }
1011 
1012 std::error_code WasmObjectFile::getSectionContents(DataRefImpl Sec,
1013                                                    StringRef &Res) const {
1014   const WasmSection &S = Sections[Sec.d.a];
1015   // This will never fail since wasm sections can never be empty (user-sections
1016   // must have a name and non-user sections each have a defined structure).
1017   Res = StringRef(reinterpret_cast<const char *>(S.Content.data()),
1018                   S.Content.size());
1019   return std::error_code();
1020 }
1021 
1022 uint64_t WasmObjectFile::getSectionAlignment(DataRefImpl Sec) const {
1023   return 1;
1024 }
1025 
1026 bool WasmObjectFile::isSectionCompressed(DataRefImpl Sec) const {
1027   return false;
1028 }
1029 
1030 bool WasmObjectFile::isSectionText(DataRefImpl Sec) const {
1031   return getWasmSection(Sec).Type == wasm::WASM_SEC_CODE;
1032 }
1033 
1034 bool WasmObjectFile::isSectionData(DataRefImpl Sec) const {
1035   return getWasmSection(Sec).Type == wasm::WASM_SEC_DATA;
1036 }
1037 
1038 bool WasmObjectFile::isSectionBSS(DataRefImpl Sec) const { return false; }
1039 
1040 bool WasmObjectFile::isSectionVirtual(DataRefImpl Sec) const { return false; }
1041 
1042 bool WasmObjectFile::isSectionBitcode(DataRefImpl Sec) const { return false; }
1043 
1044 relocation_iterator WasmObjectFile::section_rel_begin(DataRefImpl Ref) const {
1045   DataRefImpl RelocRef;
1046   RelocRef.d.a = Ref.d.a;
1047   RelocRef.d.b = 0;
1048   return relocation_iterator(RelocationRef(RelocRef, this));
1049 }
1050 
1051 relocation_iterator WasmObjectFile::section_rel_end(DataRefImpl Ref) const {
1052   const WasmSection &Sec = getWasmSection(Ref);
1053   DataRefImpl RelocRef;
1054   RelocRef.d.a = Ref.d.a;
1055   RelocRef.d.b = Sec.Relocations.size();
1056   return relocation_iterator(RelocationRef(RelocRef, this));
1057 }
1058 
1059 void WasmObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
1060   Rel.d.b++;
1061 }
1062 
1063 uint64_t WasmObjectFile::getRelocationOffset(DataRefImpl Ref) const {
1064   const wasm::WasmRelocation &Rel = getWasmRelocation(Ref);
1065   return Rel.Offset;
1066 }
1067 
1068 symbol_iterator WasmObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
1069   llvm_unreachable("not yet implemented");
1070   SymbolRef Ref;
1071   return symbol_iterator(Ref);
1072 }
1073 
1074 uint64_t WasmObjectFile::getRelocationType(DataRefImpl Ref) const {
1075   const wasm::WasmRelocation &Rel = getWasmRelocation(Ref);
1076   return Rel.Type;
1077 }
1078 
1079 void WasmObjectFile::getRelocationTypeName(
1080     DataRefImpl Ref, SmallVectorImpl<char> &Result) const {
1081   const wasm::WasmRelocation& Rel = getWasmRelocation(Ref);
1082   StringRef Res = "Unknown";
1083 
1084 #define WASM_RELOC(name, value)  \
1085   case wasm::name:              \
1086     Res = #name;               \
1087     break;
1088 
1089   switch (Rel.Type) {
1090 #include "llvm/BinaryFormat/WasmRelocs.def"
1091   }
1092 
1093 #undef WASM_RELOC
1094 
1095   Result.append(Res.begin(), Res.end());
1096 }
1097 
1098 section_iterator WasmObjectFile::section_begin() const {
1099   DataRefImpl Ref;
1100   Ref.d.a = 0;
1101   return section_iterator(SectionRef(Ref, this));
1102 }
1103 
1104 section_iterator WasmObjectFile::section_end() const {
1105   DataRefImpl Ref;
1106   Ref.d.a = Sections.size();
1107   return section_iterator(SectionRef(Ref, this));
1108 }
1109 
1110 uint8_t WasmObjectFile::getBytesInAddress() const { return 4; }
1111 
1112 StringRef WasmObjectFile::getFileFormatName() const { return "WASM"; }
1113 
1114 Triple::ArchType WasmObjectFile::getArch() const { return Triple::wasm32; }
1115 
1116 SubtargetFeatures WasmObjectFile::getFeatures() const {
1117   return SubtargetFeatures();
1118 }
1119 
1120 bool WasmObjectFile::isRelocatableObject() const {
1121   return HasLinkingSection;
1122 }
1123 
1124 const WasmSection &WasmObjectFile::getWasmSection(DataRefImpl Ref) const {
1125   assert(Ref.d.a < Sections.size());
1126   return Sections[Ref.d.a];
1127 }
1128 
1129 const WasmSection &
1130 WasmObjectFile::getWasmSection(const SectionRef &Section) const {
1131   return getWasmSection(Section.getRawDataRefImpl());
1132 }
1133 
1134 const wasm::WasmRelocation &
1135 WasmObjectFile::getWasmRelocation(const RelocationRef &Ref) const {
1136   return getWasmRelocation(Ref.getRawDataRefImpl());
1137 }
1138 
1139 const wasm::WasmRelocation &
1140 WasmObjectFile::getWasmRelocation(DataRefImpl Ref) const {
1141   assert(Ref.d.a < Sections.size());
1142   const WasmSection& Sec = Sections[Ref.d.a];
1143   assert(Ref.d.b < Sec.Relocations.size());
1144   return Sec.Relocations[Ref.d.b];
1145 }
1146