xref: /openbsd-src/gnu/llvm/llvm/lib/Object/WasmObjectFile.cpp (revision d415bd752c734aee168c4ee86ff32e8cc249eb16)
109467b48Spatrick //===- WasmObjectFile.cpp - Wasm object file implementation ---------------===//
209467b48Spatrick //
309467b48Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
409467b48Spatrick // See https://llvm.org/LICENSE.txt for license information.
509467b48Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
609467b48Spatrick //
709467b48Spatrick //===----------------------------------------------------------------------===//
809467b48Spatrick 
909467b48Spatrick #include "llvm/ADT/ArrayRef.h"
1009467b48Spatrick #include "llvm/ADT/DenseSet.h"
1109467b48Spatrick #include "llvm/ADT/SmallSet.h"
1209467b48Spatrick #include "llvm/ADT/StringRef.h"
1309467b48Spatrick #include "llvm/ADT/StringSet.h"
14097a140dSpatrick #include "llvm/ADT/StringSwitch.h"
1509467b48Spatrick #include "llvm/ADT/Triple.h"
1609467b48Spatrick #include "llvm/BinaryFormat/Wasm.h"
1709467b48Spatrick #include "llvm/MC/SubtargetFeature.h"
1809467b48Spatrick #include "llvm/Object/Binary.h"
1909467b48Spatrick #include "llvm/Object/Error.h"
2009467b48Spatrick #include "llvm/Object/ObjectFile.h"
2109467b48Spatrick #include "llvm/Object/SymbolicFile.h"
2209467b48Spatrick #include "llvm/Object/Wasm.h"
2309467b48Spatrick #include "llvm/Support/Endian.h"
2409467b48Spatrick #include "llvm/Support/Error.h"
2509467b48Spatrick #include "llvm/Support/ErrorHandling.h"
2609467b48Spatrick #include "llvm/Support/LEB128.h"
2709467b48Spatrick #include "llvm/Support/ScopedPrinter.h"
2809467b48Spatrick #include <algorithm>
2909467b48Spatrick #include <cassert>
3009467b48Spatrick #include <cstdint>
3109467b48Spatrick #include <cstring>
3209467b48Spatrick 
3309467b48Spatrick #define DEBUG_TYPE "wasm-object"
3409467b48Spatrick 
3509467b48Spatrick using namespace llvm;
3609467b48Spatrick using namespace object;
3709467b48Spatrick 
print(raw_ostream & Out) const3809467b48Spatrick void WasmSymbol::print(raw_ostream &Out) const {
3909467b48Spatrick   Out << "Name=" << Info.Name
4073471bf0Spatrick       << ", Kind=" << toString(wasm::WasmSymbolType(Info.Kind)) << ", Flags=0x"
4173471bf0Spatrick       << Twine::utohexstr(Info.Flags);
4209467b48Spatrick   if (!isTypeData()) {
4309467b48Spatrick     Out << ", ElemIndex=" << Info.ElementIndex;
4409467b48Spatrick   } else if (isDefined()) {
4509467b48Spatrick     Out << ", Segment=" << Info.DataRef.Segment;
4609467b48Spatrick     Out << ", Offset=" << Info.DataRef.Offset;
4709467b48Spatrick     Out << ", Size=" << Info.DataRef.Size;
4809467b48Spatrick   }
4909467b48Spatrick }
5009467b48Spatrick 
5109467b48Spatrick #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
dump() const5209467b48Spatrick LLVM_DUMP_METHOD void WasmSymbol::dump() const { print(dbgs()); }
5309467b48Spatrick #endif
5409467b48Spatrick 
5509467b48Spatrick Expected<std::unique_ptr<WasmObjectFile>>
createWasmObjectFile(MemoryBufferRef Buffer)5609467b48Spatrick ObjectFile::createWasmObjectFile(MemoryBufferRef Buffer) {
5709467b48Spatrick   Error Err = Error::success();
5809467b48Spatrick   auto ObjectFile = std::make_unique<WasmObjectFile>(Buffer, Err);
5909467b48Spatrick   if (Err)
6009467b48Spatrick     return std::move(Err);
6109467b48Spatrick 
6209467b48Spatrick   return std::move(ObjectFile);
6309467b48Spatrick }
6409467b48Spatrick 
6509467b48Spatrick #define VARINT7_MAX ((1 << 7) - 1)
6609467b48Spatrick #define VARINT7_MIN (-(1 << 7))
6709467b48Spatrick #define VARUINT7_MAX (1 << 7)
6809467b48Spatrick #define VARUINT1_MAX (1)
6909467b48Spatrick 
readUint8(WasmObjectFile::ReadContext & Ctx)7009467b48Spatrick static uint8_t readUint8(WasmObjectFile::ReadContext &Ctx) {
7109467b48Spatrick   if (Ctx.Ptr == Ctx.End)
7209467b48Spatrick     report_fatal_error("EOF while reading uint8");
7309467b48Spatrick   return *Ctx.Ptr++;
7409467b48Spatrick }
7509467b48Spatrick 
readUint32(WasmObjectFile::ReadContext & Ctx)7609467b48Spatrick static uint32_t readUint32(WasmObjectFile::ReadContext &Ctx) {
7709467b48Spatrick   if (Ctx.Ptr + 4 > Ctx.End)
7809467b48Spatrick     report_fatal_error("EOF while reading uint32");
7909467b48Spatrick   uint32_t Result = support::endian::read32le(Ctx.Ptr);
8009467b48Spatrick   Ctx.Ptr += 4;
8109467b48Spatrick   return Result;
8209467b48Spatrick }
8309467b48Spatrick 
readFloat32(WasmObjectFile::ReadContext & Ctx)8409467b48Spatrick static int32_t readFloat32(WasmObjectFile::ReadContext &Ctx) {
8509467b48Spatrick   if (Ctx.Ptr + 4 > Ctx.End)
8609467b48Spatrick     report_fatal_error("EOF while reading float64");
8709467b48Spatrick   int32_t Result = 0;
8809467b48Spatrick   memcpy(&Result, Ctx.Ptr, sizeof(Result));
8909467b48Spatrick   Ctx.Ptr += sizeof(Result);
9009467b48Spatrick   return Result;
9109467b48Spatrick }
9209467b48Spatrick 
readFloat64(WasmObjectFile::ReadContext & Ctx)9309467b48Spatrick static int64_t readFloat64(WasmObjectFile::ReadContext &Ctx) {
9409467b48Spatrick   if (Ctx.Ptr + 8 > Ctx.End)
9509467b48Spatrick     report_fatal_error("EOF while reading float64");
9609467b48Spatrick   int64_t Result = 0;
9709467b48Spatrick   memcpy(&Result, Ctx.Ptr, sizeof(Result));
9809467b48Spatrick   Ctx.Ptr += sizeof(Result);
9909467b48Spatrick   return Result;
10009467b48Spatrick }
10109467b48Spatrick 
readULEB128(WasmObjectFile::ReadContext & Ctx)10209467b48Spatrick static uint64_t readULEB128(WasmObjectFile::ReadContext &Ctx) {
10309467b48Spatrick   unsigned Count;
10409467b48Spatrick   const char *Error = nullptr;
10509467b48Spatrick   uint64_t Result = decodeULEB128(Ctx.Ptr, &Count, Ctx.End, &Error);
10609467b48Spatrick   if (Error)
10709467b48Spatrick     report_fatal_error(Error);
10809467b48Spatrick   Ctx.Ptr += Count;
10909467b48Spatrick   return Result;
11009467b48Spatrick }
11109467b48Spatrick 
readString(WasmObjectFile::ReadContext & Ctx)11209467b48Spatrick static StringRef readString(WasmObjectFile::ReadContext &Ctx) {
11309467b48Spatrick   uint32_t StringLen = readULEB128(Ctx);
11409467b48Spatrick   if (Ctx.Ptr + StringLen > Ctx.End)
11509467b48Spatrick     report_fatal_error("EOF while reading string");
11609467b48Spatrick   StringRef Return =
11709467b48Spatrick       StringRef(reinterpret_cast<const char *>(Ctx.Ptr), StringLen);
11809467b48Spatrick   Ctx.Ptr += StringLen;
11909467b48Spatrick   return Return;
12009467b48Spatrick }
12109467b48Spatrick 
readLEB128(WasmObjectFile::ReadContext & Ctx)12209467b48Spatrick static int64_t readLEB128(WasmObjectFile::ReadContext &Ctx) {
12309467b48Spatrick   unsigned Count;
12409467b48Spatrick   const char *Error = nullptr;
12509467b48Spatrick   uint64_t Result = decodeSLEB128(Ctx.Ptr, &Count, Ctx.End, &Error);
12609467b48Spatrick   if (Error)
12709467b48Spatrick     report_fatal_error(Error);
12809467b48Spatrick   Ctx.Ptr += Count;
12909467b48Spatrick   return Result;
13009467b48Spatrick }
13109467b48Spatrick 
readVaruint1(WasmObjectFile::ReadContext & Ctx)13209467b48Spatrick static uint8_t readVaruint1(WasmObjectFile::ReadContext &Ctx) {
13309467b48Spatrick   int64_t Result = readLEB128(Ctx);
13409467b48Spatrick   if (Result > VARUINT1_MAX || Result < 0)
13509467b48Spatrick     report_fatal_error("LEB is outside Varuint1 range");
13609467b48Spatrick   return Result;
13709467b48Spatrick }
13809467b48Spatrick 
readVarint32(WasmObjectFile::ReadContext & Ctx)13909467b48Spatrick static int32_t readVarint32(WasmObjectFile::ReadContext &Ctx) {
14009467b48Spatrick   int64_t Result = readLEB128(Ctx);
14109467b48Spatrick   if (Result > INT32_MAX || Result < INT32_MIN)
14209467b48Spatrick     report_fatal_error("LEB is outside Varint32 range");
14309467b48Spatrick   return Result;
14409467b48Spatrick }
14509467b48Spatrick 
readVaruint32(WasmObjectFile::ReadContext & Ctx)14609467b48Spatrick static uint32_t readVaruint32(WasmObjectFile::ReadContext &Ctx) {
14709467b48Spatrick   uint64_t Result = readULEB128(Ctx);
14809467b48Spatrick   if (Result > UINT32_MAX)
14909467b48Spatrick     report_fatal_error("LEB is outside Varuint32 range");
15009467b48Spatrick   return Result;
15109467b48Spatrick }
15209467b48Spatrick 
readVarint64(WasmObjectFile::ReadContext & Ctx)15309467b48Spatrick static int64_t readVarint64(WasmObjectFile::ReadContext &Ctx) {
15409467b48Spatrick   return readLEB128(Ctx);
15509467b48Spatrick }
15609467b48Spatrick 
readVaruint64(WasmObjectFile::ReadContext & Ctx)157097a140dSpatrick static uint64_t readVaruint64(WasmObjectFile::ReadContext &Ctx) {
158097a140dSpatrick   return readULEB128(Ctx);
159097a140dSpatrick }
160097a140dSpatrick 
readOpcode(WasmObjectFile::ReadContext & Ctx)16109467b48Spatrick static uint8_t readOpcode(WasmObjectFile::ReadContext &Ctx) {
16209467b48Spatrick   return readUint8(Ctx);
16309467b48Spatrick }
16409467b48Spatrick 
readInitExpr(wasm::WasmInitExpr & Expr,WasmObjectFile::ReadContext & Ctx)16509467b48Spatrick static Error readInitExpr(wasm::WasmInitExpr &Expr,
16609467b48Spatrick                           WasmObjectFile::ReadContext &Ctx) {
167*d415bd75Srobert   auto Start = Ctx.Ptr;
16809467b48Spatrick 
169*d415bd75Srobert   Expr.Extended = false;
170*d415bd75Srobert   Expr.Inst.Opcode = readOpcode(Ctx);
171*d415bd75Srobert   switch (Expr.Inst.Opcode) {
17209467b48Spatrick   case wasm::WASM_OPCODE_I32_CONST:
173*d415bd75Srobert     Expr.Inst.Value.Int32 = readVarint32(Ctx);
17409467b48Spatrick     break;
17509467b48Spatrick   case wasm::WASM_OPCODE_I64_CONST:
176*d415bd75Srobert     Expr.Inst.Value.Int64 = readVarint64(Ctx);
17709467b48Spatrick     break;
17809467b48Spatrick   case wasm::WASM_OPCODE_F32_CONST:
179*d415bd75Srobert     Expr.Inst.Value.Float32 = readFloat32(Ctx);
18009467b48Spatrick     break;
18109467b48Spatrick   case wasm::WASM_OPCODE_F64_CONST:
182*d415bd75Srobert     Expr.Inst.Value.Float64 = readFloat64(Ctx);
18309467b48Spatrick     break;
18409467b48Spatrick   case wasm::WASM_OPCODE_GLOBAL_GET:
185*d415bd75Srobert     Expr.Inst.Value.Global = readULEB128(Ctx);
18609467b48Spatrick     break;
187097a140dSpatrick   case wasm::WASM_OPCODE_REF_NULL: {
188097a140dSpatrick     wasm::ValType Ty = static_cast<wasm::ValType>(readULEB128(Ctx));
189097a140dSpatrick     if (Ty != wasm::ValType::EXTERNREF) {
19073471bf0Spatrick       return make_error<GenericBinaryError>("invalid type for ref.null",
191097a140dSpatrick                                             object_error::parse_failed);
192097a140dSpatrick     }
193097a140dSpatrick     break;
194097a140dSpatrick   }
19509467b48Spatrick   default:
196*d415bd75Srobert     Expr.Extended = true;
19709467b48Spatrick   }
19809467b48Spatrick 
199*d415bd75Srobert   if (!Expr.Extended) {
20009467b48Spatrick     uint8_t EndOpcode = readOpcode(Ctx);
201*d415bd75Srobert     if (EndOpcode != wasm::WASM_OPCODE_END)
202*d415bd75Srobert       Expr.Extended = true;
203*d415bd75Srobert   }
204*d415bd75Srobert 
205*d415bd75Srobert   if (Expr.Extended) {
206*d415bd75Srobert     Ctx.Ptr = Start;
207*d415bd75Srobert     while (true) {
208*d415bd75Srobert       uint8_t Opcode = readOpcode(Ctx);
209*d415bd75Srobert       switch (Opcode) {
210*d415bd75Srobert       case wasm::WASM_OPCODE_I32_CONST:
211*d415bd75Srobert       case wasm::WASM_OPCODE_GLOBAL_GET:
212*d415bd75Srobert       case wasm::WASM_OPCODE_REF_NULL:
213*d415bd75Srobert       case wasm::WASM_OPCODE_I64_CONST:
214*d415bd75Srobert       case wasm::WASM_OPCODE_F32_CONST:
215*d415bd75Srobert       case wasm::WASM_OPCODE_F64_CONST:
216*d415bd75Srobert         readULEB128(Ctx);
217*d415bd75Srobert         break;
218*d415bd75Srobert       case wasm::WASM_OPCODE_I32_ADD:
219*d415bd75Srobert       case wasm::WASM_OPCODE_I32_SUB:
220*d415bd75Srobert       case wasm::WASM_OPCODE_I32_MUL:
221*d415bd75Srobert       case wasm::WASM_OPCODE_I64_ADD:
222*d415bd75Srobert       case wasm::WASM_OPCODE_I64_SUB:
223*d415bd75Srobert       case wasm::WASM_OPCODE_I64_MUL:
224*d415bd75Srobert         break;
225*d415bd75Srobert       case wasm::WASM_OPCODE_END:
226*d415bd75Srobert         Expr.Body = ArrayRef<uint8_t>(Start, Ctx.Ptr - Start);
227*d415bd75Srobert         return Error::success();
228*d415bd75Srobert       default:
229*d415bd75Srobert         return make_error<GenericBinaryError>(
230*d415bd75Srobert             Twine("invalid opcode in init_expr: ") + Twine(unsigned(Opcode)),
23109467b48Spatrick             object_error::parse_failed);
23209467b48Spatrick       }
233*d415bd75Srobert     }
234*d415bd75Srobert   }
235*d415bd75Srobert 
23609467b48Spatrick   return Error::success();
23709467b48Spatrick }
23809467b48Spatrick 
readLimits(WasmObjectFile::ReadContext & Ctx)23909467b48Spatrick static wasm::WasmLimits readLimits(WasmObjectFile::ReadContext &Ctx) {
24009467b48Spatrick   wasm::WasmLimits Result;
24109467b48Spatrick   Result.Flags = readVaruint32(Ctx);
24273471bf0Spatrick   Result.Minimum = readVaruint64(Ctx);
24309467b48Spatrick   if (Result.Flags & wasm::WASM_LIMITS_FLAG_HAS_MAX)
244097a140dSpatrick     Result.Maximum = readVaruint64(Ctx);
24509467b48Spatrick   return Result;
24609467b48Spatrick }
24709467b48Spatrick 
readTableType(WasmObjectFile::ReadContext & Ctx)24873471bf0Spatrick static wasm::WasmTableType readTableType(WasmObjectFile::ReadContext &Ctx) {
24973471bf0Spatrick   wasm::WasmTableType TableType;
25073471bf0Spatrick   TableType.ElemType = readUint8(Ctx);
25173471bf0Spatrick   TableType.Limits = readLimits(Ctx);
25273471bf0Spatrick   return TableType;
25309467b48Spatrick }
25409467b48Spatrick 
readSection(WasmSection & Section,WasmObjectFile::ReadContext & Ctx,WasmSectionOrderChecker & Checker)25509467b48Spatrick static Error readSection(WasmSection &Section, WasmObjectFile::ReadContext &Ctx,
25609467b48Spatrick                          WasmSectionOrderChecker &Checker) {
25709467b48Spatrick   Section.Offset = Ctx.Ptr - Ctx.Start;
25809467b48Spatrick   Section.Type = readUint8(Ctx);
25909467b48Spatrick   LLVM_DEBUG(dbgs() << "readSection type=" << Section.Type << "\n");
26009467b48Spatrick   uint32_t Size = readVaruint32(Ctx);
26109467b48Spatrick   if (Size == 0)
26273471bf0Spatrick     return make_error<StringError>("zero length section",
26309467b48Spatrick                                    object_error::parse_failed);
26409467b48Spatrick   if (Ctx.Ptr + Size > Ctx.End)
26573471bf0Spatrick     return make_error<StringError>("section too large",
26609467b48Spatrick                                    object_error::parse_failed);
26709467b48Spatrick   if (Section.Type == wasm::WASM_SEC_CUSTOM) {
26809467b48Spatrick     WasmObjectFile::ReadContext SectionCtx;
26909467b48Spatrick     SectionCtx.Start = Ctx.Ptr;
27009467b48Spatrick     SectionCtx.Ptr = Ctx.Ptr;
27109467b48Spatrick     SectionCtx.End = Ctx.Ptr + Size;
27209467b48Spatrick 
27309467b48Spatrick     Section.Name = readString(SectionCtx);
27409467b48Spatrick 
27509467b48Spatrick     uint32_t SectionNameSize = SectionCtx.Ptr - SectionCtx.Start;
27609467b48Spatrick     Ctx.Ptr += SectionNameSize;
27709467b48Spatrick     Size -= SectionNameSize;
27809467b48Spatrick   }
27909467b48Spatrick 
28009467b48Spatrick   if (!Checker.isValidSectionOrder(Section.Type, Section.Name)) {
28173471bf0Spatrick     return make_error<StringError>("out of order section type: " +
28209467b48Spatrick                                        llvm::to_string(Section.Type),
28309467b48Spatrick                                    object_error::parse_failed);
28409467b48Spatrick   }
28509467b48Spatrick 
28609467b48Spatrick   Section.Content = ArrayRef<uint8_t>(Ctx.Ptr, Size);
28709467b48Spatrick   Ctx.Ptr += Size;
28809467b48Spatrick   return Error::success();
28909467b48Spatrick }
29009467b48Spatrick 
WasmObjectFile(MemoryBufferRef Buffer,Error & Err)29109467b48Spatrick WasmObjectFile::WasmObjectFile(MemoryBufferRef Buffer, Error &Err)
29209467b48Spatrick     : ObjectFile(Binary::ID_Wasm, Buffer) {
29309467b48Spatrick   ErrorAsOutParameter ErrAsOutParam(&Err);
29409467b48Spatrick   Header.Magic = getData().substr(0, 4);
29509467b48Spatrick   if (Header.Magic != StringRef("\0asm", 4)) {
29673471bf0Spatrick     Err = make_error<StringError>("invalid magic number",
29773471bf0Spatrick                                   object_error::parse_failed);
29809467b48Spatrick     return;
29909467b48Spatrick   }
30009467b48Spatrick 
30109467b48Spatrick   ReadContext Ctx;
30209467b48Spatrick   Ctx.Start = getData().bytes_begin();
30309467b48Spatrick   Ctx.Ptr = Ctx.Start + 4;
30409467b48Spatrick   Ctx.End = Ctx.Start + getData().size();
30509467b48Spatrick 
30609467b48Spatrick   if (Ctx.Ptr + 4 > Ctx.End) {
30773471bf0Spatrick     Err = make_error<StringError>("missing version number",
30809467b48Spatrick                                   object_error::parse_failed);
30909467b48Spatrick     return;
31009467b48Spatrick   }
31109467b48Spatrick 
31209467b48Spatrick   Header.Version = readUint32(Ctx);
31309467b48Spatrick   if (Header.Version != wasm::WasmVersion) {
31473471bf0Spatrick     Err = make_error<StringError>("invalid version number: " +
31573471bf0Spatrick                                       Twine(Header.Version),
31609467b48Spatrick                                   object_error::parse_failed);
31709467b48Spatrick     return;
31809467b48Spatrick   }
31909467b48Spatrick 
32009467b48Spatrick   WasmSectionOrderChecker Checker;
32109467b48Spatrick   while (Ctx.Ptr < Ctx.End) {
322*d415bd75Srobert     WasmSection Sec;
32309467b48Spatrick     if ((Err = readSection(Sec, Ctx, Checker)))
32409467b48Spatrick       return;
32509467b48Spatrick     if ((Err = parseSection(Sec)))
32609467b48Spatrick       return;
32709467b48Spatrick 
32809467b48Spatrick     Sections.push_back(Sec);
32909467b48Spatrick   }
33009467b48Spatrick }
33109467b48Spatrick 
parseSection(WasmSection & Sec)33209467b48Spatrick Error WasmObjectFile::parseSection(WasmSection &Sec) {
33309467b48Spatrick   ReadContext Ctx;
33409467b48Spatrick   Ctx.Start = Sec.Content.data();
33509467b48Spatrick   Ctx.End = Ctx.Start + Sec.Content.size();
33609467b48Spatrick   Ctx.Ptr = Ctx.Start;
33709467b48Spatrick   switch (Sec.Type) {
33809467b48Spatrick   case wasm::WASM_SEC_CUSTOM:
33909467b48Spatrick     return parseCustomSection(Sec, Ctx);
34009467b48Spatrick   case wasm::WASM_SEC_TYPE:
34109467b48Spatrick     return parseTypeSection(Ctx);
34209467b48Spatrick   case wasm::WASM_SEC_IMPORT:
34309467b48Spatrick     return parseImportSection(Ctx);
34409467b48Spatrick   case wasm::WASM_SEC_FUNCTION:
34509467b48Spatrick     return parseFunctionSection(Ctx);
34609467b48Spatrick   case wasm::WASM_SEC_TABLE:
34709467b48Spatrick     return parseTableSection(Ctx);
34809467b48Spatrick   case wasm::WASM_SEC_MEMORY:
34909467b48Spatrick     return parseMemorySection(Ctx);
35073471bf0Spatrick   case wasm::WASM_SEC_TAG:
35173471bf0Spatrick     return parseTagSection(Ctx);
352097a140dSpatrick   case wasm::WASM_SEC_GLOBAL:
353097a140dSpatrick     return parseGlobalSection(Ctx);
35409467b48Spatrick   case wasm::WASM_SEC_EXPORT:
35509467b48Spatrick     return parseExportSection(Ctx);
35609467b48Spatrick   case wasm::WASM_SEC_START:
35709467b48Spatrick     return parseStartSection(Ctx);
35809467b48Spatrick   case wasm::WASM_SEC_ELEM:
35909467b48Spatrick     return parseElemSection(Ctx);
36009467b48Spatrick   case wasm::WASM_SEC_CODE:
36109467b48Spatrick     return parseCodeSection(Ctx);
36209467b48Spatrick   case wasm::WASM_SEC_DATA:
36309467b48Spatrick     return parseDataSection(Ctx);
36409467b48Spatrick   case wasm::WASM_SEC_DATACOUNT:
36509467b48Spatrick     return parseDataCountSection(Ctx);
36609467b48Spatrick   default:
36709467b48Spatrick     return make_error<GenericBinaryError>(
36873471bf0Spatrick         "invalid section type: " + Twine(Sec.Type), object_error::parse_failed);
36909467b48Spatrick   }
37009467b48Spatrick }
37109467b48Spatrick 
parseDylinkSection(ReadContext & Ctx)37209467b48Spatrick Error WasmObjectFile::parseDylinkSection(ReadContext &Ctx) {
373*d415bd75Srobert   // Legacy "dylink" section support.
374*d415bd75Srobert   // See parseDylink0Section for the current "dylink.0" section parsing.
37509467b48Spatrick   HasDylinkSection = true;
37609467b48Spatrick   DylinkInfo.MemorySize = readVaruint32(Ctx);
37709467b48Spatrick   DylinkInfo.MemoryAlignment = readVaruint32(Ctx);
37809467b48Spatrick   DylinkInfo.TableSize = readVaruint32(Ctx);
37909467b48Spatrick   DylinkInfo.TableAlignment = readVaruint32(Ctx);
38009467b48Spatrick   uint32_t Count = readVaruint32(Ctx);
38109467b48Spatrick   while (Count--) {
38209467b48Spatrick     DylinkInfo.Needed.push_back(readString(Ctx));
38309467b48Spatrick   }
384*d415bd75Srobert 
38509467b48Spatrick   if (Ctx.Ptr != Ctx.End)
38609467b48Spatrick     return make_error<GenericBinaryError>("dylink section ended prematurely",
38709467b48Spatrick                                           object_error::parse_failed);
38809467b48Spatrick   return Error::success();
38909467b48Spatrick }
39009467b48Spatrick 
parseDylink0Section(ReadContext & Ctx)391*d415bd75Srobert Error WasmObjectFile::parseDylink0Section(ReadContext &Ctx) {
392*d415bd75Srobert   // See
393*d415bd75Srobert   // https://github.com/WebAssembly/tool-conventions/blob/main/DynamicLinking.md
394*d415bd75Srobert   HasDylinkSection = true;
395*d415bd75Srobert 
396*d415bd75Srobert   const uint8_t *OrigEnd = Ctx.End;
397*d415bd75Srobert   while (Ctx.Ptr < OrigEnd) {
398*d415bd75Srobert     Ctx.End = OrigEnd;
399*d415bd75Srobert     uint8_t Type = readUint8(Ctx);
400*d415bd75Srobert     uint32_t Size = readVaruint32(Ctx);
401*d415bd75Srobert     LLVM_DEBUG(dbgs() << "readSubsection type=" << int(Type) << " size=" << Size
402*d415bd75Srobert                       << "\n");
403*d415bd75Srobert     Ctx.End = Ctx.Ptr + Size;
404*d415bd75Srobert     uint32_t Count;
405*d415bd75Srobert     switch (Type) {
406*d415bd75Srobert     case wasm::WASM_DYLINK_MEM_INFO:
407*d415bd75Srobert       DylinkInfo.MemorySize = readVaruint32(Ctx);
408*d415bd75Srobert       DylinkInfo.MemoryAlignment = readVaruint32(Ctx);
409*d415bd75Srobert       DylinkInfo.TableSize = readVaruint32(Ctx);
410*d415bd75Srobert       DylinkInfo.TableAlignment = readVaruint32(Ctx);
411*d415bd75Srobert       break;
412*d415bd75Srobert     case wasm::WASM_DYLINK_NEEDED:
413*d415bd75Srobert       Count = readVaruint32(Ctx);
414*d415bd75Srobert       while (Count--) {
415*d415bd75Srobert         DylinkInfo.Needed.push_back(readString(Ctx));
416*d415bd75Srobert       }
417*d415bd75Srobert       break;
418*d415bd75Srobert     case wasm::WASM_DYLINK_EXPORT_INFO: {
419*d415bd75Srobert       uint32_t Count = readVaruint32(Ctx);
420*d415bd75Srobert       while (Count--) {
421*d415bd75Srobert         DylinkInfo.ExportInfo.push_back({readString(Ctx), readVaruint32(Ctx)});
422*d415bd75Srobert       }
423*d415bd75Srobert       break;
424*d415bd75Srobert     }
425*d415bd75Srobert     case wasm::WASM_DYLINK_IMPORT_INFO: {
426*d415bd75Srobert       uint32_t Count = readVaruint32(Ctx);
427*d415bd75Srobert       while (Count--) {
428*d415bd75Srobert         DylinkInfo.ImportInfo.push_back(
429*d415bd75Srobert             {readString(Ctx), readString(Ctx), readVaruint32(Ctx)});
430*d415bd75Srobert       }
431*d415bd75Srobert       break;
432*d415bd75Srobert     }
433*d415bd75Srobert     default:
434*d415bd75Srobert       LLVM_DEBUG(dbgs() << "unknown dylink.0 sub-section: " << Type << "\n");
435*d415bd75Srobert       Ctx.Ptr += Size;
436*d415bd75Srobert       break;
437*d415bd75Srobert     }
438*d415bd75Srobert     if (Ctx.Ptr != Ctx.End) {
439*d415bd75Srobert       return make_error<GenericBinaryError>(
440*d415bd75Srobert           "dylink.0 sub-section ended prematurely", object_error::parse_failed);
441*d415bd75Srobert     }
442*d415bd75Srobert   }
443*d415bd75Srobert 
444*d415bd75Srobert   if (Ctx.Ptr != Ctx.End)
445*d415bd75Srobert     return make_error<GenericBinaryError>("dylink.0 section ended prematurely",
446*d415bd75Srobert                                           object_error::parse_failed);
447*d415bd75Srobert   return Error::success();
448*d415bd75Srobert }
449*d415bd75Srobert 
parseNameSection(ReadContext & Ctx)45009467b48Spatrick Error WasmObjectFile::parseNameSection(ReadContext &Ctx) {
45173471bf0Spatrick   llvm::DenseSet<uint64_t> SeenFunctions;
45273471bf0Spatrick   llvm::DenseSet<uint64_t> SeenGlobals;
45373471bf0Spatrick   llvm::DenseSet<uint64_t> SeenSegments;
45409467b48Spatrick 
45509467b48Spatrick   while (Ctx.Ptr < Ctx.End) {
45609467b48Spatrick     uint8_t Type = readUint8(Ctx);
45709467b48Spatrick     uint32_t Size = readVaruint32(Ctx);
45809467b48Spatrick     const uint8_t *SubSectionEnd = Ctx.Ptr + Size;
45909467b48Spatrick     switch (Type) {
46073471bf0Spatrick     case wasm::WASM_NAMES_FUNCTION:
46173471bf0Spatrick     case wasm::WASM_NAMES_GLOBAL:
46273471bf0Spatrick     case wasm::WASM_NAMES_DATA_SEGMENT: {
46309467b48Spatrick       uint32_t Count = readVaruint32(Ctx);
46409467b48Spatrick       while (Count--) {
46509467b48Spatrick         uint32_t Index = readVaruint32(Ctx);
46609467b48Spatrick         StringRef Name = readString(Ctx);
46773471bf0Spatrick         wasm::NameType nameType = wasm::NameType::FUNCTION;
46873471bf0Spatrick         if (Type == wasm::WASM_NAMES_FUNCTION) {
46973471bf0Spatrick           if (!SeenFunctions.insert(Index).second)
47073471bf0Spatrick             return make_error<GenericBinaryError>(
47173471bf0Spatrick                 "function named more than once", object_error::parse_failed);
47209467b48Spatrick           if (!isValidFunctionIndex(Index) || Name.empty())
473*d415bd75Srobert             return make_error<GenericBinaryError>("invalid function name entry",
47409467b48Spatrick                                                   object_error::parse_failed);
47573471bf0Spatrick 
47609467b48Spatrick           if (isDefinedFunctionIndex(Index))
47709467b48Spatrick             getDefinedFunction(Index).DebugName = Name;
47873471bf0Spatrick         } else if (Type == wasm::WASM_NAMES_GLOBAL) {
47973471bf0Spatrick           nameType = wasm::NameType::GLOBAL;
48073471bf0Spatrick           if (!SeenGlobals.insert(Index).second)
48173471bf0Spatrick             return make_error<GenericBinaryError>("global named more than once",
48273471bf0Spatrick                                                   object_error::parse_failed);
48373471bf0Spatrick           if (!isValidGlobalIndex(Index) || Name.empty())
484*d415bd75Srobert             return make_error<GenericBinaryError>("invalid global name entry",
48573471bf0Spatrick                                                   object_error::parse_failed);
48673471bf0Spatrick         } else {
48773471bf0Spatrick           nameType = wasm::NameType::DATA_SEGMENT;
48873471bf0Spatrick           if (!SeenSegments.insert(Index).second)
48973471bf0Spatrick             return make_error<GenericBinaryError>(
49073471bf0Spatrick                 "segment named more than once", object_error::parse_failed);
49173471bf0Spatrick           if (Index > DataSegments.size())
492*d415bd75Srobert             return make_error<GenericBinaryError>("invalid data segment name entry",
49373471bf0Spatrick                                                   object_error::parse_failed);
49473471bf0Spatrick         }
49573471bf0Spatrick         DebugNames.push_back(wasm::WasmDebugName{nameType, Index, Name});
49609467b48Spatrick       }
49709467b48Spatrick       break;
49809467b48Spatrick     }
49909467b48Spatrick     // Ignore local names for now
50009467b48Spatrick     case wasm::WASM_NAMES_LOCAL:
50109467b48Spatrick     default:
50209467b48Spatrick       Ctx.Ptr += Size;
50309467b48Spatrick       break;
50409467b48Spatrick     }
50509467b48Spatrick     if (Ctx.Ptr != SubSectionEnd)
50609467b48Spatrick       return make_error<GenericBinaryError>(
50773471bf0Spatrick           "name sub-section ended prematurely", object_error::parse_failed);
50809467b48Spatrick   }
50909467b48Spatrick 
51009467b48Spatrick   if (Ctx.Ptr != Ctx.End)
51173471bf0Spatrick     return make_error<GenericBinaryError>("name section ended prematurely",
51209467b48Spatrick                                           object_error::parse_failed);
51309467b48Spatrick   return Error::success();
51409467b48Spatrick }
51509467b48Spatrick 
parseLinkingSection(ReadContext & Ctx)51609467b48Spatrick Error WasmObjectFile::parseLinkingSection(ReadContext &Ctx) {
51709467b48Spatrick   HasLinkingSection = true;
51809467b48Spatrick 
51909467b48Spatrick   LinkingData.Version = readVaruint32(Ctx);
52009467b48Spatrick   if (LinkingData.Version != wasm::WasmMetadataVersion) {
52109467b48Spatrick     return make_error<GenericBinaryError>(
52273471bf0Spatrick         "unexpected metadata version: " + Twine(LinkingData.Version) +
52309467b48Spatrick             " (Expected: " + Twine(wasm::WasmMetadataVersion) + ")",
52409467b48Spatrick         object_error::parse_failed);
52509467b48Spatrick   }
52609467b48Spatrick 
52709467b48Spatrick   const uint8_t *OrigEnd = Ctx.End;
52809467b48Spatrick   while (Ctx.Ptr < OrigEnd) {
52909467b48Spatrick     Ctx.End = OrigEnd;
53009467b48Spatrick     uint8_t Type = readUint8(Ctx);
53109467b48Spatrick     uint32_t Size = readVaruint32(Ctx);
53209467b48Spatrick     LLVM_DEBUG(dbgs() << "readSubsection type=" << int(Type) << " size=" << Size
53309467b48Spatrick                       << "\n");
53409467b48Spatrick     Ctx.End = Ctx.Ptr + Size;
53509467b48Spatrick     switch (Type) {
53609467b48Spatrick     case wasm::WASM_SYMBOL_TABLE:
53709467b48Spatrick       if (Error Err = parseLinkingSectionSymtab(Ctx))
53809467b48Spatrick         return Err;
53909467b48Spatrick       break;
54009467b48Spatrick     case wasm::WASM_SEGMENT_INFO: {
54109467b48Spatrick       uint32_t Count = readVaruint32(Ctx);
54209467b48Spatrick       if (Count > DataSegments.size())
54373471bf0Spatrick         return make_error<GenericBinaryError>("too many segment names",
54409467b48Spatrick                                               object_error::parse_failed);
54509467b48Spatrick       for (uint32_t I = 0; I < Count; I++) {
54609467b48Spatrick         DataSegments[I].Data.Name = readString(Ctx);
54709467b48Spatrick         DataSegments[I].Data.Alignment = readVaruint32(Ctx);
54873471bf0Spatrick         DataSegments[I].Data.LinkingFlags = readVaruint32(Ctx);
54909467b48Spatrick       }
55009467b48Spatrick       break;
55109467b48Spatrick     }
55209467b48Spatrick     case wasm::WASM_INIT_FUNCS: {
55309467b48Spatrick       uint32_t Count = readVaruint32(Ctx);
55409467b48Spatrick       LinkingData.InitFunctions.reserve(Count);
55509467b48Spatrick       for (uint32_t I = 0; I < Count; I++) {
55609467b48Spatrick         wasm::WasmInitFunc Init;
55709467b48Spatrick         Init.Priority = readVaruint32(Ctx);
55809467b48Spatrick         Init.Symbol = readVaruint32(Ctx);
55909467b48Spatrick         if (!isValidFunctionSymbol(Init.Symbol))
56073471bf0Spatrick           return make_error<GenericBinaryError>("invalid function symbol: " +
56109467b48Spatrick                                                     Twine(Init.Symbol),
56209467b48Spatrick                                                 object_error::parse_failed);
56309467b48Spatrick         LinkingData.InitFunctions.emplace_back(Init);
56409467b48Spatrick       }
56509467b48Spatrick       break;
56609467b48Spatrick     }
56709467b48Spatrick     case wasm::WASM_COMDAT_INFO:
56809467b48Spatrick       if (Error Err = parseLinkingSectionComdat(Ctx))
56909467b48Spatrick         return Err;
57009467b48Spatrick       break;
57109467b48Spatrick     default:
57209467b48Spatrick       Ctx.Ptr += Size;
57309467b48Spatrick       break;
57409467b48Spatrick     }
57509467b48Spatrick     if (Ctx.Ptr != Ctx.End)
57609467b48Spatrick       return make_error<GenericBinaryError>(
57773471bf0Spatrick           "linking sub-section ended prematurely", object_error::parse_failed);
57809467b48Spatrick   }
57909467b48Spatrick   if (Ctx.Ptr != OrigEnd)
58073471bf0Spatrick     return make_error<GenericBinaryError>("linking section ended prematurely",
58109467b48Spatrick                                           object_error::parse_failed);
58209467b48Spatrick   return Error::success();
58309467b48Spatrick }
58409467b48Spatrick 
parseLinkingSectionSymtab(ReadContext & Ctx)58509467b48Spatrick Error WasmObjectFile::parseLinkingSectionSymtab(ReadContext &Ctx) {
58609467b48Spatrick   uint32_t Count = readVaruint32(Ctx);
58709467b48Spatrick   LinkingData.SymbolTable.reserve(Count);
58809467b48Spatrick   Symbols.reserve(Count);
58909467b48Spatrick   StringSet<> SymbolNames;
59009467b48Spatrick 
59109467b48Spatrick   std::vector<wasm::WasmImport *> ImportedGlobals;
59209467b48Spatrick   std::vector<wasm::WasmImport *> ImportedFunctions;
59373471bf0Spatrick   std::vector<wasm::WasmImport *> ImportedTags;
59473471bf0Spatrick   std::vector<wasm::WasmImport *> ImportedTables;
59509467b48Spatrick   ImportedGlobals.reserve(Imports.size());
59609467b48Spatrick   ImportedFunctions.reserve(Imports.size());
59773471bf0Spatrick   ImportedTags.reserve(Imports.size());
59873471bf0Spatrick   ImportedTables.reserve(Imports.size());
59909467b48Spatrick   for (auto &I : Imports) {
60009467b48Spatrick     if (I.Kind == wasm::WASM_EXTERNAL_FUNCTION)
60109467b48Spatrick       ImportedFunctions.emplace_back(&I);
60209467b48Spatrick     else if (I.Kind == wasm::WASM_EXTERNAL_GLOBAL)
60309467b48Spatrick       ImportedGlobals.emplace_back(&I);
60473471bf0Spatrick     else if (I.Kind == wasm::WASM_EXTERNAL_TAG)
60573471bf0Spatrick       ImportedTags.emplace_back(&I);
60673471bf0Spatrick     else if (I.Kind == wasm::WASM_EXTERNAL_TABLE)
60773471bf0Spatrick       ImportedTables.emplace_back(&I);
60809467b48Spatrick   }
60909467b48Spatrick 
61009467b48Spatrick   while (Count--) {
61109467b48Spatrick     wasm::WasmSymbolInfo Info;
61209467b48Spatrick     const wasm::WasmSignature *Signature = nullptr;
61309467b48Spatrick     const wasm::WasmGlobalType *GlobalType = nullptr;
61473471bf0Spatrick     const wasm::WasmTableType *TableType = nullptr;
61509467b48Spatrick 
61609467b48Spatrick     Info.Kind = readUint8(Ctx);
61709467b48Spatrick     Info.Flags = readVaruint32(Ctx);
61809467b48Spatrick     bool IsDefined = (Info.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0;
61909467b48Spatrick 
62009467b48Spatrick     switch (Info.Kind) {
62109467b48Spatrick     case wasm::WASM_SYMBOL_TYPE_FUNCTION:
62209467b48Spatrick       Info.ElementIndex = readVaruint32(Ctx);
62309467b48Spatrick       if (!isValidFunctionIndex(Info.ElementIndex) ||
62409467b48Spatrick           IsDefined != isDefinedFunctionIndex(Info.ElementIndex))
62509467b48Spatrick         return make_error<GenericBinaryError>("invalid function symbol index",
62609467b48Spatrick                                               object_error::parse_failed);
62709467b48Spatrick       if (IsDefined) {
62809467b48Spatrick         Info.Name = readString(Ctx);
62909467b48Spatrick         unsigned FuncIndex = Info.ElementIndex - NumImportedFunctions;
63009467b48Spatrick         wasm::WasmFunction &Function = Functions[FuncIndex];
631*d415bd75Srobert         Signature = &Signatures[Function.SigIndex];
63209467b48Spatrick         if (Function.SymbolName.empty())
63309467b48Spatrick           Function.SymbolName = Info.Name;
63409467b48Spatrick       } else {
63509467b48Spatrick         wasm::WasmImport &Import = *ImportedFunctions[Info.ElementIndex];
636097a140dSpatrick         if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0) {
63709467b48Spatrick           Info.Name = readString(Ctx);
63809467b48Spatrick           Info.ImportName = Import.Field;
639097a140dSpatrick         } else {
640097a140dSpatrick           Info.Name = Import.Field;
641097a140dSpatrick         }
642097a140dSpatrick         Signature = &Signatures[Import.SigIndex];
64309467b48Spatrick         Info.ImportModule = Import.Module;
64409467b48Spatrick       }
64509467b48Spatrick       break;
64609467b48Spatrick 
64709467b48Spatrick     case wasm::WASM_SYMBOL_TYPE_GLOBAL:
64809467b48Spatrick       Info.ElementIndex = readVaruint32(Ctx);
64909467b48Spatrick       if (!isValidGlobalIndex(Info.ElementIndex) ||
65009467b48Spatrick           IsDefined != isDefinedGlobalIndex(Info.ElementIndex))
65109467b48Spatrick         return make_error<GenericBinaryError>("invalid global symbol index",
65209467b48Spatrick                                               object_error::parse_failed);
65309467b48Spatrick       if (!IsDefined && (Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) ==
65409467b48Spatrick                             wasm::WASM_SYMBOL_BINDING_WEAK)
65509467b48Spatrick         return make_error<GenericBinaryError>("undefined weak global symbol",
65609467b48Spatrick                                               object_error::parse_failed);
65709467b48Spatrick       if (IsDefined) {
65809467b48Spatrick         Info.Name = readString(Ctx);
65909467b48Spatrick         unsigned GlobalIndex = Info.ElementIndex - NumImportedGlobals;
66009467b48Spatrick         wasm::WasmGlobal &Global = Globals[GlobalIndex];
66109467b48Spatrick         GlobalType = &Global.Type;
66209467b48Spatrick         if (Global.SymbolName.empty())
66309467b48Spatrick           Global.SymbolName = Info.Name;
66409467b48Spatrick       } else {
66509467b48Spatrick         wasm::WasmImport &Import = *ImportedGlobals[Info.ElementIndex];
666097a140dSpatrick         if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0) {
66709467b48Spatrick           Info.Name = readString(Ctx);
668097a140dSpatrick           Info.ImportName = Import.Field;
669097a140dSpatrick         } else {
67009467b48Spatrick           Info.Name = Import.Field;
671097a140dSpatrick         }
67209467b48Spatrick         GlobalType = &Import.Global;
67373471bf0Spatrick         Info.ImportModule = Import.Module;
67473471bf0Spatrick       }
67573471bf0Spatrick       break;
67673471bf0Spatrick 
67773471bf0Spatrick     case wasm::WASM_SYMBOL_TYPE_TABLE:
67873471bf0Spatrick       Info.ElementIndex = readVaruint32(Ctx);
67973471bf0Spatrick       if (!isValidTableNumber(Info.ElementIndex) ||
68073471bf0Spatrick           IsDefined != isDefinedTableNumber(Info.ElementIndex))
68173471bf0Spatrick         return make_error<GenericBinaryError>("invalid table symbol index",
68273471bf0Spatrick                                               object_error::parse_failed);
68373471bf0Spatrick       if (!IsDefined && (Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) ==
68473471bf0Spatrick                             wasm::WASM_SYMBOL_BINDING_WEAK)
68573471bf0Spatrick         return make_error<GenericBinaryError>("undefined weak table symbol",
68673471bf0Spatrick                                               object_error::parse_failed);
68773471bf0Spatrick       if (IsDefined) {
68873471bf0Spatrick         Info.Name = readString(Ctx);
68973471bf0Spatrick         unsigned TableNumber = Info.ElementIndex - NumImportedTables;
69073471bf0Spatrick         wasm::WasmTable &Table = Tables[TableNumber];
69173471bf0Spatrick         TableType = &Table.Type;
69273471bf0Spatrick         if (Table.SymbolName.empty())
69373471bf0Spatrick           Table.SymbolName = Info.Name;
69473471bf0Spatrick       } else {
69573471bf0Spatrick         wasm::WasmImport &Import = *ImportedTables[Info.ElementIndex];
69673471bf0Spatrick         if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0) {
69773471bf0Spatrick           Info.Name = readString(Ctx);
69809467b48Spatrick           Info.ImportName = Import.Field;
69973471bf0Spatrick         } else {
70073471bf0Spatrick           Info.Name = Import.Field;
70173471bf0Spatrick         }
70273471bf0Spatrick         TableType = &Import.Table;
70309467b48Spatrick         Info.ImportModule = Import.Module;
70409467b48Spatrick       }
70509467b48Spatrick       break;
70609467b48Spatrick 
70709467b48Spatrick     case wasm::WASM_SYMBOL_TYPE_DATA:
70809467b48Spatrick       Info.Name = readString(Ctx);
70909467b48Spatrick       if (IsDefined) {
710097a140dSpatrick         auto Index = readVaruint32(Ctx);
71109467b48Spatrick         if (Index >= DataSegments.size())
71209467b48Spatrick           return make_error<GenericBinaryError>("invalid data symbol index",
71309467b48Spatrick                                                 object_error::parse_failed);
714097a140dSpatrick         auto Offset = readVaruint64(Ctx);
715097a140dSpatrick         auto Size = readVaruint64(Ctx);
71673471bf0Spatrick         size_t SegmentSize = DataSegments[Index].Data.Content.size();
71773471bf0Spatrick         if (Offset > SegmentSize)
71873471bf0Spatrick           return make_error<GenericBinaryError>(
71973471bf0Spatrick               "invalid data symbol offset: `" + Info.Name + "` (offset: " +
72073471bf0Spatrick                   Twine(Offset) + " segment size: " + Twine(SegmentSize) + ")",
72109467b48Spatrick               object_error::parse_failed);
72209467b48Spatrick         Info.DataRef = wasm::WasmDataReference{Index, Offset, Size};
72309467b48Spatrick       }
72409467b48Spatrick       break;
72509467b48Spatrick 
72609467b48Spatrick     case wasm::WASM_SYMBOL_TYPE_SECTION: {
72709467b48Spatrick       if ((Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) !=
72809467b48Spatrick           wasm::WASM_SYMBOL_BINDING_LOCAL)
72909467b48Spatrick         return make_error<GenericBinaryError>(
73073471bf0Spatrick             "section symbols must have local binding",
73109467b48Spatrick             object_error::parse_failed);
73209467b48Spatrick       Info.ElementIndex = readVaruint32(Ctx);
73309467b48Spatrick       // Use somewhat unique section name as symbol name.
73409467b48Spatrick       StringRef SectionName = Sections[Info.ElementIndex].Name;
73509467b48Spatrick       Info.Name = SectionName;
73609467b48Spatrick       break;
73709467b48Spatrick     }
73809467b48Spatrick 
73973471bf0Spatrick     case wasm::WASM_SYMBOL_TYPE_TAG: {
74009467b48Spatrick       Info.ElementIndex = readVaruint32(Ctx);
74173471bf0Spatrick       if (!isValidTagIndex(Info.ElementIndex) ||
74273471bf0Spatrick           IsDefined != isDefinedTagIndex(Info.ElementIndex))
74373471bf0Spatrick         return make_error<GenericBinaryError>("invalid tag symbol index",
74409467b48Spatrick                                               object_error::parse_failed);
74509467b48Spatrick       if (!IsDefined && (Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) ==
74609467b48Spatrick                             wasm::WASM_SYMBOL_BINDING_WEAK)
74709467b48Spatrick         return make_error<GenericBinaryError>("undefined weak global symbol",
74809467b48Spatrick                                               object_error::parse_failed);
74909467b48Spatrick       if (IsDefined) {
75009467b48Spatrick         Info.Name = readString(Ctx);
75173471bf0Spatrick         unsigned TagIndex = Info.ElementIndex - NumImportedTags;
75273471bf0Spatrick         wasm::WasmTag &Tag = Tags[TagIndex];
753*d415bd75Srobert         Signature = &Signatures[Tag.SigIndex];
75473471bf0Spatrick         if (Tag.SymbolName.empty())
75573471bf0Spatrick           Tag.SymbolName = Info.Name;
75609467b48Spatrick 
75709467b48Spatrick       } else {
75873471bf0Spatrick         wasm::WasmImport &Import = *ImportedTags[Info.ElementIndex];
759097a140dSpatrick         if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0) {
76009467b48Spatrick           Info.Name = readString(Ctx);
761097a140dSpatrick           Info.ImportName = Import.Field;
762097a140dSpatrick         } else {
76309467b48Spatrick           Info.Name = Import.Field;
764097a140dSpatrick         }
765*d415bd75Srobert         Signature = &Signatures[Import.SigIndex];
76609467b48Spatrick         Info.ImportModule = Import.Module;
76709467b48Spatrick       }
76809467b48Spatrick       break;
76909467b48Spatrick     }
77009467b48Spatrick 
77109467b48Spatrick     default:
77273471bf0Spatrick       return make_error<GenericBinaryError>("invalid symbol type: " +
77373471bf0Spatrick                                                 Twine(unsigned(Info.Kind)),
77409467b48Spatrick                                             object_error::parse_failed);
77509467b48Spatrick     }
77609467b48Spatrick 
77709467b48Spatrick     if ((Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) !=
77809467b48Spatrick             wasm::WASM_SYMBOL_BINDING_LOCAL &&
77909467b48Spatrick         !SymbolNames.insert(Info.Name).second)
78073471bf0Spatrick       return make_error<GenericBinaryError>("duplicate symbol name " +
78109467b48Spatrick                                                 Twine(Info.Name),
78209467b48Spatrick                                             object_error::parse_failed);
78309467b48Spatrick     LinkingData.SymbolTable.emplace_back(Info);
78473471bf0Spatrick     Symbols.emplace_back(LinkingData.SymbolTable.back(), GlobalType, TableType,
785*d415bd75Srobert                          Signature);
78609467b48Spatrick     LLVM_DEBUG(dbgs() << "Adding symbol: " << Symbols.back() << "\n");
78709467b48Spatrick   }
78809467b48Spatrick 
78909467b48Spatrick   return Error::success();
79009467b48Spatrick }
79109467b48Spatrick 
parseLinkingSectionComdat(ReadContext & Ctx)79209467b48Spatrick Error WasmObjectFile::parseLinkingSectionComdat(ReadContext &Ctx) {
79309467b48Spatrick   uint32_t ComdatCount = readVaruint32(Ctx);
79409467b48Spatrick   StringSet<> ComdatSet;
79509467b48Spatrick   for (unsigned ComdatIndex = 0; ComdatIndex < ComdatCount; ++ComdatIndex) {
79609467b48Spatrick     StringRef Name = readString(Ctx);
79709467b48Spatrick     if (Name.empty() || !ComdatSet.insert(Name).second)
79873471bf0Spatrick       return make_error<GenericBinaryError>("bad/duplicate COMDAT name " +
79909467b48Spatrick                                                 Twine(Name),
80009467b48Spatrick                                             object_error::parse_failed);
80109467b48Spatrick     LinkingData.Comdats.emplace_back(Name);
80209467b48Spatrick     uint32_t Flags = readVaruint32(Ctx);
80309467b48Spatrick     if (Flags != 0)
80473471bf0Spatrick       return make_error<GenericBinaryError>("unsupported COMDAT flags",
80509467b48Spatrick                                             object_error::parse_failed);
80609467b48Spatrick 
80709467b48Spatrick     uint32_t EntryCount = readVaruint32(Ctx);
80809467b48Spatrick     while (EntryCount--) {
80909467b48Spatrick       unsigned Kind = readVaruint32(Ctx);
81009467b48Spatrick       unsigned Index = readVaruint32(Ctx);
81109467b48Spatrick       switch (Kind) {
81209467b48Spatrick       default:
81373471bf0Spatrick         return make_error<GenericBinaryError>("invalid COMDAT entry type",
81409467b48Spatrick                                               object_error::parse_failed);
81509467b48Spatrick       case wasm::WASM_COMDAT_DATA:
81609467b48Spatrick         if (Index >= DataSegments.size())
81709467b48Spatrick           return make_error<GenericBinaryError>(
81809467b48Spatrick               "COMDAT data index out of range", object_error::parse_failed);
81909467b48Spatrick         if (DataSegments[Index].Data.Comdat != UINT32_MAX)
82073471bf0Spatrick           return make_error<GenericBinaryError>("data segment in two COMDATs",
82109467b48Spatrick                                                 object_error::parse_failed);
82209467b48Spatrick         DataSegments[Index].Data.Comdat = ComdatIndex;
82309467b48Spatrick         break;
82409467b48Spatrick       case wasm::WASM_COMDAT_FUNCTION:
82509467b48Spatrick         if (!isDefinedFunctionIndex(Index))
82609467b48Spatrick           return make_error<GenericBinaryError>(
82709467b48Spatrick               "COMDAT function index out of range", object_error::parse_failed);
82809467b48Spatrick         if (getDefinedFunction(Index).Comdat != UINT32_MAX)
82973471bf0Spatrick           return make_error<GenericBinaryError>("function in two COMDATs",
83009467b48Spatrick                                                 object_error::parse_failed);
83109467b48Spatrick         getDefinedFunction(Index).Comdat = ComdatIndex;
83209467b48Spatrick         break;
83373471bf0Spatrick       case wasm::WASM_COMDAT_SECTION:
83473471bf0Spatrick         if (Index >= Sections.size())
83573471bf0Spatrick           return make_error<GenericBinaryError>(
83673471bf0Spatrick               "COMDAT section index out of range", object_error::parse_failed);
83773471bf0Spatrick         if (Sections[Index].Type != wasm::WASM_SEC_CUSTOM)
83873471bf0Spatrick           return make_error<GenericBinaryError>(
83973471bf0Spatrick               "non-custom section in a COMDAT", object_error::parse_failed);
84073471bf0Spatrick         Sections[Index].Comdat = ComdatIndex;
84173471bf0Spatrick         break;
84209467b48Spatrick       }
84309467b48Spatrick     }
84409467b48Spatrick   }
84509467b48Spatrick   return Error::success();
84609467b48Spatrick }
84709467b48Spatrick 
parseProducersSection(ReadContext & Ctx)84809467b48Spatrick Error WasmObjectFile::parseProducersSection(ReadContext &Ctx) {
84909467b48Spatrick   llvm::SmallSet<StringRef, 3> FieldsSeen;
85009467b48Spatrick   uint32_t Fields = readVaruint32(Ctx);
85109467b48Spatrick   for (size_t I = 0; I < Fields; ++I) {
85209467b48Spatrick     StringRef FieldName = readString(Ctx);
85309467b48Spatrick     if (!FieldsSeen.insert(FieldName).second)
85409467b48Spatrick       return make_error<GenericBinaryError>(
85573471bf0Spatrick           "producers section does not have unique fields",
85609467b48Spatrick           object_error::parse_failed);
85709467b48Spatrick     std::vector<std::pair<std::string, std::string>> *ProducerVec = nullptr;
85809467b48Spatrick     if (FieldName == "language") {
85909467b48Spatrick       ProducerVec = &ProducerInfo.Languages;
86009467b48Spatrick     } else if (FieldName == "processed-by") {
86109467b48Spatrick       ProducerVec = &ProducerInfo.Tools;
86209467b48Spatrick     } else if (FieldName == "sdk") {
86309467b48Spatrick       ProducerVec = &ProducerInfo.SDKs;
86409467b48Spatrick     } else {
86509467b48Spatrick       return make_error<GenericBinaryError>(
86673471bf0Spatrick           "producers section field is not named one of language, processed-by, "
86709467b48Spatrick           "or sdk",
86809467b48Spatrick           object_error::parse_failed);
86909467b48Spatrick     }
87009467b48Spatrick     uint32_t ValueCount = readVaruint32(Ctx);
87109467b48Spatrick     llvm::SmallSet<StringRef, 8> ProducersSeen;
87209467b48Spatrick     for (size_t J = 0; J < ValueCount; ++J) {
87309467b48Spatrick       StringRef Name = readString(Ctx);
87409467b48Spatrick       StringRef Version = readString(Ctx);
87509467b48Spatrick       if (!ProducersSeen.insert(Name).second) {
87609467b48Spatrick         return make_error<GenericBinaryError>(
87773471bf0Spatrick             "producers section contains repeated producer",
87809467b48Spatrick             object_error::parse_failed);
87909467b48Spatrick       }
880097a140dSpatrick       ProducerVec->emplace_back(std::string(Name), std::string(Version));
88109467b48Spatrick     }
88209467b48Spatrick   }
88309467b48Spatrick   if (Ctx.Ptr != Ctx.End)
88473471bf0Spatrick     return make_error<GenericBinaryError>("producers section ended prematurely",
88509467b48Spatrick                                           object_error::parse_failed);
88609467b48Spatrick   return Error::success();
88709467b48Spatrick }
88809467b48Spatrick 
parseTargetFeaturesSection(ReadContext & Ctx)88909467b48Spatrick Error WasmObjectFile::parseTargetFeaturesSection(ReadContext &Ctx) {
89009467b48Spatrick   llvm::SmallSet<std::string, 8> FeaturesSeen;
89109467b48Spatrick   uint32_t FeatureCount = readVaruint32(Ctx);
89209467b48Spatrick   for (size_t I = 0; I < FeatureCount; ++I) {
89309467b48Spatrick     wasm::WasmFeatureEntry Feature;
89409467b48Spatrick     Feature.Prefix = readUint8(Ctx);
89509467b48Spatrick     switch (Feature.Prefix) {
89609467b48Spatrick     case wasm::WASM_FEATURE_PREFIX_USED:
89709467b48Spatrick     case wasm::WASM_FEATURE_PREFIX_REQUIRED:
89809467b48Spatrick     case wasm::WASM_FEATURE_PREFIX_DISALLOWED:
89909467b48Spatrick       break;
90009467b48Spatrick     default:
90173471bf0Spatrick       return make_error<GenericBinaryError>("unknown feature policy prefix",
90209467b48Spatrick                                             object_error::parse_failed);
90309467b48Spatrick     }
904097a140dSpatrick     Feature.Name = std::string(readString(Ctx));
90509467b48Spatrick     if (!FeaturesSeen.insert(Feature.Name).second)
90609467b48Spatrick       return make_error<GenericBinaryError>(
90773471bf0Spatrick           "target features section contains repeated feature \"" +
90809467b48Spatrick               Feature.Name + "\"",
90909467b48Spatrick           object_error::parse_failed);
91009467b48Spatrick     TargetFeatures.push_back(Feature);
91109467b48Spatrick   }
91209467b48Spatrick   if (Ctx.Ptr != Ctx.End)
91309467b48Spatrick     return make_error<GenericBinaryError>(
91473471bf0Spatrick         "target features section ended prematurely",
91509467b48Spatrick         object_error::parse_failed);
91609467b48Spatrick   return Error::success();
91709467b48Spatrick }
91809467b48Spatrick 
parseRelocSection(StringRef Name,ReadContext & Ctx)91909467b48Spatrick Error WasmObjectFile::parseRelocSection(StringRef Name, ReadContext &Ctx) {
92009467b48Spatrick   uint32_t SectionIndex = readVaruint32(Ctx);
92109467b48Spatrick   if (SectionIndex >= Sections.size())
92273471bf0Spatrick     return make_error<GenericBinaryError>("invalid section index",
92309467b48Spatrick                                           object_error::parse_failed);
92409467b48Spatrick   WasmSection &Section = Sections[SectionIndex];
92509467b48Spatrick   uint32_t RelocCount = readVaruint32(Ctx);
92609467b48Spatrick   uint32_t EndOffset = Section.Content.size();
92709467b48Spatrick   uint32_t PreviousOffset = 0;
92809467b48Spatrick   while (RelocCount--) {
92909467b48Spatrick     wasm::WasmRelocation Reloc = {};
93073471bf0Spatrick     uint32_t type = readVaruint32(Ctx);
93173471bf0Spatrick     Reloc.Type = type;
93209467b48Spatrick     Reloc.Offset = readVaruint32(Ctx);
93309467b48Spatrick     if (Reloc.Offset < PreviousOffset)
93473471bf0Spatrick       return make_error<GenericBinaryError>("relocations not in offset order",
93509467b48Spatrick                                             object_error::parse_failed);
93609467b48Spatrick     PreviousOffset = Reloc.Offset;
93709467b48Spatrick     Reloc.Index = readVaruint32(Ctx);
93873471bf0Spatrick     switch (type) {
93909467b48Spatrick     case wasm::R_WASM_FUNCTION_INDEX_LEB:
94009467b48Spatrick     case wasm::R_WASM_TABLE_INDEX_SLEB:
94173471bf0Spatrick     case wasm::R_WASM_TABLE_INDEX_SLEB64:
94209467b48Spatrick     case wasm::R_WASM_TABLE_INDEX_I32:
94373471bf0Spatrick     case wasm::R_WASM_TABLE_INDEX_I64:
94409467b48Spatrick     case wasm::R_WASM_TABLE_INDEX_REL_SLEB:
94573471bf0Spatrick     case wasm::R_WASM_TABLE_INDEX_REL_SLEB64:
94609467b48Spatrick       if (!isValidFunctionSymbol(Reloc.Index))
94773471bf0Spatrick         return make_error<GenericBinaryError>(
94873471bf0Spatrick             "invalid relocation function index", object_error::parse_failed);
94973471bf0Spatrick       break;
95073471bf0Spatrick     case wasm::R_WASM_TABLE_NUMBER_LEB:
95173471bf0Spatrick       if (!isValidTableSymbol(Reloc.Index))
95273471bf0Spatrick         return make_error<GenericBinaryError>("invalid relocation table index",
95309467b48Spatrick                                               object_error::parse_failed);
95409467b48Spatrick       break;
95509467b48Spatrick     case wasm::R_WASM_TYPE_INDEX_LEB:
95609467b48Spatrick       if (Reloc.Index >= Signatures.size())
95773471bf0Spatrick         return make_error<GenericBinaryError>("invalid relocation type index",
95809467b48Spatrick                                               object_error::parse_failed);
95909467b48Spatrick       break;
96009467b48Spatrick     case wasm::R_WASM_GLOBAL_INDEX_LEB:
96109467b48Spatrick       // R_WASM_GLOBAL_INDEX_LEB are can be used against function and data
96209467b48Spatrick       // symbols to refer to their GOT entries.
96309467b48Spatrick       if (!isValidGlobalSymbol(Reloc.Index) &&
96409467b48Spatrick           !isValidDataSymbol(Reloc.Index) &&
96509467b48Spatrick           !isValidFunctionSymbol(Reloc.Index))
96673471bf0Spatrick         return make_error<GenericBinaryError>("invalid relocation global index",
96709467b48Spatrick                                               object_error::parse_failed);
96809467b48Spatrick       break;
969097a140dSpatrick     case wasm::R_WASM_GLOBAL_INDEX_I32:
970097a140dSpatrick       if (!isValidGlobalSymbol(Reloc.Index))
97173471bf0Spatrick         return make_error<GenericBinaryError>("invalid relocation global index",
972097a140dSpatrick                                               object_error::parse_failed);
973097a140dSpatrick       break;
97473471bf0Spatrick     case wasm::R_WASM_TAG_INDEX_LEB:
97573471bf0Spatrick       if (!isValidTagSymbol(Reloc.Index))
97673471bf0Spatrick         return make_error<GenericBinaryError>("invalid relocation tag index",
97709467b48Spatrick                                               object_error::parse_failed);
97809467b48Spatrick       break;
97909467b48Spatrick     case wasm::R_WASM_MEMORY_ADDR_LEB:
98009467b48Spatrick     case wasm::R_WASM_MEMORY_ADDR_SLEB:
98109467b48Spatrick     case wasm::R_WASM_MEMORY_ADDR_I32:
98209467b48Spatrick     case wasm::R_WASM_MEMORY_ADDR_REL_SLEB:
98373471bf0Spatrick     case wasm::R_WASM_MEMORY_ADDR_TLS_SLEB:
98473471bf0Spatrick     case wasm::R_WASM_MEMORY_ADDR_LOCREL_I32:
98509467b48Spatrick       if (!isValidDataSymbol(Reloc.Index))
98673471bf0Spatrick         return make_error<GenericBinaryError>("invalid relocation data index",
98709467b48Spatrick                                               object_error::parse_failed);
98809467b48Spatrick       Reloc.Addend = readVarint32(Ctx);
98909467b48Spatrick       break;
990097a140dSpatrick     case wasm::R_WASM_MEMORY_ADDR_LEB64:
991097a140dSpatrick     case wasm::R_WASM_MEMORY_ADDR_SLEB64:
992097a140dSpatrick     case wasm::R_WASM_MEMORY_ADDR_I64:
993097a140dSpatrick     case wasm::R_WASM_MEMORY_ADDR_REL_SLEB64:
99473471bf0Spatrick     case wasm::R_WASM_MEMORY_ADDR_TLS_SLEB64:
995097a140dSpatrick       if (!isValidDataSymbol(Reloc.Index))
99673471bf0Spatrick         return make_error<GenericBinaryError>("invalid relocation data index",
997097a140dSpatrick                                               object_error::parse_failed);
998097a140dSpatrick       Reloc.Addend = readVarint64(Ctx);
999097a140dSpatrick       break;
100009467b48Spatrick     case wasm::R_WASM_FUNCTION_OFFSET_I32:
100109467b48Spatrick       if (!isValidFunctionSymbol(Reloc.Index))
100273471bf0Spatrick         return make_error<GenericBinaryError>(
100373471bf0Spatrick             "invalid relocation function index", object_error::parse_failed);
100409467b48Spatrick       Reloc.Addend = readVarint32(Ctx);
100509467b48Spatrick       break;
100673471bf0Spatrick     case wasm::R_WASM_FUNCTION_OFFSET_I64:
100773471bf0Spatrick       if (!isValidFunctionSymbol(Reloc.Index))
100873471bf0Spatrick         return make_error<GenericBinaryError>(
100973471bf0Spatrick             "invalid relocation function index", object_error::parse_failed);
101073471bf0Spatrick       Reloc.Addend = readVarint64(Ctx);
101173471bf0Spatrick       break;
101209467b48Spatrick     case wasm::R_WASM_SECTION_OFFSET_I32:
101309467b48Spatrick       if (!isValidSectionSymbol(Reloc.Index))
101473471bf0Spatrick         return make_error<GenericBinaryError>(
101573471bf0Spatrick             "invalid relocation section index", object_error::parse_failed);
101609467b48Spatrick       Reloc.Addend = readVarint32(Ctx);
101709467b48Spatrick       break;
101809467b48Spatrick     default:
101973471bf0Spatrick       return make_error<GenericBinaryError>("invalid relocation type: " +
102073471bf0Spatrick                                                 Twine(type),
102109467b48Spatrick                                             object_error::parse_failed);
102209467b48Spatrick     }
102309467b48Spatrick 
102409467b48Spatrick     // Relocations must fit inside the section, and must appear in order.  They
102509467b48Spatrick     // also shouldn't overlap a function/element boundary, but we don't bother
102609467b48Spatrick     // to check that.
102709467b48Spatrick     uint64_t Size = 5;
1028097a140dSpatrick     if (Reloc.Type == wasm::R_WASM_MEMORY_ADDR_LEB64 ||
1029097a140dSpatrick         Reloc.Type == wasm::R_WASM_MEMORY_ADDR_SLEB64 ||
1030097a140dSpatrick         Reloc.Type == wasm::R_WASM_MEMORY_ADDR_REL_SLEB64)
1031097a140dSpatrick       Size = 10;
103209467b48Spatrick     if (Reloc.Type == wasm::R_WASM_TABLE_INDEX_I32 ||
103309467b48Spatrick         Reloc.Type == wasm::R_WASM_MEMORY_ADDR_I32 ||
103473471bf0Spatrick         Reloc.Type == wasm::R_WASM_MEMORY_ADDR_LOCREL_I32 ||
103509467b48Spatrick         Reloc.Type == wasm::R_WASM_SECTION_OFFSET_I32 ||
1036097a140dSpatrick         Reloc.Type == wasm::R_WASM_FUNCTION_OFFSET_I32 ||
1037097a140dSpatrick         Reloc.Type == wasm::R_WASM_GLOBAL_INDEX_I32)
103809467b48Spatrick       Size = 4;
103973471bf0Spatrick     if (Reloc.Type == wasm::R_WASM_TABLE_INDEX_I64 ||
104073471bf0Spatrick         Reloc.Type == wasm::R_WASM_MEMORY_ADDR_I64 ||
104173471bf0Spatrick         Reloc.Type == wasm::R_WASM_FUNCTION_OFFSET_I64)
1042097a140dSpatrick       Size = 8;
104309467b48Spatrick     if (Reloc.Offset + Size > EndOffset)
104473471bf0Spatrick       return make_error<GenericBinaryError>("invalid relocation offset",
104509467b48Spatrick                                             object_error::parse_failed);
104609467b48Spatrick 
104709467b48Spatrick     Section.Relocations.push_back(Reloc);
104809467b48Spatrick   }
104909467b48Spatrick   if (Ctx.Ptr != Ctx.End)
105073471bf0Spatrick     return make_error<GenericBinaryError>("reloc section ended prematurely",
105109467b48Spatrick                                           object_error::parse_failed);
105209467b48Spatrick   return Error::success();
105309467b48Spatrick }
105409467b48Spatrick 
parseCustomSection(WasmSection & Sec,ReadContext & Ctx)105509467b48Spatrick Error WasmObjectFile::parseCustomSection(WasmSection &Sec, ReadContext &Ctx) {
105609467b48Spatrick   if (Sec.Name == "dylink") {
105709467b48Spatrick     if (Error Err = parseDylinkSection(Ctx))
105809467b48Spatrick       return Err;
1059*d415bd75Srobert   } else if (Sec.Name == "dylink.0") {
1060*d415bd75Srobert     if (Error Err = parseDylink0Section(Ctx))
1061*d415bd75Srobert       return Err;
106209467b48Spatrick   } else if (Sec.Name == "name") {
106309467b48Spatrick     if (Error Err = parseNameSection(Ctx))
106409467b48Spatrick       return Err;
106509467b48Spatrick   } else if (Sec.Name == "linking") {
106609467b48Spatrick     if (Error Err = parseLinkingSection(Ctx))
106709467b48Spatrick       return Err;
106809467b48Spatrick   } else if (Sec.Name == "producers") {
106909467b48Spatrick     if (Error Err = parseProducersSection(Ctx))
107009467b48Spatrick       return Err;
107109467b48Spatrick   } else if (Sec.Name == "target_features") {
107209467b48Spatrick     if (Error Err = parseTargetFeaturesSection(Ctx))
107309467b48Spatrick       return Err;
107409467b48Spatrick   } else if (Sec.Name.startswith("reloc.")) {
107509467b48Spatrick     if (Error Err = parseRelocSection(Sec.Name, Ctx))
107609467b48Spatrick       return Err;
107709467b48Spatrick   }
107809467b48Spatrick   return Error::success();
107909467b48Spatrick }
108009467b48Spatrick 
parseTypeSection(ReadContext & Ctx)108109467b48Spatrick Error WasmObjectFile::parseTypeSection(ReadContext &Ctx) {
108209467b48Spatrick   uint32_t Count = readVaruint32(Ctx);
108309467b48Spatrick   Signatures.reserve(Count);
108409467b48Spatrick   while (Count--) {
108509467b48Spatrick     wasm::WasmSignature Sig;
108609467b48Spatrick     uint8_t Form = readUint8(Ctx);
108709467b48Spatrick     if (Form != wasm::WASM_TYPE_FUNC) {
108873471bf0Spatrick       return make_error<GenericBinaryError>("invalid signature type",
108909467b48Spatrick                                             object_error::parse_failed);
109009467b48Spatrick     }
109109467b48Spatrick     uint32_t ParamCount = readVaruint32(Ctx);
109209467b48Spatrick     Sig.Params.reserve(ParamCount);
109309467b48Spatrick     while (ParamCount--) {
109409467b48Spatrick       uint32_t ParamType = readUint8(Ctx);
109509467b48Spatrick       Sig.Params.push_back(wasm::ValType(ParamType));
109609467b48Spatrick     }
109709467b48Spatrick     uint32_t ReturnCount = readVaruint32(Ctx);
109809467b48Spatrick     while (ReturnCount--) {
109909467b48Spatrick       uint32_t ReturnType = readUint8(Ctx);
110009467b48Spatrick       Sig.Returns.push_back(wasm::ValType(ReturnType));
110109467b48Spatrick     }
110209467b48Spatrick     Signatures.push_back(std::move(Sig));
110309467b48Spatrick   }
110409467b48Spatrick   if (Ctx.Ptr != Ctx.End)
110573471bf0Spatrick     return make_error<GenericBinaryError>("type section ended prematurely",
110609467b48Spatrick                                           object_error::parse_failed);
110709467b48Spatrick   return Error::success();
110809467b48Spatrick }
110909467b48Spatrick 
parseImportSection(ReadContext & Ctx)111009467b48Spatrick Error WasmObjectFile::parseImportSection(ReadContext &Ctx) {
111109467b48Spatrick   uint32_t Count = readVaruint32(Ctx);
1112*d415bd75Srobert   uint32_t NumTypes = Signatures.size();
111309467b48Spatrick   Imports.reserve(Count);
111409467b48Spatrick   for (uint32_t I = 0; I < Count; I++) {
111509467b48Spatrick     wasm::WasmImport Im;
111609467b48Spatrick     Im.Module = readString(Ctx);
111709467b48Spatrick     Im.Field = readString(Ctx);
111809467b48Spatrick     Im.Kind = readUint8(Ctx);
111909467b48Spatrick     switch (Im.Kind) {
112009467b48Spatrick     case wasm::WASM_EXTERNAL_FUNCTION:
112109467b48Spatrick       NumImportedFunctions++;
112209467b48Spatrick       Im.SigIndex = readVaruint32(Ctx);
1123*d415bd75Srobert       if (Im.SigIndex >= NumTypes)
1124*d415bd75Srobert         return make_error<GenericBinaryError>("invalid function type",
1125*d415bd75Srobert                                               object_error::parse_failed);
112609467b48Spatrick       break;
112709467b48Spatrick     case wasm::WASM_EXTERNAL_GLOBAL:
112809467b48Spatrick       NumImportedGlobals++;
112909467b48Spatrick       Im.Global.Type = readUint8(Ctx);
113009467b48Spatrick       Im.Global.Mutable = readVaruint1(Ctx);
113109467b48Spatrick       break;
113209467b48Spatrick     case wasm::WASM_EXTERNAL_MEMORY:
113309467b48Spatrick       Im.Memory = readLimits(Ctx);
113473471bf0Spatrick       if (Im.Memory.Flags & wasm::WASM_LIMITS_FLAG_IS_64)
113573471bf0Spatrick         HasMemory64 = true;
113609467b48Spatrick       break;
113773471bf0Spatrick     case wasm::WASM_EXTERNAL_TABLE: {
113873471bf0Spatrick       Im.Table = readTableType(Ctx);
113973471bf0Spatrick       NumImportedTables++;
114073471bf0Spatrick       auto ElemType = Im.Table.ElemType;
114173471bf0Spatrick       if (ElemType != wasm::WASM_TYPE_FUNCREF &&
114273471bf0Spatrick           ElemType != wasm::WASM_TYPE_EXTERNREF)
114373471bf0Spatrick         return make_error<GenericBinaryError>("invalid table element type",
114409467b48Spatrick                                               object_error::parse_failed);
114509467b48Spatrick       break;
114673471bf0Spatrick     }
114773471bf0Spatrick     case wasm::WASM_EXTERNAL_TAG:
114873471bf0Spatrick       NumImportedTags++;
1149*d415bd75Srobert       if (readUint8(Ctx) != 0) // Reserved 'attribute' field
1150*d415bd75Srobert         return make_error<GenericBinaryError>("invalid attribute",
1151*d415bd75Srobert                                               object_error::parse_failed);
1152*d415bd75Srobert       Im.SigIndex = readVaruint32(Ctx);
1153*d415bd75Srobert       if (Im.SigIndex >= NumTypes)
1154*d415bd75Srobert         return make_error<GenericBinaryError>("invalid tag type",
1155*d415bd75Srobert                                               object_error::parse_failed);
115609467b48Spatrick       break;
115709467b48Spatrick     default:
115873471bf0Spatrick       return make_error<GenericBinaryError>("unexpected import kind",
115909467b48Spatrick                                             object_error::parse_failed);
116009467b48Spatrick     }
116109467b48Spatrick     Imports.push_back(Im);
116209467b48Spatrick   }
116309467b48Spatrick   if (Ctx.Ptr != Ctx.End)
116473471bf0Spatrick     return make_error<GenericBinaryError>("import section ended prematurely",
116509467b48Spatrick                                           object_error::parse_failed);
116609467b48Spatrick   return Error::success();
116709467b48Spatrick }
116809467b48Spatrick 
parseFunctionSection(ReadContext & Ctx)116909467b48Spatrick Error WasmObjectFile::parseFunctionSection(ReadContext &Ctx) {
117009467b48Spatrick   uint32_t Count = readVaruint32(Ctx);
1171*d415bd75Srobert   Functions.reserve(Count);
117209467b48Spatrick   uint32_t NumTypes = Signatures.size();
117309467b48Spatrick   while (Count--) {
117409467b48Spatrick     uint32_t Type = readVaruint32(Ctx);
117509467b48Spatrick     if (Type >= NumTypes)
117673471bf0Spatrick       return make_error<GenericBinaryError>("invalid function type",
117709467b48Spatrick                                             object_error::parse_failed);
1178*d415bd75Srobert     wasm::WasmFunction F;
1179*d415bd75Srobert     F.SigIndex = Type;
1180*d415bd75Srobert     Functions.push_back(F);
118109467b48Spatrick   }
118209467b48Spatrick   if (Ctx.Ptr != Ctx.End)
118373471bf0Spatrick     return make_error<GenericBinaryError>("function section ended prematurely",
118409467b48Spatrick                                           object_error::parse_failed);
118509467b48Spatrick   return Error::success();
118609467b48Spatrick }
118709467b48Spatrick 
parseTableSection(ReadContext & Ctx)118809467b48Spatrick Error WasmObjectFile::parseTableSection(ReadContext &Ctx) {
118973471bf0Spatrick   TableSection = Sections.size();
119009467b48Spatrick   uint32_t Count = readVaruint32(Ctx);
119109467b48Spatrick   Tables.reserve(Count);
119209467b48Spatrick   while (Count--) {
119373471bf0Spatrick     wasm::WasmTable T;
119473471bf0Spatrick     T.Type = readTableType(Ctx);
119573471bf0Spatrick     T.Index = NumImportedTables + Tables.size();
119673471bf0Spatrick     Tables.push_back(T);
119773471bf0Spatrick     auto ElemType = Tables.back().Type.ElemType;
119873471bf0Spatrick     if (ElemType != wasm::WASM_TYPE_FUNCREF &&
119973471bf0Spatrick         ElemType != wasm::WASM_TYPE_EXTERNREF) {
120073471bf0Spatrick       return make_error<GenericBinaryError>("invalid table element type",
120109467b48Spatrick                                             object_error::parse_failed);
120209467b48Spatrick     }
120309467b48Spatrick   }
120409467b48Spatrick   if (Ctx.Ptr != Ctx.End)
120573471bf0Spatrick     return make_error<GenericBinaryError>("table section ended prematurely",
120609467b48Spatrick                                           object_error::parse_failed);
120709467b48Spatrick   return Error::success();
120809467b48Spatrick }
120909467b48Spatrick 
parseMemorySection(ReadContext & Ctx)121009467b48Spatrick Error WasmObjectFile::parseMemorySection(ReadContext &Ctx) {
121109467b48Spatrick   uint32_t Count = readVaruint32(Ctx);
121209467b48Spatrick   Memories.reserve(Count);
121309467b48Spatrick   while (Count--) {
121473471bf0Spatrick     auto Limits = readLimits(Ctx);
121573471bf0Spatrick     if (Limits.Flags & wasm::WASM_LIMITS_FLAG_IS_64)
121673471bf0Spatrick       HasMemory64 = true;
121773471bf0Spatrick     Memories.push_back(Limits);
121809467b48Spatrick   }
121909467b48Spatrick   if (Ctx.Ptr != Ctx.End)
122073471bf0Spatrick     return make_error<GenericBinaryError>("memory section ended prematurely",
122109467b48Spatrick                                           object_error::parse_failed);
122209467b48Spatrick   return Error::success();
122309467b48Spatrick }
122409467b48Spatrick 
parseTagSection(ReadContext & Ctx)122573471bf0Spatrick Error WasmObjectFile::parseTagSection(ReadContext &Ctx) {
122673471bf0Spatrick   TagSection = Sections.size();
122773471bf0Spatrick   uint32_t Count = readVaruint32(Ctx);
122873471bf0Spatrick   Tags.reserve(Count);
1229*d415bd75Srobert   uint32_t NumTypes = Signatures.size();
1230097a140dSpatrick   while (Count--) {
1231*d415bd75Srobert     if (readUint8(Ctx) != 0) // Reserved 'attribute' field
1232*d415bd75Srobert       return make_error<GenericBinaryError>("invalid attribute",
1233*d415bd75Srobert                                             object_error::parse_failed);
1234*d415bd75Srobert     uint32_t Type = readVaruint32(Ctx);
1235*d415bd75Srobert     if (Type >= NumTypes)
1236*d415bd75Srobert       return make_error<GenericBinaryError>("invalid tag type",
1237*d415bd75Srobert                                             object_error::parse_failed);
123873471bf0Spatrick     wasm::WasmTag Tag;
123973471bf0Spatrick     Tag.Index = NumImportedTags + Tags.size();
1240*d415bd75Srobert     Tag.SigIndex = Type;
124173471bf0Spatrick     Tags.push_back(Tag);
1242097a140dSpatrick   }
1243097a140dSpatrick 
1244097a140dSpatrick   if (Ctx.Ptr != Ctx.End)
124573471bf0Spatrick     return make_error<GenericBinaryError>("tag section ended prematurely",
1246097a140dSpatrick                                           object_error::parse_failed);
1247097a140dSpatrick   return Error::success();
1248097a140dSpatrick }
1249097a140dSpatrick 
parseGlobalSection(ReadContext & Ctx)125009467b48Spatrick Error WasmObjectFile::parseGlobalSection(ReadContext &Ctx) {
125109467b48Spatrick   GlobalSection = Sections.size();
125209467b48Spatrick   uint32_t Count = readVaruint32(Ctx);
125309467b48Spatrick   Globals.reserve(Count);
125409467b48Spatrick   while (Count--) {
125509467b48Spatrick     wasm::WasmGlobal Global;
125609467b48Spatrick     Global.Index = NumImportedGlobals + Globals.size();
125709467b48Spatrick     Global.Type.Type = readUint8(Ctx);
125809467b48Spatrick     Global.Type.Mutable = readVaruint1(Ctx);
125909467b48Spatrick     if (Error Err = readInitExpr(Global.InitExpr, Ctx))
126009467b48Spatrick       return Err;
126109467b48Spatrick     Globals.push_back(Global);
126209467b48Spatrick   }
126309467b48Spatrick   if (Ctx.Ptr != Ctx.End)
126473471bf0Spatrick     return make_error<GenericBinaryError>("global section ended prematurely",
126509467b48Spatrick                                           object_error::parse_failed);
126609467b48Spatrick   return Error::success();
126709467b48Spatrick }
126809467b48Spatrick 
parseExportSection(ReadContext & Ctx)126909467b48Spatrick Error WasmObjectFile::parseExportSection(ReadContext &Ctx) {
127009467b48Spatrick   uint32_t Count = readVaruint32(Ctx);
127109467b48Spatrick   Exports.reserve(Count);
127209467b48Spatrick   for (uint32_t I = 0; I < Count; I++) {
127309467b48Spatrick     wasm::WasmExport Ex;
127409467b48Spatrick     Ex.Name = readString(Ctx);
127509467b48Spatrick     Ex.Kind = readUint8(Ctx);
127609467b48Spatrick     Ex.Index = readVaruint32(Ctx);
127709467b48Spatrick     switch (Ex.Kind) {
127809467b48Spatrick     case wasm::WASM_EXTERNAL_FUNCTION:
127909467b48Spatrick 
128009467b48Spatrick       if (!isDefinedFunctionIndex(Ex.Index))
128173471bf0Spatrick         return make_error<GenericBinaryError>("invalid function export",
128209467b48Spatrick                                               object_error::parse_failed);
128309467b48Spatrick       getDefinedFunction(Ex.Index).ExportName = Ex.Name;
128409467b48Spatrick       break;
128509467b48Spatrick     case wasm::WASM_EXTERNAL_GLOBAL:
128609467b48Spatrick       if (!isValidGlobalIndex(Ex.Index))
128773471bf0Spatrick         return make_error<GenericBinaryError>("invalid global export",
128809467b48Spatrick                                               object_error::parse_failed);
128909467b48Spatrick       break;
129073471bf0Spatrick     case wasm::WASM_EXTERNAL_TAG:
129173471bf0Spatrick       if (!isValidTagIndex(Ex.Index))
129273471bf0Spatrick         return make_error<GenericBinaryError>("invalid tag export",
129309467b48Spatrick                                               object_error::parse_failed);
129409467b48Spatrick       break;
129509467b48Spatrick     case wasm::WASM_EXTERNAL_MEMORY:
129609467b48Spatrick     case wasm::WASM_EXTERNAL_TABLE:
129709467b48Spatrick       break;
129809467b48Spatrick     default:
129973471bf0Spatrick       return make_error<GenericBinaryError>("unexpected export kind",
130009467b48Spatrick                                             object_error::parse_failed);
130109467b48Spatrick     }
130209467b48Spatrick     Exports.push_back(Ex);
130309467b48Spatrick   }
130409467b48Spatrick   if (Ctx.Ptr != Ctx.End)
130573471bf0Spatrick     return make_error<GenericBinaryError>("export section ended prematurely",
130609467b48Spatrick                                           object_error::parse_failed);
130709467b48Spatrick   return Error::success();
130809467b48Spatrick }
130909467b48Spatrick 
isValidFunctionIndex(uint32_t Index) const131009467b48Spatrick bool WasmObjectFile::isValidFunctionIndex(uint32_t Index) const {
1311*d415bd75Srobert   return Index < NumImportedFunctions + Functions.size();
131209467b48Spatrick }
131309467b48Spatrick 
isDefinedFunctionIndex(uint32_t Index) const131409467b48Spatrick bool WasmObjectFile::isDefinedFunctionIndex(uint32_t Index) const {
131509467b48Spatrick   return Index >= NumImportedFunctions && isValidFunctionIndex(Index);
131609467b48Spatrick }
131709467b48Spatrick 
isValidGlobalIndex(uint32_t Index) const131809467b48Spatrick bool WasmObjectFile::isValidGlobalIndex(uint32_t Index) const {
131909467b48Spatrick   return Index < NumImportedGlobals + Globals.size();
132009467b48Spatrick }
132109467b48Spatrick 
isValidTableNumber(uint32_t Index) const132273471bf0Spatrick bool WasmObjectFile::isValidTableNumber(uint32_t Index) const {
132373471bf0Spatrick   return Index < NumImportedTables + Tables.size();
132473471bf0Spatrick }
132573471bf0Spatrick 
isDefinedGlobalIndex(uint32_t Index) const132609467b48Spatrick bool WasmObjectFile::isDefinedGlobalIndex(uint32_t Index) const {
132709467b48Spatrick   return Index >= NumImportedGlobals && isValidGlobalIndex(Index);
132809467b48Spatrick }
132909467b48Spatrick 
isDefinedTableNumber(uint32_t Index) const133073471bf0Spatrick bool WasmObjectFile::isDefinedTableNumber(uint32_t Index) const {
133173471bf0Spatrick   return Index >= NumImportedTables && isValidTableNumber(Index);
133209467b48Spatrick }
133309467b48Spatrick 
isValidTagIndex(uint32_t Index) const133473471bf0Spatrick bool WasmObjectFile::isValidTagIndex(uint32_t Index) const {
133573471bf0Spatrick   return Index < NumImportedTags + Tags.size();
133673471bf0Spatrick }
133773471bf0Spatrick 
isDefinedTagIndex(uint32_t Index) const133873471bf0Spatrick bool WasmObjectFile::isDefinedTagIndex(uint32_t Index) const {
133973471bf0Spatrick   return Index >= NumImportedTags && isValidTagIndex(Index);
134009467b48Spatrick }
134109467b48Spatrick 
isValidFunctionSymbol(uint32_t Index) const134209467b48Spatrick bool WasmObjectFile::isValidFunctionSymbol(uint32_t Index) const {
134309467b48Spatrick   return Index < Symbols.size() && Symbols[Index].isTypeFunction();
134409467b48Spatrick }
134509467b48Spatrick 
isValidTableSymbol(uint32_t Index) const134673471bf0Spatrick bool WasmObjectFile::isValidTableSymbol(uint32_t Index) const {
134773471bf0Spatrick   return Index < Symbols.size() && Symbols[Index].isTypeTable();
134873471bf0Spatrick }
134973471bf0Spatrick 
isValidGlobalSymbol(uint32_t Index) const135009467b48Spatrick bool WasmObjectFile::isValidGlobalSymbol(uint32_t Index) const {
135109467b48Spatrick   return Index < Symbols.size() && Symbols[Index].isTypeGlobal();
135209467b48Spatrick }
135309467b48Spatrick 
isValidTagSymbol(uint32_t Index) const135473471bf0Spatrick bool WasmObjectFile::isValidTagSymbol(uint32_t Index) const {
135573471bf0Spatrick   return Index < Symbols.size() && Symbols[Index].isTypeTag();
135609467b48Spatrick }
135709467b48Spatrick 
isValidDataSymbol(uint32_t Index) const135809467b48Spatrick bool WasmObjectFile::isValidDataSymbol(uint32_t Index) const {
135909467b48Spatrick   return Index < Symbols.size() && Symbols[Index].isTypeData();
136009467b48Spatrick }
136109467b48Spatrick 
isValidSectionSymbol(uint32_t Index) const136209467b48Spatrick bool WasmObjectFile::isValidSectionSymbol(uint32_t Index) const {
136309467b48Spatrick   return Index < Symbols.size() && Symbols[Index].isTypeSection();
136409467b48Spatrick }
136509467b48Spatrick 
getDefinedFunction(uint32_t Index)136609467b48Spatrick wasm::WasmFunction &WasmObjectFile::getDefinedFunction(uint32_t Index) {
136709467b48Spatrick   assert(isDefinedFunctionIndex(Index));
136809467b48Spatrick   return Functions[Index - NumImportedFunctions];
136909467b48Spatrick }
137009467b48Spatrick 
137109467b48Spatrick const wasm::WasmFunction &
getDefinedFunction(uint32_t Index) const137209467b48Spatrick WasmObjectFile::getDefinedFunction(uint32_t Index) const {
137309467b48Spatrick   assert(isDefinedFunctionIndex(Index));
137409467b48Spatrick   return Functions[Index - NumImportedFunctions];
137509467b48Spatrick }
137609467b48Spatrick 
getDefinedGlobal(uint32_t Index)137709467b48Spatrick wasm::WasmGlobal &WasmObjectFile::getDefinedGlobal(uint32_t Index) {
137809467b48Spatrick   assert(isDefinedGlobalIndex(Index));
137909467b48Spatrick   return Globals[Index - NumImportedGlobals];
138009467b48Spatrick }
138109467b48Spatrick 
getDefinedTag(uint32_t Index)138273471bf0Spatrick wasm::WasmTag &WasmObjectFile::getDefinedTag(uint32_t Index) {
138373471bf0Spatrick   assert(isDefinedTagIndex(Index));
138473471bf0Spatrick   return Tags[Index - NumImportedTags];
138509467b48Spatrick }
138609467b48Spatrick 
parseStartSection(ReadContext & Ctx)138709467b48Spatrick Error WasmObjectFile::parseStartSection(ReadContext &Ctx) {
138809467b48Spatrick   StartFunction = readVaruint32(Ctx);
138909467b48Spatrick   if (!isValidFunctionIndex(StartFunction))
139073471bf0Spatrick     return make_error<GenericBinaryError>("invalid start function",
139109467b48Spatrick                                           object_error::parse_failed);
139209467b48Spatrick   return Error::success();
139309467b48Spatrick }
139409467b48Spatrick 
parseCodeSection(ReadContext & Ctx)139509467b48Spatrick Error WasmObjectFile::parseCodeSection(ReadContext &Ctx) {
139609467b48Spatrick   CodeSection = Sections.size();
139709467b48Spatrick   uint32_t FunctionCount = readVaruint32(Ctx);
1398*d415bd75Srobert   if (FunctionCount != Functions.size()) {
139973471bf0Spatrick     return make_error<GenericBinaryError>("invalid function count",
140009467b48Spatrick                                           object_error::parse_failed);
140109467b48Spatrick   }
140209467b48Spatrick 
140309467b48Spatrick   for (uint32_t i = 0; i < FunctionCount; i++) {
140409467b48Spatrick     wasm::WasmFunction& Function = Functions[i];
140509467b48Spatrick     const uint8_t *FunctionStart = Ctx.Ptr;
140609467b48Spatrick     uint32_t Size = readVaruint32(Ctx);
140709467b48Spatrick     const uint8_t *FunctionEnd = Ctx.Ptr + Size;
140809467b48Spatrick 
140909467b48Spatrick     Function.CodeOffset = Ctx.Ptr - FunctionStart;
141009467b48Spatrick     Function.Index = NumImportedFunctions + i;
141109467b48Spatrick     Function.CodeSectionOffset = FunctionStart - Ctx.Start;
141209467b48Spatrick     Function.Size = FunctionEnd - FunctionStart;
141309467b48Spatrick 
141409467b48Spatrick     uint32_t NumLocalDecls = readVaruint32(Ctx);
141509467b48Spatrick     Function.Locals.reserve(NumLocalDecls);
141609467b48Spatrick     while (NumLocalDecls--) {
141709467b48Spatrick       wasm::WasmLocalDecl Decl;
141809467b48Spatrick       Decl.Count = readVaruint32(Ctx);
141909467b48Spatrick       Decl.Type = readUint8(Ctx);
142009467b48Spatrick       Function.Locals.push_back(Decl);
142109467b48Spatrick     }
142209467b48Spatrick 
142309467b48Spatrick     uint32_t BodySize = FunctionEnd - Ctx.Ptr;
142409467b48Spatrick     Function.Body = ArrayRef<uint8_t>(Ctx.Ptr, BodySize);
142509467b48Spatrick     // This will be set later when reading in the linking metadata section.
142609467b48Spatrick     Function.Comdat = UINT32_MAX;
142709467b48Spatrick     Ctx.Ptr += BodySize;
142809467b48Spatrick     assert(Ctx.Ptr == FunctionEnd);
142909467b48Spatrick   }
143009467b48Spatrick   if (Ctx.Ptr != Ctx.End)
143173471bf0Spatrick     return make_error<GenericBinaryError>("code section ended prematurely",
143209467b48Spatrick                                           object_error::parse_failed);
143309467b48Spatrick   return Error::success();
143409467b48Spatrick }
143509467b48Spatrick 
parseElemSection(ReadContext & Ctx)143609467b48Spatrick Error WasmObjectFile::parseElemSection(ReadContext &Ctx) {
143709467b48Spatrick   uint32_t Count = readVaruint32(Ctx);
143809467b48Spatrick   ElemSegments.reserve(Count);
143909467b48Spatrick   while (Count--) {
144009467b48Spatrick     wasm::WasmElemSegment Segment;
144173471bf0Spatrick     Segment.Flags = readVaruint32(Ctx);
144273471bf0Spatrick 
144373471bf0Spatrick     uint32_t SupportedFlags = wasm::WASM_ELEM_SEGMENT_HAS_TABLE_NUMBER |
144473471bf0Spatrick                               wasm::WASM_ELEM_SEGMENT_IS_PASSIVE |
144573471bf0Spatrick                               wasm::WASM_ELEM_SEGMENT_HAS_INIT_EXPRS;
144673471bf0Spatrick     if (Segment.Flags & ~SupportedFlags)
144773471bf0Spatrick       return make_error<GenericBinaryError>(
144873471bf0Spatrick           "Unsupported flags for element segment", object_error::parse_failed);
144973471bf0Spatrick 
145073471bf0Spatrick     if (Segment.Flags & wasm::WASM_ELEM_SEGMENT_HAS_TABLE_NUMBER)
145173471bf0Spatrick       Segment.TableNumber = readVaruint32(Ctx);
145273471bf0Spatrick     else
145373471bf0Spatrick       Segment.TableNumber = 0;
145473471bf0Spatrick     if (!isValidTableNumber(Segment.TableNumber))
145573471bf0Spatrick       return make_error<GenericBinaryError>("invalid TableNumber",
145609467b48Spatrick                                             object_error::parse_failed);
145773471bf0Spatrick 
145873471bf0Spatrick     if (Segment.Flags & wasm::WASM_ELEM_SEGMENT_IS_PASSIVE) {
1459*d415bd75Srobert       Segment.Offset.Extended = false;
1460*d415bd75Srobert       Segment.Offset.Inst.Opcode = wasm::WASM_OPCODE_I32_CONST;
1461*d415bd75Srobert       Segment.Offset.Inst.Value.Int32 = 0;
146273471bf0Spatrick     } else {
146309467b48Spatrick       if (Error Err = readInitExpr(Segment.Offset, Ctx))
146409467b48Spatrick         return Err;
146573471bf0Spatrick     }
146673471bf0Spatrick 
146773471bf0Spatrick     if (Segment.Flags & wasm::WASM_ELEM_SEGMENT_MASK_HAS_ELEM_KIND) {
146873471bf0Spatrick       Segment.ElemKind = readUint8(Ctx);
146973471bf0Spatrick       if (Segment.Flags & wasm::WASM_ELEM_SEGMENT_HAS_INIT_EXPRS) {
147073471bf0Spatrick         if (Segment.ElemKind != uint8_t(wasm::ValType::FUNCREF) &&
147173471bf0Spatrick             Segment.ElemKind != uint8_t(wasm::ValType::EXTERNREF)) {
147273471bf0Spatrick           return make_error<GenericBinaryError>("invalid reference type",
147373471bf0Spatrick                                                 object_error::parse_failed);
147473471bf0Spatrick         }
147573471bf0Spatrick       } else {
147673471bf0Spatrick         if (Segment.ElemKind != 0)
147773471bf0Spatrick           return make_error<GenericBinaryError>("invalid elemtype",
147873471bf0Spatrick                                                 object_error::parse_failed);
147973471bf0Spatrick         Segment.ElemKind = uint8_t(wasm::ValType::FUNCREF);
148073471bf0Spatrick       }
148173471bf0Spatrick     } else {
148273471bf0Spatrick       Segment.ElemKind = uint8_t(wasm::ValType::FUNCREF);
148373471bf0Spatrick     }
148473471bf0Spatrick 
148573471bf0Spatrick     if (Segment.Flags & wasm::WASM_ELEM_SEGMENT_HAS_INIT_EXPRS)
148673471bf0Spatrick       return make_error<GenericBinaryError>(
148773471bf0Spatrick           "elem segment init expressions not yet implemented",
148873471bf0Spatrick           object_error::parse_failed);
148973471bf0Spatrick 
149009467b48Spatrick     uint32_t NumElems = readVaruint32(Ctx);
149109467b48Spatrick     while (NumElems--) {
149209467b48Spatrick       Segment.Functions.push_back(readVaruint32(Ctx));
149309467b48Spatrick     }
149409467b48Spatrick     ElemSegments.push_back(Segment);
149509467b48Spatrick   }
149609467b48Spatrick   if (Ctx.Ptr != Ctx.End)
149773471bf0Spatrick     return make_error<GenericBinaryError>("elem section ended prematurely",
149809467b48Spatrick                                           object_error::parse_failed);
149909467b48Spatrick   return Error::success();
150009467b48Spatrick }
150109467b48Spatrick 
parseDataSection(ReadContext & Ctx)150209467b48Spatrick Error WasmObjectFile::parseDataSection(ReadContext &Ctx) {
150309467b48Spatrick   DataSection = Sections.size();
150409467b48Spatrick   uint32_t Count = readVaruint32(Ctx);
1505*d415bd75Srobert   if (DataCount && Count != *DataCount)
150609467b48Spatrick     return make_error<GenericBinaryError>(
150773471bf0Spatrick         "number of data segments does not match DataCount section");
150809467b48Spatrick   DataSegments.reserve(Count);
150909467b48Spatrick   while (Count--) {
151009467b48Spatrick     WasmSegment Segment;
151109467b48Spatrick     Segment.Data.InitFlags = readVaruint32(Ctx);
151273471bf0Spatrick     Segment.Data.MemoryIndex =
151373471bf0Spatrick         (Segment.Data.InitFlags & wasm::WASM_DATA_SEGMENT_HAS_MEMINDEX)
151473471bf0Spatrick             ? readVaruint32(Ctx)
151573471bf0Spatrick             : 0;
151673471bf0Spatrick     if ((Segment.Data.InitFlags & wasm::WASM_DATA_SEGMENT_IS_PASSIVE) == 0) {
151709467b48Spatrick       if (Error Err = readInitExpr(Segment.Data.Offset, Ctx))
151809467b48Spatrick         return Err;
151909467b48Spatrick     } else {
1520*d415bd75Srobert       Segment.Data.Offset.Extended = false;
1521*d415bd75Srobert       Segment.Data.Offset.Inst.Opcode = wasm::WASM_OPCODE_I32_CONST;
1522*d415bd75Srobert       Segment.Data.Offset.Inst.Value.Int32 = 0;
152309467b48Spatrick     }
152409467b48Spatrick     uint32_t Size = readVaruint32(Ctx);
152509467b48Spatrick     if (Size > (size_t)(Ctx.End - Ctx.Ptr))
152673471bf0Spatrick       return make_error<GenericBinaryError>("invalid segment size",
152709467b48Spatrick                                             object_error::parse_failed);
152809467b48Spatrick     Segment.Data.Content = ArrayRef<uint8_t>(Ctx.Ptr, Size);
152909467b48Spatrick     // The rest of these Data fields are set later, when reading in the linking
153009467b48Spatrick     // metadata section.
153109467b48Spatrick     Segment.Data.Alignment = 0;
153273471bf0Spatrick     Segment.Data.LinkingFlags = 0;
153309467b48Spatrick     Segment.Data.Comdat = UINT32_MAX;
153409467b48Spatrick     Segment.SectionOffset = Ctx.Ptr - Ctx.Start;
153509467b48Spatrick     Ctx.Ptr += Size;
153609467b48Spatrick     DataSegments.push_back(Segment);
153709467b48Spatrick   }
153809467b48Spatrick   if (Ctx.Ptr != Ctx.End)
153973471bf0Spatrick     return make_error<GenericBinaryError>("data section ended prematurely",
154009467b48Spatrick                                           object_error::parse_failed);
154109467b48Spatrick   return Error::success();
154209467b48Spatrick }
154309467b48Spatrick 
parseDataCountSection(ReadContext & Ctx)154409467b48Spatrick Error WasmObjectFile::parseDataCountSection(ReadContext &Ctx) {
154509467b48Spatrick   DataCount = readVaruint32(Ctx);
154609467b48Spatrick   return Error::success();
154709467b48Spatrick }
154809467b48Spatrick 
getHeader() const154909467b48Spatrick const wasm::WasmObjectHeader &WasmObjectFile::getHeader() const {
155009467b48Spatrick   return Header;
155109467b48Spatrick }
155209467b48Spatrick 
moveSymbolNext(DataRefImpl & Symb) const155309467b48Spatrick void WasmObjectFile::moveSymbolNext(DataRefImpl &Symb) const { Symb.d.b++; }
155409467b48Spatrick 
getSymbolFlags(DataRefImpl Symb) const1555097a140dSpatrick Expected<uint32_t> WasmObjectFile::getSymbolFlags(DataRefImpl Symb) const {
155609467b48Spatrick   uint32_t Result = SymbolRef::SF_None;
155709467b48Spatrick   const WasmSymbol &Sym = getWasmSymbol(Symb);
155809467b48Spatrick 
155909467b48Spatrick   LLVM_DEBUG(dbgs() << "getSymbolFlags: ptr=" << &Sym << " " << Sym << "\n");
156009467b48Spatrick   if (Sym.isBindingWeak())
156109467b48Spatrick     Result |= SymbolRef::SF_Weak;
156209467b48Spatrick   if (!Sym.isBindingLocal())
156309467b48Spatrick     Result |= SymbolRef::SF_Global;
156409467b48Spatrick   if (Sym.isHidden())
156509467b48Spatrick     Result |= SymbolRef::SF_Hidden;
156609467b48Spatrick   if (!Sym.isDefined())
156709467b48Spatrick     Result |= SymbolRef::SF_Undefined;
156809467b48Spatrick   if (Sym.isTypeFunction())
156909467b48Spatrick     Result |= SymbolRef::SF_Executable;
157009467b48Spatrick   return Result;
157109467b48Spatrick }
157209467b48Spatrick 
symbol_begin() const157309467b48Spatrick basic_symbol_iterator WasmObjectFile::symbol_begin() const {
157409467b48Spatrick   DataRefImpl Ref;
157509467b48Spatrick   Ref.d.a = 1; // Arbitrary non-zero value so that Ref.p is non-null
157609467b48Spatrick   Ref.d.b = 0; // Symbol index
157709467b48Spatrick   return BasicSymbolRef(Ref, this);
157809467b48Spatrick }
157909467b48Spatrick 
symbol_end() const158009467b48Spatrick basic_symbol_iterator WasmObjectFile::symbol_end() const {
158109467b48Spatrick   DataRefImpl Ref;
158209467b48Spatrick   Ref.d.a = 1; // Arbitrary non-zero value so that Ref.p is non-null
158309467b48Spatrick   Ref.d.b = Symbols.size(); // Symbol index
158409467b48Spatrick   return BasicSymbolRef(Ref, this);
158509467b48Spatrick }
158609467b48Spatrick 
getWasmSymbol(const DataRefImpl & Symb) const158709467b48Spatrick const WasmSymbol &WasmObjectFile::getWasmSymbol(const DataRefImpl &Symb) const {
158809467b48Spatrick   return Symbols[Symb.d.b];
158909467b48Spatrick }
159009467b48Spatrick 
getWasmSymbol(const SymbolRef & Symb) const159109467b48Spatrick const WasmSymbol &WasmObjectFile::getWasmSymbol(const SymbolRef &Symb) const {
159209467b48Spatrick   return getWasmSymbol(Symb.getRawDataRefImpl());
159309467b48Spatrick }
159409467b48Spatrick 
getSymbolName(DataRefImpl Symb) const159509467b48Spatrick Expected<StringRef> WasmObjectFile::getSymbolName(DataRefImpl Symb) const {
159609467b48Spatrick   return getWasmSymbol(Symb).Info.Name;
159709467b48Spatrick }
159809467b48Spatrick 
getSymbolAddress(DataRefImpl Symb) const159909467b48Spatrick Expected<uint64_t> WasmObjectFile::getSymbolAddress(DataRefImpl Symb) const {
160009467b48Spatrick   auto &Sym = getWasmSymbol(Symb);
160109467b48Spatrick   if (Sym.Info.Kind == wasm::WASM_SYMBOL_TYPE_FUNCTION &&
160209467b48Spatrick       isDefinedFunctionIndex(Sym.Info.ElementIndex))
160309467b48Spatrick     return getDefinedFunction(Sym.Info.ElementIndex).CodeSectionOffset;
160409467b48Spatrick   else
160509467b48Spatrick     return getSymbolValue(Symb);
160609467b48Spatrick }
160709467b48Spatrick 
getWasmSymbolValue(const WasmSymbol & Sym) const160809467b48Spatrick uint64_t WasmObjectFile::getWasmSymbolValue(const WasmSymbol &Sym) const {
160909467b48Spatrick   switch (Sym.Info.Kind) {
161009467b48Spatrick   case wasm::WASM_SYMBOL_TYPE_FUNCTION:
161109467b48Spatrick   case wasm::WASM_SYMBOL_TYPE_GLOBAL:
161273471bf0Spatrick   case wasm::WASM_SYMBOL_TYPE_TAG:
161373471bf0Spatrick   case wasm::WASM_SYMBOL_TYPE_TABLE:
161409467b48Spatrick     return Sym.Info.ElementIndex;
161509467b48Spatrick   case wasm::WASM_SYMBOL_TYPE_DATA: {
161609467b48Spatrick     // The value of a data symbol is the segment offset, plus the symbol
161709467b48Spatrick     // offset within the segment.
161809467b48Spatrick     uint32_t SegmentIndex = Sym.Info.DataRef.Segment;
161909467b48Spatrick     const wasm::WasmDataSegment &Segment = DataSegments[SegmentIndex].Data;
1620*d415bd75Srobert     if (Segment.Offset.Extended) {
1621*d415bd75Srobert       llvm_unreachable("extended init exprs not supported");
1622*d415bd75Srobert     } else if (Segment.Offset.Inst.Opcode == wasm::WASM_OPCODE_I32_CONST) {
1623*d415bd75Srobert       return Segment.Offset.Inst.Value.Int32 + Sym.Info.DataRef.Offset;
1624*d415bd75Srobert     } else if (Segment.Offset.Inst.Opcode == wasm::WASM_OPCODE_I64_CONST) {
1625*d415bd75Srobert       return Segment.Offset.Inst.Value.Int64 + Sym.Info.DataRef.Offset;
1626097a140dSpatrick     } else {
1627097a140dSpatrick       llvm_unreachable("unknown init expr opcode");
1628097a140dSpatrick     }
162909467b48Spatrick   }
163009467b48Spatrick   case wasm::WASM_SYMBOL_TYPE_SECTION:
163109467b48Spatrick     return 0;
163209467b48Spatrick   }
163309467b48Spatrick   llvm_unreachable("invalid symbol type");
163409467b48Spatrick }
163509467b48Spatrick 
getSymbolValueImpl(DataRefImpl Symb) const163609467b48Spatrick uint64_t WasmObjectFile::getSymbolValueImpl(DataRefImpl Symb) const {
163709467b48Spatrick   return getWasmSymbolValue(getWasmSymbol(Symb));
163809467b48Spatrick }
163909467b48Spatrick 
getSymbolAlignment(DataRefImpl Symb) const164009467b48Spatrick uint32_t WasmObjectFile::getSymbolAlignment(DataRefImpl Symb) const {
164109467b48Spatrick   llvm_unreachable("not yet implemented");
164209467b48Spatrick   return 0;
164309467b48Spatrick }
164409467b48Spatrick 
getCommonSymbolSizeImpl(DataRefImpl Symb) const164509467b48Spatrick uint64_t WasmObjectFile::getCommonSymbolSizeImpl(DataRefImpl Symb) const {
164609467b48Spatrick   llvm_unreachable("not yet implemented");
164709467b48Spatrick   return 0;
164809467b48Spatrick }
164909467b48Spatrick 
165009467b48Spatrick Expected<SymbolRef::Type>
getSymbolType(DataRefImpl Symb) const165109467b48Spatrick WasmObjectFile::getSymbolType(DataRefImpl Symb) const {
165209467b48Spatrick   const WasmSymbol &Sym = getWasmSymbol(Symb);
165309467b48Spatrick 
165409467b48Spatrick   switch (Sym.Info.Kind) {
165509467b48Spatrick   case wasm::WASM_SYMBOL_TYPE_FUNCTION:
165609467b48Spatrick     return SymbolRef::ST_Function;
165709467b48Spatrick   case wasm::WASM_SYMBOL_TYPE_GLOBAL:
165809467b48Spatrick     return SymbolRef::ST_Other;
165909467b48Spatrick   case wasm::WASM_SYMBOL_TYPE_DATA:
166009467b48Spatrick     return SymbolRef::ST_Data;
166109467b48Spatrick   case wasm::WASM_SYMBOL_TYPE_SECTION:
166209467b48Spatrick     return SymbolRef::ST_Debug;
166373471bf0Spatrick   case wasm::WASM_SYMBOL_TYPE_TAG:
166473471bf0Spatrick     return SymbolRef::ST_Other;
166573471bf0Spatrick   case wasm::WASM_SYMBOL_TYPE_TABLE:
166609467b48Spatrick     return SymbolRef::ST_Other;
166709467b48Spatrick   }
166809467b48Spatrick 
166973471bf0Spatrick   llvm_unreachable("unknown WasmSymbol::SymbolType");
167009467b48Spatrick   return SymbolRef::ST_Other;
167109467b48Spatrick }
167209467b48Spatrick 
167309467b48Spatrick Expected<section_iterator>
getSymbolSection(DataRefImpl Symb) const167409467b48Spatrick WasmObjectFile::getSymbolSection(DataRefImpl Symb) const {
167509467b48Spatrick   const WasmSymbol &Sym = getWasmSymbol(Symb);
167609467b48Spatrick   if (Sym.isUndefined())
167709467b48Spatrick     return section_end();
167809467b48Spatrick 
167909467b48Spatrick   DataRefImpl Ref;
1680097a140dSpatrick   Ref.d.a = getSymbolSectionIdImpl(Sym);
1681097a140dSpatrick   return section_iterator(SectionRef(Ref, this));
1682097a140dSpatrick }
1683097a140dSpatrick 
getSymbolSectionId(SymbolRef Symb) const1684097a140dSpatrick uint32_t WasmObjectFile::getSymbolSectionId(SymbolRef Symb) const {
1685097a140dSpatrick   const WasmSymbol &Sym = getWasmSymbol(Symb);
1686097a140dSpatrick   return getSymbolSectionIdImpl(Sym);
1687097a140dSpatrick }
1688097a140dSpatrick 
getSymbolSectionIdImpl(const WasmSymbol & Sym) const1689097a140dSpatrick uint32_t WasmObjectFile::getSymbolSectionIdImpl(const WasmSymbol &Sym) const {
169009467b48Spatrick   switch (Sym.Info.Kind) {
169109467b48Spatrick   case wasm::WASM_SYMBOL_TYPE_FUNCTION:
1692097a140dSpatrick     return CodeSection;
169309467b48Spatrick   case wasm::WASM_SYMBOL_TYPE_GLOBAL:
1694097a140dSpatrick     return GlobalSection;
169509467b48Spatrick   case wasm::WASM_SYMBOL_TYPE_DATA:
1696097a140dSpatrick     return DataSection;
169709467b48Spatrick   case wasm::WASM_SYMBOL_TYPE_SECTION:
1698097a140dSpatrick     return Sym.Info.ElementIndex;
169973471bf0Spatrick   case wasm::WASM_SYMBOL_TYPE_TAG:
170073471bf0Spatrick     return TagSection;
170173471bf0Spatrick   case wasm::WASM_SYMBOL_TYPE_TABLE:
170273471bf0Spatrick     return TableSection;
170309467b48Spatrick   default:
170473471bf0Spatrick     llvm_unreachable("unknown WasmSymbol::SymbolType");
170509467b48Spatrick   }
170609467b48Spatrick }
170709467b48Spatrick 
moveSectionNext(DataRefImpl & Sec) const170809467b48Spatrick void WasmObjectFile::moveSectionNext(DataRefImpl &Sec) const { Sec.d.a++; }
170909467b48Spatrick 
getSectionName(DataRefImpl Sec) const171009467b48Spatrick Expected<StringRef> WasmObjectFile::getSectionName(DataRefImpl Sec) const {
171109467b48Spatrick   const WasmSection &S = Sections[Sec.d.a];
1712*d415bd75Srobert   if (S.Type == wasm::WASM_SEC_CUSTOM)
171309467b48Spatrick     return S.Name;
1714*d415bd75Srobert   if (S.Type > wasm::WASM_SEC_LAST_KNOWN)
171509467b48Spatrick     return createStringError(object_error::invalid_section_index, "");
1716*d415bd75Srobert   return wasm::sectionTypeToString(S.Type);
171709467b48Spatrick }
171809467b48Spatrick 
getSectionAddress(DataRefImpl Sec) const171909467b48Spatrick uint64_t WasmObjectFile::getSectionAddress(DataRefImpl Sec) const { return 0; }
172009467b48Spatrick 
getSectionIndex(DataRefImpl Sec) const172109467b48Spatrick uint64_t WasmObjectFile::getSectionIndex(DataRefImpl Sec) const {
172209467b48Spatrick   return Sec.d.a;
172309467b48Spatrick }
172409467b48Spatrick 
getSectionSize(DataRefImpl Sec) const172509467b48Spatrick uint64_t WasmObjectFile::getSectionSize(DataRefImpl Sec) const {
172609467b48Spatrick   const WasmSection &S = Sections[Sec.d.a];
172709467b48Spatrick   return S.Content.size();
172809467b48Spatrick }
172909467b48Spatrick 
173009467b48Spatrick Expected<ArrayRef<uint8_t>>
getSectionContents(DataRefImpl Sec) const173109467b48Spatrick WasmObjectFile::getSectionContents(DataRefImpl Sec) const {
173209467b48Spatrick   const WasmSection &S = Sections[Sec.d.a];
173309467b48Spatrick   // This will never fail since wasm sections can never be empty (user-sections
173409467b48Spatrick   // must have a name and non-user sections each have a defined structure).
173509467b48Spatrick   return S.Content;
173609467b48Spatrick }
173709467b48Spatrick 
getSectionAlignment(DataRefImpl Sec) const173809467b48Spatrick uint64_t WasmObjectFile::getSectionAlignment(DataRefImpl Sec) const {
173909467b48Spatrick   return 1;
174009467b48Spatrick }
174109467b48Spatrick 
isSectionCompressed(DataRefImpl Sec) const174209467b48Spatrick bool WasmObjectFile::isSectionCompressed(DataRefImpl Sec) const {
174309467b48Spatrick   return false;
174409467b48Spatrick }
174509467b48Spatrick 
isSectionText(DataRefImpl Sec) const174609467b48Spatrick bool WasmObjectFile::isSectionText(DataRefImpl Sec) const {
174709467b48Spatrick   return getWasmSection(Sec).Type == wasm::WASM_SEC_CODE;
174809467b48Spatrick }
174909467b48Spatrick 
isSectionData(DataRefImpl Sec) const175009467b48Spatrick bool WasmObjectFile::isSectionData(DataRefImpl Sec) const {
175109467b48Spatrick   return getWasmSection(Sec).Type == wasm::WASM_SEC_DATA;
175209467b48Spatrick }
175309467b48Spatrick 
isSectionBSS(DataRefImpl Sec) const175409467b48Spatrick bool WasmObjectFile::isSectionBSS(DataRefImpl Sec) const { return false; }
175509467b48Spatrick 
isSectionVirtual(DataRefImpl Sec) const175609467b48Spatrick bool WasmObjectFile::isSectionVirtual(DataRefImpl Sec) const { return false; }
175709467b48Spatrick 
section_rel_begin(DataRefImpl Ref) const175809467b48Spatrick relocation_iterator WasmObjectFile::section_rel_begin(DataRefImpl Ref) const {
175909467b48Spatrick   DataRefImpl RelocRef;
176009467b48Spatrick   RelocRef.d.a = Ref.d.a;
176109467b48Spatrick   RelocRef.d.b = 0;
176209467b48Spatrick   return relocation_iterator(RelocationRef(RelocRef, this));
176309467b48Spatrick }
176409467b48Spatrick 
section_rel_end(DataRefImpl Ref) const176509467b48Spatrick relocation_iterator WasmObjectFile::section_rel_end(DataRefImpl Ref) const {
176609467b48Spatrick   const WasmSection &Sec = getWasmSection(Ref);
176709467b48Spatrick   DataRefImpl RelocRef;
176809467b48Spatrick   RelocRef.d.a = Ref.d.a;
176909467b48Spatrick   RelocRef.d.b = Sec.Relocations.size();
177009467b48Spatrick   return relocation_iterator(RelocationRef(RelocRef, this));
177109467b48Spatrick }
177209467b48Spatrick 
moveRelocationNext(DataRefImpl & Rel) const177309467b48Spatrick void WasmObjectFile::moveRelocationNext(DataRefImpl &Rel) const { Rel.d.b++; }
177409467b48Spatrick 
getRelocationOffset(DataRefImpl Ref) const177509467b48Spatrick uint64_t WasmObjectFile::getRelocationOffset(DataRefImpl Ref) const {
177609467b48Spatrick   const wasm::WasmRelocation &Rel = getWasmRelocation(Ref);
177709467b48Spatrick   return Rel.Offset;
177809467b48Spatrick }
177909467b48Spatrick 
getRelocationSymbol(DataRefImpl Ref) const178009467b48Spatrick symbol_iterator WasmObjectFile::getRelocationSymbol(DataRefImpl Ref) const {
178109467b48Spatrick   const wasm::WasmRelocation &Rel = getWasmRelocation(Ref);
178209467b48Spatrick   if (Rel.Type == wasm::R_WASM_TYPE_INDEX_LEB)
178309467b48Spatrick     return symbol_end();
178409467b48Spatrick   DataRefImpl Sym;
178509467b48Spatrick   Sym.d.a = 1;
178609467b48Spatrick   Sym.d.b = Rel.Index;
178709467b48Spatrick   return symbol_iterator(SymbolRef(Sym, this));
178809467b48Spatrick }
178909467b48Spatrick 
getRelocationType(DataRefImpl Ref) const179009467b48Spatrick uint64_t WasmObjectFile::getRelocationType(DataRefImpl Ref) const {
179109467b48Spatrick   const wasm::WasmRelocation &Rel = getWasmRelocation(Ref);
179209467b48Spatrick   return Rel.Type;
179309467b48Spatrick }
179409467b48Spatrick 
getRelocationTypeName(DataRefImpl Ref,SmallVectorImpl<char> & Result) const179509467b48Spatrick void WasmObjectFile::getRelocationTypeName(
179609467b48Spatrick     DataRefImpl Ref, SmallVectorImpl<char> &Result) const {
179709467b48Spatrick   const wasm::WasmRelocation &Rel = getWasmRelocation(Ref);
179809467b48Spatrick   StringRef Res = "Unknown";
179909467b48Spatrick 
180009467b48Spatrick #define WASM_RELOC(name, value)                                                \
180109467b48Spatrick   case wasm::name:                                                             \
180209467b48Spatrick     Res = #name;                                                               \
180309467b48Spatrick     break;
180409467b48Spatrick 
180509467b48Spatrick   switch (Rel.Type) {
180609467b48Spatrick #include "llvm/BinaryFormat/WasmRelocs.def"
180709467b48Spatrick   }
180809467b48Spatrick 
180909467b48Spatrick #undef WASM_RELOC
181009467b48Spatrick 
181109467b48Spatrick   Result.append(Res.begin(), Res.end());
181209467b48Spatrick }
181309467b48Spatrick 
section_begin() const181409467b48Spatrick section_iterator WasmObjectFile::section_begin() const {
181509467b48Spatrick   DataRefImpl Ref;
181609467b48Spatrick   Ref.d.a = 0;
181709467b48Spatrick   return section_iterator(SectionRef(Ref, this));
181809467b48Spatrick }
181909467b48Spatrick 
section_end() const182009467b48Spatrick section_iterator WasmObjectFile::section_end() const {
182109467b48Spatrick   DataRefImpl Ref;
182209467b48Spatrick   Ref.d.a = Sections.size();
182309467b48Spatrick   return section_iterator(SectionRef(Ref, this));
182409467b48Spatrick }
182509467b48Spatrick 
getBytesInAddress() const182673471bf0Spatrick uint8_t WasmObjectFile::getBytesInAddress() const {
182773471bf0Spatrick   return HasMemory64 ? 8 : 4;
182873471bf0Spatrick }
182909467b48Spatrick 
getFileFormatName() const183009467b48Spatrick StringRef WasmObjectFile::getFileFormatName() const { return "WASM"; }
183109467b48Spatrick 
getArch() const183273471bf0Spatrick Triple::ArchType WasmObjectFile::getArch() const {
183373471bf0Spatrick   return HasMemory64 ? Triple::wasm64 : Triple::wasm32;
183473471bf0Spatrick }
183509467b48Spatrick 
getFeatures() const1836*d415bd75Srobert Expected<SubtargetFeatures> WasmObjectFile::getFeatures() const {
183709467b48Spatrick   return SubtargetFeatures();
183809467b48Spatrick }
183909467b48Spatrick 
isRelocatableObject() const184009467b48Spatrick bool WasmObjectFile::isRelocatableObject() const { return HasLinkingSection; }
184109467b48Spatrick 
isSharedObject() const184209467b48Spatrick bool WasmObjectFile::isSharedObject() const { return HasDylinkSection; }
184309467b48Spatrick 
getWasmSection(DataRefImpl Ref) const184409467b48Spatrick const WasmSection &WasmObjectFile::getWasmSection(DataRefImpl Ref) const {
184509467b48Spatrick   assert(Ref.d.a < Sections.size());
184609467b48Spatrick   return Sections[Ref.d.a];
184709467b48Spatrick }
184809467b48Spatrick 
184909467b48Spatrick const WasmSection &
getWasmSection(const SectionRef & Section) const185009467b48Spatrick WasmObjectFile::getWasmSection(const SectionRef &Section) const {
185109467b48Spatrick   return getWasmSection(Section.getRawDataRefImpl());
185209467b48Spatrick }
185309467b48Spatrick 
185409467b48Spatrick const wasm::WasmRelocation &
getWasmRelocation(const RelocationRef & Ref) const185509467b48Spatrick WasmObjectFile::getWasmRelocation(const RelocationRef &Ref) const {
185609467b48Spatrick   return getWasmRelocation(Ref.getRawDataRefImpl());
185709467b48Spatrick }
185809467b48Spatrick 
185909467b48Spatrick const wasm::WasmRelocation &
getWasmRelocation(DataRefImpl Ref) const186009467b48Spatrick WasmObjectFile::getWasmRelocation(DataRefImpl Ref) const {
186109467b48Spatrick   assert(Ref.d.a < Sections.size());
186209467b48Spatrick   const WasmSection &Sec = Sections[Ref.d.a];
186309467b48Spatrick   assert(Ref.d.b < Sec.Relocations.size());
186409467b48Spatrick   return Sec.Relocations[Ref.d.b];
186509467b48Spatrick }
186609467b48Spatrick 
getSectionOrder(unsigned ID,StringRef CustomSectionName)186709467b48Spatrick int WasmSectionOrderChecker::getSectionOrder(unsigned ID,
186809467b48Spatrick                                              StringRef CustomSectionName) {
186909467b48Spatrick   switch (ID) {
187009467b48Spatrick   case wasm::WASM_SEC_CUSTOM:
187109467b48Spatrick     return StringSwitch<unsigned>(CustomSectionName)
187209467b48Spatrick         .Case("dylink", WASM_SEC_ORDER_DYLINK)
1873*d415bd75Srobert         .Case("dylink.0", WASM_SEC_ORDER_DYLINK)
187409467b48Spatrick         .Case("linking", WASM_SEC_ORDER_LINKING)
187509467b48Spatrick         .StartsWith("reloc.", WASM_SEC_ORDER_RELOC)
187609467b48Spatrick         .Case("name", WASM_SEC_ORDER_NAME)
187709467b48Spatrick         .Case("producers", WASM_SEC_ORDER_PRODUCERS)
187809467b48Spatrick         .Case("target_features", WASM_SEC_ORDER_TARGET_FEATURES)
187909467b48Spatrick         .Default(WASM_SEC_ORDER_NONE);
188009467b48Spatrick   case wasm::WASM_SEC_TYPE:
188109467b48Spatrick     return WASM_SEC_ORDER_TYPE;
188209467b48Spatrick   case wasm::WASM_SEC_IMPORT:
188309467b48Spatrick     return WASM_SEC_ORDER_IMPORT;
188409467b48Spatrick   case wasm::WASM_SEC_FUNCTION:
188509467b48Spatrick     return WASM_SEC_ORDER_FUNCTION;
188609467b48Spatrick   case wasm::WASM_SEC_TABLE:
188709467b48Spatrick     return WASM_SEC_ORDER_TABLE;
188809467b48Spatrick   case wasm::WASM_SEC_MEMORY:
188909467b48Spatrick     return WASM_SEC_ORDER_MEMORY;
189009467b48Spatrick   case wasm::WASM_SEC_GLOBAL:
189109467b48Spatrick     return WASM_SEC_ORDER_GLOBAL;
189209467b48Spatrick   case wasm::WASM_SEC_EXPORT:
189309467b48Spatrick     return WASM_SEC_ORDER_EXPORT;
189409467b48Spatrick   case wasm::WASM_SEC_START:
189509467b48Spatrick     return WASM_SEC_ORDER_START;
189609467b48Spatrick   case wasm::WASM_SEC_ELEM:
189709467b48Spatrick     return WASM_SEC_ORDER_ELEM;
189809467b48Spatrick   case wasm::WASM_SEC_CODE:
189909467b48Spatrick     return WASM_SEC_ORDER_CODE;
190009467b48Spatrick   case wasm::WASM_SEC_DATA:
190109467b48Spatrick     return WASM_SEC_ORDER_DATA;
190209467b48Spatrick   case wasm::WASM_SEC_DATACOUNT:
190309467b48Spatrick     return WASM_SEC_ORDER_DATACOUNT;
190473471bf0Spatrick   case wasm::WASM_SEC_TAG:
190573471bf0Spatrick     return WASM_SEC_ORDER_TAG;
190609467b48Spatrick   default:
190709467b48Spatrick     return WASM_SEC_ORDER_NONE;
190809467b48Spatrick   }
190909467b48Spatrick }
191009467b48Spatrick 
191109467b48Spatrick // Represents the edges in a directed graph where any node B reachable from node
191209467b48Spatrick // A is not allowed to appear before A in the section ordering, but may appear
191309467b48Spatrick // afterward.
1914097a140dSpatrick int WasmSectionOrderChecker::DisallowedPredecessors
1915097a140dSpatrick     [WASM_NUM_SEC_ORDERS][WASM_NUM_SEC_ORDERS] = {
1916097a140dSpatrick         // WASM_SEC_ORDER_NONE
1917097a140dSpatrick         {},
1918097a140dSpatrick         // WASM_SEC_ORDER_TYPE
1919097a140dSpatrick         {WASM_SEC_ORDER_TYPE, WASM_SEC_ORDER_IMPORT},
1920097a140dSpatrick         // WASM_SEC_ORDER_IMPORT
1921097a140dSpatrick         {WASM_SEC_ORDER_IMPORT, WASM_SEC_ORDER_FUNCTION},
1922097a140dSpatrick         // WASM_SEC_ORDER_FUNCTION
1923097a140dSpatrick         {WASM_SEC_ORDER_FUNCTION, WASM_SEC_ORDER_TABLE},
1924097a140dSpatrick         // WASM_SEC_ORDER_TABLE
1925097a140dSpatrick         {WASM_SEC_ORDER_TABLE, WASM_SEC_ORDER_MEMORY},
1926097a140dSpatrick         // WASM_SEC_ORDER_MEMORY
192773471bf0Spatrick         {WASM_SEC_ORDER_MEMORY, WASM_SEC_ORDER_TAG},
192873471bf0Spatrick         // WASM_SEC_ORDER_TAG
192973471bf0Spatrick         {WASM_SEC_ORDER_TAG, WASM_SEC_ORDER_GLOBAL},
1930097a140dSpatrick         // WASM_SEC_ORDER_GLOBAL
1931097a140dSpatrick         {WASM_SEC_ORDER_GLOBAL, WASM_SEC_ORDER_EXPORT},
1932097a140dSpatrick         // WASM_SEC_ORDER_EXPORT
1933097a140dSpatrick         {WASM_SEC_ORDER_EXPORT, WASM_SEC_ORDER_START},
1934097a140dSpatrick         // WASM_SEC_ORDER_START
1935097a140dSpatrick         {WASM_SEC_ORDER_START, WASM_SEC_ORDER_ELEM},
1936097a140dSpatrick         // WASM_SEC_ORDER_ELEM
1937097a140dSpatrick         {WASM_SEC_ORDER_ELEM, WASM_SEC_ORDER_DATACOUNT},
1938097a140dSpatrick         // WASM_SEC_ORDER_DATACOUNT
1939097a140dSpatrick         {WASM_SEC_ORDER_DATACOUNT, WASM_SEC_ORDER_CODE},
1940097a140dSpatrick         // WASM_SEC_ORDER_CODE
1941097a140dSpatrick         {WASM_SEC_ORDER_CODE, WASM_SEC_ORDER_DATA},
1942097a140dSpatrick         // WASM_SEC_ORDER_DATA
1943097a140dSpatrick         {WASM_SEC_ORDER_DATA, WASM_SEC_ORDER_LINKING},
194409467b48Spatrick 
194509467b48Spatrick         // Custom Sections
1946097a140dSpatrick         // WASM_SEC_ORDER_DYLINK
1947097a140dSpatrick         {WASM_SEC_ORDER_DYLINK, WASM_SEC_ORDER_TYPE},
1948097a140dSpatrick         // WASM_SEC_ORDER_LINKING
1949097a140dSpatrick         {WASM_SEC_ORDER_LINKING, WASM_SEC_ORDER_RELOC, WASM_SEC_ORDER_NAME},
1950097a140dSpatrick         // WASM_SEC_ORDER_RELOC (can be repeated)
1951097a140dSpatrick         {},
1952097a140dSpatrick         // WASM_SEC_ORDER_NAME
1953097a140dSpatrick         {WASM_SEC_ORDER_NAME, WASM_SEC_ORDER_PRODUCERS},
1954097a140dSpatrick         // WASM_SEC_ORDER_PRODUCERS
1955097a140dSpatrick         {WASM_SEC_ORDER_PRODUCERS, WASM_SEC_ORDER_TARGET_FEATURES},
1956097a140dSpatrick         // WASM_SEC_ORDER_TARGET_FEATURES
1957097a140dSpatrick         {WASM_SEC_ORDER_TARGET_FEATURES}};
195809467b48Spatrick 
isValidSectionOrder(unsigned ID,StringRef CustomSectionName)195909467b48Spatrick bool WasmSectionOrderChecker::isValidSectionOrder(unsigned ID,
196009467b48Spatrick                                                   StringRef CustomSectionName) {
196109467b48Spatrick   int Order = getSectionOrder(ID, CustomSectionName);
196209467b48Spatrick   if (Order == WASM_SEC_ORDER_NONE)
196309467b48Spatrick     return true;
196409467b48Spatrick 
196509467b48Spatrick   // Disallowed predecessors we need to check for
196609467b48Spatrick   SmallVector<int, WASM_NUM_SEC_ORDERS> WorkList;
196709467b48Spatrick 
196809467b48Spatrick   // Keep track of completed checks to avoid repeating work
196909467b48Spatrick   bool Checked[WASM_NUM_SEC_ORDERS] = {};
197009467b48Spatrick 
197109467b48Spatrick   int Curr = Order;
197209467b48Spatrick   while (true) {
197309467b48Spatrick     // Add new disallowed predecessors to work list
197409467b48Spatrick     for (size_t I = 0;; ++I) {
197509467b48Spatrick       int Next = DisallowedPredecessors[Curr][I];
197609467b48Spatrick       if (Next == WASM_SEC_ORDER_NONE)
197709467b48Spatrick         break;
197809467b48Spatrick       if (Checked[Next])
197909467b48Spatrick         continue;
198009467b48Spatrick       WorkList.push_back(Next);
198109467b48Spatrick       Checked[Next] = true;
198209467b48Spatrick     }
198309467b48Spatrick 
198409467b48Spatrick     if (WorkList.empty())
198509467b48Spatrick       break;
198609467b48Spatrick 
198709467b48Spatrick     // Consider next disallowed predecessor
198809467b48Spatrick     Curr = WorkList.pop_back_val();
198909467b48Spatrick     if (Seen[Curr])
199009467b48Spatrick       return false;
199109467b48Spatrick   }
199209467b48Spatrick 
199309467b48Spatrick   // Have not seen any disallowed predecessors
199409467b48Spatrick   Seen[Order] = true;
199509467b48Spatrick   return true;
199609467b48Spatrick }
1997