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; 454c0039de2SSam Clegg if (Functions.size() && !SeenCodeSection) { 45584c6f325SSam Clegg return make_error<GenericBinaryError>("names must come after code section", 4569f3fe42eSSam Clegg object_error::parse_failed); 4579f3fe42eSSam Clegg } 4584710ed7aSSam Clegg 459b7c62394SSam Clegg while (Ctx.Ptr < Ctx.End) { 460b7c62394SSam Clegg uint8_t Type = readUint8(Ctx); 461b7c62394SSam Clegg uint32_t Size = readVaruint32(Ctx); 462b7c62394SSam Clegg const uint8_t *SubSectionEnd = Ctx.Ptr + Size; 463d3d84fddSDerek Schuff switch (Type) { 4641827005cSSam Clegg case wasm::WASM_NAMES_FUNCTION: 4659a72d3e3SSam Clegg case wasm::WASM_NAMES_GLOBAL: 4669a72d3e3SSam Clegg case wasm::WASM_NAMES_DATA_SEGMENT: { 467b7c62394SSam Clegg uint32_t Count = readVaruint32(Ctx); 468d3d84fddSDerek Schuff while (Count--) { 469b7c62394SSam Clegg uint32_t Index = readVaruint32(Ctx); 470b7c62394SSam Clegg StringRef Name = readString(Ctx); 4719a72d3e3SSam Clegg wasm::NameType nameType = wasm::NameType::FUNCTION; 4721827005cSSam Clegg if (Type == wasm::WASM_NAMES_FUNCTION) { 4731827005cSSam Clegg if (!SeenFunctions.insert(Index).second) 4741827005cSSam Clegg return make_error<GenericBinaryError>( 47584c6f325SSam Clegg "function named more than once", object_error::parse_failed); 4769f3fe42eSSam Clegg if (!isValidFunctionIndex(Index) || Name.empty()) 47784c6f325SSam Clegg return make_error<GenericBinaryError>("invalid name entry", 4789f3fe42eSSam Clegg object_error::parse_failed); 4791827005cSSam Clegg 480ef90ff36SNicholas Wilson if (isDefinedFunctionIndex(Index)) 481ef90ff36SNicholas Wilson getDefinedFunction(Index).DebugName = Name; 4829a72d3e3SSam Clegg } else if (Type == wasm::WASM_NAMES_GLOBAL) { 4839a72d3e3SSam Clegg nameType = wasm::NameType::GLOBAL; 4841827005cSSam Clegg if (!SeenGlobals.insert(Index).second) 48584c6f325SSam Clegg return make_error<GenericBinaryError>("global named more than once", 4861827005cSSam Clegg object_error::parse_failed); 4871827005cSSam Clegg if (!isValidGlobalIndex(Index) || Name.empty()) 48884c6f325SSam Clegg return make_error<GenericBinaryError>("invalid name entry", 4891827005cSSam Clegg object_error::parse_failed); 4909a72d3e3SSam Clegg } else { 4919a72d3e3SSam Clegg nameType = wasm::NameType::DATA_SEGMENT; 4929a72d3e3SSam Clegg if (!SeenSegments.insert(Index).second) 4939a72d3e3SSam Clegg return make_error<GenericBinaryError>( 49484c6f325SSam Clegg "segment named more than once", object_error::parse_failed); 4959a72d3e3SSam Clegg if (Index > DataSegments.size()) 49684c6f325SSam Clegg return make_error<GenericBinaryError>("invalid named data segment", 4979a72d3e3SSam Clegg object_error::parse_failed); 4981827005cSSam Clegg } 4999a72d3e3SSam Clegg DebugNames.push_back(wasm::WasmDebugName{nameType, Index, Name}); 500d3d84fddSDerek Schuff } 501d3d84fddSDerek Schuff break; 502d3d84fddSDerek Schuff } 503d3d84fddSDerek Schuff // Ignore local names for now 504d3d84fddSDerek Schuff case wasm::WASM_NAMES_LOCAL: 505d3d84fddSDerek Schuff default: 506b7c62394SSam Clegg Ctx.Ptr += Size; 507d3d84fddSDerek Schuff break; 508d3d84fddSDerek Schuff } 509b7c62394SSam Clegg if (Ctx.Ptr != SubSectionEnd) 510f208f631SHeejin Ahn return make_error<GenericBinaryError>( 51184c6f325SSam Clegg "name sub-section ended prematurely", object_error::parse_failed); 512d3d84fddSDerek Schuff } 513d3d84fddSDerek Schuff 514b7c62394SSam Clegg if (Ctx.Ptr != Ctx.End) 51584c6f325SSam Clegg return make_error<GenericBinaryError>("name section ended prematurely", 516d3d84fddSDerek Schuff object_error::parse_failed); 517d3d84fddSDerek Schuff return Error::success(); 518d3d84fddSDerek Schuff } 519d3d84fddSDerek Schuff 520b7c62394SSam Clegg Error WasmObjectFile::parseLinkingSection(ReadContext &Ctx) { 5214df5d764SSam Clegg HasLinkingSection = true; 522c0039de2SSam Clegg if (Functions.size() && !SeenCodeSection) { 5239f3fe42eSSam Clegg return make_error<GenericBinaryError>( 52484c6f325SSam Clegg "linking data must come after code section", 525f208f631SHeejin Ahn object_error::parse_failed); 5269f3fe42eSSam Clegg } 527e7a60708SSam Clegg 528b7c62394SSam Clegg LinkingData.Version = readVaruint32(Ctx); 5296bb5a41fSSam Clegg if (LinkingData.Version != wasm::WasmMetadataVersion) { 5306bb5a41fSSam Clegg return make_error<GenericBinaryError>( 53184c6f325SSam Clegg "unexpected metadata version: " + Twine(LinkingData.Version) + 5326bb5a41fSSam Clegg " (Expected: " + Twine(wasm::WasmMetadataVersion) + ")", 5336bb5a41fSSam Clegg object_error::parse_failed); 5346bb5a41fSSam Clegg } 5356bb5a41fSSam Clegg 536b7c62394SSam Clegg const uint8_t *OrigEnd = Ctx.End; 537b7c62394SSam Clegg while (Ctx.Ptr < OrigEnd) { 538b7c62394SSam Clegg Ctx.End = OrigEnd; 539b7c62394SSam Clegg uint8_t Type = readUint8(Ctx); 540b7c62394SSam Clegg uint32_t Size = readVaruint32(Ctx); 541f4f37509SSam Clegg LLVM_DEBUG(dbgs() << "readSubsection type=" << int(Type) << " size=" << Size 542f4f37509SSam Clegg << "\n"); 543b7c62394SSam Clegg Ctx.End = Ctx.Ptr + Size; 544b7787fd0SSam Clegg switch (Type) { 5456c899ba6SSam Clegg case wasm::WASM_SYMBOL_TABLE: 546b7c62394SSam Clegg if (Error Err = parseLinkingSectionSymtab(Ctx)) 5476c899ba6SSam Clegg return Err; 548b7787fd0SSam Clegg break; 54963ebb813SSam Clegg case wasm::WASM_SEGMENT_INFO: { 550b7c62394SSam Clegg uint32_t Count = readVaruint32(Ctx); 551d95ed959SSam Clegg if (Count > DataSegments.size()) 55284c6f325SSam Clegg return make_error<GenericBinaryError>("too many segment names", 553d95ed959SSam Clegg object_error::parse_failed); 55418c56a07SHeejin Ahn for (uint32_t I = 0; I < Count; I++) { 55518c56a07SHeejin Ahn DataSegments[I].Data.Name = readString(Ctx); 55618c56a07SHeejin Ahn DataSegments[I].Data.Alignment = readVaruint32(Ctx); 5573b8d2be5SSam Clegg DataSegments[I].Data.LinkingFlags = readVaruint32(Ctx); 55863ebb813SSam Clegg } 559d95ed959SSam Clegg break; 560d95ed959SSam Clegg } 5614273998cSSam Clegg case wasm::WASM_INIT_FUNCS: { 562b7c62394SSam Clegg uint32_t Count = readVaruint32(Ctx); 5634273998cSSam Clegg LinkingData.InitFunctions.reserve(Count); 56418c56a07SHeejin Ahn for (uint32_t I = 0; I < Count; I++) { 5654273998cSSam Clegg wasm::WasmInitFunc Init; 566b7c62394SSam Clegg Init.Priority = readVaruint32(Ctx); 567b7c62394SSam Clegg Init.Symbol = readVaruint32(Ctx); 568b3748f71SNicholas Wilson if (!isValidFunctionSymbol(Init.Symbol)) 56984c6f325SSam Clegg return make_error<GenericBinaryError>("invalid function symbol: " + 5706c899ba6SSam Clegg Twine(Init.Symbol), 5714273998cSSam Clegg object_error::parse_failed); 5724273998cSSam Clegg LinkingData.InitFunctions.emplace_back(Init); 5734273998cSSam Clegg } 5744273998cSSam Clegg break; 5754273998cSSam Clegg } 576ea7caceeSSam Clegg case wasm::WASM_COMDAT_INFO: 577b7c62394SSam Clegg if (Error Err = parseLinkingSectionComdat(Ctx)) 578ea7caceeSSam Clegg return Err; 579ea7caceeSSam Clegg break; 580b7787fd0SSam Clegg default: 581b7c62394SSam Clegg Ctx.Ptr += Size; 582b7787fd0SSam Clegg break; 583b7787fd0SSam Clegg } 584b7c62394SSam Clegg if (Ctx.Ptr != Ctx.End) 585b7787fd0SSam Clegg return make_error<GenericBinaryError>( 58684c6f325SSam Clegg "linking sub-section ended prematurely", object_error::parse_failed); 587b7787fd0SSam Clegg } 588b7c62394SSam Clegg if (Ctx.Ptr != OrigEnd) 58984c6f325SSam Clegg return make_error<GenericBinaryError>("linking section ended prematurely", 590b7787fd0SSam Clegg object_error::parse_failed); 591b7787fd0SSam Clegg return Error::success(); 592b7787fd0SSam Clegg } 593b7787fd0SSam Clegg 594b7c62394SSam Clegg Error WasmObjectFile::parseLinkingSectionSymtab(ReadContext &Ctx) { 595b7c62394SSam Clegg uint32_t Count = readVaruint32(Ctx); 5966c899ba6SSam Clegg LinkingData.SymbolTable.reserve(Count); 5976c899ba6SSam Clegg Symbols.reserve(Count); 5986c899ba6SSam Clegg StringSet<> SymbolNames; 5996c899ba6SSam Clegg 6006c899ba6SSam Clegg std::vector<wasm::WasmImport *> ImportedGlobals; 6016c899ba6SSam Clegg std::vector<wasm::WasmImport *> ImportedFunctions; 6021d891d44SHeejin Ahn std::vector<wasm::WasmImport *> ImportedTags; 603feac819eSAndy Wingo std::vector<wasm::WasmImport *> ImportedTables; 6046c899ba6SSam Clegg ImportedGlobals.reserve(Imports.size()); 6056c899ba6SSam Clegg ImportedFunctions.reserve(Imports.size()); 6061d891d44SHeejin Ahn ImportedTags.reserve(Imports.size()); 607feac819eSAndy Wingo ImportedTables.reserve(Imports.size()); 6086c899ba6SSam Clegg for (auto &I : Imports) { 6096c899ba6SSam Clegg if (I.Kind == wasm::WASM_EXTERNAL_FUNCTION) 6106c899ba6SSam Clegg ImportedFunctions.emplace_back(&I); 6116c899ba6SSam Clegg else if (I.Kind == wasm::WASM_EXTERNAL_GLOBAL) 6126c899ba6SSam Clegg ImportedGlobals.emplace_back(&I); 6131d891d44SHeejin Ahn else if (I.Kind == wasm::WASM_EXTERNAL_TAG) 6141d891d44SHeejin Ahn ImportedTags.emplace_back(&I); 615feac819eSAndy Wingo else if (I.Kind == wasm::WASM_EXTERNAL_TABLE) 616feac819eSAndy Wingo ImportedTables.emplace_back(&I); 6176c899ba6SSam Clegg } 6186c899ba6SSam Clegg 6196c899ba6SSam Clegg while (Count--) { 6206c899ba6SSam Clegg wasm::WasmSymbolInfo Info; 621a2125b8dSHeejin Ahn const wasm::WasmSignature *Signature = nullptr; 6226c899ba6SSam Clegg const wasm::WasmGlobalType *GlobalType = nullptr; 62353e3b81fSAndy Wingo const wasm::WasmTableType *TableType = nullptr; 6246c899ba6SSam Clegg 625b7c62394SSam Clegg Info.Kind = readUint8(Ctx); 626b7c62394SSam Clegg Info.Flags = readVaruint32(Ctx); 6276c899ba6SSam Clegg bool IsDefined = (Info.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0; 6286c899ba6SSam Clegg 6296c899ba6SSam Clegg switch (Info.Kind) { 6306c899ba6SSam Clegg case wasm::WASM_SYMBOL_TYPE_FUNCTION: 631b7c62394SSam Clegg Info.ElementIndex = readVaruint32(Ctx); 6326c899ba6SSam Clegg if (!isValidFunctionIndex(Info.ElementIndex) || 6336c899ba6SSam Clegg IsDefined != isDefinedFunctionIndex(Info.ElementIndex)) 6346c899ba6SSam Clegg return make_error<GenericBinaryError>("invalid function symbol index", 6356c899ba6SSam Clegg object_error::parse_failed); 6366c899ba6SSam Clegg if (IsDefined) { 637b7c62394SSam Clegg Info.Name = readString(Ctx); 6386c899ba6SSam Clegg unsigned FuncIndex = Info.ElementIndex - NumImportedFunctions; 639959e7371SNicholas Wilson wasm::WasmFunction &Function = Functions[FuncIndex]; 640c0039de2SSam Clegg Signature = &Signatures[Function.SigIndex]; 641ef90ff36SNicholas Wilson if (Function.SymbolName.empty()) 642ef90ff36SNicholas Wilson Function.SymbolName = Info.Name; 6436c899ba6SSam Clegg } else { 6446c899ba6SSam Clegg wasm::WasmImport &Import = *ImportedFunctions[Info.ElementIndex]; 645bd481277SSam Clegg if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0) { 64629874ceaSDan Gohman Info.Name = readString(Ctx); 64729874ceaSDan Gohman Info.ImportName = Import.Field; 648bd481277SSam Clegg } else { 649bd481277SSam Clegg Info.Name = Import.Field; 650bd481277SSam Clegg } 651bd481277SSam Clegg Signature = &Signatures[Import.SigIndex]; 652bd481277SSam Clegg if (!Import.Module.empty()) { 65329874ceaSDan Gohman Info.ImportModule = Import.Module; 6546c899ba6SSam Clegg } 655bd481277SSam Clegg } 6566c899ba6SSam Clegg break; 6576c899ba6SSam Clegg 6586c899ba6SSam Clegg case wasm::WASM_SYMBOL_TYPE_GLOBAL: 659b7c62394SSam Clegg Info.ElementIndex = readVaruint32(Ctx); 6606c899ba6SSam Clegg if (!isValidGlobalIndex(Info.ElementIndex) || 6616c899ba6SSam Clegg IsDefined != isDefinedGlobalIndex(Info.ElementIndex)) 6626c899ba6SSam Clegg return make_error<GenericBinaryError>("invalid global symbol index", 6636c899ba6SSam Clegg object_error::parse_failed); 664f208f631SHeejin Ahn if (!IsDefined && (Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) == 66515f349f7SNicholas Wilson wasm::WASM_SYMBOL_BINDING_WEAK) 66615f349f7SNicholas Wilson return make_error<GenericBinaryError>("undefined weak global symbol", 66715f349f7SNicholas Wilson object_error::parse_failed); 6686c899ba6SSam Clegg if (IsDefined) { 669b7c62394SSam Clegg Info.Name = readString(Ctx); 6706c899ba6SSam Clegg unsigned GlobalIndex = Info.ElementIndex - NumImportedGlobals; 671959e7371SNicholas Wilson wasm::WasmGlobal &Global = Globals[GlobalIndex]; 672959e7371SNicholas Wilson GlobalType = &Global.Type; 673ef90ff36SNicholas Wilson if (Global.SymbolName.empty()) 674ef90ff36SNicholas Wilson Global.SymbolName = Info.Name; 6756c899ba6SSam Clegg } else { 6766c899ba6SSam Clegg wasm::WasmImport &Import = *ImportedGlobals[Info.ElementIndex]; 677bd481277SSam Clegg if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0) { 67829874ceaSDan Gohman Info.Name = readString(Ctx); 679bd481277SSam Clegg Info.ImportName = Import.Field; 680bd481277SSam Clegg } else { 6816c899ba6SSam Clegg Info.Name = Import.Field; 682bd481277SSam Clegg } 6836c899ba6SSam Clegg GlobalType = &Import.Global; 684bd481277SSam Clegg if (!Import.Module.empty()) { 68529874ceaSDan Gohman Info.ImportModule = Import.Module; 6866c899ba6SSam Clegg } 687bd481277SSam Clegg } 6886c899ba6SSam Clegg break; 6896c899ba6SSam Clegg 690388fb67bSPaulo Matos case wasm::WASM_SYMBOL_TYPE_TABLE: 691388fb67bSPaulo Matos Info.ElementIndex = readVaruint32(Ctx); 692a5a3659dSAndy Wingo if (!isValidTableNumber(Info.ElementIndex) || 693a5a3659dSAndy Wingo IsDefined != isDefinedTableNumber(Info.ElementIndex)) 694388fb67bSPaulo Matos return make_error<GenericBinaryError>("invalid table symbol index", 695388fb67bSPaulo Matos object_error::parse_failed); 696388fb67bSPaulo Matos if (!IsDefined && (Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) == 697388fb67bSPaulo Matos wasm::WASM_SYMBOL_BINDING_WEAK) 698388fb67bSPaulo Matos return make_error<GenericBinaryError>("undefined weak table symbol", 699388fb67bSPaulo Matos object_error::parse_failed); 700388fb67bSPaulo Matos if (IsDefined) { 701388fb67bSPaulo Matos Info.Name = readString(Ctx); 702a5a3659dSAndy Wingo unsigned TableNumber = Info.ElementIndex - NumImportedTables; 703a5a3659dSAndy Wingo wasm::WasmTable &Table = Tables[TableNumber]; 70453e3b81fSAndy Wingo TableType = &Table.Type; 7051933c9d4SAndy Wingo if (Table.SymbolName.empty()) 7061933c9d4SAndy Wingo Table.SymbolName = Info.Name; 707388fb67bSPaulo Matos } else { 708feac819eSAndy Wingo wasm::WasmImport &Import = *ImportedTables[Info.ElementIndex]; 709feac819eSAndy Wingo if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0) { 710feac819eSAndy Wingo Info.Name = readString(Ctx); 711feac819eSAndy Wingo Info.ImportName = Import.Field; 712feac819eSAndy Wingo } else { 713feac819eSAndy Wingo Info.Name = Import.Field; 714feac819eSAndy Wingo } 71553e3b81fSAndy Wingo TableType = &Import.Table; 716feac819eSAndy Wingo if (!Import.Module.empty()) { 717feac819eSAndy Wingo Info.ImportModule = Import.Module; 718feac819eSAndy Wingo } 719388fb67bSPaulo Matos } 720388fb67bSPaulo Matos break; 721388fb67bSPaulo Matos 7226c899ba6SSam Clegg case wasm::WASM_SYMBOL_TYPE_DATA: 723b7c62394SSam Clegg Info.Name = readString(Ctx); 7246c899ba6SSam Clegg if (IsDefined) { 7253b29376eSWouter van Oortmerssen auto Index = readVaruint32(Ctx); 7266c899ba6SSam Clegg if (Index >= DataSegments.size()) 7276c899ba6SSam Clegg return make_error<GenericBinaryError>("invalid data symbol index", 7286c899ba6SSam Clegg object_error::parse_failed); 7293b29376eSWouter van Oortmerssen auto Offset = readVaruint64(Ctx); 7303b29376eSWouter van Oortmerssen auto Size = readVaruint64(Ctx); 731cd01430fSSam Clegg size_t SegmentSize = DataSegments[Index].Data.Content.size(); 732cd01430fSSam Clegg if (Offset > SegmentSize) 733cd01430fSSam Clegg return make_error<GenericBinaryError>( 734cd01430fSSam Clegg "invalid data symbol offset: `" + Info.Name + "` (offset: " + 735cd01430fSSam Clegg Twine(Offset) + " segment size: " + Twine(SegmentSize) + ")", 7366c899ba6SSam Clegg object_error::parse_failed); 7376c899ba6SSam Clegg Info.DataRef = wasm::WasmDataReference{Index, Offset, Size}; 7386c899ba6SSam Clegg } 7396c899ba6SSam Clegg break; 7406c899ba6SSam Clegg 7416a31a0d6SSam Clegg case wasm::WASM_SYMBOL_TYPE_SECTION: { 742d5504a0aSSam Clegg if ((Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) != 743d5504a0aSSam Clegg wasm::WASM_SYMBOL_BINDING_LOCAL) 744e0658119SSam Clegg return make_error<GenericBinaryError>( 74584c6f325SSam Clegg "section symbols must have local binding", 746d5504a0aSSam Clegg object_error::parse_failed); 747b7c62394SSam Clegg Info.ElementIndex = readVaruint32(Ctx); 7486a31a0d6SSam Clegg // Use somewhat unique section name as symbol name. 7496a31a0d6SSam Clegg StringRef SectionName = Sections[Info.ElementIndex].Name; 7506a31a0d6SSam Clegg Info.Name = SectionName; 7516a31a0d6SSam Clegg break; 7526a31a0d6SSam Clegg } 7536a31a0d6SSam Clegg 7541d891d44SHeejin Ahn case wasm::WASM_SYMBOL_TYPE_TAG: { 755da419bdbSHeejin Ahn Info.ElementIndex = readVaruint32(Ctx); 7561d891d44SHeejin Ahn if (!isValidTagIndex(Info.ElementIndex) || 7571d891d44SHeejin Ahn IsDefined != isDefinedTagIndex(Info.ElementIndex)) 7581d891d44SHeejin Ahn return make_error<GenericBinaryError>("invalid tag symbol index", 759da419bdbSHeejin Ahn object_error::parse_failed); 760da419bdbSHeejin Ahn if (!IsDefined && (Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) == 761da419bdbSHeejin Ahn wasm::WASM_SYMBOL_BINDING_WEAK) 762da419bdbSHeejin Ahn return make_error<GenericBinaryError>("undefined weak global symbol", 763da419bdbSHeejin Ahn object_error::parse_failed); 764da419bdbSHeejin Ahn if (IsDefined) { 765da419bdbSHeejin Ahn Info.Name = readString(Ctx); 7661d891d44SHeejin Ahn unsigned TagIndex = Info.ElementIndex - NumImportedTags; 7671d891d44SHeejin Ahn wasm::WasmTag &Tag = Tags[TagIndex]; 7683ec1760dSHeejin Ahn Signature = &Signatures[Tag.SigIndex]; 7691d891d44SHeejin Ahn if (Tag.SymbolName.empty()) 7701d891d44SHeejin Ahn Tag.SymbolName = Info.Name; 771da419bdbSHeejin Ahn 772da419bdbSHeejin Ahn } else { 7731d891d44SHeejin Ahn wasm::WasmImport &Import = *ImportedTags[Info.ElementIndex]; 774bd481277SSam Clegg if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0) { 77529874ceaSDan Gohman Info.Name = readString(Ctx); 776bd481277SSam Clegg Info.ImportName = Import.Field; 777bd481277SSam Clegg } else { 77829874ceaSDan Gohman Info.Name = Import.Field; 779bd481277SSam Clegg } 7803ec1760dSHeejin Ahn Signature = &Signatures[Import.SigIndex]; 781bd481277SSam Clegg if (!Import.Module.empty()) { 78229874ceaSDan Gohman Info.ImportModule = Import.Module; 783da419bdbSHeejin Ahn } 784bd481277SSam Clegg } 785da419bdbSHeejin Ahn break; 786da419bdbSHeejin Ahn } 787da419bdbSHeejin Ahn 7886c899ba6SSam Clegg default: 78984c6f325SSam Clegg return make_error<GenericBinaryError>("invalid symbol type: " + 790d75b3719SSam Clegg Twine(unsigned(Info.Kind)), 7916c899ba6SSam Clegg object_error::parse_failed); 7926c899ba6SSam Clegg } 7936c899ba6SSam Clegg 7946c899ba6SSam Clegg if ((Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) != 7956c899ba6SSam Clegg wasm::WASM_SYMBOL_BINDING_LOCAL && 7966c899ba6SSam Clegg !SymbolNames.insert(Info.Name).second) 79784c6f325SSam Clegg return make_error<GenericBinaryError>("duplicate symbol name " + 7986c899ba6SSam Clegg Twine(Info.Name), 7996c899ba6SSam Clegg object_error::parse_failed); 8006c899ba6SSam Clegg LinkingData.SymbolTable.emplace_back(Info); 801388fb67bSPaulo Matos Symbols.emplace_back(LinkingData.SymbolTable.back(), GlobalType, TableType, 8023ec1760dSHeejin Ahn Signature); 803d34e60caSNicola Zaghen LLVM_DEBUG(dbgs() << "Adding symbol: " << Symbols.back() << "\n"); 8046c899ba6SSam Clegg } 8056c899ba6SSam Clegg 8066c899ba6SSam Clegg return Error::success(); 8076c899ba6SSam Clegg } 8086c899ba6SSam Clegg 809b7c62394SSam Clegg Error WasmObjectFile::parseLinkingSectionComdat(ReadContext &Ctx) { 810b7c62394SSam Clegg uint32_t ComdatCount = readVaruint32(Ctx); 811ea7caceeSSam Clegg StringSet<> ComdatSet; 812027b9357SNicholas Wilson for (unsigned ComdatIndex = 0; ComdatIndex < ComdatCount; ++ComdatIndex) { 813b7c62394SSam Clegg StringRef Name = readString(Ctx); 814ea7caceeSSam Clegg if (Name.empty() || !ComdatSet.insert(Name).second) 81584c6f325SSam Clegg return make_error<GenericBinaryError>("bad/duplicate COMDAT name " + 816f208f631SHeejin Ahn Twine(Name), 817ea7caceeSSam Clegg object_error::parse_failed); 818027b9357SNicholas Wilson LinkingData.Comdats.emplace_back(Name); 819b7c62394SSam Clegg uint32_t Flags = readVaruint32(Ctx); 820ea7caceeSSam Clegg if (Flags != 0) 82184c6f325SSam Clegg return make_error<GenericBinaryError>("unsupported COMDAT flags", 822ea7caceeSSam Clegg object_error::parse_failed); 823ea7caceeSSam Clegg 824b7c62394SSam Clegg uint32_t EntryCount = readVaruint32(Ctx); 825ea7caceeSSam Clegg while (EntryCount--) { 826b7c62394SSam Clegg unsigned Kind = readVaruint32(Ctx); 827b7c62394SSam Clegg unsigned Index = readVaruint32(Ctx); 828ea7caceeSSam Clegg switch (Kind) { 829ea7caceeSSam Clegg default: 83084c6f325SSam Clegg return make_error<GenericBinaryError>("invalid COMDAT entry type", 831ea7caceeSSam Clegg object_error::parse_failed); 832ea7caceeSSam Clegg case wasm::WASM_COMDAT_DATA: 833ea7caceeSSam Clegg if (Index >= DataSegments.size()) 834f208f631SHeejin Ahn return make_error<GenericBinaryError>( 835f208f631SHeejin Ahn "COMDAT data index out of range", object_error::parse_failed); 836027b9357SNicholas Wilson if (DataSegments[Index].Data.Comdat != UINT32_MAX) 83784c6f325SSam Clegg return make_error<GenericBinaryError>("data segment in two COMDATs", 838ea7caceeSSam Clegg object_error::parse_failed); 839027b9357SNicholas Wilson DataSegments[Index].Data.Comdat = ComdatIndex; 840ea7caceeSSam Clegg break; 841ea7caceeSSam Clegg case wasm::WASM_COMDAT_FUNCTION: 84223012e98SSam Clegg if (!isDefinedFunctionIndex(Index)) 843f208f631SHeejin Ahn return make_error<GenericBinaryError>( 844f208f631SHeejin Ahn "COMDAT function index out of range", object_error::parse_failed); 845027b9357SNicholas Wilson if (getDefinedFunction(Index).Comdat != UINT32_MAX) 84684c6f325SSam Clegg return make_error<GenericBinaryError>("function in two COMDATs", 847ea7caceeSSam Clegg object_error::parse_failed); 848027b9357SNicholas Wilson getDefinedFunction(Index).Comdat = ComdatIndex; 849ea7caceeSSam Clegg break; 8500a391060SDerek Schuff case wasm::WASM_COMDAT_SECTION: 8510a391060SDerek Schuff if (Index >= Sections.size()) 8520a391060SDerek Schuff return make_error<GenericBinaryError>( 8530a391060SDerek Schuff "COMDAT section index out of range", object_error::parse_failed); 8540a391060SDerek Schuff if (Sections[Index].Type != wasm::WASM_SEC_CUSTOM) 8550a391060SDerek Schuff return make_error<GenericBinaryError>( 85684c6f325SSam Clegg "non-custom section in a COMDAT", object_error::parse_failed); 8570a391060SDerek Schuff Sections[Index].Comdat = ComdatIndex; 8580a391060SDerek Schuff break; 859ea7caceeSSam Clegg } 860ea7caceeSSam Clegg } 861ea7caceeSSam Clegg } 862ea7caceeSSam Clegg return Error::success(); 863ea7caceeSSam Clegg } 864ea7caceeSSam Clegg 865cbda16ebSThomas Lively Error WasmObjectFile::parseProducersSection(ReadContext &Ctx) { 866cbda16ebSThomas Lively llvm::SmallSet<StringRef, 3> FieldsSeen; 867cbda16ebSThomas Lively uint32_t Fields = readVaruint32(Ctx); 86818c56a07SHeejin Ahn for (size_t I = 0; I < Fields; ++I) { 869cbda16ebSThomas Lively StringRef FieldName = readString(Ctx); 870cbda16ebSThomas Lively if (!FieldsSeen.insert(FieldName).second) 871cbda16ebSThomas Lively return make_error<GenericBinaryError>( 87284c6f325SSam Clegg "producers section does not have unique fields", 873cbda16ebSThomas Lively object_error::parse_failed); 874cbda16ebSThomas Lively std::vector<std::pair<std::string, std::string>> *ProducerVec = nullptr; 875cbda16ebSThomas Lively if (FieldName == "language") { 876cbda16ebSThomas Lively ProducerVec = &ProducerInfo.Languages; 877cbda16ebSThomas Lively } else if (FieldName == "processed-by") { 878cbda16ebSThomas Lively ProducerVec = &ProducerInfo.Tools; 879cbda16ebSThomas Lively } else if (FieldName == "sdk") { 880cbda16ebSThomas Lively ProducerVec = &ProducerInfo.SDKs; 881cbda16ebSThomas Lively } else { 882cbda16ebSThomas Lively return make_error<GenericBinaryError>( 88384c6f325SSam Clegg "producers section field is not named one of language, processed-by, " 884cbda16ebSThomas Lively "or sdk", 885cbda16ebSThomas Lively object_error::parse_failed); 886cbda16ebSThomas Lively } 887cbda16ebSThomas Lively uint32_t ValueCount = readVaruint32(Ctx); 888cbda16ebSThomas Lively llvm::SmallSet<StringRef, 8> ProducersSeen; 88918c56a07SHeejin Ahn for (size_t J = 0; J < ValueCount; ++J) { 890cbda16ebSThomas Lively StringRef Name = readString(Ctx); 891cbda16ebSThomas Lively StringRef Version = readString(Ctx); 892cbda16ebSThomas Lively if (!ProducersSeen.insert(Name).second) { 893cbda16ebSThomas Lively return make_error<GenericBinaryError>( 89484c6f325SSam Clegg "producers section contains repeated producer", 895cbda16ebSThomas Lively object_error::parse_failed); 896cbda16ebSThomas Lively } 897a9bc7b83SBenjamin Kramer ProducerVec->emplace_back(std::string(Name), std::string(Version)); 898cbda16ebSThomas Lively } 899cbda16ebSThomas Lively } 900cbda16ebSThomas Lively if (Ctx.Ptr != Ctx.End) 90184c6f325SSam Clegg return make_error<GenericBinaryError>("producers section ended prematurely", 902cbda16ebSThomas Lively object_error::parse_failed); 903cbda16ebSThomas Lively return Error::success(); 904cbda16ebSThomas Lively } 905cbda16ebSThomas Lively 906f6f4f843SThomas Lively Error WasmObjectFile::parseTargetFeaturesSection(ReadContext &Ctx) { 907f6f4f843SThomas Lively llvm::SmallSet<std::string, 8> FeaturesSeen; 908f6f4f843SThomas Lively uint32_t FeatureCount = readVaruint32(Ctx); 909f6f4f843SThomas Lively for (size_t I = 0; I < FeatureCount; ++I) { 910f6f4f843SThomas Lively wasm::WasmFeatureEntry Feature; 911f6f4f843SThomas Lively Feature.Prefix = readUint8(Ctx); 912f6f4f843SThomas Lively switch (Feature.Prefix) { 913f6f4f843SThomas Lively case wasm::WASM_FEATURE_PREFIX_USED: 914f6f4f843SThomas Lively case wasm::WASM_FEATURE_PREFIX_REQUIRED: 915f6f4f843SThomas Lively case wasm::WASM_FEATURE_PREFIX_DISALLOWED: 916f6f4f843SThomas Lively break; 917f6f4f843SThomas Lively default: 91884c6f325SSam Clegg return make_error<GenericBinaryError>("unknown feature policy prefix", 919f6f4f843SThomas Lively object_error::parse_failed); 920f6f4f843SThomas Lively } 921adcd0268SBenjamin Kramer Feature.Name = std::string(readString(Ctx)); 922f6f4f843SThomas Lively if (!FeaturesSeen.insert(Feature.Name).second) 923f6f4f843SThomas Lively return make_error<GenericBinaryError>( 92484c6f325SSam Clegg "target features section contains repeated feature \"" + 925f6f4f843SThomas Lively Feature.Name + "\"", 926f6f4f843SThomas Lively object_error::parse_failed); 927f6f4f843SThomas Lively TargetFeatures.push_back(Feature); 928f6f4f843SThomas Lively } 929f6f4f843SThomas Lively if (Ctx.Ptr != Ctx.End) 930f6f4f843SThomas Lively return make_error<GenericBinaryError>( 93184c6f325SSam Clegg "target features section ended prematurely", 932f6f4f843SThomas Lively object_error::parse_failed); 933f6f4f843SThomas Lively return Error::success(); 934f6f4f843SThomas Lively } 935f6f4f843SThomas Lively 936b7c62394SSam Clegg Error WasmObjectFile::parseRelocSection(StringRef Name, ReadContext &Ctx) { 937b7c62394SSam Clegg uint32_t SectionIndex = readVaruint32(Ctx); 9386f08c84aSSam Clegg if (SectionIndex >= Sections.size()) 93984c6f325SSam Clegg return make_error<GenericBinaryError>("invalid section index", 940d3d84fddSDerek Schuff object_error::parse_failed); 9416f08c84aSSam Clegg WasmSection &Section = Sections[SectionIndex]; 942b7c62394SSam Clegg uint32_t RelocCount = readVaruint32(Ctx); 9436f08c84aSSam Clegg uint32_t EndOffset = Section.Content.size(); 944f77dc2a8SSam Clegg uint32_t PreviousOffset = 0; 945d3d84fddSDerek Schuff while (RelocCount--) { 946b3748f71SNicholas Wilson wasm::WasmRelocation Reloc = {}; 947d75b3719SSam Clegg uint32_t type = readVaruint32(Ctx); 948d75b3719SSam Clegg Reloc.Type = type; 949b7c62394SSam Clegg Reloc.Offset = readVaruint32(Ctx); 950f77dc2a8SSam Clegg if (Reloc.Offset < PreviousOffset) 95184c6f325SSam Clegg return make_error<GenericBinaryError>("relocations not in offset order", 952f77dc2a8SSam Clegg object_error::parse_failed); 953f77dc2a8SSam Clegg PreviousOffset = Reloc.Offset; 954b7c62394SSam Clegg Reloc.Index = readVaruint32(Ctx); 955d75b3719SSam Clegg switch (type) { 956d1152a26SSam Clegg case wasm::R_WASM_FUNCTION_INDEX_LEB: 957d1152a26SSam Clegg case wasm::R_WASM_TABLE_INDEX_SLEB: 958cc1b9b68SWouter van Oortmerssen case wasm::R_WASM_TABLE_INDEX_SLEB64: 959d1152a26SSam Clegg case wasm::R_WASM_TABLE_INDEX_I32: 960cc1b9b68SWouter van Oortmerssen case wasm::R_WASM_TABLE_INDEX_I64: 9612a7cac93SSam Clegg case wasm::R_WASM_TABLE_INDEX_REL_SLEB: 9623a293cbfSWouter van Oortmerssen case wasm::R_WASM_TABLE_INDEX_REL_SLEB64: 963b3748f71SNicholas Wilson if (!isValidFunctionSymbol(Reloc.Index)) 96484c6f325SSam Clegg return make_error<GenericBinaryError>( 96584c6f325SSam Clegg "invalid relocation function index", object_error::parse_failed); 966b3748f71SNicholas Wilson break; 96769e2797eSPaulo Matos case wasm::R_WASM_TABLE_NUMBER_LEB: 96869e2797eSPaulo Matos if (!isValidTableSymbol(Reloc.Index)) 96984c6f325SSam Clegg return make_error<GenericBinaryError>("invalid relocation table index", 97069e2797eSPaulo Matos object_error::parse_failed); 97169e2797eSPaulo Matos break; 972d1152a26SSam Clegg case wasm::R_WASM_TYPE_INDEX_LEB: 973b3748f71SNicholas Wilson if (Reloc.Index >= Signatures.size()) 97484c6f325SSam Clegg return make_error<GenericBinaryError>("invalid relocation type index", 975b3748f71SNicholas Wilson object_error::parse_failed); 976b3748f71SNicholas Wilson break; 977d1152a26SSam Clegg case wasm::R_WASM_GLOBAL_INDEX_LEB: 978492f7529SSam Clegg // R_WASM_GLOBAL_INDEX_LEB are can be used against function and data 9797eacefedSDavid Candler // symbols to refer to their GOT entries. 980492f7529SSam Clegg if (!isValidGlobalSymbol(Reloc.Index) && 981492f7529SSam Clegg !isValidDataSymbol(Reloc.Index) && 982492f7529SSam Clegg !isValidFunctionSymbol(Reloc.Index)) 98384c6f325SSam Clegg return make_error<GenericBinaryError>("invalid relocation global index", 984b3748f71SNicholas Wilson object_error::parse_failed); 985d3d84fddSDerek Schuff break; 98648139ebcSWouter van Oortmerssen case wasm::R_WASM_GLOBAL_INDEX_I32: 98748139ebcSWouter van Oortmerssen if (!isValidGlobalSymbol(Reloc.Index)) 98884c6f325SSam Clegg return make_error<GenericBinaryError>("invalid relocation global index", 98948139ebcSWouter van Oortmerssen object_error::parse_failed); 99048139ebcSWouter van Oortmerssen break; 9911d891d44SHeejin Ahn case wasm::R_WASM_TAG_INDEX_LEB: 9921d891d44SHeejin Ahn if (!isValidTagSymbol(Reloc.Index)) 9931d891d44SHeejin Ahn return make_error<GenericBinaryError>("invalid relocation tag index", 994da419bdbSHeejin Ahn object_error::parse_failed); 995da419bdbSHeejin Ahn break; 996d1152a26SSam Clegg case wasm::R_WASM_MEMORY_ADDR_LEB: 997d1152a26SSam Clegg case wasm::R_WASM_MEMORY_ADDR_SLEB: 998d1152a26SSam Clegg case wasm::R_WASM_MEMORY_ADDR_I32: 9992a7cac93SSam Clegg case wasm::R_WASM_MEMORY_ADDR_REL_SLEB: 1000a28a4662SSam Clegg case wasm::R_WASM_MEMORY_ADDR_TLS_SLEB: 1001aa0c571aSYuta Saito case wasm::R_WASM_MEMORY_ADDR_LOCREL_I32: 1002b3748f71SNicholas Wilson if (!isValidDataSymbol(Reloc.Index)) 100384c6f325SSam Clegg return make_error<GenericBinaryError>("invalid relocation data index", 1004b3748f71SNicholas Wilson object_error::parse_failed); 1005b7c62394SSam Clegg Reloc.Addend = readVarint32(Ctx); 1006d3d84fddSDerek Schuff break; 10073b29376eSWouter van Oortmerssen case wasm::R_WASM_MEMORY_ADDR_LEB64: 10083b29376eSWouter van Oortmerssen case wasm::R_WASM_MEMORY_ADDR_SLEB64: 10093b29376eSWouter van Oortmerssen case wasm::R_WASM_MEMORY_ADDR_I64: 10103b29376eSWouter van Oortmerssen case wasm::R_WASM_MEMORY_ADDR_REL_SLEB64: 1011670944fbSWouter van Oortmerssen case wasm::R_WASM_MEMORY_ADDR_TLS_SLEB64: 10123b29376eSWouter van Oortmerssen if (!isValidDataSymbol(Reloc.Index)) 101384c6f325SSam Clegg return make_error<GenericBinaryError>("invalid relocation data index", 10143b29376eSWouter van Oortmerssen object_error::parse_failed); 10153b29376eSWouter van Oortmerssen Reloc.Addend = readVarint64(Ctx); 10163b29376eSWouter van Oortmerssen break; 1017d1152a26SSam Clegg case wasm::R_WASM_FUNCTION_OFFSET_I32: 10186a31a0d6SSam Clegg if (!isValidFunctionSymbol(Reloc.Index)) 101984c6f325SSam Clegg return make_error<GenericBinaryError>( 102084c6f325SSam Clegg "invalid relocation function index", object_error::parse_failed); 1021b7c62394SSam Clegg Reloc.Addend = readVarint32(Ctx); 10226a31a0d6SSam Clegg break; 102316f02431SWouter van Oortmerssen case wasm::R_WASM_FUNCTION_OFFSET_I64: 102416f02431SWouter van Oortmerssen if (!isValidFunctionSymbol(Reloc.Index)) 102584c6f325SSam Clegg return make_error<GenericBinaryError>( 102684c6f325SSam Clegg "invalid relocation function index", object_error::parse_failed); 102716f02431SWouter van Oortmerssen Reloc.Addend = readVarint64(Ctx); 102816f02431SWouter van Oortmerssen break; 1029d1152a26SSam Clegg case wasm::R_WASM_SECTION_OFFSET_I32: 10306a31a0d6SSam Clegg if (!isValidSectionSymbol(Reloc.Index)) 103184c6f325SSam Clegg return make_error<GenericBinaryError>( 103284c6f325SSam Clegg "invalid relocation section index", object_error::parse_failed); 1033b7c62394SSam Clegg Reloc.Addend = readVarint32(Ctx); 10346a31a0d6SSam Clegg break; 1035d3d84fddSDerek Schuff default: 103684c6f325SSam Clegg return make_error<GenericBinaryError>("invalid relocation type: " + 103784c6f325SSam Clegg Twine(type), 103884c6f325SSam Clegg object_error::parse_failed); 1039d3d84fddSDerek Schuff } 1040b3748f71SNicholas Wilson 1041b3748f71SNicholas Wilson // Relocations must fit inside the section, and must appear in order. They 1042b3748f71SNicholas Wilson // also shouldn't overlap a function/element boundary, but we don't bother 1043b3748f71SNicholas Wilson // to check that. 1044b3748f71SNicholas Wilson uint64_t Size = 5; 10453b29376eSWouter van Oortmerssen if (Reloc.Type == wasm::R_WASM_MEMORY_ADDR_LEB64 || 10463b29376eSWouter van Oortmerssen Reloc.Type == wasm::R_WASM_MEMORY_ADDR_SLEB64 || 10473b29376eSWouter van Oortmerssen Reloc.Type == wasm::R_WASM_MEMORY_ADDR_REL_SLEB64) 10483b29376eSWouter van Oortmerssen Size = 10; 1049d1152a26SSam Clegg if (Reloc.Type == wasm::R_WASM_TABLE_INDEX_I32 || 1050d1152a26SSam Clegg Reloc.Type == wasm::R_WASM_MEMORY_ADDR_I32 || 1051aa0c571aSYuta Saito Reloc.Type == wasm::R_WASM_MEMORY_ADDR_LOCREL_I32 || 1052d1152a26SSam Clegg Reloc.Type == wasm::R_WASM_SECTION_OFFSET_I32 || 105348139ebcSWouter van Oortmerssen Reloc.Type == wasm::R_WASM_FUNCTION_OFFSET_I32 || 105448139ebcSWouter van Oortmerssen Reloc.Type == wasm::R_WASM_GLOBAL_INDEX_I32) 1055b3748f71SNicholas Wilson Size = 4; 1056cc1b9b68SWouter van Oortmerssen if (Reloc.Type == wasm::R_WASM_TABLE_INDEX_I64 || 105716f02431SWouter van Oortmerssen Reloc.Type == wasm::R_WASM_MEMORY_ADDR_I64 || 105816f02431SWouter van Oortmerssen Reloc.Type == wasm::R_WASM_FUNCTION_OFFSET_I64) 10593b29376eSWouter van Oortmerssen Size = 8; 1060fa5a04fbSSam Clegg if (Reloc.Offset + Size > EndOffset) 106184c6f325SSam Clegg return make_error<GenericBinaryError>("invalid relocation offset", 1062b3748f71SNicholas Wilson object_error::parse_failed); 1063b3748f71SNicholas Wilson 10646f08c84aSSam Clegg Section.Relocations.push_back(Reloc); 1065d3d84fddSDerek Schuff } 1066b7c62394SSam Clegg if (Ctx.Ptr != Ctx.End) 106784c6f325SSam Clegg return make_error<GenericBinaryError>("reloc section ended prematurely", 1068d3d84fddSDerek Schuff object_error::parse_failed); 1069d3d84fddSDerek Schuff return Error::success(); 1070d3d84fddSDerek Schuff } 1071d3d84fddSDerek Schuff 1072b7c62394SSam Clegg Error WasmObjectFile::parseCustomSection(WasmSection &Sec, ReadContext &Ctx) { 1073e4afbc68SSam Clegg if (Sec.Name == "dylink") { 1074e4afbc68SSam Clegg if (Error Err = parseDylinkSection(Ctx)) 1075e4afbc68SSam Clegg return Err; 1076b78c85a4SSam Clegg } else if (Sec.Name == "dylink.0") { 1077b78c85a4SSam Clegg if (Error Err = parseDylink0Section(Ctx)) 1078b78c85a4SSam Clegg return Err; 1079e4afbc68SSam Clegg } else if (Sec.Name == "name") { 1080b7c62394SSam Clegg if (Error Err = parseNameSection(Ctx)) 1081d3d84fddSDerek Schuff return Err; 1082b7787fd0SSam Clegg } else if (Sec.Name == "linking") { 1083b7c62394SSam Clegg if (Error Err = parseLinkingSection(Ctx)) 1084b7787fd0SSam Clegg return Err; 1085cbda16ebSThomas Lively } else if (Sec.Name == "producers") { 1086cbda16ebSThomas Lively if (Error Err = parseProducersSection(Ctx)) 1087cbda16ebSThomas Lively return Err; 1088f6f4f843SThomas Lively } else if (Sec.Name == "target_features") { 1089f6f4f843SThomas Lively if (Error Err = parseTargetFeaturesSection(Ctx)) 1090f6f4f843SThomas Lively return Err; 1091d3d84fddSDerek Schuff } else if (Sec.Name.startswith("reloc.")) { 1092b7c62394SSam Clegg if (Error Err = parseRelocSection(Sec.Name, Ctx)) 1093d3d84fddSDerek Schuff return Err; 1094d3d84fddSDerek Schuff } 1095d3d84fddSDerek Schuff return Error::success(); 1096d3d84fddSDerek Schuff } 1097d3d84fddSDerek Schuff 1098b7c62394SSam Clegg Error WasmObjectFile::parseTypeSection(ReadContext &Ctx) { 1099b7c62394SSam Clegg uint32_t Count = readVaruint32(Ctx); 1100d3d84fddSDerek Schuff Signatures.reserve(Count); 1101d3d84fddSDerek Schuff while (Count--) { 1102d3d84fddSDerek Schuff wasm::WasmSignature Sig; 1103b7c62394SSam Clegg uint8_t Form = readUint8(Ctx); 1104d3d84fddSDerek Schuff if (Form != wasm::WASM_TYPE_FUNC) { 110584c6f325SSam Clegg return make_error<GenericBinaryError>("invalid signature type", 1106d3d84fddSDerek Schuff object_error::parse_failed); 1107d3d84fddSDerek Schuff } 1108b7c62394SSam Clegg uint32_t ParamCount = readVaruint32(Ctx); 110977a7a380SDerek Schuff Sig.Params.reserve(ParamCount); 1110d3d84fddSDerek Schuff while (ParamCount--) { 1111b7c62394SSam Clegg uint32_t ParamType = readUint8(Ctx); 111277a7a380SDerek Schuff Sig.Params.push_back(wasm::ValType(ParamType)); 1113d3d84fddSDerek Schuff } 1114b7c62394SSam Clegg uint32_t ReturnCount = readVaruint32(Ctx); 1115393d0f79SThomas Lively while (ReturnCount--) { 1116393d0f79SThomas Lively uint32_t ReturnType = readUint8(Ctx); 1117393d0f79SThomas Lively Sig.Returns.push_back(wasm::ValType(ReturnType)); 1118d3d84fddSDerek Schuff } 111977a7a380SDerek Schuff Signatures.push_back(std::move(Sig)); 1120d3d84fddSDerek Schuff } 1121b7c62394SSam Clegg if (Ctx.Ptr != Ctx.End) 112284c6f325SSam Clegg return make_error<GenericBinaryError>("type section ended prematurely", 1123d3d84fddSDerek Schuff object_error::parse_failed); 1124d3d84fddSDerek Schuff return Error::success(); 1125d3d84fddSDerek Schuff } 1126d3d84fddSDerek Schuff 1127b7c62394SSam Clegg Error WasmObjectFile::parseImportSection(ReadContext &Ctx) { 1128b7c62394SSam Clegg uint32_t Count = readVaruint32(Ctx); 11293ec1760dSHeejin Ahn uint32_t NumTypes = Signatures.size(); 1130d3d84fddSDerek Schuff Imports.reserve(Count); 113118c56a07SHeejin Ahn for (uint32_t I = 0; I < Count; I++) { 1132d3d84fddSDerek Schuff wasm::WasmImport Im; 1133b7c62394SSam Clegg Im.Module = readString(Ctx); 1134b7c62394SSam Clegg Im.Field = readString(Ctx); 1135b7c62394SSam Clegg Im.Kind = readUint8(Ctx); 1136d3d84fddSDerek Schuff switch (Im.Kind) { 1137d3d84fddSDerek Schuff case wasm::WASM_EXTERNAL_FUNCTION: 1138a3b9fe6aSSam Clegg NumImportedFunctions++; 1139b7c62394SSam Clegg Im.SigIndex = readVaruint32(Ctx); 11403ec1760dSHeejin Ahn if (Im.SigIndex >= NumTypes) 11413ec1760dSHeejin Ahn return make_error<GenericBinaryError>("invalid function type", 11423ec1760dSHeejin Ahn object_error::parse_failed); 1143d3d84fddSDerek Schuff break; 1144d3d84fddSDerek Schuff case wasm::WASM_EXTERNAL_GLOBAL: 1145a3b9fe6aSSam Clegg NumImportedGlobals++; 1146b7c62394SSam Clegg Im.Global.Type = readUint8(Ctx); 1147b7c62394SSam Clegg Im.Global.Mutable = readVaruint1(Ctx); 1148d3d84fddSDerek Schuff break; 11492ffff5afSSam Clegg case wasm::WASM_EXTERNAL_MEMORY: 1150b7c62394SSam Clegg Im.Memory = readLimits(Ctx); 115129f8c9f6SWouter van Oortmerssen if (Im.Memory.Flags & wasm::WASM_LIMITS_FLAG_IS_64) 115229f8c9f6SWouter van Oortmerssen HasMemory64 = true; 11532ffff5afSSam Clegg break; 1154388fb67bSPaulo Matos case wasm::WASM_EXTERNAL_TABLE: { 11551933c9d4SAndy Wingo Im.Table = readTableType(Ctx); 1156388fb67bSPaulo Matos NumImportedTables++; 1157388fb67bSPaulo Matos auto ElemType = Im.Table.ElemType; 1158388fb67bSPaulo Matos if (ElemType != wasm::WASM_TYPE_FUNCREF && 1159388fb67bSPaulo Matos ElemType != wasm::WASM_TYPE_EXTERNREF) 116084c6f325SSam Clegg return make_error<GenericBinaryError>("invalid table element type", 11612ffff5afSSam Clegg object_error::parse_failed); 11622ffff5afSSam Clegg break; 1163388fb67bSPaulo Matos } 11641d891d44SHeejin Ahn case wasm::WASM_EXTERNAL_TAG: 11651d891d44SHeejin Ahn NumImportedTags++; 11669261ee32SHeejin Ahn if (readUint8(Ctx) != 0) // Reserved 'attribute' field 11679261ee32SHeejin Ahn return make_error<GenericBinaryError>("invalid attribute", 11689261ee32SHeejin Ahn object_error::parse_failed); 11693ec1760dSHeejin Ahn Im.SigIndex = readVaruint32(Ctx); 11703ec1760dSHeejin Ahn if (Im.SigIndex >= NumTypes) 11713ec1760dSHeejin Ahn return make_error<GenericBinaryError>("invalid tag type", 11723ec1760dSHeejin Ahn object_error::parse_failed); 1173da419bdbSHeejin Ahn break; 1174d3d84fddSDerek Schuff default: 117584c6f325SSam Clegg return make_error<GenericBinaryError>("unexpected import kind", 1176f208f631SHeejin Ahn object_error::parse_failed); 1177d3d84fddSDerek Schuff } 1178d3d84fddSDerek Schuff Imports.push_back(Im); 1179d3d84fddSDerek Schuff } 1180b7c62394SSam Clegg if (Ctx.Ptr != Ctx.End) 118184c6f325SSam Clegg return make_error<GenericBinaryError>("import section ended prematurely", 1182d3d84fddSDerek Schuff object_error::parse_failed); 1183d3d84fddSDerek Schuff return Error::success(); 1184d3d84fddSDerek Schuff } 1185d3d84fddSDerek Schuff 1186b7c62394SSam Clegg Error WasmObjectFile::parseFunctionSection(ReadContext &Ctx) { 1187b7c62394SSam Clegg uint32_t Count = readVaruint32(Ctx); 1188c0039de2SSam Clegg Functions.reserve(Count); 11893b825105SNicholas Wilson uint32_t NumTypes = Signatures.size(); 1190d3d84fddSDerek Schuff while (Count--) { 1191b7c62394SSam Clegg uint32_t Type = readVaruint32(Ctx); 11923b825105SNicholas Wilson if (Type >= NumTypes) 119384c6f325SSam Clegg return make_error<GenericBinaryError>("invalid function type", 11943b825105SNicholas Wilson object_error::parse_failed); 1195c0039de2SSam Clegg wasm::WasmFunction F; 1196c0039de2SSam Clegg F.SigIndex = Type; 1197c0039de2SSam Clegg Functions.push_back(F); 1198d3d84fddSDerek Schuff } 1199b7c62394SSam Clegg if (Ctx.Ptr != Ctx.End) 120084c6f325SSam Clegg return make_error<GenericBinaryError>("function section ended prematurely", 1201d3d84fddSDerek Schuff object_error::parse_failed); 1202d3d84fddSDerek Schuff return Error::success(); 1203d3d84fddSDerek Schuff } 1204d3d84fddSDerek Schuff 1205b7c62394SSam Clegg Error WasmObjectFile::parseTableSection(ReadContext &Ctx) { 1206feac819eSAndy Wingo TableSection = Sections.size(); 1207b7c62394SSam Clegg uint32_t Count = readVaruint32(Ctx); 1208d3d84fddSDerek Schuff Tables.reserve(Count); 1209d3d84fddSDerek Schuff while (Count--) { 12101933c9d4SAndy Wingo wasm::WasmTable T; 12111933c9d4SAndy Wingo T.Type = readTableType(Ctx); 1212388fb67bSPaulo Matos T.Index = NumImportedTables + Tables.size(); 1213388fb67bSPaulo Matos Tables.push_back(T); 12141933c9d4SAndy Wingo auto ElemType = Tables.back().Type.ElemType; 1215388fb67bSPaulo Matos if (ElemType != wasm::WASM_TYPE_FUNCREF && 1216388fb67bSPaulo Matos ElemType != wasm::WASM_TYPE_EXTERNREF) { 121784c6f325SSam Clegg return make_error<GenericBinaryError>("invalid table element type", 1218d3d84fddSDerek Schuff object_error::parse_failed); 1219d3d84fddSDerek Schuff } 1220d3d84fddSDerek Schuff } 1221b7c62394SSam Clegg if (Ctx.Ptr != Ctx.End) 122284c6f325SSam Clegg return make_error<GenericBinaryError>("table section ended prematurely", 1223d3d84fddSDerek Schuff object_error::parse_failed); 1224d3d84fddSDerek Schuff return Error::success(); 1225d3d84fddSDerek Schuff } 1226d3d84fddSDerek Schuff 1227b7c62394SSam Clegg Error WasmObjectFile::parseMemorySection(ReadContext &Ctx) { 1228b7c62394SSam Clegg uint32_t Count = readVaruint32(Ctx); 1229d3d84fddSDerek Schuff Memories.reserve(Count); 1230d3d84fddSDerek Schuff while (Count--) { 123129f8c9f6SWouter van Oortmerssen auto Limits = readLimits(Ctx); 123229f8c9f6SWouter van Oortmerssen if (Limits.Flags & wasm::WASM_LIMITS_FLAG_IS_64) 123329f8c9f6SWouter van Oortmerssen HasMemory64 = true; 123429f8c9f6SWouter van Oortmerssen Memories.push_back(Limits); 1235d3d84fddSDerek Schuff } 1236b7c62394SSam Clegg if (Ctx.Ptr != Ctx.End) 123784c6f325SSam Clegg return make_error<GenericBinaryError>("memory section ended prematurely", 1238d3d84fddSDerek Schuff object_error::parse_failed); 1239d3d84fddSDerek Schuff return Error::success(); 1240d3d84fddSDerek Schuff } 1241d3d84fddSDerek Schuff 12421d891d44SHeejin Ahn Error WasmObjectFile::parseTagSection(ReadContext &Ctx) { 12431d891d44SHeejin Ahn TagSection = Sections.size(); 1244144ec1c3SHeejin Ahn uint32_t Count = readVaruint32(Ctx); 12451d891d44SHeejin Ahn Tags.reserve(Count); 12463ec1760dSHeejin Ahn uint32_t NumTypes = Signatures.size(); 1247f93426c5SHeejin Ahn while (Count--) { 12489261ee32SHeejin Ahn if (readUint8(Ctx) != 0) // Reserved 'attribute' field 12493ec1760dSHeejin Ahn return make_error<GenericBinaryError>("invalid attribute", 12503ec1760dSHeejin Ahn object_error::parse_failed); 12513ec1760dSHeejin Ahn uint32_t Type = readVaruint32(Ctx); 12523ec1760dSHeejin Ahn if (Type >= NumTypes) 12533ec1760dSHeejin Ahn return make_error<GenericBinaryError>("invalid tag type", 12543ec1760dSHeejin Ahn object_error::parse_failed); 12551d891d44SHeejin Ahn wasm::WasmTag Tag; 12561d891d44SHeejin Ahn Tag.Index = NumImportedTags + Tags.size(); 12573ec1760dSHeejin Ahn Tag.SigIndex = Type; 12581d891d44SHeejin Ahn Tags.push_back(Tag); 1259f93426c5SHeejin Ahn } 1260f93426c5SHeejin Ahn 1261f93426c5SHeejin Ahn if (Ctx.Ptr != Ctx.End) 12621d891d44SHeejin Ahn return make_error<GenericBinaryError>("tag section ended prematurely", 1263f93426c5SHeejin Ahn object_error::parse_failed); 1264f93426c5SHeejin Ahn return Error::success(); 1265f93426c5SHeejin Ahn } 1266f93426c5SHeejin Ahn 1267b7c62394SSam Clegg Error WasmObjectFile::parseGlobalSection(ReadContext &Ctx) { 12686c899ba6SSam Clegg GlobalSection = Sections.size(); 1269b7c62394SSam Clegg uint32_t Count = readVaruint32(Ctx); 1270d3d84fddSDerek Schuff Globals.reserve(Count); 1271d3d84fddSDerek Schuff while (Count--) { 1272d3d84fddSDerek Schuff wasm::WasmGlobal Global; 1273e53af7f6SSam Clegg Global.Index = NumImportedGlobals + Globals.size(); 1274b7c62394SSam Clegg Global.Type.Type = readUint8(Ctx); 1275b7c62394SSam Clegg Global.Type.Mutable = readVaruint1(Ctx); 1276b7c62394SSam Clegg if (Error Err = readInitExpr(Global.InitExpr, Ctx)) 1277d3d84fddSDerek Schuff return Err; 1278d3d84fddSDerek Schuff Globals.push_back(Global); 1279d3d84fddSDerek Schuff } 1280b7c62394SSam Clegg if (Ctx.Ptr != Ctx.End) 128184c6f325SSam Clegg return make_error<GenericBinaryError>("global section ended prematurely", 1282d3d84fddSDerek Schuff object_error::parse_failed); 1283d3d84fddSDerek Schuff return Error::success(); 1284d3d84fddSDerek Schuff } 1285d3d84fddSDerek Schuff 1286b7c62394SSam Clegg Error WasmObjectFile::parseExportSection(ReadContext &Ctx) { 1287b7c62394SSam Clegg uint32_t Count = readVaruint32(Ctx); 1288d3d84fddSDerek Schuff Exports.reserve(Count); 128918c56a07SHeejin Ahn for (uint32_t I = 0; I < Count; I++) { 1290d3d84fddSDerek Schuff wasm::WasmExport Ex; 1291b7c62394SSam Clegg Ex.Name = readString(Ctx); 1292b7c62394SSam Clegg Ex.Kind = readUint8(Ctx); 1293b7c62394SSam Clegg Ex.Index = readVaruint32(Ctx); 1294d3d84fddSDerek Schuff switch (Ex.Kind) { 1295d3d84fddSDerek Schuff case wasm::WASM_EXTERNAL_FUNCTION: 1296881d8778SSam Clegg 1297881d8778SSam Clegg if (!isDefinedFunctionIndex(Ex.Index)) 129884c6f325SSam Clegg return make_error<GenericBinaryError>("invalid function export", 1299a3b9fe6aSSam Clegg object_error::parse_failed); 1300881d8778SSam Clegg getDefinedFunction(Ex.Index).ExportName = Ex.Name; 1301d3d84fddSDerek Schuff break; 13026c899ba6SSam Clegg case wasm::WASM_EXTERNAL_GLOBAL: 13036c899ba6SSam Clegg if (!isValidGlobalIndex(Ex.Index)) 130484c6f325SSam Clegg return make_error<GenericBinaryError>("invalid global export", 1305a3b9fe6aSSam Clegg object_error::parse_failed); 1306d3d84fddSDerek Schuff break; 13071d891d44SHeejin Ahn case wasm::WASM_EXTERNAL_TAG: 13081d891d44SHeejin Ahn if (!isValidTagIndex(Ex.Index)) 13091d891d44SHeejin Ahn return make_error<GenericBinaryError>("invalid tag export", 1310da419bdbSHeejin Ahn object_error::parse_failed); 1311da419bdbSHeejin Ahn break; 13122ffff5afSSam Clegg case wasm::WASM_EXTERNAL_MEMORY: 13132ffff5afSSam Clegg case wasm::WASM_EXTERNAL_TABLE: 13142ffff5afSSam Clegg break; 1315d3d84fddSDerek Schuff default: 131684c6f325SSam Clegg return make_error<GenericBinaryError>("unexpected export kind", 1317f208f631SHeejin Ahn object_error::parse_failed); 1318d3d84fddSDerek Schuff } 1319b7787fd0SSam Clegg Exports.push_back(Ex); 1320d3d84fddSDerek Schuff } 1321b7c62394SSam Clegg if (Ctx.Ptr != Ctx.End) 132284c6f325SSam Clegg return make_error<GenericBinaryError>("export section ended prematurely", 1323d3d84fddSDerek Schuff object_error::parse_failed); 1324d3d84fddSDerek Schuff return Error::success(); 1325d3d84fddSDerek Schuff } 1326d3d84fddSDerek Schuff 13274273998cSSam Clegg bool WasmObjectFile::isValidFunctionIndex(uint32_t Index) const { 1328c0039de2SSam Clegg return Index < NumImportedFunctions + Functions.size(); 13294273998cSSam Clegg } 13304273998cSSam Clegg 133123012e98SSam Clegg bool WasmObjectFile::isDefinedFunctionIndex(uint32_t Index) const { 133223012e98SSam Clegg return Index >= NumImportedFunctions && isValidFunctionIndex(Index); 133323012e98SSam Clegg } 133423012e98SSam Clegg 13356c899ba6SSam Clegg bool WasmObjectFile::isValidGlobalIndex(uint32_t Index) const { 13366c899ba6SSam Clegg return Index < NumImportedGlobals + Globals.size(); 13376c899ba6SSam Clegg } 13386c899ba6SSam Clegg 1339a5a3659dSAndy Wingo bool WasmObjectFile::isValidTableNumber(uint32_t Index) const { 1340388fb67bSPaulo Matos return Index < NumImportedTables + Tables.size(); 1341388fb67bSPaulo Matos } 1342388fb67bSPaulo Matos 13436c899ba6SSam Clegg bool WasmObjectFile::isDefinedGlobalIndex(uint32_t Index) const { 13446c899ba6SSam Clegg return Index >= NumImportedGlobals && isValidGlobalIndex(Index); 13456c899ba6SSam Clegg } 13466c899ba6SSam Clegg 1347a5a3659dSAndy Wingo bool WasmObjectFile::isDefinedTableNumber(uint32_t Index) const { 1348a5a3659dSAndy Wingo return Index >= NumImportedTables && isValidTableNumber(Index); 1349388fb67bSPaulo Matos } 1350388fb67bSPaulo Matos 13511d891d44SHeejin Ahn bool WasmObjectFile::isValidTagIndex(uint32_t Index) const { 13521d891d44SHeejin Ahn return Index < NumImportedTags + Tags.size(); 1353da419bdbSHeejin Ahn } 1354da419bdbSHeejin Ahn 13551d891d44SHeejin Ahn bool WasmObjectFile::isDefinedTagIndex(uint32_t Index) const { 13561d891d44SHeejin Ahn return Index >= NumImportedTags && isValidTagIndex(Index); 1357da419bdbSHeejin Ahn } 1358da419bdbSHeejin Ahn 1359b3748f71SNicholas Wilson bool WasmObjectFile::isValidFunctionSymbol(uint32_t Index) const { 13606c899ba6SSam Clegg return Index < Symbols.size() && Symbols[Index].isTypeFunction(); 13616c899ba6SSam Clegg } 13626c899ba6SSam Clegg 136369e2797eSPaulo Matos bool WasmObjectFile::isValidTableSymbol(uint32_t Index) const { 136469e2797eSPaulo Matos return Index < Symbols.size() && Symbols[Index].isTypeTable(); 136569e2797eSPaulo Matos } 136669e2797eSPaulo Matos 1367b3748f71SNicholas Wilson bool WasmObjectFile::isValidGlobalSymbol(uint32_t Index) const { 1368b3748f71SNicholas Wilson return Index < Symbols.size() && Symbols[Index].isTypeGlobal(); 1369b3748f71SNicholas Wilson } 1370b3748f71SNicholas Wilson 13711d891d44SHeejin Ahn bool WasmObjectFile::isValidTagSymbol(uint32_t Index) const { 13721d891d44SHeejin Ahn return Index < Symbols.size() && Symbols[Index].isTypeTag(); 1373da419bdbSHeejin Ahn } 1374da419bdbSHeejin Ahn 1375b3748f71SNicholas Wilson bool WasmObjectFile::isValidDataSymbol(uint32_t Index) const { 1376b3748f71SNicholas Wilson return Index < Symbols.size() && Symbols[Index].isTypeData(); 1377b3748f71SNicholas Wilson } 1378b3748f71SNicholas Wilson 13796a31a0d6SSam Clegg bool WasmObjectFile::isValidSectionSymbol(uint32_t Index) const { 13806a31a0d6SSam Clegg return Index < Symbols.size() && Symbols[Index].isTypeSection(); 13816a31a0d6SSam Clegg } 13826a31a0d6SSam Clegg 138323012e98SSam Clegg wasm::WasmFunction &WasmObjectFile::getDefinedFunction(uint32_t Index) { 138423012e98SSam Clegg assert(isDefinedFunctionIndex(Index)); 138523012e98SSam Clegg return Functions[Index - NumImportedFunctions]; 138623012e98SSam Clegg } 138723012e98SSam Clegg 1388f3b762a0SWouter van Oortmerssen const wasm::WasmFunction & 1389f3b762a0SWouter van Oortmerssen WasmObjectFile::getDefinedFunction(uint32_t Index) const { 1390f3b762a0SWouter van Oortmerssen assert(isDefinedFunctionIndex(Index)); 1391f3b762a0SWouter van Oortmerssen return Functions[Index - NumImportedFunctions]; 1392f3b762a0SWouter van Oortmerssen } 1393f3b762a0SWouter van Oortmerssen 13946c899ba6SSam Clegg wasm::WasmGlobal &WasmObjectFile::getDefinedGlobal(uint32_t Index) { 13956c899ba6SSam Clegg assert(isDefinedGlobalIndex(Index)); 13966c899ba6SSam Clegg return Globals[Index - NumImportedGlobals]; 13976c899ba6SSam Clegg } 13986c899ba6SSam Clegg 13991d891d44SHeejin Ahn wasm::WasmTag &WasmObjectFile::getDefinedTag(uint32_t Index) { 14001d891d44SHeejin Ahn assert(isDefinedTagIndex(Index)); 14011d891d44SHeejin Ahn return Tags[Index - NumImportedTags]; 1402da419bdbSHeejin Ahn } 1403da419bdbSHeejin Ahn 1404b7c62394SSam Clegg Error WasmObjectFile::parseStartSection(ReadContext &Ctx) { 1405b7c62394SSam Clegg StartFunction = readVaruint32(Ctx); 14064273998cSSam Clegg if (!isValidFunctionIndex(StartFunction)) 140784c6f325SSam Clegg return make_error<GenericBinaryError>("invalid start function", 1408d3d84fddSDerek Schuff object_error::parse_failed); 1409d3d84fddSDerek Schuff return Error::success(); 1410d3d84fddSDerek Schuff } 1411d3d84fddSDerek Schuff 1412b7c62394SSam Clegg Error WasmObjectFile::parseCodeSection(ReadContext &Ctx) { 1413881d8778SSam Clegg SeenCodeSection = true; 14140b55ccf6SSam Clegg CodeSection = Sections.size(); 1415b7c62394SSam Clegg uint32_t FunctionCount = readVaruint32(Ctx); 1416c0039de2SSam Clegg if (FunctionCount != Functions.size()) { 141784c6f325SSam Clegg return make_error<GenericBinaryError>("invalid function count", 1418d3d84fddSDerek Schuff object_error::parse_failed); 1419d3d84fddSDerek Schuff } 1420d3d84fddSDerek Schuff 1421881d8778SSam Clegg for (uint32_t i = 0; i < FunctionCount; i++) { 1422881d8778SSam Clegg wasm::WasmFunction& Function = Functions[i]; 1423b7c62394SSam Clegg const uint8_t *FunctionStart = Ctx.Ptr; 1424b7c62394SSam Clegg uint32_t Size = readVaruint32(Ctx); 1425b7c62394SSam Clegg const uint8_t *FunctionEnd = Ctx.Ptr + Size; 1426c551522dSSam Clegg 1427b7c62394SSam Clegg Function.CodeOffset = Ctx.Ptr - FunctionStart; 1428881d8778SSam Clegg Function.Index = NumImportedFunctions + i; 1429b7c62394SSam Clegg Function.CodeSectionOffset = FunctionStart - Ctx.Start; 1430c551522dSSam Clegg Function.Size = FunctionEnd - FunctionStart; 1431d3d84fddSDerek Schuff 1432b7c62394SSam Clegg uint32_t NumLocalDecls = readVaruint32(Ctx); 1433d3d84fddSDerek Schuff Function.Locals.reserve(NumLocalDecls); 1434d3d84fddSDerek Schuff while (NumLocalDecls--) { 1435d3d84fddSDerek Schuff wasm::WasmLocalDecl Decl; 1436b7c62394SSam Clegg Decl.Count = readVaruint32(Ctx); 1437b7c62394SSam Clegg Decl.Type = readUint8(Ctx); 1438d3d84fddSDerek Schuff Function.Locals.push_back(Decl); 1439d3d84fddSDerek Schuff } 1440d3d84fddSDerek Schuff 1441b7c62394SSam Clegg uint32_t BodySize = FunctionEnd - Ctx.Ptr; 1442b7c62394SSam Clegg Function.Body = ArrayRef<uint8_t>(Ctx.Ptr, BodySize); 1443027b9357SNicholas Wilson // This will be set later when reading in the linking metadata section. 1444027b9357SNicholas Wilson Function.Comdat = UINT32_MAX; 1445b7c62394SSam Clegg Ctx.Ptr += BodySize; 1446b7c62394SSam Clegg assert(Ctx.Ptr == FunctionEnd); 1447d3d84fddSDerek Schuff } 1448b7c62394SSam Clegg if (Ctx.Ptr != Ctx.End) 144984c6f325SSam Clegg return make_error<GenericBinaryError>("code section ended prematurely", 1450d3d84fddSDerek Schuff object_error::parse_failed); 1451d3d84fddSDerek Schuff return Error::success(); 1452d3d84fddSDerek Schuff } 1453d3d84fddSDerek Schuff 1454b7c62394SSam Clegg Error WasmObjectFile::parseElemSection(ReadContext &Ctx) { 1455b7c62394SSam Clegg uint32_t Count = readVaruint32(Ctx); 1456d3d84fddSDerek Schuff ElemSegments.reserve(Count); 1457d3d84fddSDerek Schuff while (Count--) { 1458d3d84fddSDerek Schuff wasm::WasmElemSegment Segment; 1459a5a3659dSAndy Wingo Segment.Flags = readVaruint32(Ctx); 1460a5a3659dSAndy Wingo 1461a5a3659dSAndy Wingo uint32_t SupportedFlags = wasm::WASM_ELEM_SEGMENT_HAS_TABLE_NUMBER | 1462a5a3659dSAndy Wingo wasm::WASM_ELEM_SEGMENT_IS_PASSIVE | 1463a5a3659dSAndy Wingo wasm::WASM_ELEM_SEGMENT_HAS_INIT_EXPRS; 1464a5a3659dSAndy Wingo if (Segment.Flags & ~SupportedFlags) 1465a5a3659dSAndy Wingo return make_error<GenericBinaryError>( 1466a5a3659dSAndy Wingo "Unsupported flags for element segment", object_error::parse_failed); 1467a5a3659dSAndy Wingo 1468a5a3659dSAndy Wingo if (Segment.Flags & wasm::WASM_ELEM_SEGMENT_HAS_TABLE_NUMBER) 1469a5a3659dSAndy Wingo Segment.TableNumber = readVaruint32(Ctx); 1470a5a3659dSAndy Wingo else 1471a5a3659dSAndy Wingo Segment.TableNumber = 0; 1472a5a3659dSAndy Wingo if (!isValidTableNumber(Segment.TableNumber)) 1473a5a3659dSAndy Wingo return make_error<GenericBinaryError>("invalid TableNumber", 1474d3d84fddSDerek Schuff object_error::parse_failed); 1475a5a3659dSAndy Wingo 1476a5a3659dSAndy Wingo if (Segment.Flags & wasm::WASM_ELEM_SEGMENT_IS_PASSIVE) { 14772481adb5SSam Clegg Segment.Offset.Extended = false; 14789504ab32SSam Clegg Segment.Offset.Inst.Opcode = wasm::WASM_OPCODE_I32_CONST; 14799504ab32SSam Clegg Segment.Offset.Inst.Value.Int32 = 0; 1480a5a3659dSAndy Wingo } else { 1481b7c62394SSam Clegg if (Error Err = readInitExpr(Segment.Offset, Ctx)) 1482d3d84fddSDerek Schuff return Err; 1483a5a3659dSAndy Wingo } 1484a5a3659dSAndy Wingo 1485a5a3659dSAndy Wingo if (Segment.Flags & wasm::WASM_ELEM_SEGMENT_MASK_HAS_ELEM_KIND) { 1486a5a3659dSAndy Wingo Segment.ElemKind = readUint8(Ctx); 1487a5a3659dSAndy Wingo if (Segment.Flags & wasm::WASM_ELEM_SEGMENT_HAS_INIT_EXPRS) { 1488a5a3659dSAndy Wingo if (Segment.ElemKind != uint8_t(wasm::ValType::FUNCREF) && 1489a5a3659dSAndy Wingo Segment.ElemKind != uint8_t(wasm::ValType::EXTERNREF)) { 1490a5a3659dSAndy Wingo return make_error<GenericBinaryError>("invalid reference type", 1491a5a3659dSAndy Wingo object_error::parse_failed); 1492a5a3659dSAndy Wingo } 1493a5a3659dSAndy Wingo } else { 1494a5a3659dSAndy Wingo if (Segment.ElemKind != 0) 1495a5a3659dSAndy Wingo return make_error<GenericBinaryError>("invalid elemtype", 1496a5a3659dSAndy Wingo object_error::parse_failed); 1497a5a3659dSAndy Wingo Segment.ElemKind = uint8_t(wasm::ValType::FUNCREF); 1498a5a3659dSAndy Wingo } 1499a5a3659dSAndy Wingo } else { 1500a5a3659dSAndy Wingo Segment.ElemKind = uint8_t(wasm::ValType::FUNCREF); 1501a5a3659dSAndy Wingo } 1502a5a3659dSAndy Wingo 1503a5a3659dSAndy Wingo if (Segment.Flags & wasm::WASM_ELEM_SEGMENT_HAS_INIT_EXPRS) 1504a5a3659dSAndy Wingo return make_error<GenericBinaryError>( 1505a5a3659dSAndy Wingo "elem segment init expressions not yet implemented", 1506a5a3659dSAndy Wingo object_error::parse_failed); 1507a5a3659dSAndy Wingo 1508b7c62394SSam Clegg uint32_t NumElems = readVaruint32(Ctx); 1509d3d84fddSDerek Schuff while (NumElems--) { 1510b7c62394SSam Clegg Segment.Functions.push_back(readVaruint32(Ctx)); 1511d3d84fddSDerek Schuff } 1512d3d84fddSDerek Schuff ElemSegments.push_back(Segment); 1513d3d84fddSDerek Schuff } 1514b7c62394SSam Clegg if (Ctx.Ptr != Ctx.End) 151584c6f325SSam Clegg return make_error<GenericBinaryError>("elem section ended prematurely", 1516d3d84fddSDerek Schuff object_error::parse_failed); 1517d3d84fddSDerek Schuff return Error::success(); 1518d3d84fddSDerek Schuff } 1519d3d84fddSDerek Schuff 1520b7c62394SSam Clegg Error WasmObjectFile::parseDataSection(ReadContext &Ctx) { 15210b55ccf6SSam Clegg DataSection = Sections.size(); 1522b7c62394SSam Clegg uint32_t Count = readVaruint32(Ctx); 1523fef8de66SThomas Lively if (DataCount && Count != DataCount.getValue()) 1524fef8de66SThomas Lively return make_error<GenericBinaryError>( 152584c6f325SSam Clegg "number of data segments does not match DataCount section"); 1526d3d84fddSDerek Schuff DataSegments.reserve(Count); 1527d3d84fddSDerek Schuff while (Count--) { 15289c07f94aSSam Clegg WasmSegment Segment; 15292e150409SThomas Lively Segment.Data.InitFlags = readVaruint32(Ctx); 1530831a143eSAndy Wingo Segment.Data.MemoryIndex = 1531831a143eSAndy Wingo (Segment.Data.InitFlags & wasm::WASM_DATA_SEGMENT_HAS_MEMINDEX) 1532831a143eSAndy Wingo ? readVaruint32(Ctx) 1533831a143eSAndy Wingo : 0; 1534831a143eSAndy Wingo if ((Segment.Data.InitFlags & wasm::WASM_DATA_SEGMENT_IS_PASSIVE) == 0) { 1535b7c62394SSam Clegg if (Error Err = readInitExpr(Segment.Data.Offset, Ctx)) 1536d3d84fddSDerek Schuff return Err; 15372e150409SThomas Lively } else { 15389b27fbd1SSam Clegg Segment.Data.Offset.Extended = false; 15399504ab32SSam Clegg Segment.Data.Offset.Inst.Opcode = wasm::WASM_OPCODE_I32_CONST; 15409504ab32SSam Clegg Segment.Data.Offset.Inst.Value.Int32 = 0; 15412e150409SThomas Lively } 1542b7c62394SSam Clegg uint32_t Size = readVaruint32(Ctx); 1543dcf5bd27SSimon Pilgrim if (Size > (size_t)(Ctx.End - Ctx.Ptr)) 154484c6f325SSam Clegg return make_error<GenericBinaryError>("invalid segment size", 15454bbc6b55SSam Clegg object_error::parse_failed); 1546b7c62394SSam Clegg Segment.Data.Content = ArrayRef<uint8_t>(Ctx.Ptr, Size); 1547027b9357SNicholas Wilson // The rest of these Data fields are set later, when reading in the linking 1548027b9357SNicholas Wilson // metadata section. 154963ebb813SSam Clegg Segment.Data.Alignment = 0; 15503b8d2be5SSam Clegg Segment.Data.LinkingFlags = 0; 1551027b9357SNicholas Wilson Segment.Data.Comdat = UINT32_MAX; 1552b7c62394SSam Clegg Segment.SectionOffset = Ctx.Ptr - Ctx.Start; 1553b7c62394SSam Clegg Ctx.Ptr += Size; 1554d3d84fddSDerek Schuff DataSegments.push_back(Segment); 1555d3d84fddSDerek Schuff } 1556b7c62394SSam Clegg if (Ctx.Ptr != Ctx.End) 155784c6f325SSam Clegg return make_error<GenericBinaryError>("data section ended prematurely", 1558d3d84fddSDerek Schuff object_error::parse_failed); 15592c6f75ddSDerek Schuff return Error::success(); 15602c6f75ddSDerek Schuff } 15612c6f75ddSDerek Schuff 1562fef8de66SThomas Lively Error WasmObjectFile::parseDataCountSection(ReadContext &Ctx) { 1563fef8de66SThomas Lively DataCount = readVaruint32(Ctx); 1564fef8de66SThomas Lively return Error::success(); 1565fef8de66SThomas Lively } 1566fef8de66SThomas Lively 15672c6f75ddSDerek Schuff const wasm::WasmObjectHeader &WasmObjectFile::getHeader() const { 15682c6f75ddSDerek Schuff return Header; 15692c6f75ddSDerek Schuff } 15702c6f75ddSDerek Schuff 15712a193e0dSSam Clegg void WasmObjectFile::moveSymbolNext(DataRefImpl &Symb) const { Symb.d.b++; } 15722c6f75ddSDerek Schuff 1573ac00376aSvgxbj Expected<uint32_t> WasmObjectFile::getSymbolFlags(DataRefImpl Symb) const { 1574fc5b5cd2SSam Clegg uint32_t Result = SymbolRef::SF_None; 1575d3d84fddSDerek Schuff const WasmSymbol &Sym = getWasmSymbol(Symb); 1576fc5b5cd2SSam Clegg 1577d34e60caSNicola Zaghen LLVM_DEBUG(dbgs() << "getSymbolFlags: ptr=" << &Sym << " " << Sym << "\n"); 15786e7f1826SSam Clegg if (Sym.isBindingWeak()) 1579b7787fd0SSam Clegg Result |= SymbolRef::SF_Weak; 15806e7f1826SSam Clegg if (!Sym.isBindingLocal()) 158131a2c809SSam Clegg Result |= SymbolRef::SF_Global; 1582a2b35dacSSam Clegg if (Sym.isHidden()) 1583a2b35dacSSam Clegg Result |= SymbolRef::SF_Hidden; 15846c899ba6SSam Clegg if (!Sym.isDefined()) 1585fc5b5cd2SSam Clegg Result |= SymbolRef::SF_Undefined; 15866c899ba6SSam Clegg if (Sym.isTypeFunction()) 15876c899ba6SSam Clegg Result |= SymbolRef::SF_Executable; 1588fc5b5cd2SSam Clegg return Result; 15892c6f75ddSDerek Schuff } 15902c6f75ddSDerek Schuff 15912c6f75ddSDerek Schuff basic_symbol_iterator WasmObjectFile::symbol_begin() const { 1592d3d84fddSDerek Schuff DataRefImpl Ref; 15932a193e0dSSam Clegg Ref.d.a = 1; // Arbitrary non-zero value so that Ref.p is non-null 15942a193e0dSSam Clegg Ref.d.b = 0; // Symbol index 1595d3d84fddSDerek Schuff return BasicSymbolRef(Ref, this); 15962c6f75ddSDerek Schuff } 15972c6f75ddSDerek Schuff 15982c6f75ddSDerek Schuff basic_symbol_iterator WasmObjectFile::symbol_end() const { 1599d3d84fddSDerek Schuff DataRefImpl Ref; 16002a193e0dSSam Clegg Ref.d.a = 1; // Arbitrary non-zero value so that Ref.p is non-null 16012a193e0dSSam Clegg Ref.d.b = Symbols.size(); // Symbol index 1602d3d84fddSDerek Schuff return BasicSymbolRef(Ref, this); 1603d3d84fddSDerek Schuff } 1604d3d84fddSDerek Schuff 16052ffff5afSSam Clegg const WasmSymbol &WasmObjectFile::getWasmSymbol(const DataRefImpl &Symb) const { 16062a193e0dSSam Clegg return Symbols[Symb.d.b]; 16072c6f75ddSDerek Schuff } 16082c6f75ddSDerek Schuff 16092ffff5afSSam Clegg const WasmSymbol &WasmObjectFile::getWasmSymbol(const SymbolRef &Symb) const { 16102ffff5afSSam Clegg return getWasmSymbol(Symb.getRawDataRefImpl()); 16112ffff5afSSam Clegg } 16122ffff5afSSam Clegg 16132c6f75ddSDerek Schuff Expected<StringRef> WasmObjectFile::getSymbolName(DataRefImpl Symb) const { 16146c899ba6SSam Clegg return getWasmSymbol(Symb).Info.Name; 16152c6f75ddSDerek Schuff } 16162c6f75ddSDerek Schuff 16172c6f75ddSDerek Schuff Expected<uint64_t> WasmObjectFile::getSymbolAddress(DataRefImpl Symb) const { 1618f3b762a0SWouter van Oortmerssen auto &Sym = getWasmSymbol(Symb); 1619f3b762a0SWouter van Oortmerssen if (Sym.Info.Kind == wasm::WASM_SYMBOL_TYPE_FUNCTION && 1620f3b762a0SWouter van Oortmerssen isDefinedFunctionIndex(Sym.Info.ElementIndex)) 1621f3b762a0SWouter van Oortmerssen return getDefinedFunction(Sym.Info.ElementIndex).CodeSectionOffset; 1622f3b762a0SWouter van Oortmerssen else 1623fc5b5cd2SSam Clegg return getSymbolValue(Symb); 16242c6f75ddSDerek Schuff } 16252c6f75ddSDerek Schuff 162631a2c809SSam Clegg uint64_t WasmObjectFile::getWasmSymbolValue(const WasmSymbol &Sym) const { 16276c899ba6SSam Clegg switch (Sym.Info.Kind) { 16286c899ba6SSam Clegg case wasm::WASM_SYMBOL_TYPE_FUNCTION: 16296c899ba6SSam Clegg case wasm::WASM_SYMBOL_TYPE_GLOBAL: 16301d891d44SHeejin Ahn case wasm::WASM_SYMBOL_TYPE_TAG: 1631feac819eSAndy Wingo case wasm::WASM_SYMBOL_TYPE_TABLE: 16326c899ba6SSam Clegg return Sym.Info.ElementIndex; 16336c899ba6SSam Clegg case wasm::WASM_SYMBOL_TYPE_DATA: { 16346c899ba6SSam Clegg // The value of a data symbol is the segment offset, plus the symbol 16356c899ba6SSam Clegg // offset within the segment. 16366c899ba6SSam Clegg uint32_t SegmentIndex = Sym.Info.DataRef.Segment; 16376c899ba6SSam Clegg const wasm::WasmDataSegment &Segment = DataSegments[SegmentIndex].Data; 16389504ab32SSam Clegg if (Segment.Offset.Extended) { 16399504ab32SSam Clegg llvm_unreachable("extended init exprs not supported"); 16409504ab32SSam Clegg } else if (Segment.Offset.Inst.Opcode == wasm::WASM_OPCODE_I32_CONST) { 16419504ab32SSam Clegg return Segment.Offset.Inst.Value.Int32 + Sym.Info.DataRef.Offset; 16429504ab32SSam Clegg } else if (Segment.Offset.Inst.Opcode == wasm::WASM_OPCODE_I64_CONST) { 16439504ab32SSam Clegg return Segment.Offset.Inst.Value.Int64 + Sym.Info.DataRef.Offset; 16443b29376eSWouter van Oortmerssen } else { 16453b29376eSWouter van Oortmerssen llvm_unreachable("unknown init expr opcode"); 16463b29376eSWouter van Oortmerssen } 1647b09cfa51SSam Clegg } 16486a31a0d6SSam Clegg case wasm::WASM_SYMBOL_TYPE_SECTION: 16496a31a0d6SSam Clegg return 0; 16502c6f75ddSDerek Schuff } 16517f055deeSSam Clegg llvm_unreachable("invalid symbol type"); 1652b7787fd0SSam Clegg } 16532c6f75ddSDerek Schuff 165431a2c809SSam Clegg uint64_t WasmObjectFile::getSymbolValueImpl(DataRefImpl Symb) const { 165531a2c809SSam Clegg return getWasmSymbolValue(getWasmSymbol(Symb)); 165631a2c809SSam Clegg } 165731a2c809SSam Clegg 16582c6f75ddSDerek Schuff uint32_t WasmObjectFile::getSymbolAlignment(DataRefImpl Symb) const { 16592c6f75ddSDerek Schuff llvm_unreachable("not yet implemented"); 16602c6f75ddSDerek Schuff return 0; 16612c6f75ddSDerek Schuff } 16622c6f75ddSDerek Schuff 16632c6f75ddSDerek Schuff uint64_t WasmObjectFile::getCommonSymbolSizeImpl(DataRefImpl Symb) const { 16642c6f75ddSDerek Schuff llvm_unreachable("not yet implemented"); 16652c6f75ddSDerek Schuff return 0; 16662c6f75ddSDerek Schuff } 16672c6f75ddSDerek Schuff 16682c6f75ddSDerek Schuff Expected<SymbolRef::Type> 16692c6f75ddSDerek Schuff WasmObjectFile::getSymbolType(DataRefImpl Symb) const { 1670fc5b5cd2SSam Clegg const WasmSymbol &Sym = getWasmSymbol(Symb); 1671fc5b5cd2SSam Clegg 16726c899ba6SSam Clegg switch (Sym.Info.Kind) { 16736c899ba6SSam Clegg case wasm::WASM_SYMBOL_TYPE_FUNCTION: 1674fc5b5cd2SSam Clegg return SymbolRef::ST_Function; 16756c899ba6SSam Clegg case wasm::WASM_SYMBOL_TYPE_GLOBAL: 16766c899ba6SSam Clegg return SymbolRef::ST_Other; 16776c899ba6SSam Clegg case wasm::WASM_SYMBOL_TYPE_DATA: 1678fc5b5cd2SSam Clegg return SymbolRef::ST_Data; 16796a31a0d6SSam Clegg case wasm::WASM_SYMBOL_TYPE_SECTION: 16806a31a0d6SSam Clegg return SymbolRef::ST_Debug; 16811d891d44SHeejin Ahn case wasm::WASM_SYMBOL_TYPE_TAG: 1682da419bdbSHeejin Ahn return SymbolRef::ST_Other; 1683feac819eSAndy Wingo case wasm::WASM_SYMBOL_TYPE_TABLE: 1684feac819eSAndy Wingo return SymbolRef::ST_Other; 1685fc5b5cd2SSam Clegg } 1686fc5b5cd2SSam Clegg 168784c6f325SSam Clegg llvm_unreachable("unknown WasmSymbol::SymbolType"); 1688fc5b5cd2SSam Clegg return SymbolRef::ST_Other; 16892c6f75ddSDerek Schuff } 16902c6f75ddSDerek Schuff 16912c6f75ddSDerek Schuff Expected<section_iterator> 16922c6f75ddSDerek Schuff WasmObjectFile::getSymbolSection(DataRefImpl Symb) const { 16930b55ccf6SSam Clegg const WasmSymbol &Sym = getWasmSymbol(Symb); 16946c899ba6SSam Clegg if (Sym.isUndefined()) 16950b55ccf6SSam Clegg return section_end(); 16966c899ba6SSam Clegg 16976c899ba6SSam Clegg DataRefImpl Ref; 1698da6a896eSDerek Schuff Ref.d.a = getSymbolSectionIdImpl(Sym); 1699da6a896eSDerek Schuff return section_iterator(SectionRef(Ref, this)); 1700da6a896eSDerek Schuff } 1701da6a896eSDerek Schuff 1702da6a896eSDerek Schuff uint32_t WasmObjectFile::getSymbolSectionId(SymbolRef Symb) const { 1703da6a896eSDerek Schuff const WasmSymbol &Sym = getWasmSymbol(Symb); 1704da6a896eSDerek Schuff return getSymbolSectionIdImpl(Sym); 1705da6a896eSDerek Schuff } 1706da6a896eSDerek Schuff 1707da6a896eSDerek Schuff uint32_t WasmObjectFile::getSymbolSectionIdImpl(const WasmSymbol &Sym) const { 17086c899ba6SSam Clegg switch (Sym.Info.Kind) { 17096c899ba6SSam Clegg case wasm::WASM_SYMBOL_TYPE_FUNCTION: 1710da6a896eSDerek Schuff return CodeSection; 17116c899ba6SSam Clegg case wasm::WASM_SYMBOL_TYPE_GLOBAL: 1712da6a896eSDerek Schuff return GlobalSection; 17136c899ba6SSam Clegg case wasm::WASM_SYMBOL_TYPE_DATA: 1714da6a896eSDerek Schuff return DataSection; 1715da419bdbSHeejin Ahn case wasm::WASM_SYMBOL_TYPE_SECTION: 1716da6a896eSDerek Schuff return Sym.Info.ElementIndex; 17171d891d44SHeejin Ahn case wasm::WASM_SYMBOL_TYPE_TAG: 17181d891d44SHeejin Ahn return TagSection; 1719feac819eSAndy Wingo case wasm::WASM_SYMBOL_TYPE_TABLE: 1720feac819eSAndy Wingo return TableSection; 17216c899ba6SSam Clegg default: 172284c6f325SSam Clegg llvm_unreachable("unknown WasmSymbol::SymbolType"); 17236c899ba6SSam Clegg } 17242c6f75ddSDerek Schuff } 17252c6f75ddSDerek Schuff 17262c6f75ddSDerek Schuff void WasmObjectFile::moveSectionNext(DataRefImpl &Sec) const { Sec.d.a++; } 17272c6f75ddSDerek Schuff 17288be28cdcSFangrui Song Expected<StringRef> WasmObjectFile::getSectionName(DataRefImpl Sec) const { 1729d3d84fddSDerek Schuff const WasmSection &S = Sections[Sec.d.a]; 1730a205f290SDerek Schuff if (S.Type == wasm::WASM_SEC_CUSTOM) 17318be28cdcSFangrui Song return S.Name; 1732*2ae385e5SDerek Schuff if (S.Type > wasm::WASM_SEC_LAST_KNOWN) 17338be28cdcSFangrui Song return createStringError(object_error::invalid_section_index, ""); 1734a205f290SDerek Schuff return wasm::sectionTypeToString(S.Type); 17352c6f75ddSDerek Schuff } 17362c6f75ddSDerek Schuff 17372c6f75ddSDerek Schuff uint64_t WasmObjectFile::getSectionAddress(DataRefImpl Sec) const { return 0; } 17382c6f75ddSDerek Schuff 1739a25d329bSGeorge Rimar uint64_t WasmObjectFile::getSectionIndex(DataRefImpl Sec) const { 1740a25d329bSGeorge Rimar return Sec.d.a; 1741a25d329bSGeorge Rimar } 1742a25d329bSGeorge Rimar 17432c6f75ddSDerek Schuff uint64_t WasmObjectFile::getSectionSize(DataRefImpl Sec) const { 1744d3d84fddSDerek Schuff const WasmSection &S = Sections[Sec.d.a]; 17452c6f75ddSDerek Schuff return S.Content.size(); 17462c6f75ddSDerek Schuff } 17472c6f75ddSDerek Schuff 1748e1cb2c0fSFangrui Song Expected<ArrayRef<uint8_t>> 1749e1cb2c0fSFangrui Song WasmObjectFile::getSectionContents(DataRefImpl Sec) const { 1750d3d84fddSDerek Schuff const WasmSection &S = Sections[Sec.d.a]; 17512c6f75ddSDerek Schuff // This will never fail since wasm sections can never be empty (user-sections 17522c6f75ddSDerek Schuff // must have a name and non-user sections each have a defined structure). 1753e1cb2c0fSFangrui Song return S.Content; 17542c6f75ddSDerek Schuff } 17552c6f75ddSDerek Schuff 17562c6f75ddSDerek Schuff uint64_t WasmObjectFile::getSectionAlignment(DataRefImpl Sec) const { 17572c6f75ddSDerek Schuff return 1; 17582c6f75ddSDerek Schuff } 17592c6f75ddSDerek Schuff 17602c6f75ddSDerek Schuff bool WasmObjectFile::isSectionCompressed(DataRefImpl Sec) const { 17612c6f75ddSDerek Schuff return false; 17622c6f75ddSDerek Schuff } 17632c6f75ddSDerek Schuff 17642c6f75ddSDerek Schuff bool WasmObjectFile::isSectionText(DataRefImpl Sec) const { 1765d3d84fddSDerek Schuff return getWasmSection(Sec).Type == wasm::WASM_SEC_CODE; 17662c6f75ddSDerek Schuff } 17672c6f75ddSDerek Schuff 17682c6f75ddSDerek Schuff bool WasmObjectFile::isSectionData(DataRefImpl Sec) const { 1769d3d84fddSDerek Schuff return getWasmSection(Sec).Type == wasm::WASM_SEC_DATA; 17702c6f75ddSDerek Schuff } 17712c6f75ddSDerek Schuff 17722c6f75ddSDerek Schuff bool WasmObjectFile::isSectionBSS(DataRefImpl Sec) const { return false; } 17732c6f75ddSDerek Schuff 17742c6f75ddSDerek Schuff bool WasmObjectFile::isSectionVirtual(DataRefImpl Sec) const { return false; } 17752c6f75ddSDerek Schuff 1776d3d84fddSDerek Schuff relocation_iterator WasmObjectFile::section_rel_begin(DataRefImpl Ref) const { 1777d3d84fddSDerek Schuff DataRefImpl RelocRef; 1778d3d84fddSDerek Schuff RelocRef.d.a = Ref.d.a; 1779d3d84fddSDerek Schuff RelocRef.d.b = 0; 1780d3d84fddSDerek Schuff return relocation_iterator(RelocationRef(RelocRef, this)); 17812c6f75ddSDerek Schuff } 17822c6f75ddSDerek Schuff 1783d3d84fddSDerek Schuff relocation_iterator WasmObjectFile::section_rel_end(DataRefImpl Ref) const { 1784d3d84fddSDerek Schuff const WasmSection &Sec = getWasmSection(Ref); 1785d3d84fddSDerek Schuff DataRefImpl RelocRef; 1786d3d84fddSDerek Schuff RelocRef.d.a = Ref.d.a; 1787d3d84fddSDerek Schuff RelocRef.d.b = Sec.Relocations.size(); 1788d3d84fddSDerek Schuff return relocation_iterator(RelocationRef(RelocRef, this)); 17892c6f75ddSDerek Schuff } 17902c6f75ddSDerek Schuff 1791f208f631SHeejin Ahn void WasmObjectFile::moveRelocationNext(DataRefImpl &Rel) const { Rel.d.b++; } 17922c6f75ddSDerek Schuff 1793d3d84fddSDerek Schuff uint64_t WasmObjectFile::getRelocationOffset(DataRefImpl Ref) const { 1794d3d84fddSDerek Schuff const wasm::WasmRelocation &Rel = getWasmRelocation(Ref); 1795d3d84fddSDerek Schuff return Rel.Offset; 17962c6f75ddSDerek Schuff } 17972c6f75ddSDerek Schuff 1798f676cdd5SSam Clegg symbol_iterator WasmObjectFile::getRelocationSymbol(DataRefImpl Ref) const { 1799f676cdd5SSam Clegg const wasm::WasmRelocation &Rel = getWasmRelocation(Ref); 1800d1152a26SSam Clegg if (Rel.Type == wasm::R_WASM_TYPE_INDEX_LEB) 1801f676cdd5SSam Clegg return symbol_end(); 1802f676cdd5SSam Clegg DataRefImpl Sym; 1803c7d2e5f1SSam Clegg Sym.d.a = 1; 1804c7d2e5f1SSam Clegg Sym.d.b = Rel.Index; 1805f676cdd5SSam Clegg return symbol_iterator(SymbolRef(Sym, this)); 18062c6f75ddSDerek Schuff } 18072c6f75ddSDerek Schuff 1808d3d84fddSDerek Schuff uint64_t WasmObjectFile::getRelocationType(DataRefImpl Ref) const { 1809d3d84fddSDerek Schuff const wasm::WasmRelocation &Rel = getWasmRelocation(Ref); 1810d3d84fddSDerek Schuff return Rel.Type; 18112c6f75ddSDerek Schuff } 18122c6f75ddSDerek Schuff 18132c6f75ddSDerek Schuff void WasmObjectFile::getRelocationTypeName( 1814d3d84fddSDerek Schuff DataRefImpl Ref, SmallVectorImpl<char> &Result) const { 1815d3d84fddSDerek Schuff const wasm::WasmRelocation &Rel = getWasmRelocation(Ref); 1816d3d84fddSDerek Schuff StringRef Res = "Unknown"; 1817d3d84fddSDerek Schuff 1818d3d84fddSDerek Schuff #define WASM_RELOC(name, value) \ 1819d3d84fddSDerek Schuff case wasm::name: \ 1820d3d84fddSDerek Schuff Res = #name; \ 1821d3d84fddSDerek Schuff break; 1822d3d84fddSDerek Schuff 1823d3d84fddSDerek Schuff switch (Rel.Type) { 1824c5d8bc83SSam Clegg #include "llvm/BinaryFormat/WasmRelocs.def" 1825d3d84fddSDerek Schuff } 1826d3d84fddSDerek Schuff 1827d3d84fddSDerek Schuff #undef WASM_RELOC 1828d3d84fddSDerek Schuff 1829d3d84fddSDerek Schuff Result.append(Res.begin(), Res.end()); 18302c6f75ddSDerek Schuff } 18312c6f75ddSDerek Schuff 18322c6f75ddSDerek Schuff section_iterator WasmObjectFile::section_begin() const { 18332c6f75ddSDerek Schuff DataRefImpl Ref; 18342c6f75ddSDerek Schuff Ref.d.a = 0; 18352c6f75ddSDerek Schuff return section_iterator(SectionRef(Ref, this)); 18362c6f75ddSDerek Schuff } 18372c6f75ddSDerek Schuff 18382c6f75ddSDerek Schuff section_iterator WasmObjectFile::section_end() const { 18392c6f75ddSDerek Schuff DataRefImpl Ref; 18402c6f75ddSDerek Schuff Ref.d.a = Sections.size(); 18412c6f75ddSDerek Schuff return section_iterator(SectionRef(Ref, this)); 18422c6f75ddSDerek Schuff } 18432c6f75ddSDerek Schuff 184429f8c9f6SWouter van Oortmerssen uint8_t WasmObjectFile::getBytesInAddress() const { 184529f8c9f6SWouter van Oortmerssen return HasMemory64 ? 8 : 4; 184629f8c9f6SWouter van Oortmerssen } 18472c6f75ddSDerek Schuff 18482c6f75ddSDerek Schuff StringRef WasmObjectFile::getFileFormatName() const { return "WASM"; } 18492c6f75ddSDerek Schuff 185029f8c9f6SWouter van Oortmerssen Triple::ArchType WasmObjectFile::getArch() const { 185129f8c9f6SWouter van Oortmerssen return HasMemory64 ? Triple::wasm64 : Triple::wasm32; 185229f8c9f6SWouter van Oortmerssen } 18532c6f75ddSDerek Schuff 18542c6f75ddSDerek Schuff SubtargetFeatures WasmObjectFile::getFeatures() const { 18552c6f75ddSDerek Schuff return SubtargetFeatures(); 18562c6f75ddSDerek Schuff } 18572c6f75ddSDerek Schuff 1858f208f631SHeejin Ahn bool WasmObjectFile::isRelocatableObject() const { return HasLinkingSection; } 18592c6f75ddSDerek Schuff 186003801256SSam Clegg bool WasmObjectFile::isSharedObject() const { return HasDylinkSection; } 186103801256SSam Clegg 1862d3d84fddSDerek Schuff const WasmSection &WasmObjectFile::getWasmSection(DataRefImpl Ref) const { 186316fe5822SDavide Italiano assert(Ref.d.a < Sections.size()); 1864d3d84fddSDerek Schuff return Sections[Ref.d.a]; 1865d3d84fddSDerek Schuff } 1866d3d84fddSDerek Schuff 1867d3d84fddSDerek Schuff const WasmSection & 18682c6f75ddSDerek Schuff WasmObjectFile::getWasmSection(const SectionRef &Section) const { 1869d3d84fddSDerek Schuff return getWasmSection(Section.getRawDataRefImpl()); 1870d3d84fddSDerek Schuff } 1871d3d84fddSDerek Schuff 1872d3d84fddSDerek Schuff const wasm::WasmRelocation & 1873d3d84fddSDerek Schuff WasmObjectFile::getWasmRelocation(const RelocationRef &Ref) const { 1874d3d84fddSDerek Schuff return getWasmRelocation(Ref.getRawDataRefImpl()); 1875d3d84fddSDerek Schuff } 1876d3d84fddSDerek Schuff 1877d3d84fddSDerek Schuff const wasm::WasmRelocation & 1878d3d84fddSDerek Schuff WasmObjectFile::getWasmRelocation(DataRefImpl Ref) const { 187916fe5822SDavide Italiano assert(Ref.d.a < Sections.size()); 1880d3d84fddSDerek Schuff const WasmSection &Sec = Sections[Ref.d.a]; 188116fe5822SDavide Italiano assert(Ref.d.b < Sec.Relocations.size()); 1882d3d84fddSDerek Schuff return Sec.Relocations[Ref.d.b]; 18832c6f75ddSDerek Schuff } 1884feef720bSHeejin Ahn 1885feef720bSHeejin Ahn int WasmSectionOrderChecker::getSectionOrder(unsigned ID, 1886feef720bSHeejin Ahn StringRef CustomSectionName) { 1887feef720bSHeejin Ahn switch (ID) { 1888feef720bSHeejin Ahn case wasm::WASM_SEC_CUSTOM: 1889feef720bSHeejin Ahn return StringSwitch<unsigned>(CustomSectionName) 1890feef720bSHeejin Ahn .Case("dylink", WASM_SEC_ORDER_DYLINK) 1891b78c85a4SSam Clegg .Case("dylink.0", WASM_SEC_ORDER_DYLINK) 1892feef720bSHeejin Ahn .Case("linking", WASM_SEC_ORDER_LINKING) 1893feef720bSHeejin Ahn .StartsWith("reloc.", WASM_SEC_ORDER_RELOC) 1894feef720bSHeejin Ahn .Case("name", WASM_SEC_ORDER_NAME) 1895feef720bSHeejin Ahn .Case("producers", WASM_SEC_ORDER_PRODUCERS) 1896f6f4f843SThomas Lively .Case("target_features", WASM_SEC_ORDER_TARGET_FEATURES) 18979757bba4SThomas Lively .Default(WASM_SEC_ORDER_NONE); 1898feef720bSHeejin Ahn case wasm::WASM_SEC_TYPE: 1899feef720bSHeejin Ahn return WASM_SEC_ORDER_TYPE; 1900feef720bSHeejin Ahn case wasm::WASM_SEC_IMPORT: 1901feef720bSHeejin Ahn return WASM_SEC_ORDER_IMPORT; 1902feef720bSHeejin Ahn case wasm::WASM_SEC_FUNCTION: 1903feef720bSHeejin Ahn return WASM_SEC_ORDER_FUNCTION; 1904feef720bSHeejin Ahn case wasm::WASM_SEC_TABLE: 1905feef720bSHeejin Ahn return WASM_SEC_ORDER_TABLE; 1906feef720bSHeejin Ahn case wasm::WASM_SEC_MEMORY: 1907feef720bSHeejin Ahn return WASM_SEC_ORDER_MEMORY; 1908feef720bSHeejin Ahn case wasm::WASM_SEC_GLOBAL: 1909feef720bSHeejin Ahn return WASM_SEC_ORDER_GLOBAL; 1910feef720bSHeejin Ahn case wasm::WASM_SEC_EXPORT: 1911feef720bSHeejin Ahn return WASM_SEC_ORDER_EXPORT; 1912feef720bSHeejin Ahn case wasm::WASM_SEC_START: 1913feef720bSHeejin Ahn return WASM_SEC_ORDER_START; 1914feef720bSHeejin Ahn case wasm::WASM_SEC_ELEM: 1915feef720bSHeejin Ahn return WASM_SEC_ORDER_ELEM; 1916feef720bSHeejin Ahn case wasm::WASM_SEC_CODE: 1917feef720bSHeejin Ahn return WASM_SEC_ORDER_CODE; 1918feef720bSHeejin Ahn case wasm::WASM_SEC_DATA: 1919feef720bSHeejin Ahn return WASM_SEC_ORDER_DATA; 1920feef720bSHeejin Ahn case wasm::WASM_SEC_DATACOUNT: 1921feef720bSHeejin Ahn return WASM_SEC_ORDER_DATACOUNT; 19221d891d44SHeejin Ahn case wasm::WASM_SEC_TAG: 19231d891d44SHeejin Ahn return WASM_SEC_ORDER_TAG; 1924feef720bSHeejin Ahn default: 1925fe8aabf9SSam Clegg return WASM_SEC_ORDER_NONE; 1926feef720bSHeejin Ahn } 1927feef720bSHeejin Ahn } 1928feef720bSHeejin Ahn 19299757bba4SThomas Lively // Represents the edges in a directed graph where any node B reachable from node 19309757bba4SThomas Lively // A is not allowed to appear before A in the section ordering, but may appear 19319757bba4SThomas Lively // afterward. 1932f93426c5SHeejin Ahn int WasmSectionOrderChecker::DisallowedPredecessors 1933f93426c5SHeejin Ahn [WASM_NUM_SEC_ORDERS][WASM_NUM_SEC_ORDERS] = { 1934f93426c5SHeejin Ahn // WASM_SEC_ORDER_NONE 1935f93426c5SHeejin Ahn {}, 1936f93426c5SHeejin Ahn // WASM_SEC_ORDER_TYPE 1937f93426c5SHeejin Ahn {WASM_SEC_ORDER_TYPE, WASM_SEC_ORDER_IMPORT}, 1938f93426c5SHeejin Ahn // WASM_SEC_ORDER_IMPORT 1939f93426c5SHeejin Ahn {WASM_SEC_ORDER_IMPORT, WASM_SEC_ORDER_FUNCTION}, 1940f93426c5SHeejin Ahn // WASM_SEC_ORDER_FUNCTION 1941f93426c5SHeejin Ahn {WASM_SEC_ORDER_FUNCTION, WASM_SEC_ORDER_TABLE}, 1942f93426c5SHeejin Ahn // WASM_SEC_ORDER_TABLE 1943f93426c5SHeejin Ahn {WASM_SEC_ORDER_TABLE, WASM_SEC_ORDER_MEMORY}, 1944f93426c5SHeejin Ahn // WASM_SEC_ORDER_MEMORY 19451d891d44SHeejin Ahn {WASM_SEC_ORDER_MEMORY, WASM_SEC_ORDER_TAG}, 19461d891d44SHeejin Ahn // WASM_SEC_ORDER_TAG 19471d891d44SHeejin Ahn {WASM_SEC_ORDER_TAG, WASM_SEC_ORDER_GLOBAL}, 1948f93426c5SHeejin Ahn // WASM_SEC_ORDER_GLOBAL 1949f93426c5SHeejin Ahn {WASM_SEC_ORDER_GLOBAL, WASM_SEC_ORDER_EXPORT}, 1950f93426c5SHeejin Ahn // WASM_SEC_ORDER_EXPORT 1951f93426c5SHeejin Ahn {WASM_SEC_ORDER_EXPORT, WASM_SEC_ORDER_START}, 1952f93426c5SHeejin Ahn // WASM_SEC_ORDER_START 1953f93426c5SHeejin Ahn {WASM_SEC_ORDER_START, WASM_SEC_ORDER_ELEM}, 1954f93426c5SHeejin Ahn // WASM_SEC_ORDER_ELEM 1955f93426c5SHeejin Ahn {WASM_SEC_ORDER_ELEM, WASM_SEC_ORDER_DATACOUNT}, 1956f93426c5SHeejin Ahn // WASM_SEC_ORDER_DATACOUNT 1957f93426c5SHeejin Ahn {WASM_SEC_ORDER_DATACOUNT, WASM_SEC_ORDER_CODE}, 1958f93426c5SHeejin Ahn // WASM_SEC_ORDER_CODE 1959f93426c5SHeejin Ahn {WASM_SEC_ORDER_CODE, WASM_SEC_ORDER_DATA}, 1960f93426c5SHeejin Ahn // WASM_SEC_ORDER_DATA 1961f93426c5SHeejin Ahn {WASM_SEC_ORDER_DATA, WASM_SEC_ORDER_LINKING}, 19629757bba4SThomas Lively 19639757bba4SThomas Lively // Custom Sections 1964f93426c5SHeejin Ahn // WASM_SEC_ORDER_DYLINK 1965f93426c5SHeejin Ahn {WASM_SEC_ORDER_DYLINK, WASM_SEC_ORDER_TYPE}, 1966f93426c5SHeejin Ahn // WASM_SEC_ORDER_LINKING 1967f93426c5SHeejin Ahn {WASM_SEC_ORDER_LINKING, WASM_SEC_ORDER_RELOC, WASM_SEC_ORDER_NAME}, 1968f93426c5SHeejin Ahn // WASM_SEC_ORDER_RELOC (can be repeated) 1969f93426c5SHeejin Ahn {}, 1970f93426c5SHeejin Ahn // WASM_SEC_ORDER_NAME 1971f93426c5SHeejin Ahn {WASM_SEC_ORDER_NAME, WASM_SEC_ORDER_PRODUCERS}, 1972f93426c5SHeejin Ahn // WASM_SEC_ORDER_PRODUCERS 1973f93426c5SHeejin Ahn {WASM_SEC_ORDER_PRODUCERS, WASM_SEC_ORDER_TARGET_FEATURES}, 1974f93426c5SHeejin Ahn // WASM_SEC_ORDER_TARGET_FEATURES 1975f93426c5SHeejin Ahn {WASM_SEC_ORDER_TARGET_FEATURES}}; 19769757bba4SThomas Lively 1977feef720bSHeejin Ahn bool WasmSectionOrderChecker::isValidSectionOrder(unsigned ID, 1978feef720bSHeejin Ahn StringRef CustomSectionName) { 1979feef720bSHeejin Ahn int Order = getSectionOrder(ID, CustomSectionName); 19809757bba4SThomas Lively if (Order == WASM_SEC_ORDER_NONE) 1981feef720bSHeejin Ahn return true; 19829757bba4SThomas Lively 19839757bba4SThomas Lively // Disallowed predecessors we need to check for 19849757bba4SThomas Lively SmallVector<int, WASM_NUM_SEC_ORDERS> WorkList; 19859757bba4SThomas Lively 19869757bba4SThomas Lively // Keep track of completed checks to avoid repeating work 19879757bba4SThomas Lively bool Checked[WASM_NUM_SEC_ORDERS] = {}; 19889757bba4SThomas Lively 19899757bba4SThomas Lively int Curr = Order; 19909757bba4SThomas Lively while (true) { 19919757bba4SThomas Lively // Add new disallowed predecessors to work list 19929757bba4SThomas Lively for (size_t I = 0;; ++I) { 19939757bba4SThomas Lively int Next = DisallowedPredecessors[Curr][I]; 19949757bba4SThomas Lively if (Next == WASM_SEC_ORDER_NONE) 19959757bba4SThomas Lively break; 19969757bba4SThomas Lively if (Checked[Next]) 19979757bba4SThomas Lively continue; 19989757bba4SThomas Lively WorkList.push_back(Next); 19999757bba4SThomas Lively Checked[Next] = true; 20009757bba4SThomas Lively } 20019757bba4SThomas Lively 20029757bba4SThomas Lively if (WorkList.empty()) 20039757bba4SThomas Lively break; 20049757bba4SThomas Lively 20059757bba4SThomas Lively // Consider next disallowed predecessor 20069757bba4SThomas Lively Curr = WorkList.pop_back_val(); 20079757bba4SThomas Lively if (Seen[Curr]) 20089757bba4SThomas Lively return false; 20099757bba4SThomas Lively } 20109757bba4SThomas Lively 20119757bba4SThomas Lively // Have not seen any disallowed predecessors 20129757bba4SThomas Lively Seen[Order] = true; 20139757bba4SThomas Lively return true; 2014feef720bSHeejin Ahn } 2015