144d95122SEugene Zelenko //===- WasmObjectFile.cpp - Wasm object file implementation ---------------===// 22c6f75ddSDerek Schuff // 32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information. 52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 62c6f75ddSDerek Schuff // 72c6f75ddSDerek Schuff //===----------------------------------------------------------------------===// 82c6f75ddSDerek Schuff 944d95122SEugene Zelenko #include "llvm/ADT/ArrayRef.h" 104710ed7aSSam Clegg #include "llvm/ADT/DenseSet.h" 11cbda16ebSThomas Lively #include "llvm/ADT/SmallSet.h" 1244d95122SEugene Zelenko #include "llvm/ADT/StringRef.h" 13ea7caceeSSam Clegg #include "llvm/ADT/StringSet.h" 140ea52537SSimon Pilgrim #include "llvm/ADT/StringSwitch.h" 1544d95122SEugene Zelenko #include "llvm/ADT/Triple.h" 16264b5d9eSZachary Turner #include "llvm/BinaryFormat/Wasm.h" 179f5094dfSEugene Zelenko #include "llvm/MC/SubtargetFeature.h" 1844d95122SEugene Zelenko #include "llvm/Object/Binary.h" 1944d95122SEugene Zelenko #include "llvm/Object/Error.h" 2044d95122SEugene Zelenko #include "llvm/Object/ObjectFile.h" 2144d95122SEugene Zelenko #include "llvm/Object/SymbolicFile.h" 222c6f75ddSDerek Schuff #include "llvm/Object/Wasm.h" 232c6f75ddSDerek Schuff #include "llvm/Support/Endian.h" 2444d95122SEugene Zelenko #include "llvm/Support/Error.h" 2544d95122SEugene Zelenko #include "llvm/Support/ErrorHandling.h" 262c6f75ddSDerek Schuff #include "llvm/Support/LEB128.h" 27feef720bSHeejin Ahn #include "llvm/Support/ScopedPrinter.h" 2844d95122SEugene Zelenko #include <algorithm> 299f5094dfSEugene Zelenko #include <cassert> 3044d95122SEugene Zelenko #include <cstdint> 319f5094dfSEugene Zelenko #include <cstring> 322c6f75ddSDerek Schuff 33b7787fd0SSam Clegg #define DEBUG_TYPE "wasm-object" 34b7787fd0SSam Clegg 3544d95122SEugene Zelenko using namespace llvm; 3644d95122SEugene Zelenko using namespace object; 372c6f75ddSDerek Schuff 38659932b0SJF Bastien void WasmSymbol::print(raw_ostream &Out) const { 39659932b0SJF Bastien Out << "Name=" << Info.Name 4073332d73SSam Clegg << ", Kind=" << toString(wasm::WasmSymbolType(Info.Kind)) << ", Flags=0x" 4173332d73SSam Clegg << Twine::utohexstr(Info.Flags); 42659932b0SJF Bastien if (!isTypeData()) { 43659932b0SJF Bastien Out << ", ElemIndex=" << Info.ElementIndex; 44659932b0SJF Bastien } else if (isDefined()) { 45659932b0SJF Bastien Out << ", Segment=" << Info.DataRef.Segment; 46659932b0SJF Bastien Out << ", Offset=" << Info.DataRef.Offset; 47659932b0SJF Bastien Out << ", Size=" << Info.DataRef.Size; 48659932b0SJF Bastien } 49659932b0SJF Bastien } 50659932b0SJF Bastien 51ddc84bf7SJF Bastien #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 52ddc84bf7SJF Bastien LLVM_DUMP_METHOD void WasmSymbol::dump() const { print(dbgs()); } 53ddc84bf7SJF Bastien #endif 54ddc84bf7SJF Bastien 552c6f75ddSDerek Schuff Expected<std::unique_ptr<WasmObjectFile>> 562c6f75ddSDerek Schuff ObjectFile::createWasmObjectFile(MemoryBufferRef Buffer) { 572c6f75ddSDerek Schuff Error Err = Error::success(); 580eaee545SJonas Devlieghere auto ObjectFile = std::make_unique<WasmObjectFile>(Buffer, Err); 592c6f75ddSDerek Schuff if (Err) 60c55cf4afSBill Wendling return std::move(Err); 612c6f75ddSDerek Schuff 62c55cf4afSBill Wendling return std::move(ObjectFile); 632c6f75ddSDerek Schuff } 642c6f75ddSDerek Schuff 65d3d84fddSDerek Schuff #define VARINT7_MAX ((1 << 7) - 1) 66d3d84fddSDerek Schuff #define VARINT7_MIN (-(1 << 7)) 67d3d84fddSDerek Schuff #define VARUINT7_MAX (1 << 7) 68d3d84fddSDerek Schuff #define VARUINT1_MAX (1) 69d3d84fddSDerek Schuff 70b7c62394SSam Clegg static uint8_t readUint8(WasmObjectFile::ReadContext &Ctx) { 71b7c62394SSam Clegg if (Ctx.Ptr == Ctx.End) 72b7c62394SSam Clegg report_fatal_error("EOF while reading uint8"); 73b7c62394SSam Clegg return *Ctx.Ptr++; 74b7c62394SSam Clegg } 75d3d84fddSDerek Schuff 76b7c62394SSam Clegg static uint32_t readUint32(WasmObjectFile::ReadContext &Ctx) { 77b7c62394SSam Clegg if (Ctx.Ptr + 4 > Ctx.End) 78b7c62394SSam Clegg report_fatal_error("EOF while reading uint32"); 79b7c62394SSam Clegg uint32_t Result = support::endian::read32le(Ctx.Ptr); 80b7c62394SSam Clegg Ctx.Ptr += 4; 812c6f75ddSDerek Schuff return Result; 822c6f75ddSDerek Schuff } 832c6f75ddSDerek Schuff 84b7c62394SSam Clegg static int32_t readFloat32(WasmObjectFile::ReadContext &Ctx) { 85e3d6b978SJonas Devlieghere if (Ctx.Ptr + 4 > Ctx.End) 86e3d6b978SJonas Devlieghere report_fatal_error("EOF while reading float64"); 87d3d84fddSDerek Schuff int32_t Result = 0; 88b7c62394SSam Clegg memcpy(&Result, Ctx.Ptr, sizeof(Result)); 89b7c62394SSam Clegg Ctx.Ptr += sizeof(Result); 90d3d84fddSDerek Schuff return Result; 91d3d84fddSDerek Schuff } 92d3d84fddSDerek Schuff 93b7c62394SSam Clegg static int64_t readFloat64(WasmObjectFile::ReadContext &Ctx) { 94e3d6b978SJonas Devlieghere if (Ctx.Ptr + 8 > Ctx.End) 95e3d6b978SJonas Devlieghere report_fatal_error("EOF while reading float64"); 96d3d84fddSDerek Schuff int64_t Result = 0; 97b7c62394SSam Clegg memcpy(&Result, Ctx.Ptr, sizeof(Result)); 98b7c62394SSam Clegg Ctx.Ptr += sizeof(Result); 99d3d84fddSDerek Schuff return Result; 100d3d84fddSDerek Schuff } 101d3d84fddSDerek Schuff 102b7c62394SSam Clegg static uint64_t readULEB128(WasmObjectFile::ReadContext &Ctx) { 1032c6f75ddSDerek Schuff unsigned Count; 104b7c62394SSam Clegg const char *Error = nullptr; 105b7c62394SSam Clegg uint64_t Result = decodeULEB128(Ctx.Ptr, &Count, Ctx.End, &Error); 106b7c62394SSam Clegg if (Error) 107b7c62394SSam Clegg report_fatal_error(Error); 108b7c62394SSam Clegg Ctx.Ptr += Count; 1092c6f75ddSDerek Schuff return Result; 1102c6f75ddSDerek Schuff } 1112c6f75ddSDerek Schuff 112b7c62394SSam Clegg static StringRef readString(WasmObjectFile::ReadContext &Ctx) { 113b7c62394SSam Clegg uint32_t StringLen = readULEB128(Ctx); 114b7c62394SSam Clegg if (Ctx.Ptr + StringLen > Ctx.End) 115b7c62394SSam Clegg report_fatal_error("EOF while reading string"); 116b7c62394SSam Clegg StringRef Return = 117b7c62394SSam Clegg StringRef(reinterpret_cast<const char *>(Ctx.Ptr), StringLen); 118b7c62394SSam Clegg Ctx.Ptr += StringLen; 1192c6f75ddSDerek Schuff return Return; 1202c6f75ddSDerek Schuff } 1212c6f75ddSDerek Schuff 122b7c62394SSam Clegg static int64_t readLEB128(WasmObjectFile::ReadContext &Ctx) { 123d3d84fddSDerek Schuff unsigned Count; 124b7c62394SSam Clegg const char *Error = nullptr; 125b7c62394SSam Clegg uint64_t Result = decodeSLEB128(Ctx.Ptr, &Count, Ctx.End, &Error); 126b7c62394SSam Clegg if (Error) 127b7c62394SSam Clegg report_fatal_error(Error); 128b7c62394SSam Clegg Ctx.Ptr += Count; 129d3d84fddSDerek Schuff return Result; 130d3d84fddSDerek Schuff } 131d3d84fddSDerek Schuff 132b7c62394SSam Clegg static uint8_t readVaruint1(WasmObjectFile::ReadContext &Ctx) { 13318c56a07SHeejin Ahn int64_t Result = readLEB128(Ctx); 13418c56a07SHeejin Ahn if (Result > VARUINT1_MAX || Result < 0) 1354bbc6b55SSam Clegg report_fatal_error("LEB is outside Varuint1 range"); 13618c56a07SHeejin Ahn return Result; 137d3d84fddSDerek Schuff } 138d3d84fddSDerek Schuff 139b7c62394SSam Clegg static int32_t readVarint32(WasmObjectFile::ReadContext &Ctx) { 14018c56a07SHeejin Ahn int64_t Result = readLEB128(Ctx); 14118c56a07SHeejin Ahn if (Result > INT32_MAX || Result < INT32_MIN) 1424bbc6b55SSam Clegg report_fatal_error("LEB is outside Varint32 range"); 14318c56a07SHeejin Ahn return Result; 144d3d84fddSDerek Schuff } 145d3d84fddSDerek Schuff 146b7c62394SSam Clegg static uint32_t readVaruint32(WasmObjectFile::ReadContext &Ctx) { 14718c56a07SHeejin Ahn uint64_t Result = readULEB128(Ctx); 14818c56a07SHeejin Ahn if (Result > UINT32_MAX) 1494bbc6b55SSam Clegg report_fatal_error("LEB is outside Varuint32 range"); 15018c56a07SHeejin Ahn return Result; 151d3d84fddSDerek Schuff } 152d3d84fddSDerek Schuff 153b7c62394SSam Clegg static int64_t readVarint64(WasmObjectFile::ReadContext &Ctx) { 154b7c62394SSam Clegg return readLEB128(Ctx); 155d3d84fddSDerek Schuff } 156d3d84fddSDerek Schuff 1573b29376eSWouter van Oortmerssen static uint64_t readVaruint64(WasmObjectFile::ReadContext &Ctx) { 1583b29376eSWouter van Oortmerssen return readULEB128(Ctx); 1593b29376eSWouter van Oortmerssen } 1603b29376eSWouter van Oortmerssen 161b7c62394SSam Clegg static uint8_t readOpcode(WasmObjectFile::ReadContext &Ctx) { 162b7c62394SSam Clegg return readUint8(Ctx); 163d3d84fddSDerek Schuff } 164d3d84fddSDerek Schuff 165b7c62394SSam Clegg static Error readInitExpr(wasm::WasmInitExpr &Expr, 166b7c62394SSam Clegg WasmObjectFile::ReadContext &Ctx) { 1679504ab32SSam Clegg auto Start = Ctx.Ptr; 168d3d84fddSDerek Schuff 1699504ab32SSam Clegg Expr.Extended = false; 1709504ab32SSam Clegg Expr.Inst.Opcode = readOpcode(Ctx); 1719504ab32SSam Clegg switch (Expr.Inst.Opcode) { 172d3d84fddSDerek Schuff case wasm::WASM_OPCODE_I32_CONST: 1739504ab32SSam Clegg Expr.Inst.Value.Int32 = readVarint32(Ctx); 174d3d84fddSDerek Schuff break; 175d3d84fddSDerek Schuff case wasm::WASM_OPCODE_I64_CONST: 1769504ab32SSam Clegg Expr.Inst.Value.Int64 = readVarint64(Ctx); 177d3d84fddSDerek Schuff break; 178d3d84fddSDerek Schuff case wasm::WASM_OPCODE_F32_CONST: 1799504ab32SSam Clegg Expr.Inst.Value.Float32 = readFloat32(Ctx); 180d3d84fddSDerek Schuff break; 181d3d84fddSDerek Schuff case wasm::WASM_OPCODE_F64_CONST: 1829504ab32SSam Clegg Expr.Inst.Value.Float64 = readFloat64(Ctx); 183d3d84fddSDerek Schuff break; 1846a87ddacSThomas Lively case wasm::WASM_OPCODE_GLOBAL_GET: 1859504ab32SSam Clegg Expr.Inst.Value.Global = readULEB128(Ctx); 186d3d84fddSDerek Schuff break; 18779aad89dSSam Clegg case wasm::WASM_OPCODE_REF_NULL: { 18879aad89dSSam Clegg wasm::ValType Ty = static_cast<wasm::ValType>(readULEB128(Ctx)); 18979aad89dSSam Clegg if (Ty != wasm::ValType::EXTERNREF) { 19084c6f325SSam Clegg return make_error<GenericBinaryError>("invalid type for ref.null", 19179aad89dSSam Clegg object_error::parse_failed); 19279aad89dSSam Clegg } 19379aad89dSSam Clegg break; 19479aad89dSSam Clegg } 195d3d84fddSDerek Schuff default: 1969504ab32SSam Clegg Expr.Extended = true; 197d3d84fddSDerek Schuff } 198d3d84fddSDerek Schuff 1999504ab32SSam Clegg if (!Expr.Extended) { 200b7c62394SSam Clegg uint8_t EndOpcode = readOpcode(Ctx); 2019504ab32SSam Clegg if (EndOpcode != wasm::WASM_OPCODE_END) 2029504ab32SSam Clegg Expr.Extended = true; 2039504ab32SSam Clegg } 2049504ab32SSam Clegg 2059504ab32SSam Clegg if (Expr.Extended) { 2069504ab32SSam Clegg Ctx.Ptr = Start; 2079504ab32SSam Clegg while (1) { 2089504ab32SSam Clegg uint8_t Opcode = readOpcode(Ctx); 2099504ab32SSam Clegg switch (Opcode) { 2109504ab32SSam Clegg case wasm::WASM_OPCODE_I32_CONST: 2119504ab32SSam Clegg case wasm::WASM_OPCODE_GLOBAL_GET: 2129504ab32SSam Clegg case wasm::WASM_OPCODE_REF_NULL: 2139504ab32SSam Clegg case wasm::WASM_OPCODE_I64_CONST: 2149504ab32SSam Clegg case wasm::WASM_OPCODE_F32_CONST: 2159504ab32SSam Clegg case wasm::WASM_OPCODE_F64_CONST: 2169504ab32SSam Clegg readULEB128(Ctx); 2179504ab32SSam Clegg break; 2189504ab32SSam Clegg case wasm::WASM_OPCODE_I32_ADD: 2199504ab32SSam Clegg case wasm::WASM_OPCODE_I32_SUB: 2209504ab32SSam Clegg case wasm::WASM_OPCODE_I32_MUL: 2219504ab32SSam Clegg case wasm::WASM_OPCODE_I64_ADD: 2229504ab32SSam Clegg case wasm::WASM_OPCODE_I64_SUB: 2239504ab32SSam Clegg case wasm::WASM_OPCODE_I64_MUL: 2249504ab32SSam Clegg break; 2259504ab32SSam Clegg case wasm::WASM_OPCODE_END: 2269504ab32SSam Clegg Expr.Body = ArrayRef<uint8_t>(Start, Ctx.Ptr - Start); 2279504ab32SSam Clegg return Error::success(); 2289504ab32SSam Clegg default: 2299504ab32SSam Clegg return make_error<GenericBinaryError>( 2309504ab32SSam Clegg Twine("invalid opcode in init_expr: ") + Twine(unsigned(Opcode)), 231d3d84fddSDerek Schuff object_error::parse_failed); 232d3d84fddSDerek Schuff } 2339504ab32SSam Clegg } 2349504ab32SSam Clegg } 2359504ab32SSam Clegg 236d3d84fddSDerek Schuff return Error::success(); 237d3d84fddSDerek Schuff } 238d3d84fddSDerek Schuff 239b7c62394SSam Clegg static wasm::WasmLimits readLimits(WasmObjectFile::ReadContext &Ctx) { 240d3d84fddSDerek Schuff wasm::WasmLimits Result; 24168818062SDerek Schuff Result.Flags = readVaruint32(Ctx); 2429ac5620cSAndy Wingo Result.Minimum = readVaruint64(Ctx); 243d3d84fddSDerek Schuff if (Result.Flags & wasm::WASM_LIMITS_FLAG_HAS_MAX) 2444d135b04SWouter van Oortmerssen Result.Maximum = readVaruint64(Ctx); 245d3d84fddSDerek Schuff return Result; 246d3d84fddSDerek Schuff } 247d3d84fddSDerek Schuff 2481933c9d4SAndy Wingo static wasm::WasmTableType readTableType(WasmObjectFile::ReadContext &Ctx) { 2491933c9d4SAndy Wingo wasm::WasmTableType TableType; 2501933c9d4SAndy Wingo TableType.ElemType = readUint8(Ctx); 2511933c9d4SAndy Wingo TableType.Limits = readLimits(Ctx); 2521933c9d4SAndy Wingo return TableType; 2532ffff5afSSam Clegg } 2542ffff5afSSam Clegg 255feef720bSHeejin Ahn static Error readSection(WasmSection &Section, WasmObjectFile::ReadContext &Ctx, 256feef720bSHeejin Ahn WasmSectionOrderChecker &Checker) { 257b7c62394SSam Clegg Section.Offset = Ctx.Ptr - Ctx.Start; 258b7c62394SSam Clegg Section.Type = readUint8(Ctx); 259f4f37509SSam Clegg LLVM_DEBUG(dbgs() << "readSection type=" << Section.Type << "\n"); 260b7c62394SSam Clegg uint32_t Size = readVaruint32(Ctx); 2612c6f75ddSDerek Schuff if (Size == 0) 26284c6f325SSam Clegg return make_error<StringError>("zero length section", 2632c6f75ddSDerek Schuff object_error::parse_failed); 264b7c62394SSam Clegg if (Ctx.Ptr + Size > Ctx.End) 26584c6f325SSam Clegg return make_error<StringError>("section too large", 26635b50a83SVedant Kumar object_error::parse_failed); 2679745afa6SSam Clegg if (Section.Type == wasm::WASM_SEC_CUSTOM) { 2688511777dSJonas Devlieghere WasmObjectFile::ReadContext SectionCtx; 2698511777dSJonas Devlieghere SectionCtx.Start = Ctx.Ptr; 2708511777dSJonas Devlieghere SectionCtx.Ptr = Ctx.Ptr; 2718511777dSJonas Devlieghere SectionCtx.End = Ctx.Ptr + Size; 2728511777dSJonas Devlieghere 2738511777dSJonas Devlieghere Section.Name = readString(SectionCtx); 2748511777dSJonas Devlieghere 2758511777dSJonas Devlieghere uint32_t SectionNameSize = SectionCtx.Ptr - SectionCtx.Start; 2768511777dSJonas Devlieghere Ctx.Ptr += SectionNameSize; 2778511777dSJonas Devlieghere Size -= SectionNameSize; 2789745afa6SSam Clegg } 279feef720bSHeejin Ahn 280feef720bSHeejin Ahn if (!Checker.isValidSectionOrder(Section.Type, Section.Name)) { 28184c6f325SSam Clegg return make_error<StringError>("out of order section type: " + 282feef720bSHeejin Ahn llvm::to_string(Section.Type), 283feef720bSHeejin Ahn object_error::parse_failed); 284feef720bSHeejin Ahn } 285feef720bSHeejin Ahn 286b7c62394SSam Clegg Section.Content = ArrayRef<uint8_t>(Ctx.Ptr, Size); 287b7c62394SSam Clegg Ctx.Ptr += Size; 2882c6f75ddSDerek Schuff return Error::success(); 2892c6f75ddSDerek Schuff } 2902c6f75ddSDerek Schuff 2912c6f75ddSDerek Schuff WasmObjectFile::WasmObjectFile(MemoryBufferRef Buffer, Error &Err) 2929f5094dfSEugene Zelenko : ObjectFile(Binary::ID_Wasm, Buffer) { 2932c6f75ddSDerek Schuff ErrorAsOutParameter ErrAsOutParam(&Err); 2942c6f75ddSDerek Schuff Header.Magic = getData().substr(0, 4); 2952c6f75ddSDerek Schuff if (Header.Magic != StringRef("\0asm", 4)) { 29684c6f325SSam Clegg Err = make_error<StringError>("invalid magic number", 29784c6f325SSam Clegg object_error::parse_failed); 2982c6f75ddSDerek Schuff return; 2992c6f75ddSDerek Schuff } 300a845167dSJonas Devlieghere 301b7c62394SSam Clegg ReadContext Ctx; 3026a0746a9SFangrui Song Ctx.Start = getData().bytes_begin(); 303b7c62394SSam Clegg Ctx.Ptr = Ctx.Start + 4; 304b7c62394SSam Clegg Ctx.End = Ctx.Start + getData().size(); 305a845167dSJonas Devlieghere 306b7c62394SSam Clegg if (Ctx.Ptr + 4 > Ctx.End) { 30784c6f325SSam Clegg Err = make_error<StringError>("missing version number", 308a845167dSJonas Devlieghere object_error::parse_failed); 309a845167dSJonas Devlieghere return; 310a845167dSJonas Devlieghere } 311a845167dSJonas Devlieghere 312b7c62394SSam Clegg Header.Version = readUint32(Ctx); 3132c6f75ddSDerek Schuff if (Header.Version != wasm::WasmVersion) { 31484c6f325SSam Clegg Err = make_error<StringError>("invalid version number: " + 31584c6f325SSam Clegg Twine(Header.Version), 3162c6f75ddSDerek Schuff object_error::parse_failed); 3172c6f75ddSDerek Schuff return; 3182c6f75ddSDerek Schuff } 3192c6f75ddSDerek Schuff 320feef720bSHeejin Ahn WasmSectionOrderChecker Checker; 321b7c62394SSam Clegg while (Ctx.Ptr < Ctx.End) { 322e4b2f305SSam Clegg WasmSection Sec; 323feef720bSHeejin Ahn if ((Err = readSection(Sec, Ctx, Checker))) 3242c6f75ddSDerek Schuff return; 325d3d84fddSDerek Schuff if ((Err = parseSection(Sec))) 3262c6f75ddSDerek Schuff return; 327d3d84fddSDerek Schuff 3282c6f75ddSDerek Schuff Sections.push_back(Sec); 3292c6f75ddSDerek Schuff } 3302c6f75ddSDerek Schuff } 3312c6f75ddSDerek Schuff 332d3d84fddSDerek Schuff Error WasmObjectFile::parseSection(WasmSection &Sec) { 333b7c62394SSam Clegg ReadContext Ctx; 334b7c62394SSam Clegg Ctx.Start = Sec.Content.data(); 335b7c62394SSam Clegg Ctx.End = Ctx.Start + Sec.Content.size(); 336b7c62394SSam Clegg Ctx.Ptr = Ctx.Start; 337d3d84fddSDerek Schuff switch (Sec.Type) { 338d3d84fddSDerek Schuff case wasm::WASM_SEC_CUSTOM: 339b7c62394SSam Clegg return parseCustomSection(Sec, Ctx); 340d3d84fddSDerek Schuff case wasm::WASM_SEC_TYPE: 341b7c62394SSam Clegg return parseTypeSection(Ctx); 342d3d84fddSDerek Schuff case wasm::WASM_SEC_IMPORT: 343b7c62394SSam Clegg return parseImportSection(Ctx); 344d3d84fddSDerek Schuff case wasm::WASM_SEC_FUNCTION: 345b7c62394SSam Clegg return parseFunctionSection(Ctx); 346d3d84fddSDerek Schuff case wasm::WASM_SEC_TABLE: 347b7c62394SSam Clegg return parseTableSection(Ctx); 348d3d84fddSDerek Schuff case wasm::WASM_SEC_MEMORY: 349b7c62394SSam Clegg return parseMemorySection(Ctx); 3501d891d44SHeejin Ahn case wasm::WASM_SEC_TAG: 3511d891d44SHeejin Ahn return parseTagSection(Ctx); 352f93426c5SHeejin Ahn case wasm::WASM_SEC_GLOBAL: 353f93426c5SHeejin Ahn return parseGlobalSection(Ctx); 354d3d84fddSDerek Schuff case wasm::WASM_SEC_EXPORT: 355b7c62394SSam Clegg return parseExportSection(Ctx); 356d3d84fddSDerek Schuff case wasm::WASM_SEC_START: 357b7c62394SSam Clegg return parseStartSection(Ctx); 358d3d84fddSDerek Schuff case wasm::WASM_SEC_ELEM: 359b7c62394SSam Clegg return parseElemSection(Ctx); 360d3d84fddSDerek Schuff case wasm::WASM_SEC_CODE: 361b7c62394SSam Clegg return parseCodeSection(Ctx); 362d3d84fddSDerek Schuff case wasm::WASM_SEC_DATA: 363b7c62394SSam Clegg return parseDataSection(Ctx); 364fef8de66SThomas Lively case wasm::WASM_SEC_DATACOUNT: 365fef8de66SThomas Lively return parseDataCountSection(Ctx); 366d3d84fddSDerek Schuff default: 367fe8aabf9SSam Clegg return make_error<GenericBinaryError>( 36884c6f325SSam Clegg "invalid section type: " + Twine(Sec.Type), object_error::parse_failed); 369d3d84fddSDerek Schuff } 370d3d84fddSDerek Schuff } 371d3d84fddSDerek Schuff 372e4afbc68SSam Clegg Error WasmObjectFile::parseDylinkSection(ReadContext &Ctx) { 373b78c85a4SSam Clegg // Legacy "dylink" section support. 374b78c85a4SSam Clegg // See parseDylink0Section for the current "dylink.0" section parsing. 375a688a42cSSam Clegg HasDylinkSection = true; 376e4afbc68SSam Clegg DylinkInfo.MemorySize = readVaruint32(Ctx); 377e4afbc68SSam Clegg DylinkInfo.MemoryAlignment = readVaruint32(Ctx); 378e4afbc68SSam Clegg DylinkInfo.TableSize = readVaruint32(Ctx); 379e4afbc68SSam Clegg DylinkInfo.TableAlignment = readVaruint32(Ctx); 38003801256SSam Clegg uint32_t Count = readVaruint32(Ctx); 38103801256SSam Clegg while (Count--) { 38203801256SSam Clegg DylinkInfo.Needed.push_back(readString(Ctx)); 38303801256SSam Clegg } 384b78c85a4SSam Clegg 385e4afbc68SSam Clegg if (Ctx.Ptr != Ctx.End) 386e4afbc68SSam Clegg return make_error<GenericBinaryError>("dylink section ended prematurely", 387e4afbc68SSam Clegg object_error::parse_failed); 388e4afbc68SSam Clegg return Error::success(); 389e4afbc68SSam Clegg } 390e4afbc68SSam Clegg 391b78c85a4SSam Clegg Error WasmObjectFile::parseDylink0Section(ReadContext &Ctx) { 392b78c85a4SSam Clegg // See 393c71fbdd8SQuinn Pham // https://github.com/WebAssembly/tool-conventions/blob/main/DynamicLinking.md 394b78c85a4SSam Clegg HasDylinkSection = true; 395b78c85a4SSam Clegg 396b78c85a4SSam Clegg const uint8_t *OrigEnd = Ctx.End; 397b78c85a4SSam Clegg while (Ctx.Ptr < OrigEnd) { 398b78c85a4SSam Clegg Ctx.End = OrigEnd; 399b78c85a4SSam Clegg uint8_t Type = readUint8(Ctx); 400b78c85a4SSam Clegg uint32_t Size = readVaruint32(Ctx); 401b78c85a4SSam Clegg LLVM_DEBUG(dbgs() << "readSubsection type=" << int(Type) << " size=" << Size 402b78c85a4SSam Clegg << "\n"); 403b78c85a4SSam Clegg Ctx.End = Ctx.Ptr + Size; 404b78c85a4SSam Clegg uint32_t Count; 405b78c85a4SSam Clegg switch (Type) { 406b78c85a4SSam Clegg case wasm::WASM_DYLINK_MEM_INFO: 407b78c85a4SSam Clegg DylinkInfo.MemorySize = readVaruint32(Ctx); 408b78c85a4SSam Clegg DylinkInfo.MemoryAlignment = readVaruint32(Ctx); 409b78c85a4SSam Clegg DylinkInfo.TableSize = readVaruint32(Ctx); 410b78c85a4SSam Clegg DylinkInfo.TableAlignment = readVaruint32(Ctx); 411b78c85a4SSam Clegg break; 412b78c85a4SSam Clegg case wasm::WASM_DYLINK_NEEDED: 413b78c85a4SSam Clegg Count = readVaruint32(Ctx); 414b78c85a4SSam Clegg while (Count--) { 415b78c85a4SSam Clegg DylinkInfo.Needed.push_back(readString(Ctx)); 416b78c85a4SSam Clegg } 417b78c85a4SSam Clegg break; 418ef8c9135SSam Clegg case wasm::WASM_DYLINK_EXPORT_INFO: { 419ef8c9135SSam Clegg uint32_t Count = readVaruint32(Ctx); 420ef8c9135SSam Clegg while (Count--) { 421ef8c9135SSam Clegg DylinkInfo.ExportInfo.push_back({readString(Ctx), readVaruint32(Ctx)}); 422ef8c9135SSam Clegg } 423ef8c9135SSam Clegg break; 424ef8c9135SSam Clegg } 425659a0839SSam Clegg case wasm::WASM_DYLINK_IMPORT_INFO: { 426659a0839SSam Clegg uint32_t Count = readVaruint32(Ctx); 427659a0839SSam Clegg while (Count--) { 428659a0839SSam Clegg DylinkInfo.ImportInfo.push_back( 429659a0839SSam Clegg {readString(Ctx), readString(Ctx), readVaruint32(Ctx)}); 430659a0839SSam Clegg } 431659a0839SSam Clegg break; 432659a0839SSam Clegg } 433b78c85a4SSam Clegg default: 434210cbcf4SSam Clegg LLVM_DEBUG(dbgs() << "unknown dylink.0 sub-section: " << Type << "\n"); 435b78c85a4SSam Clegg Ctx.Ptr += Size; 436b78c85a4SSam Clegg break; 437b78c85a4SSam Clegg } 438b78c85a4SSam Clegg if (Ctx.Ptr != Ctx.End) { 439b78c85a4SSam Clegg return make_error<GenericBinaryError>( 440b78c85a4SSam Clegg "dylink.0 sub-section ended prematurely", object_error::parse_failed); 441b78c85a4SSam Clegg } 442b78c85a4SSam Clegg } 443b78c85a4SSam Clegg 444b78c85a4SSam Clegg if (Ctx.Ptr != Ctx.End) 445b78c85a4SSam Clegg return make_error<GenericBinaryError>("dylink.0 section ended prematurely", 446b78c85a4SSam Clegg object_error::parse_failed); 447b78c85a4SSam Clegg return Error::success(); 448b78c85a4SSam Clegg } 449b78c85a4SSam Clegg 450b7c62394SSam Clegg Error WasmObjectFile::parseNameSection(ReadContext &Ctx) { 4511827005cSSam Clegg llvm::DenseSet<uint64_t> SeenFunctions; 4521827005cSSam Clegg llvm::DenseSet<uint64_t> SeenGlobals; 4539a72d3e3SSam Clegg llvm::DenseSet<uint64_t> SeenSegments; 4544710ed7aSSam Clegg 455b7c62394SSam Clegg while (Ctx.Ptr < Ctx.End) { 456b7c62394SSam Clegg uint8_t Type = readUint8(Ctx); 457b7c62394SSam Clegg uint32_t Size = readVaruint32(Ctx); 458b7c62394SSam Clegg const uint8_t *SubSectionEnd = Ctx.Ptr + Size; 459d3d84fddSDerek Schuff switch (Type) { 4601827005cSSam Clegg case wasm::WASM_NAMES_FUNCTION: 4619a72d3e3SSam Clegg case wasm::WASM_NAMES_GLOBAL: 4629a72d3e3SSam Clegg case wasm::WASM_NAMES_DATA_SEGMENT: { 463b7c62394SSam Clegg uint32_t Count = readVaruint32(Ctx); 464d3d84fddSDerek Schuff while (Count--) { 465b7c62394SSam Clegg uint32_t Index = readVaruint32(Ctx); 466b7c62394SSam Clegg StringRef Name = readString(Ctx); 4679a72d3e3SSam Clegg wasm::NameType nameType = wasm::NameType::FUNCTION; 4681827005cSSam Clegg if (Type == wasm::WASM_NAMES_FUNCTION) { 4691827005cSSam Clegg if (!SeenFunctions.insert(Index).second) 4701827005cSSam Clegg return make_error<GenericBinaryError>( 47184c6f325SSam Clegg "function named more than once", object_error::parse_failed); 4729f3fe42eSSam Clegg if (!isValidFunctionIndex(Index) || Name.empty()) 473*5a082d9cSDerek Schuff return make_error<GenericBinaryError>("invalid function name entry", 4749f3fe42eSSam Clegg object_error::parse_failed); 4751827005cSSam Clegg 476ef90ff36SNicholas Wilson if (isDefinedFunctionIndex(Index)) 477ef90ff36SNicholas Wilson getDefinedFunction(Index).DebugName = Name; 4789a72d3e3SSam Clegg } else if (Type == wasm::WASM_NAMES_GLOBAL) { 4799a72d3e3SSam Clegg nameType = wasm::NameType::GLOBAL; 4801827005cSSam Clegg if (!SeenGlobals.insert(Index).second) 48184c6f325SSam Clegg return make_error<GenericBinaryError>("global named more than once", 4821827005cSSam Clegg object_error::parse_failed); 4831827005cSSam Clegg if (!isValidGlobalIndex(Index) || Name.empty()) 484*5a082d9cSDerek Schuff return make_error<GenericBinaryError>("invalid global name entry", 4851827005cSSam Clegg object_error::parse_failed); 4869a72d3e3SSam Clegg } else { 4879a72d3e3SSam Clegg nameType = wasm::NameType::DATA_SEGMENT; 4889a72d3e3SSam Clegg if (!SeenSegments.insert(Index).second) 4899a72d3e3SSam Clegg return make_error<GenericBinaryError>( 49084c6f325SSam Clegg "segment named more than once", object_error::parse_failed); 4919a72d3e3SSam Clegg if (Index > DataSegments.size()) 492*5a082d9cSDerek Schuff return make_error<GenericBinaryError>("invalid data segment name entry", 4939a72d3e3SSam Clegg object_error::parse_failed); 4941827005cSSam Clegg } 4959a72d3e3SSam Clegg DebugNames.push_back(wasm::WasmDebugName{nameType, Index, Name}); 496d3d84fddSDerek Schuff } 497d3d84fddSDerek Schuff break; 498d3d84fddSDerek Schuff } 499d3d84fddSDerek Schuff // Ignore local names for now 500d3d84fddSDerek Schuff case wasm::WASM_NAMES_LOCAL: 501d3d84fddSDerek Schuff default: 502b7c62394SSam Clegg Ctx.Ptr += Size; 503d3d84fddSDerek Schuff break; 504d3d84fddSDerek Schuff } 505b7c62394SSam Clegg if (Ctx.Ptr != SubSectionEnd) 506f208f631SHeejin Ahn return make_error<GenericBinaryError>( 50784c6f325SSam Clegg "name sub-section ended prematurely", object_error::parse_failed); 508d3d84fddSDerek Schuff } 509d3d84fddSDerek Schuff 510b7c62394SSam Clegg if (Ctx.Ptr != Ctx.End) 51184c6f325SSam Clegg return make_error<GenericBinaryError>("name section ended prematurely", 512d3d84fddSDerek Schuff object_error::parse_failed); 513d3d84fddSDerek Schuff return Error::success(); 514d3d84fddSDerek Schuff } 515d3d84fddSDerek Schuff 516b7c62394SSam Clegg Error WasmObjectFile::parseLinkingSection(ReadContext &Ctx) { 5174df5d764SSam Clegg HasLinkingSection = true; 518e7a60708SSam Clegg 519b7c62394SSam Clegg LinkingData.Version = readVaruint32(Ctx); 5206bb5a41fSSam Clegg if (LinkingData.Version != wasm::WasmMetadataVersion) { 5216bb5a41fSSam Clegg return make_error<GenericBinaryError>( 52284c6f325SSam Clegg "unexpected metadata version: " + Twine(LinkingData.Version) + 5236bb5a41fSSam Clegg " (Expected: " + Twine(wasm::WasmMetadataVersion) + ")", 5246bb5a41fSSam Clegg object_error::parse_failed); 5256bb5a41fSSam Clegg } 5266bb5a41fSSam Clegg 527b7c62394SSam Clegg const uint8_t *OrigEnd = Ctx.End; 528b7c62394SSam Clegg while (Ctx.Ptr < OrigEnd) { 529b7c62394SSam Clegg Ctx.End = OrigEnd; 530b7c62394SSam Clegg uint8_t Type = readUint8(Ctx); 531b7c62394SSam Clegg uint32_t Size = readVaruint32(Ctx); 532f4f37509SSam Clegg LLVM_DEBUG(dbgs() << "readSubsection type=" << int(Type) << " size=" << Size 533f4f37509SSam Clegg << "\n"); 534b7c62394SSam Clegg Ctx.End = Ctx.Ptr + Size; 535b7787fd0SSam Clegg switch (Type) { 5366c899ba6SSam Clegg case wasm::WASM_SYMBOL_TABLE: 537b7c62394SSam Clegg if (Error Err = parseLinkingSectionSymtab(Ctx)) 5386c899ba6SSam Clegg return Err; 539b7787fd0SSam Clegg break; 54063ebb813SSam Clegg case wasm::WASM_SEGMENT_INFO: { 541b7c62394SSam Clegg uint32_t Count = readVaruint32(Ctx); 542d95ed959SSam Clegg if (Count > DataSegments.size()) 54384c6f325SSam Clegg return make_error<GenericBinaryError>("too many segment names", 544d95ed959SSam Clegg object_error::parse_failed); 54518c56a07SHeejin Ahn for (uint32_t I = 0; I < Count; I++) { 54618c56a07SHeejin Ahn DataSegments[I].Data.Name = readString(Ctx); 54718c56a07SHeejin Ahn DataSegments[I].Data.Alignment = readVaruint32(Ctx); 5483b8d2be5SSam Clegg DataSegments[I].Data.LinkingFlags = readVaruint32(Ctx); 54963ebb813SSam Clegg } 550d95ed959SSam Clegg break; 551d95ed959SSam Clegg } 5524273998cSSam Clegg case wasm::WASM_INIT_FUNCS: { 553b7c62394SSam Clegg uint32_t Count = readVaruint32(Ctx); 5544273998cSSam Clegg LinkingData.InitFunctions.reserve(Count); 55518c56a07SHeejin Ahn for (uint32_t I = 0; I < Count; I++) { 5564273998cSSam Clegg wasm::WasmInitFunc Init; 557b7c62394SSam Clegg Init.Priority = readVaruint32(Ctx); 558b7c62394SSam Clegg Init.Symbol = readVaruint32(Ctx); 559b3748f71SNicholas Wilson if (!isValidFunctionSymbol(Init.Symbol)) 56084c6f325SSam Clegg return make_error<GenericBinaryError>("invalid function symbol: " + 5616c899ba6SSam Clegg Twine(Init.Symbol), 5624273998cSSam Clegg object_error::parse_failed); 5634273998cSSam Clegg LinkingData.InitFunctions.emplace_back(Init); 5644273998cSSam Clegg } 5654273998cSSam Clegg break; 5664273998cSSam Clegg } 567ea7caceeSSam Clegg case wasm::WASM_COMDAT_INFO: 568b7c62394SSam Clegg if (Error Err = parseLinkingSectionComdat(Ctx)) 569ea7caceeSSam Clegg return Err; 570ea7caceeSSam Clegg break; 571b7787fd0SSam Clegg default: 572b7c62394SSam Clegg Ctx.Ptr += Size; 573b7787fd0SSam Clegg break; 574b7787fd0SSam Clegg } 575b7c62394SSam Clegg if (Ctx.Ptr != Ctx.End) 576b7787fd0SSam Clegg return make_error<GenericBinaryError>( 57784c6f325SSam Clegg "linking sub-section ended prematurely", object_error::parse_failed); 578b7787fd0SSam Clegg } 579b7c62394SSam Clegg if (Ctx.Ptr != OrigEnd) 58084c6f325SSam Clegg return make_error<GenericBinaryError>("linking section ended prematurely", 581b7787fd0SSam Clegg object_error::parse_failed); 582b7787fd0SSam Clegg return Error::success(); 583b7787fd0SSam Clegg } 584b7787fd0SSam Clegg 585b7c62394SSam Clegg Error WasmObjectFile::parseLinkingSectionSymtab(ReadContext &Ctx) { 586b7c62394SSam Clegg uint32_t Count = readVaruint32(Ctx); 5876c899ba6SSam Clegg LinkingData.SymbolTable.reserve(Count); 5886c899ba6SSam Clegg Symbols.reserve(Count); 5896c899ba6SSam Clegg StringSet<> SymbolNames; 5906c899ba6SSam Clegg 5916c899ba6SSam Clegg std::vector<wasm::WasmImport *> ImportedGlobals; 5926c899ba6SSam Clegg std::vector<wasm::WasmImport *> ImportedFunctions; 5931d891d44SHeejin Ahn std::vector<wasm::WasmImport *> ImportedTags; 594feac819eSAndy Wingo std::vector<wasm::WasmImport *> ImportedTables; 5956c899ba6SSam Clegg ImportedGlobals.reserve(Imports.size()); 5966c899ba6SSam Clegg ImportedFunctions.reserve(Imports.size()); 5971d891d44SHeejin Ahn ImportedTags.reserve(Imports.size()); 598feac819eSAndy Wingo ImportedTables.reserve(Imports.size()); 5996c899ba6SSam Clegg for (auto &I : Imports) { 6006c899ba6SSam Clegg if (I.Kind == wasm::WASM_EXTERNAL_FUNCTION) 6016c899ba6SSam Clegg ImportedFunctions.emplace_back(&I); 6026c899ba6SSam Clegg else if (I.Kind == wasm::WASM_EXTERNAL_GLOBAL) 6036c899ba6SSam Clegg ImportedGlobals.emplace_back(&I); 6041d891d44SHeejin Ahn else if (I.Kind == wasm::WASM_EXTERNAL_TAG) 6051d891d44SHeejin Ahn ImportedTags.emplace_back(&I); 606feac819eSAndy Wingo else if (I.Kind == wasm::WASM_EXTERNAL_TABLE) 607feac819eSAndy Wingo ImportedTables.emplace_back(&I); 6086c899ba6SSam Clegg } 6096c899ba6SSam Clegg 6106c899ba6SSam Clegg while (Count--) { 6116c899ba6SSam Clegg wasm::WasmSymbolInfo Info; 612a2125b8dSHeejin Ahn const wasm::WasmSignature *Signature = nullptr; 6136c899ba6SSam Clegg const wasm::WasmGlobalType *GlobalType = nullptr; 61453e3b81fSAndy Wingo const wasm::WasmTableType *TableType = nullptr; 6156c899ba6SSam Clegg 616b7c62394SSam Clegg Info.Kind = readUint8(Ctx); 617b7c62394SSam Clegg Info.Flags = readVaruint32(Ctx); 6186c899ba6SSam Clegg bool IsDefined = (Info.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0; 6196c899ba6SSam Clegg 6206c899ba6SSam Clegg switch (Info.Kind) { 6216c899ba6SSam Clegg case wasm::WASM_SYMBOL_TYPE_FUNCTION: 622b7c62394SSam Clegg Info.ElementIndex = readVaruint32(Ctx); 6236c899ba6SSam Clegg if (!isValidFunctionIndex(Info.ElementIndex) || 6246c899ba6SSam Clegg IsDefined != isDefinedFunctionIndex(Info.ElementIndex)) 6256c899ba6SSam Clegg return make_error<GenericBinaryError>("invalid function symbol index", 6266c899ba6SSam Clegg object_error::parse_failed); 6276c899ba6SSam Clegg if (IsDefined) { 628b7c62394SSam Clegg Info.Name = readString(Ctx); 6296c899ba6SSam Clegg unsigned FuncIndex = Info.ElementIndex - NumImportedFunctions; 630959e7371SNicholas Wilson wasm::WasmFunction &Function = Functions[FuncIndex]; 631c0039de2SSam Clegg Signature = &Signatures[Function.SigIndex]; 632ef90ff36SNicholas Wilson if (Function.SymbolName.empty()) 633ef90ff36SNicholas Wilson Function.SymbolName = Info.Name; 6346c899ba6SSam Clegg } else { 6356c899ba6SSam Clegg wasm::WasmImport &Import = *ImportedFunctions[Info.ElementIndex]; 636bd481277SSam Clegg if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0) { 63729874ceaSDan Gohman Info.Name = readString(Ctx); 63829874ceaSDan Gohman Info.ImportName = Import.Field; 639bd481277SSam Clegg } else { 640bd481277SSam Clegg Info.Name = Import.Field; 641bd481277SSam Clegg } 642bd481277SSam Clegg Signature = &Signatures[Import.SigIndex]; 643bd481277SSam Clegg if (!Import.Module.empty()) { 64429874ceaSDan Gohman Info.ImportModule = Import.Module; 6456c899ba6SSam Clegg } 646bd481277SSam Clegg } 6476c899ba6SSam Clegg break; 6486c899ba6SSam Clegg 6496c899ba6SSam Clegg case wasm::WASM_SYMBOL_TYPE_GLOBAL: 650b7c62394SSam Clegg Info.ElementIndex = readVaruint32(Ctx); 6516c899ba6SSam Clegg if (!isValidGlobalIndex(Info.ElementIndex) || 6526c899ba6SSam Clegg IsDefined != isDefinedGlobalIndex(Info.ElementIndex)) 6536c899ba6SSam Clegg return make_error<GenericBinaryError>("invalid global symbol index", 6546c899ba6SSam Clegg object_error::parse_failed); 655f208f631SHeejin Ahn if (!IsDefined && (Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) == 65615f349f7SNicholas Wilson wasm::WASM_SYMBOL_BINDING_WEAK) 65715f349f7SNicholas Wilson return make_error<GenericBinaryError>("undefined weak global symbol", 65815f349f7SNicholas Wilson object_error::parse_failed); 6596c899ba6SSam Clegg if (IsDefined) { 660b7c62394SSam Clegg Info.Name = readString(Ctx); 6616c899ba6SSam Clegg unsigned GlobalIndex = Info.ElementIndex - NumImportedGlobals; 662959e7371SNicholas Wilson wasm::WasmGlobal &Global = Globals[GlobalIndex]; 663959e7371SNicholas Wilson GlobalType = &Global.Type; 664ef90ff36SNicholas Wilson if (Global.SymbolName.empty()) 665ef90ff36SNicholas Wilson Global.SymbolName = Info.Name; 6666c899ba6SSam Clegg } else { 6676c899ba6SSam Clegg wasm::WasmImport &Import = *ImportedGlobals[Info.ElementIndex]; 668bd481277SSam Clegg if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0) { 66929874ceaSDan Gohman Info.Name = readString(Ctx); 670bd481277SSam Clegg Info.ImportName = Import.Field; 671bd481277SSam Clegg } else { 6726c899ba6SSam Clegg Info.Name = Import.Field; 673bd481277SSam Clegg } 6746c899ba6SSam Clegg GlobalType = &Import.Global; 675bd481277SSam Clegg if (!Import.Module.empty()) { 67629874ceaSDan Gohman Info.ImportModule = Import.Module; 6776c899ba6SSam Clegg } 678bd481277SSam Clegg } 6796c899ba6SSam Clegg break; 6806c899ba6SSam Clegg 681388fb67bSPaulo Matos case wasm::WASM_SYMBOL_TYPE_TABLE: 682388fb67bSPaulo Matos Info.ElementIndex = readVaruint32(Ctx); 683a5a3659dSAndy Wingo if (!isValidTableNumber(Info.ElementIndex) || 684a5a3659dSAndy Wingo IsDefined != isDefinedTableNumber(Info.ElementIndex)) 685388fb67bSPaulo Matos return make_error<GenericBinaryError>("invalid table symbol index", 686388fb67bSPaulo Matos object_error::parse_failed); 687388fb67bSPaulo Matos if (!IsDefined && (Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) == 688388fb67bSPaulo Matos wasm::WASM_SYMBOL_BINDING_WEAK) 689388fb67bSPaulo Matos return make_error<GenericBinaryError>("undefined weak table symbol", 690388fb67bSPaulo Matos object_error::parse_failed); 691388fb67bSPaulo Matos if (IsDefined) { 692388fb67bSPaulo Matos Info.Name = readString(Ctx); 693a5a3659dSAndy Wingo unsigned TableNumber = Info.ElementIndex - NumImportedTables; 694a5a3659dSAndy Wingo wasm::WasmTable &Table = Tables[TableNumber]; 69553e3b81fSAndy Wingo TableType = &Table.Type; 6961933c9d4SAndy Wingo if (Table.SymbolName.empty()) 6971933c9d4SAndy Wingo Table.SymbolName = Info.Name; 698388fb67bSPaulo Matos } else { 699feac819eSAndy Wingo wasm::WasmImport &Import = *ImportedTables[Info.ElementIndex]; 700feac819eSAndy Wingo if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0) { 701feac819eSAndy Wingo Info.Name = readString(Ctx); 702feac819eSAndy Wingo Info.ImportName = Import.Field; 703feac819eSAndy Wingo } else { 704feac819eSAndy Wingo Info.Name = Import.Field; 705feac819eSAndy Wingo } 70653e3b81fSAndy Wingo TableType = &Import.Table; 707feac819eSAndy Wingo if (!Import.Module.empty()) { 708feac819eSAndy Wingo Info.ImportModule = Import.Module; 709feac819eSAndy Wingo } 710388fb67bSPaulo Matos } 711388fb67bSPaulo Matos break; 712388fb67bSPaulo Matos 7136c899ba6SSam Clegg case wasm::WASM_SYMBOL_TYPE_DATA: 714b7c62394SSam Clegg Info.Name = readString(Ctx); 7156c899ba6SSam Clegg if (IsDefined) { 7163b29376eSWouter van Oortmerssen auto Index = readVaruint32(Ctx); 7176c899ba6SSam Clegg if (Index >= DataSegments.size()) 7186c899ba6SSam Clegg return make_error<GenericBinaryError>("invalid data symbol index", 7196c899ba6SSam Clegg object_error::parse_failed); 7203b29376eSWouter van Oortmerssen auto Offset = readVaruint64(Ctx); 7213b29376eSWouter van Oortmerssen auto Size = readVaruint64(Ctx); 722cd01430fSSam Clegg size_t SegmentSize = DataSegments[Index].Data.Content.size(); 723cd01430fSSam Clegg if (Offset > SegmentSize) 724cd01430fSSam Clegg return make_error<GenericBinaryError>( 725cd01430fSSam Clegg "invalid data symbol offset: `" + Info.Name + "` (offset: " + 726cd01430fSSam Clegg Twine(Offset) + " segment size: " + Twine(SegmentSize) + ")", 7276c899ba6SSam Clegg object_error::parse_failed); 7286c899ba6SSam Clegg Info.DataRef = wasm::WasmDataReference{Index, Offset, Size}; 7296c899ba6SSam Clegg } 7306c899ba6SSam Clegg break; 7316c899ba6SSam Clegg 7326a31a0d6SSam Clegg case wasm::WASM_SYMBOL_TYPE_SECTION: { 733d5504a0aSSam Clegg if ((Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) != 734d5504a0aSSam Clegg wasm::WASM_SYMBOL_BINDING_LOCAL) 735e0658119SSam Clegg return make_error<GenericBinaryError>( 73684c6f325SSam Clegg "section symbols must have local binding", 737d5504a0aSSam Clegg object_error::parse_failed); 738b7c62394SSam Clegg Info.ElementIndex = readVaruint32(Ctx); 7396a31a0d6SSam Clegg // Use somewhat unique section name as symbol name. 7406a31a0d6SSam Clegg StringRef SectionName = Sections[Info.ElementIndex].Name; 7416a31a0d6SSam Clegg Info.Name = SectionName; 7426a31a0d6SSam Clegg break; 7436a31a0d6SSam Clegg } 7446a31a0d6SSam Clegg 7451d891d44SHeejin Ahn case wasm::WASM_SYMBOL_TYPE_TAG: { 746da419bdbSHeejin Ahn Info.ElementIndex = readVaruint32(Ctx); 7471d891d44SHeejin Ahn if (!isValidTagIndex(Info.ElementIndex) || 7481d891d44SHeejin Ahn IsDefined != isDefinedTagIndex(Info.ElementIndex)) 7491d891d44SHeejin Ahn return make_error<GenericBinaryError>("invalid tag symbol index", 750da419bdbSHeejin Ahn object_error::parse_failed); 751da419bdbSHeejin Ahn if (!IsDefined && (Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) == 752da419bdbSHeejin Ahn wasm::WASM_SYMBOL_BINDING_WEAK) 753da419bdbSHeejin Ahn return make_error<GenericBinaryError>("undefined weak global symbol", 754da419bdbSHeejin Ahn object_error::parse_failed); 755da419bdbSHeejin Ahn if (IsDefined) { 756da419bdbSHeejin Ahn Info.Name = readString(Ctx); 7571d891d44SHeejin Ahn unsigned TagIndex = Info.ElementIndex - NumImportedTags; 7581d891d44SHeejin Ahn wasm::WasmTag &Tag = Tags[TagIndex]; 7593ec1760dSHeejin Ahn Signature = &Signatures[Tag.SigIndex]; 7601d891d44SHeejin Ahn if (Tag.SymbolName.empty()) 7611d891d44SHeejin Ahn Tag.SymbolName = Info.Name; 762da419bdbSHeejin Ahn 763da419bdbSHeejin Ahn } else { 7641d891d44SHeejin Ahn wasm::WasmImport &Import = *ImportedTags[Info.ElementIndex]; 765bd481277SSam Clegg if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0) { 76629874ceaSDan Gohman Info.Name = readString(Ctx); 767bd481277SSam Clegg Info.ImportName = Import.Field; 768bd481277SSam Clegg } else { 76929874ceaSDan Gohman Info.Name = Import.Field; 770bd481277SSam Clegg } 7713ec1760dSHeejin Ahn Signature = &Signatures[Import.SigIndex]; 772bd481277SSam Clegg if (!Import.Module.empty()) { 77329874ceaSDan Gohman Info.ImportModule = Import.Module; 774da419bdbSHeejin Ahn } 775bd481277SSam Clegg } 776da419bdbSHeejin Ahn break; 777da419bdbSHeejin Ahn } 778da419bdbSHeejin Ahn 7796c899ba6SSam Clegg default: 78084c6f325SSam Clegg return make_error<GenericBinaryError>("invalid symbol type: " + 781d75b3719SSam Clegg Twine(unsigned(Info.Kind)), 7826c899ba6SSam Clegg object_error::parse_failed); 7836c899ba6SSam Clegg } 7846c899ba6SSam Clegg 7856c899ba6SSam Clegg if ((Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) != 7866c899ba6SSam Clegg wasm::WASM_SYMBOL_BINDING_LOCAL && 7876c899ba6SSam Clegg !SymbolNames.insert(Info.Name).second) 78884c6f325SSam Clegg return make_error<GenericBinaryError>("duplicate symbol name " + 7896c899ba6SSam Clegg Twine(Info.Name), 7906c899ba6SSam Clegg object_error::parse_failed); 7916c899ba6SSam Clegg LinkingData.SymbolTable.emplace_back(Info); 792388fb67bSPaulo Matos Symbols.emplace_back(LinkingData.SymbolTable.back(), GlobalType, TableType, 7933ec1760dSHeejin Ahn Signature); 794d34e60caSNicola Zaghen LLVM_DEBUG(dbgs() << "Adding symbol: " << Symbols.back() << "\n"); 7956c899ba6SSam Clegg } 7966c899ba6SSam Clegg 7976c899ba6SSam Clegg return Error::success(); 7986c899ba6SSam Clegg } 7996c899ba6SSam Clegg 800b7c62394SSam Clegg Error WasmObjectFile::parseLinkingSectionComdat(ReadContext &Ctx) { 801b7c62394SSam Clegg uint32_t ComdatCount = readVaruint32(Ctx); 802ea7caceeSSam Clegg StringSet<> ComdatSet; 803027b9357SNicholas Wilson for (unsigned ComdatIndex = 0; ComdatIndex < ComdatCount; ++ComdatIndex) { 804b7c62394SSam Clegg StringRef Name = readString(Ctx); 805ea7caceeSSam Clegg if (Name.empty() || !ComdatSet.insert(Name).second) 80684c6f325SSam Clegg return make_error<GenericBinaryError>("bad/duplicate COMDAT name " + 807f208f631SHeejin Ahn Twine(Name), 808ea7caceeSSam Clegg object_error::parse_failed); 809027b9357SNicholas Wilson LinkingData.Comdats.emplace_back(Name); 810b7c62394SSam Clegg uint32_t Flags = readVaruint32(Ctx); 811ea7caceeSSam Clegg if (Flags != 0) 81284c6f325SSam Clegg return make_error<GenericBinaryError>("unsupported COMDAT flags", 813ea7caceeSSam Clegg object_error::parse_failed); 814ea7caceeSSam Clegg 815b7c62394SSam Clegg uint32_t EntryCount = readVaruint32(Ctx); 816ea7caceeSSam Clegg while (EntryCount--) { 817b7c62394SSam Clegg unsigned Kind = readVaruint32(Ctx); 818b7c62394SSam Clegg unsigned Index = readVaruint32(Ctx); 819ea7caceeSSam Clegg switch (Kind) { 820ea7caceeSSam Clegg default: 82184c6f325SSam Clegg return make_error<GenericBinaryError>("invalid COMDAT entry type", 822ea7caceeSSam Clegg object_error::parse_failed); 823ea7caceeSSam Clegg case wasm::WASM_COMDAT_DATA: 824ea7caceeSSam Clegg if (Index >= DataSegments.size()) 825f208f631SHeejin Ahn return make_error<GenericBinaryError>( 826f208f631SHeejin Ahn "COMDAT data index out of range", object_error::parse_failed); 827027b9357SNicholas Wilson if (DataSegments[Index].Data.Comdat != UINT32_MAX) 82884c6f325SSam Clegg return make_error<GenericBinaryError>("data segment in two COMDATs", 829ea7caceeSSam Clegg object_error::parse_failed); 830027b9357SNicholas Wilson DataSegments[Index].Data.Comdat = ComdatIndex; 831ea7caceeSSam Clegg break; 832ea7caceeSSam Clegg case wasm::WASM_COMDAT_FUNCTION: 83323012e98SSam Clegg if (!isDefinedFunctionIndex(Index)) 834f208f631SHeejin Ahn return make_error<GenericBinaryError>( 835f208f631SHeejin Ahn "COMDAT function index out of range", object_error::parse_failed); 836027b9357SNicholas Wilson if (getDefinedFunction(Index).Comdat != UINT32_MAX) 83784c6f325SSam Clegg return make_error<GenericBinaryError>("function in two COMDATs", 838ea7caceeSSam Clegg object_error::parse_failed); 839027b9357SNicholas Wilson getDefinedFunction(Index).Comdat = ComdatIndex; 840ea7caceeSSam Clegg break; 8410a391060SDerek Schuff case wasm::WASM_COMDAT_SECTION: 8420a391060SDerek Schuff if (Index >= Sections.size()) 8430a391060SDerek Schuff return make_error<GenericBinaryError>( 8440a391060SDerek Schuff "COMDAT section index out of range", object_error::parse_failed); 8450a391060SDerek Schuff if (Sections[Index].Type != wasm::WASM_SEC_CUSTOM) 8460a391060SDerek Schuff return make_error<GenericBinaryError>( 84784c6f325SSam Clegg "non-custom section in a COMDAT", object_error::parse_failed); 8480a391060SDerek Schuff Sections[Index].Comdat = ComdatIndex; 8490a391060SDerek Schuff break; 850ea7caceeSSam Clegg } 851ea7caceeSSam Clegg } 852ea7caceeSSam Clegg } 853ea7caceeSSam Clegg return Error::success(); 854ea7caceeSSam Clegg } 855ea7caceeSSam Clegg 856cbda16ebSThomas Lively Error WasmObjectFile::parseProducersSection(ReadContext &Ctx) { 857cbda16ebSThomas Lively llvm::SmallSet<StringRef, 3> FieldsSeen; 858cbda16ebSThomas Lively uint32_t Fields = readVaruint32(Ctx); 85918c56a07SHeejin Ahn for (size_t I = 0; I < Fields; ++I) { 860cbda16ebSThomas Lively StringRef FieldName = readString(Ctx); 861cbda16ebSThomas Lively if (!FieldsSeen.insert(FieldName).second) 862cbda16ebSThomas Lively return make_error<GenericBinaryError>( 86384c6f325SSam Clegg "producers section does not have unique fields", 864cbda16ebSThomas Lively object_error::parse_failed); 865cbda16ebSThomas Lively std::vector<std::pair<std::string, std::string>> *ProducerVec = nullptr; 866cbda16ebSThomas Lively if (FieldName == "language") { 867cbda16ebSThomas Lively ProducerVec = &ProducerInfo.Languages; 868cbda16ebSThomas Lively } else if (FieldName == "processed-by") { 869cbda16ebSThomas Lively ProducerVec = &ProducerInfo.Tools; 870cbda16ebSThomas Lively } else if (FieldName == "sdk") { 871cbda16ebSThomas Lively ProducerVec = &ProducerInfo.SDKs; 872cbda16ebSThomas Lively } else { 873cbda16ebSThomas Lively return make_error<GenericBinaryError>( 87484c6f325SSam Clegg "producers section field is not named one of language, processed-by, " 875cbda16ebSThomas Lively "or sdk", 876cbda16ebSThomas Lively object_error::parse_failed); 877cbda16ebSThomas Lively } 878cbda16ebSThomas Lively uint32_t ValueCount = readVaruint32(Ctx); 879cbda16ebSThomas Lively llvm::SmallSet<StringRef, 8> ProducersSeen; 88018c56a07SHeejin Ahn for (size_t J = 0; J < ValueCount; ++J) { 881cbda16ebSThomas Lively StringRef Name = readString(Ctx); 882cbda16ebSThomas Lively StringRef Version = readString(Ctx); 883cbda16ebSThomas Lively if (!ProducersSeen.insert(Name).second) { 884cbda16ebSThomas Lively return make_error<GenericBinaryError>( 88584c6f325SSam Clegg "producers section contains repeated producer", 886cbda16ebSThomas Lively object_error::parse_failed); 887cbda16ebSThomas Lively } 888a9bc7b83SBenjamin Kramer ProducerVec->emplace_back(std::string(Name), std::string(Version)); 889cbda16ebSThomas Lively } 890cbda16ebSThomas Lively } 891cbda16ebSThomas Lively if (Ctx.Ptr != Ctx.End) 89284c6f325SSam Clegg return make_error<GenericBinaryError>("producers section ended prematurely", 893cbda16ebSThomas Lively object_error::parse_failed); 894cbda16ebSThomas Lively return Error::success(); 895cbda16ebSThomas Lively } 896cbda16ebSThomas Lively 897f6f4f843SThomas Lively Error WasmObjectFile::parseTargetFeaturesSection(ReadContext &Ctx) { 898f6f4f843SThomas Lively llvm::SmallSet<std::string, 8> FeaturesSeen; 899f6f4f843SThomas Lively uint32_t FeatureCount = readVaruint32(Ctx); 900f6f4f843SThomas Lively for (size_t I = 0; I < FeatureCount; ++I) { 901f6f4f843SThomas Lively wasm::WasmFeatureEntry Feature; 902f6f4f843SThomas Lively Feature.Prefix = readUint8(Ctx); 903f6f4f843SThomas Lively switch (Feature.Prefix) { 904f6f4f843SThomas Lively case wasm::WASM_FEATURE_PREFIX_USED: 905f6f4f843SThomas Lively case wasm::WASM_FEATURE_PREFIX_REQUIRED: 906f6f4f843SThomas Lively case wasm::WASM_FEATURE_PREFIX_DISALLOWED: 907f6f4f843SThomas Lively break; 908f6f4f843SThomas Lively default: 90984c6f325SSam Clegg return make_error<GenericBinaryError>("unknown feature policy prefix", 910f6f4f843SThomas Lively object_error::parse_failed); 911f6f4f843SThomas Lively } 912adcd0268SBenjamin Kramer Feature.Name = std::string(readString(Ctx)); 913f6f4f843SThomas Lively if (!FeaturesSeen.insert(Feature.Name).second) 914f6f4f843SThomas Lively return make_error<GenericBinaryError>( 91584c6f325SSam Clegg "target features section contains repeated feature \"" + 916f6f4f843SThomas Lively Feature.Name + "\"", 917f6f4f843SThomas Lively object_error::parse_failed); 918f6f4f843SThomas Lively TargetFeatures.push_back(Feature); 919f6f4f843SThomas Lively } 920f6f4f843SThomas Lively if (Ctx.Ptr != Ctx.End) 921f6f4f843SThomas Lively return make_error<GenericBinaryError>( 92284c6f325SSam Clegg "target features section ended prematurely", 923f6f4f843SThomas Lively object_error::parse_failed); 924f6f4f843SThomas Lively return Error::success(); 925f6f4f843SThomas Lively } 926f6f4f843SThomas Lively 927b7c62394SSam Clegg Error WasmObjectFile::parseRelocSection(StringRef Name, ReadContext &Ctx) { 928b7c62394SSam Clegg uint32_t SectionIndex = readVaruint32(Ctx); 9296f08c84aSSam Clegg if (SectionIndex >= Sections.size()) 93084c6f325SSam Clegg return make_error<GenericBinaryError>("invalid section index", 931d3d84fddSDerek Schuff object_error::parse_failed); 9326f08c84aSSam Clegg WasmSection &Section = Sections[SectionIndex]; 933b7c62394SSam Clegg uint32_t RelocCount = readVaruint32(Ctx); 9346f08c84aSSam Clegg uint32_t EndOffset = Section.Content.size(); 935f77dc2a8SSam Clegg uint32_t PreviousOffset = 0; 936d3d84fddSDerek Schuff while (RelocCount--) { 937b3748f71SNicholas Wilson wasm::WasmRelocation Reloc = {}; 938d75b3719SSam Clegg uint32_t type = readVaruint32(Ctx); 939d75b3719SSam Clegg Reloc.Type = type; 940b7c62394SSam Clegg Reloc.Offset = readVaruint32(Ctx); 941f77dc2a8SSam Clegg if (Reloc.Offset < PreviousOffset) 94284c6f325SSam Clegg return make_error<GenericBinaryError>("relocations not in offset order", 943f77dc2a8SSam Clegg object_error::parse_failed); 944f77dc2a8SSam Clegg PreviousOffset = Reloc.Offset; 945b7c62394SSam Clegg Reloc.Index = readVaruint32(Ctx); 946d75b3719SSam Clegg switch (type) { 947d1152a26SSam Clegg case wasm::R_WASM_FUNCTION_INDEX_LEB: 948d1152a26SSam Clegg case wasm::R_WASM_TABLE_INDEX_SLEB: 949cc1b9b68SWouter van Oortmerssen case wasm::R_WASM_TABLE_INDEX_SLEB64: 950d1152a26SSam Clegg case wasm::R_WASM_TABLE_INDEX_I32: 951cc1b9b68SWouter van Oortmerssen case wasm::R_WASM_TABLE_INDEX_I64: 9522a7cac93SSam Clegg case wasm::R_WASM_TABLE_INDEX_REL_SLEB: 9533a293cbfSWouter van Oortmerssen case wasm::R_WASM_TABLE_INDEX_REL_SLEB64: 954b3748f71SNicholas Wilson if (!isValidFunctionSymbol(Reloc.Index)) 95584c6f325SSam Clegg return make_error<GenericBinaryError>( 95684c6f325SSam Clegg "invalid relocation function index", object_error::parse_failed); 957b3748f71SNicholas Wilson break; 95869e2797eSPaulo Matos case wasm::R_WASM_TABLE_NUMBER_LEB: 95969e2797eSPaulo Matos if (!isValidTableSymbol(Reloc.Index)) 96084c6f325SSam Clegg return make_error<GenericBinaryError>("invalid relocation table index", 96169e2797eSPaulo Matos object_error::parse_failed); 96269e2797eSPaulo Matos break; 963d1152a26SSam Clegg case wasm::R_WASM_TYPE_INDEX_LEB: 964b3748f71SNicholas Wilson if (Reloc.Index >= Signatures.size()) 96584c6f325SSam Clegg return make_error<GenericBinaryError>("invalid relocation type index", 966b3748f71SNicholas Wilson object_error::parse_failed); 967b3748f71SNicholas Wilson break; 968d1152a26SSam Clegg case wasm::R_WASM_GLOBAL_INDEX_LEB: 969492f7529SSam Clegg // R_WASM_GLOBAL_INDEX_LEB are can be used against function and data 9707eacefedSDavid Candler // symbols to refer to their GOT entries. 971492f7529SSam Clegg if (!isValidGlobalSymbol(Reloc.Index) && 972492f7529SSam Clegg !isValidDataSymbol(Reloc.Index) && 973492f7529SSam Clegg !isValidFunctionSymbol(Reloc.Index)) 97484c6f325SSam Clegg return make_error<GenericBinaryError>("invalid relocation global index", 975b3748f71SNicholas Wilson object_error::parse_failed); 976d3d84fddSDerek Schuff break; 97748139ebcSWouter van Oortmerssen case wasm::R_WASM_GLOBAL_INDEX_I32: 97848139ebcSWouter van Oortmerssen if (!isValidGlobalSymbol(Reloc.Index)) 97984c6f325SSam Clegg return make_error<GenericBinaryError>("invalid relocation global index", 98048139ebcSWouter van Oortmerssen object_error::parse_failed); 98148139ebcSWouter van Oortmerssen break; 9821d891d44SHeejin Ahn case wasm::R_WASM_TAG_INDEX_LEB: 9831d891d44SHeejin Ahn if (!isValidTagSymbol(Reloc.Index)) 9841d891d44SHeejin Ahn return make_error<GenericBinaryError>("invalid relocation tag index", 985da419bdbSHeejin Ahn object_error::parse_failed); 986da419bdbSHeejin Ahn break; 987d1152a26SSam Clegg case wasm::R_WASM_MEMORY_ADDR_LEB: 988d1152a26SSam Clegg case wasm::R_WASM_MEMORY_ADDR_SLEB: 989d1152a26SSam Clegg case wasm::R_WASM_MEMORY_ADDR_I32: 9902a7cac93SSam Clegg case wasm::R_WASM_MEMORY_ADDR_REL_SLEB: 991a28a4662SSam Clegg case wasm::R_WASM_MEMORY_ADDR_TLS_SLEB: 992aa0c571aSYuta Saito case wasm::R_WASM_MEMORY_ADDR_LOCREL_I32: 993b3748f71SNicholas Wilson if (!isValidDataSymbol(Reloc.Index)) 99484c6f325SSam Clegg return make_error<GenericBinaryError>("invalid relocation data index", 995b3748f71SNicholas Wilson object_error::parse_failed); 996b7c62394SSam Clegg Reloc.Addend = readVarint32(Ctx); 997d3d84fddSDerek Schuff break; 9983b29376eSWouter van Oortmerssen case wasm::R_WASM_MEMORY_ADDR_LEB64: 9993b29376eSWouter van Oortmerssen case wasm::R_WASM_MEMORY_ADDR_SLEB64: 10003b29376eSWouter van Oortmerssen case wasm::R_WASM_MEMORY_ADDR_I64: 10013b29376eSWouter van Oortmerssen case wasm::R_WASM_MEMORY_ADDR_REL_SLEB64: 1002670944fbSWouter van Oortmerssen case wasm::R_WASM_MEMORY_ADDR_TLS_SLEB64: 10033b29376eSWouter van Oortmerssen if (!isValidDataSymbol(Reloc.Index)) 100484c6f325SSam Clegg return make_error<GenericBinaryError>("invalid relocation data index", 10053b29376eSWouter van Oortmerssen object_error::parse_failed); 10063b29376eSWouter van Oortmerssen Reloc.Addend = readVarint64(Ctx); 10073b29376eSWouter van Oortmerssen break; 1008d1152a26SSam Clegg case wasm::R_WASM_FUNCTION_OFFSET_I32: 10096a31a0d6SSam Clegg if (!isValidFunctionSymbol(Reloc.Index)) 101084c6f325SSam Clegg return make_error<GenericBinaryError>( 101184c6f325SSam Clegg "invalid relocation function index", object_error::parse_failed); 1012b7c62394SSam Clegg Reloc.Addend = readVarint32(Ctx); 10136a31a0d6SSam Clegg break; 101416f02431SWouter van Oortmerssen case wasm::R_WASM_FUNCTION_OFFSET_I64: 101516f02431SWouter van Oortmerssen if (!isValidFunctionSymbol(Reloc.Index)) 101684c6f325SSam Clegg return make_error<GenericBinaryError>( 101784c6f325SSam Clegg "invalid relocation function index", object_error::parse_failed); 101816f02431SWouter van Oortmerssen Reloc.Addend = readVarint64(Ctx); 101916f02431SWouter van Oortmerssen break; 1020d1152a26SSam Clegg case wasm::R_WASM_SECTION_OFFSET_I32: 10216a31a0d6SSam Clegg if (!isValidSectionSymbol(Reloc.Index)) 102284c6f325SSam Clegg return make_error<GenericBinaryError>( 102384c6f325SSam Clegg "invalid relocation section index", object_error::parse_failed); 1024b7c62394SSam Clegg Reloc.Addend = readVarint32(Ctx); 10256a31a0d6SSam Clegg break; 1026d3d84fddSDerek Schuff default: 102784c6f325SSam Clegg return make_error<GenericBinaryError>("invalid relocation type: " + 102884c6f325SSam Clegg Twine(type), 102984c6f325SSam Clegg object_error::parse_failed); 1030d3d84fddSDerek Schuff } 1031b3748f71SNicholas Wilson 1032b3748f71SNicholas Wilson // Relocations must fit inside the section, and must appear in order. They 1033b3748f71SNicholas Wilson // also shouldn't overlap a function/element boundary, but we don't bother 1034b3748f71SNicholas Wilson // to check that. 1035b3748f71SNicholas Wilson uint64_t Size = 5; 10363b29376eSWouter van Oortmerssen if (Reloc.Type == wasm::R_WASM_MEMORY_ADDR_LEB64 || 10373b29376eSWouter van Oortmerssen Reloc.Type == wasm::R_WASM_MEMORY_ADDR_SLEB64 || 10383b29376eSWouter van Oortmerssen Reloc.Type == wasm::R_WASM_MEMORY_ADDR_REL_SLEB64) 10393b29376eSWouter van Oortmerssen Size = 10; 1040d1152a26SSam Clegg if (Reloc.Type == wasm::R_WASM_TABLE_INDEX_I32 || 1041d1152a26SSam Clegg Reloc.Type == wasm::R_WASM_MEMORY_ADDR_I32 || 1042aa0c571aSYuta Saito Reloc.Type == wasm::R_WASM_MEMORY_ADDR_LOCREL_I32 || 1043d1152a26SSam Clegg Reloc.Type == wasm::R_WASM_SECTION_OFFSET_I32 || 104448139ebcSWouter van Oortmerssen Reloc.Type == wasm::R_WASM_FUNCTION_OFFSET_I32 || 104548139ebcSWouter van Oortmerssen Reloc.Type == wasm::R_WASM_GLOBAL_INDEX_I32) 1046b3748f71SNicholas Wilson Size = 4; 1047cc1b9b68SWouter van Oortmerssen if (Reloc.Type == wasm::R_WASM_TABLE_INDEX_I64 || 104816f02431SWouter van Oortmerssen Reloc.Type == wasm::R_WASM_MEMORY_ADDR_I64 || 104916f02431SWouter van Oortmerssen Reloc.Type == wasm::R_WASM_FUNCTION_OFFSET_I64) 10503b29376eSWouter van Oortmerssen Size = 8; 1051fa5a04fbSSam Clegg if (Reloc.Offset + Size > EndOffset) 105284c6f325SSam Clegg return make_error<GenericBinaryError>("invalid relocation offset", 1053b3748f71SNicholas Wilson object_error::parse_failed); 1054b3748f71SNicholas Wilson 10556f08c84aSSam Clegg Section.Relocations.push_back(Reloc); 1056d3d84fddSDerek Schuff } 1057b7c62394SSam Clegg if (Ctx.Ptr != Ctx.End) 105884c6f325SSam Clegg return make_error<GenericBinaryError>("reloc section ended prematurely", 1059d3d84fddSDerek Schuff object_error::parse_failed); 1060d3d84fddSDerek Schuff return Error::success(); 1061d3d84fddSDerek Schuff } 1062d3d84fddSDerek Schuff 1063b7c62394SSam Clegg Error WasmObjectFile::parseCustomSection(WasmSection &Sec, ReadContext &Ctx) { 1064e4afbc68SSam Clegg if (Sec.Name == "dylink") { 1065e4afbc68SSam Clegg if (Error Err = parseDylinkSection(Ctx)) 1066e4afbc68SSam Clegg return Err; 1067b78c85a4SSam Clegg } else if (Sec.Name == "dylink.0") { 1068b78c85a4SSam Clegg if (Error Err = parseDylink0Section(Ctx)) 1069b78c85a4SSam Clegg return Err; 1070e4afbc68SSam Clegg } else if (Sec.Name == "name") { 1071b7c62394SSam Clegg if (Error Err = parseNameSection(Ctx)) 1072d3d84fddSDerek Schuff return Err; 1073b7787fd0SSam Clegg } else if (Sec.Name == "linking") { 1074b7c62394SSam Clegg if (Error Err = parseLinkingSection(Ctx)) 1075b7787fd0SSam Clegg return Err; 1076cbda16ebSThomas Lively } else if (Sec.Name == "producers") { 1077cbda16ebSThomas Lively if (Error Err = parseProducersSection(Ctx)) 1078cbda16ebSThomas Lively return Err; 1079f6f4f843SThomas Lively } else if (Sec.Name == "target_features") { 1080f6f4f843SThomas Lively if (Error Err = parseTargetFeaturesSection(Ctx)) 1081f6f4f843SThomas Lively return Err; 1082d3d84fddSDerek Schuff } else if (Sec.Name.startswith("reloc.")) { 1083b7c62394SSam Clegg if (Error Err = parseRelocSection(Sec.Name, Ctx)) 1084d3d84fddSDerek Schuff return Err; 1085d3d84fddSDerek Schuff } 1086d3d84fddSDerek Schuff return Error::success(); 1087d3d84fddSDerek Schuff } 1088d3d84fddSDerek Schuff 1089b7c62394SSam Clegg Error WasmObjectFile::parseTypeSection(ReadContext &Ctx) { 1090b7c62394SSam Clegg uint32_t Count = readVaruint32(Ctx); 1091d3d84fddSDerek Schuff Signatures.reserve(Count); 1092d3d84fddSDerek Schuff while (Count--) { 1093d3d84fddSDerek Schuff wasm::WasmSignature Sig; 1094b7c62394SSam Clegg uint8_t Form = readUint8(Ctx); 1095d3d84fddSDerek Schuff if (Form != wasm::WASM_TYPE_FUNC) { 109684c6f325SSam Clegg return make_error<GenericBinaryError>("invalid signature type", 1097d3d84fddSDerek Schuff object_error::parse_failed); 1098d3d84fddSDerek Schuff } 1099b7c62394SSam Clegg uint32_t ParamCount = readVaruint32(Ctx); 110077a7a380SDerek Schuff Sig.Params.reserve(ParamCount); 1101d3d84fddSDerek Schuff while (ParamCount--) { 1102b7c62394SSam Clegg uint32_t ParamType = readUint8(Ctx); 110377a7a380SDerek Schuff Sig.Params.push_back(wasm::ValType(ParamType)); 1104d3d84fddSDerek Schuff } 1105b7c62394SSam Clegg uint32_t ReturnCount = readVaruint32(Ctx); 1106393d0f79SThomas Lively while (ReturnCount--) { 1107393d0f79SThomas Lively uint32_t ReturnType = readUint8(Ctx); 1108393d0f79SThomas Lively Sig.Returns.push_back(wasm::ValType(ReturnType)); 1109d3d84fddSDerek Schuff } 111077a7a380SDerek Schuff Signatures.push_back(std::move(Sig)); 1111d3d84fddSDerek Schuff } 1112b7c62394SSam Clegg if (Ctx.Ptr != Ctx.End) 111384c6f325SSam Clegg return make_error<GenericBinaryError>("type section ended prematurely", 1114d3d84fddSDerek Schuff object_error::parse_failed); 1115d3d84fddSDerek Schuff return Error::success(); 1116d3d84fddSDerek Schuff } 1117d3d84fddSDerek Schuff 1118b7c62394SSam Clegg Error WasmObjectFile::parseImportSection(ReadContext &Ctx) { 1119b7c62394SSam Clegg uint32_t Count = readVaruint32(Ctx); 11203ec1760dSHeejin Ahn uint32_t NumTypes = Signatures.size(); 1121d3d84fddSDerek Schuff Imports.reserve(Count); 112218c56a07SHeejin Ahn for (uint32_t I = 0; I < Count; I++) { 1123d3d84fddSDerek Schuff wasm::WasmImport Im; 1124b7c62394SSam Clegg Im.Module = readString(Ctx); 1125b7c62394SSam Clegg Im.Field = readString(Ctx); 1126b7c62394SSam Clegg Im.Kind = readUint8(Ctx); 1127d3d84fddSDerek Schuff switch (Im.Kind) { 1128d3d84fddSDerek Schuff case wasm::WASM_EXTERNAL_FUNCTION: 1129a3b9fe6aSSam Clegg NumImportedFunctions++; 1130b7c62394SSam Clegg Im.SigIndex = readVaruint32(Ctx); 11313ec1760dSHeejin Ahn if (Im.SigIndex >= NumTypes) 11323ec1760dSHeejin Ahn return make_error<GenericBinaryError>("invalid function type", 11333ec1760dSHeejin Ahn object_error::parse_failed); 1134d3d84fddSDerek Schuff break; 1135d3d84fddSDerek Schuff case wasm::WASM_EXTERNAL_GLOBAL: 1136a3b9fe6aSSam Clegg NumImportedGlobals++; 1137b7c62394SSam Clegg Im.Global.Type = readUint8(Ctx); 1138b7c62394SSam Clegg Im.Global.Mutable = readVaruint1(Ctx); 1139d3d84fddSDerek Schuff break; 11402ffff5afSSam Clegg case wasm::WASM_EXTERNAL_MEMORY: 1141b7c62394SSam Clegg Im.Memory = readLimits(Ctx); 114229f8c9f6SWouter van Oortmerssen if (Im.Memory.Flags & wasm::WASM_LIMITS_FLAG_IS_64) 114329f8c9f6SWouter van Oortmerssen HasMemory64 = true; 11442ffff5afSSam Clegg break; 1145388fb67bSPaulo Matos case wasm::WASM_EXTERNAL_TABLE: { 11461933c9d4SAndy Wingo Im.Table = readTableType(Ctx); 1147388fb67bSPaulo Matos NumImportedTables++; 1148388fb67bSPaulo Matos auto ElemType = Im.Table.ElemType; 1149388fb67bSPaulo Matos if (ElemType != wasm::WASM_TYPE_FUNCREF && 1150388fb67bSPaulo Matos ElemType != wasm::WASM_TYPE_EXTERNREF) 115184c6f325SSam Clegg return make_error<GenericBinaryError>("invalid table element type", 11522ffff5afSSam Clegg object_error::parse_failed); 11532ffff5afSSam Clegg break; 1154388fb67bSPaulo Matos } 11551d891d44SHeejin Ahn case wasm::WASM_EXTERNAL_TAG: 11561d891d44SHeejin Ahn NumImportedTags++; 11579261ee32SHeejin Ahn if (readUint8(Ctx) != 0) // Reserved 'attribute' field 11589261ee32SHeejin Ahn return make_error<GenericBinaryError>("invalid attribute", 11599261ee32SHeejin Ahn object_error::parse_failed); 11603ec1760dSHeejin Ahn Im.SigIndex = readVaruint32(Ctx); 11613ec1760dSHeejin Ahn if (Im.SigIndex >= NumTypes) 11623ec1760dSHeejin Ahn return make_error<GenericBinaryError>("invalid tag type", 11633ec1760dSHeejin Ahn object_error::parse_failed); 1164da419bdbSHeejin Ahn break; 1165d3d84fddSDerek Schuff default: 116684c6f325SSam Clegg return make_error<GenericBinaryError>("unexpected import kind", 1167f208f631SHeejin Ahn object_error::parse_failed); 1168d3d84fddSDerek Schuff } 1169d3d84fddSDerek Schuff Imports.push_back(Im); 1170d3d84fddSDerek Schuff } 1171b7c62394SSam Clegg if (Ctx.Ptr != Ctx.End) 117284c6f325SSam Clegg return make_error<GenericBinaryError>("import section ended prematurely", 1173d3d84fddSDerek Schuff object_error::parse_failed); 1174d3d84fddSDerek Schuff return Error::success(); 1175d3d84fddSDerek Schuff } 1176d3d84fddSDerek Schuff 1177b7c62394SSam Clegg Error WasmObjectFile::parseFunctionSection(ReadContext &Ctx) { 1178b7c62394SSam Clegg uint32_t Count = readVaruint32(Ctx); 1179c0039de2SSam Clegg Functions.reserve(Count); 11803b825105SNicholas Wilson uint32_t NumTypes = Signatures.size(); 1181d3d84fddSDerek Schuff while (Count--) { 1182b7c62394SSam Clegg uint32_t Type = readVaruint32(Ctx); 11833b825105SNicholas Wilson if (Type >= NumTypes) 118484c6f325SSam Clegg return make_error<GenericBinaryError>("invalid function type", 11853b825105SNicholas Wilson object_error::parse_failed); 1186c0039de2SSam Clegg wasm::WasmFunction F; 1187c0039de2SSam Clegg F.SigIndex = Type; 1188c0039de2SSam Clegg Functions.push_back(F); 1189d3d84fddSDerek Schuff } 1190b7c62394SSam Clegg if (Ctx.Ptr != Ctx.End) 119184c6f325SSam Clegg return make_error<GenericBinaryError>("function section ended prematurely", 1192d3d84fddSDerek Schuff object_error::parse_failed); 1193d3d84fddSDerek Schuff return Error::success(); 1194d3d84fddSDerek Schuff } 1195d3d84fddSDerek Schuff 1196b7c62394SSam Clegg Error WasmObjectFile::parseTableSection(ReadContext &Ctx) { 1197feac819eSAndy Wingo TableSection = Sections.size(); 1198b7c62394SSam Clegg uint32_t Count = readVaruint32(Ctx); 1199d3d84fddSDerek Schuff Tables.reserve(Count); 1200d3d84fddSDerek Schuff while (Count--) { 12011933c9d4SAndy Wingo wasm::WasmTable T; 12021933c9d4SAndy Wingo T.Type = readTableType(Ctx); 1203388fb67bSPaulo Matos T.Index = NumImportedTables + Tables.size(); 1204388fb67bSPaulo Matos Tables.push_back(T); 12051933c9d4SAndy Wingo auto ElemType = Tables.back().Type.ElemType; 1206388fb67bSPaulo Matos if (ElemType != wasm::WASM_TYPE_FUNCREF && 1207388fb67bSPaulo Matos ElemType != wasm::WASM_TYPE_EXTERNREF) { 120884c6f325SSam Clegg return make_error<GenericBinaryError>("invalid table element type", 1209d3d84fddSDerek Schuff object_error::parse_failed); 1210d3d84fddSDerek Schuff } 1211d3d84fddSDerek Schuff } 1212b7c62394SSam Clegg if (Ctx.Ptr != Ctx.End) 121384c6f325SSam Clegg return make_error<GenericBinaryError>("table section ended prematurely", 1214d3d84fddSDerek Schuff object_error::parse_failed); 1215d3d84fddSDerek Schuff return Error::success(); 1216d3d84fddSDerek Schuff } 1217d3d84fddSDerek Schuff 1218b7c62394SSam Clegg Error WasmObjectFile::parseMemorySection(ReadContext &Ctx) { 1219b7c62394SSam Clegg uint32_t Count = readVaruint32(Ctx); 1220d3d84fddSDerek Schuff Memories.reserve(Count); 1221d3d84fddSDerek Schuff while (Count--) { 122229f8c9f6SWouter van Oortmerssen auto Limits = readLimits(Ctx); 122329f8c9f6SWouter van Oortmerssen if (Limits.Flags & wasm::WASM_LIMITS_FLAG_IS_64) 122429f8c9f6SWouter van Oortmerssen HasMemory64 = true; 122529f8c9f6SWouter van Oortmerssen Memories.push_back(Limits); 1226d3d84fddSDerek Schuff } 1227b7c62394SSam Clegg if (Ctx.Ptr != Ctx.End) 122884c6f325SSam Clegg return make_error<GenericBinaryError>("memory section ended prematurely", 1229d3d84fddSDerek Schuff object_error::parse_failed); 1230d3d84fddSDerek Schuff return Error::success(); 1231d3d84fddSDerek Schuff } 1232d3d84fddSDerek Schuff 12331d891d44SHeejin Ahn Error WasmObjectFile::parseTagSection(ReadContext &Ctx) { 12341d891d44SHeejin Ahn TagSection = Sections.size(); 1235144ec1c3SHeejin Ahn uint32_t Count = readVaruint32(Ctx); 12361d891d44SHeejin Ahn Tags.reserve(Count); 12373ec1760dSHeejin Ahn uint32_t NumTypes = Signatures.size(); 1238f93426c5SHeejin Ahn while (Count--) { 12399261ee32SHeejin Ahn if (readUint8(Ctx) != 0) // Reserved 'attribute' field 12403ec1760dSHeejin Ahn return make_error<GenericBinaryError>("invalid attribute", 12413ec1760dSHeejin Ahn object_error::parse_failed); 12423ec1760dSHeejin Ahn uint32_t Type = readVaruint32(Ctx); 12433ec1760dSHeejin Ahn if (Type >= NumTypes) 12443ec1760dSHeejin Ahn return make_error<GenericBinaryError>("invalid tag type", 12453ec1760dSHeejin Ahn object_error::parse_failed); 12461d891d44SHeejin Ahn wasm::WasmTag Tag; 12471d891d44SHeejin Ahn Tag.Index = NumImportedTags + Tags.size(); 12483ec1760dSHeejin Ahn Tag.SigIndex = Type; 12491d891d44SHeejin Ahn Tags.push_back(Tag); 1250f93426c5SHeejin Ahn } 1251f93426c5SHeejin Ahn 1252f93426c5SHeejin Ahn if (Ctx.Ptr != Ctx.End) 12531d891d44SHeejin Ahn return make_error<GenericBinaryError>("tag section ended prematurely", 1254f93426c5SHeejin Ahn object_error::parse_failed); 1255f93426c5SHeejin Ahn return Error::success(); 1256f93426c5SHeejin Ahn } 1257f93426c5SHeejin Ahn 1258b7c62394SSam Clegg Error WasmObjectFile::parseGlobalSection(ReadContext &Ctx) { 12596c899ba6SSam Clegg GlobalSection = Sections.size(); 1260b7c62394SSam Clegg uint32_t Count = readVaruint32(Ctx); 1261d3d84fddSDerek Schuff Globals.reserve(Count); 1262d3d84fddSDerek Schuff while (Count--) { 1263d3d84fddSDerek Schuff wasm::WasmGlobal Global; 1264e53af7f6SSam Clegg Global.Index = NumImportedGlobals + Globals.size(); 1265b7c62394SSam Clegg Global.Type.Type = readUint8(Ctx); 1266b7c62394SSam Clegg Global.Type.Mutable = readVaruint1(Ctx); 1267b7c62394SSam Clegg if (Error Err = readInitExpr(Global.InitExpr, Ctx)) 1268d3d84fddSDerek Schuff return Err; 1269d3d84fddSDerek Schuff Globals.push_back(Global); 1270d3d84fddSDerek Schuff } 1271b7c62394SSam Clegg if (Ctx.Ptr != Ctx.End) 127284c6f325SSam Clegg return make_error<GenericBinaryError>("global section ended prematurely", 1273d3d84fddSDerek Schuff object_error::parse_failed); 1274d3d84fddSDerek Schuff return Error::success(); 1275d3d84fddSDerek Schuff } 1276d3d84fddSDerek Schuff 1277b7c62394SSam Clegg Error WasmObjectFile::parseExportSection(ReadContext &Ctx) { 1278b7c62394SSam Clegg uint32_t Count = readVaruint32(Ctx); 1279d3d84fddSDerek Schuff Exports.reserve(Count); 128018c56a07SHeejin Ahn for (uint32_t I = 0; I < Count; I++) { 1281d3d84fddSDerek Schuff wasm::WasmExport Ex; 1282b7c62394SSam Clegg Ex.Name = readString(Ctx); 1283b7c62394SSam Clegg Ex.Kind = readUint8(Ctx); 1284b7c62394SSam Clegg Ex.Index = readVaruint32(Ctx); 1285d3d84fddSDerek Schuff switch (Ex.Kind) { 1286d3d84fddSDerek Schuff case wasm::WASM_EXTERNAL_FUNCTION: 1287881d8778SSam Clegg 1288881d8778SSam Clegg if (!isDefinedFunctionIndex(Ex.Index)) 128984c6f325SSam Clegg return make_error<GenericBinaryError>("invalid function export", 1290a3b9fe6aSSam Clegg object_error::parse_failed); 1291881d8778SSam Clegg getDefinedFunction(Ex.Index).ExportName = Ex.Name; 1292d3d84fddSDerek Schuff break; 12936c899ba6SSam Clegg case wasm::WASM_EXTERNAL_GLOBAL: 12946c899ba6SSam Clegg if (!isValidGlobalIndex(Ex.Index)) 129584c6f325SSam Clegg return make_error<GenericBinaryError>("invalid global export", 1296a3b9fe6aSSam Clegg object_error::parse_failed); 1297d3d84fddSDerek Schuff break; 12981d891d44SHeejin Ahn case wasm::WASM_EXTERNAL_TAG: 12991d891d44SHeejin Ahn if (!isValidTagIndex(Ex.Index)) 13001d891d44SHeejin Ahn return make_error<GenericBinaryError>("invalid tag export", 1301da419bdbSHeejin Ahn object_error::parse_failed); 1302da419bdbSHeejin Ahn break; 13032ffff5afSSam Clegg case wasm::WASM_EXTERNAL_MEMORY: 13042ffff5afSSam Clegg case wasm::WASM_EXTERNAL_TABLE: 13052ffff5afSSam Clegg break; 1306d3d84fddSDerek Schuff default: 130784c6f325SSam Clegg return make_error<GenericBinaryError>("unexpected export kind", 1308f208f631SHeejin Ahn object_error::parse_failed); 1309d3d84fddSDerek Schuff } 1310b7787fd0SSam Clegg Exports.push_back(Ex); 1311d3d84fddSDerek Schuff } 1312b7c62394SSam Clegg if (Ctx.Ptr != Ctx.End) 131384c6f325SSam Clegg return make_error<GenericBinaryError>("export section ended prematurely", 1314d3d84fddSDerek Schuff object_error::parse_failed); 1315d3d84fddSDerek Schuff return Error::success(); 1316d3d84fddSDerek Schuff } 1317d3d84fddSDerek Schuff 13184273998cSSam Clegg bool WasmObjectFile::isValidFunctionIndex(uint32_t Index) const { 1319c0039de2SSam Clegg return Index < NumImportedFunctions + Functions.size(); 13204273998cSSam Clegg } 13214273998cSSam Clegg 132223012e98SSam Clegg bool WasmObjectFile::isDefinedFunctionIndex(uint32_t Index) const { 132323012e98SSam Clegg return Index >= NumImportedFunctions && isValidFunctionIndex(Index); 132423012e98SSam Clegg } 132523012e98SSam Clegg 13266c899ba6SSam Clegg bool WasmObjectFile::isValidGlobalIndex(uint32_t Index) const { 13276c899ba6SSam Clegg return Index < NumImportedGlobals + Globals.size(); 13286c899ba6SSam Clegg } 13296c899ba6SSam Clegg 1330a5a3659dSAndy Wingo bool WasmObjectFile::isValidTableNumber(uint32_t Index) const { 1331388fb67bSPaulo Matos return Index < NumImportedTables + Tables.size(); 1332388fb67bSPaulo Matos } 1333388fb67bSPaulo Matos 13346c899ba6SSam Clegg bool WasmObjectFile::isDefinedGlobalIndex(uint32_t Index) const { 13356c899ba6SSam Clegg return Index >= NumImportedGlobals && isValidGlobalIndex(Index); 13366c899ba6SSam Clegg } 13376c899ba6SSam Clegg 1338a5a3659dSAndy Wingo bool WasmObjectFile::isDefinedTableNumber(uint32_t Index) const { 1339a5a3659dSAndy Wingo return Index >= NumImportedTables && isValidTableNumber(Index); 1340388fb67bSPaulo Matos } 1341388fb67bSPaulo Matos 13421d891d44SHeejin Ahn bool WasmObjectFile::isValidTagIndex(uint32_t Index) const { 13431d891d44SHeejin Ahn return Index < NumImportedTags + Tags.size(); 1344da419bdbSHeejin Ahn } 1345da419bdbSHeejin Ahn 13461d891d44SHeejin Ahn bool WasmObjectFile::isDefinedTagIndex(uint32_t Index) const { 13471d891d44SHeejin Ahn return Index >= NumImportedTags && isValidTagIndex(Index); 1348da419bdbSHeejin Ahn } 1349da419bdbSHeejin Ahn 1350b3748f71SNicholas Wilson bool WasmObjectFile::isValidFunctionSymbol(uint32_t Index) const { 13516c899ba6SSam Clegg return Index < Symbols.size() && Symbols[Index].isTypeFunction(); 13526c899ba6SSam Clegg } 13536c899ba6SSam Clegg 135469e2797eSPaulo Matos bool WasmObjectFile::isValidTableSymbol(uint32_t Index) const { 135569e2797eSPaulo Matos return Index < Symbols.size() && Symbols[Index].isTypeTable(); 135669e2797eSPaulo Matos } 135769e2797eSPaulo Matos 1358b3748f71SNicholas Wilson bool WasmObjectFile::isValidGlobalSymbol(uint32_t Index) const { 1359b3748f71SNicholas Wilson return Index < Symbols.size() && Symbols[Index].isTypeGlobal(); 1360b3748f71SNicholas Wilson } 1361b3748f71SNicholas Wilson 13621d891d44SHeejin Ahn bool WasmObjectFile::isValidTagSymbol(uint32_t Index) const { 13631d891d44SHeejin Ahn return Index < Symbols.size() && Symbols[Index].isTypeTag(); 1364da419bdbSHeejin Ahn } 1365da419bdbSHeejin Ahn 1366b3748f71SNicholas Wilson bool WasmObjectFile::isValidDataSymbol(uint32_t Index) const { 1367b3748f71SNicholas Wilson return Index < Symbols.size() && Symbols[Index].isTypeData(); 1368b3748f71SNicholas Wilson } 1369b3748f71SNicholas Wilson 13706a31a0d6SSam Clegg bool WasmObjectFile::isValidSectionSymbol(uint32_t Index) const { 13716a31a0d6SSam Clegg return Index < Symbols.size() && Symbols[Index].isTypeSection(); 13726a31a0d6SSam Clegg } 13736a31a0d6SSam Clegg 137423012e98SSam Clegg wasm::WasmFunction &WasmObjectFile::getDefinedFunction(uint32_t Index) { 137523012e98SSam Clegg assert(isDefinedFunctionIndex(Index)); 137623012e98SSam Clegg return Functions[Index - NumImportedFunctions]; 137723012e98SSam Clegg } 137823012e98SSam Clegg 1379f3b762a0SWouter van Oortmerssen const wasm::WasmFunction & 1380f3b762a0SWouter van Oortmerssen WasmObjectFile::getDefinedFunction(uint32_t Index) const { 1381f3b762a0SWouter van Oortmerssen assert(isDefinedFunctionIndex(Index)); 1382f3b762a0SWouter van Oortmerssen return Functions[Index - NumImportedFunctions]; 1383f3b762a0SWouter van Oortmerssen } 1384f3b762a0SWouter van Oortmerssen 13856c899ba6SSam Clegg wasm::WasmGlobal &WasmObjectFile::getDefinedGlobal(uint32_t Index) { 13866c899ba6SSam Clegg assert(isDefinedGlobalIndex(Index)); 13876c899ba6SSam Clegg return Globals[Index - NumImportedGlobals]; 13886c899ba6SSam Clegg } 13896c899ba6SSam Clegg 13901d891d44SHeejin Ahn wasm::WasmTag &WasmObjectFile::getDefinedTag(uint32_t Index) { 13911d891d44SHeejin Ahn assert(isDefinedTagIndex(Index)); 13921d891d44SHeejin Ahn return Tags[Index - NumImportedTags]; 1393da419bdbSHeejin Ahn } 1394da419bdbSHeejin Ahn 1395b7c62394SSam Clegg Error WasmObjectFile::parseStartSection(ReadContext &Ctx) { 1396b7c62394SSam Clegg StartFunction = readVaruint32(Ctx); 13974273998cSSam Clegg if (!isValidFunctionIndex(StartFunction)) 139884c6f325SSam Clegg return make_error<GenericBinaryError>("invalid start function", 1399d3d84fddSDerek Schuff object_error::parse_failed); 1400d3d84fddSDerek Schuff return Error::success(); 1401d3d84fddSDerek Schuff } 1402d3d84fddSDerek Schuff 1403b7c62394SSam Clegg Error WasmObjectFile::parseCodeSection(ReadContext &Ctx) { 14040b55ccf6SSam Clegg CodeSection = Sections.size(); 1405b7c62394SSam Clegg uint32_t FunctionCount = readVaruint32(Ctx); 1406c0039de2SSam Clegg if (FunctionCount != Functions.size()) { 140784c6f325SSam Clegg return make_error<GenericBinaryError>("invalid function count", 1408d3d84fddSDerek Schuff object_error::parse_failed); 1409d3d84fddSDerek Schuff } 1410d3d84fddSDerek Schuff 1411881d8778SSam Clegg for (uint32_t i = 0; i < FunctionCount; i++) { 1412881d8778SSam Clegg wasm::WasmFunction& Function = Functions[i]; 1413b7c62394SSam Clegg const uint8_t *FunctionStart = Ctx.Ptr; 1414b7c62394SSam Clegg uint32_t Size = readVaruint32(Ctx); 1415b7c62394SSam Clegg const uint8_t *FunctionEnd = Ctx.Ptr + Size; 1416c551522dSSam Clegg 1417b7c62394SSam Clegg Function.CodeOffset = Ctx.Ptr - FunctionStart; 1418881d8778SSam Clegg Function.Index = NumImportedFunctions + i; 1419b7c62394SSam Clegg Function.CodeSectionOffset = FunctionStart - Ctx.Start; 1420c551522dSSam Clegg Function.Size = FunctionEnd - FunctionStart; 1421d3d84fddSDerek Schuff 1422b7c62394SSam Clegg uint32_t NumLocalDecls = readVaruint32(Ctx); 1423d3d84fddSDerek Schuff Function.Locals.reserve(NumLocalDecls); 1424d3d84fddSDerek Schuff while (NumLocalDecls--) { 1425d3d84fddSDerek Schuff wasm::WasmLocalDecl Decl; 1426b7c62394SSam Clegg Decl.Count = readVaruint32(Ctx); 1427b7c62394SSam Clegg Decl.Type = readUint8(Ctx); 1428d3d84fddSDerek Schuff Function.Locals.push_back(Decl); 1429d3d84fddSDerek Schuff } 1430d3d84fddSDerek Schuff 1431b7c62394SSam Clegg uint32_t BodySize = FunctionEnd - Ctx.Ptr; 1432b7c62394SSam Clegg Function.Body = ArrayRef<uint8_t>(Ctx.Ptr, BodySize); 1433027b9357SNicholas Wilson // This will be set later when reading in the linking metadata section. 1434027b9357SNicholas Wilson Function.Comdat = UINT32_MAX; 1435b7c62394SSam Clegg Ctx.Ptr += BodySize; 1436b7c62394SSam Clegg assert(Ctx.Ptr == FunctionEnd); 1437d3d84fddSDerek Schuff } 1438b7c62394SSam Clegg if (Ctx.Ptr != Ctx.End) 143984c6f325SSam Clegg return make_error<GenericBinaryError>("code section ended prematurely", 1440d3d84fddSDerek Schuff object_error::parse_failed); 1441d3d84fddSDerek Schuff return Error::success(); 1442d3d84fddSDerek Schuff } 1443d3d84fddSDerek Schuff 1444b7c62394SSam Clegg Error WasmObjectFile::parseElemSection(ReadContext &Ctx) { 1445b7c62394SSam Clegg uint32_t Count = readVaruint32(Ctx); 1446d3d84fddSDerek Schuff ElemSegments.reserve(Count); 1447d3d84fddSDerek Schuff while (Count--) { 1448d3d84fddSDerek Schuff wasm::WasmElemSegment Segment; 1449a5a3659dSAndy Wingo Segment.Flags = readVaruint32(Ctx); 1450a5a3659dSAndy Wingo 1451a5a3659dSAndy Wingo uint32_t SupportedFlags = wasm::WASM_ELEM_SEGMENT_HAS_TABLE_NUMBER | 1452a5a3659dSAndy Wingo wasm::WASM_ELEM_SEGMENT_IS_PASSIVE | 1453a5a3659dSAndy Wingo wasm::WASM_ELEM_SEGMENT_HAS_INIT_EXPRS; 1454a5a3659dSAndy Wingo if (Segment.Flags & ~SupportedFlags) 1455a5a3659dSAndy Wingo return make_error<GenericBinaryError>( 1456a5a3659dSAndy Wingo "Unsupported flags for element segment", object_error::parse_failed); 1457a5a3659dSAndy Wingo 1458a5a3659dSAndy Wingo if (Segment.Flags & wasm::WASM_ELEM_SEGMENT_HAS_TABLE_NUMBER) 1459a5a3659dSAndy Wingo Segment.TableNumber = readVaruint32(Ctx); 1460a5a3659dSAndy Wingo else 1461a5a3659dSAndy Wingo Segment.TableNumber = 0; 1462a5a3659dSAndy Wingo if (!isValidTableNumber(Segment.TableNumber)) 1463a5a3659dSAndy Wingo return make_error<GenericBinaryError>("invalid TableNumber", 1464d3d84fddSDerek Schuff object_error::parse_failed); 1465a5a3659dSAndy Wingo 1466a5a3659dSAndy Wingo if (Segment.Flags & wasm::WASM_ELEM_SEGMENT_IS_PASSIVE) { 14672481adb5SSam Clegg Segment.Offset.Extended = false; 14689504ab32SSam Clegg Segment.Offset.Inst.Opcode = wasm::WASM_OPCODE_I32_CONST; 14699504ab32SSam Clegg Segment.Offset.Inst.Value.Int32 = 0; 1470a5a3659dSAndy Wingo } else { 1471b7c62394SSam Clegg if (Error Err = readInitExpr(Segment.Offset, Ctx)) 1472d3d84fddSDerek Schuff return Err; 1473a5a3659dSAndy Wingo } 1474a5a3659dSAndy Wingo 1475a5a3659dSAndy Wingo if (Segment.Flags & wasm::WASM_ELEM_SEGMENT_MASK_HAS_ELEM_KIND) { 1476a5a3659dSAndy Wingo Segment.ElemKind = readUint8(Ctx); 1477a5a3659dSAndy Wingo if (Segment.Flags & wasm::WASM_ELEM_SEGMENT_HAS_INIT_EXPRS) { 1478a5a3659dSAndy Wingo if (Segment.ElemKind != uint8_t(wasm::ValType::FUNCREF) && 1479a5a3659dSAndy Wingo Segment.ElemKind != uint8_t(wasm::ValType::EXTERNREF)) { 1480a5a3659dSAndy Wingo return make_error<GenericBinaryError>("invalid reference type", 1481a5a3659dSAndy Wingo object_error::parse_failed); 1482a5a3659dSAndy Wingo } 1483a5a3659dSAndy Wingo } else { 1484a5a3659dSAndy Wingo if (Segment.ElemKind != 0) 1485a5a3659dSAndy Wingo return make_error<GenericBinaryError>("invalid elemtype", 1486a5a3659dSAndy Wingo object_error::parse_failed); 1487a5a3659dSAndy Wingo Segment.ElemKind = uint8_t(wasm::ValType::FUNCREF); 1488a5a3659dSAndy Wingo } 1489a5a3659dSAndy Wingo } else { 1490a5a3659dSAndy Wingo Segment.ElemKind = uint8_t(wasm::ValType::FUNCREF); 1491a5a3659dSAndy Wingo } 1492a5a3659dSAndy Wingo 1493a5a3659dSAndy Wingo if (Segment.Flags & wasm::WASM_ELEM_SEGMENT_HAS_INIT_EXPRS) 1494a5a3659dSAndy Wingo return make_error<GenericBinaryError>( 1495a5a3659dSAndy Wingo "elem segment init expressions not yet implemented", 1496a5a3659dSAndy Wingo object_error::parse_failed); 1497a5a3659dSAndy Wingo 1498b7c62394SSam Clegg uint32_t NumElems = readVaruint32(Ctx); 1499d3d84fddSDerek Schuff while (NumElems--) { 1500b7c62394SSam Clegg Segment.Functions.push_back(readVaruint32(Ctx)); 1501d3d84fddSDerek Schuff } 1502d3d84fddSDerek Schuff ElemSegments.push_back(Segment); 1503d3d84fddSDerek Schuff } 1504b7c62394SSam Clegg if (Ctx.Ptr != Ctx.End) 150584c6f325SSam Clegg return make_error<GenericBinaryError>("elem section ended prematurely", 1506d3d84fddSDerek Schuff object_error::parse_failed); 1507d3d84fddSDerek Schuff return Error::success(); 1508d3d84fddSDerek Schuff } 1509d3d84fddSDerek Schuff 1510b7c62394SSam Clegg Error WasmObjectFile::parseDataSection(ReadContext &Ctx) { 15110b55ccf6SSam Clegg DataSection = Sections.size(); 1512b7c62394SSam Clegg uint32_t Count = readVaruint32(Ctx); 15137a47ee51SKazu Hirata if (DataCount && Count != *DataCount) 1514fef8de66SThomas Lively return make_error<GenericBinaryError>( 151584c6f325SSam Clegg "number of data segments does not match DataCount section"); 1516d3d84fddSDerek Schuff DataSegments.reserve(Count); 1517d3d84fddSDerek Schuff while (Count--) { 15189c07f94aSSam Clegg WasmSegment Segment; 15192e150409SThomas Lively Segment.Data.InitFlags = readVaruint32(Ctx); 1520831a143eSAndy Wingo Segment.Data.MemoryIndex = 1521831a143eSAndy Wingo (Segment.Data.InitFlags & wasm::WASM_DATA_SEGMENT_HAS_MEMINDEX) 1522831a143eSAndy Wingo ? readVaruint32(Ctx) 1523831a143eSAndy Wingo : 0; 1524831a143eSAndy Wingo if ((Segment.Data.InitFlags & wasm::WASM_DATA_SEGMENT_IS_PASSIVE) == 0) { 1525b7c62394SSam Clegg if (Error Err = readInitExpr(Segment.Data.Offset, Ctx)) 1526d3d84fddSDerek Schuff return Err; 15272e150409SThomas Lively } else { 15289b27fbd1SSam Clegg Segment.Data.Offset.Extended = false; 15299504ab32SSam Clegg Segment.Data.Offset.Inst.Opcode = wasm::WASM_OPCODE_I32_CONST; 15309504ab32SSam Clegg Segment.Data.Offset.Inst.Value.Int32 = 0; 15312e150409SThomas Lively } 1532b7c62394SSam Clegg uint32_t Size = readVaruint32(Ctx); 1533dcf5bd27SSimon Pilgrim if (Size > (size_t)(Ctx.End - Ctx.Ptr)) 153484c6f325SSam Clegg return make_error<GenericBinaryError>("invalid segment size", 15354bbc6b55SSam Clegg object_error::parse_failed); 1536b7c62394SSam Clegg Segment.Data.Content = ArrayRef<uint8_t>(Ctx.Ptr, Size); 1537027b9357SNicholas Wilson // The rest of these Data fields are set later, when reading in the linking 1538027b9357SNicholas Wilson // metadata section. 153963ebb813SSam Clegg Segment.Data.Alignment = 0; 15403b8d2be5SSam Clegg Segment.Data.LinkingFlags = 0; 1541027b9357SNicholas Wilson Segment.Data.Comdat = UINT32_MAX; 1542b7c62394SSam Clegg Segment.SectionOffset = Ctx.Ptr - Ctx.Start; 1543b7c62394SSam Clegg Ctx.Ptr += Size; 1544d3d84fddSDerek Schuff DataSegments.push_back(Segment); 1545d3d84fddSDerek Schuff } 1546b7c62394SSam Clegg if (Ctx.Ptr != Ctx.End) 154784c6f325SSam Clegg return make_error<GenericBinaryError>("data section ended prematurely", 1548d3d84fddSDerek Schuff object_error::parse_failed); 15492c6f75ddSDerek Schuff return Error::success(); 15502c6f75ddSDerek Schuff } 15512c6f75ddSDerek Schuff 1552fef8de66SThomas Lively Error WasmObjectFile::parseDataCountSection(ReadContext &Ctx) { 1553fef8de66SThomas Lively DataCount = readVaruint32(Ctx); 1554fef8de66SThomas Lively return Error::success(); 1555fef8de66SThomas Lively } 1556fef8de66SThomas Lively 15572c6f75ddSDerek Schuff const wasm::WasmObjectHeader &WasmObjectFile::getHeader() const { 15582c6f75ddSDerek Schuff return Header; 15592c6f75ddSDerek Schuff } 15602c6f75ddSDerek Schuff 15612a193e0dSSam Clegg void WasmObjectFile::moveSymbolNext(DataRefImpl &Symb) const { Symb.d.b++; } 15622c6f75ddSDerek Schuff 1563ac00376aSvgxbj Expected<uint32_t> WasmObjectFile::getSymbolFlags(DataRefImpl Symb) const { 1564fc5b5cd2SSam Clegg uint32_t Result = SymbolRef::SF_None; 1565d3d84fddSDerek Schuff const WasmSymbol &Sym = getWasmSymbol(Symb); 1566fc5b5cd2SSam Clegg 1567d34e60caSNicola Zaghen LLVM_DEBUG(dbgs() << "getSymbolFlags: ptr=" << &Sym << " " << Sym << "\n"); 15686e7f1826SSam Clegg if (Sym.isBindingWeak()) 1569b7787fd0SSam Clegg Result |= SymbolRef::SF_Weak; 15706e7f1826SSam Clegg if (!Sym.isBindingLocal()) 157131a2c809SSam Clegg Result |= SymbolRef::SF_Global; 1572a2b35dacSSam Clegg if (Sym.isHidden()) 1573a2b35dacSSam Clegg Result |= SymbolRef::SF_Hidden; 15746c899ba6SSam Clegg if (!Sym.isDefined()) 1575fc5b5cd2SSam Clegg Result |= SymbolRef::SF_Undefined; 15766c899ba6SSam Clegg if (Sym.isTypeFunction()) 15776c899ba6SSam Clegg Result |= SymbolRef::SF_Executable; 1578fc5b5cd2SSam Clegg return Result; 15792c6f75ddSDerek Schuff } 15802c6f75ddSDerek Schuff 15812c6f75ddSDerek Schuff basic_symbol_iterator WasmObjectFile::symbol_begin() const { 1582d3d84fddSDerek Schuff DataRefImpl Ref; 15832a193e0dSSam Clegg Ref.d.a = 1; // Arbitrary non-zero value so that Ref.p is non-null 15842a193e0dSSam Clegg Ref.d.b = 0; // Symbol index 1585d3d84fddSDerek Schuff return BasicSymbolRef(Ref, this); 15862c6f75ddSDerek Schuff } 15872c6f75ddSDerek Schuff 15882c6f75ddSDerek Schuff basic_symbol_iterator WasmObjectFile::symbol_end() const { 1589d3d84fddSDerek Schuff DataRefImpl Ref; 15902a193e0dSSam Clegg Ref.d.a = 1; // Arbitrary non-zero value so that Ref.p is non-null 15912a193e0dSSam Clegg Ref.d.b = Symbols.size(); // Symbol index 1592d3d84fddSDerek Schuff return BasicSymbolRef(Ref, this); 1593d3d84fddSDerek Schuff } 1594d3d84fddSDerek Schuff 15952ffff5afSSam Clegg const WasmSymbol &WasmObjectFile::getWasmSymbol(const DataRefImpl &Symb) const { 15962a193e0dSSam Clegg return Symbols[Symb.d.b]; 15972c6f75ddSDerek Schuff } 15982c6f75ddSDerek Schuff 15992ffff5afSSam Clegg const WasmSymbol &WasmObjectFile::getWasmSymbol(const SymbolRef &Symb) const { 16002ffff5afSSam Clegg return getWasmSymbol(Symb.getRawDataRefImpl()); 16012ffff5afSSam Clegg } 16022ffff5afSSam Clegg 16032c6f75ddSDerek Schuff Expected<StringRef> WasmObjectFile::getSymbolName(DataRefImpl Symb) const { 16046c899ba6SSam Clegg return getWasmSymbol(Symb).Info.Name; 16052c6f75ddSDerek Schuff } 16062c6f75ddSDerek Schuff 16072c6f75ddSDerek Schuff Expected<uint64_t> WasmObjectFile::getSymbolAddress(DataRefImpl Symb) const { 1608f3b762a0SWouter van Oortmerssen auto &Sym = getWasmSymbol(Symb); 1609f3b762a0SWouter van Oortmerssen if (Sym.Info.Kind == wasm::WASM_SYMBOL_TYPE_FUNCTION && 1610f3b762a0SWouter van Oortmerssen isDefinedFunctionIndex(Sym.Info.ElementIndex)) 1611f3b762a0SWouter van Oortmerssen return getDefinedFunction(Sym.Info.ElementIndex).CodeSectionOffset; 1612f3b762a0SWouter van Oortmerssen else 1613fc5b5cd2SSam Clegg return getSymbolValue(Symb); 16142c6f75ddSDerek Schuff } 16152c6f75ddSDerek Schuff 161631a2c809SSam Clegg uint64_t WasmObjectFile::getWasmSymbolValue(const WasmSymbol &Sym) const { 16176c899ba6SSam Clegg switch (Sym.Info.Kind) { 16186c899ba6SSam Clegg case wasm::WASM_SYMBOL_TYPE_FUNCTION: 16196c899ba6SSam Clegg case wasm::WASM_SYMBOL_TYPE_GLOBAL: 16201d891d44SHeejin Ahn case wasm::WASM_SYMBOL_TYPE_TAG: 1621feac819eSAndy Wingo case wasm::WASM_SYMBOL_TYPE_TABLE: 16226c899ba6SSam Clegg return Sym.Info.ElementIndex; 16236c899ba6SSam Clegg case wasm::WASM_SYMBOL_TYPE_DATA: { 16246c899ba6SSam Clegg // The value of a data symbol is the segment offset, plus the symbol 16256c899ba6SSam Clegg // offset within the segment. 16266c899ba6SSam Clegg uint32_t SegmentIndex = Sym.Info.DataRef.Segment; 16276c899ba6SSam Clegg const wasm::WasmDataSegment &Segment = DataSegments[SegmentIndex].Data; 16289504ab32SSam Clegg if (Segment.Offset.Extended) { 16299504ab32SSam Clegg llvm_unreachable("extended init exprs not supported"); 16309504ab32SSam Clegg } else if (Segment.Offset.Inst.Opcode == wasm::WASM_OPCODE_I32_CONST) { 16319504ab32SSam Clegg return Segment.Offset.Inst.Value.Int32 + Sym.Info.DataRef.Offset; 16329504ab32SSam Clegg } else if (Segment.Offset.Inst.Opcode == wasm::WASM_OPCODE_I64_CONST) { 16339504ab32SSam Clegg return Segment.Offset.Inst.Value.Int64 + Sym.Info.DataRef.Offset; 16343b29376eSWouter van Oortmerssen } else { 16353b29376eSWouter van Oortmerssen llvm_unreachable("unknown init expr opcode"); 16363b29376eSWouter van Oortmerssen } 1637b09cfa51SSam Clegg } 16386a31a0d6SSam Clegg case wasm::WASM_SYMBOL_TYPE_SECTION: 16396a31a0d6SSam Clegg return 0; 16402c6f75ddSDerek Schuff } 16417f055deeSSam Clegg llvm_unreachable("invalid symbol type"); 1642b7787fd0SSam Clegg } 16432c6f75ddSDerek Schuff 164431a2c809SSam Clegg uint64_t WasmObjectFile::getSymbolValueImpl(DataRefImpl Symb) const { 164531a2c809SSam Clegg return getWasmSymbolValue(getWasmSymbol(Symb)); 164631a2c809SSam Clegg } 164731a2c809SSam Clegg 16482c6f75ddSDerek Schuff uint32_t WasmObjectFile::getSymbolAlignment(DataRefImpl Symb) const { 16492c6f75ddSDerek Schuff llvm_unreachable("not yet implemented"); 16502c6f75ddSDerek Schuff return 0; 16512c6f75ddSDerek Schuff } 16522c6f75ddSDerek Schuff 16532c6f75ddSDerek Schuff uint64_t WasmObjectFile::getCommonSymbolSizeImpl(DataRefImpl Symb) const { 16542c6f75ddSDerek Schuff llvm_unreachable("not yet implemented"); 16552c6f75ddSDerek Schuff return 0; 16562c6f75ddSDerek Schuff } 16572c6f75ddSDerek Schuff 16582c6f75ddSDerek Schuff Expected<SymbolRef::Type> 16592c6f75ddSDerek Schuff WasmObjectFile::getSymbolType(DataRefImpl Symb) const { 1660fc5b5cd2SSam Clegg const WasmSymbol &Sym = getWasmSymbol(Symb); 1661fc5b5cd2SSam Clegg 16626c899ba6SSam Clegg switch (Sym.Info.Kind) { 16636c899ba6SSam Clegg case wasm::WASM_SYMBOL_TYPE_FUNCTION: 1664fc5b5cd2SSam Clegg return SymbolRef::ST_Function; 16656c899ba6SSam Clegg case wasm::WASM_SYMBOL_TYPE_GLOBAL: 16666c899ba6SSam Clegg return SymbolRef::ST_Other; 16676c899ba6SSam Clegg case wasm::WASM_SYMBOL_TYPE_DATA: 1668fc5b5cd2SSam Clegg return SymbolRef::ST_Data; 16696a31a0d6SSam Clegg case wasm::WASM_SYMBOL_TYPE_SECTION: 16706a31a0d6SSam Clegg return SymbolRef::ST_Debug; 16711d891d44SHeejin Ahn case wasm::WASM_SYMBOL_TYPE_TAG: 1672da419bdbSHeejin Ahn return SymbolRef::ST_Other; 1673feac819eSAndy Wingo case wasm::WASM_SYMBOL_TYPE_TABLE: 1674feac819eSAndy Wingo return SymbolRef::ST_Other; 1675fc5b5cd2SSam Clegg } 1676fc5b5cd2SSam Clegg 167784c6f325SSam Clegg llvm_unreachable("unknown WasmSymbol::SymbolType"); 1678fc5b5cd2SSam Clegg return SymbolRef::ST_Other; 16792c6f75ddSDerek Schuff } 16802c6f75ddSDerek Schuff 16812c6f75ddSDerek Schuff Expected<section_iterator> 16822c6f75ddSDerek Schuff WasmObjectFile::getSymbolSection(DataRefImpl Symb) const { 16830b55ccf6SSam Clegg const WasmSymbol &Sym = getWasmSymbol(Symb); 16846c899ba6SSam Clegg if (Sym.isUndefined()) 16850b55ccf6SSam Clegg return section_end(); 16866c899ba6SSam Clegg 16876c899ba6SSam Clegg DataRefImpl Ref; 1688da6a896eSDerek Schuff Ref.d.a = getSymbolSectionIdImpl(Sym); 1689da6a896eSDerek Schuff return section_iterator(SectionRef(Ref, this)); 1690da6a896eSDerek Schuff } 1691da6a896eSDerek Schuff 1692da6a896eSDerek Schuff uint32_t WasmObjectFile::getSymbolSectionId(SymbolRef Symb) const { 1693da6a896eSDerek Schuff const WasmSymbol &Sym = getWasmSymbol(Symb); 1694da6a896eSDerek Schuff return getSymbolSectionIdImpl(Sym); 1695da6a896eSDerek Schuff } 1696da6a896eSDerek Schuff 1697da6a896eSDerek Schuff uint32_t WasmObjectFile::getSymbolSectionIdImpl(const WasmSymbol &Sym) const { 16986c899ba6SSam Clegg switch (Sym.Info.Kind) { 16996c899ba6SSam Clegg case wasm::WASM_SYMBOL_TYPE_FUNCTION: 1700da6a896eSDerek Schuff return CodeSection; 17016c899ba6SSam Clegg case wasm::WASM_SYMBOL_TYPE_GLOBAL: 1702da6a896eSDerek Schuff return GlobalSection; 17036c899ba6SSam Clegg case wasm::WASM_SYMBOL_TYPE_DATA: 1704da6a896eSDerek Schuff return DataSection; 1705da419bdbSHeejin Ahn case wasm::WASM_SYMBOL_TYPE_SECTION: 1706da6a896eSDerek Schuff return Sym.Info.ElementIndex; 17071d891d44SHeejin Ahn case wasm::WASM_SYMBOL_TYPE_TAG: 17081d891d44SHeejin Ahn return TagSection; 1709feac819eSAndy Wingo case wasm::WASM_SYMBOL_TYPE_TABLE: 1710feac819eSAndy Wingo return TableSection; 17116c899ba6SSam Clegg default: 171284c6f325SSam Clegg llvm_unreachable("unknown WasmSymbol::SymbolType"); 17136c899ba6SSam Clegg } 17142c6f75ddSDerek Schuff } 17152c6f75ddSDerek Schuff 17162c6f75ddSDerek Schuff void WasmObjectFile::moveSectionNext(DataRefImpl &Sec) const { Sec.d.a++; } 17172c6f75ddSDerek Schuff 17188be28cdcSFangrui Song Expected<StringRef> WasmObjectFile::getSectionName(DataRefImpl Sec) const { 1719d3d84fddSDerek Schuff const WasmSection &S = Sections[Sec.d.a]; 1720a205f290SDerek Schuff if (S.Type == wasm::WASM_SEC_CUSTOM) 17218be28cdcSFangrui Song return S.Name; 17222ae385e5SDerek Schuff if (S.Type > wasm::WASM_SEC_LAST_KNOWN) 17238be28cdcSFangrui Song return createStringError(object_error::invalid_section_index, ""); 1724a205f290SDerek Schuff return wasm::sectionTypeToString(S.Type); 17252c6f75ddSDerek Schuff } 17262c6f75ddSDerek Schuff 17272c6f75ddSDerek Schuff uint64_t WasmObjectFile::getSectionAddress(DataRefImpl Sec) const { return 0; } 17282c6f75ddSDerek Schuff 1729a25d329bSGeorge Rimar uint64_t WasmObjectFile::getSectionIndex(DataRefImpl Sec) const { 1730a25d329bSGeorge Rimar return Sec.d.a; 1731a25d329bSGeorge Rimar } 1732a25d329bSGeorge Rimar 17332c6f75ddSDerek Schuff uint64_t WasmObjectFile::getSectionSize(DataRefImpl Sec) const { 1734d3d84fddSDerek Schuff const WasmSection &S = Sections[Sec.d.a]; 17352c6f75ddSDerek Schuff return S.Content.size(); 17362c6f75ddSDerek Schuff } 17372c6f75ddSDerek Schuff 1738e1cb2c0fSFangrui Song Expected<ArrayRef<uint8_t>> 1739e1cb2c0fSFangrui Song WasmObjectFile::getSectionContents(DataRefImpl Sec) const { 1740d3d84fddSDerek Schuff const WasmSection &S = Sections[Sec.d.a]; 17412c6f75ddSDerek Schuff // This will never fail since wasm sections can never be empty (user-sections 17422c6f75ddSDerek Schuff // must have a name and non-user sections each have a defined structure). 1743e1cb2c0fSFangrui Song return S.Content; 17442c6f75ddSDerek Schuff } 17452c6f75ddSDerek Schuff 17462c6f75ddSDerek Schuff uint64_t WasmObjectFile::getSectionAlignment(DataRefImpl Sec) const { 17472c6f75ddSDerek Schuff return 1; 17482c6f75ddSDerek Schuff } 17492c6f75ddSDerek Schuff 17502c6f75ddSDerek Schuff bool WasmObjectFile::isSectionCompressed(DataRefImpl Sec) const { 17512c6f75ddSDerek Schuff return false; 17522c6f75ddSDerek Schuff } 17532c6f75ddSDerek Schuff 17542c6f75ddSDerek Schuff bool WasmObjectFile::isSectionText(DataRefImpl Sec) const { 1755d3d84fddSDerek Schuff return getWasmSection(Sec).Type == wasm::WASM_SEC_CODE; 17562c6f75ddSDerek Schuff } 17572c6f75ddSDerek Schuff 17582c6f75ddSDerek Schuff bool WasmObjectFile::isSectionData(DataRefImpl Sec) const { 1759d3d84fddSDerek Schuff return getWasmSection(Sec).Type == wasm::WASM_SEC_DATA; 17602c6f75ddSDerek Schuff } 17612c6f75ddSDerek Schuff 17622c6f75ddSDerek Schuff bool WasmObjectFile::isSectionBSS(DataRefImpl Sec) const { return false; } 17632c6f75ddSDerek Schuff 17642c6f75ddSDerek Schuff bool WasmObjectFile::isSectionVirtual(DataRefImpl Sec) const { return false; } 17652c6f75ddSDerek Schuff 1766d3d84fddSDerek Schuff relocation_iterator WasmObjectFile::section_rel_begin(DataRefImpl Ref) const { 1767d3d84fddSDerek Schuff DataRefImpl RelocRef; 1768d3d84fddSDerek Schuff RelocRef.d.a = Ref.d.a; 1769d3d84fddSDerek Schuff RelocRef.d.b = 0; 1770d3d84fddSDerek Schuff return relocation_iterator(RelocationRef(RelocRef, this)); 17712c6f75ddSDerek Schuff } 17722c6f75ddSDerek Schuff 1773d3d84fddSDerek Schuff relocation_iterator WasmObjectFile::section_rel_end(DataRefImpl Ref) const { 1774d3d84fddSDerek Schuff const WasmSection &Sec = getWasmSection(Ref); 1775d3d84fddSDerek Schuff DataRefImpl RelocRef; 1776d3d84fddSDerek Schuff RelocRef.d.a = Ref.d.a; 1777d3d84fddSDerek Schuff RelocRef.d.b = Sec.Relocations.size(); 1778d3d84fddSDerek Schuff return relocation_iterator(RelocationRef(RelocRef, this)); 17792c6f75ddSDerek Schuff } 17802c6f75ddSDerek Schuff 1781f208f631SHeejin Ahn void WasmObjectFile::moveRelocationNext(DataRefImpl &Rel) const { Rel.d.b++; } 17822c6f75ddSDerek Schuff 1783d3d84fddSDerek Schuff uint64_t WasmObjectFile::getRelocationOffset(DataRefImpl Ref) const { 1784d3d84fddSDerek Schuff const wasm::WasmRelocation &Rel = getWasmRelocation(Ref); 1785d3d84fddSDerek Schuff return Rel.Offset; 17862c6f75ddSDerek Schuff } 17872c6f75ddSDerek Schuff 1788f676cdd5SSam Clegg symbol_iterator WasmObjectFile::getRelocationSymbol(DataRefImpl Ref) const { 1789f676cdd5SSam Clegg const wasm::WasmRelocation &Rel = getWasmRelocation(Ref); 1790d1152a26SSam Clegg if (Rel.Type == wasm::R_WASM_TYPE_INDEX_LEB) 1791f676cdd5SSam Clegg return symbol_end(); 1792f676cdd5SSam Clegg DataRefImpl Sym; 1793c7d2e5f1SSam Clegg Sym.d.a = 1; 1794c7d2e5f1SSam Clegg Sym.d.b = Rel.Index; 1795f676cdd5SSam Clegg return symbol_iterator(SymbolRef(Sym, this)); 17962c6f75ddSDerek Schuff } 17972c6f75ddSDerek Schuff 1798d3d84fddSDerek Schuff uint64_t WasmObjectFile::getRelocationType(DataRefImpl Ref) const { 1799d3d84fddSDerek Schuff const wasm::WasmRelocation &Rel = getWasmRelocation(Ref); 1800d3d84fddSDerek Schuff return Rel.Type; 18012c6f75ddSDerek Schuff } 18022c6f75ddSDerek Schuff 18032c6f75ddSDerek Schuff void WasmObjectFile::getRelocationTypeName( 1804d3d84fddSDerek Schuff DataRefImpl Ref, SmallVectorImpl<char> &Result) const { 1805d3d84fddSDerek Schuff const wasm::WasmRelocation &Rel = getWasmRelocation(Ref); 1806d3d84fddSDerek Schuff StringRef Res = "Unknown"; 1807d3d84fddSDerek Schuff 1808d3d84fddSDerek Schuff #define WASM_RELOC(name, value) \ 1809d3d84fddSDerek Schuff case wasm::name: \ 1810d3d84fddSDerek Schuff Res = #name; \ 1811d3d84fddSDerek Schuff break; 1812d3d84fddSDerek Schuff 1813d3d84fddSDerek Schuff switch (Rel.Type) { 1814c5d8bc83SSam Clegg #include "llvm/BinaryFormat/WasmRelocs.def" 1815d3d84fddSDerek Schuff } 1816d3d84fddSDerek Schuff 1817d3d84fddSDerek Schuff #undef WASM_RELOC 1818d3d84fddSDerek Schuff 1819d3d84fddSDerek Schuff Result.append(Res.begin(), Res.end()); 18202c6f75ddSDerek Schuff } 18212c6f75ddSDerek Schuff 18222c6f75ddSDerek Schuff section_iterator WasmObjectFile::section_begin() const { 18232c6f75ddSDerek Schuff DataRefImpl Ref; 18242c6f75ddSDerek Schuff Ref.d.a = 0; 18252c6f75ddSDerek Schuff return section_iterator(SectionRef(Ref, this)); 18262c6f75ddSDerek Schuff } 18272c6f75ddSDerek Schuff 18282c6f75ddSDerek Schuff section_iterator WasmObjectFile::section_end() const { 18292c6f75ddSDerek Schuff DataRefImpl Ref; 18302c6f75ddSDerek Schuff Ref.d.a = Sections.size(); 18312c6f75ddSDerek Schuff return section_iterator(SectionRef(Ref, this)); 18322c6f75ddSDerek Schuff } 18332c6f75ddSDerek Schuff 183429f8c9f6SWouter van Oortmerssen uint8_t WasmObjectFile::getBytesInAddress() const { 183529f8c9f6SWouter van Oortmerssen return HasMemory64 ? 8 : 4; 183629f8c9f6SWouter van Oortmerssen } 18372c6f75ddSDerek Schuff 18382c6f75ddSDerek Schuff StringRef WasmObjectFile::getFileFormatName() const { return "WASM"; } 18392c6f75ddSDerek Schuff 184029f8c9f6SWouter van Oortmerssen Triple::ArchType WasmObjectFile::getArch() const { 184129f8c9f6SWouter van Oortmerssen return HasMemory64 ? Triple::wasm64 : Triple::wasm32; 184229f8c9f6SWouter van Oortmerssen } 18432c6f75ddSDerek Schuff 18442c6f75ddSDerek Schuff SubtargetFeatures WasmObjectFile::getFeatures() const { 18452c6f75ddSDerek Schuff return SubtargetFeatures(); 18462c6f75ddSDerek Schuff } 18472c6f75ddSDerek Schuff 1848f208f631SHeejin Ahn bool WasmObjectFile::isRelocatableObject() const { return HasLinkingSection; } 18492c6f75ddSDerek Schuff 185003801256SSam Clegg bool WasmObjectFile::isSharedObject() const { return HasDylinkSection; } 185103801256SSam Clegg 1852d3d84fddSDerek Schuff const WasmSection &WasmObjectFile::getWasmSection(DataRefImpl Ref) const { 185316fe5822SDavide Italiano assert(Ref.d.a < Sections.size()); 1854d3d84fddSDerek Schuff return Sections[Ref.d.a]; 1855d3d84fddSDerek Schuff } 1856d3d84fddSDerek Schuff 1857d3d84fddSDerek Schuff const WasmSection & 18582c6f75ddSDerek Schuff WasmObjectFile::getWasmSection(const SectionRef &Section) const { 1859d3d84fddSDerek Schuff return getWasmSection(Section.getRawDataRefImpl()); 1860d3d84fddSDerek Schuff } 1861d3d84fddSDerek Schuff 1862d3d84fddSDerek Schuff const wasm::WasmRelocation & 1863d3d84fddSDerek Schuff WasmObjectFile::getWasmRelocation(const RelocationRef &Ref) const { 1864d3d84fddSDerek Schuff return getWasmRelocation(Ref.getRawDataRefImpl()); 1865d3d84fddSDerek Schuff } 1866d3d84fddSDerek Schuff 1867d3d84fddSDerek Schuff const wasm::WasmRelocation & 1868d3d84fddSDerek Schuff WasmObjectFile::getWasmRelocation(DataRefImpl Ref) const { 186916fe5822SDavide Italiano assert(Ref.d.a < Sections.size()); 1870d3d84fddSDerek Schuff const WasmSection &Sec = Sections[Ref.d.a]; 187116fe5822SDavide Italiano assert(Ref.d.b < Sec.Relocations.size()); 1872d3d84fddSDerek Schuff return Sec.Relocations[Ref.d.b]; 18732c6f75ddSDerek Schuff } 1874feef720bSHeejin Ahn 1875feef720bSHeejin Ahn int WasmSectionOrderChecker::getSectionOrder(unsigned ID, 1876feef720bSHeejin Ahn StringRef CustomSectionName) { 1877feef720bSHeejin Ahn switch (ID) { 1878feef720bSHeejin Ahn case wasm::WASM_SEC_CUSTOM: 1879feef720bSHeejin Ahn return StringSwitch<unsigned>(CustomSectionName) 1880feef720bSHeejin Ahn .Case("dylink", WASM_SEC_ORDER_DYLINK) 1881b78c85a4SSam Clegg .Case("dylink.0", WASM_SEC_ORDER_DYLINK) 1882feef720bSHeejin Ahn .Case("linking", WASM_SEC_ORDER_LINKING) 1883feef720bSHeejin Ahn .StartsWith("reloc.", WASM_SEC_ORDER_RELOC) 1884feef720bSHeejin Ahn .Case("name", WASM_SEC_ORDER_NAME) 1885feef720bSHeejin Ahn .Case("producers", WASM_SEC_ORDER_PRODUCERS) 1886f6f4f843SThomas Lively .Case("target_features", WASM_SEC_ORDER_TARGET_FEATURES) 18879757bba4SThomas Lively .Default(WASM_SEC_ORDER_NONE); 1888feef720bSHeejin Ahn case wasm::WASM_SEC_TYPE: 1889feef720bSHeejin Ahn return WASM_SEC_ORDER_TYPE; 1890feef720bSHeejin Ahn case wasm::WASM_SEC_IMPORT: 1891feef720bSHeejin Ahn return WASM_SEC_ORDER_IMPORT; 1892feef720bSHeejin Ahn case wasm::WASM_SEC_FUNCTION: 1893feef720bSHeejin Ahn return WASM_SEC_ORDER_FUNCTION; 1894feef720bSHeejin Ahn case wasm::WASM_SEC_TABLE: 1895feef720bSHeejin Ahn return WASM_SEC_ORDER_TABLE; 1896feef720bSHeejin Ahn case wasm::WASM_SEC_MEMORY: 1897feef720bSHeejin Ahn return WASM_SEC_ORDER_MEMORY; 1898feef720bSHeejin Ahn case wasm::WASM_SEC_GLOBAL: 1899feef720bSHeejin Ahn return WASM_SEC_ORDER_GLOBAL; 1900feef720bSHeejin Ahn case wasm::WASM_SEC_EXPORT: 1901feef720bSHeejin Ahn return WASM_SEC_ORDER_EXPORT; 1902feef720bSHeejin Ahn case wasm::WASM_SEC_START: 1903feef720bSHeejin Ahn return WASM_SEC_ORDER_START; 1904feef720bSHeejin Ahn case wasm::WASM_SEC_ELEM: 1905feef720bSHeejin Ahn return WASM_SEC_ORDER_ELEM; 1906feef720bSHeejin Ahn case wasm::WASM_SEC_CODE: 1907feef720bSHeejin Ahn return WASM_SEC_ORDER_CODE; 1908feef720bSHeejin Ahn case wasm::WASM_SEC_DATA: 1909feef720bSHeejin Ahn return WASM_SEC_ORDER_DATA; 1910feef720bSHeejin Ahn case wasm::WASM_SEC_DATACOUNT: 1911feef720bSHeejin Ahn return WASM_SEC_ORDER_DATACOUNT; 19121d891d44SHeejin Ahn case wasm::WASM_SEC_TAG: 19131d891d44SHeejin Ahn return WASM_SEC_ORDER_TAG; 1914feef720bSHeejin Ahn default: 1915fe8aabf9SSam Clegg return WASM_SEC_ORDER_NONE; 1916feef720bSHeejin Ahn } 1917feef720bSHeejin Ahn } 1918feef720bSHeejin Ahn 19199757bba4SThomas Lively // Represents the edges in a directed graph where any node B reachable from node 19209757bba4SThomas Lively // A is not allowed to appear before A in the section ordering, but may appear 19219757bba4SThomas Lively // afterward. 1922f93426c5SHeejin Ahn int WasmSectionOrderChecker::DisallowedPredecessors 1923f93426c5SHeejin Ahn [WASM_NUM_SEC_ORDERS][WASM_NUM_SEC_ORDERS] = { 1924f93426c5SHeejin Ahn // WASM_SEC_ORDER_NONE 1925f93426c5SHeejin Ahn {}, 1926f93426c5SHeejin Ahn // WASM_SEC_ORDER_TYPE 1927f93426c5SHeejin Ahn {WASM_SEC_ORDER_TYPE, WASM_SEC_ORDER_IMPORT}, 1928f93426c5SHeejin Ahn // WASM_SEC_ORDER_IMPORT 1929f93426c5SHeejin Ahn {WASM_SEC_ORDER_IMPORT, WASM_SEC_ORDER_FUNCTION}, 1930f93426c5SHeejin Ahn // WASM_SEC_ORDER_FUNCTION 1931f93426c5SHeejin Ahn {WASM_SEC_ORDER_FUNCTION, WASM_SEC_ORDER_TABLE}, 1932f93426c5SHeejin Ahn // WASM_SEC_ORDER_TABLE 1933f93426c5SHeejin Ahn {WASM_SEC_ORDER_TABLE, WASM_SEC_ORDER_MEMORY}, 1934f93426c5SHeejin Ahn // WASM_SEC_ORDER_MEMORY 19351d891d44SHeejin Ahn {WASM_SEC_ORDER_MEMORY, WASM_SEC_ORDER_TAG}, 19361d891d44SHeejin Ahn // WASM_SEC_ORDER_TAG 19371d891d44SHeejin Ahn {WASM_SEC_ORDER_TAG, WASM_SEC_ORDER_GLOBAL}, 1938f93426c5SHeejin Ahn // WASM_SEC_ORDER_GLOBAL 1939f93426c5SHeejin Ahn {WASM_SEC_ORDER_GLOBAL, WASM_SEC_ORDER_EXPORT}, 1940f93426c5SHeejin Ahn // WASM_SEC_ORDER_EXPORT 1941f93426c5SHeejin Ahn {WASM_SEC_ORDER_EXPORT, WASM_SEC_ORDER_START}, 1942f93426c5SHeejin Ahn // WASM_SEC_ORDER_START 1943f93426c5SHeejin Ahn {WASM_SEC_ORDER_START, WASM_SEC_ORDER_ELEM}, 1944f93426c5SHeejin Ahn // WASM_SEC_ORDER_ELEM 1945f93426c5SHeejin Ahn {WASM_SEC_ORDER_ELEM, WASM_SEC_ORDER_DATACOUNT}, 1946f93426c5SHeejin Ahn // WASM_SEC_ORDER_DATACOUNT 1947f93426c5SHeejin Ahn {WASM_SEC_ORDER_DATACOUNT, WASM_SEC_ORDER_CODE}, 1948f93426c5SHeejin Ahn // WASM_SEC_ORDER_CODE 1949f93426c5SHeejin Ahn {WASM_SEC_ORDER_CODE, WASM_SEC_ORDER_DATA}, 1950f93426c5SHeejin Ahn // WASM_SEC_ORDER_DATA 1951f93426c5SHeejin Ahn {WASM_SEC_ORDER_DATA, WASM_SEC_ORDER_LINKING}, 19529757bba4SThomas Lively 19539757bba4SThomas Lively // Custom Sections 1954f93426c5SHeejin Ahn // WASM_SEC_ORDER_DYLINK 1955f93426c5SHeejin Ahn {WASM_SEC_ORDER_DYLINK, WASM_SEC_ORDER_TYPE}, 1956f93426c5SHeejin Ahn // WASM_SEC_ORDER_LINKING 1957f93426c5SHeejin Ahn {WASM_SEC_ORDER_LINKING, WASM_SEC_ORDER_RELOC, WASM_SEC_ORDER_NAME}, 1958f93426c5SHeejin Ahn // WASM_SEC_ORDER_RELOC (can be repeated) 1959f93426c5SHeejin Ahn {}, 1960f93426c5SHeejin Ahn // WASM_SEC_ORDER_NAME 1961f93426c5SHeejin Ahn {WASM_SEC_ORDER_NAME, WASM_SEC_ORDER_PRODUCERS}, 1962f93426c5SHeejin Ahn // WASM_SEC_ORDER_PRODUCERS 1963f93426c5SHeejin Ahn {WASM_SEC_ORDER_PRODUCERS, WASM_SEC_ORDER_TARGET_FEATURES}, 1964f93426c5SHeejin Ahn // WASM_SEC_ORDER_TARGET_FEATURES 1965f93426c5SHeejin Ahn {WASM_SEC_ORDER_TARGET_FEATURES}}; 19669757bba4SThomas Lively 1967feef720bSHeejin Ahn bool WasmSectionOrderChecker::isValidSectionOrder(unsigned ID, 1968feef720bSHeejin Ahn StringRef CustomSectionName) { 1969feef720bSHeejin Ahn int Order = getSectionOrder(ID, CustomSectionName); 19709757bba4SThomas Lively if (Order == WASM_SEC_ORDER_NONE) 1971feef720bSHeejin Ahn return true; 19729757bba4SThomas Lively 19739757bba4SThomas Lively // Disallowed predecessors we need to check for 19749757bba4SThomas Lively SmallVector<int, WASM_NUM_SEC_ORDERS> WorkList; 19759757bba4SThomas Lively 19769757bba4SThomas Lively // Keep track of completed checks to avoid repeating work 19779757bba4SThomas Lively bool Checked[WASM_NUM_SEC_ORDERS] = {}; 19789757bba4SThomas Lively 19799757bba4SThomas Lively int Curr = Order; 19809757bba4SThomas Lively while (true) { 19819757bba4SThomas Lively // Add new disallowed predecessors to work list 19829757bba4SThomas Lively for (size_t I = 0;; ++I) { 19839757bba4SThomas Lively int Next = DisallowedPredecessors[Curr][I]; 19849757bba4SThomas Lively if (Next == WASM_SEC_ORDER_NONE) 19859757bba4SThomas Lively break; 19869757bba4SThomas Lively if (Checked[Next]) 19879757bba4SThomas Lively continue; 19889757bba4SThomas Lively WorkList.push_back(Next); 19899757bba4SThomas Lively Checked[Next] = true; 19909757bba4SThomas Lively } 19919757bba4SThomas Lively 19929757bba4SThomas Lively if (WorkList.empty()) 19939757bba4SThomas Lively break; 19949757bba4SThomas Lively 19959757bba4SThomas Lively // Consider next disallowed predecessor 19969757bba4SThomas Lively Curr = WorkList.pop_back_val(); 19979757bba4SThomas Lively if (Seen[Curr]) 19989757bba4SThomas Lively return false; 19999757bba4SThomas Lively } 20009757bba4SThomas Lively 20019757bba4SThomas Lively // Have not seen any disallowed predecessors 20029757bba4SThomas Lively Seen[Order] = true; 20039757bba4SThomas Lively return true; 2004feef720bSHeejin Ahn } 2005