10b57cec5SDimitry Andric //===- WasmObjectFile.cpp - Wasm object file implementation ---------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric
90b57cec5SDimitry Andric #include "llvm/ADT/ArrayRef.h"
100b57cec5SDimitry Andric #include "llvm/ADT/DenseSet.h"
110b57cec5SDimitry Andric #include "llvm/ADT/SmallSet.h"
120b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h"
130b57cec5SDimitry Andric #include "llvm/ADT/StringSet.h"
145ffd83dbSDimitry Andric #include "llvm/ADT/StringSwitch.h"
150b57cec5SDimitry Andric #include "llvm/BinaryFormat/Wasm.h"
160b57cec5SDimitry Andric #include "llvm/Object/Binary.h"
170b57cec5SDimitry Andric #include "llvm/Object/Error.h"
180b57cec5SDimitry Andric #include "llvm/Object/ObjectFile.h"
190b57cec5SDimitry Andric #include "llvm/Object/SymbolicFile.h"
200b57cec5SDimitry Andric #include "llvm/Object/Wasm.h"
210b57cec5SDimitry Andric #include "llvm/Support/Endian.h"
220b57cec5SDimitry Andric #include "llvm/Support/Error.h"
230b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
240b57cec5SDimitry Andric #include "llvm/Support/LEB128.h"
250b57cec5SDimitry Andric #include "llvm/Support/ScopedPrinter.h"
26fe013be4SDimitry Andric #include "llvm/TargetParser/SubtargetFeature.h"
27fe013be4SDimitry Andric #include "llvm/TargetParser/Triple.h"
280b57cec5SDimitry Andric #include <algorithm>
290b57cec5SDimitry Andric #include <cassert>
300b57cec5SDimitry Andric #include <cstdint>
310b57cec5SDimitry Andric #include <cstring>
320b57cec5SDimitry Andric
330b57cec5SDimitry Andric #define DEBUG_TYPE "wasm-object"
340b57cec5SDimitry Andric
350b57cec5SDimitry Andric using namespace llvm;
360b57cec5SDimitry Andric using namespace object;
370b57cec5SDimitry Andric
print(raw_ostream & Out) const380b57cec5SDimitry Andric void WasmSymbol::print(raw_ostream &Out) const {
390b57cec5SDimitry Andric Out << "Name=" << Info.Name
40fe6060f1SDimitry Andric << ", Kind=" << toString(wasm::WasmSymbolType(Info.Kind)) << ", Flags=0x"
41fe013be4SDimitry Andric << Twine::utohexstr(Info.Flags) << " [";
42fe013be4SDimitry Andric switch (getBinding()) {
43fe013be4SDimitry Andric case wasm::WASM_SYMBOL_BINDING_GLOBAL: Out << "global"; break;
44fe013be4SDimitry Andric case wasm::WASM_SYMBOL_BINDING_LOCAL: Out << "local"; break;
45fe013be4SDimitry Andric case wasm::WASM_SYMBOL_BINDING_WEAK: Out << "weak"; break;
46fe013be4SDimitry Andric }
47fe013be4SDimitry Andric if (isHidden()) {
48fe013be4SDimitry Andric Out << ", hidden";
49fe013be4SDimitry Andric } else {
50fe013be4SDimitry Andric Out << ", default";
51fe013be4SDimitry Andric }
52fe013be4SDimitry Andric Out << "]";
530b57cec5SDimitry Andric if (!isTypeData()) {
540b57cec5SDimitry Andric Out << ", ElemIndex=" << Info.ElementIndex;
550b57cec5SDimitry Andric } else if (isDefined()) {
560b57cec5SDimitry Andric Out << ", Segment=" << Info.DataRef.Segment;
570b57cec5SDimitry Andric Out << ", Offset=" << Info.DataRef.Offset;
580b57cec5SDimitry Andric Out << ", Size=" << Info.DataRef.Size;
590b57cec5SDimitry Andric }
600b57cec5SDimitry Andric }
610b57cec5SDimitry Andric
620b57cec5SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
dump() const630b57cec5SDimitry Andric LLVM_DUMP_METHOD void WasmSymbol::dump() const { print(dbgs()); }
640b57cec5SDimitry Andric #endif
650b57cec5SDimitry Andric
660b57cec5SDimitry Andric Expected<std::unique_ptr<WasmObjectFile>>
createWasmObjectFile(MemoryBufferRef Buffer)670b57cec5SDimitry Andric ObjectFile::createWasmObjectFile(MemoryBufferRef Buffer) {
680b57cec5SDimitry Andric Error Err = Error::success();
698bcb0991SDimitry Andric auto ObjectFile = std::make_unique<WasmObjectFile>(Buffer, Err);
700b57cec5SDimitry Andric if (Err)
710b57cec5SDimitry Andric return std::move(Err);
720b57cec5SDimitry Andric
730b57cec5SDimitry Andric return std::move(ObjectFile);
740b57cec5SDimitry Andric }
750b57cec5SDimitry Andric
760b57cec5SDimitry Andric #define VARINT7_MAX ((1 << 7) - 1)
770b57cec5SDimitry Andric #define VARINT7_MIN (-(1 << 7))
780b57cec5SDimitry Andric #define VARUINT7_MAX (1 << 7)
790b57cec5SDimitry Andric #define VARUINT1_MAX (1)
800b57cec5SDimitry Andric
readUint8(WasmObjectFile::ReadContext & Ctx)810b57cec5SDimitry Andric static uint8_t readUint8(WasmObjectFile::ReadContext &Ctx) {
820b57cec5SDimitry Andric if (Ctx.Ptr == Ctx.End)
830b57cec5SDimitry Andric report_fatal_error("EOF while reading uint8");
840b57cec5SDimitry Andric return *Ctx.Ptr++;
850b57cec5SDimitry Andric }
860b57cec5SDimitry Andric
readUint32(WasmObjectFile::ReadContext & Ctx)870b57cec5SDimitry Andric static uint32_t readUint32(WasmObjectFile::ReadContext &Ctx) {
880b57cec5SDimitry Andric if (Ctx.Ptr + 4 > Ctx.End)
890b57cec5SDimitry Andric report_fatal_error("EOF while reading uint32");
900b57cec5SDimitry Andric uint32_t Result = support::endian::read32le(Ctx.Ptr);
910b57cec5SDimitry Andric Ctx.Ptr += 4;
920b57cec5SDimitry Andric return Result;
930b57cec5SDimitry Andric }
940b57cec5SDimitry Andric
readFloat32(WasmObjectFile::ReadContext & Ctx)950b57cec5SDimitry Andric static int32_t readFloat32(WasmObjectFile::ReadContext &Ctx) {
960b57cec5SDimitry Andric if (Ctx.Ptr + 4 > Ctx.End)
970b57cec5SDimitry Andric report_fatal_error("EOF while reading float64");
980b57cec5SDimitry Andric int32_t Result = 0;
990b57cec5SDimitry Andric memcpy(&Result, Ctx.Ptr, sizeof(Result));
1000b57cec5SDimitry Andric Ctx.Ptr += sizeof(Result);
1010b57cec5SDimitry Andric return Result;
1020b57cec5SDimitry Andric }
1030b57cec5SDimitry Andric
readFloat64(WasmObjectFile::ReadContext & Ctx)1040b57cec5SDimitry Andric static int64_t readFloat64(WasmObjectFile::ReadContext &Ctx) {
1050b57cec5SDimitry Andric if (Ctx.Ptr + 8 > Ctx.End)
1060b57cec5SDimitry Andric report_fatal_error("EOF while reading float64");
1070b57cec5SDimitry Andric int64_t Result = 0;
1080b57cec5SDimitry Andric memcpy(&Result, Ctx.Ptr, sizeof(Result));
1090b57cec5SDimitry Andric Ctx.Ptr += sizeof(Result);
1100b57cec5SDimitry Andric return Result;
1110b57cec5SDimitry Andric }
1120b57cec5SDimitry Andric
readULEB128(WasmObjectFile::ReadContext & Ctx)1130b57cec5SDimitry Andric static uint64_t readULEB128(WasmObjectFile::ReadContext &Ctx) {
1140b57cec5SDimitry Andric unsigned Count;
1150b57cec5SDimitry Andric const char *Error = nullptr;
1160b57cec5SDimitry Andric uint64_t Result = decodeULEB128(Ctx.Ptr, &Count, Ctx.End, &Error);
1170b57cec5SDimitry Andric if (Error)
1180b57cec5SDimitry Andric report_fatal_error(Error);
1190b57cec5SDimitry Andric Ctx.Ptr += Count;
1200b57cec5SDimitry Andric return Result;
1210b57cec5SDimitry Andric }
1220b57cec5SDimitry Andric
readString(WasmObjectFile::ReadContext & Ctx)1230b57cec5SDimitry Andric static StringRef readString(WasmObjectFile::ReadContext &Ctx) {
1240b57cec5SDimitry Andric uint32_t StringLen = readULEB128(Ctx);
1250b57cec5SDimitry Andric if (Ctx.Ptr + StringLen > Ctx.End)
1260b57cec5SDimitry Andric report_fatal_error("EOF while reading string");
1270b57cec5SDimitry Andric StringRef Return =
1280b57cec5SDimitry Andric StringRef(reinterpret_cast<const char *>(Ctx.Ptr), StringLen);
1290b57cec5SDimitry Andric Ctx.Ptr += StringLen;
1300b57cec5SDimitry Andric return Return;
1310b57cec5SDimitry Andric }
1320b57cec5SDimitry Andric
readLEB128(WasmObjectFile::ReadContext & Ctx)1330b57cec5SDimitry Andric static int64_t readLEB128(WasmObjectFile::ReadContext &Ctx) {
1340b57cec5SDimitry Andric unsigned Count;
1350b57cec5SDimitry Andric const char *Error = nullptr;
1360b57cec5SDimitry Andric uint64_t Result = decodeSLEB128(Ctx.Ptr, &Count, Ctx.End, &Error);
1370b57cec5SDimitry Andric if (Error)
1380b57cec5SDimitry Andric report_fatal_error(Error);
1390b57cec5SDimitry Andric Ctx.Ptr += Count;
1400b57cec5SDimitry Andric return Result;
1410b57cec5SDimitry Andric }
1420b57cec5SDimitry Andric
readVaruint1(WasmObjectFile::ReadContext & Ctx)1430b57cec5SDimitry Andric static uint8_t readVaruint1(WasmObjectFile::ReadContext &Ctx) {
1440b57cec5SDimitry Andric int64_t Result = readLEB128(Ctx);
1450b57cec5SDimitry Andric if (Result > VARUINT1_MAX || Result < 0)
1460b57cec5SDimitry Andric report_fatal_error("LEB is outside Varuint1 range");
1470b57cec5SDimitry Andric return Result;
1480b57cec5SDimitry Andric }
1490b57cec5SDimitry Andric
readVarint32(WasmObjectFile::ReadContext & Ctx)1500b57cec5SDimitry Andric static int32_t readVarint32(WasmObjectFile::ReadContext &Ctx) {
1510b57cec5SDimitry Andric int64_t Result = readLEB128(Ctx);
1520b57cec5SDimitry Andric if (Result > INT32_MAX || Result < INT32_MIN)
1530b57cec5SDimitry Andric report_fatal_error("LEB is outside Varint32 range");
1540b57cec5SDimitry Andric return Result;
1550b57cec5SDimitry Andric }
1560b57cec5SDimitry Andric
readVaruint32(WasmObjectFile::ReadContext & Ctx)1570b57cec5SDimitry Andric static uint32_t readVaruint32(WasmObjectFile::ReadContext &Ctx) {
1580b57cec5SDimitry Andric uint64_t Result = readULEB128(Ctx);
1590b57cec5SDimitry Andric if (Result > UINT32_MAX)
1600b57cec5SDimitry Andric report_fatal_error("LEB is outside Varuint32 range");
1610b57cec5SDimitry Andric return Result;
1620b57cec5SDimitry Andric }
1630b57cec5SDimitry Andric
readVarint64(WasmObjectFile::ReadContext & Ctx)1640b57cec5SDimitry Andric static int64_t readVarint64(WasmObjectFile::ReadContext &Ctx) {
1650b57cec5SDimitry Andric return readLEB128(Ctx);
1660b57cec5SDimitry Andric }
1670b57cec5SDimitry Andric
readVaruint64(WasmObjectFile::ReadContext & Ctx)1685ffd83dbSDimitry Andric static uint64_t readVaruint64(WasmObjectFile::ReadContext &Ctx) {
1695ffd83dbSDimitry Andric return readULEB128(Ctx);
1705ffd83dbSDimitry Andric }
1715ffd83dbSDimitry Andric
readOpcode(WasmObjectFile::ReadContext & Ctx)1720b57cec5SDimitry Andric static uint8_t readOpcode(WasmObjectFile::ReadContext &Ctx) {
1730b57cec5SDimitry Andric return readUint8(Ctx);
1740b57cec5SDimitry Andric }
1750b57cec5SDimitry Andric
readInitExpr(wasm::WasmInitExpr & Expr,WasmObjectFile::ReadContext & Ctx)1760b57cec5SDimitry Andric static Error readInitExpr(wasm::WasmInitExpr &Expr,
1770b57cec5SDimitry Andric WasmObjectFile::ReadContext &Ctx) {
17881ad6265SDimitry Andric auto Start = Ctx.Ptr;
1790b57cec5SDimitry Andric
18081ad6265SDimitry Andric Expr.Extended = false;
18181ad6265SDimitry Andric Expr.Inst.Opcode = readOpcode(Ctx);
18281ad6265SDimitry Andric switch (Expr.Inst.Opcode) {
1830b57cec5SDimitry Andric case wasm::WASM_OPCODE_I32_CONST:
18481ad6265SDimitry Andric Expr.Inst.Value.Int32 = readVarint32(Ctx);
1850b57cec5SDimitry Andric break;
1860b57cec5SDimitry Andric case wasm::WASM_OPCODE_I64_CONST:
18781ad6265SDimitry Andric Expr.Inst.Value.Int64 = readVarint64(Ctx);
1880b57cec5SDimitry Andric break;
1890b57cec5SDimitry Andric case wasm::WASM_OPCODE_F32_CONST:
19081ad6265SDimitry Andric Expr.Inst.Value.Float32 = readFloat32(Ctx);
1910b57cec5SDimitry Andric break;
1920b57cec5SDimitry Andric case wasm::WASM_OPCODE_F64_CONST:
19381ad6265SDimitry Andric Expr.Inst.Value.Float64 = readFloat64(Ctx);
1940b57cec5SDimitry Andric break;
1950b57cec5SDimitry Andric case wasm::WASM_OPCODE_GLOBAL_GET:
19681ad6265SDimitry Andric Expr.Inst.Value.Global = readULEB128(Ctx);
1970b57cec5SDimitry Andric break;
1985ffd83dbSDimitry Andric case wasm::WASM_OPCODE_REF_NULL: {
1995ffd83dbSDimitry Andric wasm::ValType Ty = static_cast<wasm::ValType>(readULEB128(Ctx));
2005ffd83dbSDimitry Andric if (Ty != wasm::ValType::EXTERNREF) {
201e8d8bef9SDimitry Andric return make_error<GenericBinaryError>("invalid type for ref.null",
2025ffd83dbSDimitry Andric object_error::parse_failed);
2035ffd83dbSDimitry Andric }
2045ffd83dbSDimitry Andric break;
2055ffd83dbSDimitry Andric }
2060b57cec5SDimitry Andric default:
20781ad6265SDimitry Andric Expr.Extended = true;
2080b57cec5SDimitry Andric }
2090b57cec5SDimitry Andric
21081ad6265SDimitry Andric if (!Expr.Extended) {
2110b57cec5SDimitry Andric uint8_t EndOpcode = readOpcode(Ctx);
21281ad6265SDimitry Andric if (EndOpcode != wasm::WASM_OPCODE_END)
21381ad6265SDimitry Andric Expr.Extended = true;
21481ad6265SDimitry Andric }
21581ad6265SDimitry Andric
21681ad6265SDimitry Andric if (Expr.Extended) {
21781ad6265SDimitry Andric Ctx.Ptr = Start;
218fcaf7f86SDimitry Andric while (true) {
21981ad6265SDimitry Andric uint8_t Opcode = readOpcode(Ctx);
22081ad6265SDimitry Andric switch (Opcode) {
22181ad6265SDimitry Andric case wasm::WASM_OPCODE_I32_CONST:
22281ad6265SDimitry Andric case wasm::WASM_OPCODE_GLOBAL_GET:
22381ad6265SDimitry Andric case wasm::WASM_OPCODE_REF_NULL:
22481ad6265SDimitry Andric case wasm::WASM_OPCODE_I64_CONST:
22581ad6265SDimitry Andric case wasm::WASM_OPCODE_F32_CONST:
22681ad6265SDimitry Andric case wasm::WASM_OPCODE_F64_CONST:
22781ad6265SDimitry Andric readULEB128(Ctx);
22881ad6265SDimitry Andric break;
22981ad6265SDimitry Andric case wasm::WASM_OPCODE_I32_ADD:
23081ad6265SDimitry Andric case wasm::WASM_OPCODE_I32_SUB:
23181ad6265SDimitry Andric case wasm::WASM_OPCODE_I32_MUL:
23281ad6265SDimitry Andric case wasm::WASM_OPCODE_I64_ADD:
23381ad6265SDimitry Andric case wasm::WASM_OPCODE_I64_SUB:
23481ad6265SDimitry Andric case wasm::WASM_OPCODE_I64_MUL:
23581ad6265SDimitry Andric break;
23681ad6265SDimitry Andric case wasm::WASM_OPCODE_END:
23781ad6265SDimitry Andric Expr.Body = ArrayRef<uint8_t>(Start, Ctx.Ptr - Start);
23881ad6265SDimitry Andric return Error::success();
23981ad6265SDimitry Andric default:
24081ad6265SDimitry Andric return make_error<GenericBinaryError>(
24181ad6265SDimitry Andric Twine("invalid opcode in init_expr: ") + Twine(unsigned(Opcode)),
2420b57cec5SDimitry Andric object_error::parse_failed);
2430b57cec5SDimitry Andric }
24481ad6265SDimitry Andric }
24581ad6265SDimitry Andric }
24681ad6265SDimitry Andric
2470b57cec5SDimitry Andric return Error::success();
2480b57cec5SDimitry Andric }
2490b57cec5SDimitry Andric
readLimits(WasmObjectFile::ReadContext & Ctx)2500b57cec5SDimitry Andric static wasm::WasmLimits readLimits(WasmObjectFile::ReadContext &Ctx) {
2510b57cec5SDimitry Andric wasm::WasmLimits Result;
2520b57cec5SDimitry Andric Result.Flags = readVaruint32(Ctx);
253fe6060f1SDimitry Andric Result.Minimum = readVaruint64(Ctx);
2540b57cec5SDimitry Andric if (Result.Flags & wasm::WASM_LIMITS_FLAG_HAS_MAX)
2555ffd83dbSDimitry Andric Result.Maximum = readVaruint64(Ctx);
2560b57cec5SDimitry Andric return Result;
2570b57cec5SDimitry Andric }
2580b57cec5SDimitry Andric
readTableType(WasmObjectFile::ReadContext & Ctx)259e8d8bef9SDimitry Andric static wasm::WasmTableType readTableType(WasmObjectFile::ReadContext &Ctx) {
260e8d8bef9SDimitry Andric wasm::WasmTableType TableType;
261*a58f00eaSDimitry Andric TableType.ElemType = wasm::ValType(readVaruint32(Ctx));
262e8d8bef9SDimitry Andric TableType.Limits = readLimits(Ctx);
263e8d8bef9SDimitry Andric return TableType;
2640b57cec5SDimitry Andric }
2650b57cec5SDimitry Andric
readSection(WasmSection & Section,WasmObjectFile::ReadContext & Ctx,WasmSectionOrderChecker & Checker)2660b57cec5SDimitry Andric static Error readSection(WasmSection &Section, WasmObjectFile::ReadContext &Ctx,
2670b57cec5SDimitry Andric WasmSectionOrderChecker &Checker) {
2680b57cec5SDimitry Andric Section.Type = readUint8(Ctx);
2690b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "readSection type=" << Section.Type << "\n");
270271697daSDimitry Andric // When reading the section's size, store the size of the LEB used to encode
271271697daSDimitry Andric // it. This allows objcopy/strip to reproduce the binary identically.
272271697daSDimitry Andric const uint8_t *PreSizePtr = Ctx.Ptr;
2730b57cec5SDimitry Andric uint32_t Size = readVaruint32(Ctx);
274271697daSDimitry Andric Section.HeaderSecSizeEncodingLen = Ctx.Ptr - PreSizePtr;
275e710425bSDimitry Andric Section.Offset = Ctx.Ptr - Ctx.Start;
2760b57cec5SDimitry Andric if (Size == 0)
277e8d8bef9SDimitry Andric return make_error<StringError>("zero length section",
2780b57cec5SDimitry Andric object_error::parse_failed);
2790b57cec5SDimitry Andric if (Ctx.Ptr + Size > Ctx.End)
280e8d8bef9SDimitry Andric return make_error<StringError>("section too large",
2810b57cec5SDimitry Andric object_error::parse_failed);
2820b57cec5SDimitry Andric if (Section.Type == wasm::WASM_SEC_CUSTOM) {
2830b57cec5SDimitry Andric WasmObjectFile::ReadContext SectionCtx;
2840b57cec5SDimitry Andric SectionCtx.Start = Ctx.Ptr;
2850b57cec5SDimitry Andric SectionCtx.Ptr = Ctx.Ptr;
2860b57cec5SDimitry Andric SectionCtx.End = Ctx.Ptr + Size;
2870b57cec5SDimitry Andric
2880b57cec5SDimitry Andric Section.Name = readString(SectionCtx);
2890b57cec5SDimitry Andric
2900b57cec5SDimitry Andric uint32_t SectionNameSize = SectionCtx.Ptr - SectionCtx.Start;
2910b57cec5SDimitry Andric Ctx.Ptr += SectionNameSize;
2920b57cec5SDimitry Andric Size -= SectionNameSize;
2930b57cec5SDimitry Andric }
2940b57cec5SDimitry Andric
2950b57cec5SDimitry Andric if (!Checker.isValidSectionOrder(Section.Type, Section.Name)) {
296e8d8bef9SDimitry Andric return make_error<StringError>("out of order section type: " +
2970b57cec5SDimitry Andric llvm::to_string(Section.Type),
2980b57cec5SDimitry Andric object_error::parse_failed);
2990b57cec5SDimitry Andric }
3000b57cec5SDimitry Andric
3010b57cec5SDimitry Andric Section.Content = ArrayRef<uint8_t>(Ctx.Ptr, Size);
3020b57cec5SDimitry Andric Ctx.Ptr += Size;
3030b57cec5SDimitry Andric return Error::success();
3040b57cec5SDimitry Andric }
3050b57cec5SDimitry Andric
WasmObjectFile(MemoryBufferRef Buffer,Error & Err)3060b57cec5SDimitry Andric WasmObjectFile::WasmObjectFile(MemoryBufferRef Buffer, Error &Err)
3070b57cec5SDimitry Andric : ObjectFile(Binary::ID_Wasm, Buffer) {
3080b57cec5SDimitry Andric ErrorAsOutParameter ErrAsOutParam(&Err);
3090b57cec5SDimitry Andric Header.Magic = getData().substr(0, 4);
3100b57cec5SDimitry Andric if (Header.Magic != StringRef("\0asm", 4)) {
311e8d8bef9SDimitry Andric Err = make_error<StringError>("invalid magic number",
312e8d8bef9SDimitry Andric object_error::parse_failed);
3130b57cec5SDimitry Andric return;
3140b57cec5SDimitry Andric }
3150b57cec5SDimitry Andric
3160b57cec5SDimitry Andric ReadContext Ctx;
3170b57cec5SDimitry Andric Ctx.Start = getData().bytes_begin();
3180b57cec5SDimitry Andric Ctx.Ptr = Ctx.Start + 4;
3190b57cec5SDimitry Andric Ctx.End = Ctx.Start + getData().size();
3200b57cec5SDimitry Andric
3210b57cec5SDimitry Andric if (Ctx.Ptr + 4 > Ctx.End) {
322e8d8bef9SDimitry Andric Err = make_error<StringError>("missing version number",
3230b57cec5SDimitry Andric object_error::parse_failed);
3240b57cec5SDimitry Andric return;
3250b57cec5SDimitry Andric }
3260b57cec5SDimitry Andric
3270b57cec5SDimitry Andric Header.Version = readUint32(Ctx);
3280b57cec5SDimitry Andric if (Header.Version != wasm::WasmVersion) {
329e8d8bef9SDimitry Andric Err = make_error<StringError>("invalid version number: " +
330e8d8bef9SDimitry Andric Twine(Header.Version),
3310b57cec5SDimitry Andric object_error::parse_failed);
3320b57cec5SDimitry Andric return;
3330b57cec5SDimitry Andric }
3340b57cec5SDimitry Andric
3350b57cec5SDimitry Andric WasmSectionOrderChecker Checker;
3360b57cec5SDimitry Andric while (Ctx.Ptr < Ctx.End) {
337349cc55cSDimitry Andric WasmSection Sec;
3380b57cec5SDimitry Andric if ((Err = readSection(Sec, Ctx, Checker)))
3390b57cec5SDimitry Andric return;
3400b57cec5SDimitry Andric if ((Err = parseSection(Sec)))
3410b57cec5SDimitry Andric return;
3420b57cec5SDimitry Andric
3430b57cec5SDimitry Andric Sections.push_back(Sec);
3440b57cec5SDimitry Andric }
3450b57cec5SDimitry Andric }
3460b57cec5SDimitry Andric
parseSection(WasmSection & Sec)3470b57cec5SDimitry Andric Error WasmObjectFile::parseSection(WasmSection &Sec) {
3480b57cec5SDimitry Andric ReadContext Ctx;
3490b57cec5SDimitry Andric Ctx.Start = Sec.Content.data();
3500b57cec5SDimitry Andric Ctx.End = Ctx.Start + Sec.Content.size();
3510b57cec5SDimitry Andric Ctx.Ptr = Ctx.Start;
3520b57cec5SDimitry Andric switch (Sec.Type) {
3530b57cec5SDimitry Andric case wasm::WASM_SEC_CUSTOM:
3540b57cec5SDimitry Andric return parseCustomSection(Sec, Ctx);
3550b57cec5SDimitry Andric case wasm::WASM_SEC_TYPE:
3560b57cec5SDimitry Andric return parseTypeSection(Ctx);
3570b57cec5SDimitry Andric case wasm::WASM_SEC_IMPORT:
3580b57cec5SDimitry Andric return parseImportSection(Ctx);
3590b57cec5SDimitry Andric case wasm::WASM_SEC_FUNCTION:
3600b57cec5SDimitry Andric return parseFunctionSection(Ctx);
3610b57cec5SDimitry Andric case wasm::WASM_SEC_TABLE:
3620b57cec5SDimitry Andric return parseTableSection(Ctx);
3630b57cec5SDimitry Andric case wasm::WASM_SEC_MEMORY:
3640b57cec5SDimitry Andric return parseMemorySection(Ctx);
365fe6060f1SDimitry Andric case wasm::WASM_SEC_TAG:
366fe6060f1SDimitry Andric return parseTagSection(Ctx);
3675ffd83dbSDimitry Andric case wasm::WASM_SEC_GLOBAL:
3685ffd83dbSDimitry Andric return parseGlobalSection(Ctx);
3690b57cec5SDimitry Andric case wasm::WASM_SEC_EXPORT:
3700b57cec5SDimitry Andric return parseExportSection(Ctx);
3710b57cec5SDimitry Andric case wasm::WASM_SEC_START:
3720b57cec5SDimitry Andric return parseStartSection(Ctx);
3730b57cec5SDimitry Andric case wasm::WASM_SEC_ELEM:
3740b57cec5SDimitry Andric return parseElemSection(Ctx);
3750b57cec5SDimitry Andric case wasm::WASM_SEC_CODE:
3760b57cec5SDimitry Andric return parseCodeSection(Ctx);
3770b57cec5SDimitry Andric case wasm::WASM_SEC_DATA:
3780b57cec5SDimitry Andric return parseDataSection(Ctx);
3790b57cec5SDimitry Andric case wasm::WASM_SEC_DATACOUNT:
3800b57cec5SDimitry Andric return parseDataCountSection(Ctx);
3810b57cec5SDimitry Andric default:
3820b57cec5SDimitry Andric return make_error<GenericBinaryError>(
383e8d8bef9SDimitry Andric "invalid section type: " + Twine(Sec.Type), object_error::parse_failed);
3840b57cec5SDimitry Andric }
3850b57cec5SDimitry Andric }
3860b57cec5SDimitry Andric
parseDylinkSection(ReadContext & Ctx)3870b57cec5SDimitry Andric Error WasmObjectFile::parseDylinkSection(ReadContext &Ctx) {
388349cc55cSDimitry Andric // Legacy "dylink" section support.
389349cc55cSDimitry Andric // See parseDylink0Section for the current "dylink.0" section parsing.
3900b57cec5SDimitry Andric HasDylinkSection = true;
3910b57cec5SDimitry Andric DylinkInfo.MemorySize = readVaruint32(Ctx);
3920b57cec5SDimitry Andric DylinkInfo.MemoryAlignment = readVaruint32(Ctx);
3930b57cec5SDimitry Andric DylinkInfo.TableSize = readVaruint32(Ctx);
3940b57cec5SDimitry Andric DylinkInfo.TableAlignment = readVaruint32(Ctx);
3950b57cec5SDimitry Andric uint32_t Count = readVaruint32(Ctx);
3960b57cec5SDimitry Andric while (Count--) {
3970b57cec5SDimitry Andric DylinkInfo.Needed.push_back(readString(Ctx));
3980b57cec5SDimitry Andric }
399349cc55cSDimitry Andric
4000b57cec5SDimitry Andric if (Ctx.Ptr != Ctx.End)
4010b57cec5SDimitry Andric return make_error<GenericBinaryError>("dylink section ended prematurely",
4020b57cec5SDimitry Andric object_error::parse_failed);
4030b57cec5SDimitry Andric return Error::success();
4040b57cec5SDimitry Andric }
4050b57cec5SDimitry Andric
parseDylink0Section(ReadContext & Ctx)406349cc55cSDimitry Andric Error WasmObjectFile::parseDylink0Section(ReadContext &Ctx) {
407349cc55cSDimitry Andric // See
408349cc55cSDimitry Andric // https://github.com/WebAssembly/tool-conventions/blob/main/DynamicLinking.md
409349cc55cSDimitry Andric HasDylinkSection = true;
410349cc55cSDimitry Andric
411349cc55cSDimitry Andric const uint8_t *OrigEnd = Ctx.End;
412349cc55cSDimitry Andric while (Ctx.Ptr < OrigEnd) {
413349cc55cSDimitry Andric Ctx.End = OrigEnd;
414349cc55cSDimitry Andric uint8_t Type = readUint8(Ctx);
415349cc55cSDimitry Andric uint32_t Size = readVaruint32(Ctx);
416349cc55cSDimitry Andric LLVM_DEBUG(dbgs() << "readSubsection type=" << int(Type) << " size=" << Size
417349cc55cSDimitry Andric << "\n");
418349cc55cSDimitry Andric Ctx.End = Ctx.Ptr + Size;
419349cc55cSDimitry Andric uint32_t Count;
420349cc55cSDimitry Andric switch (Type) {
421349cc55cSDimitry Andric case wasm::WASM_DYLINK_MEM_INFO:
422349cc55cSDimitry Andric DylinkInfo.MemorySize = readVaruint32(Ctx);
423349cc55cSDimitry Andric DylinkInfo.MemoryAlignment = readVaruint32(Ctx);
424349cc55cSDimitry Andric DylinkInfo.TableSize = readVaruint32(Ctx);
425349cc55cSDimitry Andric DylinkInfo.TableAlignment = readVaruint32(Ctx);
426349cc55cSDimitry Andric break;
427349cc55cSDimitry Andric case wasm::WASM_DYLINK_NEEDED:
428349cc55cSDimitry Andric Count = readVaruint32(Ctx);
429349cc55cSDimitry Andric while (Count--) {
430349cc55cSDimitry Andric DylinkInfo.Needed.push_back(readString(Ctx));
431349cc55cSDimitry Andric }
432349cc55cSDimitry Andric break;
433349cc55cSDimitry Andric case wasm::WASM_DYLINK_EXPORT_INFO: {
434349cc55cSDimitry Andric uint32_t Count = readVaruint32(Ctx);
435349cc55cSDimitry Andric while (Count--) {
436349cc55cSDimitry Andric DylinkInfo.ExportInfo.push_back({readString(Ctx), readVaruint32(Ctx)});
437349cc55cSDimitry Andric }
438349cc55cSDimitry Andric break;
439349cc55cSDimitry Andric }
440349cc55cSDimitry Andric case wasm::WASM_DYLINK_IMPORT_INFO: {
441349cc55cSDimitry Andric uint32_t Count = readVaruint32(Ctx);
442349cc55cSDimitry Andric while (Count--) {
443349cc55cSDimitry Andric DylinkInfo.ImportInfo.push_back(
444349cc55cSDimitry Andric {readString(Ctx), readString(Ctx), readVaruint32(Ctx)});
445349cc55cSDimitry Andric }
446349cc55cSDimitry Andric break;
447349cc55cSDimitry Andric }
448349cc55cSDimitry Andric default:
449349cc55cSDimitry Andric LLVM_DEBUG(dbgs() << "unknown dylink.0 sub-section: " << Type << "\n");
450349cc55cSDimitry Andric Ctx.Ptr += Size;
451349cc55cSDimitry Andric break;
452349cc55cSDimitry Andric }
453349cc55cSDimitry Andric if (Ctx.Ptr != Ctx.End) {
454349cc55cSDimitry Andric return make_error<GenericBinaryError>(
455349cc55cSDimitry Andric "dylink.0 sub-section ended prematurely", object_error::parse_failed);
456349cc55cSDimitry Andric }
457349cc55cSDimitry Andric }
458349cc55cSDimitry Andric
459349cc55cSDimitry Andric if (Ctx.Ptr != Ctx.End)
460349cc55cSDimitry Andric return make_error<GenericBinaryError>("dylink.0 section ended prematurely",
461349cc55cSDimitry Andric object_error::parse_failed);
462349cc55cSDimitry Andric return Error::success();
463349cc55cSDimitry Andric }
464349cc55cSDimitry Andric
parseNameSection(ReadContext & Ctx)4650b57cec5SDimitry Andric Error WasmObjectFile::parseNameSection(ReadContext &Ctx) {
466e8d8bef9SDimitry Andric llvm::DenseSet<uint64_t> SeenFunctions;
467e8d8bef9SDimitry Andric llvm::DenseSet<uint64_t> SeenGlobals;
468e8d8bef9SDimitry Andric llvm::DenseSet<uint64_t> SeenSegments;
4690b57cec5SDimitry Andric
4700b57cec5SDimitry Andric while (Ctx.Ptr < Ctx.End) {
4710b57cec5SDimitry Andric uint8_t Type = readUint8(Ctx);
4720b57cec5SDimitry Andric uint32_t Size = readVaruint32(Ctx);
4730b57cec5SDimitry Andric const uint8_t *SubSectionEnd = Ctx.Ptr + Size;
4740b57cec5SDimitry Andric switch (Type) {
475e8d8bef9SDimitry Andric case wasm::WASM_NAMES_FUNCTION:
476e8d8bef9SDimitry Andric case wasm::WASM_NAMES_GLOBAL:
477e8d8bef9SDimitry Andric case wasm::WASM_NAMES_DATA_SEGMENT: {
4780b57cec5SDimitry Andric uint32_t Count = readVaruint32(Ctx);
4790b57cec5SDimitry Andric while (Count--) {
4800b57cec5SDimitry Andric uint32_t Index = readVaruint32(Ctx);
4810b57cec5SDimitry Andric StringRef Name = readString(Ctx);
482e8d8bef9SDimitry Andric wasm::NameType nameType = wasm::NameType::FUNCTION;
483e8d8bef9SDimitry Andric if (Type == wasm::WASM_NAMES_FUNCTION) {
484e8d8bef9SDimitry Andric if (!SeenFunctions.insert(Index).second)
485e8d8bef9SDimitry Andric return make_error<GenericBinaryError>(
486e8d8bef9SDimitry Andric "function named more than once", object_error::parse_failed);
4870b57cec5SDimitry Andric if (!isValidFunctionIndex(Index) || Name.empty())
48881ad6265SDimitry Andric return make_error<GenericBinaryError>("invalid function name entry",
4890b57cec5SDimitry Andric object_error::parse_failed);
490e8d8bef9SDimitry Andric
4910b57cec5SDimitry Andric if (isDefinedFunctionIndex(Index))
4920b57cec5SDimitry Andric getDefinedFunction(Index).DebugName = Name;
493e8d8bef9SDimitry Andric } else if (Type == wasm::WASM_NAMES_GLOBAL) {
494e8d8bef9SDimitry Andric nameType = wasm::NameType::GLOBAL;
495e8d8bef9SDimitry Andric if (!SeenGlobals.insert(Index).second)
496e8d8bef9SDimitry Andric return make_error<GenericBinaryError>("global named more than once",
497e8d8bef9SDimitry Andric object_error::parse_failed);
498e8d8bef9SDimitry Andric if (!isValidGlobalIndex(Index) || Name.empty())
49981ad6265SDimitry Andric return make_error<GenericBinaryError>("invalid global name entry",
500e8d8bef9SDimitry Andric object_error::parse_failed);
501e8d8bef9SDimitry Andric } else {
502e8d8bef9SDimitry Andric nameType = wasm::NameType::DATA_SEGMENT;
503e8d8bef9SDimitry Andric if (!SeenSegments.insert(Index).second)
504e8d8bef9SDimitry Andric return make_error<GenericBinaryError>(
505e8d8bef9SDimitry Andric "segment named more than once", object_error::parse_failed);
506e8d8bef9SDimitry Andric if (Index > DataSegments.size())
50781ad6265SDimitry Andric return make_error<GenericBinaryError>("invalid data segment name entry",
508e8d8bef9SDimitry Andric object_error::parse_failed);
509e8d8bef9SDimitry Andric }
510e8d8bef9SDimitry Andric DebugNames.push_back(wasm::WasmDebugName{nameType, Index, Name});
5110b57cec5SDimitry Andric }
5120b57cec5SDimitry Andric break;
5130b57cec5SDimitry Andric }
5140b57cec5SDimitry Andric // Ignore local names for now
5150b57cec5SDimitry Andric case wasm::WASM_NAMES_LOCAL:
5160b57cec5SDimitry Andric default:
5170b57cec5SDimitry Andric Ctx.Ptr += Size;
5180b57cec5SDimitry Andric break;
5190b57cec5SDimitry Andric }
5200b57cec5SDimitry Andric if (Ctx.Ptr != SubSectionEnd)
5210b57cec5SDimitry Andric return make_error<GenericBinaryError>(
522e8d8bef9SDimitry Andric "name sub-section ended prematurely", object_error::parse_failed);
5230b57cec5SDimitry Andric }
5240b57cec5SDimitry Andric
5250b57cec5SDimitry Andric if (Ctx.Ptr != Ctx.End)
526e8d8bef9SDimitry Andric return make_error<GenericBinaryError>("name section ended prematurely",
5270b57cec5SDimitry Andric object_error::parse_failed);
5280b57cec5SDimitry Andric return Error::success();
5290b57cec5SDimitry Andric }
5300b57cec5SDimitry Andric
parseLinkingSection(ReadContext & Ctx)5310b57cec5SDimitry Andric Error WasmObjectFile::parseLinkingSection(ReadContext &Ctx) {
5320b57cec5SDimitry Andric HasLinkingSection = true;
5330b57cec5SDimitry Andric
5340b57cec5SDimitry Andric LinkingData.Version = readVaruint32(Ctx);
5350b57cec5SDimitry Andric if (LinkingData.Version != wasm::WasmMetadataVersion) {
5360b57cec5SDimitry Andric return make_error<GenericBinaryError>(
537e8d8bef9SDimitry Andric "unexpected metadata version: " + Twine(LinkingData.Version) +
5380b57cec5SDimitry Andric " (Expected: " + Twine(wasm::WasmMetadataVersion) + ")",
5390b57cec5SDimitry Andric object_error::parse_failed);
5400b57cec5SDimitry Andric }
5410b57cec5SDimitry Andric
5420b57cec5SDimitry Andric const uint8_t *OrigEnd = Ctx.End;
5430b57cec5SDimitry Andric while (Ctx.Ptr < OrigEnd) {
5440b57cec5SDimitry Andric Ctx.End = OrigEnd;
5450b57cec5SDimitry Andric uint8_t Type = readUint8(Ctx);
5460b57cec5SDimitry Andric uint32_t Size = readVaruint32(Ctx);
5470b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "readSubsection type=" << int(Type) << " size=" << Size
5480b57cec5SDimitry Andric << "\n");
5490b57cec5SDimitry Andric Ctx.End = Ctx.Ptr + Size;
5500b57cec5SDimitry Andric switch (Type) {
5510b57cec5SDimitry Andric case wasm::WASM_SYMBOL_TABLE:
5520b57cec5SDimitry Andric if (Error Err = parseLinkingSectionSymtab(Ctx))
5530b57cec5SDimitry Andric return Err;
5540b57cec5SDimitry Andric break;
5550b57cec5SDimitry Andric case wasm::WASM_SEGMENT_INFO: {
5560b57cec5SDimitry Andric uint32_t Count = readVaruint32(Ctx);
5570b57cec5SDimitry Andric if (Count > DataSegments.size())
558e8d8bef9SDimitry Andric return make_error<GenericBinaryError>("too many segment names",
5590b57cec5SDimitry Andric object_error::parse_failed);
5600b57cec5SDimitry Andric for (uint32_t I = 0; I < Count; I++) {
5610b57cec5SDimitry Andric DataSegments[I].Data.Name = readString(Ctx);
5620b57cec5SDimitry Andric DataSegments[I].Data.Alignment = readVaruint32(Ctx);
563fe6060f1SDimitry Andric DataSegments[I].Data.LinkingFlags = readVaruint32(Ctx);
5640b57cec5SDimitry Andric }
5650b57cec5SDimitry Andric break;
5660b57cec5SDimitry Andric }
5670b57cec5SDimitry Andric case wasm::WASM_INIT_FUNCS: {
5680b57cec5SDimitry Andric uint32_t Count = readVaruint32(Ctx);
5690b57cec5SDimitry Andric LinkingData.InitFunctions.reserve(Count);
5700b57cec5SDimitry Andric for (uint32_t I = 0; I < Count; I++) {
5710b57cec5SDimitry Andric wasm::WasmInitFunc Init;
5720b57cec5SDimitry Andric Init.Priority = readVaruint32(Ctx);
5730b57cec5SDimitry Andric Init.Symbol = readVaruint32(Ctx);
5740b57cec5SDimitry Andric if (!isValidFunctionSymbol(Init.Symbol))
575e8d8bef9SDimitry Andric return make_error<GenericBinaryError>("invalid function symbol: " +
5760b57cec5SDimitry Andric Twine(Init.Symbol),
5770b57cec5SDimitry Andric object_error::parse_failed);
5780b57cec5SDimitry Andric LinkingData.InitFunctions.emplace_back(Init);
5790b57cec5SDimitry Andric }
5800b57cec5SDimitry Andric break;
5810b57cec5SDimitry Andric }
5820b57cec5SDimitry Andric case wasm::WASM_COMDAT_INFO:
5830b57cec5SDimitry Andric if (Error Err = parseLinkingSectionComdat(Ctx))
5840b57cec5SDimitry Andric return Err;
5850b57cec5SDimitry Andric break;
5860b57cec5SDimitry Andric default:
5870b57cec5SDimitry Andric Ctx.Ptr += Size;
5880b57cec5SDimitry Andric break;
5890b57cec5SDimitry Andric }
5900b57cec5SDimitry Andric if (Ctx.Ptr != Ctx.End)
5910b57cec5SDimitry Andric return make_error<GenericBinaryError>(
592e8d8bef9SDimitry Andric "linking sub-section ended prematurely", object_error::parse_failed);
5930b57cec5SDimitry Andric }
5940b57cec5SDimitry Andric if (Ctx.Ptr != OrigEnd)
595e8d8bef9SDimitry Andric return make_error<GenericBinaryError>("linking section ended prematurely",
5960b57cec5SDimitry Andric object_error::parse_failed);
5970b57cec5SDimitry Andric return Error::success();
5980b57cec5SDimitry Andric }
5990b57cec5SDimitry Andric
parseLinkingSectionSymtab(ReadContext & Ctx)6000b57cec5SDimitry Andric Error WasmObjectFile::parseLinkingSectionSymtab(ReadContext &Ctx) {
6010b57cec5SDimitry Andric uint32_t Count = readVaruint32(Ctx);
602e710425bSDimitry Andric // Clear out any symbol information that was derived from the exports
603e710425bSDimitry Andric // section.
604e710425bSDimitry Andric LinkingData.SymbolTable.clear();
605e710425bSDimitry Andric Symbols.clear();
6060b57cec5SDimitry Andric LinkingData.SymbolTable.reserve(Count);
6070b57cec5SDimitry Andric Symbols.reserve(Count);
6080b57cec5SDimitry Andric StringSet<> SymbolNames;
6090b57cec5SDimitry Andric
6100b57cec5SDimitry Andric std::vector<wasm::WasmImport *> ImportedGlobals;
6110b57cec5SDimitry Andric std::vector<wasm::WasmImport *> ImportedFunctions;
612fe6060f1SDimitry Andric std::vector<wasm::WasmImport *> ImportedTags;
613e8d8bef9SDimitry Andric std::vector<wasm::WasmImport *> ImportedTables;
6140b57cec5SDimitry Andric ImportedGlobals.reserve(Imports.size());
6150b57cec5SDimitry Andric ImportedFunctions.reserve(Imports.size());
616fe6060f1SDimitry Andric ImportedTags.reserve(Imports.size());
617e8d8bef9SDimitry Andric ImportedTables.reserve(Imports.size());
6180b57cec5SDimitry Andric for (auto &I : Imports) {
6190b57cec5SDimitry Andric if (I.Kind == wasm::WASM_EXTERNAL_FUNCTION)
6200b57cec5SDimitry Andric ImportedFunctions.emplace_back(&I);
6210b57cec5SDimitry Andric else if (I.Kind == wasm::WASM_EXTERNAL_GLOBAL)
6220b57cec5SDimitry Andric ImportedGlobals.emplace_back(&I);
623fe6060f1SDimitry Andric else if (I.Kind == wasm::WASM_EXTERNAL_TAG)
624fe6060f1SDimitry Andric ImportedTags.emplace_back(&I);
625e8d8bef9SDimitry Andric else if (I.Kind == wasm::WASM_EXTERNAL_TABLE)
626e8d8bef9SDimitry Andric ImportedTables.emplace_back(&I);
6270b57cec5SDimitry Andric }
6280b57cec5SDimitry Andric
6290b57cec5SDimitry Andric while (Count--) {
6300b57cec5SDimitry Andric wasm::WasmSymbolInfo Info;
6310b57cec5SDimitry Andric const wasm::WasmSignature *Signature = nullptr;
6320b57cec5SDimitry Andric const wasm::WasmGlobalType *GlobalType = nullptr;
633e8d8bef9SDimitry Andric const wasm::WasmTableType *TableType = nullptr;
6340b57cec5SDimitry Andric
6350b57cec5SDimitry Andric Info.Kind = readUint8(Ctx);
6360b57cec5SDimitry Andric Info.Flags = readVaruint32(Ctx);
6370b57cec5SDimitry Andric bool IsDefined = (Info.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0;
6380b57cec5SDimitry Andric
6390b57cec5SDimitry Andric switch (Info.Kind) {
6400b57cec5SDimitry Andric case wasm::WASM_SYMBOL_TYPE_FUNCTION:
6410b57cec5SDimitry Andric Info.ElementIndex = readVaruint32(Ctx);
6420b57cec5SDimitry Andric if (!isValidFunctionIndex(Info.ElementIndex) ||
6430b57cec5SDimitry Andric IsDefined != isDefinedFunctionIndex(Info.ElementIndex))
6440b57cec5SDimitry Andric return make_error<GenericBinaryError>("invalid function symbol index",
6450b57cec5SDimitry Andric object_error::parse_failed);
6460b57cec5SDimitry Andric if (IsDefined) {
6470b57cec5SDimitry Andric Info.Name = readString(Ctx);
6480b57cec5SDimitry Andric unsigned FuncIndex = Info.ElementIndex - NumImportedFunctions;
6490b57cec5SDimitry Andric wasm::WasmFunction &Function = Functions[FuncIndex];
650349cc55cSDimitry Andric Signature = &Signatures[Function.SigIndex];
6510b57cec5SDimitry Andric if (Function.SymbolName.empty())
6520b57cec5SDimitry Andric Function.SymbolName = Info.Name;
6530b57cec5SDimitry Andric } else {
6540b57cec5SDimitry Andric wasm::WasmImport &Import = *ImportedFunctions[Info.ElementIndex];
6555ffd83dbSDimitry Andric if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0) {
6560b57cec5SDimitry Andric Info.Name = readString(Ctx);
6570b57cec5SDimitry Andric Info.ImportName = Import.Field;
6585ffd83dbSDimitry Andric } else {
6595ffd83dbSDimitry Andric Info.Name = Import.Field;
6605ffd83dbSDimitry Andric }
6615ffd83dbSDimitry Andric Signature = &Signatures[Import.SigIndex];
6620b57cec5SDimitry Andric Info.ImportModule = Import.Module;
6630b57cec5SDimitry Andric }
6640b57cec5SDimitry Andric break;
6650b57cec5SDimitry Andric
6660b57cec5SDimitry Andric case wasm::WASM_SYMBOL_TYPE_GLOBAL:
6670b57cec5SDimitry Andric Info.ElementIndex = readVaruint32(Ctx);
6680b57cec5SDimitry Andric if (!isValidGlobalIndex(Info.ElementIndex) ||
6690b57cec5SDimitry Andric IsDefined != isDefinedGlobalIndex(Info.ElementIndex))
6700b57cec5SDimitry Andric return make_error<GenericBinaryError>("invalid global symbol index",
6710b57cec5SDimitry Andric object_error::parse_failed);
6720b57cec5SDimitry Andric if (!IsDefined && (Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) ==
6730b57cec5SDimitry Andric wasm::WASM_SYMBOL_BINDING_WEAK)
6740b57cec5SDimitry Andric return make_error<GenericBinaryError>("undefined weak global symbol",
6750b57cec5SDimitry Andric object_error::parse_failed);
6760b57cec5SDimitry Andric if (IsDefined) {
6770b57cec5SDimitry Andric Info.Name = readString(Ctx);
6780b57cec5SDimitry Andric unsigned GlobalIndex = Info.ElementIndex - NumImportedGlobals;
6790b57cec5SDimitry Andric wasm::WasmGlobal &Global = Globals[GlobalIndex];
6800b57cec5SDimitry Andric GlobalType = &Global.Type;
6810b57cec5SDimitry Andric if (Global.SymbolName.empty())
6820b57cec5SDimitry Andric Global.SymbolName = Info.Name;
6830b57cec5SDimitry Andric } else {
6840b57cec5SDimitry Andric wasm::WasmImport &Import = *ImportedGlobals[Info.ElementIndex];
6855ffd83dbSDimitry Andric if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0) {
6860b57cec5SDimitry Andric Info.Name = readString(Ctx);
6875ffd83dbSDimitry Andric Info.ImportName = Import.Field;
6885ffd83dbSDimitry Andric } else {
6890b57cec5SDimitry Andric Info.Name = Import.Field;
6905ffd83dbSDimitry Andric }
6910b57cec5SDimitry Andric GlobalType = &Import.Global;
692e8d8bef9SDimitry Andric Info.ImportModule = Import.Module;
693e8d8bef9SDimitry Andric }
694e8d8bef9SDimitry Andric break;
695e8d8bef9SDimitry Andric
696e8d8bef9SDimitry Andric case wasm::WASM_SYMBOL_TYPE_TABLE:
697e8d8bef9SDimitry Andric Info.ElementIndex = readVaruint32(Ctx);
698fe6060f1SDimitry Andric if (!isValidTableNumber(Info.ElementIndex) ||
699fe6060f1SDimitry Andric IsDefined != isDefinedTableNumber(Info.ElementIndex))
700e8d8bef9SDimitry Andric return make_error<GenericBinaryError>("invalid table symbol index",
701e8d8bef9SDimitry Andric object_error::parse_failed);
702e8d8bef9SDimitry Andric if (!IsDefined && (Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) ==
703e8d8bef9SDimitry Andric wasm::WASM_SYMBOL_BINDING_WEAK)
704e8d8bef9SDimitry Andric return make_error<GenericBinaryError>("undefined weak table symbol",
705e8d8bef9SDimitry Andric object_error::parse_failed);
706e8d8bef9SDimitry Andric if (IsDefined) {
707e8d8bef9SDimitry Andric Info.Name = readString(Ctx);
708fe6060f1SDimitry Andric unsigned TableNumber = Info.ElementIndex - NumImportedTables;
709fe6060f1SDimitry Andric wasm::WasmTable &Table = Tables[TableNumber];
710e8d8bef9SDimitry Andric TableType = &Table.Type;
711e8d8bef9SDimitry Andric if (Table.SymbolName.empty())
712e8d8bef9SDimitry Andric Table.SymbolName = Info.Name;
713e8d8bef9SDimitry Andric } else {
714e8d8bef9SDimitry Andric wasm::WasmImport &Import = *ImportedTables[Info.ElementIndex];
715e8d8bef9SDimitry Andric if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0) {
716e8d8bef9SDimitry Andric Info.Name = readString(Ctx);
7170b57cec5SDimitry Andric Info.ImportName = Import.Field;
718e8d8bef9SDimitry Andric } else {
719e8d8bef9SDimitry Andric Info.Name = Import.Field;
720e8d8bef9SDimitry Andric }
721e8d8bef9SDimitry Andric TableType = &Import.Table;
7220b57cec5SDimitry Andric Info.ImportModule = Import.Module;
7230b57cec5SDimitry Andric }
7240b57cec5SDimitry Andric break;
7250b57cec5SDimitry Andric
7260b57cec5SDimitry Andric case wasm::WASM_SYMBOL_TYPE_DATA:
7270b57cec5SDimitry Andric Info.Name = readString(Ctx);
7280b57cec5SDimitry Andric if (IsDefined) {
7295ffd83dbSDimitry Andric auto Index = readVaruint32(Ctx);
7305ffd83dbSDimitry Andric auto Offset = readVaruint64(Ctx);
7315ffd83dbSDimitry Andric auto Size = readVaruint64(Ctx);
732c9157d92SDimitry Andric if (!(Info.Flags & wasm::WASM_SYMBOL_ABSOLUTE)) {
733c9157d92SDimitry Andric if (static_cast<size_t>(Index) >= DataSegments.size())
734c9157d92SDimitry Andric return make_error<GenericBinaryError>(
735c9157d92SDimitry Andric "invalid data segment index: " + Twine(Index),
736c9157d92SDimitry Andric object_error::parse_failed);
737fe6060f1SDimitry Andric size_t SegmentSize = DataSegments[Index].Data.Content.size();
738fe6060f1SDimitry Andric if (Offset > SegmentSize)
739fe6060f1SDimitry Andric return make_error<GenericBinaryError>(
740c9157d92SDimitry Andric "invalid data symbol offset: `" + Info.Name +
741c9157d92SDimitry Andric "` (offset: " + Twine(Offset) +
742c9157d92SDimitry Andric " segment size: " + Twine(SegmentSize) + ")",
7430b57cec5SDimitry Andric object_error::parse_failed);
744c9157d92SDimitry Andric }
7450b57cec5SDimitry Andric Info.DataRef = wasm::WasmDataReference{Index, Offset, Size};
7460b57cec5SDimitry Andric }
7470b57cec5SDimitry Andric break;
7480b57cec5SDimitry Andric
7490b57cec5SDimitry Andric case wasm::WASM_SYMBOL_TYPE_SECTION: {
7500b57cec5SDimitry Andric if ((Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) !=
7510b57cec5SDimitry Andric wasm::WASM_SYMBOL_BINDING_LOCAL)
7520b57cec5SDimitry Andric return make_error<GenericBinaryError>(
753e8d8bef9SDimitry Andric "section symbols must have local binding",
7540b57cec5SDimitry Andric object_error::parse_failed);
7550b57cec5SDimitry Andric Info.ElementIndex = readVaruint32(Ctx);
7560b57cec5SDimitry Andric // Use somewhat unique section name as symbol name.
7570b57cec5SDimitry Andric StringRef SectionName = Sections[Info.ElementIndex].Name;
7580b57cec5SDimitry Andric Info.Name = SectionName;
7590b57cec5SDimitry Andric break;
7600b57cec5SDimitry Andric }
7610b57cec5SDimitry Andric
762fe6060f1SDimitry Andric case wasm::WASM_SYMBOL_TYPE_TAG: {
7630b57cec5SDimitry Andric Info.ElementIndex = readVaruint32(Ctx);
764fe6060f1SDimitry Andric if (!isValidTagIndex(Info.ElementIndex) ||
765fe6060f1SDimitry Andric IsDefined != isDefinedTagIndex(Info.ElementIndex))
766fe6060f1SDimitry Andric return make_error<GenericBinaryError>("invalid tag symbol index",
7670b57cec5SDimitry Andric object_error::parse_failed);
7680b57cec5SDimitry Andric if (!IsDefined && (Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) ==
7690b57cec5SDimitry Andric wasm::WASM_SYMBOL_BINDING_WEAK)
7700b57cec5SDimitry Andric return make_error<GenericBinaryError>("undefined weak global symbol",
7710b57cec5SDimitry Andric object_error::parse_failed);
7720b57cec5SDimitry Andric if (IsDefined) {
7730b57cec5SDimitry Andric Info.Name = readString(Ctx);
774fe6060f1SDimitry Andric unsigned TagIndex = Info.ElementIndex - NumImportedTags;
775fe6060f1SDimitry Andric wasm::WasmTag &Tag = Tags[TagIndex];
776349cc55cSDimitry Andric Signature = &Signatures[Tag.SigIndex];
777fe6060f1SDimitry Andric if (Tag.SymbolName.empty())
778fe6060f1SDimitry Andric Tag.SymbolName = Info.Name;
7790b57cec5SDimitry Andric
7800b57cec5SDimitry Andric } else {
781fe6060f1SDimitry Andric wasm::WasmImport &Import = *ImportedTags[Info.ElementIndex];
7825ffd83dbSDimitry Andric if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0) {
7830b57cec5SDimitry Andric Info.Name = readString(Ctx);
7845ffd83dbSDimitry Andric Info.ImportName = Import.Field;
7855ffd83dbSDimitry Andric } else {
7860b57cec5SDimitry Andric Info.Name = Import.Field;
7875ffd83dbSDimitry Andric }
788349cc55cSDimitry Andric Signature = &Signatures[Import.SigIndex];
7890b57cec5SDimitry Andric Info.ImportModule = Import.Module;
7900b57cec5SDimitry Andric }
7910b57cec5SDimitry Andric break;
7920b57cec5SDimitry Andric }
7930b57cec5SDimitry Andric
7940b57cec5SDimitry Andric default:
795e8d8bef9SDimitry Andric return make_error<GenericBinaryError>("invalid symbol type: " +
796e8d8bef9SDimitry Andric Twine(unsigned(Info.Kind)),
7970b57cec5SDimitry Andric object_error::parse_failed);
7980b57cec5SDimitry Andric }
7990b57cec5SDimitry Andric
8000b57cec5SDimitry Andric if ((Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) !=
8010b57cec5SDimitry Andric wasm::WASM_SYMBOL_BINDING_LOCAL &&
8020b57cec5SDimitry Andric !SymbolNames.insert(Info.Name).second)
803e8d8bef9SDimitry Andric return make_error<GenericBinaryError>("duplicate symbol name " +
8040b57cec5SDimitry Andric Twine(Info.Name),
8050b57cec5SDimitry Andric object_error::parse_failed);
8060b57cec5SDimitry Andric LinkingData.SymbolTable.emplace_back(Info);
807e8d8bef9SDimitry Andric Symbols.emplace_back(LinkingData.SymbolTable.back(), GlobalType, TableType,
808349cc55cSDimitry Andric Signature);
8090b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Adding symbol: " << Symbols.back() << "\n");
8100b57cec5SDimitry Andric }
8110b57cec5SDimitry Andric
8120b57cec5SDimitry Andric return Error::success();
8130b57cec5SDimitry Andric }
8140b57cec5SDimitry Andric
parseLinkingSectionComdat(ReadContext & Ctx)8150b57cec5SDimitry Andric Error WasmObjectFile::parseLinkingSectionComdat(ReadContext &Ctx) {
8160b57cec5SDimitry Andric uint32_t ComdatCount = readVaruint32(Ctx);
8170b57cec5SDimitry Andric StringSet<> ComdatSet;
8180b57cec5SDimitry Andric for (unsigned ComdatIndex = 0; ComdatIndex < ComdatCount; ++ComdatIndex) {
8190b57cec5SDimitry Andric StringRef Name = readString(Ctx);
8200b57cec5SDimitry Andric if (Name.empty() || !ComdatSet.insert(Name).second)
821e8d8bef9SDimitry Andric return make_error<GenericBinaryError>("bad/duplicate COMDAT name " +
8220b57cec5SDimitry Andric Twine(Name),
8230b57cec5SDimitry Andric object_error::parse_failed);
8240b57cec5SDimitry Andric LinkingData.Comdats.emplace_back(Name);
8250b57cec5SDimitry Andric uint32_t Flags = readVaruint32(Ctx);
8260b57cec5SDimitry Andric if (Flags != 0)
827e8d8bef9SDimitry Andric return make_error<GenericBinaryError>("unsupported COMDAT flags",
8280b57cec5SDimitry Andric object_error::parse_failed);
8290b57cec5SDimitry Andric
8300b57cec5SDimitry Andric uint32_t EntryCount = readVaruint32(Ctx);
8310b57cec5SDimitry Andric while (EntryCount--) {
8320b57cec5SDimitry Andric unsigned Kind = readVaruint32(Ctx);
8330b57cec5SDimitry Andric unsigned Index = readVaruint32(Ctx);
8340b57cec5SDimitry Andric switch (Kind) {
8350b57cec5SDimitry Andric default:
836e8d8bef9SDimitry Andric return make_error<GenericBinaryError>("invalid COMDAT entry type",
8370b57cec5SDimitry Andric object_error::parse_failed);
8380b57cec5SDimitry Andric case wasm::WASM_COMDAT_DATA:
8390b57cec5SDimitry Andric if (Index >= DataSegments.size())
8400b57cec5SDimitry Andric return make_error<GenericBinaryError>(
8410b57cec5SDimitry Andric "COMDAT data index out of range", object_error::parse_failed);
8420b57cec5SDimitry Andric if (DataSegments[Index].Data.Comdat != UINT32_MAX)
843e8d8bef9SDimitry Andric return make_error<GenericBinaryError>("data segment in two COMDATs",
8440b57cec5SDimitry Andric object_error::parse_failed);
8450b57cec5SDimitry Andric DataSegments[Index].Data.Comdat = ComdatIndex;
8460b57cec5SDimitry Andric break;
8470b57cec5SDimitry Andric case wasm::WASM_COMDAT_FUNCTION:
8480b57cec5SDimitry Andric if (!isDefinedFunctionIndex(Index))
8490b57cec5SDimitry Andric return make_error<GenericBinaryError>(
8500b57cec5SDimitry Andric "COMDAT function index out of range", object_error::parse_failed);
8510b57cec5SDimitry Andric if (getDefinedFunction(Index).Comdat != UINT32_MAX)
852e8d8bef9SDimitry Andric return make_error<GenericBinaryError>("function in two COMDATs",
8530b57cec5SDimitry Andric object_error::parse_failed);
8540b57cec5SDimitry Andric getDefinedFunction(Index).Comdat = ComdatIndex;
8550b57cec5SDimitry Andric break;
856e8d8bef9SDimitry Andric case wasm::WASM_COMDAT_SECTION:
857e8d8bef9SDimitry Andric if (Index >= Sections.size())
858e8d8bef9SDimitry Andric return make_error<GenericBinaryError>(
859e8d8bef9SDimitry Andric "COMDAT section index out of range", object_error::parse_failed);
860e8d8bef9SDimitry Andric if (Sections[Index].Type != wasm::WASM_SEC_CUSTOM)
861e8d8bef9SDimitry Andric return make_error<GenericBinaryError>(
862e8d8bef9SDimitry Andric "non-custom section in a COMDAT", object_error::parse_failed);
863e8d8bef9SDimitry Andric Sections[Index].Comdat = ComdatIndex;
864e8d8bef9SDimitry Andric break;
8650b57cec5SDimitry Andric }
8660b57cec5SDimitry Andric }
8670b57cec5SDimitry Andric }
8680b57cec5SDimitry Andric return Error::success();
8690b57cec5SDimitry Andric }
8700b57cec5SDimitry Andric
parseProducersSection(ReadContext & Ctx)8710b57cec5SDimitry Andric Error WasmObjectFile::parseProducersSection(ReadContext &Ctx) {
8720b57cec5SDimitry Andric llvm::SmallSet<StringRef, 3> FieldsSeen;
8730b57cec5SDimitry Andric uint32_t Fields = readVaruint32(Ctx);
8740b57cec5SDimitry Andric for (size_t I = 0; I < Fields; ++I) {
8750b57cec5SDimitry Andric StringRef FieldName = readString(Ctx);
8760b57cec5SDimitry Andric if (!FieldsSeen.insert(FieldName).second)
8770b57cec5SDimitry Andric return make_error<GenericBinaryError>(
878e8d8bef9SDimitry Andric "producers section does not have unique fields",
8790b57cec5SDimitry Andric object_error::parse_failed);
8800b57cec5SDimitry Andric std::vector<std::pair<std::string, std::string>> *ProducerVec = nullptr;
8810b57cec5SDimitry Andric if (FieldName == "language") {
8820b57cec5SDimitry Andric ProducerVec = &ProducerInfo.Languages;
8830b57cec5SDimitry Andric } else if (FieldName == "processed-by") {
8840b57cec5SDimitry Andric ProducerVec = &ProducerInfo.Tools;
8850b57cec5SDimitry Andric } else if (FieldName == "sdk") {
8860b57cec5SDimitry Andric ProducerVec = &ProducerInfo.SDKs;
8870b57cec5SDimitry Andric } else {
8880b57cec5SDimitry Andric return make_error<GenericBinaryError>(
889e8d8bef9SDimitry Andric "producers section field is not named one of language, processed-by, "
8900b57cec5SDimitry Andric "or sdk",
8910b57cec5SDimitry Andric object_error::parse_failed);
8920b57cec5SDimitry Andric }
8930b57cec5SDimitry Andric uint32_t ValueCount = readVaruint32(Ctx);
8940b57cec5SDimitry Andric llvm::SmallSet<StringRef, 8> ProducersSeen;
8950b57cec5SDimitry Andric for (size_t J = 0; J < ValueCount; ++J) {
8960b57cec5SDimitry Andric StringRef Name = readString(Ctx);
8970b57cec5SDimitry Andric StringRef Version = readString(Ctx);
8980b57cec5SDimitry Andric if (!ProducersSeen.insert(Name).second) {
8990b57cec5SDimitry Andric return make_error<GenericBinaryError>(
900e8d8bef9SDimitry Andric "producers section contains repeated producer",
9010b57cec5SDimitry Andric object_error::parse_failed);
9020b57cec5SDimitry Andric }
9035ffd83dbSDimitry Andric ProducerVec->emplace_back(std::string(Name), std::string(Version));
9040b57cec5SDimitry Andric }
9050b57cec5SDimitry Andric }
9060b57cec5SDimitry Andric if (Ctx.Ptr != Ctx.End)
907e8d8bef9SDimitry Andric return make_error<GenericBinaryError>("producers section ended prematurely",
9080b57cec5SDimitry Andric object_error::parse_failed);
9090b57cec5SDimitry Andric return Error::success();
9100b57cec5SDimitry Andric }
9110b57cec5SDimitry Andric
parseTargetFeaturesSection(ReadContext & Ctx)9120b57cec5SDimitry Andric Error WasmObjectFile::parseTargetFeaturesSection(ReadContext &Ctx) {
9130b57cec5SDimitry Andric llvm::SmallSet<std::string, 8> FeaturesSeen;
9140b57cec5SDimitry Andric uint32_t FeatureCount = readVaruint32(Ctx);
9150b57cec5SDimitry Andric for (size_t I = 0; I < FeatureCount; ++I) {
9160b57cec5SDimitry Andric wasm::WasmFeatureEntry Feature;
9170b57cec5SDimitry Andric Feature.Prefix = readUint8(Ctx);
9180b57cec5SDimitry Andric switch (Feature.Prefix) {
9190b57cec5SDimitry Andric case wasm::WASM_FEATURE_PREFIX_USED:
9200b57cec5SDimitry Andric case wasm::WASM_FEATURE_PREFIX_REQUIRED:
9210b57cec5SDimitry Andric case wasm::WASM_FEATURE_PREFIX_DISALLOWED:
9220b57cec5SDimitry Andric break;
9230b57cec5SDimitry Andric default:
924e8d8bef9SDimitry Andric return make_error<GenericBinaryError>("unknown feature policy prefix",
9250b57cec5SDimitry Andric object_error::parse_failed);
9260b57cec5SDimitry Andric }
9275ffd83dbSDimitry Andric Feature.Name = std::string(readString(Ctx));
9280b57cec5SDimitry Andric if (!FeaturesSeen.insert(Feature.Name).second)
9290b57cec5SDimitry Andric return make_error<GenericBinaryError>(
930e8d8bef9SDimitry Andric "target features section contains repeated feature \"" +
9310b57cec5SDimitry Andric Feature.Name + "\"",
9320b57cec5SDimitry Andric object_error::parse_failed);
9330b57cec5SDimitry Andric TargetFeatures.push_back(Feature);
9340b57cec5SDimitry Andric }
9350b57cec5SDimitry Andric if (Ctx.Ptr != Ctx.End)
9360b57cec5SDimitry Andric return make_error<GenericBinaryError>(
937e8d8bef9SDimitry Andric "target features section ended prematurely",
9380b57cec5SDimitry Andric object_error::parse_failed);
9390b57cec5SDimitry Andric return Error::success();
9400b57cec5SDimitry Andric }
9410b57cec5SDimitry Andric
parseRelocSection(StringRef Name,ReadContext & Ctx)9420b57cec5SDimitry Andric Error WasmObjectFile::parseRelocSection(StringRef Name, ReadContext &Ctx) {
9430b57cec5SDimitry Andric uint32_t SectionIndex = readVaruint32(Ctx);
9440b57cec5SDimitry Andric if (SectionIndex >= Sections.size())
945e8d8bef9SDimitry Andric return make_error<GenericBinaryError>("invalid section index",
9460b57cec5SDimitry Andric object_error::parse_failed);
9470b57cec5SDimitry Andric WasmSection &Section = Sections[SectionIndex];
9480b57cec5SDimitry Andric uint32_t RelocCount = readVaruint32(Ctx);
9490b57cec5SDimitry Andric uint32_t EndOffset = Section.Content.size();
9500b57cec5SDimitry Andric uint32_t PreviousOffset = 0;
9510b57cec5SDimitry Andric while (RelocCount--) {
9520b57cec5SDimitry Andric wasm::WasmRelocation Reloc = {};
953e8d8bef9SDimitry Andric uint32_t type = readVaruint32(Ctx);
954e8d8bef9SDimitry Andric Reloc.Type = type;
9550b57cec5SDimitry Andric Reloc.Offset = readVaruint32(Ctx);
9560b57cec5SDimitry Andric if (Reloc.Offset < PreviousOffset)
957e8d8bef9SDimitry Andric return make_error<GenericBinaryError>("relocations not in offset order",
9580b57cec5SDimitry Andric object_error::parse_failed);
9590b57cec5SDimitry Andric PreviousOffset = Reloc.Offset;
9600b57cec5SDimitry Andric Reloc.Index = readVaruint32(Ctx);
961e8d8bef9SDimitry Andric switch (type) {
9620b57cec5SDimitry Andric case wasm::R_WASM_FUNCTION_INDEX_LEB:
963fe013be4SDimitry Andric case wasm::R_WASM_FUNCTION_INDEX_I32:
9640b57cec5SDimitry Andric case wasm::R_WASM_TABLE_INDEX_SLEB:
965e8d8bef9SDimitry Andric case wasm::R_WASM_TABLE_INDEX_SLEB64:
9660b57cec5SDimitry Andric case wasm::R_WASM_TABLE_INDEX_I32:
967e8d8bef9SDimitry Andric case wasm::R_WASM_TABLE_INDEX_I64:
9680b57cec5SDimitry Andric case wasm::R_WASM_TABLE_INDEX_REL_SLEB:
969fe6060f1SDimitry Andric case wasm::R_WASM_TABLE_INDEX_REL_SLEB64:
9700b57cec5SDimitry Andric if (!isValidFunctionSymbol(Reloc.Index))
971e8d8bef9SDimitry Andric return make_error<GenericBinaryError>(
972e8d8bef9SDimitry Andric "invalid relocation function index", object_error::parse_failed);
973e8d8bef9SDimitry Andric break;
974e8d8bef9SDimitry Andric case wasm::R_WASM_TABLE_NUMBER_LEB:
975e8d8bef9SDimitry Andric if (!isValidTableSymbol(Reloc.Index))
976e8d8bef9SDimitry Andric return make_error<GenericBinaryError>("invalid relocation table index",
9770b57cec5SDimitry Andric object_error::parse_failed);
9780b57cec5SDimitry Andric break;
9790b57cec5SDimitry Andric case wasm::R_WASM_TYPE_INDEX_LEB:
9800b57cec5SDimitry Andric if (Reloc.Index >= Signatures.size())
981e8d8bef9SDimitry Andric return make_error<GenericBinaryError>("invalid relocation type index",
9820b57cec5SDimitry Andric object_error::parse_failed);
9830b57cec5SDimitry Andric break;
9840b57cec5SDimitry Andric case wasm::R_WASM_GLOBAL_INDEX_LEB:
9850b57cec5SDimitry Andric // R_WASM_GLOBAL_INDEX_LEB are can be used against function and data
9868bcb0991SDimitry Andric // symbols to refer to their GOT entries.
9870b57cec5SDimitry Andric if (!isValidGlobalSymbol(Reloc.Index) &&
9880b57cec5SDimitry Andric !isValidDataSymbol(Reloc.Index) &&
9890b57cec5SDimitry Andric !isValidFunctionSymbol(Reloc.Index))
990e8d8bef9SDimitry Andric return make_error<GenericBinaryError>("invalid relocation global index",
9910b57cec5SDimitry Andric object_error::parse_failed);
9920b57cec5SDimitry Andric break;
9935ffd83dbSDimitry Andric case wasm::R_WASM_GLOBAL_INDEX_I32:
9945ffd83dbSDimitry Andric if (!isValidGlobalSymbol(Reloc.Index))
995e8d8bef9SDimitry Andric return make_error<GenericBinaryError>("invalid relocation global index",
9965ffd83dbSDimitry Andric object_error::parse_failed);
9975ffd83dbSDimitry Andric break;
998fe6060f1SDimitry Andric case wasm::R_WASM_TAG_INDEX_LEB:
999fe6060f1SDimitry Andric if (!isValidTagSymbol(Reloc.Index))
1000fe6060f1SDimitry Andric return make_error<GenericBinaryError>("invalid relocation tag index",
10010b57cec5SDimitry Andric object_error::parse_failed);
10020b57cec5SDimitry Andric break;
10030b57cec5SDimitry Andric case wasm::R_WASM_MEMORY_ADDR_LEB:
10040b57cec5SDimitry Andric case wasm::R_WASM_MEMORY_ADDR_SLEB:
10050b57cec5SDimitry Andric case wasm::R_WASM_MEMORY_ADDR_I32:
10060b57cec5SDimitry Andric case wasm::R_WASM_MEMORY_ADDR_REL_SLEB:
1007e8d8bef9SDimitry Andric case wasm::R_WASM_MEMORY_ADDR_TLS_SLEB:
1008fe6060f1SDimitry Andric case wasm::R_WASM_MEMORY_ADDR_LOCREL_I32:
10090b57cec5SDimitry Andric if (!isValidDataSymbol(Reloc.Index))
1010e8d8bef9SDimitry Andric return make_error<GenericBinaryError>("invalid relocation data index",
10110b57cec5SDimitry Andric object_error::parse_failed);
10120b57cec5SDimitry Andric Reloc.Addend = readVarint32(Ctx);
10130b57cec5SDimitry Andric break;
10145ffd83dbSDimitry Andric case wasm::R_WASM_MEMORY_ADDR_LEB64:
10155ffd83dbSDimitry Andric case wasm::R_WASM_MEMORY_ADDR_SLEB64:
10165ffd83dbSDimitry Andric case wasm::R_WASM_MEMORY_ADDR_I64:
10175ffd83dbSDimitry Andric case wasm::R_WASM_MEMORY_ADDR_REL_SLEB64:
1018fe6060f1SDimitry Andric case wasm::R_WASM_MEMORY_ADDR_TLS_SLEB64:
10195ffd83dbSDimitry Andric if (!isValidDataSymbol(Reloc.Index))
1020e8d8bef9SDimitry Andric return make_error<GenericBinaryError>("invalid relocation data index",
10215ffd83dbSDimitry Andric object_error::parse_failed);
10225ffd83dbSDimitry Andric Reloc.Addend = readVarint64(Ctx);
10235ffd83dbSDimitry Andric break;
10240b57cec5SDimitry Andric case wasm::R_WASM_FUNCTION_OFFSET_I32:
10250b57cec5SDimitry Andric if (!isValidFunctionSymbol(Reloc.Index))
1026e8d8bef9SDimitry Andric return make_error<GenericBinaryError>(
1027e8d8bef9SDimitry Andric "invalid relocation function index", object_error::parse_failed);
10280b57cec5SDimitry Andric Reloc.Addend = readVarint32(Ctx);
10290b57cec5SDimitry Andric break;
1030e8d8bef9SDimitry Andric case wasm::R_WASM_FUNCTION_OFFSET_I64:
1031e8d8bef9SDimitry Andric if (!isValidFunctionSymbol(Reloc.Index))
1032e8d8bef9SDimitry Andric return make_error<GenericBinaryError>(
1033e8d8bef9SDimitry Andric "invalid relocation function index", object_error::parse_failed);
1034e8d8bef9SDimitry Andric Reloc.Addend = readVarint64(Ctx);
1035e8d8bef9SDimitry Andric break;
10360b57cec5SDimitry Andric case wasm::R_WASM_SECTION_OFFSET_I32:
10370b57cec5SDimitry Andric if (!isValidSectionSymbol(Reloc.Index))
1038e8d8bef9SDimitry Andric return make_error<GenericBinaryError>(
1039e8d8bef9SDimitry Andric "invalid relocation section index", object_error::parse_failed);
10400b57cec5SDimitry Andric Reloc.Addend = readVarint32(Ctx);
10410b57cec5SDimitry Andric break;
10420b57cec5SDimitry Andric default:
1043e8d8bef9SDimitry Andric return make_error<GenericBinaryError>("invalid relocation type: " +
1044e8d8bef9SDimitry Andric Twine(type),
10450b57cec5SDimitry Andric object_error::parse_failed);
10460b57cec5SDimitry Andric }
10470b57cec5SDimitry Andric
10480b57cec5SDimitry Andric // Relocations must fit inside the section, and must appear in order. They
10490b57cec5SDimitry Andric // also shouldn't overlap a function/element boundary, but we don't bother
10500b57cec5SDimitry Andric // to check that.
10510b57cec5SDimitry Andric uint64_t Size = 5;
10525ffd83dbSDimitry Andric if (Reloc.Type == wasm::R_WASM_MEMORY_ADDR_LEB64 ||
10535ffd83dbSDimitry Andric Reloc.Type == wasm::R_WASM_MEMORY_ADDR_SLEB64 ||
10545ffd83dbSDimitry Andric Reloc.Type == wasm::R_WASM_MEMORY_ADDR_REL_SLEB64)
10555ffd83dbSDimitry Andric Size = 10;
10560b57cec5SDimitry Andric if (Reloc.Type == wasm::R_WASM_TABLE_INDEX_I32 ||
10570b57cec5SDimitry Andric Reloc.Type == wasm::R_WASM_MEMORY_ADDR_I32 ||
1058fe6060f1SDimitry Andric Reloc.Type == wasm::R_WASM_MEMORY_ADDR_LOCREL_I32 ||
10590b57cec5SDimitry Andric Reloc.Type == wasm::R_WASM_SECTION_OFFSET_I32 ||
10605ffd83dbSDimitry Andric Reloc.Type == wasm::R_WASM_FUNCTION_OFFSET_I32 ||
1061fe013be4SDimitry Andric Reloc.Type == wasm::R_WASM_FUNCTION_INDEX_I32 ||
10625ffd83dbSDimitry Andric Reloc.Type == wasm::R_WASM_GLOBAL_INDEX_I32)
10630b57cec5SDimitry Andric Size = 4;
1064e8d8bef9SDimitry Andric if (Reloc.Type == wasm::R_WASM_TABLE_INDEX_I64 ||
1065e8d8bef9SDimitry Andric Reloc.Type == wasm::R_WASM_MEMORY_ADDR_I64 ||
1066e8d8bef9SDimitry Andric Reloc.Type == wasm::R_WASM_FUNCTION_OFFSET_I64)
10675ffd83dbSDimitry Andric Size = 8;
10680b57cec5SDimitry Andric if (Reloc.Offset + Size > EndOffset)
1069e8d8bef9SDimitry Andric return make_error<GenericBinaryError>("invalid relocation offset",
10700b57cec5SDimitry Andric object_error::parse_failed);
10710b57cec5SDimitry Andric
10720b57cec5SDimitry Andric Section.Relocations.push_back(Reloc);
10730b57cec5SDimitry Andric }
10740b57cec5SDimitry Andric if (Ctx.Ptr != Ctx.End)
1075e8d8bef9SDimitry Andric return make_error<GenericBinaryError>("reloc section ended prematurely",
10760b57cec5SDimitry Andric object_error::parse_failed);
10770b57cec5SDimitry Andric return Error::success();
10780b57cec5SDimitry Andric }
10790b57cec5SDimitry Andric
parseCustomSection(WasmSection & Sec,ReadContext & Ctx)10800b57cec5SDimitry Andric Error WasmObjectFile::parseCustomSection(WasmSection &Sec, ReadContext &Ctx) {
10810b57cec5SDimitry Andric if (Sec.Name == "dylink") {
10820b57cec5SDimitry Andric if (Error Err = parseDylinkSection(Ctx))
10830b57cec5SDimitry Andric return Err;
1084349cc55cSDimitry Andric } else if (Sec.Name == "dylink.0") {
1085349cc55cSDimitry Andric if (Error Err = parseDylink0Section(Ctx))
1086349cc55cSDimitry Andric return Err;
10870b57cec5SDimitry Andric } else if (Sec.Name == "name") {
10880b57cec5SDimitry Andric if (Error Err = parseNameSection(Ctx))
10890b57cec5SDimitry Andric return Err;
10900b57cec5SDimitry Andric } else if (Sec.Name == "linking") {
10910b57cec5SDimitry Andric if (Error Err = parseLinkingSection(Ctx))
10920b57cec5SDimitry Andric return Err;
10930b57cec5SDimitry Andric } else if (Sec.Name == "producers") {
10940b57cec5SDimitry Andric if (Error Err = parseProducersSection(Ctx))
10950b57cec5SDimitry Andric return Err;
10960b57cec5SDimitry Andric } else if (Sec.Name == "target_features") {
10970b57cec5SDimitry Andric if (Error Err = parseTargetFeaturesSection(Ctx))
10980b57cec5SDimitry Andric return Err;
1099c9157d92SDimitry Andric } else if (Sec.Name.starts_with("reloc.")) {
11000b57cec5SDimitry Andric if (Error Err = parseRelocSection(Sec.Name, Ctx))
11010b57cec5SDimitry Andric return Err;
11020b57cec5SDimitry Andric }
11030b57cec5SDimitry Andric return Error::success();
11040b57cec5SDimitry Andric }
11050b57cec5SDimitry Andric
parseTypeSection(ReadContext & Ctx)11060b57cec5SDimitry Andric Error WasmObjectFile::parseTypeSection(ReadContext &Ctx) {
11070b57cec5SDimitry Andric uint32_t Count = readVaruint32(Ctx);
11080b57cec5SDimitry Andric Signatures.reserve(Count);
11090b57cec5SDimitry Andric while (Count--) {
11100b57cec5SDimitry Andric wasm::WasmSignature Sig;
11110b57cec5SDimitry Andric uint8_t Form = readUint8(Ctx);
11120b57cec5SDimitry Andric if (Form != wasm::WASM_TYPE_FUNC) {
1113e8d8bef9SDimitry Andric return make_error<GenericBinaryError>("invalid signature type",
11140b57cec5SDimitry Andric object_error::parse_failed);
11150b57cec5SDimitry Andric }
11160b57cec5SDimitry Andric uint32_t ParamCount = readVaruint32(Ctx);
11170b57cec5SDimitry Andric Sig.Params.reserve(ParamCount);
11180b57cec5SDimitry Andric while (ParamCount--) {
11190b57cec5SDimitry Andric uint32_t ParamType = readUint8(Ctx);
11200b57cec5SDimitry Andric Sig.Params.push_back(wasm::ValType(ParamType));
11210b57cec5SDimitry Andric }
11220b57cec5SDimitry Andric uint32_t ReturnCount = readVaruint32(Ctx);
11238bcb0991SDimitry Andric while (ReturnCount--) {
11248bcb0991SDimitry Andric uint32_t ReturnType = readUint8(Ctx);
11258bcb0991SDimitry Andric Sig.Returns.push_back(wasm::ValType(ReturnType));
11260b57cec5SDimitry Andric }
11270b57cec5SDimitry Andric Signatures.push_back(std::move(Sig));
11280b57cec5SDimitry Andric }
11290b57cec5SDimitry Andric if (Ctx.Ptr != Ctx.End)
1130e8d8bef9SDimitry Andric return make_error<GenericBinaryError>("type section ended prematurely",
11310b57cec5SDimitry Andric object_error::parse_failed);
11320b57cec5SDimitry Andric return Error::success();
11330b57cec5SDimitry Andric }
11340b57cec5SDimitry Andric
parseImportSection(ReadContext & Ctx)11350b57cec5SDimitry Andric Error WasmObjectFile::parseImportSection(ReadContext &Ctx) {
11360b57cec5SDimitry Andric uint32_t Count = readVaruint32(Ctx);
1137349cc55cSDimitry Andric uint32_t NumTypes = Signatures.size();
11380b57cec5SDimitry Andric Imports.reserve(Count);
11390b57cec5SDimitry Andric for (uint32_t I = 0; I < Count; I++) {
11400b57cec5SDimitry Andric wasm::WasmImport Im;
11410b57cec5SDimitry Andric Im.Module = readString(Ctx);
11420b57cec5SDimitry Andric Im.Field = readString(Ctx);
11430b57cec5SDimitry Andric Im.Kind = readUint8(Ctx);
11440b57cec5SDimitry Andric switch (Im.Kind) {
11450b57cec5SDimitry Andric case wasm::WASM_EXTERNAL_FUNCTION:
11460b57cec5SDimitry Andric NumImportedFunctions++;
11470b57cec5SDimitry Andric Im.SigIndex = readVaruint32(Ctx);
1148349cc55cSDimitry Andric if (Im.SigIndex >= NumTypes)
1149349cc55cSDimitry Andric return make_error<GenericBinaryError>("invalid function type",
1150349cc55cSDimitry Andric object_error::parse_failed);
11510b57cec5SDimitry Andric break;
11520b57cec5SDimitry Andric case wasm::WASM_EXTERNAL_GLOBAL:
11530b57cec5SDimitry Andric NumImportedGlobals++;
11540b57cec5SDimitry Andric Im.Global.Type = readUint8(Ctx);
11550b57cec5SDimitry Andric Im.Global.Mutable = readVaruint1(Ctx);
11560b57cec5SDimitry Andric break;
11570b57cec5SDimitry Andric case wasm::WASM_EXTERNAL_MEMORY:
11580b57cec5SDimitry Andric Im.Memory = readLimits(Ctx);
1159e8d8bef9SDimitry Andric if (Im.Memory.Flags & wasm::WASM_LIMITS_FLAG_IS_64)
1160e8d8bef9SDimitry Andric HasMemory64 = true;
11610b57cec5SDimitry Andric break;
1162e8d8bef9SDimitry Andric case wasm::WASM_EXTERNAL_TABLE: {
1163e8d8bef9SDimitry Andric Im.Table = readTableType(Ctx);
1164e8d8bef9SDimitry Andric NumImportedTables++;
1165e8d8bef9SDimitry Andric auto ElemType = Im.Table.ElemType;
1166*a58f00eaSDimitry Andric if (ElemType != wasm::ValType::FUNCREF &&
1167*a58f00eaSDimitry Andric ElemType != wasm::ValType::EXTERNREF)
1168e8d8bef9SDimitry Andric return make_error<GenericBinaryError>("invalid table element type",
11690b57cec5SDimitry Andric object_error::parse_failed);
11700b57cec5SDimitry Andric break;
1171e8d8bef9SDimitry Andric }
1172fe6060f1SDimitry Andric case wasm::WASM_EXTERNAL_TAG:
1173fe6060f1SDimitry Andric NumImportedTags++;
1174349cc55cSDimitry Andric if (readUint8(Ctx) != 0) // Reserved 'attribute' field
1175349cc55cSDimitry Andric return make_error<GenericBinaryError>("invalid attribute",
1176349cc55cSDimitry Andric object_error::parse_failed);
1177349cc55cSDimitry Andric Im.SigIndex = readVaruint32(Ctx);
1178349cc55cSDimitry Andric if (Im.SigIndex >= NumTypes)
1179349cc55cSDimitry Andric return make_error<GenericBinaryError>("invalid tag type",
1180349cc55cSDimitry Andric object_error::parse_failed);
11810b57cec5SDimitry Andric break;
11820b57cec5SDimitry Andric default:
1183e8d8bef9SDimitry Andric return make_error<GenericBinaryError>("unexpected import kind",
11840b57cec5SDimitry Andric object_error::parse_failed);
11850b57cec5SDimitry Andric }
11860b57cec5SDimitry Andric Imports.push_back(Im);
11870b57cec5SDimitry Andric }
11880b57cec5SDimitry Andric if (Ctx.Ptr != Ctx.End)
1189e8d8bef9SDimitry Andric return make_error<GenericBinaryError>("import section ended prematurely",
11900b57cec5SDimitry Andric object_error::parse_failed);
11910b57cec5SDimitry Andric return Error::success();
11920b57cec5SDimitry Andric }
11930b57cec5SDimitry Andric
parseFunctionSection(ReadContext & Ctx)11940b57cec5SDimitry Andric Error WasmObjectFile::parseFunctionSection(ReadContext &Ctx) {
11950b57cec5SDimitry Andric uint32_t Count = readVaruint32(Ctx);
1196349cc55cSDimitry Andric Functions.reserve(Count);
11970b57cec5SDimitry Andric uint32_t NumTypes = Signatures.size();
11980b57cec5SDimitry Andric while (Count--) {
11990b57cec5SDimitry Andric uint32_t Type = readVaruint32(Ctx);
12000b57cec5SDimitry Andric if (Type >= NumTypes)
1201e8d8bef9SDimitry Andric return make_error<GenericBinaryError>("invalid function type",
12020b57cec5SDimitry Andric object_error::parse_failed);
1203349cc55cSDimitry Andric wasm::WasmFunction F;
1204349cc55cSDimitry Andric F.SigIndex = Type;
1205349cc55cSDimitry Andric Functions.push_back(F);
12060b57cec5SDimitry Andric }
12070b57cec5SDimitry Andric if (Ctx.Ptr != Ctx.End)
1208e8d8bef9SDimitry Andric return make_error<GenericBinaryError>("function section ended prematurely",
12090b57cec5SDimitry Andric object_error::parse_failed);
12100b57cec5SDimitry Andric return Error::success();
12110b57cec5SDimitry Andric }
12120b57cec5SDimitry Andric
parseTableSection(ReadContext & Ctx)12130b57cec5SDimitry Andric Error WasmObjectFile::parseTableSection(ReadContext &Ctx) {
1214e8d8bef9SDimitry Andric TableSection = Sections.size();
12150b57cec5SDimitry Andric uint32_t Count = readVaruint32(Ctx);
12160b57cec5SDimitry Andric Tables.reserve(Count);
12170b57cec5SDimitry Andric while (Count--) {
1218e8d8bef9SDimitry Andric wasm::WasmTable T;
1219e8d8bef9SDimitry Andric T.Type = readTableType(Ctx);
1220e8d8bef9SDimitry Andric T.Index = NumImportedTables + Tables.size();
1221e8d8bef9SDimitry Andric Tables.push_back(T);
1222e8d8bef9SDimitry Andric auto ElemType = Tables.back().Type.ElemType;
1223*a58f00eaSDimitry Andric if (ElemType != wasm::ValType::FUNCREF &&
1224*a58f00eaSDimitry Andric ElemType != wasm::ValType::EXTERNREF) {
1225e8d8bef9SDimitry Andric return make_error<GenericBinaryError>("invalid table element type",
12260b57cec5SDimitry Andric object_error::parse_failed);
12270b57cec5SDimitry Andric }
12280b57cec5SDimitry Andric }
12290b57cec5SDimitry Andric if (Ctx.Ptr != Ctx.End)
1230e8d8bef9SDimitry Andric return make_error<GenericBinaryError>("table section ended prematurely",
12310b57cec5SDimitry Andric object_error::parse_failed);
12320b57cec5SDimitry Andric return Error::success();
12330b57cec5SDimitry Andric }
12340b57cec5SDimitry Andric
parseMemorySection(ReadContext & Ctx)12350b57cec5SDimitry Andric Error WasmObjectFile::parseMemorySection(ReadContext &Ctx) {
12360b57cec5SDimitry Andric uint32_t Count = readVaruint32(Ctx);
12370b57cec5SDimitry Andric Memories.reserve(Count);
12380b57cec5SDimitry Andric while (Count--) {
1239e8d8bef9SDimitry Andric auto Limits = readLimits(Ctx);
1240e8d8bef9SDimitry Andric if (Limits.Flags & wasm::WASM_LIMITS_FLAG_IS_64)
1241e8d8bef9SDimitry Andric HasMemory64 = true;
1242e8d8bef9SDimitry Andric Memories.push_back(Limits);
12430b57cec5SDimitry Andric }
12440b57cec5SDimitry Andric if (Ctx.Ptr != Ctx.End)
1245e8d8bef9SDimitry Andric return make_error<GenericBinaryError>("memory section ended prematurely",
12460b57cec5SDimitry Andric object_error::parse_failed);
12470b57cec5SDimitry Andric return Error::success();
12480b57cec5SDimitry Andric }
12490b57cec5SDimitry Andric
parseTagSection(ReadContext & Ctx)1250fe6060f1SDimitry Andric Error WasmObjectFile::parseTagSection(ReadContext &Ctx) {
1251fe6060f1SDimitry Andric TagSection = Sections.size();
1252fe6060f1SDimitry Andric uint32_t Count = readVaruint32(Ctx);
1253fe6060f1SDimitry Andric Tags.reserve(Count);
1254349cc55cSDimitry Andric uint32_t NumTypes = Signatures.size();
12555ffd83dbSDimitry Andric while (Count--) {
1256349cc55cSDimitry Andric if (readUint8(Ctx) != 0) // Reserved 'attribute' field
1257349cc55cSDimitry Andric return make_error<GenericBinaryError>("invalid attribute",
1258349cc55cSDimitry Andric object_error::parse_failed);
1259349cc55cSDimitry Andric uint32_t Type = readVaruint32(Ctx);
1260349cc55cSDimitry Andric if (Type >= NumTypes)
1261349cc55cSDimitry Andric return make_error<GenericBinaryError>("invalid tag type",
1262349cc55cSDimitry Andric object_error::parse_failed);
1263fe6060f1SDimitry Andric wasm::WasmTag Tag;
1264fe6060f1SDimitry Andric Tag.Index = NumImportedTags + Tags.size();
1265349cc55cSDimitry Andric Tag.SigIndex = Type;
1266fe6060f1SDimitry Andric Tags.push_back(Tag);
12675ffd83dbSDimitry Andric }
12685ffd83dbSDimitry Andric
12695ffd83dbSDimitry Andric if (Ctx.Ptr != Ctx.End)
1270fe6060f1SDimitry Andric return make_error<GenericBinaryError>("tag section ended prematurely",
12715ffd83dbSDimitry Andric object_error::parse_failed);
12725ffd83dbSDimitry Andric return Error::success();
12735ffd83dbSDimitry Andric }
12745ffd83dbSDimitry Andric
parseGlobalSection(ReadContext & Ctx)12750b57cec5SDimitry Andric Error WasmObjectFile::parseGlobalSection(ReadContext &Ctx) {
12760b57cec5SDimitry Andric GlobalSection = Sections.size();
12770b57cec5SDimitry Andric uint32_t Count = readVaruint32(Ctx);
12780b57cec5SDimitry Andric Globals.reserve(Count);
12790b57cec5SDimitry Andric while (Count--) {
12800b57cec5SDimitry Andric wasm::WasmGlobal Global;
12810b57cec5SDimitry Andric Global.Index = NumImportedGlobals + Globals.size();
12820b57cec5SDimitry Andric Global.Type.Type = readUint8(Ctx);
12830b57cec5SDimitry Andric Global.Type.Mutable = readVaruint1(Ctx);
12840b57cec5SDimitry Andric if (Error Err = readInitExpr(Global.InitExpr, Ctx))
12850b57cec5SDimitry Andric return Err;
12860b57cec5SDimitry Andric Globals.push_back(Global);
12870b57cec5SDimitry Andric }
12880b57cec5SDimitry Andric if (Ctx.Ptr != Ctx.End)
1289e8d8bef9SDimitry Andric return make_error<GenericBinaryError>("global section ended prematurely",
12900b57cec5SDimitry Andric object_error::parse_failed);
12910b57cec5SDimitry Andric return Error::success();
12920b57cec5SDimitry Andric }
12930b57cec5SDimitry Andric
parseExportSection(ReadContext & Ctx)12940b57cec5SDimitry Andric Error WasmObjectFile::parseExportSection(ReadContext &Ctx) {
12950b57cec5SDimitry Andric uint32_t Count = readVaruint32(Ctx);
12960b57cec5SDimitry Andric Exports.reserve(Count);
1297e710425bSDimitry Andric LinkingData.SymbolTable.reserve(Count);
1298e710425bSDimitry Andric Symbols.reserve(Count);
12990b57cec5SDimitry Andric for (uint32_t I = 0; I < Count; I++) {
13000b57cec5SDimitry Andric wasm::WasmExport Ex;
13010b57cec5SDimitry Andric Ex.Name = readString(Ctx);
13020b57cec5SDimitry Andric Ex.Kind = readUint8(Ctx);
13030b57cec5SDimitry Andric Ex.Index = readVaruint32(Ctx);
1304e710425bSDimitry Andric const wasm::WasmSignature *Signature = nullptr;
1305e710425bSDimitry Andric const wasm::WasmGlobalType *GlobalType = nullptr;
1306e710425bSDimitry Andric const wasm::WasmTableType *TableType = nullptr;
1307e710425bSDimitry Andric wasm::WasmSymbolInfo Info;
1308e710425bSDimitry Andric Info.Name = Ex.Name;
1309e710425bSDimitry Andric Info.Flags = 0;
13100b57cec5SDimitry Andric switch (Ex.Kind) {
1311e710425bSDimitry Andric case wasm::WASM_EXTERNAL_FUNCTION: {
1312480093f4SDimitry Andric if (!isDefinedFunctionIndex(Ex.Index))
1313e8d8bef9SDimitry Andric return make_error<GenericBinaryError>("invalid function export",
13140b57cec5SDimitry Andric object_error::parse_failed);
1315480093f4SDimitry Andric getDefinedFunction(Ex.Index).ExportName = Ex.Name;
1316e710425bSDimitry Andric Info.Kind = wasm::WASM_SYMBOL_TYPE_FUNCTION;
1317e710425bSDimitry Andric Info.ElementIndex = Ex.Index;
1318e710425bSDimitry Andric unsigned FuncIndex = Info.ElementIndex - NumImportedFunctions;
1319e710425bSDimitry Andric wasm::WasmFunction &Function = Functions[FuncIndex];
1320e710425bSDimitry Andric Signature = &Signatures[Function.SigIndex];
13210b57cec5SDimitry Andric break;
1322e710425bSDimitry Andric }
1323e710425bSDimitry Andric case wasm::WASM_EXTERNAL_GLOBAL: {
13240b57cec5SDimitry Andric if (!isValidGlobalIndex(Ex.Index))
1325e8d8bef9SDimitry Andric return make_error<GenericBinaryError>("invalid global export",
13260b57cec5SDimitry Andric object_error::parse_failed);
1327e710425bSDimitry Andric Info.Kind = wasm::WASM_SYMBOL_TYPE_DATA;
1328e710425bSDimitry Andric uint64_t Offset = 0;
1329e710425bSDimitry Andric if (isDefinedGlobalIndex(Ex.Index)) {
1330e710425bSDimitry Andric auto Global = getDefinedGlobal(Ex.Index);
1331e710425bSDimitry Andric if (!Global.InitExpr.Extended) {
1332e710425bSDimitry Andric auto Inst = Global.InitExpr.Inst;
1333e710425bSDimitry Andric if (Inst.Opcode == wasm::WASM_OPCODE_I32_CONST) {
1334e710425bSDimitry Andric Offset = Inst.Value.Int32;
1335e710425bSDimitry Andric } else if (Inst.Opcode == wasm::WASM_OPCODE_I64_CONST) {
1336e710425bSDimitry Andric Offset = Inst.Value.Int64;
1337e710425bSDimitry Andric }
1338e710425bSDimitry Andric }
1339e710425bSDimitry Andric }
1340e710425bSDimitry Andric Info.DataRef = wasm::WasmDataReference{0, Offset, 0};
13410b57cec5SDimitry Andric break;
1342e710425bSDimitry Andric }
1343fe6060f1SDimitry Andric case wasm::WASM_EXTERNAL_TAG:
1344fe6060f1SDimitry Andric if (!isValidTagIndex(Ex.Index))
1345fe6060f1SDimitry Andric return make_error<GenericBinaryError>("invalid tag export",
13460b57cec5SDimitry Andric object_error::parse_failed);
1347e710425bSDimitry Andric Info.Kind = wasm::WASM_SYMBOL_TYPE_TAG;
1348e710425bSDimitry Andric Info.ElementIndex = Ex.Index;
13490b57cec5SDimitry Andric break;
13500b57cec5SDimitry Andric case wasm::WASM_EXTERNAL_MEMORY:
1351e710425bSDimitry Andric break;
13520b57cec5SDimitry Andric case wasm::WASM_EXTERNAL_TABLE:
1353e710425bSDimitry Andric Info.Kind = wasm::WASM_SYMBOL_TYPE_TABLE;
1354cdc20ff6SDimitry Andric Info.ElementIndex = Ex.Index;
13550b57cec5SDimitry Andric break;
13560b57cec5SDimitry Andric default:
1357e8d8bef9SDimitry Andric return make_error<GenericBinaryError>("unexpected export kind",
13580b57cec5SDimitry Andric object_error::parse_failed);
13590b57cec5SDimitry Andric }
13600b57cec5SDimitry Andric Exports.push_back(Ex);
1361e710425bSDimitry Andric if (Ex.Kind != wasm::WASM_EXTERNAL_MEMORY) {
1362e710425bSDimitry Andric LinkingData.SymbolTable.emplace_back(Info);
1363e710425bSDimitry Andric Symbols.emplace_back(LinkingData.SymbolTable.back(), GlobalType,
1364e710425bSDimitry Andric TableType, Signature);
1365e710425bSDimitry Andric LLVM_DEBUG(dbgs() << "Adding symbol: " << Symbols.back() << "\n");
1366e710425bSDimitry Andric }
13670b57cec5SDimitry Andric }
13680b57cec5SDimitry Andric if (Ctx.Ptr != Ctx.End)
1369e8d8bef9SDimitry Andric return make_error<GenericBinaryError>("export section ended prematurely",
13700b57cec5SDimitry Andric object_error::parse_failed);
13710b57cec5SDimitry Andric return Error::success();
13720b57cec5SDimitry Andric }
13730b57cec5SDimitry Andric
isValidFunctionIndex(uint32_t Index) const13740b57cec5SDimitry Andric bool WasmObjectFile::isValidFunctionIndex(uint32_t Index) const {
1375349cc55cSDimitry Andric return Index < NumImportedFunctions + Functions.size();
13760b57cec5SDimitry Andric }
13770b57cec5SDimitry Andric
isDefinedFunctionIndex(uint32_t Index) const13780b57cec5SDimitry Andric bool WasmObjectFile::isDefinedFunctionIndex(uint32_t Index) const {
13790b57cec5SDimitry Andric return Index >= NumImportedFunctions && isValidFunctionIndex(Index);
13800b57cec5SDimitry Andric }
13810b57cec5SDimitry Andric
isValidGlobalIndex(uint32_t Index) const13820b57cec5SDimitry Andric bool WasmObjectFile::isValidGlobalIndex(uint32_t Index) const {
13830b57cec5SDimitry Andric return Index < NumImportedGlobals + Globals.size();
13840b57cec5SDimitry Andric }
13850b57cec5SDimitry Andric
isValidTableNumber(uint32_t Index) const1386fe6060f1SDimitry Andric bool WasmObjectFile::isValidTableNumber(uint32_t Index) const {
1387e8d8bef9SDimitry Andric return Index < NumImportedTables + Tables.size();
1388e8d8bef9SDimitry Andric }
1389e8d8bef9SDimitry Andric
isDefinedGlobalIndex(uint32_t Index) const13900b57cec5SDimitry Andric bool WasmObjectFile::isDefinedGlobalIndex(uint32_t Index) const {
13910b57cec5SDimitry Andric return Index >= NumImportedGlobals && isValidGlobalIndex(Index);
13920b57cec5SDimitry Andric }
13930b57cec5SDimitry Andric
isDefinedTableNumber(uint32_t Index) const1394fe6060f1SDimitry Andric bool WasmObjectFile::isDefinedTableNumber(uint32_t Index) const {
1395fe6060f1SDimitry Andric return Index >= NumImportedTables && isValidTableNumber(Index);
1396e8d8bef9SDimitry Andric }
1397e8d8bef9SDimitry Andric
isValidTagIndex(uint32_t Index) const1398fe6060f1SDimitry Andric bool WasmObjectFile::isValidTagIndex(uint32_t Index) const {
1399fe6060f1SDimitry Andric return Index < NumImportedTags + Tags.size();
14000b57cec5SDimitry Andric }
14010b57cec5SDimitry Andric
isDefinedTagIndex(uint32_t Index) const1402fe6060f1SDimitry Andric bool WasmObjectFile::isDefinedTagIndex(uint32_t Index) const {
1403fe6060f1SDimitry Andric return Index >= NumImportedTags && isValidTagIndex(Index);
14040b57cec5SDimitry Andric }
14050b57cec5SDimitry Andric
isValidFunctionSymbol(uint32_t Index) const14060b57cec5SDimitry Andric bool WasmObjectFile::isValidFunctionSymbol(uint32_t Index) const {
14070b57cec5SDimitry Andric return Index < Symbols.size() && Symbols[Index].isTypeFunction();
14080b57cec5SDimitry Andric }
14090b57cec5SDimitry Andric
isValidTableSymbol(uint32_t Index) const1410e8d8bef9SDimitry Andric bool WasmObjectFile::isValidTableSymbol(uint32_t Index) const {
1411e8d8bef9SDimitry Andric return Index < Symbols.size() && Symbols[Index].isTypeTable();
1412e8d8bef9SDimitry Andric }
1413e8d8bef9SDimitry Andric
isValidGlobalSymbol(uint32_t Index) const14140b57cec5SDimitry Andric bool WasmObjectFile::isValidGlobalSymbol(uint32_t Index) const {
14150b57cec5SDimitry Andric return Index < Symbols.size() && Symbols[Index].isTypeGlobal();
14160b57cec5SDimitry Andric }
14170b57cec5SDimitry Andric
isValidTagSymbol(uint32_t Index) const1418fe6060f1SDimitry Andric bool WasmObjectFile::isValidTagSymbol(uint32_t Index) const {
1419fe6060f1SDimitry Andric return Index < Symbols.size() && Symbols[Index].isTypeTag();
14200b57cec5SDimitry Andric }
14210b57cec5SDimitry Andric
isValidDataSymbol(uint32_t Index) const14220b57cec5SDimitry Andric bool WasmObjectFile::isValidDataSymbol(uint32_t Index) const {
14230b57cec5SDimitry Andric return Index < Symbols.size() && Symbols[Index].isTypeData();
14240b57cec5SDimitry Andric }
14250b57cec5SDimitry Andric
isValidSectionSymbol(uint32_t Index) const14260b57cec5SDimitry Andric bool WasmObjectFile::isValidSectionSymbol(uint32_t Index) const {
14270b57cec5SDimitry Andric return Index < Symbols.size() && Symbols[Index].isTypeSection();
14280b57cec5SDimitry Andric }
14290b57cec5SDimitry Andric
getDefinedFunction(uint32_t Index)14300b57cec5SDimitry Andric wasm::WasmFunction &WasmObjectFile::getDefinedFunction(uint32_t Index) {
14310b57cec5SDimitry Andric assert(isDefinedFunctionIndex(Index));
14320b57cec5SDimitry Andric return Functions[Index - NumImportedFunctions];
14330b57cec5SDimitry Andric }
14340b57cec5SDimitry Andric
14350b57cec5SDimitry Andric const wasm::WasmFunction &
getDefinedFunction(uint32_t Index) const14360b57cec5SDimitry Andric WasmObjectFile::getDefinedFunction(uint32_t Index) const {
14370b57cec5SDimitry Andric assert(isDefinedFunctionIndex(Index));
14380b57cec5SDimitry Andric return Functions[Index - NumImportedFunctions];
14390b57cec5SDimitry Andric }
14400b57cec5SDimitry Andric
getDefinedGlobal(uint32_t Index)14410b57cec5SDimitry Andric wasm::WasmGlobal &WasmObjectFile::getDefinedGlobal(uint32_t Index) {
14420b57cec5SDimitry Andric assert(isDefinedGlobalIndex(Index));
14430b57cec5SDimitry Andric return Globals[Index - NumImportedGlobals];
14440b57cec5SDimitry Andric }
14450b57cec5SDimitry Andric
getDefinedTag(uint32_t Index)1446fe6060f1SDimitry Andric wasm::WasmTag &WasmObjectFile::getDefinedTag(uint32_t Index) {
1447fe6060f1SDimitry Andric assert(isDefinedTagIndex(Index));
1448fe6060f1SDimitry Andric return Tags[Index - NumImportedTags];
14490b57cec5SDimitry Andric }
14500b57cec5SDimitry Andric
parseStartSection(ReadContext & Ctx)14510b57cec5SDimitry Andric Error WasmObjectFile::parseStartSection(ReadContext &Ctx) {
14520b57cec5SDimitry Andric StartFunction = readVaruint32(Ctx);
14530b57cec5SDimitry Andric if (!isValidFunctionIndex(StartFunction))
1454e8d8bef9SDimitry Andric return make_error<GenericBinaryError>("invalid start function",
14550b57cec5SDimitry Andric object_error::parse_failed);
14560b57cec5SDimitry Andric return Error::success();
14570b57cec5SDimitry Andric }
14580b57cec5SDimitry Andric
parseCodeSection(ReadContext & Ctx)14590b57cec5SDimitry Andric Error WasmObjectFile::parseCodeSection(ReadContext &Ctx) {
14600b57cec5SDimitry Andric CodeSection = Sections.size();
14610b57cec5SDimitry Andric uint32_t FunctionCount = readVaruint32(Ctx);
1462349cc55cSDimitry Andric if (FunctionCount != Functions.size()) {
1463e8d8bef9SDimitry Andric return make_error<GenericBinaryError>("invalid function count",
14640b57cec5SDimitry Andric object_error::parse_failed);
14650b57cec5SDimitry Andric }
14660b57cec5SDimitry Andric
1467480093f4SDimitry Andric for (uint32_t i = 0; i < FunctionCount; i++) {
1468480093f4SDimitry Andric wasm::WasmFunction& Function = Functions[i];
14690b57cec5SDimitry Andric const uint8_t *FunctionStart = Ctx.Ptr;
14700b57cec5SDimitry Andric uint32_t Size = readVaruint32(Ctx);
14710b57cec5SDimitry Andric const uint8_t *FunctionEnd = Ctx.Ptr + Size;
14720b57cec5SDimitry Andric
14730b57cec5SDimitry Andric Function.CodeOffset = Ctx.Ptr - FunctionStart;
1474480093f4SDimitry Andric Function.Index = NumImportedFunctions + i;
14750b57cec5SDimitry Andric Function.CodeSectionOffset = FunctionStart - Ctx.Start;
14760b57cec5SDimitry Andric Function.Size = FunctionEnd - FunctionStart;
14770b57cec5SDimitry Andric
14780b57cec5SDimitry Andric uint32_t NumLocalDecls = readVaruint32(Ctx);
14790b57cec5SDimitry Andric Function.Locals.reserve(NumLocalDecls);
14800b57cec5SDimitry Andric while (NumLocalDecls--) {
14810b57cec5SDimitry Andric wasm::WasmLocalDecl Decl;
14820b57cec5SDimitry Andric Decl.Count = readVaruint32(Ctx);
14830b57cec5SDimitry Andric Decl.Type = readUint8(Ctx);
14840b57cec5SDimitry Andric Function.Locals.push_back(Decl);
14850b57cec5SDimitry Andric }
14860b57cec5SDimitry Andric
14870b57cec5SDimitry Andric uint32_t BodySize = FunctionEnd - Ctx.Ptr;
1488de8261c4SDimitry Andric // Ensure that Function is within Ctx's buffer.
1489de8261c4SDimitry Andric if (Ctx.Ptr + BodySize > Ctx.End) {
1490de8261c4SDimitry Andric return make_error<GenericBinaryError>("Function extends beyond buffer",
1491de8261c4SDimitry Andric object_error::parse_failed);
1492de8261c4SDimitry Andric }
14930b57cec5SDimitry Andric Function.Body = ArrayRef<uint8_t>(Ctx.Ptr, BodySize);
14940b57cec5SDimitry Andric // This will be set later when reading in the linking metadata section.
14950b57cec5SDimitry Andric Function.Comdat = UINT32_MAX;
14960b57cec5SDimitry Andric Ctx.Ptr += BodySize;
14970b57cec5SDimitry Andric assert(Ctx.Ptr == FunctionEnd);
14980b57cec5SDimitry Andric }
14990b57cec5SDimitry Andric if (Ctx.Ptr != Ctx.End)
1500e8d8bef9SDimitry Andric return make_error<GenericBinaryError>("code section ended prematurely",
15010b57cec5SDimitry Andric object_error::parse_failed);
15020b57cec5SDimitry Andric return Error::success();
15030b57cec5SDimitry Andric }
15040b57cec5SDimitry Andric
parseElemSection(ReadContext & Ctx)15050b57cec5SDimitry Andric Error WasmObjectFile::parseElemSection(ReadContext &Ctx) {
15060b57cec5SDimitry Andric uint32_t Count = readVaruint32(Ctx);
15070b57cec5SDimitry Andric ElemSegments.reserve(Count);
15080b57cec5SDimitry Andric while (Count--) {
15090b57cec5SDimitry Andric wasm::WasmElemSegment Segment;
1510fe6060f1SDimitry Andric Segment.Flags = readVaruint32(Ctx);
1511fe6060f1SDimitry Andric
1512fe6060f1SDimitry Andric uint32_t SupportedFlags = wasm::WASM_ELEM_SEGMENT_HAS_TABLE_NUMBER |
1513fe6060f1SDimitry Andric wasm::WASM_ELEM_SEGMENT_IS_PASSIVE |
1514fe6060f1SDimitry Andric wasm::WASM_ELEM_SEGMENT_HAS_INIT_EXPRS;
1515fe6060f1SDimitry Andric if (Segment.Flags & ~SupportedFlags)
1516fe6060f1SDimitry Andric return make_error<GenericBinaryError>(
1517fe6060f1SDimitry Andric "Unsupported flags for element segment", object_error::parse_failed);
1518fe6060f1SDimitry Andric
1519fe6060f1SDimitry Andric if (Segment.Flags & wasm::WASM_ELEM_SEGMENT_HAS_TABLE_NUMBER)
1520fe6060f1SDimitry Andric Segment.TableNumber = readVaruint32(Ctx);
1521fe6060f1SDimitry Andric else
1522fe6060f1SDimitry Andric Segment.TableNumber = 0;
1523fe6060f1SDimitry Andric if (!isValidTableNumber(Segment.TableNumber))
1524fe6060f1SDimitry Andric return make_error<GenericBinaryError>("invalid TableNumber",
15250b57cec5SDimitry Andric object_error::parse_failed);
1526fe6060f1SDimitry Andric
1527fe6060f1SDimitry Andric if (Segment.Flags & wasm::WASM_ELEM_SEGMENT_IS_PASSIVE) {
152881ad6265SDimitry Andric Segment.Offset.Extended = false;
152981ad6265SDimitry Andric Segment.Offset.Inst.Opcode = wasm::WASM_OPCODE_I32_CONST;
153081ad6265SDimitry Andric Segment.Offset.Inst.Value.Int32 = 0;
1531fe6060f1SDimitry Andric } else {
15320b57cec5SDimitry Andric if (Error Err = readInitExpr(Segment.Offset, Ctx))
15330b57cec5SDimitry Andric return Err;
1534fe6060f1SDimitry Andric }
1535fe6060f1SDimitry Andric
1536fe6060f1SDimitry Andric if (Segment.Flags & wasm::WASM_ELEM_SEGMENT_MASK_HAS_ELEM_KIND) {
1537*a58f00eaSDimitry Andric auto ElemKind = readVaruint32(Ctx);
1538fe6060f1SDimitry Andric if (Segment.Flags & wasm::WASM_ELEM_SEGMENT_HAS_INIT_EXPRS) {
1539*a58f00eaSDimitry Andric Segment.ElemKind = wasm::ValType(ElemKind);
1540*a58f00eaSDimitry Andric if (Segment.ElemKind != wasm::ValType::FUNCREF &&
1541*a58f00eaSDimitry Andric Segment.ElemKind != wasm::ValType::EXTERNREF) {
1542fe6060f1SDimitry Andric return make_error<GenericBinaryError>("invalid reference type",
1543fe6060f1SDimitry Andric object_error::parse_failed);
1544fe6060f1SDimitry Andric }
1545fe6060f1SDimitry Andric } else {
1546*a58f00eaSDimitry Andric if (ElemKind != 0)
1547fe6060f1SDimitry Andric return make_error<GenericBinaryError>("invalid elemtype",
1548fe6060f1SDimitry Andric object_error::parse_failed);
1549*a58f00eaSDimitry Andric Segment.ElemKind = wasm::ValType::FUNCREF;
1550fe6060f1SDimitry Andric }
1551fe6060f1SDimitry Andric } else {
1552*a58f00eaSDimitry Andric Segment.ElemKind = wasm::ValType::FUNCREF;
1553fe6060f1SDimitry Andric }
1554fe6060f1SDimitry Andric
1555fe6060f1SDimitry Andric if (Segment.Flags & wasm::WASM_ELEM_SEGMENT_HAS_INIT_EXPRS)
1556fe6060f1SDimitry Andric return make_error<GenericBinaryError>(
1557fe6060f1SDimitry Andric "elem segment init expressions not yet implemented",
1558fe6060f1SDimitry Andric object_error::parse_failed);
1559fe6060f1SDimitry Andric
15600b57cec5SDimitry Andric uint32_t NumElems = readVaruint32(Ctx);
15610b57cec5SDimitry Andric while (NumElems--) {
15620b57cec5SDimitry Andric Segment.Functions.push_back(readVaruint32(Ctx));
15630b57cec5SDimitry Andric }
15640b57cec5SDimitry Andric ElemSegments.push_back(Segment);
15650b57cec5SDimitry Andric }
15660b57cec5SDimitry Andric if (Ctx.Ptr != Ctx.End)
1567e8d8bef9SDimitry Andric return make_error<GenericBinaryError>("elem section ended prematurely",
15680b57cec5SDimitry Andric object_error::parse_failed);
15690b57cec5SDimitry Andric return Error::success();
15700b57cec5SDimitry Andric }
15710b57cec5SDimitry Andric
parseDataSection(ReadContext & Ctx)15720b57cec5SDimitry Andric Error WasmObjectFile::parseDataSection(ReadContext &Ctx) {
15730b57cec5SDimitry Andric DataSection = Sections.size();
15740b57cec5SDimitry Andric uint32_t Count = readVaruint32(Ctx);
157581ad6265SDimitry Andric if (DataCount && Count != *DataCount)
15760b57cec5SDimitry Andric return make_error<GenericBinaryError>(
1577e8d8bef9SDimitry Andric "number of data segments does not match DataCount section");
15780b57cec5SDimitry Andric DataSegments.reserve(Count);
15790b57cec5SDimitry Andric while (Count--) {
15800b57cec5SDimitry Andric WasmSegment Segment;
15810b57cec5SDimitry Andric Segment.Data.InitFlags = readVaruint32(Ctx);
1582e8d8bef9SDimitry Andric Segment.Data.MemoryIndex =
1583e8d8bef9SDimitry Andric (Segment.Data.InitFlags & wasm::WASM_DATA_SEGMENT_HAS_MEMINDEX)
1584e8d8bef9SDimitry Andric ? readVaruint32(Ctx)
1585e8d8bef9SDimitry Andric : 0;
1586e8d8bef9SDimitry Andric if ((Segment.Data.InitFlags & wasm::WASM_DATA_SEGMENT_IS_PASSIVE) == 0) {
15870b57cec5SDimitry Andric if (Error Err = readInitExpr(Segment.Data.Offset, Ctx))
15880b57cec5SDimitry Andric return Err;
15890b57cec5SDimitry Andric } else {
159081ad6265SDimitry Andric Segment.Data.Offset.Extended = false;
159181ad6265SDimitry Andric Segment.Data.Offset.Inst.Opcode = wasm::WASM_OPCODE_I32_CONST;
159281ad6265SDimitry Andric Segment.Data.Offset.Inst.Value.Int32 = 0;
15930b57cec5SDimitry Andric }
15940b57cec5SDimitry Andric uint32_t Size = readVaruint32(Ctx);
15950b57cec5SDimitry Andric if (Size > (size_t)(Ctx.End - Ctx.Ptr))
1596e8d8bef9SDimitry Andric return make_error<GenericBinaryError>("invalid segment size",
15970b57cec5SDimitry Andric object_error::parse_failed);
15980b57cec5SDimitry Andric Segment.Data.Content = ArrayRef<uint8_t>(Ctx.Ptr, Size);
15990b57cec5SDimitry Andric // The rest of these Data fields are set later, when reading in the linking
16000b57cec5SDimitry Andric // metadata section.
16010b57cec5SDimitry Andric Segment.Data.Alignment = 0;
1602fe6060f1SDimitry Andric Segment.Data.LinkingFlags = 0;
16030b57cec5SDimitry Andric Segment.Data.Comdat = UINT32_MAX;
16040b57cec5SDimitry Andric Segment.SectionOffset = Ctx.Ptr - Ctx.Start;
16050b57cec5SDimitry Andric Ctx.Ptr += Size;
16060b57cec5SDimitry Andric DataSegments.push_back(Segment);
16070b57cec5SDimitry Andric }
16080b57cec5SDimitry Andric if (Ctx.Ptr != Ctx.End)
1609e8d8bef9SDimitry Andric return make_error<GenericBinaryError>("data section ended prematurely",
16100b57cec5SDimitry Andric object_error::parse_failed);
16110b57cec5SDimitry Andric return Error::success();
16120b57cec5SDimitry Andric }
16130b57cec5SDimitry Andric
parseDataCountSection(ReadContext & Ctx)16140b57cec5SDimitry Andric Error WasmObjectFile::parseDataCountSection(ReadContext &Ctx) {
16150b57cec5SDimitry Andric DataCount = readVaruint32(Ctx);
16160b57cec5SDimitry Andric return Error::success();
16170b57cec5SDimitry Andric }
16180b57cec5SDimitry Andric
getHeader() const16190b57cec5SDimitry Andric const wasm::WasmObjectHeader &WasmObjectFile::getHeader() const {
16200b57cec5SDimitry Andric return Header;
16210b57cec5SDimitry Andric }
16220b57cec5SDimitry Andric
moveSymbolNext(DataRefImpl & Symb) const16230b57cec5SDimitry Andric void WasmObjectFile::moveSymbolNext(DataRefImpl &Symb) const { Symb.d.b++; }
16240b57cec5SDimitry Andric
getSymbolFlags(DataRefImpl Symb) const16255ffd83dbSDimitry Andric Expected<uint32_t> WasmObjectFile::getSymbolFlags(DataRefImpl Symb) const {
16260b57cec5SDimitry Andric uint32_t Result = SymbolRef::SF_None;
16270b57cec5SDimitry Andric const WasmSymbol &Sym = getWasmSymbol(Symb);
16280b57cec5SDimitry Andric
16290b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "getSymbolFlags: ptr=" << &Sym << " " << Sym << "\n");
16300b57cec5SDimitry Andric if (Sym.isBindingWeak())
16310b57cec5SDimitry Andric Result |= SymbolRef::SF_Weak;
16320b57cec5SDimitry Andric if (!Sym.isBindingLocal())
16330b57cec5SDimitry Andric Result |= SymbolRef::SF_Global;
16340b57cec5SDimitry Andric if (Sym.isHidden())
16350b57cec5SDimitry Andric Result |= SymbolRef::SF_Hidden;
16360b57cec5SDimitry Andric if (!Sym.isDefined())
16370b57cec5SDimitry Andric Result |= SymbolRef::SF_Undefined;
16380b57cec5SDimitry Andric if (Sym.isTypeFunction())
16390b57cec5SDimitry Andric Result |= SymbolRef::SF_Executable;
16400b57cec5SDimitry Andric return Result;
16410b57cec5SDimitry Andric }
16420b57cec5SDimitry Andric
symbol_begin() const16430b57cec5SDimitry Andric basic_symbol_iterator WasmObjectFile::symbol_begin() const {
16440b57cec5SDimitry Andric DataRefImpl Ref;
16450b57cec5SDimitry Andric Ref.d.a = 1; // Arbitrary non-zero value so that Ref.p is non-null
16460b57cec5SDimitry Andric Ref.d.b = 0; // Symbol index
16470b57cec5SDimitry Andric return BasicSymbolRef(Ref, this);
16480b57cec5SDimitry Andric }
16490b57cec5SDimitry Andric
symbol_end() const16500b57cec5SDimitry Andric basic_symbol_iterator WasmObjectFile::symbol_end() const {
16510b57cec5SDimitry Andric DataRefImpl Ref;
16520b57cec5SDimitry Andric Ref.d.a = 1; // Arbitrary non-zero value so that Ref.p is non-null
16530b57cec5SDimitry Andric Ref.d.b = Symbols.size(); // Symbol index
16540b57cec5SDimitry Andric return BasicSymbolRef(Ref, this);
16550b57cec5SDimitry Andric }
16560b57cec5SDimitry Andric
getWasmSymbol(const DataRefImpl & Symb) const16570b57cec5SDimitry Andric const WasmSymbol &WasmObjectFile::getWasmSymbol(const DataRefImpl &Symb) const {
16580b57cec5SDimitry Andric return Symbols[Symb.d.b];
16590b57cec5SDimitry Andric }
16600b57cec5SDimitry Andric
getWasmSymbol(const SymbolRef & Symb) const16610b57cec5SDimitry Andric const WasmSymbol &WasmObjectFile::getWasmSymbol(const SymbolRef &Symb) const {
16620b57cec5SDimitry Andric return getWasmSymbol(Symb.getRawDataRefImpl());
16630b57cec5SDimitry Andric }
16640b57cec5SDimitry Andric
getSymbolName(DataRefImpl Symb) const16650b57cec5SDimitry Andric Expected<StringRef> WasmObjectFile::getSymbolName(DataRefImpl Symb) const {
16660b57cec5SDimitry Andric return getWasmSymbol(Symb).Info.Name;
16670b57cec5SDimitry Andric }
16680b57cec5SDimitry Andric
getSymbolAddress(DataRefImpl Symb) const16690b57cec5SDimitry Andric Expected<uint64_t> WasmObjectFile::getSymbolAddress(DataRefImpl Symb) const {
16700b57cec5SDimitry Andric auto &Sym = getWasmSymbol(Symb);
16710b57cec5SDimitry Andric if (Sym.Info.Kind == wasm::WASM_SYMBOL_TYPE_FUNCTION &&
1672de8261c4SDimitry Andric isDefinedFunctionIndex(Sym.Info.ElementIndex)) {
1673de8261c4SDimitry Andric // For object files, use the section offset. The linker relies on this.
1674de8261c4SDimitry Andric // For linked files, use the file offset. This behavior matches the way
1675de8261c4SDimitry Andric // browsers print stack traces and is useful for binary size analysis.
1676de8261c4SDimitry Andric // (see https://webassembly.github.io/spec/web-api/index.html#conventions)
1677de8261c4SDimitry Andric uint32_t Adjustment = isRelocatableObject() || isSharedObject()
1678de8261c4SDimitry Andric ? 0
1679de8261c4SDimitry Andric : Sections[CodeSection].Offset;
1680de8261c4SDimitry Andric return getDefinedFunction(Sym.Info.ElementIndex).CodeSectionOffset +
1681de8261c4SDimitry Andric Adjustment;
1682de8261c4SDimitry Andric }
16830b57cec5SDimitry Andric return getSymbolValue(Symb);
16840b57cec5SDimitry Andric }
16850b57cec5SDimitry Andric
getWasmSymbolValue(const WasmSymbol & Sym) const16860b57cec5SDimitry Andric uint64_t WasmObjectFile::getWasmSymbolValue(const WasmSymbol &Sym) const {
16870b57cec5SDimitry Andric switch (Sym.Info.Kind) {
16880b57cec5SDimitry Andric case wasm::WASM_SYMBOL_TYPE_FUNCTION:
16890b57cec5SDimitry Andric case wasm::WASM_SYMBOL_TYPE_GLOBAL:
1690fe6060f1SDimitry Andric case wasm::WASM_SYMBOL_TYPE_TAG:
1691e8d8bef9SDimitry Andric case wasm::WASM_SYMBOL_TYPE_TABLE:
16920b57cec5SDimitry Andric return Sym.Info.ElementIndex;
16930b57cec5SDimitry Andric case wasm::WASM_SYMBOL_TYPE_DATA: {
16940b57cec5SDimitry Andric // The value of a data symbol is the segment offset, plus the symbol
16950b57cec5SDimitry Andric // offset within the segment.
16960b57cec5SDimitry Andric uint32_t SegmentIndex = Sym.Info.DataRef.Segment;
16970b57cec5SDimitry Andric const wasm::WasmDataSegment &Segment = DataSegments[SegmentIndex].Data;
169881ad6265SDimitry Andric if (Segment.Offset.Extended) {
169981ad6265SDimitry Andric llvm_unreachable("extended init exprs not supported");
170081ad6265SDimitry Andric } else if (Segment.Offset.Inst.Opcode == wasm::WASM_OPCODE_I32_CONST) {
170181ad6265SDimitry Andric return Segment.Offset.Inst.Value.Int32 + Sym.Info.DataRef.Offset;
170281ad6265SDimitry Andric } else if (Segment.Offset.Inst.Opcode == wasm::WASM_OPCODE_I64_CONST) {
170381ad6265SDimitry Andric return Segment.Offset.Inst.Value.Int64 + Sym.Info.DataRef.Offset;
1704e710425bSDimitry Andric } else if (Segment.Offset.Inst.Opcode == wasm::WASM_OPCODE_GLOBAL_GET) {
1705e710425bSDimitry Andric return Sym.Info.DataRef.Offset;
17065ffd83dbSDimitry Andric } else {
17075ffd83dbSDimitry Andric llvm_unreachable("unknown init expr opcode");
17085ffd83dbSDimitry Andric }
17090b57cec5SDimitry Andric }
17100b57cec5SDimitry Andric case wasm::WASM_SYMBOL_TYPE_SECTION:
17110b57cec5SDimitry Andric return 0;
17120b57cec5SDimitry Andric }
17130b57cec5SDimitry Andric llvm_unreachable("invalid symbol type");
17140b57cec5SDimitry Andric }
17150b57cec5SDimitry Andric
getSymbolValueImpl(DataRefImpl Symb) const17160b57cec5SDimitry Andric uint64_t WasmObjectFile::getSymbolValueImpl(DataRefImpl Symb) const {
17170b57cec5SDimitry Andric return getWasmSymbolValue(getWasmSymbol(Symb));
17180b57cec5SDimitry Andric }
17190b57cec5SDimitry Andric
getSymbolAlignment(DataRefImpl Symb) const17200b57cec5SDimitry Andric uint32_t WasmObjectFile::getSymbolAlignment(DataRefImpl Symb) const {
17210b57cec5SDimitry Andric llvm_unreachable("not yet implemented");
17220b57cec5SDimitry Andric return 0;
17230b57cec5SDimitry Andric }
17240b57cec5SDimitry Andric
getCommonSymbolSizeImpl(DataRefImpl Symb) const17250b57cec5SDimitry Andric uint64_t WasmObjectFile::getCommonSymbolSizeImpl(DataRefImpl Symb) const {
17260b57cec5SDimitry Andric llvm_unreachable("not yet implemented");
17270b57cec5SDimitry Andric return 0;
17280b57cec5SDimitry Andric }
17290b57cec5SDimitry Andric
17300b57cec5SDimitry Andric Expected<SymbolRef::Type>
getSymbolType(DataRefImpl Symb) const17310b57cec5SDimitry Andric WasmObjectFile::getSymbolType(DataRefImpl Symb) const {
17320b57cec5SDimitry Andric const WasmSymbol &Sym = getWasmSymbol(Symb);
17330b57cec5SDimitry Andric
17340b57cec5SDimitry Andric switch (Sym.Info.Kind) {
17350b57cec5SDimitry Andric case wasm::WASM_SYMBOL_TYPE_FUNCTION:
17360b57cec5SDimitry Andric return SymbolRef::ST_Function;
17370b57cec5SDimitry Andric case wasm::WASM_SYMBOL_TYPE_GLOBAL:
17380b57cec5SDimitry Andric return SymbolRef::ST_Other;
17390b57cec5SDimitry Andric case wasm::WASM_SYMBOL_TYPE_DATA:
17400b57cec5SDimitry Andric return SymbolRef::ST_Data;
17410b57cec5SDimitry Andric case wasm::WASM_SYMBOL_TYPE_SECTION:
17420b57cec5SDimitry Andric return SymbolRef::ST_Debug;
1743fe6060f1SDimitry Andric case wasm::WASM_SYMBOL_TYPE_TAG:
17440b57cec5SDimitry Andric return SymbolRef::ST_Other;
1745e8d8bef9SDimitry Andric case wasm::WASM_SYMBOL_TYPE_TABLE:
1746e8d8bef9SDimitry Andric return SymbolRef::ST_Other;
17470b57cec5SDimitry Andric }
17480b57cec5SDimitry Andric
1749e8d8bef9SDimitry Andric llvm_unreachable("unknown WasmSymbol::SymbolType");
17500b57cec5SDimitry Andric return SymbolRef::ST_Other;
17510b57cec5SDimitry Andric }
17520b57cec5SDimitry Andric
17530b57cec5SDimitry Andric Expected<section_iterator>
getSymbolSection(DataRefImpl Symb) const17540b57cec5SDimitry Andric WasmObjectFile::getSymbolSection(DataRefImpl Symb) const {
17550b57cec5SDimitry Andric const WasmSymbol &Sym = getWasmSymbol(Symb);
17560b57cec5SDimitry Andric if (Sym.isUndefined())
17570b57cec5SDimitry Andric return section_end();
17580b57cec5SDimitry Andric
17590b57cec5SDimitry Andric DataRefImpl Ref;
17605ffd83dbSDimitry Andric Ref.d.a = getSymbolSectionIdImpl(Sym);
17615ffd83dbSDimitry Andric return section_iterator(SectionRef(Ref, this));
17625ffd83dbSDimitry Andric }
17635ffd83dbSDimitry Andric
getSymbolSectionId(SymbolRef Symb) const17645ffd83dbSDimitry Andric uint32_t WasmObjectFile::getSymbolSectionId(SymbolRef Symb) const {
17655ffd83dbSDimitry Andric const WasmSymbol &Sym = getWasmSymbol(Symb);
17665ffd83dbSDimitry Andric return getSymbolSectionIdImpl(Sym);
17675ffd83dbSDimitry Andric }
17685ffd83dbSDimitry Andric
getSymbolSectionIdImpl(const WasmSymbol & Sym) const17695ffd83dbSDimitry Andric uint32_t WasmObjectFile::getSymbolSectionIdImpl(const WasmSymbol &Sym) const {
17700b57cec5SDimitry Andric switch (Sym.Info.Kind) {
17710b57cec5SDimitry Andric case wasm::WASM_SYMBOL_TYPE_FUNCTION:
17725ffd83dbSDimitry Andric return CodeSection;
17730b57cec5SDimitry Andric case wasm::WASM_SYMBOL_TYPE_GLOBAL:
17745ffd83dbSDimitry Andric return GlobalSection;
17750b57cec5SDimitry Andric case wasm::WASM_SYMBOL_TYPE_DATA:
17765ffd83dbSDimitry Andric return DataSection;
17770b57cec5SDimitry Andric case wasm::WASM_SYMBOL_TYPE_SECTION:
17785ffd83dbSDimitry Andric return Sym.Info.ElementIndex;
1779fe6060f1SDimitry Andric case wasm::WASM_SYMBOL_TYPE_TAG:
1780fe6060f1SDimitry Andric return TagSection;
1781e8d8bef9SDimitry Andric case wasm::WASM_SYMBOL_TYPE_TABLE:
1782e8d8bef9SDimitry Andric return TableSection;
17830b57cec5SDimitry Andric default:
1784e8d8bef9SDimitry Andric llvm_unreachable("unknown WasmSymbol::SymbolType");
17850b57cec5SDimitry Andric }
17860b57cec5SDimitry Andric }
17870b57cec5SDimitry Andric
moveSectionNext(DataRefImpl & Sec) const17880b57cec5SDimitry Andric void WasmObjectFile::moveSectionNext(DataRefImpl &Sec) const { Sec.d.a++; }
17890b57cec5SDimitry Andric
getSectionName(DataRefImpl Sec) const17900b57cec5SDimitry Andric Expected<StringRef> WasmObjectFile::getSectionName(DataRefImpl Sec) const {
17910b57cec5SDimitry Andric const WasmSection &S = Sections[Sec.d.a];
179281ad6265SDimitry Andric if (S.Type == wasm::WASM_SEC_CUSTOM)
17930b57cec5SDimitry Andric return S.Name;
179481ad6265SDimitry Andric if (S.Type > wasm::WASM_SEC_LAST_KNOWN)
17950b57cec5SDimitry Andric return createStringError(object_error::invalid_section_index, "");
179681ad6265SDimitry Andric return wasm::sectionTypeToString(S.Type);
17970b57cec5SDimitry Andric }
17980b57cec5SDimitry Andric
getSectionAddress(DataRefImpl Sec) const17990b57cec5SDimitry Andric uint64_t WasmObjectFile::getSectionAddress(DataRefImpl Sec) const { return 0; }
18000b57cec5SDimitry Andric
getSectionIndex(DataRefImpl Sec) const18010b57cec5SDimitry Andric uint64_t WasmObjectFile::getSectionIndex(DataRefImpl Sec) const {
18020b57cec5SDimitry Andric return Sec.d.a;
18030b57cec5SDimitry Andric }
18040b57cec5SDimitry Andric
getSectionSize(DataRefImpl Sec) const18050b57cec5SDimitry Andric uint64_t WasmObjectFile::getSectionSize(DataRefImpl Sec) const {
18060b57cec5SDimitry Andric const WasmSection &S = Sections[Sec.d.a];
18070b57cec5SDimitry Andric return S.Content.size();
18080b57cec5SDimitry Andric }
18090b57cec5SDimitry Andric
18100b57cec5SDimitry Andric Expected<ArrayRef<uint8_t>>
getSectionContents(DataRefImpl Sec) const18110b57cec5SDimitry Andric WasmObjectFile::getSectionContents(DataRefImpl Sec) const {
18120b57cec5SDimitry Andric const WasmSection &S = Sections[Sec.d.a];
18130b57cec5SDimitry Andric // This will never fail since wasm sections can never be empty (user-sections
18140b57cec5SDimitry Andric // must have a name and non-user sections each have a defined structure).
18150b57cec5SDimitry Andric return S.Content;
18160b57cec5SDimitry Andric }
18170b57cec5SDimitry Andric
getSectionAlignment(DataRefImpl Sec) const18180b57cec5SDimitry Andric uint64_t WasmObjectFile::getSectionAlignment(DataRefImpl Sec) const {
18190b57cec5SDimitry Andric return 1;
18200b57cec5SDimitry Andric }
18210b57cec5SDimitry Andric
isSectionCompressed(DataRefImpl Sec) const18220b57cec5SDimitry Andric bool WasmObjectFile::isSectionCompressed(DataRefImpl Sec) const {
18230b57cec5SDimitry Andric return false;
18240b57cec5SDimitry Andric }
18250b57cec5SDimitry Andric
isSectionText(DataRefImpl Sec) const18260b57cec5SDimitry Andric bool WasmObjectFile::isSectionText(DataRefImpl Sec) const {
18270b57cec5SDimitry Andric return getWasmSection(Sec).Type == wasm::WASM_SEC_CODE;
18280b57cec5SDimitry Andric }
18290b57cec5SDimitry Andric
isSectionData(DataRefImpl Sec) const18300b57cec5SDimitry Andric bool WasmObjectFile::isSectionData(DataRefImpl Sec) const {
18310b57cec5SDimitry Andric return getWasmSection(Sec).Type == wasm::WASM_SEC_DATA;
18320b57cec5SDimitry Andric }
18330b57cec5SDimitry Andric
isSectionBSS(DataRefImpl Sec) const18340b57cec5SDimitry Andric bool WasmObjectFile::isSectionBSS(DataRefImpl Sec) const { return false; }
18350b57cec5SDimitry Andric
isSectionVirtual(DataRefImpl Sec) const18360b57cec5SDimitry Andric bool WasmObjectFile::isSectionVirtual(DataRefImpl Sec) const { return false; }
18370b57cec5SDimitry Andric
section_rel_begin(DataRefImpl Ref) const18380b57cec5SDimitry Andric relocation_iterator WasmObjectFile::section_rel_begin(DataRefImpl Ref) const {
18390b57cec5SDimitry Andric DataRefImpl RelocRef;
18400b57cec5SDimitry Andric RelocRef.d.a = Ref.d.a;
18410b57cec5SDimitry Andric RelocRef.d.b = 0;
18420b57cec5SDimitry Andric return relocation_iterator(RelocationRef(RelocRef, this));
18430b57cec5SDimitry Andric }
18440b57cec5SDimitry Andric
section_rel_end(DataRefImpl Ref) const18450b57cec5SDimitry Andric relocation_iterator WasmObjectFile::section_rel_end(DataRefImpl Ref) const {
18460b57cec5SDimitry Andric const WasmSection &Sec = getWasmSection(Ref);
18470b57cec5SDimitry Andric DataRefImpl RelocRef;
18480b57cec5SDimitry Andric RelocRef.d.a = Ref.d.a;
18490b57cec5SDimitry Andric RelocRef.d.b = Sec.Relocations.size();
18500b57cec5SDimitry Andric return relocation_iterator(RelocationRef(RelocRef, this));
18510b57cec5SDimitry Andric }
18520b57cec5SDimitry Andric
moveRelocationNext(DataRefImpl & Rel) const18530b57cec5SDimitry Andric void WasmObjectFile::moveRelocationNext(DataRefImpl &Rel) const { Rel.d.b++; }
18540b57cec5SDimitry Andric
getRelocationOffset(DataRefImpl Ref) const18550b57cec5SDimitry Andric uint64_t WasmObjectFile::getRelocationOffset(DataRefImpl Ref) const {
18560b57cec5SDimitry Andric const wasm::WasmRelocation &Rel = getWasmRelocation(Ref);
18570b57cec5SDimitry Andric return Rel.Offset;
18580b57cec5SDimitry Andric }
18590b57cec5SDimitry Andric
getRelocationSymbol(DataRefImpl Ref) const18600b57cec5SDimitry Andric symbol_iterator WasmObjectFile::getRelocationSymbol(DataRefImpl Ref) const {
18610b57cec5SDimitry Andric const wasm::WasmRelocation &Rel = getWasmRelocation(Ref);
18620b57cec5SDimitry Andric if (Rel.Type == wasm::R_WASM_TYPE_INDEX_LEB)
18630b57cec5SDimitry Andric return symbol_end();
18640b57cec5SDimitry Andric DataRefImpl Sym;
18650b57cec5SDimitry Andric Sym.d.a = 1;
18660b57cec5SDimitry Andric Sym.d.b = Rel.Index;
18670b57cec5SDimitry Andric return symbol_iterator(SymbolRef(Sym, this));
18680b57cec5SDimitry Andric }
18690b57cec5SDimitry Andric
getRelocationType(DataRefImpl Ref) const18700b57cec5SDimitry Andric uint64_t WasmObjectFile::getRelocationType(DataRefImpl Ref) const {
18710b57cec5SDimitry Andric const wasm::WasmRelocation &Rel = getWasmRelocation(Ref);
18720b57cec5SDimitry Andric return Rel.Type;
18730b57cec5SDimitry Andric }
18740b57cec5SDimitry Andric
getRelocationTypeName(DataRefImpl Ref,SmallVectorImpl<char> & Result) const18750b57cec5SDimitry Andric void WasmObjectFile::getRelocationTypeName(
18760b57cec5SDimitry Andric DataRefImpl Ref, SmallVectorImpl<char> &Result) const {
18770b57cec5SDimitry Andric const wasm::WasmRelocation &Rel = getWasmRelocation(Ref);
18780b57cec5SDimitry Andric StringRef Res = "Unknown";
18790b57cec5SDimitry Andric
18800b57cec5SDimitry Andric #define WASM_RELOC(name, value) \
18810b57cec5SDimitry Andric case wasm::name: \
18820b57cec5SDimitry Andric Res = #name; \
18830b57cec5SDimitry Andric break;
18840b57cec5SDimitry Andric
18850b57cec5SDimitry Andric switch (Rel.Type) {
18860b57cec5SDimitry Andric #include "llvm/BinaryFormat/WasmRelocs.def"
18870b57cec5SDimitry Andric }
18880b57cec5SDimitry Andric
18890b57cec5SDimitry Andric #undef WASM_RELOC
18900b57cec5SDimitry Andric
18910b57cec5SDimitry Andric Result.append(Res.begin(), Res.end());
18920b57cec5SDimitry Andric }
18930b57cec5SDimitry Andric
section_begin() const18940b57cec5SDimitry Andric section_iterator WasmObjectFile::section_begin() const {
18950b57cec5SDimitry Andric DataRefImpl Ref;
18960b57cec5SDimitry Andric Ref.d.a = 0;
18970b57cec5SDimitry Andric return section_iterator(SectionRef(Ref, this));
18980b57cec5SDimitry Andric }
18990b57cec5SDimitry Andric
section_end() const19000b57cec5SDimitry Andric section_iterator WasmObjectFile::section_end() const {
19010b57cec5SDimitry Andric DataRefImpl Ref;
19020b57cec5SDimitry Andric Ref.d.a = Sections.size();
19030b57cec5SDimitry Andric return section_iterator(SectionRef(Ref, this));
19040b57cec5SDimitry Andric }
19050b57cec5SDimitry Andric
getBytesInAddress() const1906e8d8bef9SDimitry Andric uint8_t WasmObjectFile::getBytesInAddress() const {
1907e8d8bef9SDimitry Andric return HasMemory64 ? 8 : 4;
1908e8d8bef9SDimitry Andric }
19090b57cec5SDimitry Andric
getFileFormatName() const19100b57cec5SDimitry Andric StringRef WasmObjectFile::getFileFormatName() const { return "WASM"; }
19110b57cec5SDimitry Andric
getArch() const1912e8d8bef9SDimitry Andric Triple::ArchType WasmObjectFile::getArch() const {
1913e8d8bef9SDimitry Andric return HasMemory64 ? Triple::wasm64 : Triple::wasm32;
1914e8d8bef9SDimitry Andric }
19150b57cec5SDimitry Andric
getFeatures() const1916bdd1243dSDimitry Andric Expected<SubtargetFeatures> WasmObjectFile::getFeatures() const {
19170b57cec5SDimitry Andric return SubtargetFeatures();
19180b57cec5SDimitry Andric }
19190b57cec5SDimitry Andric
isRelocatableObject() const19200b57cec5SDimitry Andric bool WasmObjectFile::isRelocatableObject() const { return HasLinkingSection; }
19210b57cec5SDimitry Andric
isSharedObject() const19220b57cec5SDimitry Andric bool WasmObjectFile::isSharedObject() const { return HasDylinkSection; }
19230b57cec5SDimitry Andric
getWasmSection(DataRefImpl Ref) const19240b57cec5SDimitry Andric const WasmSection &WasmObjectFile::getWasmSection(DataRefImpl Ref) const {
19250b57cec5SDimitry Andric assert(Ref.d.a < Sections.size());
19260b57cec5SDimitry Andric return Sections[Ref.d.a];
19270b57cec5SDimitry Andric }
19280b57cec5SDimitry Andric
19290b57cec5SDimitry Andric const WasmSection &
getWasmSection(const SectionRef & Section) const19300b57cec5SDimitry Andric WasmObjectFile::getWasmSection(const SectionRef &Section) const {
19310b57cec5SDimitry Andric return getWasmSection(Section.getRawDataRefImpl());
19320b57cec5SDimitry Andric }
19330b57cec5SDimitry Andric
19340b57cec5SDimitry Andric const wasm::WasmRelocation &
getWasmRelocation(const RelocationRef & Ref) const19350b57cec5SDimitry Andric WasmObjectFile::getWasmRelocation(const RelocationRef &Ref) const {
19360b57cec5SDimitry Andric return getWasmRelocation(Ref.getRawDataRefImpl());
19370b57cec5SDimitry Andric }
19380b57cec5SDimitry Andric
19390b57cec5SDimitry Andric const wasm::WasmRelocation &
getWasmRelocation(DataRefImpl Ref) const19400b57cec5SDimitry Andric WasmObjectFile::getWasmRelocation(DataRefImpl Ref) const {
19410b57cec5SDimitry Andric assert(Ref.d.a < Sections.size());
19420b57cec5SDimitry Andric const WasmSection &Sec = Sections[Ref.d.a];
19430b57cec5SDimitry Andric assert(Ref.d.b < Sec.Relocations.size());
19440b57cec5SDimitry Andric return Sec.Relocations[Ref.d.b];
19450b57cec5SDimitry Andric }
19460b57cec5SDimitry Andric
getSectionOrder(unsigned ID,StringRef CustomSectionName)19470b57cec5SDimitry Andric int WasmSectionOrderChecker::getSectionOrder(unsigned ID,
19480b57cec5SDimitry Andric StringRef CustomSectionName) {
19490b57cec5SDimitry Andric switch (ID) {
19500b57cec5SDimitry Andric case wasm::WASM_SEC_CUSTOM:
19510b57cec5SDimitry Andric return StringSwitch<unsigned>(CustomSectionName)
19520b57cec5SDimitry Andric .Case("dylink", WASM_SEC_ORDER_DYLINK)
1953349cc55cSDimitry Andric .Case("dylink.0", WASM_SEC_ORDER_DYLINK)
19540b57cec5SDimitry Andric .Case("linking", WASM_SEC_ORDER_LINKING)
19550b57cec5SDimitry Andric .StartsWith("reloc.", WASM_SEC_ORDER_RELOC)
19560b57cec5SDimitry Andric .Case("name", WASM_SEC_ORDER_NAME)
19570b57cec5SDimitry Andric .Case("producers", WASM_SEC_ORDER_PRODUCERS)
19580b57cec5SDimitry Andric .Case("target_features", WASM_SEC_ORDER_TARGET_FEATURES)
19590b57cec5SDimitry Andric .Default(WASM_SEC_ORDER_NONE);
19600b57cec5SDimitry Andric case wasm::WASM_SEC_TYPE:
19610b57cec5SDimitry Andric return WASM_SEC_ORDER_TYPE;
19620b57cec5SDimitry Andric case wasm::WASM_SEC_IMPORT:
19630b57cec5SDimitry Andric return WASM_SEC_ORDER_IMPORT;
19640b57cec5SDimitry Andric case wasm::WASM_SEC_FUNCTION:
19650b57cec5SDimitry Andric return WASM_SEC_ORDER_FUNCTION;
19660b57cec5SDimitry Andric case wasm::WASM_SEC_TABLE:
19670b57cec5SDimitry Andric return WASM_SEC_ORDER_TABLE;
19680b57cec5SDimitry Andric case wasm::WASM_SEC_MEMORY:
19690b57cec5SDimitry Andric return WASM_SEC_ORDER_MEMORY;
19700b57cec5SDimitry Andric case wasm::WASM_SEC_GLOBAL:
19710b57cec5SDimitry Andric return WASM_SEC_ORDER_GLOBAL;
19720b57cec5SDimitry Andric case wasm::WASM_SEC_EXPORT:
19730b57cec5SDimitry Andric return WASM_SEC_ORDER_EXPORT;
19740b57cec5SDimitry Andric case wasm::WASM_SEC_START:
19750b57cec5SDimitry Andric return WASM_SEC_ORDER_START;
19760b57cec5SDimitry Andric case wasm::WASM_SEC_ELEM:
19770b57cec5SDimitry Andric return WASM_SEC_ORDER_ELEM;
19780b57cec5SDimitry Andric case wasm::WASM_SEC_CODE:
19790b57cec5SDimitry Andric return WASM_SEC_ORDER_CODE;
19800b57cec5SDimitry Andric case wasm::WASM_SEC_DATA:
19810b57cec5SDimitry Andric return WASM_SEC_ORDER_DATA;
19820b57cec5SDimitry Andric case wasm::WASM_SEC_DATACOUNT:
19830b57cec5SDimitry Andric return WASM_SEC_ORDER_DATACOUNT;
1984fe6060f1SDimitry Andric case wasm::WASM_SEC_TAG:
1985fe6060f1SDimitry Andric return WASM_SEC_ORDER_TAG;
19860b57cec5SDimitry Andric default:
19870b57cec5SDimitry Andric return WASM_SEC_ORDER_NONE;
19880b57cec5SDimitry Andric }
19890b57cec5SDimitry Andric }
19900b57cec5SDimitry Andric
19910b57cec5SDimitry Andric // Represents the edges in a directed graph where any node B reachable from node
19920b57cec5SDimitry Andric // A is not allowed to appear before A in the section ordering, but may appear
19930b57cec5SDimitry Andric // afterward.
19945ffd83dbSDimitry Andric int WasmSectionOrderChecker::DisallowedPredecessors
19955ffd83dbSDimitry Andric [WASM_NUM_SEC_ORDERS][WASM_NUM_SEC_ORDERS] = {
19965ffd83dbSDimitry Andric // WASM_SEC_ORDER_NONE
19975ffd83dbSDimitry Andric {},
19985ffd83dbSDimitry Andric // WASM_SEC_ORDER_TYPE
19995ffd83dbSDimitry Andric {WASM_SEC_ORDER_TYPE, WASM_SEC_ORDER_IMPORT},
20005ffd83dbSDimitry Andric // WASM_SEC_ORDER_IMPORT
20015ffd83dbSDimitry Andric {WASM_SEC_ORDER_IMPORT, WASM_SEC_ORDER_FUNCTION},
20025ffd83dbSDimitry Andric // WASM_SEC_ORDER_FUNCTION
20035ffd83dbSDimitry Andric {WASM_SEC_ORDER_FUNCTION, WASM_SEC_ORDER_TABLE},
20045ffd83dbSDimitry Andric // WASM_SEC_ORDER_TABLE
20055ffd83dbSDimitry Andric {WASM_SEC_ORDER_TABLE, WASM_SEC_ORDER_MEMORY},
20065ffd83dbSDimitry Andric // WASM_SEC_ORDER_MEMORY
2007fe6060f1SDimitry Andric {WASM_SEC_ORDER_MEMORY, WASM_SEC_ORDER_TAG},
2008fe6060f1SDimitry Andric // WASM_SEC_ORDER_TAG
2009fe6060f1SDimitry Andric {WASM_SEC_ORDER_TAG, WASM_SEC_ORDER_GLOBAL},
20105ffd83dbSDimitry Andric // WASM_SEC_ORDER_GLOBAL
20115ffd83dbSDimitry Andric {WASM_SEC_ORDER_GLOBAL, WASM_SEC_ORDER_EXPORT},
20125ffd83dbSDimitry Andric // WASM_SEC_ORDER_EXPORT
20135ffd83dbSDimitry Andric {WASM_SEC_ORDER_EXPORT, WASM_SEC_ORDER_START},
20145ffd83dbSDimitry Andric // WASM_SEC_ORDER_START
20155ffd83dbSDimitry Andric {WASM_SEC_ORDER_START, WASM_SEC_ORDER_ELEM},
20165ffd83dbSDimitry Andric // WASM_SEC_ORDER_ELEM
20175ffd83dbSDimitry Andric {WASM_SEC_ORDER_ELEM, WASM_SEC_ORDER_DATACOUNT},
20185ffd83dbSDimitry Andric // WASM_SEC_ORDER_DATACOUNT
20195ffd83dbSDimitry Andric {WASM_SEC_ORDER_DATACOUNT, WASM_SEC_ORDER_CODE},
20205ffd83dbSDimitry Andric // WASM_SEC_ORDER_CODE
20215ffd83dbSDimitry Andric {WASM_SEC_ORDER_CODE, WASM_SEC_ORDER_DATA},
20225ffd83dbSDimitry Andric // WASM_SEC_ORDER_DATA
20235ffd83dbSDimitry Andric {WASM_SEC_ORDER_DATA, WASM_SEC_ORDER_LINKING},
20240b57cec5SDimitry Andric
20250b57cec5SDimitry Andric // Custom Sections
20265ffd83dbSDimitry Andric // WASM_SEC_ORDER_DYLINK
20275ffd83dbSDimitry Andric {WASM_SEC_ORDER_DYLINK, WASM_SEC_ORDER_TYPE},
20285ffd83dbSDimitry Andric // WASM_SEC_ORDER_LINKING
20295ffd83dbSDimitry Andric {WASM_SEC_ORDER_LINKING, WASM_SEC_ORDER_RELOC, WASM_SEC_ORDER_NAME},
20305ffd83dbSDimitry Andric // WASM_SEC_ORDER_RELOC (can be repeated)
20315ffd83dbSDimitry Andric {},
20325ffd83dbSDimitry Andric // WASM_SEC_ORDER_NAME
20335ffd83dbSDimitry Andric {WASM_SEC_ORDER_NAME, WASM_SEC_ORDER_PRODUCERS},
20345ffd83dbSDimitry Andric // WASM_SEC_ORDER_PRODUCERS
20355ffd83dbSDimitry Andric {WASM_SEC_ORDER_PRODUCERS, WASM_SEC_ORDER_TARGET_FEATURES},
20365ffd83dbSDimitry Andric // WASM_SEC_ORDER_TARGET_FEATURES
20375ffd83dbSDimitry Andric {WASM_SEC_ORDER_TARGET_FEATURES}};
20380b57cec5SDimitry Andric
isValidSectionOrder(unsigned ID,StringRef CustomSectionName)20390b57cec5SDimitry Andric bool WasmSectionOrderChecker::isValidSectionOrder(unsigned ID,
20400b57cec5SDimitry Andric StringRef CustomSectionName) {
20410b57cec5SDimitry Andric int Order = getSectionOrder(ID, CustomSectionName);
20420b57cec5SDimitry Andric if (Order == WASM_SEC_ORDER_NONE)
20430b57cec5SDimitry Andric return true;
20440b57cec5SDimitry Andric
20450b57cec5SDimitry Andric // Disallowed predecessors we need to check for
20460b57cec5SDimitry Andric SmallVector<int, WASM_NUM_SEC_ORDERS> WorkList;
20470b57cec5SDimitry Andric
20480b57cec5SDimitry Andric // Keep track of completed checks to avoid repeating work
20490b57cec5SDimitry Andric bool Checked[WASM_NUM_SEC_ORDERS] = {};
20500b57cec5SDimitry Andric
20510b57cec5SDimitry Andric int Curr = Order;
20520b57cec5SDimitry Andric while (true) {
20530b57cec5SDimitry Andric // Add new disallowed predecessors to work list
20540b57cec5SDimitry Andric for (size_t I = 0;; ++I) {
20550b57cec5SDimitry Andric int Next = DisallowedPredecessors[Curr][I];
20560b57cec5SDimitry Andric if (Next == WASM_SEC_ORDER_NONE)
20570b57cec5SDimitry Andric break;
20580b57cec5SDimitry Andric if (Checked[Next])
20590b57cec5SDimitry Andric continue;
20600b57cec5SDimitry Andric WorkList.push_back(Next);
20610b57cec5SDimitry Andric Checked[Next] = true;
20620b57cec5SDimitry Andric }
20630b57cec5SDimitry Andric
20640b57cec5SDimitry Andric if (WorkList.empty())
20650b57cec5SDimitry Andric break;
20660b57cec5SDimitry Andric
20670b57cec5SDimitry Andric // Consider next disallowed predecessor
20680b57cec5SDimitry Andric Curr = WorkList.pop_back_val();
20690b57cec5SDimitry Andric if (Seen[Curr])
20700b57cec5SDimitry Andric return false;
20710b57cec5SDimitry Andric }
20720b57cec5SDimitry Andric
20730b57cec5SDimitry Andric // Have not seen any disallowed predecessors
20740b57cec5SDimitry Andric Seen[Order] = true;
20750b57cec5SDimitry Andric return true;
20760b57cec5SDimitry Andric }
2077