17a7e6055SDimitry Andric //===- WasmObjectFile.cpp - Wasm object file implementation ---------------===//
2d88c1a5aSDimitry Andric //
3d88c1a5aSDimitry Andric //                     The LLVM Compiler Infrastructure
4d88c1a5aSDimitry Andric //
5d88c1a5aSDimitry Andric // This file is distributed under the University of Illinois Open Source
6d88c1a5aSDimitry Andric // License. See LICENSE.TXT for details.
7d88c1a5aSDimitry Andric //
8d88c1a5aSDimitry Andric //===----------------------------------------------------------------------===//
9d88c1a5aSDimitry Andric 
107a7e6055SDimitry Andric #include "llvm/ADT/ArrayRef.h"
117a7e6055SDimitry Andric #include "llvm/ADT/STLExtras.h"
127a7e6055SDimitry Andric #include "llvm/ADT/StringRef.h"
137a7e6055SDimitry Andric #include "llvm/ADT/Triple.h"
14db17bf38SDimitry Andric #include "llvm/BinaryFormat/Wasm.h"
1551690af2SDimitry Andric #include "llvm/MC/SubtargetFeature.h"
167a7e6055SDimitry Andric #include "llvm/Object/Binary.h"
177a7e6055SDimitry Andric #include "llvm/Object/Error.h"
187a7e6055SDimitry Andric #include "llvm/Object/ObjectFile.h"
197a7e6055SDimitry Andric #include "llvm/Object/SymbolicFile.h"
20d88c1a5aSDimitry Andric #include "llvm/Object/Wasm.h"
21d88c1a5aSDimitry Andric #include "llvm/Support/Endian.h"
227a7e6055SDimitry Andric #include "llvm/Support/Error.h"
237a7e6055SDimitry Andric #include "llvm/Support/ErrorHandling.h"
24d88c1a5aSDimitry Andric #include "llvm/Support/LEB128.h"
257a7e6055SDimitry Andric #include <algorithm>
2651690af2SDimitry Andric #include <cassert>
277a7e6055SDimitry Andric #include <cstdint>
2851690af2SDimitry Andric #include <cstring>
297a7e6055SDimitry Andric #include <system_error>
30d88c1a5aSDimitry Andric 
31edd7eaddSDimitry Andric #define DEBUG_TYPE "wasm-object"
32edd7eaddSDimitry Andric 
337a7e6055SDimitry Andric using namespace llvm;
347a7e6055SDimitry Andric using namespace object;
35d88c1a5aSDimitry Andric 
36d88c1a5aSDimitry Andric Expected<std::unique_ptr<WasmObjectFile>>
37d88c1a5aSDimitry Andric ObjectFile::createWasmObjectFile(MemoryBufferRef Buffer) {
38d88c1a5aSDimitry Andric   Error Err = Error::success();
39d88c1a5aSDimitry Andric   auto ObjectFile = llvm::make_unique<WasmObjectFile>(Buffer, Err);
40d88c1a5aSDimitry Andric   if (Err)
41d88c1a5aSDimitry Andric     return std::move(Err);
42d88c1a5aSDimitry Andric 
43d88c1a5aSDimitry Andric   return std::move(ObjectFile);
44d88c1a5aSDimitry Andric }
45d88c1a5aSDimitry Andric 
467a7e6055SDimitry Andric #define VARINT7_MAX ((1<<7)-1)
477a7e6055SDimitry Andric #define VARINT7_MIN (-(1<<7))
487a7e6055SDimitry Andric #define VARUINT7_MAX (1<<7)
497a7e6055SDimitry Andric #define VARUINT1_MAX (1)
50d88c1a5aSDimitry Andric 
517a7e6055SDimitry Andric static uint8_t readUint8(const uint8_t *&Ptr) { return *Ptr++; }
527a7e6055SDimitry Andric 
537a7e6055SDimitry Andric static uint32_t readUint32(const uint8_t *&Ptr) {
54d88c1a5aSDimitry Andric   uint32_t Result = support::endian::read32le(Ptr);
55d88c1a5aSDimitry Andric   Ptr += sizeof(Result);
56d88c1a5aSDimitry Andric   return Result;
57d88c1a5aSDimitry Andric }
58d88c1a5aSDimitry Andric 
597a7e6055SDimitry Andric static int32_t readFloat32(const uint8_t *&Ptr) {
607a7e6055SDimitry Andric   int32_t Result = 0;
617a7e6055SDimitry Andric   memcpy(&Result, Ptr, sizeof(Result));
627a7e6055SDimitry Andric   Ptr += sizeof(Result);
637a7e6055SDimitry Andric   return Result;
647a7e6055SDimitry Andric }
657a7e6055SDimitry Andric 
667a7e6055SDimitry Andric static int64_t readFloat64(const uint8_t *&Ptr) {
677a7e6055SDimitry Andric   int64_t Result = 0;
687a7e6055SDimitry Andric   memcpy(&Result, Ptr, sizeof(Result));
697a7e6055SDimitry Andric   Ptr += sizeof(Result);
707a7e6055SDimitry Andric   return Result;
717a7e6055SDimitry Andric }
727a7e6055SDimitry Andric 
737a7e6055SDimitry Andric static uint64_t readULEB128(const uint8_t *&Ptr) {
74d88c1a5aSDimitry Andric   unsigned Count;
75d88c1a5aSDimitry Andric   uint64_t Result = decodeULEB128(Ptr, &Count);
76d88c1a5aSDimitry Andric   Ptr += Count;
77d88c1a5aSDimitry Andric   return Result;
78d88c1a5aSDimitry Andric }
79d88c1a5aSDimitry Andric 
807a7e6055SDimitry Andric static StringRef readString(const uint8_t *&Ptr) {
81d88c1a5aSDimitry Andric   uint32_t StringLen = readULEB128(Ptr);
82d88c1a5aSDimitry Andric   StringRef Return = StringRef(reinterpret_cast<const char *>(Ptr), StringLen);
83d88c1a5aSDimitry Andric   Ptr += StringLen;
84d88c1a5aSDimitry Andric   return Return;
85d88c1a5aSDimitry Andric }
86d88c1a5aSDimitry Andric 
877a7e6055SDimitry Andric static int64_t readLEB128(const uint8_t *&Ptr) {
887a7e6055SDimitry Andric   unsigned Count;
897a7e6055SDimitry Andric   uint64_t Result = decodeSLEB128(Ptr, &Count);
907a7e6055SDimitry Andric   Ptr += Count;
917a7e6055SDimitry Andric   return Result;
927a7e6055SDimitry Andric }
937a7e6055SDimitry Andric 
947a7e6055SDimitry Andric static uint8_t readVaruint1(const uint8_t *&Ptr) {
957a7e6055SDimitry Andric   int64_t result = readLEB128(Ptr);
967a7e6055SDimitry Andric   assert(result <= VARUINT1_MAX && result >= 0);
977a7e6055SDimitry Andric   return result;
987a7e6055SDimitry Andric }
997a7e6055SDimitry Andric 
1007a7e6055SDimitry Andric static int8_t readVarint7(const uint8_t *&Ptr) {
1017a7e6055SDimitry Andric   int64_t result = readLEB128(Ptr);
1027a7e6055SDimitry Andric   assert(result <= VARINT7_MAX && result >= VARINT7_MIN);
1037a7e6055SDimitry Andric   return result;
1047a7e6055SDimitry Andric }
1057a7e6055SDimitry Andric 
1067a7e6055SDimitry Andric static uint8_t readVaruint7(const uint8_t *&Ptr) {
1077a7e6055SDimitry Andric   uint64_t result = readULEB128(Ptr);
1087a7e6055SDimitry Andric   assert(result <= VARUINT7_MAX);
1097a7e6055SDimitry Andric   return result;
1107a7e6055SDimitry Andric }
1117a7e6055SDimitry Andric 
1127a7e6055SDimitry Andric static int32_t readVarint32(const uint8_t *&Ptr) {
1137a7e6055SDimitry Andric   int64_t result = readLEB128(Ptr);
1147a7e6055SDimitry Andric   assert(result <= INT32_MAX && result >= INT32_MIN);
1157a7e6055SDimitry Andric   return result;
1167a7e6055SDimitry Andric }
1177a7e6055SDimitry Andric 
1187a7e6055SDimitry Andric static uint32_t readVaruint32(const uint8_t *&Ptr) {
1197a7e6055SDimitry Andric   uint64_t result = readULEB128(Ptr);
1207a7e6055SDimitry Andric   assert(result <= UINT32_MAX);
1217a7e6055SDimitry Andric   return result;
1227a7e6055SDimitry Andric }
1237a7e6055SDimitry Andric 
1247a7e6055SDimitry Andric static int64_t readVarint64(const uint8_t *&Ptr) {
1257a7e6055SDimitry Andric   return readLEB128(Ptr);
1267a7e6055SDimitry Andric }
1277a7e6055SDimitry Andric 
1287a7e6055SDimitry Andric static uint8_t readOpcode(const uint8_t *&Ptr) {
1297a7e6055SDimitry Andric   return readUint8(Ptr);
1307a7e6055SDimitry Andric }
1317a7e6055SDimitry Andric 
1327a7e6055SDimitry Andric static Error readInitExpr(wasm::WasmInitExpr &Expr, const uint8_t *&Ptr) {
1337a7e6055SDimitry Andric   Expr.Opcode = readOpcode(Ptr);
1347a7e6055SDimitry Andric 
1357a7e6055SDimitry Andric   switch (Expr.Opcode) {
1367a7e6055SDimitry Andric   case wasm::WASM_OPCODE_I32_CONST:
1377a7e6055SDimitry Andric     Expr.Value.Int32 = readVarint32(Ptr);
1387a7e6055SDimitry Andric     break;
1397a7e6055SDimitry Andric   case wasm::WASM_OPCODE_I64_CONST:
1407a7e6055SDimitry Andric     Expr.Value.Int64 = readVarint64(Ptr);
1417a7e6055SDimitry Andric     break;
1427a7e6055SDimitry Andric   case wasm::WASM_OPCODE_F32_CONST:
1437a7e6055SDimitry Andric     Expr.Value.Float32 = readFloat32(Ptr);
1447a7e6055SDimitry Andric     break;
1457a7e6055SDimitry Andric   case wasm::WASM_OPCODE_F64_CONST:
1467a7e6055SDimitry Andric     Expr.Value.Float64 = readFloat64(Ptr);
1477a7e6055SDimitry Andric     break;
1487a7e6055SDimitry Andric   case wasm::WASM_OPCODE_GET_GLOBAL:
14951690af2SDimitry Andric     Expr.Value.Global = readULEB128(Ptr);
1507a7e6055SDimitry Andric     break;
1517a7e6055SDimitry Andric   default:
1527a7e6055SDimitry Andric     return make_error<GenericBinaryError>("Invalid opcode in init_expr",
1537a7e6055SDimitry Andric                                           object_error::parse_failed);
1547a7e6055SDimitry Andric   }
1557a7e6055SDimitry Andric 
1567a7e6055SDimitry Andric   uint8_t EndOpcode = readOpcode(Ptr);
1577a7e6055SDimitry Andric   if (EndOpcode != wasm::WASM_OPCODE_END) {
1587a7e6055SDimitry Andric     return make_error<GenericBinaryError>("Invalid init_expr",
1597a7e6055SDimitry Andric                                           object_error::parse_failed);
1607a7e6055SDimitry Andric   }
1617a7e6055SDimitry Andric   return Error::success();
1627a7e6055SDimitry Andric }
1637a7e6055SDimitry Andric 
1647a7e6055SDimitry Andric static wasm::WasmLimits readLimits(const uint8_t *&Ptr) {
1657a7e6055SDimitry Andric   wasm::WasmLimits Result;
1667a7e6055SDimitry Andric   Result.Flags = readVaruint1(Ptr);
1677a7e6055SDimitry Andric   Result.Initial = readVaruint32(Ptr);
1687a7e6055SDimitry Andric   if (Result.Flags & wasm::WASM_LIMITS_FLAG_HAS_MAX)
1697a7e6055SDimitry Andric     Result.Maximum = readVaruint32(Ptr);
1707a7e6055SDimitry Andric   return Result;
1717a7e6055SDimitry Andric }
1727a7e6055SDimitry Andric 
1735517e702SDimitry Andric static wasm::WasmTable readTable(const uint8_t *&Ptr) {
1745517e702SDimitry Andric   wasm::WasmTable Table;
1755517e702SDimitry Andric   Table.ElemType = readVarint7(Ptr);
1765517e702SDimitry Andric   Table.Limits = readLimits(Ptr);
1775517e702SDimitry Andric   return Table;
1785517e702SDimitry Andric }
1795517e702SDimitry Andric 
1807a7e6055SDimitry Andric static Error readSection(WasmSection &Section, const uint8_t *&Ptr,
181d88c1a5aSDimitry Andric                          const uint8_t *Start) {
182d88c1a5aSDimitry Andric   // TODO(sbc): Avoid reading past EOF in the case of malformed files.
183d88c1a5aSDimitry Andric   Section.Offset = Ptr - Start;
1847a7e6055SDimitry Andric   Section.Type = readVaruint7(Ptr);
1857a7e6055SDimitry Andric   uint32_t Size = readVaruint32(Ptr);
186d88c1a5aSDimitry Andric   if (Size == 0)
187d88c1a5aSDimitry Andric     return make_error<StringError>("Zero length section",
188d88c1a5aSDimitry Andric                                    object_error::parse_failed);
189d88c1a5aSDimitry Andric   Section.Content = ArrayRef<uint8_t>(Ptr, Size);
190d88c1a5aSDimitry Andric   Ptr += Size;
191d88c1a5aSDimitry Andric   return Error::success();
192d88c1a5aSDimitry Andric }
193d88c1a5aSDimitry Andric 
194d88c1a5aSDimitry Andric WasmObjectFile::WasmObjectFile(MemoryBufferRef Buffer, Error &Err)
19551690af2SDimitry Andric     : ObjectFile(Binary::ID_Wasm, Buffer) {
196d88c1a5aSDimitry Andric   ErrorAsOutParameter ErrAsOutParam(&Err);
197d88c1a5aSDimitry Andric   Header.Magic = getData().substr(0, 4);
198d88c1a5aSDimitry Andric   if (Header.Magic != StringRef("\0asm", 4)) {
199d88c1a5aSDimitry Andric     Err = make_error<StringError>("Bad magic number",
200d88c1a5aSDimitry Andric                                   object_error::parse_failed);
201d88c1a5aSDimitry Andric     return;
202d88c1a5aSDimitry Andric   }
203d88c1a5aSDimitry Andric   const uint8_t *Ptr = getPtr(4);
204d88c1a5aSDimitry Andric   Header.Version = readUint32(Ptr);
205d88c1a5aSDimitry Andric   if (Header.Version != wasm::WasmVersion) {
206d88c1a5aSDimitry Andric     Err = make_error<StringError>("Bad version number",
207d88c1a5aSDimitry Andric                                   object_error::parse_failed);
208d88c1a5aSDimitry Andric     return;
209d88c1a5aSDimitry Andric   }
210d88c1a5aSDimitry Andric 
211d88c1a5aSDimitry Andric   const uint8_t *Eof = getPtr(getData().size());
2127a7e6055SDimitry Andric   WasmSection Sec;
213d88c1a5aSDimitry Andric   while (Ptr < Eof) {
214d88c1a5aSDimitry Andric     if ((Err = readSection(Sec, Ptr, getPtr(0))))
215d88c1a5aSDimitry Andric       return;
2167a7e6055SDimitry Andric     if ((Err = parseSection(Sec)))
217d88c1a5aSDimitry Andric       return;
2187a7e6055SDimitry Andric 
219d88c1a5aSDimitry Andric     Sections.push_back(Sec);
220d88c1a5aSDimitry Andric   }
221d88c1a5aSDimitry Andric }
222d88c1a5aSDimitry Andric 
2237a7e6055SDimitry Andric Error WasmObjectFile::parseSection(WasmSection &Sec) {
2247a7e6055SDimitry Andric   const uint8_t* Start = Sec.Content.data();
2257a7e6055SDimitry Andric   const uint8_t* End = Start + Sec.Content.size();
2267a7e6055SDimitry Andric   switch (Sec.Type) {
2277a7e6055SDimitry Andric   case wasm::WASM_SEC_CUSTOM:
2287a7e6055SDimitry Andric     return parseCustomSection(Sec, Start, End);
2297a7e6055SDimitry Andric   case wasm::WASM_SEC_TYPE:
2307a7e6055SDimitry Andric     return parseTypeSection(Start, End);
2317a7e6055SDimitry Andric   case wasm::WASM_SEC_IMPORT:
2327a7e6055SDimitry Andric     return parseImportSection(Start, End);
2337a7e6055SDimitry Andric   case wasm::WASM_SEC_FUNCTION:
2347a7e6055SDimitry Andric     return parseFunctionSection(Start, End);
2357a7e6055SDimitry Andric   case wasm::WASM_SEC_TABLE:
2367a7e6055SDimitry Andric     return parseTableSection(Start, End);
2377a7e6055SDimitry Andric   case wasm::WASM_SEC_MEMORY:
2387a7e6055SDimitry Andric     return parseMemorySection(Start, End);
2397a7e6055SDimitry Andric   case wasm::WASM_SEC_GLOBAL:
2407a7e6055SDimitry Andric     return parseGlobalSection(Start, End);
2417a7e6055SDimitry Andric   case wasm::WASM_SEC_EXPORT:
2427a7e6055SDimitry Andric     return parseExportSection(Start, End);
2437a7e6055SDimitry Andric   case wasm::WASM_SEC_START:
2447a7e6055SDimitry Andric     return parseStartSection(Start, End);
2457a7e6055SDimitry Andric   case wasm::WASM_SEC_ELEM:
2467a7e6055SDimitry Andric     return parseElemSection(Start, End);
2477a7e6055SDimitry Andric   case wasm::WASM_SEC_CODE:
2487a7e6055SDimitry Andric     return parseCodeSection(Start, End);
2497a7e6055SDimitry Andric   case wasm::WASM_SEC_DATA:
2507a7e6055SDimitry Andric     return parseDataSection(Start, End);
2517a7e6055SDimitry Andric   default:
2527a7e6055SDimitry Andric     return make_error<GenericBinaryError>("Bad section type",
2537a7e6055SDimitry Andric                                           object_error::parse_failed);
2547a7e6055SDimitry Andric   }
2557a7e6055SDimitry Andric }
2567a7e6055SDimitry Andric 
2577a7e6055SDimitry Andric Error WasmObjectFile::parseNameSection(const uint8_t *Ptr, const uint8_t *End) {
2587a7e6055SDimitry Andric   while (Ptr < End) {
2597a7e6055SDimitry Andric     uint8_t Type = readVarint7(Ptr);
2607a7e6055SDimitry Andric     uint32_t Size = readVaruint32(Ptr);
261edd7eaddSDimitry Andric     const uint8_t *SubSectionEnd = Ptr + Size;
2627a7e6055SDimitry Andric     switch (Type) {
2637a7e6055SDimitry Andric     case wasm::WASM_NAMES_FUNCTION: {
2647a7e6055SDimitry Andric       uint32_t Count = readVaruint32(Ptr);
2657a7e6055SDimitry Andric       while (Count--) {
2660f5676f4SDimitry Andric         uint32_t Index = readVaruint32(Ptr);
2677a7e6055SDimitry Andric         StringRef Name = readString(Ptr);
26851690af2SDimitry Andric         if (!Name.empty())
2697a7e6055SDimitry Andric           Symbols.emplace_back(Name,
2700f5676f4SDimitry Andric                                WasmSymbol::SymbolType::DEBUG_FUNCTION_NAME,
2710f5676f4SDimitry Andric                                Sections.size(), Index);
2727a7e6055SDimitry Andric       }
2737a7e6055SDimitry Andric       break;
2747a7e6055SDimitry Andric     }
2757a7e6055SDimitry Andric     // Ignore local names for now
2767a7e6055SDimitry Andric     case wasm::WASM_NAMES_LOCAL:
2777a7e6055SDimitry Andric     default:
2787a7e6055SDimitry Andric       Ptr += Size;
2797a7e6055SDimitry Andric       break;
2807a7e6055SDimitry Andric     }
281edd7eaddSDimitry Andric     if (Ptr != SubSectionEnd)
282edd7eaddSDimitry Andric       return make_error<GenericBinaryError>("Name sub-section ended prematurely",
283edd7eaddSDimitry Andric                                             object_error::parse_failed);
2847a7e6055SDimitry Andric   }
2857a7e6055SDimitry Andric 
2867a7e6055SDimitry Andric   if (Ptr != End)
2877a7e6055SDimitry Andric     return make_error<GenericBinaryError>("Name section ended prematurely",
2887a7e6055SDimitry Andric                                           object_error::parse_failed);
2897a7e6055SDimitry Andric   return Error::success();
2907a7e6055SDimitry Andric }
2917a7e6055SDimitry Andric 
292edd7eaddSDimitry Andric Error WasmObjectFile::parseLinkingSection(const uint8_t *Ptr,
293edd7eaddSDimitry Andric                                           const uint8_t *End) {
294edd7eaddSDimitry Andric   while (Ptr < End) {
295edd7eaddSDimitry Andric     uint8_t Type = readVarint7(Ptr);
296edd7eaddSDimitry Andric     uint32_t Size = readVaruint32(Ptr);
297edd7eaddSDimitry Andric     const uint8_t *SubSectionEnd = Ptr + Size;
298edd7eaddSDimitry Andric     switch (Type) {
299edd7eaddSDimitry Andric     case wasm::WASM_SYMBOL_INFO: {
300edd7eaddSDimitry Andric       uint32_t Count = readVaruint32(Ptr);
301edd7eaddSDimitry Andric       while (Count--) {
302edd7eaddSDimitry Andric         StringRef Symbol = readString(Ptr);
303edd7eaddSDimitry Andric         DEBUG(dbgs() << "reading syminfo: " << Symbol << "\n");
304edd7eaddSDimitry Andric         uint32_t Flags = readVaruint32(Ptr);
305edd7eaddSDimitry Andric         auto iter = SymbolMap.find(Symbol);
306edd7eaddSDimitry Andric         if (iter == SymbolMap.end()) {
307edd7eaddSDimitry Andric           return make_error<GenericBinaryError>(
308edd7eaddSDimitry Andric               "Invalid symbol name in linking section",
309edd7eaddSDimitry Andric               object_error::parse_failed);
310edd7eaddSDimitry Andric         }
311edd7eaddSDimitry Andric         uint32_t SymIndex = iter->second;
312edd7eaddSDimitry Andric         assert(SymIndex < Symbols.size());
313edd7eaddSDimitry Andric         Symbols[SymIndex].Flags = Flags;
314edd7eaddSDimitry Andric         DEBUG(dbgs() << "Set symbol flags index:"
315edd7eaddSDimitry Andric                      << SymIndex << " name:"
316edd7eaddSDimitry Andric                      << Symbols[SymIndex].Name << " exptected:"
317edd7eaddSDimitry Andric                      << Symbol << " flags: " << Flags << "\n");
318edd7eaddSDimitry Andric       }
319edd7eaddSDimitry Andric       break;
320edd7eaddSDimitry Andric     }
321edd7eaddSDimitry Andric     case wasm::WASM_STACK_POINTER:
322edd7eaddSDimitry Andric     default:
323edd7eaddSDimitry Andric       Ptr += Size;
324edd7eaddSDimitry Andric       break;
325edd7eaddSDimitry Andric     }
326edd7eaddSDimitry Andric     if (Ptr != SubSectionEnd)
327edd7eaddSDimitry Andric       return make_error<GenericBinaryError>(
328edd7eaddSDimitry Andric           "Linking sub-section ended prematurely", object_error::parse_failed);
329edd7eaddSDimitry Andric   }
330edd7eaddSDimitry Andric   if (Ptr != End)
331edd7eaddSDimitry Andric     return make_error<GenericBinaryError>("Linking section ended prematurely",
332edd7eaddSDimitry Andric                                           object_error::parse_failed);
333edd7eaddSDimitry Andric   return Error::success();
334edd7eaddSDimitry Andric }
335edd7eaddSDimitry Andric 
3367a7e6055SDimitry Andric WasmSection* WasmObjectFile::findCustomSectionByName(StringRef Name) {
3377a7e6055SDimitry Andric   for (WasmSection& Section : Sections) {
3387a7e6055SDimitry Andric     if (Section.Type == wasm::WASM_SEC_CUSTOM && Section.Name == Name)
3397a7e6055SDimitry Andric       return &Section;
3407a7e6055SDimitry Andric   }
3417a7e6055SDimitry Andric   return nullptr;
3427a7e6055SDimitry Andric }
3437a7e6055SDimitry Andric 
3447a7e6055SDimitry Andric WasmSection* WasmObjectFile::findSectionByType(uint32_t Type) {
3457a7e6055SDimitry Andric   assert(Type != wasm::WASM_SEC_CUSTOM);
3467a7e6055SDimitry Andric   for (WasmSection& Section : Sections) {
3477a7e6055SDimitry Andric     if (Section.Type == Type)
3487a7e6055SDimitry Andric       return &Section;
3497a7e6055SDimitry Andric   }
3507a7e6055SDimitry Andric   return nullptr;
3517a7e6055SDimitry Andric }
3527a7e6055SDimitry Andric 
3537a7e6055SDimitry Andric Error WasmObjectFile::parseRelocSection(StringRef Name, const uint8_t *Ptr,
3547a7e6055SDimitry Andric                                         const uint8_t *End) {
3557a7e6055SDimitry Andric   uint8_t SectionCode = readVarint7(Ptr);
3567a7e6055SDimitry Andric   WasmSection* Section = nullptr;
3577a7e6055SDimitry Andric   if (SectionCode == wasm::WASM_SEC_CUSTOM) {
3587a7e6055SDimitry Andric     StringRef Name = readString(Ptr);
3597a7e6055SDimitry Andric     Section = findCustomSectionByName(Name);
3607a7e6055SDimitry Andric   } else {
3617a7e6055SDimitry Andric     Section = findSectionByType(SectionCode);
3627a7e6055SDimitry Andric   }
3637a7e6055SDimitry Andric   if (!Section)
3647a7e6055SDimitry Andric     return make_error<GenericBinaryError>("Invalid section code",
3657a7e6055SDimitry Andric                                           object_error::parse_failed);
3667a7e6055SDimitry Andric   uint32_t RelocCount = readVaruint32(Ptr);
3677a7e6055SDimitry Andric   while (RelocCount--) {
3687a7e6055SDimitry Andric     wasm::WasmRelocation Reloc;
3697a7e6055SDimitry Andric     memset(&Reloc, 0, sizeof(Reloc));
3707a7e6055SDimitry Andric     Reloc.Type = readVaruint32(Ptr);
3717a7e6055SDimitry Andric     Reloc.Offset = readVaruint32(Ptr);
3727a7e6055SDimitry Andric     Reloc.Index = readVaruint32(Ptr);
3737a7e6055SDimitry Andric     switch (Reloc.Type) {
3747a7e6055SDimitry Andric     case wasm::R_WEBASSEMBLY_FUNCTION_INDEX_LEB:
3757a7e6055SDimitry Andric     case wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB:
3767a7e6055SDimitry Andric     case wasm::R_WEBASSEMBLY_TABLE_INDEX_I32:
37751690af2SDimitry Andric     case wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB:
378edd7eaddSDimitry Andric     case wasm::R_WEBASSEMBLY_GLOBAL_INDEX_LEB:
3797a7e6055SDimitry Andric       break;
3807a7e6055SDimitry Andric     case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_LEB:
3817a7e6055SDimitry Andric     case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_SLEB:
3827a7e6055SDimitry Andric     case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_I32:
38351690af2SDimitry Andric       Reloc.Addend = readVarint32(Ptr);
3847a7e6055SDimitry Andric       break;
3857a7e6055SDimitry Andric     default:
386edd7eaddSDimitry Andric       return make_error<GenericBinaryError>("Bad relocation type: " +
387edd7eaddSDimitry Andric                                                 Twine(Reloc.Type),
3887a7e6055SDimitry Andric                                             object_error::parse_failed);
3897a7e6055SDimitry Andric     }
3907a7e6055SDimitry Andric     Section->Relocations.push_back(Reloc);
3917a7e6055SDimitry Andric   }
3927a7e6055SDimitry Andric   if (Ptr != End)
3937a7e6055SDimitry Andric     return make_error<GenericBinaryError>("Reloc section ended prematurely",
3947a7e6055SDimitry Andric                                           object_error::parse_failed);
3957a7e6055SDimitry Andric   return Error::success();
3967a7e6055SDimitry Andric }
3977a7e6055SDimitry Andric 
3987a7e6055SDimitry Andric Error WasmObjectFile::parseCustomSection(WasmSection &Sec,
3997a7e6055SDimitry Andric                                          const uint8_t *Ptr, const uint8_t *End) {
400d88c1a5aSDimitry Andric   Sec.Name = readString(Ptr);
4017a7e6055SDimitry Andric   if (Sec.Name == "name") {
4027a7e6055SDimitry Andric     if (Error Err = parseNameSection(Ptr, End))
4037a7e6055SDimitry Andric       return Err;
404edd7eaddSDimitry Andric   } else if (Sec.Name == "linking") {
405edd7eaddSDimitry Andric     if (Error Err = parseLinkingSection(Ptr, End))
406edd7eaddSDimitry Andric       return Err;
4077a7e6055SDimitry Andric   } else if (Sec.Name.startswith("reloc.")) {
4087a7e6055SDimitry Andric     if (Error Err = parseRelocSection(Sec.Name, Ptr, End))
4097a7e6055SDimitry Andric       return Err;
4107a7e6055SDimitry Andric   }
4117a7e6055SDimitry Andric   return Error::success();
4127a7e6055SDimitry Andric }
4137a7e6055SDimitry Andric 
4147a7e6055SDimitry Andric Error WasmObjectFile::parseTypeSection(const uint8_t *Ptr, const uint8_t *End) {
4157a7e6055SDimitry Andric   uint32_t Count = readVaruint32(Ptr);
4167a7e6055SDimitry Andric   Signatures.reserve(Count);
4177a7e6055SDimitry Andric   while (Count--) {
4187a7e6055SDimitry Andric     wasm::WasmSignature Sig;
4197a7e6055SDimitry Andric     Sig.ReturnType = wasm::WASM_TYPE_NORESULT;
4207a7e6055SDimitry Andric     int8_t Form = readVarint7(Ptr);
4217a7e6055SDimitry Andric     if (Form != wasm::WASM_TYPE_FUNC) {
4227a7e6055SDimitry Andric       return make_error<GenericBinaryError>("Invalid signature type",
4237a7e6055SDimitry Andric                                             object_error::parse_failed);
4247a7e6055SDimitry Andric     }
4257a7e6055SDimitry Andric     uint32_t ParamCount = readVaruint32(Ptr);
4267a7e6055SDimitry Andric     Sig.ParamTypes.reserve(ParamCount);
4277a7e6055SDimitry Andric     while (ParamCount--) {
4287a7e6055SDimitry Andric       uint32_t ParamType = readVarint7(Ptr);
4297a7e6055SDimitry Andric       Sig.ParamTypes.push_back(ParamType);
4307a7e6055SDimitry Andric     }
4317a7e6055SDimitry Andric     uint32_t ReturnCount = readVaruint32(Ptr);
4327a7e6055SDimitry Andric     if (ReturnCount) {
4337a7e6055SDimitry Andric       if (ReturnCount != 1) {
4347a7e6055SDimitry Andric         return make_error<GenericBinaryError>(
4357a7e6055SDimitry Andric             "Multiple return types not supported", object_error::parse_failed);
4367a7e6055SDimitry Andric       }
4377a7e6055SDimitry Andric       Sig.ReturnType = readVarint7(Ptr);
4387a7e6055SDimitry Andric     }
4397a7e6055SDimitry Andric     Signatures.push_back(Sig);
4407a7e6055SDimitry Andric   }
4417a7e6055SDimitry Andric   if (Ptr != End)
4427a7e6055SDimitry Andric     return make_error<GenericBinaryError>("Type section ended prematurely",
4437a7e6055SDimitry Andric                                           object_error::parse_failed);
4447a7e6055SDimitry Andric   return Error::success();
4457a7e6055SDimitry Andric }
4467a7e6055SDimitry Andric 
4477a7e6055SDimitry Andric Error WasmObjectFile::parseImportSection(const uint8_t *Ptr, const uint8_t *End) {
4487a7e6055SDimitry Andric   uint32_t Count = readVaruint32(Ptr);
4497a7e6055SDimitry Andric   Imports.reserve(Count);
4500f5676f4SDimitry Andric   for (uint32_t i = 0; i < Count; i++) {
4517a7e6055SDimitry Andric     wasm::WasmImport Im;
4527a7e6055SDimitry Andric     Im.Module = readString(Ptr);
4537a7e6055SDimitry Andric     Im.Field = readString(Ptr);
4547a7e6055SDimitry Andric     Im.Kind = readUint8(Ptr);
4557a7e6055SDimitry Andric     switch (Im.Kind) {
4567a7e6055SDimitry Andric     case wasm::WASM_EXTERNAL_FUNCTION:
4577a7e6055SDimitry Andric       Im.SigIndex = readVaruint32(Ptr);
458edd7eaddSDimitry Andric       SymbolMap.try_emplace(Im.Field, Symbols.size());
4590f5676f4SDimitry Andric       Symbols.emplace_back(Im.Field, WasmSymbol::SymbolType::FUNCTION_IMPORT,
4600f5676f4SDimitry Andric                            Sections.size(), i);
461edd7eaddSDimitry Andric       DEBUG(dbgs() << "Adding import: " << Symbols.back()
462edd7eaddSDimitry Andric                    << " sym index:" << Symbols.size() << "\n");
4637a7e6055SDimitry Andric       break;
4647a7e6055SDimitry Andric     case wasm::WASM_EXTERNAL_GLOBAL:
4655517e702SDimitry Andric       Im.Global.Type = readVarint7(Ptr);
4665517e702SDimitry Andric       Im.Global.Mutable = readVaruint1(Ptr);
467edd7eaddSDimitry Andric       SymbolMap.try_emplace(Im.Field, Symbols.size());
4680f5676f4SDimitry Andric       Symbols.emplace_back(Im.Field, WasmSymbol::SymbolType::GLOBAL_IMPORT,
4690f5676f4SDimitry Andric                            Sections.size(), i);
470edd7eaddSDimitry Andric       DEBUG(dbgs() << "Adding import: " << Symbols.back()
471edd7eaddSDimitry Andric                    << " sym index:" << Symbols.size() << "\n");
4727a7e6055SDimitry Andric       break;
4735517e702SDimitry Andric     case wasm::WASM_EXTERNAL_MEMORY:
4745517e702SDimitry Andric       Im.Memory = readLimits(Ptr);
4755517e702SDimitry Andric       break;
4765517e702SDimitry Andric     case wasm::WASM_EXTERNAL_TABLE:
4775517e702SDimitry Andric       Im.Table = readTable(Ptr);
4785517e702SDimitry Andric       if (Im.Table.ElemType != wasm::WASM_TYPE_ANYFUNC) {
4795517e702SDimitry Andric         return make_error<GenericBinaryError>("Invalid table element type",
4805517e702SDimitry Andric                                               object_error::parse_failed);
4815517e702SDimitry Andric       }
4825517e702SDimitry Andric       break;
4837a7e6055SDimitry Andric     default:
4847a7e6055SDimitry Andric       return make_error<GenericBinaryError>(
4857a7e6055SDimitry Andric           "Unexpected import kind", object_error::parse_failed);
4867a7e6055SDimitry Andric     }
4877a7e6055SDimitry Andric     Imports.push_back(Im);
4887a7e6055SDimitry Andric   }
4897a7e6055SDimitry Andric   if (Ptr != End)
4907a7e6055SDimitry Andric     return make_error<GenericBinaryError>("Import section ended prematurely",
4917a7e6055SDimitry Andric                                           object_error::parse_failed);
4927a7e6055SDimitry Andric   return Error::success();
4937a7e6055SDimitry Andric }
4947a7e6055SDimitry Andric 
4957a7e6055SDimitry Andric Error WasmObjectFile::parseFunctionSection(const uint8_t *Ptr, const uint8_t *End) {
4967a7e6055SDimitry Andric   uint32_t Count = readVaruint32(Ptr);
4977a7e6055SDimitry Andric   FunctionTypes.reserve(Count);
4987a7e6055SDimitry Andric   while (Count--) {
4997a7e6055SDimitry Andric     FunctionTypes.push_back(readVaruint32(Ptr));
5007a7e6055SDimitry Andric   }
5017a7e6055SDimitry Andric   if (Ptr != End)
5027a7e6055SDimitry Andric     return make_error<GenericBinaryError>("Function section ended prematurely",
5037a7e6055SDimitry Andric                                           object_error::parse_failed);
5047a7e6055SDimitry Andric   return Error::success();
5057a7e6055SDimitry Andric }
5067a7e6055SDimitry Andric 
5077a7e6055SDimitry Andric Error WasmObjectFile::parseTableSection(const uint8_t *Ptr, const uint8_t *End) {
5087a7e6055SDimitry Andric   uint32_t Count = readVaruint32(Ptr);
5097a7e6055SDimitry Andric   Tables.reserve(Count);
5107a7e6055SDimitry Andric   while (Count--) {
5115517e702SDimitry Andric     Tables.push_back(readTable(Ptr));
5125517e702SDimitry Andric     if (Tables.back().ElemType != wasm::WASM_TYPE_ANYFUNC) {
5137a7e6055SDimitry Andric       return make_error<GenericBinaryError>("Invalid table element type",
5147a7e6055SDimitry Andric                                             object_error::parse_failed);
5157a7e6055SDimitry Andric     }
5167a7e6055SDimitry Andric   }
5177a7e6055SDimitry Andric   if (Ptr != End)
5187a7e6055SDimitry Andric     return make_error<GenericBinaryError>("Table section ended prematurely",
5197a7e6055SDimitry Andric                                           object_error::parse_failed);
5207a7e6055SDimitry Andric   return Error::success();
5217a7e6055SDimitry Andric }
5227a7e6055SDimitry Andric 
5237a7e6055SDimitry Andric Error WasmObjectFile::parseMemorySection(const uint8_t *Ptr, const uint8_t *End) {
5247a7e6055SDimitry Andric   uint32_t Count = readVaruint32(Ptr);
5257a7e6055SDimitry Andric   Memories.reserve(Count);
5267a7e6055SDimitry Andric   while (Count--) {
5277a7e6055SDimitry Andric     Memories.push_back(readLimits(Ptr));
5287a7e6055SDimitry Andric   }
5297a7e6055SDimitry Andric   if (Ptr != End)
5307a7e6055SDimitry Andric     return make_error<GenericBinaryError>("Memory section ended prematurely",
5317a7e6055SDimitry Andric                                           object_error::parse_failed);
5327a7e6055SDimitry Andric   return Error::success();
5337a7e6055SDimitry Andric }
5347a7e6055SDimitry Andric 
5357a7e6055SDimitry Andric Error WasmObjectFile::parseGlobalSection(const uint8_t *Ptr, const uint8_t *End) {
5367a7e6055SDimitry Andric   uint32_t Count = readVaruint32(Ptr);
5377a7e6055SDimitry Andric   Globals.reserve(Count);
5387a7e6055SDimitry Andric   while (Count--) {
5397a7e6055SDimitry Andric     wasm::WasmGlobal Global;
5407a7e6055SDimitry Andric     Global.Type = readVarint7(Ptr);
5417a7e6055SDimitry Andric     Global.Mutable = readVaruint1(Ptr);
5427a7e6055SDimitry Andric     if (Error Err = readInitExpr(Global.InitExpr, Ptr))
5437a7e6055SDimitry Andric       return Err;
5447a7e6055SDimitry Andric     Globals.push_back(Global);
5457a7e6055SDimitry Andric   }
5467a7e6055SDimitry Andric   if (Ptr != End)
5477a7e6055SDimitry Andric     return make_error<GenericBinaryError>("Global section ended prematurely",
5487a7e6055SDimitry Andric                                           object_error::parse_failed);
5497a7e6055SDimitry Andric   return Error::success();
5507a7e6055SDimitry Andric }
5517a7e6055SDimitry Andric 
5527a7e6055SDimitry Andric Error WasmObjectFile::parseExportSection(const uint8_t *Ptr, const uint8_t *End) {
5537a7e6055SDimitry Andric   uint32_t Count = readVaruint32(Ptr);
5547a7e6055SDimitry Andric   Exports.reserve(Count);
5550f5676f4SDimitry Andric   for (uint32_t i = 0; i < Count; i++) {
5567a7e6055SDimitry Andric     wasm::WasmExport Ex;
5577a7e6055SDimitry Andric     Ex.Name = readString(Ptr);
5587a7e6055SDimitry Andric     Ex.Kind = readUint8(Ptr);
5597a7e6055SDimitry Andric     Ex.Index = readVaruint32(Ptr);
5607a7e6055SDimitry Andric     switch (Ex.Kind) {
5617a7e6055SDimitry Andric     case wasm::WASM_EXTERNAL_FUNCTION:
562edd7eaddSDimitry Andric       SymbolMap.try_emplace(Ex.Name, Symbols.size());
5630f5676f4SDimitry Andric       Symbols.emplace_back(Ex.Name, WasmSymbol::SymbolType::FUNCTION_EXPORT,
5640f5676f4SDimitry Andric                            Sections.size(), i);
565edd7eaddSDimitry Andric       DEBUG(dbgs() << "Adding export: " << Symbols.back()
566edd7eaddSDimitry Andric                    << " sym index:" << Symbols.size() << "\n");
5677a7e6055SDimitry Andric       break;
5687a7e6055SDimitry Andric     case wasm::WASM_EXTERNAL_GLOBAL:
569edd7eaddSDimitry Andric       SymbolMap.try_emplace(Ex.Name, Symbols.size());
5700f5676f4SDimitry Andric       Symbols.emplace_back(Ex.Name, WasmSymbol::SymbolType::GLOBAL_EXPORT,
5710f5676f4SDimitry Andric                            Sections.size(), i);
572edd7eaddSDimitry Andric       DEBUG(dbgs() << "Adding export: " << Symbols.back()
573edd7eaddSDimitry Andric                    << " sym index:" << Symbols.size() << "\n");
5747a7e6055SDimitry Andric       break;
5755517e702SDimitry Andric     case wasm::WASM_EXTERNAL_MEMORY:
5765517e702SDimitry Andric     case wasm::WASM_EXTERNAL_TABLE:
5775517e702SDimitry Andric       break;
5787a7e6055SDimitry Andric     default:
5797a7e6055SDimitry Andric       return make_error<GenericBinaryError>(
5807a7e6055SDimitry Andric           "Unexpected export kind", object_error::parse_failed);
5817a7e6055SDimitry Andric     }
582edd7eaddSDimitry Andric     Exports.push_back(Ex);
5837a7e6055SDimitry Andric   }
5847a7e6055SDimitry Andric   if (Ptr != End)
5857a7e6055SDimitry Andric     return make_error<GenericBinaryError>("Export section ended prematurely",
5867a7e6055SDimitry Andric                                           object_error::parse_failed);
5877a7e6055SDimitry Andric   return Error::success();
5887a7e6055SDimitry Andric }
5897a7e6055SDimitry Andric 
5907a7e6055SDimitry Andric Error WasmObjectFile::parseStartSection(const uint8_t *Ptr, const uint8_t *End) {
5917a7e6055SDimitry Andric   StartFunction = readVaruint32(Ptr);
5925517e702SDimitry Andric   if (StartFunction >= FunctionTypes.size())
5937a7e6055SDimitry Andric     return make_error<GenericBinaryError>("Invalid start function",
5947a7e6055SDimitry Andric                                           object_error::parse_failed);
5957a7e6055SDimitry Andric   return Error::success();
5967a7e6055SDimitry Andric }
5977a7e6055SDimitry Andric 
5987a7e6055SDimitry Andric Error WasmObjectFile::parseCodeSection(const uint8_t *Ptr, const uint8_t *End) {
5997a7e6055SDimitry Andric   uint32_t FunctionCount = readVaruint32(Ptr);
6007a7e6055SDimitry Andric   if (FunctionCount != FunctionTypes.size()) {
6017a7e6055SDimitry Andric     return make_error<GenericBinaryError>("Invalid function count",
6027a7e6055SDimitry Andric                                           object_error::parse_failed);
6037a7e6055SDimitry Andric   }
6047a7e6055SDimitry Andric 
6057a7e6055SDimitry Andric   CodeSection = ArrayRef<uint8_t>(Ptr, End - Ptr);
6067a7e6055SDimitry Andric 
6077a7e6055SDimitry Andric   while (FunctionCount--) {
6087a7e6055SDimitry Andric     wasm::WasmFunction Function;
6097a7e6055SDimitry Andric     uint32_t FunctionSize = readVaruint32(Ptr);
6107a7e6055SDimitry Andric     const uint8_t *FunctionEnd = Ptr + FunctionSize;
6117a7e6055SDimitry Andric 
6127a7e6055SDimitry Andric     uint32_t NumLocalDecls = readVaruint32(Ptr);
6137a7e6055SDimitry Andric     Function.Locals.reserve(NumLocalDecls);
6147a7e6055SDimitry Andric     while (NumLocalDecls--) {
6157a7e6055SDimitry Andric       wasm::WasmLocalDecl Decl;
6167a7e6055SDimitry Andric       Decl.Count = readVaruint32(Ptr);
6177a7e6055SDimitry Andric       Decl.Type = readVarint7(Ptr);
6187a7e6055SDimitry Andric       Function.Locals.push_back(Decl);
6197a7e6055SDimitry Andric     }
6207a7e6055SDimitry Andric 
6217a7e6055SDimitry Andric     uint32_t BodySize = FunctionEnd - Ptr;
6227a7e6055SDimitry Andric     Function.Body = ArrayRef<uint8_t>(Ptr, BodySize);
6237a7e6055SDimitry Andric     Ptr += BodySize;
6247a7e6055SDimitry Andric     assert(Ptr == FunctionEnd);
6257a7e6055SDimitry Andric     Functions.push_back(Function);
6267a7e6055SDimitry Andric   }
6277a7e6055SDimitry Andric   if (Ptr != End)
6287a7e6055SDimitry Andric     return make_error<GenericBinaryError>("Code section ended prematurely",
6297a7e6055SDimitry Andric                                           object_error::parse_failed);
6307a7e6055SDimitry Andric   return Error::success();
6317a7e6055SDimitry Andric }
6327a7e6055SDimitry Andric 
6337a7e6055SDimitry Andric Error WasmObjectFile::parseElemSection(const uint8_t *Ptr, const uint8_t *End) {
6347a7e6055SDimitry Andric   uint32_t Count = readVaruint32(Ptr);
6357a7e6055SDimitry Andric   ElemSegments.reserve(Count);
6367a7e6055SDimitry Andric   while (Count--) {
6377a7e6055SDimitry Andric     wasm::WasmElemSegment Segment;
6387a7e6055SDimitry Andric     Segment.TableIndex = readVaruint32(Ptr);
6397a7e6055SDimitry Andric     if (Segment.TableIndex != 0) {
6407a7e6055SDimitry Andric       return make_error<GenericBinaryError>("Invalid TableIndex",
6417a7e6055SDimitry Andric                                             object_error::parse_failed);
6427a7e6055SDimitry Andric     }
6437a7e6055SDimitry Andric     if (Error Err = readInitExpr(Segment.Offset, Ptr))
6447a7e6055SDimitry Andric       return Err;
6457a7e6055SDimitry Andric     uint32_t NumElems = readVaruint32(Ptr);
6467a7e6055SDimitry Andric     while (NumElems--) {
6477a7e6055SDimitry Andric       Segment.Functions.push_back(readVaruint32(Ptr));
6487a7e6055SDimitry Andric     }
6497a7e6055SDimitry Andric     ElemSegments.push_back(Segment);
6507a7e6055SDimitry Andric   }
6517a7e6055SDimitry Andric   if (Ptr != End)
6527a7e6055SDimitry Andric     return make_error<GenericBinaryError>("Elem section ended prematurely",
6537a7e6055SDimitry Andric                                           object_error::parse_failed);
6547a7e6055SDimitry Andric   return Error::success();
6557a7e6055SDimitry Andric }
6567a7e6055SDimitry Andric 
6577a7e6055SDimitry Andric Error WasmObjectFile::parseDataSection(const uint8_t *Ptr, const uint8_t *End) {
6587a7e6055SDimitry Andric   uint32_t Count = readVaruint32(Ptr);
6597a7e6055SDimitry Andric   DataSegments.reserve(Count);
6607a7e6055SDimitry Andric   while (Count--) {
6617a7e6055SDimitry Andric     wasm::WasmDataSegment Segment;
6627a7e6055SDimitry Andric     Segment.Index = readVaruint32(Ptr);
6637a7e6055SDimitry Andric     if (Error Err = readInitExpr(Segment.Offset, Ptr))
6647a7e6055SDimitry Andric       return Err;
6657a7e6055SDimitry Andric     uint32_t Size = readVaruint32(Ptr);
6667a7e6055SDimitry Andric     Segment.Content = ArrayRef<uint8_t>(Ptr, Size);
6677a7e6055SDimitry Andric     Ptr += Size;
6687a7e6055SDimitry Andric     DataSegments.push_back(Segment);
6697a7e6055SDimitry Andric   }
6707a7e6055SDimitry Andric   if (Ptr != End)
6717a7e6055SDimitry Andric     return make_error<GenericBinaryError>("Data section ended prematurely",
6727a7e6055SDimitry Andric                                           object_error::parse_failed);
673d88c1a5aSDimitry Andric   return Error::success();
674d88c1a5aSDimitry Andric }
675d88c1a5aSDimitry Andric 
676d88c1a5aSDimitry Andric const uint8_t *WasmObjectFile::getPtr(size_t Offset) const {
677d88c1a5aSDimitry Andric   return reinterpret_cast<const uint8_t *>(getData().substr(Offset, 1).data());
678d88c1a5aSDimitry Andric }
679d88c1a5aSDimitry Andric 
680d88c1a5aSDimitry Andric const wasm::WasmObjectHeader &WasmObjectFile::getHeader() const {
681d88c1a5aSDimitry Andric   return Header;
682d88c1a5aSDimitry Andric }
683d88c1a5aSDimitry Andric 
6847a7e6055SDimitry Andric void WasmObjectFile::moveSymbolNext(DataRefImpl &Symb) const { Symb.d.a++; }
685d88c1a5aSDimitry Andric 
686d88c1a5aSDimitry Andric uint32_t WasmObjectFile::getSymbolFlags(DataRefImpl Symb) const {
6870f5676f4SDimitry Andric   uint32_t Result = SymbolRef::SF_None;
6887a7e6055SDimitry Andric   const WasmSymbol &Sym = getWasmSymbol(Symb);
6890f5676f4SDimitry Andric 
690edd7eaddSDimitry Andric   DEBUG(dbgs() << "getSymbolFlags: ptr=" << &Sym << " " << Sym << "\n");
691edd7eaddSDimitry Andric   if (Sym.Flags & wasm::WASM_SYMBOL_FLAG_WEAK)
692edd7eaddSDimitry Andric     Result |= SymbolRef::SF_Weak;
693edd7eaddSDimitry Andric 
6947a7e6055SDimitry Andric   switch (Sym.Type) {
6957a7e6055SDimitry Andric   case WasmSymbol::SymbolType::FUNCTION_IMPORT:
6960f5676f4SDimitry Andric     Result |= SymbolRef::SF_Undefined | SymbolRef::SF_Executable;
6970f5676f4SDimitry Andric     break;
6987a7e6055SDimitry Andric   case WasmSymbol::SymbolType::FUNCTION_EXPORT:
6990f5676f4SDimitry Andric     Result |= SymbolRef::SF_Global | SymbolRef::SF_Executable;
7000f5676f4SDimitry Andric     break;
7017a7e6055SDimitry Andric   case WasmSymbol::SymbolType::DEBUG_FUNCTION_NAME:
7020f5676f4SDimitry Andric     Result |= SymbolRef::SF_Executable;
703edd7eaddSDimitry Andric     Result |= SymbolRef::SF_FormatSpecific;
7040f5676f4SDimitry Andric     break;
7057a7e6055SDimitry Andric   case WasmSymbol::SymbolType::GLOBAL_IMPORT:
7060f5676f4SDimitry Andric     Result |= SymbolRef::SF_Undefined;
7070f5676f4SDimitry Andric     break;
7087a7e6055SDimitry Andric   case WasmSymbol::SymbolType::GLOBAL_EXPORT:
7090f5676f4SDimitry Andric     Result |= SymbolRef::SF_Global;
7100f5676f4SDimitry Andric     break;
7117a7e6055SDimitry Andric   }
7120f5676f4SDimitry Andric 
7130f5676f4SDimitry Andric   return Result;
714d88c1a5aSDimitry Andric }
715d88c1a5aSDimitry Andric 
716d88c1a5aSDimitry Andric basic_symbol_iterator WasmObjectFile::symbol_begin() const {
7177a7e6055SDimitry Andric   DataRefImpl Ref;
7187a7e6055SDimitry Andric   Ref.d.a = 0;
7197a7e6055SDimitry Andric   return BasicSymbolRef(Ref, this);
720d88c1a5aSDimitry Andric }
721d88c1a5aSDimitry Andric 
722d88c1a5aSDimitry Andric basic_symbol_iterator WasmObjectFile::symbol_end() const {
7237a7e6055SDimitry Andric   DataRefImpl Ref;
7247a7e6055SDimitry Andric   Ref.d.a = Symbols.size();
7257a7e6055SDimitry Andric   return BasicSymbolRef(Ref, this);
7267a7e6055SDimitry Andric }
7277a7e6055SDimitry Andric 
7285517e702SDimitry Andric const WasmSymbol &WasmObjectFile::getWasmSymbol(const DataRefImpl &Symb) const {
7297a7e6055SDimitry Andric   return Symbols[Symb.d.a];
730d88c1a5aSDimitry Andric }
731d88c1a5aSDimitry Andric 
7325517e702SDimitry Andric const WasmSymbol &WasmObjectFile::getWasmSymbol(const SymbolRef &Symb) const {
7335517e702SDimitry Andric   return getWasmSymbol(Symb.getRawDataRefImpl());
7345517e702SDimitry Andric }
7355517e702SDimitry Andric 
736d88c1a5aSDimitry Andric Expected<StringRef> WasmObjectFile::getSymbolName(DataRefImpl Symb) const {
737edd7eaddSDimitry Andric   return getWasmSymbol(Symb).Name;
738d88c1a5aSDimitry Andric }
739d88c1a5aSDimitry Andric 
740d88c1a5aSDimitry Andric Expected<uint64_t> WasmObjectFile::getSymbolAddress(DataRefImpl Symb) const {
7410f5676f4SDimitry Andric   return getSymbolValue(Symb);
742d88c1a5aSDimitry Andric }
743d88c1a5aSDimitry Andric 
744d88c1a5aSDimitry Andric uint64_t WasmObjectFile::getSymbolValueImpl(DataRefImpl Symb) const {
7450f5676f4SDimitry Andric   const WasmSymbol& Sym = getWasmSymbol(Symb);
746edd7eaddSDimitry Andric   switch (Sym.Type) {
747edd7eaddSDimitry Andric   case WasmSymbol::SymbolType::FUNCTION_IMPORT:
748edd7eaddSDimitry Andric   case WasmSymbol::SymbolType::GLOBAL_IMPORT:
749edd7eaddSDimitry Andric     return 0;
750edd7eaddSDimitry Andric   case WasmSymbol::SymbolType::FUNCTION_EXPORT:
751edd7eaddSDimitry Andric   case WasmSymbol::SymbolType::GLOBAL_EXPORT:
752edd7eaddSDimitry Andric     return Exports[Sym.ElementIndex].Index;
753edd7eaddSDimitry Andric   case WasmSymbol::SymbolType::DEBUG_FUNCTION_NAME:
7540f5676f4SDimitry Andric     return Sym.ElementIndex;
755d88c1a5aSDimitry Andric   }
756edd7eaddSDimitry Andric   llvm_unreachable("invalid symbol type");
757edd7eaddSDimitry Andric }
758d88c1a5aSDimitry Andric 
759d88c1a5aSDimitry Andric uint32_t WasmObjectFile::getSymbolAlignment(DataRefImpl Symb) const {
760d88c1a5aSDimitry Andric   llvm_unreachable("not yet implemented");
761d88c1a5aSDimitry Andric   return 0;
762d88c1a5aSDimitry Andric }
763d88c1a5aSDimitry Andric 
764d88c1a5aSDimitry Andric uint64_t WasmObjectFile::getCommonSymbolSizeImpl(DataRefImpl Symb) const {
765d88c1a5aSDimitry Andric   llvm_unreachable("not yet implemented");
766d88c1a5aSDimitry Andric   return 0;
767d88c1a5aSDimitry Andric }
768d88c1a5aSDimitry Andric 
769d88c1a5aSDimitry Andric Expected<SymbolRef::Type>
770d88c1a5aSDimitry Andric WasmObjectFile::getSymbolType(DataRefImpl Symb) const {
7710f5676f4SDimitry Andric   const WasmSymbol &Sym = getWasmSymbol(Symb);
7720f5676f4SDimitry Andric 
7730f5676f4SDimitry Andric   switch (Sym.Type) {
7740f5676f4SDimitry Andric   case WasmSymbol::SymbolType::FUNCTION_IMPORT:
7750f5676f4SDimitry Andric   case WasmSymbol::SymbolType::FUNCTION_EXPORT:
7760f5676f4SDimitry Andric   case WasmSymbol::SymbolType::DEBUG_FUNCTION_NAME:
7770f5676f4SDimitry Andric     return SymbolRef::ST_Function;
7780f5676f4SDimitry Andric   case WasmSymbol::SymbolType::GLOBAL_IMPORT:
7790f5676f4SDimitry Andric   case WasmSymbol::SymbolType::GLOBAL_EXPORT:
7800f5676f4SDimitry Andric     return SymbolRef::ST_Data;
7810f5676f4SDimitry Andric   }
7820f5676f4SDimitry Andric 
7830f5676f4SDimitry Andric   llvm_unreachable("Unknown WasmSymbol::SymbolType");
7840f5676f4SDimitry Andric   return SymbolRef::ST_Other;
785d88c1a5aSDimitry Andric }
786d88c1a5aSDimitry Andric 
787d88c1a5aSDimitry Andric Expected<section_iterator>
788d88c1a5aSDimitry Andric WasmObjectFile::getSymbolSection(DataRefImpl Symb) const {
7890f5676f4SDimitry Andric   DataRefImpl Ref;
7900f5676f4SDimitry Andric   Ref.d.a = getWasmSymbol(Symb).Section;
7910f5676f4SDimitry Andric   return section_iterator(SectionRef(Ref, this));
792d88c1a5aSDimitry Andric }
793d88c1a5aSDimitry Andric 
794d88c1a5aSDimitry Andric void WasmObjectFile::moveSectionNext(DataRefImpl &Sec) const { Sec.d.a++; }
795d88c1a5aSDimitry Andric 
796d88c1a5aSDimitry Andric std::error_code WasmObjectFile::getSectionName(DataRefImpl Sec,
797d88c1a5aSDimitry Andric                                                StringRef &Res) const {
7987a7e6055SDimitry Andric   const WasmSection &S = Sections[Sec.d.a];
799d88c1a5aSDimitry Andric #define ECase(X)                                                               \
800d88c1a5aSDimitry Andric   case wasm::WASM_SEC_##X:                                                     \
801d88c1a5aSDimitry Andric     Res = #X;                                                                  \
802d88c1a5aSDimitry Andric     break
803d88c1a5aSDimitry Andric   switch (S.Type) {
804d88c1a5aSDimitry Andric     ECase(TYPE);
805d88c1a5aSDimitry Andric     ECase(IMPORT);
806d88c1a5aSDimitry Andric     ECase(FUNCTION);
807d88c1a5aSDimitry Andric     ECase(TABLE);
808d88c1a5aSDimitry Andric     ECase(MEMORY);
809d88c1a5aSDimitry Andric     ECase(GLOBAL);
810d88c1a5aSDimitry Andric     ECase(EXPORT);
811d88c1a5aSDimitry Andric     ECase(START);
812d88c1a5aSDimitry Andric     ECase(ELEM);
813d88c1a5aSDimitry Andric     ECase(CODE);
814d88c1a5aSDimitry Andric     ECase(DATA);
8157a7e6055SDimitry Andric   case wasm::WASM_SEC_CUSTOM:
816d88c1a5aSDimitry Andric     Res = S.Name;
817d88c1a5aSDimitry Andric     break;
818d88c1a5aSDimitry Andric   default:
819d88c1a5aSDimitry Andric     return object_error::invalid_section_index;
820d88c1a5aSDimitry Andric   }
821d88c1a5aSDimitry Andric #undef ECase
822d88c1a5aSDimitry Andric   return std::error_code();
823d88c1a5aSDimitry Andric }
824d88c1a5aSDimitry Andric 
825d88c1a5aSDimitry Andric uint64_t WasmObjectFile::getSectionAddress(DataRefImpl Sec) const { return 0; }
826d88c1a5aSDimitry Andric 
827302affcbSDimitry Andric uint64_t WasmObjectFile::getSectionIndex(DataRefImpl Sec) const {
828302affcbSDimitry Andric   return Sec.d.a;
829302affcbSDimitry Andric }
830302affcbSDimitry Andric 
831d88c1a5aSDimitry Andric uint64_t WasmObjectFile::getSectionSize(DataRefImpl Sec) const {
8327a7e6055SDimitry Andric   const WasmSection &S = Sections[Sec.d.a];
833d88c1a5aSDimitry Andric   return S.Content.size();
834d88c1a5aSDimitry Andric }
835d88c1a5aSDimitry Andric 
836d88c1a5aSDimitry Andric std::error_code WasmObjectFile::getSectionContents(DataRefImpl Sec,
837d88c1a5aSDimitry Andric                                                    StringRef &Res) const {
8387a7e6055SDimitry Andric   const WasmSection &S = Sections[Sec.d.a];
839d88c1a5aSDimitry Andric   // This will never fail since wasm sections can never be empty (user-sections
840d88c1a5aSDimitry Andric   // must have a name and non-user sections each have a defined structure).
841d88c1a5aSDimitry Andric   Res = StringRef(reinterpret_cast<const char *>(S.Content.data()),
842d88c1a5aSDimitry Andric                   S.Content.size());
843d88c1a5aSDimitry Andric   return std::error_code();
844d88c1a5aSDimitry Andric }
845d88c1a5aSDimitry Andric 
846d88c1a5aSDimitry Andric uint64_t WasmObjectFile::getSectionAlignment(DataRefImpl Sec) const {
847d88c1a5aSDimitry Andric   return 1;
848d88c1a5aSDimitry Andric }
849d88c1a5aSDimitry Andric 
850d88c1a5aSDimitry Andric bool WasmObjectFile::isSectionCompressed(DataRefImpl Sec) const {
851d88c1a5aSDimitry Andric   return false;
852d88c1a5aSDimitry Andric }
853d88c1a5aSDimitry Andric 
854d88c1a5aSDimitry Andric bool WasmObjectFile::isSectionText(DataRefImpl Sec) const {
8557a7e6055SDimitry Andric   return getWasmSection(Sec).Type == wasm::WASM_SEC_CODE;
856d88c1a5aSDimitry Andric }
857d88c1a5aSDimitry Andric 
858d88c1a5aSDimitry Andric bool WasmObjectFile::isSectionData(DataRefImpl Sec) const {
8597a7e6055SDimitry Andric   return getWasmSection(Sec).Type == wasm::WASM_SEC_DATA;
860d88c1a5aSDimitry Andric }
861d88c1a5aSDimitry Andric 
862d88c1a5aSDimitry Andric bool WasmObjectFile::isSectionBSS(DataRefImpl Sec) const { return false; }
863d88c1a5aSDimitry Andric 
864d88c1a5aSDimitry Andric bool WasmObjectFile::isSectionVirtual(DataRefImpl Sec) const { return false; }
865d88c1a5aSDimitry Andric 
866d88c1a5aSDimitry Andric bool WasmObjectFile::isSectionBitcode(DataRefImpl Sec) const { return false; }
867d88c1a5aSDimitry Andric 
8687a7e6055SDimitry Andric relocation_iterator WasmObjectFile::section_rel_begin(DataRefImpl Ref) const {
8697a7e6055SDimitry Andric   DataRefImpl RelocRef;
8707a7e6055SDimitry Andric   RelocRef.d.a = Ref.d.a;
8717a7e6055SDimitry Andric   RelocRef.d.b = 0;
8727a7e6055SDimitry Andric   return relocation_iterator(RelocationRef(RelocRef, this));
873d88c1a5aSDimitry Andric }
874d88c1a5aSDimitry Andric 
8757a7e6055SDimitry Andric relocation_iterator WasmObjectFile::section_rel_end(DataRefImpl Ref) const {
8767a7e6055SDimitry Andric   const WasmSection &Sec = getWasmSection(Ref);
8777a7e6055SDimitry Andric   DataRefImpl RelocRef;
8787a7e6055SDimitry Andric   RelocRef.d.a = Ref.d.a;
8797a7e6055SDimitry Andric   RelocRef.d.b = Sec.Relocations.size();
8807a7e6055SDimitry Andric   return relocation_iterator(RelocationRef(RelocRef, this));
881d88c1a5aSDimitry Andric }
882d88c1a5aSDimitry Andric 
883d88c1a5aSDimitry Andric void WasmObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
8847a7e6055SDimitry Andric   Rel.d.b++;
885d88c1a5aSDimitry Andric }
886d88c1a5aSDimitry Andric 
8877a7e6055SDimitry Andric uint64_t WasmObjectFile::getRelocationOffset(DataRefImpl Ref) const {
8887a7e6055SDimitry Andric   const wasm::WasmRelocation &Rel = getWasmRelocation(Ref);
8897a7e6055SDimitry Andric   return Rel.Offset;
890d88c1a5aSDimitry Andric }
891d88c1a5aSDimitry Andric 
892d88c1a5aSDimitry Andric symbol_iterator WasmObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
893d88c1a5aSDimitry Andric   llvm_unreachable("not yet implemented");
894d88c1a5aSDimitry Andric   SymbolRef Ref;
895d88c1a5aSDimitry Andric   return symbol_iterator(Ref);
896d88c1a5aSDimitry Andric }
897d88c1a5aSDimitry Andric 
8987a7e6055SDimitry Andric uint64_t WasmObjectFile::getRelocationType(DataRefImpl Ref) const {
8997a7e6055SDimitry Andric   const wasm::WasmRelocation &Rel = getWasmRelocation(Ref);
9007a7e6055SDimitry Andric   return Rel.Type;
901d88c1a5aSDimitry Andric }
902d88c1a5aSDimitry Andric 
903d88c1a5aSDimitry Andric void WasmObjectFile::getRelocationTypeName(
9047a7e6055SDimitry Andric     DataRefImpl Ref, SmallVectorImpl<char> &Result) const {
9057a7e6055SDimitry Andric   const wasm::WasmRelocation& Rel = getWasmRelocation(Ref);
9067a7e6055SDimitry Andric   StringRef Res = "Unknown";
9077a7e6055SDimitry Andric 
9087a7e6055SDimitry Andric #define WASM_RELOC(name, value)  \
9097a7e6055SDimitry Andric   case wasm::name:              \
9107a7e6055SDimitry Andric     Res = #name;               \
9117a7e6055SDimitry Andric     break;
9127a7e6055SDimitry Andric 
9137a7e6055SDimitry Andric   switch (Rel.Type) {
914db17bf38SDimitry Andric #include "llvm/BinaryFormat/WasmRelocs/WebAssembly.def"
9157a7e6055SDimitry Andric   }
9167a7e6055SDimitry Andric 
9177a7e6055SDimitry Andric #undef WASM_RELOC
9187a7e6055SDimitry Andric 
9197a7e6055SDimitry Andric   Result.append(Res.begin(), Res.end());
920d88c1a5aSDimitry Andric }
921d88c1a5aSDimitry Andric 
922d88c1a5aSDimitry Andric section_iterator WasmObjectFile::section_begin() const {
923d88c1a5aSDimitry Andric   DataRefImpl Ref;
924d88c1a5aSDimitry Andric   Ref.d.a = 0;
925d88c1a5aSDimitry Andric   return section_iterator(SectionRef(Ref, this));
926d88c1a5aSDimitry Andric }
927d88c1a5aSDimitry Andric 
928d88c1a5aSDimitry Andric section_iterator WasmObjectFile::section_end() const {
929d88c1a5aSDimitry Andric   DataRefImpl Ref;
930d88c1a5aSDimitry Andric   Ref.d.a = Sections.size();
931d88c1a5aSDimitry Andric   return section_iterator(SectionRef(Ref, this));
932d88c1a5aSDimitry Andric }
933d88c1a5aSDimitry Andric 
934d88c1a5aSDimitry Andric uint8_t WasmObjectFile::getBytesInAddress() const { return 4; }
935d88c1a5aSDimitry Andric 
936d88c1a5aSDimitry Andric StringRef WasmObjectFile::getFileFormatName() const { return "WASM"; }
937d88c1a5aSDimitry Andric 
938d88c1a5aSDimitry Andric unsigned WasmObjectFile::getArch() const { return Triple::wasm32; }
939d88c1a5aSDimitry Andric 
940d88c1a5aSDimitry Andric SubtargetFeatures WasmObjectFile::getFeatures() const {
941d88c1a5aSDimitry Andric   return SubtargetFeatures();
942d88c1a5aSDimitry Andric }
943d88c1a5aSDimitry Andric 
944d88c1a5aSDimitry Andric bool WasmObjectFile::isRelocatableObject() const { return false; }
945d88c1a5aSDimitry Andric 
9467a7e6055SDimitry Andric const WasmSection &WasmObjectFile::getWasmSection(DataRefImpl Ref) const {
9477a7e6055SDimitry Andric   assert(Ref.d.a < Sections.size());
9487a7e6055SDimitry Andric   return Sections[Ref.d.a];
949d88c1a5aSDimitry Andric }
950d88c1a5aSDimitry Andric 
9517a7e6055SDimitry Andric const WasmSection &
9527a7e6055SDimitry Andric WasmObjectFile::getWasmSection(const SectionRef &Section) const {
9537a7e6055SDimitry Andric   return getWasmSection(Section.getRawDataRefImpl());
9547a7e6055SDimitry Andric }
9557a7e6055SDimitry Andric 
9567a7e6055SDimitry Andric const wasm::WasmRelocation &
9577a7e6055SDimitry Andric WasmObjectFile::getWasmRelocation(const RelocationRef &Ref) const {
9587a7e6055SDimitry Andric   return getWasmRelocation(Ref.getRawDataRefImpl());
9597a7e6055SDimitry Andric }
9607a7e6055SDimitry Andric 
9617a7e6055SDimitry Andric const wasm::WasmRelocation &
9627a7e6055SDimitry Andric WasmObjectFile::getWasmRelocation(DataRefImpl Ref) const {
9637a7e6055SDimitry Andric   assert(Ref.d.a < Sections.size());
9647a7e6055SDimitry Andric   const WasmSection& Sec = Sections[Ref.d.a];
9657a7e6055SDimitry Andric   assert(Ref.d.b < Sec.Relocations.size());
9667a7e6055SDimitry Andric   return Sec.Relocations[Ref.d.b];
9677a7e6055SDimitry Andric }
968