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