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