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"
114ba319b5SDimitry Andric #include "llvm/ADT/DenseSet.h"
127a7e6055SDimitry Andric #include "llvm/ADT/STLExtras.h"
137a7e6055SDimitry Andric #include "llvm/ADT/StringRef.h"
144ba319b5SDimitry Andric #include "llvm/ADT/StringSet.h"
157a7e6055SDimitry Andric #include "llvm/ADT/Triple.h"
16db17bf38SDimitry Andric #include "llvm/BinaryFormat/Wasm.h"
1751690af2SDimitry Andric #include "llvm/MC/SubtargetFeature.h"
187a7e6055SDimitry Andric #include "llvm/Object/Binary.h"
197a7e6055SDimitry Andric #include "llvm/Object/Error.h"
207a7e6055SDimitry Andric #include "llvm/Object/ObjectFile.h"
217a7e6055SDimitry Andric #include "llvm/Object/SymbolicFile.h"
22d88c1a5aSDimitry Andric #include "llvm/Object/Wasm.h"
23d88c1a5aSDimitry Andric #include "llvm/Support/Endian.h"
247a7e6055SDimitry Andric #include "llvm/Support/Error.h"
257a7e6055SDimitry Andric #include "llvm/Support/ErrorHandling.h"
26d88c1a5aSDimitry Andric #include "llvm/Support/LEB128.h"
27*b5893f02SDimitry Andric #include "llvm/Support/ScopedPrinter.h"
287a7e6055SDimitry Andric #include <algorithm>
2951690af2SDimitry Andric #include <cassert>
307a7e6055SDimitry Andric #include <cstdint>
3151690af2SDimitry Andric #include <cstring>
327a7e6055SDimitry Andric #include <system_error>
33d88c1a5aSDimitry Andric 
34edd7eaddSDimitry Andric #define DEBUG_TYPE "wasm-object"
35edd7eaddSDimitry Andric 
367a7e6055SDimitry Andric using namespace llvm;
377a7e6055SDimitry Andric using namespace object;
38d88c1a5aSDimitry Andric 
print(raw_ostream & Out) const394ba319b5SDimitry Andric void WasmSymbol::print(raw_ostream &Out) const {
404ba319b5SDimitry Andric   Out << "Name=" << Info.Name
414ba319b5SDimitry Andric       << ", Kind=" << toString(wasm::WasmSymbolType(Info.Kind))
424ba319b5SDimitry Andric       << ", Flags=" << Info.Flags;
434ba319b5SDimitry Andric   if (!isTypeData()) {
444ba319b5SDimitry Andric     Out << ", ElemIndex=" << Info.ElementIndex;
454ba319b5SDimitry Andric   } else if (isDefined()) {
464ba319b5SDimitry Andric     Out << ", Segment=" << Info.DataRef.Segment;
474ba319b5SDimitry Andric     Out << ", Offset=" << Info.DataRef.Offset;
484ba319b5SDimitry Andric     Out << ", Size=" << Info.DataRef.Size;
494ba319b5SDimitry Andric   }
504ba319b5SDimitry Andric }
514ba319b5SDimitry Andric 
524ba319b5SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
dump() const534ba319b5SDimitry Andric LLVM_DUMP_METHOD void WasmSymbol::dump() const { print(dbgs()); }
544ba319b5SDimitry Andric #endif
554ba319b5SDimitry Andric 
56d88c1a5aSDimitry Andric Expected<std::unique_ptr<WasmObjectFile>>
createWasmObjectFile(MemoryBufferRef Buffer)57d88c1a5aSDimitry Andric ObjectFile::createWasmObjectFile(MemoryBufferRef Buffer) {
58d88c1a5aSDimitry Andric   Error Err = Error::success();
59d88c1a5aSDimitry Andric   auto ObjectFile = llvm::make_unique<WasmObjectFile>(Buffer, Err);
60d88c1a5aSDimitry Andric   if (Err)
61d88c1a5aSDimitry Andric     return std::move(Err);
62d88c1a5aSDimitry Andric 
63d88c1a5aSDimitry Andric   return std::move(ObjectFile);
64d88c1a5aSDimitry Andric }
65d88c1a5aSDimitry Andric 
667a7e6055SDimitry Andric #define VARINT7_MAX ((1 << 7) - 1)
677a7e6055SDimitry Andric #define VARINT7_MIN (-(1 << 7))
687a7e6055SDimitry Andric #define VARUINT7_MAX (1 << 7)
697a7e6055SDimitry Andric #define VARUINT1_MAX (1)
70d88c1a5aSDimitry Andric 
readUint8(WasmObjectFile::ReadContext & Ctx)714ba319b5SDimitry Andric static uint8_t readUint8(WasmObjectFile::ReadContext &Ctx) {
724ba319b5SDimitry Andric   if (Ctx.Ptr == Ctx.End)
734ba319b5SDimitry Andric     report_fatal_error("EOF while reading uint8");
744ba319b5SDimitry Andric   return *Ctx.Ptr++;
754ba319b5SDimitry Andric }
767a7e6055SDimitry Andric 
readUint32(WasmObjectFile::ReadContext & Ctx)774ba319b5SDimitry Andric static uint32_t readUint32(WasmObjectFile::ReadContext &Ctx) {
784ba319b5SDimitry Andric   if (Ctx.Ptr + 4 > Ctx.End)
794ba319b5SDimitry Andric     report_fatal_error("EOF while reading uint32");
804ba319b5SDimitry Andric   uint32_t Result = support::endian::read32le(Ctx.Ptr);
814ba319b5SDimitry Andric   Ctx.Ptr += 4;
82d88c1a5aSDimitry Andric   return Result;
83d88c1a5aSDimitry Andric }
84d88c1a5aSDimitry Andric 
readFloat32(WasmObjectFile::ReadContext & Ctx)854ba319b5SDimitry Andric static int32_t readFloat32(WasmObjectFile::ReadContext &Ctx) {
86*b5893f02SDimitry Andric   if (Ctx.Ptr + 4 > Ctx.End)
87*b5893f02SDimitry Andric     report_fatal_error("EOF while reading float64");
887a7e6055SDimitry Andric   int32_t Result = 0;
894ba319b5SDimitry Andric   memcpy(&Result, Ctx.Ptr, sizeof(Result));
904ba319b5SDimitry Andric   Ctx.Ptr += sizeof(Result);
917a7e6055SDimitry Andric   return Result;
927a7e6055SDimitry Andric }
937a7e6055SDimitry Andric 
readFloat64(WasmObjectFile::ReadContext & Ctx)944ba319b5SDimitry Andric static int64_t readFloat64(WasmObjectFile::ReadContext &Ctx) {
95*b5893f02SDimitry Andric   if (Ctx.Ptr + 8 > Ctx.End)
96*b5893f02SDimitry Andric     report_fatal_error("EOF while reading float64");
977a7e6055SDimitry Andric   int64_t Result = 0;
984ba319b5SDimitry Andric   memcpy(&Result, Ctx.Ptr, sizeof(Result));
994ba319b5SDimitry Andric   Ctx.Ptr += sizeof(Result);
1007a7e6055SDimitry Andric   return Result;
1017a7e6055SDimitry Andric }
1027a7e6055SDimitry Andric 
readULEB128(WasmObjectFile::ReadContext & Ctx)1034ba319b5SDimitry Andric static uint64_t readULEB128(WasmObjectFile::ReadContext &Ctx) {
104d88c1a5aSDimitry Andric   unsigned Count;
1054ba319b5SDimitry Andric   const char *Error = nullptr;
1064ba319b5SDimitry Andric   uint64_t Result = decodeULEB128(Ctx.Ptr, &Count, Ctx.End, &Error);
1074ba319b5SDimitry Andric   if (Error)
1084ba319b5SDimitry Andric     report_fatal_error(Error);
1094ba319b5SDimitry Andric   Ctx.Ptr += Count;
110d88c1a5aSDimitry Andric   return Result;
111d88c1a5aSDimitry Andric }
112d88c1a5aSDimitry Andric 
readString(WasmObjectFile::ReadContext & Ctx)1134ba319b5SDimitry Andric static StringRef readString(WasmObjectFile::ReadContext &Ctx) {
1144ba319b5SDimitry Andric   uint32_t StringLen = readULEB128(Ctx);
1154ba319b5SDimitry Andric   if (Ctx.Ptr + StringLen > Ctx.End)
1164ba319b5SDimitry Andric     report_fatal_error("EOF while reading string");
1174ba319b5SDimitry Andric   StringRef Return =
1184ba319b5SDimitry Andric       StringRef(reinterpret_cast<const char *>(Ctx.Ptr), StringLen);
1194ba319b5SDimitry Andric   Ctx.Ptr += StringLen;
120d88c1a5aSDimitry Andric   return Return;
121d88c1a5aSDimitry Andric }
122d88c1a5aSDimitry Andric 
readLEB128(WasmObjectFile::ReadContext & Ctx)1234ba319b5SDimitry Andric static int64_t readLEB128(WasmObjectFile::ReadContext &Ctx) {
1247a7e6055SDimitry Andric   unsigned Count;
1254ba319b5SDimitry Andric   const char *Error = nullptr;
1264ba319b5SDimitry Andric   uint64_t Result = decodeSLEB128(Ctx.Ptr, &Count, Ctx.End, &Error);
1274ba319b5SDimitry Andric   if (Error)
1284ba319b5SDimitry Andric     report_fatal_error(Error);
1294ba319b5SDimitry Andric   Ctx.Ptr += Count;
1307a7e6055SDimitry Andric   return Result;
1317a7e6055SDimitry Andric }
1327a7e6055SDimitry Andric 
readVaruint1(WasmObjectFile::ReadContext & Ctx)1334ba319b5SDimitry Andric static uint8_t readVaruint1(WasmObjectFile::ReadContext &Ctx) {
1344ba319b5SDimitry Andric   int64_t result = readLEB128(Ctx);
1354ba319b5SDimitry Andric   if (result > VARUINT1_MAX || result < 0)
1364ba319b5SDimitry Andric     report_fatal_error("LEB is outside Varuint1 range");
1377a7e6055SDimitry Andric   return result;
1387a7e6055SDimitry Andric }
1397a7e6055SDimitry Andric 
readVarint32(WasmObjectFile::ReadContext & Ctx)1404ba319b5SDimitry Andric static int32_t readVarint32(WasmObjectFile::ReadContext &Ctx) {
1414ba319b5SDimitry Andric   int64_t result = readLEB128(Ctx);
1424ba319b5SDimitry Andric   if (result > INT32_MAX || result < INT32_MIN)
1434ba319b5SDimitry Andric     report_fatal_error("LEB is outside Varint32 range");
1447a7e6055SDimitry Andric   return result;
1457a7e6055SDimitry Andric }
1467a7e6055SDimitry Andric 
readVaruint32(WasmObjectFile::ReadContext & Ctx)1474ba319b5SDimitry Andric static uint32_t readVaruint32(WasmObjectFile::ReadContext &Ctx) {
1484ba319b5SDimitry Andric   uint64_t result = readULEB128(Ctx);
1494ba319b5SDimitry Andric   if (result > UINT32_MAX)
1504ba319b5SDimitry Andric     report_fatal_error("LEB is outside Varuint32 range");
1517a7e6055SDimitry Andric   return result;
1527a7e6055SDimitry Andric }
1537a7e6055SDimitry Andric 
readVarint64(WasmObjectFile::ReadContext & Ctx)1544ba319b5SDimitry Andric static int64_t readVarint64(WasmObjectFile::ReadContext &Ctx) {
1554ba319b5SDimitry Andric   return readLEB128(Ctx);
1567a7e6055SDimitry Andric }
1577a7e6055SDimitry Andric 
readOpcode(WasmObjectFile::ReadContext & Ctx)1584ba319b5SDimitry Andric static uint8_t readOpcode(WasmObjectFile::ReadContext &Ctx) {
1594ba319b5SDimitry Andric   return readUint8(Ctx);
1607a7e6055SDimitry Andric }
1617a7e6055SDimitry Andric 
readInitExpr(wasm::WasmInitExpr & Expr,WasmObjectFile::ReadContext & Ctx)1624ba319b5SDimitry Andric static Error readInitExpr(wasm::WasmInitExpr &Expr,
1634ba319b5SDimitry Andric                           WasmObjectFile::ReadContext &Ctx) {
1644ba319b5SDimitry Andric   Expr.Opcode = readOpcode(Ctx);
1657a7e6055SDimitry Andric 
1667a7e6055SDimitry Andric   switch (Expr.Opcode) {
1677a7e6055SDimitry Andric   case wasm::WASM_OPCODE_I32_CONST:
1684ba319b5SDimitry Andric     Expr.Value.Int32 = readVarint32(Ctx);
1697a7e6055SDimitry Andric     break;
1707a7e6055SDimitry Andric   case wasm::WASM_OPCODE_I64_CONST:
1714ba319b5SDimitry Andric     Expr.Value.Int64 = readVarint64(Ctx);
1727a7e6055SDimitry Andric     break;
1737a7e6055SDimitry Andric   case wasm::WASM_OPCODE_F32_CONST:
1744ba319b5SDimitry Andric     Expr.Value.Float32 = readFloat32(Ctx);
1757a7e6055SDimitry Andric     break;
1767a7e6055SDimitry Andric   case wasm::WASM_OPCODE_F64_CONST:
1774ba319b5SDimitry Andric     Expr.Value.Float64 = readFloat64(Ctx);
1787a7e6055SDimitry Andric     break;
179*b5893f02SDimitry Andric   case wasm::WASM_OPCODE_GLOBAL_GET:
1804ba319b5SDimitry Andric     Expr.Value.Global = readULEB128(Ctx);
1817a7e6055SDimitry Andric     break;
1827a7e6055SDimitry Andric   default:
1837a7e6055SDimitry Andric     return make_error<GenericBinaryError>("Invalid opcode in init_expr",
1847a7e6055SDimitry Andric                                           object_error::parse_failed);
1857a7e6055SDimitry Andric   }
1867a7e6055SDimitry Andric 
1874ba319b5SDimitry Andric   uint8_t EndOpcode = readOpcode(Ctx);
1887a7e6055SDimitry Andric   if (EndOpcode != wasm::WASM_OPCODE_END) {
1897a7e6055SDimitry Andric     return make_error<GenericBinaryError>("Invalid init_expr",
1907a7e6055SDimitry Andric                                           object_error::parse_failed);
1917a7e6055SDimitry Andric   }
1927a7e6055SDimitry Andric   return Error::success();
1937a7e6055SDimitry Andric }
1947a7e6055SDimitry Andric 
readLimits(WasmObjectFile::ReadContext & Ctx)1954ba319b5SDimitry Andric static wasm::WasmLimits readLimits(WasmObjectFile::ReadContext &Ctx) {
1967a7e6055SDimitry Andric   wasm::WasmLimits Result;
197*b5893f02SDimitry Andric   Result.Flags = readVaruint32(Ctx);
1984ba319b5SDimitry Andric   Result.Initial = readVaruint32(Ctx);
1997a7e6055SDimitry Andric   if (Result.Flags & wasm::WASM_LIMITS_FLAG_HAS_MAX)
2004ba319b5SDimitry Andric     Result.Maximum = readVaruint32(Ctx);
2017a7e6055SDimitry Andric   return Result;
2027a7e6055SDimitry Andric }
2037a7e6055SDimitry Andric 
readTable(WasmObjectFile::ReadContext & Ctx)2044ba319b5SDimitry Andric static wasm::WasmTable readTable(WasmObjectFile::ReadContext &Ctx) {
2055517e702SDimitry Andric   wasm::WasmTable Table;
2064ba319b5SDimitry Andric   Table.ElemType = readUint8(Ctx);
2074ba319b5SDimitry Andric   Table.Limits = readLimits(Ctx);
2085517e702SDimitry Andric   return Table;
2095517e702SDimitry Andric }
2105517e702SDimitry Andric 
readSection(WasmSection & Section,WasmObjectFile::ReadContext & Ctx,WasmSectionOrderChecker & Checker)211*b5893f02SDimitry Andric static Error readSection(WasmSection &Section, WasmObjectFile::ReadContext &Ctx,
212*b5893f02SDimitry Andric                          WasmSectionOrderChecker &Checker) {
2134ba319b5SDimitry Andric   Section.Offset = Ctx.Ptr - Ctx.Start;
2144ba319b5SDimitry Andric   Section.Type = readUint8(Ctx);
2154ba319b5SDimitry Andric   LLVM_DEBUG(dbgs() << "readSection type=" << Section.Type << "\n");
2164ba319b5SDimitry Andric   uint32_t Size = readVaruint32(Ctx);
217d88c1a5aSDimitry Andric   if (Size == 0)
218d88c1a5aSDimitry Andric     return make_error<StringError>("Zero length section",
219d88c1a5aSDimitry Andric                                    object_error::parse_failed);
2204ba319b5SDimitry Andric   if (Ctx.Ptr + Size > Ctx.End)
2212cab237bSDimitry Andric     return make_error<StringError>("Section too large",
2222cab237bSDimitry Andric                                    object_error::parse_failed);
2234ba319b5SDimitry Andric   if (Section.Type == wasm::WASM_SEC_CUSTOM) {
224*b5893f02SDimitry Andric     WasmObjectFile::ReadContext SectionCtx;
225*b5893f02SDimitry Andric     SectionCtx.Start = Ctx.Ptr;
226*b5893f02SDimitry Andric     SectionCtx.Ptr = Ctx.Ptr;
227*b5893f02SDimitry Andric     SectionCtx.End = Ctx.Ptr + Size;
228*b5893f02SDimitry Andric 
229*b5893f02SDimitry Andric     Section.Name = readString(SectionCtx);
230*b5893f02SDimitry Andric 
231*b5893f02SDimitry Andric     uint32_t SectionNameSize = SectionCtx.Ptr - SectionCtx.Start;
232*b5893f02SDimitry Andric     Ctx.Ptr += SectionNameSize;
233*b5893f02SDimitry Andric     Size -= SectionNameSize;
2344ba319b5SDimitry Andric   }
235*b5893f02SDimitry Andric 
236*b5893f02SDimitry Andric   if (!Checker.isValidSectionOrder(Section.Type, Section.Name)) {
237*b5893f02SDimitry Andric     return make_error<StringError>("Out of order section type: " +
238*b5893f02SDimitry Andric                                        llvm::to_string(Section.Type),
239*b5893f02SDimitry Andric                                    object_error::parse_failed);
240*b5893f02SDimitry Andric   }
241*b5893f02SDimitry Andric 
2424ba319b5SDimitry Andric   Section.Content = ArrayRef<uint8_t>(Ctx.Ptr, Size);
2434ba319b5SDimitry Andric   Ctx.Ptr += Size;
244d88c1a5aSDimitry Andric   return Error::success();
245d88c1a5aSDimitry Andric }
246d88c1a5aSDimitry Andric 
WasmObjectFile(MemoryBufferRef Buffer,Error & Err)247d88c1a5aSDimitry Andric WasmObjectFile::WasmObjectFile(MemoryBufferRef Buffer, Error &Err)
24851690af2SDimitry Andric     : ObjectFile(Binary::ID_Wasm, Buffer) {
249d88c1a5aSDimitry Andric   ErrorAsOutParameter ErrAsOutParam(&Err);
250d88c1a5aSDimitry Andric   Header.Magic = getData().substr(0, 4);
251d88c1a5aSDimitry Andric   if (Header.Magic != StringRef("\0asm", 4)) {
252*b5893f02SDimitry Andric     Err =
253*b5893f02SDimitry Andric         make_error<StringError>("Bad magic number", object_error::parse_failed);
254d88c1a5aSDimitry Andric     return;
255d88c1a5aSDimitry Andric   }
2562cab237bSDimitry Andric 
2574ba319b5SDimitry Andric   ReadContext Ctx;
2584ba319b5SDimitry Andric   Ctx.Start = getPtr(0);
2594ba319b5SDimitry Andric   Ctx.Ptr = Ctx.Start + 4;
2604ba319b5SDimitry Andric   Ctx.End = Ctx.Start + getData().size();
2612cab237bSDimitry Andric 
2624ba319b5SDimitry Andric   if (Ctx.Ptr + 4 > Ctx.End) {
2632cab237bSDimitry Andric     Err = make_error<StringError>("Missing version number",
2642cab237bSDimitry Andric                                   object_error::parse_failed);
2652cab237bSDimitry Andric     return;
2662cab237bSDimitry Andric   }
2672cab237bSDimitry Andric 
2684ba319b5SDimitry Andric   Header.Version = readUint32(Ctx);
269d88c1a5aSDimitry Andric   if (Header.Version != wasm::WasmVersion) {
270d88c1a5aSDimitry Andric     Err = make_error<StringError>("Bad version number",
271d88c1a5aSDimitry Andric                                   object_error::parse_failed);
272d88c1a5aSDimitry Andric     return;
273d88c1a5aSDimitry Andric   }
274d88c1a5aSDimitry Andric 
2757a7e6055SDimitry Andric   WasmSection Sec;
276*b5893f02SDimitry Andric   WasmSectionOrderChecker Checker;
2774ba319b5SDimitry Andric   while (Ctx.Ptr < Ctx.End) {
278*b5893f02SDimitry Andric     if ((Err = readSection(Sec, Ctx, Checker)))
279d88c1a5aSDimitry Andric       return;
2807a7e6055SDimitry Andric     if ((Err = parseSection(Sec)))
281d88c1a5aSDimitry Andric       return;
2827a7e6055SDimitry Andric 
283d88c1a5aSDimitry Andric     Sections.push_back(Sec);
284d88c1a5aSDimitry Andric   }
285d88c1a5aSDimitry Andric }
286d88c1a5aSDimitry Andric 
parseSection(WasmSection & Sec)2877a7e6055SDimitry Andric Error WasmObjectFile::parseSection(WasmSection &Sec) {
2884ba319b5SDimitry Andric   ReadContext Ctx;
2894ba319b5SDimitry Andric   Ctx.Start = Sec.Content.data();
2904ba319b5SDimitry Andric   Ctx.End = Ctx.Start + Sec.Content.size();
2914ba319b5SDimitry Andric   Ctx.Ptr = Ctx.Start;
2927a7e6055SDimitry Andric   switch (Sec.Type) {
2937a7e6055SDimitry Andric   case wasm::WASM_SEC_CUSTOM:
2944ba319b5SDimitry Andric     return parseCustomSection(Sec, Ctx);
2957a7e6055SDimitry Andric   case wasm::WASM_SEC_TYPE:
2964ba319b5SDimitry Andric     return parseTypeSection(Ctx);
2977a7e6055SDimitry Andric   case wasm::WASM_SEC_IMPORT:
2984ba319b5SDimitry Andric     return parseImportSection(Ctx);
2997a7e6055SDimitry Andric   case wasm::WASM_SEC_FUNCTION:
3004ba319b5SDimitry Andric     return parseFunctionSection(Ctx);
3017a7e6055SDimitry Andric   case wasm::WASM_SEC_TABLE:
3024ba319b5SDimitry Andric     return parseTableSection(Ctx);
3037a7e6055SDimitry Andric   case wasm::WASM_SEC_MEMORY:
3044ba319b5SDimitry Andric     return parseMemorySection(Ctx);
3057a7e6055SDimitry Andric   case wasm::WASM_SEC_GLOBAL:
3064ba319b5SDimitry Andric     return parseGlobalSection(Ctx);
307*b5893f02SDimitry Andric   case wasm::WASM_SEC_EVENT:
308*b5893f02SDimitry Andric     return parseEventSection(Ctx);
3097a7e6055SDimitry Andric   case wasm::WASM_SEC_EXPORT:
3104ba319b5SDimitry Andric     return parseExportSection(Ctx);
3117a7e6055SDimitry Andric   case wasm::WASM_SEC_START:
3124ba319b5SDimitry Andric     return parseStartSection(Ctx);
3137a7e6055SDimitry Andric   case wasm::WASM_SEC_ELEM:
3144ba319b5SDimitry Andric     return parseElemSection(Ctx);
3157a7e6055SDimitry Andric   case wasm::WASM_SEC_CODE:
3164ba319b5SDimitry Andric     return parseCodeSection(Ctx);
3177a7e6055SDimitry Andric   case wasm::WASM_SEC_DATA:
3184ba319b5SDimitry Andric     return parseDataSection(Ctx);
3197a7e6055SDimitry Andric   default:
3207a7e6055SDimitry Andric     return make_error<GenericBinaryError>("Bad section type",
3217a7e6055SDimitry Andric                                           object_error::parse_failed);
3227a7e6055SDimitry Andric   }
3237a7e6055SDimitry Andric }
3247a7e6055SDimitry Andric 
parseDylinkSection(ReadContext & Ctx)325*b5893f02SDimitry Andric Error WasmObjectFile::parseDylinkSection(ReadContext &Ctx) {
326*b5893f02SDimitry Andric   // See https://github.com/WebAssembly/tool-conventions/blob/master/DynamicLinking.md
327*b5893f02SDimitry Andric   DylinkInfo.MemorySize = readVaruint32(Ctx);
328*b5893f02SDimitry Andric   DylinkInfo.MemoryAlignment = readVaruint32(Ctx);
329*b5893f02SDimitry Andric   DylinkInfo.TableSize = readVaruint32(Ctx);
330*b5893f02SDimitry Andric   DylinkInfo.TableAlignment = readVaruint32(Ctx);
331*b5893f02SDimitry Andric   uint32_t Count = readVaruint32(Ctx);
332*b5893f02SDimitry Andric   while (Count--) {
333*b5893f02SDimitry Andric     DylinkInfo.Needed.push_back(readString(Ctx));
334*b5893f02SDimitry Andric   }
335*b5893f02SDimitry Andric   if (Ctx.Ptr != Ctx.End)
336*b5893f02SDimitry Andric     return make_error<GenericBinaryError>("dylink section ended prematurely",
337*b5893f02SDimitry Andric                                           object_error::parse_failed);
338*b5893f02SDimitry Andric   return Error::success();
339*b5893f02SDimitry Andric }
340*b5893f02SDimitry Andric 
parseNameSection(ReadContext & Ctx)3414ba319b5SDimitry Andric Error WasmObjectFile::parseNameSection(ReadContext &Ctx) {
3424ba319b5SDimitry Andric   llvm::DenseSet<uint64_t> Seen;
3434ba319b5SDimitry Andric   if (Functions.size() != FunctionTypes.size()) {
3444ba319b5SDimitry Andric     return make_error<GenericBinaryError>("Names must come after code section",
3454ba319b5SDimitry Andric                                           object_error::parse_failed);
3464ba319b5SDimitry Andric   }
3474ba319b5SDimitry Andric 
3484ba319b5SDimitry Andric   while (Ctx.Ptr < Ctx.End) {
3494ba319b5SDimitry Andric     uint8_t Type = readUint8(Ctx);
3504ba319b5SDimitry Andric     uint32_t Size = readVaruint32(Ctx);
3514ba319b5SDimitry Andric     const uint8_t *SubSectionEnd = Ctx.Ptr + Size;
3527a7e6055SDimitry Andric     switch (Type) {
3537a7e6055SDimitry Andric     case wasm::WASM_NAMES_FUNCTION: {
3544ba319b5SDimitry Andric       uint32_t Count = readVaruint32(Ctx);
3557a7e6055SDimitry Andric       while (Count--) {
3564ba319b5SDimitry Andric         uint32_t Index = readVaruint32(Ctx);
3574ba319b5SDimitry Andric         if (!Seen.insert(Index).second)
3584ba319b5SDimitry Andric           return make_error<GenericBinaryError>("Function named more than once",
3594ba319b5SDimitry Andric                                                 object_error::parse_failed);
3604ba319b5SDimitry Andric         StringRef Name = readString(Ctx);
3614ba319b5SDimitry Andric         if (!isValidFunctionIndex(Index) || Name.empty())
3624ba319b5SDimitry Andric           return make_error<GenericBinaryError>("Invalid name entry",
3634ba319b5SDimitry Andric                                                 object_error::parse_failed);
3644ba319b5SDimitry Andric         DebugNames.push_back(wasm::WasmFunctionName{Index, Name});
3654ba319b5SDimitry Andric         if (isDefinedFunctionIndex(Index))
3664ba319b5SDimitry Andric           getDefinedFunction(Index).DebugName = Name;
3677a7e6055SDimitry Andric       }
3687a7e6055SDimitry Andric       break;
3697a7e6055SDimitry Andric     }
3707a7e6055SDimitry Andric     // Ignore local names for now
3717a7e6055SDimitry Andric     case wasm::WASM_NAMES_LOCAL:
3727a7e6055SDimitry Andric     default:
3734ba319b5SDimitry Andric       Ctx.Ptr += Size;
3747a7e6055SDimitry Andric       break;
3757a7e6055SDimitry Andric     }
3764ba319b5SDimitry Andric     if (Ctx.Ptr != SubSectionEnd)
377*b5893f02SDimitry Andric       return make_error<GenericBinaryError>(
378*b5893f02SDimitry Andric           "Name sub-section ended prematurely", object_error::parse_failed);
3797a7e6055SDimitry Andric   }
3807a7e6055SDimitry Andric 
3814ba319b5SDimitry Andric   if (Ctx.Ptr != Ctx.End)
3827a7e6055SDimitry Andric     return make_error<GenericBinaryError>("Name section ended prematurely",
3837a7e6055SDimitry Andric                                           object_error::parse_failed);
3847a7e6055SDimitry Andric   return Error::success();
3857a7e6055SDimitry Andric }
3867a7e6055SDimitry Andric 
parseLinkingSection(ReadContext & Ctx)3874ba319b5SDimitry Andric Error WasmObjectFile::parseLinkingSection(ReadContext &Ctx) {
388a580b014SDimitry Andric   HasLinkingSection = true;
3894ba319b5SDimitry Andric   if (Functions.size() != FunctionTypes.size()) {
390edd7eaddSDimitry Andric     return make_error<GenericBinaryError>(
391*b5893f02SDimitry Andric         "Linking data must come after code section",
392*b5893f02SDimitry Andric         object_error::parse_failed);
3934ba319b5SDimitry Andric   }
3944ba319b5SDimitry Andric 
3954ba319b5SDimitry Andric   LinkingData.Version = readVaruint32(Ctx);
3964ba319b5SDimitry Andric   if (LinkingData.Version != wasm::WasmMetadataVersion) {
3974ba319b5SDimitry Andric     return make_error<GenericBinaryError>(
3984ba319b5SDimitry Andric         "Unexpected metadata version: " + Twine(LinkingData.Version) +
3994ba319b5SDimitry Andric             " (Expected: " + Twine(wasm::WasmMetadataVersion) + ")",
400edd7eaddSDimitry Andric         object_error::parse_failed);
401edd7eaddSDimitry Andric   }
4024ba319b5SDimitry Andric 
4034ba319b5SDimitry Andric   const uint8_t *OrigEnd = Ctx.End;
4044ba319b5SDimitry Andric   while (Ctx.Ptr < OrigEnd) {
4054ba319b5SDimitry Andric     Ctx.End = OrigEnd;
4064ba319b5SDimitry Andric     uint8_t Type = readUint8(Ctx);
4074ba319b5SDimitry Andric     uint32_t Size = readVaruint32(Ctx);
4084ba319b5SDimitry Andric     LLVM_DEBUG(dbgs() << "readSubsection type=" << int(Type) << " size=" << Size
4094ba319b5SDimitry Andric                       << "\n");
4104ba319b5SDimitry Andric     Ctx.End = Ctx.Ptr + Size;
4114ba319b5SDimitry Andric     switch (Type) {
4124ba319b5SDimitry Andric     case wasm::WASM_SYMBOL_TABLE:
4134ba319b5SDimitry Andric       if (Error Err = parseLinkingSectionSymtab(Ctx))
4144ba319b5SDimitry Andric         return Err;
415a580b014SDimitry Andric       break;
4162cab237bSDimitry Andric     case wasm::WASM_SEGMENT_INFO: {
4174ba319b5SDimitry Andric       uint32_t Count = readVaruint32(Ctx);
4182cab237bSDimitry Andric       if (Count > DataSegments.size())
4192cab237bSDimitry Andric         return make_error<GenericBinaryError>("Too many segment names",
4202cab237bSDimitry Andric                                               object_error::parse_failed);
4212cab237bSDimitry Andric       for (uint32_t i = 0; i < Count; i++) {
4224ba319b5SDimitry Andric         DataSegments[i].Data.Name = readString(Ctx);
4234ba319b5SDimitry Andric         DataSegments[i].Data.Alignment = readVaruint32(Ctx);
4244ba319b5SDimitry Andric         DataSegments[i].Data.Flags = readVaruint32(Ctx);
4252cab237bSDimitry Andric       }
426a580b014SDimitry Andric       break;
4272cab237bSDimitry Andric     }
4282cab237bSDimitry Andric     case wasm::WASM_INIT_FUNCS: {
4294ba319b5SDimitry Andric       uint32_t Count = readVaruint32(Ctx);
4302cab237bSDimitry Andric       LinkingData.InitFunctions.reserve(Count);
4312cab237bSDimitry Andric       for (uint32_t i = 0; i < Count; i++) {
4322cab237bSDimitry Andric         wasm::WasmInitFunc Init;
4334ba319b5SDimitry Andric         Init.Priority = readVaruint32(Ctx);
4344ba319b5SDimitry Andric         Init.Symbol = readVaruint32(Ctx);
4354ba319b5SDimitry Andric         if (!isValidFunctionSymbol(Init.Symbol))
4364ba319b5SDimitry Andric           return make_error<GenericBinaryError>("Invalid function symbol: " +
4374ba319b5SDimitry Andric                                                     Twine(Init.Symbol),
4382cab237bSDimitry Andric                                                 object_error::parse_failed);
4392cab237bSDimitry Andric         LinkingData.InitFunctions.emplace_back(Init);
4402cab237bSDimitry Andric       }
4412cab237bSDimitry Andric       break;
4422cab237bSDimitry Andric     }
4434ba319b5SDimitry Andric     case wasm::WASM_COMDAT_INFO:
4444ba319b5SDimitry Andric       if (Error Err = parseLinkingSectionComdat(Ctx))
4454ba319b5SDimitry Andric         return Err;
4464ba319b5SDimitry Andric       break;
447edd7eaddSDimitry Andric     default:
4484ba319b5SDimitry Andric       Ctx.Ptr += Size;
449edd7eaddSDimitry Andric       break;
450edd7eaddSDimitry Andric     }
4514ba319b5SDimitry Andric     if (Ctx.Ptr != Ctx.End)
452edd7eaddSDimitry Andric       return make_error<GenericBinaryError>(
453edd7eaddSDimitry Andric           "Linking sub-section ended prematurely", object_error::parse_failed);
454edd7eaddSDimitry Andric   }
4554ba319b5SDimitry Andric   if (Ctx.Ptr != OrigEnd)
456edd7eaddSDimitry Andric     return make_error<GenericBinaryError>("Linking section ended prematurely",
457edd7eaddSDimitry Andric                                           object_error::parse_failed);
458edd7eaddSDimitry Andric   return Error::success();
459edd7eaddSDimitry Andric }
460edd7eaddSDimitry Andric 
parseLinkingSectionSymtab(ReadContext & Ctx)4614ba319b5SDimitry Andric Error WasmObjectFile::parseLinkingSectionSymtab(ReadContext &Ctx) {
4624ba319b5SDimitry Andric   uint32_t Count = readVaruint32(Ctx);
4634ba319b5SDimitry Andric   LinkingData.SymbolTable.reserve(Count);
4644ba319b5SDimitry Andric   Symbols.reserve(Count);
4654ba319b5SDimitry Andric   StringSet<> SymbolNames;
4664ba319b5SDimitry Andric 
4674ba319b5SDimitry Andric   std::vector<wasm::WasmImport *> ImportedGlobals;
4684ba319b5SDimitry Andric   std::vector<wasm::WasmImport *> ImportedFunctions;
469*b5893f02SDimitry Andric   std::vector<wasm::WasmImport *> ImportedEvents;
4704ba319b5SDimitry Andric   ImportedGlobals.reserve(Imports.size());
4714ba319b5SDimitry Andric   ImportedFunctions.reserve(Imports.size());
472*b5893f02SDimitry Andric   ImportedEvents.reserve(Imports.size());
4734ba319b5SDimitry Andric   for (auto &I : Imports) {
4744ba319b5SDimitry Andric     if (I.Kind == wasm::WASM_EXTERNAL_FUNCTION)
4754ba319b5SDimitry Andric       ImportedFunctions.emplace_back(&I);
4764ba319b5SDimitry Andric     else if (I.Kind == wasm::WASM_EXTERNAL_GLOBAL)
4774ba319b5SDimitry Andric       ImportedGlobals.emplace_back(&I);
478*b5893f02SDimitry Andric     else if (I.Kind == wasm::WASM_EXTERNAL_EVENT)
479*b5893f02SDimitry Andric       ImportedEvents.emplace_back(&I);
4807a7e6055SDimitry Andric   }
4817a7e6055SDimitry Andric 
4824ba319b5SDimitry Andric   while (Count--) {
4834ba319b5SDimitry Andric     wasm::WasmSymbolInfo Info;
484*b5893f02SDimitry Andric     const wasm::WasmSignature *Signature = nullptr;
4854ba319b5SDimitry Andric     const wasm::WasmGlobalType *GlobalType = nullptr;
486*b5893f02SDimitry Andric     const wasm::WasmEventType *EventType = nullptr;
4877a7e6055SDimitry Andric 
4884ba319b5SDimitry Andric     Info.Kind = readUint8(Ctx);
4894ba319b5SDimitry Andric     Info.Flags = readVaruint32(Ctx);
4904ba319b5SDimitry Andric     bool IsDefined = (Info.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0;
4914ba319b5SDimitry Andric 
4924ba319b5SDimitry Andric     switch (Info.Kind) {
4934ba319b5SDimitry Andric     case wasm::WASM_SYMBOL_TYPE_FUNCTION:
4944ba319b5SDimitry Andric       Info.ElementIndex = readVaruint32(Ctx);
4954ba319b5SDimitry Andric       if (!isValidFunctionIndex(Info.ElementIndex) ||
4964ba319b5SDimitry Andric           IsDefined != isDefinedFunctionIndex(Info.ElementIndex))
4974ba319b5SDimitry Andric         return make_error<GenericBinaryError>("invalid function symbol index",
4987a7e6055SDimitry Andric                                               object_error::parse_failed);
4994ba319b5SDimitry Andric       if (IsDefined) {
5004ba319b5SDimitry Andric         Info.Name = readString(Ctx);
5014ba319b5SDimitry Andric         unsigned FuncIndex = Info.ElementIndex - NumImportedFunctions;
502*b5893f02SDimitry Andric         Signature = &Signatures[FunctionTypes[FuncIndex]];
5034ba319b5SDimitry Andric         wasm::WasmFunction &Function = Functions[FuncIndex];
5044ba319b5SDimitry Andric         if (Function.SymbolName.empty())
5054ba319b5SDimitry Andric           Function.SymbolName = Info.Name;
5064ba319b5SDimitry Andric       } else {
5074ba319b5SDimitry Andric         wasm::WasmImport &Import = *ImportedFunctions[Info.ElementIndex];
508*b5893f02SDimitry Andric         if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0)
509*b5893f02SDimitry Andric           Info.Name = readString(Ctx);
510*b5893f02SDimitry Andric         else
5114ba319b5SDimitry Andric           Info.Name = Import.Field;
512*b5893f02SDimitry Andric         Signature = &Signatures[Import.SigIndex];
513*b5893f02SDimitry Andric         Info.ImportName = Import.Field;
514*b5893f02SDimitry Andric         Info.ImportModule = Import.Module;
5154ba319b5SDimitry Andric       }
5164ba319b5SDimitry Andric       break;
5174ba319b5SDimitry Andric 
5184ba319b5SDimitry Andric     case wasm::WASM_SYMBOL_TYPE_GLOBAL:
5194ba319b5SDimitry Andric       Info.ElementIndex = readVaruint32(Ctx);
5204ba319b5SDimitry Andric       if (!isValidGlobalIndex(Info.ElementIndex) ||
5214ba319b5SDimitry Andric           IsDefined != isDefinedGlobalIndex(Info.ElementIndex))
5224ba319b5SDimitry Andric         return make_error<GenericBinaryError>("invalid global symbol index",
5234ba319b5SDimitry Andric                                               object_error::parse_failed);
524*b5893f02SDimitry Andric       if (!IsDefined && (Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) ==
5254ba319b5SDimitry Andric                             wasm::WASM_SYMBOL_BINDING_WEAK)
5264ba319b5SDimitry Andric         return make_error<GenericBinaryError>("undefined weak global symbol",
5274ba319b5SDimitry Andric                                               object_error::parse_failed);
5284ba319b5SDimitry Andric       if (IsDefined) {
5294ba319b5SDimitry Andric         Info.Name = readString(Ctx);
5304ba319b5SDimitry Andric         unsigned GlobalIndex = Info.ElementIndex - NumImportedGlobals;
5314ba319b5SDimitry Andric         wasm::WasmGlobal &Global = Globals[GlobalIndex];
5324ba319b5SDimitry Andric         GlobalType = &Global.Type;
5334ba319b5SDimitry Andric         if (Global.SymbolName.empty())
5344ba319b5SDimitry Andric           Global.SymbolName = Info.Name;
5354ba319b5SDimitry Andric       } else {
5364ba319b5SDimitry Andric         wasm::WasmImport &Import = *ImportedGlobals[Info.ElementIndex];
537*b5893f02SDimitry Andric         if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0)
538*b5893f02SDimitry Andric           Info.Name = readString(Ctx);
539*b5893f02SDimitry Andric         else
5404ba319b5SDimitry Andric           Info.Name = Import.Field;
5414ba319b5SDimitry Andric         GlobalType = &Import.Global;
542*b5893f02SDimitry Andric         Info.ImportName = Import.Field;
543*b5893f02SDimitry Andric         Info.ImportModule = Import.Module;
5444ba319b5SDimitry Andric       }
5454ba319b5SDimitry Andric       break;
5464ba319b5SDimitry Andric 
5474ba319b5SDimitry Andric     case wasm::WASM_SYMBOL_TYPE_DATA:
5484ba319b5SDimitry Andric       Info.Name = readString(Ctx);
5494ba319b5SDimitry Andric       if (IsDefined) {
5504ba319b5SDimitry Andric         uint32_t Index = readVaruint32(Ctx);
5514ba319b5SDimitry Andric         if (Index >= DataSegments.size())
5524ba319b5SDimitry Andric           return make_error<GenericBinaryError>("invalid data symbol index",
5534ba319b5SDimitry Andric                                                 object_error::parse_failed);
5544ba319b5SDimitry Andric         uint32_t Offset = readVaruint32(Ctx);
5554ba319b5SDimitry Andric         uint32_t Size = readVaruint32(Ctx);
5564ba319b5SDimitry Andric         if (Offset + Size > DataSegments[Index].Data.Content.size())
5574ba319b5SDimitry Andric           return make_error<GenericBinaryError>("invalid data symbol offset",
5584ba319b5SDimitry Andric                                                 object_error::parse_failed);
5594ba319b5SDimitry Andric         Info.DataRef = wasm::WasmDataReference{Index, Offset, Size};
5604ba319b5SDimitry Andric       }
5614ba319b5SDimitry Andric       break;
5624ba319b5SDimitry Andric 
5634ba319b5SDimitry Andric     case wasm::WASM_SYMBOL_TYPE_SECTION: {
5644ba319b5SDimitry Andric       if ((Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) !=
5654ba319b5SDimitry Andric           wasm::WASM_SYMBOL_BINDING_LOCAL)
5664ba319b5SDimitry Andric         return make_error<GenericBinaryError>(
5674ba319b5SDimitry Andric             "Section symbols must have local binding",
5684ba319b5SDimitry Andric             object_error::parse_failed);
5694ba319b5SDimitry Andric       Info.ElementIndex = readVaruint32(Ctx);
5704ba319b5SDimitry Andric       // Use somewhat unique section name as symbol name.
5714ba319b5SDimitry Andric       StringRef SectionName = Sections[Info.ElementIndex].Name;
5724ba319b5SDimitry Andric       Info.Name = SectionName;
5734ba319b5SDimitry Andric       break;
5744ba319b5SDimitry Andric     }
5754ba319b5SDimitry Andric 
576*b5893f02SDimitry Andric     case wasm::WASM_SYMBOL_TYPE_EVENT: {
577*b5893f02SDimitry Andric       Info.ElementIndex = readVaruint32(Ctx);
578*b5893f02SDimitry Andric       if (!isValidEventIndex(Info.ElementIndex) ||
579*b5893f02SDimitry Andric           IsDefined != isDefinedEventIndex(Info.ElementIndex))
580*b5893f02SDimitry Andric         return make_error<GenericBinaryError>("invalid event symbol index",
581*b5893f02SDimitry Andric                                               object_error::parse_failed);
582*b5893f02SDimitry Andric       if (!IsDefined && (Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) ==
583*b5893f02SDimitry Andric                             wasm::WASM_SYMBOL_BINDING_WEAK)
584*b5893f02SDimitry Andric         return make_error<GenericBinaryError>("undefined weak global symbol",
585*b5893f02SDimitry Andric                                               object_error::parse_failed);
586*b5893f02SDimitry Andric       if (IsDefined) {
587*b5893f02SDimitry Andric         Info.Name = readString(Ctx);
588*b5893f02SDimitry Andric         unsigned EventIndex = Info.ElementIndex - NumImportedEvents;
589*b5893f02SDimitry Andric         wasm::WasmEvent &Event = Events[EventIndex];
590*b5893f02SDimitry Andric         Signature = &Signatures[Event.Type.SigIndex];
591*b5893f02SDimitry Andric         EventType = &Event.Type;
592*b5893f02SDimitry Andric         if (Event.SymbolName.empty())
593*b5893f02SDimitry Andric           Event.SymbolName = Info.Name;
594*b5893f02SDimitry Andric 
595*b5893f02SDimitry Andric       } else {
596*b5893f02SDimitry Andric         wasm::WasmImport &Import = *ImportedEvents[Info.ElementIndex];
597*b5893f02SDimitry Andric         if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0)
598*b5893f02SDimitry Andric           Info.Name = readString(Ctx);
599*b5893f02SDimitry Andric         else
600*b5893f02SDimitry Andric           Info.Name = Import.Field;
601*b5893f02SDimitry Andric         EventType = &Import.Event;
602*b5893f02SDimitry Andric         Signature = &Signatures[EventType->SigIndex];
603*b5893f02SDimitry Andric         Info.ImportName = Import.Field;
604*b5893f02SDimitry Andric         Info.ImportModule = Import.Module;
605*b5893f02SDimitry Andric       }
606*b5893f02SDimitry Andric       break;
607*b5893f02SDimitry Andric     }
608*b5893f02SDimitry Andric 
6094ba319b5SDimitry Andric     default:
6104ba319b5SDimitry Andric       return make_error<GenericBinaryError>("Invalid symbol type",
6114ba319b5SDimitry Andric                                             object_error::parse_failed);
6124ba319b5SDimitry Andric     }
6134ba319b5SDimitry Andric 
6144ba319b5SDimitry Andric     if ((Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) !=
6154ba319b5SDimitry Andric             wasm::WASM_SYMBOL_BINDING_LOCAL &&
6164ba319b5SDimitry Andric         !SymbolNames.insert(Info.Name).second)
6174ba319b5SDimitry Andric       return make_error<GenericBinaryError>("Duplicate symbol name " +
6184ba319b5SDimitry Andric                                                 Twine(Info.Name),
6194ba319b5SDimitry Andric                                             object_error::parse_failed);
6204ba319b5SDimitry Andric     LinkingData.SymbolTable.emplace_back(Info);
621*b5893f02SDimitry Andric     Symbols.emplace_back(LinkingData.SymbolTable.back(), GlobalType, EventType,
622*b5893f02SDimitry Andric                          Signature);
6234ba319b5SDimitry Andric     LLVM_DEBUG(dbgs() << "Adding symbol: " << Symbols.back() << "\n");
6244ba319b5SDimitry Andric   }
6254ba319b5SDimitry Andric 
6264ba319b5SDimitry Andric   return Error::success();
6274ba319b5SDimitry Andric }
6284ba319b5SDimitry Andric 
parseLinkingSectionComdat(ReadContext & Ctx)6294ba319b5SDimitry Andric Error WasmObjectFile::parseLinkingSectionComdat(ReadContext &Ctx) {
6304ba319b5SDimitry Andric   uint32_t ComdatCount = readVaruint32(Ctx);
6314ba319b5SDimitry Andric   StringSet<> ComdatSet;
6324ba319b5SDimitry Andric   for (unsigned ComdatIndex = 0; ComdatIndex < ComdatCount; ++ComdatIndex) {
6334ba319b5SDimitry Andric     StringRef Name = readString(Ctx);
6344ba319b5SDimitry Andric     if (Name.empty() || !ComdatSet.insert(Name).second)
635*b5893f02SDimitry Andric       return make_error<GenericBinaryError>("Bad/duplicate COMDAT name " +
636*b5893f02SDimitry Andric                                                 Twine(Name),
6374ba319b5SDimitry Andric                                             object_error::parse_failed);
6384ba319b5SDimitry Andric     LinkingData.Comdats.emplace_back(Name);
6394ba319b5SDimitry Andric     uint32_t Flags = readVaruint32(Ctx);
6404ba319b5SDimitry Andric     if (Flags != 0)
6414ba319b5SDimitry Andric       return make_error<GenericBinaryError>("Unsupported COMDAT flags",
6424ba319b5SDimitry Andric                                             object_error::parse_failed);
6434ba319b5SDimitry Andric 
6444ba319b5SDimitry Andric     uint32_t EntryCount = readVaruint32(Ctx);
6454ba319b5SDimitry Andric     while (EntryCount--) {
6464ba319b5SDimitry Andric       unsigned Kind = readVaruint32(Ctx);
6474ba319b5SDimitry Andric       unsigned Index = readVaruint32(Ctx);
6484ba319b5SDimitry Andric       switch (Kind) {
6494ba319b5SDimitry Andric       default:
6504ba319b5SDimitry Andric         return make_error<GenericBinaryError>("Invalid COMDAT entry type",
6514ba319b5SDimitry Andric                                               object_error::parse_failed);
6524ba319b5SDimitry Andric       case wasm::WASM_COMDAT_DATA:
6534ba319b5SDimitry Andric         if (Index >= DataSegments.size())
654*b5893f02SDimitry Andric           return make_error<GenericBinaryError>(
655*b5893f02SDimitry Andric               "COMDAT data index out of range", object_error::parse_failed);
6564ba319b5SDimitry Andric         if (DataSegments[Index].Data.Comdat != UINT32_MAX)
6574ba319b5SDimitry Andric           return make_error<GenericBinaryError>("Data segment in two COMDATs",
6584ba319b5SDimitry Andric                                                 object_error::parse_failed);
6594ba319b5SDimitry Andric         DataSegments[Index].Data.Comdat = ComdatIndex;
6604ba319b5SDimitry Andric         break;
6614ba319b5SDimitry Andric       case wasm::WASM_COMDAT_FUNCTION:
6624ba319b5SDimitry Andric         if (!isDefinedFunctionIndex(Index))
663*b5893f02SDimitry Andric           return make_error<GenericBinaryError>(
664*b5893f02SDimitry Andric               "COMDAT function index out of range", object_error::parse_failed);
6654ba319b5SDimitry Andric         if (getDefinedFunction(Index).Comdat != UINT32_MAX)
6664ba319b5SDimitry Andric           return make_error<GenericBinaryError>("Function in two COMDATs",
6674ba319b5SDimitry Andric                                                 object_error::parse_failed);
6684ba319b5SDimitry Andric         getDefinedFunction(Index).Comdat = ComdatIndex;
6694ba319b5SDimitry Andric         break;
6704ba319b5SDimitry Andric       }
6714ba319b5SDimitry Andric     }
6724ba319b5SDimitry Andric   }
6734ba319b5SDimitry Andric   return Error::success();
6744ba319b5SDimitry Andric }
6754ba319b5SDimitry Andric 
parseRelocSection(StringRef Name,ReadContext & Ctx)6764ba319b5SDimitry Andric Error WasmObjectFile::parseRelocSection(StringRef Name, ReadContext &Ctx) {
6774ba319b5SDimitry Andric   uint32_t SectionIndex = readVaruint32(Ctx);
6784ba319b5SDimitry Andric   if (SectionIndex >= Sections.size())
6794ba319b5SDimitry Andric     return make_error<GenericBinaryError>("Invalid section index",
6804ba319b5SDimitry Andric                                           object_error::parse_failed);
6814ba319b5SDimitry Andric   WasmSection &Section = Sections[SectionIndex];
6824ba319b5SDimitry Andric   uint32_t RelocCount = readVaruint32(Ctx);
6834ba319b5SDimitry Andric   uint32_t EndOffset = Section.Content.size();
684*b5893f02SDimitry Andric   uint32_t PreviousOffset = 0;
6857a7e6055SDimitry Andric   while (RelocCount--) {
6864ba319b5SDimitry Andric     wasm::WasmRelocation Reloc = {};
6874ba319b5SDimitry Andric     Reloc.Type = readVaruint32(Ctx);
6884ba319b5SDimitry Andric     Reloc.Offset = readVaruint32(Ctx);
689*b5893f02SDimitry Andric     if (Reloc.Offset < PreviousOffset)
690*b5893f02SDimitry Andric       return make_error<GenericBinaryError>("Relocations not in offset order",
691*b5893f02SDimitry Andric                                             object_error::parse_failed);
692*b5893f02SDimitry Andric     PreviousOffset = Reloc.Offset;
6934ba319b5SDimitry Andric     Reloc.Index = readVaruint32(Ctx);
6947a7e6055SDimitry Andric     switch (Reloc.Type) {
6957a7e6055SDimitry Andric     case wasm::R_WEBASSEMBLY_FUNCTION_INDEX_LEB:
6967a7e6055SDimitry Andric     case wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB:
6977a7e6055SDimitry Andric     case wasm::R_WEBASSEMBLY_TABLE_INDEX_I32:
6984ba319b5SDimitry Andric       if (!isValidFunctionSymbol(Reloc.Index))
6994ba319b5SDimitry Andric         return make_error<GenericBinaryError>("Bad relocation function index",
7004ba319b5SDimitry Andric                                               object_error::parse_failed);
7014ba319b5SDimitry Andric       break;
70251690af2SDimitry Andric     case wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB:
7034ba319b5SDimitry Andric       if (Reloc.Index >= Signatures.size())
7044ba319b5SDimitry Andric         return make_error<GenericBinaryError>("Bad relocation type index",
7054ba319b5SDimitry Andric                                               object_error::parse_failed);
7064ba319b5SDimitry Andric       break;
707edd7eaddSDimitry Andric     case wasm::R_WEBASSEMBLY_GLOBAL_INDEX_LEB:
7084ba319b5SDimitry Andric       if (!isValidGlobalSymbol(Reloc.Index))
7094ba319b5SDimitry Andric         return make_error<GenericBinaryError>("Bad relocation global index",
7104ba319b5SDimitry Andric                                               object_error::parse_failed);
7117a7e6055SDimitry Andric       break;
712*b5893f02SDimitry Andric     case wasm::R_WEBASSEMBLY_EVENT_INDEX_LEB:
713*b5893f02SDimitry Andric       if (!isValidEventSymbol(Reloc.Index))
714*b5893f02SDimitry Andric         return make_error<GenericBinaryError>("Bad relocation event index",
715*b5893f02SDimitry Andric                                               object_error::parse_failed);
716*b5893f02SDimitry Andric       break;
7172cab237bSDimitry Andric     case wasm::R_WEBASSEMBLY_MEMORY_ADDR_LEB:
7182cab237bSDimitry Andric     case wasm::R_WEBASSEMBLY_MEMORY_ADDR_SLEB:
7192cab237bSDimitry Andric     case wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32:
7204ba319b5SDimitry Andric       if (!isValidDataSymbol(Reloc.Index))
7214ba319b5SDimitry Andric         return make_error<GenericBinaryError>("Bad relocation data index",
7224ba319b5SDimitry Andric                                               object_error::parse_failed);
7234ba319b5SDimitry Andric       Reloc.Addend = readVarint32(Ctx);
7244ba319b5SDimitry Andric       break;
7254ba319b5SDimitry Andric     case wasm::R_WEBASSEMBLY_FUNCTION_OFFSET_I32:
7264ba319b5SDimitry Andric       if (!isValidFunctionSymbol(Reloc.Index))
7274ba319b5SDimitry Andric         return make_error<GenericBinaryError>("Bad relocation function index",
7284ba319b5SDimitry Andric                                               object_error::parse_failed);
7294ba319b5SDimitry Andric       Reloc.Addend = readVarint32(Ctx);
7304ba319b5SDimitry Andric       break;
7314ba319b5SDimitry Andric     case wasm::R_WEBASSEMBLY_SECTION_OFFSET_I32:
7324ba319b5SDimitry Andric       if (!isValidSectionSymbol(Reloc.Index))
7334ba319b5SDimitry Andric         return make_error<GenericBinaryError>("Bad relocation section index",
7344ba319b5SDimitry Andric                                               object_error::parse_failed);
7354ba319b5SDimitry Andric       Reloc.Addend = readVarint32(Ctx);
7367a7e6055SDimitry Andric       break;
7377a7e6055SDimitry Andric     default:
738edd7eaddSDimitry Andric       return make_error<GenericBinaryError>("Bad relocation type: " +
739edd7eaddSDimitry Andric                                                 Twine(Reloc.Type),
7407a7e6055SDimitry Andric                                             object_error::parse_failed);
7417a7e6055SDimitry Andric     }
7424ba319b5SDimitry Andric 
7434ba319b5SDimitry Andric     // Relocations must fit inside the section, and must appear in order.  They
7444ba319b5SDimitry Andric     // also shouldn't overlap a function/element boundary, but we don't bother
7454ba319b5SDimitry Andric     // to check that.
7464ba319b5SDimitry Andric     uint64_t Size = 5;
7474ba319b5SDimitry Andric     if (Reloc.Type == wasm::R_WEBASSEMBLY_TABLE_INDEX_I32 ||
7484ba319b5SDimitry Andric         Reloc.Type == wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32 ||
7494ba319b5SDimitry Andric         Reloc.Type == wasm::R_WEBASSEMBLY_SECTION_OFFSET_I32 ||
7504ba319b5SDimitry Andric         Reloc.Type == wasm::R_WEBASSEMBLY_FUNCTION_OFFSET_I32)
7514ba319b5SDimitry Andric       Size = 4;
7524ba319b5SDimitry Andric     if (Reloc.Offset + Size > EndOffset)
7534ba319b5SDimitry Andric       return make_error<GenericBinaryError>("Bad relocation offset",
7544ba319b5SDimitry Andric                                             object_error::parse_failed);
7554ba319b5SDimitry Andric 
7564ba319b5SDimitry Andric     Section.Relocations.push_back(Reloc);
7577a7e6055SDimitry Andric   }
7584ba319b5SDimitry Andric   if (Ctx.Ptr != Ctx.End)
7597a7e6055SDimitry Andric     return make_error<GenericBinaryError>("Reloc section ended prematurely",
7607a7e6055SDimitry Andric                                           object_error::parse_failed);
7617a7e6055SDimitry Andric   return Error::success();
7627a7e6055SDimitry Andric }
7637a7e6055SDimitry Andric 
parseCustomSection(WasmSection & Sec,ReadContext & Ctx)7644ba319b5SDimitry Andric Error WasmObjectFile::parseCustomSection(WasmSection &Sec, ReadContext &Ctx) {
765*b5893f02SDimitry Andric   if (Sec.Name == "dylink") {
766*b5893f02SDimitry Andric     if (Error Err = parseDylinkSection(Ctx))
767*b5893f02SDimitry Andric       return Err;
768*b5893f02SDimitry Andric   } else if (Sec.Name == "name") {
7694ba319b5SDimitry Andric     if (Error Err = parseNameSection(Ctx))
7707a7e6055SDimitry Andric       return Err;
771edd7eaddSDimitry Andric   } else if (Sec.Name == "linking") {
7724ba319b5SDimitry Andric     if (Error Err = parseLinkingSection(Ctx))
773edd7eaddSDimitry Andric       return Err;
7747a7e6055SDimitry Andric   } else if (Sec.Name.startswith("reloc.")) {
7754ba319b5SDimitry Andric     if (Error Err = parseRelocSection(Sec.Name, Ctx))
7767a7e6055SDimitry Andric       return Err;
7777a7e6055SDimitry Andric   }
7787a7e6055SDimitry Andric   return Error::success();
7797a7e6055SDimitry Andric }
7807a7e6055SDimitry Andric 
parseTypeSection(ReadContext & Ctx)7814ba319b5SDimitry Andric Error WasmObjectFile::parseTypeSection(ReadContext &Ctx) {
7824ba319b5SDimitry Andric   uint32_t Count = readVaruint32(Ctx);
7837a7e6055SDimitry Andric   Signatures.reserve(Count);
7847a7e6055SDimitry Andric   while (Count--) {
7857a7e6055SDimitry Andric     wasm::WasmSignature Sig;
7864ba319b5SDimitry Andric     uint8_t Form = readUint8(Ctx);
7877a7e6055SDimitry Andric     if (Form != wasm::WASM_TYPE_FUNC) {
7887a7e6055SDimitry Andric       return make_error<GenericBinaryError>("Invalid signature type",
7897a7e6055SDimitry Andric                                             object_error::parse_failed);
7907a7e6055SDimitry Andric     }
7914ba319b5SDimitry Andric     uint32_t ParamCount = readVaruint32(Ctx);
792*b5893f02SDimitry Andric     Sig.Params.reserve(ParamCount);
7937a7e6055SDimitry Andric     while (ParamCount--) {
7944ba319b5SDimitry Andric       uint32_t ParamType = readUint8(Ctx);
795*b5893f02SDimitry Andric       Sig.Params.push_back(wasm::ValType(ParamType));
7967a7e6055SDimitry Andric     }
7974ba319b5SDimitry Andric     uint32_t ReturnCount = readVaruint32(Ctx);
7987a7e6055SDimitry Andric     if (ReturnCount) {
7997a7e6055SDimitry Andric       if (ReturnCount != 1) {
8007a7e6055SDimitry Andric         return make_error<GenericBinaryError>(
8017a7e6055SDimitry Andric             "Multiple return types not supported", object_error::parse_failed);
8027a7e6055SDimitry Andric       }
803*b5893f02SDimitry Andric       Sig.Returns.push_back(wasm::ValType(readUint8(Ctx)));
8047a7e6055SDimitry Andric     }
805*b5893f02SDimitry Andric     Signatures.push_back(std::move(Sig));
8067a7e6055SDimitry Andric   }
8074ba319b5SDimitry Andric   if (Ctx.Ptr != Ctx.End)
8087a7e6055SDimitry Andric     return make_error<GenericBinaryError>("Type section ended prematurely",
8097a7e6055SDimitry Andric                                           object_error::parse_failed);
8107a7e6055SDimitry Andric   return Error::success();
8117a7e6055SDimitry Andric }
8127a7e6055SDimitry Andric 
parseImportSection(ReadContext & Ctx)8134ba319b5SDimitry Andric Error WasmObjectFile::parseImportSection(ReadContext &Ctx) {
8144ba319b5SDimitry Andric   uint32_t Count = readVaruint32(Ctx);
8157a7e6055SDimitry Andric   Imports.reserve(Count);
8160f5676f4SDimitry Andric   for (uint32_t i = 0; i < Count; i++) {
8177a7e6055SDimitry Andric     wasm::WasmImport Im;
8184ba319b5SDimitry Andric     Im.Module = readString(Ctx);
8194ba319b5SDimitry Andric     Im.Field = readString(Ctx);
8204ba319b5SDimitry Andric     Im.Kind = readUint8(Ctx);
8217a7e6055SDimitry Andric     switch (Im.Kind) {
8227a7e6055SDimitry Andric     case wasm::WASM_EXTERNAL_FUNCTION:
8232cab237bSDimitry Andric       NumImportedFunctions++;
8244ba319b5SDimitry Andric       Im.SigIndex = readVaruint32(Ctx);
8257a7e6055SDimitry Andric       break;
8267a7e6055SDimitry Andric     case wasm::WASM_EXTERNAL_GLOBAL:
8272cab237bSDimitry Andric       NumImportedGlobals++;
8284ba319b5SDimitry Andric       Im.Global.Type = readUint8(Ctx);
8294ba319b5SDimitry Andric       Im.Global.Mutable = readVaruint1(Ctx);
8307a7e6055SDimitry Andric       break;
8315517e702SDimitry Andric     case wasm::WASM_EXTERNAL_MEMORY:
8324ba319b5SDimitry Andric       Im.Memory = readLimits(Ctx);
8335517e702SDimitry Andric       break;
8345517e702SDimitry Andric     case wasm::WASM_EXTERNAL_TABLE:
8354ba319b5SDimitry Andric       Im.Table = readTable(Ctx);
836*b5893f02SDimitry Andric       if (Im.Table.ElemType != wasm::WASM_TYPE_FUNCREF)
8375517e702SDimitry Andric         return make_error<GenericBinaryError>("Invalid table element type",
8385517e702SDimitry Andric                                               object_error::parse_failed);
8395517e702SDimitry Andric       break;
840*b5893f02SDimitry Andric     case wasm::WASM_EXTERNAL_EVENT:
841*b5893f02SDimitry Andric       NumImportedEvents++;
842*b5893f02SDimitry Andric       Im.Event.Attribute = readVarint32(Ctx);
843*b5893f02SDimitry Andric       Im.Event.SigIndex = readVarint32(Ctx);
844*b5893f02SDimitry Andric       break;
8457a7e6055SDimitry Andric     default:
846*b5893f02SDimitry Andric       return make_error<GenericBinaryError>("Unexpected import kind",
847*b5893f02SDimitry Andric                                             object_error::parse_failed);
8487a7e6055SDimitry Andric     }
8497a7e6055SDimitry Andric     Imports.push_back(Im);
8507a7e6055SDimitry Andric   }
8514ba319b5SDimitry Andric   if (Ctx.Ptr != Ctx.End)
8527a7e6055SDimitry Andric     return make_error<GenericBinaryError>("Import section ended prematurely",
8537a7e6055SDimitry Andric                                           object_error::parse_failed);
8547a7e6055SDimitry Andric   return Error::success();
8557a7e6055SDimitry Andric }
8567a7e6055SDimitry Andric 
parseFunctionSection(ReadContext & Ctx)8574ba319b5SDimitry Andric Error WasmObjectFile::parseFunctionSection(ReadContext &Ctx) {
8584ba319b5SDimitry Andric   uint32_t Count = readVaruint32(Ctx);
8597a7e6055SDimitry Andric   FunctionTypes.reserve(Count);
8604ba319b5SDimitry Andric   uint32_t NumTypes = Signatures.size();
8617a7e6055SDimitry Andric   while (Count--) {
8624ba319b5SDimitry Andric     uint32_t Type = readVaruint32(Ctx);
8634ba319b5SDimitry Andric     if (Type >= NumTypes)
8644ba319b5SDimitry Andric       return make_error<GenericBinaryError>("Invalid function type",
8654ba319b5SDimitry Andric                                             object_error::parse_failed);
8664ba319b5SDimitry Andric     FunctionTypes.push_back(Type);
8677a7e6055SDimitry Andric   }
8684ba319b5SDimitry Andric   if (Ctx.Ptr != Ctx.End)
8697a7e6055SDimitry Andric     return make_error<GenericBinaryError>("Function section ended prematurely",
8707a7e6055SDimitry Andric                                           object_error::parse_failed);
8717a7e6055SDimitry Andric   return Error::success();
8727a7e6055SDimitry Andric }
8737a7e6055SDimitry Andric 
parseTableSection(ReadContext & Ctx)8744ba319b5SDimitry Andric Error WasmObjectFile::parseTableSection(ReadContext &Ctx) {
8754ba319b5SDimitry Andric   uint32_t Count = readVaruint32(Ctx);
8767a7e6055SDimitry Andric   Tables.reserve(Count);
8777a7e6055SDimitry Andric   while (Count--) {
8784ba319b5SDimitry Andric     Tables.push_back(readTable(Ctx));
879*b5893f02SDimitry Andric     if (Tables.back().ElemType != wasm::WASM_TYPE_FUNCREF) {
8807a7e6055SDimitry Andric       return make_error<GenericBinaryError>("Invalid table element type",
8817a7e6055SDimitry Andric                                             object_error::parse_failed);
8827a7e6055SDimitry Andric     }
8837a7e6055SDimitry Andric   }
8844ba319b5SDimitry Andric   if (Ctx.Ptr != Ctx.End)
8857a7e6055SDimitry Andric     return make_error<GenericBinaryError>("Table section ended prematurely",
8867a7e6055SDimitry Andric                                           object_error::parse_failed);
8877a7e6055SDimitry Andric   return Error::success();
8887a7e6055SDimitry Andric }
8897a7e6055SDimitry Andric 
parseMemorySection(ReadContext & Ctx)8904ba319b5SDimitry Andric Error WasmObjectFile::parseMemorySection(ReadContext &Ctx) {
8914ba319b5SDimitry Andric   uint32_t Count = readVaruint32(Ctx);
8927a7e6055SDimitry Andric   Memories.reserve(Count);
8937a7e6055SDimitry Andric   while (Count--) {
8944ba319b5SDimitry Andric     Memories.push_back(readLimits(Ctx));
8957a7e6055SDimitry Andric   }
8964ba319b5SDimitry Andric   if (Ctx.Ptr != Ctx.End)
8977a7e6055SDimitry Andric     return make_error<GenericBinaryError>("Memory section ended prematurely",
8987a7e6055SDimitry Andric                                           object_error::parse_failed);
8997a7e6055SDimitry Andric   return Error::success();
9007a7e6055SDimitry Andric }
9017a7e6055SDimitry Andric 
parseGlobalSection(ReadContext & Ctx)9024ba319b5SDimitry Andric Error WasmObjectFile::parseGlobalSection(ReadContext &Ctx) {
9034ba319b5SDimitry Andric   GlobalSection = Sections.size();
9044ba319b5SDimitry Andric   uint32_t Count = readVaruint32(Ctx);
9057a7e6055SDimitry Andric   Globals.reserve(Count);
9067a7e6055SDimitry Andric   while (Count--) {
9077a7e6055SDimitry Andric     wasm::WasmGlobal Global;
9084ba319b5SDimitry Andric     Global.Index = NumImportedGlobals + Globals.size();
9094ba319b5SDimitry Andric     Global.Type.Type = readUint8(Ctx);
9104ba319b5SDimitry Andric     Global.Type.Mutable = readVaruint1(Ctx);
9114ba319b5SDimitry Andric     if (Error Err = readInitExpr(Global.InitExpr, Ctx))
9127a7e6055SDimitry Andric       return Err;
9137a7e6055SDimitry Andric     Globals.push_back(Global);
9147a7e6055SDimitry Andric   }
9154ba319b5SDimitry Andric   if (Ctx.Ptr != Ctx.End)
9167a7e6055SDimitry Andric     return make_error<GenericBinaryError>("Global section ended prematurely",
9177a7e6055SDimitry Andric                                           object_error::parse_failed);
9187a7e6055SDimitry Andric   return Error::success();
9197a7e6055SDimitry Andric }
9207a7e6055SDimitry Andric 
parseEventSection(ReadContext & Ctx)921*b5893f02SDimitry Andric Error WasmObjectFile::parseEventSection(ReadContext &Ctx) {
922*b5893f02SDimitry Andric   EventSection = Sections.size();
923*b5893f02SDimitry Andric   uint32_t Count = readVarint32(Ctx);
924*b5893f02SDimitry Andric   Events.reserve(Count);
925*b5893f02SDimitry Andric   while (Count--) {
926*b5893f02SDimitry Andric     wasm::WasmEvent Event;
927*b5893f02SDimitry Andric     Event.Index = NumImportedEvents + Events.size();
928*b5893f02SDimitry Andric     Event.Type.Attribute = readVaruint32(Ctx);
929*b5893f02SDimitry Andric     Event.Type.SigIndex = readVarint32(Ctx);
930*b5893f02SDimitry Andric     Events.push_back(Event);
931*b5893f02SDimitry Andric   }
932*b5893f02SDimitry Andric 
933*b5893f02SDimitry Andric   if (Ctx.Ptr != Ctx.End)
934*b5893f02SDimitry Andric     return make_error<GenericBinaryError>("Event section ended prematurely",
935*b5893f02SDimitry Andric                                           object_error::parse_failed);
936*b5893f02SDimitry Andric   return Error::success();
937*b5893f02SDimitry Andric }
938*b5893f02SDimitry Andric 
parseExportSection(ReadContext & Ctx)9394ba319b5SDimitry Andric Error WasmObjectFile::parseExportSection(ReadContext &Ctx) {
9404ba319b5SDimitry Andric   uint32_t Count = readVaruint32(Ctx);
9417a7e6055SDimitry Andric   Exports.reserve(Count);
9420f5676f4SDimitry Andric   for (uint32_t i = 0; i < Count; i++) {
9437a7e6055SDimitry Andric     wasm::WasmExport Ex;
9444ba319b5SDimitry Andric     Ex.Name = readString(Ctx);
9454ba319b5SDimitry Andric     Ex.Kind = readUint8(Ctx);
9464ba319b5SDimitry Andric     Ex.Index = readVaruint32(Ctx);
9477a7e6055SDimitry Andric     switch (Ex.Kind) {
9487a7e6055SDimitry Andric     case wasm::WASM_EXTERNAL_FUNCTION:
9494ba319b5SDimitry Andric       if (!isValidFunctionIndex(Ex.Index))
9502cab237bSDimitry Andric         return make_error<GenericBinaryError>("Invalid function export",
9512cab237bSDimitry Andric                                               object_error::parse_failed);
9527a7e6055SDimitry Andric       break;
9534ba319b5SDimitry Andric     case wasm::WASM_EXTERNAL_GLOBAL:
9544ba319b5SDimitry Andric       if (!isValidGlobalIndex(Ex.Index))
9552cab237bSDimitry Andric         return make_error<GenericBinaryError>("Invalid global export",
9562cab237bSDimitry Andric                                               object_error::parse_failed);
9577a7e6055SDimitry Andric       break;
958*b5893f02SDimitry Andric     case wasm::WASM_EXTERNAL_EVENT:
959*b5893f02SDimitry Andric       if (!isValidEventIndex(Ex.Index))
960*b5893f02SDimitry Andric         return make_error<GenericBinaryError>("Invalid event export",
961*b5893f02SDimitry Andric                                               object_error::parse_failed);
962*b5893f02SDimitry Andric       break;
9635517e702SDimitry Andric     case wasm::WASM_EXTERNAL_MEMORY:
9645517e702SDimitry Andric     case wasm::WASM_EXTERNAL_TABLE:
9655517e702SDimitry Andric       break;
9667a7e6055SDimitry Andric     default:
967*b5893f02SDimitry Andric       return make_error<GenericBinaryError>("Unexpected export kind",
968*b5893f02SDimitry Andric                                             object_error::parse_failed);
9697a7e6055SDimitry Andric     }
970edd7eaddSDimitry Andric     Exports.push_back(Ex);
9717a7e6055SDimitry Andric   }
9724ba319b5SDimitry Andric   if (Ctx.Ptr != Ctx.End)
9737a7e6055SDimitry Andric     return make_error<GenericBinaryError>("Export section ended prematurely",
9747a7e6055SDimitry Andric                                           object_error::parse_failed);
9757a7e6055SDimitry Andric   return Error::success();
9767a7e6055SDimitry Andric }
9777a7e6055SDimitry Andric 
isValidFunctionIndex(uint32_t Index) const9782cab237bSDimitry Andric bool WasmObjectFile::isValidFunctionIndex(uint32_t Index) const {
9794ba319b5SDimitry Andric   return Index < NumImportedFunctions + FunctionTypes.size();
9802cab237bSDimitry Andric }
9812cab237bSDimitry Andric 
isDefinedFunctionIndex(uint32_t Index) const9824ba319b5SDimitry Andric bool WasmObjectFile::isDefinedFunctionIndex(uint32_t Index) const {
9834ba319b5SDimitry Andric   return Index >= NumImportedFunctions && isValidFunctionIndex(Index);
9844ba319b5SDimitry Andric }
9854ba319b5SDimitry Andric 
isValidGlobalIndex(uint32_t Index) const9864ba319b5SDimitry Andric bool WasmObjectFile::isValidGlobalIndex(uint32_t Index) const {
9874ba319b5SDimitry Andric   return Index < NumImportedGlobals + Globals.size();
9884ba319b5SDimitry Andric }
9894ba319b5SDimitry Andric 
isDefinedGlobalIndex(uint32_t Index) const9904ba319b5SDimitry Andric bool WasmObjectFile::isDefinedGlobalIndex(uint32_t Index) const {
9914ba319b5SDimitry Andric   return Index >= NumImportedGlobals && isValidGlobalIndex(Index);
9924ba319b5SDimitry Andric }
9934ba319b5SDimitry Andric 
isValidEventIndex(uint32_t Index) const994*b5893f02SDimitry Andric bool WasmObjectFile::isValidEventIndex(uint32_t Index) const {
995*b5893f02SDimitry Andric   return Index < NumImportedEvents + Events.size();
996*b5893f02SDimitry Andric }
997*b5893f02SDimitry Andric 
isDefinedEventIndex(uint32_t Index) const998*b5893f02SDimitry Andric bool WasmObjectFile::isDefinedEventIndex(uint32_t Index) const {
999*b5893f02SDimitry Andric   return Index >= NumImportedEvents && isValidEventIndex(Index);
1000*b5893f02SDimitry Andric }
1001*b5893f02SDimitry Andric 
isValidFunctionSymbol(uint32_t Index) const10024ba319b5SDimitry Andric bool WasmObjectFile::isValidFunctionSymbol(uint32_t Index) const {
10034ba319b5SDimitry Andric   return Index < Symbols.size() && Symbols[Index].isTypeFunction();
10044ba319b5SDimitry Andric }
10054ba319b5SDimitry Andric 
isValidGlobalSymbol(uint32_t Index) const10064ba319b5SDimitry Andric bool WasmObjectFile::isValidGlobalSymbol(uint32_t Index) const {
10074ba319b5SDimitry Andric   return Index < Symbols.size() && Symbols[Index].isTypeGlobal();
10084ba319b5SDimitry Andric }
10094ba319b5SDimitry Andric 
isValidEventSymbol(uint32_t Index) const1010*b5893f02SDimitry Andric bool WasmObjectFile::isValidEventSymbol(uint32_t Index) const {
1011*b5893f02SDimitry Andric   return Index < Symbols.size() && Symbols[Index].isTypeEvent();
1012*b5893f02SDimitry Andric }
1013*b5893f02SDimitry Andric 
isValidDataSymbol(uint32_t Index) const10144ba319b5SDimitry Andric bool WasmObjectFile::isValidDataSymbol(uint32_t Index) const {
10154ba319b5SDimitry Andric   return Index < Symbols.size() && Symbols[Index].isTypeData();
10164ba319b5SDimitry Andric }
10174ba319b5SDimitry Andric 
isValidSectionSymbol(uint32_t Index) const10184ba319b5SDimitry Andric bool WasmObjectFile::isValidSectionSymbol(uint32_t Index) const {
10194ba319b5SDimitry Andric   return Index < Symbols.size() && Symbols[Index].isTypeSection();
10204ba319b5SDimitry Andric }
10214ba319b5SDimitry Andric 
getDefinedFunction(uint32_t Index)10224ba319b5SDimitry Andric wasm::WasmFunction &WasmObjectFile::getDefinedFunction(uint32_t Index) {
10234ba319b5SDimitry Andric   assert(isDefinedFunctionIndex(Index));
10244ba319b5SDimitry Andric   return Functions[Index - NumImportedFunctions];
10254ba319b5SDimitry Andric }
10264ba319b5SDimitry Andric 
getDefinedGlobal(uint32_t Index)10274ba319b5SDimitry Andric wasm::WasmGlobal &WasmObjectFile::getDefinedGlobal(uint32_t Index) {
10284ba319b5SDimitry Andric   assert(isDefinedGlobalIndex(Index));
10294ba319b5SDimitry Andric   return Globals[Index - NumImportedGlobals];
10304ba319b5SDimitry Andric }
10314ba319b5SDimitry Andric 
getDefinedEvent(uint32_t Index)1032*b5893f02SDimitry Andric wasm::WasmEvent &WasmObjectFile::getDefinedEvent(uint32_t Index) {
1033*b5893f02SDimitry Andric   assert(isDefinedEventIndex(Index));
1034*b5893f02SDimitry Andric   return Events[Index - NumImportedEvents];
1035*b5893f02SDimitry Andric }
1036*b5893f02SDimitry Andric 
parseStartSection(ReadContext & Ctx)10374ba319b5SDimitry Andric Error WasmObjectFile::parseStartSection(ReadContext &Ctx) {
10384ba319b5SDimitry Andric   StartFunction = readVaruint32(Ctx);
10392cab237bSDimitry Andric   if (!isValidFunctionIndex(StartFunction))
10407a7e6055SDimitry Andric     return make_error<GenericBinaryError>("Invalid start function",
10417a7e6055SDimitry Andric                                           object_error::parse_failed);
10427a7e6055SDimitry Andric   return Error::success();
10437a7e6055SDimitry Andric }
10447a7e6055SDimitry Andric 
parseCodeSection(ReadContext & Ctx)10454ba319b5SDimitry Andric Error WasmObjectFile::parseCodeSection(ReadContext &Ctx) {
10464ba319b5SDimitry Andric   CodeSection = Sections.size();
10474ba319b5SDimitry Andric   uint32_t FunctionCount = readVaruint32(Ctx);
10487a7e6055SDimitry Andric   if (FunctionCount != FunctionTypes.size()) {
10497a7e6055SDimitry Andric     return make_error<GenericBinaryError>("Invalid function count",
10507a7e6055SDimitry Andric                                           object_error::parse_failed);
10517a7e6055SDimitry Andric   }
10527a7e6055SDimitry Andric 
10537a7e6055SDimitry Andric   while (FunctionCount--) {
10547a7e6055SDimitry Andric     wasm::WasmFunction Function;
10554ba319b5SDimitry Andric     const uint8_t *FunctionStart = Ctx.Ptr;
10564ba319b5SDimitry Andric     uint32_t Size = readVaruint32(Ctx);
10574ba319b5SDimitry Andric     const uint8_t *FunctionEnd = Ctx.Ptr + Size;
10582cab237bSDimitry Andric 
10594ba319b5SDimitry Andric     Function.CodeOffset = Ctx.Ptr - FunctionStart;
10604ba319b5SDimitry Andric     Function.Index = NumImportedFunctions + Functions.size();
10614ba319b5SDimitry Andric     Function.CodeSectionOffset = FunctionStart - Ctx.Start;
10622cab237bSDimitry Andric     Function.Size = FunctionEnd - FunctionStart;
10637a7e6055SDimitry Andric 
10644ba319b5SDimitry Andric     uint32_t NumLocalDecls = readVaruint32(Ctx);
10657a7e6055SDimitry Andric     Function.Locals.reserve(NumLocalDecls);
10667a7e6055SDimitry Andric     while (NumLocalDecls--) {
10677a7e6055SDimitry Andric       wasm::WasmLocalDecl Decl;
10684ba319b5SDimitry Andric       Decl.Count = readVaruint32(Ctx);
10694ba319b5SDimitry Andric       Decl.Type = readUint8(Ctx);
10707a7e6055SDimitry Andric       Function.Locals.push_back(Decl);
10717a7e6055SDimitry Andric     }
10727a7e6055SDimitry Andric 
10734ba319b5SDimitry Andric     uint32_t BodySize = FunctionEnd - Ctx.Ptr;
10744ba319b5SDimitry Andric     Function.Body = ArrayRef<uint8_t>(Ctx.Ptr, BodySize);
10754ba319b5SDimitry Andric     // This will be set later when reading in the linking metadata section.
10764ba319b5SDimitry Andric     Function.Comdat = UINT32_MAX;
10774ba319b5SDimitry Andric     Ctx.Ptr += BodySize;
10784ba319b5SDimitry Andric     assert(Ctx.Ptr == FunctionEnd);
10797a7e6055SDimitry Andric     Functions.push_back(Function);
10807a7e6055SDimitry Andric   }
10814ba319b5SDimitry Andric   if (Ctx.Ptr != Ctx.End)
10827a7e6055SDimitry Andric     return make_error<GenericBinaryError>("Code section ended prematurely",
10837a7e6055SDimitry Andric                                           object_error::parse_failed);
10847a7e6055SDimitry Andric   return Error::success();
10857a7e6055SDimitry Andric }
10867a7e6055SDimitry Andric 
parseElemSection(ReadContext & Ctx)10874ba319b5SDimitry Andric Error WasmObjectFile::parseElemSection(ReadContext &Ctx) {
10884ba319b5SDimitry Andric   uint32_t Count = readVaruint32(Ctx);
10897a7e6055SDimitry Andric   ElemSegments.reserve(Count);
10907a7e6055SDimitry Andric   while (Count--) {
10917a7e6055SDimitry Andric     wasm::WasmElemSegment Segment;
10924ba319b5SDimitry Andric     Segment.TableIndex = readVaruint32(Ctx);
10937a7e6055SDimitry Andric     if (Segment.TableIndex != 0) {
10947a7e6055SDimitry Andric       return make_error<GenericBinaryError>("Invalid TableIndex",
10957a7e6055SDimitry Andric                                             object_error::parse_failed);
10967a7e6055SDimitry Andric     }
10974ba319b5SDimitry Andric     if (Error Err = readInitExpr(Segment.Offset, Ctx))
10987a7e6055SDimitry Andric       return Err;
10994ba319b5SDimitry Andric     uint32_t NumElems = readVaruint32(Ctx);
11007a7e6055SDimitry Andric     while (NumElems--) {
11014ba319b5SDimitry Andric       Segment.Functions.push_back(readVaruint32(Ctx));
11027a7e6055SDimitry Andric     }
11037a7e6055SDimitry Andric     ElemSegments.push_back(Segment);
11047a7e6055SDimitry Andric   }
11054ba319b5SDimitry Andric   if (Ctx.Ptr != Ctx.End)
11067a7e6055SDimitry Andric     return make_error<GenericBinaryError>("Elem section ended prematurely",
11077a7e6055SDimitry Andric                                           object_error::parse_failed);
11087a7e6055SDimitry Andric   return Error::success();
11097a7e6055SDimitry Andric }
11107a7e6055SDimitry Andric 
parseDataSection(ReadContext & Ctx)11114ba319b5SDimitry Andric Error WasmObjectFile::parseDataSection(ReadContext &Ctx) {
11124ba319b5SDimitry Andric   DataSection = Sections.size();
11134ba319b5SDimitry Andric   uint32_t Count = readVaruint32(Ctx);
11147a7e6055SDimitry Andric   DataSegments.reserve(Count);
11157a7e6055SDimitry Andric   while (Count--) {
1116c4394386SDimitry Andric     WasmSegment Segment;
11174ba319b5SDimitry Andric     Segment.Data.MemoryIndex = readVaruint32(Ctx);
11184ba319b5SDimitry Andric     if (Error Err = readInitExpr(Segment.Data.Offset, Ctx))
11197a7e6055SDimitry Andric       return Err;
11204ba319b5SDimitry Andric     uint32_t Size = readVaruint32(Ctx);
11214ba319b5SDimitry Andric     if (Size > (size_t)(Ctx.End - Ctx.Ptr))
11224ba319b5SDimitry Andric       return make_error<GenericBinaryError>("Invalid segment size",
11234ba319b5SDimitry Andric                                             object_error::parse_failed);
11244ba319b5SDimitry Andric     Segment.Data.Content = ArrayRef<uint8_t>(Ctx.Ptr, Size);
11254ba319b5SDimitry Andric     // The rest of these Data fields are set later, when reading in the linking
11264ba319b5SDimitry Andric     // metadata section.
11272cab237bSDimitry Andric     Segment.Data.Alignment = 0;
11282cab237bSDimitry Andric     Segment.Data.Flags = 0;
11294ba319b5SDimitry Andric     Segment.Data.Comdat = UINT32_MAX;
11304ba319b5SDimitry Andric     Segment.SectionOffset = Ctx.Ptr - Ctx.Start;
11314ba319b5SDimitry Andric     Ctx.Ptr += Size;
11327a7e6055SDimitry Andric     DataSegments.push_back(Segment);
11337a7e6055SDimitry Andric   }
11344ba319b5SDimitry Andric   if (Ctx.Ptr != Ctx.End)
11357a7e6055SDimitry Andric     return make_error<GenericBinaryError>("Data section ended prematurely",
11367a7e6055SDimitry Andric                                           object_error::parse_failed);
1137d88c1a5aSDimitry Andric   return Error::success();
1138d88c1a5aSDimitry Andric }
1139d88c1a5aSDimitry Andric 
getPtr(size_t Offset) const1140d88c1a5aSDimitry Andric const uint8_t *WasmObjectFile::getPtr(size_t Offset) const {
11414ba319b5SDimitry Andric   return reinterpret_cast<const uint8_t *>(getData().data() + Offset);
1142d88c1a5aSDimitry Andric }
1143d88c1a5aSDimitry Andric 
getHeader() const1144d88c1a5aSDimitry Andric const wasm::WasmObjectHeader &WasmObjectFile::getHeader() const {
1145d88c1a5aSDimitry Andric   return Header;
1146d88c1a5aSDimitry Andric }
1147d88c1a5aSDimitry Andric 
moveSymbolNext(DataRefImpl & Symb) const11487a7e6055SDimitry Andric void WasmObjectFile::moveSymbolNext(DataRefImpl &Symb) const { Symb.d.a++; }
1149d88c1a5aSDimitry Andric 
getSymbolFlags(DataRefImpl Symb) const1150d88c1a5aSDimitry Andric uint32_t WasmObjectFile::getSymbolFlags(DataRefImpl Symb) const {
11510f5676f4SDimitry Andric   uint32_t Result = SymbolRef::SF_None;
11527a7e6055SDimitry Andric   const WasmSymbol &Sym = getWasmSymbol(Symb);
11530f5676f4SDimitry Andric 
11544ba319b5SDimitry Andric   LLVM_DEBUG(dbgs() << "getSymbolFlags: ptr=" << &Sym << " " << Sym << "\n");
11554ba319b5SDimitry Andric   if (Sym.isBindingWeak())
1156edd7eaddSDimitry Andric     Result |= SymbolRef::SF_Weak;
11574ba319b5SDimitry Andric   if (!Sym.isBindingLocal())
11582cab237bSDimitry Andric     Result |= SymbolRef::SF_Global;
11592cab237bSDimitry Andric   if (Sym.isHidden())
11602cab237bSDimitry Andric     Result |= SymbolRef::SF_Hidden;
11614ba319b5SDimitry Andric   if (!Sym.isDefined())
11620f5676f4SDimitry Andric     Result |= SymbolRef::SF_Undefined;
11634ba319b5SDimitry Andric   if (Sym.isTypeFunction())
11644ba319b5SDimitry Andric     Result |= SymbolRef::SF_Executable;
11650f5676f4SDimitry Andric   return Result;
1166d88c1a5aSDimitry Andric }
1167d88c1a5aSDimitry Andric 
symbol_begin() const1168d88c1a5aSDimitry Andric basic_symbol_iterator WasmObjectFile::symbol_begin() const {
11697a7e6055SDimitry Andric   DataRefImpl Ref;
11707a7e6055SDimitry Andric   Ref.d.a = 0;
11717a7e6055SDimitry Andric   return BasicSymbolRef(Ref, this);
1172d88c1a5aSDimitry Andric }
1173d88c1a5aSDimitry Andric 
symbol_end() const1174d88c1a5aSDimitry Andric basic_symbol_iterator WasmObjectFile::symbol_end() const {
11757a7e6055SDimitry Andric   DataRefImpl Ref;
11767a7e6055SDimitry Andric   Ref.d.a = Symbols.size();
11777a7e6055SDimitry Andric   return BasicSymbolRef(Ref, this);
11787a7e6055SDimitry Andric }
11797a7e6055SDimitry Andric 
getWasmSymbol(const DataRefImpl & Symb) const11805517e702SDimitry Andric const WasmSymbol &WasmObjectFile::getWasmSymbol(const DataRefImpl &Symb) const {
11817a7e6055SDimitry Andric   return Symbols[Symb.d.a];
1182d88c1a5aSDimitry Andric }
1183d88c1a5aSDimitry Andric 
getWasmSymbol(const SymbolRef & Symb) const11845517e702SDimitry Andric const WasmSymbol &WasmObjectFile::getWasmSymbol(const SymbolRef &Symb) const {
11855517e702SDimitry Andric   return getWasmSymbol(Symb.getRawDataRefImpl());
11865517e702SDimitry Andric }
11875517e702SDimitry Andric 
getSymbolName(DataRefImpl Symb) const1188d88c1a5aSDimitry Andric Expected<StringRef> WasmObjectFile::getSymbolName(DataRefImpl Symb) const {
11894ba319b5SDimitry Andric   return getWasmSymbol(Symb).Info.Name;
1190d88c1a5aSDimitry Andric }
1191d88c1a5aSDimitry Andric 
getSymbolAddress(DataRefImpl Symb) const1192d88c1a5aSDimitry Andric Expected<uint64_t> WasmObjectFile::getSymbolAddress(DataRefImpl Symb) const {
11930f5676f4SDimitry Andric   return getSymbolValue(Symb);
1194d88c1a5aSDimitry Andric }
1195d88c1a5aSDimitry Andric 
getWasmSymbolValue(const WasmSymbol & Sym) const11962cab237bSDimitry Andric uint64_t WasmObjectFile::getWasmSymbolValue(const WasmSymbol &Sym) const {
11974ba319b5SDimitry Andric   switch (Sym.Info.Kind) {
11984ba319b5SDimitry Andric   case wasm::WASM_SYMBOL_TYPE_FUNCTION:
11994ba319b5SDimitry Andric   case wasm::WASM_SYMBOL_TYPE_GLOBAL:
1200*b5893f02SDimitry Andric   case wasm::WASM_SYMBOL_TYPE_EVENT:
12014ba319b5SDimitry Andric     return Sym.Info.ElementIndex;
12024ba319b5SDimitry Andric   case wasm::WASM_SYMBOL_TYPE_DATA: {
12034ba319b5SDimitry Andric     // The value of a data symbol is the segment offset, plus the symbol
12044ba319b5SDimitry Andric     // offset within the segment.
12054ba319b5SDimitry Andric     uint32_t SegmentIndex = Sym.Info.DataRef.Segment;
12064ba319b5SDimitry Andric     const wasm::WasmDataSegment &Segment = DataSegments[SegmentIndex].Data;
12074ba319b5SDimitry Andric     assert(Segment.Offset.Opcode == wasm::WASM_OPCODE_I32_CONST);
12084ba319b5SDimitry Andric     return Segment.Offset.Value.Int32 + Sym.Info.DataRef.Offset;
12092cab237bSDimitry Andric   }
12104ba319b5SDimitry Andric   case wasm::WASM_SYMBOL_TYPE_SECTION:
12114ba319b5SDimitry Andric     return 0;
1212d88c1a5aSDimitry Andric   }
1213edd7eaddSDimitry Andric   llvm_unreachable("invalid symbol type");
1214edd7eaddSDimitry Andric }
1215d88c1a5aSDimitry Andric 
getSymbolValueImpl(DataRefImpl Symb) const12162cab237bSDimitry Andric uint64_t WasmObjectFile::getSymbolValueImpl(DataRefImpl Symb) const {
12172cab237bSDimitry Andric   return getWasmSymbolValue(getWasmSymbol(Symb));
12182cab237bSDimitry Andric }
12192cab237bSDimitry Andric 
getSymbolAlignment(DataRefImpl Symb) const1220d88c1a5aSDimitry Andric uint32_t WasmObjectFile::getSymbolAlignment(DataRefImpl Symb) const {
1221d88c1a5aSDimitry Andric   llvm_unreachable("not yet implemented");
1222d88c1a5aSDimitry Andric   return 0;
1223d88c1a5aSDimitry Andric }
1224d88c1a5aSDimitry Andric 
getCommonSymbolSizeImpl(DataRefImpl Symb) const1225d88c1a5aSDimitry Andric uint64_t WasmObjectFile::getCommonSymbolSizeImpl(DataRefImpl Symb) const {
1226d88c1a5aSDimitry Andric   llvm_unreachable("not yet implemented");
1227d88c1a5aSDimitry Andric   return 0;
1228d88c1a5aSDimitry Andric }
1229d88c1a5aSDimitry Andric 
1230d88c1a5aSDimitry Andric Expected<SymbolRef::Type>
getSymbolType(DataRefImpl Symb) const1231d88c1a5aSDimitry Andric WasmObjectFile::getSymbolType(DataRefImpl Symb) const {
12320f5676f4SDimitry Andric   const WasmSymbol &Sym = getWasmSymbol(Symb);
12330f5676f4SDimitry Andric 
12344ba319b5SDimitry Andric   switch (Sym.Info.Kind) {
12354ba319b5SDimitry Andric   case wasm::WASM_SYMBOL_TYPE_FUNCTION:
12360f5676f4SDimitry Andric     return SymbolRef::ST_Function;
12374ba319b5SDimitry Andric   case wasm::WASM_SYMBOL_TYPE_GLOBAL:
12384ba319b5SDimitry Andric     return SymbolRef::ST_Other;
12394ba319b5SDimitry Andric   case wasm::WASM_SYMBOL_TYPE_DATA:
12400f5676f4SDimitry Andric     return SymbolRef::ST_Data;
12414ba319b5SDimitry Andric   case wasm::WASM_SYMBOL_TYPE_SECTION:
12424ba319b5SDimitry Andric     return SymbolRef::ST_Debug;
1243*b5893f02SDimitry Andric   case wasm::WASM_SYMBOL_TYPE_EVENT:
1244*b5893f02SDimitry Andric     return SymbolRef::ST_Other;
12450f5676f4SDimitry Andric   }
12460f5676f4SDimitry Andric 
12470f5676f4SDimitry Andric   llvm_unreachable("Unknown WasmSymbol::SymbolType");
12480f5676f4SDimitry Andric   return SymbolRef::ST_Other;
1249d88c1a5aSDimitry Andric }
1250d88c1a5aSDimitry Andric 
1251d88c1a5aSDimitry Andric Expected<section_iterator>
getSymbolSection(DataRefImpl Symb) const1252d88c1a5aSDimitry Andric WasmObjectFile::getSymbolSection(DataRefImpl Symb) const {
12534ba319b5SDimitry Andric   const WasmSymbol &Sym = getWasmSymbol(Symb);
12544ba319b5SDimitry Andric   if (Sym.isUndefined())
12554ba319b5SDimitry Andric     return section_end();
12564ba319b5SDimitry Andric 
12570f5676f4SDimitry Andric   DataRefImpl Ref;
12584ba319b5SDimitry Andric   switch (Sym.Info.Kind) {
12594ba319b5SDimitry Andric   case wasm::WASM_SYMBOL_TYPE_FUNCTION:
12604ba319b5SDimitry Andric     Ref.d.a = CodeSection;
12614ba319b5SDimitry Andric     break;
12624ba319b5SDimitry Andric   case wasm::WASM_SYMBOL_TYPE_GLOBAL:
12634ba319b5SDimitry Andric     Ref.d.a = GlobalSection;
12644ba319b5SDimitry Andric     break;
12654ba319b5SDimitry Andric   case wasm::WASM_SYMBOL_TYPE_DATA:
12664ba319b5SDimitry Andric     Ref.d.a = DataSection;
12674ba319b5SDimitry Andric     break;
1268*b5893f02SDimitry Andric   case wasm::WASM_SYMBOL_TYPE_SECTION:
12694ba319b5SDimitry Andric     Ref.d.a = Sym.Info.ElementIndex;
12704ba319b5SDimitry Andric     break;
1271*b5893f02SDimitry Andric   case wasm::WASM_SYMBOL_TYPE_EVENT:
1272*b5893f02SDimitry Andric     Ref.d.a = EventSection;
1273*b5893f02SDimitry Andric     break;
12744ba319b5SDimitry Andric   default:
12754ba319b5SDimitry Andric     llvm_unreachable("Unknown WasmSymbol::SymbolType");
12764ba319b5SDimitry Andric   }
12770f5676f4SDimitry Andric   return section_iterator(SectionRef(Ref, this));
1278d88c1a5aSDimitry Andric }
1279d88c1a5aSDimitry Andric 
moveSectionNext(DataRefImpl & Sec) const1280d88c1a5aSDimitry Andric void WasmObjectFile::moveSectionNext(DataRefImpl &Sec) const { Sec.d.a++; }
1281d88c1a5aSDimitry Andric 
getSectionName(DataRefImpl Sec,StringRef & Res) const1282d88c1a5aSDimitry Andric std::error_code WasmObjectFile::getSectionName(DataRefImpl Sec,
1283d88c1a5aSDimitry Andric                                                StringRef &Res) const {
12847a7e6055SDimitry Andric   const WasmSection &S = Sections[Sec.d.a];
1285d88c1a5aSDimitry Andric #define ECase(X)                                                               \
1286d88c1a5aSDimitry Andric   case wasm::WASM_SEC_##X:                                                     \
1287d88c1a5aSDimitry Andric     Res = #X;                                                                  \
1288d88c1a5aSDimitry Andric     break
1289d88c1a5aSDimitry Andric   switch (S.Type) {
1290d88c1a5aSDimitry Andric     ECase(TYPE);
1291d88c1a5aSDimitry Andric     ECase(IMPORT);
1292d88c1a5aSDimitry Andric     ECase(FUNCTION);
1293d88c1a5aSDimitry Andric     ECase(TABLE);
1294d88c1a5aSDimitry Andric     ECase(MEMORY);
1295d88c1a5aSDimitry Andric     ECase(GLOBAL);
1296*b5893f02SDimitry Andric     ECase(EVENT);
1297d88c1a5aSDimitry Andric     ECase(EXPORT);
1298d88c1a5aSDimitry Andric     ECase(START);
1299d88c1a5aSDimitry Andric     ECase(ELEM);
1300d88c1a5aSDimitry Andric     ECase(CODE);
1301d88c1a5aSDimitry Andric     ECase(DATA);
13027a7e6055SDimitry Andric   case wasm::WASM_SEC_CUSTOM:
1303d88c1a5aSDimitry Andric     Res = S.Name;
1304d88c1a5aSDimitry Andric     break;
1305d88c1a5aSDimitry Andric   default:
1306d88c1a5aSDimitry Andric     return object_error::invalid_section_index;
1307d88c1a5aSDimitry Andric   }
1308d88c1a5aSDimitry Andric #undef ECase
1309d88c1a5aSDimitry Andric   return std::error_code();
1310d88c1a5aSDimitry Andric }
1311d88c1a5aSDimitry Andric 
getSectionAddress(DataRefImpl Sec) const1312d88c1a5aSDimitry Andric uint64_t WasmObjectFile::getSectionAddress(DataRefImpl Sec) const { return 0; }
1313d88c1a5aSDimitry Andric 
getSectionIndex(DataRefImpl Sec) const1314302affcbSDimitry Andric uint64_t WasmObjectFile::getSectionIndex(DataRefImpl Sec) const {
1315302affcbSDimitry Andric   return Sec.d.a;
1316302affcbSDimitry Andric }
1317302affcbSDimitry Andric 
getSectionSize(DataRefImpl Sec) const1318d88c1a5aSDimitry Andric uint64_t WasmObjectFile::getSectionSize(DataRefImpl Sec) const {
13197a7e6055SDimitry Andric   const WasmSection &S = Sections[Sec.d.a];
1320d88c1a5aSDimitry Andric   return S.Content.size();
1321d88c1a5aSDimitry Andric }
1322d88c1a5aSDimitry Andric 
getSectionContents(DataRefImpl Sec,StringRef & Res) const1323d88c1a5aSDimitry Andric std::error_code WasmObjectFile::getSectionContents(DataRefImpl Sec,
1324d88c1a5aSDimitry Andric                                                    StringRef &Res) const {
13257a7e6055SDimitry Andric   const WasmSection &S = Sections[Sec.d.a];
1326d88c1a5aSDimitry Andric   // This will never fail since wasm sections can never be empty (user-sections
1327d88c1a5aSDimitry Andric   // must have a name and non-user sections each have a defined structure).
1328d88c1a5aSDimitry Andric   Res = StringRef(reinterpret_cast<const char *>(S.Content.data()),
1329d88c1a5aSDimitry Andric                   S.Content.size());
1330d88c1a5aSDimitry Andric   return std::error_code();
1331d88c1a5aSDimitry Andric }
1332d88c1a5aSDimitry Andric 
getSectionAlignment(DataRefImpl Sec) const1333d88c1a5aSDimitry Andric uint64_t WasmObjectFile::getSectionAlignment(DataRefImpl Sec) const {
1334d88c1a5aSDimitry Andric   return 1;
1335d88c1a5aSDimitry Andric }
1336d88c1a5aSDimitry Andric 
isSectionCompressed(DataRefImpl Sec) const1337d88c1a5aSDimitry Andric bool WasmObjectFile::isSectionCompressed(DataRefImpl Sec) const {
1338d88c1a5aSDimitry Andric   return false;
1339d88c1a5aSDimitry Andric }
1340d88c1a5aSDimitry Andric 
isSectionText(DataRefImpl Sec) const1341d88c1a5aSDimitry Andric bool WasmObjectFile::isSectionText(DataRefImpl Sec) const {
13427a7e6055SDimitry Andric   return getWasmSection(Sec).Type == wasm::WASM_SEC_CODE;
1343d88c1a5aSDimitry Andric }
1344d88c1a5aSDimitry Andric 
isSectionData(DataRefImpl Sec) const1345d88c1a5aSDimitry Andric bool WasmObjectFile::isSectionData(DataRefImpl Sec) const {
13467a7e6055SDimitry Andric   return getWasmSection(Sec).Type == wasm::WASM_SEC_DATA;
1347d88c1a5aSDimitry Andric }
1348d88c1a5aSDimitry Andric 
isSectionBSS(DataRefImpl Sec) const1349d88c1a5aSDimitry Andric bool WasmObjectFile::isSectionBSS(DataRefImpl Sec) const { return false; }
1350d88c1a5aSDimitry Andric 
isSectionVirtual(DataRefImpl Sec) const1351d88c1a5aSDimitry Andric bool WasmObjectFile::isSectionVirtual(DataRefImpl Sec) const { return false; }
1352d88c1a5aSDimitry Andric 
isSectionBitcode(DataRefImpl Sec) const1353d88c1a5aSDimitry Andric bool WasmObjectFile::isSectionBitcode(DataRefImpl Sec) const { return false; }
1354d88c1a5aSDimitry Andric 
section_rel_begin(DataRefImpl Ref) const13557a7e6055SDimitry Andric relocation_iterator WasmObjectFile::section_rel_begin(DataRefImpl Ref) const {
13567a7e6055SDimitry Andric   DataRefImpl RelocRef;
13577a7e6055SDimitry Andric   RelocRef.d.a = Ref.d.a;
13587a7e6055SDimitry Andric   RelocRef.d.b = 0;
13597a7e6055SDimitry Andric   return relocation_iterator(RelocationRef(RelocRef, this));
1360d88c1a5aSDimitry Andric }
1361d88c1a5aSDimitry Andric 
section_rel_end(DataRefImpl Ref) const13627a7e6055SDimitry Andric relocation_iterator WasmObjectFile::section_rel_end(DataRefImpl Ref) const {
13637a7e6055SDimitry Andric   const WasmSection &Sec = getWasmSection(Ref);
13647a7e6055SDimitry Andric   DataRefImpl RelocRef;
13657a7e6055SDimitry Andric   RelocRef.d.a = Ref.d.a;
13667a7e6055SDimitry Andric   RelocRef.d.b = Sec.Relocations.size();
13677a7e6055SDimitry Andric   return relocation_iterator(RelocationRef(RelocRef, this));
1368d88c1a5aSDimitry Andric }
1369d88c1a5aSDimitry Andric 
moveRelocationNext(DataRefImpl & Rel) const1370*b5893f02SDimitry Andric void WasmObjectFile::moveRelocationNext(DataRefImpl &Rel) const { Rel.d.b++; }
1371d88c1a5aSDimitry Andric 
getRelocationOffset(DataRefImpl Ref) const13727a7e6055SDimitry Andric uint64_t WasmObjectFile::getRelocationOffset(DataRefImpl Ref) const {
13737a7e6055SDimitry Andric   const wasm::WasmRelocation &Rel = getWasmRelocation(Ref);
13747a7e6055SDimitry Andric   return Rel.Offset;
1375d88c1a5aSDimitry Andric }
1376d88c1a5aSDimitry Andric 
getRelocationSymbol(DataRefImpl Ref) const13774ba319b5SDimitry Andric symbol_iterator WasmObjectFile::getRelocationSymbol(DataRefImpl Ref) const {
13784ba319b5SDimitry Andric   const wasm::WasmRelocation &Rel = getWasmRelocation(Ref);
13794ba319b5SDimitry Andric   if (Rel.Type == wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB)
13804ba319b5SDimitry Andric     return symbol_end();
13814ba319b5SDimitry Andric   DataRefImpl Sym;
13824ba319b5SDimitry Andric   Sym.d.a = Rel.Index;
13834ba319b5SDimitry Andric   Sym.d.b = 0;
13844ba319b5SDimitry Andric   return symbol_iterator(SymbolRef(Sym, this));
1385d88c1a5aSDimitry Andric }
1386d88c1a5aSDimitry Andric 
getRelocationType(DataRefImpl Ref) const13877a7e6055SDimitry Andric uint64_t WasmObjectFile::getRelocationType(DataRefImpl Ref) const {
13887a7e6055SDimitry Andric   const wasm::WasmRelocation &Rel = getWasmRelocation(Ref);
13897a7e6055SDimitry Andric   return Rel.Type;
1390d88c1a5aSDimitry Andric }
1391d88c1a5aSDimitry Andric 
getRelocationTypeName(DataRefImpl Ref,SmallVectorImpl<char> & Result) const1392d88c1a5aSDimitry Andric void WasmObjectFile::getRelocationTypeName(
13937a7e6055SDimitry Andric     DataRefImpl Ref, SmallVectorImpl<char> &Result) const {
13947a7e6055SDimitry Andric   const wasm::WasmRelocation &Rel = getWasmRelocation(Ref);
13957a7e6055SDimitry Andric   StringRef Res = "Unknown";
13967a7e6055SDimitry Andric 
13977a7e6055SDimitry Andric #define WASM_RELOC(name, value)                                                \
13987a7e6055SDimitry Andric   case wasm::name:                                                             \
13997a7e6055SDimitry Andric     Res = #name;                                                               \
14007a7e6055SDimitry Andric     break;
14017a7e6055SDimitry Andric 
14027a7e6055SDimitry Andric   switch (Rel.Type) {
1403da09e106SDimitry Andric #include "llvm/BinaryFormat/WasmRelocs.def"
14047a7e6055SDimitry Andric   }
14057a7e6055SDimitry Andric 
14067a7e6055SDimitry Andric #undef WASM_RELOC
14077a7e6055SDimitry Andric 
14087a7e6055SDimitry Andric   Result.append(Res.begin(), Res.end());
1409d88c1a5aSDimitry Andric }
1410d88c1a5aSDimitry Andric 
section_begin() const1411d88c1a5aSDimitry Andric section_iterator WasmObjectFile::section_begin() const {
1412d88c1a5aSDimitry Andric   DataRefImpl Ref;
1413d88c1a5aSDimitry Andric   Ref.d.a = 0;
1414d88c1a5aSDimitry Andric   return section_iterator(SectionRef(Ref, this));
1415d88c1a5aSDimitry Andric }
1416d88c1a5aSDimitry Andric 
section_end() const1417d88c1a5aSDimitry Andric section_iterator WasmObjectFile::section_end() const {
1418d88c1a5aSDimitry Andric   DataRefImpl Ref;
1419d88c1a5aSDimitry Andric   Ref.d.a = Sections.size();
1420d88c1a5aSDimitry Andric   return section_iterator(SectionRef(Ref, this));
1421d88c1a5aSDimitry Andric }
1422d88c1a5aSDimitry Andric 
getBytesInAddress() const1423d88c1a5aSDimitry Andric uint8_t WasmObjectFile::getBytesInAddress() const { return 4; }
1424d88c1a5aSDimitry Andric 
getFileFormatName() const1425d88c1a5aSDimitry Andric StringRef WasmObjectFile::getFileFormatName() const { return "WASM"; }
1426d88c1a5aSDimitry Andric 
getArch() const14272cab237bSDimitry Andric Triple::ArchType WasmObjectFile::getArch() const { return Triple::wasm32; }
1428d88c1a5aSDimitry Andric 
getFeatures() const1429d88c1a5aSDimitry Andric SubtargetFeatures WasmObjectFile::getFeatures() const {
1430d88c1a5aSDimitry Andric   return SubtargetFeatures();
1431d88c1a5aSDimitry Andric }
1432d88c1a5aSDimitry Andric 
isRelocatableObject() const1433*b5893f02SDimitry Andric bool WasmObjectFile::isRelocatableObject() const { return HasLinkingSection; }
1434*b5893f02SDimitry Andric 
isSharedObject() const1435*b5893f02SDimitry Andric bool WasmObjectFile::isSharedObject() const { return HasDylinkSection; }
1436d88c1a5aSDimitry Andric 
getWasmSection(DataRefImpl Ref) const14377a7e6055SDimitry Andric const WasmSection &WasmObjectFile::getWasmSection(DataRefImpl Ref) const {
14387a7e6055SDimitry Andric   assert(Ref.d.a < Sections.size());
14397a7e6055SDimitry Andric   return Sections[Ref.d.a];
1440d88c1a5aSDimitry Andric }
1441d88c1a5aSDimitry Andric 
14427a7e6055SDimitry Andric const WasmSection &
getWasmSection(const SectionRef & Section) const14437a7e6055SDimitry Andric WasmObjectFile::getWasmSection(const SectionRef &Section) const {
14447a7e6055SDimitry Andric   return getWasmSection(Section.getRawDataRefImpl());
14457a7e6055SDimitry Andric }
14467a7e6055SDimitry Andric 
14477a7e6055SDimitry Andric const wasm::WasmRelocation &
getWasmRelocation(const RelocationRef & Ref) const14487a7e6055SDimitry Andric WasmObjectFile::getWasmRelocation(const RelocationRef &Ref) const {
14497a7e6055SDimitry Andric   return getWasmRelocation(Ref.getRawDataRefImpl());
14507a7e6055SDimitry Andric }
14517a7e6055SDimitry Andric 
14527a7e6055SDimitry Andric const wasm::WasmRelocation &
getWasmRelocation(DataRefImpl Ref) const14537a7e6055SDimitry Andric WasmObjectFile::getWasmRelocation(DataRefImpl Ref) const {
14547a7e6055SDimitry Andric   assert(Ref.d.a < Sections.size());
14557a7e6055SDimitry Andric   const WasmSection &Sec = Sections[Ref.d.a];
14567a7e6055SDimitry Andric   assert(Ref.d.b < Sec.Relocations.size());
14577a7e6055SDimitry Andric   return Sec.Relocations[Ref.d.b];
14587a7e6055SDimitry Andric }
1459*b5893f02SDimitry Andric 
getSectionOrder(unsigned ID,StringRef CustomSectionName)1460*b5893f02SDimitry Andric int WasmSectionOrderChecker::getSectionOrder(unsigned ID,
1461*b5893f02SDimitry Andric                                              StringRef CustomSectionName) {
1462*b5893f02SDimitry Andric   switch (ID) {
1463*b5893f02SDimitry Andric   case wasm::WASM_SEC_CUSTOM:
1464*b5893f02SDimitry Andric     return StringSwitch<unsigned>(CustomSectionName)
1465*b5893f02SDimitry Andric         .Case("dylink", WASM_SEC_ORDER_DYLINK)
1466*b5893f02SDimitry Andric         .Case("linking", WASM_SEC_ORDER_LINKING)
1467*b5893f02SDimitry Andric         .StartsWith("reloc.", WASM_SEC_ORDER_RELOC)
1468*b5893f02SDimitry Andric         .Case("name", WASM_SEC_ORDER_NAME)
1469*b5893f02SDimitry Andric         .Case("producers", WASM_SEC_ORDER_PRODUCERS)
1470*b5893f02SDimitry Andric         .Default(-1);
1471*b5893f02SDimitry Andric   case wasm::WASM_SEC_TYPE:
1472*b5893f02SDimitry Andric     return WASM_SEC_ORDER_TYPE;
1473*b5893f02SDimitry Andric   case wasm::WASM_SEC_IMPORT:
1474*b5893f02SDimitry Andric     return WASM_SEC_ORDER_IMPORT;
1475*b5893f02SDimitry Andric   case wasm::WASM_SEC_FUNCTION:
1476*b5893f02SDimitry Andric     return WASM_SEC_ORDER_FUNCTION;
1477*b5893f02SDimitry Andric   case wasm::WASM_SEC_TABLE:
1478*b5893f02SDimitry Andric     return WASM_SEC_ORDER_TABLE;
1479*b5893f02SDimitry Andric   case wasm::WASM_SEC_MEMORY:
1480*b5893f02SDimitry Andric     return WASM_SEC_ORDER_MEMORY;
1481*b5893f02SDimitry Andric   case wasm::WASM_SEC_GLOBAL:
1482*b5893f02SDimitry Andric     return WASM_SEC_ORDER_GLOBAL;
1483*b5893f02SDimitry Andric   case wasm::WASM_SEC_EXPORT:
1484*b5893f02SDimitry Andric     return WASM_SEC_ORDER_EXPORT;
1485*b5893f02SDimitry Andric   case wasm::WASM_SEC_START:
1486*b5893f02SDimitry Andric     return WASM_SEC_ORDER_START;
1487*b5893f02SDimitry Andric   case wasm::WASM_SEC_ELEM:
1488*b5893f02SDimitry Andric     return WASM_SEC_ORDER_ELEM;
1489*b5893f02SDimitry Andric   case wasm::WASM_SEC_CODE:
1490*b5893f02SDimitry Andric     return WASM_SEC_ORDER_CODE;
1491*b5893f02SDimitry Andric   case wasm::WASM_SEC_DATA:
1492*b5893f02SDimitry Andric     return WASM_SEC_ORDER_DATA;
1493*b5893f02SDimitry Andric   case wasm::WASM_SEC_DATACOUNT:
1494*b5893f02SDimitry Andric     return WASM_SEC_ORDER_DATACOUNT;
1495*b5893f02SDimitry Andric   case wasm::WASM_SEC_EVENT:
1496*b5893f02SDimitry Andric     return WASM_SEC_ORDER_EVENT;
1497*b5893f02SDimitry Andric   default:
1498*b5893f02SDimitry Andric     llvm_unreachable("invalid section");
1499*b5893f02SDimitry Andric   }
1500*b5893f02SDimitry Andric }
1501*b5893f02SDimitry Andric 
isValidSectionOrder(unsigned ID,StringRef CustomSectionName)1502*b5893f02SDimitry Andric bool WasmSectionOrderChecker::isValidSectionOrder(unsigned ID,
1503*b5893f02SDimitry Andric                                                   StringRef CustomSectionName) {
1504*b5893f02SDimitry Andric   int Order = getSectionOrder(ID, CustomSectionName);
1505*b5893f02SDimitry Andric   if (Order == -1) // Skip unknown sections
1506*b5893f02SDimitry Andric     return true;
1507*b5893f02SDimitry Andric   // There can be multiple "reloc." sections. Otherwise there shouldn't be any
1508*b5893f02SDimitry Andric   // duplicate section orders.
1509*b5893f02SDimitry Andric   bool IsValid = (LastOrder == Order && Order == WASM_SEC_ORDER_RELOC) ||
1510*b5893f02SDimitry Andric                  LastOrder < Order;
1511*b5893f02SDimitry Andric   LastOrder = Order;
1512*b5893f02SDimitry Andric   return IsValid;
1513*b5893f02SDimitry Andric }
1514