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/STLExtras.h"
120b57cec5SDimitry Andric #include "llvm/ADT/SmallSet.h"
130b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h"
140b57cec5SDimitry Andric #include "llvm/ADT/StringSet.h"
155ffd83dbSDimitry Andric #include "llvm/ADT/StringSwitch.h"
160b57cec5SDimitry Andric #include "llvm/ADT/Triple.h"
170b57cec5SDimitry Andric #include "llvm/BinaryFormat/Wasm.h"
180b57cec5SDimitry Andric #include "llvm/MC/SubtargetFeature.h"
190b57cec5SDimitry Andric #include "llvm/Object/Binary.h"
200b57cec5SDimitry Andric #include "llvm/Object/Error.h"
210b57cec5SDimitry Andric #include "llvm/Object/ObjectFile.h"
220b57cec5SDimitry Andric #include "llvm/Object/SymbolicFile.h"
230b57cec5SDimitry Andric #include "llvm/Object/Wasm.h"
240b57cec5SDimitry Andric #include "llvm/Support/Endian.h"
250b57cec5SDimitry Andric #include "llvm/Support/Error.h"
260b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
270b57cec5SDimitry Andric #include "llvm/Support/LEB128.h"
280b57cec5SDimitry Andric #include "llvm/Support/ScopedPrinter.h"
290b57cec5SDimitry Andric #include <algorithm>
300b57cec5SDimitry Andric #include <cassert>
310b57cec5SDimitry Andric #include <cstdint>
320b57cec5SDimitry Andric #include <cstring>
330b57cec5SDimitry Andric #include <system_error>
340b57cec5SDimitry Andric 
350b57cec5SDimitry Andric #define DEBUG_TYPE "wasm-object"
360b57cec5SDimitry Andric 
370b57cec5SDimitry Andric using namespace llvm;
380b57cec5SDimitry Andric using namespace object;
390b57cec5SDimitry Andric 
print(raw_ostream & Out) const400b57cec5SDimitry Andric void WasmSymbol::print(raw_ostream &Out) const {
410b57cec5SDimitry Andric   Out << "Name=" << Info.Name
42*5f7ddb14SDimitry Andric       << ", Kind=" << toString(wasm::WasmSymbolType(Info.Kind)) << ", Flags=0x"
43*5f7ddb14SDimitry Andric       << Twine::utohexstr(Info.Flags);
440b57cec5SDimitry Andric   if (!isTypeData()) {
450b57cec5SDimitry Andric     Out << ", ElemIndex=" << Info.ElementIndex;
460b57cec5SDimitry Andric   } else if (isDefined()) {
470b57cec5SDimitry Andric     Out << ", Segment=" << Info.DataRef.Segment;
480b57cec5SDimitry Andric     Out << ", Offset=" << Info.DataRef.Offset;
490b57cec5SDimitry Andric     Out << ", Size=" << Info.DataRef.Size;
500b57cec5SDimitry Andric   }
510b57cec5SDimitry Andric }
520b57cec5SDimitry Andric 
530b57cec5SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
dump() const540b57cec5SDimitry Andric LLVM_DUMP_METHOD void WasmSymbol::dump() const { print(dbgs()); }
550b57cec5SDimitry Andric #endif
560b57cec5SDimitry Andric 
570b57cec5SDimitry Andric Expected<std::unique_ptr<WasmObjectFile>>
createWasmObjectFile(MemoryBufferRef Buffer)580b57cec5SDimitry Andric ObjectFile::createWasmObjectFile(MemoryBufferRef Buffer) {
590b57cec5SDimitry Andric   Error Err = Error::success();
608bcb0991SDimitry Andric   auto ObjectFile = std::make_unique<WasmObjectFile>(Buffer, Err);
610b57cec5SDimitry Andric   if (Err)
620b57cec5SDimitry Andric     return std::move(Err);
630b57cec5SDimitry Andric 
640b57cec5SDimitry Andric   return std::move(ObjectFile);
650b57cec5SDimitry Andric }
660b57cec5SDimitry Andric 
670b57cec5SDimitry Andric #define VARINT7_MAX ((1 << 7) - 1)
680b57cec5SDimitry Andric #define VARINT7_MIN (-(1 << 7))
690b57cec5SDimitry Andric #define VARUINT7_MAX (1 << 7)
700b57cec5SDimitry Andric #define VARUINT1_MAX (1)
710b57cec5SDimitry Andric 
readUint8(WasmObjectFile::ReadContext & Ctx)720b57cec5SDimitry Andric static uint8_t readUint8(WasmObjectFile::ReadContext &Ctx) {
730b57cec5SDimitry Andric   if (Ctx.Ptr == Ctx.End)
740b57cec5SDimitry Andric     report_fatal_error("EOF while reading uint8");
750b57cec5SDimitry Andric   return *Ctx.Ptr++;
760b57cec5SDimitry Andric }
770b57cec5SDimitry Andric 
readUint32(WasmObjectFile::ReadContext & Ctx)780b57cec5SDimitry Andric static uint32_t readUint32(WasmObjectFile::ReadContext &Ctx) {
790b57cec5SDimitry Andric   if (Ctx.Ptr + 4 > Ctx.End)
800b57cec5SDimitry Andric     report_fatal_error("EOF while reading uint32");
810b57cec5SDimitry Andric   uint32_t Result = support::endian::read32le(Ctx.Ptr);
820b57cec5SDimitry Andric   Ctx.Ptr += 4;
830b57cec5SDimitry Andric   return Result;
840b57cec5SDimitry Andric }
850b57cec5SDimitry Andric 
readFloat32(WasmObjectFile::ReadContext & Ctx)860b57cec5SDimitry Andric static int32_t readFloat32(WasmObjectFile::ReadContext &Ctx) {
870b57cec5SDimitry Andric   if (Ctx.Ptr + 4 > Ctx.End)
880b57cec5SDimitry Andric     report_fatal_error("EOF while reading float64");
890b57cec5SDimitry Andric   int32_t Result = 0;
900b57cec5SDimitry Andric   memcpy(&Result, Ctx.Ptr, sizeof(Result));
910b57cec5SDimitry Andric   Ctx.Ptr += sizeof(Result);
920b57cec5SDimitry Andric   return Result;
930b57cec5SDimitry Andric }
940b57cec5SDimitry Andric 
readFloat64(WasmObjectFile::ReadContext & Ctx)950b57cec5SDimitry Andric static int64_t readFloat64(WasmObjectFile::ReadContext &Ctx) {
960b57cec5SDimitry Andric   if (Ctx.Ptr + 8 > Ctx.End)
970b57cec5SDimitry Andric     report_fatal_error("EOF while reading float64");
980b57cec5SDimitry Andric   int64_t Result = 0;
990b57cec5SDimitry Andric   memcpy(&Result, Ctx.Ptr, sizeof(Result));
1000b57cec5SDimitry Andric   Ctx.Ptr += sizeof(Result);
1010b57cec5SDimitry Andric   return Result;
1020b57cec5SDimitry Andric }
1030b57cec5SDimitry Andric 
readULEB128(WasmObjectFile::ReadContext & Ctx)1040b57cec5SDimitry Andric static uint64_t readULEB128(WasmObjectFile::ReadContext &Ctx) {
1050b57cec5SDimitry Andric   unsigned Count;
1060b57cec5SDimitry Andric   const char *Error = nullptr;
1070b57cec5SDimitry Andric   uint64_t Result = decodeULEB128(Ctx.Ptr, &Count, Ctx.End, &Error);
1080b57cec5SDimitry Andric   if (Error)
1090b57cec5SDimitry Andric     report_fatal_error(Error);
1100b57cec5SDimitry Andric   Ctx.Ptr += Count;
1110b57cec5SDimitry Andric   return Result;
1120b57cec5SDimitry Andric }
1130b57cec5SDimitry Andric 
readString(WasmObjectFile::ReadContext & Ctx)1140b57cec5SDimitry Andric static StringRef readString(WasmObjectFile::ReadContext &Ctx) {
1150b57cec5SDimitry Andric   uint32_t StringLen = readULEB128(Ctx);
1160b57cec5SDimitry Andric   if (Ctx.Ptr + StringLen > Ctx.End)
1170b57cec5SDimitry Andric     report_fatal_error("EOF while reading string");
1180b57cec5SDimitry Andric   StringRef Return =
1190b57cec5SDimitry Andric       StringRef(reinterpret_cast<const char *>(Ctx.Ptr), StringLen);
1200b57cec5SDimitry Andric   Ctx.Ptr += StringLen;
1210b57cec5SDimitry Andric   return Return;
1220b57cec5SDimitry Andric }
1230b57cec5SDimitry Andric 
readLEB128(WasmObjectFile::ReadContext & Ctx)1240b57cec5SDimitry Andric static int64_t readLEB128(WasmObjectFile::ReadContext &Ctx) {
1250b57cec5SDimitry Andric   unsigned Count;
1260b57cec5SDimitry Andric   const char *Error = nullptr;
1270b57cec5SDimitry Andric   uint64_t Result = decodeSLEB128(Ctx.Ptr, &Count, Ctx.End, &Error);
1280b57cec5SDimitry Andric   if (Error)
1290b57cec5SDimitry Andric     report_fatal_error(Error);
1300b57cec5SDimitry Andric   Ctx.Ptr += Count;
1310b57cec5SDimitry Andric   return Result;
1320b57cec5SDimitry Andric }
1330b57cec5SDimitry Andric 
readVaruint1(WasmObjectFile::ReadContext & Ctx)1340b57cec5SDimitry Andric static uint8_t readVaruint1(WasmObjectFile::ReadContext &Ctx) {
1350b57cec5SDimitry Andric   int64_t Result = readLEB128(Ctx);
1360b57cec5SDimitry Andric   if (Result > VARUINT1_MAX || Result < 0)
1370b57cec5SDimitry Andric     report_fatal_error("LEB is outside Varuint1 range");
1380b57cec5SDimitry Andric   return Result;
1390b57cec5SDimitry Andric }
1400b57cec5SDimitry Andric 
readVarint32(WasmObjectFile::ReadContext & Ctx)1410b57cec5SDimitry Andric static int32_t readVarint32(WasmObjectFile::ReadContext &Ctx) {
1420b57cec5SDimitry Andric   int64_t Result = readLEB128(Ctx);
1430b57cec5SDimitry Andric   if (Result > INT32_MAX || Result < INT32_MIN)
1440b57cec5SDimitry Andric     report_fatal_error("LEB is outside Varint32 range");
1450b57cec5SDimitry Andric   return Result;
1460b57cec5SDimitry Andric }
1470b57cec5SDimitry Andric 
readVaruint32(WasmObjectFile::ReadContext & Ctx)1480b57cec5SDimitry Andric static uint32_t readVaruint32(WasmObjectFile::ReadContext &Ctx) {
1490b57cec5SDimitry Andric   uint64_t Result = readULEB128(Ctx);
1500b57cec5SDimitry Andric   if (Result > UINT32_MAX)
1510b57cec5SDimitry Andric     report_fatal_error("LEB is outside Varuint32 range");
1520b57cec5SDimitry Andric   return Result;
1530b57cec5SDimitry Andric }
1540b57cec5SDimitry Andric 
readVarint64(WasmObjectFile::ReadContext & Ctx)1550b57cec5SDimitry Andric static int64_t readVarint64(WasmObjectFile::ReadContext &Ctx) {
1560b57cec5SDimitry Andric   return readLEB128(Ctx);
1570b57cec5SDimitry Andric }
1580b57cec5SDimitry Andric 
readVaruint64(WasmObjectFile::ReadContext & Ctx)1595ffd83dbSDimitry Andric static uint64_t readVaruint64(WasmObjectFile::ReadContext &Ctx) {
1605ffd83dbSDimitry Andric   return readULEB128(Ctx);
1615ffd83dbSDimitry Andric }
1625ffd83dbSDimitry Andric 
readOpcode(WasmObjectFile::ReadContext & Ctx)1630b57cec5SDimitry Andric static uint8_t readOpcode(WasmObjectFile::ReadContext &Ctx) {
1640b57cec5SDimitry Andric   return readUint8(Ctx);
1650b57cec5SDimitry Andric }
1660b57cec5SDimitry Andric 
readInitExpr(wasm::WasmInitExpr & Expr,WasmObjectFile::ReadContext & Ctx)1670b57cec5SDimitry Andric static Error readInitExpr(wasm::WasmInitExpr &Expr,
1680b57cec5SDimitry Andric                           WasmObjectFile::ReadContext &Ctx) {
1690b57cec5SDimitry Andric   Expr.Opcode = readOpcode(Ctx);
1700b57cec5SDimitry Andric 
1710b57cec5SDimitry Andric   switch (Expr.Opcode) {
1720b57cec5SDimitry Andric   case wasm::WASM_OPCODE_I32_CONST:
1730b57cec5SDimitry Andric     Expr.Value.Int32 = readVarint32(Ctx);
1740b57cec5SDimitry Andric     break;
1750b57cec5SDimitry Andric   case wasm::WASM_OPCODE_I64_CONST:
1760b57cec5SDimitry Andric     Expr.Value.Int64 = readVarint64(Ctx);
1770b57cec5SDimitry Andric     break;
1780b57cec5SDimitry Andric   case wasm::WASM_OPCODE_F32_CONST:
1790b57cec5SDimitry Andric     Expr.Value.Float32 = readFloat32(Ctx);
1800b57cec5SDimitry Andric     break;
1810b57cec5SDimitry Andric   case wasm::WASM_OPCODE_F64_CONST:
1820b57cec5SDimitry Andric     Expr.Value.Float64 = readFloat64(Ctx);
1830b57cec5SDimitry Andric     break;
1840b57cec5SDimitry Andric   case wasm::WASM_OPCODE_GLOBAL_GET:
1850b57cec5SDimitry Andric     Expr.Value.Global = readULEB128(Ctx);
1860b57cec5SDimitry Andric     break;
1875ffd83dbSDimitry Andric   case wasm::WASM_OPCODE_REF_NULL: {
1885ffd83dbSDimitry Andric     wasm::ValType Ty = static_cast<wasm::ValType>(readULEB128(Ctx));
1895ffd83dbSDimitry Andric     if (Ty != wasm::ValType::EXTERNREF) {
190af732203SDimitry Andric       return make_error<GenericBinaryError>("invalid type for ref.null",
1915ffd83dbSDimitry Andric                                             object_error::parse_failed);
1925ffd83dbSDimitry Andric     }
1935ffd83dbSDimitry Andric     break;
1945ffd83dbSDimitry Andric   }
1950b57cec5SDimitry Andric   default:
196af732203SDimitry Andric     return make_error<GenericBinaryError>("invalid opcode in init_expr",
1970b57cec5SDimitry Andric                                           object_error::parse_failed);
1980b57cec5SDimitry Andric   }
1990b57cec5SDimitry Andric 
2000b57cec5SDimitry Andric   uint8_t EndOpcode = readOpcode(Ctx);
2010b57cec5SDimitry Andric   if (EndOpcode != wasm::WASM_OPCODE_END) {
202af732203SDimitry Andric     return make_error<GenericBinaryError>("invalid init_expr",
2030b57cec5SDimitry Andric                                           object_error::parse_failed);
2040b57cec5SDimitry Andric   }
2050b57cec5SDimitry Andric   return Error::success();
2060b57cec5SDimitry Andric }
2070b57cec5SDimitry Andric 
readLimits(WasmObjectFile::ReadContext & Ctx)2080b57cec5SDimitry Andric static wasm::WasmLimits readLimits(WasmObjectFile::ReadContext &Ctx) {
2090b57cec5SDimitry Andric   wasm::WasmLimits Result;
2100b57cec5SDimitry Andric   Result.Flags = readVaruint32(Ctx);
211*5f7ddb14SDimitry Andric   Result.Minimum = readVaruint64(Ctx);
2120b57cec5SDimitry Andric   if (Result.Flags & wasm::WASM_LIMITS_FLAG_HAS_MAX)
2135ffd83dbSDimitry Andric     Result.Maximum = readVaruint64(Ctx);
2140b57cec5SDimitry Andric   return Result;
2150b57cec5SDimitry Andric }
2160b57cec5SDimitry Andric 
readTableType(WasmObjectFile::ReadContext & Ctx)217af732203SDimitry Andric static wasm::WasmTableType readTableType(WasmObjectFile::ReadContext &Ctx) {
218af732203SDimitry Andric   wasm::WasmTableType TableType;
219af732203SDimitry Andric   TableType.ElemType = readUint8(Ctx);
220af732203SDimitry Andric   TableType.Limits = readLimits(Ctx);
221af732203SDimitry Andric   return TableType;
2220b57cec5SDimitry Andric }
2230b57cec5SDimitry Andric 
readSection(WasmSection & Section,WasmObjectFile::ReadContext & Ctx,WasmSectionOrderChecker & Checker)2240b57cec5SDimitry Andric static Error readSection(WasmSection &Section, WasmObjectFile::ReadContext &Ctx,
2250b57cec5SDimitry Andric                          WasmSectionOrderChecker &Checker) {
2260b57cec5SDimitry Andric   Section.Offset = Ctx.Ptr - Ctx.Start;
2270b57cec5SDimitry Andric   Section.Type = readUint8(Ctx);
2280b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << "readSection type=" << Section.Type << "\n");
2290b57cec5SDimitry Andric   uint32_t Size = readVaruint32(Ctx);
2300b57cec5SDimitry Andric   if (Size == 0)
231af732203SDimitry Andric     return make_error<StringError>("zero length section",
2320b57cec5SDimitry Andric                                    object_error::parse_failed);
2330b57cec5SDimitry Andric   if (Ctx.Ptr + Size > Ctx.End)
234af732203SDimitry Andric     return make_error<StringError>("section too large",
2350b57cec5SDimitry Andric                                    object_error::parse_failed);
2360b57cec5SDimitry Andric   if (Section.Type == wasm::WASM_SEC_CUSTOM) {
2370b57cec5SDimitry Andric     WasmObjectFile::ReadContext SectionCtx;
2380b57cec5SDimitry Andric     SectionCtx.Start = Ctx.Ptr;
2390b57cec5SDimitry Andric     SectionCtx.Ptr = Ctx.Ptr;
2400b57cec5SDimitry Andric     SectionCtx.End = Ctx.Ptr + Size;
2410b57cec5SDimitry Andric 
2420b57cec5SDimitry Andric     Section.Name = readString(SectionCtx);
2430b57cec5SDimitry Andric 
2440b57cec5SDimitry Andric     uint32_t SectionNameSize = SectionCtx.Ptr - SectionCtx.Start;
2450b57cec5SDimitry Andric     Ctx.Ptr += SectionNameSize;
2460b57cec5SDimitry Andric     Size -= SectionNameSize;
2470b57cec5SDimitry Andric   }
2480b57cec5SDimitry Andric 
2490b57cec5SDimitry Andric   if (!Checker.isValidSectionOrder(Section.Type, Section.Name)) {
250af732203SDimitry Andric     return make_error<StringError>("out of order section type: " +
2510b57cec5SDimitry Andric                                        llvm::to_string(Section.Type),
2520b57cec5SDimitry Andric                                    object_error::parse_failed);
2530b57cec5SDimitry Andric   }
2540b57cec5SDimitry Andric 
2550b57cec5SDimitry Andric   Section.Content = ArrayRef<uint8_t>(Ctx.Ptr, Size);
2560b57cec5SDimitry Andric   Ctx.Ptr += Size;
2570b57cec5SDimitry Andric   return Error::success();
2580b57cec5SDimitry Andric }
2590b57cec5SDimitry Andric 
WasmObjectFile(MemoryBufferRef Buffer,Error & Err)2600b57cec5SDimitry Andric WasmObjectFile::WasmObjectFile(MemoryBufferRef Buffer, Error &Err)
2610b57cec5SDimitry Andric     : ObjectFile(Binary::ID_Wasm, Buffer) {
2620b57cec5SDimitry Andric   ErrorAsOutParameter ErrAsOutParam(&Err);
2630b57cec5SDimitry Andric   Header.Magic = getData().substr(0, 4);
2640b57cec5SDimitry Andric   if (Header.Magic != StringRef("\0asm", 4)) {
265af732203SDimitry Andric     Err = make_error<StringError>("invalid magic number",
266af732203SDimitry Andric                                   object_error::parse_failed);
2670b57cec5SDimitry Andric     return;
2680b57cec5SDimitry Andric   }
2690b57cec5SDimitry Andric 
2700b57cec5SDimitry Andric   ReadContext Ctx;
2710b57cec5SDimitry Andric   Ctx.Start = getData().bytes_begin();
2720b57cec5SDimitry Andric   Ctx.Ptr = Ctx.Start + 4;
2730b57cec5SDimitry Andric   Ctx.End = Ctx.Start + getData().size();
2740b57cec5SDimitry Andric 
2750b57cec5SDimitry Andric   if (Ctx.Ptr + 4 > Ctx.End) {
276af732203SDimitry Andric     Err = make_error<StringError>("missing version number",
2770b57cec5SDimitry Andric                                   object_error::parse_failed);
2780b57cec5SDimitry Andric     return;
2790b57cec5SDimitry Andric   }
2800b57cec5SDimitry Andric 
2810b57cec5SDimitry Andric   Header.Version = readUint32(Ctx);
2820b57cec5SDimitry Andric   if (Header.Version != wasm::WasmVersion) {
283af732203SDimitry Andric     Err = make_error<StringError>("invalid version number: " +
284af732203SDimitry Andric                                       Twine(Header.Version),
2850b57cec5SDimitry Andric                                   object_error::parse_failed);
2860b57cec5SDimitry Andric     return;
2870b57cec5SDimitry Andric   }
2880b57cec5SDimitry Andric 
2890b57cec5SDimitry Andric   WasmSection Sec;
2900b57cec5SDimitry Andric   WasmSectionOrderChecker Checker;
2910b57cec5SDimitry Andric   while (Ctx.Ptr < Ctx.End) {
2920b57cec5SDimitry Andric     if ((Err = readSection(Sec, Ctx, Checker)))
2930b57cec5SDimitry Andric       return;
2940b57cec5SDimitry Andric     if ((Err = parseSection(Sec)))
2950b57cec5SDimitry Andric       return;
2960b57cec5SDimitry Andric 
2970b57cec5SDimitry Andric     Sections.push_back(Sec);
2980b57cec5SDimitry Andric   }
2990b57cec5SDimitry Andric }
3000b57cec5SDimitry Andric 
parseSection(WasmSection & Sec)3010b57cec5SDimitry Andric Error WasmObjectFile::parseSection(WasmSection &Sec) {
3020b57cec5SDimitry Andric   ReadContext Ctx;
3030b57cec5SDimitry Andric   Ctx.Start = Sec.Content.data();
3040b57cec5SDimitry Andric   Ctx.End = Ctx.Start + Sec.Content.size();
3050b57cec5SDimitry Andric   Ctx.Ptr = Ctx.Start;
3060b57cec5SDimitry Andric   switch (Sec.Type) {
3070b57cec5SDimitry Andric   case wasm::WASM_SEC_CUSTOM:
3080b57cec5SDimitry Andric     return parseCustomSection(Sec, Ctx);
3090b57cec5SDimitry Andric   case wasm::WASM_SEC_TYPE:
3100b57cec5SDimitry Andric     return parseTypeSection(Ctx);
3110b57cec5SDimitry Andric   case wasm::WASM_SEC_IMPORT:
3120b57cec5SDimitry Andric     return parseImportSection(Ctx);
3130b57cec5SDimitry Andric   case wasm::WASM_SEC_FUNCTION:
3140b57cec5SDimitry Andric     return parseFunctionSection(Ctx);
3150b57cec5SDimitry Andric   case wasm::WASM_SEC_TABLE:
3160b57cec5SDimitry Andric     return parseTableSection(Ctx);
3170b57cec5SDimitry Andric   case wasm::WASM_SEC_MEMORY:
3180b57cec5SDimitry Andric     return parseMemorySection(Ctx);
319*5f7ddb14SDimitry Andric   case wasm::WASM_SEC_TAG:
320*5f7ddb14SDimitry Andric     return parseTagSection(Ctx);
3215ffd83dbSDimitry Andric   case wasm::WASM_SEC_GLOBAL:
3225ffd83dbSDimitry Andric     return parseGlobalSection(Ctx);
3230b57cec5SDimitry Andric   case wasm::WASM_SEC_EXPORT:
3240b57cec5SDimitry Andric     return parseExportSection(Ctx);
3250b57cec5SDimitry Andric   case wasm::WASM_SEC_START:
3260b57cec5SDimitry Andric     return parseStartSection(Ctx);
3270b57cec5SDimitry Andric   case wasm::WASM_SEC_ELEM:
3280b57cec5SDimitry Andric     return parseElemSection(Ctx);
3290b57cec5SDimitry Andric   case wasm::WASM_SEC_CODE:
3300b57cec5SDimitry Andric     return parseCodeSection(Ctx);
3310b57cec5SDimitry Andric   case wasm::WASM_SEC_DATA:
3320b57cec5SDimitry Andric     return parseDataSection(Ctx);
3330b57cec5SDimitry Andric   case wasm::WASM_SEC_DATACOUNT:
3340b57cec5SDimitry Andric     return parseDataCountSection(Ctx);
3350b57cec5SDimitry Andric   default:
3360b57cec5SDimitry Andric     return make_error<GenericBinaryError>(
337af732203SDimitry Andric         "invalid section type: " + Twine(Sec.Type), object_error::parse_failed);
3380b57cec5SDimitry Andric   }
3390b57cec5SDimitry Andric }
3400b57cec5SDimitry Andric 
parseDylinkSection(ReadContext & Ctx)3410b57cec5SDimitry Andric Error WasmObjectFile::parseDylinkSection(ReadContext &Ctx) {
3420b57cec5SDimitry Andric   // See https://github.com/WebAssembly/tool-conventions/blob/master/DynamicLinking.md
3430b57cec5SDimitry Andric   HasDylinkSection = true;
3440b57cec5SDimitry Andric   DylinkInfo.MemorySize = readVaruint32(Ctx);
3450b57cec5SDimitry Andric   DylinkInfo.MemoryAlignment = readVaruint32(Ctx);
3460b57cec5SDimitry Andric   DylinkInfo.TableSize = readVaruint32(Ctx);
3470b57cec5SDimitry Andric   DylinkInfo.TableAlignment = readVaruint32(Ctx);
3480b57cec5SDimitry Andric   uint32_t Count = readVaruint32(Ctx);
3490b57cec5SDimitry Andric   while (Count--) {
3500b57cec5SDimitry Andric     DylinkInfo.Needed.push_back(readString(Ctx));
3510b57cec5SDimitry Andric   }
3520b57cec5SDimitry Andric   if (Ctx.Ptr != Ctx.End)
3530b57cec5SDimitry Andric     return make_error<GenericBinaryError>("dylink section ended prematurely",
3540b57cec5SDimitry Andric                                           object_error::parse_failed);
3550b57cec5SDimitry Andric   return Error::success();
3560b57cec5SDimitry Andric }
3570b57cec5SDimitry Andric 
parseNameSection(ReadContext & Ctx)3580b57cec5SDimitry Andric Error WasmObjectFile::parseNameSection(ReadContext &Ctx) {
359af732203SDimitry Andric   llvm::DenseSet<uint64_t> SeenFunctions;
360af732203SDimitry Andric   llvm::DenseSet<uint64_t> SeenGlobals;
361af732203SDimitry Andric   llvm::DenseSet<uint64_t> SeenSegments;
362480093f4SDimitry Andric   if (FunctionTypes.size() && !SeenCodeSection) {
363af732203SDimitry Andric     return make_error<GenericBinaryError>("names must come after code section",
3640b57cec5SDimitry Andric                                           object_error::parse_failed);
3650b57cec5SDimitry Andric   }
3660b57cec5SDimitry Andric 
3670b57cec5SDimitry Andric   while (Ctx.Ptr < Ctx.End) {
3680b57cec5SDimitry Andric     uint8_t Type = readUint8(Ctx);
3690b57cec5SDimitry Andric     uint32_t Size = readVaruint32(Ctx);
3700b57cec5SDimitry Andric     const uint8_t *SubSectionEnd = Ctx.Ptr + Size;
3710b57cec5SDimitry Andric     switch (Type) {
372af732203SDimitry Andric     case wasm::WASM_NAMES_FUNCTION:
373af732203SDimitry Andric     case wasm::WASM_NAMES_GLOBAL:
374af732203SDimitry Andric     case wasm::WASM_NAMES_DATA_SEGMENT: {
3750b57cec5SDimitry Andric       uint32_t Count = readVaruint32(Ctx);
3760b57cec5SDimitry Andric       while (Count--) {
3770b57cec5SDimitry Andric         uint32_t Index = readVaruint32(Ctx);
3780b57cec5SDimitry Andric         StringRef Name = readString(Ctx);
379af732203SDimitry Andric         wasm::NameType nameType = wasm::NameType::FUNCTION;
380af732203SDimitry Andric         if (Type == wasm::WASM_NAMES_FUNCTION) {
381af732203SDimitry Andric           if (!SeenFunctions.insert(Index).second)
382af732203SDimitry Andric             return make_error<GenericBinaryError>(
383af732203SDimitry Andric                 "function named more than once", object_error::parse_failed);
3840b57cec5SDimitry Andric           if (!isValidFunctionIndex(Index) || Name.empty())
385af732203SDimitry Andric             return make_error<GenericBinaryError>("invalid name entry",
3860b57cec5SDimitry Andric                                                   object_error::parse_failed);
387af732203SDimitry Andric 
3880b57cec5SDimitry Andric           if (isDefinedFunctionIndex(Index))
3890b57cec5SDimitry Andric             getDefinedFunction(Index).DebugName = Name;
390af732203SDimitry Andric         } else if (Type == wasm::WASM_NAMES_GLOBAL) {
391af732203SDimitry Andric           nameType = wasm::NameType::GLOBAL;
392af732203SDimitry Andric           if (!SeenGlobals.insert(Index).second)
393af732203SDimitry Andric             return make_error<GenericBinaryError>("global named more than once",
394af732203SDimitry Andric                                                   object_error::parse_failed);
395af732203SDimitry Andric           if (!isValidGlobalIndex(Index) || Name.empty())
396af732203SDimitry Andric             return make_error<GenericBinaryError>("invalid name entry",
397af732203SDimitry Andric                                                   object_error::parse_failed);
398af732203SDimitry Andric         } else {
399af732203SDimitry Andric           nameType = wasm::NameType::DATA_SEGMENT;
400af732203SDimitry Andric           if (!SeenSegments.insert(Index).second)
401af732203SDimitry Andric             return make_error<GenericBinaryError>(
402af732203SDimitry Andric                 "segment named more than once", object_error::parse_failed);
403af732203SDimitry Andric           if (Index > DataSegments.size())
404af732203SDimitry Andric             return make_error<GenericBinaryError>("invalid named data segment",
405af732203SDimitry Andric                                                   object_error::parse_failed);
406af732203SDimitry Andric         }
407af732203SDimitry Andric         DebugNames.push_back(wasm::WasmDebugName{nameType, Index, Name});
4080b57cec5SDimitry Andric       }
4090b57cec5SDimitry Andric       break;
4100b57cec5SDimitry Andric     }
4110b57cec5SDimitry Andric     // Ignore local names for now
4120b57cec5SDimitry Andric     case wasm::WASM_NAMES_LOCAL:
4130b57cec5SDimitry Andric     default:
4140b57cec5SDimitry Andric       Ctx.Ptr += Size;
4150b57cec5SDimitry Andric       break;
4160b57cec5SDimitry Andric     }
4170b57cec5SDimitry Andric     if (Ctx.Ptr != SubSectionEnd)
4180b57cec5SDimitry Andric       return make_error<GenericBinaryError>(
419af732203SDimitry Andric           "name sub-section ended prematurely", object_error::parse_failed);
4200b57cec5SDimitry Andric   }
4210b57cec5SDimitry Andric 
4220b57cec5SDimitry Andric   if (Ctx.Ptr != Ctx.End)
423af732203SDimitry Andric     return make_error<GenericBinaryError>("name section ended prematurely",
4240b57cec5SDimitry Andric                                           object_error::parse_failed);
4250b57cec5SDimitry Andric   return Error::success();
4260b57cec5SDimitry Andric }
4270b57cec5SDimitry Andric 
parseLinkingSection(ReadContext & Ctx)4280b57cec5SDimitry Andric Error WasmObjectFile::parseLinkingSection(ReadContext &Ctx) {
4290b57cec5SDimitry Andric   HasLinkingSection = true;
430480093f4SDimitry Andric   if (FunctionTypes.size() && !SeenCodeSection) {
4310b57cec5SDimitry Andric     return make_error<GenericBinaryError>(
432af732203SDimitry Andric         "linking data must come after code section",
4330b57cec5SDimitry Andric         object_error::parse_failed);
4340b57cec5SDimitry Andric   }
4350b57cec5SDimitry Andric 
4360b57cec5SDimitry Andric   LinkingData.Version = readVaruint32(Ctx);
4370b57cec5SDimitry Andric   if (LinkingData.Version != wasm::WasmMetadataVersion) {
4380b57cec5SDimitry Andric     return make_error<GenericBinaryError>(
439af732203SDimitry Andric         "unexpected metadata version: " + Twine(LinkingData.Version) +
4400b57cec5SDimitry Andric             " (Expected: " + Twine(wasm::WasmMetadataVersion) + ")",
4410b57cec5SDimitry Andric         object_error::parse_failed);
4420b57cec5SDimitry Andric   }
4430b57cec5SDimitry Andric 
4440b57cec5SDimitry Andric   const uint8_t *OrigEnd = Ctx.End;
4450b57cec5SDimitry Andric   while (Ctx.Ptr < OrigEnd) {
4460b57cec5SDimitry Andric     Ctx.End = OrigEnd;
4470b57cec5SDimitry Andric     uint8_t Type = readUint8(Ctx);
4480b57cec5SDimitry Andric     uint32_t Size = readVaruint32(Ctx);
4490b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "readSubsection type=" << int(Type) << " size=" << Size
4500b57cec5SDimitry Andric                       << "\n");
4510b57cec5SDimitry Andric     Ctx.End = Ctx.Ptr + Size;
4520b57cec5SDimitry Andric     switch (Type) {
4530b57cec5SDimitry Andric     case wasm::WASM_SYMBOL_TABLE:
4540b57cec5SDimitry Andric       if (Error Err = parseLinkingSectionSymtab(Ctx))
4550b57cec5SDimitry Andric         return Err;
4560b57cec5SDimitry Andric       break;
4570b57cec5SDimitry Andric     case wasm::WASM_SEGMENT_INFO: {
4580b57cec5SDimitry Andric       uint32_t Count = readVaruint32(Ctx);
4590b57cec5SDimitry Andric       if (Count > DataSegments.size())
460af732203SDimitry Andric         return make_error<GenericBinaryError>("too many segment names",
4610b57cec5SDimitry Andric                                               object_error::parse_failed);
4620b57cec5SDimitry Andric       for (uint32_t I = 0; I < Count; I++) {
4630b57cec5SDimitry Andric         DataSegments[I].Data.Name = readString(Ctx);
4640b57cec5SDimitry Andric         DataSegments[I].Data.Alignment = readVaruint32(Ctx);
465*5f7ddb14SDimitry Andric         DataSegments[I].Data.LinkingFlags = readVaruint32(Ctx);
4660b57cec5SDimitry Andric       }
4670b57cec5SDimitry Andric       break;
4680b57cec5SDimitry Andric     }
4690b57cec5SDimitry Andric     case wasm::WASM_INIT_FUNCS: {
4700b57cec5SDimitry Andric       uint32_t Count = readVaruint32(Ctx);
4710b57cec5SDimitry Andric       LinkingData.InitFunctions.reserve(Count);
4720b57cec5SDimitry Andric       for (uint32_t I = 0; I < Count; I++) {
4730b57cec5SDimitry Andric         wasm::WasmInitFunc Init;
4740b57cec5SDimitry Andric         Init.Priority = readVaruint32(Ctx);
4750b57cec5SDimitry Andric         Init.Symbol = readVaruint32(Ctx);
4760b57cec5SDimitry Andric         if (!isValidFunctionSymbol(Init.Symbol))
477af732203SDimitry Andric           return make_error<GenericBinaryError>("invalid function symbol: " +
4780b57cec5SDimitry Andric                                                     Twine(Init.Symbol),
4790b57cec5SDimitry Andric                                                 object_error::parse_failed);
4800b57cec5SDimitry Andric         LinkingData.InitFunctions.emplace_back(Init);
4810b57cec5SDimitry Andric       }
4820b57cec5SDimitry Andric       break;
4830b57cec5SDimitry Andric     }
4840b57cec5SDimitry Andric     case wasm::WASM_COMDAT_INFO:
4850b57cec5SDimitry Andric       if (Error Err = parseLinkingSectionComdat(Ctx))
4860b57cec5SDimitry Andric         return Err;
4870b57cec5SDimitry Andric       break;
4880b57cec5SDimitry Andric     default:
4890b57cec5SDimitry Andric       Ctx.Ptr += Size;
4900b57cec5SDimitry Andric       break;
4910b57cec5SDimitry Andric     }
4920b57cec5SDimitry Andric     if (Ctx.Ptr != Ctx.End)
4930b57cec5SDimitry Andric       return make_error<GenericBinaryError>(
494af732203SDimitry Andric           "linking sub-section ended prematurely", object_error::parse_failed);
4950b57cec5SDimitry Andric   }
4960b57cec5SDimitry Andric   if (Ctx.Ptr != OrigEnd)
497af732203SDimitry Andric     return make_error<GenericBinaryError>("linking section ended prematurely",
4980b57cec5SDimitry Andric                                           object_error::parse_failed);
4990b57cec5SDimitry Andric   return Error::success();
5000b57cec5SDimitry Andric }
5010b57cec5SDimitry Andric 
parseLinkingSectionSymtab(ReadContext & Ctx)5020b57cec5SDimitry Andric Error WasmObjectFile::parseLinkingSectionSymtab(ReadContext &Ctx) {
5030b57cec5SDimitry Andric   uint32_t Count = readVaruint32(Ctx);
5040b57cec5SDimitry Andric   LinkingData.SymbolTable.reserve(Count);
5050b57cec5SDimitry Andric   Symbols.reserve(Count);
5060b57cec5SDimitry Andric   StringSet<> SymbolNames;
5070b57cec5SDimitry Andric 
5080b57cec5SDimitry Andric   std::vector<wasm::WasmImport *> ImportedGlobals;
5090b57cec5SDimitry Andric   std::vector<wasm::WasmImport *> ImportedFunctions;
510*5f7ddb14SDimitry Andric   std::vector<wasm::WasmImport *> ImportedTags;
511af732203SDimitry Andric   std::vector<wasm::WasmImport *> ImportedTables;
5120b57cec5SDimitry Andric   ImportedGlobals.reserve(Imports.size());
5130b57cec5SDimitry Andric   ImportedFunctions.reserve(Imports.size());
514*5f7ddb14SDimitry Andric   ImportedTags.reserve(Imports.size());
515af732203SDimitry Andric   ImportedTables.reserve(Imports.size());
5160b57cec5SDimitry Andric   for (auto &I : Imports) {
5170b57cec5SDimitry Andric     if (I.Kind == wasm::WASM_EXTERNAL_FUNCTION)
5180b57cec5SDimitry Andric       ImportedFunctions.emplace_back(&I);
5190b57cec5SDimitry Andric     else if (I.Kind == wasm::WASM_EXTERNAL_GLOBAL)
5200b57cec5SDimitry Andric       ImportedGlobals.emplace_back(&I);
521*5f7ddb14SDimitry Andric     else if (I.Kind == wasm::WASM_EXTERNAL_TAG)
522*5f7ddb14SDimitry Andric       ImportedTags.emplace_back(&I);
523af732203SDimitry Andric     else if (I.Kind == wasm::WASM_EXTERNAL_TABLE)
524af732203SDimitry Andric       ImportedTables.emplace_back(&I);
5250b57cec5SDimitry Andric   }
5260b57cec5SDimitry Andric 
5270b57cec5SDimitry Andric   while (Count--) {
5280b57cec5SDimitry Andric     wasm::WasmSymbolInfo Info;
5290b57cec5SDimitry Andric     const wasm::WasmSignature *Signature = nullptr;
5300b57cec5SDimitry Andric     const wasm::WasmGlobalType *GlobalType = nullptr;
531af732203SDimitry Andric     const wasm::WasmTableType *TableType = nullptr;
532*5f7ddb14SDimitry Andric     const wasm::WasmTagType *TagType = nullptr;
5330b57cec5SDimitry Andric 
5340b57cec5SDimitry Andric     Info.Kind = readUint8(Ctx);
5350b57cec5SDimitry Andric     Info.Flags = readVaruint32(Ctx);
5360b57cec5SDimitry Andric     bool IsDefined = (Info.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0;
5370b57cec5SDimitry Andric 
5380b57cec5SDimitry Andric     switch (Info.Kind) {
5390b57cec5SDimitry Andric     case wasm::WASM_SYMBOL_TYPE_FUNCTION:
5400b57cec5SDimitry Andric       Info.ElementIndex = readVaruint32(Ctx);
5410b57cec5SDimitry Andric       if (!isValidFunctionIndex(Info.ElementIndex) ||
5420b57cec5SDimitry Andric           IsDefined != isDefinedFunctionIndex(Info.ElementIndex))
5430b57cec5SDimitry Andric         return make_error<GenericBinaryError>("invalid function symbol index",
5440b57cec5SDimitry Andric                                               object_error::parse_failed);
5450b57cec5SDimitry Andric       if (IsDefined) {
5460b57cec5SDimitry Andric         Info.Name = readString(Ctx);
5470b57cec5SDimitry Andric         unsigned FuncIndex = Info.ElementIndex - NumImportedFunctions;
5480b57cec5SDimitry Andric         Signature = &Signatures[FunctionTypes[FuncIndex]];
5490b57cec5SDimitry Andric         wasm::WasmFunction &Function = Functions[FuncIndex];
5500b57cec5SDimitry Andric         if (Function.SymbolName.empty())
5510b57cec5SDimitry Andric           Function.SymbolName = Info.Name;
5520b57cec5SDimitry Andric       } else {
5530b57cec5SDimitry Andric         wasm::WasmImport &Import = *ImportedFunctions[Info.ElementIndex];
5545ffd83dbSDimitry Andric         if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0) {
5550b57cec5SDimitry Andric           Info.Name = readString(Ctx);
5560b57cec5SDimitry Andric           Info.ImportName = Import.Field;
5575ffd83dbSDimitry Andric         } else {
5585ffd83dbSDimitry Andric           Info.Name = Import.Field;
5595ffd83dbSDimitry Andric         }
5605ffd83dbSDimitry Andric         Signature = &Signatures[Import.SigIndex];
5615ffd83dbSDimitry Andric         if (!Import.Module.empty()) {
5620b57cec5SDimitry Andric           Info.ImportModule = Import.Module;
5630b57cec5SDimitry Andric         }
5645ffd83dbSDimitry Andric       }
5650b57cec5SDimitry Andric       break;
5660b57cec5SDimitry Andric 
5670b57cec5SDimitry Andric     case wasm::WASM_SYMBOL_TYPE_GLOBAL:
5680b57cec5SDimitry Andric       Info.ElementIndex = readVaruint32(Ctx);
5690b57cec5SDimitry Andric       if (!isValidGlobalIndex(Info.ElementIndex) ||
5700b57cec5SDimitry Andric           IsDefined != isDefinedGlobalIndex(Info.ElementIndex))
5710b57cec5SDimitry Andric         return make_error<GenericBinaryError>("invalid global symbol index",
5720b57cec5SDimitry Andric                                               object_error::parse_failed);
5730b57cec5SDimitry Andric       if (!IsDefined && (Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) ==
5740b57cec5SDimitry Andric                             wasm::WASM_SYMBOL_BINDING_WEAK)
5750b57cec5SDimitry Andric         return make_error<GenericBinaryError>("undefined weak global symbol",
5760b57cec5SDimitry Andric                                               object_error::parse_failed);
5770b57cec5SDimitry Andric       if (IsDefined) {
5780b57cec5SDimitry Andric         Info.Name = readString(Ctx);
5790b57cec5SDimitry Andric         unsigned GlobalIndex = Info.ElementIndex - NumImportedGlobals;
5800b57cec5SDimitry Andric         wasm::WasmGlobal &Global = Globals[GlobalIndex];
5810b57cec5SDimitry Andric         GlobalType = &Global.Type;
5820b57cec5SDimitry Andric         if (Global.SymbolName.empty())
5830b57cec5SDimitry Andric           Global.SymbolName = Info.Name;
5840b57cec5SDimitry Andric       } else {
5850b57cec5SDimitry Andric         wasm::WasmImport &Import = *ImportedGlobals[Info.ElementIndex];
5865ffd83dbSDimitry Andric         if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0) {
5870b57cec5SDimitry Andric           Info.Name = readString(Ctx);
5885ffd83dbSDimitry Andric           Info.ImportName = Import.Field;
5895ffd83dbSDimitry Andric         } else {
5900b57cec5SDimitry Andric           Info.Name = Import.Field;
5915ffd83dbSDimitry Andric         }
5920b57cec5SDimitry Andric         GlobalType = &Import.Global;
593af732203SDimitry Andric         if (!Import.Module.empty()) {
594af732203SDimitry Andric           Info.ImportModule = Import.Module;
595af732203SDimitry Andric         }
596af732203SDimitry Andric       }
597af732203SDimitry Andric       break;
598af732203SDimitry Andric 
599af732203SDimitry Andric     case wasm::WASM_SYMBOL_TYPE_TABLE:
600af732203SDimitry Andric       Info.ElementIndex = readVaruint32(Ctx);
601*5f7ddb14SDimitry Andric       if (!isValidTableNumber(Info.ElementIndex) ||
602*5f7ddb14SDimitry Andric           IsDefined != isDefinedTableNumber(Info.ElementIndex))
603af732203SDimitry Andric         return make_error<GenericBinaryError>("invalid table symbol index",
604af732203SDimitry Andric                                               object_error::parse_failed);
605af732203SDimitry Andric       if (!IsDefined && (Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) ==
606af732203SDimitry Andric                             wasm::WASM_SYMBOL_BINDING_WEAK)
607af732203SDimitry Andric         return make_error<GenericBinaryError>("undefined weak table symbol",
608af732203SDimitry Andric                                               object_error::parse_failed);
609af732203SDimitry Andric       if (IsDefined) {
610af732203SDimitry Andric         Info.Name = readString(Ctx);
611*5f7ddb14SDimitry Andric         unsigned TableNumber = Info.ElementIndex - NumImportedTables;
612*5f7ddb14SDimitry Andric         wasm::WasmTable &Table = Tables[TableNumber];
613af732203SDimitry Andric         TableType = &Table.Type;
614af732203SDimitry Andric         if (Table.SymbolName.empty())
615af732203SDimitry Andric           Table.SymbolName = Info.Name;
616af732203SDimitry Andric       } else {
617af732203SDimitry Andric         wasm::WasmImport &Import = *ImportedTables[Info.ElementIndex];
618af732203SDimitry Andric         if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0) {
619af732203SDimitry Andric           Info.Name = readString(Ctx);
6200b57cec5SDimitry Andric           Info.ImportName = Import.Field;
621af732203SDimitry Andric         } else {
622af732203SDimitry Andric           Info.Name = Import.Field;
623af732203SDimitry Andric         }
624af732203SDimitry Andric         TableType = &Import.Table;
6255ffd83dbSDimitry Andric         if (!Import.Module.empty()) {
6260b57cec5SDimitry Andric           Info.ImportModule = Import.Module;
6270b57cec5SDimitry Andric         }
6285ffd83dbSDimitry Andric       }
6290b57cec5SDimitry Andric       break;
6300b57cec5SDimitry Andric 
6310b57cec5SDimitry Andric     case wasm::WASM_SYMBOL_TYPE_DATA:
6320b57cec5SDimitry Andric       Info.Name = readString(Ctx);
6330b57cec5SDimitry Andric       if (IsDefined) {
6345ffd83dbSDimitry Andric         auto Index = readVaruint32(Ctx);
6350b57cec5SDimitry Andric         if (Index >= DataSegments.size())
6360b57cec5SDimitry Andric           return make_error<GenericBinaryError>("invalid data symbol index",
6370b57cec5SDimitry Andric                                                 object_error::parse_failed);
6385ffd83dbSDimitry Andric         auto Offset = readVaruint64(Ctx);
6395ffd83dbSDimitry Andric         auto Size = readVaruint64(Ctx);
640*5f7ddb14SDimitry Andric         size_t SegmentSize = DataSegments[Index].Data.Content.size();
641*5f7ddb14SDimitry Andric         if (Offset > SegmentSize)
642*5f7ddb14SDimitry Andric           return make_error<GenericBinaryError>(
643*5f7ddb14SDimitry Andric               "invalid data symbol offset: `" + Info.Name + "` (offset: " +
644*5f7ddb14SDimitry Andric                   Twine(Offset) + " segment size: " + Twine(SegmentSize) + ")",
6450b57cec5SDimitry Andric               object_error::parse_failed);
6460b57cec5SDimitry Andric         Info.DataRef = wasm::WasmDataReference{Index, Offset, Size};
6470b57cec5SDimitry Andric       }
6480b57cec5SDimitry Andric       break;
6490b57cec5SDimitry Andric 
6500b57cec5SDimitry Andric     case wasm::WASM_SYMBOL_TYPE_SECTION: {
6510b57cec5SDimitry Andric       if ((Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) !=
6520b57cec5SDimitry Andric           wasm::WASM_SYMBOL_BINDING_LOCAL)
6530b57cec5SDimitry Andric         return make_error<GenericBinaryError>(
654af732203SDimitry Andric             "section symbols must have local binding",
6550b57cec5SDimitry Andric             object_error::parse_failed);
6560b57cec5SDimitry Andric       Info.ElementIndex = readVaruint32(Ctx);
6570b57cec5SDimitry Andric       // Use somewhat unique section name as symbol name.
6580b57cec5SDimitry Andric       StringRef SectionName = Sections[Info.ElementIndex].Name;
6590b57cec5SDimitry Andric       Info.Name = SectionName;
6600b57cec5SDimitry Andric       break;
6610b57cec5SDimitry Andric     }
6620b57cec5SDimitry Andric 
663*5f7ddb14SDimitry Andric     case wasm::WASM_SYMBOL_TYPE_TAG: {
6640b57cec5SDimitry Andric       Info.ElementIndex = readVaruint32(Ctx);
665*5f7ddb14SDimitry Andric       if (!isValidTagIndex(Info.ElementIndex) ||
666*5f7ddb14SDimitry Andric           IsDefined != isDefinedTagIndex(Info.ElementIndex))
667*5f7ddb14SDimitry Andric         return make_error<GenericBinaryError>("invalid tag symbol index",
6680b57cec5SDimitry Andric                                               object_error::parse_failed);
6690b57cec5SDimitry Andric       if (!IsDefined && (Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) ==
6700b57cec5SDimitry Andric                             wasm::WASM_SYMBOL_BINDING_WEAK)
6710b57cec5SDimitry Andric         return make_error<GenericBinaryError>("undefined weak global symbol",
6720b57cec5SDimitry Andric                                               object_error::parse_failed);
6730b57cec5SDimitry Andric       if (IsDefined) {
6740b57cec5SDimitry Andric         Info.Name = readString(Ctx);
675*5f7ddb14SDimitry Andric         unsigned TagIndex = Info.ElementIndex - NumImportedTags;
676*5f7ddb14SDimitry Andric         wasm::WasmTag &Tag = Tags[TagIndex];
677*5f7ddb14SDimitry Andric         Signature = &Signatures[Tag.Type.SigIndex];
678*5f7ddb14SDimitry Andric         TagType = &Tag.Type;
679*5f7ddb14SDimitry Andric         if (Tag.SymbolName.empty())
680*5f7ddb14SDimitry Andric           Tag.SymbolName = Info.Name;
6810b57cec5SDimitry Andric 
6820b57cec5SDimitry Andric       } else {
683*5f7ddb14SDimitry Andric         wasm::WasmImport &Import = *ImportedTags[Info.ElementIndex];
6845ffd83dbSDimitry Andric         if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0) {
6850b57cec5SDimitry Andric           Info.Name = readString(Ctx);
6865ffd83dbSDimitry Andric           Info.ImportName = Import.Field;
6875ffd83dbSDimitry Andric         } else {
6880b57cec5SDimitry Andric           Info.Name = Import.Field;
6895ffd83dbSDimitry Andric         }
690*5f7ddb14SDimitry Andric         TagType = &Import.Tag;
691*5f7ddb14SDimitry Andric         Signature = &Signatures[TagType->SigIndex];
6925ffd83dbSDimitry Andric         if (!Import.Module.empty()) {
6930b57cec5SDimitry Andric           Info.ImportModule = Import.Module;
6940b57cec5SDimitry Andric         }
6955ffd83dbSDimitry Andric       }
6960b57cec5SDimitry Andric       break;
6970b57cec5SDimitry Andric     }
6980b57cec5SDimitry Andric 
6990b57cec5SDimitry Andric     default:
700af732203SDimitry Andric       return make_error<GenericBinaryError>("invalid symbol type: " +
701af732203SDimitry Andric                                                 Twine(unsigned(Info.Kind)),
7020b57cec5SDimitry Andric                                             object_error::parse_failed);
7030b57cec5SDimitry Andric     }
7040b57cec5SDimitry Andric 
7050b57cec5SDimitry Andric     if ((Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) !=
7060b57cec5SDimitry Andric             wasm::WASM_SYMBOL_BINDING_LOCAL &&
7070b57cec5SDimitry Andric         !SymbolNames.insert(Info.Name).second)
708af732203SDimitry Andric       return make_error<GenericBinaryError>("duplicate symbol name " +
7090b57cec5SDimitry Andric                                                 Twine(Info.Name),
7100b57cec5SDimitry Andric                                             object_error::parse_failed);
7110b57cec5SDimitry Andric     LinkingData.SymbolTable.emplace_back(Info);
712af732203SDimitry Andric     Symbols.emplace_back(LinkingData.SymbolTable.back(), GlobalType, TableType,
713*5f7ddb14SDimitry Andric                          TagType, Signature);
7140b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "Adding symbol: " << Symbols.back() << "\n");
7150b57cec5SDimitry Andric   }
7160b57cec5SDimitry Andric 
7170b57cec5SDimitry Andric   return Error::success();
7180b57cec5SDimitry Andric }
7190b57cec5SDimitry Andric 
parseLinkingSectionComdat(ReadContext & Ctx)7200b57cec5SDimitry Andric Error WasmObjectFile::parseLinkingSectionComdat(ReadContext &Ctx) {
7210b57cec5SDimitry Andric   uint32_t ComdatCount = readVaruint32(Ctx);
7220b57cec5SDimitry Andric   StringSet<> ComdatSet;
7230b57cec5SDimitry Andric   for (unsigned ComdatIndex = 0; ComdatIndex < ComdatCount; ++ComdatIndex) {
7240b57cec5SDimitry Andric     StringRef Name = readString(Ctx);
7250b57cec5SDimitry Andric     if (Name.empty() || !ComdatSet.insert(Name).second)
726af732203SDimitry Andric       return make_error<GenericBinaryError>("bad/duplicate COMDAT name " +
7270b57cec5SDimitry Andric                                                 Twine(Name),
7280b57cec5SDimitry Andric                                             object_error::parse_failed);
7290b57cec5SDimitry Andric     LinkingData.Comdats.emplace_back(Name);
7300b57cec5SDimitry Andric     uint32_t Flags = readVaruint32(Ctx);
7310b57cec5SDimitry Andric     if (Flags != 0)
732af732203SDimitry Andric       return make_error<GenericBinaryError>("unsupported COMDAT flags",
7330b57cec5SDimitry Andric                                             object_error::parse_failed);
7340b57cec5SDimitry Andric 
7350b57cec5SDimitry Andric     uint32_t EntryCount = readVaruint32(Ctx);
7360b57cec5SDimitry Andric     while (EntryCount--) {
7370b57cec5SDimitry Andric       unsigned Kind = readVaruint32(Ctx);
7380b57cec5SDimitry Andric       unsigned Index = readVaruint32(Ctx);
7390b57cec5SDimitry Andric       switch (Kind) {
7400b57cec5SDimitry Andric       default:
741af732203SDimitry Andric         return make_error<GenericBinaryError>("invalid COMDAT entry type",
7420b57cec5SDimitry Andric                                               object_error::parse_failed);
7430b57cec5SDimitry Andric       case wasm::WASM_COMDAT_DATA:
7440b57cec5SDimitry Andric         if (Index >= DataSegments.size())
7450b57cec5SDimitry Andric           return make_error<GenericBinaryError>(
7460b57cec5SDimitry Andric               "COMDAT data index out of range", object_error::parse_failed);
7470b57cec5SDimitry Andric         if (DataSegments[Index].Data.Comdat != UINT32_MAX)
748af732203SDimitry Andric           return make_error<GenericBinaryError>("data segment in two COMDATs",
7490b57cec5SDimitry Andric                                                 object_error::parse_failed);
7500b57cec5SDimitry Andric         DataSegments[Index].Data.Comdat = ComdatIndex;
7510b57cec5SDimitry Andric         break;
7520b57cec5SDimitry Andric       case wasm::WASM_COMDAT_FUNCTION:
7530b57cec5SDimitry Andric         if (!isDefinedFunctionIndex(Index))
7540b57cec5SDimitry Andric           return make_error<GenericBinaryError>(
7550b57cec5SDimitry Andric               "COMDAT function index out of range", object_error::parse_failed);
7560b57cec5SDimitry Andric         if (getDefinedFunction(Index).Comdat != UINT32_MAX)
757af732203SDimitry Andric           return make_error<GenericBinaryError>("function in two COMDATs",
7580b57cec5SDimitry Andric                                                 object_error::parse_failed);
7590b57cec5SDimitry Andric         getDefinedFunction(Index).Comdat = ComdatIndex;
7600b57cec5SDimitry Andric         break;
761af732203SDimitry Andric       case wasm::WASM_COMDAT_SECTION:
762af732203SDimitry Andric         if (Index >= Sections.size())
763af732203SDimitry Andric           return make_error<GenericBinaryError>(
764af732203SDimitry Andric               "COMDAT section index out of range", object_error::parse_failed);
765af732203SDimitry Andric         if (Sections[Index].Type != wasm::WASM_SEC_CUSTOM)
766af732203SDimitry Andric           return make_error<GenericBinaryError>(
767af732203SDimitry Andric               "non-custom section in a COMDAT", object_error::parse_failed);
768af732203SDimitry Andric         Sections[Index].Comdat = ComdatIndex;
769af732203SDimitry Andric         break;
7700b57cec5SDimitry Andric       }
7710b57cec5SDimitry Andric     }
7720b57cec5SDimitry Andric   }
7730b57cec5SDimitry Andric   return Error::success();
7740b57cec5SDimitry Andric }
7750b57cec5SDimitry Andric 
parseProducersSection(ReadContext & Ctx)7760b57cec5SDimitry Andric Error WasmObjectFile::parseProducersSection(ReadContext &Ctx) {
7770b57cec5SDimitry Andric   llvm::SmallSet<StringRef, 3> FieldsSeen;
7780b57cec5SDimitry Andric   uint32_t Fields = readVaruint32(Ctx);
7790b57cec5SDimitry Andric   for (size_t I = 0; I < Fields; ++I) {
7800b57cec5SDimitry Andric     StringRef FieldName = readString(Ctx);
7810b57cec5SDimitry Andric     if (!FieldsSeen.insert(FieldName).second)
7820b57cec5SDimitry Andric       return make_error<GenericBinaryError>(
783af732203SDimitry Andric           "producers section does not have unique fields",
7840b57cec5SDimitry Andric           object_error::parse_failed);
7850b57cec5SDimitry Andric     std::vector<std::pair<std::string, std::string>> *ProducerVec = nullptr;
7860b57cec5SDimitry Andric     if (FieldName == "language") {
7870b57cec5SDimitry Andric       ProducerVec = &ProducerInfo.Languages;
7880b57cec5SDimitry Andric     } else if (FieldName == "processed-by") {
7890b57cec5SDimitry Andric       ProducerVec = &ProducerInfo.Tools;
7900b57cec5SDimitry Andric     } else if (FieldName == "sdk") {
7910b57cec5SDimitry Andric       ProducerVec = &ProducerInfo.SDKs;
7920b57cec5SDimitry Andric     } else {
7930b57cec5SDimitry Andric       return make_error<GenericBinaryError>(
794af732203SDimitry Andric           "producers section field is not named one of language, processed-by, "
7950b57cec5SDimitry Andric           "or sdk",
7960b57cec5SDimitry Andric           object_error::parse_failed);
7970b57cec5SDimitry Andric     }
7980b57cec5SDimitry Andric     uint32_t ValueCount = readVaruint32(Ctx);
7990b57cec5SDimitry Andric     llvm::SmallSet<StringRef, 8> ProducersSeen;
8000b57cec5SDimitry Andric     for (size_t J = 0; J < ValueCount; ++J) {
8010b57cec5SDimitry Andric       StringRef Name = readString(Ctx);
8020b57cec5SDimitry Andric       StringRef Version = readString(Ctx);
8030b57cec5SDimitry Andric       if (!ProducersSeen.insert(Name).second) {
8040b57cec5SDimitry Andric         return make_error<GenericBinaryError>(
805af732203SDimitry Andric             "producers section contains repeated producer",
8060b57cec5SDimitry Andric             object_error::parse_failed);
8070b57cec5SDimitry Andric       }
8085ffd83dbSDimitry Andric       ProducerVec->emplace_back(std::string(Name), std::string(Version));
8090b57cec5SDimitry Andric     }
8100b57cec5SDimitry Andric   }
8110b57cec5SDimitry Andric   if (Ctx.Ptr != Ctx.End)
812af732203SDimitry Andric     return make_error<GenericBinaryError>("producers section ended prematurely",
8130b57cec5SDimitry Andric                                           object_error::parse_failed);
8140b57cec5SDimitry Andric   return Error::success();
8150b57cec5SDimitry Andric }
8160b57cec5SDimitry Andric 
parseTargetFeaturesSection(ReadContext & Ctx)8170b57cec5SDimitry Andric Error WasmObjectFile::parseTargetFeaturesSection(ReadContext &Ctx) {
8180b57cec5SDimitry Andric   llvm::SmallSet<std::string, 8> FeaturesSeen;
8190b57cec5SDimitry Andric   uint32_t FeatureCount = readVaruint32(Ctx);
8200b57cec5SDimitry Andric   for (size_t I = 0; I < FeatureCount; ++I) {
8210b57cec5SDimitry Andric     wasm::WasmFeatureEntry Feature;
8220b57cec5SDimitry Andric     Feature.Prefix = readUint8(Ctx);
8230b57cec5SDimitry Andric     switch (Feature.Prefix) {
8240b57cec5SDimitry Andric     case wasm::WASM_FEATURE_PREFIX_USED:
8250b57cec5SDimitry Andric     case wasm::WASM_FEATURE_PREFIX_REQUIRED:
8260b57cec5SDimitry Andric     case wasm::WASM_FEATURE_PREFIX_DISALLOWED:
8270b57cec5SDimitry Andric       break;
8280b57cec5SDimitry Andric     default:
829af732203SDimitry Andric       return make_error<GenericBinaryError>("unknown feature policy prefix",
8300b57cec5SDimitry Andric                                             object_error::parse_failed);
8310b57cec5SDimitry Andric     }
8325ffd83dbSDimitry Andric     Feature.Name = std::string(readString(Ctx));
8330b57cec5SDimitry Andric     if (!FeaturesSeen.insert(Feature.Name).second)
8340b57cec5SDimitry Andric       return make_error<GenericBinaryError>(
835af732203SDimitry Andric           "target features section contains repeated feature \"" +
8360b57cec5SDimitry Andric               Feature.Name + "\"",
8370b57cec5SDimitry Andric           object_error::parse_failed);
8380b57cec5SDimitry Andric     TargetFeatures.push_back(Feature);
8390b57cec5SDimitry Andric   }
8400b57cec5SDimitry Andric   if (Ctx.Ptr != Ctx.End)
8410b57cec5SDimitry Andric     return make_error<GenericBinaryError>(
842af732203SDimitry Andric         "target features section ended prematurely",
8430b57cec5SDimitry Andric         object_error::parse_failed);
8440b57cec5SDimitry Andric   return Error::success();
8450b57cec5SDimitry Andric }
8460b57cec5SDimitry Andric 
parseRelocSection(StringRef Name,ReadContext & Ctx)8470b57cec5SDimitry Andric Error WasmObjectFile::parseRelocSection(StringRef Name, ReadContext &Ctx) {
8480b57cec5SDimitry Andric   uint32_t SectionIndex = readVaruint32(Ctx);
8490b57cec5SDimitry Andric   if (SectionIndex >= Sections.size())
850af732203SDimitry Andric     return make_error<GenericBinaryError>("invalid section index",
8510b57cec5SDimitry Andric                                           object_error::parse_failed);
8520b57cec5SDimitry Andric   WasmSection &Section = Sections[SectionIndex];
8530b57cec5SDimitry Andric   uint32_t RelocCount = readVaruint32(Ctx);
8540b57cec5SDimitry Andric   uint32_t EndOffset = Section.Content.size();
8550b57cec5SDimitry Andric   uint32_t PreviousOffset = 0;
8560b57cec5SDimitry Andric   while (RelocCount--) {
8570b57cec5SDimitry Andric     wasm::WasmRelocation Reloc = {};
858af732203SDimitry Andric     uint32_t type = readVaruint32(Ctx);
859af732203SDimitry Andric     Reloc.Type = type;
8600b57cec5SDimitry Andric     Reloc.Offset = readVaruint32(Ctx);
8610b57cec5SDimitry Andric     if (Reloc.Offset < PreviousOffset)
862af732203SDimitry Andric       return make_error<GenericBinaryError>("relocations not in offset order",
8630b57cec5SDimitry Andric                                             object_error::parse_failed);
8640b57cec5SDimitry Andric     PreviousOffset = Reloc.Offset;
8650b57cec5SDimitry Andric     Reloc.Index = readVaruint32(Ctx);
866af732203SDimitry Andric     switch (type) {
8670b57cec5SDimitry Andric     case wasm::R_WASM_FUNCTION_INDEX_LEB:
8680b57cec5SDimitry Andric     case wasm::R_WASM_TABLE_INDEX_SLEB:
869af732203SDimitry Andric     case wasm::R_WASM_TABLE_INDEX_SLEB64:
8700b57cec5SDimitry Andric     case wasm::R_WASM_TABLE_INDEX_I32:
871af732203SDimitry Andric     case wasm::R_WASM_TABLE_INDEX_I64:
8720b57cec5SDimitry Andric     case wasm::R_WASM_TABLE_INDEX_REL_SLEB:
873*5f7ddb14SDimitry Andric     case wasm::R_WASM_TABLE_INDEX_REL_SLEB64:
8740b57cec5SDimitry Andric       if (!isValidFunctionSymbol(Reloc.Index))
875af732203SDimitry Andric         return make_error<GenericBinaryError>(
876af732203SDimitry Andric             "invalid relocation function index", object_error::parse_failed);
877af732203SDimitry Andric       break;
878af732203SDimitry Andric     case wasm::R_WASM_TABLE_NUMBER_LEB:
879af732203SDimitry Andric       if (!isValidTableSymbol(Reloc.Index))
880af732203SDimitry Andric         return make_error<GenericBinaryError>("invalid relocation table index",
8810b57cec5SDimitry Andric                                               object_error::parse_failed);
8820b57cec5SDimitry Andric       break;
8830b57cec5SDimitry Andric     case wasm::R_WASM_TYPE_INDEX_LEB:
8840b57cec5SDimitry Andric       if (Reloc.Index >= Signatures.size())
885af732203SDimitry Andric         return make_error<GenericBinaryError>("invalid relocation type index",
8860b57cec5SDimitry Andric                                               object_error::parse_failed);
8870b57cec5SDimitry Andric       break;
8880b57cec5SDimitry Andric     case wasm::R_WASM_GLOBAL_INDEX_LEB:
8890b57cec5SDimitry Andric       // R_WASM_GLOBAL_INDEX_LEB are can be used against function and data
8908bcb0991SDimitry Andric       // symbols to refer to their GOT entries.
8910b57cec5SDimitry Andric       if (!isValidGlobalSymbol(Reloc.Index) &&
8920b57cec5SDimitry Andric           !isValidDataSymbol(Reloc.Index) &&
8930b57cec5SDimitry Andric           !isValidFunctionSymbol(Reloc.Index))
894af732203SDimitry Andric         return make_error<GenericBinaryError>("invalid relocation global index",
8950b57cec5SDimitry Andric                                               object_error::parse_failed);
8960b57cec5SDimitry Andric       break;
8975ffd83dbSDimitry Andric     case wasm::R_WASM_GLOBAL_INDEX_I32:
8985ffd83dbSDimitry Andric       if (!isValidGlobalSymbol(Reloc.Index))
899af732203SDimitry Andric         return make_error<GenericBinaryError>("invalid relocation global index",
9005ffd83dbSDimitry Andric                                               object_error::parse_failed);
9015ffd83dbSDimitry Andric       break;
902*5f7ddb14SDimitry Andric     case wasm::R_WASM_TAG_INDEX_LEB:
903*5f7ddb14SDimitry Andric       if (!isValidTagSymbol(Reloc.Index))
904*5f7ddb14SDimitry Andric         return make_error<GenericBinaryError>("invalid relocation tag index",
9050b57cec5SDimitry Andric                                               object_error::parse_failed);
9060b57cec5SDimitry Andric       break;
9070b57cec5SDimitry Andric     case wasm::R_WASM_MEMORY_ADDR_LEB:
9080b57cec5SDimitry Andric     case wasm::R_WASM_MEMORY_ADDR_SLEB:
9090b57cec5SDimitry Andric     case wasm::R_WASM_MEMORY_ADDR_I32:
9100b57cec5SDimitry Andric     case wasm::R_WASM_MEMORY_ADDR_REL_SLEB:
911af732203SDimitry Andric     case wasm::R_WASM_MEMORY_ADDR_TLS_SLEB:
912*5f7ddb14SDimitry Andric     case wasm::R_WASM_MEMORY_ADDR_LOCREL_I32:
9130b57cec5SDimitry Andric       if (!isValidDataSymbol(Reloc.Index))
914af732203SDimitry Andric         return make_error<GenericBinaryError>("invalid relocation data index",
9150b57cec5SDimitry Andric                                               object_error::parse_failed);
9160b57cec5SDimitry Andric       Reloc.Addend = readVarint32(Ctx);
9170b57cec5SDimitry Andric       break;
9185ffd83dbSDimitry Andric     case wasm::R_WASM_MEMORY_ADDR_LEB64:
9195ffd83dbSDimitry Andric     case wasm::R_WASM_MEMORY_ADDR_SLEB64:
9205ffd83dbSDimitry Andric     case wasm::R_WASM_MEMORY_ADDR_I64:
9215ffd83dbSDimitry Andric     case wasm::R_WASM_MEMORY_ADDR_REL_SLEB64:
922*5f7ddb14SDimitry Andric     case wasm::R_WASM_MEMORY_ADDR_TLS_SLEB64:
9235ffd83dbSDimitry Andric       if (!isValidDataSymbol(Reloc.Index))
924af732203SDimitry Andric         return make_error<GenericBinaryError>("invalid relocation data index",
9255ffd83dbSDimitry Andric                                               object_error::parse_failed);
9265ffd83dbSDimitry Andric       Reloc.Addend = readVarint64(Ctx);
9275ffd83dbSDimitry Andric       break;
9280b57cec5SDimitry Andric     case wasm::R_WASM_FUNCTION_OFFSET_I32:
9290b57cec5SDimitry Andric       if (!isValidFunctionSymbol(Reloc.Index))
930af732203SDimitry Andric         return make_error<GenericBinaryError>(
931af732203SDimitry Andric             "invalid relocation function index", object_error::parse_failed);
9320b57cec5SDimitry Andric       Reloc.Addend = readVarint32(Ctx);
9330b57cec5SDimitry Andric       break;
934af732203SDimitry Andric     case wasm::R_WASM_FUNCTION_OFFSET_I64:
935af732203SDimitry Andric       if (!isValidFunctionSymbol(Reloc.Index))
936af732203SDimitry Andric         return make_error<GenericBinaryError>(
937af732203SDimitry Andric             "invalid relocation function index", object_error::parse_failed);
938af732203SDimitry Andric       Reloc.Addend = readVarint64(Ctx);
939af732203SDimitry Andric       break;
9400b57cec5SDimitry Andric     case wasm::R_WASM_SECTION_OFFSET_I32:
9410b57cec5SDimitry Andric       if (!isValidSectionSymbol(Reloc.Index))
942af732203SDimitry Andric         return make_error<GenericBinaryError>(
943af732203SDimitry Andric             "invalid relocation section index", object_error::parse_failed);
9440b57cec5SDimitry Andric       Reloc.Addend = readVarint32(Ctx);
9450b57cec5SDimitry Andric       break;
9460b57cec5SDimitry Andric     default:
947af732203SDimitry Andric       return make_error<GenericBinaryError>("invalid relocation type: " +
948af732203SDimitry Andric                                                 Twine(type),
9490b57cec5SDimitry Andric                                             object_error::parse_failed);
9500b57cec5SDimitry Andric     }
9510b57cec5SDimitry Andric 
9520b57cec5SDimitry Andric     // Relocations must fit inside the section, and must appear in order.  They
9530b57cec5SDimitry Andric     // also shouldn't overlap a function/element boundary, but we don't bother
9540b57cec5SDimitry Andric     // to check that.
9550b57cec5SDimitry Andric     uint64_t Size = 5;
9565ffd83dbSDimitry Andric     if (Reloc.Type == wasm::R_WASM_MEMORY_ADDR_LEB64 ||
9575ffd83dbSDimitry Andric         Reloc.Type == wasm::R_WASM_MEMORY_ADDR_SLEB64 ||
9585ffd83dbSDimitry Andric         Reloc.Type == wasm::R_WASM_MEMORY_ADDR_REL_SLEB64)
9595ffd83dbSDimitry Andric       Size = 10;
9600b57cec5SDimitry Andric     if (Reloc.Type == wasm::R_WASM_TABLE_INDEX_I32 ||
9610b57cec5SDimitry Andric         Reloc.Type == wasm::R_WASM_MEMORY_ADDR_I32 ||
962*5f7ddb14SDimitry Andric         Reloc.Type == wasm::R_WASM_MEMORY_ADDR_LOCREL_I32 ||
9630b57cec5SDimitry Andric         Reloc.Type == wasm::R_WASM_SECTION_OFFSET_I32 ||
9645ffd83dbSDimitry Andric         Reloc.Type == wasm::R_WASM_FUNCTION_OFFSET_I32 ||
9655ffd83dbSDimitry Andric         Reloc.Type == wasm::R_WASM_GLOBAL_INDEX_I32)
9660b57cec5SDimitry Andric       Size = 4;
967af732203SDimitry Andric     if (Reloc.Type == wasm::R_WASM_TABLE_INDEX_I64 ||
968af732203SDimitry Andric         Reloc.Type == wasm::R_WASM_MEMORY_ADDR_I64 ||
969af732203SDimitry Andric         Reloc.Type == wasm::R_WASM_FUNCTION_OFFSET_I64)
9705ffd83dbSDimitry Andric       Size = 8;
9710b57cec5SDimitry Andric     if (Reloc.Offset + Size > EndOffset)
972af732203SDimitry Andric       return make_error<GenericBinaryError>("invalid relocation offset",
9730b57cec5SDimitry Andric                                             object_error::parse_failed);
9740b57cec5SDimitry Andric 
9750b57cec5SDimitry Andric     Section.Relocations.push_back(Reloc);
9760b57cec5SDimitry Andric   }
9770b57cec5SDimitry Andric   if (Ctx.Ptr != Ctx.End)
978af732203SDimitry Andric     return make_error<GenericBinaryError>("reloc section ended prematurely",
9790b57cec5SDimitry Andric                                           object_error::parse_failed);
9800b57cec5SDimitry Andric   return Error::success();
9810b57cec5SDimitry Andric }
9820b57cec5SDimitry Andric 
parseCustomSection(WasmSection & Sec,ReadContext & Ctx)9830b57cec5SDimitry Andric Error WasmObjectFile::parseCustomSection(WasmSection &Sec, ReadContext &Ctx) {
9840b57cec5SDimitry Andric   if (Sec.Name == "dylink") {
9850b57cec5SDimitry Andric     if (Error Err = parseDylinkSection(Ctx))
9860b57cec5SDimitry Andric       return Err;
9870b57cec5SDimitry Andric   } else if (Sec.Name == "name") {
9880b57cec5SDimitry Andric     if (Error Err = parseNameSection(Ctx))
9890b57cec5SDimitry Andric       return Err;
9900b57cec5SDimitry Andric   } else if (Sec.Name == "linking") {
9910b57cec5SDimitry Andric     if (Error Err = parseLinkingSection(Ctx))
9920b57cec5SDimitry Andric       return Err;
9930b57cec5SDimitry Andric   } else if (Sec.Name == "producers") {
9940b57cec5SDimitry Andric     if (Error Err = parseProducersSection(Ctx))
9950b57cec5SDimitry Andric       return Err;
9960b57cec5SDimitry Andric   } else if (Sec.Name == "target_features") {
9970b57cec5SDimitry Andric     if (Error Err = parseTargetFeaturesSection(Ctx))
9980b57cec5SDimitry Andric       return Err;
9990b57cec5SDimitry Andric   } else if (Sec.Name.startswith("reloc.")) {
10000b57cec5SDimitry Andric     if (Error Err = parseRelocSection(Sec.Name, Ctx))
10010b57cec5SDimitry Andric       return Err;
10020b57cec5SDimitry Andric   }
10030b57cec5SDimitry Andric   return Error::success();
10040b57cec5SDimitry Andric }
10050b57cec5SDimitry Andric 
parseTypeSection(ReadContext & Ctx)10060b57cec5SDimitry Andric Error WasmObjectFile::parseTypeSection(ReadContext &Ctx) {
10070b57cec5SDimitry Andric   uint32_t Count = readVaruint32(Ctx);
10080b57cec5SDimitry Andric   Signatures.reserve(Count);
10090b57cec5SDimitry Andric   while (Count--) {
10100b57cec5SDimitry Andric     wasm::WasmSignature Sig;
10110b57cec5SDimitry Andric     uint8_t Form = readUint8(Ctx);
10120b57cec5SDimitry Andric     if (Form != wasm::WASM_TYPE_FUNC) {
1013af732203SDimitry Andric       return make_error<GenericBinaryError>("invalid signature type",
10140b57cec5SDimitry Andric                                             object_error::parse_failed);
10150b57cec5SDimitry Andric     }
10160b57cec5SDimitry Andric     uint32_t ParamCount = readVaruint32(Ctx);
10170b57cec5SDimitry Andric     Sig.Params.reserve(ParamCount);
10180b57cec5SDimitry Andric     while (ParamCount--) {
10190b57cec5SDimitry Andric       uint32_t ParamType = readUint8(Ctx);
10200b57cec5SDimitry Andric       Sig.Params.push_back(wasm::ValType(ParamType));
10210b57cec5SDimitry Andric     }
10220b57cec5SDimitry Andric     uint32_t ReturnCount = readVaruint32(Ctx);
10238bcb0991SDimitry Andric     while (ReturnCount--) {
10248bcb0991SDimitry Andric       uint32_t ReturnType = readUint8(Ctx);
10258bcb0991SDimitry Andric       Sig.Returns.push_back(wasm::ValType(ReturnType));
10260b57cec5SDimitry Andric     }
10270b57cec5SDimitry Andric     Signatures.push_back(std::move(Sig));
10280b57cec5SDimitry Andric   }
10290b57cec5SDimitry Andric   if (Ctx.Ptr != Ctx.End)
1030af732203SDimitry Andric     return make_error<GenericBinaryError>("type section ended prematurely",
10310b57cec5SDimitry Andric                                           object_error::parse_failed);
10320b57cec5SDimitry Andric   return Error::success();
10330b57cec5SDimitry Andric }
10340b57cec5SDimitry Andric 
parseImportSection(ReadContext & Ctx)10350b57cec5SDimitry Andric Error WasmObjectFile::parseImportSection(ReadContext &Ctx) {
10360b57cec5SDimitry Andric   uint32_t Count = readVaruint32(Ctx);
10370b57cec5SDimitry Andric   Imports.reserve(Count);
10380b57cec5SDimitry Andric   for (uint32_t I = 0; I < Count; I++) {
10390b57cec5SDimitry Andric     wasm::WasmImport Im;
10400b57cec5SDimitry Andric     Im.Module = readString(Ctx);
10410b57cec5SDimitry Andric     Im.Field = readString(Ctx);
10420b57cec5SDimitry Andric     Im.Kind = readUint8(Ctx);
10430b57cec5SDimitry Andric     switch (Im.Kind) {
10440b57cec5SDimitry Andric     case wasm::WASM_EXTERNAL_FUNCTION:
10450b57cec5SDimitry Andric       NumImportedFunctions++;
10460b57cec5SDimitry Andric       Im.SigIndex = readVaruint32(Ctx);
10470b57cec5SDimitry Andric       break;
10480b57cec5SDimitry Andric     case wasm::WASM_EXTERNAL_GLOBAL:
10490b57cec5SDimitry Andric       NumImportedGlobals++;
10500b57cec5SDimitry Andric       Im.Global.Type = readUint8(Ctx);
10510b57cec5SDimitry Andric       Im.Global.Mutable = readVaruint1(Ctx);
10520b57cec5SDimitry Andric       break;
10530b57cec5SDimitry Andric     case wasm::WASM_EXTERNAL_MEMORY:
10540b57cec5SDimitry Andric       Im.Memory = readLimits(Ctx);
1055af732203SDimitry Andric       if (Im.Memory.Flags & wasm::WASM_LIMITS_FLAG_IS_64)
1056af732203SDimitry Andric         HasMemory64 = true;
10570b57cec5SDimitry Andric       break;
1058af732203SDimitry Andric     case wasm::WASM_EXTERNAL_TABLE: {
1059af732203SDimitry Andric       Im.Table = readTableType(Ctx);
1060af732203SDimitry Andric       NumImportedTables++;
1061af732203SDimitry Andric       auto ElemType = Im.Table.ElemType;
1062af732203SDimitry Andric       if (ElemType != wasm::WASM_TYPE_FUNCREF &&
1063af732203SDimitry Andric           ElemType != wasm::WASM_TYPE_EXTERNREF)
1064af732203SDimitry Andric         return make_error<GenericBinaryError>("invalid table element type",
10650b57cec5SDimitry Andric                                               object_error::parse_failed);
10660b57cec5SDimitry Andric       break;
1067af732203SDimitry Andric     }
1068*5f7ddb14SDimitry Andric     case wasm::WASM_EXTERNAL_TAG:
1069*5f7ddb14SDimitry Andric       NumImportedTags++;
1070*5f7ddb14SDimitry Andric       Im.Tag.Attribute = readUint8(Ctx);
1071*5f7ddb14SDimitry Andric       Im.Tag.SigIndex = readVarint32(Ctx);
10720b57cec5SDimitry Andric       break;
10730b57cec5SDimitry Andric     default:
1074af732203SDimitry Andric       return make_error<GenericBinaryError>("unexpected import kind",
10750b57cec5SDimitry Andric                                             object_error::parse_failed);
10760b57cec5SDimitry Andric     }
10770b57cec5SDimitry Andric     Imports.push_back(Im);
10780b57cec5SDimitry Andric   }
10790b57cec5SDimitry Andric   if (Ctx.Ptr != Ctx.End)
1080af732203SDimitry Andric     return make_error<GenericBinaryError>("import section ended prematurely",
10810b57cec5SDimitry Andric                                           object_error::parse_failed);
10820b57cec5SDimitry Andric   return Error::success();
10830b57cec5SDimitry Andric }
10840b57cec5SDimitry Andric 
parseFunctionSection(ReadContext & Ctx)10850b57cec5SDimitry Andric Error WasmObjectFile::parseFunctionSection(ReadContext &Ctx) {
10860b57cec5SDimitry Andric   uint32_t Count = readVaruint32(Ctx);
10870b57cec5SDimitry Andric   FunctionTypes.reserve(Count);
1088480093f4SDimitry Andric   Functions.resize(Count);
10890b57cec5SDimitry Andric   uint32_t NumTypes = Signatures.size();
10900b57cec5SDimitry Andric   while (Count--) {
10910b57cec5SDimitry Andric     uint32_t Type = readVaruint32(Ctx);
10920b57cec5SDimitry Andric     if (Type >= NumTypes)
1093af732203SDimitry Andric       return make_error<GenericBinaryError>("invalid function type",
10940b57cec5SDimitry Andric                                             object_error::parse_failed);
10950b57cec5SDimitry Andric     FunctionTypes.push_back(Type);
10960b57cec5SDimitry Andric   }
10970b57cec5SDimitry Andric   if (Ctx.Ptr != Ctx.End)
1098af732203SDimitry Andric     return make_error<GenericBinaryError>("function section ended prematurely",
10990b57cec5SDimitry Andric                                           object_error::parse_failed);
11000b57cec5SDimitry Andric   return Error::success();
11010b57cec5SDimitry Andric }
11020b57cec5SDimitry Andric 
parseTableSection(ReadContext & Ctx)11030b57cec5SDimitry Andric Error WasmObjectFile::parseTableSection(ReadContext &Ctx) {
1104af732203SDimitry Andric   TableSection = Sections.size();
11050b57cec5SDimitry Andric   uint32_t Count = readVaruint32(Ctx);
11060b57cec5SDimitry Andric   Tables.reserve(Count);
11070b57cec5SDimitry Andric   while (Count--) {
1108af732203SDimitry Andric     wasm::WasmTable T;
1109af732203SDimitry Andric     T.Type = readTableType(Ctx);
1110af732203SDimitry Andric     T.Index = NumImportedTables + Tables.size();
1111af732203SDimitry Andric     Tables.push_back(T);
1112af732203SDimitry Andric     auto ElemType = Tables.back().Type.ElemType;
1113af732203SDimitry Andric     if (ElemType != wasm::WASM_TYPE_FUNCREF &&
1114af732203SDimitry Andric         ElemType != wasm::WASM_TYPE_EXTERNREF) {
1115af732203SDimitry Andric       return make_error<GenericBinaryError>("invalid table element type",
11160b57cec5SDimitry Andric                                             object_error::parse_failed);
11170b57cec5SDimitry Andric     }
11180b57cec5SDimitry Andric   }
11190b57cec5SDimitry Andric   if (Ctx.Ptr != Ctx.End)
1120af732203SDimitry Andric     return make_error<GenericBinaryError>("table section ended prematurely",
11210b57cec5SDimitry Andric                                           object_error::parse_failed);
11220b57cec5SDimitry Andric   return Error::success();
11230b57cec5SDimitry Andric }
11240b57cec5SDimitry Andric 
parseMemorySection(ReadContext & Ctx)11250b57cec5SDimitry Andric Error WasmObjectFile::parseMemorySection(ReadContext &Ctx) {
11260b57cec5SDimitry Andric   uint32_t Count = readVaruint32(Ctx);
11270b57cec5SDimitry Andric   Memories.reserve(Count);
11280b57cec5SDimitry Andric   while (Count--) {
1129af732203SDimitry Andric     auto Limits = readLimits(Ctx);
1130af732203SDimitry Andric     if (Limits.Flags & wasm::WASM_LIMITS_FLAG_IS_64)
1131af732203SDimitry Andric       HasMemory64 = true;
1132af732203SDimitry Andric     Memories.push_back(Limits);
11330b57cec5SDimitry Andric   }
11340b57cec5SDimitry Andric   if (Ctx.Ptr != Ctx.End)
1135af732203SDimitry Andric     return make_error<GenericBinaryError>("memory section ended prematurely",
11360b57cec5SDimitry Andric                                           object_error::parse_failed);
11370b57cec5SDimitry Andric   return Error::success();
11380b57cec5SDimitry Andric }
11390b57cec5SDimitry Andric 
parseTagSection(ReadContext & Ctx)1140*5f7ddb14SDimitry Andric Error WasmObjectFile::parseTagSection(ReadContext &Ctx) {
1141*5f7ddb14SDimitry Andric   TagSection = Sections.size();
1142*5f7ddb14SDimitry Andric   uint32_t Count = readVaruint32(Ctx);
1143*5f7ddb14SDimitry Andric   Tags.reserve(Count);
11445ffd83dbSDimitry Andric   while (Count--) {
1145*5f7ddb14SDimitry Andric     wasm::WasmTag Tag;
1146*5f7ddb14SDimitry Andric     Tag.Index = NumImportedTags + Tags.size();
1147*5f7ddb14SDimitry Andric     Tag.Type.Attribute = readUint8(Ctx);
1148*5f7ddb14SDimitry Andric     Tag.Type.SigIndex = readVaruint32(Ctx);
1149*5f7ddb14SDimitry Andric     Tags.push_back(Tag);
11505ffd83dbSDimitry Andric   }
11515ffd83dbSDimitry Andric 
11525ffd83dbSDimitry Andric   if (Ctx.Ptr != Ctx.End)
1153*5f7ddb14SDimitry Andric     return make_error<GenericBinaryError>("tag section ended prematurely",
11545ffd83dbSDimitry Andric                                           object_error::parse_failed);
11555ffd83dbSDimitry Andric   return Error::success();
11565ffd83dbSDimitry Andric }
11575ffd83dbSDimitry Andric 
parseGlobalSection(ReadContext & Ctx)11580b57cec5SDimitry Andric Error WasmObjectFile::parseGlobalSection(ReadContext &Ctx) {
11590b57cec5SDimitry Andric   GlobalSection = Sections.size();
11600b57cec5SDimitry Andric   uint32_t Count = readVaruint32(Ctx);
11610b57cec5SDimitry Andric   Globals.reserve(Count);
11620b57cec5SDimitry Andric   while (Count--) {
11630b57cec5SDimitry Andric     wasm::WasmGlobal Global;
11640b57cec5SDimitry Andric     Global.Index = NumImportedGlobals + Globals.size();
11650b57cec5SDimitry Andric     Global.Type.Type = readUint8(Ctx);
11660b57cec5SDimitry Andric     Global.Type.Mutable = readVaruint1(Ctx);
11670b57cec5SDimitry Andric     if (Error Err = readInitExpr(Global.InitExpr, Ctx))
11680b57cec5SDimitry Andric       return Err;
11690b57cec5SDimitry Andric     Globals.push_back(Global);
11700b57cec5SDimitry Andric   }
11710b57cec5SDimitry Andric   if (Ctx.Ptr != Ctx.End)
1172af732203SDimitry Andric     return make_error<GenericBinaryError>("global section ended prematurely",
11730b57cec5SDimitry Andric                                           object_error::parse_failed);
11740b57cec5SDimitry Andric   return Error::success();
11750b57cec5SDimitry Andric }
11760b57cec5SDimitry Andric 
parseExportSection(ReadContext & Ctx)11770b57cec5SDimitry Andric Error WasmObjectFile::parseExportSection(ReadContext &Ctx) {
11780b57cec5SDimitry Andric   uint32_t Count = readVaruint32(Ctx);
11790b57cec5SDimitry Andric   Exports.reserve(Count);
11800b57cec5SDimitry Andric   for (uint32_t I = 0; I < Count; I++) {
11810b57cec5SDimitry Andric     wasm::WasmExport Ex;
11820b57cec5SDimitry Andric     Ex.Name = readString(Ctx);
11830b57cec5SDimitry Andric     Ex.Kind = readUint8(Ctx);
11840b57cec5SDimitry Andric     Ex.Index = readVaruint32(Ctx);
11850b57cec5SDimitry Andric     switch (Ex.Kind) {
11860b57cec5SDimitry Andric     case wasm::WASM_EXTERNAL_FUNCTION:
1187480093f4SDimitry Andric 
1188480093f4SDimitry Andric       if (!isDefinedFunctionIndex(Ex.Index))
1189af732203SDimitry Andric         return make_error<GenericBinaryError>("invalid function export",
11900b57cec5SDimitry Andric                                               object_error::parse_failed);
1191480093f4SDimitry Andric       getDefinedFunction(Ex.Index).ExportName = Ex.Name;
11920b57cec5SDimitry Andric       break;
11930b57cec5SDimitry Andric     case wasm::WASM_EXTERNAL_GLOBAL:
11940b57cec5SDimitry Andric       if (!isValidGlobalIndex(Ex.Index))
1195af732203SDimitry Andric         return make_error<GenericBinaryError>("invalid global export",
11960b57cec5SDimitry Andric                                               object_error::parse_failed);
11970b57cec5SDimitry Andric       break;
1198*5f7ddb14SDimitry Andric     case wasm::WASM_EXTERNAL_TAG:
1199*5f7ddb14SDimitry Andric       if (!isValidTagIndex(Ex.Index))
1200*5f7ddb14SDimitry Andric         return make_error<GenericBinaryError>("invalid tag export",
12010b57cec5SDimitry Andric                                               object_error::parse_failed);
12020b57cec5SDimitry Andric       break;
12030b57cec5SDimitry Andric     case wasm::WASM_EXTERNAL_MEMORY:
12040b57cec5SDimitry Andric     case wasm::WASM_EXTERNAL_TABLE:
12050b57cec5SDimitry Andric       break;
12060b57cec5SDimitry Andric     default:
1207af732203SDimitry Andric       return make_error<GenericBinaryError>("unexpected export kind",
12080b57cec5SDimitry Andric                                             object_error::parse_failed);
12090b57cec5SDimitry Andric     }
12100b57cec5SDimitry Andric     Exports.push_back(Ex);
12110b57cec5SDimitry Andric   }
12120b57cec5SDimitry Andric   if (Ctx.Ptr != Ctx.End)
1213af732203SDimitry Andric     return make_error<GenericBinaryError>("export section ended prematurely",
12140b57cec5SDimitry Andric                                           object_error::parse_failed);
12150b57cec5SDimitry Andric   return Error::success();
12160b57cec5SDimitry Andric }
12170b57cec5SDimitry Andric 
isValidFunctionIndex(uint32_t Index) const12180b57cec5SDimitry Andric bool WasmObjectFile::isValidFunctionIndex(uint32_t Index) const {
12190b57cec5SDimitry Andric   return Index < NumImportedFunctions + FunctionTypes.size();
12200b57cec5SDimitry Andric }
12210b57cec5SDimitry Andric 
isDefinedFunctionIndex(uint32_t Index) const12220b57cec5SDimitry Andric bool WasmObjectFile::isDefinedFunctionIndex(uint32_t Index) const {
12230b57cec5SDimitry Andric   return Index >= NumImportedFunctions && isValidFunctionIndex(Index);
12240b57cec5SDimitry Andric }
12250b57cec5SDimitry Andric 
isValidGlobalIndex(uint32_t Index) const12260b57cec5SDimitry Andric bool WasmObjectFile::isValidGlobalIndex(uint32_t Index) const {
12270b57cec5SDimitry Andric   return Index < NumImportedGlobals + Globals.size();
12280b57cec5SDimitry Andric }
12290b57cec5SDimitry Andric 
isValidTableNumber(uint32_t Index) const1230*5f7ddb14SDimitry Andric bool WasmObjectFile::isValidTableNumber(uint32_t Index) const {
1231af732203SDimitry Andric   return Index < NumImportedTables + Tables.size();
1232af732203SDimitry Andric }
1233af732203SDimitry Andric 
isDefinedGlobalIndex(uint32_t Index) const12340b57cec5SDimitry Andric bool WasmObjectFile::isDefinedGlobalIndex(uint32_t Index) const {
12350b57cec5SDimitry Andric   return Index >= NumImportedGlobals && isValidGlobalIndex(Index);
12360b57cec5SDimitry Andric }
12370b57cec5SDimitry Andric 
isDefinedTableNumber(uint32_t Index) const1238*5f7ddb14SDimitry Andric bool WasmObjectFile::isDefinedTableNumber(uint32_t Index) const {
1239*5f7ddb14SDimitry Andric   return Index >= NumImportedTables && isValidTableNumber(Index);
1240af732203SDimitry Andric }
1241af732203SDimitry Andric 
isValidTagIndex(uint32_t Index) const1242*5f7ddb14SDimitry Andric bool WasmObjectFile::isValidTagIndex(uint32_t Index) const {
1243*5f7ddb14SDimitry Andric   return Index < NumImportedTags + Tags.size();
12440b57cec5SDimitry Andric }
12450b57cec5SDimitry Andric 
isDefinedTagIndex(uint32_t Index) const1246*5f7ddb14SDimitry Andric bool WasmObjectFile::isDefinedTagIndex(uint32_t Index) const {
1247*5f7ddb14SDimitry Andric   return Index >= NumImportedTags && isValidTagIndex(Index);
12480b57cec5SDimitry Andric }
12490b57cec5SDimitry Andric 
isValidFunctionSymbol(uint32_t Index) const12500b57cec5SDimitry Andric bool WasmObjectFile::isValidFunctionSymbol(uint32_t Index) const {
12510b57cec5SDimitry Andric   return Index < Symbols.size() && Symbols[Index].isTypeFunction();
12520b57cec5SDimitry Andric }
12530b57cec5SDimitry Andric 
isValidTableSymbol(uint32_t Index) const1254af732203SDimitry Andric bool WasmObjectFile::isValidTableSymbol(uint32_t Index) const {
1255af732203SDimitry Andric   return Index < Symbols.size() && Symbols[Index].isTypeTable();
1256af732203SDimitry Andric }
1257af732203SDimitry Andric 
isValidGlobalSymbol(uint32_t Index) const12580b57cec5SDimitry Andric bool WasmObjectFile::isValidGlobalSymbol(uint32_t Index) const {
12590b57cec5SDimitry Andric   return Index < Symbols.size() && Symbols[Index].isTypeGlobal();
12600b57cec5SDimitry Andric }
12610b57cec5SDimitry Andric 
isValidTagSymbol(uint32_t Index) const1262*5f7ddb14SDimitry Andric bool WasmObjectFile::isValidTagSymbol(uint32_t Index) const {
1263*5f7ddb14SDimitry Andric   return Index < Symbols.size() && Symbols[Index].isTypeTag();
12640b57cec5SDimitry Andric }
12650b57cec5SDimitry Andric 
isValidDataSymbol(uint32_t Index) const12660b57cec5SDimitry Andric bool WasmObjectFile::isValidDataSymbol(uint32_t Index) const {
12670b57cec5SDimitry Andric   return Index < Symbols.size() && Symbols[Index].isTypeData();
12680b57cec5SDimitry Andric }
12690b57cec5SDimitry Andric 
isValidSectionSymbol(uint32_t Index) const12700b57cec5SDimitry Andric bool WasmObjectFile::isValidSectionSymbol(uint32_t Index) const {
12710b57cec5SDimitry Andric   return Index < Symbols.size() && Symbols[Index].isTypeSection();
12720b57cec5SDimitry Andric }
12730b57cec5SDimitry Andric 
getDefinedFunction(uint32_t Index)12740b57cec5SDimitry Andric wasm::WasmFunction &WasmObjectFile::getDefinedFunction(uint32_t Index) {
12750b57cec5SDimitry Andric   assert(isDefinedFunctionIndex(Index));
12760b57cec5SDimitry Andric   return Functions[Index - NumImportedFunctions];
12770b57cec5SDimitry Andric }
12780b57cec5SDimitry Andric 
12790b57cec5SDimitry Andric const wasm::WasmFunction &
getDefinedFunction(uint32_t Index) const12800b57cec5SDimitry Andric WasmObjectFile::getDefinedFunction(uint32_t Index) const {
12810b57cec5SDimitry Andric   assert(isDefinedFunctionIndex(Index));
12820b57cec5SDimitry Andric   return Functions[Index - NumImportedFunctions];
12830b57cec5SDimitry Andric }
12840b57cec5SDimitry Andric 
getDefinedGlobal(uint32_t Index)12850b57cec5SDimitry Andric wasm::WasmGlobal &WasmObjectFile::getDefinedGlobal(uint32_t Index) {
12860b57cec5SDimitry Andric   assert(isDefinedGlobalIndex(Index));
12870b57cec5SDimitry Andric   return Globals[Index - NumImportedGlobals];
12880b57cec5SDimitry Andric }
12890b57cec5SDimitry Andric 
getDefinedTag(uint32_t Index)1290*5f7ddb14SDimitry Andric wasm::WasmTag &WasmObjectFile::getDefinedTag(uint32_t Index) {
1291*5f7ddb14SDimitry Andric   assert(isDefinedTagIndex(Index));
1292*5f7ddb14SDimitry Andric   return Tags[Index - NumImportedTags];
12930b57cec5SDimitry Andric }
12940b57cec5SDimitry Andric 
parseStartSection(ReadContext & Ctx)12950b57cec5SDimitry Andric Error WasmObjectFile::parseStartSection(ReadContext &Ctx) {
12960b57cec5SDimitry Andric   StartFunction = readVaruint32(Ctx);
12970b57cec5SDimitry Andric   if (!isValidFunctionIndex(StartFunction))
1298af732203SDimitry Andric     return make_error<GenericBinaryError>("invalid start function",
12990b57cec5SDimitry Andric                                           object_error::parse_failed);
13000b57cec5SDimitry Andric   return Error::success();
13010b57cec5SDimitry Andric }
13020b57cec5SDimitry Andric 
parseCodeSection(ReadContext & Ctx)13030b57cec5SDimitry Andric Error WasmObjectFile::parseCodeSection(ReadContext &Ctx) {
1304480093f4SDimitry Andric   SeenCodeSection = true;
13050b57cec5SDimitry Andric   CodeSection = Sections.size();
13060b57cec5SDimitry Andric   uint32_t FunctionCount = readVaruint32(Ctx);
13070b57cec5SDimitry Andric   if (FunctionCount != FunctionTypes.size()) {
1308af732203SDimitry Andric     return make_error<GenericBinaryError>("invalid function count",
13090b57cec5SDimitry Andric                                           object_error::parse_failed);
13100b57cec5SDimitry Andric   }
13110b57cec5SDimitry Andric 
1312480093f4SDimitry Andric   for (uint32_t i = 0; i < FunctionCount; i++) {
1313480093f4SDimitry Andric     wasm::WasmFunction& Function = Functions[i];
13140b57cec5SDimitry Andric     const uint8_t *FunctionStart = Ctx.Ptr;
13150b57cec5SDimitry Andric     uint32_t Size = readVaruint32(Ctx);
13160b57cec5SDimitry Andric     const uint8_t *FunctionEnd = Ctx.Ptr + Size;
13170b57cec5SDimitry Andric 
13180b57cec5SDimitry Andric     Function.CodeOffset = Ctx.Ptr - FunctionStart;
1319480093f4SDimitry Andric     Function.Index = NumImportedFunctions + i;
13200b57cec5SDimitry Andric     Function.CodeSectionOffset = FunctionStart - Ctx.Start;
13210b57cec5SDimitry Andric     Function.Size = FunctionEnd - FunctionStart;
13220b57cec5SDimitry Andric 
13230b57cec5SDimitry Andric     uint32_t NumLocalDecls = readVaruint32(Ctx);
13240b57cec5SDimitry Andric     Function.Locals.reserve(NumLocalDecls);
13250b57cec5SDimitry Andric     while (NumLocalDecls--) {
13260b57cec5SDimitry Andric       wasm::WasmLocalDecl Decl;
13270b57cec5SDimitry Andric       Decl.Count = readVaruint32(Ctx);
13280b57cec5SDimitry Andric       Decl.Type = readUint8(Ctx);
13290b57cec5SDimitry Andric       Function.Locals.push_back(Decl);
13300b57cec5SDimitry Andric     }
13310b57cec5SDimitry Andric 
13320b57cec5SDimitry Andric     uint32_t BodySize = FunctionEnd - Ctx.Ptr;
13330b57cec5SDimitry Andric     Function.Body = ArrayRef<uint8_t>(Ctx.Ptr, BodySize);
13340b57cec5SDimitry Andric     // This will be set later when reading in the linking metadata section.
13350b57cec5SDimitry Andric     Function.Comdat = UINT32_MAX;
13360b57cec5SDimitry Andric     Ctx.Ptr += BodySize;
13370b57cec5SDimitry Andric     assert(Ctx.Ptr == FunctionEnd);
13380b57cec5SDimitry Andric   }
13390b57cec5SDimitry Andric   if (Ctx.Ptr != Ctx.End)
1340af732203SDimitry Andric     return make_error<GenericBinaryError>("code section ended prematurely",
13410b57cec5SDimitry Andric                                           object_error::parse_failed);
13420b57cec5SDimitry Andric   return Error::success();
13430b57cec5SDimitry Andric }
13440b57cec5SDimitry Andric 
parseElemSection(ReadContext & Ctx)13450b57cec5SDimitry Andric Error WasmObjectFile::parseElemSection(ReadContext &Ctx) {
13460b57cec5SDimitry Andric   uint32_t Count = readVaruint32(Ctx);
13470b57cec5SDimitry Andric   ElemSegments.reserve(Count);
13480b57cec5SDimitry Andric   while (Count--) {
13490b57cec5SDimitry Andric     wasm::WasmElemSegment Segment;
1350*5f7ddb14SDimitry Andric     Segment.Flags = readVaruint32(Ctx);
1351*5f7ddb14SDimitry Andric 
1352*5f7ddb14SDimitry Andric     uint32_t SupportedFlags = wasm::WASM_ELEM_SEGMENT_HAS_TABLE_NUMBER |
1353*5f7ddb14SDimitry Andric                               wasm::WASM_ELEM_SEGMENT_IS_PASSIVE |
1354*5f7ddb14SDimitry Andric                               wasm::WASM_ELEM_SEGMENT_HAS_INIT_EXPRS;
1355*5f7ddb14SDimitry Andric     if (Segment.Flags & ~SupportedFlags)
1356*5f7ddb14SDimitry Andric       return make_error<GenericBinaryError>(
1357*5f7ddb14SDimitry Andric           "Unsupported flags for element segment", object_error::parse_failed);
1358*5f7ddb14SDimitry Andric 
1359*5f7ddb14SDimitry Andric     if (Segment.Flags & wasm::WASM_ELEM_SEGMENT_HAS_TABLE_NUMBER)
1360*5f7ddb14SDimitry Andric       Segment.TableNumber = readVaruint32(Ctx);
1361*5f7ddb14SDimitry Andric     else
1362*5f7ddb14SDimitry Andric       Segment.TableNumber = 0;
1363*5f7ddb14SDimitry Andric     if (!isValidTableNumber(Segment.TableNumber))
1364*5f7ddb14SDimitry Andric       return make_error<GenericBinaryError>("invalid TableNumber",
13650b57cec5SDimitry Andric                                             object_error::parse_failed);
1366*5f7ddb14SDimitry Andric 
1367*5f7ddb14SDimitry Andric     if (Segment.Flags & wasm::WASM_ELEM_SEGMENT_IS_PASSIVE) {
1368*5f7ddb14SDimitry Andric       Segment.Offset.Opcode = wasm::WASM_OPCODE_I32_CONST;
1369*5f7ddb14SDimitry Andric       Segment.Offset.Value.Int32 = 0;
1370*5f7ddb14SDimitry Andric     } else {
13710b57cec5SDimitry Andric       if (Error Err = readInitExpr(Segment.Offset, Ctx))
13720b57cec5SDimitry Andric         return Err;
1373*5f7ddb14SDimitry Andric     }
1374*5f7ddb14SDimitry Andric 
1375*5f7ddb14SDimitry Andric     if (Segment.Flags & wasm::WASM_ELEM_SEGMENT_MASK_HAS_ELEM_KIND) {
1376*5f7ddb14SDimitry Andric       Segment.ElemKind = readUint8(Ctx);
1377*5f7ddb14SDimitry Andric       if (Segment.Flags & wasm::WASM_ELEM_SEGMENT_HAS_INIT_EXPRS) {
1378*5f7ddb14SDimitry Andric         if (Segment.ElemKind != uint8_t(wasm::ValType::FUNCREF) &&
1379*5f7ddb14SDimitry Andric             Segment.ElemKind != uint8_t(wasm::ValType::EXTERNREF)) {
1380*5f7ddb14SDimitry Andric           return make_error<GenericBinaryError>("invalid reference type",
1381*5f7ddb14SDimitry Andric                                                 object_error::parse_failed);
1382*5f7ddb14SDimitry Andric         }
1383*5f7ddb14SDimitry Andric       } else {
1384*5f7ddb14SDimitry Andric         if (Segment.ElemKind != 0)
1385*5f7ddb14SDimitry Andric           return make_error<GenericBinaryError>("invalid elemtype",
1386*5f7ddb14SDimitry Andric                                                 object_error::parse_failed);
1387*5f7ddb14SDimitry Andric         Segment.ElemKind = uint8_t(wasm::ValType::FUNCREF);
1388*5f7ddb14SDimitry Andric       }
1389*5f7ddb14SDimitry Andric     } else {
1390*5f7ddb14SDimitry Andric       Segment.ElemKind = uint8_t(wasm::ValType::FUNCREF);
1391*5f7ddb14SDimitry Andric     }
1392*5f7ddb14SDimitry Andric 
1393*5f7ddb14SDimitry Andric     if (Segment.Flags & wasm::WASM_ELEM_SEGMENT_HAS_INIT_EXPRS)
1394*5f7ddb14SDimitry Andric       return make_error<GenericBinaryError>(
1395*5f7ddb14SDimitry Andric           "elem segment init expressions not yet implemented",
1396*5f7ddb14SDimitry Andric           object_error::parse_failed);
1397*5f7ddb14SDimitry Andric 
13980b57cec5SDimitry Andric     uint32_t NumElems = readVaruint32(Ctx);
13990b57cec5SDimitry Andric     while (NumElems--) {
14000b57cec5SDimitry Andric       Segment.Functions.push_back(readVaruint32(Ctx));
14010b57cec5SDimitry Andric     }
14020b57cec5SDimitry Andric     ElemSegments.push_back(Segment);
14030b57cec5SDimitry Andric   }
14040b57cec5SDimitry Andric   if (Ctx.Ptr != Ctx.End)
1405af732203SDimitry Andric     return make_error<GenericBinaryError>("elem section ended prematurely",
14060b57cec5SDimitry Andric                                           object_error::parse_failed);
14070b57cec5SDimitry Andric   return Error::success();
14080b57cec5SDimitry Andric }
14090b57cec5SDimitry Andric 
parseDataSection(ReadContext & Ctx)14100b57cec5SDimitry Andric Error WasmObjectFile::parseDataSection(ReadContext &Ctx) {
14110b57cec5SDimitry Andric   DataSection = Sections.size();
14120b57cec5SDimitry Andric   uint32_t Count = readVaruint32(Ctx);
14130b57cec5SDimitry Andric   if (DataCount && Count != DataCount.getValue())
14140b57cec5SDimitry Andric     return make_error<GenericBinaryError>(
1415af732203SDimitry Andric         "number of data segments does not match DataCount section");
14160b57cec5SDimitry Andric   DataSegments.reserve(Count);
14170b57cec5SDimitry Andric   while (Count--) {
14180b57cec5SDimitry Andric     WasmSegment Segment;
14190b57cec5SDimitry Andric     Segment.Data.InitFlags = readVaruint32(Ctx);
1420af732203SDimitry Andric     Segment.Data.MemoryIndex =
1421af732203SDimitry Andric         (Segment.Data.InitFlags & wasm::WASM_DATA_SEGMENT_HAS_MEMINDEX)
1422af732203SDimitry Andric             ? readVaruint32(Ctx)
1423af732203SDimitry Andric             : 0;
1424af732203SDimitry Andric     if ((Segment.Data.InitFlags & wasm::WASM_DATA_SEGMENT_IS_PASSIVE) == 0) {
14250b57cec5SDimitry Andric       if (Error Err = readInitExpr(Segment.Data.Offset, Ctx))
14260b57cec5SDimitry Andric         return Err;
14270b57cec5SDimitry Andric     } else {
14280b57cec5SDimitry Andric       Segment.Data.Offset.Opcode = wasm::WASM_OPCODE_I32_CONST;
14290b57cec5SDimitry Andric       Segment.Data.Offset.Value.Int32 = 0;
14300b57cec5SDimitry Andric     }
14310b57cec5SDimitry Andric     uint32_t Size = readVaruint32(Ctx);
14320b57cec5SDimitry Andric     if (Size > (size_t)(Ctx.End - Ctx.Ptr))
1433af732203SDimitry Andric       return make_error<GenericBinaryError>("invalid segment size",
14340b57cec5SDimitry Andric                                             object_error::parse_failed);
14350b57cec5SDimitry Andric     Segment.Data.Content = ArrayRef<uint8_t>(Ctx.Ptr, Size);
14360b57cec5SDimitry Andric     // The rest of these Data fields are set later, when reading in the linking
14370b57cec5SDimitry Andric     // metadata section.
14380b57cec5SDimitry Andric     Segment.Data.Alignment = 0;
1439*5f7ddb14SDimitry Andric     Segment.Data.LinkingFlags = 0;
14400b57cec5SDimitry Andric     Segment.Data.Comdat = UINT32_MAX;
14410b57cec5SDimitry Andric     Segment.SectionOffset = Ctx.Ptr - Ctx.Start;
14420b57cec5SDimitry Andric     Ctx.Ptr += Size;
14430b57cec5SDimitry Andric     DataSegments.push_back(Segment);
14440b57cec5SDimitry Andric   }
14450b57cec5SDimitry Andric   if (Ctx.Ptr != Ctx.End)
1446af732203SDimitry Andric     return make_error<GenericBinaryError>("data section ended prematurely",
14470b57cec5SDimitry Andric                                           object_error::parse_failed);
14480b57cec5SDimitry Andric   return Error::success();
14490b57cec5SDimitry Andric }
14500b57cec5SDimitry Andric 
parseDataCountSection(ReadContext & Ctx)14510b57cec5SDimitry Andric Error WasmObjectFile::parseDataCountSection(ReadContext &Ctx) {
14520b57cec5SDimitry Andric   DataCount = readVaruint32(Ctx);
14530b57cec5SDimitry Andric   return Error::success();
14540b57cec5SDimitry Andric }
14550b57cec5SDimitry Andric 
getHeader() const14560b57cec5SDimitry Andric const wasm::WasmObjectHeader &WasmObjectFile::getHeader() const {
14570b57cec5SDimitry Andric   return Header;
14580b57cec5SDimitry Andric }
14590b57cec5SDimitry Andric 
moveSymbolNext(DataRefImpl & Symb) const14600b57cec5SDimitry Andric void WasmObjectFile::moveSymbolNext(DataRefImpl &Symb) const { Symb.d.b++; }
14610b57cec5SDimitry Andric 
getSymbolFlags(DataRefImpl Symb) const14625ffd83dbSDimitry Andric Expected<uint32_t> WasmObjectFile::getSymbolFlags(DataRefImpl Symb) const {
14630b57cec5SDimitry Andric   uint32_t Result = SymbolRef::SF_None;
14640b57cec5SDimitry Andric   const WasmSymbol &Sym = getWasmSymbol(Symb);
14650b57cec5SDimitry Andric 
14660b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << "getSymbolFlags: ptr=" << &Sym << " " << Sym << "\n");
14670b57cec5SDimitry Andric   if (Sym.isBindingWeak())
14680b57cec5SDimitry Andric     Result |= SymbolRef::SF_Weak;
14690b57cec5SDimitry Andric   if (!Sym.isBindingLocal())
14700b57cec5SDimitry Andric     Result |= SymbolRef::SF_Global;
14710b57cec5SDimitry Andric   if (Sym.isHidden())
14720b57cec5SDimitry Andric     Result |= SymbolRef::SF_Hidden;
14730b57cec5SDimitry Andric   if (!Sym.isDefined())
14740b57cec5SDimitry Andric     Result |= SymbolRef::SF_Undefined;
14750b57cec5SDimitry Andric   if (Sym.isTypeFunction())
14760b57cec5SDimitry Andric     Result |= SymbolRef::SF_Executable;
14770b57cec5SDimitry Andric   return Result;
14780b57cec5SDimitry Andric }
14790b57cec5SDimitry Andric 
symbol_begin() const14800b57cec5SDimitry Andric basic_symbol_iterator WasmObjectFile::symbol_begin() const {
14810b57cec5SDimitry Andric   DataRefImpl Ref;
14820b57cec5SDimitry Andric   Ref.d.a = 1; // Arbitrary non-zero value so that Ref.p is non-null
14830b57cec5SDimitry Andric   Ref.d.b = 0; // Symbol index
14840b57cec5SDimitry Andric   return BasicSymbolRef(Ref, this);
14850b57cec5SDimitry Andric }
14860b57cec5SDimitry Andric 
symbol_end() const14870b57cec5SDimitry Andric basic_symbol_iterator WasmObjectFile::symbol_end() const {
14880b57cec5SDimitry Andric   DataRefImpl Ref;
14890b57cec5SDimitry Andric   Ref.d.a = 1; // Arbitrary non-zero value so that Ref.p is non-null
14900b57cec5SDimitry Andric   Ref.d.b = Symbols.size(); // Symbol index
14910b57cec5SDimitry Andric   return BasicSymbolRef(Ref, this);
14920b57cec5SDimitry Andric }
14930b57cec5SDimitry Andric 
getWasmSymbol(const DataRefImpl & Symb) const14940b57cec5SDimitry Andric const WasmSymbol &WasmObjectFile::getWasmSymbol(const DataRefImpl &Symb) const {
14950b57cec5SDimitry Andric   return Symbols[Symb.d.b];
14960b57cec5SDimitry Andric }
14970b57cec5SDimitry Andric 
getWasmSymbol(const SymbolRef & Symb) const14980b57cec5SDimitry Andric const WasmSymbol &WasmObjectFile::getWasmSymbol(const SymbolRef &Symb) const {
14990b57cec5SDimitry Andric   return getWasmSymbol(Symb.getRawDataRefImpl());
15000b57cec5SDimitry Andric }
15010b57cec5SDimitry Andric 
getSymbolName(DataRefImpl Symb) const15020b57cec5SDimitry Andric Expected<StringRef> WasmObjectFile::getSymbolName(DataRefImpl Symb) const {
15030b57cec5SDimitry Andric   return getWasmSymbol(Symb).Info.Name;
15040b57cec5SDimitry Andric }
15050b57cec5SDimitry Andric 
getSymbolAddress(DataRefImpl Symb) const15060b57cec5SDimitry Andric Expected<uint64_t> WasmObjectFile::getSymbolAddress(DataRefImpl Symb) const {
15070b57cec5SDimitry Andric   auto &Sym = getWasmSymbol(Symb);
15080b57cec5SDimitry Andric   if (Sym.Info.Kind == wasm::WASM_SYMBOL_TYPE_FUNCTION &&
15090b57cec5SDimitry Andric       isDefinedFunctionIndex(Sym.Info.ElementIndex))
15100b57cec5SDimitry Andric     return getDefinedFunction(Sym.Info.ElementIndex).CodeSectionOffset;
15110b57cec5SDimitry Andric   else
15120b57cec5SDimitry Andric     return getSymbolValue(Symb);
15130b57cec5SDimitry Andric }
15140b57cec5SDimitry Andric 
getWasmSymbolValue(const WasmSymbol & Sym) const15150b57cec5SDimitry Andric uint64_t WasmObjectFile::getWasmSymbolValue(const WasmSymbol &Sym) const {
15160b57cec5SDimitry Andric   switch (Sym.Info.Kind) {
15170b57cec5SDimitry Andric   case wasm::WASM_SYMBOL_TYPE_FUNCTION:
15180b57cec5SDimitry Andric   case wasm::WASM_SYMBOL_TYPE_GLOBAL:
1519*5f7ddb14SDimitry Andric   case wasm::WASM_SYMBOL_TYPE_TAG:
1520af732203SDimitry Andric   case wasm::WASM_SYMBOL_TYPE_TABLE:
15210b57cec5SDimitry Andric     return Sym.Info.ElementIndex;
15220b57cec5SDimitry Andric   case wasm::WASM_SYMBOL_TYPE_DATA: {
15230b57cec5SDimitry Andric     // The value of a data symbol is the segment offset, plus the symbol
15240b57cec5SDimitry Andric     // offset within the segment.
15250b57cec5SDimitry Andric     uint32_t SegmentIndex = Sym.Info.DataRef.Segment;
15260b57cec5SDimitry Andric     const wasm::WasmDataSegment &Segment = DataSegments[SegmentIndex].Data;
15275ffd83dbSDimitry Andric     if (Segment.Offset.Opcode == wasm::WASM_OPCODE_I32_CONST) {
15280b57cec5SDimitry Andric       return Segment.Offset.Value.Int32 + Sym.Info.DataRef.Offset;
15295ffd83dbSDimitry Andric     } else if (Segment.Offset.Opcode == wasm::WASM_OPCODE_I64_CONST) {
15305ffd83dbSDimitry Andric       return Segment.Offset.Value.Int64 + Sym.Info.DataRef.Offset;
15315ffd83dbSDimitry Andric     } else {
15325ffd83dbSDimitry Andric       llvm_unreachable("unknown init expr opcode");
15335ffd83dbSDimitry Andric     }
15340b57cec5SDimitry Andric   }
15350b57cec5SDimitry Andric   case wasm::WASM_SYMBOL_TYPE_SECTION:
15360b57cec5SDimitry Andric     return 0;
15370b57cec5SDimitry Andric   }
15380b57cec5SDimitry Andric   llvm_unreachable("invalid symbol type");
15390b57cec5SDimitry Andric }
15400b57cec5SDimitry Andric 
getSymbolValueImpl(DataRefImpl Symb) const15410b57cec5SDimitry Andric uint64_t WasmObjectFile::getSymbolValueImpl(DataRefImpl Symb) const {
15420b57cec5SDimitry Andric   return getWasmSymbolValue(getWasmSymbol(Symb));
15430b57cec5SDimitry Andric }
15440b57cec5SDimitry Andric 
getSymbolAlignment(DataRefImpl Symb) const15450b57cec5SDimitry Andric uint32_t WasmObjectFile::getSymbolAlignment(DataRefImpl Symb) const {
15460b57cec5SDimitry Andric   llvm_unreachable("not yet implemented");
15470b57cec5SDimitry Andric   return 0;
15480b57cec5SDimitry Andric }
15490b57cec5SDimitry Andric 
getCommonSymbolSizeImpl(DataRefImpl Symb) const15500b57cec5SDimitry Andric uint64_t WasmObjectFile::getCommonSymbolSizeImpl(DataRefImpl Symb) const {
15510b57cec5SDimitry Andric   llvm_unreachable("not yet implemented");
15520b57cec5SDimitry Andric   return 0;
15530b57cec5SDimitry Andric }
15540b57cec5SDimitry Andric 
15550b57cec5SDimitry Andric Expected<SymbolRef::Type>
getSymbolType(DataRefImpl Symb) const15560b57cec5SDimitry Andric WasmObjectFile::getSymbolType(DataRefImpl Symb) const {
15570b57cec5SDimitry Andric   const WasmSymbol &Sym = getWasmSymbol(Symb);
15580b57cec5SDimitry Andric 
15590b57cec5SDimitry Andric   switch (Sym.Info.Kind) {
15600b57cec5SDimitry Andric   case wasm::WASM_SYMBOL_TYPE_FUNCTION:
15610b57cec5SDimitry Andric     return SymbolRef::ST_Function;
15620b57cec5SDimitry Andric   case wasm::WASM_SYMBOL_TYPE_GLOBAL:
15630b57cec5SDimitry Andric     return SymbolRef::ST_Other;
15640b57cec5SDimitry Andric   case wasm::WASM_SYMBOL_TYPE_DATA:
15650b57cec5SDimitry Andric     return SymbolRef::ST_Data;
15660b57cec5SDimitry Andric   case wasm::WASM_SYMBOL_TYPE_SECTION:
15670b57cec5SDimitry Andric     return SymbolRef::ST_Debug;
1568*5f7ddb14SDimitry Andric   case wasm::WASM_SYMBOL_TYPE_TAG:
15690b57cec5SDimitry Andric     return SymbolRef::ST_Other;
1570af732203SDimitry Andric   case wasm::WASM_SYMBOL_TYPE_TABLE:
1571af732203SDimitry Andric     return SymbolRef::ST_Other;
15720b57cec5SDimitry Andric   }
15730b57cec5SDimitry Andric 
1574af732203SDimitry Andric   llvm_unreachable("unknown WasmSymbol::SymbolType");
15750b57cec5SDimitry Andric   return SymbolRef::ST_Other;
15760b57cec5SDimitry Andric }
15770b57cec5SDimitry Andric 
15780b57cec5SDimitry Andric Expected<section_iterator>
getSymbolSection(DataRefImpl Symb) const15790b57cec5SDimitry Andric WasmObjectFile::getSymbolSection(DataRefImpl Symb) const {
15800b57cec5SDimitry Andric   const WasmSymbol &Sym = getWasmSymbol(Symb);
15810b57cec5SDimitry Andric   if (Sym.isUndefined())
15820b57cec5SDimitry Andric     return section_end();
15830b57cec5SDimitry Andric 
15840b57cec5SDimitry Andric   DataRefImpl Ref;
15855ffd83dbSDimitry Andric   Ref.d.a = getSymbolSectionIdImpl(Sym);
15865ffd83dbSDimitry Andric   return section_iterator(SectionRef(Ref, this));
15875ffd83dbSDimitry Andric }
15885ffd83dbSDimitry Andric 
getSymbolSectionId(SymbolRef Symb) const15895ffd83dbSDimitry Andric uint32_t WasmObjectFile::getSymbolSectionId(SymbolRef Symb) const {
15905ffd83dbSDimitry Andric   const WasmSymbol &Sym = getWasmSymbol(Symb);
15915ffd83dbSDimitry Andric   return getSymbolSectionIdImpl(Sym);
15925ffd83dbSDimitry Andric }
15935ffd83dbSDimitry Andric 
getSymbolSectionIdImpl(const WasmSymbol & Sym) const15945ffd83dbSDimitry Andric uint32_t WasmObjectFile::getSymbolSectionIdImpl(const WasmSymbol &Sym) const {
15950b57cec5SDimitry Andric   switch (Sym.Info.Kind) {
15960b57cec5SDimitry Andric   case wasm::WASM_SYMBOL_TYPE_FUNCTION:
15975ffd83dbSDimitry Andric     return CodeSection;
15980b57cec5SDimitry Andric   case wasm::WASM_SYMBOL_TYPE_GLOBAL:
15995ffd83dbSDimitry Andric     return GlobalSection;
16000b57cec5SDimitry Andric   case wasm::WASM_SYMBOL_TYPE_DATA:
16015ffd83dbSDimitry Andric     return DataSection;
16020b57cec5SDimitry Andric   case wasm::WASM_SYMBOL_TYPE_SECTION:
16035ffd83dbSDimitry Andric     return Sym.Info.ElementIndex;
1604*5f7ddb14SDimitry Andric   case wasm::WASM_SYMBOL_TYPE_TAG:
1605*5f7ddb14SDimitry Andric     return TagSection;
1606af732203SDimitry Andric   case wasm::WASM_SYMBOL_TYPE_TABLE:
1607af732203SDimitry Andric     return TableSection;
16080b57cec5SDimitry Andric   default:
1609af732203SDimitry Andric     llvm_unreachable("unknown WasmSymbol::SymbolType");
16100b57cec5SDimitry Andric   }
16110b57cec5SDimitry Andric }
16120b57cec5SDimitry Andric 
moveSectionNext(DataRefImpl & Sec) const16130b57cec5SDimitry Andric void WasmObjectFile::moveSectionNext(DataRefImpl &Sec) const { Sec.d.a++; }
16140b57cec5SDimitry Andric 
getSectionName(DataRefImpl Sec) const16150b57cec5SDimitry Andric Expected<StringRef> WasmObjectFile::getSectionName(DataRefImpl Sec) const {
16160b57cec5SDimitry Andric   const WasmSection &S = Sections[Sec.d.a];
16170b57cec5SDimitry Andric #define ECase(X)                                                               \
16180b57cec5SDimitry Andric   case wasm::WASM_SEC_##X:                                                     \
16190b57cec5SDimitry Andric     return #X;
16200b57cec5SDimitry Andric   switch (S.Type) {
16210b57cec5SDimitry Andric     ECase(TYPE);
16220b57cec5SDimitry Andric     ECase(IMPORT);
16230b57cec5SDimitry Andric     ECase(FUNCTION);
16240b57cec5SDimitry Andric     ECase(TABLE);
16250b57cec5SDimitry Andric     ECase(MEMORY);
16260b57cec5SDimitry Andric     ECase(GLOBAL);
1627*5f7ddb14SDimitry Andric     ECase(TAG);
16280b57cec5SDimitry Andric     ECase(EXPORT);
16290b57cec5SDimitry Andric     ECase(START);
16300b57cec5SDimitry Andric     ECase(ELEM);
16310b57cec5SDimitry Andric     ECase(CODE);
16320b57cec5SDimitry Andric     ECase(DATA);
16330b57cec5SDimitry Andric     ECase(DATACOUNT);
16340b57cec5SDimitry Andric   case wasm::WASM_SEC_CUSTOM:
16350b57cec5SDimitry Andric     return S.Name;
16360b57cec5SDimitry Andric   default:
16370b57cec5SDimitry Andric     return createStringError(object_error::invalid_section_index, "");
16380b57cec5SDimitry Andric   }
16390b57cec5SDimitry Andric #undef ECase
16400b57cec5SDimitry Andric }
16410b57cec5SDimitry Andric 
getSectionAddress(DataRefImpl Sec) const16420b57cec5SDimitry Andric uint64_t WasmObjectFile::getSectionAddress(DataRefImpl Sec) const { return 0; }
16430b57cec5SDimitry Andric 
getSectionIndex(DataRefImpl Sec) const16440b57cec5SDimitry Andric uint64_t WasmObjectFile::getSectionIndex(DataRefImpl Sec) const {
16450b57cec5SDimitry Andric   return Sec.d.a;
16460b57cec5SDimitry Andric }
16470b57cec5SDimitry Andric 
getSectionSize(DataRefImpl Sec) const16480b57cec5SDimitry Andric uint64_t WasmObjectFile::getSectionSize(DataRefImpl Sec) const {
16490b57cec5SDimitry Andric   const WasmSection &S = Sections[Sec.d.a];
16500b57cec5SDimitry Andric   return S.Content.size();
16510b57cec5SDimitry Andric }
16520b57cec5SDimitry Andric 
16530b57cec5SDimitry Andric Expected<ArrayRef<uint8_t>>
getSectionContents(DataRefImpl Sec) const16540b57cec5SDimitry Andric WasmObjectFile::getSectionContents(DataRefImpl Sec) const {
16550b57cec5SDimitry Andric   const WasmSection &S = Sections[Sec.d.a];
16560b57cec5SDimitry Andric   // This will never fail since wasm sections can never be empty (user-sections
16570b57cec5SDimitry Andric   // must have a name and non-user sections each have a defined structure).
16580b57cec5SDimitry Andric   return S.Content;
16590b57cec5SDimitry Andric }
16600b57cec5SDimitry Andric 
getSectionAlignment(DataRefImpl Sec) const16610b57cec5SDimitry Andric uint64_t WasmObjectFile::getSectionAlignment(DataRefImpl Sec) const {
16620b57cec5SDimitry Andric   return 1;
16630b57cec5SDimitry Andric }
16640b57cec5SDimitry Andric 
isSectionCompressed(DataRefImpl Sec) const16650b57cec5SDimitry Andric bool WasmObjectFile::isSectionCompressed(DataRefImpl Sec) const {
16660b57cec5SDimitry Andric   return false;
16670b57cec5SDimitry Andric }
16680b57cec5SDimitry Andric 
isSectionText(DataRefImpl Sec) const16690b57cec5SDimitry Andric bool WasmObjectFile::isSectionText(DataRefImpl Sec) const {
16700b57cec5SDimitry Andric   return getWasmSection(Sec).Type == wasm::WASM_SEC_CODE;
16710b57cec5SDimitry Andric }
16720b57cec5SDimitry Andric 
isSectionData(DataRefImpl Sec) const16730b57cec5SDimitry Andric bool WasmObjectFile::isSectionData(DataRefImpl Sec) const {
16740b57cec5SDimitry Andric   return getWasmSection(Sec).Type == wasm::WASM_SEC_DATA;
16750b57cec5SDimitry Andric }
16760b57cec5SDimitry Andric 
isSectionBSS(DataRefImpl Sec) const16770b57cec5SDimitry Andric bool WasmObjectFile::isSectionBSS(DataRefImpl Sec) const { return false; }
16780b57cec5SDimitry Andric 
isSectionVirtual(DataRefImpl Sec) const16790b57cec5SDimitry Andric bool WasmObjectFile::isSectionVirtual(DataRefImpl Sec) const { return false; }
16800b57cec5SDimitry Andric 
section_rel_begin(DataRefImpl Ref) const16810b57cec5SDimitry Andric relocation_iterator WasmObjectFile::section_rel_begin(DataRefImpl Ref) const {
16820b57cec5SDimitry Andric   DataRefImpl RelocRef;
16830b57cec5SDimitry Andric   RelocRef.d.a = Ref.d.a;
16840b57cec5SDimitry Andric   RelocRef.d.b = 0;
16850b57cec5SDimitry Andric   return relocation_iterator(RelocationRef(RelocRef, this));
16860b57cec5SDimitry Andric }
16870b57cec5SDimitry Andric 
section_rel_end(DataRefImpl Ref) const16880b57cec5SDimitry Andric relocation_iterator WasmObjectFile::section_rel_end(DataRefImpl Ref) const {
16890b57cec5SDimitry Andric   const WasmSection &Sec = getWasmSection(Ref);
16900b57cec5SDimitry Andric   DataRefImpl RelocRef;
16910b57cec5SDimitry Andric   RelocRef.d.a = Ref.d.a;
16920b57cec5SDimitry Andric   RelocRef.d.b = Sec.Relocations.size();
16930b57cec5SDimitry Andric   return relocation_iterator(RelocationRef(RelocRef, this));
16940b57cec5SDimitry Andric }
16950b57cec5SDimitry Andric 
moveRelocationNext(DataRefImpl & Rel) const16960b57cec5SDimitry Andric void WasmObjectFile::moveRelocationNext(DataRefImpl &Rel) const { Rel.d.b++; }
16970b57cec5SDimitry Andric 
getRelocationOffset(DataRefImpl Ref) const16980b57cec5SDimitry Andric uint64_t WasmObjectFile::getRelocationOffset(DataRefImpl Ref) const {
16990b57cec5SDimitry Andric   const wasm::WasmRelocation &Rel = getWasmRelocation(Ref);
17000b57cec5SDimitry Andric   return Rel.Offset;
17010b57cec5SDimitry Andric }
17020b57cec5SDimitry Andric 
getRelocationSymbol(DataRefImpl Ref) const17030b57cec5SDimitry Andric symbol_iterator WasmObjectFile::getRelocationSymbol(DataRefImpl Ref) const {
17040b57cec5SDimitry Andric   const wasm::WasmRelocation &Rel = getWasmRelocation(Ref);
17050b57cec5SDimitry Andric   if (Rel.Type == wasm::R_WASM_TYPE_INDEX_LEB)
17060b57cec5SDimitry Andric     return symbol_end();
17070b57cec5SDimitry Andric   DataRefImpl Sym;
17080b57cec5SDimitry Andric   Sym.d.a = 1;
17090b57cec5SDimitry Andric   Sym.d.b = Rel.Index;
17100b57cec5SDimitry Andric   return symbol_iterator(SymbolRef(Sym, this));
17110b57cec5SDimitry Andric }
17120b57cec5SDimitry Andric 
getRelocationType(DataRefImpl Ref) const17130b57cec5SDimitry Andric uint64_t WasmObjectFile::getRelocationType(DataRefImpl Ref) const {
17140b57cec5SDimitry Andric   const wasm::WasmRelocation &Rel = getWasmRelocation(Ref);
17150b57cec5SDimitry Andric   return Rel.Type;
17160b57cec5SDimitry Andric }
17170b57cec5SDimitry Andric 
getRelocationTypeName(DataRefImpl Ref,SmallVectorImpl<char> & Result) const17180b57cec5SDimitry Andric void WasmObjectFile::getRelocationTypeName(
17190b57cec5SDimitry Andric     DataRefImpl Ref, SmallVectorImpl<char> &Result) const {
17200b57cec5SDimitry Andric   const wasm::WasmRelocation &Rel = getWasmRelocation(Ref);
17210b57cec5SDimitry Andric   StringRef Res = "Unknown";
17220b57cec5SDimitry Andric 
17230b57cec5SDimitry Andric #define WASM_RELOC(name, value)                                                \
17240b57cec5SDimitry Andric   case wasm::name:                                                             \
17250b57cec5SDimitry Andric     Res = #name;                                                               \
17260b57cec5SDimitry Andric     break;
17270b57cec5SDimitry Andric 
17280b57cec5SDimitry Andric   switch (Rel.Type) {
17290b57cec5SDimitry Andric #include "llvm/BinaryFormat/WasmRelocs.def"
17300b57cec5SDimitry Andric   }
17310b57cec5SDimitry Andric 
17320b57cec5SDimitry Andric #undef WASM_RELOC
17330b57cec5SDimitry Andric 
17340b57cec5SDimitry Andric   Result.append(Res.begin(), Res.end());
17350b57cec5SDimitry Andric }
17360b57cec5SDimitry Andric 
section_begin() const17370b57cec5SDimitry Andric section_iterator WasmObjectFile::section_begin() const {
17380b57cec5SDimitry Andric   DataRefImpl Ref;
17390b57cec5SDimitry Andric   Ref.d.a = 0;
17400b57cec5SDimitry Andric   return section_iterator(SectionRef(Ref, this));
17410b57cec5SDimitry Andric }
17420b57cec5SDimitry Andric 
section_end() const17430b57cec5SDimitry Andric section_iterator WasmObjectFile::section_end() const {
17440b57cec5SDimitry Andric   DataRefImpl Ref;
17450b57cec5SDimitry Andric   Ref.d.a = Sections.size();
17460b57cec5SDimitry Andric   return section_iterator(SectionRef(Ref, this));
17470b57cec5SDimitry Andric }
17480b57cec5SDimitry Andric 
getBytesInAddress() const1749af732203SDimitry Andric uint8_t WasmObjectFile::getBytesInAddress() const {
1750af732203SDimitry Andric   return HasMemory64 ? 8 : 4;
1751af732203SDimitry Andric }
17520b57cec5SDimitry Andric 
getFileFormatName() const17530b57cec5SDimitry Andric StringRef WasmObjectFile::getFileFormatName() const { return "WASM"; }
17540b57cec5SDimitry Andric 
getArch() const1755af732203SDimitry Andric Triple::ArchType WasmObjectFile::getArch() const {
1756af732203SDimitry Andric   return HasMemory64 ? Triple::wasm64 : Triple::wasm32;
1757af732203SDimitry Andric }
17580b57cec5SDimitry Andric 
getFeatures() const17590b57cec5SDimitry Andric SubtargetFeatures WasmObjectFile::getFeatures() const {
17600b57cec5SDimitry Andric   return SubtargetFeatures();
17610b57cec5SDimitry Andric }
17620b57cec5SDimitry Andric 
isRelocatableObject() const17630b57cec5SDimitry Andric bool WasmObjectFile::isRelocatableObject() const { return HasLinkingSection; }
17640b57cec5SDimitry Andric 
isSharedObject() const17650b57cec5SDimitry Andric bool WasmObjectFile::isSharedObject() const { return HasDylinkSection; }
17660b57cec5SDimitry Andric 
getWasmSection(DataRefImpl Ref) const17670b57cec5SDimitry Andric const WasmSection &WasmObjectFile::getWasmSection(DataRefImpl Ref) const {
17680b57cec5SDimitry Andric   assert(Ref.d.a < Sections.size());
17690b57cec5SDimitry Andric   return Sections[Ref.d.a];
17700b57cec5SDimitry Andric }
17710b57cec5SDimitry Andric 
17720b57cec5SDimitry Andric const WasmSection &
getWasmSection(const SectionRef & Section) const17730b57cec5SDimitry Andric WasmObjectFile::getWasmSection(const SectionRef &Section) const {
17740b57cec5SDimitry Andric   return getWasmSection(Section.getRawDataRefImpl());
17750b57cec5SDimitry Andric }
17760b57cec5SDimitry Andric 
17770b57cec5SDimitry Andric const wasm::WasmRelocation &
getWasmRelocation(const RelocationRef & Ref) const17780b57cec5SDimitry Andric WasmObjectFile::getWasmRelocation(const RelocationRef &Ref) const {
17790b57cec5SDimitry Andric   return getWasmRelocation(Ref.getRawDataRefImpl());
17800b57cec5SDimitry Andric }
17810b57cec5SDimitry Andric 
17820b57cec5SDimitry Andric const wasm::WasmRelocation &
getWasmRelocation(DataRefImpl Ref) const17830b57cec5SDimitry Andric WasmObjectFile::getWasmRelocation(DataRefImpl Ref) const {
17840b57cec5SDimitry Andric   assert(Ref.d.a < Sections.size());
17850b57cec5SDimitry Andric   const WasmSection &Sec = Sections[Ref.d.a];
17860b57cec5SDimitry Andric   assert(Ref.d.b < Sec.Relocations.size());
17870b57cec5SDimitry Andric   return Sec.Relocations[Ref.d.b];
17880b57cec5SDimitry Andric }
17890b57cec5SDimitry Andric 
getSectionOrder(unsigned ID,StringRef CustomSectionName)17900b57cec5SDimitry Andric int WasmSectionOrderChecker::getSectionOrder(unsigned ID,
17910b57cec5SDimitry Andric                                              StringRef CustomSectionName) {
17920b57cec5SDimitry Andric   switch (ID) {
17930b57cec5SDimitry Andric   case wasm::WASM_SEC_CUSTOM:
17940b57cec5SDimitry Andric     return StringSwitch<unsigned>(CustomSectionName)
17950b57cec5SDimitry Andric         .Case("dylink", WASM_SEC_ORDER_DYLINK)
17960b57cec5SDimitry Andric         .Case("linking", WASM_SEC_ORDER_LINKING)
17970b57cec5SDimitry Andric         .StartsWith("reloc.", WASM_SEC_ORDER_RELOC)
17980b57cec5SDimitry Andric         .Case("name", WASM_SEC_ORDER_NAME)
17990b57cec5SDimitry Andric         .Case("producers", WASM_SEC_ORDER_PRODUCERS)
18000b57cec5SDimitry Andric         .Case("target_features", WASM_SEC_ORDER_TARGET_FEATURES)
18010b57cec5SDimitry Andric         .Default(WASM_SEC_ORDER_NONE);
18020b57cec5SDimitry Andric   case wasm::WASM_SEC_TYPE:
18030b57cec5SDimitry Andric     return WASM_SEC_ORDER_TYPE;
18040b57cec5SDimitry Andric   case wasm::WASM_SEC_IMPORT:
18050b57cec5SDimitry Andric     return WASM_SEC_ORDER_IMPORT;
18060b57cec5SDimitry Andric   case wasm::WASM_SEC_FUNCTION:
18070b57cec5SDimitry Andric     return WASM_SEC_ORDER_FUNCTION;
18080b57cec5SDimitry Andric   case wasm::WASM_SEC_TABLE:
18090b57cec5SDimitry Andric     return WASM_SEC_ORDER_TABLE;
18100b57cec5SDimitry Andric   case wasm::WASM_SEC_MEMORY:
18110b57cec5SDimitry Andric     return WASM_SEC_ORDER_MEMORY;
18120b57cec5SDimitry Andric   case wasm::WASM_SEC_GLOBAL:
18130b57cec5SDimitry Andric     return WASM_SEC_ORDER_GLOBAL;
18140b57cec5SDimitry Andric   case wasm::WASM_SEC_EXPORT:
18150b57cec5SDimitry Andric     return WASM_SEC_ORDER_EXPORT;
18160b57cec5SDimitry Andric   case wasm::WASM_SEC_START:
18170b57cec5SDimitry Andric     return WASM_SEC_ORDER_START;
18180b57cec5SDimitry Andric   case wasm::WASM_SEC_ELEM:
18190b57cec5SDimitry Andric     return WASM_SEC_ORDER_ELEM;
18200b57cec5SDimitry Andric   case wasm::WASM_SEC_CODE:
18210b57cec5SDimitry Andric     return WASM_SEC_ORDER_CODE;
18220b57cec5SDimitry Andric   case wasm::WASM_SEC_DATA:
18230b57cec5SDimitry Andric     return WASM_SEC_ORDER_DATA;
18240b57cec5SDimitry Andric   case wasm::WASM_SEC_DATACOUNT:
18250b57cec5SDimitry Andric     return WASM_SEC_ORDER_DATACOUNT;
1826*5f7ddb14SDimitry Andric   case wasm::WASM_SEC_TAG:
1827*5f7ddb14SDimitry Andric     return WASM_SEC_ORDER_TAG;
18280b57cec5SDimitry Andric   default:
18290b57cec5SDimitry Andric     return WASM_SEC_ORDER_NONE;
18300b57cec5SDimitry Andric   }
18310b57cec5SDimitry Andric }
18320b57cec5SDimitry Andric 
18330b57cec5SDimitry Andric // Represents the edges in a directed graph where any node B reachable from node
18340b57cec5SDimitry Andric // A is not allowed to appear before A in the section ordering, but may appear
18350b57cec5SDimitry Andric // afterward.
18365ffd83dbSDimitry Andric int WasmSectionOrderChecker::DisallowedPredecessors
18375ffd83dbSDimitry Andric     [WASM_NUM_SEC_ORDERS][WASM_NUM_SEC_ORDERS] = {
18385ffd83dbSDimitry Andric         // WASM_SEC_ORDER_NONE
18395ffd83dbSDimitry Andric         {},
18405ffd83dbSDimitry Andric         // WASM_SEC_ORDER_TYPE
18415ffd83dbSDimitry Andric         {WASM_SEC_ORDER_TYPE, WASM_SEC_ORDER_IMPORT},
18425ffd83dbSDimitry Andric         // WASM_SEC_ORDER_IMPORT
18435ffd83dbSDimitry Andric         {WASM_SEC_ORDER_IMPORT, WASM_SEC_ORDER_FUNCTION},
18445ffd83dbSDimitry Andric         // WASM_SEC_ORDER_FUNCTION
18455ffd83dbSDimitry Andric         {WASM_SEC_ORDER_FUNCTION, WASM_SEC_ORDER_TABLE},
18465ffd83dbSDimitry Andric         // WASM_SEC_ORDER_TABLE
18475ffd83dbSDimitry Andric         {WASM_SEC_ORDER_TABLE, WASM_SEC_ORDER_MEMORY},
18485ffd83dbSDimitry Andric         // WASM_SEC_ORDER_MEMORY
1849*5f7ddb14SDimitry Andric         {WASM_SEC_ORDER_MEMORY, WASM_SEC_ORDER_TAG},
1850*5f7ddb14SDimitry Andric         // WASM_SEC_ORDER_TAG
1851*5f7ddb14SDimitry Andric         {WASM_SEC_ORDER_TAG, WASM_SEC_ORDER_GLOBAL},
18525ffd83dbSDimitry Andric         // WASM_SEC_ORDER_GLOBAL
18535ffd83dbSDimitry Andric         {WASM_SEC_ORDER_GLOBAL, WASM_SEC_ORDER_EXPORT},
18545ffd83dbSDimitry Andric         // WASM_SEC_ORDER_EXPORT
18555ffd83dbSDimitry Andric         {WASM_SEC_ORDER_EXPORT, WASM_SEC_ORDER_START},
18565ffd83dbSDimitry Andric         // WASM_SEC_ORDER_START
18575ffd83dbSDimitry Andric         {WASM_SEC_ORDER_START, WASM_SEC_ORDER_ELEM},
18585ffd83dbSDimitry Andric         // WASM_SEC_ORDER_ELEM
18595ffd83dbSDimitry Andric         {WASM_SEC_ORDER_ELEM, WASM_SEC_ORDER_DATACOUNT},
18605ffd83dbSDimitry Andric         // WASM_SEC_ORDER_DATACOUNT
18615ffd83dbSDimitry Andric         {WASM_SEC_ORDER_DATACOUNT, WASM_SEC_ORDER_CODE},
18625ffd83dbSDimitry Andric         // WASM_SEC_ORDER_CODE
18635ffd83dbSDimitry Andric         {WASM_SEC_ORDER_CODE, WASM_SEC_ORDER_DATA},
18645ffd83dbSDimitry Andric         // WASM_SEC_ORDER_DATA
18655ffd83dbSDimitry Andric         {WASM_SEC_ORDER_DATA, WASM_SEC_ORDER_LINKING},
18660b57cec5SDimitry Andric 
18670b57cec5SDimitry Andric         // Custom Sections
18685ffd83dbSDimitry Andric         // WASM_SEC_ORDER_DYLINK
18695ffd83dbSDimitry Andric         {WASM_SEC_ORDER_DYLINK, WASM_SEC_ORDER_TYPE},
18705ffd83dbSDimitry Andric         // WASM_SEC_ORDER_LINKING
18715ffd83dbSDimitry Andric         {WASM_SEC_ORDER_LINKING, WASM_SEC_ORDER_RELOC, WASM_SEC_ORDER_NAME},
18725ffd83dbSDimitry Andric         // WASM_SEC_ORDER_RELOC (can be repeated)
18735ffd83dbSDimitry Andric         {},
18745ffd83dbSDimitry Andric         // WASM_SEC_ORDER_NAME
18755ffd83dbSDimitry Andric         {WASM_SEC_ORDER_NAME, WASM_SEC_ORDER_PRODUCERS},
18765ffd83dbSDimitry Andric         // WASM_SEC_ORDER_PRODUCERS
18775ffd83dbSDimitry Andric         {WASM_SEC_ORDER_PRODUCERS, WASM_SEC_ORDER_TARGET_FEATURES},
18785ffd83dbSDimitry Andric         // WASM_SEC_ORDER_TARGET_FEATURES
18795ffd83dbSDimitry Andric         {WASM_SEC_ORDER_TARGET_FEATURES}};
18800b57cec5SDimitry Andric 
isValidSectionOrder(unsigned ID,StringRef CustomSectionName)18810b57cec5SDimitry Andric bool WasmSectionOrderChecker::isValidSectionOrder(unsigned ID,
18820b57cec5SDimitry Andric                                                   StringRef CustomSectionName) {
18830b57cec5SDimitry Andric   int Order = getSectionOrder(ID, CustomSectionName);
18840b57cec5SDimitry Andric   if (Order == WASM_SEC_ORDER_NONE)
18850b57cec5SDimitry Andric     return true;
18860b57cec5SDimitry Andric 
18870b57cec5SDimitry Andric   // Disallowed predecessors we need to check for
18880b57cec5SDimitry Andric   SmallVector<int, WASM_NUM_SEC_ORDERS> WorkList;
18890b57cec5SDimitry Andric 
18900b57cec5SDimitry Andric   // Keep track of completed checks to avoid repeating work
18910b57cec5SDimitry Andric   bool Checked[WASM_NUM_SEC_ORDERS] = {};
18920b57cec5SDimitry Andric 
18930b57cec5SDimitry Andric   int Curr = Order;
18940b57cec5SDimitry Andric   while (true) {
18950b57cec5SDimitry Andric     // Add new disallowed predecessors to work list
18960b57cec5SDimitry Andric     for (size_t I = 0;; ++I) {
18970b57cec5SDimitry Andric       int Next = DisallowedPredecessors[Curr][I];
18980b57cec5SDimitry Andric       if (Next == WASM_SEC_ORDER_NONE)
18990b57cec5SDimitry Andric         break;
19000b57cec5SDimitry Andric       if (Checked[Next])
19010b57cec5SDimitry Andric         continue;
19020b57cec5SDimitry Andric       WorkList.push_back(Next);
19030b57cec5SDimitry Andric       Checked[Next] = true;
19040b57cec5SDimitry Andric     }
19050b57cec5SDimitry Andric 
19060b57cec5SDimitry Andric     if (WorkList.empty())
19070b57cec5SDimitry Andric       break;
19080b57cec5SDimitry Andric 
19090b57cec5SDimitry Andric     // Consider next disallowed predecessor
19100b57cec5SDimitry Andric     Curr = WorkList.pop_back_val();
19110b57cec5SDimitry Andric     if (Seen[Curr])
19120b57cec5SDimitry Andric       return false;
19130b57cec5SDimitry Andric   }
19140b57cec5SDimitry Andric 
19150b57cec5SDimitry Andric   // Have not seen any disallowed predecessors
19160b57cec5SDimitry Andric   Seen[Order] = true;
19170b57cec5SDimitry Andric   return true;
19180b57cec5SDimitry Andric }
1919