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   if (Functions.size() != FunctionTypes.size()) {
274     return make_error<GenericBinaryError>("Names must come after code section",
275                                           object_error::parse_failed);
276   }
277 
278   while (Ptr < End) {
279     uint8_t Type = readVarint7(Ptr);
280     uint32_t Size = readVaruint32(Ptr);
281     const uint8_t *SubSectionEnd = Ptr + Size;
282     switch (Type) {
283     case wasm::WASM_NAMES_FUNCTION: {
284       uint32_t Count = readVaruint32(Ptr);
285       while (Count--) {
286         uint32_t Index = readVaruint32(Ptr);
287         if (!Seen.insert(Index).second)
288           return make_error<GenericBinaryError>("Function named more than once",
289                                                 object_error::parse_failed);
290         StringRef Name = readString(Ptr);
291         if (!isValidFunctionIndex(Index) || Name.empty())
292           return make_error<GenericBinaryError>("Invalid name entry",
293                                                 object_error::parse_failed);
294         DebugNames.push_back(wasm::WasmFunctionName{Index, Name});
295         if (isDefinedFunctionIndex(Index)) {
296           // Override any existing name; the name specified by the "names"
297           // section is the Function's canonical name.
298           getDefinedFunction(Index).Name = Name;
299         }
300       }
301       break;
302     }
303     // Ignore local names for now
304     case wasm::WASM_NAMES_LOCAL:
305     default:
306       Ptr += Size;
307       break;
308     }
309     if (Ptr != SubSectionEnd)
310       return make_error<GenericBinaryError>("Name sub-section ended prematurely",
311                                             object_error::parse_failed);
312   }
313 
314   if (Ptr != End)
315     return make_error<GenericBinaryError>("Name section ended prematurely",
316                                           object_error::parse_failed);
317   return Error::success();
318 }
319 
320 void WasmObjectFile::populateSymbolTable() {
321   // Add imports to symbol table
322   size_t GlobalIndex = 0;
323   size_t FunctionIndex = 0;
324   for (const wasm::WasmImport& Import : Imports) {
325     switch (Import.Kind) {
326     case wasm::WASM_EXTERNAL_GLOBAL:
327       assert(Import.Global.Type == wasm::WASM_TYPE_I32);
328       SymbolMap.try_emplace(Import.Field, Symbols.size());
329       Symbols.emplace_back(Import.Field, WasmSymbol::SymbolType::GLOBAL_IMPORT,
330                            ImportSection, GlobalIndex++);
331       DEBUG(dbgs() << "Adding import: " << Symbols.back()
332                    << " sym index:" << Symbols.size() << "\n");
333       break;
334     case wasm::WASM_EXTERNAL_FUNCTION:
335       SymbolMap.try_emplace(Import.Field, Symbols.size());
336       Symbols.emplace_back(Import.Field,
337                            WasmSymbol::SymbolType::FUNCTION_IMPORT,
338                            ImportSection, FunctionIndex++, Import.SigIndex);
339       DEBUG(dbgs() << "Adding import: " << Symbols.back()
340                    << " sym index:" << Symbols.size() << "\n");
341       break;
342     default:
343       break;
344     }
345   }
346 
347   // Add exports to symbol table
348   for (const wasm::WasmExport& Export : Exports) {
349     if (Export.Kind == wasm::WASM_EXTERNAL_FUNCTION ||
350         Export.Kind == wasm::WASM_EXTERNAL_GLOBAL) {
351       WasmSymbol::SymbolType ExportType =
352           Export.Kind == wasm::WASM_EXTERNAL_FUNCTION
353               ? WasmSymbol::SymbolType::FUNCTION_EXPORT
354               : WasmSymbol::SymbolType::GLOBAL_EXPORT;
355       auto Pair = SymbolMap.try_emplace(Export.Name, Symbols.size());
356       if (Pair.second) {
357         Symbols.emplace_back(Export.Name, ExportType,
358                              ExportSection, Export.Index);
359         DEBUG(dbgs() << "Adding export: " << Symbols.back()
360                      << " sym index:" << Symbols.size() << "\n");
361       } else {
362         uint32_t SymIndex = Pair.first->second;
363         const WasmSymbol &OldSym = Symbols[SymIndex];
364         WasmSymbol NewSym(Export.Name, ExportType, ExportSection, Export.Index);
365         NewSym.setAltIndex(OldSym.ElementIndex);
366         Symbols[SymIndex] = NewSym;
367 
368         DEBUG(dbgs() << "Replacing existing symbol:  " << NewSym
369                      << " sym index:" << SymIndex << "\n");
370       }
371     }
372     if (Export.Kind == wasm::WASM_EXTERNAL_FUNCTION &&
373         isDefinedFunctionIndex(Export.Index)) {
374       auto &Function = getDefinedFunction(Export.Index);
375       if (Function.Name.empty()) {
376         // Use the export's name to set a name for the Function, but only if one
377         // hasn't already been set.
378         Function.Name = Export.Name;
379       }
380     }
381   }
382 }
383 
384 Error WasmObjectFile::parseLinkingSection(const uint8_t *Ptr,
385                                           const uint8_t *End) {
386   HasLinkingSection = true;
387   if (Functions.size() != FunctionTypes.size()) {
388     return make_error<GenericBinaryError>(
389         "Linking data must come after code section", object_error::parse_failed);
390   }
391 
392   // Only populate the symbol table with imports and exports if the object
393   // has a linking section (i.e. its a relocatable object file). Otherwise
394   // the global might not represent symbols at all.
395   populateSymbolTable();
396 
397   while (Ptr < End) {
398     uint8_t Type = readVarint7(Ptr);
399     uint32_t Size = readVaruint32(Ptr);
400     const uint8_t *SubSectionEnd = Ptr + Size;
401     switch (Type) {
402     case wasm::WASM_SYMBOL_INFO: {
403       uint32_t Count = readVaruint32(Ptr);
404       while (Count--) {
405         StringRef Symbol = readString(Ptr);
406         uint32_t Flags = readVaruint32(Ptr);
407         auto iter = SymbolMap.find(Symbol);
408         if (iter == SymbolMap.end()) {
409           return make_error<GenericBinaryError>(
410               "Invalid symbol name in linking section: " + Symbol,
411               object_error::parse_failed);
412         }
413         uint32_t SymIndex = iter->second;
414         assert(SymIndex < Symbols.size());
415         Symbols[SymIndex].Flags = Flags;
416         DEBUG(dbgs() << "Set symbol flags index:"
417                      << SymIndex << " name:"
418                      << Symbols[SymIndex].Name << " expected:"
419                      << Symbol << " flags: " << Flags << "\n");
420       }
421       break;
422     }
423     case wasm::WASM_DATA_SIZE:
424       LinkingData.DataSize = readVaruint32(Ptr);
425       break;
426     case wasm::WASM_SEGMENT_INFO: {
427       uint32_t Count = readVaruint32(Ptr);
428       if (Count > DataSegments.size())
429         return make_error<GenericBinaryError>("Too many segment names",
430                                               object_error::parse_failed);
431       for (uint32_t i = 0; i < Count; i++) {
432         DataSegments[i].Data.Name = readString(Ptr);
433         DataSegments[i].Data.Alignment = readVaruint32(Ptr);
434         DataSegments[i].Data.Flags = readVaruint32(Ptr);
435       }
436       break;
437     }
438     case wasm::WASM_INIT_FUNCS: {
439       uint32_t Count = readVaruint32(Ptr);
440       LinkingData.InitFunctions.reserve(Count);
441       for (uint32_t i = 0; i < Count; i++) {
442         wasm::WasmInitFunc Init;
443         Init.Priority = readVaruint32(Ptr);
444         Init.FunctionIndex = readVaruint32(Ptr);
445         if (!isValidFunctionIndex(Init.FunctionIndex))
446           return make_error<GenericBinaryError>("Invalid function index: " +
447                                                     Twine(Init.FunctionIndex),
448                                                 object_error::parse_failed);
449         LinkingData.InitFunctions.emplace_back(Init);
450       }
451       break;
452     }
453     case wasm::WASM_COMDAT_INFO:
454       if (Error Err = parseLinkingSectionComdat(Ptr, SubSectionEnd))
455         return Err;
456       break;
457     default:
458       Ptr += Size;
459       break;
460     }
461     if (Ptr != SubSectionEnd)
462       return make_error<GenericBinaryError>(
463           "Linking sub-section ended prematurely", object_error::parse_failed);
464   }
465   if (Ptr != End)
466     return make_error<GenericBinaryError>("Linking section ended prematurely",
467                                           object_error::parse_failed);
468   return Error::success();
469 }
470 
471 Error WasmObjectFile::parseLinkingSectionComdat(const uint8_t *&Ptr,
472                                                 const uint8_t *End)
473 {
474   uint32_t ComdatCount = readVaruint32(Ptr);
475   StringSet<> ComdatSet;
476   while (ComdatCount--) {
477     StringRef Name = readString(Ptr);
478     if (Name.empty() || !ComdatSet.insert(Name).second)
479       return make_error<GenericBinaryError>("Bad/duplicate COMDAT name " + Twine(Name),
480                                             object_error::parse_failed);
481     Comdats.emplace_back(Name);
482     uint32_t Flags = readVaruint32(Ptr);
483     if (Flags != 0)
484       return make_error<GenericBinaryError>("Unsupported COMDAT flags",
485                                             object_error::parse_failed);
486 
487     uint32_t EntryCount = readVaruint32(Ptr);
488     while (EntryCount--) {
489       unsigned Kind = readVaruint32(Ptr);
490       unsigned Index = readVaruint32(Ptr);
491       switch (Kind) {
492       default:
493         return make_error<GenericBinaryError>("Invalid COMDAT entry type",
494                                               object_error::parse_failed);
495       case wasm::WASM_COMDAT_DATA:
496         if (Index >= DataSegments.size())
497           return make_error<GenericBinaryError>("COMDAT data index out of range",
498                                                 object_error::parse_failed);
499         if (!DataSegments[Index].Data.Comdat.empty())
500           return make_error<GenericBinaryError>("Data segment in two COMDATs",
501                                                 object_error::parse_failed);
502         DataSegments[Index].Data.Comdat = Name;
503         break;
504       case wasm::WASM_COMDAT_FUNCTION:
505         if (!isDefinedFunctionIndex(Index))
506           return make_error<GenericBinaryError>("COMDAT function index out of range",
507                                                 object_error::parse_failed);
508         if (!getDefinedFunction(Index).Comdat.empty())
509           return make_error<GenericBinaryError>("Function in two COMDATs",
510                                                 object_error::parse_failed);
511         getDefinedFunction(Index).Comdat = Name;
512         break;
513       }
514     }
515   }
516   return Error::success();
517 }
518 
519 WasmSection* WasmObjectFile::findCustomSectionByName(StringRef Name) {
520   for (WasmSection& Section : Sections) {
521     if (Section.Type == wasm::WASM_SEC_CUSTOM && Section.Name == Name)
522       return &Section;
523   }
524   return nullptr;
525 }
526 
527 WasmSection* WasmObjectFile::findSectionByType(uint32_t Type) {
528   assert(Type != wasm::WASM_SEC_CUSTOM);
529   for (WasmSection& Section : Sections) {
530     if (Section.Type == Type)
531       return &Section;
532   }
533   return nullptr;
534 }
535 
536 Error WasmObjectFile::parseRelocSection(StringRef Name, const uint8_t *Ptr,
537                                         const uint8_t *End) {
538   uint8_t SectionCode = readVarint7(Ptr);
539   WasmSection* Section = nullptr;
540   if (SectionCode == wasm::WASM_SEC_CUSTOM) {
541     StringRef Name = readString(Ptr);
542     Section = findCustomSectionByName(Name);
543   } else {
544     Section = findSectionByType(SectionCode);
545   }
546   if (!Section)
547     return make_error<GenericBinaryError>("Invalid section code",
548                                           object_error::parse_failed);
549   uint32_t RelocCount = readVaruint32(Ptr);
550   while (RelocCount--) {
551     wasm::WasmRelocation Reloc;
552     memset(&Reloc, 0, sizeof(Reloc));
553     Reloc.Type = readVaruint32(Ptr);
554     Reloc.Offset = readVaruint32(Ptr);
555     Reloc.Index = readVaruint32(Ptr);
556     switch (Reloc.Type) {
557     case wasm::R_WEBASSEMBLY_FUNCTION_INDEX_LEB:
558     case wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB:
559     case wasm::R_WEBASSEMBLY_TABLE_INDEX_I32:
560     case wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB:
561     case wasm::R_WEBASSEMBLY_GLOBAL_INDEX_LEB:
562       break;
563     case wasm::R_WEBASSEMBLY_MEMORY_ADDR_LEB:
564     case wasm::R_WEBASSEMBLY_MEMORY_ADDR_SLEB:
565     case wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32:
566       Reloc.Addend = readVarint32(Ptr);
567       break;
568     default:
569       return make_error<GenericBinaryError>("Bad relocation type: " +
570                                                 Twine(Reloc.Type),
571                                             object_error::parse_failed);
572     }
573     Section->Relocations.push_back(Reloc);
574   }
575   if (Ptr != End)
576     return make_error<GenericBinaryError>("Reloc section ended prematurely",
577                                           object_error::parse_failed);
578   return Error::success();
579 }
580 
581 Error WasmObjectFile::parseCustomSection(WasmSection &Sec,
582                                          const uint8_t *Ptr, const uint8_t *End) {
583   Sec.Name = readString(Ptr);
584   if (Sec.Name == "name") {
585     if (Error Err = parseNameSection(Ptr, End))
586       return Err;
587   } else if (Sec.Name == "linking") {
588     if (Error Err = parseLinkingSection(Ptr, End))
589       return Err;
590   } else if (Sec.Name.startswith("reloc.")) {
591     if (Error Err = parseRelocSection(Sec.Name, Ptr, End))
592       return Err;
593   }
594   return Error::success();
595 }
596 
597 Error WasmObjectFile::parseTypeSection(const uint8_t *Ptr, const uint8_t *End) {
598   uint32_t Count = readVaruint32(Ptr);
599   Signatures.reserve(Count);
600   while (Count--) {
601     wasm::WasmSignature Sig;
602     Sig.ReturnType = wasm::WASM_TYPE_NORESULT;
603     int8_t Form = readVarint7(Ptr);
604     if (Form != wasm::WASM_TYPE_FUNC) {
605       return make_error<GenericBinaryError>("Invalid signature type",
606                                             object_error::parse_failed);
607     }
608     uint32_t ParamCount = readVaruint32(Ptr);
609     Sig.ParamTypes.reserve(ParamCount);
610     while (ParamCount--) {
611       uint32_t ParamType = readVarint7(Ptr);
612       Sig.ParamTypes.push_back(ParamType);
613     }
614     uint32_t ReturnCount = readVaruint32(Ptr);
615     if (ReturnCount) {
616       if (ReturnCount != 1) {
617         return make_error<GenericBinaryError>(
618             "Multiple return types not supported", object_error::parse_failed);
619       }
620       Sig.ReturnType = readVarint7(Ptr);
621     }
622     Signatures.push_back(Sig);
623   }
624   if (Ptr != End)
625     return make_error<GenericBinaryError>("Type section ended prematurely",
626                                           object_error::parse_failed);
627   return Error::success();
628 }
629 
630 Error WasmObjectFile::parseImportSection(const uint8_t *Ptr, const uint8_t *End) {
631   ImportSection = Sections.size();
632   uint32_t Count = readVaruint32(Ptr);
633   Imports.reserve(Count);
634   for (uint32_t i = 0; i < Count; i++) {
635     wasm::WasmImport Im;
636     Im.Module = readString(Ptr);
637     Im.Field = readString(Ptr);
638     Im.Kind = readUint8(Ptr);
639     switch (Im.Kind) {
640     case wasm::WASM_EXTERNAL_FUNCTION:
641       NumImportedFunctions++;
642       Im.SigIndex = readVaruint32(Ptr);
643       break;
644     case wasm::WASM_EXTERNAL_GLOBAL:
645       NumImportedGlobals++;
646       Im.Global.Type = readVarint7(Ptr);
647       Im.Global.Mutable = readVaruint1(Ptr);
648       break;
649     case wasm::WASM_EXTERNAL_MEMORY:
650       Im.Memory = readLimits(Ptr);
651       break;
652     case wasm::WASM_EXTERNAL_TABLE:
653       Im.Table = readTable(Ptr);
654       if (Im.Table.ElemType != wasm::WASM_TYPE_ANYFUNC)
655         return make_error<GenericBinaryError>("Invalid table element type",
656                                               object_error::parse_failed);
657       break;
658     default:
659       return make_error<GenericBinaryError>(
660           "Unexpected import kind", object_error::parse_failed);
661     }
662     Imports.push_back(Im);
663   }
664   if (Ptr != End)
665     return make_error<GenericBinaryError>("Import section ended prematurely",
666                                           object_error::parse_failed);
667   return Error::success();
668 }
669 
670 Error WasmObjectFile::parseFunctionSection(const uint8_t *Ptr, const uint8_t *End) {
671   uint32_t Count = readVaruint32(Ptr);
672   FunctionTypes.reserve(Count);
673   while (Count--) {
674     FunctionTypes.push_back(readVaruint32(Ptr));
675   }
676   if (Ptr != End)
677     return make_error<GenericBinaryError>("Function section ended prematurely",
678                                           object_error::parse_failed);
679   return Error::success();
680 }
681 
682 Error WasmObjectFile::parseTableSection(const uint8_t *Ptr, const uint8_t *End) {
683   uint32_t Count = readVaruint32(Ptr);
684   Tables.reserve(Count);
685   while (Count--) {
686     Tables.push_back(readTable(Ptr));
687     if (Tables.back().ElemType != wasm::WASM_TYPE_ANYFUNC) {
688       return make_error<GenericBinaryError>("Invalid table element type",
689                                             object_error::parse_failed);
690     }
691   }
692   if (Ptr != End)
693     return make_error<GenericBinaryError>("Table section ended prematurely",
694                                           object_error::parse_failed);
695   return Error::success();
696 }
697 
698 Error WasmObjectFile::parseMemorySection(const uint8_t *Ptr, const uint8_t *End) {
699   uint32_t Count = readVaruint32(Ptr);
700   Memories.reserve(Count);
701   while (Count--) {
702     Memories.push_back(readLimits(Ptr));
703   }
704   if (Ptr != End)
705     return make_error<GenericBinaryError>("Memory section ended prematurely",
706                                           object_error::parse_failed);
707   return Error::success();
708 }
709 
710 Error WasmObjectFile::parseGlobalSection(const uint8_t *Ptr, const uint8_t *End) {
711   uint32_t Count = readVaruint32(Ptr);
712   Globals.reserve(Count);
713   while (Count--) {
714     wasm::WasmGlobal Global;
715     Global.Index = NumImportedGlobals + Globals.size();
716     Global.Type = readVarint7(Ptr);
717     Global.Mutable = readVaruint1(Ptr);
718     if (Error Err = readInitExpr(Global.InitExpr, Ptr))
719       return Err;
720     Globals.push_back(Global);
721   }
722   if (Ptr != End)
723     return make_error<GenericBinaryError>("Global section ended prematurely",
724                                           object_error::parse_failed);
725   return Error::success();
726 }
727 
728 Error WasmObjectFile::parseExportSection(const uint8_t *Ptr, const uint8_t *End) {
729   ExportSection = Sections.size();
730   uint32_t Count = readVaruint32(Ptr);
731   Exports.reserve(Count);
732   for (uint32_t i = 0; i < Count; i++) {
733     wasm::WasmExport Ex;
734     Ex.Name = readString(Ptr);
735     Ex.Kind = readUint8(Ptr);
736     Ex.Index = readVaruint32(Ptr);
737     switch (Ex.Kind) {
738     case wasm::WASM_EXTERNAL_FUNCTION:
739       if (!isValidFunctionIndex(Ex.Index))
740         return make_error<GenericBinaryError>("Invalid function export",
741                                               object_error::parse_failed);
742       break;
743     case wasm::WASM_EXTERNAL_GLOBAL: {
744       if (Ex.Index >= Globals.size() + NumImportedGlobals)
745         return make_error<GenericBinaryError>("Invalid global export",
746                                               object_error::parse_failed);
747       break;
748     }
749     case wasm::WASM_EXTERNAL_MEMORY:
750     case wasm::WASM_EXTERNAL_TABLE:
751       break;
752     default:
753       return make_error<GenericBinaryError>(
754           "Unexpected export kind", object_error::parse_failed);
755     }
756     Exports.push_back(Ex);
757   }
758   if (Ptr != End)
759     return make_error<GenericBinaryError>("Export section ended prematurely",
760                                           object_error::parse_failed);
761   return Error::success();
762 }
763 
764 bool WasmObjectFile::isValidFunctionIndex(uint32_t Index) const {
765   return Index < FunctionTypes.size() + NumImportedFunctions;
766 }
767 
768 bool WasmObjectFile::isDefinedFunctionIndex(uint32_t Index) const {
769   return Index >= NumImportedFunctions && isValidFunctionIndex(Index);
770 }
771 
772 wasm::WasmFunction& WasmObjectFile::getDefinedFunction(uint32_t Index) {
773   assert(isDefinedFunctionIndex(Index));
774   return Functions[Index - NumImportedFunctions];
775 }
776 
777 Error WasmObjectFile::parseStartSection(const uint8_t *Ptr, const uint8_t *End) {
778   StartFunction = readVaruint32(Ptr);
779   if (!isValidFunctionIndex(StartFunction))
780     return make_error<GenericBinaryError>("Invalid start function",
781                                           object_error::parse_failed);
782   return Error::success();
783 }
784 
785 Error WasmObjectFile::parseCodeSection(const uint8_t *Ptr, const uint8_t *End) {
786   const uint8_t *CodeSectionStart = Ptr;
787   uint32_t FunctionCount = readVaruint32(Ptr);
788   if (FunctionCount != FunctionTypes.size()) {
789     return make_error<GenericBinaryError>("Invalid function count",
790                                           object_error::parse_failed);
791   }
792 
793   while (FunctionCount--) {
794     wasm::WasmFunction Function;
795     const uint8_t *FunctionStart = Ptr;
796     uint32_t Size = readVaruint32(Ptr);
797     const uint8_t *FunctionEnd = Ptr + Size;
798 
799     Function.Index = NumImportedFunctions + Functions.size();
800     Function.CodeSectionOffset = FunctionStart - CodeSectionStart;
801     Function.Size = FunctionEnd - FunctionStart;
802 
803     uint32_t NumLocalDecls = readVaruint32(Ptr);
804     Function.Locals.reserve(NumLocalDecls);
805     while (NumLocalDecls--) {
806       wasm::WasmLocalDecl Decl;
807       Decl.Count = readVaruint32(Ptr);
808       Decl.Type = readVarint7(Ptr);
809       Function.Locals.push_back(Decl);
810     }
811 
812     uint32_t BodySize = FunctionEnd - Ptr;
813     Function.Body = ArrayRef<uint8_t>(Ptr, BodySize);
814     Ptr += BodySize;
815     assert(Ptr == FunctionEnd);
816     Functions.push_back(Function);
817   }
818   if (Ptr != End)
819     return make_error<GenericBinaryError>("Code section ended prematurely",
820                                           object_error::parse_failed);
821   return Error::success();
822 }
823 
824 Error WasmObjectFile::parseElemSection(const uint8_t *Ptr, const uint8_t *End) {
825   uint32_t Count = readVaruint32(Ptr);
826   ElemSegments.reserve(Count);
827   while (Count--) {
828     wasm::WasmElemSegment Segment;
829     Segment.TableIndex = readVaruint32(Ptr);
830     if (Segment.TableIndex != 0) {
831       return make_error<GenericBinaryError>("Invalid TableIndex",
832                                             object_error::parse_failed);
833     }
834     if (Error Err = readInitExpr(Segment.Offset, Ptr))
835       return Err;
836     uint32_t NumElems = readVaruint32(Ptr);
837     while (NumElems--) {
838       Segment.Functions.push_back(readVaruint32(Ptr));
839     }
840     ElemSegments.push_back(Segment);
841   }
842   if (Ptr != End)
843     return make_error<GenericBinaryError>("Elem section ended prematurely",
844                                           object_error::parse_failed);
845   return Error::success();
846 }
847 
848 Error WasmObjectFile::parseDataSection(const uint8_t *Ptr, const uint8_t *End) {
849   const uint8_t *Start = Ptr;
850   uint32_t Count = readVaruint32(Ptr);
851   DataSegments.reserve(Count);
852   while (Count--) {
853     WasmSegment Segment;
854     Segment.Data.MemoryIndex = readVaruint32(Ptr);
855     if (Error Err = readInitExpr(Segment.Data.Offset, Ptr))
856       return Err;
857     uint32_t Size = readVaruint32(Ptr);
858     Segment.Data.Content = ArrayRef<uint8_t>(Ptr, Size);
859     Segment.Data.Alignment = 0;
860     Segment.Data.Flags = 0;
861     Segment.SectionOffset = Ptr - Start;
862     Ptr += Size;
863     DataSegments.push_back(Segment);
864   }
865   if (Ptr != End)
866     return make_error<GenericBinaryError>("Data section ended prematurely",
867                                           object_error::parse_failed);
868   return Error::success();
869 }
870 
871 const uint8_t *WasmObjectFile::getPtr(size_t Offset) const {
872   return reinterpret_cast<const uint8_t *>(getData().substr(Offset, 1).data());
873 }
874 
875 const wasm::WasmObjectHeader &WasmObjectFile::getHeader() const {
876   return Header;
877 }
878 
879 void WasmObjectFile::moveSymbolNext(DataRefImpl &Symb) const { Symb.d.a++; }
880 
881 uint32_t WasmObjectFile::getSymbolFlags(DataRefImpl Symb) const {
882   uint32_t Result = SymbolRef::SF_None;
883   const WasmSymbol &Sym = getWasmSymbol(Symb);
884 
885   DEBUG(dbgs() << "getSymbolFlags: ptr=" << &Sym << " " << Sym << "\n");
886   if (Sym.isWeak())
887     Result |= SymbolRef::SF_Weak;
888   if (!Sym.isLocal())
889     Result |= SymbolRef::SF_Global;
890   if (Sym.isHidden())
891     Result |= SymbolRef::SF_Hidden;
892 
893   switch (Sym.Type) {
894   case WasmSymbol::SymbolType::FUNCTION_IMPORT:
895     Result |= SymbolRef::SF_Undefined | SymbolRef::SF_Executable;
896     break;
897   case WasmSymbol::SymbolType::FUNCTION_EXPORT:
898     Result |= SymbolRef::SF_Executable;
899     break;
900   case WasmSymbol::SymbolType::GLOBAL_IMPORT:
901     Result |= SymbolRef::SF_Undefined;
902     break;
903   case WasmSymbol::SymbolType::GLOBAL_EXPORT:
904     break;
905   }
906 
907   return Result;
908 }
909 
910 basic_symbol_iterator WasmObjectFile::symbol_begin() const {
911   DataRefImpl Ref;
912   Ref.d.a = 0;
913   return BasicSymbolRef(Ref, this);
914 }
915 
916 basic_symbol_iterator WasmObjectFile::symbol_end() const {
917   DataRefImpl Ref;
918   Ref.d.a = Symbols.size();
919   return BasicSymbolRef(Ref, this);
920 }
921 
922 const WasmSymbol &WasmObjectFile::getWasmSymbol(const DataRefImpl &Symb) const {
923   return Symbols[Symb.d.a];
924 }
925 
926 const WasmSymbol &WasmObjectFile::getWasmSymbol(const SymbolRef &Symb) const {
927   return getWasmSymbol(Symb.getRawDataRefImpl());
928 }
929 
930 Expected<StringRef> WasmObjectFile::getSymbolName(DataRefImpl Symb) const {
931   return getWasmSymbol(Symb).Name;
932 }
933 
934 Expected<uint64_t> WasmObjectFile::getSymbolAddress(DataRefImpl Symb) const {
935   return getSymbolValue(Symb);
936 }
937 
938 uint64_t WasmObjectFile::getWasmSymbolValue(const WasmSymbol& Sym) const {
939   switch (Sym.Type) {
940   case WasmSymbol::SymbolType::FUNCTION_IMPORT:
941   case WasmSymbol::SymbolType::GLOBAL_IMPORT:
942   case WasmSymbol::SymbolType::FUNCTION_EXPORT:
943     return Sym.ElementIndex;
944   case WasmSymbol::SymbolType::GLOBAL_EXPORT: {
945     uint32_t GlobalIndex = Sym.ElementIndex - NumImportedGlobals;
946     assert(GlobalIndex < Globals.size());
947     const wasm::WasmGlobal &Global = Globals[GlobalIndex];
948     // WasmSymbols correspond only to I32_CONST globals
949     assert(Global.InitExpr.Opcode == wasm::WASM_OPCODE_I32_CONST);
950     return Global.InitExpr.Value.Int32;
951   }
952   }
953   llvm_unreachable("invalid symbol type");
954 }
955 
956 uint64_t WasmObjectFile::getSymbolValueImpl(DataRefImpl Symb) const {
957   return getWasmSymbolValue(getWasmSymbol(Symb));
958 }
959 
960 uint32_t WasmObjectFile::getSymbolAlignment(DataRefImpl Symb) const {
961   llvm_unreachable("not yet implemented");
962   return 0;
963 }
964 
965 uint64_t WasmObjectFile::getCommonSymbolSizeImpl(DataRefImpl Symb) const {
966   llvm_unreachable("not yet implemented");
967   return 0;
968 }
969 
970 Expected<SymbolRef::Type>
971 WasmObjectFile::getSymbolType(DataRefImpl Symb) const {
972   const WasmSymbol &Sym = getWasmSymbol(Symb);
973 
974   switch (Sym.Type) {
975   case WasmSymbol::SymbolType::FUNCTION_IMPORT:
976   case WasmSymbol::SymbolType::FUNCTION_EXPORT:
977     return SymbolRef::ST_Function;
978   case WasmSymbol::SymbolType::GLOBAL_IMPORT:
979   case WasmSymbol::SymbolType::GLOBAL_EXPORT:
980     return SymbolRef::ST_Data;
981   }
982 
983   llvm_unreachable("Unknown WasmSymbol::SymbolType");
984   return SymbolRef::ST_Other;
985 }
986 
987 Expected<section_iterator>
988 WasmObjectFile::getSymbolSection(DataRefImpl Symb) const {
989   DataRefImpl Ref;
990   Ref.d.a = getWasmSymbol(Symb).Section;
991   return section_iterator(SectionRef(Ref, this));
992 }
993 
994 void WasmObjectFile::moveSectionNext(DataRefImpl &Sec) const { Sec.d.a++; }
995 
996 std::error_code WasmObjectFile::getSectionName(DataRefImpl Sec,
997                                                StringRef &Res) const {
998   const WasmSection &S = Sections[Sec.d.a];
999 #define ECase(X)                                                               \
1000   case wasm::WASM_SEC_##X:                                                     \
1001     Res = #X;                                                                  \
1002     break
1003   switch (S.Type) {
1004     ECase(TYPE);
1005     ECase(IMPORT);
1006     ECase(FUNCTION);
1007     ECase(TABLE);
1008     ECase(MEMORY);
1009     ECase(GLOBAL);
1010     ECase(EXPORT);
1011     ECase(START);
1012     ECase(ELEM);
1013     ECase(CODE);
1014     ECase(DATA);
1015   case wasm::WASM_SEC_CUSTOM:
1016     Res = S.Name;
1017     break;
1018   default:
1019     return object_error::invalid_section_index;
1020   }
1021 #undef ECase
1022   return std::error_code();
1023 }
1024 
1025 uint64_t WasmObjectFile::getSectionAddress(DataRefImpl Sec) const { return 0; }
1026 
1027 uint64_t WasmObjectFile::getSectionIndex(DataRefImpl Sec) const {
1028   return Sec.d.a;
1029 }
1030 
1031 uint64_t WasmObjectFile::getSectionSize(DataRefImpl Sec) const {
1032   const WasmSection &S = Sections[Sec.d.a];
1033   return S.Content.size();
1034 }
1035 
1036 std::error_code WasmObjectFile::getSectionContents(DataRefImpl Sec,
1037                                                    StringRef &Res) const {
1038   const WasmSection &S = Sections[Sec.d.a];
1039   // This will never fail since wasm sections can never be empty (user-sections
1040   // must have a name and non-user sections each have a defined structure).
1041   Res = StringRef(reinterpret_cast<const char *>(S.Content.data()),
1042                   S.Content.size());
1043   return std::error_code();
1044 }
1045 
1046 uint64_t WasmObjectFile::getSectionAlignment(DataRefImpl Sec) const {
1047   return 1;
1048 }
1049 
1050 bool WasmObjectFile::isSectionCompressed(DataRefImpl Sec) const {
1051   return false;
1052 }
1053 
1054 bool WasmObjectFile::isSectionText(DataRefImpl Sec) const {
1055   return getWasmSection(Sec).Type == wasm::WASM_SEC_CODE;
1056 }
1057 
1058 bool WasmObjectFile::isSectionData(DataRefImpl Sec) const {
1059   return getWasmSection(Sec).Type == wasm::WASM_SEC_DATA;
1060 }
1061 
1062 bool WasmObjectFile::isSectionBSS(DataRefImpl Sec) const { return false; }
1063 
1064 bool WasmObjectFile::isSectionVirtual(DataRefImpl Sec) const { return false; }
1065 
1066 bool WasmObjectFile::isSectionBitcode(DataRefImpl Sec) const { return false; }
1067 
1068 relocation_iterator WasmObjectFile::section_rel_begin(DataRefImpl Ref) const {
1069   DataRefImpl RelocRef;
1070   RelocRef.d.a = Ref.d.a;
1071   RelocRef.d.b = 0;
1072   return relocation_iterator(RelocationRef(RelocRef, this));
1073 }
1074 
1075 relocation_iterator WasmObjectFile::section_rel_end(DataRefImpl Ref) const {
1076   const WasmSection &Sec = getWasmSection(Ref);
1077   DataRefImpl RelocRef;
1078   RelocRef.d.a = Ref.d.a;
1079   RelocRef.d.b = Sec.Relocations.size();
1080   return relocation_iterator(RelocationRef(RelocRef, this));
1081 }
1082 
1083 void WasmObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
1084   Rel.d.b++;
1085 }
1086 
1087 uint64_t WasmObjectFile::getRelocationOffset(DataRefImpl Ref) const {
1088   const wasm::WasmRelocation &Rel = getWasmRelocation(Ref);
1089   return Rel.Offset;
1090 }
1091 
1092 symbol_iterator WasmObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
1093   llvm_unreachable("not yet implemented");
1094   SymbolRef Ref;
1095   return symbol_iterator(Ref);
1096 }
1097 
1098 uint64_t WasmObjectFile::getRelocationType(DataRefImpl Ref) const {
1099   const wasm::WasmRelocation &Rel = getWasmRelocation(Ref);
1100   return Rel.Type;
1101 }
1102 
1103 void WasmObjectFile::getRelocationTypeName(
1104     DataRefImpl Ref, SmallVectorImpl<char> &Result) const {
1105   const wasm::WasmRelocation& Rel = getWasmRelocation(Ref);
1106   StringRef Res = "Unknown";
1107 
1108 #define WASM_RELOC(name, value)  \
1109   case wasm::name:              \
1110     Res = #name;               \
1111     break;
1112 
1113   switch (Rel.Type) {
1114 #include "llvm/BinaryFormat/WasmRelocs.def"
1115   }
1116 
1117 #undef WASM_RELOC
1118 
1119   Result.append(Res.begin(), Res.end());
1120 }
1121 
1122 section_iterator WasmObjectFile::section_begin() const {
1123   DataRefImpl Ref;
1124   Ref.d.a = 0;
1125   return section_iterator(SectionRef(Ref, this));
1126 }
1127 
1128 section_iterator WasmObjectFile::section_end() const {
1129   DataRefImpl Ref;
1130   Ref.d.a = Sections.size();
1131   return section_iterator(SectionRef(Ref, this));
1132 }
1133 
1134 uint8_t WasmObjectFile::getBytesInAddress() const { return 4; }
1135 
1136 StringRef WasmObjectFile::getFileFormatName() const { return "WASM"; }
1137 
1138 Triple::ArchType WasmObjectFile::getArch() const { return Triple::wasm32; }
1139 
1140 SubtargetFeatures WasmObjectFile::getFeatures() const {
1141   return SubtargetFeatures();
1142 }
1143 
1144 bool WasmObjectFile::isRelocatableObject() const {
1145   return HasLinkingSection;
1146 }
1147 
1148 const WasmSection &WasmObjectFile::getWasmSection(DataRefImpl Ref) const {
1149   assert(Ref.d.a < Sections.size());
1150   return Sections[Ref.d.a];
1151 }
1152 
1153 const WasmSection &
1154 WasmObjectFile::getWasmSection(const SectionRef &Section) const {
1155   return getWasmSection(Section.getRawDataRefImpl());
1156 }
1157 
1158 const wasm::WasmRelocation &
1159 WasmObjectFile::getWasmRelocation(const RelocationRef &Ref) const {
1160   return getWasmRelocation(Ref.getRawDataRefImpl());
1161 }
1162 
1163 const wasm::WasmRelocation &
1164 WasmObjectFile::getWasmRelocation(DataRefImpl Ref) const {
1165   assert(Ref.d.a < Sections.size());
1166   const WasmSection& Sec = Sections[Ref.d.a];
1167   assert(Ref.d.b < Sec.Relocations.size());
1168   return Sec.Relocations[Ref.d.b];
1169 }
1170