17a7e6055SDimitry Andric //===- WasmObjectFile.cpp - Wasm object file implementation ---------------===//
2d88c1a5aSDimitry Andric //
3d88c1a5aSDimitry Andric // The LLVM Compiler Infrastructure
4d88c1a5aSDimitry Andric //
5d88c1a5aSDimitry Andric // This file is distributed under the University of Illinois Open Source
6d88c1a5aSDimitry Andric // License. See LICENSE.TXT for details.
7d88c1a5aSDimitry Andric //
8d88c1a5aSDimitry Andric //===----------------------------------------------------------------------===//
9d88c1a5aSDimitry Andric
107a7e6055SDimitry Andric #include "llvm/ADT/ArrayRef.h"
114ba319b5SDimitry Andric #include "llvm/ADT/DenseSet.h"
127a7e6055SDimitry Andric #include "llvm/ADT/STLExtras.h"
137a7e6055SDimitry Andric #include "llvm/ADT/StringRef.h"
144ba319b5SDimitry Andric #include "llvm/ADT/StringSet.h"
157a7e6055SDimitry Andric #include "llvm/ADT/Triple.h"
16db17bf38SDimitry Andric #include "llvm/BinaryFormat/Wasm.h"
1751690af2SDimitry Andric #include "llvm/MC/SubtargetFeature.h"
187a7e6055SDimitry Andric #include "llvm/Object/Binary.h"
197a7e6055SDimitry Andric #include "llvm/Object/Error.h"
207a7e6055SDimitry Andric #include "llvm/Object/ObjectFile.h"
217a7e6055SDimitry Andric #include "llvm/Object/SymbolicFile.h"
22d88c1a5aSDimitry Andric #include "llvm/Object/Wasm.h"
23d88c1a5aSDimitry Andric #include "llvm/Support/Endian.h"
247a7e6055SDimitry Andric #include "llvm/Support/Error.h"
257a7e6055SDimitry Andric #include "llvm/Support/ErrorHandling.h"
26d88c1a5aSDimitry Andric #include "llvm/Support/LEB128.h"
27*b5893f02SDimitry Andric #include "llvm/Support/ScopedPrinter.h"
287a7e6055SDimitry Andric #include <algorithm>
2951690af2SDimitry Andric #include <cassert>
307a7e6055SDimitry Andric #include <cstdint>
3151690af2SDimitry Andric #include <cstring>
327a7e6055SDimitry Andric #include <system_error>
33d88c1a5aSDimitry Andric
34edd7eaddSDimitry Andric #define DEBUG_TYPE "wasm-object"
35edd7eaddSDimitry Andric
367a7e6055SDimitry Andric using namespace llvm;
377a7e6055SDimitry Andric using namespace object;
38d88c1a5aSDimitry Andric
print(raw_ostream & Out) const394ba319b5SDimitry Andric void WasmSymbol::print(raw_ostream &Out) const {
404ba319b5SDimitry Andric Out << "Name=" << Info.Name
414ba319b5SDimitry Andric << ", Kind=" << toString(wasm::WasmSymbolType(Info.Kind))
424ba319b5SDimitry Andric << ", Flags=" << Info.Flags;
434ba319b5SDimitry Andric if (!isTypeData()) {
444ba319b5SDimitry Andric Out << ", ElemIndex=" << Info.ElementIndex;
454ba319b5SDimitry Andric } else if (isDefined()) {
464ba319b5SDimitry Andric Out << ", Segment=" << Info.DataRef.Segment;
474ba319b5SDimitry Andric Out << ", Offset=" << Info.DataRef.Offset;
484ba319b5SDimitry Andric Out << ", Size=" << Info.DataRef.Size;
494ba319b5SDimitry Andric }
504ba319b5SDimitry Andric }
514ba319b5SDimitry Andric
524ba319b5SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
dump() const534ba319b5SDimitry Andric LLVM_DUMP_METHOD void WasmSymbol::dump() const { print(dbgs()); }
544ba319b5SDimitry Andric #endif
554ba319b5SDimitry Andric
56d88c1a5aSDimitry Andric Expected<std::unique_ptr<WasmObjectFile>>
createWasmObjectFile(MemoryBufferRef Buffer)57d88c1a5aSDimitry Andric ObjectFile::createWasmObjectFile(MemoryBufferRef Buffer) {
58d88c1a5aSDimitry Andric Error Err = Error::success();
59d88c1a5aSDimitry Andric auto ObjectFile = llvm::make_unique<WasmObjectFile>(Buffer, Err);
60d88c1a5aSDimitry Andric if (Err)
61d88c1a5aSDimitry Andric return std::move(Err);
62d88c1a5aSDimitry Andric
63d88c1a5aSDimitry Andric return std::move(ObjectFile);
64d88c1a5aSDimitry Andric }
65d88c1a5aSDimitry Andric
667a7e6055SDimitry Andric #define VARINT7_MAX ((1 << 7) - 1)
677a7e6055SDimitry Andric #define VARINT7_MIN (-(1 << 7))
687a7e6055SDimitry Andric #define VARUINT7_MAX (1 << 7)
697a7e6055SDimitry Andric #define VARUINT1_MAX (1)
70d88c1a5aSDimitry Andric
readUint8(WasmObjectFile::ReadContext & Ctx)714ba319b5SDimitry Andric static uint8_t readUint8(WasmObjectFile::ReadContext &Ctx) {
724ba319b5SDimitry Andric if (Ctx.Ptr == Ctx.End)
734ba319b5SDimitry Andric report_fatal_error("EOF while reading uint8");
744ba319b5SDimitry Andric return *Ctx.Ptr++;
754ba319b5SDimitry Andric }
767a7e6055SDimitry Andric
readUint32(WasmObjectFile::ReadContext & Ctx)774ba319b5SDimitry Andric static uint32_t readUint32(WasmObjectFile::ReadContext &Ctx) {
784ba319b5SDimitry Andric if (Ctx.Ptr + 4 > Ctx.End)
794ba319b5SDimitry Andric report_fatal_error("EOF while reading uint32");
804ba319b5SDimitry Andric uint32_t Result = support::endian::read32le(Ctx.Ptr);
814ba319b5SDimitry Andric Ctx.Ptr += 4;
82d88c1a5aSDimitry Andric return Result;
83d88c1a5aSDimitry Andric }
84d88c1a5aSDimitry Andric
readFloat32(WasmObjectFile::ReadContext & Ctx)854ba319b5SDimitry Andric static int32_t readFloat32(WasmObjectFile::ReadContext &Ctx) {
86*b5893f02SDimitry Andric if (Ctx.Ptr + 4 > Ctx.End)
87*b5893f02SDimitry Andric report_fatal_error("EOF while reading float64");
887a7e6055SDimitry Andric int32_t Result = 0;
894ba319b5SDimitry Andric memcpy(&Result, Ctx.Ptr, sizeof(Result));
904ba319b5SDimitry Andric Ctx.Ptr += sizeof(Result);
917a7e6055SDimitry Andric return Result;
927a7e6055SDimitry Andric }
937a7e6055SDimitry Andric
readFloat64(WasmObjectFile::ReadContext & Ctx)944ba319b5SDimitry Andric static int64_t readFloat64(WasmObjectFile::ReadContext &Ctx) {
95*b5893f02SDimitry Andric if (Ctx.Ptr + 8 > Ctx.End)
96*b5893f02SDimitry Andric report_fatal_error("EOF while reading float64");
977a7e6055SDimitry Andric int64_t Result = 0;
984ba319b5SDimitry Andric memcpy(&Result, Ctx.Ptr, sizeof(Result));
994ba319b5SDimitry Andric Ctx.Ptr += sizeof(Result);
1007a7e6055SDimitry Andric return Result;
1017a7e6055SDimitry Andric }
1027a7e6055SDimitry Andric
readULEB128(WasmObjectFile::ReadContext & Ctx)1034ba319b5SDimitry Andric static uint64_t readULEB128(WasmObjectFile::ReadContext &Ctx) {
104d88c1a5aSDimitry Andric unsigned Count;
1054ba319b5SDimitry Andric const char *Error = nullptr;
1064ba319b5SDimitry Andric uint64_t Result = decodeULEB128(Ctx.Ptr, &Count, Ctx.End, &Error);
1074ba319b5SDimitry Andric if (Error)
1084ba319b5SDimitry Andric report_fatal_error(Error);
1094ba319b5SDimitry Andric Ctx.Ptr += Count;
110d88c1a5aSDimitry Andric return Result;
111d88c1a5aSDimitry Andric }
112d88c1a5aSDimitry Andric
readString(WasmObjectFile::ReadContext & Ctx)1134ba319b5SDimitry Andric static StringRef readString(WasmObjectFile::ReadContext &Ctx) {
1144ba319b5SDimitry Andric uint32_t StringLen = readULEB128(Ctx);
1154ba319b5SDimitry Andric if (Ctx.Ptr + StringLen > Ctx.End)
1164ba319b5SDimitry Andric report_fatal_error("EOF while reading string");
1174ba319b5SDimitry Andric StringRef Return =
1184ba319b5SDimitry Andric StringRef(reinterpret_cast<const char *>(Ctx.Ptr), StringLen);
1194ba319b5SDimitry Andric Ctx.Ptr += StringLen;
120d88c1a5aSDimitry Andric return Return;
121d88c1a5aSDimitry Andric }
122d88c1a5aSDimitry Andric
readLEB128(WasmObjectFile::ReadContext & Ctx)1234ba319b5SDimitry Andric static int64_t readLEB128(WasmObjectFile::ReadContext &Ctx) {
1247a7e6055SDimitry Andric unsigned Count;
1254ba319b5SDimitry Andric const char *Error = nullptr;
1264ba319b5SDimitry Andric uint64_t Result = decodeSLEB128(Ctx.Ptr, &Count, Ctx.End, &Error);
1274ba319b5SDimitry Andric if (Error)
1284ba319b5SDimitry Andric report_fatal_error(Error);
1294ba319b5SDimitry Andric Ctx.Ptr += Count;
1307a7e6055SDimitry Andric return Result;
1317a7e6055SDimitry Andric }
1327a7e6055SDimitry Andric
readVaruint1(WasmObjectFile::ReadContext & Ctx)1334ba319b5SDimitry Andric static uint8_t readVaruint1(WasmObjectFile::ReadContext &Ctx) {
1344ba319b5SDimitry Andric int64_t result = readLEB128(Ctx);
1354ba319b5SDimitry Andric if (result > VARUINT1_MAX || result < 0)
1364ba319b5SDimitry Andric report_fatal_error("LEB is outside Varuint1 range");
1377a7e6055SDimitry Andric return result;
1387a7e6055SDimitry Andric }
1397a7e6055SDimitry Andric
readVarint32(WasmObjectFile::ReadContext & Ctx)1404ba319b5SDimitry Andric static int32_t readVarint32(WasmObjectFile::ReadContext &Ctx) {
1414ba319b5SDimitry Andric int64_t result = readLEB128(Ctx);
1424ba319b5SDimitry Andric if (result > INT32_MAX || result < INT32_MIN)
1434ba319b5SDimitry Andric report_fatal_error("LEB is outside Varint32 range");
1447a7e6055SDimitry Andric return result;
1457a7e6055SDimitry Andric }
1467a7e6055SDimitry Andric
readVaruint32(WasmObjectFile::ReadContext & Ctx)1474ba319b5SDimitry Andric static uint32_t readVaruint32(WasmObjectFile::ReadContext &Ctx) {
1484ba319b5SDimitry Andric uint64_t result = readULEB128(Ctx);
1494ba319b5SDimitry Andric if (result > UINT32_MAX)
1504ba319b5SDimitry Andric report_fatal_error("LEB is outside Varuint32 range");
1517a7e6055SDimitry Andric return result;
1527a7e6055SDimitry Andric }
1537a7e6055SDimitry Andric
readVarint64(WasmObjectFile::ReadContext & Ctx)1544ba319b5SDimitry Andric static int64_t readVarint64(WasmObjectFile::ReadContext &Ctx) {
1554ba319b5SDimitry Andric return readLEB128(Ctx);
1567a7e6055SDimitry Andric }
1577a7e6055SDimitry Andric
readOpcode(WasmObjectFile::ReadContext & Ctx)1584ba319b5SDimitry Andric static uint8_t readOpcode(WasmObjectFile::ReadContext &Ctx) {
1594ba319b5SDimitry Andric return readUint8(Ctx);
1607a7e6055SDimitry Andric }
1617a7e6055SDimitry Andric
readInitExpr(wasm::WasmInitExpr & Expr,WasmObjectFile::ReadContext & Ctx)1624ba319b5SDimitry Andric static Error readInitExpr(wasm::WasmInitExpr &Expr,
1634ba319b5SDimitry Andric WasmObjectFile::ReadContext &Ctx) {
1644ba319b5SDimitry Andric Expr.Opcode = readOpcode(Ctx);
1657a7e6055SDimitry Andric
1667a7e6055SDimitry Andric switch (Expr.Opcode) {
1677a7e6055SDimitry Andric case wasm::WASM_OPCODE_I32_CONST:
1684ba319b5SDimitry Andric Expr.Value.Int32 = readVarint32(Ctx);
1697a7e6055SDimitry Andric break;
1707a7e6055SDimitry Andric case wasm::WASM_OPCODE_I64_CONST:
1714ba319b5SDimitry Andric Expr.Value.Int64 = readVarint64(Ctx);
1727a7e6055SDimitry Andric break;
1737a7e6055SDimitry Andric case wasm::WASM_OPCODE_F32_CONST:
1744ba319b5SDimitry Andric Expr.Value.Float32 = readFloat32(Ctx);
1757a7e6055SDimitry Andric break;
1767a7e6055SDimitry Andric case wasm::WASM_OPCODE_F64_CONST:
1774ba319b5SDimitry Andric Expr.Value.Float64 = readFloat64(Ctx);
1787a7e6055SDimitry Andric break;
179*b5893f02SDimitry Andric case wasm::WASM_OPCODE_GLOBAL_GET:
1804ba319b5SDimitry Andric Expr.Value.Global = readULEB128(Ctx);
1817a7e6055SDimitry Andric break;
1827a7e6055SDimitry Andric default:
1837a7e6055SDimitry Andric return make_error<GenericBinaryError>("Invalid opcode in init_expr",
1847a7e6055SDimitry Andric object_error::parse_failed);
1857a7e6055SDimitry Andric }
1867a7e6055SDimitry Andric
1874ba319b5SDimitry Andric uint8_t EndOpcode = readOpcode(Ctx);
1887a7e6055SDimitry Andric if (EndOpcode != wasm::WASM_OPCODE_END) {
1897a7e6055SDimitry Andric return make_error<GenericBinaryError>("Invalid init_expr",
1907a7e6055SDimitry Andric object_error::parse_failed);
1917a7e6055SDimitry Andric }
1927a7e6055SDimitry Andric return Error::success();
1937a7e6055SDimitry Andric }
1947a7e6055SDimitry Andric
readLimits(WasmObjectFile::ReadContext & Ctx)1954ba319b5SDimitry Andric static wasm::WasmLimits readLimits(WasmObjectFile::ReadContext &Ctx) {
1967a7e6055SDimitry Andric wasm::WasmLimits Result;
197*b5893f02SDimitry Andric Result.Flags = readVaruint32(Ctx);
1984ba319b5SDimitry Andric Result.Initial = readVaruint32(Ctx);
1997a7e6055SDimitry Andric if (Result.Flags & wasm::WASM_LIMITS_FLAG_HAS_MAX)
2004ba319b5SDimitry Andric Result.Maximum = readVaruint32(Ctx);
2017a7e6055SDimitry Andric return Result;
2027a7e6055SDimitry Andric }
2037a7e6055SDimitry Andric
readTable(WasmObjectFile::ReadContext & Ctx)2044ba319b5SDimitry Andric static wasm::WasmTable readTable(WasmObjectFile::ReadContext &Ctx) {
2055517e702SDimitry Andric wasm::WasmTable Table;
2064ba319b5SDimitry Andric Table.ElemType = readUint8(Ctx);
2074ba319b5SDimitry Andric Table.Limits = readLimits(Ctx);
2085517e702SDimitry Andric return Table;
2095517e702SDimitry Andric }
2105517e702SDimitry Andric
readSection(WasmSection & Section,WasmObjectFile::ReadContext & Ctx,WasmSectionOrderChecker & Checker)211*b5893f02SDimitry Andric static Error readSection(WasmSection &Section, WasmObjectFile::ReadContext &Ctx,
212*b5893f02SDimitry Andric WasmSectionOrderChecker &Checker) {
2134ba319b5SDimitry Andric Section.Offset = Ctx.Ptr - Ctx.Start;
2144ba319b5SDimitry Andric Section.Type = readUint8(Ctx);
2154ba319b5SDimitry Andric LLVM_DEBUG(dbgs() << "readSection type=" << Section.Type << "\n");
2164ba319b5SDimitry Andric uint32_t Size = readVaruint32(Ctx);
217d88c1a5aSDimitry Andric if (Size == 0)
218d88c1a5aSDimitry Andric return make_error<StringError>("Zero length section",
219d88c1a5aSDimitry Andric object_error::parse_failed);
2204ba319b5SDimitry Andric if (Ctx.Ptr + Size > Ctx.End)
2212cab237bSDimitry Andric return make_error<StringError>("Section too large",
2222cab237bSDimitry Andric object_error::parse_failed);
2234ba319b5SDimitry Andric if (Section.Type == wasm::WASM_SEC_CUSTOM) {
224*b5893f02SDimitry Andric WasmObjectFile::ReadContext SectionCtx;
225*b5893f02SDimitry Andric SectionCtx.Start = Ctx.Ptr;
226*b5893f02SDimitry Andric SectionCtx.Ptr = Ctx.Ptr;
227*b5893f02SDimitry Andric SectionCtx.End = Ctx.Ptr + Size;
228*b5893f02SDimitry Andric
229*b5893f02SDimitry Andric Section.Name = readString(SectionCtx);
230*b5893f02SDimitry Andric
231*b5893f02SDimitry Andric uint32_t SectionNameSize = SectionCtx.Ptr - SectionCtx.Start;
232*b5893f02SDimitry Andric Ctx.Ptr += SectionNameSize;
233*b5893f02SDimitry Andric Size -= SectionNameSize;
2344ba319b5SDimitry Andric }
235*b5893f02SDimitry Andric
236*b5893f02SDimitry Andric if (!Checker.isValidSectionOrder(Section.Type, Section.Name)) {
237*b5893f02SDimitry Andric return make_error<StringError>("Out of order section type: " +
238*b5893f02SDimitry Andric llvm::to_string(Section.Type),
239*b5893f02SDimitry Andric object_error::parse_failed);
240*b5893f02SDimitry Andric }
241*b5893f02SDimitry Andric
2424ba319b5SDimitry Andric Section.Content = ArrayRef<uint8_t>(Ctx.Ptr, Size);
2434ba319b5SDimitry Andric Ctx.Ptr += Size;
244d88c1a5aSDimitry Andric return Error::success();
245d88c1a5aSDimitry Andric }
246d88c1a5aSDimitry Andric
WasmObjectFile(MemoryBufferRef Buffer,Error & Err)247d88c1a5aSDimitry Andric WasmObjectFile::WasmObjectFile(MemoryBufferRef Buffer, Error &Err)
24851690af2SDimitry Andric : ObjectFile(Binary::ID_Wasm, Buffer) {
249d88c1a5aSDimitry Andric ErrorAsOutParameter ErrAsOutParam(&Err);
250d88c1a5aSDimitry Andric Header.Magic = getData().substr(0, 4);
251d88c1a5aSDimitry Andric if (Header.Magic != StringRef("\0asm", 4)) {
252*b5893f02SDimitry Andric Err =
253*b5893f02SDimitry Andric make_error<StringError>("Bad magic number", object_error::parse_failed);
254d88c1a5aSDimitry Andric return;
255d88c1a5aSDimitry Andric }
2562cab237bSDimitry Andric
2574ba319b5SDimitry Andric ReadContext Ctx;
2584ba319b5SDimitry Andric Ctx.Start = getPtr(0);
2594ba319b5SDimitry Andric Ctx.Ptr = Ctx.Start + 4;
2604ba319b5SDimitry Andric Ctx.End = Ctx.Start + getData().size();
2612cab237bSDimitry Andric
2624ba319b5SDimitry Andric if (Ctx.Ptr + 4 > Ctx.End) {
2632cab237bSDimitry Andric Err = make_error<StringError>("Missing version number",
2642cab237bSDimitry Andric object_error::parse_failed);
2652cab237bSDimitry Andric return;
2662cab237bSDimitry Andric }
2672cab237bSDimitry Andric
2684ba319b5SDimitry Andric Header.Version = readUint32(Ctx);
269d88c1a5aSDimitry Andric if (Header.Version != wasm::WasmVersion) {
270d88c1a5aSDimitry Andric Err = make_error<StringError>("Bad version number",
271d88c1a5aSDimitry Andric object_error::parse_failed);
272d88c1a5aSDimitry Andric return;
273d88c1a5aSDimitry Andric }
274d88c1a5aSDimitry Andric
2757a7e6055SDimitry Andric WasmSection Sec;
276*b5893f02SDimitry Andric WasmSectionOrderChecker Checker;
2774ba319b5SDimitry Andric while (Ctx.Ptr < Ctx.End) {
278*b5893f02SDimitry Andric if ((Err = readSection(Sec, Ctx, Checker)))
279d88c1a5aSDimitry Andric return;
2807a7e6055SDimitry Andric if ((Err = parseSection(Sec)))
281d88c1a5aSDimitry Andric return;
2827a7e6055SDimitry Andric
283d88c1a5aSDimitry Andric Sections.push_back(Sec);
284d88c1a5aSDimitry Andric }
285d88c1a5aSDimitry Andric }
286d88c1a5aSDimitry Andric
parseSection(WasmSection & Sec)2877a7e6055SDimitry Andric Error WasmObjectFile::parseSection(WasmSection &Sec) {
2884ba319b5SDimitry Andric ReadContext Ctx;
2894ba319b5SDimitry Andric Ctx.Start = Sec.Content.data();
2904ba319b5SDimitry Andric Ctx.End = Ctx.Start + Sec.Content.size();
2914ba319b5SDimitry Andric Ctx.Ptr = Ctx.Start;
2927a7e6055SDimitry Andric switch (Sec.Type) {
2937a7e6055SDimitry Andric case wasm::WASM_SEC_CUSTOM:
2944ba319b5SDimitry Andric return parseCustomSection(Sec, Ctx);
2957a7e6055SDimitry Andric case wasm::WASM_SEC_TYPE:
2964ba319b5SDimitry Andric return parseTypeSection(Ctx);
2977a7e6055SDimitry Andric case wasm::WASM_SEC_IMPORT:
2984ba319b5SDimitry Andric return parseImportSection(Ctx);
2997a7e6055SDimitry Andric case wasm::WASM_SEC_FUNCTION:
3004ba319b5SDimitry Andric return parseFunctionSection(Ctx);
3017a7e6055SDimitry Andric case wasm::WASM_SEC_TABLE:
3024ba319b5SDimitry Andric return parseTableSection(Ctx);
3037a7e6055SDimitry Andric case wasm::WASM_SEC_MEMORY:
3044ba319b5SDimitry Andric return parseMemorySection(Ctx);
3057a7e6055SDimitry Andric case wasm::WASM_SEC_GLOBAL:
3064ba319b5SDimitry Andric return parseGlobalSection(Ctx);
307*b5893f02SDimitry Andric case wasm::WASM_SEC_EVENT:
308*b5893f02SDimitry Andric return parseEventSection(Ctx);
3097a7e6055SDimitry Andric case wasm::WASM_SEC_EXPORT:
3104ba319b5SDimitry Andric return parseExportSection(Ctx);
3117a7e6055SDimitry Andric case wasm::WASM_SEC_START:
3124ba319b5SDimitry Andric return parseStartSection(Ctx);
3137a7e6055SDimitry Andric case wasm::WASM_SEC_ELEM:
3144ba319b5SDimitry Andric return parseElemSection(Ctx);
3157a7e6055SDimitry Andric case wasm::WASM_SEC_CODE:
3164ba319b5SDimitry Andric return parseCodeSection(Ctx);
3177a7e6055SDimitry Andric case wasm::WASM_SEC_DATA:
3184ba319b5SDimitry Andric return parseDataSection(Ctx);
3197a7e6055SDimitry Andric default:
3207a7e6055SDimitry Andric return make_error<GenericBinaryError>("Bad section type",
3217a7e6055SDimitry Andric object_error::parse_failed);
3227a7e6055SDimitry Andric }
3237a7e6055SDimitry Andric }
3247a7e6055SDimitry Andric
parseDylinkSection(ReadContext & Ctx)325*b5893f02SDimitry Andric Error WasmObjectFile::parseDylinkSection(ReadContext &Ctx) {
326*b5893f02SDimitry Andric // See https://github.com/WebAssembly/tool-conventions/blob/master/DynamicLinking.md
327*b5893f02SDimitry Andric DylinkInfo.MemorySize = readVaruint32(Ctx);
328*b5893f02SDimitry Andric DylinkInfo.MemoryAlignment = readVaruint32(Ctx);
329*b5893f02SDimitry Andric DylinkInfo.TableSize = readVaruint32(Ctx);
330*b5893f02SDimitry Andric DylinkInfo.TableAlignment = readVaruint32(Ctx);
331*b5893f02SDimitry Andric uint32_t Count = readVaruint32(Ctx);
332*b5893f02SDimitry Andric while (Count--) {
333*b5893f02SDimitry Andric DylinkInfo.Needed.push_back(readString(Ctx));
334*b5893f02SDimitry Andric }
335*b5893f02SDimitry Andric if (Ctx.Ptr != Ctx.End)
336*b5893f02SDimitry Andric return make_error<GenericBinaryError>("dylink section ended prematurely",
337*b5893f02SDimitry Andric object_error::parse_failed);
338*b5893f02SDimitry Andric return Error::success();
339*b5893f02SDimitry Andric }
340*b5893f02SDimitry Andric
parseNameSection(ReadContext & Ctx)3414ba319b5SDimitry Andric Error WasmObjectFile::parseNameSection(ReadContext &Ctx) {
3424ba319b5SDimitry Andric llvm::DenseSet<uint64_t> Seen;
3434ba319b5SDimitry Andric if (Functions.size() != FunctionTypes.size()) {
3444ba319b5SDimitry Andric return make_error<GenericBinaryError>("Names must come after code section",
3454ba319b5SDimitry Andric object_error::parse_failed);
3464ba319b5SDimitry Andric }
3474ba319b5SDimitry Andric
3484ba319b5SDimitry Andric while (Ctx.Ptr < Ctx.End) {
3494ba319b5SDimitry Andric uint8_t Type = readUint8(Ctx);
3504ba319b5SDimitry Andric uint32_t Size = readVaruint32(Ctx);
3514ba319b5SDimitry Andric const uint8_t *SubSectionEnd = Ctx.Ptr + Size;
3527a7e6055SDimitry Andric switch (Type) {
3537a7e6055SDimitry Andric case wasm::WASM_NAMES_FUNCTION: {
3544ba319b5SDimitry Andric uint32_t Count = readVaruint32(Ctx);
3557a7e6055SDimitry Andric while (Count--) {
3564ba319b5SDimitry Andric uint32_t Index = readVaruint32(Ctx);
3574ba319b5SDimitry Andric if (!Seen.insert(Index).second)
3584ba319b5SDimitry Andric return make_error<GenericBinaryError>("Function named more than once",
3594ba319b5SDimitry Andric object_error::parse_failed);
3604ba319b5SDimitry Andric StringRef Name = readString(Ctx);
3614ba319b5SDimitry Andric if (!isValidFunctionIndex(Index) || Name.empty())
3624ba319b5SDimitry Andric return make_error<GenericBinaryError>("Invalid name entry",
3634ba319b5SDimitry Andric object_error::parse_failed);
3644ba319b5SDimitry Andric DebugNames.push_back(wasm::WasmFunctionName{Index, Name});
3654ba319b5SDimitry Andric if (isDefinedFunctionIndex(Index))
3664ba319b5SDimitry Andric getDefinedFunction(Index).DebugName = Name;
3677a7e6055SDimitry Andric }
3687a7e6055SDimitry Andric break;
3697a7e6055SDimitry Andric }
3707a7e6055SDimitry Andric // Ignore local names for now
3717a7e6055SDimitry Andric case wasm::WASM_NAMES_LOCAL:
3727a7e6055SDimitry Andric default:
3734ba319b5SDimitry Andric Ctx.Ptr += Size;
3747a7e6055SDimitry Andric break;
3757a7e6055SDimitry Andric }
3764ba319b5SDimitry Andric if (Ctx.Ptr != SubSectionEnd)
377*b5893f02SDimitry Andric return make_error<GenericBinaryError>(
378*b5893f02SDimitry Andric "Name sub-section ended prematurely", object_error::parse_failed);
3797a7e6055SDimitry Andric }
3807a7e6055SDimitry Andric
3814ba319b5SDimitry Andric if (Ctx.Ptr != Ctx.End)
3827a7e6055SDimitry Andric return make_error<GenericBinaryError>("Name section ended prematurely",
3837a7e6055SDimitry Andric object_error::parse_failed);
3847a7e6055SDimitry Andric return Error::success();
3857a7e6055SDimitry Andric }
3867a7e6055SDimitry Andric
parseLinkingSection(ReadContext & Ctx)3874ba319b5SDimitry Andric Error WasmObjectFile::parseLinkingSection(ReadContext &Ctx) {
388a580b014SDimitry Andric HasLinkingSection = true;
3894ba319b5SDimitry Andric if (Functions.size() != FunctionTypes.size()) {
390edd7eaddSDimitry Andric return make_error<GenericBinaryError>(
391*b5893f02SDimitry Andric "Linking data must come after code section",
392*b5893f02SDimitry Andric object_error::parse_failed);
3934ba319b5SDimitry Andric }
3944ba319b5SDimitry Andric
3954ba319b5SDimitry Andric LinkingData.Version = readVaruint32(Ctx);
3964ba319b5SDimitry Andric if (LinkingData.Version != wasm::WasmMetadataVersion) {
3974ba319b5SDimitry Andric return make_error<GenericBinaryError>(
3984ba319b5SDimitry Andric "Unexpected metadata version: " + Twine(LinkingData.Version) +
3994ba319b5SDimitry Andric " (Expected: " + Twine(wasm::WasmMetadataVersion) + ")",
400edd7eaddSDimitry Andric object_error::parse_failed);
401edd7eaddSDimitry Andric }
4024ba319b5SDimitry Andric
4034ba319b5SDimitry Andric const uint8_t *OrigEnd = Ctx.End;
4044ba319b5SDimitry Andric while (Ctx.Ptr < OrigEnd) {
4054ba319b5SDimitry Andric Ctx.End = OrigEnd;
4064ba319b5SDimitry Andric uint8_t Type = readUint8(Ctx);
4074ba319b5SDimitry Andric uint32_t Size = readVaruint32(Ctx);
4084ba319b5SDimitry Andric LLVM_DEBUG(dbgs() << "readSubsection type=" << int(Type) << " size=" << Size
4094ba319b5SDimitry Andric << "\n");
4104ba319b5SDimitry Andric Ctx.End = Ctx.Ptr + Size;
4114ba319b5SDimitry Andric switch (Type) {
4124ba319b5SDimitry Andric case wasm::WASM_SYMBOL_TABLE:
4134ba319b5SDimitry Andric if (Error Err = parseLinkingSectionSymtab(Ctx))
4144ba319b5SDimitry Andric return Err;
415a580b014SDimitry Andric break;
4162cab237bSDimitry Andric case wasm::WASM_SEGMENT_INFO: {
4174ba319b5SDimitry Andric uint32_t Count = readVaruint32(Ctx);
4182cab237bSDimitry Andric if (Count > DataSegments.size())
4192cab237bSDimitry Andric return make_error<GenericBinaryError>("Too many segment names",
4202cab237bSDimitry Andric object_error::parse_failed);
4212cab237bSDimitry Andric for (uint32_t i = 0; i < Count; i++) {
4224ba319b5SDimitry Andric DataSegments[i].Data.Name = readString(Ctx);
4234ba319b5SDimitry Andric DataSegments[i].Data.Alignment = readVaruint32(Ctx);
4244ba319b5SDimitry Andric DataSegments[i].Data.Flags = readVaruint32(Ctx);
4252cab237bSDimitry Andric }
426a580b014SDimitry Andric break;
4272cab237bSDimitry Andric }
4282cab237bSDimitry Andric case wasm::WASM_INIT_FUNCS: {
4294ba319b5SDimitry Andric uint32_t Count = readVaruint32(Ctx);
4302cab237bSDimitry Andric LinkingData.InitFunctions.reserve(Count);
4312cab237bSDimitry Andric for (uint32_t i = 0; i < Count; i++) {
4322cab237bSDimitry Andric wasm::WasmInitFunc Init;
4334ba319b5SDimitry Andric Init.Priority = readVaruint32(Ctx);
4344ba319b5SDimitry Andric Init.Symbol = readVaruint32(Ctx);
4354ba319b5SDimitry Andric if (!isValidFunctionSymbol(Init.Symbol))
4364ba319b5SDimitry Andric return make_error<GenericBinaryError>("Invalid function symbol: " +
4374ba319b5SDimitry Andric Twine(Init.Symbol),
4382cab237bSDimitry Andric object_error::parse_failed);
4392cab237bSDimitry Andric LinkingData.InitFunctions.emplace_back(Init);
4402cab237bSDimitry Andric }
4412cab237bSDimitry Andric break;
4422cab237bSDimitry Andric }
4434ba319b5SDimitry Andric case wasm::WASM_COMDAT_INFO:
4444ba319b5SDimitry Andric if (Error Err = parseLinkingSectionComdat(Ctx))
4454ba319b5SDimitry Andric return Err;
4464ba319b5SDimitry Andric break;
447edd7eaddSDimitry Andric default:
4484ba319b5SDimitry Andric Ctx.Ptr += Size;
449edd7eaddSDimitry Andric break;
450edd7eaddSDimitry Andric }
4514ba319b5SDimitry Andric if (Ctx.Ptr != Ctx.End)
452edd7eaddSDimitry Andric return make_error<GenericBinaryError>(
453edd7eaddSDimitry Andric "Linking sub-section ended prematurely", object_error::parse_failed);
454edd7eaddSDimitry Andric }
4554ba319b5SDimitry Andric if (Ctx.Ptr != OrigEnd)
456edd7eaddSDimitry Andric return make_error<GenericBinaryError>("Linking section ended prematurely",
457edd7eaddSDimitry Andric object_error::parse_failed);
458edd7eaddSDimitry Andric return Error::success();
459edd7eaddSDimitry Andric }
460edd7eaddSDimitry Andric
parseLinkingSectionSymtab(ReadContext & Ctx)4614ba319b5SDimitry Andric Error WasmObjectFile::parseLinkingSectionSymtab(ReadContext &Ctx) {
4624ba319b5SDimitry Andric uint32_t Count = readVaruint32(Ctx);
4634ba319b5SDimitry Andric LinkingData.SymbolTable.reserve(Count);
4644ba319b5SDimitry Andric Symbols.reserve(Count);
4654ba319b5SDimitry Andric StringSet<> SymbolNames;
4664ba319b5SDimitry Andric
4674ba319b5SDimitry Andric std::vector<wasm::WasmImport *> ImportedGlobals;
4684ba319b5SDimitry Andric std::vector<wasm::WasmImport *> ImportedFunctions;
469*b5893f02SDimitry Andric std::vector<wasm::WasmImport *> ImportedEvents;
4704ba319b5SDimitry Andric ImportedGlobals.reserve(Imports.size());
4714ba319b5SDimitry Andric ImportedFunctions.reserve(Imports.size());
472*b5893f02SDimitry Andric ImportedEvents.reserve(Imports.size());
4734ba319b5SDimitry Andric for (auto &I : Imports) {
4744ba319b5SDimitry Andric if (I.Kind == wasm::WASM_EXTERNAL_FUNCTION)
4754ba319b5SDimitry Andric ImportedFunctions.emplace_back(&I);
4764ba319b5SDimitry Andric else if (I.Kind == wasm::WASM_EXTERNAL_GLOBAL)
4774ba319b5SDimitry Andric ImportedGlobals.emplace_back(&I);
478*b5893f02SDimitry Andric else if (I.Kind == wasm::WASM_EXTERNAL_EVENT)
479*b5893f02SDimitry Andric ImportedEvents.emplace_back(&I);
4807a7e6055SDimitry Andric }
4817a7e6055SDimitry Andric
4824ba319b5SDimitry Andric while (Count--) {
4834ba319b5SDimitry Andric wasm::WasmSymbolInfo Info;
484*b5893f02SDimitry Andric const wasm::WasmSignature *Signature = nullptr;
4854ba319b5SDimitry Andric const wasm::WasmGlobalType *GlobalType = nullptr;
486*b5893f02SDimitry Andric const wasm::WasmEventType *EventType = nullptr;
4877a7e6055SDimitry Andric
4884ba319b5SDimitry Andric Info.Kind = readUint8(Ctx);
4894ba319b5SDimitry Andric Info.Flags = readVaruint32(Ctx);
4904ba319b5SDimitry Andric bool IsDefined = (Info.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0;
4914ba319b5SDimitry Andric
4924ba319b5SDimitry Andric switch (Info.Kind) {
4934ba319b5SDimitry Andric case wasm::WASM_SYMBOL_TYPE_FUNCTION:
4944ba319b5SDimitry Andric Info.ElementIndex = readVaruint32(Ctx);
4954ba319b5SDimitry Andric if (!isValidFunctionIndex(Info.ElementIndex) ||
4964ba319b5SDimitry Andric IsDefined != isDefinedFunctionIndex(Info.ElementIndex))
4974ba319b5SDimitry Andric return make_error<GenericBinaryError>("invalid function symbol index",
4987a7e6055SDimitry Andric object_error::parse_failed);
4994ba319b5SDimitry Andric if (IsDefined) {
5004ba319b5SDimitry Andric Info.Name = readString(Ctx);
5014ba319b5SDimitry Andric unsigned FuncIndex = Info.ElementIndex - NumImportedFunctions;
502*b5893f02SDimitry Andric Signature = &Signatures[FunctionTypes[FuncIndex]];
5034ba319b5SDimitry Andric wasm::WasmFunction &Function = Functions[FuncIndex];
5044ba319b5SDimitry Andric if (Function.SymbolName.empty())
5054ba319b5SDimitry Andric Function.SymbolName = Info.Name;
5064ba319b5SDimitry Andric } else {
5074ba319b5SDimitry Andric wasm::WasmImport &Import = *ImportedFunctions[Info.ElementIndex];
508*b5893f02SDimitry Andric if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0)
509*b5893f02SDimitry Andric Info.Name = readString(Ctx);
510*b5893f02SDimitry Andric else
5114ba319b5SDimitry Andric Info.Name = Import.Field;
512*b5893f02SDimitry Andric Signature = &Signatures[Import.SigIndex];
513*b5893f02SDimitry Andric Info.ImportName = Import.Field;
514*b5893f02SDimitry Andric Info.ImportModule = Import.Module;
5154ba319b5SDimitry Andric }
5164ba319b5SDimitry Andric break;
5174ba319b5SDimitry Andric
5184ba319b5SDimitry Andric case wasm::WASM_SYMBOL_TYPE_GLOBAL:
5194ba319b5SDimitry Andric Info.ElementIndex = readVaruint32(Ctx);
5204ba319b5SDimitry Andric if (!isValidGlobalIndex(Info.ElementIndex) ||
5214ba319b5SDimitry Andric IsDefined != isDefinedGlobalIndex(Info.ElementIndex))
5224ba319b5SDimitry Andric return make_error<GenericBinaryError>("invalid global symbol index",
5234ba319b5SDimitry Andric object_error::parse_failed);
524*b5893f02SDimitry Andric if (!IsDefined && (Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) ==
5254ba319b5SDimitry Andric wasm::WASM_SYMBOL_BINDING_WEAK)
5264ba319b5SDimitry Andric return make_error<GenericBinaryError>("undefined weak global symbol",
5274ba319b5SDimitry Andric object_error::parse_failed);
5284ba319b5SDimitry Andric if (IsDefined) {
5294ba319b5SDimitry Andric Info.Name = readString(Ctx);
5304ba319b5SDimitry Andric unsigned GlobalIndex = Info.ElementIndex - NumImportedGlobals;
5314ba319b5SDimitry Andric wasm::WasmGlobal &Global = Globals[GlobalIndex];
5324ba319b5SDimitry Andric GlobalType = &Global.Type;
5334ba319b5SDimitry Andric if (Global.SymbolName.empty())
5344ba319b5SDimitry Andric Global.SymbolName = Info.Name;
5354ba319b5SDimitry Andric } else {
5364ba319b5SDimitry Andric wasm::WasmImport &Import = *ImportedGlobals[Info.ElementIndex];
537*b5893f02SDimitry Andric if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0)
538*b5893f02SDimitry Andric Info.Name = readString(Ctx);
539*b5893f02SDimitry Andric else
5404ba319b5SDimitry Andric Info.Name = Import.Field;
5414ba319b5SDimitry Andric GlobalType = &Import.Global;
542*b5893f02SDimitry Andric Info.ImportName = Import.Field;
543*b5893f02SDimitry Andric Info.ImportModule = Import.Module;
5444ba319b5SDimitry Andric }
5454ba319b5SDimitry Andric break;
5464ba319b5SDimitry Andric
5474ba319b5SDimitry Andric case wasm::WASM_SYMBOL_TYPE_DATA:
5484ba319b5SDimitry Andric Info.Name = readString(Ctx);
5494ba319b5SDimitry Andric if (IsDefined) {
5504ba319b5SDimitry Andric uint32_t Index = readVaruint32(Ctx);
5514ba319b5SDimitry Andric if (Index >= DataSegments.size())
5524ba319b5SDimitry Andric return make_error<GenericBinaryError>("invalid data symbol index",
5534ba319b5SDimitry Andric object_error::parse_failed);
5544ba319b5SDimitry Andric uint32_t Offset = readVaruint32(Ctx);
5554ba319b5SDimitry Andric uint32_t Size = readVaruint32(Ctx);
5564ba319b5SDimitry Andric if (Offset + Size > DataSegments[Index].Data.Content.size())
5574ba319b5SDimitry Andric return make_error<GenericBinaryError>("invalid data symbol offset",
5584ba319b5SDimitry Andric object_error::parse_failed);
5594ba319b5SDimitry Andric Info.DataRef = wasm::WasmDataReference{Index, Offset, Size};
5604ba319b5SDimitry Andric }
5614ba319b5SDimitry Andric break;
5624ba319b5SDimitry Andric
5634ba319b5SDimitry Andric case wasm::WASM_SYMBOL_TYPE_SECTION: {
5644ba319b5SDimitry Andric if ((Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) !=
5654ba319b5SDimitry Andric wasm::WASM_SYMBOL_BINDING_LOCAL)
5664ba319b5SDimitry Andric return make_error<GenericBinaryError>(
5674ba319b5SDimitry Andric "Section symbols must have local binding",
5684ba319b5SDimitry Andric object_error::parse_failed);
5694ba319b5SDimitry Andric Info.ElementIndex = readVaruint32(Ctx);
5704ba319b5SDimitry Andric // Use somewhat unique section name as symbol name.
5714ba319b5SDimitry Andric StringRef SectionName = Sections[Info.ElementIndex].Name;
5724ba319b5SDimitry Andric Info.Name = SectionName;
5734ba319b5SDimitry Andric break;
5744ba319b5SDimitry Andric }
5754ba319b5SDimitry Andric
576*b5893f02SDimitry Andric case wasm::WASM_SYMBOL_TYPE_EVENT: {
577*b5893f02SDimitry Andric Info.ElementIndex = readVaruint32(Ctx);
578*b5893f02SDimitry Andric if (!isValidEventIndex(Info.ElementIndex) ||
579*b5893f02SDimitry Andric IsDefined != isDefinedEventIndex(Info.ElementIndex))
580*b5893f02SDimitry Andric return make_error<GenericBinaryError>("invalid event symbol index",
581*b5893f02SDimitry Andric object_error::parse_failed);
582*b5893f02SDimitry Andric if (!IsDefined && (Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) ==
583*b5893f02SDimitry Andric wasm::WASM_SYMBOL_BINDING_WEAK)
584*b5893f02SDimitry Andric return make_error<GenericBinaryError>("undefined weak global symbol",
585*b5893f02SDimitry Andric object_error::parse_failed);
586*b5893f02SDimitry Andric if (IsDefined) {
587*b5893f02SDimitry Andric Info.Name = readString(Ctx);
588*b5893f02SDimitry Andric unsigned EventIndex = Info.ElementIndex - NumImportedEvents;
589*b5893f02SDimitry Andric wasm::WasmEvent &Event = Events[EventIndex];
590*b5893f02SDimitry Andric Signature = &Signatures[Event.Type.SigIndex];
591*b5893f02SDimitry Andric EventType = &Event.Type;
592*b5893f02SDimitry Andric if (Event.SymbolName.empty())
593*b5893f02SDimitry Andric Event.SymbolName = Info.Name;
594*b5893f02SDimitry Andric
595*b5893f02SDimitry Andric } else {
596*b5893f02SDimitry Andric wasm::WasmImport &Import = *ImportedEvents[Info.ElementIndex];
597*b5893f02SDimitry Andric if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0)
598*b5893f02SDimitry Andric Info.Name = readString(Ctx);
599*b5893f02SDimitry Andric else
600*b5893f02SDimitry Andric Info.Name = Import.Field;
601*b5893f02SDimitry Andric EventType = &Import.Event;
602*b5893f02SDimitry Andric Signature = &Signatures[EventType->SigIndex];
603*b5893f02SDimitry Andric Info.ImportName = Import.Field;
604*b5893f02SDimitry Andric Info.ImportModule = Import.Module;
605*b5893f02SDimitry Andric }
606*b5893f02SDimitry Andric break;
607*b5893f02SDimitry Andric }
608*b5893f02SDimitry Andric
6094ba319b5SDimitry Andric default:
6104ba319b5SDimitry Andric return make_error<GenericBinaryError>("Invalid symbol type",
6114ba319b5SDimitry Andric object_error::parse_failed);
6124ba319b5SDimitry Andric }
6134ba319b5SDimitry Andric
6144ba319b5SDimitry Andric if ((Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) !=
6154ba319b5SDimitry Andric wasm::WASM_SYMBOL_BINDING_LOCAL &&
6164ba319b5SDimitry Andric !SymbolNames.insert(Info.Name).second)
6174ba319b5SDimitry Andric return make_error<GenericBinaryError>("Duplicate symbol name " +
6184ba319b5SDimitry Andric Twine(Info.Name),
6194ba319b5SDimitry Andric object_error::parse_failed);
6204ba319b5SDimitry Andric LinkingData.SymbolTable.emplace_back(Info);
621*b5893f02SDimitry Andric Symbols.emplace_back(LinkingData.SymbolTable.back(), GlobalType, EventType,
622*b5893f02SDimitry Andric Signature);
6234ba319b5SDimitry Andric LLVM_DEBUG(dbgs() << "Adding symbol: " << Symbols.back() << "\n");
6244ba319b5SDimitry Andric }
6254ba319b5SDimitry Andric
6264ba319b5SDimitry Andric return Error::success();
6274ba319b5SDimitry Andric }
6284ba319b5SDimitry Andric
parseLinkingSectionComdat(ReadContext & Ctx)6294ba319b5SDimitry Andric Error WasmObjectFile::parseLinkingSectionComdat(ReadContext &Ctx) {
6304ba319b5SDimitry Andric uint32_t ComdatCount = readVaruint32(Ctx);
6314ba319b5SDimitry Andric StringSet<> ComdatSet;
6324ba319b5SDimitry Andric for (unsigned ComdatIndex = 0; ComdatIndex < ComdatCount; ++ComdatIndex) {
6334ba319b5SDimitry Andric StringRef Name = readString(Ctx);
6344ba319b5SDimitry Andric if (Name.empty() || !ComdatSet.insert(Name).second)
635*b5893f02SDimitry Andric return make_error<GenericBinaryError>("Bad/duplicate COMDAT name " +
636*b5893f02SDimitry Andric Twine(Name),
6374ba319b5SDimitry Andric object_error::parse_failed);
6384ba319b5SDimitry Andric LinkingData.Comdats.emplace_back(Name);
6394ba319b5SDimitry Andric uint32_t Flags = readVaruint32(Ctx);
6404ba319b5SDimitry Andric if (Flags != 0)
6414ba319b5SDimitry Andric return make_error<GenericBinaryError>("Unsupported COMDAT flags",
6424ba319b5SDimitry Andric object_error::parse_failed);
6434ba319b5SDimitry Andric
6444ba319b5SDimitry Andric uint32_t EntryCount = readVaruint32(Ctx);
6454ba319b5SDimitry Andric while (EntryCount--) {
6464ba319b5SDimitry Andric unsigned Kind = readVaruint32(Ctx);
6474ba319b5SDimitry Andric unsigned Index = readVaruint32(Ctx);
6484ba319b5SDimitry Andric switch (Kind) {
6494ba319b5SDimitry Andric default:
6504ba319b5SDimitry Andric return make_error<GenericBinaryError>("Invalid COMDAT entry type",
6514ba319b5SDimitry Andric object_error::parse_failed);
6524ba319b5SDimitry Andric case wasm::WASM_COMDAT_DATA:
6534ba319b5SDimitry Andric if (Index >= DataSegments.size())
654*b5893f02SDimitry Andric return make_error<GenericBinaryError>(
655*b5893f02SDimitry Andric "COMDAT data index out of range", object_error::parse_failed);
6564ba319b5SDimitry Andric if (DataSegments[Index].Data.Comdat != UINT32_MAX)
6574ba319b5SDimitry Andric return make_error<GenericBinaryError>("Data segment in two COMDATs",
6584ba319b5SDimitry Andric object_error::parse_failed);
6594ba319b5SDimitry Andric DataSegments[Index].Data.Comdat = ComdatIndex;
6604ba319b5SDimitry Andric break;
6614ba319b5SDimitry Andric case wasm::WASM_COMDAT_FUNCTION:
6624ba319b5SDimitry Andric if (!isDefinedFunctionIndex(Index))
663*b5893f02SDimitry Andric return make_error<GenericBinaryError>(
664*b5893f02SDimitry Andric "COMDAT function index out of range", object_error::parse_failed);
6654ba319b5SDimitry Andric if (getDefinedFunction(Index).Comdat != UINT32_MAX)
6664ba319b5SDimitry Andric return make_error<GenericBinaryError>("Function in two COMDATs",
6674ba319b5SDimitry Andric object_error::parse_failed);
6684ba319b5SDimitry Andric getDefinedFunction(Index).Comdat = ComdatIndex;
6694ba319b5SDimitry Andric break;
6704ba319b5SDimitry Andric }
6714ba319b5SDimitry Andric }
6724ba319b5SDimitry Andric }
6734ba319b5SDimitry Andric return Error::success();
6744ba319b5SDimitry Andric }
6754ba319b5SDimitry Andric
parseRelocSection(StringRef Name,ReadContext & Ctx)6764ba319b5SDimitry Andric Error WasmObjectFile::parseRelocSection(StringRef Name, ReadContext &Ctx) {
6774ba319b5SDimitry Andric uint32_t SectionIndex = readVaruint32(Ctx);
6784ba319b5SDimitry Andric if (SectionIndex >= Sections.size())
6794ba319b5SDimitry Andric return make_error<GenericBinaryError>("Invalid section index",
6804ba319b5SDimitry Andric object_error::parse_failed);
6814ba319b5SDimitry Andric WasmSection &Section = Sections[SectionIndex];
6824ba319b5SDimitry Andric uint32_t RelocCount = readVaruint32(Ctx);
6834ba319b5SDimitry Andric uint32_t EndOffset = Section.Content.size();
684*b5893f02SDimitry Andric uint32_t PreviousOffset = 0;
6857a7e6055SDimitry Andric while (RelocCount--) {
6864ba319b5SDimitry Andric wasm::WasmRelocation Reloc = {};
6874ba319b5SDimitry Andric Reloc.Type = readVaruint32(Ctx);
6884ba319b5SDimitry Andric Reloc.Offset = readVaruint32(Ctx);
689*b5893f02SDimitry Andric if (Reloc.Offset < PreviousOffset)
690*b5893f02SDimitry Andric return make_error<GenericBinaryError>("Relocations not in offset order",
691*b5893f02SDimitry Andric object_error::parse_failed);
692*b5893f02SDimitry Andric PreviousOffset = Reloc.Offset;
6934ba319b5SDimitry Andric Reloc.Index = readVaruint32(Ctx);
6947a7e6055SDimitry Andric switch (Reloc.Type) {
6957a7e6055SDimitry Andric case wasm::R_WEBASSEMBLY_FUNCTION_INDEX_LEB:
6967a7e6055SDimitry Andric case wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB:
6977a7e6055SDimitry Andric case wasm::R_WEBASSEMBLY_TABLE_INDEX_I32:
6984ba319b5SDimitry Andric if (!isValidFunctionSymbol(Reloc.Index))
6994ba319b5SDimitry Andric return make_error<GenericBinaryError>("Bad relocation function index",
7004ba319b5SDimitry Andric object_error::parse_failed);
7014ba319b5SDimitry Andric break;
70251690af2SDimitry Andric case wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB:
7034ba319b5SDimitry Andric if (Reloc.Index >= Signatures.size())
7044ba319b5SDimitry Andric return make_error<GenericBinaryError>("Bad relocation type index",
7054ba319b5SDimitry Andric object_error::parse_failed);
7064ba319b5SDimitry Andric break;
707edd7eaddSDimitry Andric case wasm::R_WEBASSEMBLY_GLOBAL_INDEX_LEB:
7084ba319b5SDimitry Andric if (!isValidGlobalSymbol(Reloc.Index))
7094ba319b5SDimitry Andric return make_error<GenericBinaryError>("Bad relocation global index",
7104ba319b5SDimitry Andric object_error::parse_failed);
7117a7e6055SDimitry Andric break;
712*b5893f02SDimitry Andric case wasm::R_WEBASSEMBLY_EVENT_INDEX_LEB:
713*b5893f02SDimitry Andric if (!isValidEventSymbol(Reloc.Index))
714*b5893f02SDimitry Andric return make_error<GenericBinaryError>("Bad relocation event index",
715*b5893f02SDimitry Andric object_error::parse_failed);
716*b5893f02SDimitry Andric break;
7172cab237bSDimitry Andric case wasm::R_WEBASSEMBLY_MEMORY_ADDR_LEB:
7182cab237bSDimitry Andric case wasm::R_WEBASSEMBLY_MEMORY_ADDR_SLEB:
7192cab237bSDimitry Andric case wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32:
7204ba319b5SDimitry Andric if (!isValidDataSymbol(Reloc.Index))
7214ba319b5SDimitry Andric return make_error<GenericBinaryError>("Bad relocation data index",
7224ba319b5SDimitry Andric object_error::parse_failed);
7234ba319b5SDimitry Andric Reloc.Addend = readVarint32(Ctx);
7244ba319b5SDimitry Andric break;
7254ba319b5SDimitry Andric case wasm::R_WEBASSEMBLY_FUNCTION_OFFSET_I32:
7264ba319b5SDimitry Andric if (!isValidFunctionSymbol(Reloc.Index))
7274ba319b5SDimitry Andric return make_error<GenericBinaryError>("Bad relocation function index",
7284ba319b5SDimitry Andric object_error::parse_failed);
7294ba319b5SDimitry Andric Reloc.Addend = readVarint32(Ctx);
7304ba319b5SDimitry Andric break;
7314ba319b5SDimitry Andric case wasm::R_WEBASSEMBLY_SECTION_OFFSET_I32:
7324ba319b5SDimitry Andric if (!isValidSectionSymbol(Reloc.Index))
7334ba319b5SDimitry Andric return make_error<GenericBinaryError>("Bad relocation section index",
7344ba319b5SDimitry Andric object_error::parse_failed);
7354ba319b5SDimitry Andric Reloc.Addend = readVarint32(Ctx);
7367a7e6055SDimitry Andric break;
7377a7e6055SDimitry Andric default:
738edd7eaddSDimitry Andric return make_error<GenericBinaryError>("Bad relocation type: " +
739edd7eaddSDimitry Andric Twine(Reloc.Type),
7407a7e6055SDimitry Andric object_error::parse_failed);
7417a7e6055SDimitry Andric }
7424ba319b5SDimitry Andric
7434ba319b5SDimitry Andric // Relocations must fit inside the section, and must appear in order. They
7444ba319b5SDimitry Andric // also shouldn't overlap a function/element boundary, but we don't bother
7454ba319b5SDimitry Andric // to check that.
7464ba319b5SDimitry Andric uint64_t Size = 5;
7474ba319b5SDimitry Andric if (Reloc.Type == wasm::R_WEBASSEMBLY_TABLE_INDEX_I32 ||
7484ba319b5SDimitry Andric Reloc.Type == wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32 ||
7494ba319b5SDimitry Andric Reloc.Type == wasm::R_WEBASSEMBLY_SECTION_OFFSET_I32 ||
7504ba319b5SDimitry Andric Reloc.Type == wasm::R_WEBASSEMBLY_FUNCTION_OFFSET_I32)
7514ba319b5SDimitry Andric Size = 4;
7524ba319b5SDimitry Andric if (Reloc.Offset + Size > EndOffset)
7534ba319b5SDimitry Andric return make_error<GenericBinaryError>("Bad relocation offset",
7544ba319b5SDimitry Andric object_error::parse_failed);
7554ba319b5SDimitry Andric
7564ba319b5SDimitry Andric Section.Relocations.push_back(Reloc);
7577a7e6055SDimitry Andric }
7584ba319b5SDimitry Andric if (Ctx.Ptr != Ctx.End)
7597a7e6055SDimitry Andric return make_error<GenericBinaryError>("Reloc section ended prematurely",
7607a7e6055SDimitry Andric object_error::parse_failed);
7617a7e6055SDimitry Andric return Error::success();
7627a7e6055SDimitry Andric }
7637a7e6055SDimitry Andric
parseCustomSection(WasmSection & Sec,ReadContext & Ctx)7644ba319b5SDimitry Andric Error WasmObjectFile::parseCustomSection(WasmSection &Sec, ReadContext &Ctx) {
765*b5893f02SDimitry Andric if (Sec.Name == "dylink") {
766*b5893f02SDimitry Andric if (Error Err = parseDylinkSection(Ctx))
767*b5893f02SDimitry Andric return Err;
768*b5893f02SDimitry Andric } else if (Sec.Name == "name") {
7694ba319b5SDimitry Andric if (Error Err = parseNameSection(Ctx))
7707a7e6055SDimitry Andric return Err;
771edd7eaddSDimitry Andric } else if (Sec.Name == "linking") {
7724ba319b5SDimitry Andric if (Error Err = parseLinkingSection(Ctx))
773edd7eaddSDimitry Andric return Err;
7747a7e6055SDimitry Andric } else if (Sec.Name.startswith("reloc.")) {
7754ba319b5SDimitry Andric if (Error Err = parseRelocSection(Sec.Name, Ctx))
7767a7e6055SDimitry Andric return Err;
7777a7e6055SDimitry Andric }
7787a7e6055SDimitry Andric return Error::success();
7797a7e6055SDimitry Andric }
7807a7e6055SDimitry Andric
parseTypeSection(ReadContext & Ctx)7814ba319b5SDimitry Andric Error WasmObjectFile::parseTypeSection(ReadContext &Ctx) {
7824ba319b5SDimitry Andric uint32_t Count = readVaruint32(Ctx);
7837a7e6055SDimitry Andric Signatures.reserve(Count);
7847a7e6055SDimitry Andric while (Count--) {
7857a7e6055SDimitry Andric wasm::WasmSignature Sig;
7864ba319b5SDimitry Andric uint8_t Form = readUint8(Ctx);
7877a7e6055SDimitry Andric if (Form != wasm::WASM_TYPE_FUNC) {
7887a7e6055SDimitry Andric return make_error<GenericBinaryError>("Invalid signature type",
7897a7e6055SDimitry Andric object_error::parse_failed);
7907a7e6055SDimitry Andric }
7914ba319b5SDimitry Andric uint32_t ParamCount = readVaruint32(Ctx);
792*b5893f02SDimitry Andric Sig.Params.reserve(ParamCount);
7937a7e6055SDimitry Andric while (ParamCount--) {
7944ba319b5SDimitry Andric uint32_t ParamType = readUint8(Ctx);
795*b5893f02SDimitry Andric Sig.Params.push_back(wasm::ValType(ParamType));
7967a7e6055SDimitry Andric }
7974ba319b5SDimitry Andric uint32_t ReturnCount = readVaruint32(Ctx);
7987a7e6055SDimitry Andric if (ReturnCount) {
7997a7e6055SDimitry Andric if (ReturnCount != 1) {
8007a7e6055SDimitry Andric return make_error<GenericBinaryError>(
8017a7e6055SDimitry Andric "Multiple return types not supported", object_error::parse_failed);
8027a7e6055SDimitry Andric }
803*b5893f02SDimitry Andric Sig.Returns.push_back(wasm::ValType(readUint8(Ctx)));
8047a7e6055SDimitry Andric }
805*b5893f02SDimitry Andric Signatures.push_back(std::move(Sig));
8067a7e6055SDimitry Andric }
8074ba319b5SDimitry Andric if (Ctx.Ptr != Ctx.End)
8087a7e6055SDimitry Andric return make_error<GenericBinaryError>("Type section ended prematurely",
8097a7e6055SDimitry Andric object_error::parse_failed);
8107a7e6055SDimitry Andric return Error::success();
8117a7e6055SDimitry Andric }
8127a7e6055SDimitry Andric
parseImportSection(ReadContext & Ctx)8134ba319b5SDimitry Andric Error WasmObjectFile::parseImportSection(ReadContext &Ctx) {
8144ba319b5SDimitry Andric uint32_t Count = readVaruint32(Ctx);
8157a7e6055SDimitry Andric Imports.reserve(Count);
8160f5676f4SDimitry Andric for (uint32_t i = 0; i < Count; i++) {
8177a7e6055SDimitry Andric wasm::WasmImport Im;
8184ba319b5SDimitry Andric Im.Module = readString(Ctx);
8194ba319b5SDimitry Andric Im.Field = readString(Ctx);
8204ba319b5SDimitry Andric Im.Kind = readUint8(Ctx);
8217a7e6055SDimitry Andric switch (Im.Kind) {
8227a7e6055SDimitry Andric case wasm::WASM_EXTERNAL_FUNCTION:
8232cab237bSDimitry Andric NumImportedFunctions++;
8244ba319b5SDimitry Andric Im.SigIndex = readVaruint32(Ctx);
8257a7e6055SDimitry Andric break;
8267a7e6055SDimitry Andric case wasm::WASM_EXTERNAL_GLOBAL:
8272cab237bSDimitry Andric NumImportedGlobals++;
8284ba319b5SDimitry Andric Im.Global.Type = readUint8(Ctx);
8294ba319b5SDimitry Andric Im.Global.Mutable = readVaruint1(Ctx);
8307a7e6055SDimitry Andric break;
8315517e702SDimitry Andric case wasm::WASM_EXTERNAL_MEMORY:
8324ba319b5SDimitry Andric Im.Memory = readLimits(Ctx);
8335517e702SDimitry Andric break;
8345517e702SDimitry Andric case wasm::WASM_EXTERNAL_TABLE:
8354ba319b5SDimitry Andric Im.Table = readTable(Ctx);
836*b5893f02SDimitry Andric if (Im.Table.ElemType != wasm::WASM_TYPE_FUNCREF)
8375517e702SDimitry Andric return make_error<GenericBinaryError>("Invalid table element type",
8385517e702SDimitry Andric object_error::parse_failed);
8395517e702SDimitry Andric break;
840*b5893f02SDimitry Andric case wasm::WASM_EXTERNAL_EVENT:
841*b5893f02SDimitry Andric NumImportedEvents++;
842*b5893f02SDimitry Andric Im.Event.Attribute = readVarint32(Ctx);
843*b5893f02SDimitry Andric Im.Event.SigIndex = readVarint32(Ctx);
844*b5893f02SDimitry Andric break;
8457a7e6055SDimitry Andric default:
846*b5893f02SDimitry Andric return make_error<GenericBinaryError>("Unexpected import kind",
847*b5893f02SDimitry Andric object_error::parse_failed);
8487a7e6055SDimitry Andric }
8497a7e6055SDimitry Andric Imports.push_back(Im);
8507a7e6055SDimitry Andric }
8514ba319b5SDimitry Andric if (Ctx.Ptr != Ctx.End)
8527a7e6055SDimitry Andric return make_error<GenericBinaryError>("Import section ended prematurely",
8537a7e6055SDimitry Andric object_error::parse_failed);
8547a7e6055SDimitry Andric return Error::success();
8557a7e6055SDimitry Andric }
8567a7e6055SDimitry Andric
parseFunctionSection(ReadContext & Ctx)8574ba319b5SDimitry Andric Error WasmObjectFile::parseFunctionSection(ReadContext &Ctx) {
8584ba319b5SDimitry Andric uint32_t Count = readVaruint32(Ctx);
8597a7e6055SDimitry Andric FunctionTypes.reserve(Count);
8604ba319b5SDimitry Andric uint32_t NumTypes = Signatures.size();
8617a7e6055SDimitry Andric while (Count--) {
8624ba319b5SDimitry Andric uint32_t Type = readVaruint32(Ctx);
8634ba319b5SDimitry Andric if (Type >= NumTypes)
8644ba319b5SDimitry Andric return make_error<GenericBinaryError>("Invalid function type",
8654ba319b5SDimitry Andric object_error::parse_failed);
8664ba319b5SDimitry Andric FunctionTypes.push_back(Type);
8677a7e6055SDimitry Andric }
8684ba319b5SDimitry Andric if (Ctx.Ptr != Ctx.End)
8697a7e6055SDimitry Andric return make_error<GenericBinaryError>("Function section ended prematurely",
8707a7e6055SDimitry Andric object_error::parse_failed);
8717a7e6055SDimitry Andric return Error::success();
8727a7e6055SDimitry Andric }
8737a7e6055SDimitry Andric
parseTableSection(ReadContext & Ctx)8744ba319b5SDimitry Andric Error WasmObjectFile::parseTableSection(ReadContext &Ctx) {
8754ba319b5SDimitry Andric uint32_t Count = readVaruint32(Ctx);
8767a7e6055SDimitry Andric Tables.reserve(Count);
8777a7e6055SDimitry Andric while (Count--) {
8784ba319b5SDimitry Andric Tables.push_back(readTable(Ctx));
879*b5893f02SDimitry Andric if (Tables.back().ElemType != wasm::WASM_TYPE_FUNCREF) {
8807a7e6055SDimitry Andric return make_error<GenericBinaryError>("Invalid table element type",
8817a7e6055SDimitry Andric object_error::parse_failed);
8827a7e6055SDimitry Andric }
8837a7e6055SDimitry Andric }
8844ba319b5SDimitry Andric if (Ctx.Ptr != Ctx.End)
8857a7e6055SDimitry Andric return make_error<GenericBinaryError>("Table section ended prematurely",
8867a7e6055SDimitry Andric object_error::parse_failed);
8877a7e6055SDimitry Andric return Error::success();
8887a7e6055SDimitry Andric }
8897a7e6055SDimitry Andric
parseMemorySection(ReadContext & Ctx)8904ba319b5SDimitry Andric Error WasmObjectFile::parseMemorySection(ReadContext &Ctx) {
8914ba319b5SDimitry Andric uint32_t Count = readVaruint32(Ctx);
8927a7e6055SDimitry Andric Memories.reserve(Count);
8937a7e6055SDimitry Andric while (Count--) {
8944ba319b5SDimitry Andric Memories.push_back(readLimits(Ctx));
8957a7e6055SDimitry Andric }
8964ba319b5SDimitry Andric if (Ctx.Ptr != Ctx.End)
8977a7e6055SDimitry Andric return make_error<GenericBinaryError>("Memory section ended prematurely",
8987a7e6055SDimitry Andric object_error::parse_failed);
8997a7e6055SDimitry Andric return Error::success();
9007a7e6055SDimitry Andric }
9017a7e6055SDimitry Andric
parseGlobalSection(ReadContext & Ctx)9024ba319b5SDimitry Andric Error WasmObjectFile::parseGlobalSection(ReadContext &Ctx) {
9034ba319b5SDimitry Andric GlobalSection = Sections.size();
9044ba319b5SDimitry Andric uint32_t Count = readVaruint32(Ctx);
9057a7e6055SDimitry Andric Globals.reserve(Count);
9067a7e6055SDimitry Andric while (Count--) {
9077a7e6055SDimitry Andric wasm::WasmGlobal Global;
9084ba319b5SDimitry Andric Global.Index = NumImportedGlobals + Globals.size();
9094ba319b5SDimitry Andric Global.Type.Type = readUint8(Ctx);
9104ba319b5SDimitry Andric Global.Type.Mutable = readVaruint1(Ctx);
9114ba319b5SDimitry Andric if (Error Err = readInitExpr(Global.InitExpr, Ctx))
9127a7e6055SDimitry Andric return Err;
9137a7e6055SDimitry Andric Globals.push_back(Global);
9147a7e6055SDimitry Andric }
9154ba319b5SDimitry Andric if (Ctx.Ptr != Ctx.End)
9167a7e6055SDimitry Andric return make_error<GenericBinaryError>("Global section ended prematurely",
9177a7e6055SDimitry Andric object_error::parse_failed);
9187a7e6055SDimitry Andric return Error::success();
9197a7e6055SDimitry Andric }
9207a7e6055SDimitry Andric
parseEventSection(ReadContext & Ctx)921*b5893f02SDimitry Andric Error WasmObjectFile::parseEventSection(ReadContext &Ctx) {
922*b5893f02SDimitry Andric EventSection = Sections.size();
923*b5893f02SDimitry Andric uint32_t Count = readVarint32(Ctx);
924*b5893f02SDimitry Andric Events.reserve(Count);
925*b5893f02SDimitry Andric while (Count--) {
926*b5893f02SDimitry Andric wasm::WasmEvent Event;
927*b5893f02SDimitry Andric Event.Index = NumImportedEvents + Events.size();
928*b5893f02SDimitry Andric Event.Type.Attribute = readVaruint32(Ctx);
929*b5893f02SDimitry Andric Event.Type.SigIndex = readVarint32(Ctx);
930*b5893f02SDimitry Andric Events.push_back(Event);
931*b5893f02SDimitry Andric }
932*b5893f02SDimitry Andric
933*b5893f02SDimitry Andric if (Ctx.Ptr != Ctx.End)
934*b5893f02SDimitry Andric return make_error<GenericBinaryError>("Event section ended prematurely",
935*b5893f02SDimitry Andric object_error::parse_failed);
936*b5893f02SDimitry Andric return Error::success();
937*b5893f02SDimitry Andric }
938*b5893f02SDimitry Andric
parseExportSection(ReadContext & Ctx)9394ba319b5SDimitry Andric Error WasmObjectFile::parseExportSection(ReadContext &Ctx) {
9404ba319b5SDimitry Andric uint32_t Count = readVaruint32(Ctx);
9417a7e6055SDimitry Andric Exports.reserve(Count);
9420f5676f4SDimitry Andric for (uint32_t i = 0; i < Count; i++) {
9437a7e6055SDimitry Andric wasm::WasmExport Ex;
9444ba319b5SDimitry Andric Ex.Name = readString(Ctx);
9454ba319b5SDimitry Andric Ex.Kind = readUint8(Ctx);
9464ba319b5SDimitry Andric Ex.Index = readVaruint32(Ctx);
9477a7e6055SDimitry Andric switch (Ex.Kind) {
9487a7e6055SDimitry Andric case wasm::WASM_EXTERNAL_FUNCTION:
9494ba319b5SDimitry Andric if (!isValidFunctionIndex(Ex.Index))
9502cab237bSDimitry Andric return make_error<GenericBinaryError>("Invalid function export",
9512cab237bSDimitry Andric object_error::parse_failed);
9527a7e6055SDimitry Andric break;
9534ba319b5SDimitry Andric case wasm::WASM_EXTERNAL_GLOBAL:
9544ba319b5SDimitry Andric if (!isValidGlobalIndex(Ex.Index))
9552cab237bSDimitry Andric return make_error<GenericBinaryError>("Invalid global export",
9562cab237bSDimitry Andric object_error::parse_failed);
9577a7e6055SDimitry Andric break;
958*b5893f02SDimitry Andric case wasm::WASM_EXTERNAL_EVENT:
959*b5893f02SDimitry Andric if (!isValidEventIndex(Ex.Index))
960*b5893f02SDimitry Andric return make_error<GenericBinaryError>("Invalid event export",
961*b5893f02SDimitry Andric object_error::parse_failed);
962*b5893f02SDimitry Andric break;
9635517e702SDimitry Andric case wasm::WASM_EXTERNAL_MEMORY:
9645517e702SDimitry Andric case wasm::WASM_EXTERNAL_TABLE:
9655517e702SDimitry Andric break;
9667a7e6055SDimitry Andric default:
967*b5893f02SDimitry Andric return make_error<GenericBinaryError>("Unexpected export kind",
968*b5893f02SDimitry Andric object_error::parse_failed);
9697a7e6055SDimitry Andric }
970edd7eaddSDimitry Andric Exports.push_back(Ex);
9717a7e6055SDimitry Andric }
9724ba319b5SDimitry Andric if (Ctx.Ptr != Ctx.End)
9737a7e6055SDimitry Andric return make_error<GenericBinaryError>("Export section ended prematurely",
9747a7e6055SDimitry Andric object_error::parse_failed);
9757a7e6055SDimitry Andric return Error::success();
9767a7e6055SDimitry Andric }
9777a7e6055SDimitry Andric
isValidFunctionIndex(uint32_t Index) const9782cab237bSDimitry Andric bool WasmObjectFile::isValidFunctionIndex(uint32_t Index) const {
9794ba319b5SDimitry Andric return Index < NumImportedFunctions + FunctionTypes.size();
9802cab237bSDimitry Andric }
9812cab237bSDimitry Andric
isDefinedFunctionIndex(uint32_t Index) const9824ba319b5SDimitry Andric bool WasmObjectFile::isDefinedFunctionIndex(uint32_t Index) const {
9834ba319b5SDimitry Andric return Index >= NumImportedFunctions && isValidFunctionIndex(Index);
9844ba319b5SDimitry Andric }
9854ba319b5SDimitry Andric
isValidGlobalIndex(uint32_t Index) const9864ba319b5SDimitry Andric bool WasmObjectFile::isValidGlobalIndex(uint32_t Index) const {
9874ba319b5SDimitry Andric return Index < NumImportedGlobals + Globals.size();
9884ba319b5SDimitry Andric }
9894ba319b5SDimitry Andric
isDefinedGlobalIndex(uint32_t Index) const9904ba319b5SDimitry Andric bool WasmObjectFile::isDefinedGlobalIndex(uint32_t Index) const {
9914ba319b5SDimitry Andric return Index >= NumImportedGlobals && isValidGlobalIndex(Index);
9924ba319b5SDimitry Andric }
9934ba319b5SDimitry Andric
isValidEventIndex(uint32_t Index) const994*b5893f02SDimitry Andric bool WasmObjectFile::isValidEventIndex(uint32_t Index) const {
995*b5893f02SDimitry Andric return Index < NumImportedEvents + Events.size();
996*b5893f02SDimitry Andric }
997*b5893f02SDimitry Andric
isDefinedEventIndex(uint32_t Index) const998*b5893f02SDimitry Andric bool WasmObjectFile::isDefinedEventIndex(uint32_t Index) const {
999*b5893f02SDimitry Andric return Index >= NumImportedEvents && isValidEventIndex(Index);
1000*b5893f02SDimitry Andric }
1001*b5893f02SDimitry Andric
isValidFunctionSymbol(uint32_t Index) const10024ba319b5SDimitry Andric bool WasmObjectFile::isValidFunctionSymbol(uint32_t Index) const {
10034ba319b5SDimitry Andric return Index < Symbols.size() && Symbols[Index].isTypeFunction();
10044ba319b5SDimitry Andric }
10054ba319b5SDimitry Andric
isValidGlobalSymbol(uint32_t Index) const10064ba319b5SDimitry Andric bool WasmObjectFile::isValidGlobalSymbol(uint32_t Index) const {
10074ba319b5SDimitry Andric return Index < Symbols.size() && Symbols[Index].isTypeGlobal();
10084ba319b5SDimitry Andric }
10094ba319b5SDimitry Andric
isValidEventSymbol(uint32_t Index) const1010*b5893f02SDimitry Andric bool WasmObjectFile::isValidEventSymbol(uint32_t Index) const {
1011*b5893f02SDimitry Andric return Index < Symbols.size() && Symbols[Index].isTypeEvent();
1012*b5893f02SDimitry Andric }
1013*b5893f02SDimitry Andric
isValidDataSymbol(uint32_t Index) const10144ba319b5SDimitry Andric bool WasmObjectFile::isValidDataSymbol(uint32_t Index) const {
10154ba319b5SDimitry Andric return Index < Symbols.size() && Symbols[Index].isTypeData();
10164ba319b5SDimitry Andric }
10174ba319b5SDimitry Andric
isValidSectionSymbol(uint32_t Index) const10184ba319b5SDimitry Andric bool WasmObjectFile::isValidSectionSymbol(uint32_t Index) const {
10194ba319b5SDimitry Andric return Index < Symbols.size() && Symbols[Index].isTypeSection();
10204ba319b5SDimitry Andric }
10214ba319b5SDimitry Andric
getDefinedFunction(uint32_t Index)10224ba319b5SDimitry Andric wasm::WasmFunction &WasmObjectFile::getDefinedFunction(uint32_t Index) {
10234ba319b5SDimitry Andric assert(isDefinedFunctionIndex(Index));
10244ba319b5SDimitry Andric return Functions[Index - NumImportedFunctions];
10254ba319b5SDimitry Andric }
10264ba319b5SDimitry Andric
getDefinedGlobal(uint32_t Index)10274ba319b5SDimitry Andric wasm::WasmGlobal &WasmObjectFile::getDefinedGlobal(uint32_t Index) {
10284ba319b5SDimitry Andric assert(isDefinedGlobalIndex(Index));
10294ba319b5SDimitry Andric return Globals[Index - NumImportedGlobals];
10304ba319b5SDimitry Andric }
10314ba319b5SDimitry Andric
getDefinedEvent(uint32_t Index)1032*b5893f02SDimitry Andric wasm::WasmEvent &WasmObjectFile::getDefinedEvent(uint32_t Index) {
1033*b5893f02SDimitry Andric assert(isDefinedEventIndex(Index));
1034*b5893f02SDimitry Andric return Events[Index - NumImportedEvents];
1035*b5893f02SDimitry Andric }
1036*b5893f02SDimitry Andric
parseStartSection(ReadContext & Ctx)10374ba319b5SDimitry Andric Error WasmObjectFile::parseStartSection(ReadContext &Ctx) {
10384ba319b5SDimitry Andric StartFunction = readVaruint32(Ctx);
10392cab237bSDimitry Andric if (!isValidFunctionIndex(StartFunction))
10407a7e6055SDimitry Andric return make_error<GenericBinaryError>("Invalid start function",
10417a7e6055SDimitry Andric object_error::parse_failed);
10427a7e6055SDimitry Andric return Error::success();
10437a7e6055SDimitry Andric }
10447a7e6055SDimitry Andric
parseCodeSection(ReadContext & Ctx)10454ba319b5SDimitry Andric Error WasmObjectFile::parseCodeSection(ReadContext &Ctx) {
10464ba319b5SDimitry Andric CodeSection = Sections.size();
10474ba319b5SDimitry Andric uint32_t FunctionCount = readVaruint32(Ctx);
10487a7e6055SDimitry Andric if (FunctionCount != FunctionTypes.size()) {
10497a7e6055SDimitry Andric return make_error<GenericBinaryError>("Invalid function count",
10507a7e6055SDimitry Andric object_error::parse_failed);
10517a7e6055SDimitry Andric }
10527a7e6055SDimitry Andric
10537a7e6055SDimitry Andric while (FunctionCount--) {
10547a7e6055SDimitry Andric wasm::WasmFunction Function;
10554ba319b5SDimitry Andric const uint8_t *FunctionStart = Ctx.Ptr;
10564ba319b5SDimitry Andric uint32_t Size = readVaruint32(Ctx);
10574ba319b5SDimitry Andric const uint8_t *FunctionEnd = Ctx.Ptr + Size;
10582cab237bSDimitry Andric
10594ba319b5SDimitry Andric Function.CodeOffset = Ctx.Ptr - FunctionStart;
10604ba319b5SDimitry Andric Function.Index = NumImportedFunctions + Functions.size();
10614ba319b5SDimitry Andric Function.CodeSectionOffset = FunctionStart - Ctx.Start;
10622cab237bSDimitry Andric Function.Size = FunctionEnd - FunctionStart;
10637a7e6055SDimitry Andric
10644ba319b5SDimitry Andric uint32_t NumLocalDecls = readVaruint32(Ctx);
10657a7e6055SDimitry Andric Function.Locals.reserve(NumLocalDecls);
10667a7e6055SDimitry Andric while (NumLocalDecls--) {
10677a7e6055SDimitry Andric wasm::WasmLocalDecl Decl;
10684ba319b5SDimitry Andric Decl.Count = readVaruint32(Ctx);
10694ba319b5SDimitry Andric Decl.Type = readUint8(Ctx);
10707a7e6055SDimitry Andric Function.Locals.push_back(Decl);
10717a7e6055SDimitry Andric }
10727a7e6055SDimitry Andric
10734ba319b5SDimitry Andric uint32_t BodySize = FunctionEnd - Ctx.Ptr;
10744ba319b5SDimitry Andric Function.Body = ArrayRef<uint8_t>(Ctx.Ptr, BodySize);
10754ba319b5SDimitry Andric // This will be set later when reading in the linking metadata section.
10764ba319b5SDimitry Andric Function.Comdat = UINT32_MAX;
10774ba319b5SDimitry Andric Ctx.Ptr += BodySize;
10784ba319b5SDimitry Andric assert(Ctx.Ptr == FunctionEnd);
10797a7e6055SDimitry Andric Functions.push_back(Function);
10807a7e6055SDimitry Andric }
10814ba319b5SDimitry Andric if (Ctx.Ptr != Ctx.End)
10827a7e6055SDimitry Andric return make_error<GenericBinaryError>("Code section ended prematurely",
10837a7e6055SDimitry Andric object_error::parse_failed);
10847a7e6055SDimitry Andric return Error::success();
10857a7e6055SDimitry Andric }
10867a7e6055SDimitry Andric
parseElemSection(ReadContext & Ctx)10874ba319b5SDimitry Andric Error WasmObjectFile::parseElemSection(ReadContext &Ctx) {
10884ba319b5SDimitry Andric uint32_t Count = readVaruint32(Ctx);
10897a7e6055SDimitry Andric ElemSegments.reserve(Count);
10907a7e6055SDimitry Andric while (Count--) {
10917a7e6055SDimitry Andric wasm::WasmElemSegment Segment;
10924ba319b5SDimitry Andric Segment.TableIndex = readVaruint32(Ctx);
10937a7e6055SDimitry Andric if (Segment.TableIndex != 0) {
10947a7e6055SDimitry Andric return make_error<GenericBinaryError>("Invalid TableIndex",
10957a7e6055SDimitry Andric object_error::parse_failed);
10967a7e6055SDimitry Andric }
10974ba319b5SDimitry Andric if (Error Err = readInitExpr(Segment.Offset, Ctx))
10987a7e6055SDimitry Andric return Err;
10994ba319b5SDimitry Andric uint32_t NumElems = readVaruint32(Ctx);
11007a7e6055SDimitry Andric while (NumElems--) {
11014ba319b5SDimitry Andric Segment.Functions.push_back(readVaruint32(Ctx));
11027a7e6055SDimitry Andric }
11037a7e6055SDimitry Andric ElemSegments.push_back(Segment);
11047a7e6055SDimitry Andric }
11054ba319b5SDimitry Andric if (Ctx.Ptr != Ctx.End)
11067a7e6055SDimitry Andric return make_error<GenericBinaryError>("Elem section ended prematurely",
11077a7e6055SDimitry Andric object_error::parse_failed);
11087a7e6055SDimitry Andric return Error::success();
11097a7e6055SDimitry Andric }
11107a7e6055SDimitry Andric
parseDataSection(ReadContext & Ctx)11114ba319b5SDimitry Andric Error WasmObjectFile::parseDataSection(ReadContext &Ctx) {
11124ba319b5SDimitry Andric DataSection = Sections.size();
11134ba319b5SDimitry Andric uint32_t Count = readVaruint32(Ctx);
11147a7e6055SDimitry Andric DataSegments.reserve(Count);
11157a7e6055SDimitry Andric while (Count--) {
1116c4394386SDimitry Andric WasmSegment Segment;
11174ba319b5SDimitry Andric Segment.Data.MemoryIndex = readVaruint32(Ctx);
11184ba319b5SDimitry Andric if (Error Err = readInitExpr(Segment.Data.Offset, Ctx))
11197a7e6055SDimitry Andric return Err;
11204ba319b5SDimitry Andric uint32_t Size = readVaruint32(Ctx);
11214ba319b5SDimitry Andric if (Size > (size_t)(Ctx.End - Ctx.Ptr))
11224ba319b5SDimitry Andric return make_error<GenericBinaryError>("Invalid segment size",
11234ba319b5SDimitry Andric object_error::parse_failed);
11244ba319b5SDimitry Andric Segment.Data.Content = ArrayRef<uint8_t>(Ctx.Ptr, Size);
11254ba319b5SDimitry Andric // The rest of these Data fields are set later, when reading in the linking
11264ba319b5SDimitry Andric // metadata section.
11272cab237bSDimitry Andric Segment.Data.Alignment = 0;
11282cab237bSDimitry Andric Segment.Data.Flags = 0;
11294ba319b5SDimitry Andric Segment.Data.Comdat = UINT32_MAX;
11304ba319b5SDimitry Andric Segment.SectionOffset = Ctx.Ptr - Ctx.Start;
11314ba319b5SDimitry Andric Ctx.Ptr += Size;
11327a7e6055SDimitry Andric DataSegments.push_back(Segment);
11337a7e6055SDimitry Andric }
11344ba319b5SDimitry Andric if (Ctx.Ptr != Ctx.End)
11357a7e6055SDimitry Andric return make_error<GenericBinaryError>("Data section ended prematurely",
11367a7e6055SDimitry Andric object_error::parse_failed);
1137d88c1a5aSDimitry Andric return Error::success();
1138d88c1a5aSDimitry Andric }
1139d88c1a5aSDimitry Andric
getPtr(size_t Offset) const1140d88c1a5aSDimitry Andric const uint8_t *WasmObjectFile::getPtr(size_t Offset) const {
11414ba319b5SDimitry Andric return reinterpret_cast<const uint8_t *>(getData().data() + Offset);
1142d88c1a5aSDimitry Andric }
1143d88c1a5aSDimitry Andric
getHeader() const1144d88c1a5aSDimitry Andric const wasm::WasmObjectHeader &WasmObjectFile::getHeader() const {
1145d88c1a5aSDimitry Andric return Header;
1146d88c1a5aSDimitry Andric }
1147d88c1a5aSDimitry Andric
moveSymbolNext(DataRefImpl & Symb) const11487a7e6055SDimitry Andric void WasmObjectFile::moveSymbolNext(DataRefImpl &Symb) const { Symb.d.a++; }
1149d88c1a5aSDimitry Andric
getSymbolFlags(DataRefImpl Symb) const1150d88c1a5aSDimitry Andric uint32_t WasmObjectFile::getSymbolFlags(DataRefImpl Symb) const {
11510f5676f4SDimitry Andric uint32_t Result = SymbolRef::SF_None;
11527a7e6055SDimitry Andric const WasmSymbol &Sym = getWasmSymbol(Symb);
11530f5676f4SDimitry Andric
11544ba319b5SDimitry Andric LLVM_DEBUG(dbgs() << "getSymbolFlags: ptr=" << &Sym << " " << Sym << "\n");
11554ba319b5SDimitry Andric if (Sym.isBindingWeak())
1156edd7eaddSDimitry Andric Result |= SymbolRef::SF_Weak;
11574ba319b5SDimitry Andric if (!Sym.isBindingLocal())
11582cab237bSDimitry Andric Result |= SymbolRef::SF_Global;
11592cab237bSDimitry Andric if (Sym.isHidden())
11602cab237bSDimitry Andric Result |= SymbolRef::SF_Hidden;
11614ba319b5SDimitry Andric if (!Sym.isDefined())
11620f5676f4SDimitry Andric Result |= SymbolRef::SF_Undefined;
11634ba319b5SDimitry Andric if (Sym.isTypeFunction())
11644ba319b5SDimitry Andric Result |= SymbolRef::SF_Executable;
11650f5676f4SDimitry Andric return Result;
1166d88c1a5aSDimitry Andric }
1167d88c1a5aSDimitry Andric
symbol_begin() const1168d88c1a5aSDimitry Andric basic_symbol_iterator WasmObjectFile::symbol_begin() const {
11697a7e6055SDimitry Andric DataRefImpl Ref;
11707a7e6055SDimitry Andric Ref.d.a = 0;
11717a7e6055SDimitry Andric return BasicSymbolRef(Ref, this);
1172d88c1a5aSDimitry Andric }
1173d88c1a5aSDimitry Andric
symbol_end() const1174d88c1a5aSDimitry Andric basic_symbol_iterator WasmObjectFile::symbol_end() const {
11757a7e6055SDimitry Andric DataRefImpl Ref;
11767a7e6055SDimitry Andric Ref.d.a = Symbols.size();
11777a7e6055SDimitry Andric return BasicSymbolRef(Ref, this);
11787a7e6055SDimitry Andric }
11797a7e6055SDimitry Andric
getWasmSymbol(const DataRefImpl & Symb) const11805517e702SDimitry Andric const WasmSymbol &WasmObjectFile::getWasmSymbol(const DataRefImpl &Symb) const {
11817a7e6055SDimitry Andric return Symbols[Symb.d.a];
1182d88c1a5aSDimitry Andric }
1183d88c1a5aSDimitry Andric
getWasmSymbol(const SymbolRef & Symb) const11845517e702SDimitry Andric const WasmSymbol &WasmObjectFile::getWasmSymbol(const SymbolRef &Symb) const {
11855517e702SDimitry Andric return getWasmSymbol(Symb.getRawDataRefImpl());
11865517e702SDimitry Andric }
11875517e702SDimitry Andric
getSymbolName(DataRefImpl Symb) const1188d88c1a5aSDimitry Andric Expected<StringRef> WasmObjectFile::getSymbolName(DataRefImpl Symb) const {
11894ba319b5SDimitry Andric return getWasmSymbol(Symb).Info.Name;
1190d88c1a5aSDimitry Andric }
1191d88c1a5aSDimitry Andric
getSymbolAddress(DataRefImpl Symb) const1192d88c1a5aSDimitry Andric Expected<uint64_t> WasmObjectFile::getSymbolAddress(DataRefImpl Symb) const {
11930f5676f4SDimitry Andric return getSymbolValue(Symb);
1194d88c1a5aSDimitry Andric }
1195d88c1a5aSDimitry Andric
getWasmSymbolValue(const WasmSymbol & Sym) const11962cab237bSDimitry Andric uint64_t WasmObjectFile::getWasmSymbolValue(const WasmSymbol &Sym) const {
11974ba319b5SDimitry Andric switch (Sym.Info.Kind) {
11984ba319b5SDimitry Andric case wasm::WASM_SYMBOL_TYPE_FUNCTION:
11994ba319b5SDimitry Andric case wasm::WASM_SYMBOL_TYPE_GLOBAL:
1200*b5893f02SDimitry Andric case wasm::WASM_SYMBOL_TYPE_EVENT:
12014ba319b5SDimitry Andric return Sym.Info.ElementIndex;
12024ba319b5SDimitry Andric case wasm::WASM_SYMBOL_TYPE_DATA: {
12034ba319b5SDimitry Andric // The value of a data symbol is the segment offset, plus the symbol
12044ba319b5SDimitry Andric // offset within the segment.
12054ba319b5SDimitry Andric uint32_t SegmentIndex = Sym.Info.DataRef.Segment;
12064ba319b5SDimitry Andric const wasm::WasmDataSegment &Segment = DataSegments[SegmentIndex].Data;
12074ba319b5SDimitry Andric assert(Segment.Offset.Opcode == wasm::WASM_OPCODE_I32_CONST);
12084ba319b5SDimitry Andric return Segment.Offset.Value.Int32 + Sym.Info.DataRef.Offset;
12092cab237bSDimitry Andric }
12104ba319b5SDimitry Andric case wasm::WASM_SYMBOL_TYPE_SECTION:
12114ba319b5SDimitry Andric return 0;
1212d88c1a5aSDimitry Andric }
1213edd7eaddSDimitry Andric llvm_unreachable("invalid symbol type");
1214edd7eaddSDimitry Andric }
1215d88c1a5aSDimitry Andric
getSymbolValueImpl(DataRefImpl Symb) const12162cab237bSDimitry Andric uint64_t WasmObjectFile::getSymbolValueImpl(DataRefImpl Symb) const {
12172cab237bSDimitry Andric return getWasmSymbolValue(getWasmSymbol(Symb));
12182cab237bSDimitry Andric }
12192cab237bSDimitry Andric
getSymbolAlignment(DataRefImpl Symb) const1220d88c1a5aSDimitry Andric uint32_t WasmObjectFile::getSymbolAlignment(DataRefImpl Symb) const {
1221d88c1a5aSDimitry Andric llvm_unreachable("not yet implemented");
1222d88c1a5aSDimitry Andric return 0;
1223d88c1a5aSDimitry Andric }
1224d88c1a5aSDimitry Andric
getCommonSymbolSizeImpl(DataRefImpl Symb) const1225d88c1a5aSDimitry Andric uint64_t WasmObjectFile::getCommonSymbolSizeImpl(DataRefImpl Symb) const {
1226d88c1a5aSDimitry Andric llvm_unreachable("not yet implemented");
1227d88c1a5aSDimitry Andric return 0;
1228d88c1a5aSDimitry Andric }
1229d88c1a5aSDimitry Andric
1230d88c1a5aSDimitry Andric Expected<SymbolRef::Type>
getSymbolType(DataRefImpl Symb) const1231d88c1a5aSDimitry Andric WasmObjectFile::getSymbolType(DataRefImpl Symb) const {
12320f5676f4SDimitry Andric const WasmSymbol &Sym = getWasmSymbol(Symb);
12330f5676f4SDimitry Andric
12344ba319b5SDimitry Andric switch (Sym.Info.Kind) {
12354ba319b5SDimitry Andric case wasm::WASM_SYMBOL_TYPE_FUNCTION:
12360f5676f4SDimitry Andric return SymbolRef::ST_Function;
12374ba319b5SDimitry Andric case wasm::WASM_SYMBOL_TYPE_GLOBAL:
12384ba319b5SDimitry Andric return SymbolRef::ST_Other;
12394ba319b5SDimitry Andric case wasm::WASM_SYMBOL_TYPE_DATA:
12400f5676f4SDimitry Andric return SymbolRef::ST_Data;
12414ba319b5SDimitry Andric case wasm::WASM_SYMBOL_TYPE_SECTION:
12424ba319b5SDimitry Andric return SymbolRef::ST_Debug;
1243*b5893f02SDimitry Andric case wasm::WASM_SYMBOL_TYPE_EVENT:
1244*b5893f02SDimitry Andric return SymbolRef::ST_Other;
12450f5676f4SDimitry Andric }
12460f5676f4SDimitry Andric
12470f5676f4SDimitry Andric llvm_unreachable("Unknown WasmSymbol::SymbolType");
12480f5676f4SDimitry Andric return SymbolRef::ST_Other;
1249d88c1a5aSDimitry Andric }
1250d88c1a5aSDimitry Andric
1251d88c1a5aSDimitry Andric Expected<section_iterator>
getSymbolSection(DataRefImpl Symb) const1252d88c1a5aSDimitry Andric WasmObjectFile::getSymbolSection(DataRefImpl Symb) const {
12534ba319b5SDimitry Andric const WasmSymbol &Sym = getWasmSymbol(Symb);
12544ba319b5SDimitry Andric if (Sym.isUndefined())
12554ba319b5SDimitry Andric return section_end();
12564ba319b5SDimitry Andric
12570f5676f4SDimitry Andric DataRefImpl Ref;
12584ba319b5SDimitry Andric switch (Sym.Info.Kind) {
12594ba319b5SDimitry Andric case wasm::WASM_SYMBOL_TYPE_FUNCTION:
12604ba319b5SDimitry Andric Ref.d.a = CodeSection;
12614ba319b5SDimitry Andric break;
12624ba319b5SDimitry Andric case wasm::WASM_SYMBOL_TYPE_GLOBAL:
12634ba319b5SDimitry Andric Ref.d.a = GlobalSection;
12644ba319b5SDimitry Andric break;
12654ba319b5SDimitry Andric case wasm::WASM_SYMBOL_TYPE_DATA:
12664ba319b5SDimitry Andric Ref.d.a = DataSection;
12674ba319b5SDimitry Andric break;
1268*b5893f02SDimitry Andric case wasm::WASM_SYMBOL_TYPE_SECTION:
12694ba319b5SDimitry Andric Ref.d.a = Sym.Info.ElementIndex;
12704ba319b5SDimitry Andric break;
1271*b5893f02SDimitry Andric case wasm::WASM_SYMBOL_TYPE_EVENT:
1272*b5893f02SDimitry Andric Ref.d.a = EventSection;
1273*b5893f02SDimitry Andric break;
12744ba319b5SDimitry Andric default:
12754ba319b5SDimitry Andric llvm_unreachable("Unknown WasmSymbol::SymbolType");
12764ba319b5SDimitry Andric }
12770f5676f4SDimitry Andric return section_iterator(SectionRef(Ref, this));
1278d88c1a5aSDimitry Andric }
1279d88c1a5aSDimitry Andric
moveSectionNext(DataRefImpl & Sec) const1280d88c1a5aSDimitry Andric void WasmObjectFile::moveSectionNext(DataRefImpl &Sec) const { Sec.d.a++; }
1281d88c1a5aSDimitry Andric
getSectionName(DataRefImpl Sec,StringRef & Res) const1282d88c1a5aSDimitry Andric std::error_code WasmObjectFile::getSectionName(DataRefImpl Sec,
1283d88c1a5aSDimitry Andric StringRef &Res) const {
12847a7e6055SDimitry Andric const WasmSection &S = Sections[Sec.d.a];
1285d88c1a5aSDimitry Andric #define ECase(X) \
1286d88c1a5aSDimitry Andric case wasm::WASM_SEC_##X: \
1287d88c1a5aSDimitry Andric Res = #X; \
1288d88c1a5aSDimitry Andric break
1289d88c1a5aSDimitry Andric switch (S.Type) {
1290d88c1a5aSDimitry Andric ECase(TYPE);
1291d88c1a5aSDimitry Andric ECase(IMPORT);
1292d88c1a5aSDimitry Andric ECase(FUNCTION);
1293d88c1a5aSDimitry Andric ECase(TABLE);
1294d88c1a5aSDimitry Andric ECase(MEMORY);
1295d88c1a5aSDimitry Andric ECase(GLOBAL);
1296*b5893f02SDimitry Andric ECase(EVENT);
1297d88c1a5aSDimitry Andric ECase(EXPORT);
1298d88c1a5aSDimitry Andric ECase(START);
1299d88c1a5aSDimitry Andric ECase(ELEM);
1300d88c1a5aSDimitry Andric ECase(CODE);
1301d88c1a5aSDimitry Andric ECase(DATA);
13027a7e6055SDimitry Andric case wasm::WASM_SEC_CUSTOM:
1303d88c1a5aSDimitry Andric Res = S.Name;
1304d88c1a5aSDimitry Andric break;
1305d88c1a5aSDimitry Andric default:
1306d88c1a5aSDimitry Andric return object_error::invalid_section_index;
1307d88c1a5aSDimitry Andric }
1308d88c1a5aSDimitry Andric #undef ECase
1309d88c1a5aSDimitry Andric return std::error_code();
1310d88c1a5aSDimitry Andric }
1311d88c1a5aSDimitry Andric
getSectionAddress(DataRefImpl Sec) const1312d88c1a5aSDimitry Andric uint64_t WasmObjectFile::getSectionAddress(DataRefImpl Sec) const { return 0; }
1313d88c1a5aSDimitry Andric
getSectionIndex(DataRefImpl Sec) const1314302affcbSDimitry Andric uint64_t WasmObjectFile::getSectionIndex(DataRefImpl Sec) const {
1315302affcbSDimitry Andric return Sec.d.a;
1316302affcbSDimitry Andric }
1317302affcbSDimitry Andric
getSectionSize(DataRefImpl Sec) const1318d88c1a5aSDimitry Andric uint64_t WasmObjectFile::getSectionSize(DataRefImpl Sec) const {
13197a7e6055SDimitry Andric const WasmSection &S = Sections[Sec.d.a];
1320d88c1a5aSDimitry Andric return S.Content.size();
1321d88c1a5aSDimitry Andric }
1322d88c1a5aSDimitry Andric
getSectionContents(DataRefImpl Sec,StringRef & Res) const1323d88c1a5aSDimitry Andric std::error_code WasmObjectFile::getSectionContents(DataRefImpl Sec,
1324d88c1a5aSDimitry Andric StringRef &Res) const {
13257a7e6055SDimitry Andric const WasmSection &S = Sections[Sec.d.a];
1326d88c1a5aSDimitry Andric // This will never fail since wasm sections can never be empty (user-sections
1327d88c1a5aSDimitry Andric // must have a name and non-user sections each have a defined structure).
1328d88c1a5aSDimitry Andric Res = StringRef(reinterpret_cast<const char *>(S.Content.data()),
1329d88c1a5aSDimitry Andric S.Content.size());
1330d88c1a5aSDimitry Andric return std::error_code();
1331d88c1a5aSDimitry Andric }
1332d88c1a5aSDimitry Andric
getSectionAlignment(DataRefImpl Sec) const1333d88c1a5aSDimitry Andric uint64_t WasmObjectFile::getSectionAlignment(DataRefImpl Sec) const {
1334d88c1a5aSDimitry Andric return 1;
1335d88c1a5aSDimitry Andric }
1336d88c1a5aSDimitry Andric
isSectionCompressed(DataRefImpl Sec) const1337d88c1a5aSDimitry Andric bool WasmObjectFile::isSectionCompressed(DataRefImpl Sec) const {
1338d88c1a5aSDimitry Andric return false;
1339d88c1a5aSDimitry Andric }
1340d88c1a5aSDimitry Andric
isSectionText(DataRefImpl Sec) const1341d88c1a5aSDimitry Andric bool WasmObjectFile::isSectionText(DataRefImpl Sec) const {
13427a7e6055SDimitry Andric return getWasmSection(Sec).Type == wasm::WASM_SEC_CODE;
1343d88c1a5aSDimitry Andric }
1344d88c1a5aSDimitry Andric
isSectionData(DataRefImpl Sec) const1345d88c1a5aSDimitry Andric bool WasmObjectFile::isSectionData(DataRefImpl Sec) const {
13467a7e6055SDimitry Andric return getWasmSection(Sec).Type == wasm::WASM_SEC_DATA;
1347d88c1a5aSDimitry Andric }
1348d88c1a5aSDimitry Andric
isSectionBSS(DataRefImpl Sec) const1349d88c1a5aSDimitry Andric bool WasmObjectFile::isSectionBSS(DataRefImpl Sec) const { return false; }
1350d88c1a5aSDimitry Andric
isSectionVirtual(DataRefImpl Sec) const1351d88c1a5aSDimitry Andric bool WasmObjectFile::isSectionVirtual(DataRefImpl Sec) const { return false; }
1352d88c1a5aSDimitry Andric
isSectionBitcode(DataRefImpl Sec) const1353d88c1a5aSDimitry Andric bool WasmObjectFile::isSectionBitcode(DataRefImpl Sec) const { return false; }
1354d88c1a5aSDimitry Andric
section_rel_begin(DataRefImpl Ref) const13557a7e6055SDimitry Andric relocation_iterator WasmObjectFile::section_rel_begin(DataRefImpl Ref) const {
13567a7e6055SDimitry Andric DataRefImpl RelocRef;
13577a7e6055SDimitry Andric RelocRef.d.a = Ref.d.a;
13587a7e6055SDimitry Andric RelocRef.d.b = 0;
13597a7e6055SDimitry Andric return relocation_iterator(RelocationRef(RelocRef, this));
1360d88c1a5aSDimitry Andric }
1361d88c1a5aSDimitry Andric
section_rel_end(DataRefImpl Ref) const13627a7e6055SDimitry Andric relocation_iterator WasmObjectFile::section_rel_end(DataRefImpl Ref) const {
13637a7e6055SDimitry Andric const WasmSection &Sec = getWasmSection(Ref);
13647a7e6055SDimitry Andric DataRefImpl RelocRef;
13657a7e6055SDimitry Andric RelocRef.d.a = Ref.d.a;
13667a7e6055SDimitry Andric RelocRef.d.b = Sec.Relocations.size();
13677a7e6055SDimitry Andric return relocation_iterator(RelocationRef(RelocRef, this));
1368d88c1a5aSDimitry Andric }
1369d88c1a5aSDimitry Andric
moveRelocationNext(DataRefImpl & Rel) const1370*b5893f02SDimitry Andric void WasmObjectFile::moveRelocationNext(DataRefImpl &Rel) const { Rel.d.b++; }
1371d88c1a5aSDimitry Andric
getRelocationOffset(DataRefImpl Ref) const13727a7e6055SDimitry Andric uint64_t WasmObjectFile::getRelocationOffset(DataRefImpl Ref) const {
13737a7e6055SDimitry Andric const wasm::WasmRelocation &Rel = getWasmRelocation(Ref);
13747a7e6055SDimitry Andric return Rel.Offset;
1375d88c1a5aSDimitry Andric }
1376d88c1a5aSDimitry Andric
getRelocationSymbol(DataRefImpl Ref) const13774ba319b5SDimitry Andric symbol_iterator WasmObjectFile::getRelocationSymbol(DataRefImpl Ref) const {
13784ba319b5SDimitry Andric const wasm::WasmRelocation &Rel = getWasmRelocation(Ref);
13794ba319b5SDimitry Andric if (Rel.Type == wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB)
13804ba319b5SDimitry Andric return symbol_end();
13814ba319b5SDimitry Andric DataRefImpl Sym;
13824ba319b5SDimitry Andric Sym.d.a = Rel.Index;
13834ba319b5SDimitry Andric Sym.d.b = 0;
13844ba319b5SDimitry Andric return symbol_iterator(SymbolRef(Sym, this));
1385d88c1a5aSDimitry Andric }
1386d88c1a5aSDimitry Andric
getRelocationType(DataRefImpl Ref) const13877a7e6055SDimitry Andric uint64_t WasmObjectFile::getRelocationType(DataRefImpl Ref) const {
13887a7e6055SDimitry Andric const wasm::WasmRelocation &Rel = getWasmRelocation(Ref);
13897a7e6055SDimitry Andric return Rel.Type;
1390d88c1a5aSDimitry Andric }
1391d88c1a5aSDimitry Andric
getRelocationTypeName(DataRefImpl Ref,SmallVectorImpl<char> & Result) const1392d88c1a5aSDimitry Andric void WasmObjectFile::getRelocationTypeName(
13937a7e6055SDimitry Andric DataRefImpl Ref, SmallVectorImpl<char> &Result) const {
13947a7e6055SDimitry Andric const wasm::WasmRelocation &Rel = getWasmRelocation(Ref);
13957a7e6055SDimitry Andric StringRef Res = "Unknown";
13967a7e6055SDimitry Andric
13977a7e6055SDimitry Andric #define WASM_RELOC(name, value) \
13987a7e6055SDimitry Andric case wasm::name: \
13997a7e6055SDimitry Andric Res = #name; \
14007a7e6055SDimitry Andric break;
14017a7e6055SDimitry Andric
14027a7e6055SDimitry Andric switch (Rel.Type) {
1403da09e106SDimitry Andric #include "llvm/BinaryFormat/WasmRelocs.def"
14047a7e6055SDimitry Andric }
14057a7e6055SDimitry Andric
14067a7e6055SDimitry Andric #undef WASM_RELOC
14077a7e6055SDimitry Andric
14087a7e6055SDimitry Andric Result.append(Res.begin(), Res.end());
1409d88c1a5aSDimitry Andric }
1410d88c1a5aSDimitry Andric
section_begin() const1411d88c1a5aSDimitry Andric section_iterator WasmObjectFile::section_begin() const {
1412d88c1a5aSDimitry Andric DataRefImpl Ref;
1413d88c1a5aSDimitry Andric Ref.d.a = 0;
1414d88c1a5aSDimitry Andric return section_iterator(SectionRef(Ref, this));
1415d88c1a5aSDimitry Andric }
1416d88c1a5aSDimitry Andric
section_end() const1417d88c1a5aSDimitry Andric section_iterator WasmObjectFile::section_end() const {
1418d88c1a5aSDimitry Andric DataRefImpl Ref;
1419d88c1a5aSDimitry Andric Ref.d.a = Sections.size();
1420d88c1a5aSDimitry Andric return section_iterator(SectionRef(Ref, this));
1421d88c1a5aSDimitry Andric }
1422d88c1a5aSDimitry Andric
getBytesInAddress() const1423d88c1a5aSDimitry Andric uint8_t WasmObjectFile::getBytesInAddress() const { return 4; }
1424d88c1a5aSDimitry Andric
getFileFormatName() const1425d88c1a5aSDimitry Andric StringRef WasmObjectFile::getFileFormatName() const { return "WASM"; }
1426d88c1a5aSDimitry Andric
getArch() const14272cab237bSDimitry Andric Triple::ArchType WasmObjectFile::getArch() const { return Triple::wasm32; }
1428d88c1a5aSDimitry Andric
getFeatures() const1429d88c1a5aSDimitry Andric SubtargetFeatures WasmObjectFile::getFeatures() const {
1430d88c1a5aSDimitry Andric return SubtargetFeatures();
1431d88c1a5aSDimitry Andric }
1432d88c1a5aSDimitry Andric
isRelocatableObject() const1433*b5893f02SDimitry Andric bool WasmObjectFile::isRelocatableObject() const { return HasLinkingSection; }
1434*b5893f02SDimitry Andric
isSharedObject() const1435*b5893f02SDimitry Andric bool WasmObjectFile::isSharedObject() const { return HasDylinkSection; }
1436d88c1a5aSDimitry Andric
getWasmSection(DataRefImpl Ref) const14377a7e6055SDimitry Andric const WasmSection &WasmObjectFile::getWasmSection(DataRefImpl Ref) const {
14387a7e6055SDimitry Andric assert(Ref.d.a < Sections.size());
14397a7e6055SDimitry Andric return Sections[Ref.d.a];
1440d88c1a5aSDimitry Andric }
1441d88c1a5aSDimitry Andric
14427a7e6055SDimitry Andric const WasmSection &
getWasmSection(const SectionRef & Section) const14437a7e6055SDimitry Andric WasmObjectFile::getWasmSection(const SectionRef &Section) const {
14447a7e6055SDimitry Andric return getWasmSection(Section.getRawDataRefImpl());
14457a7e6055SDimitry Andric }
14467a7e6055SDimitry Andric
14477a7e6055SDimitry Andric const wasm::WasmRelocation &
getWasmRelocation(const RelocationRef & Ref) const14487a7e6055SDimitry Andric WasmObjectFile::getWasmRelocation(const RelocationRef &Ref) const {
14497a7e6055SDimitry Andric return getWasmRelocation(Ref.getRawDataRefImpl());
14507a7e6055SDimitry Andric }
14517a7e6055SDimitry Andric
14527a7e6055SDimitry Andric const wasm::WasmRelocation &
getWasmRelocation(DataRefImpl Ref) const14537a7e6055SDimitry Andric WasmObjectFile::getWasmRelocation(DataRefImpl Ref) const {
14547a7e6055SDimitry Andric assert(Ref.d.a < Sections.size());
14557a7e6055SDimitry Andric const WasmSection &Sec = Sections[Ref.d.a];
14567a7e6055SDimitry Andric assert(Ref.d.b < Sec.Relocations.size());
14577a7e6055SDimitry Andric return Sec.Relocations[Ref.d.b];
14587a7e6055SDimitry Andric }
1459*b5893f02SDimitry Andric
getSectionOrder(unsigned ID,StringRef CustomSectionName)1460*b5893f02SDimitry Andric int WasmSectionOrderChecker::getSectionOrder(unsigned ID,
1461*b5893f02SDimitry Andric StringRef CustomSectionName) {
1462*b5893f02SDimitry Andric switch (ID) {
1463*b5893f02SDimitry Andric case wasm::WASM_SEC_CUSTOM:
1464*b5893f02SDimitry Andric return StringSwitch<unsigned>(CustomSectionName)
1465*b5893f02SDimitry Andric .Case("dylink", WASM_SEC_ORDER_DYLINK)
1466*b5893f02SDimitry Andric .Case("linking", WASM_SEC_ORDER_LINKING)
1467*b5893f02SDimitry Andric .StartsWith("reloc.", WASM_SEC_ORDER_RELOC)
1468*b5893f02SDimitry Andric .Case("name", WASM_SEC_ORDER_NAME)
1469*b5893f02SDimitry Andric .Case("producers", WASM_SEC_ORDER_PRODUCERS)
1470*b5893f02SDimitry Andric .Default(-1);
1471*b5893f02SDimitry Andric case wasm::WASM_SEC_TYPE:
1472*b5893f02SDimitry Andric return WASM_SEC_ORDER_TYPE;
1473*b5893f02SDimitry Andric case wasm::WASM_SEC_IMPORT:
1474*b5893f02SDimitry Andric return WASM_SEC_ORDER_IMPORT;
1475*b5893f02SDimitry Andric case wasm::WASM_SEC_FUNCTION:
1476*b5893f02SDimitry Andric return WASM_SEC_ORDER_FUNCTION;
1477*b5893f02SDimitry Andric case wasm::WASM_SEC_TABLE:
1478*b5893f02SDimitry Andric return WASM_SEC_ORDER_TABLE;
1479*b5893f02SDimitry Andric case wasm::WASM_SEC_MEMORY:
1480*b5893f02SDimitry Andric return WASM_SEC_ORDER_MEMORY;
1481*b5893f02SDimitry Andric case wasm::WASM_SEC_GLOBAL:
1482*b5893f02SDimitry Andric return WASM_SEC_ORDER_GLOBAL;
1483*b5893f02SDimitry Andric case wasm::WASM_SEC_EXPORT:
1484*b5893f02SDimitry Andric return WASM_SEC_ORDER_EXPORT;
1485*b5893f02SDimitry Andric case wasm::WASM_SEC_START:
1486*b5893f02SDimitry Andric return WASM_SEC_ORDER_START;
1487*b5893f02SDimitry Andric case wasm::WASM_SEC_ELEM:
1488*b5893f02SDimitry Andric return WASM_SEC_ORDER_ELEM;
1489*b5893f02SDimitry Andric case wasm::WASM_SEC_CODE:
1490*b5893f02SDimitry Andric return WASM_SEC_ORDER_CODE;
1491*b5893f02SDimitry Andric case wasm::WASM_SEC_DATA:
1492*b5893f02SDimitry Andric return WASM_SEC_ORDER_DATA;
1493*b5893f02SDimitry Andric case wasm::WASM_SEC_DATACOUNT:
1494*b5893f02SDimitry Andric return WASM_SEC_ORDER_DATACOUNT;
1495*b5893f02SDimitry Andric case wasm::WASM_SEC_EVENT:
1496*b5893f02SDimitry Andric return WASM_SEC_ORDER_EVENT;
1497*b5893f02SDimitry Andric default:
1498*b5893f02SDimitry Andric llvm_unreachable("invalid section");
1499*b5893f02SDimitry Andric }
1500*b5893f02SDimitry Andric }
1501*b5893f02SDimitry Andric
isValidSectionOrder(unsigned ID,StringRef CustomSectionName)1502*b5893f02SDimitry Andric bool WasmSectionOrderChecker::isValidSectionOrder(unsigned ID,
1503*b5893f02SDimitry Andric StringRef CustomSectionName) {
1504*b5893f02SDimitry Andric int Order = getSectionOrder(ID, CustomSectionName);
1505*b5893f02SDimitry Andric if (Order == -1) // Skip unknown sections
1506*b5893f02SDimitry Andric return true;
1507*b5893f02SDimitry Andric // There can be multiple "reloc." sections. Otherwise there shouldn't be any
1508*b5893f02SDimitry Andric // duplicate section orders.
1509*b5893f02SDimitry Andric bool IsValid = (LastOrder == Order && Order == WASM_SEC_ORDER_RELOC) ||
1510*b5893f02SDimitry Andric LastOrder < Order;
1511*b5893f02SDimitry Andric LastOrder = Order;
1512*b5893f02SDimitry Andric return IsValid;
1513*b5893f02SDimitry Andric }
1514