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