xref: /src/contrib/llvm-project/llvm/lib/Object/WasmObjectFile.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
171d5a254SDimitry Andric //===- WasmObjectFile.cpp - Wasm object file implementation ---------------===//
2b915e9e0SDimitry Andric //
3e6d15924SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e6d15924SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5e6d15924SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6b915e9e0SDimitry Andric //
7b915e9e0SDimitry Andric //===----------------------------------------------------------------------===//
8b915e9e0SDimitry Andric 
971d5a254SDimitry Andric #include "llvm/ADT/ArrayRef.h"
10eb11fae6SDimitry Andric #include "llvm/ADT/DenseSet.h"
11e6d15924SDimitry Andric #include "llvm/ADT/SmallSet.h"
1271d5a254SDimitry Andric #include "llvm/ADT/StringRef.h"
13eb11fae6SDimitry Andric #include "llvm/ADT/StringSet.h"
14cfca06d7SDimitry Andric #include "llvm/ADT/StringSwitch.h"
157ab83427SDimitry Andric #include "llvm/BinaryFormat/Wasm.h"
1671d5a254SDimitry Andric #include "llvm/Object/Binary.h"
1771d5a254SDimitry Andric #include "llvm/Object/Error.h"
1871d5a254SDimitry Andric #include "llvm/Object/ObjectFile.h"
1971d5a254SDimitry Andric #include "llvm/Object/SymbolicFile.h"
20b915e9e0SDimitry Andric #include "llvm/Object/Wasm.h"
21b915e9e0SDimitry Andric #include "llvm/Support/Endian.h"
2271d5a254SDimitry Andric #include "llvm/Support/Error.h"
2371d5a254SDimitry Andric #include "llvm/Support/ErrorHandling.h"
24ac9a064cSDimitry Andric #include "llvm/Support/Format.h"
25b915e9e0SDimitry Andric #include "llvm/Support/LEB128.h"
26d8e91e46SDimitry Andric #include "llvm/Support/ScopedPrinter.h"
277fa27ce4SDimitry Andric #include "llvm/TargetParser/SubtargetFeature.h"
287fa27ce4SDimitry Andric #include "llvm/TargetParser/Triple.h"
2971d5a254SDimitry Andric #include <algorithm>
3012f3ca4cSDimitry Andric #include <cassert>
3171d5a254SDimitry Andric #include <cstdint>
3212f3ca4cSDimitry Andric #include <cstring>
33ac9a064cSDimitry Andric #include <limits>
34b915e9e0SDimitry Andric 
3508bbd35aSDimitry Andric #define DEBUG_TYPE "wasm-object"
3608bbd35aSDimitry Andric 
3771d5a254SDimitry Andric using namespace llvm;
3871d5a254SDimitry Andric using namespace object;
39b915e9e0SDimitry Andric 
print(raw_ostream & Out) const40eb11fae6SDimitry Andric void WasmSymbol::print(raw_ostream &Out) const {
41eb11fae6SDimitry Andric   Out << "Name=" << Info.Name
42344a3780SDimitry Andric       << ", Kind=" << toString(wasm::WasmSymbolType(Info.Kind)) << ", Flags=0x"
437fa27ce4SDimitry Andric       << Twine::utohexstr(Info.Flags) << " [";
447fa27ce4SDimitry Andric   switch (getBinding()) {
457fa27ce4SDimitry Andric     case wasm::WASM_SYMBOL_BINDING_GLOBAL: Out << "global"; break;
467fa27ce4SDimitry Andric     case wasm::WASM_SYMBOL_BINDING_LOCAL: Out << "local"; break;
477fa27ce4SDimitry Andric     case wasm::WASM_SYMBOL_BINDING_WEAK: Out << "weak"; break;
487fa27ce4SDimitry Andric   }
497fa27ce4SDimitry Andric   if (isHidden()) {
507fa27ce4SDimitry Andric     Out << ", hidden";
517fa27ce4SDimitry Andric   } else {
527fa27ce4SDimitry Andric     Out << ", default";
537fa27ce4SDimitry Andric   }
547fa27ce4SDimitry Andric   Out << "]";
55eb11fae6SDimitry Andric   if (!isTypeData()) {
56eb11fae6SDimitry Andric     Out << ", ElemIndex=" << Info.ElementIndex;
57eb11fae6SDimitry Andric   } else if (isDefined()) {
58eb11fae6SDimitry Andric     Out << ", Segment=" << Info.DataRef.Segment;
59eb11fae6SDimitry Andric     Out << ", Offset=" << Info.DataRef.Offset;
60eb11fae6SDimitry Andric     Out << ", Size=" << Info.DataRef.Size;
61eb11fae6SDimitry Andric   }
62eb11fae6SDimitry Andric }
63eb11fae6SDimitry Andric 
64eb11fae6SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
dump() const65eb11fae6SDimitry Andric LLVM_DUMP_METHOD void WasmSymbol::dump() const { print(dbgs()); }
66eb11fae6SDimitry Andric #endif
67eb11fae6SDimitry Andric 
68b915e9e0SDimitry Andric Expected<std::unique_ptr<WasmObjectFile>>
createWasmObjectFile(MemoryBufferRef Buffer)69b915e9e0SDimitry Andric ObjectFile::createWasmObjectFile(MemoryBufferRef Buffer) {
70b915e9e0SDimitry Andric   Error Err = Error::success();
711d5ae102SDimitry Andric   auto ObjectFile = std::make_unique<WasmObjectFile>(Buffer, Err);
72b915e9e0SDimitry Andric   if (Err)
73b915e9e0SDimitry Andric     return std::move(Err);
74b915e9e0SDimitry Andric 
75b915e9e0SDimitry Andric   return std::move(ObjectFile);
76b915e9e0SDimitry Andric }
77b915e9e0SDimitry Andric 
7871d5a254SDimitry Andric #define VARINT7_MAX ((1 << 7) - 1)
7971d5a254SDimitry Andric #define VARINT7_MIN (-(1 << 7))
8071d5a254SDimitry Andric #define VARUINT7_MAX (1 << 7)
8171d5a254SDimitry Andric #define VARUINT1_MAX (1)
82b915e9e0SDimitry Andric 
readUint8(WasmObjectFile::ReadContext & Ctx)83eb11fae6SDimitry Andric static uint8_t readUint8(WasmObjectFile::ReadContext &Ctx) {
84eb11fae6SDimitry Andric   if (Ctx.Ptr == Ctx.End)
85eb11fae6SDimitry Andric     report_fatal_error("EOF while reading uint8");
86eb11fae6SDimitry Andric   return *Ctx.Ptr++;
87eb11fae6SDimitry Andric }
8871d5a254SDimitry Andric 
readUint32(WasmObjectFile::ReadContext & Ctx)89eb11fae6SDimitry Andric static uint32_t readUint32(WasmObjectFile::ReadContext &Ctx) {
90eb11fae6SDimitry Andric   if (Ctx.Ptr + 4 > Ctx.End)
91eb11fae6SDimitry Andric     report_fatal_error("EOF while reading uint32");
92eb11fae6SDimitry Andric   uint32_t Result = support::endian::read32le(Ctx.Ptr);
93eb11fae6SDimitry Andric   Ctx.Ptr += 4;
94b915e9e0SDimitry Andric   return Result;
95b915e9e0SDimitry Andric }
96b915e9e0SDimitry Andric 
readFloat32(WasmObjectFile::ReadContext & Ctx)97eb11fae6SDimitry Andric static int32_t readFloat32(WasmObjectFile::ReadContext &Ctx) {
98d8e91e46SDimitry Andric   if (Ctx.Ptr + 4 > Ctx.End)
99d8e91e46SDimitry Andric     report_fatal_error("EOF while reading float64");
10071d5a254SDimitry Andric   int32_t Result = 0;
101eb11fae6SDimitry Andric   memcpy(&Result, Ctx.Ptr, sizeof(Result));
102eb11fae6SDimitry Andric   Ctx.Ptr += sizeof(Result);
10371d5a254SDimitry Andric   return Result;
10471d5a254SDimitry Andric }
10571d5a254SDimitry Andric 
readFloat64(WasmObjectFile::ReadContext & Ctx)106eb11fae6SDimitry Andric static int64_t readFloat64(WasmObjectFile::ReadContext &Ctx) {
107d8e91e46SDimitry Andric   if (Ctx.Ptr + 8 > Ctx.End)
108d8e91e46SDimitry Andric     report_fatal_error("EOF while reading float64");
10971d5a254SDimitry Andric   int64_t Result = 0;
110eb11fae6SDimitry Andric   memcpy(&Result, Ctx.Ptr, sizeof(Result));
111eb11fae6SDimitry Andric   Ctx.Ptr += sizeof(Result);
11271d5a254SDimitry Andric   return Result;
11371d5a254SDimitry Andric }
11471d5a254SDimitry Andric 
readULEB128(WasmObjectFile::ReadContext & Ctx)115eb11fae6SDimitry Andric static uint64_t readULEB128(WasmObjectFile::ReadContext &Ctx) {
116b915e9e0SDimitry Andric   unsigned Count;
117eb11fae6SDimitry Andric   const char *Error = nullptr;
118eb11fae6SDimitry Andric   uint64_t Result = decodeULEB128(Ctx.Ptr, &Count, Ctx.End, &Error);
119eb11fae6SDimitry Andric   if (Error)
120eb11fae6SDimitry Andric     report_fatal_error(Error);
121eb11fae6SDimitry Andric   Ctx.Ptr += Count;
122b915e9e0SDimitry Andric   return Result;
123b915e9e0SDimitry Andric }
124b915e9e0SDimitry Andric 
readString(WasmObjectFile::ReadContext & Ctx)125eb11fae6SDimitry Andric static StringRef readString(WasmObjectFile::ReadContext &Ctx) {
126eb11fae6SDimitry Andric   uint32_t StringLen = readULEB128(Ctx);
127eb11fae6SDimitry Andric   if (Ctx.Ptr + StringLen > Ctx.End)
128eb11fae6SDimitry Andric     report_fatal_error("EOF while reading string");
129eb11fae6SDimitry Andric   StringRef Return =
130eb11fae6SDimitry Andric       StringRef(reinterpret_cast<const char *>(Ctx.Ptr), StringLen);
131eb11fae6SDimitry Andric   Ctx.Ptr += StringLen;
132b915e9e0SDimitry Andric   return Return;
133b915e9e0SDimitry Andric }
134b915e9e0SDimitry Andric 
readLEB128(WasmObjectFile::ReadContext & Ctx)135eb11fae6SDimitry Andric static int64_t readLEB128(WasmObjectFile::ReadContext &Ctx) {
13671d5a254SDimitry Andric   unsigned Count;
137eb11fae6SDimitry Andric   const char *Error = nullptr;
138eb11fae6SDimitry Andric   uint64_t Result = decodeSLEB128(Ctx.Ptr, &Count, Ctx.End, &Error);
139eb11fae6SDimitry Andric   if (Error)
140eb11fae6SDimitry Andric     report_fatal_error(Error);
141eb11fae6SDimitry Andric   Ctx.Ptr += Count;
14271d5a254SDimitry Andric   return Result;
14371d5a254SDimitry Andric }
14471d5a254SDimitry Andric 
readVaruint1(WasmObjectFile::ReadContext & Ctx)145eb11fae6SDimitry Andric static uint8_t readVaruint1(WasmObjectFile::ReadContext &Ctx) {
146e6d15924SDimitry Andric   int64_t Result = readLEB128(Ctx);
147e6d15924SDimitry Andric   if (Result > VARUINT1_MAX || Result < 0)
148eb11fae6SDimitry Andric     report_fatal_error("LEB is outside Varuint1 range");
149e6d15924SDimitry Andric   return Result;
15071d5a254SDimitry Andric }
15171d5a254SDimitry Andric 
readVarint32(WasmObjectFile::ReadContext & Ctx)152eb11fae6SDimitry Andric static int32_t readVarint32(WasmObjectFile::ReadContext &Ctx) {
153e6d15924SDimitry Andric   int64_t Result = readLEB128(Ctx);
154e6d15924SDimitry Andric   if (Result > INT32_MAX || Result < INT32_MIN)
155eb11fae6SDimitry Andric     report_fatal_error("LEB is outside Varint32 range");
156e6d15924SDimitry Andric   return Result;
15771d5a254SDimitry Andric }
15871d5a254SDimitry Andric 
readVaruint32(WasmObjectFile::ReadContext & Ctx)159eb11fae6SDimitry Andric static uint32_t readVaruint32(WasmObjectFile::ReadContext &Ctx) {
160e6d15924SDimitry Andric   uint64_t Result = readULEB128(Ctx);
161e6d15924SDimitry Andric   if (Result > UINT32_MAX)
162eb11fae6SDimitry Andric     report_fatal_error("LEB is outside Varuint32 range");
163e6d15924SDimitry Andric   return Result;
16471d5a254SDimitry Andric }
16571d5a254SDimitry Andric 
readVarint64(WasmObjectFile::ReadContext & Ctx)166eb11fae6SDimitry Andric static int64_t readVarint64(WasmObjectFile::ReadContext &Ctx) {
167eb11fae6SDimitry Andric   return readLEB128(Ctx);
16871d5a254SDimitry Andric }
16971d5a254SDimitry Andric 
readVaruint64(WasmObjectFile::ReadContext & Ctx)170cfca06d7SDimitry Andric static uint64_t readVaruint64(WasmObjectFile::ReadContext &Ctx) {
171cfca06d7SDimitry Andric   return readULEB128(Ctx);
172cfca06d7SDimitry Andric }
173cfca06d7SDimitry Andric 
readOpcode(WasmObjectFile::ReadContext & Ctx)174eb11fae6SDimitry Andric static uint8_t readOpcode(WasmObjectFile::ReadContext &Ctx) {
175eb11fae6SDimitry Andric   return readUint8(Ctx);
17671d5a254SDimitry Andric }
17771d5a254SDimitry Andric 
parseValType(WasmObjectFile::ReadContext & Ctx,uint32_t Code)178ac9a064cSDimitry Andric static wasm::ValType parseValType(WasmObjectFile::ReadContext &Ctx,
179ac9a064cSDimitry Andric                                   uint32_t Code) {
180ac9a064cSDimitry Andric   // only directly encoded FUNCREF/EXTERNREF/EXNREF are supported
181ac9a064cSDimitry Andric   // (not ref null func, ref null extern, or ref null exn)
182ac9a064cSDimitry Andric   switch (Code) {
183ac9a064cSDimitry Andric   case wasm::WASM_TYPE_I32:
184ac9a064cSDimitry Andric   case wasm::WASM_TYPE_I64:
185ac9a064cSDimitry Andric   case wasm::WASM_TYPE_F32:
186ac9a064cSDimitry Andric   case wasm::WASM_TYPE_F64:
187ac9a064cSDimitry Andric   case wasm::WASM_TYPE_V128:
188ac9a064cSDimitry Andric   case wasm::WASM_TYPE_FUNCREF:
189ac9a064cSDimitry Andric   case wasm::WASM_TYPE_EXTERNREF:
190ac9a064cSDimitry Andric   case wasm::WASM_TYPE_EXNREF:
191ac9a064cSDimitry Andric     return wasm::ValType(Code);
192ac9a064cSDimitry Andric   }
193ac9a064cSDimitry Andric   if (Code == wasm::WASM_TYPE_NULLABLE || Code == wasm::WASM_TYPE_NONNULLABLE) {
194ac9a064cSDimitry Andric     /* Discard HeapType */ readVarint64(Ctx);
195ac9a064cSDimitry Andric   }
196ac9a064cSDimitry Andric   return wasm::ValType(wasm::ValType::OTHERREF);
197ac9a064cSDimitry Andric }
198ac9a064cSDimitry Andric 
readInitExpr(wasm::WasmInitExpr & Expr,WasmObjectFile::ReadContext & Ctx)199eb11fae6SDimitry Andric static Error readInitExpr(wasm::WasmInitExpr &Expr,
200eb11fae6SDimitry Andric                           WasmObjectFile::ReadContext &Ctx) {
201145449b1SDimitry Andric   auto Start = Ctx.Ptr;
20271d5a254SDimitry Andric 
203145449b1SDimitry Andric   Expr.Extended = false;
204145449b1SDimitry Andric   Expr.Inst.Opcode = readOpcode(Ctx);
205145449b1SDimitry Andric   switch (Expr.Inst.Opcode) {
20671d5a254SDimitry Andric   case wasm::WASM_OPCODE_I32_CONST:
207145449b1SDimitry Andric     Expr.Inst.Value.Int32 = readVarint32(Ctx);
20871d5a254SDimitry Andric     break;
20971d5a254SDimitry Andric   case wasm::WASM_OPCODE_I64_CONST:
210145449b1SDimitry Andric     Expr.Inst.Value.Int64 = readVarint64(Ctx);
21171d5a254SDimitry Andric     break;
21271d5a254SDimitry Andric   case wasm::WASM_OPCODE_F32_CONST:
213145449b1SDimitry Andric     Expr.Inst.Value.Float32 = readFloat32(Ctx);
21471d5a254SDimitry Andric     break;
21571d5a254SDimitry Andric   case wasm::WASM_OPCODE_F64_CONST:
216145449b1SDimitry Andric     Expr.Inst.Value.Float64 = readFloat64(Ctx);
21771d5a254SDimitry Andric     break;
218d8e91e46SDimitry Andric   case wasm::WASM_OPCODE_GLOBAL_GET:
219145449b1SDimitry Andric     Expr.Inst.Value.Global = readULEB128(Ctx);
22071d5a254SDimitry Andric     break;
221cfca06d7SDimitry Andric   case wasm::WASM_OPCODE_REF_NULL: {
222ac9a064cSDimitry Andric     /* Discard type */ parseValType(Ctx, readVaruint32(Ctx));
223cfca06d7SDimitry Andric     break;
224cfca06d7SDimitry Andric   }
22571d5a254SDimitry Andric   default:
226145449b1SDimitry Andric     Expr.Extended = true;
22771d5a254SDimitry Andric   }
22871d5a254SDimitry Andric 
229145449b1SDimitry Andric   if (!Expr.Extended) {
230eb11fae6SDimitry Andric     uint8_t EndOpcode = readOpcode(Ctx);
231145449b1SDimitry Andric     if (EndOpcode != wasm::WASM_OPCODE_END)
232145449b1SDimitry Andric       Expr.Extended = true;
233145449b1SDimitry Andric   }
234145449b1SDimitry Andric 
235145449b1SDimitry Andric   if (Expr.Extended) {
236145449b1SDimitry Andric     Ctx.Ptr = Start;
2374b4fe385SDimitry Andric     while (true) {
238145449b1SDimitry Andric       uint8_t Opcode = readOpcode(Ctx);
239145449b1SDimitry Andric       switch (Opcode) {
240145449b1SDimitry Andric       case wasm::WASM_OPCODE_I32_CONST:
241145449b1SDimitry Andric       case wasm::WASM_OPCODE_GLOBAL_GET:
242145449b1SDimitry Andric       case wasm::WASM_OPCODE_REF_NULL:
243ac9a064cSDimitry Andric       case wasm::WASM_OPCODE_REF_FUNC:
244145449b1SDimitry Andric       case wasm::WASM_OPCODE_I64_CONST:
245145449b1SDimitry Andric         readULEB128(Ctx);
246145449b1SDimitry Andric         break;
247ac9a064cSDimitry Andric       case wasm::WASM_OPCODE_F32_CONST:
248ac9a064cSDimitry Andric         readFloat32(Ctx);
249ac9a064cSDimitry Andric         break;
250ac9a064cSDimitry Andric       case wasm::WASM_OPCODE_F64_CONST:
251ac9a064cSDimitry Andric         readFloat64(Ctx);
252ac9a064cSDimitry Andric         break;
253145449b1SDimitry Andric       case wasm::WASM_OPCODE_I32_ADD:
254145449b1SDimitry Andric       case wasm::WASM_OPCODE_I32_SUB:
255145449b1SDimitry Andric       case wasm::WASM_OPCODE_I32_MUL:
256145449b1SDimitry Andric       case wasm::WASM_OPCODE_I64_ADD:
257145449b1SDimitry Andric       case wasm::WASM_OPCODE_I64_SUB:
258145449b1SDimitry Andric       case wasm::WASM_OPCODE_I64_MUL:
259145449b1SDimitry Andric         break;
260ac9a064cSDimitry Andric       case wasm::WASM_OPCODE_GC_PREFIX:
261ac9a064cSDimitry Andric         break;
262ac9a064cSDimitry Andric       // The GC opcodes are in a separate (prefixed space). This flat switch
263ac9a064cSDimitry Andric       // structure works as long as there is no overlap between the GC and
264ac9a064cSDimitry Andric       // general opcodes used in init exprs.
265ac9a064cSDimitry Andric       case wasm::WASM_OPCODE_STRUCT_NEW:
266ac9a064cSDimitry Andric       case wasm::WASM_OPCODE_STRUCT_NEW_DEFAULT:
267ac9a064cSDimitry Andric       case wasm::WASM_OPCODE_ARRAY_NEW:
268ac9a064cSDimitry Andric       case wasm::WASM_OPCODE_ARRAY_NEW_DEFAULT:
269ac9a064cSDimitry Andric         readULEB128(Ctx); // heap type index
270ac9a064cSDimitry Andric         break;
271ac9a064cSDimitry Andric       case wasm::WASM_OPCODE_ARRAY_NEW_FIXED:
272ac9a064cSDimitry Andric         readULEB128(Ctx); // heap type index
273ac9a064cSDimitry Andric         readULEB128(Ctx); // array size
274ac9a064cSDimitry Andric         break;
275ac9a064cSDimitry Andric       case wasm::WASM_OPCODE_REF_I31:
276ac9a064cSDimitry Andric         break;
277145449b1SDimitry Andric       case wasm::WASM_OPCODE_END:
278145449b1SDimitry Andric         Expr.Body = ArrayRef<uint8_t>(Start, Ctx.Ptr - Start);
279145449b1SDimitry Andric         return Error::success();
280145449b1SDimitry Andric       default:
281145449b1SDimitry Andric         return make_error<GenericBinaryError>(
282145449b1SDimitry Andric             Twine("invalid opcode in init_expr: ") + Twine(unsigned(Opcode)),
28371d5a254SDimitry Andric             object_error::parse_failed);
28471d5a254SDimitry Andric       }
285145449b1SDimitry Andric     }
286145449b1SDimitry Andric   }
287145449b1SDimitry Andric 
28871d5a254SDimitry Andric   return Error::success();
28971d5a254SDimitry Andric }
29071d5a254SDimitry Andric 
readLimits(WasmObjectFile::ReadContext & Ctx)291eb11fae6SDimitry Andric static wasm::WasmLimits readLimits(WasmObjectFile::ReadContext &Ctx) {
29271d5a254SDimitry Andric   wasm::WasmLimits Result;
293d8e91e46SDimitry Andric   Result.Flags = readVaruint32(Ctx);
294344a3780SDimitry Andric   Result.Minimum = readVaruint64(Ctx);
29571d5a254SDimitry Andric   if (Result.Flags & wasm::WASM_LIMITS_FLAG_HAS_MAX)
296cfca06d7SDimitry Andric     Result.Maximum = readVaruint64(Ctx);
29771d5a254SDimitry Andric   return Result;
29871d5a254SDimitry Andric }
29971d5a254SDimitry Andric 
readTableType(WasmObjectFile::ReadContext & Ctx)300b60736ecSDimitry Andric static wasm::WasmTableType readTableType(WasmObjectFile::ReadContext &Ctx) {
301b60736ecSDimitry Andric   wasm::WasmTableType TableType;
302ac9a064cSDimitry Andric   auto ElemType = parseValType(Ctx, readVaruint32(Ctx));
303ac9a064cSDimitry Andric   TableType.ElemType = ElemType;
304b60736ecSDimitry Andric   TableType.Limits = readLimits(Ctx);
305b60736ecSDimitry Andric   return TableType;
3066b3f41edSDimitry Andric }
3076b3f41edSDimitry Andric 
readSection(WasmSection & Section,WasmObjectFile::ReadContext & Ctx,WasmSectionOrderChecker & Checker)308d8e91e46SDimitry Andric static Error readSection(WasmSection &Section, WasmObjectFile::ReadContext &Ctx,
309d8e91e46SDimitry Andric                          WasmSectionOrderChecker &Checker) {
310eb11fae6SDimitry Andric   Section.Type = readUint8(Ctx);
311eb11fae6SDimitry Andric   LLVM_DEBUG(dbgs() << "readSection type=" << Section.Type << "\n");
312b1c73532SDimitry Andric   // When reading the section's size, store the size of the LEB used to encode
313b1c73532SDimitry Andric   // it. This allows objcopy/strip to reproduce the binary identically.
314b1c73532SDimitry Andric   const uint8_t *PreSizePtr = Ctx.Ptr;
315eb11fae6SDimitry Andric   uint32_t Size = readVaruint32(Ctx);
316b1c73532SDimitry Andric   Section.HeaderSecSizeEncodingLen = Ctx.Ptr - PreSizePtr;
31799aabd70SDimitry Andric   Section.Offset = Ctx.Ptr - Ctx.Start;
318b915e9e0SDimitry Andric   if (Size == 0)
319b60736ecSDimitry Andric     return make_error<StringError>("zero length section",
320b915e9e0SDimitry Andric                                    object_error::parse_failed);
321eb11fae6SDimitry Andric   if (Ctx.Ptr + Size > Ctx.End)
322b60736ecSDimitry Andric     return make_error<StringError>("section too large",
323044eb2f6SDimitry Andric                                    object_error::parse_failed);
324eb11fae6SDimitry Andric   if (Section.Type == wasm::WASM_SEC_CUSTOM) {
325d8e91e46SDimitry Andric     WasmObjectFile::ReadContext SectionCtx;
326d8e91e46SDimitry Andric     SectionCtx.Start = Ctx.Ptr;
327d8e91e46SDimitry Andric     SectionCtx.Ptr = Ctx.Ptr;
328d8e91e46SDimitry Andric     SectionCtx.End = Ctx.Ptr + Size;
329d8e91e46SDimitry Andric 
330d8e91e46SDimitry Andric     Section.Name = readString(SectionCtx);
331d8e91e46SDimitry Andric 
332d8e91e46SDimitry Andric     uint32_t SectionNameSize = SectionCtx.Ptr - SectionCtx.Start;
333d8e91e46SDimitry Andric     Ctx.Ptr += SectionNameSize;
334d8e91e46SDimitry Andric     Size -= SectionNameSize;
335eb11fae6SDimitry Andric   }
336d8e91e46SDimitry Andric 
337d8e91e46SDimitry Andric   if (!Checker.isValidSectionOrder(Section.Type, Section.Name)) {
338b60736ecSDimitry Andric     return make_error<StringError>("out of order section type: " +
339d8e91e46SDimitry Andric                                        llvm::to_string(Section.Type),
340d8e91e46SDimitry Andric                                    object_error::parse_failed);
341d8e91e46SDimitry Andric   }
342d8e91e46SDimitry Andric 
343eb11fae6SDimitry Andric   Section.Content = ArrayRef<uint8_t>(Ctx.Ptr, Size);
344eb11fae6SDimitry Andric   Ctx.Ptr += Size;
345b915e9e0SDimitry Andric   return Error::success();
346b915e9e0SDimitry Andric }
347b915e9e0SDimitry Andric 
WasmObjectFile(MemoryBufferRef Buffer,Error & Err)348b915e9e0SDimitry Andric WasmObjectFile::WasmObjectFile(MemoryBufferRef Buffer, Error &Err)
34912f3ca4cSDimitry Andric     : ObjectFile(Binary::ID_Wasm, Buffer) {
350b915e9e0SDimitry Andric   ErrorAsOutParameter ErrAsOutParam(&Err);
351b915e9e0SDimitry Andric   Header.Magic = getData().substr(0, 4);
352b915e9e0SDimitry Andric   if (Header.Magic != StringRef("\0asm", 4)) {
353b60736ecSDimitry Andric     Err = make_error<StringError>("invalid magic number",
354b60736ecSDimitry Andric                                   object_error::parse_failed);
355b915e9e0SDimitry Andric     return;
356b915e9e0SDimitry Andric   }
357044eb2f6SDimitry Andric 
358eb11fae6SDimitry Andric   ReadContext Ctx;
359e6d15924SDimitry Andric   Ctx.Start = getData().bytes_begin();
360eb11fae6SDimitry Andric   Ctx.Ptr = Ctx.Start + 4;
361eb11fae6SDimitry Andric   Ctx.End = Ctx.Start + getData().size();
362044eb2f6SDimitry Andric 
363eb11fae6SDimitry Andric   if (Ctx.Ptr + 4 > Ctx.End) {
364b60736ecSDimitry Andric     Err = make_error<StringError>("missing version number",
365044eb2f6SDimitry Andric                                   object_error::parse_failed);
366044eb2f6SDimitry Andric     return;
367044eb2f6SDimitry Andric   }
368044eb2f6SDimitry Andric 
369eb11fae6SDimitry Andric   Header.Version = readUint32(Ctx);
370b915e9e0SDimitry Andric   if (Header.Version != wasm::WasmVersion) {
371b60736ecSDimitry Andric     Err = make_error<StringError>("invalid version number: " +
372b60736ecSDimitry Andric                                       Twine(Header.Version),
373b915e9e0SDimitry Andric                                   object_error::parse_failed);
374b915e9e0SDimitry Andric     return;
375b915e9e0SDimitry Andric   }
376b915e9e0SDimitry Andric 
377d8e91e46SDimitry Andric   WasmSectionOrderChecker Checker;
378eb11fae6SDimitry Andric   while (Ctx.Ptr < Ctx.End) {
379c0981da4SDimitry Andric     WasmSection Sec;
380d8e91e46SDimitry Andric     if ((Err = readSection(Sec, Ctx, Checker)))
381b915e9e0SDimitry Andric       return;
38271d5a254SDimitry Andric     if ((Err = parseSection(Sec)))
383b915e9e0SDimitry Andric       return;
38471d5a254SDimitry Andric 
385b915e9e0SDimitry Andric     Sections.push_back(Sec);
386b915e9e0SDimitry Andric   }
387b915e9e0SDimitry Andric }
388b915e9e0SDimitry Andric 
parseSection(WasmSection & Sec)38971d5a254SDimitry Andric Error WasmObjectFile::parseSection(WasmSection &Sec) {
390eb11fae6SDimitry Andric   ReadContext Ctx;
391eb11fae6SDimitry Andric   Ctx.Start = Sec.Content.data();
392eb11fae6SDimitry Andric   Ctx.End = Ctx.Start + Sec.Content.size();
393eb11fae6SDimitry Andric   Ctx.Ptr = Ctx.Start;
39471d5a254SDimitry Andric   switch (Sec.Type) {
39571d5a254SDimitry Andric   case wasm::WASM_SEC_CUSTOM:
396eb11fae6SDimitry Andric     return parseCustomSection(Sec, Ctx);
39771d5a254SDimitry Andric   case wasm::WASM_SEC_TYPE:
398eb11fae6SDimitry Andric     return parseTypeSection(Ctx);
39971d5a254SDimitry Andric   case wasm::WASM_SEC_IMPORT:
400eb11fae6SDimitry Andric     return parseImportSection(Ctx);
40171d5a254SDimitry Andric   case wasm::WASM_SEC_FUNCTION:
402eb11fae6SDimitry Andric     return parseFunctionSection(Ctx);
40371d5a254SDimitry Andric   case wasm::WASM_SEC_TABLE:
404eb11fae6SDimitry Andric     return parseTableSection(Ctx);
40571d5a254SDimitry Andric   case wasm::WASM_SEC_MEMORY:
406eb11fae6SDimitry Andric     return parseMemorySection(Ctx);
407344a3780SDimitry Andric   case wasm::WASM_SEC_TAG:
408344a3780SDimitry Andric     return parseTagSection(Ctx);
409cfca06d7SDimitry Andric   case wasm::WASM_SEC_GLOBAL:
410cfca06d7SDimitry Andric     return parseGlobalSection(Ctx);
41171d5a254SDimitry Andric   case wasm::WASM_SEC_EXPORT:
412eb11fae6SDimitry Andric     return parseExportSection(Ctx);
41371d5a254SDimitry Andric   case wasm::WASM_SEC_START:
414eb11fae6SDimitry Andric     return parseStartSection(Ctx);
41571d5a254SDimitry Andric   case wasm::WASM_SEC_ELEM:
416eb11fae6SDimitry Andric     return parseElemSection(Ctx);
41771d5a254SDimitry Andric   case wasm::WASM_SEC_CODE:
418eb11fae6SDimitry Andric     return parseCodeSection(Ctx);
41971d5a254SDimitry Andric   case wasm::WASM_SEC_DATA:
420eb11fae6SDimitry Andric     return parseDataSection(Ctx);
421e6d15924SDimitry Andric   case wasm::WASM_SEC_DATACOUNT:
422e6d15924SDimitry Andric     return parseDataCountSection(Ctx);
42371d5a254SDimitry Andric   default:
424e6d15924SDimitry Andric     return make_error<GenericBinaryError>(
425b60736ecSDimitry Andric         "invalid section type: " + Twine(Sec.Type), object_error::parse_failed);
42671d5a254SDimitry Andric   }
42771d5a254SDimitry Andric }
42871d5a254SDimitry Andric 
parseDylinkSection(ReadContext & Ctx)429d8e91e46SDimitry Andric Error WasmObjectFile::parseDylinkSection(ReadContext &Ctx) {
430c0981da4SDimitry Andric   // Legacy "dylink" section support.
431c0981da4SDimitry Andric   // See parseDylink0Section for the current "dylink.0" section parsing.
432e6d15924SDimitry Andric   HasDylinkSection = true;
433d8e91e46SDimitry Andric   DylinkInfo.MemorySize = readVaruint32(Ctx);
434d8e91e46SDimitry Andric   DylinkInfo.MemoryAlignment = readVaruint32(Ctx);
435d8e91e46SDimitry Andric   DylinkInfo.TableSize = readVaruint32(Ctx);
436d8e91e46SDimitry Andric   DylinkInfo.TableAlignment = readVaruint32(Ctx);
437d8e91e46SDimitry Andric   uint32_t Count = readVaruint32(Ctx);
438d8e91e46SDimitry Andric   while (Count--) {
439d8e91e46SDimitry Andric     DylinkInfo.Needed.push_back(readString(Ctx));
440d8e91e46SDimitry Andric   }
441c0981da4SDimitry Andric 
442d8e91e46SDimitry Andric   if (Ctx.Ptr != Ctx.End)
443d8e91e46SDimitry Andric     return make_error<GenericBinaryError>("dylink section ended prematurely",
444d8e91e46SDimitry Andric                                           object_error::parse_failed);
445d8e91e46SDimitry Andric   return Error::success();
446d8e91e46SDimitry Andric }
447d8e91e46SDimitry Andric 
parseDylink0Section(ReadContext & Ctx)448c0981da4SDimitry Andric Error WasmObjectFile::parseDylink0Section(ReadContext &Ctx) {
449c0981da4SDimitry Andric   // See
450c0981da4SDimitry Andric   // https://github.com/WebAssembly/tool-conventions/blob/main/DynamicLinking.md
451c0981da4SDimitry Andric   HasDylinkSection = true;
452c0981da4SDimitry Andric 
453c0981da4SDimitry Andric   const uint8_t *OrigEnd = Ctx.End;
454c0981da4SDimitry Andric   while (Ctx.Ptr < OrigEnd) {
455c0981da4SDimitry Andric     Ctx.End = OrigEnd;
456c0981da4SDimitry Andric     uint8_t Type = readUint8(Ctx);
457c0981da4SDimitry Andric     uint32_t Size = readVaruint32(Ctx);
458c0981da4SDimitry Andric     LLVM_DEBUG(dbgs() << "readSubsection type=" << int(Type) << " size=" << Size
459c0981da4SDimitry Andric                       << "\n");
460c0981da4SDimitry Andric     Ctx.End = Ctx.Ptr + Size;
461c0981da4SDimitry Andric     uint32_t Count;
462c0981da4SDimitry Andric     switch (Type) {
463c0981da4SDimitry Andric     case wasm::WASM_DYLINK_MEM_INFO:
464c0981da4SDimitry Andric       DylinkInfo.MemorySize = readVaruint32(Ctx);
465c0981da4SDimitry Andric       DylinkInfo.MemoryAlignment = readVaruint32(Ctx);
466c0981da4SDimitry Andric       DylinkInfo.TableSize = readVaruint32(Ctx);
467c0981da4SDimitry Andric       DylinkInfo.TableAlignment = readVaruint32(Ctx);
468c0981da4SDimitry Andric       break;
469c0981da4SDimitry Andric     case wasm::WASM_DYLINK_NEEDED:
470c0981da4SDimitry Andric       Count = readVaruint32(Ctx);
471c0981da4SDimitry Andric       while (Count--) {
472c0981da4SDimitry Andric         DylinkInfo.Needed.push_back(readString(Ctx));
473c0981da4SDimitry Andric       }
474c0981da4SDimitry Andric       break;
475c0981da4SDimitry Andric     case wasm::WASM_DYLINK_EXPORT_INFO: {
476c0981da4SDimitry Andric       uint32_t Count = readVaruint32(Ctx);
477c0981da4SDimitry Andric       while (Count--) {
478c0981da4SDimitry Andric         DylinkInfo.ExportInfo.push_back({readString(Ctx), readVaruint32(Ctx)});
479c0981da4SDimitry Andric       }
480c0981da4SDimitry Andric       break;
481c0981da4SDimitry Andric     }
482c0981da4SDimitry Andric     case wasm::WASM_DYLINK_IMPORT_INFO: {
483c0981da4SDimitry Andric       uint32_t Count = readVaruint32(Ctx);
484c0981da4SDimitry Andric       while (Count--) {
485c0981da4SDimitry Andric         DylinkInfo.ImportInfo.push_back(
486c0981da4SDimitry Andric             {readString(Ctx), readString(Ctx), readVaruint32(Ctx)});
487c0981da4SDimitry Andric       }
488c0981da4SDimitry Andric       break;
489c0981da4SDimitry Andric     }
490c0981da4SDimitry Andric     default:
491c0981da4SDimitry Andric       LLVM_DEBUG(dbgs() << "unknown dylink.0 sub-section: " << Type << "\n");
492c0981da4SDimitry Andric       Ctx.Ptr += Size;
493c0981da4SDimitry Andric       break;
494c0981da4SDimitry Andric     }
495c0981da4SDimitry Andric     if (Ctx.Ptr != Ctx.End) {
496c0981da4SDimitry Andric       return make_error<GenericBinaryError>(
497c0981da4SDimitry Andric           "dylink.0 sub-section ended prematurely", object_error::parse_failed);
498c0981da4SDimitry Andric     }
499c0981da4SDimitry Andric   }
500c0981da4SDimitry Andric 
501c0981da4SDimitry Andric   if (Ctx.Ptr != Ctx.End)
502c0981da4SDimitry Andric     return make_error<GenericBinaryError>("dylink.0 section ended prematurely",
503c0981da4SDimitry Andric                                           object_error::parse_failed);
504c0981da4SDimitry Andric   return Error::success();
505c0981da4SDimitry Andric }
506c0981da4SDimitry Andric 
parseNameSection(ReadContext & Ctx)507eb11fae6SDimitry Andric Error WasmObjectFile::parseNameSection(ReadContext &Ctx) {
508b60736ecSDimitry Andric   llvm::DenseSet<uint64_t> SeenFunctions;
509b60736ecSDimitry Andric   llvm::DenseSet<uint64_t> SeenGlobals;
510b60736ecSDimitry Andric   llvm::DenseSet<uint64_t> SeenSegments;
511eb11fae6SDimitry Andric 
512ac9a064cSDimitry Andric   // If we have linking section (symbol table) or if we are parsing a DSO
513ac9a064cSDimitry Andric   // then we don't use the name section for symbol information.
514ac9a064cSDimitry Andric   bool PopulateSymbolTable = !HasLinkingSection && !HasDylinkSection;
515ac9a064cSDimitry Andric 
516ac9a064cSDimitry Andric   // If we are using the name section for symbol information then it will
517ac9a064cSDimitry Andric   // supersede any symbols created by the export section.
518ac9a064cSDimitry Andric   if (PopulateSymbolTable)
519ac9a064cSDimitry Andric     Symbols.clear();
520ac9a064cSDimitry Andric 
521eb11fae6SDimitry Andric   while (Ctx.Ptr < Ctx.End) {
522eb11fae6SDimitry Andric     uint8_t Type = readUint8(Ctx);
523eb11fae6SDimitry Andric     uint32_t Size = readVaruint32(Ctx);
524eb11fae6SDimitry Andric     const uint8_t *SubSectionEnd = Ctx.Ptr + Size;
525ac9a064cSDimitry Andric 
52671d5a254SDimitry Andric     switch (Type) {
527b60736ecSDimitry Andric     case wasm::WASM_NAMES_FUNCTION:
528b60736ecSDimitry Andric     case wasm::WASM_NAMES_GLOBAL:
529b60736ecSDimitry Andric     case wasm::WASM_NAMES_DATA_SEGMENT: {
530eb11fae6SDimitry Andric       uint32_t Count = readVaruint32(Ctx);
53171d5a254SDimitry Andric       while (Count--) {
532eb11fae6SDimitry Andric         uint32_t Index = readVaruint32(Ctx);
533eb11fae6SDimitry Andric         StringRef Name = readString(Ctx);
534b60736ecSDimitry Andric         wasm::NameType nameType = wasm::NameType::FUNCTION;
535ac9a064cSDimitry Andric         wasm::WasmSymbolInfo Info{Name,
536ac9a064cSDimitry Andric                                   /*Kind */ wasm::WASM_SYMBOL_TYPE_FUNCTION,
537ac9a064cSDimitry Andric                                   /* Flags */ 0,
538ac9a064cSDimitry Andric                                   /* ImportModule */ std::nullopt,
539ac9a064cSDimitry Andric                                   /* ImportName */ std::nullopt,
540ac9a064cSDimitry Andric                                   /* ExportName */ std::nullopt,
541ac9a064cSDimitry Andric                                   {/* ElementIndex */ Index}};
542ac9a064cSDimitry Andric         const wasm::WasmSignature *Signature = nullptr;
543ac9a064cSDimitry Andric         const wasm::WasmGlobalType *GlobalType = nullptr;
544ac9a064cSDimitry Andric         const wasm::WasmTableType *TableType = nullptr;
545b60736ecSDimitry Andric         if (Type == wasm::WASM_NAMES_FUNCTION) {
546b60736ecSDimitry Andric           if (!SeenFunctions.insert(Index).second)
547b60736ecSDimitry Andric             return make_error<GenericBinaryError>(
548b60736ecSDimitry Andric                 "function named more than once", object_error::parse_failed);
549eb11fae6SDimitry Andric           if (!isValidFunctionIndex(Index) || Name.empty())
550145449b1SDimitry Andric             return make_error<GenericBinaryError>("invalid function name entry",
551eb11fae6SDimitry Andric                                                   object_error::parse_failed);
552b60736ecSDimitry Andric 
553ac9a064cSDimitry Andric           if (isDefinedFunctionIndex(Index)) {
554ac9a064cSDimitry Andric             wasm::WasmFunction &F = getDefinedFunction(Index);
555ac9a064cSDimitry Andric             F.DebugName = Name;
556ac9a064cSDimitry Andric             Signature = &Signatures[F.SigIndex];
557ac9a064cSDimitry Andric             if (F.ExportName) {
558ac9a064cSDimitry Andric               Info.ExportName = F.ExportName;
559ac9a064cSDimitry Andric               Info.Flags |= wasm::WASM_SYMBOL_BINDING_GLOBAL;
560ac9a064cSDimitry Andric             } else {
561ac9a064cSDimitry Andric               Info.Flags |= wasm::WASM_SYMBOL_BINDING_LOCAL;
562ac9a064cSDimitry Andric             }
563ac9a064cSDimitry Andric           } else {
564ac9a064cSDimitry Andric             Info.Flags |= wasm::WASM_SYMBOL_UNDEFINED;
565ac9a064cSDimitry Andric           }
566b60736ecSDimitry Andric         } else if (Type == wasm::WASM_NAMES_GLOBAL) {
567b60736ecSDimitry Andric           if (!SeenGlobals.insert(Index).second)
568b60736ecSDimitry Andric             return make_error<GenericBinaryError>("global named more than once",
569b60736ecSDimitry Andric                                                   object_error::parse_failed);
570b60736ecSDimitry Andric           if (!isValidGlobalIndex(Index) || Name.empty())
571145449b1SDimitry Andric             return make_error<GenericBinaryError>("invalid global name entry",
572b60736ecSDimitry Andric                                                   object_error::parse_failed);
573ac9a064cSDimitry Andric           nameType = wasm::NameType::GLOBAL;
574ac9a064cSDimitry Andric           Info.Kind = wasm::WASM_SYMBOL_TYPE_GLOBAL;
575ac9a064cSDimitry Andric           if (isDefinedGlobalIndex(Index)) {
576ac9a064cSDimitry Andric             GlobalType = &getDefinedGlobal(Index).Type;
577b60736ecSDimitry Andric           } else {
578ac9a064cSDimitry Andric             Info.Flags |= wasm::WASM_SYMBOL_UNDEFINED;
579ac9a064cSDimitry Andric           }
580ac9a064cSDimitry Andric         } else {
581b60736ecSDimitry Andric           if (!SeenSegments.insert(Index).second)
582b60736ecSDimitry Andric             return make_error<GenericBinaryError>(
583b60736ecSDimitry Andric                 "segment named more than once", object_error::parse_failed);
584b60736ecSDimitry Andric           if (Index > DataSegments.size())
585145449b1SDimitry Andric             return make_error<GenericBinaryError>("invalid data segment name entry",
586b60736ecSDimitry Andric                                                   object_error::parse_failed);
587ac9a064cSDimitry Andric           nameType = wasm::NameType::DATA_SEGMENT;
588ac9a064cSDimitry Andric           Info.Kind = wasm::WASM_SYMBOL_TYPE_DATA;
589ac9a064cSDimitry Andric           Info.Flags |= wasm::WASM_SYMBOL_BINDING_LOCAL;
590ac9a064cSDimitry Andric           assert(Index < DataSegments.size());
591ac9a064cSDimitry Andric           Info.DataRef = wasm::WasmDataReference{
592ac9a064cSDimitry Andric               Index, 0, DataSegments[Index].Data.Content.size()};
593b60736ecSDimitry Andric         }
594b60736ecSDimitry Andric         DebugNames.push_back(wasm::WasmDebugName{nameType, Index, Name});
595ac9a064cSDimitry Andric         if (PopulateSymbolTable)
596ac9a064cSDimitry Andric           Symbols.emplace_back(Info, GlobalType, TableType, Signature);
59771d5a254SDimitry Andric       }
59871d5a254SDimitry Andric       break;
59971d5a254SDimitry Andric     }
60071d5a254SDimitry Andric     // Ignore local names for now
60171d5a254SDimitry Andric     case wasm::WASM_NAMES_LOCAL:
60271d5a254SDimitry Andric     default:
603eb11fae6SDimitry Andric       Ctx.Ptr += Size;
60471d5a254SDimitry Andric       break;
60571d5a254SDimitry Andric     }
606eb11fae6SDimitry Andric     if (Ctx.Ptr != SubSectionEnd)
607d8e91e46SDimitry Andric       return make_error<GenericBinaryError>(
608b60736ecSDimitry Andric           "name sub-section ended prematurely", object_error::parse_failed);
60971d5a254SDimitry Andric   }
61071d5a254SDimitry Andric 
611eb11fae6SDimitry Andric   if (Ctx.Ptr != Ctx.End)
612b60736ecSDimitry Andric     return make_error<GenericBinaryError>("name section ended prematurely",
61371d5a254SDimitry Andric                                           object_error::parse_failed);
61471d5a254SDimitry Andric   return Error::success();
61571d5a254SDimitry Andric }
61671d5a254SDimitry Andric 
parseLinkingSection(ReadContext & Ctx)617eb11fae6SDimitry Andric Error WasmObjectFile::parseLinkingSection(ReadContext &Ctx) {
6189df3605dSDimitry Andric   HasLinkingSection = true;
619eb11fae6SDimitry Andric 
620eb11fae6SDimitry Andric   LinkingData.Version = readVaruint32(Ctx);
621eb11fae6SDimitry Andric   if (LinkingData.Version != wasm::WasmMetadataVersion) {
622eb11fae6SDimitry Andric     return make_error<GenericBinaryError>(
623b60736ecSDimitry Andric         "unexpected metadata version: " + Twine(LinkingData.Version) +
624eb11fae6SDimitry Andric             " (Expected: " + Twine(wasm::WasmMetadataVersion) + ")",
62508bbd35aSDimitry Andric         object_error::parse_failed);
62608bbd35aSDimitry Andric   }
627eb11fae6SDimitry Andric 
628eb11fae6SDimitry Andric   const uint8_t *OrigEnd = Ctx.End;
629eb11fae6SDimitry Andric   while (Ctx.Ptr < OrigEnd) {
630eb11fae6SDimitry Andric     Ctx.End = OrigEnd;
631eb11fae6SDimitry Andric     uint8_t Type = readUint8(Ctx);
632eb11fae6SDimitry Andric     uint32_t Size = readVaruint32(Ctx);
633eb11fae6SDimitry Andric     LLVM_DEBUG(dbgs() << "readSubsection type=" << int(Type) << " size=" << Size
634eb11fae6SDimitry Andric                       << "\n");
635eb11fae6SDimitry Andric     Ctx.End = Ctx.Ptr + Size;
636eb11fae6SDimitry Andric     switch (Type) {
637eb11fae6SDimitry Andric     case wasm::WASM_SYMBOL_TABLE:
638eb11fae6SDimitry Andric       if (Error Err = parseLinkingSectionSymtab(Ctx))
639eb11fae6SDimitry Andric         return Err;
6409df3605dSDimitry Andric       break;
641044eb2f6SDimitry Andric     case wasm::WASM_SEGMENT_INFO: {
642eb11fae6SDimitry Andric       uint32_t Count = readVaruint32(Ctx);
643044eb2f6SDimitry Andric       if (Count > DataSegments.size())
644b60736ecSDimitry Andric         return make_error<GenericBinaryError>("too many segment names",
645044eb2f6SDimitry Andric                                               object_error::parse_failed);
646e6d15924SDimitry Andric       for (uint32_t I = 0; I < Count; I++) {
647e6d15924SDimitry Andric         DataSegments[I].Data.Name = readString(Ctx);
648e6d15924SDimitry Andric         DataSegments[I].Data.Alignment = readVaruint32(Ctx);
649344a3780SDimitry Andric         DataSegments[I].Data.LinkingFlags = readVaruint32(Ctx);
650044eb2f6SDimitry Andric       }
6519df3605dSDimitry Andric       break;
652044eb2f6SDimitry Andric     }
653044eb2f6SDimitry Andric     case wasm::WASM_INIT_FUNCS: {
654eb11fae6SDimitry Andric       uint32_t Count = readVaruint32(Ctx);
655044eb2f6SDimitry Andric       LinkingData.InitFunctions.reserve(Count);
656e6d15924SDimitry Andric       for (uint32_t I = 0; I < Count; I++) {
657044eb2f6SDimitry Andric         wasm::WasmInitFunc Init;
658eb11fae6SDimitry Andric         Init.Priority = readVaruint32(Ctx);
659eb11fae6SDimitry Andric         Init.Symbol = readVaruint32(Ctx);
660eb11fae6SDimitry Andric         if (!isValidFunctionSymbol(Init.Symbol))
661b60736ecSDimitry Andric           return make_error<GenericBinaryError>("invalid function symbol: " +
662eb11fae6SDimitry Andric                                                     Twine(Init.Symbol),
663044eb2f6SDimitry Andric                                                 object_error::parse_failed);
664044eb2f6SDimitry Andric         LinkingData.InitFunctions.emplace_back(Init);
665044eb2f6SDimitry Andric       }
666044eb2f6SDimitry Andric       break;
667044eb2f6SDimitry Andric     }
668eb11fae6SDimitry Andric     case wasm::WASM_COMDAT_INFO:
669eb11fae6SDimitry Andric       if (Error Err = parseLinkingSectionComdat(Ctx))
670eb11fae6SDimitry Andric         return Err;
671eb11fae6SDimitry Andric       break;
67208bbd35aSDimitry Andric     default:
673eb11fae6SDimitry Andric       Ctx.Ptr += Size;
67408bbd35aSDimitry Andric       break;
67508bbd35aSDimitry Andric     }
676eb11fae6SDimitry Andric     if (Ctx.Ptr != Ctx.End)
67708bbd35aSDimitry Andric       return make_error<GenericBinaryError>(
678b60736ecSDimitry Andric           "linking sub-section ended prematurely", object_error::parse_failed);
67908bbd35aSDimitry Andric   }
680eb11fae6SDimitry Andric   if (Ctx.Ptr != OrigEnd)
681b60736ecSDimitry Andric     return make_error<GenericBinaryError>("linking section ended prematurely",
68208bbd35aSDimitry Andric                                           object_error::parse_failed);
68308bbd35aSDimitry Andric   return Error::success();
68408bbd35aSDimitry Andric }
68508bbd35aSDimitry Andric 
parseLinkingSectionSymtab(ReadContext & Ctx)686eb11fae6SDimitry Andric Error WasmObjectFile::parseLinkingSectionSymtab(ReadContext &Ctx) {
687eb11fae6SDimitry Andric   uint32_t Count = readVaruint32(Ctx);
68899aabd70SDimitry Andric   // Clear out any symbol information that was derived from the exports
68999aabd70SDimitry Andric   // section.
69099aabd70SDimitry Andric   Symbols.clear();
691eb11fae6SDimitry Andric   Symbols.reserve(Count);
692eb11fae6SDimitry Andric   StringSet<> SymbolNames;
693eb11fae6SDimitry Andric 
694eb11fae6SDimitry Andric   std::vector<wasm::WasmImport *> ImportedGlobals;
695eb11fae6SDimitry Andric   std::vector<wasm::WasmImport *> ImportedFunctions;
696344a3780SDimitry Andric   std::vector<wasm::WasmImport *> ImportedTags;
697b60736ecSDimitry Andric   std::vector<wasm::WasmImport *> ImportedTables;
698eb11fae6SDimitry Andric   ImportedGlobals.reserve(Imports.size());
699eb11fae6SDimitry Andric   ImportedFunctions.reserve(Imports.size());
700344a3780SDimitry Andric   ImportedTags.reserve(Imports.size());
701b60736ecSDimitry Andric   ImportedTables.reserve(Imports.size());
702eb11fae6SDimitry Andric   for (auto &I : Imports) {
703eb11fae6SDimitry Andric     if (I.Kind == wasm::WASM_EXTERNAL_FUNCTION)
704eb11fae6SDimitry Andric       ImportedFunctions.emplace_back(&I);
705eb11fae6SDimitry Andric     else if (I.Kind == wasm::WASM_EXTERNAL_GLOBAL)
706eb11fae6SDimitry Andric       ImportedGlobals.emplace_back(&I);
707344a3780SDimitry Andric     else if (I.Kind == wasm::WASM_EXTERNAL_TAG)
708344a3780SDimitry Andric       ImportedTags.emplace_back(&I);
709b60736ecSDimitry Andric     else if (I.Kind == wasm::WASM_EXTERNAL_TABLE)
710b60736ecSDimitry Andric       ImportedTables.emplace_back(&I);
71171d5a254SDimitry Andric   }
71271d5a254SDimitry Andric 
713eb11fae6SDimitry Andric   while (Count--) {
714eb11fae6SDimitry Andric     wasm::WasmSymbolInfo Info;
715d8e91e46SDimitry Andric     const wasm::WasmSignature *Signature = nullptr;
716eb11fae6SDimitry Andric     const wasm::WasmGlobalType *GlobalType = nullptr;
717b60736ecSDimitry Andric     const wasm::WasmTableType *TableType = nullptr;
71871d5a254SDimitry Andric 
719eb11fae6SDimitry Andric     Info.Kind = readUint8(Ctx);
720eb11fae6SDimitry Andric     Info.Flags = readVaruint32(Ctx);
721eb11fae6SDimitry Andric     bool IsDefined = (Info.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0;
722eb11fae6SDimitry Andric 
723eb11fae6SDimitry Andric     switch (Info.Kind) {
724eb11fae6SDimitry Andric     case wasm::WASM_SYMBOL_TYPE_FUNCTION:
725eb11fae6SDimitry Andric       Info.ElementIndex = readVaruint32(Ctx);
726eb11fae6SDimitry Andric       if (!isValidFunctionIndex(Info.ElementIndex) ||
727eb11fae6SDimitry Andric           IsDefined != isDefinedFunctionIndex(Info.ElementIndex))
728eb11fae6SDimitry Andric         return make_error<GenericBinaryError>("invalid function symbol index",
72971d5a254SDimitry Andric                                               object_error::parse_failed);
730eb11fae6SDimitry Andric       if (IsDefined) {
731eb11fae6SDimitry Andric         Info.Name = readString(Ctx);
732eb11fae6SDimitry Andric         unsigned FuncIndex = Info.ElementIndex - NumImportedFunctions;
733eb11fae6SDimitry Andric         wasm::WasmFunction &Function = Functions[FuncIndex];
734c0981da4SDimitry Andric         Signature = &Signatures[Function.SigIndex];
735eb11fae6SDimitry Andric         if (Function.SymbolName.empty())
736eb11fae6SDimitry Andric           Function.SymbolName = Info.Name;
737eb11fae6SDimitry Andric       } else {
738eb11fae6SDimitry Andric         wasm::WasmImport &Import = *ImportedFunctions[Info.ElementIndex];
739cfca06d7SDimitry Andric         if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0) {
740e6d15924SDimitry Andric           Info.Name = readString(Ctx);
741e6d15924SDimitry Andric           Info.ImportName = Import.Field;
742cfca06d7SDimitry Andric         } else {
743cfca06d7SDimitry Andric           Info.Name = Import.Field;
744cfca06d7SDimitry Andric         }
745cfca06d7SDimitry Andric         Signature = &Signatures[Import.SigIndex];
746e6d15924SDimitry Andric         Info.ImportModule = Import.Module;
747eb11fae6SDimitry Andric       }
748eb11fae6SDimitry Andric       break;
749eb11fae6SDimitry Andric 
750eb11fae6SDimitry Andric     case wasm::WASM_SYMBOL_TYPE_GLOBAL:
751eb11fae6SDimitry Andric       Info.ElementIndex = readVaruint32(Ctx);
752eb11fae6SDimitry Andric       if (!isValidGlobalIndex(Info.ElementIndex) ||
753eb11fae6SDimitry Andric           IsDefined != isDefinedGlobalIndex(Info.ElementIndex))
754eb11fae6SDimitry Andric         return make_error<GenericBinaryError>("invalid global symbol index",
755eb11fae6SDimitry Andric                                               object_error::parse_failed);
756d8e91e46SDimitry Andric       if (!IsDefined && (Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) ==
757eb11fae6SDimitry Andric                             wasm::WASM_SYMBOL_BINDING_WEAK)
758eb11fae6SDimitry Andric         return make_error<GenericBinaryError>("undefined weak global symbol",
759eb11fae6SDimitry Andric                                               object_error::parse_failed);
760eb11fae6SDimitry Andric       if (IsDefined) {
761eb11fae6SDimitry Andric         Info.Name = readString(Ctx);
762eb11fae6SDimitry Andric         unsigned GlobalIndex = Info.ElementIndex - NumImportedGlobals;
763eb11fae6SDimitry Andric         wasm::WasmGlobal &Global = Globals[GlobalIndex];
764eb11fae6SDimitry Andric         GlobalType = &Global.Type;
765eb11fae6SDimitry Andric         if (Global.SymbolName.empty())
766eb11fae6SDimitry Andric           Global.SymbolName = Info.Name;
767eb11fae6SDimitry Andric       } else {
768eb11fae6SDimitry Andric         wasm::WasmImport &Import = *ImportedGlobals[Info.ElementIndex];
769cfca06d7SDimitry Andric         if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0) {
770e6d15924SDimitry Andric           Info.Name = readString(Ctx);
771cfca06d7SDimitry Andric           Info.ImportName = Import.Field;
772cfca06d7SDimitry Andric         } else {
773eb11fae6SDimitry Andric           Info.Name = Import.Field;
774cfca06d7SDimitry Andric         }
775eb11fae6SDimitry Andric         GlobalType = &Import.Global;
776b60736ecSDimitry Andric         Info.ImportModule = Import.Module;
777b60736ecSDimitry Andric       }
778b60736ecSDimitry Andric       break;
779b60736ecSDimitry Andric 
780b60736ecSDimitry Andric     case wasm::WASM_SYMBOL_TYPE_TABLE:
781b60736ecSDimitry Andric       Info.ElementIndex = readVaruint32(Ctx);
782344a3780SDimitry Andric       if (!isValidTableNumber(Info.ElementIndex) ||
783344a3780SDimitry Andric           IsDefined != isDefinedTableNumber(Info.ElementIndex))
784b60736ecSDimitry Andric         return make_error<GenericBinaryError>("invalid table symbol index",
785b60736ecSDimitry Andric                                               object_error::parse_failed);
786b60736ecSDimitry Andric       if (!IsDefined && (Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) ==
787b60736ecSDimitry Andric                             wasm::WASM_SYMBOL_BINDING_WEAK)
788b60736ecSDimitry Andric         return make_error<GenericBinaryError>("undefined weak table symbol",
789b60736ecSDimitry Andric                                               object_error::parse_failed);
790b60736ecSDimitry Andric       if (IsDefined) {
791b60736ecSDimitry Andric         Info.Name = readString(Ctx);
792344a3780SDimitry Andric         unsigned TableNumber = Info.ElementIndex - NumImportedTables;
793344a3780SDimitry Andric         wasm::WasmTable &Table = Tables[TableNumber];
794b60736ecSDimitry Andric         TableType = &Table.Type;
795b60736ecSDimitry Andric         if (Table.SymbolName.empty())
796b60736ecSDimitry Andric           Table.SymbolName = Info.Name;
797b60736ecSDimitry Andric       } else {
798b60736ecSDimitry Andric         wasm::WasmImport &Import = *ImportedTables[Info.ElementIndex];
799b60736ecSDimitry Andric         if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0) {
800b60736ecSDimitry Andric           Info.Name = readString(Ctx);
801e6d15924SDimitry Andric           Info.ImportName = Import.Field;
802b60736ecSDimitry Andric         } else {
803b60736ecSDimitry Andric           Info.Name = Import.Field;
804b60736ecSDimitry Andric         }
805b60736ecSDimitry Andric         TableType = &Import.Table;
806e6d15924SDimitry Andric         Info.ImportModule = Import.Module;
807eb11fae6SDimitry Andric       }
808eb11fae6SDimitry Andric       break;
809eb11fae6SDimitry Andric 
810eb11fae6SDimitry Andric     case wasm::WASM_SYMBOL_TYPE_DATA:
811eb11fae6SDimitry Andric       Info.Name = readString(Ctx);
812eb11fae6SDimitry Andric       if (IsDefined) {
813cfca06d7SDimitry Andric         auto Index = readVaruint32(Ctx);
814cfca06d7SDimitry Andric         auto Offset = readVaruint64(Ctx);
815cfca06d7SDimitry Andric         auto Size = readVaruint64(Ctx);
816b1c73532SDimitry Andric         if (!(Info.Flags & wasm::WASM_SYMBOL_ABSOLUTE)) {
817b1c73532SDimitry Andric           if (static_cast<size_t>(Index) >= DataSegments.size())
818b1c73532SDimitry Andric             return make_error<GenericBinaryError>(
819b1c73532SDimitry Andric                 "invalid data segment index: " + Twine(Index),
820b1c73532SDimitry Andric                 object_error::parse_failed);
821344a3780SDimitry Andric           size_t SegmentSize = DataSegments[Index].Data.Content.size();
822344a3780SDimitry Andric           if (Offset > SegmentSize)
823344a3780SDimitry Andric             return make_error<GenericBinaryError>(
824b1c73532SDimitry Andric                 "invalid data symbol offset: `" + Info.Name +
825b1c73532SDimitry Andric                     "` (offset: " + Twine(Offset) +
826b1c73532SDimitry Andric                     " segment size: " + Twine(SegmentSize) + ")",
827eb11fae6SDimitry Andric                 object_error::parse_failed);
828b1c73532SDimitry Andric         }
829eb11fae6SDimitry Andric         Info.DataRef = wasm::WasmDataReference{Index, Offset, Size};
830eb11fae6SDimitry Andric       }
831eb11fae6SDimitry Andric       break;
832eb11fae6SDimitry Andric 
833eb11fae6SDimitry Andric     case wasm::WASM_SYMBOL_TYPE_SECTION: {
834eb11fae6SDimitry Andric       if ((Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) !=
835eb11fae6SDimitry Andric           wasm::WASM_SYMBOL_BINDING_LOCAL)
836eb11fae6SDimitry Andric         return make_error<GenericBinaryError>(
837b60736ecSDimitry Andric             "section symbols must have local binding",
838eb11fae6SDimitry Andric             object_error::parse_failed);
839eb11fae6SDimitry Andric       Info.ElementIndex = readVaruint32(Ctx);
840eb11fae6SDimitry Andric       // Use somewhat unique section name as symbol name.
841eb11fae6SDimitry Andric       StringRef SectionName = Sections[Info.ElementIndex].Name;
842eb11fae6SDimitry Andric       Info.Name = SectionName;
843eb11fae6SDimitry Andric       break;
844eb11fae6SDimitry Andric     }
845eb11fae6SDimitry Andric 
846344a3780SDimitry Andric     case wasm::WASM_SYMBOL_TYPE_TAG: {
847d8e91e46SDimitry Andric       Info.ElementIndex = readVaruint32(Ctx);
848344a3780SDimitry Andric       if (!isValidTagIndex(Info.ElementIndex) ||
849344a3780SDimitry Andric           IsDefined != isDefinedTagIndex(Info.ElementIndex))
850344a3780SDimitry Andric         return make_error<GenericBinaryError>("invalid tag symbol index",
851d8e91e46SDimitry Andric                                               object_error::parse_failed);
852d8e91e46SDimitry Andric       if (!IsDefined && (Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) ==
853d8e91e46SDimitry Andric                             wasm::WASM_SYMBOL_BINDING_WEAK)
854d8e91e46SDimitry Andric         return make_error<GenericBinaryError>("undefined weak global symbol",
855d8e91e46SDimitry Andric                                               object_error::parse_failed);
856d8e91e46SDimitry Andric       if (IsDefined) {
857d8e91e46SDimitry Andric         Info.Name = readString(Ctx);
858344a3780SDimitry Andric         unsigned TagIndex = Info.ElementIndex - NumImportedTags;
859344a3780SDimitry Andric         wasm::WasmTag &Tag = Tags[TagIndex];
860c0981da4SDimitry Andric         Signature = &Signatures[Tag.SigIndex];
861344a3780SDimitry Andric         if (Tag.SymbolName.empty())
862344a3780SDimitry Andric           Tag.SymbolName = Info.Name;
863d8e91e46SDimitry Andric 
864d8e91e46SDimitry Andric       } else {
865344a3780SDimitry Andric         wasm::WasmImport &Import = *ImportedTags[Info.ElementIndex];
866cfca06d7SDimitry Andric         if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0) {
867e6d15924SDimitry Andric           Info.Name = readString(Ctx);
868cfca06d7SDimitry Andric           Info.ImportName = Import.Field;
869cfca06d7SDimitry Andric         } else {
870e6d15924SDimitry Andric           Info.Name = Import.Field;
871cfca06d7SDimitry Andric         }
872c0981da4SDimitry Andric         Signature = &Signatures[Import.SigIndex];
873e6d15924SDimitry Andric         Info.ImportModule = Import.Module;
874d8e91e46SDimitry Andric       }
875d8e91e46SDimitry Andric       break;
876d8e91e46SDimitry Andric     }
877d8e91e46SDimitry Andric 
878eb11fae6SDimitry Andric     default:
879b60736ecSDimitry Andric       return make_error<GenericBinaryError>("invalid symbol type: " +
880b60736ecSDimitry Andric                                                 Twine(unsigned(Info.Kind)),
881eb11fae6SDimitry Andric                                             object_error::parse_failed);
882eb11fae6SDimitry Andric     }
883eb11fae6SDimitry Andric 
884eb11fae6SDimitry Andric     if ((Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) !=
885eb11fae6SDimitry Andric             wasm::WASM_SYMBOL_BINDING_LOCAL &&
886eb11fae6SDimitry Andric         !SymbolNames.insert(Info.Name).second)
887b60736ecSDimitry Andric       return make_error<GenericBinaryError>("duplicate symbol name " +
888eb11fae6SDimitry Andric                                                 Twine(Info.Name),
889eb11fae6SDimitry Andric                                             object_error::parse_failed);
890ac9a064cSDimitry Andric     Symbols.emplace_back(Info, GlobalType, TableType, Signature);
891eb11fae6SDimitry Andric     LLVM_DEBUG(dbgs() << "Adding symbol: " << Symbols.back() << "\n");
892eb11fae6SDimitry Andric   }
893eb11fae6SDimitry Andric 
894eb11fae6SDimitry Andric   return Error::success();
895eb11fae6SDimitry Andric }
896eb11fae6SDimitry Andric 
parseLinkingSectionComdat(ReadContext & Ctx)897eb11fae6SDimitry Andric Error WasmObjectFile::parseLinkingSectionComdat(ReadContext &Ctx) {
898eb11fae6SDimitry Andric   uint32_t ComdatCount = readVaruint32(Ctx);
899eb11fae6SDimitry Andric   StringSet<> ComdatSet;
900eb11fae6SDimitry Andric   for (unsigned ComdatIndex = 0; ComdatIndex < ComdatCount; ++ComdatIndex) {
901eb11fae6SDimitry Andric     StringRef Name = readString(Ctx);
902eb11fae6SDimitry Andric     if (Name.empty() || !ComdatSet.insert(Name).second)
903b60736ecSDimitry Andric       return make_error<GenericBinaryError>("bad/duplicate COMDAT name " +
904d8e91e46SDimitry Andric                                                 Twine(Name),
905eb11fae6SDimitry Andric                                             object_error::parse_failed);
906eb11fae6SDimitry Andric     LinkingData.Comdats.emplace_back(Name);
907eb11fae6SDimitry Andric     uint32_t Flags = readVaruint32(Ctx);
908eb11fae6SDimitry Andric     if (Flags != 0)
909b60736ecSDimitry Andric       return make_error<GenericBinaryError>("unsupported COMDAT flags",
910eb11fae6SDimitry Andric                                             object_error::parse_failed);
911eb11fae6SDimitry Andric 
912eb11fae6SDimitry Andric     uint32_t EntryCount = readVaruint32(Ctx);
913eb11fae6SDimitry Andric     while (EntryCount--) {
914eb11fae6SDimitry Andric       unsigned Kind = readVaruint32(Ctx);
915eb11fae6SDimitry Andric       unsigned Index = readVaruint32(Ctx);
916eb11fae6SDimitry Andric       switch (Kind) {
917eb11fae6SDimitry Andric       default:
918b60736ecSDimitry Andric         return make_error<GenericBinaryError>("invalid COMDAT entry type",
919eb11fae6SDimitry Andric                                               object_error::parse_failed);
920eb11fae6SDimitry Andric       case wasm::WASM_COMDAT_DATA:
921eb11fae6SDimitry Andric         if (Index >= DataSegments.size())
922d8e91e46SDimitry Andric           return make_error<GenericBinaryError>(
923d8e91e46SDimitry Andric               "COMDAT data index out of range", object_error::parse_failed);
924eb11fae6SDimitry Andric         if (DataSegments[Index].Data.Comdat != UINT32_MAX)
925b60736ecSDimitry Andric           return make_error<GenericBinaryError>("data segment in two COMDATs",
926eb11fae6SDimitry Andric                                                 object_error::parse_failed);
927eb11fae6SDimitry Andric         DataSegments[Index].Data.Comdat = ComdatIndex;
928eb11fae6SDimitry Andric         break;
929eb11fae6SDimitry Andric       case wasm::WASM_COMDAT_FUNCTION:
930eb11fae6SDimitry Andric         if (!isDefinedFunctionIndex(Index))
931d8e91e46SDimitry Andric           return make_error<GenericBinaryError>(
932d8e91e46SDimitry Andric               "COMDAT function index out of range", object_error::parse_failed);
933eb11fae6SDimitry Andric         if (getDefinedFunction(Index).Comdat != UINT32_MAX)
934b60736ecSDimitry Andric           return make_error<GenericBinaryError>("function in two COMDATs",
935eb11fae6SDimitry Andric                                                 object_error::parse_failed);
936eb11fae6SDimitry Andric         getDefinedFunction(Index).Comdat = ComdatIndex;
937eb11fae6SDimitry Andric         break;
938b60736ecSDimitry Andric       case wasm::WASM_COMDAT_SECTION:
939b60736ecSDimitry Andric         if (Index >= Sections.size())
940b60736ecSDimitry Andric           return make_error<GenericBinaryError>(
941b60736ecSDimitry Andric               "COMDAT section index out of range", object_error::parse_failed);
942b60736ecSDimitry Andric         if (Sections[Index].Type != wasm::WASM_SEC_CUSTOM)
943b60736ecSDimitry Andric           return make_error<GenericBinaryError>(
944b60736ecSDimitry Andric               "non-custom section in a COMDAT", object_error::parse_failed);
945b60736ecSDimitry Andric         Sections[Index].Comdat = ComdatIndex;
946b60736ecSDimitry Andric         break;
947eb11fae6SDimitry Andric       }
948eb11fae6SDimitry Andric     }
949eb11fae6SDimitry Andric   }
950eb11fae6SDimitry Andric   return Error::success();
951eb11fae6SDimitry Andric }
952eb11fae6SDimitry Andric 
parseProducersSection(ReadContext & Ctx)953e6d15924SDimitry Andric Error WasmObjectFile::parseProducersSection(ReadContext &Ctx) {
954e6d15924SDimitry Andric   llvm::SmallSet<StringRef, 3> FieldsSeen;
955e6d15924SDimitry Andric   uint32_t Fields = readVaruint32(Ctx);
956e6d15924SDimitry Andric   for (size_t I = 0; I < Fields; ++I) {
957e6d15924SDimitry Andric     StringRef FieldName = readString(Ctx);
958e6d15924SDimitry Andric     if (!FieldsSeen.insert(FieldName).second)
959e6d15924SDimitry Andric       return make_error<GenericBinaryError>(
960b60736ecSDimitry Andric           "producers section does not have unique fields",
961e6d15924SDimitry Andric           object_error::parse_failed);
962e6d15924SDimitry Andric     std::vector<std::pair<std::string, std::string>> *ProducerVec = nullptr;
963e6d15924SDimitry Andric     if (FieldName == "language") {
964e6d15924SDimitry Andric       ProducerVec = &ProducerInfo.Languages;
965e6d15924SDimitry Andric     } else if (FieldName == "processed-by") {
966e6d15924SDimitry Andric       ProducerVec = &ProducerInfo.Tools;
967e6d15924SDimitry Andric     } else if (FieldName == "sdk") {
968e6d15924SDimitry Andric       ProducerVec = &ProducerInfo.SDKs;
969e6d15924SDimitry Andric     } else {
970e6d15924SDimitry Andric       return make_error<GenericBinaryError>(
971b60736ecSDimitry Andric           "producers section field is not named one of language, processed-by, "
972e6d15924SDimitry Andric           "or sdk",
973e6d15924SDimitry Andric           object_error::parse_failed);
974e6d15924SDimitry Andric     }
975e6d15924SDimitry Andric     uint32_t ValueCount = readVaruint32(Ctx);
976e6d15924SDimitry Andric     llvm::SmallSet<StringRef, 8> ProducersSeen;
977e6d15924SDimitry Andric     for (size_t J = 0; J < ValueCount; ++J) {
978e6d15924SDimitry Andric       StringRef Name = readString(Ctx);
979e6d15924SDimitry Andric       StringRef Version = readString(Ctx);
980e6d15924SDimitry Andric       if (!ProducersSeen.insert(Name).second) {
981e6d15924SDimitry Andric         return make_error<GenericBinaryError>(
982b60736ecSDimitry Andric             "producers section contains repeated producer",
983e6d15924SDimitry Andric             object_error::parse_failed);
984e6d15924SDimitry Andric       }
985cfca06d7SDimitry Andric       ProducerVec->emplace_back(std::string(Name), std::string(Version));
986e6d15924SDimitry Andric     }
987e6d15924SDimitry Andric   }
988e6d15924SDimitry Andric   if (Ctx.Ptr != Ctx.End)
989b60736ecSDimitry Andric     return make_error<GenericBinaryError>("producers section ended prematurely",
990e6d15924SDimitry Andric                                           object_error::parse_failed);
991e6d15924SDimitry Andric   return Error::success();
992e6d15924SDimitry Andric }
993e6d15924SDimitry Andric 
parseTargetFeaturesSection(ReadContext & Ctx)994e6d15924SDimitry Andric Error WasmObjectFile::parseTargetFeaturesSection(ReadContext &Ctx) {
995e6d15924SDimitry Andric   llvm::SmallSet<std::string, 8> FeaturesSeen;
996e6d15924SDimitry Andric   uint32_t FeatureCount = readVaruint32(Ctx);
997e6d15924SDimitry Andric   for (size_t I = 0; I < FeatureCount; ++I) {
998e6d15924SDimitry Andric     wasm::WasmFeatureEntry Feature;
999e6d15924SDimitry Andric     Feature.Prefix = readUint8(Ctx);
1000e6d15924SDimitry Andric     switch (Feature.Prefix) {
1001e6d15924SDimitry Andric     case wasm::WASM_FEATURE_PREFIX_USED:
1002e6d15924SDimitry Andric     case wasm::WASM_FEATURE_PREFIX_REQUIRED:
1003e6d15924SDimitry Andric     case wasm::WASM_FEATURE_PREFIX_DISALLOWED:
1004e6d15924SDimitry Andric       break;
1005e6d15924SDimitry Andric     default:
1006b60736ecSDimitry Andric       return make_error<GenericBinaryError>("unknown feature policy prefix",
1007e6d15924SDimitry Andric                                             object_error::parse_failed);
1008e6d15924SDimitry Andric     }
1009cfca06d7SDimitry Andric     Feature.Name = std::string(readString(Ctx));
1010e6d15924SDimitry Andric     if (!FeaturesSeen.insert(Feature.Name).second)
1011e6d15924SDimitry Andric       return make_error<GenericBinaryError>(
1012b60736ecSDimitry Andric           "target features section contains repeated feature \"" +
1013e6d15924SDimitry Andric               Feature.Name + "\"",
1014e6d15924SDimitry Andric           object_error::parse_failed);
1015e6d15924SDimitry Andric     TargetFeatures.push_back(Feature);
1016e6d15924SDimitry Andric   }
1017e6d15924SDimitry Andric   if (Ctx.Ptr != Ctx.End)
1018e6d15924SDimitry Andric     return make_error<GenericBinaryError>(
1019b60736ecSDimitry Andric         "target features section ended prematurely",
1020e6d15924SDimitry Andric         object_error::parse_failed);
1021e6d15924SDimitry Andric   return Error::success();
1022e6d15924SDimitry Andric }
1023e6d15924SDimitry Andric 
parseRelocSection(StringRef Name,ReadContext & Ctx)1024eb11fae6SDimitry Andric Error WasmObjectFile::parseRelocSection(StringRef Name, ReadContext &Ctx) {
1025eb11fae6SDimitry Andric   uint32_t SectionIndex = readVaruint32(Ctx);
1026eb11fae6SDimitry Andric   if (SectionIndex >= Sections.size())
1027b60736ecSDimitry Andric     return make_error<GenericBinaryError>("invalid section index",
1028eb11fae6SDimitry Andric                                           object_error::parse_failed);
1029eb11fae6SDimitry Andric   WasmSection &Section = Sections[SectionIndex];
1030eb11fae6SDimitry Andric   uint32_t RelocCount = readVaruint32(Ctx);
1031eb11fae6SDimitry Andric   uint32_t EndOffset = Section.Content.size();
1032d8e91e46SDimitry Andric   uint32_t PreviousOffset = 0;
103371d5a254SDimitry Andric   while (RelocCount--) {
1034eb11fae6SDimitry Andric     wasm::WasmRelocation Reloc = {};
1035b60736ecSDimitry Andric     uint32_t type = readVaruint32(Ctx);
1036b60736ecSDimitry Andric     Reloc.Type = type;
1037eb11fae6SDimitry Andric     Reloc.Offset = readVaruint32(Ctx);
1038d8e91e46SDimitry Andric     if (Reloc.Offset < PreviousOffset)
1039b60736ecSDimitry Andric       return make_error<GenericBinaryError>("relocations not in offset order",
1040d8e91e46SDimitry Andric                                             object_error::parse_failed);
1041ac9a064cSDimitry Andric 
1042ac9a064cSDimitry Andric     auto badReloc = [&](StringRef msg) {
1043ac9a064cSDimitry Andric       return make_error<GenericBinaryError>(
1044ac9a064cSDimitry Andric           msg + ": " + Twine(Symbols[Reloc.Index].Info.Name),
1045ac9a064cSDimitry Andric           object_error::parse_failed);
1046ac9a064cSDimitry Andric     };
1047ac9a064cSDimitry Andric 
1048d8e91e46SDimitry Andric     PreviousOffset = Reloc.Offset;
1049eb11fae6SDimitry Andric     Reloc.Index = readVaruint32(Ctx);
1050b60736ecSDimitry Andric     switch (type) {
1051e6d15924SDimitry Andric     case wasm::R_WASM_FUNCTION_INDEX_LEB:
10527fa27ce4SDimitry Andric     case wasm::R_WASM_FUNCTION_INDEX_I32:
1053e6d15924SDimitry Andric     case wasm::R_WASM_TABLE_INDEX_SLEB:
1054b60736ecSDimitry Andric     case wasm::R_WASM_TABLE_INDEX_SLEB64:
1055e6d15924SDimitry Andric     case wasm::R_WASM_TABLE_INDEX_I32:
1056b60736ecSDimitry Andric     case wasm::R_WASM_TABLE_INDEX_I64:
1057e6d15924SDimitry Andric     case wasm::R_WASM_TABLE_INDEX_REL_SLEB:
1058344a3780SDimitry Andric     case wasm::R_WASM_TABLE_INDEX_REL_SLEB64:
1059eb11fae6SDimitry Andric       if (!isValidFunctionSymbol(Reloc.Index))
1060ac9a064cSDimitry Andric         return badReloc("invalid function relocation");
1061b60736ecSDimitry Andric       break;
1062b60736ecSDimitry Andric     case wasm::R_WASM_TABLE_NUMBER_LEB:
1063b60736ecSDimitry Andric       if (!isValidTableSymbol(Reloc.Index))
1064ac9a064cSDimitry Andric         return badReloc("invalid table relocation");
1065eb11fae6SDimitry Andric       break;
1066e6d15924SDimitry Andric     case wasm::R_WASM_TYPE_INDEX_LEB:
1067eb11fae6SDimitry Andric       if (Reloc.Index >= Signatures.size())
1068ac9a064cSDimitry Andric         return badReloc("invalid relocation type index");
1069eb11fae6SDimitry Andric       break;
1070e6d15924SDimitry Andric     case wasm::R_WASM_GLOBAL_INDEX_LEB:
1071e6d15924SDimitry Andric       // R_WASM_GLOBAL_INDEX_LEB are can be used against function and data
10721d5ae102SDimitry Andric       // symbols to refer to their GOT entries.
1073e6d15924SDimitry Andric       if (!isValidGlobalSymbol(Reloc.Index) &&
1074e6d15924SDimitry Andric           !isValidDataSymbol(Reloc.Index) &&
1075e6d15924SDimitry Andric           !isValidFunctionSymbol(Reloc.Index))
1076ac9a064cSDimitry Andric         return badReloc("invalid global relocation");
107771d5a254SDimitry Andric       break;
1078cfca06d7SDimitry Andric     case wasm::R_WASM_GLOBAL_INDEX_I32:
1079cfca06d7SDimitry Andric       if (!isValidGlobalSymbol(Reloc.Index))
1080ac9a064cSDimitry Andric         return badReloc("invalid global relocation");
1081cfca06d7SDimitry Andric       break;
1082344a3780SDimitry Andric     case wasm::R_WASM_TAG_INDEX_LEB:
1083344a3780SDimitry Andric       if (!isValidTagSymbol(Reloc.Index))
1084ac9a064cSDimitry Andric         return badReloc("invalid tag relocation");
1085d8e91e46SDimitry Andric       break;
1086e6d15924SDimitry Andric     case wasm::R_WASM_MEMORY_ADDR_LEB:
1087e6d15924SDimitry Andric     case wasm::R_WASM_MEMORY_ADDR_SLEB:
1088e6d15924SDimitry Andric     case wasm::R_WASM_MEMORY_ADDR_I32:
1089e6d15924SDimitry Andric     case wasm::R_WASM_MEMORY_ADDR_REL_SLEB:
1090b60736ecSDimitry Andric     case wasm::R_WASM_MEMORY_ADDR_TLS_SLEB:
1091344a3780SDimitry Andric     case wasm::R_WASM_MEMORY_ADDR_LOCREL_I32:
1092eb11fae6SDimitry Andric       if (!isValidDataSymbol(Reloc.Index))
1093ac9a064cSDimitry Andric         return badReloc("invalid data relocation");
1094eb11fae6SDimitry Andric       Reloc.Addend = readVarint32(Ctx);
1095eb11fae6SDimitry Andric       break;
1096cfca06d7SDimitry Andric     case wasm::R_WASM_MEMORY_ADDR_LEB64:
1097cfca06d7SDimitry Andric     case wasm::R_WASM_MEMORY_ADDR_SLEB64:
1098cfca06d7SDimitry Andric     case wasm::R_WASM_MEMORY_ADDR_I64:
1099cfca06d7SDimitry Andric     case wasm::R_WASM_MEMORY_ADDR_REL_SLEB64:
1100344a3780SDimitry Andric     case wasm::R_WASM_MEMORY_ADDR_TLS_SLEB64:
1101cfca06d7SDimitry Andric       if (!isValidDataSymbol(Reloc.Index))
1102ac9a064cSDimitry Andric         return badReloc("invalid data relocation");
1103cfca06d7SDimitry Andric       Reloc.Addend = readVarint64(Ctx);
1104cfca06d7SDimitry Andric       break;
1105e6d15924SDimitry Andric     case wasm::R_WASM_FUNCTION_OFFSET_I32:
1106eb11fae6SDimitry Andric       if (!isValidFunctionSymbol(Reloc.Index))
1107ac9a064cSDimitry Andric         return badReloc("invalid function relocation");
1108eb11fae6SDimitry Andric       Reloc.Addend = readVarint32(Ctx);
1109eb11fae6SDimitry Andric       break;
1110b60736ecSDimitry Andric     case wasm::R_WASM_FUNCTION_OFFSET_I64:
1111b60736ecSDimitry Andric       if (!isValidFunctionSymbol(Reloc.Index))
1112ac9a064cSDimitry Andric         return badReloc("invalid function relocation");
1113b60736ecSDimitry Andric       Reloc.Addend = readVarint64(Ctx);
1114b60736ecSDimitry Andric       break;
1115e6d15924SDimitry Andric     case wasm::R_WASM_SECTION_OFFSET_I32:
1116eb11fae6SDimitry Andric       if (!isValidSectionSymbol(Reloc.Index))
1117ac9a064cSDimitry Andric         return badReloc("invalid section relocation");
1118eb11fae6SDimitry Andric       Reloc.Addend = readVarint32(Ctx);
111971d5a254SDimitry Andric       break;
112071d5a254SDimitry Andric     default:
1121b60736ecSDimitry Andric       return make_error<GenericBinaryError>("invalid relocation type: " +
1122b60736ecSDimitry Andric                                                 Twine(type),
112371d5a254SDimitry Andric                                             object_error::parse_failed);
112471d5a254SDimitry Andric     }
1125eb11fae6SDimitry Andric 
1126eb11fae6SDimitry Andric     // Relocations must fit inside the section, and must appear in order.  They
1127eb11fae6SDimitry Andric     // also shouldn't overlap a function/element boundary, but we don't bother
1128eb11fae6SDimitry Andric     // to check that.
1129eb11fae6SDimitry Andric     uint64_t Size = 5;
1130cfca06d7SDimitry Andric     if (Reloc.Type == wasm::R_WASM_MEMORY_ADDR_LEB64 ||
1131cfca06d7SDimitry Andric         Reloc.Type == wasm::R_WASM_MEMORY_ADDR_SLEB64 ||
1132cfca06d7SDimitry Andric         Reloc.Type == wasm::R_WASM_MEMORY_ADDR_REL_SLEB64)
1133cfca06d7SDimitry Andric       Size = 10;
1134e6d15924SDimitry Andric     if (Reloc.Type == wasm::R_WASM_TABLE_INDEX_I32 ||
1135e6d15924SDimitry Andric         Reloc.Type == wasm::R_WASM_MEMORY_ADDR_I32 ||
1136344a3780SDimitry Andric         Reloc.Type == wasm::R_WASM_MEMORY_ADDR_LOCREL_I32 ||
1137e6d15924SDimitry Andric         Reloc.Type == wasm::R_WASM_SECTION_OFFSET_I32 ||
1138cfca06d7SDimitry Andric         Reloc.Type == wasm::R_WASM_FUNCTION_OFFSET_I32 ||
11397fa27ce4SDimitry Andric         Reloc.Type == wasm::R_WASM_FUNCTION_INDEX_I32 ||
1140cfca06d7SDimitry Andric         Reloc.Type == wasm::R_WASM_GLOBAL_INDEX_I32)
1141eb11fae6SDimitry Andric       Size = 4;
1142b60736ecSDimitry Andric     if (Reloc.Type == wasm::R_WASM_TABLE_INDEX_I64 ||
1143b60736ecSDimitry Andric         Reloc.Type == wasm::R_WASM_MEMORY_ADDR_I64 ||
1144b60736ecSDimitry Andric         Reloc.Type == wasm::R_WASM_FUNCTION_OFFSET_I64)
1145cfca06d7SDimitry Andric       Size = 8;
1146eb11fae6SDimitry Andric     if (Reloc.Offset + Size > EndOffset)
1147b60736ecSDimitry Andric       return make_error<GenericBinaryError>("invalid relocation offset",
1148eb11fae6SDimitry Andric                                             object_error::parse_failed);
1149eb11fae6SDimitry Andric 
1150eb11fae6SDimitry Andric     Section.Relocations.push_back(Reloc);
115171d5a254SDimitry Andric   }
1152eb11fae6SDimitry Andric   if (Ctx.Ptr != Ctx.End)
1153b60736ecSDimitry Andric     return make_error<GenericBinaryError>("reloc section ended prematurely",
115471d5a254SDimitry Andric                                           object_error::parse_failed);
115571d5a254SDimitry Andric   return Error::success();
115671d5a254SDimitry Andric }
115771d5a254SDimitry Andric 
parseCustomSection(WasmSection & Sec,ReadContext & Ctx)1158eb11fae6SDimitry Andric Error WasmObjectFile::parseCustomSection(WasmSection &Sec, ReadContext &Ctx) {
1159d8e91e46SDimitry Andric   if (Sec.Name == "dylink") {
1160d8e91e46SDimitry Andric     if (Error Err = parseDylinkSection(Ctx))
1161d8e91e46SDimitry Andric       return Err;
1162c0981da4SDimitry Andric   } else if (Sec.Name == "dylink.0") {
1163c0981da4SDimitry Andric     if (Error Err = parseDylink0Section(Ctx))
1164c0981da4SDimitry Andric       return Err;
1165d8e91e46SDimitry Andric   } else if (Sec.Name == "name") {
1166eb11fae6SDimitry Andric     if (Error Err = parseNameSection(Ctx))
116771d5a254SDimitry Andric       return Err;
116808bbd35aSDimitry Andric   } else if (Sec.Name == "linking") {
1169eb11fae6SDimitry Andric     if (Error Err = parseLinkingSection(Ctx))
117008bbd35aSDimitry Andric       return Err;
1171e6d15924SDimitry Andric   } else if (Sec.Name == "producers") {
1172e6d15924SDimitry Andric     if (Error Err = parseProducersSection(Ctx))
1173e6d15924SDimitry Andric       return Err;
1174e6d15924SDimitry Andric   } else if (Sec.Name == "target_features") {
1175e6d15924SDimitry Andric     if (Error Err = parseTargetFeaturesSection(Ctx))
1176e6d15924SDimitry Andric       return Err;
1177312c0ed1SDimitry Andric   } else if (Sec.Name.starts_with("reloc.")) {
1178eb11fae6SDimitry Andric     if (Error Err = parseRelocSection(Sec.Name, Ctx))
117971d5a254SDimitry Andric       return Err;
118071d5a254SDimitry Andric   }
118171d5a254SDimitry Andric   return Error::success();
118271d5a254SDimitry Andric }
118371d5a254SDimitry Andric 
parseTypeSection(ReadContext & Ctx)1184eb11fae6SDimitry Andric Error WasmObjectFile::parseTypeSection(ReadContext &Ctx) {
1185ac9a064cSDimitry Andric   auto parseFieldDef = [&]() {
1186ac9a064cSDimitry Andric     uint32_t TypeCode = readVaruint32((Ctx));
1187ac9a064cSDimitry Andric     /* Discard StorageType */ parseValType(Ctx, TypeCode);
1188ac9a064cSDimitry Andric     /* Discard Mutability */ readVaruint32(Ctx);
1189ac9a064cSDimitry Andric   };
1190ac9a064cSDimitry Andric 
1191eb11fae6SDimitry Andric   uint32_t Count = readVaruint32(Ctx);
119271d5a254SDimitry Andric   Signatures.reserve(Count);
119371d5a254SDimitry Andric   while (Count--) {
119471d5a254SDimitry Andric     wasm::WasmSignature Sig;
1195eb11fae6SDimitry Andric     uint8_t Form = readUint8(Ctx);
1196ac9a064cSDimitry Andric     if (Form == wasm::WASM_TYPE_REC) {
1197ac9a064cSDimitry Andric       // Rec groups expand the type index space (beyond what was declared at
1198ac9a064cSDimitry Andric       // the top of the section, and also consume one element in that space.
1199ac9a064cSDimitry Andric       uint32_t RecSize = readVaruint32(Ctx);
1200ac9a064cSDimitry Andric       if (RecSize == 0)
1201ac9a064cSDimitry Andric         return make_error<GenericBinaryError>("Rec group size cannot be 0",
1202ac9a064cSDimitry Andric                                               object_error::parse_failed);
1203ac9a064cSDimitry Andric       Signatures.reserve(Signatures.size() + RecSize);
1204ac9a064cSDimitry Andric       Count += RecSize;
1205ac9a064cSDimitry Andric       Sig.Kind = wasm::WasmSignature::Placeholder;
1206ac9a064cSDimitry Andric       Signatures.push_back(std::move(Sig));
1207ac9a064cSDimitry Andric       HasUnmodeledTypes = true;
1208ac9a064cSDimitry Andric       continue;
1209ac9a064cSDimitry Andric     }
121071d5a254SDimitry Andric     if (Form != wasm::WASM_TYPE_FUNC) {
1211ac9a064cSDimitry Andric       // Currently LLVM only models function types, and not other composite
1212ac9a064cSDimitry Andric       // types. Here we parse the type declarations just enough to skip past
1213ac9a064cSDimitry Andric       // them in the binary.
1214ac9a064cSDimitry Andric       if (Form == wasm::WASM_TYPE_SUB || Form == wasm::WASM_TYPE_SUB_FINAL) {
1215ac9a064cSDimitry Andric         uint32_t Supers = readVaruint32(Ctx);
1216ac9a064cSDimitry Andric         if (Supers > 0) {
1217ac9a064cSDimitry Andric           if (Supers != 1)
1218ac9a064cSDimitry Andric             return make_error<GenericBinaryError>(
1219ac9a064cSDimitry Andric                 "Invalid number of supertypes", object_error::parse_failed);
1220ac9a064cSDimitry Andric           /* Discard SuperIndex */ readVaruint32(Ctx);
1221ac9a064cSDimitry Andric         }
1222ac9a064cSDimitry Andric         Form = readVaruint32(Ctx);
1223ac9a064cSDimitry Andric       }
1224ac9a064cSDimitry Andric       if (Form == wasm::WASM_TYPE_STRUCT) {
1225ac9a064cSDimitry Andric         uint32_t FieldCount = readVaruint32(Ctx);
1226ac9a064cSDimitry Andric         while (FieldCount--) {
1227ac9a064cSDimitry Andric           parseFieldDef();
1228ac9a064cSDimitry Andric         }
1229ac9a064cSDimitry Andric       } else if (Form == wasm::WASM_TYPE_ARRAY) {
1230ac9a064cSDimitry Andric         parseFieldDef();
1231ac9a064cSDimitry Andric       } else {
1232ac9a064cSDimitry Andric         return make_error<GenericBinaryError>("bad form",
123371d5a254SDimitry Andric                                               object_error::parse_failed);
123471d5a254SDimitry Andric       }
1235ac9a064cSDimitry Andric       Sig.Kind = wasm::WasmSignature::Placeholder;
1236ac9a064cSDimitry Andric       Signatures.push_back(std::move(Sig));
1237ac9a064cSDimitry Andric       HasUnmodeledTypes = true;
1238ac9a064cSDimitry Andric       continue;
1239ac9a064cSDimitry Andric     }
1240ac9a064cSDimitry Andric 
1241eb11fae6SDimitry Andric     uint32_t ParamCount = readVaruint32(Ctx);
1242d8e91e46SDimitry Andric     Sig.Params.reserve(ParamCount);
124371d5a254SDimitry Andric     while (ParamCount--) {
1244eb11fae6SDimitry Andric       uint32_t ParamType = readUint8(Ctx);
1245ac9a064cSDimitry Andric       Sig.Params.push_back(parseValType(Ctx, ParamType));
1246ac9a064cSDimitry Andric       continue;
124771d5a254SDimitry Andric     }
1248eb11fae6SDimitry Andric     uint32_t ReturnCount = readVaruint32(Ctx);
12491d5ae102SDimitry Andric     while (ReturnCount--) {
12501d5ae102SDimitry Andric       uint32_t ReturnType = readUint8(Ctx);
1251ac9a064cSDimitry Andric       Sig.Returns.push_back(parseValType(Ctx, ReturnType));
125271d5a254SDimitry Andric     }
1253ac9a064cSDimitry Andric 
1254d8e91e46SDimitry Andric     Signatures.push_back(std::move(Sig));
125571d5a254SDimitry Andric   }
1256eb11fae6SDimitry Andric   if (Ctx.Ptr != Ctx.End)
1257b60736ecSDimitry Andric     return make_error<GenericBinaryError>("type section ended prematurely",
125871d5a254SDimitry Andric                                           object_error::parse_failed);
125971d5a254SDimitry Andric   return Error::success();
126071d5a254SDimitry Andric }
126171d5a254SDimitry Andric 
parseImportSection(ReadContext & Ctx)1262eb11fae6SDimitry Andric Error WasmObjectFile::parseImportSection(ReadContext &Ctx) {
1263eb11fae6SDimitry Andric   uint32_t Count = readVaruint32(Ctx);
1264c0981da4SDimitry Andric   uint32_t NumTypes = Signatures.size();
126571d5a254SDimitry Andric   Imports.reserve(Count);
1266e6d15924SDimitry Andric   for (uint32_t I = 0; I < Count; I++) {
126771d5a254SDimitry Andric     wasm::WasmImport Im;
1268eb11fae6SDimitry Andric     Im.Module = readString(Ctx);
1269eb11fae6SDimitry Andric     Im.Field = readString(Ctx);
1270eb11fae6SDimitry Andric     Im.Kind = readUint8(Ctx);
127171d5a254SDimitry Andric     switch (Im.Kind) {
127271d5a254SDimitry Andric     case wasm::WASM_EXTERNAL_FUNCTION:
1273044eb2f6SDimitry Andric       NumImportedFunctions++;
1274eb11fae6SDimitry Andric       Im.SigIndex = readVaruint32(Ctx);
1275c0981da4SDimitry Andric       if (Im.SigIndex >= NumTypes)
1276c0981da4SDimitry Andric         return make_error<GenericBinaryError>("invalid function type",
1277c0981da4SDimitry Andric                                               object_error::parse_failed);
127871d5a254SDimitry Andric       break;
127971d5a254SDimitry Andric     case wasm::WASM_EXTERNAL_GLOBAL:
1280044eb2f6SDimitry Andric       NumImportedGlobals++;
1281eb11fae6SDimitry Andric       Im.Global.Type = readUint8(Ctx);
1282eb11fae6SDimitry Andric       Im.Global.Mutable = readVaruint1(Ctx);
128371d5a254SDimitry Andric       break;
12846b3f41edSDimitry Andric     case wasm::WASM_EXTERNAL_MEMORY:
1285eb11fae6SDimitry Andric       Im.Memory = readLimits(Ctx);
1286b60736ecSDimitry Andric       if (Im.Memory.Flags & wasm::WASM_LIMITS_FLAG_IS_64)
1287b60736ecSDimitry Andric         HasMemory64 = true;
12886b3f41edSDimitry Andric       break;
1289b60736ecSDimitry Andric     case wasm::WASM_EXTERNAL_TABLE: {
1290b60736ecSDimitry Andric       Im.Table = readTableType(Ctx);
1291b60736ecSDimitry Andric       NumImportedTables++;
1292b60736ecSDimitry Andric       auto ElemType = Im.Table.ElemType;
12934df029ccSDimitry Andric       if (ElemType != wasm::ValType::FUNCREF &&
1294ac9a064cSDimitry Andric           ElemType != wasm::ValType::EXTERNREF &&
1295ac9a064cSDimitry Andric           ElemType != wasm::ValType::EXNREF &&
1296ac9a064cSDimitry Andric           ElemType != wasm::ValType::OTHERREF)
1297b60736ecSDimitry Andric         return make_error<GenericBinaryError>("invalid table element type",
12986b3f41edSDimitry Andric                                               object_error::parse_failed);
12996b3f41edSDimitry Andric       break;
1300b60736ecSDimitry Andric     }
1301344a3780SDimitry Andric     case wasm::WASM_EXTERNAL_TAG:
1302344a3780SDimitry Andric       NumImportedTags++;
1303c0981da4SDimitry Andric       if (readUint8(Ctx) != 0) // Reserved 'attribute' field
1304c0981da4SDimitry Andric         return make_error<GenericBinaryError>("invalid attribute",
1305c0981da4SDimitry Andric                                               object_error::parse_failed);
1306c0981da4SDimitry Andric       Im.SigIndex = readVaruint32(Ctx);
1307c0981da4SDimitry Andric       if (Im.SigIndex >= NumTypes)
1308c0981da4SDimitry Andric         return make_error<GenericBinaryError>("invalid tag type",
1309c0981da4SDimitry Andric                                               object_error::parse_failed);
1310d8e91e46SDimitry Andric       break;
131171d5a254SDimitry Andric     default:
1312b60736ecSDimitry Andric       return make_error<GenericBinaryError>("unexpected import kind",
1313d8e91e46SDimitry Andric                                             object_error::parse_failed);
131471d5a254SDimitry Andric     }
131571d5a254SDimitry Andric     Imports.push_back(Im);
131671d5a254SDimitry Andric   }
1317eb11fae6SDimitry Andric   if (Ctx.Ptr != Ctx.End)
1318b60736ecSDimitry Andric     return make_error<GenericBinaryError>("import section ended prematurely",
131971d5a254SDimitry Andric                                           object_error::parse_failed);
132071d5a254SDimitry Andric   return Error::success();
132171d5a254SDimitry Andric }
132271d5a254SDimitry Andric 
parseFunctionSection(ReadContext & Ctx)1323eb11fae6SDimitry Andric Error WasmObjectFile::parseFunctionSection(ReadContext &Ctx) {
1324eb11fae6SDimitry Andric   uint32_t Count = readVaruint32(Ctx);
1325c0981da4SDimitry Andric   Functions.reserve(Count);
1326eb11fae6SDimitry Andric   uint32_t NumTypes = Signatures.size();
132771d5a254SDimitry Andric   while (Count--) {
1328eb11fae6SDimitry Andric     uint32_t Type = readVaruint32(Ctx);
1329eb11fae6SDimitry Andric     if (Type >= NumTypes)
1330b60736ecSDimitry Andric       return make_error<GenericBinaryError>("invalid function type",
1331eb11fae6SDimitry Andric                                             object_error::parse_failed);
1332c0981da4SDimitry Andric     wasm::WasmFunction F;
1333c0981da4SDimitry Andric     F.SigIndex = Type;
1334c0981da4SDimitry Andric     Functions.push_back(F);
133571d5a254SDimitry Andric   }
1336eb11fae6SDimitry Andric   if (Ctx.Ptr != Ctx.End)
1337b60736ecSDimitry Andric     return make_error<GenericBinaryError>("function section ended prematurely",
133871d5a254SDimitry Andric                                           object_error::parse_failed);
133971d5a254SDimitry Andric   return Error::success();
134071d5a254SDimitry Andric }
134171d5a254SDimitry Andric 
parseTableSection(ReadContext & Ctx)1342eb11fae6SDimitry Andric Error WasmObjectFile::parseTableSection(ReadContext &Ctx) {
1343b60736ecSDimitry Andric   TableSection = Sections.size();
1344eb11fae6SDimitry Andric   uint32_t Count = readVaruint32(Ctx);
134571d5a254SDimitry Andric   Tables.reserve(Count);
134671d5a254SDimitry Andric   while (Count--) {
1347b60736ecSDimitry Andric     wasm::WasmTable T;
1348b60736ecSDimitry Andric     T.Type = readTableType(Ctx);
1349b60736ecSDimitry Andric     T.Index = NumImportedTables + Tables.size();
1350b60736ecSDimitry Andric     Tables.push_back(T);
1351b60736ecSDimitry Andric     auto ElemType = Tables.back().Type.ElemType;
13524df029ccSDimitry Andric     if (ElemType != wasm::ValType::FUNCREF &&
1353ac9a064cSDimitry Andric         ElemType != wasm::ValType::EXTERNREF &&
1354ac9a064cSDimitry Andric         ElemType != wasm::ValType::EXNREF &&
1355ac9a064cSDimitry Andric         ElemType != wasm::ValType::OTHERREF) {
1356b60736ecSDimitry Andric       return make_error<GenericBinaryError>("invalid table element type",
135771d5a254SDimitry Andric                                             object_error::parse_failed);
135871d5a254SDimitry Andric     }
135971d5a254SDimitry Andric   }
1360eb11fae6SDimitry Andric   if (Ctx.Ptr != Ctx.End)
1361b60736ecSDimitry Andric     return make_error<GenericBinaryError>("table section ended prematurely",
136271d5a254SDimitry Andric                                           object_error::parse_failed);
136371d5a254SDimitry Andric   return Error::success();
136471d5a254SDimitry Andric }
136571d5a254SDimitry Andric 
parseMemorySection(ReadContext & Ctx)1366eb11fae6SDimitry Andric Error WasmObjectFile::parseMemorySection(ReadContext &Ctx) {
1367eb11fae6SDimitry Andric   uint32_t Count = readVaruint32(Ctx);
136871d5a254SDimitry Andric   Memories.reserve(Count);
136971d5a254SDimitry Andric   while (Count--) {
1370b60736ecSDimitry Andric     auto Limits = readLimits(Ctx);
1371b60736ecSDimitry Andric     if (Limits.Flags & wasm::WASM_LIMITS_FLAG_IS_64)
1372b60736ecSDimitry Andric       HasMemory64 = true;
1373b60736ecSDimitry Andric     Memories.push_back(Limits);
137471d5a254SDimitry Andric   }
1375eb11fae6SDimitry Andric   if (Ctx.Ptr != Ctx.End)
1376b60736ecSDimitry Andric     return make_error<GenericBinaryError>("memory section ended prematurely",
137771d5a254SDimitry Andric                                           object_error::parse_failed);
137871d5a254SDimitry Andric   return Error::success();
137971d5a254SDimitry Andric }
138071d5a254SDimitry Andric 
parseTagSection(ReadContext & Ctx)1381344a3780SDimitry Andric Error WasmObjectFile::parseTagSection(ReadContext &Ctx) {
1382344a3780SDimitry Andric   TagSection = Sections.size();
1383344a3780SDimitry Andric   uint32_t Count = readVaruint32(Ctx);
1384344a3780SDimitry Andric   Tags.reserve(Count);
1385c0981da4SDimitry Andric   uint32_t NumTypes = Signatures.size();
1386cfca06d7SDimitry Andric   while (Count--) {
1387c0981da4SDimitry Andric     if (readUint8(Ctx) != 0) // Reserved 'attribute' field
1388c0981da4SDimitry Andric       return make_error<GenericBinaryError>("invalid attribute",
1389c0981da4SDimitry Andric                                             object_error::parse_failed);
1390c0981da4SDimitry Andric     uint32_t Type = readVaruint32(Ctx);
1391c0981da4SDimitry Andric     if (Type >= NumTypes)
1392c0981da4SDimitry Andric       return make_error<GenericBinaryError>("invalid tag type",
1393c0981da4SDimitry Andric                                             object_error::parse_failed);
1394344a3780SDimitry Andric     wasm::WasmTag Tag;
1395344a3780SDimitry Andric     Tag.Index = NumImportedTags + Tags.size();
1396c0981da4SDimitry Andric     Tag.SigIndex = Type;
1397ac9a064cSDimitry Andric     Signatures[Type].Kind = wasm::WasmSignature::Tag;
1398344a3780SDimitry Andric     Tags.push_back(Tag);
1399cfca06d7SDimitry Andric   }
1400cfca06d7SDimitry Andric 
1401cfca06d7SDimitry Andric   if (Ctx.Ptr != Ctx.End)
1402344a3780SDimitry Andric     return make_error<GenericBinaryError>("tag section ended prematurely",
1403cfca06d7SDimitry Andric                                           object_error::parse_failed);
1404cfca06d7SDimitry Andric   return Error::success();
1405cfca06d7SDimitry Andric }
1406cfca06d7SDimitry Andric 
parseGlobalSection(ReadContext & Ctx)1407eb11fae6SDimitry Andric Error WasmObjectFile::parseGlobalSection(ReadContext &Ctx) {
1408eb11fae6SDimitry Andric   GlobalSection = Sections.size();
1409ac9a064cSDimitry Andric   const uint8_t *SectionStart = Ctx.Ptr;
1410eb11fae6SDimitry Andric   uint32_t Count = readVaruint32(Ctx);
141171d5a254SDimitry Andric   Globals.reserve(Count);
141271d5a254SDimitry Andric   while (Count--) {
141371d5a254SDimitry Andric     wasm::WasmGlobal Global;
1414eb11fae6SDimitry Andric     Global.Index = NumImportedGlobals + Globals.size();
1415ac9a064cSDimitry Andric     const uint8_t *GlobalStart = Ctx.Ptr;
1416ac9a064cSDimitry Andric     Global.Offset = static_cast<uint32_t>(GlobalStart - SectionStart);
1417ac9a064cSDimitry Andric     auto GlobalOpcode = readVaruint32(Ctx);
1418ac9a064cSDimitry Andric     Global.Type.Type = (uint8_t)parseValType(Ctx, GlobalOpcode);
1419eb11fae6SDimitry Andric     Global.Type.Mutable = readVaruint1(Ctx);
1420eb11fae6SDimitry Andric     if (Error Err = readInitExpr(Global.InitExpr, Ctx))
142171d5a254SDimitry Andric       return Err;
1422ac9a064cSDimitry Andric     Global.Size = static_cast<uint32_t>(Ctx.Ptr - GlobalStart);
142371d5a254SDimitry Andric     Globals.push_back(Global);
142471d5a254SDimitry Andric   }
1425eb11fae6SDimitry Andric   if (Ctx.Ptr != Ctx.End)
1426b60736ecSDimitry Andric     return make_error<GenericBinaryError>("global section ended prematurely",
142771d5a254SDimitry Andric                                           object_error::parse_failed);
142871d5a254SDimitry Andric   return Error::success();
142971d5a254SDimitry Andric }
143071d5a254SDimitry Andric 
parseExportSection(ReadContext & Ctx)1431eb11fae6SDimitry Andric Error WasmObjectFile::parseExportSection(ReadContext &Ctx) {
1432eb11fae6SDimitry Andric   uint32_t Count = readVaruint32(Ctx);
143371d5a254SDimitry Andric   Exports.reserve(Count);
143499aabd70SDimitry Andric   Symbols.reserve(Count);
1435e6d15924SDimitry Andric   for (uint32_t I = 0; I < Count; I++) {
143671d5a254SDimitry Andric     wasm::WasmExport Ex;
1437eb11fae6SDimitry Andric     Ex.Name = readString(Ctx);
1438eb11fae6SDimitry Andric     Ex.Kind = readUint8(Ctx);
1439eb11fae6SDimitry Andric     Ex.Index = readVaruint32(Ctx);
144099aabd70SDimitry Andric     const wasm::WasmSignature *Signature = nullptr;
144199aabd70SDimitry Andric     const wasm::WasmGlobalType *GlobalType = nullptr;
144299aabd70SDimitry Andric     const wasm::WasmTableType *TableType = nullptr;
144399aabd70SDimitry Andric     wasm::WasmSymbolInfo Info;
144499aabd70SDimitry Andric     Info.Name = Ex.Name;
144599aabd70SDimitry Andric     Info.Flags = 0;
144671d5a254SDimitry Andric     switch (Ex.Kind) {
144799aabd70SDimitry Andric     case wasm::WASM_EXTERNAL_FUNCTION: {
1448706b4fc4SDimitry Andric       if (!isDefinedFunctionIndex(Ex.Index))
1449b60736ecSDimitry Andric         return make_error<GenericBinaryError>("invalid function export",
1450044eb2f6SDimitry Andric                                               object_error::parse_failed);
1451706b4fc4SDimitry Andric       getDefinedFunction(Ex.Index).ExportName = Ex.Name;
145299aabd70SDimitry Andric       Info.Kind = wasm::WASM_SYMBOL_TYPE_FUNCTION;
145399aabd70SDimitry Andric       Info.ElementIndex = Ex.Index;
145499aabd70SDimitry Andric       unsigned FuncIndex = Info.ElementIndex - NumImportedFunctions;
145599aabd70SDimitry Andric       wasm::WasmFunction &Function = Functions[FuncIndex];
145699aabd70SDimitry Andric       Signature = &Signatures[Function.SigIndex];
145771d5a254SDimitry Andric       break;
145899aabd70SDimitry Andric     }
145999aabd70SDimitry Andric     case wasm::WASM_EXTERNAL_GLOBAL: {
1460eb11fae6SDimitry Andric       if (!isValidGlobalIndex(Ex.Index))
1461b60736ecSDimitry Andric         return make_error<GenericBinaryError>("invalid global export",
1462044eb2f6SDimitry Andric                                               object_error::parse_failed);
146399aabd70SDimitry Andric       Info.Kind = wasm::WASM_SYMBOL_TYPE_DATA;
146499aabd70SDimitry Andric       uint64_t Offset = 0;
146599aabd70SDimitry Andric       if (isDefinedGlobalIndex(Ex.Index)) {
146699aabd70SDimitry Andric         auto Global = getDefinedGlobal(Ex.Index);
146799aabd70SDimitry Andric         if (!Global.InitExpr.Extended) {
146899aabd70SDimitry Andric           auto Inst = Global.InitExpr.Inst;
146999aabd70SDimitry Andric           if (Inst.Opcode == wasm::WASM_OPCODE_I32_CONST) {
147099aabd70SDimitry Andric             Offset = Inst.Value.Int32;
147199aabd70SDimitry Andric           } else if (Inst.Opcode == wasm::WASM_OPCODE_I64_CONST) {
147299aabd70SDimitry Andric             Offset = Inst.Value.Int64;
147399aabd70SDimitry Andric           }
147499aabd70SDimitry Andric         }
147599aabd70SDimitry Andric       }
147699aabd70SDimitry Andric       Info.DataRef = wasm::WasmDataReference{0, Offset, 0};
147771d5a254SDimitry Andric       break;
147899aabd70SDimitry Andric     }
1479344a3780SDimitry Andric     case wasm::WASM_EXTERNAL_TAG:
1480344a3780SDimitry Andric       if (!isValidTagIndex(Ex.Index))
1481344a3780SDimitry Andric         return make_error<GenericBinaryError>("invalid tag export",
1482d8e91e46SDimitry Andric                                               object_error::parse_failed);
148399aabd70SDimitry Andric       Info.Kind = wasm::WASM_SYMBOL_TYPE_TAG;
148499aabd70SDimitry Andric       Info.ElementIndex = Ex.Index;
1485d8e91e46SDimitry Andric       break;
14866b3f41edSDimitry Andric     case wasm::WASM_EXTERNAL_MEMORY:
148799aabd70SDimitry Andric       break;
14886b3f41edSDimitry Andric     case wasm::WASM_EXTERNAL_TABLE:
148999aabd70SDimitry Andric       Info.Kind = wasm::WASM_SYMBOL_TYPE_TABLE;
1490aca2e42cSDimitry Andric       Info.ElementIndex = Ex.Index;
14916b3f41edSDimitry Andric       break;
149271d5a254SDimitry Andric     default:
1493b60736ecSDimitry Andric       return make_error<GenericBinaryError>("unexpected export kind",
1494d8e91e46SDimitry Andric                                             object_error::parse_failed);
149571d5a254SDimitry Andric     }
149608bbd35aSDimitry Andric     Exports.push_back(Ex);
149799aabd70SDimitry Andric     if (Ex.Kind != wasm::WASM_EXTERNAL_MEMORY) {
1498ac9a064cSDimitry Andric       Symbols.emplace_back(Info, GlobalType, TableType, Signature);
149999aabd70SDimitry Andric       LLVM_DEBUG(dbgs() << "Adding symbol: " << Symbols.back() << "\n");
150099aabd70SDimitry Andric     }
150171d5a254SDimitry Andric   }
1502eb11fae6SDimitry Andric   if (Ctx.Ptr != Ctx.End)
1503b60736ecSDimitry Andric     return make_error<GenericBinaryError>("export section ended prematurely",
150471d5a254SDimitry Andric                                           object_error::parse_failed);
150571d5a254SDimitry Andric   return Error::success();
150671d5a254SDimitry Andric }
150771d5a254SDimitry Andric 
isValidFunctionIndex(uint32_t Index) const1508044eb2f6SDimitry Andric bool WasmObjectFile::isValidFunctionIndex(uint32_t Index) const {
1509c0981da4SDimitry Andric   return Index < NumImportedFunctions + Functions.size();
1510044eb2f6SDimitry Andric }
1511044eb2f6SDimitry Andric 
isDefinedFunctionIndex(uint32_t Index) const1512eb11fae6SDimitry Andric bool WasmObjectFile::isDefinedFunctionIndex(uint32_t Index) const {
1513eb11fae6SDimitry Andric   return Index >= NumImportedFunctions && isValidFunctionIndex(Index);
1514eb11fae6SDimitry Andric }
1515eb11fae6SDimitry Andric 
isValidGlobalIndex(uint32_t Index) const1516eb11fae6SDimitry Andric bool WasmObjectFile::isValidGlobalIndex(uint32_t Index) const {
1517eb11fae6SDimitry Andric   return Index < NumImportedGlobals + Globals.size();
1518eb11fae6SDimitry Andric }
1519eb11fae6SDimitry Andric 
isValidTableNumber(uint32_t Index) const1520344a3780SDimitry Andric bool WasmObjectFile::isValidTableNumber(uint32_t Index) const {
1521b60736ecSDimitry Andric   return Index < NumImportedTables + Tables.size();
1522b60736ecSDimitry Andric }
1523b60736ecSDimitry Andric 
isDefinedGlobalIndex(uint32_t Index) const1524eb11fae6SDimitry Andric bool WasmObjectFile::isDefinedGlobalIndex(uint32_t Index) const {
1525eb11fae6SDimitry Andric   return Index >= NumImportedGlobals && isValidGlobalIndex(Index);
1526eb11fae6SDimitry Andric }
1527eb11fae6SDimitry Andric 
isDefinedTableNumber(uint32_t Index) const1528344a3780SDimitry Andric bool WasmObjectFile::isDefinedTableNumber(uint32_t Index) const {
1529344a3780SDimitry Andric   return Index >= NumImportedTables && isValidTableNumber(Index);
1530b60736ecSDimitry Andric }
1531b60736ecSDimitry Andric 
isValidTagIndex(uint32_t Index) const1532344a3780SDimitry Andric bool WasmObjectFile::isValidTagIndex(uint32_t Index) const {
1533344a3780SDimitry Andric   return Index < NumImportedTags + Tags.size();
1534d8e91e46SDimitry Andric }
1535d8e91e46SDimitry Andric 
isDefinedTagIndex(uint32_t Index) const1536344a3780SDimitry Andric bool WasmObjectFile::isDefinedTagIndex(uint32_t Index) const {
1537344a3780SDimitry Andric   return Index >= NumImportedTags && isValidTagIndex(Index);
1538d8e91e46SDimitry Andric }
1539d8e91e46SDimitry Andric 
isValidFunctionSymbol(uint32_t Index) const1540eb11fae6SDimitry Andric bool WasmObjectFile::isValidFunctionSymbol(uint32_t Index) const {
1541eb11fae6SDimitry Andric   return Index < Symbols.size() && Symbols[Index].isTypeFunction();
1542eb11fae6SDimitry Andric }
1543eb11fae6SDimitry Andric 
isValidTableSymbol(uint32_t Index) const1544b60736ecSDimitry Andric bool WasmObjectFile::isValidTableSymbol(uint32_t Index) const {
1545b60736ecSDimitry Andric   return Index < Symbols.size() && Symbols[Index].isTypeTable();
1546b60736ecSDimitry Andric }
1547b60736ecSDimitry Andric 
isValidGlobalSymbol(uint32_t Index) const1548eb11fae6SDimitry Andric bool WasmObjectFile::isValidGlobalSymbol(uint32_t Index) const {
1549eb11fae6SDimitry Andric   return Index < Symbols.size() && Symbols[Index].isTypeGlobal();
1550eb11fae6SDimitry Andric }
1551eb11fae6SDimitry Andric 
isValidTagSymbol(uint32_t Index) const1552344a3780SDimitry Andric bool WasmObjectFile::isValidTagSymbol(uint32_t Index) const {
1553344a3780SDimitry Andric   return Index < Symbols.size() && Symbols[Index].isTypeTag();
1554d8e91e46SDimitry Andric }
1555d8e91e46SDimitry Andric 
isValidDataSymbol(uint32_t Index) const1556eb11fae6SDimitry Andric bool WasmObjectFile::isValidDataSymbol(uint32_t Index) const {
1557eb11fae6SDimitry Andric   return Index < Symbols.size() && Symbols[Index].isTypeData();
1558eb11fae6SDimitry Andric }
1559eb11fae6SDimitry Andric 
isValidSectionSymbol(uint32_t Index) const1560eb11fae6SDimitry Andric bool WasmObjectFile::isValidSectionSymbol(uint32_t Index) const {
1561eb11fae6SDimitry Andric   return Index < Symbols.size() && Symbols[Index].isTypeSection();
1562eb11fae6SDimitry Andric }
1563eb11fae6SDimitry Andric 
getDefinedFunction(uint32_t Index)1564eb11fae6SDimitry Andric wasm::WasmFunction &WasmObjectFile::getDefinedFunction(uint32_t Index) {
1565eb11fae6SDimitry Andric   assert(isDefinedFunctionIndex(Index));
1566eb11fae6SDimitry Andric   return Functions[Index - NumImportedFunctions];
1567eb11fae6SDimitry Andric }
1568eb11fae6SDimitry Andric 
1569e6d15924SDimitry Andric const wasm::WasmFunction &
getDefinedFunction(uint32_t Index) const1570e6d15924SDimitry Andric WasmObjectFile::getDefinedFunction(uint32_t Index) const {
1571e6d15924SDimitry Andric   assert(isDefinedFunctionIndex(Index));
1572e6d15924SDimitry Andric   return Functions[Index - NumImportedFunctions];
1573e6d15924SDimitry Andric }
1574e6d15924SDimitry Andric 
getDefinedGlobal(uint32_t Index) const1575ac9a064cSDimitry Andric const wasm::WasmGlobal &WasmObjectFile::getDefinedGlobal(uint32_t Index) const {
1576eb11fae6SDimitry Andric   assert(isDefinedGlobalIndex(Index));
1577eb11fae6SDimitry Andric   return Globals[Index - NumImportedGlobals];
1578eb11fae6SDimitry Andric }
1579eb11fae6SDimitry Andric 
getDefinedTag(uint32_t Index)1580344a3780SDimitry Andric wasm::WasmTag &WasmObjectFile::getDefinedTag(uint32_t Index) {
1581344a3780SDimitry Andric   assert(isDefinedTagIndex(Index));
1582344a3780SDimitry Andric   return Tags[Index - NumImportedTags];
1583d8e91e46SDimitry Andric }
1584d8e91e46SDimitry Andric 
parseStartSection(ReadContext & Ctx)1585eb11fae6SDimitry Andric Error WasmObjectFile::parseStartSection(ReadContext &Ctx) {
1586eb11fae6SDimitry Andric   StartFunction = readVaruint32(Ctx);
1587044eb2f6SDimitry Andric   if (!isValidFunctionIndex(StartFunction))
1588b60736ecSDimitry Andric     return make_error<GenericBinaryError>("invalid start function",
158971d5a254SDimitry Andric                                           object_error::parse_failed);
159071d5a254SDimitry Andric   return Error::success();
159171d5a254SDimitry Andric }
159271d5a254SDimitry Andric 
parseCodeSection(ReadContext & Ctx)1593eb11fae6SDimitry Andric Error WasmObjectFile::parseCodeSection(ReadContext &Ctx) {
1594eb11fae6SDimitry Andric   CodeSection = Sections.size();
1595eb11fae6SDimitry Andric   uint32_t FunctionCount = readVaruint32(Ctx);
1596c0981da4SDimitry Andric   if (FunctionCount != Functions.size()) {
1597b60736ecSDimitry Andric     return make_error<GenericBinaryError>("invalid function count",
159871d5a254SDimitry Andric                                           object_error::parse_failed);
159971d5a254SDimitry Andric   }
160071d5a254SDimitry Andric 
1601706b4fc4SDimitry Andric   for (uint32_t i = 0; i < FunctionCount; i++) {
1602706b4fc4SDimitry Andric     wasm::WasmFunction& Function = Functions[i];
1603eb11fae6SDimitry Andric     const uint8_t *FunctionStart = Ctx.Ptr;
1604eb11fae6SDimitry Andric     uint32_t Size = readVaruint32(Ctx);
1605eb11fae6SDimitry Andric     const uint8_t *FunctionEnd = Ctx.Ptr + Size;
1606044eb2f6SDimitry Andric 
1607eb11fae6SDimitry Andric     Function.CodeOffset = Ctx.Ptr - FunctionStart;
1608706b4fc4SDimitry Andric     Function.Index = NumImportedFunctions + i;
1609eb11fae6SDimitry Andric     Function.CodeSectionOffset = FunctionStart - Ctx.Start;
1610044eb2f6SDimitry Andric     Function.Size = FunctionEnd - FunctionStart;
161171d5a254SDimitry Andric 
1612eb11fae6SDimitry Andric     uint32_t NumLocalDecls = readVaruint32(Ctx);
161371d5a254SDimitry Andric     Function.Locals.reserve(NumLocalDecls);
161471d5a254SDimitry Andric     while (NumLocalDecls--) {
161571d5a254SDimitry Andric       wasm::WasmLocalDecl Decl;
1616eb11fae6SDimitry Andric       Decl.Count = readVaruint32(Ctx);
1617eb11fae6SDimitry Andric       Decl.Type = readUint8(Ctx);
161871d5a254SDimitry Andric       Function.Locals.push_back(Decl);
161971d5a254SDimitry Andric     }
162071d5a254SDimitry Andric 
1621eb11fae6SDimitry Andric     uint32_t BodySize = FunctionEnd - Ctx.Ptr;
162277dbea07SDimitry Andric     // Ensure that Function is within Ctx's buffer.
162377dbea07SDimitry Andric     if (Ctx.Ptr + BodySize > Ctx.End) {
162477dbea07SDimitry Andric       return make_error<GenericBinaryError>("Function extends beyond buffer",
162577dbea07SDimitry Andric                                             object_error::parse_failed);
162677dbea07SDimitry Andric     }
1627eb11fae6SDimitry Andric     Function.Body = ArrayRef<uint8_t>(Ctx.Ptr, BodySize);
1628eb11fae6SDimitry Andric     // This will be set later when reading in the linking metadata section.
1629eb11fae6SDimitry Andric     Function.Comdat = UINT32_MAX;
1630eb11fae6SDimitry Andric     Ctx.Ptr += BodySize;
1631eb11fae6SDimitry Andric     assert(Ctx.Ptr == FunctionEnd);
163271d5a254SDimitry Andric   }
1633eb11fae6SDimitry Andric   if (Ctx.Ptr != Ctx.End)
1634b60736ecSDimitry Andric     return make_error<GenericBinaryError>("code section ended prematurely",
163571d5a254SDimitry Andric                                           object_error::parse_failed);
163671d5a254SDimitry Andric   return Error::success();
163771d5a254SDimitry Andric }
163871d5a254SDimitry Andric 
parseElemSection(ReadContext & Ctx)1639eb11fae6SDimitry Andric Error WasmObjectFile::parseElemSection(ReadContext &Ctx) {
1640eb11fae6SDimitry Andric   uint32_t Count = readVaruint32(Ctx);
164171d5a254SDimitry Andric   ElemSegments.reserve(Count);
164271d5a254SDimitry Andric   while (Count--) {
164371d5a254SDimitry Andric     wasm::WasmElemSegment Segment;
1644344a3780SDimitry Andric     Segment.Flags = readVaruint32(Ctx);
1645344a3780SDimitry Andric 
1646344a3780SDimitry Andric     uint32_t SupportedFlags = wasm::WASM_ELEM_SEGMENT_HAS_TABLE_NUMBER |
1647344a3780SDimitry Andric                               wasm::WASM_ELEM_SEGMENT_IS_PASSIVE |
1648344a3780SDimitry Andric                               wasm::WASM_ELEM_SEGMENT_HAS_INIT_EXPRS;
1649344a3780SDimitry Andric     if (Segment.Flags & ~SupportedFlags)
1650344a3780SDimitry Andric       return make_error<GenericBinaryError>(
1651344a3780SDimitry Andric           "Unsupported flags for element segment", object_error::parse_failed);
1652344a3780SDimitry Andric 
1653ac9a064cSDimitry Andric     bool IsPassive = (Segment.Flags & wasm::WASM_ELEM_SEGMENT_IS_PASSIVE) != 0;
1654ac9a064cSDimitry Andric     bool IsDeclarative =
1655ac9a064cSDimitry Andric         IsPassive && (Segment.Flags & wasm::WASM_ELEM_SEGMENT_IS_DECLARATIVE);
1656ac9a064cSDimitry Andric     bool HasTableNumber =
1657ac9a064cSDimitry Andric         !IsPassive &&
1658ac9a064cSDimitry Andric         (Segment.Flags & wasm::WASM_ELEM_SEGMENT_HAS_TABLE_NUMBER);
1659ac9a064cSDimitry Andric     bool HasInitExprs =
1660ac9a064cSDimitry Andric         (Segment.Flags & wasm::WASM_ELEM_SEGMENT_HAS_INIT_EXPRS);
1661ac9a064cSDimitry Andric     bool HasElemKind =
1662ac9a064cSDimitry Andric         (Segment.Flags & wasm::WASM_ELEM_SEGMENT_MASK_HAS_ELEM_KIND) &&
1663ac9a064cSDimitry Andric         !HasInitExprs;
1664ac9a064cSDimitry Andric 
1665ac9a064cSDimitry Andric     if (HasTableNumber)
1666344a3780SDimitry Andric       Segment.TableNumber = readVaruint32(Ctx);
1667344a3780SDimitry Andric     else
1668344a3780SDimitry Andric       Segment.TableNumber = 0;
1669ac9a064cSDimitry Andric 
1670344a3780SDimitry Andric     if (!isValidTableNumber(Segment.TableNumber))
1671344a3780SDimitry Andric       return make_error<GenericBinaryError>("invalid TableNumber",
167271d5a254SDimitry Andric                                             object_error::parse_failed);
1673344a3780SDimitry Andric 
1674ac9a064cSDimitry Andric     if (IsPassive || IsDeclarative) {
1675145449b1SDimitry Andric       Segment.Offset.Extended = false;
1676145449b1SDimitry Andric       Segment.Offset.Inst.Opcode = wasm::WASM_OPCODE_I32_CONST;
1677145449b1SDimitry Andric       Segment.Offset.Inst.Value.Int32 = 0;
1678344a3780SDimitry Andric     } else {
1679eb11fae6SDimitry Andric       if (Error Err = readInitExpr(Segment.Offset, Ctx))
168071d5a254SDimitry Andric         return Err;
1681344a3780SDimitry Andric     }
1682344a3780SDimitry Andric 
1683ac9a064cSDimitry Andric     if (HasElemKind) {
16844df029ccSDimitry Andric       auto ElemKind = readVaruint32(Ctx);
1685344a3780SDimitry Andric       if (Segment.Flags & wasm::WASM_ELEM_SEGMENT_HAS_INIT_EXPRS) {
1686ac9a064cSDimitry Andric         Segment.ElemKind = parseValType(Ctx, ElemKind);
16874df029ccSDimitry Andric         if (Segment.ElemKind != wasm::ValType::FUNCREF &&
1688ac9a064cSDimitry Andric             Segment.ElemKind != wasm::ValType::EXTERNREF &&
1689ac9a064cSDimitry Andric             Segment.ElemKind != wasm::ValType::EXNREF &&
1690ac9a064cSDimitry Andric             Segment.ElemKind != wasm::ValType::OTHERREF) {
1691ac9a064cSDimitry Andric           return make_error<GenericBinaryError>("invalid elem type",
1692344a3780SDimitry Andric                                                 object_error::parse_failed);
1693344a3780SDimitry Andric         }
1694344a3780SDimitry Andric       } else {
16954df029ccSDimitry Andric         if (ElemKind != 0)
1696344a3780SDimitry Andric           return make_error<GenericBinaryError>("invalid elem type",
1697344a3780SDimitry Andric                                                 object_error::parse_failed);
16984df029ccSDimitry Andric         Segment.ElemKind = wasm::ValType::FUNCREF;
1699344a3780SDimitry Andric       }
1700ac9a064cSDimitry Andric     } else if (HasInitExprs) {
1701ac9a064cSDimitry Andric       auto ElemType = parseValType(Ctx, readVaruint32(Ctx));
1702ac9a064cSDimitry Andric       Segment.ElemKind = ElemType;
1703344a3780SDimitry Andric     } else {
17044df029ccSDimitry Andric       Segment.ElemKind = wasm::ValType::FUNCREF;
1705344a3780SDimitry Andric     }
1706344a3780SDimitry Andric 
1707eb11fae6SDimitry Andric     uint32_t NumElems = readVaruint32(Ctx);
1708ac9a064cSDimitry Andric 
1709ac9a064cSDimitry Andric     if (HasInitExprs) {
1710ac9a064cSDimitry Andric       while (NumElems--) {
1711ac9a064cSDimitry Andric         wasm::WasmInitExpr Expr;
1712ac9a064cSDimitry Andric         if (Error Err = readInitExpr(Expr, Ctx))
1713ac9a064cSDimitry Andric           return Err;
1714ac9a064cSDimitry Andric       }
1715ac9a064cSDimitry Andric     } else {
171671d5a254SDimitry Andric       while (NumElems--) {
1717eb11fae6SDimitry Andric         Segment.Functions.push_back(readVaruint32(Ctx));
171871d5a254SDimitry Andric       }
1719ac9a064cSDimitry Andric     }
172071d5a254SDimitry Andric     ElemSegments.push_back(Segment);
172171d5a254SDimitry Andric   }
1722eb11fae6SDimitry Andric   if (Ctx.Ptr != Ctx.End)
1723b60736ecSDimitry Andric     return make_error<GenericBinaryError>("elem section ended prematurely",
172471d5a254SDimitry Andric                                           object_error::parse_failed);
172571d5a254SDimitry Andric   return Error::success();
172671d5a254SDimitry Andric }
172771d5a254SDimitry Andric 
parseDataSection(ReadContext & Ctx)1728eb11fae6SDimitry Andric Error WasmObjectFile::parseDataSection(ReadContext &Ctx) {
1729eb11fae6SDimitry Andric   DataSection = Sections.size();
1730eb11fae6SDimitry Andric   uint32_t Count = readVaruint32(Ctx);
1731145449b1SDimitry Andric   if (DataCount && Count != *DataCount)
1732e6d15924SDimitry Andric     return make_error<GenericBinaryError>(
1733b60736ecSDimitry Andric         "number of data segments does not match DataCount section");
173471d5a254SDimitry Andric   DataSegments.reserve(Count);
173571d5a254SDimitry Andric   while (Count--) {
1736ca089b24SDimitry Andric     WasmSegment Segment;
1737e6d15924SDimitry Andric     Segment.Data.InitFlags = readVaruint32(Ctx);
1738b60736ecSDimitry Andric     Segment.Data.MemoryIndex =
1739b60736ecSDimitry Andric         (Segment.Data.InitFlags & wasm::WASM_DATA_SEGMENT_HAS_MEMINDEX)
1740b60736ecSDimitry Andric             ? readVaruint32(Ctx)
1741b60736ecSDimitry Andric             : 0;
1742b60736ecSDimitry Andric     if ((Segment.Data.InitFlags & wasm::WASM_DATA_SEGMENT_IS_PASSIVE) == 0) {
1743eb11fae6SDimitry Andric       if (Error Err = readInitExpr(Segment.Data.Offset, Ctx))
174471d5a254SDimitry Andric         return Err;
1745e6d15924SDimitry Andric     } else {
1746145449b1SDimitry Andric       Segment.Data.Offset.Extended = false;
1747145449b1SDimitry Andric       Segment.Data.Offset.Inst.Opcode = wasm::WASM_OPCODE_I32_CONST;
1748145449b1SDimitry Andric       Segment.Data.Offset.Inst.Value.Int32 = 0;
1749e6d15924SDimitry Andric     }
1750eb11fae6SDimitry Andric     uint32_t Size = readVaruint32(Ctx);
1751eb11fae6SDimitry Andric     if (Size > (size_t)(Ctx.End - Ctx.Ptr))
1752b60736ecSDimitry Andric       return make_error<GenericBinaryError>("invalid segment size",
1753eb11fae6SDimitry Andric                                             object_error::parse_failed);
1754eb11fae6SDimitry Andric     Segment.Data.Content = ArrayRef<uint8_t>(Ctx.Ptr, Size);
1755eb11fae6SDimitry Andric     // The rest of these Data fields are set later, when reading in the linking
1756eb11fae6SDimitry Andric     // metadata section.
1757044eb2f6SDimitry Andric     Segment.Data.Alignment = 0;
1758344a3780SDimitry Andric     Segment.Data.LinkingFlags = 0;
1759eb11fae6SDimitry Andric     Segment.Data.Comdat = UINT32_MAX;
1760eb11fae6SDimitry Andric     Segment.SectionOffset = Ctx.Ptr - Ctx.Start;
1761eb11fae6SDimitry Andric     Ctx.Ptr += Size;
176271d5a254SDimitry Andric     DataSegments.push_back(Segment);
176371d5a254SDimitry Andric   }
1764eb11fae6SDimitry Andric   if (Ctx.Ptr != Ctx.End)
1765b60736ecSDimitry Andric     return make_error<GenericBinaryError>("data section ended prematurely",
176671d5a254SDimitry Andric                                           object_error::parse_failed);
1767b915e9e0SDimitry Andric   return Error::success();
1768b915e9e0SDimitry Andric }
1769b915e9e0SDimitry Andric 
parseDataCountSection(ReadContext & Ctx)1770e6d15924SDimitry Andric Error WasmObjectFile::parseDataCountSection(ReadContext &Ctx) {
1771e6d15924SDimitry Andric   DataCount = readVaruint32(Ctx);
1772e6d15924SDimitry Andric   return Error::success();
1773b915e9e0SDimitry Andric }
1774b915e9e0SDimitry Andric 
getHeader() const1775b915e9e0SDimitry Andric const wasm::WasmObjectHeader &WasmObjectFile::getHeader() const {
1776b915e9e0SDimitry Andric   return Header;
1777b915e9e0SDimitry Andric }
1778b915e9e0SDimitry Andric 
moveSymbolNext(DataRefImpl & Symb) const1779e6d15924SDimitry Andric void WasmObjectFile::moveSymbolNext(DataRefImpl &Symb) const { Symb.d.b++; }
1780b915e9e0SDimitry Andric 
getSymbolFlags(DataRefImpl Symb) const1781cfca06d7SDimitry Andric Expected<uint32_t> WasmObjectFile::getSymbolFlags(DataRefImpl Symb) const {
1782c46e6a59SDimitry Andric   uint32_t Result = SymbolRef::SF_None;
178371d5a254SDimitry Andric   const WasmSymbol &Sym = getWasmSymbol(Symb);
1784c46e6a59SDimitry Andric 
1785eb11fae6SDimitry Andric   LLVM_DEBUG(dbgs() << "getSymbolFlags: ptr=" << &Sym << " " << Sym << "\n");
1786eb11fae6SDimitry Andric   if (Sym.isBindingWeak())
178708bbd35aSDimitry Andric     Result |= SymbolRef::SF_Weak;
1788eb11fae6SDimitry Andric   if (!Sym.isBindingLocal())
1789044eb2f6SDimitry Andric     Result |= SymbolRef::SF_Global;
1790044eb2f6SDimitry Andric   if (Sym.isHidden())
1791044eb2f6SDimitry Andric     Result |= SymbolRef::SF_Hidden;
1792eb11fae6SDimitry Andric   if (!Sym.isDefined())
1793c46e6a59SDimitry Andric     Result |= SymbolRef::SF_Undefined;
1794eb11fae6SDimitry Andric   if (Sym.isTypeFunction())
1795eb11fae6SDimitry Andric     Result |= SymbolRef::SF_Executable;
1796c46e6a59SDimitry Andric   return Result;
1797b915e9e0SDimitry Andric }
1798b915e9e0SDimitry Andric 
symbol_begin() const1799b915e9e0SDimitry Andric basic_symbol_iterator WasmObjectFile::symbol_begin() const {
180071d5a254SDimitry Andric   DataRefImpl Ref;
1801e6d15924SDimitry Andric   Ref.d.a = 1; // Arbitrary non-zero value so that Ref.p is non-null
1802e6d15924SDimitry Andric   Ref.d.b = 0; // Symbol index
180371d5a254SDimitry Andric   return BasicSymbolRef(Ref, this);
1804b915e9e0SDimitry Andric }
1805b915e9e0SDimitry Andric 
symbol_end() const1806b915e9e0SDimitry Andric basic_symbol_iterator WasmObjectFile::symbol_end() const {
180771d5a254SDimitry Andric   DataRefImpl Ref;
1808e6d15924SDimitry Andric   Ref.d.a = 1; // Arbitrary non-zero value so that Ref.p is non-null
1809e6d15924SDimitry Andric   Ref.d.b = Symbols.size(); // Symbol index
181071d5a254SDimitry Andric   return BasicSymbolRef(Ref, this);
181171d5a254SDimitry Andric }
181271d5a254SDimitry Andric 
getWasmSymbol(const DataRefImpl & Symb) const18136b3f41edSDimitry Andric const WasmSymbol &WasmObjectFile::getWasmSymbol(const DataRefImpl &Symb) const {
1814e6d15924SDimitry Andric   return Symbols[Symb.d.b];
1815b915e9e0SDimitry Andric }
1816b915e9e0SDimitry Andric 
getWasmSymbol(const SymbolRef & Symb) const18176b3f41edSDimitry Andric const WasmSymbol &WasmObjectFile::getWasmSymbol(const SymbolRef &Symb) const {
18186b3f41edSDimitry Andric   return getWasmSymbol(Symb.getRawDataRefImpl());
18196b3f41edSDimitry Andric }
18206b3f41edSDimitry Andric 
getSymbolName(DataRefImpl Symb) const1821b915e9e0SDimitry Andric Expected<StringRef> WasmObjectFile::getSymbolName(DataRefImpl Symb) const {
1822eb11fae6SDimitry Andric   return getWasmSymbol(Symb).Info.Name;
1823b915e9e0SDimitry Andric }
1824b915e9e0SDimitry Andric 
getSymbolAddress(DataRefImpl Symb) const1825b915e9e0SDimitry Andric Expected<uint64_t> WasmObjectFile::getSymbolAddress(DataRefImpl Symb) const {
1826e6d15924SDimitry Andric   auto &Sym = getWasmSymbol(Symb);
1827ac9a064cSDimitry Andric   if (!Sym.isDefined())
1828ac9a064cSDimitry Andric     return 0;
1829ac9a064cSDimitry Andric   Expected<section_iterator> Sec = getSymbolSection(Symb);
1830ac9a064cSDimitry Andric   if (!Sec)
1831ac9a064cSDimitry Andric     return Sec.takeError();
1832ac9a064cSDimitry Andric   uint32_t SectionAddress = getSectionAddress(Sec.get()->getRawDataRefImpl());
1833e6d15924SDimitry Andric   if (Sym.Info.Kind == wasm::WASM_SYMBOL_TYPE_FUNCTION &&
183477dbea07SDimitry Andric       isDefinedFunctionIndex(Sym.Info.ElementIndex)) {
183577dbea07SDimitry Andric     return getDefinedFunction(Sym.Info.ElementIndex).CodeSectionOffset +
1836ac9a064cSDimitry Andric            SectionAddress;
183777dbea07SDimitry Andric   }
1838ac9a064cSDimitry Andric   if (Sym.Info.Kind == wasm::WASM_SYMBOL_TYPE_GLOBAL &&
1839ac9a064cSDimitry Andric       isDefinedGlobalIndex(Sym.Info.ElementIndex)) {
1840ac9a064cSDimitry Andric     return getDefinedGlobal(Sym.Info.ElementIndex).Offset + SectionAddress;
1841ac9a064cSDimitry Andric   }
1842ac9a064cSDimitry Andric 
1843c46e6a59SDimitry Andric   return getSymbolValue(Symb);
1844b915e9e0SDimitry Andric }
1845b915e9e0SDimitry Andric 
getWasmSymbolValue(const WasmSymbol & Sym) const1846044eb2f6SDimitry Andric uint64_t WasmObjectFile::getWasmSymbolValue(const WasmSymbol &Sym) const {
1847eb11fae6SDimitry Andric   switch (Sym.Info.Kind) {
1848eb11fae6SDimitry Andric   case wasm::WASM_SYMBOL_TYPE_FUNCTION:
1849eb11fae6SDimitry Andric   case wasm::WASM_SYMBOL_TYPE_GLOBAL:
1850344a3780SDimitry Andric   case wasm::WASM_SYMBOL_TYPE_TAG:
1851b60736ecSDimitry Andric   case wasm::WASM_SYMBOL_TYPE_TABLE:
1852eb11fae6SDimitry Andric     return Sym.Info.ElementIndex;
1853eb11fae6SDimitry Andric   case wasm::WASM_SYMBOL_TYPE_DATA: {
1854eb11fae6SDimitry Andric     // The value of a data symbol is the segment offset, plus the symbol
1855eb11fae6SDimitry Andric     // offset within the segment.
1856eb11fae6SDimitry Andric     uint32_t SegmentIndex = Sym.Info.DataRef.Segment;
1857eb11fae6SDimitry Andric     const wasm::WasmDataSegment &Segment = DataSegments[SegmentIndex].Data;
1858145449b1SDimitry Andric     if (Segment.Offset.Extended) {
1859145449b1SDimitry Andric       llvm_unreachable("extended init exprs not supported");
1860145449b1SDimitry Andric     } else if (Segment.Offset.Inst.Opcode == wasm::WASM_OPCODE_I32_CONST) {
1861145449b1SDimitry Andric       return Segment.Offset.Inst.Value.Int32 + Sym.Info.DataRef.Offset;
1862145449b1SDimitry Andric     } else if (Segment.Offset.Inst.Opcode == wasm::WASM_OPCODE_I64_CONST) {
1863145449b1SDimitry Andric       return Segment.Offset.Inst.Value.Int64 + Sym.Info.DataRef.Offset;
186499aabd70SDimitry Andric     } else if (Segment.Offset.Inst.Opcode == wasm::WASM_OPCODE_GLOBAL_GET) {
186599aabd70SDimitry Andric       return Sym.Info.DataRef.Offset;
1866cfca06d7SDimitry Andric     } else {
1867cfca06d7SDimitry Andric       llvm_unreachable("unknown init expr opcode");
1868cfca06d7SDimitry Andric     }
1869044eb2f6SDimitry Andric   }
1870eb11fae6SDimitry Andric   case wasm::WASM_SYMBOL_TYPE_SECTION:
1871eb11fae6SDimitry Andric     return 0;
1872b915e9e0SDimitry Andric   }
187308bbd35aSDimitry Andric   llvm_unreachable("invalid symbol type");
187408bbd35aSDimitry Andric }
1875b915e9e0SDimitry Andric 
getSymbolValueImpl(DataRefImpl Symb) const1876044eb2f6SDimitry Andric uint64_t WasmObjectFile::getSymbolValueImpl(DataRefImpl Symb) const {
1877044eb2f6SDimitry Andric   return getWasmSymbolValue(getWasmSymbol(Symb));
1878044eb2f6SDimitry Andric }
1879044eb2f6SDimitry Andric 
getSymbolAlignment(DataRefImpl Symb) const1880b915e9e0SDimitry Andric uint32_t WasmObjectFile::getSymbolAlignment(DataRefImpl Symb) const {
1881b915e9e0SDimitry Andric   llvm_unreachable("not yet implemented");
1882b915e9e0SDimitry Andric   return 0;
1883b915e9e0SDimitry Andric }
1884b915e9e0SDimitry Andric 
getCommonSymbolSizeImpl(DataRefImpl Symb) const1885b915e9e0SDimitry Andric uint64_t WasmObjectFile::getCommonSymbolSizeImpl(DataRefImpl Symb) const {
1886b915e9e0SDimitry Andric   llvm_unreachable("not yet implemented");
1887b915e9e0SDimitry Andric   return 0;
1888b915e9e0SDimitry Andric }
1889b915e9e0SDimitry Andric 
1890b915e9e0SDimitry Andric Expected<SymbolRef::Type>
getSymbolType(DataRefImpl Symb) const1891b915e9e0SDimitry Andric WasmObjectFile::getSymbolType(DataRefImpl Symb) const {
1892c46e6a59SDimitry Andric   const WasmSymbol &Sym = getWasmSymbol(Symb);
1893c46e6a59SDimitry Andric 
1894eb11fae6SDimitry Andric   switch (Sym.Info.Kind) {
1895eb11fae6SDimitry Andric   case wasm::WASM_SYMBOL_TYPE_FUNCTION:
1896c46e6a59SDimitry Andric     return SymbolRef::ST_Function;
1897eb11fae6SDimitry Andric   case wasm::WASM_SYMBOL_TYPE_GLOBAL:
1898eb11fae6SDimitry Andric     return SymbolRef::ST_Other;
1899eb11fae6SDimitry Andric   case wasm::WASM_SYMBOL_TYPE_DATA:
1900c46e6a59SDimitry Andric     return SymbolRef::ST_Data;
1901eb11fae6SDimitry Andric   case wasm::WASM_SYMBOL_TYPE_SECTION:
1902eb11fae6SDimitry Andric     return SymbolRef::ST_Debug;
1903344a3780SDimitry Andric   case wasm::WASM_SYMBOL_TYPE_TAG:
1904d8e91e46SDimitry Andric     return SymbolRef::ST_Other;
1905b60736ecSDimitry Andric   case wasm::WASM_SYMBOL_TYPE_TABLE:
1906b60736ecSDimitry Andric     return SymbolRef::ST_Other;
1907c46e6a59SDimitry Andric   }
1908c46e6a59SDimitry Andric 
1909b60736ecSDimitry Andric   llvm_unreachable("unknown WasmSymbol::SymbolType");
1910c46e6a59SDimitry Andric   return SymbolRef::ST_Other;
1911b915e9e0SDimitry Andric }
1912b915e9e0SDimitry Andric 
1913b915e9e0SDimitry Andric Expected<section_iterator>
getSymbolSection(DataRefImpl Symb) const1914b915e9e0SDimitry Andric WasmObjectFile::getSymbolSection(DataRefImpl Symb) const {
1915eb11fae6SDimitry Andric   const WasmSymbol &Sym = getWasmSymbol(Symb);
1916eb11fae6SDimitry Andric   if (Sym.isUndefined())
1917eb11fae6SDimitry Andric     return section_end();
1918eb11fae6SDimitry Andric 
1919c46e6a59SDimitry Andric   DataRefImpl Ref;
1920cfca06d7SDimitry Andric   Ref.d.a = getSymbolSectionIdImpl(Sym);
1921cfca06d7SDimitry Andric   return section_iterator(SectionRef(Ref, this));
1922cfca06d7SDimitry Andric }
1923cfca06d7SDimitry Andric 
getSymbolSectionId(SymbolRef Symb) const1924cfca06d7SDimitry Andric uint32_t WasmObjectFile::getSymbolSectionId(SymbolRef Symb) const {
1925cfca06d7SDimitry Andric   const WasmSymbol &Sym = getWasmSymbol(Symb);
1926cfca06d7SDimitry Andric   return getSymbolSectionIdImpl(Sym);
1927cfca06d7SDimitry Andric }
1928cfca06d7SDimitry Andric 
getSymbolSectionIdImpl(const WasmSymbol & Sym) const1929cfca06d7SDimitry Andric uint32_t WasmObjectFile::getSymbolSectionIdImpl(const WasmSymbol &Sym) const {
1930eb11fae6SDimitry Andric   switch (Sym.Info.Kind) {
1931eb11fae6SDimitry Andric   case wasm::WASM_SYMBOL_TYPE_FUNCTION:
1932cfca06d7SDimitry Andric     return CodeSection;
1933eb11fae6SDimitry Andric   case wasm::WASM_SYMBOL_TYPE_GLOBAL:
1934cfca06d7SDimitry Andric     return GlobalSection;
1935eb11fae6SDimitry Andric   case wasm::WASM_SYMBOL_TYPE_DATA:
1936cfca06d7SDimitry Andric     return DataSection;
1937d8e91e46SDimitry Andric   case wasm::WASM_SYMBOL_TYPE_SECTION:
1938cfca06d7SDimitry Andric     return Sym.Info.ElementIndex;
1939344a3780SDimitry Andric   case wasm::WASM_SYMBOL_TYPE_TAG:
1940344a3780SDimitry Andric     return TagSection;
1941b60736ecSDimitry Andric   case wasm::WASM_SYMBOL_TYPE_TABLE:
1942b60736ecSDimitry Andric     return TableSection;
1943eb11fae6SDimitry Andric   default:
1944b60736ecSDimitry Andric     llvm_unreachable("unknown WasmSymbol::SymbolType");
1945eb11fae6SDimitry Andric   }
1946b915e9e0SDimitry Andric }
1947b915e9e0SDimitry Andric 
getSymbolSize(SymbolRef Symb) const1948ac9a064cSDimitry Andric uint32_t WasmObjectFile::getSymbolSize(SymbolRef Symb) const {
1949ac9a064cSDimitry Andric   const WasmSymbol &Sym = getWasmSymbol(Symb);
1950ac9a064cSDimitry Andric   if (!Sym.isDefined())
1951ac9a064cSDimitry Andric     return 0;
1952ac9a064cSDimitry Andric   if (Sym.isTypeGlobal())
1953ac9a064cSDimitry Andric     return getDefinedGlobal(Sym.Info.ElementIndex).Size;
1954ac9a064cSDimitry Andric   if (Sym.isTypeData())
1955ac9a064cSDimitry Andric     return Sym.Info.DataRef.Size;
1956ac9a064cSDimitry Andric   if (Sym.isTypeFunction())
1957ac9a064cSDimitry Andric     return functions()[Sym.Info.ElementIndex - getNumImportedFunctions()].Size;
1958ac9a064cSDimitry Andric   // Currently symbol size is only tracked for data segments and functions. In
1959ac9a064cSDimitry Andric   // principle we could also track size (e.g. binary size) for tables, globals
1960ac9a064cSDimitry Andric   // and element segments etc too.
1961ac9a064cSDimitry Andric   return 0;
1962ac9a064cSDimitry Andric }
1963ac9a064cSDimitry Andric 
moveSectionNext(DataRefImpl & Sec) const1964b915e9e0SDimitry Andric void WasmObjectFile::moveSectionNext(DataRefImpl &Sec) const { Sec.d.a++; }
1965b915e9e0SDimitry Andric 
getSectionName(DataRefImpl Sec) const1966e6d15924SDimitry Andric Expected<StringRef> WasmObjectFile::getSectionName(DataRefImpl Sec) const {
196771d5a254SDimitry Andric   const WasmSection &S = Sections[Sec.d.a];
1968145449b1SDimitry Andric   if (S.Type == wasm::WASM_SEC_CUSTOM)
1969e6d15924SDimitry Andric     return S.Name;
1970145449b1SDimitry Andric   if (S.Type > wasm::WASM_SEC_LAST_KNOWN)
1971e6d15924SDimitry Andric     return createStringError(object_error::invalid_section_index, "");
1972145449b1SDimitry Andric   return wasm::sectionTypeToString(S.Type);
1973b915e9e0SDimitry Andric }
1974b915e9e0SDimitry Andric 
getSectionAddress(DataRefImpl Sec) const1975ac9a064cSDimitry Andric uint64_t WasmObjectFile::getSectionAddress(DataRefImpl Sec) const {
1976ac9a064cSDimitry Andric   // For object files, use 0 for section addresses, and section offsets for
1977ac9a064cSDimitry Andric   // symbol addresses. For linked files, use file offsets.
1978ac9a064cSDimitry Andric   // See also getSymbolAddress.
1979ac9a064cSDimitry Andric   return isRelocatableObject() || isSharedObject() ? 0
1980ac9a064cSDimitry Andric                                                    : Sections[Sec.d.a].Offset;
1981ac9a064cSDimitry Andric }
1982b915e9e0SDimitry Andric 
getSectionIndex(DataRefImpl Sec) const1983ab44ce3dSDimitry Andric uint64_t WasmObjectFile::getSectionIndex(DataRefImpl Sec) const {
1984ab44ce3dSDimitry Andric   return Sec.d.a;
1985ab44ce3dSDimitry Andric }
1986ab44ce3dSDimitry Andric 
getSectionSize(DataRefImpl Sec) const1987b915e9e0SDimitry Andric uint64_t WasmObjectFile::getSectionSize(DataRefImpl Sec) const {
198871d5a254SDimitry Andric   const WasmSection &S = Sections[Sec.d.a];
1989b915e9e0SDimitry Andric   return S.Content.size();
1990b915e9e0SDimitry Andric }
1991b915e9e0SDimitry Andric 
1992e6d15924SDimitry Andric Expected<ArrayRef<uint8_t>>
getSectionContents(DataRefImpl Sec) const1993e6d15924SDimitry Andric WasmObjectFile::getSectionContents(DataRefImpl Sec) const {
199471d5a254SDimitry Andric   const WasmSection &S = Sections[Sec.d.a];
1995b915e9e0SDimitry Andric   // This will never fail since wasm sections can never be empty (user-sections
1996b915e9e0SDimitry Andric   // must have a name and non-user sections each have a defined structure).
1997e6d15924SDimitry Andric   return S.Content;
1998b915e9e0SDimitry Andric }
1999b915e9e0SDimitry Andric 
getSectionAlignment(DataRefImpl Sec) const2000b915e9e0SDimitry Andric uint64_t WasmObjectFile::getSectionAlignment(DataRefImpl Sec) const {
2001b915e9e0SDimitry Andric   return 1;
2002b915e9e0SDimitry Andric }
2003b915e9e0SDimitry Andric 
isSectionCompressed(DataRefImpl Sec) const2004b915e9e0SDimitry Andric bool WasmObjectFile::isSectionCompressed(DataRefImpl Sec) const {
2005b915e9e0SDimitry Andric   return false;
2006b915e9e0SDimitry Andric }
2007b915e9e0SDimitry Andric 
isSectionText(DataRefImpl Sec) const2008b915e9e0SDimitry Andric bool WasmObjectFile::isSectionText(DataRefImpl Sec) const {
200971d5a254SDimitry Andric   return getWasmSection(Sec).Type == wasm::WASM_SEC_CODE;
2010b915e9e0SDimitry Andric }
2011b915e9e0SDimitry Andric 
isSectionData(DataRefImpl Sec) const2012b915e9e0SDimitry Andric bool WasmObjectFile::isSectionData(DataRefImpl Sec) const {
201371d5a254SDimitry Andric   return getWasmSection(Sec).Type == wasm::WASM_SEC_DATA;
2014b915e9e0SDimitry Andric }
2015b915e9e0SDimitry Andric 
isSectionBSS(DataRefImpl Sec) const2016b915e9e0SDimitry Andric bool WasmObjectFile::isSectionBSS(DataRefImpl Sec) const { return false; }
2017b915e9e0SDimitry Andric 
isSectionVirtual(DataRefImpl Sec) const2018b915e9e0SDimitry Andric bool WasmObjectFile::isSectionVirtual(DataRefImpl Sec) const { return false; }
2019b915e9e0SDimitry Andric 
section_rel_begin(DataRefImpl Ref) const202071d5a254SDimitry Andric relocation_iterator WasmObjectFile::section_rel_begin(DataRefImpl Ref) const {
202171d5a254SDimitry Andric   DataRefImpl RelocRef;
202271d5a254SDimitry Andric   RelocRef.d.a = Ref.d.a;
202371d5a254SDimitry Andric   RelocRef.d.b = 0;
202471d5a254SDimitry Andric   return relocation_iterator(RelocationRef(RelocRef, this));
2025b915e9e0SDimitry Andric }
2026b915e9e0SDimitry Andric 
section_rel_end(DataRefImpl Ref) const202771d5a254SDimitry Andric relocation_iterator WasmObjectFile::section_rel_end(DataRefImpl Ref) const {
202871d5a254SDimitry Andric   const WasmSection &Sec = getWasmSection(Ref);
202971d5a254SDimitry Andric   DataRefImpl RelocRef;
203071d5a254SDimitry Andric   RelocRef.d.a = Ref.d.a;
203171d5a254SDimitry Andric   RelocRef.d.b = Sec.Relocations.size();
203271d5a254SDimitry Andric   return relocation_iterator(RelocationRef(RelocRef, this));
2033b915e9e0SDimitry Andric }
2034b915e9e0SDimitry Andric 
moveRelocationNext(DataRefImpl & Rel) const2035d8e91e46SDimitry Andric void WasmObjectFile::moveRelocationNext(DataRefImpl &Rel) const { Rel.d.b++; }
2036b915e9e0SDimitry Andric 
getRelocationOffset(DataRefImpl Ref) const203771d5a254SDimitry Andric uint64_t WasmObjectFile::getRelocationOffset(DataRefImpl Ref) const {
203871d5a254SDimitry Andric   const wasm::WasmRelocation &Rel = getWasmRelocation(Ref);
203971d5a254SDimitry Andric   return Rel.Offset;
2040b915e9e0SDimitry Andric }
2041b915e9e0SDimitry Andric 
getRelocationSymbol(DataRefImpl Ref) const2042eb11fae6SDimitry Andric symbol_iterator WasmObjectFile::getRelocationSymbol(DataRefImpl Ref) const {
2043eb11fae6SDimitry Andric   const wasm::WasmRelocation &Rel = getWasmRelocation(Ref);
2044e6d15924SDimitry Andric   if (Rel.Type == wasm::R_WASM_TYPE_INDEX_LEB)
2045eb11fae6SDimitry Andric     return symbol_end();
2046eb11fae6SDimitry Andric   DataRefImpl Sym;
2047e6d15924SDimitry Andric   Sym.d.a = 1;
2048e6d15924SDimitry Andric   Sym.d.b = Rel.Index;
2049eb11fae6SDimitry Andric   return symbol_iterator(SymbolRef(Sym, this));
2050b915e9e0SDimitry Andric }
2051b915e9e0SDimitry Andric 
getRelocationType(DataRefImpl Ref) const205271d5a254SDimitry Andric uint64_t WasmObjectFile::getRelocationType(DataRefImpl Ref) const {
205371d5a254SDimitry Andric   const wasm::WasmRelocation &Rel = getWasmRelocation(Ref);
205471d5a254SDimitry Andric   return Rel.Type;
2055b915e9e0SDimitry Andric }
2056b915e9e0SDimitry Andric 
getRelocationTypeName(DataRefImpl Ref,SmallVectorImpl<char> & Result) const2057b915e9e0SDimitry Andric void WasmObjectFile::getRelocationTypeName(
205871d5a254SDimitry Andric     DataRefImpl Ref, SmallVectorImpl<char> &Result) const {
205971d5a254SDimitry Andric   const wasm::WasmRelocation &Rel = getWasmRelocation(Ref);
206071d5a254SDimitry Andric   StringRef Res = "Unknown";
206171d5a254SDimitry Andric 
206271d5a254SDimitry Andric #define WASM_RELOC(name, value)                                                \
206371d5a254SDimitry Andric   case wasm::name:                                                             \
206471d5a254SDimitry Andric     Res = #name;                                                               \
206571d5a254SDimitry Andric     break;
206671d5a254SDimitry Andric 
206771d5a254SDimitry Andric   switch (Rel.Type) {
2068c7dac04cSDimitry Andric #include "llvm/BinaryFormat/WasmRelocs.def"
206971d5a254SDimitry Andric   }
207071d5a254SDimitry Andric 
207171d5a254SDimitry Andric #undef WASM_RELOC
207271d5a254SDimitry Andric 
207371d5a254SDimitry Andric   Result.append(Res.begin(), Res.end());
2074b915e9e0SDimitry Andric }
2075b915e9e0SDimitry Andric 
section_begin() const2076b915e9e0SDimitry Andric section_iterator WasmObjectFile::section_begin() const {
2077b915e9e0SDimitry Andric   DataRefImpl Ref;
2078b915e9e0SDimitry Andric   Ref.d.a = 0;
2079b915e9e0SDimitry Andric   return section_iterator(SectionRef(Ref, this));
2080b915e9e0SDimitry Andric }
2081b915e9e0SDimitry Andric 
section_end() const2082b915e9e0SDimitry Andric section_iterator WasmObjectFile::section_end() const {
2083b915e9e0SDimitry Andric   DataRefImpl Ref;
2084b915e9e0SDimitry Andric   Ref.d.a = Sections.size();
2085b915e9e0SDimitry Andric   return section_iterator(SectionRef(Ref, this));
2086b915e9e0SDimitry Andric }
2087b915e9e0SDimitry Andric 
getBytesInAddress() const2088b60736ecSDimitry Andric uint8_t WasmObjectFile::getBytesInAddress() const {
2089b60736ecSDimitry Andric   return HasMemory64 ? 8 : 4;
2090b60736ecSDimitry Andric }
2091b915e9e0SDimitry Andric 
getFileFormatName() const2092b915e9e0SDimitry Andric StringRef WasmObjectFile::getFileFormatName() const { return "WASM"; }
2093b915e9e0SDimitry Andric 
getArch() const2094b60736ecSDimitry Andric Triple::ArchType WasmObjectFile::getArch() const {
2095b60736ecSDimitry Andric   return HasMemory64 ? Triple::wasm64 : Triple::wasm32;
2096b60736ecSDimitry Andric }
2097b915e9e0SDimitry Andric 
getFeatures() const2098e3b55780SDimitry Andric Expected<SubtargetFeatures> WasmObjectFile::getFeatures() const {
2099b915e9e0SDimitry Andric   return SubtargetFeatures();
2100b915e9e0SDimitry Andric }
2101b915e9e0SDimitry Andric 
isRelocatableObject() const2102d8e91e46SDimitry Andric bool WasmObjectFile::isRelocatableObject() const { return HasLinkingSection; }
2103d8e91e46SDimitry Andric 
isSharedObject() const2104d8e91e46SDimitry Andric bool WasmObjectFile::isSharedObject() const { return HasDylinkSection; }
2105b915e9e0SDimitry Andric 
getWasmSection(DataRefImpl Ref) const210671d5a254SDimitry Andric const WasmSection &WasmObjectFile::getWasmSection(DataRefImpl Ref) const {
210771d5a254SDimitry Andric   assert(Ref.d.a < Sections.size());
210871d5a254SDimitry Andric   return Sections[Ref.d.a];
2109b915e9e0SDimitry Andric }
2110b915e9e0SDimitry Andric 
211171d5a254SDimitry Andric const WasmSection &
getWasmSection(const SectionRef & Section) const211271d5a254SDimitry Andric WasmObjectFile::getWasmSection(const SectionRef &Section) const {
211371d5a254SDimitry Andric   return getWasmSection(Section.getRawDataRefImpl());
211471d5a254SDimitry Andric }
211571d5a254SDimitry Andric 
211671d5a254SDimitry Andric const wasm::WasmRelocation &
getWasmRelocation(const RelocationRef & Ref) const211771d5a254SDimitry Andric WasmObjectFile::getWasmRelocation(const RelocationRef &Ref) const {
211871d5a254SDimitry Andric   return getWasmRelocation(Ref.getRawDataRefImpl());
211971d5a254SDimitry Andric }
212071d5a254SDimitry Andric 
212171d5a254SDimitry Andric const wasm::WasmRelocation &
getWasmRelocation(DataRefImpl Ref) const212271d5a254SDimitry Andric WasmObjectFile::getWasmRelocation(DataRefImpl Ref) const {
212371d5a254SDimitry Andric   assert(Ref.d.a < Sections.size());
212471d5a254SDimitry Andric   const WasmSection &Sec = Sections[Ref.d.a];
212571d5a254SDimitry Andric   assert(Ref.d.b < Sec.Relocations.size());
212671d5a254SDimitry Andric   return Sec.Relocations[Ref.d.b];
212771d5a254SDimitry Andric }
2128d8e91e46SDimitry Andric 
getSectionOrder(unsigned ID,StringRef CustomSectionName)2129d8e91e46SDimitry Andric int WasmSectionOrderChecker::getSectionOrder(unsigned ID,
2130d8e91e46SDimitry Andric                                              StringRef CustomSectionName) {
2131d8e91e46SDimitry Andric   switch (ID) {
2132d8e91e46SDimitry Andric   case wasm::WASM_SEC_CUSTOM:
2133d8e91e46SDimitry Andric     return StringSwitch<unsigned>(CustomSectionName)
2134d8e91e46SDimitry Andric         .Case("dylink", WASM_SEC_ORDER_DYLINK)
2135c0981da4SDimitry Andric         .Case("dylink.0", WASM_SEC_ORDER_DYLINK)
2136d8e91e46SDimitry Andric         .Case("linking", WASM_SEC_ORDER_LINKING)
2137d8e91e46SDimitry Andric         .StartsWith("reloc.", WASM_SEC_ORDER_RELOC)
2138d8e91e46SDimitry Andric         .Case("name", WASM_SEC_ORDER_NAME)
2139d8e91e46SDimitry Andric         .Case("producers", WASM_SEC_ORDER_PRODUCERS)
2140e6d15924SDimitry Andric         .Case("target_features", WASM_SEC_ORDER_TARGET_FEATURES)
2141e6d15924SDimitry Andric         .Default(WASM_SEC_ORDER_NONE);
2142d8e91e46SDimitry Andric   case wasm::WASM_SEC_TYPE:
2143d8e91e46SDimitry Andric     return WASM_SEC_ORDER_TYPE;
2144d8e91e46SDimitry Andric   case wasm::WASM_SEC_IMPORT:
2145d8e91e46SDimitry Andric     return WASM_SEC_ORDER_IMPORT;
2146d8e91e46SDimitry Andric   case wasm::WASM_SEC_FUNCTION:
2147d8e91e46SDimitry Andric     return WASM_SEC_ORDER_FUNCTION;
2148d8e91e46SDimitry Andric   case wasm::WASM_SEC_TABLE:
2149d8e91e46SDimitry Andric     return WASM_SEC_ORDER_TABLE;
2150d8e91e46SDimitry Andric   case wasm::WASM_SEC_MEMORY:
2151d8e91e46SDimitry Andric     return WASM_SEC_ORDER_MEMORY;
2152d8e91e46SDimitry Andric   case wasm::WASM_SEC_GLOBAL:
2153d8e91e46SDimitry Andric     return WASM_SEC_ORDER_GLOBAL;
2154d8e91e46SDimitry Andric   case wasm::WASM_SEC_EXPORT:
2155d8e91e46SDimitry Andric     return WASM_SEC_ORDER_EXPORT;
2156d8e91e46SDimitry Andric   case wasm::WASM_SEC_START:
2157d8e91e46SDimitry Andric     return WASM_SEC_ORDER_START;
2158d8e91e46SDimitry Andric   case wasm::WASM_SEC_ELEM:
2159d8e91e46SDimitry Andric     return WASM_SEC_ORDER_ELEM;
2160d8e91e46SDimitry Andric   case wasm::WASM_SEC_CODE:
2161d8e91e46SDimitry Andric     return WASM_SEC_ORDER_CODE;
2162d8e91e46SDimitry Andric   case wasm::WASM_SEC_DATA:
2163d8e91e46SDimitry Andric     return WASM_SEC_ORDER_DATA;
2164d8e91e46SDimitry Andric   case wasm::WASM_SEC_DATACOUNT:
2165d8e91e46SDimitry Andric     return WASM_SEC_ORDER_DATACOUNT;
2166344a3780SDimitry Andric   case wasm::WASM_SEC_TAG:
2167344a3780SDimitry Andric     return WASM_SEC_ORDER_TAG;
2168d8e91e46SDimitry Andric   default:
2169e6d15924SDimitry Andric     return WASM_SEC_ORDER_NONE;
2170d8e91e46SDimitry Andric   }
2171d8e91e46SDimitry Andric }
2172d8e91e46SDimitry Andric 
2173e6d15924SDimitry Andric // Represents the edges in a directed graph where any node B reachable from node
2174e6d15924SDimitry Andric // A is not allowed to appear before A in the section ordering, but may appear
2175e6d15924SDimitry Andric // afterward.
2176cfca06d7SDimitry Andric int WasmSectionOrderChecker::DisallowedPredecessors
2177cfca06d7SDimitry Andric     [WASM_NUM_SEC_ORDERS][WASM_NUM_SEC_ORDERS] = {
2178cfca06d7SDimitry Andric         // WASM_SEC_ORDER_NONE
2179cfca06d7SDimitry Andric         {},
2180cfca06d7SDimitry Andric         // WASM_SEC_ORDER_TYPE
2181cfca06d7SDimitry Andric         {WASM_SEC_ORDER_TYPE, WASM_SEC_ORDER_IMPORT},
2182cfca06d7SDimitry Andric         // WASM_SEC_ORDER_IMPORT
2183cfca06d7SDimitry Andric         {WASM_SEC_ORDER_IMPORT, WASM_SEC_ORDER_FUNCTION},
2184cfca06d7SDimitry Andric         // WASM_SEC_ORDER_FUNCTION
2185cfca06d7SDimitry Andric         {WASM_SEC_ORDER_FUNCTION, WASM_SEC_ORDER_TABLE},
2186cfca06d7SDimitry Andric         // WASM_SEC_ORDER_TABLE
2187cfca06d7SDimitry Andric         {WASM_SEC_ORDER_TABLE, WASM_SEC_ORDER_MEMORY},
2188cfca06d7SDimitry Andric         // WASM_SEC_ORDER_MEMORY
2189344a3780SDimitry Andric         {WASM_SEC_ORDER_MEMORY, WASM_SEC_ORDER_TAG},
2190344a3780SDimitry Andric         // WASM_SEC_ORDER_TAG
2191344a3780SDimitry Andric         {WASM_SEC_ORDER_TAG, WASM_SEC_ORDER_GLOBAL},
2192cfca06d7SDimitry Andric         // WASM_SEC_ORDER_GLOBAL
2193cfca06d7SDimitry Andric         {WASM_SEC_ORDER_GLOBAL, WASM_SEC_ORDER_EXPORT},
2194cfca06d7SDimitry Andric         // WASM_SEC_ORDER_EXPORT
2195cfca06d7SDimitry Andric         {WASM_SEC_ORDER_EXPORT, WASM_SEC_ORDER_START},
2196cfca06d7SDimitry Andric         // WASM_SEC_ORDER_START
2197cfca06d7SDimitry Andric         {WASM_SEC_ORDER_START, WASM_SEC_ORDER_ELEM},
2198cfca06d7SDimitry Andric         // WASM_SEC_ORDER_ELEM
2199cfca06d7SDimitry Andric         {WASM_SEC_ORDER_ELEM, WASM_SEC_ORDER_DATACOUNT},
2200cfca06d7SDimitry Andric         // WASM_SEC_ORDER_DATACOUNT
2201cfca06d7SDimitry Andric         {WASM_SEC_ORDER_DATACOUNT, WASM_SEC_ORDER_CODE},
2202cfca06d7SDimitry Andric         // WASM_SEC_ORDER_CODE
2203cfca06d7SDimitry Andric         {WASM_SEC_ORDER_CODE, WASM_SEC_ORDER_DATA},
2204cfca06d7SDimitry Andric         // WASM_SEC_ORDER_DATA
2205cfca06d7SDimitry Andric         {WASM_SEC_ORDER_DATA, WASM_SEC_ORDER_LINKING},
2206e6d15924SDimitry Andric 
2207e6d15924SDimitry Andric         // Custom Sections
2208cfca06d7SDimitry Andric         // WASM_SEC_ORDER_DYLINK
2209cfca06d7SDimitry Andric         {WASM_SEC_ORDER_DYLINK, WASM_SEC_ORDER_TYPE},
2210cfca06d7SDimitry Andric         // WASM_SEC_ORDER_LINKING
2211cfca06d7SDimitry Andric         {WASM_SEC_ORDER_LINKING, WASM_SEC_ORDER_RELOC, WASM_SEC_ORDER_NAME},
2212cfca06d7SDimitry Andric         // WASM_SEC_ORDER_RELOC (can be repeated)
2213cfca06d7SDimitry Andric         {},
2214cfca06d7SDimitry Andric         // WASM_SEC_ORDER_NAME
2215cfca06d7SDimitry Andric         {WASM_SEC_ORDER_NAME, WASM_SEC_ORDER_PRODUCERS},
2216cfca06d7SDimitry Andric         // WASM_SEC_ORDER_PRODUCERS
2217cfca06d7SDimitry Andric         {WASM_SEC_ORDER_PRODUCERS, WASM_SEC_ORDER_TARGET_FEATURES},
2218cfca06d7SDimitry Andric         // WASM_SEC_ORDER_TARGET_FEATURES
2219cfca06d7SDimitry Andric         {WASM_SEC_ORDER_TARGET_FEATURES}};
2220e6d15924SDimitry Andric 
isValidSectionOrder(unsigned ID,StringRef CustomSectionName)2221d8e91e46SDimitry Andric bool WasmSectionOrderChecker::isValidSectionOrder(unsigned ID,
2222d8e91e46SDimitry Andric                                                   StringRef CustomSectionName) {
2223d8e91e46SDimitry Andric   int Order = getSectionOrder(ID, CustomSectionName);
2224e6d15924SDimitry Andric   if (Order == WASM_SEC_ORDER_NONE)
2225d8e91e46SDimitry Andric     return true;
2226e6d15924SDimitry Andric 
2227e6d15924SDimitry Andric   // Disallowed predecessors we need to check for
2228e6d15924SDimitry Andric   SmallVector<int, WASM_NUM_SEC_ORDERS> WorkList;
2229e6d15924SDimitry Andric 
2230e6d15924SDimitry Andric   // Keep track of completed checks to avoid repeating work
2231e6d15924SDimitry Andric   bool Checked[WASM_NUM_SEC_ORDERS] = {};
2232e6d15924SDimitry Andric 
2233e6d15924SDimitry Andric   int Curr = Order;
2234e6d15924SDimitry Andric   while (true) {
2235e6d15924SDimitry Andric     // Add new disallowed predecessors to work list
2236e6d15924SDimitry Andric     for (size_t I = 0;; ++I) {
2237e6d15924SDimitry Andric       int Next = DisallowedPredecessors[Curr][I];
2238e6d15924SDimitry Andric       if (Next == WASM_SEC_ORDER_NONE)
2239e6d15924SDimitry Andric         break;
2240e6d15924SDimitry Andric       if (Checked[Next])
2241e6d15924SDimitry Andric         continue;
2242e6d15924SDimitry Andric       WorkList.push_back(Next);
2243e6d15924SDimitry Andric       Checked[Next] = true;
2244e6d15924SDimitry Andric     }
2245e6d15924SDimitry Andric 
2246e6d15924SDimitry Andric     if (WorkList.empty())
2247e6d15924SDimitry Andric       break;
2248e6d15924SDimitry Andric 
2249e6d15924SDimitry Andric     // Consider next disallowed predecessor
2250e6d15924SDimitry Andric     Curr = WorkList.pop_back_val();
2251e6d15924SDimitry Andric     if (Seen[Curr])
2252e6d15924SDimitry Andric       return false;
2253e6d15924SDimitry Andric   }
2254e6d15924SDimitry Andric 
2255e6d15924SDimitry Andric   // Have not seen any disallowed predecessors
2256e6d15924SDimitry Andric   Seen[Order] = true;
2257e6d15924SDimitry Andric   return true;
2258d8e91e46SDimitry Andric }
2259