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