10b57cec5SDimitry Andric //===- WasmObjectFile.cpp - Wasm object file implementation ---------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric 90b57cec5SDimitry Andric #include "llvm/ADT/ArrayRef.h" 100b57cec5SDimitry Andric #include "llvm/ADT/DenseSet.h" 110b57cec5SDimitry Andric #include "llvm/ADT/SmallSet.h" 120b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h" 130b57cec5SDimitry Andric #include "llvm/ADT/StringSet.h" 145ffd83dbSDimitry Andric #include "llvm/ADT/StringSwitch.h" 150b57cec5SDimitry Andric #include "llvm/BinaryFormat/Wasm.h" 160b57cec5SDimitry Andric #include "llvm/Object/Binary.h" 170b57cec5SDimitry Andric #include "llvm/Object/Error.h" 180b57cec5SDimitry Andric #include "llvm/Object/ObjectFile.h" 190b57cec5SDimitry Andric #include "llvm/Object/SymbolicFile.h" 200b57cec5SDimitry Andric #include "llvm/Object/Wasm.h" 210b57cec5SDimitry Andric #include "llvm/Support/Endian.h" 220b57cec5SDimitry Andric #include "llvm/Support/Error.h" 230b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h" 24*0fca6ea1SDimitry Andric #include "llvm/Support/Format.h" 250b57cec5SDimitry Andric #include "llvm/Support/LEB128.h" 260b57cec5SDimitry Andric #include "llvm/Support/ScopedPrinter.h" 2706c3fb27SDimitry Andric #include "llvm/TargetParser/SubtargetFeature.h" 2806c3fb27SDimitry Andric #include "llvm/TargetParser/Triple.h" 290b57cec5SDimitry Andric #include <algorithm> 300b57cec5SDimitry Andric #include <cassert> 310b57cec5SDimitry Andric #include <cstdint> 320b57cec5SDimitry Andric #include <cstring> 33*0fca6ea1SDimitry Andric #include <limits> 340b57cec5SDimitry Andric 350b57cec5SDimitry Andric #define DEBUG_TYPE "wasm-object" 360b57cec5SDimitry Andric 370b57cec5SDimitry Andric using namespace llvm; 380b57cec5SDimitry Andric using namespace object; 390b57cec5SDimitry Andric 400b57cec5SDimitry Andric void WasmSymbol::print(raw_ostream &Out) const { 410b57cec5SDimitry Andric Out << "Name=" << Info.Name 42fe6060f1SDimitry Andric << ", Kind=" << toString(wasm::WasmSymbolType(Info.Kind)) << ", Flags=0x" 4306c3fb27SDimitry Andric << Twine::utohexstr(Info.Flags) << " ["; 4406c3fb27SDimitry Andric switch (getBinding()) { 4506c3fb27SDimitry Andric case wasm::WASM_SYMBOL_BINDING_GLOBAL: Out << "global"; break; 4606c3fb27SDimitry Andric case wasm::WASM_SYMBOL_BINDING_LOCAL: Out << "local"; break; 4706c3fb27SDimitry Andric case wasm::WASM_SYMBOL_BINDING_WEAK: Out << "weak"; break; 4806c3fb27SDimitry Andric } 4906c3fb27SDimitry Andric if (isHidden()) { 5006c3fb27SDimitry Andric Out << ", hidden"; 5106c3fb27SDimitry Andric } else { 5206c3fb27SDimitry Andric Out << ", default"; 5306c3fb27SDimitry Andric } 5406c3fb27SDimitry Andric Out << "]"; 550b57cec5SDimitry Andric if (!isTypeData()) { 560b57cec5SDimitry Andric Out << ", ElemIndex=" << Info.ElementIndex; 570b57cec5SDimitry Andric } else if (isDefined()) { 580b57cec5SDimitry Andric Out << ", Segment=" << Info.DataRef.Segment; 590b57cec5SDimitry Andric Out << ", Offset=" << Info.DataRef.Offset; 600b57cec5SDimitry Andric Out << ", Size=" << Info.DataRef.Size; 610b57cec5SDimitry Andric } 620b57cec5SDimitry Andric } 630b57cec5SDimitry Andric 640b57cec5SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 650b57cec5SDimitry Andric LLVM_DUMP_METHOD void WasmSymbol::dump() const { print(dbgs()); } 660b57cec5SDimitry Andric #endif 670b57cec5SDimitry Andric 680b57cec5SDimitry Andric Expected<std::unique_ptr<WasmObjectFile>> 690b57cec5SDimitry Andric ObjectFile::createWasmObjectFile(MemoryBufferRef Buffer) { 700b57cec5SDimitry Andric Error Err = Error::success(); 718bcb0991SDimitry Andric auto ObjectFile = std::make_unique<WasmObjectFile>(Buffer, Err); 720b57cec5SDimitry Andric if (Err) 730b57cec5SDimitry Andric return std::move(Err); 740b57cec5SDimitry Andric 750b57cec5SDimitry Andric return std::move(ObjectFile); 760b57cec5SDimitry Andric } 770b57cec5SDimitry Andric 780b57cec5SDimitry Andric #define VARINT7_MAX ((1 << 7) - 1) 790b57cec5SDimitry Andric #define VARINT7_MIN (-(1 << 7)) 800b57cec5SDimitry Andric #define VARUINT7_MAX (1 << 7) 810b57cec5SDimitry Andric #define VARUINT1_MAX (1) 820b57cec5SDimitry Andric 830b57cec5SDimitry Andric static uint8_t readUint8(WasmObjectFile::ReadContext &Ctx) { 840b57cec5SDimitry Andric if (Ctx.Ptr == Ctx.End) 850b57cec5SDimitry Andric report_fatal_error("EOF while reading uint8"); 860b57cec5SDimitry Andric return *Ctx.Ptr++; 870b57cec5SDimitry Andric } 880b57cec5SDimitry Andric 890b57cec5SDimitry Andric static uint32_t readUint32(WasmObjectFile::ReadContext &Ctx) { 900b57cec5SDimitry Andric if (Ctx.Ptr + 4 > Ctx.End) 910b57cec5SDimitry Andric report_fatal_error("EOF while reading uint32"); 920b57cec5SDimitry Andric uint32_t Result = support::endian::read32le(Ctx.Ptr); 930b57cec5SDimitry Andric Ctx.Ptr += 4; 940b57cec5SDimitry Andric return Result; 950b57cec5SDimitry Andric } 960b57cec5SDimitry Andric 970b57cec5SDimitry Andric static int32_t readFloat32(WasmObjectFile::ReadContext &Ctx) { 980b57cec5SDimitry Andric if (Ctx.Ptr + 4 > Ctx.End) 990b57cec5SDimitry Andric report_fatal_error("EOF while reading float64"); 1000b57cec5SDimitry Andric int32_t Result = 0; 1010b57cec5SDimitry Andric memcpy(&Result, Ctx.Ptr, sizeof(Result)); 1020b57cec5SDimitry Andric Ctx.Ptr += sizeof(Result); 1030b57cec5SDimitry Andric return Result; 1040b57cec5SDimitry Andric } 1050b57cec5SDimitry Andric 1060b57cec5SDimitry Andric static int64_t readFloat64(WasmObjectFile::ReadContext &Ctx) { 1070b57cec5SDimitry Andric if (Ctx.Ptr + 8 > Ctx.End) 1080b57cec5SDimitry Andric report_fatal_error("EOF while reading float64"); 1090b57cec5SDimitry Andric int64_t Result = 0; 1100b57cec5SDimitry Andric memcpy(&Result, Ctx.Ptr, sizeof(Result)); 1110b57cec5SDimitry Andric Ctx.Ptr += sizeof(Result); 1120b57cec5SDimitry Andric return Result; 1130b57cec5SDimitry Andric } 1140b57cec5SDimitry Andric 1150b57cec5SDimitry Andric static uint64_t readULEB128(WasmObjectFile::ReadContext &Ctx) { 1160b57cec5SDimitry Andric unsigned Count; 1170b57cec5SDimitry Andric const char *Error = nullptr; 1180b57cec5SDimitry Andric uint64_t Result = decodeULEB128(Ctx.Ptr, &Count, Ctx.End, &Error); 1190b57cec5SDimitry Andric if (Error) 1200b57cec5SDimitry Andric report_fatal_error(Error); 1210b57cec5SDimitry Andric Ctx.Ptr += Count; 1220b57cec5SDimitry Andric return Result; 1230b57cec5SDimitry Andric } 1240b57cec5SDimitry Andric 1250b57cec5SDimitry Andric static StringRef readString(WasmObjectFile::ReadContext &Ctx) { 1260b57cec5SDimitry Andric uint32_t StringLen = readULEB128(Ctx); 1270b57cec5SDimitry Andric if (Ctx.Ptr + StringLen > Ctx.End) 1280b57cec5SDimitry Andric report_fatal_error("EOF while reading string"); 1290b57cec5SDimitry Andric StringRef Return = 1300b57cec5SDimitry Andric StringRef(reinterpret_cast<const char *>(Ctx.Ptr), StringLen); 1310b57cec5SDimitry Andric Ctx.Ptr += StringLen; 1320b57cec5SDimitry Andric return Return; 1330b57cec5SDimitry Andric } 1340b57cec5SDimitry Andric 1350b57cec5SDimitry Andric static int64_t readLEB128(WasmObjectFile::ReadContext &Ctx) { 1360b57cec5SDimitry Andric unsigned Count; 1370b57cec5SDimitry Andric const char *Error = nullptr; 1380b57cec5SDimitry Andric uint64_t Result = decodeSLEB128(Ctx.Ptr, &Count, Ctx.End, &Error); 1390b57cec5SDimitry Andric if (Error) 1400b57cec5SDimitry Andric report_fatal_error(Error); 1410b57cec5SDimitry Andric Ctx.Ptr += Count; 1420b57cec5SDimitry Andric return Result; 1430b57cec5SDimitry Andric } 1440b57cec5SDimitry Andric 1450b57cec5SDimitry Andric static uint8_t readVaruint1(WasmObjectFile::ReadContext &Ctx) { 1460b57cec5SDimitry Andric int64_t Result = readLEB128(Ctx); 1470b57cec5SDimitry Andric if (Result > VARUINT1_MAX || Result < 0) 1480b57cec5SDimitry Andric report_fatal_error("LEB is outside Varuint1 range"); 1490b57cec5SDimitry Andric return Result; 1500b57cec5SDimitry Andric } 1510b57cec5SDimitry Andric 1520b57cec5SDimitry Andric static int32_t readVarint32(WasmObjectFile::ReadContext &Ctx) { 1530b57cec5SDimitry Andric int64_t Result = readLEB128(Ctx); 1540b57cec5SDimitry Andric if (Result > INT32_MAX || Result < INT32_MIN) 1550b57cec5SDimitry Andric report_fatal_error("LEB is outside Varint32 range"); 1560b57cec5SDimitry Andric return Result; 1570b57cec5SDimitry Andric } 1580b57cec5SDimitry Andric 1590b57cec5SDimitry Andric static uint32_t readVaruint32(WasmObjectFile::ReadContext &Ctx) { 1600b57cec5SDimitry Andric uint64_t Result = readULEB128(Ctx); 1610b57cec5SDimitry Andric if (Result > UINT32_MAX) 1620b57cec5SDimitry Andric report_fatal_error("LEB is outside Varuint32 range"); 1630b57cec5SDimitry Andric return Result; 1640b57cec5SDimitry Andric } 1650b57cec5SDimitry Andric 1660b57cec5SDimitry Andric static int64_t readVarint64(WasmObjectFile::ReadContext &Ctx) { 1670b57cec5SDimitry Andric return readLEB128(Ctx); 1680b57cec5SDimitry Andric } 1690b57cec5SDimitry Andric 1705ffd83dbSDimitry Andric static uint64_t readVaruint64(WasmObjectFile::ReadContext &Ctx) { 1715ffd83dbSDimitry Andric return readULEB128(Ctx); 1725ffd83dbSDimitry Andric } 1735ffd83dbSDimitry Andric 1740b57cec5SDimitry Andric static uint8_t readOpcode(WasmObjectFile::ReadContext &Ctx) { 1750b57cec5SDimitry Andric return readUint8(Ctx); 1760b57cec5SDimitry Andric } 1770b57cec5SDimitry Andric 178*0fca6ea1SDimitry Andric static wasm::ValType parseValType(WasmObjectFile::ReadContext &Ctx, 179*0fca6ea1SDimitry Andric uint32_t Code) { 180*0fca6ea1SDimitry Andric // only directly encoded FUNCREF/EXTERNREF/EXNREF are supported 181*0fca6ea1SDimitry Andric // (not ref null func, ref null extern, or ref null exn) 182*0fca6ea1SDimitry Andric switch (Code) { 183*0fca6ea1SDimitry Andric case wasm::WASM_TYPE_I32: 184*0fca6ea1SDimitry Andric case wasm::WASM_TYPE_I64: 185*0fca6ea1SDimitry Andric case wasm::WASM_TYPE_F32: 186*0fca6ea1SDimitry Andric case wasm::WASM_TYPE_F64: 187*0fca6ea1SDimitry Andric case wasm::WASM_TYPE_V128: 188*0fca6ea1SDimitry Andric case wasm::WASM_TYPE_FUNCREF: 189*0fca6ea1SDimitry Andric case wasm::WASM_TYPE_EXTERNREF: 190*0fca6ea1SDimitry Andric case wasm::WASM_TYPE_EXNREF: 191*0fca6ea1SDimitry Andric return wasm::ValType(Code); 192*0fca6ea1SDimitry Andric } 193*0fca6ea1SDimitry Andric if (Code == wasm::WASM_TYPE_NULLABLE || Code == wasm::WASM_TYPE_NONNULLABLE) { 194*0fca6ea1SDimitry Andric /* Discard HeapType */ readVarint64(Ctx); 195*0fca6ea1SDimitry Andric } 196*0fca6ea1SDimitry Andric return wasm::ValType(wasm::ValType::OTHERREF); 197*0fca6ea1SDimitry Andric } 198*0fca6ea1SDimitry Andric 1990b57cec5SDimitry Andric static Error readInitExpr(wasm::WasmInitExpr &Expr, 2000b57cec5SDimitry Andric WasmObjectFile::ReadContext &Ctx) { 20181ad6265SDimitry Andric auto Start = Ctx.Ptr; 2020b57cec5SDimitry Andric 20381ad6265SDimitry Andric Expr.Extended = false; 20481ad6265SDimitry Andric Expr.Inst.Opcode = readOpcode(Ctx); 20581ad6265SDimitry Andric switch (Expr.Inst.Opcode) { 2060b57cec5SDimitry Andric case wasm::WASM_OPCODE_I32_CONST: 20781ad6265SDimitry Andric Expr.Inst.Value.Int32 = readVarint32(Ctx); 2080b57cec5SDimitry Andric break; 2090b57cec5SDimitry Andric case wasm::WASM_OPCODE_I64_CONST: 21081ad6265SDimitry Andric Expr.Inst.Value.Int64 = readVarint64(Ctx); 2110b57cec5SDimitry Andric break; 2120b57cec5SDimitry Andric case wasm::WASM_OPCODE_F32_CONST: 21381ad6265SDimitry Andric Expr.Inst.Value.Float32 = readFloat32(Ctx); 2140b57cec5SDimitry Andric break; 2150b57cec5SDimitry Andric case wasm::WASM_OPCODE_F64_CONST: 21681ad6265SDimitry Andric Expr.Inst.Value.Float64 = readFloat64(Ctx); 2170b57cec5SDimitry Andric break; 2180b57cec5SDimitry Andric case wasm::WASM_OPCODE_GLOBAL_GET: 21981ad6265SDimitry Andric Expr.Inst.Value.Global = readULEB128(Ctx); 2200b57cec5SDimitry Andric break; 2215ffd83dbSDimitry Andric case wasm::WASM_OPCODE_REF_NULL: { 222*0fca6ea1SDimitry Andric /* Discard type */ parseValType(Ctx, readVaruint32(Ctx)); 2235ffd83dbSDimitry Andric break; 2245ffd83dbSDimitry Andric } 2250b57cec5SDimitry Andric default: 22681ad6265SDimitry Andric Expr.Extended = true; 2270b57cec5SDimitry Andric } 2280b57cec5SDimitry Andric 22981ad6265SDimitry Andric if (!Expr.Extended) { 2300b57cec5SDimitry Andric uint8_t EndOpcode = readOpcode(Ctx); 23181ad6265SDimitry Andric if (EndOpcode != wasm::WASM_OPCODE_END) 23281ad6265SDimitry Andric Expr.Extended = true; 23381ad6265SDimitry Andric } 23481ad6265SDimitry Andric 23581ad6265SDimitry Andric if (Expr.Extended) { 23681ad6265SDimitry Andric Ctx.Ptr = Start; 237fcaf7f86SDimitry Andric while (true) { 23881ad6265SDimitry Andric uint8_t Opcode = readOpcode(Ctx); 23981ad6265SDimitry Andric switch (Opcode) { 24081ad6265SDimitry Andric case wasm::WASM_OPCODE_I32_CONST: 24181ad6265SDimitry Andric case wasm::WASM_OPCODE_GLOBAL_GET: 24281ad6265SDimitry Andric case wasm::WASM_OPCODE_REF_NULL: 243*0fca6ea1SDimitry Andric case wasm::WASM_OPCODE_REF_FUNC: 24481ad6265SDimitry Andric case wasm::WASM_OPCODE_I64_CONST: 24581ad6265SDimitry Andric readULEB128(Ctx); 24681ad6265SDimitry Andric break; 247*0fca6ea1SDimitry Andric case wasm::WASM_OPCODE_F32_CONST: 248*0fca6ea1SDimitry Andric readFloat32(Ctx); 249*0fca6ea1SDimitry Andric break; 250*0fca6ea1SDimitry Andric case wasm::WASM_OPCODE_F64_CONST: 251*0fca6ea1SDimitry Andric readFloat64(Ctx); 252*0fca6ea1SDimitry Andric break; 25381ad6265SDimitry Andric case wasm::WASM_OPCODE_I32_ADD: 25481ad6265SDimitry Andric case wasm::WASM_OPCODE_I32_SUB: 25581ad6265SDimitry Andric case wasm::WASM_OPCODE_I32_MUL: 25681ad6265SDimitry Andric case wasm::WASM_OPCODE_I64_ADD: 25781ad6265SDimitry Andric case wasm::WASM_OPCODE_I64_SUB: 25881ad6265SDimitry Andric case wasm::WASM_OPCODE_I64_MUL: 25981ad6265SDimitry Andric break; 260*0fca6ea1SDimitry Andric case wasm::WASM_OPCODE_GC_PREFIX: 261*0fca6ea1SDimitry Andric break; 262*0fca6ea1SDimitry Andric // The GC opcodes are in a separate (prefixed space). This flat switch 263*0fca6ea1SDimitry Andric // structure works as long as there is no overlap between the GC and 264*0fca6ea1SDimitry Andric // general opcodes used in init exprs. 265*0fca6ea1SDimitry Andric case wasm::WASM_OPCODE_STRUCT_NEW: 266*0fca6ea1SDimitry Andric case wasm::WASM_OPCODE_STRUCT_NEW_DEFAULT: 267*0fca6ea1SDimitry Andric case wasm::WASM_OPCODE_ARRAY_NEW: 268*0fca6ea1SDimitry Andric case wasm::WASM_OPCODE_ARRAY_NEW_DEFAULT: 269*0fca6ea1SDimitry Andric readULEB128(Ctx); // heap type index 270*0fca6ea1SDimitry Andric break; 271*0fca6ea1SDimitry Andric case wasm::WASM_OPCODE_ARRAY_NEW_FIXED: 272*0fca6ea1SDimitry Andric readULEB128(Ctx); // heap type index 273*0fca6ea1SDimitry Andric readULEB128(Ctx); // array size 274*0fca6ea1SDimitry Andric break; 275*0fca6ea1SDimitry Andric case wasm::WASM_OPCODE_REF_I31: 276*0fca6ea1SDimitry Andric break; 27781ad6265SDimitry Andric case wasm::WASM_OPCODE_END: 27881ad6265SDimitry Andric Expr.Body = ArrayRef<uint8_t>(Start, Ctx.Ptr - Start); 27981ad6265SDimitry Andric return Error::success(); 28081ad6265SDimitry Andric default: 28181ad6265SDimitry Andric return make_error<GenericBinaryError>( 28281ad6265SDimitry Andric Twine("invalid opcode in init_expr: ") + Twine(unsigned(Opcode)), 2830b57cec5SDimitry Andric object_error::parse_failed); 2840b57cec5SDimitry Andric } 28581ad6265SDimitry Andric } 28681ad6265SDimitry Andric } 28781ad6265SDimitry Andric 2880b57cec5SDimitry Andric return Error::success(); 2890b57cec5SDimitry Andric } 2900b57cec5SDimitry Andric 2910b57cec5SDimitry Andric static wasm::WasmLimits readLimits(WasmObjectFile::ReadContext &Ctx) { 2920b57cec5SDimitry Andric wasm::WasmLimits Result; 2930b57cec5SDimitry Andric Result.Flags = readVaruint32(Ctx); 294fe6060f1SDimitry Andric Result.Minimum = readVaruint64(Ctx); 2950b57cec5SDimitry Andric if (Result.Flags & wasm::WASM_LIMITS_FLAG_HAS_MAX) 2965ffd83dbSDimitry Andric Result.Maximum = readVaruint64(Ctx); 2970b57cec5SDimitry Andric return Result; 2980b57cec5SDimitry Andric } 2990b57cec5SDimitry Andric 300e8d8bef9SDimitry Andric static wasm::WasmTableType readTableType(WasmObjectFile::ReadContext &Ctx) { 301e8d8bef9SDimitry Andric wasm::WasmTableType TableType; 302*0fca6ea1SDimitry Andric auto ElemType = parseValType(Ctx, readVaruint32(Ctx)); 303*0fca6ea1SDimitry Andric TableType.ElemType = ElemType; 304e8d8bef9SDimitry Andric TableType.Limits = readLimits(Ctx); 305e8d8bef9SDimitry Andric return TableType; 3060b57cec5SDimitry Andric } 3070b57cec5SDimitry Andric 3080b57cec5SDimitry Andric static Error readSection(WasmSection &Section, WasmObjectFile::ReadContext &Ctx, 3090b57cec5SDimitry Andric WasmSectionOrderChecker &Checker) { 3100b57cec5SDimitry Andric Section.Type = readUint8(Ctx); 3110b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "readSection type=" << Section.Type << "\n"); 3128a4dda33SDimitry Andric // When reading the section's size, store the size of the LEB used to encode 3138a4dda33SDimitry Andric // it. This allows objcopy/strip to reproduce the binary identically. 3148a4dda33SDimitry Andric const uint8_t *PreSizePtr = Ctx.Ptr; 3150b57cec5SDimitry Andric uint32_t Size = readVaruint32(Ctx); 3168a4dda33SDimitry Andric Section.HeaderSecSizeEncodingLen = Ctx.Ptr - PreSizePtr; 317cb14a3feSDimitry Andric Section.Offset = Ctx.Ptr - Ctx.Start; 3180b57cec5SDimitry Andric if (Size == 0) 319e8d8bef9SDimitry Andric return make_error<StringError>("zero length section", 3200b57cec5SDimitry Andric object_error::parse_failed); 3210b57cec5SDimitry Andric if (Ctx.Ptr + Size > Ctx.End) 322e8d8bef9SDimitry Andric return make_error<StringError>("section too large", 3230b57cec5SDimitry Andric object_error::parse_failed); 3240b57cec5SDimitry Andric if (Section.Type == wasm::WASM_SEC_CUSTOM) { 3250b57cec5SDimitry Andric WasmObjectFile::ReadContext SectionCtx; 3260b57cec5SDimitry Andric SectionCtx.Start = Ctx.Ptr; 3270b57cec5SDimitry Andric SectionCtx.Ptr = Ctx.Ptr; 3280b57cec5SDimitry Andric SectionCtx.End = Ctx.Ptr + Size; 3290b57cec5SDimitry Andric 3300b57cec5SDimitry Andric Section.Name = readString(SectionCtx); 3310b57cec5SDimitry Andric 3320b57cec5SDimitry Andric uint32_t SectionNameSize = SectionCtx.Ptr - SectionCtx.Start; 3330b57cec5SDimitry Andric Ctx.Ptr += SectionNameSize; 3340b57cec5SDimitry Andric Size -= SectionNameSize; 3350b57cec5SDimitry Andric } 3360b57cec5SDimitry Andric 3370b57cec5SDimitry Andric if (!Checker.isValidSectionOrder(Section.Type, Section.Name)) { 338e8d8bef9SDimitry Andric return make_error<StringError>("out of order section type: " + 3390b57cec5SDimitry Andric llvm::to_string(Section.Type), 3400b57cec5SDimitry Andric object_error::parse_failed); 3410b57cec5SDimitry Andric } 3420b57cec5SDimitry Andric 3430b57cec5SDimitry Andric Section.Content = ArrayRef<uint8_t>(Ctx.Ptr, Size); 3440b57cec5SDimitry Andric Ctx.Ptr += Size; 3450b57cec5SDimitry Andric return Error::success(); 3460b57cec5SDimitry Andric } 3470b57cec5SDimitry Andric 3480b57cec5SDimitry Andric WasmObjectFile::WasmObjectFile(MemoryBufferRef Buffer, Error &Err) 3490b57cec5SDimitry Andric : ObjectFile(Binary::ID_Wasm, Buffer) { 3500b57cec5SDimitry Andric ErrorAsOutParameter ErrAsOutParam(&Err); 3510b57cec5SDimitry Andric Header.Magic = getData().substr(0, 4); 3520b57cec5SDimitry Andric if (Header.Magic != StringRef("\0asm", 4)) { 353e8d8bef9SDimitry Andric Err = make_error<StringError>("invalid magic number", 354e8d8bef9SDimitry Andric object_error::parse_failed); 3550b57cec5SDimitry Andric return; 3560b57cec5SDimitry Andric } 3570b57cec5SDimitry Andric 3580b57cec5SDimitry Andric ReadContext Ctx; 3590b57cec5SDimitry Andric Ctx.Start = getData().bytes_begin(); 3600b57cec5SDimitry Andric Ctx.Ptr = Ctx.Start + 4; 3610b57cec5SDimitry Andric Ctx.End = Ctx.Start + getData().size(); 3620b57cec5SDimitry Andric 3630b57cec5SDimitry Andric if (Ctx.Ptr + 4 > Ctx.End) { 364e8d8bef9SDimitry Andric Err = make_error<StringError>("missing version number", 3650b57cec5SDimitry Andric object_error::parse_failed); 3660b57cec5SDimitry Andric return; 3670b57cec5SDimitry Andric } 3680b57cec5SDimitry Andric 3690b57cec5SDimitry Andric Header.Version = readUint32(Ctx); 3700b57cec5SDimitry Andric if (Header.Version != wasm::WasmVersion) { 371e8d8bef9SDimitry Andric Err = make_error<StringError>("invalid version number: " + 372e8d8bef9SDimitry Andric Twine(Header.Version), 3730b57cec5SDimitry Andric object_error::parse_failed); 3740b57cec5SDimitry Andric return; 3750b57cec5SDimitry Andric } 3760b57cec5SDimitry Andric 3770b57cec5SDimitry Andric WasmSectionOrderChecker Checker; 3780b57cec5SDimitry Andric while (Ctx.Ptr < Ctx.End) { 379349cc55cSDimitry Andric WasmSection Sec; 3800b57cec5SDimitry Andric if ((Err = readSection(Sec, Ctx, Checker))) 3810b57cec5SDimitry Andric return; 3820b57cec5SDimitry Andric if ((Err = parseSection(Sec))) 3830b57cec5SDimitry Andric return; 3840b57cec5SDimitry Andric 3850b57cec5SDimitry Andric Sections.push_back(Sec); 3860b57cec5SDimitry Andric } 3870b57cec5SDimitry Andric } 3880b57cec5SDimitry Andric 3890b57cec5SDimitry Andric Error WasmObjectFile::parseSection(WasmSection &Sec) { 3900b57cec5SDimitry Andric ReadContext Ctx; 3910b57cec5SDimitry Andric Ctx.Start = Sec.Content.data(); 3920b57cec5SDimitry Andric Ctx.End = Ctx.Start + Sec.Content.size(); 3930b57cec5SDimitry Andric Ctx.Ptr = Ctx.Start; 3940b57cec5SDimitry Andric switch (Sec.Type) { 3950b57cec5SDimitry Andric case wasm::WASM_SEC_CUSTOM: 3960b57cec5SDimitry Andric return parseCustomSection(Sec, Ctx); 3970b57cec5SDimitry Andric case wasm::WASM_SEC_TYPE: 3980b57cec5SDimitry Andric return parseTypeSection(Ctx); 3990b57cec5SDimitry Andric case wasm::WASM_SEC_IMPORT: 4000b57cec5SDimitry Andric return parseImportSection(Ctx); 4010b57cec5SDimitry Andric case wasm::WASM_SEC_FUNCTION: 4020b57cec5SDimitry Andric return parseFunctionSection(Ctx); 4030b57cec5SDimitry Andric case wasm::WASM_SEC_TABLE: 4040b57cec5SDimitry Andric return parseTableSection(Ctx); 4050b57cec5SDimitry Andric case wasm::WASM_SEC_MEMORY: 4060b57cec5SDimitry Andric return parseMemorySection(Ctx); 407fe6060f1SDimitry Andric case wasm::WASM_SEC_TAG: 408fe6060f1SDimitry Andric return parseTagSection(Ctx); 4095ffd83dbSDimitry Andric case wasm::WASM_SEC_GLOBAL: 4105ffd83dbSDimitry Andric return parseGlobalSection(Ctx); 4110b57cec5SDimitry Andric case wasm::WASM_SEC_EXPORT: 4120b57cec5SDimitry Andric return parseExportSection(Ctx); 4130b57cec5SDimitry Andric case wasm::WASM_SEC_START: 4140b57cec5SDimitry Andric return parseStartSection(Ctx); 4150b57cec5SDimitry Andric case wasm::WASM_SEC_ELEM: 4160b57cec5SDimitry Andric return parseElemSection(Ctx); 4170b57cec5SDimitry Andric case wasm::WASM_SEC_CODE: 4180b57cec5SDimitry Andric return parseCodeSection(Ctx); 4190b57cec5SDimitry Andric case wasm::WASM_SEC_DATA: 4200b57cec5SDimitry Andric return parseDataSection(Ctx); 4210b57cec5SDimitry Andric case wasm::WASM_SEC_DATACOUNT: 4220b57cec5SDimitry Andric return parseDataCountSection(Ctx); 4230b57cec5SDimitry Andric default: 4240b57cec5SDimitry Andric return make_error<GenericBinaryError>( 425e8d8bef9SDimitry Andric "invalid section type: " + Twine(Sec.Type), object_error::parse_failed); 4260b57cec5SDimitry Andric } 4270b57cec5SDimitry Andric } 4280b57cec5SDimitry Andric 4290b57cec5SDimitry Andric Error WasmObjectFile::parseDylinkSection(ReadContext &Ctx) { 430349cc55cSDimitry Andric // Legacy "dylink" section support. 431349cc55cSDimitry Andric // See parseDylink0Section for the current "dylink.0" section parsing. 4320b57cec5SDimitry Andric HasDylinkSection = true; 4330b57cec5SDimitry Andric DylinkInfo.MemorySize = readVaruint32(Ctx); 4340b57cec5SDimitry Andric DylinkInfo.MemoryAlignment = readVaruint32(Ctx); 4350b57cec5SDimitry Andric DylinkInfo.TableSize = readVaruint32(Ctx); 4360b57cec5SDimitry Andric DylinkInfo.TableAlignment = readVaruint32(Ctx); 4370b57cec5SDimitry Andric uint32_t Count = readVaruint32(Ctx); 4380b57cec5SDimitry Andric while (Count--) { 4390b57cec5SDimitry Andric DylinkInfo.Needed.push_back(readString(Ctx)); 4400b57cec5SDimitry Andric } 441349cc55cSDimitry Andric 4420b57cec5SDimitry Andric if (Ctx.Ptr != Ctx.End) 4430b57cec5SDimitry Andric return make_error<GenericBinaryError>("dylink section ended prematurely", 4440b57cec5SDimitry Andric object_error::parse_failed); 4450b57cec5SDimitry Andric return Error::success(); 4460b57cec5SDimitry Andric } 4470b57cec5SDimitry Andric 448349cc55cSDimitry Andric Error WasmObjectFile::parseDylink0Section(ReadContext &Ctx) { 449349cc55cSDimitry Andric // See 450349cc55cSDimitry Andric // https://github.com/WebAssembly/tool-conventions/blob/main/DynamicLinking.md 451349cc55cSDimitry Andric HasDylinkSection = true; 452349cc55cSDimitry Andric 453349cc55cSDimitry Andric const uint8_t *OrigEnd = Ctx.End; 454349cc55cSDimitry Andric while (Ctx.Ptr < OrigEnd) { 455349cc55cSDimitry Andric Ctx.End = OrigEnd; 456349cc55cSDimitry Andric uint8_t Type = readUint8(Ctx); 457349cc55cSDimitry Andric uint32_t Size = readVaruint32(Ctx); 458349cc55cSDimitry Andric LLVM_DEBUG(dbgs() << "readSubsection type=" << int(Type) << " size=" << Size 459349cc55cSDimitry Andric << "\n"); 460349cc55cSDimitry Andric Ctx.End = Ctx.Ptr + Size; 461349cc55cSDimitry Andric uint32_t Count; 462349cc55cSDimitry Andric switch (Type) { 463349cc55cSDimitry Andric case wasm::WASM_DYLINK_MEM_INFO: 464349cc55cSDimitry Andric DylinkInfo.MemorySize = readVaruint32(Ctx); 465349cc55cSDimitry Andric DylinkInfo.MemoryAlignment = readVaruint32(Ctx); 466349cc55cSDimitry Andric DylinkInfo.TableSize = readVaruint32(Ctx); 467349cc55cSDimitry Andric DylinkInfo.TableAlignment = readVaruint32(Ctx); 468349cc55cSDimitry Andric break; 469349cc55cSDimitry Andric case wasm::WASM_DYLINK_NEEDED: 470349cc55cSDimitry Andric Count = readVaruint32(Ctx); 471349cc55cSDimitry Andric while (Count--) { 472349cc55cSDimitry Andric DylinkInfo.Needed.push_back(readString(Ctx)); 473349cc55cSDimitry Andric } 474349cc55cSDimitry Andric break; 475349cc55cSDimitry Andric case wasm::WASM_DYLINK_EXPORT_INFO: { 476349cc55cSDimitry Andric uint32_t Count = readVaruint32(Ctx); 477349cc55cSDimitry Andric while (Count--) { 478349cc55cSDimitry Andric DylinkInfo.ExportInfo.push_back({readString(Ctx), readVaruint32(Ctx)}); 479349cc55cSDimitry Andric } 480349cc55cSDimitry Andric break; 481349cc55cSDimitry Andric } 482349cc55cSDimitry Andric case wasm::WASM_DYLINK_IMPORT_INFO: { 483349cc55cSDimitry Andric uint32_t Count = readVaruint32(Ctx); 484349cc55cSDimitry Andric while (Count--) { 485349cc55cSDimitry Andric DylinkInfo.ImportInfo.push_back( 486349cc55cSDimitry Andric {readString(Ctx), readString(Ctx), readVaruint32(Ctx)}); 487349cc55cSDimitry Andric } 488349cc55cSDimitry Andric break; 489349cc55cSDimitry Andric } 490349cc55cSDimitry Andric default: 491349cc55cSDimitry Andric LLVM_DEBUG(dbgs() << "unknown dylink.0 sub-section: " << Type << "\n"); 492349cc55cSDimitry Andric Ctx.Ptr += Size; 493349cc55cSDimitry Andric break; 494349cc55cSDimitry Andric } 495349cc55cSDimitry Andric if (Ctx.Ptr != Ctx.End) { 496349cc55cSDimitry Andric return make_error<GenericBinaryError>( 497349cc55cSDimitry Andric "dylink.0 sub-section ended prematurely", object_error::parse_failed); 498349cc55cSDimitry Andric } 499349cc55cSDimitry Andric } 500349cc55cSDimitry Andric 501349cc55cSDimitry Andric if (Ctx.Ptr != Ctx.End) 502349cc55cSDimitry Andric return make_error<GenericBinaryError>("dylink.0 section ended prematurely", 503349cc55cSDimitry Andric object_error::parse_failed); 504349cc55cSDimitry Andric return Error::success(); 505349cc55cSDimitry Andric } 506349cc55cSDimitry Andric 5070b57cec5SDimitry Andric Error WasmObjectFile::parseNameSection(ReadContext &Ctx) { 508e8d8bef9SDimitry Andric llvm::DenseSet<uint64_t> SeenFunctions; 509e8d8bef9SDimitry Andric llvm::DenseSet<uint64_t> SeenGlobals; 510e8d8bef9SDimitry Andric llvm::DenseSet<uint64_t> SeenSegments; 5110b57cec5SDimitry Andric 512*0fca6ea1SDimitry Andric // If we have linking section (symbol table) or if we are parsing a DSO 513*0fca6ea1SDimitry Andric // then we don't use the name section for symbol information. 514*0fca6ea1SDimitry Andric bool PopulateSymbolTable = !HasLinkingSection && !HasDylinkSection; 515*0fca6ea1SDimitry Andric 516*0fca6ea1SDimitry Andric // If we are using the name section for symbol information then it will 517*0fca6ea1SDimitry Andric // supersede any symbols created by the export section. 518*0fca6ea1SDimitry Andric if (PopulateSymbolTable) 519*0fca6ea1SDimitry Andric Symbols.clear(); 520*0fca6ea1SDimitry Andric 5210b57cec5SDimitry Andric while (Ctx.Ptr < Ctx.End) { 5220b57cec5SDimitry Andric uint8_t Type = readUint8(Ctx); 5230b57cec5SDimitry Andric uint32_t Size = readVaruint32(Ctx); 5240b57cec5SDimitry Andric const uint8_t *SubSectionEnd = Ctx.Ptr + Size; 525*0fca6ea1SDimitry Andric 5260b57cec5SDimitry Andric switch (Type) { 527e8d8bef9SDimitry Andric case wasm::WASM_NAMES_FUNCTION: 528e8d8bef9SDimitry Andric case wasm::WASM_NAMES_GLOBAL: 529e8d8bef9SDimitry Andric case wasm::WASM_NAMES_DATA_SEGMENT: { 5300b57cec5SDimitry Andric uint32_t Count = readVaruint32(Ctx); 5310b57cec5SDimitry Andric while (Count--) { 5320b57cec5SDimitry Andric uint32_t Index = readVaruint32(Ctx); 5330b57cec5SDimitry Andric StringRef Name = readString(Ctx); 534e8d8bef9SDimitry Andric wasm::NameType nameType = wasm::NameType::FUNCTION; 535*0fca6ea1SDimitry Andric wasm::WasmSymbolInfo Info{Name, 536*0fca6ea1SDimitry Andric /*Kind */ wasm::WASM_SYMBOL_TYPE_FUNCTION, 537*0fca6ea1SDimitry Andric /* Flags */ 0, 538*0fca6ea1SDimitry Andric /* ImportModule */ std::nullopt, 539*0fca6ea1SDimitry Andric /* ImportName */ std::nullopt, 540*0fca6ea1SDimitry Andric /* ExportName */ std::nullopt, 541*0fca6ea1SDimitry Andric {/* ElementIndex */ Index}}; 542*0fca6ea1SDimitry Andric const wasm::WasmSignature *Signature = nullptr; 543*0fca6ea1SDimitry Andric const wasm::WasmGlobalType *GlobalType = nullptr; 544*0fca6ea1SDimitry Andric const wasm::WasmTableType *TableType = nullptr; 545e8d8bef9SDimitry Andric if (Type == wasm::WASM_NAMES_FUNCTION) { 546e8d8bef9SDimitry Andric if (!SeenFunctions.insert(Index).second) 547e8d8bef9SDimitry Andric return make_error<GenericBinaryError>( 548e8d8bef9SDimitry Andric "function named more than once", object_error::parse_failed); 5490b57cec5SDimitry Andric if (!isValidFunctionIndex(Index) || Name.empty()) 55081ad6265SDimitry Andric return make_error<GenericBinaryError>("invalid function name entry", 5510b57cec5SDimitry Andric object_error::parse_failed); 552e8d8bef9SDimitry Andric 553*0fca6ea1SDimitry Andric if (isDefinedFunctionIndex(Index)) { 554*0fca6ea1SDimitry Andric wasm::WasmFunction &F = getDefinedFunction(Index); 555*0fca6ea1SDimitry Andric F.DebugName = Name; 556*0fca6ea1SDimitry Andric Signature = &Signatures[F.SigIndex]; 557*0fca6ea1SDimitry Andric if (F.ExportName) { 558*0fca6ea1SDimitry Andric Info.ExportName = F.ExportName; 559*0fca6ea1SDimitry Andric Info.Flags |= wasm::WASM_SYMBOL_BINDING_GLOBAL; 560*0fca6ea1SDimitry Andric } else { 561*0fca6ea1SDimitry Andric Info.Flags |= wasm::WASM_SYMBOL_BINDING_LOCAL; 562*0fca6ea1SDimitry Andric } 563*0fca6ea1SDimitry Andric } else { 564*0fca6ea1SDimitry Andric Info.Flags |= wasm::WASM_SYMBOL_UNDEFINED; 565*0fca6ea1SDimitry Andric } 566e8d8bef9SDimitry Andric } else if (Type == wasm::WASM_NAMES_GLOBAL) { 567e8d8bef9SDimitry Andric if (!SeenGlobals.insert(Index).second) 568e8d8bef9SDimitry Andric return make_error<GenericBinaryError>("global named more than once", 569e8d8bef9SDimitry Andric object_error::parse_failed); 570e8d8bef9SDimitry Andric if (!isValidGlobalIndex(Index) || Name.empty()) 57181ad6265SDimitry Andric return make_error<GenericBinaryError>("invalid global name entry", 572e8d8bef9SDimitry Andric object_error::parse_failed); 573*0fca6ea1SDimitry Andric nameType = wasm::NameType::GLOBAL; 574*0fca6ea1SDimitry Andric Info.Kind = wasm::WASM_SYMBOL_TYPE_GLOBAL; 575*0fca6ea1SDimitry Andric if (isDefinedGlobalIndex(Index)) { 576*0fca6ea1SDimitry Andric GlobalType = &getDefinedGlobal(Index).Type; 577e8d8bef9SDimitry Andric } else { 578*0fca6ea1SDimitry Andric Info.Flags |= wasm::WASM_SYMBOL_UNDEFINED; 579*0fca6ea1SDimitry Andric } 580*0fca6ea1SDimitry Andric } else { 581e8d8bef9SDimitry Andric if (!SeenSegments.insert(Index).second) 582e8d8bef9SDimitry Andric return make_error<GenericBinaryError>( 583e8d8bef9SDimitry Andric "segment named more than once", object_error::parse_failed); 584e8d8bef9SDimitry Andric if (Index > DataSegments.size()) 58581ad6265SDimitry Andric return make_error<GenericBinaryError>("invalid data segment name entry", 586e8d8bef9SDimitry Andric object_error::parse_failed); 587*0fca6ea1SDimitry Andric nameType = wasm::NameType::DATA_SEGMENT; 588*0fca6ea1SDimitry Andric Info.Kind = wasm::WASM_SYMBOL_TYPE_DATA; 589*0fca6ea1SDimitry Andric Info.Flags |= wasm::WASM_SYMBOL_BINDING_LOCAL; 590*0fca6ea1SDimitry Andric assert(Index < DataSegments.size()); 591*0fca6ea1SDimitry Andric Info.DataRef = wasm::WasmDataReference{ 592*0fca6ea1SDimitry Andric Index, 0, DataSegments[Index].Data.Content.size()}; 593e8d8bef9SDimitry Andric } 594e8d8bef9SDimitry Andric DebugNames.push_back(wasm::WasmDebugName{nameType, Index, Name}); 595*0fca6ea1SDimitry Andric if (PopulateSymbolTable) 596*0fca6ea1SDimitry Andric Symbols.emplace_back(Info, GlobalType, TableType, Signature); 5970b57cec5SDimitry Andric } 5980b57cec5SDimitry Andric break; 5990b57cec5SDimitry Andric } 6000b57cec5SDimitry Andric // Ignore local names for now 6010b57cec5SDimitry Andric case wasm::WASM_NAMES_LOCAL: 6020b57cec5SDimitry Andric default: 6030b57cec5SDimitry Andric Ctx.Ptr += Size; 6040b57cec5SDimitry Andric break; 6050b57cec5SDimitry Andric } 6060b57cec5SDimitry Andric if (Ctx.Ptr != SubSectionEnd) 6070b57cec5SDimitry Andric return make_error<GenericBinaryError>( 608e8d8bef9SDimitry Andric "name sub-section ended prematurely", object_error::parse_failed); 6090b57cec5SDimitry Andric } 6100b57cec5SDimitry Andric 6110b57cec5SDimitry Andric if (Ctx.Ptr != Ctx.End) 612e8d8bef9SDimitry Andric return make_error<GenericBinaryError>("name section ended prematurely", 6130b57cec5SDimitry Andric object_error::parse_failed); 6140b57cec5SDimitry Andric return Error::success(); 6150b57cec5SDimitry Andric } 6160b57cec5SDimitry Andric 6170b57cec5SDimitry Andric Error WasmObjectFile::parseLinkingSection(ReadContext &Ctx) { 6180b57cec5SDimitry Andric HasLinkingSection = true; 6190b57cec5SDimitry Andric 6200b57cec5SDimitry Andric LinkingData.Version = readVaruint32(Ctx); 6210b57cec5SDimitry Andric if (LinkingData.Version != wasm::WasmMetadataVersion) { 6220b57cec5SDimitry Andric return make_error<GenericBinaryError>( 623e8d8bef9SDimitry Andric "unexpected metadata version: " + Twine(LinkingData.Version) + 6240b57cec5SDimitry Andric " (Expected: " + Twine(wasm::WasmMetadataVersion) + ")", 6250b57cec5SDimitry Andric object_error::parse_failed); 6260b57cec5SDimitry Andric } 6270b57cec5SDimitry Andric 6280b57cec5SDimitry Andric const uint8_t *OrigEnd = Ctx.End; 6290b57cec5SDimitry Andric while (Ctx.Ptr < OrigEnd) { 6300b57cec5SDimitry Andric Ctx.End = OrigEnd; 6310b57cec5SDimitry Andric uint8_t Type = readUint8(Ctx); 6320b57cec5SDimitry Andric uint32_t Size = readVaruint32(Ctx); 6330b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "readSubsection type=" << int(Type) << " size=" << Size 6340b57cec5SDimitry Andric << "\n"); 6350b57cec5SDimitry Andric Ctx.End = Ctx.Ptr + Size; 6360b57cec5SDimitry Andric switch (Type) { 6370b57cec5SDimitry Andric case wasm::WASM_SYMBOL_TABLE: 6380b57cec5SDimitry Andric if (Error Err = parseLinkingSectionSymtab(Ctx)) 6390b57cec5SDimitry Andric return Err; 6400b57cec5SDimitry Andric break; 6410b57cec5SDimitry Andric case wasm::WASM_SEGMENT_INFO: { 6420b57cec5SDimitry Andric uint32_t Count = readVaruint32(Ctx); 6430b57cec5SDimitry Andric if (Count > DataSegments.size()) 644e8d8bef9SDimitry Andric return make_error<GenericBinaryError>("too many segment names", 6450b57cec5SDimitry Andric object_error::parse_failed); 6460b57cec5SDimitry Andric for (uint32_t I = 0; I < Count; I++) { 6470b57cec5SDimitry Andric DataSegments[I].Data.Name = readString(Ctx); 6480b57cec5SDimitry Andric DataSegments[I].Data.Alignment = readVaruint32(Ctx); 649fe6060f1SDimitry Andric DataSegments[I].Data.LinkingFlags = readVaruint32(Ctx); 6500b57cec5SDimitry Andric } 6510b57cec5SDimitry Andric break; 6520b57cec5SDimitry Andric } 6530b57cec5SDimitry Andric case wasm::WASM_INIT_FUNCS: { 6540b57cec5SDimitry Andric uint32_t Count = readVaruint32(Ctx); 6550b57cec5SDimitry Andric LinkingData.InitFunctions.reserve(Count); 6560b57cec5SDimitry Andric for (uint32_t I = 0; I < Count; I++) { 6570b57cec5SDimitry Andric wasm::WasmInitFunc Init; 6580b57cec5SDimitry Andric Init.Priority = readVaruint32(Ctx); 6590b57cec5SDimitry Andric Init.Symbol = readVaruint32(Ctx); 6600b57cec5SDimitry Andric if (!isValidFunctionSymbol(Init.Symbol)) 661e8d8bef9SDimitry Andric return make_error<GenericBinaryError>("invalid function symbol: " + 6620b57cec5SDimitry Andric Twine(Init.Symbol), 6630b57cec5SDimitry Andric object_error::parse_failed); 6640b57cec5SDimitry Andric LinkingData.InitFunctions.emplace_back(Init); 6650b57cec5SDimitry Andric } 6660b57cec5SDimitry Andric break; 6670b57cec5SDimitry Andric } 6680b57cec5SDimitry Andric case wasm::WASM_COMDAT_INFO: 6690b57cec5SDimitry Andric if (Error Err = parseLinkingSectionComdat(Ctx)) 6700b57cec5SDimitry Andric return Err; 6710b57cec5SDimitry Andric break; 6720b57cec5SDimitry Andric default: 6730b57cec5SDimitry Andric Ctx.Ptr += Size; 6740b57cec5SDimitry Andric break; 6750b57cec5SDimitry Andric } 6760b57cec5SDimitry Andric if (Ctx.Ptr != Ctx.End) 6770b57cec5SDimitry Andric return make_error<GenericBinaryError>( 678e8d8bef9SDimitry Andric "linking sub-section ended prematurely", object_error::parse_failed); 6790b57cec5SDimitry Andric } 6800b57cec5SDimitry Andric if (Ctx.Ptr != OrigEnd) 681e8d8bef9SDimitry Andric return make_error<GenericBinaryError>("linking section ended prematurely", 6820b57cec5SDimitry Andric object_error::parse_failed); 6830b57cec5SDimitry Andric return Error::success(); 6840b57cec5SDimitry Andric } 6850b57cec5SDimitry Andric 6860b57cec5SDimitry Andric Error WasmObjectFile::parseLinkingSectionSymtab(ReadContext &Ctx) { 6870b57cec5SDimitry Andric uint32_t Count = readVaruint32(Ctx); 688cb14a3feSDimitry Andric // Clear out any symbol information that was derived from the exports 689cb14a3feSDimitry Andric // section. 690cb14a3feSDimitry Andric Symbols.clear(); 6910b57cec5SDimitry Andric Symbols.reserve(Count); 6920b57cec5SDimitry Andric StringSet<> SymbolNames; 6930b57cec5SDimitry Andric 6940b57cec5SDimitry Andric std::vector<wasm::WasmImport *> ImportedGlobals; 6950b57cec5SDimitry Andric std::vector<wasm::WasmImport *> ImportedFunctions; 696fe6060f1SDimitry Andric std::vector<wasm::WasmImport *> ImportedTags; 697e8d8bef9SDimitry Andric std::vector<wasm::WasmImport *> ImportedTables; 6980b57cec5SDimitry Andric ImportedGlobals.reserve(Imports.size()); 6990b57cec5SDimitry Andric ImportedFunctions.reserve(Imports.size()); 700fe6060f1SDimitry Andric ImportedTags.reserve(Imports.size()); 701e8d8bef9SDimitry Andric ImportedTables.reserve(Imports.size()); 7020b57cec5SDimitry Andric for (auto &I : Imports) { 7030b57cec5SDimitry Andric if (I.Kind == wasm::WASM_EXTERNAL_FUNCTION) 7040b57cec5SDimitry Andric ImportedFunctions.emplace_back(&I); 7050b57cec5SDimitry Andric else if (I.Kind == wasm::WASM_EXTERNAL_GLOBAL) 7060b57cec5SDimitry Andric ImportedGlobals.emplace_back(&I); 707fe6060f1SDimitry Andric else if (I.Kind == wasm::WASM_EXTERNAL_TAG) 708fe6060f1SDimitry Andric ImportedTags.emplace_back(&I); 709e8d8bef9SDimitry Andric else if (I.Kind == wasm::WASM_EXTERNAL_TABLE) 710e8d8bef9SDimitry Andric ImportedTables.emplace_back(&I); 7110b57cec5SDimitry Andric } 7120b57cec5SDimitry Andric 7130b57cec5SDimitry Andric while (Count--) { 7140b57cec5SDimitry Andric wasm::WasmSymbolInfo Info; 7150b57cec5SDimitry Andric const wasm::WasmSignature *Signature = nullptr; 7160b57cec5SDimitry Andric const wasm::WasmGlobalType *GlobalType = nullptr; 717e8d8bef9SDimitry Andric const wasm::WasmTableType *TableType = nullptr; 7180b57cec5SDimitry Andric 7190b57cec5SDimitry Andric Info.Kind = readUint8(Ctx); 7200b57cec5SDimitry Andric Info.Flags = readVaruint32(Ctx); 7210b57cec5SDimitry Andric bool IsDefined = (Info.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0; 7220b57cec5SDimitry Andric 7230b57cec5SDimitry Andric switch (Info.Kind) { 7240b57cec5SDimitry Andric case wasm::WASM_SYMBOL_TYPE_FUNCTION: 7250b57cec5SDimitry Andric Info.ElementIndex = readVaruint32(Ctx); 7260b57cec5SDimitry Andric if (!isValidFunctionIndex(Info.ElementIndex) || 7270b57cec5SDimitry Andric IsDefined != isDefinedFunctionIndex(Info.ElementIndex)) 7280b57cec5SDimitry Andric return make_error<GenericBinaryError>("invalid function symbol index", 7290b57cec5SDimitry Andric object_error::parse_failed); 7300b57cec5SDimitry Andric if (IsDefined) { 7310b57cec5SDimitry Andric Info.Name = readString(Ctx); 7320b57cec5SDimitry Andric unsigned FuncIndex = Info.ElementIndex - NumImportedFunctions; 7330b57cec5SDimitry Andric wasm::WasmFunction &Function = Functions[FuncIndex]; 734349cc55cSDimitry Andric Signature = &Signatures[Function.SigIndex]; 7350b57cec5SDimitry Andric if (Function.SymbolName.empty()) 7360b57cec5SDimitry Andric Function.SymbolName = Info.Name; 7370b57cec5SDimitry Andric } else { 7380b57cec5SDimitry Andric wasm::WasmImport &Import = *ImportedFunctions[Info.ElementIndex]; 7395ffd83dbSDimitry Andric if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0) { 7400b57cec5SDimitry Andric Info.Name = readString(Ctx); 7410b57cec5SDimitry Andric Info.ImportName = Import.Field; 7425ffd83dbSDimitry Andric } else { 7435ffd83dbSDimitry Andric Info.Name = Import.Field; 7445ffd83dbSDimitry Andric } 7455ffd83dbSDimitry Andric Signature = &Signatures[Import.SigIndex]; 7460b57cec5SDimitry Andric Info.ImportModule = Import.Module; 7470b57cec5SDimitry Andric } 7480b57cec5SDimitry Andric break; 7490b57cec5SDimitry Andric 7500b57cec5SDimitry Andric case wasm::WASM_SYMBOL_TYPE_GLOBAL: 7510b57cec5SDimitry Andric Info.ElementIndex = readVaruint32(Ctx); 7520b57cec5SDimitry Andric if (!isValidGlobalIndex(Info.ElementIndex) || 7530b57cec5SDimitry Andric IsDefined != isDefinedGlobalIndex(Info.ElementIndex)) 7540b57cec5SDimitry Andric return make_error<GenericBinaryError>("invalid global symbol index", 7550b57cec5SDimitry Andric object_error::parse_failed); 7560b57cec5SDimitry Andric if (!IsDefined && (Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) == 7570b57cec5SDimitry Andric wasm::WASM_SYMBOL_BINDING_WEAK) 7580b57cec5SDimitry Andric return make_error<GenericBinaryError>("undefined weak global symbol", 7590b57cec5SDimitry Andric object_error::parse_failed); 7600b57cec5SDimitry Andric if (IsDefined) { 7610b57cec5SDimitry Andric Info.Name = readString(Ctx); 7620b57cec5SDimitry Andric unsigned GlobalIndex = Info.ElementIndex - NumImportedGlobals; 7630b57cec5SDimitry Andric wasm::WasmGlobal &Global = Globals[GlobalIndex]; 7640b57cec5SDimitry Andric GlobalType = &Global.Type; 7650b57cec5SDimitry Andric if (Global.SymbolName.empty()) 7660b57cec5SDimitry Andric Global.SymbolName = Info.Name; 7670b57cec5SDimitry Andric } else { 7680b57cec5SDimitry Andric wasm::WasmImport &Import = *ImportedGlobals[Info.ElementIndex]; 7695ffd83dbSDimitry Andric if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0) { 7700b57cec5SDimitry Andric Info.Name = readString(Ctx); 7715ffd83dbSDimitry Andric Info.ImportName = Import.Field; 7725ffd83dbSDimitry Andric } else { 7730b57cec5SDimitry Andric Info.Name = Import.Field; 7745ffd83dbSDimitry Andric } 7750b57cec5SDimitry Andric GlobalType = &Import.Global; 776e8d8bef9SDimitry Andric Info.ImportModule = Import.Module; 777e8d8bef9SDimitry Andric } 778e8d8bef9SDimitry Andric break; 779e8d8bef9SDimitry Andric 780e8d8bef9SDimitry Andric case wasm::WASM_SYMBOL_TYPE_TABLE: 781e8d8bef9SDimitry Andric Info.ElementIndex = readVaruint32(Ctx); 782fe6060f1SDimitry Andric if (!isValidTableNumber(Info.ElementIndex) || 783fe6060f1SDimitry Andric IsDefined != isDefinedTableNumber(Info.ElementIndex)) 784e8d8bef9SDimitry Andric return make_error<GenericBinaryError>("invalid table symbol index", 785e8d8bef9SDimitry Andric object_error::parse_failed); 786e8d8bef9SDimitry Andric if (!IsDefined && (Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) == 787e8d8bef9SDimitry Andric wasm::WASM_SYMBOL_BINDING_WEAK) 788e8d8bef9SDimitry Andric return make_error<GenericBinaryError>("undefined weak table symbol", 789e8d8bef9SDimitry Andric object_error::parse_failed); 790e8d8bef9SDimitry Andric if (IsDefined) { 791e8d8bef9SDimitry Andric Info.Name = readString(Ctx); 792fe6060f1SDimitry Andric unsigned TableNumber = Info.ElementIndex - NumImportedTables; 793fe6060f1SDimitry Andric wasm::WasmTable &Table = Tables[TableNumber]; 794e8d8bef9SDimitry Andric TableType = &Table.Type; 795e8d8bef9SDimitry Andric if (Table.SymbolName.empty()) 796e8d8bef9SDimitry Andric Table.SymbolName = Info.Name; 797e8d8bef9SDimitry Andric } else { 798e8d8bef9SDimitry Andric wasm::WasmImport &Import = *ImportedTables[Info.ElementIndex]; 799e8d8bef9SDimitry Andric if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0) { 800e8d8bef9SDimitry Andric Info.Name = readString(Ctx); 8010b57cec5SDimitry Andric Info.ImportName = Import.Field; 802e8d8bef9SDimitry Andric } else { 803e8d8bef9SDimitry Andric Info.Name = Import.Field; 804e8d8bef9SDimitry Andric } 805e8d8bef9SDimitry Andric TableType = &Import.Table; 8060b57cec5SDimitry Andric Info.ImportModule = Import.Module; 8070b57cec5SDimitry Andric } 8080b57cec5SDimitry Andric break; 8090b57cec5SDimitry Andric 8100b57cec5SDimitry Andric case wasm::WASM_SYMBOL_TYPE_DATA: 8110b57cec5SDimitry Andric Info.Name = readString(Ctx); 8120b57cec5SDimitry Andric if (IsDefined) { 8135ffd83dbSDimitry Andric auto Index = readVaruint32(Ctx); 8145ffd83dbSDimitry Andric auto Offset = readVaruint64(Ctx); 8155ffd83dbSDimitry Andric auto Size = readVaruint64(Ctx); 8165f757f3fSDimitry Andric if (!(Info.Flags & wasm::WASM_SYMBOL_ABSOLUTE)) { 8175f757f3fSDimitry Andric if (static_cast<size_t>(Index) >= DataSegments.size()) 8185f757f3fSDimitry Andric return make_error<GenericBinaryError>( 8195f757f3fSDimitry Andric "invalid data segment index: " + Twine(Index), 8205f757f3fSDimitry Andric object_error::parse_failed); 821fe6060f1SDimitry Andric size_t SegmentSize = DataSegments[Index].Data.Content.size(); 822fe6060f1SDimitry Andric if (Offset > SegmentSize) 823fe6060f1SDimitry Andric return make_error<GenericBinaryError>( 8245f757f3fSDimitry Andric "invalid data symbol offset: `" + Info.Name + 8255f757f3fSDimitry Andric "` (offset: " + Twine(Offset) + 8265f757f3fSDimitry Andric " segment size: " + Twine(SegmentSize) + ")", 8270b57cec5SDimitry Andric object_error::parse_failed); 8285f757f3fSDimitry Andric } 8290b57cec5SDimitry Andric Info.DataRef = wasm::WasmDataReference{Index, Offset, Size}; 8300b57cec5SDimitry Andric } 8310b57cec5SDimitry Andric break; 8320b57cec5SDimitry Andric 8330b57cec5SDimitry Andric case wasm::WASM_SYMBOL_TYPE_SECTION: { 8340b57cec5SDimitry Andric if ((Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) != 8350b57cec5SDimitry Andric wasm::WASM_SYMBOL_BINDING_LOCAL) 8360b57cec5SDimitry Andric return make_error<GenericBinaryError>( 837e8d8bef9SDimitry Andric "section symbols must have local binding", 8380b57cec5SDimitry Andric object_error::parse_failed); 8390b57cec5SDimitry Andric Info.ElementIndex = readVaruint32(Ctx); 8400b57cec5SDimitry Andric // Use somewhat unique section name as symbol name. 8410b57cec5SDimitry Andric StringRef SectionName = Sections[Info.ElementIndex].Name; 8420b57cec5SDimitry Andric Info.Name = SectionName; 8430b57cec5SDimitry Andric break; 8440b57cec5SDimitry Andric } 8450b57cec5SDimitry Andric 846fe6060f1SDimitry Andric case wasm::WASM_SYMBOL_TYPE_TAG: { 8470b57cec5SDimitry Andric Info.ElementIndex = readVaruint32(Ctx); 848fe6060f1SDimitry Andric if (!isValidTagIndex(Info.ElementIndex) || 849fe6060f1SDimitry Andric IsDefined != isDefinedTagIndex(Info.ElementIndex)) 850fe6060f1SDimitry Andric return make_error<GenericBinaryError>("invalid tag symbol index", 8510b57cec5SDimitry Andric object_error::parse_failed); 8520b57cec5SDimitry Andric if (!IsDefined && (Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) == 8530b57cec5SDimitry Andric wasm::WASM_SYMBOL_BINDING_WEAK) 8540b57cec5SDimitry Andric return make_error<GenericBinaryError>("undefined weak global symbol", 8550b57cec5SDimitry Andric object_error::parse_failed); 8560b57cec5SDimitry Andric if (IsDefined) { 8570b57cec5SDimitry Andric Info.Name = readString(Ctx); 858fe6060f1SDimitry Andric unsigned TagIndex = Info.ElementIndex - NumImportedTags; 859fe6060f1SDimitry Andric wasm::WasmTag &Tag = Tags[TagIndex]; 860349cc55cSDimitry Andric Signature = &Signatures[Tag.SigIndex]; 861fe6060f1SDimitry Andric if (Tag.SymbolName.empty()) 862fe6060f1SDimitry Andric Tag.SymbolName = Info.Name; 8630b57cec5SDimitry Andric 8640b57cec5SDimitry Andric } else { 865fe6060f1SDimitry Andric wasm::WasmImport &Import = *ImportedTags[Info.ElementIndex]; 8665ffd83dbSDimitry Andric if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0) { 8670b57cec5SDimitry Andric Info.Name = readString(Ctx); 8685ffd83dbSDimitry Andric Info.ImportName = Import.Field; 8695ffd83dbSDimitry Andric } else { 8700b57cec5SDimitry Andric Info.Name = Import.Field; 8715ffd83dbSDimitry Andric } 872349cc55cSDimitry Andric Signature = &Signatures[Import.SigIndex]; 8730b57cec5SDimitry Andric Info.ImportModule = Import.Module; 8740b57cec5SDimitry Andric } 8750b57cec5SDimitry Andric break; 8760b57cec5SDimitry Andric } 8770b57cec5SDimitry Andric 8780b57cec5SDimitry Andric default: 879e8d8bef9SDimitry Andric return make_error<GenericBinaryError>("invalid symbol type: " + 880e8d8bef9SDimitry Andric Twine(unsigned(Info.Kind)), 8810b57cec5SDimitry Andric object_error::parse_failed); 8820b57cec5SDimitry Andric } 8830b57cec5SDimitry Andric 8840b57cec5SDimitry Andric if ((Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) != 8850b57cec5SDimitry Andric wasm::WASM_SYMBOL_BINDING_LOCAL && 8860b57cec5SDimitry Andric !SymbolNames.insert(Info.Name).second) 887e8d8bef9SDimitry Andric return make_error<GenericBinaryError>("duplicate symbol name " + 8880b57cec5SDimitry Andric Twine(Info.Name), 8890b57cec5SDimitry Andric object_error::parse_failed); 890*0fca6ea1SDimitry Andric Symbols.emplace_back(Info, GlobalType, TableType, Signature); 8910b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Adding symbol: " << Symbols.back() << "\n"); 8920b57cec5SDimitry Andric } 8930b57cec5SDimitry Andric 8940b57cec5SDimitry Andric return Error::success(); 8950b57cec5SDimitry Andric } 8960b57cec5SDimitry Andric 8970b57cec5SDimitry Andric Error WasmObjectFile::parseLinkingSectionComdat(ReadContext &Ctx) { 8980b57cec5SDimitry Andric uint32_t ComdatCount = readVaruint32(Ctx); 8990b57cec5SDimitry Andric StringSet<> ComdatSet; 9000b57cec5SDimitry Andric for (unsigned ComdatIndex = 0; ComdatIndex < ComdatCount; ++ComdatIndex) { 9010b57cec5SDimitry Andric StringRef Name = readString(Ctx); 9020b57cec5SDimitry Andric if (Name.empty() || !ComdatSet.insert(Name).second) 903e8d8bef9SDimitry Andric return make_error<GenericBinaryError>("bad/duplicate COMDAT name " + 9040b57cec5SDimitry Andric Twine(Name), 9050b57cec5SDimitry Andric object_error::parse_failed); 9060b57cec5SDimitry Andric LinkingData.Comdats.emplace_back(Name); 9070b57cec5SDimitry Andric uint32_t Flags = readVaruint32(Ctx); 9080b57cec5SDimitry Andric if (Flags != 0) 909e8d8bef9SDimitry Andric return make_error<GenericBinaryError>("unsupported COMDAT flags", 9100b57cec5SDimitry Andric object_error::parse_failed); 9110b57cec5SDimitry Andric 9120b57cec5SDimitry Andric uint32_t EntryCount = readVaruint32(Ctx); 9130b57cec5SDimitry Andric while (EntryCount--) { 9140b57cec5SDimitry Andric unsigned Kind = readVaruint32(Ctx); 9150b57cec5SDimitry Andric unsigned Index = readVaruint32(Ctx); 9160b57cec5SDimitry Andric switch (Kind) { 9170b57cec5SDimitry Andric default: 918e8d8bef9SDimitry Andric return make_error<GenericBinaryError>("invalid COMDAT entry type", 9190b57cec5SDimitry Andric object_error::parse_failed); 9200b57cec5SDimitry Andric case wasm::WASM_COMDAT_DATA: 9210b57cec5SDimitry Andric if (Index >= DataSegments.size()) 9220b57cec5SDimitry Andric return make_error<GenericBinaryError>( 9230b57cec5SDimitry Andric "COMDAT data index out of range", object_error::parse_failed); 9240b57cec5SDimitry Andric if (DataSegments[Index].Data.Comdat != UINT32_MAX) 925e8d8bef9SDimitry Andric return make_error<GenericBinaryError>("data segment in two COMDATs", 9260b57cec5SDimitry Andric object_error::parse_failed); 9270b57cec5SDimitry Andric DataSegments[Index].Data.Comdat = ComdatIndex; 9280b57cec5SDimitry Andric break; 9290b57cec5SDimitry Andric case wasm::WASM_COMDAT_FUNCTION: 9300b57cec5SDimitry Andric if (!isDefinedFunctionIndex(Index)) 9310b57cec5SDimitry Andric return make_error<GenericBinaryError>( 9320b57cec5SDimitry Andric "COMDAT function index out of range", object_error::parse_failed); 9330b57cec5SDimitry Andric if (getDefinedFunction(Index).Comdat != UINT32_MAX) 934e8d8bef9SDimitry Andric return make_error<GenericBinaryError>("function in two COMDATs", 9350b57cec5SDimitry Andric object_error::parse_failed); 9360b57cec5SDimitry Andric getDefinedFunction(Index).Comdat = ComdatIndex; 9370b57cec5SDimitry Andric break; 938e8d8bef9SDimitry Andric case wasm::WASM_COMDAT_SECTION: 939e8d8bef9SDimitry Andric if (Index >= Sections.size()) 940e8d8bef9SDimitry Andric return make_error<GenericBinaryError>( 941e8d8bef9SDimitry Andric "COMDAT section index out of range", object_error::parse_failed); 942e8d8bef9SDimitry Andric if (Sections[Index].Type != wasm::WASM_SEC_CUSTOM) 943e8d8bef9SDimitry Andric return make_error<GenericBinaryError>( 944e8d8bef9SDimitry Andric "non-custom section in a COMDAT", object_error::parse_failed); 945e8d8bef9SDimitry Andric Sections[Index].Comdat = ComdatIndex; 946e8d8bef9SDimitry Andric break; 9470b57cec5SDimitry Andric } 9480b57cec5SDimitry Andric } 9490b57cec5SDimitry Andric } 9500b57cec5SDimitry Andric return Error::success(); 9510b57cec5SDimitry Andric } 9520b57cec5SDimitry Andric 9530b57cec5SDimitry Andric Error WasmObjectFile::parseProducersSection(ReadContext &Ctx) { 9540b57cec5SDimitry Andric llvm::SmallSet<StringRef, 3> FieldsSeen; 9550b57cec5SDimitry Andric uint32_t Fields = readVaruint32(Ctx); 9560b57cec5SDimitry Andric for (size_t I = 0; I < Fields; ++I) { 9570b57cec5SDimitry Andric StringRef FieldName = readString(Ctx); 9580b57cec5SDimitry Andric if (!FieldsSeen.insert(FieldName).second) 9590b57cec5SDimitry Andric return make_error<GenericBinaryError>( 960e8d8bef9SDimitry Andric "producers section does not have unique fields", 9610b57cec5SDimitry Andric object_error::parse_failed); 9620b57cec5SDimitry Andric std::vector<std::pair<std::string, std::string>> *ProducerVec = nullptr; 9630b57cec5SDimitry Andric if (FieldName == "language") { 9640b57cec5SDimitry Andric ProducerVec = &ProducerInfo.Languages; 9650b57cec5SDimitry Andric } else if (FieldName == "processed-by") { 9660b57cec5SDimitry Andric ProducerVec = &ProducerInfo.Tools; 9670b57cec5SDimitry Andric } else if (FieldName == "sdk") { 9680b57cec5SDimitry Andric ProducerVec = &ProducerInfo.SDKs; 9690b57cec5SDimitry Andric } else { 9700b57cec5SDimitry Andric return make_error<GenericBinaryError>( 971e8d8bef9SDimitry Andric "producers section field is not named one of language, processed-by, " 9720b57cec5SDimitry Andric "or sdk", 9730b57cec5SDimitry Andric object_error::parse_failed); 9740b57cec5SDimitry Andric } 9750b57cec5SDimitry Andric uint32_t ValueCount = readVaruint32(Ctx); 9760b57cec5SDimitry Andric llvm::SmallSet<StringRef, 8> ProducersSeen; 9770b57cec5SDimitry Andric for (size_t J = 0; J < ValueCount; ++J) { 9780b57cec5SDimitry Andric StringRef Name = readString(Ctx); 9790b57cec5SDimitry Andric StringRef Version = readString(Ctx); 9800b57cec5SDimitry Andric if (!ProducersSeen.insert(Name).second) { 9810b57cec5SDimitry Andric return make_error<GenericBinaryError>( 982e8d8bef9SDimitry Andric "producers section contains repeated producer", 9830b57cec5SDimitry Andric object_error::parse_failed); 9840b57cec5SDimitry Andric } 9855ffd83dbSDimitry Andric ProducerVec->emplace_back(std::string(Name), std::string(Version)); 9860b57cec5SDimitry Andric } 9870b57cec5SDimitry Andric } 9880b57cec5SDimitry Andric if (Ctx.Ptr != Ctx.End) 989e8d8bef9SDimitry Andric return make_error<GenericBinaryError>("producers section ended prematurely", 9900b57cec5SDimitry Andric object_error::parse_failed); 9910b57cec5SDimitry Andric return Error::success(); 9920b57cec5SDimitry Andric } 9930b57cec5SDimitry Andric 9940b57cec5SDimitry Andric Error WasmObjectFile::parseTargetFeaturesSection(ReadContext &Ctx) { 9950b57cec5SDimitry Andric llvm::SmallSet<std::string, 8> FeaturesSeen; 9960b57cec5SDimitry Andric uint32_t FeatureCount = readVaruint32(Ctx); 9970b57cec5SDimitry Andric for (size_t I = 0; I < FeatureCount; ++I) { 9980b57cec5SDimitry Andric wasm::WasmFeatureEntry Feature; 9990b57cec5SDimitry Andric Feature.Prefix = readUint8(Ctx); 10000b57cec5SDimitry Andric switch (Feature.Prefix) { 10010b57cec5SDimitry Andric case wasm::WASM_FEATURE_PREFIX_USED: 10020b57cec5SDimitry Andric case wasm::WASM_FEATURE_PREFIX_REQUIRED: 10030b57cec5SDimitry Andric case wasm::WASM_FEATURE_PREFIX_DISALLOWED: 10040b57cec5SDimitry Andric break; 10050b57cec5SDimitry Andric default: 1006e8d8bef9SDimitry Andric return make_error<GenericBinaryError>("unknown feature policy prefix", 10070b57cec5SDimitry Andric object_error::parse_failed); 10080b57cec5SDimitry Andric } 10095ffd83dbSDimitry Andric Feature.Name = std::string(readString(Ctx)); 10100b57cec5SDimitry Andric if (!FeaturesSeen.insert(Feature.Name).second) 10110b57cec5SDimitry Andric return make_error<GenericBinaryError>( 1012e8d8bef9SDimitry Andric "target features section contains repeated feature \"" + 10130b57cec5SDimitry Andric Feature.Name + "\"", 10140b57cec5SDimitry Andric object_error::parse_failed); 10150b57cec5SDimitry Andric TargetFeatures.push_back(Feature); 10160b57cec5SDimitry Andric } 10170b57cec5SDimitry Andric if (Ctx.Ptr != Ctx.End) 10180b57cec5SDimitry Andric return make_error<GenericBinaryError>( 1019e8d8bef9SDimitry Andric "target features section ended prematurely", 10200b57cec5SDimitry Andric object_error::parse_failed); 10210b57cec5SDimitry Andric return Error::success(); 10220b57cec5SDimitry Andric } 10230b57cec5SDimitry Andric 10240b57cec5SDimitry Andric Error WasmObjectFile::parseRelocSection(StringRef Name, ReadContext &Ctx) { 10250b57cec5SDimitry Andric uint32_t SectionIndex = readVaruint32(Ctx); 10260b57cec5SDimitry Andric if (SectionIndex >= Sections.size()) 1027e8d8bef9SDimitry Andric return make_error<GenericBinaryError>("invalid section index", 10280b57cec5SDimitry Andric object_error::parse_failed); 10290b57cec5SDimitry Andric WasmSection &Section = Sections[SectionIndex]; 10300b57cec5SDimitry Andric uint32_t RelocCount = readVaruint32(Ctx); 10310b57cec5SDimitry Andric uint32_t EndOffset = Section.Content.size(); 10320b57cec5SDimitry Andric uint32_t PreviousOffset = 0; 10330b57cec5SDimitry Andric while (RelocCount--) { 10340b57cec5SDimitry Andric wasm::WasmRelocation Reloc = {}; 1035e8d8bef9SDimitry Andric uint32_t type = readVaruint32(Ctx); 1036e8d8bef9SDimitry Andric Reloc.Type = type; 10370b57cec5SDimitry Andric Reloc.Offset = readVaruint32(Ctx); 10380b57cec5SDimitry Andric if (Reloc.Offset < PreviousOffset) 1039e8d8bef9SDimitry Andric return make_error<GenericBinaryError>("relocations not in offset order", 10400b57cec5SDimitry Andric object_error::parse_failed); 1041*0fca6ea1SDimitry Andric 1042*0fca6ea1SDimitry Andric auto badReloc = [&](StringRef msg) { 1043*0fca6ea1SDimitry Andric return make_error<GenericBinaryError>( 1044*0fca6ea1SDimitry Andric msg + ": " + Twine(Symbols[Reloc.Index].Info.Name), 1045*0fca6ea1SDimitry Andric object_error::parse_failed); 1046*0fca6ea1SDimitry Andric }; 1047*0fca6ea1SDimitry Andric 10480b57cec5SDimitry Andric PreviousOffset = Reloc.Offset; 10490b57cec5SDimitry Andric Reloc.Index = readVaruint32(Ctx); 1050e8d8bef9SDimitry Andric switch (type) { 10510b57cec5SDimitry Andric case wasm::R_WASM_FUNCTION_INDEX_LEB: 105206c3fb27SDimitry Andric case wasm::R_WASM_FUNCTION_INDEX_I32: 10530b57cec5SDimitry Andric case wasm::R_WASM_TABLE_INDEX_SLEB: 1054e8d8bef9SDimitry Andric case wasm::R_WASM_TABLE_INDEX_SLEB64: 10550b57cec5SDimitry Andric case wasm::R_WASM_TABLE_INDEX_I32: 1056e8d8bef9SDimitry Andric case wasm::R_WASM_TABLE_INDEX_I64: 10570b57cec5SDimitry Andric case wasm::R_WASM_TABLE_INDEX_REL_SLEB: 1058fe6060f1SDimitry Andric case wasm::R_WASM_TABLE_INDEX_REL_SLEB64: 10590b57cec5SDimitry Andric if (!isValidFunctionSymbol(Reloc.Index)) 1060*0fca6ea1SDimitry Andric return badReloc("invalid function relocation"); 1061e8d8bef9SDimitry Andric break; 1062e8d8bef9SDimitry Andric case wasm::R_WASM_TABLE_NUMBER_LEB: 1063e8d8bef9SDimitry Andric if (!isValidTableSymbol(Reloc.Index)) 1064*0fca6ea1SDimitry Andric return badReloc("invalid table relocation"); 10650b57cec5SDimitry Andric break; 10660b57cec5SDimitry Andric case wasm::R_WASM_TYPE_INDEX_LEB: 10670b57cec5SDimitry Andric if (Reloc.Index >= Signatures.size()) 1068*0fca6ea1SDimitry Andric return badReloc("invalid relocation type index"); 10690b57cec5SDimitry Andric break; 10700b57cec5SDimitry Andric case wasm::R_WASM_GLOBAL_INDEX_LEB: 10710b57cec5SDimitry Andric // R_WASM_GLOBAL_INDEX_LEB are can be used against function and data 10728bcb0991SDimitry Andric // symbols to refer to their GOT entries. 10730b57cec5SDimitry Andric if (!isValidGlobalSymbol(Reloc.Index) && 10740b57cec5SDimitry Andric !isValidDataSymbol(Reloc.Index) && 10750b57cec5SDimitry Andric !isValidFunctionSymbol(Reloc.Index)) 1076*0fca6ea1SDimitry Andric return badReloc("invalid global relocation"); 10770b57cec5SDimitry Andric break; 10785ffd83dbSDimitry Andric case wasm::R_WASM_GLOBAL_INDEX_I32: 10795ffd83dbSDimitry Andric if (!isValidGlobalSymbol(Reloc.Index)) 1080*0fca6ea1SDimitry Andric return badReloc("invalid global relocation"); 10815ffd83dbSDimitry Andric break; 1082fe6060f1SDimitry Andric case wasm::R_WASM_TAG_INDEX_LEB: 1083fe6060f1SDimitry Andric if (!isValidTagSymbol(Reloc.Index)) 1084*0fca6ea1SDimitry Andric return badReloc("invalid tag relocation"); 10850b57cec5SDimitry Andric break; 10860b57cec5SDimitry Andric case wasm::R_WASM_MEMORY_ADDR_LEB: 10870b57cec5SDimitry Andric case wasm::R_WASM_MEMORY_ADDR_SLEB: 10880b57cec5SDimitry Andric case wasm::R_WASM_MEMORY_ADDR_I32: 10890b57cec5SDimitry Andric case wasm::R_WASM_MEMORY_ADDR_REL_SLEB: 1090e8d8bef9SDimitry Andric case wasm::R_WASM_MEMORY_ADDR_TLS_SLEB: 1091fe6060f1SDimitry Andric case wasm::R_WASM_MEMORY_ADDR_LOCREL_I32: 10920b57cec5SDimitry Andric if (!isValidDataSymbol(Reloc.Index)) 1093*0fca6ea1SDimitry Andric return badReloc("invalid data relocation"); 10940b57cec5SDimitry Andric Reloc.Addend = readVarint32(Ctx); 10950b57cec5SDimitry Andric break; 10965ffd83dbSDimitry Andric case wasm::R_WASM_MEMORY_ADDR_LEB64: 10975ffd83dbSDimitry Andric case wasm::R_WASM_MEMORY_ADDR_SLEB64: 10985ffd83dbSDimitry Andric case wasm::R_WASM_MEMORY_ADDR_I64: 10995ffd83dbSDimitry Andric case wasm::R_WASM_MEMORY_ADDR_REL_SLEB64: 1100fe6060f1SDimitry Andric case wasm::R_WASM_MEMORY_ADDR_TLS_SLEB64: 11015ffd83dbSDimitry Andric if (!isValidDataSymbol(Reloc.Index)) 1102*0fca6ea1SDimitry Andric return badReloc("invalid data relocation"); 11035ffd83dbSDimitry Andric Reloc.Addend = readVarint64(Ctx); 11045ffd83dbSDimitry Andric break; 11050b57cec5SDimitry Andric case wasm::R_WASM_FUNCTION_OFFSET_I32: 11060b57cec5SDimitry Andric if (!isValidFunctionSymbol(Reloc.Index)) 1107*0fca6ea1SDimitry Andric return badReloc("invalid function relocation"); 11080b57cec5SDimitry Andric Reloc.Addend = readVarint32(Ctx); 11090b57cec5SDimitry Andric break; 1110e8d8bef9SDimitry Andric case wasm::R_WASM_FUNCTION_OFFSET_I64: 1111e8d8bef9SDimitry Andric if (!isValidFunctionSymbol(Reloc.Index)) 1112*0fca6ea1SDimitry Andric return badReloc("invalid function relocation"); 1113e8d8bef9SDimitry Andric Reloc.Addend = readVarint64(Ctx); 1114e8d8bef9SDimitry Andric break; 11150b57cec5SDimitry Andric case wasm::R_WASM_SECTION_OFFSET_I32: 11160b57cec5SDimitry Andric if (!isValidSectionSymbol(Reloc.Index)) 1117*0fca6ea1SDimitry Andric return badReloc("invalid section relocation"); 11180b57cec5SDimitry Andric Reloc.Addend = readVarint32(Ctx); 11190b57cec5SDimitry Andric break; 11200b57cec5SDimitry Andric default: 1121e8d8bef9SDimitry Andric return make_error<GenericBinaryError>("invalid relocation type: " + 1122e8d8bef9SDimitry Andric Twine(type), 11230b57cec5SDimitry Andric object_error::parse_failed); 11240b57cec5SDimitry Andric } 11250b57cec5SDimitry Andric 11260b57cec5SDimitry Andric // Relocations must fit inside the section, and must appear in order. They 11270b57cec5SDimitry Andric // also shouldn't overlap a function/element boundary, but we don't bother 11280b57cec5SDimitry Andric // to check that. 11290b57cec5SDimitry Andric uint64_t Size = 5; 11305ffd83dbSDimitry Andric if (Reloc.Type == wasm::R_WASM_MEMORY_ADDR_LEB64 || 11315ffd83dbSDimitry Andric Reloc.Type == wasm::R_WASM_MEMORY_ADDR_SLEB64 || 11325ffd83dbSDimitry Andric Reloc.Type == wasm::R_WASM_MEMORY_ADDR_REL_SLEB64) 11335ffd83dbSDimitry Andric Size = 10; 11340b57cec5SDimitry Andric if (Reloc.Type == wasm::R_WASM_TABLE_INDEX_I32 || 11350b57cec5SDimitry Andric Reloc.Type == wasm::R_WASM_MEMORY_ADDR_I32 || 1136fe6060f1SDimitry Andric Reloc.Type == wasm::R_WASM_MEMORY_ADDR_LOCREL_I32 || 11370b57cec5SDimitry Andric Reloc.Type == wasm::R_WASM_SECTION_OFFSET_I32 || 11385ffd83dbSDimitry Andric Reloc.Type == wasm::R_WASM_FUNCTION_OFFSET_I32 || 113906c3fb27SDimitry Andric Reloc.Type == wasm::R_WASM_FUNCTION_INDEX_I32 || 11405ffd83dbSDimitry Andric Reloc.Type == wasm::R_WASM_GLOBAL_INDEX_I32) 11410b57cec5SDimitry Andric Size = 4; 1142e8d8bef9SDimitry Andric if (Reloc.Type == wasm::R_WASM_TABLE_INDEX_I64 || 1143e8d8bef9SDimitry Andric Reloc.Type == wasm::R_WASM_MEMORY_ADDR_I64 || 1144e8d8bef9SDimitry Andric Reloc.Type == wasm::R_WASM_FUNCTION_OFFSET_I64) 11455ffd83dbSDimitry Andric Size = 8; 11460b57cec5SDimitry Andric if (Reloc.Offset + Size > EndOffset) 1147e8d8bef9SDimitry Andric return make_error<GenericBinaryError>("invalid relocation offset", 11480b57cec5SDimitry Andric object_error::parse_failed); 11490b57cec5SDimitry Andric 11500b57cec5SDimitry Andric Section.Relocations.push_back(Reloc); 11510b57cec5SDimitry Andric } 11520b57cec5SDimitry Andric if (Ctx.Ptr != Ctx.End) 1153e8d8bef9SDimitry Andric return make_error<GenericBinaryError>("reloc section ended prematurely", 11540b57cec5SDimitry Andric object_error::parse_failed); 11550b57cec5SDimitry Andric return Error::success(); 11560b57cec5SDimitry Andric } 11570b57cec5SDimitry Andric 11580b57cec5SDimitry Andric Error WasmObjectFile::parseCustomSection(WasmSection &Sec, ReadContext &Ctx) { 11590b57cec5SDimitry Andric if (Sec.Name == "dylink") { 11600b57cec5SDimitry Andric if (Error Err = parseDylinkSection(Ctx)) 11610b57cec5SDimitry Andric return Err; 1162349cc55cSDimitry Andric } else if (Sec.Name == "dylink.0") { 1163349cc55cSDimitry Andric if (Error Err = parseDylink0Section(Ctx)) 1164349cc55cSDimitry Andric return Err; 11650b57cec5SDimitry Andric } else if (Sec.Name == "name") { 11660b57cec5SDimitry Andric if (Error Err = parseNameSection(Ctx)) 11670b57cec5SDimitry Andric return Err; 11680b57cec5SDimitry Andric } else if (Sec.Name == "linking") { 11690b57cec5SDimitry Andric if (Error Err = parseLinkingSection(Ctx)) 11700b57cec5SDimitry Andric return Err; 11710b57cec5SDimitry Andric } else if (Sec.Name == "producers") { 11720b57cec5SDimitry Andric if (Error Err = parseProducersSection(Ctx)) 11730b57cec5SDimitry Andric return Err; 11740b57cec5SDimitry Andric } else if (Sec.Name == "target_features") { 11750b57cec5SDimitry Andric if (Error Err = parseTargetFeaturesSection(Ctx)) 11760b57cec5SDimitry Andric return Err; 11775f757f3fSDimitry Andric } else if (Sec.Name.starts_with("reloc.")) { 11780b57cec5SDimitry Andric if (Error Err = parseRelocSection(Sec.Name, Ctx)) 11790b57cec5SDimitry Andric return Err; 11800b57cec5SDimitry Andric } 11810b57cec5SDimitry Andric return Error::success(); 11820b57cec5SDimitry Andric } 11830b57cec5SDimitry Andric 11840b57cec5SDimitry Andric Error WasmObjectFile::parseTypeSection(ReadContext &Ctx) { 1185*0fca6ea1SDimitry Andric auto parseFieldDef = [&]() { 1186*0fca6ea1SDimitry Andric uint32_t TypeCode = readVaruint32((Ctx)); 1187*0fca6ea1SDimitry Andric /* Discard StorageType */ parseValType(Ctx, TypeCode); 1188*0fca6ea1SDimitry Andric /* Discard Mutability */ readVaruint32(Ctx); 1189*0fca6ea1SDimitry Andric }; 1190*0fca6ea1SDimitry Andric 11910b57cec5SDimitry Andric uint32_t Count = readVaruint32(Ctx); 11920b57cec5SDimitry Andric Signatures.reserve(Count); 11930b57cec5SDimitry Andric while (Count--) { 11940b57cec5SDimitry Andric wasm::WasmSignature Sig; 11950b57cec5SDimitry Andric uint8_t Form = readUint8(Ctx); 1196*0fca6ea1SDimitry Andric if (Form == wasm::WASM_TYPE_REC) { 1197*0fca6ea1SDimitry Andric // Rec groups expand the type index space (beyond what was declared at 1198*0fca6ea1SDimitry Andric // the top of the section, and also consume one element in that space. 1199*0fca6ea1SDimitry Andric uint32_t RecSize = readVaruint32(Ctx); 1200*0fca6ea1SDimitry Andric if (RecSize == 0) 1201*0fca6ea1SDimitry Andric return make_error<GenericBinaryError>("Rec group size cannot be 0", 1202*0fca6ea1SDimitry Andric object_error::parse_failed); 1203*0fca6ea1SDimitry Andric Signatures.reserve(Signatures.size() + RecSize); 1204*0fca6ea1SDimitry Andric Count += RecSize; 1205*0fca6ea1SDimitry Andric Sig.Kind = wasm::WasmSignature::Placeholder; 1206*0fca6ea1SDimitry Andric Signatures.push_back(std::move(Sig)); 1207*0fca6ea1SDimitry Andric HasUnmodeledTypes = true; 1208*0fca6ea1SDimitry Andric continue; 1209*0fca6ea1SDimitry Andric } 12100b57cec5SDimitry Andric if (Form != wasm::WASM_TYPE_FUNC) { 1211*0fca6ea1SDimitry Andric // Currently LLVM only models function types, and not other composite 1212*0fca6ea1SDimitry Andric // types. Here we parse the type declarations just enough to skip past 1213*0fca6ea1SDimitry Andric // them in the binary. 1214*0fca6ea1SDimitry Andric if (Form == wasm::WASM_TYPE_SUB || Form == wasm::WASM_TYPE_SUB_FINAL) { 1215*0fca6ea1SDimitry Andric uint32_t Supers = readVaruint32(Ctx); 1216*0fca6ea1SDimitry Andric if (Supers > 0) { 1217*0fca6ea1SDimitry Andric if (Supers != 1) 1218*0fca6ea1SDimitry Andric return make_error<GenericBinaryError>( 1219*0fca6ea1SDimitry Andric "Invalid number of supertypes", object_error::parse_failed); 1220*0fca6ea1SDimitry Andric /* Discard SuperIndex */ readVaruint32(Ctx); 1221*0fca6ea1SDimitry Andric } 1222*0fca6ea1SDimitry Andric Form = readVaruint32(Ctx); 1223*0fca6ea1SDimitry Andric } 1224*0fca6ea1SDimitry Andric if (Form == wasm::WASM_TYPE_STRUCT) { 1225*0fca6ea1SDimitry Andric uint32_t FieldCount = readVaruint32(Ctx); 1226*0fca6ea1SDimitry Andric while (FieldCount--) { 1227*0fca6ea1SDimitry Andric parseFieldDef(); 1228*0fca6ea1SDimitry Andric } 1229*0fca6ea1SDimitry Andric } else if (Form == wasm::WASM_TYPE_ARRAY) { 1230*0fca6ea1SDimitry Andric parseFieldDef(); 1231*0fca6ea1SDimitry Andric } else { 1232*0fca6ea1SDimitry Andric return make_error<GenericBinaryError>("bad form", 12330b57cec5SDimitry Andric object_error::parse_failed); 12340b57cec5SDimitry Andric } 1235*0fca6ea1SDimitry Andric Sig.Kind = wasm::WasmSignature::Placeholder; 1236*0fca6ea1SDimitry Andric Signatures.push_back(std::move(Sig)); 1237*0fca6ea1SDimitry Andric HasUnmodeledTypes = true; 1238*0fca6ea1SDimitry Andric continue; 1239*0fca6ea1SDimitry Andric } 1240*0fca6ea1SDimitry Andric 12410b57cec5SDimitry Andric uint32_t ParamCount = readVaruint32(Ctx); 12420b57cec5SDimitry Andric Sig.Params.reserve(ParamCount); 12430b57cec5SDimitry Andric while (ParamCount--) { 12440b57cec5SDimitry Andric uint32_t ParamType = readUint8(Ctx); 1245*0fca6ea1SDimitry Andric Sig.Params.push_back(parseValType(Ctx, ParamType)); 1246*0fca6ea1SDimitry Andric continue; 12470b57cec5SDimitry Andric } 12480b57cec5SDimitry Andric uint32_t ReturnCount = readVaruint32(Ctx); 12498bcb0991SDimitry Andric while (ReturnCount--) { 12508bcb0991SDimitry Andric uint32_t ReturnType = readUint8(Ctx); 1251*0fca6ea1SDimitry Andric Sig.Returns.push_back(parseValType(Ctx, ReturnType)); 12520b57cec5SDimitry Andric } 1253*0fca6ea1SDimitry Andric 12540b57cec5SDimitry Andric Signatures.push_back(std::move(Sig)); 12550b57cec5SDimitry Andric } 12560b57cec5SDimitry Andric if (Ctx.Ptr != Ctx.End) 1257e8d8bef9SDimitry Andric return make_error<GenericBinaryError>("type section ended prematurely", 12580b57cec5SDimitry Andric object_error::parse_failed); 12590b57cec5SDimitry Andric return Error::success(); 12600b57cec5SDimitry Andric } 12610b57cec5SDimitry Andric 12620b57cec5SDimitry Andric Error WasmObjectFile::parseImportSection(ReadContext &Ctx) { 12630b57cec5SDimitry Andric uint32_t Count = readVaruint32(Ctx); 1264349cc55cSDimitry Andric uint32_t NumTypes = Signatures.size(); 12650b57cec5SDimitry Andric Imports.reserve(Count); 12660b57cec5SDimitry Andric for (uint32_t I = 0; I < Count; I++) { 12670b57cec5SDimitry Andric wasm::WasmImport Im; 12680b57cec5SDimitry Andric Im.Module = readString(Ctx); 12690b57cec5SDimitry Andric Im.Field = readString(Ctx); 12700b57cec5SDimitry Andric Im.Kind = readUint8(Ctx); 12710b57cec5SDimitry Andric switch (Im.Kind) { 12720b57cec5SDimitry Andric case wasm::WASM_EXTERNAL_FUNCTION: 12730b57cec5SDimitry Andric NumImportedFunctions++; 12740b57cec5SDimitry Andric Im.SigIndex = readVaruint32(Ctx); 1275349cc55cSDimitry Andric if (Im.SigIndex >= NumTypes) 1276349cc55cSDimitry Andric return make_error<GenericBinaryError>("invalid function type", 1277349cc55cSDimitry Andric object_error::parse_failed); 12780b57cec5SDimitry Andric break; 12790b57cec5SDimitry Andric case wasm::WASM_EXTERNAL_GLOBAL: 12800b57cec5SDimitry Andric NumImportedGlobals++; 12810b57cec5SDimitry Andric Im.Global.Type = readUint8(Ctx); 12820b57cec5SDimitry Andric Im.Global.Mutable = readVaruint1(Ctx); 12830b57cec5SDimitry Andric break; 12840b57cec5SDimitry Andric case wasm::WASM_EXTERNAL_MEMORY: 12850b57cec5SDimitry Andric Im.Memory = readLimits(Ctx); 1286e8d8bef9SDimitry Andric if (Im.Memory.Flags & wasm::WASM_LIMITS_FLAG_IS_64) 1287e8d8bef9SDimitry Andric HasMemory64 = true; 12880b57cec5SDimitry Andric break; 1289e8d8bef9SDimitry Andric case wasm::WASM_EXTERNAL_TABLE: { 1290e8d8bef9SDimitry Andric Im.Table = readTableType(Ctx); 1291e8d8bef9SDimitry Andric NumImportedTables++; 1292e8d8bef9SDimitry Andric auto ElemType = Im.Table.ElemType; 12937a6dacacSDimitry Andric if (ElemType != wasm::ValType::FUNCREF && 1294*0fca6ea1SDimitry Andric ElemType != wasm::ValType::EXTERNREF && 1295*0fca6ea1SDimitry Andric ElemType != wasm::ValType::EXNREF && 1296*0fca6ea1SDimitry Andric ElemType != wasm::ValType::OTHERREF) 1297e8d8bef9SDimitry Andric return make_error<GenericBinaryError>("invalid table element type", 12980b57cec5SDimitry Andric object_error::parse_failed); 12990b57cec5SDimitry Andric break; 1300e8d8bef9SDimitry Andric } 1301fe6060f1SDimitry Andric case wasm::WASM_EXTERNAL_TAG: 1302fe6060f1SDimitry Andric NumImportedTags++; 1303349cc55cSDimitry Andric if (readUint8(Ctx) != 0) // Reserved 'attribute' field 1304349cc55cSDimitry Andric return make_error<GenericBinaryError>("invalid attribute", 1305349cc55cSDimitry Andric object_error::parse_failed); 1306349cc55cSDimitry Andric Im.SigIndex = readVaruint32(Ctx); 1307349cc55cSDimitry Andric if (Im.SigIndex >= NumTypes) 1308349cc55cSDimitry Andric return make_error<GenericBinaryError>("invalid tag type", 1309349cc55cSDimitry Andric object_error::parse_failed); 13100b57cec5SDimitry Andric break; 13110b57cec5SDimitry Andric default: 1312e8d8bef9SDimitry Andric return make_error<GenericBinaryError>("unexpected import kind", 13130b57cec5SDimitry Andric object_error::parse_failed); 13140b57cec5SDimitry Andric } 13150b57cec5SDimitry Andric Imports.push_back(Im); 13160b57cec5SDimitry Andric } 13170b57cec5SDimitry Andric if (Ctx.Ptr != Ctx.End) 1318e8d8bef9SDimitry Andric return make_error<GenericBinaryError>("import section ended prematurely", 13190b57cec5SDimitry Andric object_error::parse_failed); 13200b57cec5SDimitry Andric return Error::success(); 13210b57cec5SDimitry Andric } 13220b57cec5SDimitry Andric 13230b57cec5SDimitry Andric Error WasmObjectFile::parseFunctionSection(ReadContext &Ctx) { 13240b57cec5SDimitry Andric uint32_t Count = readVaruint32(Ctx); 1325349cc55cSDimitry Andric Functions.reserve(Count); 13260b57cec5SDimitry Andric uint32_t NumTypes = Signatures.size(); 13270b57cec5SDimitry Andric while (Count--) { 13280b57cec5SDimitry Andric uint32_t Type = readVaruint32(Ctx); 13290b57cec5SDimitry Andric if (Type >= NumTypes) 1330e8d8bef9SDimitry Andric return make_error<GenericBinaryError>("invalid function type", 13310b57cec5SDimitry Andric object_error::parse_failed); 1332349cc55cSDimitry Andric wasm::WasmFunction F; 1333349cc55cSDimitry Andric F.SigIndex = Type; 1334349cc55cSDimitry Andric Functions.push_back(F); 13350b57cec5SDimitry Andric } 13360b57cec5SDimitry Andric if (Ctx.Ptr != Ctx.End) 1337e8d8bef9SDimitry Andric return make_error<GenericBinaryError>("function section ended prematurely", 13380b57cec5SDimitry Andric object_error::parse_failed); 13390b57cec5SDimitry Andric return Error::success(); 13400b57cec5SDimitry Andric } 13410b57cec5SDimitry Andric 13420b57cec5SDimitry Andric Error WasmObjectFile::parseTableSection(ReadContext &Ctx) { 1343e8d8bef9SDimitry Andric TableSection = Sections.size(); 13440b57cec5SDimitry Andric uint32_t Count = readVaruint32(Ctx); 13450b57cec5SDimitry Andric Tables.reserve(Count); 13460b57cec5SDimitry Andric while (Count--) { 1347e8d8bef9SDimitry Andric wasm::WasmTable T; 1348e8d8bef9SDimitry Andric T.Type = readTableType(Ctx); 1349e8d8bef9SDimitry Andric T.Index = NumImportedTables + Tables.size(); 1350e8d8bef9SDimitry Andric Tables.push_back(T); 1351e8d8bef9SDimitry Andric auto ElemType = Tables.back().Type.ElemType; 13527a6dacacSDimitry Andric if (ElemType != wasm::ValType::FUNCREF && 1353*0fca6ea1SDimitry Andric ElemType != wasm::ValType::EXTERNREF && 1354*0fca6ea1SDimitry Andric ElemType != wasm::ValType::EXNREF && 1355*0fca6ea1SDimitry Andric ElemType != wasm::ValType::OTHERREF) { 1356e8d8bef9SDimitry Andric return make_error<GenericBinaryError>("invalid table element type", 13570b57cec5SDimitry Andric object_error::parse_failed); 13580b57cec5SDimitry Andric } 13590b57cec5SDimitry Andric } 13600b57cec5SDimitry Andric if (Ctx.Ptr != Ctx.End) 1361e8d8bef9SDimitry Andric return make_error<GenericBinaryError>("table section ended prematurely", 13620b57cec5SDimitry Andric object_error::parse_failed); 13630b57cec5SDimitry Andric return Error::success(); 13640b57cec5SDimitry Andric } 13650b57cec5SDimitry Andric 13660b57cec5SDimitry Andric Error WasmObjectFile::parseMemorySection(ReadContext &Ctx) { 13670b57cec5SDimitry Andric uint32_t Count = readVaruint32(Ctx); 13680b57cec5SDimitry Andric Memories.reserve(Count); 13690b57cec5SDimitry Andric while (Count--) { 1370e8d8bef9SDimitry Andric auto Limits = readLimits(Ctx); 1371e8d8bef9SDimitry Andric if (Limits.Flags & wasm::WASM_LIMITS_FLAG_IS_64) 1372e8d8bef9SDimitry Andric HasMemory64 = true; 1373e8d8bef9SDimitry Andric Memories.push_back(Limits); 13740b57cec5SDimitry Andric } 13750b57cec5SDimitry Andric if (Ctx.Ptr != Ctx.End) 1376e8d8bef9SDimitry Andric return make_error<GenericBinaryError>("memory section ended prematurely", 13770b57cec5SDimitry Andric object_error::parse_failed); 13780b57cec5SDimitry Andric return Error::success(); 13790b57cec5SDimitry Andric } 13800b57cec5SDimitry Andric 1381fe6060f1SDimitry Andric Error WasmObjectFile::parseTagSection(ReadContext &Ctx) { 1382fe6060f1SDimitry Andric TagSection = Sections.size(); 1383fe6060f1SDimitry Andric uint32_t Count = readVaruint32(Ctx); 1384fe6060f1SDimitry Andric Tags.reserve(Count); 1385349cc55cSDimitry Andric uint32_t NumTypes = Signatures.size(); 13865ffd83dbSDimitry Andric while (Count--) { 1387349cc55cSDimitry Andric if (readUint8(Ctx) != 0) // Reserved 'attribute' field 1388349cc55cSDimitry Andric return make_error<GenericBinaryError>("invalid attribute", 1389349cc55cSDimitry Andric object_error::parse_failed); 1390349cc55cSDimitry Andric uint32_t Type = readVaruint32(Ctx); 1391349cc55cSDimitry Andric if (Type >= NumTypes) 1392349cc55cSDimitry Andric return make_error<GenericBinaryError>("invalid tag type", 1393349cc55cSDimitry Andric object_error::parse_failed); 1394fe6060f1SDimitry Andric wasm::WasmTag Tag; 1395fe6060f1SDimitry Andric Tag.Index = NumImportedTags + Tags.size(); 1396349cc55cSDimitry Andric Tag.SigIndex = Type; 1397*0fca6ea1SDimitry Andric Signatures[Type].Kind = wasm::WasmSignature::Tag; 1398fe6060f1SDimitry Andric Tags.push_back(Tag); 13995ffd83dbSDimitry Andric } 14005ffd83dbSDimitry Andric 14015ffd83dbSDimitry Andric if (Ctx.Ptr != Ctx.End) 1402fe6060f1SDimitry Andric return make_error<GenericBinaryError>("tag section ended prematurely", 14035ffd83dbSDimitry Andric object_error::parse_failed); 14045ffd83dbSDimitry Andric return Error::success(); 14055ffd83dbSDimitry Andric } 14065ffd83dbSDimitry Andric 14070b57cec5SDimitry Andric Error WasmObjectFile::parseGlobalSection(ReadContext &Ctx) { 14080b57cec5SDimitry Andric GlobalSection = Sections.size(); 1409*0fca6ea1SDimitry Andric const uint8_t *SectionStart = Ctx.Ptr; 14100b57cec5SDimitry Andric uint32_t Count = readVaruint32(Ctx); 14110b57cec5SDimitry Andric Globals.reserve(Count); 14120b57cec5SDimitry Andric while (Count--) { 14130b57cec5SDimitry Andric wasm::WasmGlobal Global; 14140b57cec5SDimitry Andric Global.Index = NumImportedGlobals + Globals.size(); 1415*0fca6ea1SDimitry Andric const uint8_t *GlobalStart = Ctx.Ptr; 1416*0fca6ea1SDimitry Andric Global.Offset = static_cast<uint32_t>(GlobalStart - SectionStart); 1417*0fca6ea1SDimitry Andric auto GlobalOpcode = readVaruint32(Ctx); 1418*0fca6ea1SDimitry Andric Global.Type.Type = (uint8_t)parseValType(Ctx, GlobalOpcode); 14190b57cec5SDimitry Andric Global.Type.Mutable = readVaruint1(Ctx); 14200b57cec5SDimitry Andric if (Error Err = readInitExpr(Global.InitExpr, Ctx)) 14210b57cec5SDimitry Andric return Err; 1422*0fca6ea1SDimitry Andric Global.Size = static_cast<uint32_t>(Ctx.Ptr - GlobalStart); 14230b57cec5SDimitry Andric Globals.push_back(Global); 14240b57cec5SDimitry Andric } 14250b57cec5SDimitry Andric if (Ctx.Ptr != Ctx.End) 1426e8d8bef9SDimitry Andric return make_error<GenericBinaryError>("global section ended prematurely", 14270b57cec5SDimitry Andric object_error::parse_failed); 14280b57cec5SDimitry Andric return Error::success(); 14290b57cec5SDimitry Andric } 14300b57cec5SDimitry Andric 14310b57cec5SDimitry Andric Error WasmObjectFile::parseExportSection(ReadContext &Ctx) { 14320b57cec5SDimitry Andric uint32_t Count = readVaruint32(Ctx); 14330b57cec5SDimitry Andric Exports.reserve(Count); 1434cb14a3feSDimitry Andric Symbols.reserve(Count); 14350b57cec5SDimitry Andric for (uint32_t I = 0; I < Count; I++) { 14360b57cec5SDimitry Andric wasm::WasmExport Ex; 14370b57cec5SDimitry Andric Ex.Name = readString(Ctx); 14380b57cec5SDimitry Andric Ex.Kind = readUint8(Ctx); 14390b57cec5SDimitry Andric Ex.Index = readVaruint32(Ctx); 1440cb14a3feSDimitry Andric const wasm::WasmSignature *Signature = nullptr; 1441cb14a3feSDimitry Andric const wasm::WasmGlobalType *GlobalType = nullptr; 1442cb14a3feSDimitry Andric const wasm::WasmTableType *TableType = nullptr; 1443cb14a3feSDimitry Andric wasm::WasmSymbolInfo Info; 1444cb14a3feSDimitry Andric Info.Name = Ex.Name; 1445cb14a3feSDimitry Andric Info.Flags = 0; 14460b57cec5SDimitry Andric switch (Ex.Kind) { 1447cb14a3feSDimitry Andric case wasm::WASM_EXTERNAL_FUNCTION: { 1448480093f4SDimitry Andric if (!isDefinedFunctionIndex(Ex.Index)) 1449e8d8bef9SDimitry Andric return make_error<GenericBinaryError>("invalid function export", 14500b57cec5SDimitry Andric object_error::parse_failed); 1451480093f4SDimitry Andric getDefinedFunction(Ex.Index).ExportName = Ex.Name; 1452cb14a3feSDimitry Andric Info.Kind = wasm::WASM_SYMBOL_TYPE_FUNCTION; 1453cb14a3feSDimitry Andric Info.ElementIndex = Ex.Index; 1454cb14a3feSDimitry Andric unsigned FuncIndex = Info.ElementIndex - NumImportedFunctions; 1455cb14a3feSDimitry Andric wasm::WasmFunction &Function = Functions[FuncIndex]; 1456cb14a3feSDimitry Andric Signature = &Signatures[Function.SigIndex]; 14570b57cec5SDimitry Andric break; 1458cb14a3feSDimitry Andric } 1459cb14a3feSDimitry Andric case wasm::WASM_EXTERNAL_GLOBAL: { 14600b57cec5SDimitry Andric if (!isValidGlobalIndex(Ex.Index)) 1461e8d8bef9SDimitry Andric return make_error<GenericBinaryError>("invalid global export", 14620b57cec5SDimitry Andric object_error::parse_failed); 1463cb14a3feSDimitry Andric Info.Kind = wasm::WASM_SYMBOL_TYPE_DATA; 1464cb14a3feSDimitry Andric uint64_t Offset = 0; 1465cb14a3feSDimitry Andric if (isDefinedGlobalIndex(Ex.Index)) { 1466cb14a3feSDimitry Andric auto Global = getDefinedGlobal(Ex.Index); 1467cb14a3feSDimitry Andric if (!Global.InitExpr.Extended) { 1468cb14a3feSDimitry Andric auto Inst = Global.InitExpr.Inst; 1469cb14a3feSDimitry Andric if (Inst.Opcode == wasm::WASM_OPCODE_I32_CONST) { 1470cb14a3feSDimitry Andric Offset = Inst.Value.Int32; 1471cb14a3feSDimitry Andric } else if (Inst.Opcode == wasm::WASM_OPCODE_I64_CONST) { 1472cb14a3feSDimitry Andric Offset = Inst.Value.Int64; 1473cb14a3feSDimitry Andric } 1474cb14a3feSDimitry Andric } 1475cb14a3feSDimitry Andric } 1476cb14a3feSDimitry Andric Info.DataRef = wasm::WasmDataReference{0, Offset, 0}; 14770b57cec5SDimitry Andric break; 1478cb14a3feSDimitry Andric } 1479fe6060f1SDimitry Andric case wasm::WASM_EXTERNAL_TAG: 1480fe6060f1SDimitry Andric if (!isValidTagIndex(Ex.Index)) 1481fe6060f1SDimitry Andric return make_error<GenericBinaryError>("invalid tag export", 14820b57cec5SDimitry Andric object_error::parse_failed); 1483cb14a3feSDimitry Andric Info.Kind = wasm::WASM_SYMBOL_TYPE_TAG; 1484cb14a3feSDimitry Andric Info.ElementIndex = Ex.Index; 14850b57cec5SDimitry Andric break; 14860b57cec5SDimitry Andric case wasm::WASM_EXTERNAL_MEMORY: 1487cb14a3feSDimitry Andric break; 14880b57cec5SDimitry Andric case wasm::WASM_EXTERNAL_TABLE: 1489cb14a3feSDimitry Andric Info.Kind = wasm::WASM_SYMBOL_TYPE_TABLE; 14901db9f3b2SDimitry Andric Info.ElementIndex = Ex.Index; 14910b57cec5SDimitry Andric break; 14920b57cec5SDimitry Andric default: 1493e8d8bef9SDimitry Andric return make_error<GenericBinaryError>("unexpected export kind", 14940b57cec5SDimitry Andric object_error::parse_failed); 14950b57cec5SDimitry Andric } 14960b57cec5SDimitry Andric Exports.push_back(Ex); 1497cb14a3feSDimitry Andric if (Ex.Kind != wasm::WASM_EXTERNAL_MEMORY) { 1498*0fca6ea1SDimitry Andric Symbols.emplace_back(Info, GlobalType, TableType, Signature); 1499cb14a3feSDimitry Andric LLVM_DEBUG(dbgs() << "Adding symbol: " << Symbols.back() << "\n"); 1500cb14a3feSDimitry Andric } 15010b57cec5SDimitry Andric } 15020b57cec5SDimitry Andric if (Ctx.Ptr != Ctx.End) 1503e8d8bef9SDimitry Andric return make_error<GenericBinaryError>("export section ended prematurely", 15040b57cec5SDimitry Andric object_error::parse_failed); 15050b57cec5SDimitry Andric return Error::success(); 15060b57cec5SDimitry Andric } 15070b57cec5SDimitry Andric 15080b57cec5SDimitry Andric bool WasmObjectFile::isValidFunctionIndex(uint32_t Index) const { 1509349cc55cSDimitry Andric return Index < NumImportedFunctions + Functions.size(); 15100b57cec5SDimitry Andric } 15110b57cec5SDimitry Andric 15120b57cec5SDimitry Andric bool WasmObjectFile::isDefinedFunctionIndex(uint32_t Index) const { 15130b57cec5SDimitry Andric return Index >= NumImportedFunctions && isValidFunctionIndex(Index); 15140b57cec5SDimitry Andric } 15150b57cec5SDimitry Andric 15160b57cec5SDimitry Andric bool WasmObjectFile::isValidGlobalIndex(uint32_t Index) const { 15170b57cec5SDimitry Andric return Index < NumImportedGlobals + Globals.size(); 15180b57cec5SDimitry Andric } 15190b57cec5SDimitry Andric 1520fe6060f1SDimitry Andric bool WasmObjectFile::isValidTableNumber(uint32_t Index) const { 1521e8d8bef9SDimitry Andric return Index < NumImportedTables + Tables.size(); 1522e8d8bef9SDimitry Andric } 1523e8d8bef9SDimitry Andric 15240b57cec5SDimitry Andric bool WasmObjectFile::isDefinedGlobalIndex(uint32_t Index) const { 15250b57cec5SDimitry Andric return Index >= NumImportedGlobals && isValidGlobalIndex(Index); 15260b57cec5SDimitry Andric } 15270b57cec5SDimitry Andric 1528fe6060f1SDimitry Andric bool WasmObjectFile::isDefinedTableNumber(uint32_t Index) const { 1529fe6060f1SDimitry Andric return Index >= NumImportedTables && isValidTableNumber(Index); 1530e8d8bef9SDimitry Andric } 1531e8d8bef9SDimitry Andric 1532fe6060f1SDimitry Andric bool WasmObjectFile::isValidTagIndex(uint32_t Index) const { 1533fe6060f1SDimitry Andric return Index < NumImportedTags + Tags.size(); 15340b57cec5SDimitry Andric } 15350b57cec5SDimitry Andric 1536fe6060f1SDimitry Andric bool WasmObjectFile::isDefinedTagIndex(uint32_t Index) const { 1537fe6060f1SDimitry Andric return Index >= NumImportedTags && isValidTagIndex(Index); 15380b57cec5SDimitry Andric } 15390b57cec5SDimitry Andric 15400b57cec5SDimitry Andric bool WasmObjectFile::isValidFunctionSymbol(uint32_t Index) const { 15410b57cec5SDimitry Andric return Index < Symbols.size() && Symbols[Index].isTypeFunction(); 15420b57cec5SDimitry Andric } 15430b57cec5SDimitry Andric 1544e8d8bef9SDimitry Andric bool WasmObjectFile::isValidTableSymbol(uint32_t Index) const { 1545e8d8bef9SDimitry Andric return Index < Symbols.size() && Symbols[Index].isTypeTable(); 1546e8d8bef9SDimitry Andric } 1547e8d8bef9SDimitry Andric 15480b57cec5SDimitry Andric bool WasmObjectFile::isValidGlobalSymbol(uint32_t Index) const { 15490b57cec5SDimitry Andric return Index < Symbols.size() && Symbols[Index].isTypeGlobal(); 15500b57cec5SDimitry Andric } 15510b57cec5SDimitry Andric 1552fe6060f1SDimitry Andric bool WasmObjectFile::isValidTagSymbol(uint32_t Index) const { 1553fe6060f1SDimitry Andric return Index < Symbols.size() && Symbols[Index].isTypeTag(); 15540b57cec5SDimitry Andric } 15550b57cec5SDimitry Andric 15560b57cec5SDimitry Andric bool WasmObjectFile::isValidDataSymbol(uint32_t Index) const { 15570b57cec5SDimitry Andric return Index < Symbols.size() && Symbols[Index].isTypeData(); 15580b57cec5SDimitry Andric } 15590b57cec5SDimitry Andric 15600b57cec5SDimitry Andric bool WasmObjectFile::isValidSectionSymbol(uint32_t Index) const { 15610b57cec5SDimitry Andric return Index < Symbols.size() && Symbols[Index].isTypeSection(); 15620b57cec5SDimitry Andric } 15630b57cec5SDimitry Andric 15640b57cec5SDimitry Andric wasm::WasmFunction &WasmObjectFile::getDefinedFunction(uint32_t Index) { 15650b57cec5SDimitry Andric assert(isDefinedFunctionIndex(Index)); 15660b57cec5SDimitry Andric return Functions[Index - NumImportedFunctions]; 15670b57cec5SDimitry Andric } 15680b57cec5SDimitry Andric 15690b57cec5SDimitry Andric const wasm::WasmFunction & 15700b57cec5SDimitry Andric WasmObjectFile::getDefinedFunction(uint32_t Index) const { 15710b57cec5SDimitry Andric assert(isDefinedFunctionIndex(Index)); 15720b57cec5SDimitry Andric return Functions[Index - NumImportedFunctions]; 15730b57cec5SDimitry Andric } 15740b57cec5SDimitry Andric 1575*0fca6ea1SDimitry Andric const wasm::WasmGlobal &WasmObjectFile::getDefinedGlobal(uint32_t Index) const { 15760b57cec5SDimitry Andric assert(isDefinedGlobalIndex(Index)); 15770b57cec5SDimitry Andric return Globals[Index - NumImportedGlobals]; 15780b57cec5SDimitry Andric } 15790b57cec5SDimitry Andric 1580fe6060f1SDimitry Andric wasm::WasmTag &WasmObjectFile::getDefinedTag(uint32_t Index) { 1581fe6060f1SDimitry Andric assert(isDefinedTagIndex(Index)); 1582fe6060f1SDimitry Andric return Tags[Index - NumImportedTags]; 15830b57cec5SDimitry Andric } 15840b57cec5SDimitry Andric 15850b57cec5SDimitry Andric Error WasmObjectFile::parseStartSection(ReadContext &Ctx) { 15860b57cec5SDimitry Andric StartFunction = readVaruint32(Ctx); 15870b57cec5SDimitry Andric if (!isValidFunctionIndex(StartFunction)) 1588e8d8bef9SDimitry Andric return make_error<GenericBinaryError>("invalid start function", 15890b57cec5SDimitry Andric object_error::parse_failed); 15900b57cec5SDimitry Andric return Error::success(); 15910b57cec5SDimitry Andric } 15920b57cec5SDimitry Andric 15930b57cec5SDimitry Andric Error WasmObjectFile::parseCodeSection(ReadContext &Ctx) { 15940b57cec5SDimitry Andric CodeSection = Sections.size(); 15950b57cec5SDimitry Andric uint32_t FunctionCount = readVaruint32(Ctx); 1596349cc55cSDimitry Andric if (FunctionCount != Functions.size()) { 1597e8d8bef9SDimitry Andric return make_error<GenericBinaryError>("invalid function count", 15980b57cec5SDimitry Andric object_error::parse_failed); 15990b57cec5SDimitry Andric } 16000b57cec5SDimitry Andric 1601480093f4SDimitry Andric for (uint32_t i = 0; i < FunctionCount; i++) { 1602480093f4SDimitry Andric wasm::WasmFunction& Function = Functions[i]; 16030b57cec5SDimitry Andric const uint8_t *FunctionStart = Ctx.Ptr; 16040b57cec5SDimitry Andric uint32_t Size = readVaruint32(Ctx); 16050b57cec5SDimitry Andric const uint8_t *FunctionEnd = Ctx.Ptr + Size; 16060b57cec5SDimitry Andric 16070b57cec5SDimitry Andric Function.CodeOffset = Ctx.Ptr - FunctionStart; 1608480093f4SDimitry Andric Function.Index = NumImportedFunctions + i; 16090b57cec5SDimitry Andric Function.CodeSectionOffset = FunctionStart - Ctx.Start; 16100b57cec5SDimitry Andric Function.Size = FunctionEnd - FunctionStart; 16110b57cec5SDimitry Andric 16120b57cec5SDimitry Andric uint32_t NumLocalDecls = readVaruint32(Ctx); 16130b57cec5SDimitry Andric Function.Locals.reserve(NumLocalDecls); 16140b57cec5SDimitry Andric while (NumLocalDecls--) { 16150b57cec5SDimitry Andric wasm::WasmLocalDecl Decl; 16160b57cec5SDimitry Andric Decl.Count = readVaruint32(Ctx); 16170b57cec5SDimitry Andric Decl.Type = readUint8(Ctx); 16180b57cec5SDimitry Andric Function.Locals.push_back(Decl); 16190b57cec5SDimitry Andric } 16200b57cec5SDimitry Andric 16210b57cec5SDimitry Andric uint32_t BodySize = FunctionEnd - Ctx.Ptr; 1622647cbc5dSDimitry Andric // Ensure that Function is within Ctx's buffer. 1623647cbc5dSDimitry Andric if (Ctx.Ptr + BodySize > Ctx.End) { 1624647cbc5dSDimitry Andric return make_error<GenericBinaryError>("Function extends beyond buffer", 1625647cbc5dSDimitry Andric object_error::parse_failed); 1626647cbc5dSDimitry Andric } 16270b57cec5SDimitry Andric Function.Body = ArrayRef<uint8_t>(Ctx.Ptr, BodySize); 16280b57cec5SDimitry Andric // This will be set later when reading in the linking metadata section. 16290b57cec5SDimitry Andric Function.Comdat = UINT32_MAX; 16300b57cec5SDimitry Andric Ctx.Ptr += BodySize; 16310b57cec5SDimitry Andric assert(Ctx.Ptr == FunctionEnd); 16320b57cec5SDimitry Andric } 16330b57cec5SDimitry Andric if (Ctx.Ptr != Ctx.End) 1634e8d8bef9SDimitry Andric return make_error<GenericBinaryError>("code section ended prematurely", 16350b57cec5SDimitry Andric object_error::parse_failed); 16360b57cec5SDimitry Andric return Error::success(); 16370b57cec5SDimitry Andric } 16380b57cec5SDimitry Andric 16390b57cec5SDimitry Andric Error WasmObjectFile::parseElemSection(ReadContext &Ctx) { 16400b57cec5SDimitry Andric uint32_t Count = readVaruint32(Ctx); 16410b57cec5SDimitry Andric ElemSegments.reserve(Count); 16420b57cec5SDimitry Andric while (Count--) { 16430b57cec5SDimitry Andric wasm::WasmElemSegment Segment; 1644fe6060f1SDimitry Andric Segment.Flags = readVaruint32(Ctx); 1645fe6060f1SDimitry Andric 1646fe6060f1SDimitry Andric uint32_t SupportedFlags = wasm::WASM_ELEM_SEGMENT_HAS_TABLE_NUMBER | 1647fe6060f1SDimitry Andric wasm::WASM_ELEM_SEGMENT_IS_PASSIVE | 1648fe6060f1SDimitry Andric wasm::WASM_ELEM_SEGMENT_HAS_INIT_EXPRS; 1649fe6060f1SDimitry Andric if (Segment.Flags & ~SupportedFlags) 1650fe6060f1SDimitry Andric return make_error<GenericBinaryError>( 1651fe6060f1SDimitry Andric "Unsupported flags for element segment", object_error::parse_failed); 1652fe6060f1SDimitry Andric 1653*0fca6ea1SDimitry Andric bool IsPassive = (Segment.Flags & wasm::WASM_ELEM_SEGMENT_IS_PASSIVE) != 0; 1654*0fca6ea1SDimitry Andric bool IsDeclarative = 1655*0fca6ea1SDimitry Andric IsPassive && (Segment.Flags & wasm::WASM_ELEM_SEGMENT_IS_DECLARATIVE); 1656*0fca6ea1SDimitry Andric bool HasTableNumber = 1657*0fca6ea1SDimitry Andric !IsPassive && 1658*0fca6ea1SDimitry Andric (Segment.Flags & wasm::WASM_ELEM_SEGMENT_HAS_TABLE_NUMBER); 1659*0fca6ea1SDimitry Andric bool HasInitExprs = 1660*0fca6ea1SDimitry Andric (Segment.Flags & wasm::WASM_ELEM_SEGMENT_HAS_INIT_EXPRS); 1661*0fca6ea1SDimitry Andric bool HasElemKind = 1662*0fca6ea1SDimitry Andric (Segment.Flags & wasm::WASM_ELEM_SEGMENT_MASK_HAS_ELEM_KIND) && 1663*0fca6ea1SDimitry Andric !HasInitExprs; 1664*0fca6ea1SDimitry Andric 1665*0fca6ea1SDimitry Andric if (HasTableNumber) 1666fe6060f1SDimitry Andric Segment.TableNumber = readVaruint32(Ctx); 1667fe6060f1SDimitry Andric else 1668fe6060f1SDimitry Andric Segment.TableNumber = 0; 1669*0fca6ea1SDimitry Andric 1670fe6060f1SDimitry Andric if (!isValidTableNumber(Segment.TableNumber)) 1671fe6060f1SDimitry Andric return make_error<GenericBinaryError>("invalid TableNumber", 16720b57cec5SDimitry Andric object_error::parse_failed); 1673fe6060f1SDimitry Andric 1674*0fca6ea1SDimitry Andric if (IsPassive || IsDeclarative) { 167581ad6265SDimitry Andric Segment.Offset.Extended = false; 167681ad6265SDimitry Andric Segment.Offset.Inst.Opcode = wasm::WASM_OPCODE_I32_CONST; 167781ad6265SDimitry Andric Segment.Offset.Inst.Value.Int32 = 0; 1678fe6060f1SDimitry Andric } else { 16790b57cec5SDimitry Andric if (Error Err = readInitExpr(Segment.Offset, Ctx)) 16800b57cec5SDimitry Andric return Err; 1681fe6060f1SDimitry Andric } 1682fe6060f1SDimitry Andric 1683*0fca6ea1SDimitry Andric if (HasElemKind) { 16847a6dacacSDimitry Andric auto ElemKind = readVaruint32(Ctx); 1685fe6060f1SDimitry Andric if (Segment.Flags & wasm::WASM_ELEM_SEGMENT_HAS_INIT_EXPRS) { 1686*0fca6ea1SDimitry Andric Segment.ElemKind = parseValType(Ctx, ElemKind); 16877a6dacacSDimitry Andric if (Segment.ElemKind != wasm::ValType::FUNCREF && 1688*0fca6ea1SDimitry Andric Segment.ElemKind != wasm::ValType::EXTERNREF && 1689*0fca6ea1SDimitry Andric Segment.ElemKind != wasm::ValType::EXNREF && 1690*0fca6ea1SDimitry Andric Segment.ElemKind != wasm::ValType::OTHERREF) { 1691*0fca6ea1SDimitry Andric return make_error<GenericBinaryError>("invalid elem type", 1692fe6060f1SDimitry Andric object_error::parse_failed); 1693fe6060f1SDimitry Andric } 1694fe6060f1SDimitry Andric } else { 16957a6dacacSDimitry Andric if (ElemKind != 0) 1696fe6060f1SDimitry Andric return make_error<GenericBinaryError>("invalid elem type", 1697fe6060f1SDimitry Andric object_error::parse_failed); 16987a6dacacSDimitry Andric Segment.ElemKind = wasm::ValType::FUNCREF; 1699fe6060f1SDimitry Andric } 1700*0fca6ea1SDimitry Andric } else if (HasInitExprs) { 1701*0fca6ea1SDimitry Andric auto ElemType = parseValType(Ctx, readVaruint32(Ctx)); 1702*0fca6ea1SDimitry Andric Segment.ElemKind = ElemType; 1703fe6060f1SDimitry Andric } else { 17047a6dacacSDimitry Andric Segment.ElemKind = wasm::ValType::FUNCREF; 1705fe6060f1SDimitry Andric } 1706fe6060f1SDimitry Andric 17070b57cec5SDimitry Andric uint32_t NumElems = readVaruint32(Ctx); 1708*0fca6ea1SDimitry Andric 1709*0fca6ea1SDimitry Andric if (HasInitExprs) { 1710*0fca6ea1SDimitry Andric while (NumElems--) { 1711*0fca6ea1SDimitry Andric wasm::WasmInitExpr Expr; 1712*0fca6ea1SDimitry Andric if (Error Err = readInitExpr(Expr, Ctx)) 1713*0fca6ea1SDimitry Andric return Err; 1714*0fca6ea1SDimitry Andric } 1715*0fca6ea1SDimitry Andric } else { 17160b57cec5SDimitry Andric while (NumElems--) { 17170b57cec5SDimitry Andric Segment.Functions.push_back(readVaruint32(Ctx)); 17180b57cec5SDimitry Andric } 1719*0fca6ea1SDimitry Andric } 17200b57cec5SDimitry Andric ElemSegments.push_back(Segment); 17210b57cec5SDimitry Andric } 17220b57cec5SDimitry Andric if (Ctx.Ptr != Ctx.End) 1723e8d8bef9SDimitry Andric return make_error<GenericBinaryError>("elem section ended prematurely", 17240b57cec5SDimitry Andric object_error::parse_failed); 17250b57cec5SDimitry Andric return Error::success(); 17260b57cec5SDimitry Andric } 17270b57cec5SDimitry Andric 17280b57cec5SDimitry Andric Error WasmObjectFile::parseDataSection(ReadContext &Ctx) { 17290b57cec5SDimitry Andric DataSection = Sections.size(); 17300b57cec5SDimitry Andric uint32_t Count = readVaruint32(Ctx); 173181ad6265SDimitry Andric if (DataCount && Count != *DataCount) 17320b57cec5SDimitry Andric return make_error<GenericBinaryError>( 1733e8d8bef9SDimitry Andric "number of data segments does not match DataCount section"); 17340b57cec5SDimitry Andric DataSegments.reserve(Count); 17350b57cec5SDimitry Andric while (Count--) { 17360b57cec5SDimitry Andric WasmSegment Segment; 17370b57cec5SDimitry Andric Segment.Data.InitFlags = readVaruint32(Ctx); 1738e8d8bef9SDimitry Andric Segment.Data.MemoryIndex = 1739e8d8bef9SDimitry Andric (Segment.Data.InitFlags & wasm::WASM_DATA_SEGMENT_HAS_MEMINDEX) 1740e8d8bef9SDimitry Andric ? readVaruint32(Ctx) 1741e8d8bef9SDimitry Andric : 0; 1742e8d8bef9SDimitry Andric if ((Segment.Data.InitFlags & wasm::WASM_DATA_SEGMENT_IS_PASSIVE) == 0) { 17430b57cec5SDimitry Andric if (Error Err = readInitExpr(Segment.Data.Offset, Ctx)) 17440b57cec5SDimitry Andric return Err; 17450b57cec5SDimitry Andric } else { 174681ad6265SDimitry Andric Segment.Data.Offset.Extended = false; 174781ad6265SDimitry Andric Segment.Data.Offset.Inst.Opcode = wasm::WASM_OPCODE_I32_CONST; 174881ad6265SDimitry Andric Segment.Data.Offset.Inst.Value.Int32 = 0; 17490b57cec5SDimitry Andric } 17500b57cec5SDimitry Andric uint32_t Size = readVaruint32(Ctx); 17510b57cec5SDimitry Andric if (Size > (size_t)(Ctx.End - Ctx.Ptr)) 1752e8d8bef9SDimitry Andric return make_error<GenericBinaryError>("invalid segment size", 17530b57cec5SDimitry Andric object_error::parse_failed); 17540b57cec5SDimitry Andric Segment.Data.Content = ArrayRef<uint8_t>(Ctx.Ptr, Size); 17550b57cec5SDimitry Andric // The rest of these Data fields are set later, when reading in the linking 17560b57cec5SDimitry Andric // metadata section. 17570b57cec5SDimitry Andric Segment.Data.Alignment = 0; 1758fe6060f1SDimitry Andric Segment.Data.LinkingFlags = 0; 17590b57cec5SDimitry Andric Segment.Data.Comdat = UINT32_MAX; 17600b57cec5SDimitry Andric Segment.SectionOffset = Ctx.Ptr - Ctx.Start; 17610b57cec5SDimitry Andric Ctx.Ptr += Size; 17620b57cec5SDimitry Andric DataSegments.push_back(Segment); 17630b57cec5SDimitry Andric } 17640b57cec5SDimitry Andric if (Ctx.Ptr != Ctx.End) 1765e8d8bef9SDimitry Andric return make_error<GenericBinaryError>("data section ended prematurely", 17660b57cec5SDimitry Andric object_error::parse_failed); 17670b57cec5SDimitry Andric return Error::success(); 17680b57cec5SDimitry Andric } 17690b57cec5SDimitry Andric 17700b57cec5SDimitry Andric Error WasmObjectFile::parseDataCountSection(ReadContext &Ctx) { 17710b57cec5SDimitry Andric DataCount = readVaruint32(Ctx); 17720b57cec5SDimitry Andric return Error::success(); 17730b57cec5SDimitry Andric } 17740b57cec5SDimitry Andric 17750b57cec5SDimitry Andric const wasm::WasmObjectHeader &WasmObjectFile::getHeader() const { 17760b57cec5SDimitry Andric return Header; 17770b57cec5SDimitry Andric } 17780b57cec5SDimitry Andric 17790b57cec5SDimitry Andric void WasmObjectFile::moveSymbolNext(DataRefImpl &Symb) const { Symb.d.b++; } 17800b57cec5SDimitry Andric 17815ffd83dbSDimitry Andric Expected<uint32_t> WasmObjectFile::getSymbolFlags(DataRefImpl Symb) const { 17820b57cec5SDimitry Andric uint32_t Result = SymbolRef::SF_None; 17830b57cec5SDimitry Andric const WasmSymbol &Sym = getWasmSymbol(Symb); 17840b57cec5SDimitry Andric 17850b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "getSymbolFlags: ptr=" << &Sym << " " << Sym << "\n"); 17860b57cec5SDimitry Andric if (Sym.isBindingWeak()) 17870b57cec5SDimitry Andric Result |= SymbolRef::SF_Weak; 17880b57cec5SDimitry Andric if (!Sym.isBindingLocal()) 17890b57cec5SDimitry Andric Result |= SymbolRef::SF_Global; 17900b57cec5SDimitry Andric if (Sym.isHidden()) 17910b57cec5SDimitry Andric Result |= SymbolRef::SF_Hidden; 17920b57cec5SDimitry Andric if (!Sym.isDefined()) 17930b57cec5SDimitry Andric Result |= SymbolRef::SF_Undefined; 17940b57cec5SDimitry Andric if (Sym.isTypeFunction()) 17950b57cec5SDimitry Andric Result |= SymbolRef::SF_Executable; 17960b57cec5SDimitry Andric return Result; 17970b57cec5SDimitry Andric } 17980b57cec5SDimitry Andric 17990b57cec5SDimitry Andric basic_symbol_iterator WasmObjectFile::symbol_begin() const { 18000b57cec5SDimitry Andric DataRefImpl Ref; 18010b57cec5SDimitry Andric Ref.d.a = 1; // Arbitrary non-zero value so that Ref.p is non-null 18020b57cec5SDimitry Andric Ref.d.b = 0; // Symbol index 18030b57cec5SDimitry Andric return BasicSymbolRef(Ref, this); 18040b57cec5SDimitry Andric } 18050b57cec5SDimitry Andric 18060b57cec5SDimitry Andric basic_symbol_iterator WasmObjectFile::symbol_end() const { 18070b57cec5SDimitry Andric DataRefImpl Ref; 18080b57cec5SDimitry Andric Ref.d.a = 1; // Arbitrary non-zero value so that Ref.p is non-null 18090b57cec5SDimitry Andric Ref.d.b = Symbols.size(); // Symbol index 18100b57cec5SDimitry Andric return BasicSymbolRef(Ref, this); 18110b57cec5SDimitry Andric } 18120b57cec5SDimitry Andric 18130b57cec5SDimitry Andric const WasmSymbol &WasmObjectFile::getWasmSymbol(const DataRefImpl &Symb) const { 18140b57cec5SDimitry Andric return Symbols[Symb.d.b]; 18150b57cec5SDimitry Andric } 18160b57cec5SDimitry Andric 18170b57cec5SDimitry Andric const WasmSymbol &WasmObjectFile::getWasmSymbol(const SymbolRef &Symb) const { 18180b57cec5SDimitry Andric return getWasmSymbol(Symb.getRawDataRefImpl()); 18190b57cec5SDimitry Andric } 18200b57cec5SDimitry Andric 18210b57cec5SDimitry Andric Expected<StringRef> WasmObjectFile::getSymbolName(DataRefImpl Symb) const { 18220b57cec5SDimitry Andric return getWasmSymbol(Symb).Info.Name; 18230b57cec5SDimitry Andric } 18240b57cec5SDimitry Andric 18250b57cec5SDimitry Andric Expected<uint64_t> WasmObjectFile::getSymbolAddress(DataRefImpl Symb) const { 18260b57cec5SDimitry Andric auto &Sym = getWasmSymbol(Symb); 1827*0fca6ea1SDimitry Andric if (!Sym.isDefined()) 1828*0fca6ea1SDimitry Andric return 0; 1829*0fca6ea1SDimitry Andric Expected<section_iterator> Sec = getSymbolSection(Symb); 1830*0fca6ea1SDimitry Andric if (!Sec) 1831*0fca6ea1SDimitry Andric return Sec.takeError(); 1832*0fca6ea1SDimitry Andric uint32_t SectionAddress = getSectionAddress(Sec.get()->getRawDataRefImpl()); 18330b57cec5SDimitry Andric if (Sym.Info.Kind == wasm::WASM_SYMBOL_TYPE_FUNCTION && 1834647cbc5dSDimitry Andric isDefinedFunctionIndex(Sym.Info.ElementIndex)) { 1835647cbc5dSDimitry Andric return getDefinedFunction(Sym.Info.ElementIndex).CodeSectionOffset + 1836*0fca6ea1SDimitry Andric SectionAddress; 1837647cbc5dSDimitry Andric } 1838*0fca6ea1SDimitry Andric if (Sym.Info.Kind == wasm::WASM_SYMBOL_TYPE_GLOBAL && 1839*0fca6ea1SDimitry Andric isDefinedGlobalIndex(Sym.Info.ElementIndex)) { 1840*0fca6ea1SDimitry Andric return getDefinedGlobal(Sym.Info.ElementIndex).Offset + SectionAddress; 1841*0fca6ea1SDimitry Andric } 1842*0fca6ea1SDimitry Andric 18430b57cec5SDimitry Andric return getSymbolValue(Symb); 18440b57cec5SDimitry Andric } 18450b57cec5SDimitry Andric 18460b57cec5SDimitry Andric uint64_t WasmObjectFile::getWasmSymbolValue(const WasmSymbol &Sym) const { 18470b57cec5SDimitry Andric switch (Sym.Info.Kind) { 18480b57cec5SDimitry Andric case wasm::WASM_SYMBOL_TYPE_FUNCTION: 18490b57cec5SDimitry Andric case wasm::WASM_SYMBOL_TYPE_GLOBAL: 1850fe6060f1SDimitry Andric case wasm::WASM_SYMBOL_TYPE_TAG: 1851e8d8bef9SDimitry Andric case wasm::WASM_SYMBOL_TYPE_TABLE: 18520b57cec5SDimitry Andric return Sym.Info.ElementIndex; 18530b57cec5SDimitry Andric case wasm::WASM_SYMBOL_TYPE_DATA: { 18540b57cec5SDimitry Andric // The value of a data symbol is the segment offset, plus the symbol 18550b57cec5SDimitry Andric // offset within the segment. 18560b57cec5SDimitry Andric uint32_t SegmentIndex = Sym.Info.DataRef.Segment; 18570b57cec5SDimitry Andric const wasm::WasmDataSegment &Segment = DataSegments[SegmentIndex].Data; 185881ad6265SDimitry Andric if (Segment.Offset.Extended) { 185981ad6265SDimitry Andric llvm_unreachable("extended init exprs not supported"); 186081ad6265SDimitry Andric } else if (Segment.Offset.Inst.Opcode == wasm::WASM_OPCODE_I32_CONST) { 186181ad6265SDimitry Andric return Segment.Offset.Inst.Value.Int32 + Sym.Info.DataRef.Offset; 186281ad6265SDimitry Andric } else if (Segment.Offset.Inst.Opcode == wasm::WASM_OPCODE_I64_CONST) { 186381ad6265SDimitry Andric return Segment.Offset.Inst.Value.Int64 + Sym.Info.DataRef.Offset; 1864cb14a3feSDimitry Andric } else if (Segment.Offset.Inst.Opcode == wasm::WASM_OPCODE_GLOBAL_GET) { 1865cb14a3feSDimitry Andric return Sym.Info.DataRef.Offset; 18665ffd83dbSDimitry Andric } else { 18675ffd83dbSDimitry Andric llvm_unreachable("unknown init expr opcode"); 18685ffd83dbSDimitry Andric } 18690b57cec5SDimitry Andric } 18700b57cec5SDimitry Andric case wasm::WASM_SYMBOL_TYPE_SECTION: 18710b57cec5SDimitry Andric return 0; 18720b57cec5SDimitry Andric } 18730b57cec5SDimitry Andric llvm_unreachable("invalid symbol type"); 18740b57cec5SDimitry Andric } 18750b57cec5SDimitry Andric 18760b57cec5SDimitry Andric uint64_t WasmObjectFile::getSymbolValueImpl(DataRefImpl Symb) const { 18770b57cec5SDimitry Andric return getWasmSymbolValue(getWasmSymbol(Symb)); 18780b57cec5SDimitry Andric } 18790b57cec5SDimitry Andric 18800b57cec5SDimitry Andric uint32_t WasmObjectFile::getSymbolAlignment(DataRefImpl Symb) const { 18810b57cec5SDimitry Andric llvm_unreachable("not yet implemented"); 18820b57cec5SDimitry Andric return 0; 18830b57cec5SDimitry Andric } 18840b57cec5SDimitry Andric 18850b57cec5SDimitry Andric uint64_t WasmObjectFile::getCommonSymbolSizeImpl(DataRefImpl Symb) const { 18860b57cec5SDimitry Andric llvm_unreachable("not yet implemented"); 18870b57cec5SDimitry Andric return 0; 18880b57cec5SDimitry Andric } 18890b57cec5SDimitry Andric 18900b57cec5SDimitry Andric Expected<SymbolRef::Type> 18910b57cec5SDimitry Andric WasmObjectFile::getSymbolType(DataRefImpl Symb) const { 18920b57cec5SDimitry Andric const WasmSymbol &Sym = getWasmSymbol(Symb); 18930b57cec5SDimitry Andric 18940b57cec5SDimitry Andric switch (Sym.Info.Kind) { 18950b57cec5SDimitry Andric case wasm::WASM_SYMBOL_TYPE_FUNCTION: 18960b57cec5SDimitry Andric return SymbolRef::ST_Function; 18970b57cec5SDimitry Andric case wasm::WASM_SYMBOL_TYPE_GLOBAL: 18980b57cec5SDimitry Andric return SymbolRef::ST_Other; 18990b57cec5SDimitry Andric case wasm::WASM_SYMBOL_TYPE_DATA: 19000b57cec5SDimitry Andric return SymbolRef::ST_Data; 19010b57cec5SDimitry Andric case wasm::WASM_SYMBOL_TYPE_SECTION: 19020b57cec5SDimitry Andric return SymbolRef::ST_Debug; 1903fe6060f1SDimitry Andric case wasm::WASM_SYMBOL_TYPE_TAG: 19040b57cec5SDimitry Andric return SymbolRef::ST_Other; 1905e8d8bef9SDimitry Andric case wasm::WASM_SYMBOL_TYPE_TABLE: 1906e8d8bef9SDimitry Andric return SymbolRef::ST_Other; 19070b57cec5SDimitry Andric } 19080b57cec5SDimitry Andric 1909e8d8bef9SDimitry Andric llvm_unreachable("unknown WasmSymbol::SymbolType"); 19100b57cec5SDimitry Andric return SymbolRef::ST_Other; 19110b57cec5SDimitry Andric } 19120b57cec5SDimitry Andric 19130b57cec5SDimitry Andric Expected<section_iterator> 19140b57cec5SDimitry Andric WasmObjectFile::getSymbolSection(DataRefImpl Symb) const { 19150b57cec5SDimitry Andric const WasmSymbol &Sym = getWasmSymbol(Symb); 19160b57cec5SDimitry Andric if (Sym.isUndefined()) 19170b57cec5SDimitry Andric return section_end(); 19180b57cec5SDimitry Andric 19190b57cec5SDimitry Andric DataRefImpl Ref; 19205ffd83dbSDimitry Andric Ref.d.a = getSymbolSectionIdImpl(Sym); 19215ffd83dbSDimitry Andric return section_iterator(SectionRef(Ref, this)); 19225ffd83dbSDimitry Andric } 19235ffd83dbSDimitry Andric 19245ffd83dbSDimitry Andric uint32_t WasmObjectFile::getSymbolSectionId(SymbolRef Symb) const { 19255ffd83dbSDimitry Andric const WasmSymbol &Sym = getWasmSymbol(Symb); 19265ffd83dbSDimitry Andric return getSymbolSectionIdImpl(Sym); 19275ffd83dbSDimitry Andric } 19285ffd83dbSDimitry Andric 19295ffd83dbSDimitry Andric uint32_t WasmObjectFile::getSymbolSectionIdImpl(const WasmSymbol &Sym) const { 19300b57cec5SDimitry Andric switch (Sym.Info.Kind) { 19310b57cec5SDimitry Andric case wasm::WASM_SYMBOL_TYPE_FUNCTION: 19325ffd83dbSDimitry Andric return CodeSection; 19330b57cec5SDimitry Andric case wasm::WASM_SYMBOL_TYPE_GLOBAL: 19345ffd83dbSDimitry Andric return GlobalSection; 19350b57cec5SDimitry Andric case wasm::WASM_SYMBOL_TYPE_DATA: 19365ffd83dbSDimitry Andric return DataSection; 19370b57cec5SDimitry Andric case wasm::WASM_SYMBOL_TYPE_SECTION: 19385ffd83dbSDimitry Andric return Sym.Info.ElementIndex; 1939fe6060f1SDimitry Andric case wasm::WASM_SYMBOL_TYPE_TAG: 1940fe6060f1SDimitry Andric return TagSection; 1941e8d8bef9SDimitry Andric case wasm::WASM_SYMBOL_TYPE_TABLE: 1942e8d8bef9SDimitry Andric return TableSection; 19430b57cec5SDimitry Andric default: 1944e8d8bef9SDimitry Andric llvm_unreachable("unknown WasmSymbol::SymbolType"); 19450b57cec5SDimitry Andric } 19460b57cec5SDimitry Andric } 19470b57cec5SDimitry Andric 1948*0fca6ea1SDimitry Andric uint32_t WasmObjectFile::getSymbolSize(SymbolRef Symb) const { 1949*0fca6ea1SDimitry Andric const WasmSymbol &Sym = getWasmSymbol(Symb); 1950*0fca6ea1SDimitry Andric if (!Sym.isDefined()) 1951*0fca6ea1SDimitry Andric return 0; 1952*0fca6ea1SDimitry Andric if (Sym.isTypeGlobal()) 1953*0fca6ea1SDimitry Andric return getDefinedGlobal(Sym.Info.ElementIndex).Size; 1954*0fca6ea1SDimitry Andric if (Sym.isTypeData()) 1955*0fca6ea1SDimitry Andric return Sym.Info.DataRef.Size; 1956*0fca6ea1SDimitry Andric if (Sym.isTypeFunction()) 1957*0fca6ea1SDimitry Andric return functions()[Sym.Info.ElementIndex - getNumImportedFunctions()].Size; 1958*0fca6ea1SDimitry Andric // Currently symbol size is only tracked for data segments and functions. In 1959*0fca6ea1SDimitry Andric // principle we could also track size (e.g. binary size) for tables, globals 1960*0fca6ea1SDimitry Andric // and element segments etc too. 1961*0fca6ea1SDimitry Andric return 0; 1962*0fca6ea1SDimitry Andric } 1963*0fca6ea1SDimitry Andric 19640b57cec5SDimitry Andric void WasmObjectFile::moveSectionNext(DataRefImpl &Sec) const { Sec.d.a++; } 19650b57cec5SDimitry Andric 19660b57cec5SDimitry Andric Expected<StringRef> WasmObjectFile::getSectionName(DataRefImpl Sec) const { 19670b57cec5SDimitry Andric const WasmSection &S = Sections[Sec.d.a]; 196881ad6265SDimitry Andric if (S.Type == wasm::WASM_SEC_CUSTOM) 19690b57cec5SDimitry Andric return S.Name; 197081ad6265SDimitry Andric if (S.Type > wasm::WASM_SEC_LAST_KNOWN) 19710b57cec5SDimitry Andric return createStringError(object_error::invalid_section_index, ""); 197281ad6265SDimitry Andric return wasm::sectionTypeToString(S.Type); 19730b57cec5SDimitry Andric } 19740b57cec5SDimitry Andric 1975*0fca6ea1SDimitry Andric uint64_t WasmObjectFile::getSectionAddress(DataRefImpl Sec) const { 1976*0fca6ea1SDimitry Andric // For object files, use 0 for section addresses, and section offsets for 1977*0fca6ea1SDimitry Andric // symbol addresses. For linked files, use file offsets. 1978*0fca6ea1SDimitry Andric // See also getSymbolAddress. 1979*0fca6ea1SDimitry Andric return isRelocatableObject() || isSharedObject() ? 0 1980*0fca6ea1SDimitry Andric : Sections[Sec.d.a].Offset; 1981*0fca6ea1SDimitry Andric } 19820b57cec5SDimitry Andric 19830b57cec5SDimitry Andric uint64_t WasmObjectFile::getSectionIndex(DataRefImpl Sec) const { 19840b57cec5SDimitry Andric return Sec.d.a; 19850b57cec5SDimitry Andric } 19860b57cec5SDimitry Andric 19870b57cec5SDimitry Andric uint64_t WasmObjectFile::getSectionSize(DataRefImpl Sec) const { 19880b57cec5SDimitry Andric const WasmSection &S = Sections[Sec.d.a]; 19890b57cec5SDimitry Andric return S.Content.size(); 19900b57cec5SDimitry Andric } 19910b57cec5SDimitry Andric 19920b57cec5SDimitry Andric Expected<ArrayRef<uint8_t>> 19930b57cec5SDimitry Andric WasmObjectFile::getSectionContents(DataRefImpl Sec) const { 19940b57cec5SDimitry Andric const WasmSection &S = Sections[Sec.d.a]; 19950b57cec5SDimitry Andric // This will never fail since wasm sections can never be empty (user-sections 19960b57cec5SDimitry Andric // must have a name and non-user sections each have a defined structure). 19970b57cec5SDimitry Andric return S.Content; 19980b57cec5SDimitry Andric } 19990b57cec5SDimitry Andric 20000b57cec5SDimitry Andric uint64_t WasmObjectFile::getSectionAlignment(DataRefImpl Sec) const { 20010b57cec5SDimitry Andric return 1; 20020b57cec5SDimitry Andric } 20030b57cec5SDimitry Andric 20040b57cec5SDimitry Andric bool WasmObjectFile::isSectionCompressed(DataRefImpl Sec) const { 20050b57cec5SDimitry Andric return false; 20060b57cec5SDimitry Andric } 20070b57cec5SDimitry Andric 20080b57cec5SDimitry Andric bool WasmObjectFile::isSectionText(DataRefImpl Sec) const { 20090b57cec5SDimitry Andric return getWasmSection(Sec).Type == wasm::WASM_SEC_CODE; 20100b57cec5SDimitry Andric } 20110b57cec5SDimitry Andric 20120b57cec5SDimitry Andric bool WasmObjectFile::isSectionData(DataRefImpl Sec) const { 20130b57cec5SDimitry Andric return getWasmSection(Sec).Type == wasm::WASM_SEC_DATA; 20140b57cec5SDimitry Andric } 20150b57cec5SDimitry Andric 20160b57cec5SDimitry Andric bool WasmObjectFile::isSectionBSS(DataRefImpl Sec) const { return false; } 20170b57cec5SDimitry Andric 20180b57cec5SDimitry Andric bool WasmObjectFile::isSectionVirtual(DataRefImpl Sec) const { return false; } 20190b57cec5SDimitry Andric 20200b57cec5SDimitry Andric relocation_iterator WasmObjectFile::section_rel_begin(DataRefImpl Ref) const { 20210b57cec5SDimitry Andric DataRefImpl RelocRef; 20220b57cec5SDimitry Andric RelocRef.d.a = Ref.d.a; 20230b57cec5SDimitry Andric RelocRef.d.b = 0; 20240b57cec5SDimitry Andric return relocation_iterator(RelocationRef(RelocRef, this)); 20250b57cec5SDimitry Andric } 20260b57cec5SDimitry Andric 20270b57cec5SDimitry Andric relocation_iterator WasmObjectFile::section_rel_end(DataRefImpl Ref) const { 20280b57cec5SDimitry Andric const WasmSection &Sec = getWasmSection(Ref); 20290b57cec5SDimitry Andric DataRefImpl RelocRef; 20300b57cec5SDimitry Andric RelocRef.d.a = Ref.d.a; 20310b57cec5SDimitry Andric RelocRef.d.b = Sec.Relocations.size(); 20320b57cec5SDimitry Andric return relocation_iterator(RelocationRef(RelocRef, this)); 20330b57cec5SDimitry Andric } 20340b57cec5SDimitry Andric 20350b57cec5SDimitry Andric void WasmObjectFile::moveRelocationNext(DataRefImpl &Rel) const { Rel.d.b++; } 20360b57cec5SDimitry Andric 20370b57cec5SDimitry Andric uint64_t WasmObjectFile::getRelocationOffset(DataRefImpl Ref) const { 20380b57cec5SDimitry Andric const wasm::WasmRelocation &Rel = getWasmRelocation(Ref); 20390b57cec5SDimitry Andric return Rel.Offset; 20400b57cec5SDimitry Andric } 20410b57cec5SDimitry Andric 20420b57cec5SDimitry Andric symbol_iterator WasmObjectFile::getRelocationSymbol(DataRefImpl Ref) const { 20430b57cec5SDimitry Andric const wasm::WasmRelocation &Rel = getWasmRelocation(Ref); 20440b57cec5SDimitry Andric if (Rel.Type == wasm::R_WASM_TYPE_INDEX_LEB) 20450b57cec5SDimitry Andric return symbol_end(); 20460b57cec5SDimitry Andric DataRefImpl Sym; 20470b57cec5SDimitry Andric Sym.d.a = 1; 20480b57cec5SDimitry Andric Sym.d.b = Rel.Index; 20490b57cec5SDimitry Andric return symbol_iterator(SymbolRef(Sym, this)); 20500b57cec5SDimitry Andric } 20510b57cec5SDimitry Andric 20520b57cec5SDimitry Andric uint64_t WasmObjectFile::getRelocationType(DataRefImpl Ref) const { 20530b57cec5SDimitry Andric const wasm::WasmRelocation &Rel = getWasmRelocation(Ref); 20540b57cec5SDimitry Andric return Rel.Type; 20550b57cec5SDimitry Andric } 20560b57cec5SDimitry Andric 20570b57cec5SDimitry Andric void WasmObjectFile::getRelocationTypeName( 20580b57cec5SDimitry Andric DataRefImpl Ref, SmallVectorImpl<char> &Result) const { 20590b57cec5SDimitry Andric const wasm::WasmRelocation &Rel = getWasmRelocation(Ref); 20600b57cec5SDimitry Andric StringRef Res = "Unknown"; 20610b57cec5SDimitry Andric 20620b57cec5SDimitry Andric #define WASM_RELOC(name, value) \ 20630b57cec5SDimitry Andric case wasm::name: \ 20640b57cec5SDimitry Andric Res = #name; \ 20650b57cec5SDimitry Andric break; 20660b57cec5SDimitry Andric 20670b57cec5SDimitry Andric switch (Rel.Type) { 20680b57cec5SDimitry Andric #include "llvm/BinaryFormat/WasmRelocs.def" 20690b57cec5SDimitry Andric } 20700b57cec5SDimitry Andric 20710b57cec5SDimitry Andric #undef WASM_RELOC 20720b57cec5SDimitry Andric 20730b57cec5SDimitry Andric Result.append(Res.begin(), Res.end()); 20740b57cec5SDimitry Andric } 20750b57cec5SDimitry Andric 20760b57cec5SDimitry Andric section_iterator WasmObjectFile::section_begin() const { 20770b57cec5SDimitry Andric DataRefImpl Ref; 20780b57cec5SDimitry Andric Ref.d.a = 0; 20790b57cec5SDimitry Andric return section_iterator(SectionRef(Ref, this)); 20800b57cec5SDimitry Andric } 20810b57cec5SDimitry Andric 20820b57cec5SDimitry Andric section_iterator WasmObjectFile::section_end() const { 20830b57cec5SDimitry Andric DataRefImpl Ref; 20840b57cec5SDimitry Andric Ref.d.a = Sections.size(); 20850b57cec5SDimitry Andric return section_iterator(SectionRef(Ref, this)); 20860b57cec5SDimitry Andric } 20870b57cec5SDimitry Andric 2088e8d8bef9SDimitry Andric uint8_t WasmObjectFile::getBytesInAddress() const { 2089e8d8bef9SDimitry Andric return HasMemory64 ? 8 : 4; 2090e8d8bef9SDimitry Andric } 20910b57cec5SDimitry Andric 20920b57cec5SDimitry Andric StringRef WasmObjectFile::getFileFormatName() const { return "WASM"; } 20930b57cec5SDimitry Andric 2094e8d8bef9SDimitry Andric Triple::ArchType WasmObjectFile::getArch() const { 2095e8d8bef9SDimitry Andric return HasMemory64 ? Triple::wasm64 : Triple::wasm32; 2096e8d8bef9SDimitry Andric } 20970b57cec5SDimitry Andric 2098bdd1243dSDimitry Andric Expected<SubtargetFeatures> WasmObjectFile::getFeatures() const { 20990b57cec5SDimitry Andric return SubtargetFeatures(); 21000b57cec5SDimitry Andric } 21010b57cec5SDimitry Andric 21020b57cec5SDimitry Andric bool WasmObjectFile::isRelocatableObject() const { return HasLinkingSection; } 21030b57cec5SDimitry Andric 21040b57cec5SDimitry Andric bool WasmObjectFile::isSharedObject() const { return HasDylinkSection; } 21050b57cec5SDimitry Andric 21060b57cec5SDimitry Andric const WasmSection &WasmObjectFile::getWasmSection(DataRefImpl Ref) const { 21070b57cec5SDimitry Andric assert(Ref.d.a < Sections.size()); 21080b57cec5SDimitry Andric return Sections[Ref.d.a]; 21090b57cec5SDimitry Andric } 21100b57cec5SDimitry Andric 21110b57cec5SDimitry Andric const WasmSection & 21120b57cec5SDimitry Andric WasmObjectFile::getWasmSection(const SectionRef &Section) const { 21130b57cec5SDimitry Andric return getWasmSection(Section.getRawDataRefImpl()); 21140b57cec5SDimitry Andric } 21150b57cec5SDimitry Andric 21160b57cec5SDimitry Andric const wasm::WasmRelocation & 21170b57cec5SDimitry Andric WasmObjectFile::getWasmRelocation(const RelocationRef &Ref) const { 21180b57cec5SDimitry Andric return getWasmRelocation(Ref.getRawDataRefImpl()); 21190b57cec5SDimitry Andric } 21200b57cec5SDimitry Andric 21210b57cec5SDimitry Andric const wasm::WasmRelocation & 21220b57cec5SDimitry Andric WasmObjectFile::getWasmRelocation(DataRefImpl Ref) const { 21230b57cec5SDimitry Andric assert(Ref.d.a < Sections.size()); 21240b57cec5SDimitry Andric const WasmSection &Sec = Sections[Ref.d.a]; 21250b57cec5SDimitry Andric assert(Ref.d.b < Sec.Relocations.size()); 21260b57cec5SDimitry Andric return Sec.Relocations[Ref.d.b]; 21270b57cec5SDimitry Andric } 21280b57cec5SDimitry Andric 21290b57cec5SDimitry Andric int WasmSectionOrderChecker::getSectionOrder(unsigned ID, 21300b57cec5SDimitry Andric StringRef CustomSectionName) { 21310b57cec5SDimitry Andric switch (ID) { 21320b57cec5SDimitry Andric case wasm::WASM_SEC_CUSTOM: 21330b57cec5SDimitry Andric return StringSwitch<unsigned>(CustomSectionName) 21340b57cec5SDimitry Andric .Case("dylink", WASM_SEC_ORDER_DYLINK) 2135349cc55cSDimitry Andric .Case("dylink.0", WASM_SEC_ORDER_DYLINK) 21360b57cec5SDimitry Andric .Case("linking", WASM_SEC_ORDER_LINKING) 21370b57cec5SDimitry Andric .StartsWith("reloc.", WASM_SEC_ORDER_RELOC) 21380b57cec5SDimitry Andric .Case("name", WASM_SEC_ORDER_NAME) 21390b57cec5SDimitry Andric .Case("producers", WASM_SEC_ORDER_PRODUCERS) 21400b57cec5SDimitry Andric .Case("target_features", WASM_SEC_ORDER_TARGET_FEATURES) 21410b57cec5SDimitry Andric .Default(WASM_SEC_ORDER_NONE); 21420b57cec5SDimitry Andric case wasm::WASM_SEC_TYPE: 21430b57cec5SDimitry Andric return WASM_SEC_ORDER_TYPE; 21440b57cec5SDimitry Andric case wasm::WASM_SEC_IMPORT: 21450b57cec5SDimitry Andric return WASM_SEC_ORDER_IMPORT; 21460b57cec5SDimitry Andric case wasm::WASM_SEC_FUNCTION: 21470b57cec5SDimitry Andric return WASM_SEC_ORDER_FUNCTION; 21480b57cec5SDimitry Andric case wasm::WASM_SEC_TABLE: 21490b57cec5SDimitry Andric return WASM_SEC_ORDER_TABLE; 21500b57cec5SDimitry Andric case wasm::WASM_SEC_MEMORY: 21510b57cec5SDimitry Andric return WASM_SEC_ORDER_MEMORY; 21520b57cec5SDimitry Andric case wasm::WASM_SEC_GLOBAL: 21530b57cec5SDimitry Andric return WASM_SEC_ORDER_GLOBAL; 21540b57cec5SDimitry Andric case wasm::WASM_SEC_EXPORT: 21550b57cec5SDimitry Andric return WASM_SEC_ORDER_EXPORT; 21560b57cec5SDimitry Andric case wasm::WASM_SEC_START: 21570b57cec5SDimitry Andric return WASM_SEC_ORDER_START; 21580b57cec5SDimitry Andric case wasm::WASM_SEC_ELEM: 21590b57cec5SDimitry Andric return WASM_SEC_ORDER_ELEM; 21600b57cec5SDimitry Andric case wasm::WASM_SEC_CODE: 21610b57cec5SDimitry Andric return WASM_SEC_ORDER_CODE; 21620b57cec5SDimitry Andric case wasm::WASM_SEC_DATA: 21630b57cec5SDimitry Andric return WASM_SEC_ORDER_DATA; 21640b57cec5SDimitry Andric case wasm::WASM_SEC_DATACOUNT: 21650b57cec5SDimitry Andric return WASM_SEC_ORDER_DATACOUNT; 2166fe6060f1SDimitry Andric case wasm::WASM_SEC_TAG: 2167fe6060f1SDimitry Andric return WASM_SEC_ORDER_TAG; 21680b57cec5SDimitry Andric default: 21690b57cec5SDimitry Andric return WASM_SEC_ORDER_NONE; 21700b57cec5SDimitry Andric } 21710b57cec5SDimitry Andric } 21720b57cec5SDimitry Andric 21730b57cec5SDimitry Andric // Represents the edges in a directed graph where any node B reachable from node 21740b57cec5SDimitry Andric // A is not allowed to appear before A in the section ordering, but may appear 21750b57cec5SDimitry Andric // afterward. 21765ffd83dbSDimitry Andric int WasmSectionOrderChecker::DisallowedPredecessors 21775ffd83dbSDimitry Andric [WASM_NUM_SEC_ORDERS][WASM_NUM_SEC_ORDERS] = { 21785ffd83dbSDimitry Andric // WASM_SEC_ORDER_NONE 21795ffd83dbSDimitry Andric {}, 21805ffd83dbSDimitry Andric // WASM_SEC_ORDER_TYPE 21815ffd83dbSDimitry Andric {WASM_SEC_ORDER_TYPE, WASM_SEC_ORDER_IMPORT}, 21825ffd83dbSDimitry Andric // WASM_SEC_ORDER_IMPORT 21835ffd83dbSDimitry Andric {WASM_SEC_ORDER_IMPORT, WASM_SEC_ORDER_FUNCTION}, 21845ffd83dbSDimitry Andric // WASM_SEC_ORDER_FUNCTION 21855ffd83dbSDimitry Andric {WASM_SEC_ORDER_FUNCTION, WASM_SEC_ORDER_TABLE}, 21865ffd83dbSDimitry Andric // WASM_SEC_ORDER_TABLE 21875ffd83dbSDimitry Andric {WASM_SEC_ORDER_TABLE, WASM_SEC_ORDER_MEMORY}, 21885ffd83dbSDimitry Andric // WASM_SEC_ORDER_MEMORY 2189fe6060f1SDimitry Andric {WASM_SEC_ORDER_MEMORY, WASM_SEC_ORDER_TAG}, 2190fe6060f1SDimitry Andric // WASM_SEC_ORDER_TAG 2191fe6060f1SDimitry Andric {WASM_SEC_ORDER_TAG, WASM_SEC_ORDER_GLOBAL}, 21925ffd83dbSDimitry Andric // WASM_SEC_ORDER_GLOBAL 21935ffd83dbSDimitry Andric {WASM_SEC_ORDER_GLOBAL, WASM_SEC_ORDER_EXPORT}, 21945ffd83dbSDimitry Andric // WASM_SEC_ORDER_EXPORT 21955ffd83dbSDimitry Andric {WASM_SEC_ORDER_EXPORT, WASM_SEC_ORDER_START}, 21965ffd83dbSDimitry Andric // WASM_SEC_ORDER_START 21975ffd83dbSDimitry Andric {WASM_SEC_ORDER_START, WASM_SEC_ORDER_ELEM}, 21985ffd83dbSDimitry Andric // WASM_SEC_ORDER_ELEM 21995ffd83dbSDimitry Andric {WASM_SEC_ORDER_ELEM, WASM_SEC_ORDER_DATACOUNT}, 22005ffd83dbSDimitry Andric // WASM_SEC_ORDER_DATACOUNT 22015ffd83dbSDimitry Andric {WASM_SEC_ORDER_DATACOUNT, WASM_SEC_ORDER_CODE}, 22025ffd83dbSDimitry Andric // WASM_SEC_ORDER_CODE 22035ffd83dbSDimitry Andric {WASM_SEC_ORDER_CODE, WASM_SEC_ORDER_DATA}, 22045ffd83dbSDimitry Andric // WASM_SEC_ORDER_DATA 22055ffd83dbSDimitry Andric {WASM_SEC_ORDER_DATA, WASM_SEC_ORDER_LINKING}, 22060b57cec5SDimitry Andric 22070b57cec5SDimitry Andric // Custom Sections 22085ffd83dbSDimitry Andric // WASM_SEC_ORDER_DYLINK 22095ffd83dbSDimitry Andric {WASM_SEC_ORDER_DYLINK, WASM_SEC_ORDER_TYPE}, 22105ffd83dbSDimitry Andric // WASM_SEC_ORDER_LINKING 22115ffd83dbSDimitry Andric {WASM_SEC_ORDER_LINKING, WASM_SEC_ORDER_RELOC, WASM_SEC_ORDER_NAME}, 22125ffd83dbSDimitry Andric // WASM_SEC_ORDER_RELOC (can be repeated) 22135ffd83dbSDimitry Andric {}, 22145ffd83dbSDimitry Andric // WASM_SEC_ORDER_NAME 22155ffd83dbSDimitry Andric {WASM_SEC_ORDER_NAME, WASM_SEC_ORDER_PRODUCERS}, 22165ffd83dbSDimitry Andric // WASM_SEC_ORDER_PRODUCERS 22175ffd83dbSDimitry Andric {WASM_SEC_ORDER_PRODUCERS, WASM_SEC_ORDER_TARGET_FEATURES}, 22185ffd83dbSDimitry Andric // WASM_SEC_ORDER_TARGET_FEATURES 22195ffd83dbSDimitry Andric {WASM_SEC_ORDER_TARGET_FEATURES}}; 22200b57cec5SDimitry Andric 22210b57cec5SDimitry Andric bool WasmSectionOrderChecker::isValidSectionOrder(unsigned ID, 22220b57cec5SDimitry Andric StringRef CustomSectionName) { 22230b57cec5SDimitry Andric int Order = getSectionOrder(ID, CustomSectionName); 22240b57cec5SDimitry Andric if (Order == WASM_SEC_ORDER_NONE) 22250b57cec5SDimitry Andric return true; 22260b57cec5SDimitry Andric 22270b57cec5SDimitry Andric // Disallowed predecessors we need to check for 22280b57cec5SDimitry Andric SmallVector<int, WASM_NUM_SEC_ORDERS> WorkList; 22290b57cec5SDimitry Andric 22300b57cec5SDimitry Andric // Keep track of completed checks to avoid repeating work 22310b57cec5SDimitry Andric bool Checked[WASM_NUM_SEC_ORDERS] = {}; 22320b57cec5SDimitry Andric 22330b57cec5SDimitry Andric int Curr = Order; 22340b57cec5SDimitry Andric while (true) { 22350b57cec5SDimitry Andric // Add new disallowed predecessors to work list 22360b57cec5SDimitry Andric for (size_t I = 0;; ++I) { 22370b57cec5SDimitry Andric int Next = DisallowedPredecessors[Curr][I]; 22380b57cec5SDimitry Andric if (Next == WASM_SEC_ORDER_NONE) 22390b57cec5SDimitry Andric break; 22400b57cec5SDimitry Andric if (Checked[Next]) 22410b57cec5SDimitry Andric continue; 22420b57cec5SDimitry Andric WorkList.push_back(Next); 22430b57cec5SDimitry Andric Checked[Next] = true; 22440b57cec5SDimitry Andric } 22450b57cec5SDimitry Andric 22460b57cec5SDimitry Andric if (WorkList.empty()) 22470b57cec5SDimitry Andric break; 22480b57cec5SDimitry Andric 22490b57cec5SDimitry Andric // Consider next disallowed predecessor 22500b57cec5SDimitry Andric Curr = WorkList.pop_back_val(); 22510b57cec5SDimitry Andric if (Seen[Curr]) 22520b57cec5SDimitry Andric return false; 22530b57cec5SDimitry Andric } 22540b57cec5SDimitry Andric 22550b57cec5SDimitry Andric // Have not seen any disallowed predecessors 22560b57cec5SDimitry Andric Seen[Order] = true; 22570b57cec5SDimitry Andric return true; 22580b57cec5SDimitry Andric } 2259