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" 117a7e6055SDimitry Andric #include "llvm/ADT/STLExtras.h" 127a7e6055SDimitry Andric #include "llvm/ADT/StringRef.h" 137a7e6055SDimitry Andric #include "llvm/ADT/Triple.h" 14db17bf38SDimitry Andric #include "llvm/BinaryFormat/Wasm.h" 1551690af2SDimitry Andric #include "llvm/MC/SubtargetFeature.h" 167a7e6055SDimitry Andric #include "llvm/Object/Binary.h" 177a7e6055SDimitry Andric #include "llvm/Object/Error.h" 187a7e6055SDimitry Andric #include "llvm/Object/ObjectFile.h" 197a7e6055SDimitry Andric #include "llvm/Object/SymbolicFile.h" 20d88c1a5aSDimitry Andric #include "llvm/Object/Wasm.h" 21d88c1a5aSDimitry Andric #include "llvm/Support/Endian.h" 227a7e6055SDimitry Andric #include "llvm/Support/Error.h" 237a7e6055SDimitry Andric #include "llvm/Support/ErrorHandling.h" 24d88c1a5aSDimitry Andric #include "llvm/Support/LEB128.h" 257a7e6055SDimitry Andric #include <algorithm> 2651690af2SDimitry Andric #include <cassert> 277a7e6055SDimitry Andric #include <cstdint> 2851690af2SDimitry Andric #include <cstring> 297a7e6055SDimitry Andric #include <system_error> 30d88c1a5aSDimitry Andric 31edd7eaddSDimitry Andric #define DEBUG_TYPE "wasm-object" 32edd7eaddSDimitry Andric 337a7e6055SDimitry Andric using namespace llvm; 347a7e6055SDimitry Andric using namespace object; 35d88c1a5aSDimitry Andric 36d88c1a5aSDimitry Andric Expected<std::unique_ptr<WasmObjectFile>> 37d88c1a5aSDimitry Andric ObjectFile::createWasmObjectFile(MemoryBufferRef Buffer) { 38d88c1a5aSDimitry Andric Error Err = Error::success(); 39d88c1a5aSDimitry Andric auto ObjectFile = llvm::make_unique<WasmObjectFile>(Buffer, Err); 40d88c1a5aSDimitry Andric if (Err) 41d88c1a5aSDimitry Andric return std::move(Err); 42d88c1a5aSDimitry Andric 43d88c1a5aSDimitry Andric return std::move(ObjectFile); 44d88c1a5aSDimitry Andric } 45d88c1a5aSDimitry Andric 467a7e6055SDimitry Andric #define VARINT7_MAX ((1<<7)-1) 477a7e6055SDimitry Andric #define VARINT7_MIN (-(1<<7)) 487a7e6055SDimitry Andric #define VARUINT7_MAX (1<<7) 497a7e6055SDimitry Andric #define VARUINT1_MAX (1) 50d88c1a5aSDimitry Andric 517a7e6055SDimitry Andric static uint8_t readUint8(const uint8_t *&Ptr) { return *Ptr++; } 527a7e6055SDimitry Andric 537a7e6055SDimitry Andric static uint32_t readUint32(const uint8_t *&Ptr) { 54d88c1a5aSDimitry Andric uint32_t Result = support::endian::read32le(Ptr); 55d88c1a5aSDimitry Andric Ptr += sizeof(Result); 56d88c1a5aSDimitry Andric return Result; 57d88c1a5aSDimitry Andric } 58d88c1a5aSDimitry Andric 597a7e6055SDimitry Andric static int32_t readFloat32(const uint8_t *&Ptr) { 607a7e6055SDimitry Andric int32_t Result = 0; 617a7e6055SDimitry Andric memcpy(&Result, Ptr, sizeof(Result)); 627a7e6055SDimitry Andric Ptr += sizeof(Result); 637a7e6055SDimitry Andric return Result; 647a7e6055SDimitry Andric } 657a7e6055SDimitry Andric 667a7e6055SDimitry Andric static int64_t readFloat64(const uint8_t *&Ptr) { 677a7e6055SDimitry Andric int64_t Result = 0; 687a7e6055SDimitry Andric memcpy(&Result, Ptr, sizeof(Result)); 697a7e6055SDimitry Andric Ptr += sizeof(Result); 707a7e6055SDimitry Andric return Result; 717a7e6055SDimitry Andric } 727a7e6055SDimitry Andric 737a7e6055SDimitry Andric static uint64_t readULEB128(const uint8_t *&Ptr) { 74d88c1a5aSDimitry Andric unsigned Count; 75d88c1a5aSDimitry Andric uint64_t Result = decodeULEB128(Ptr, &Count); 76d88c1a5aSDimitry Andric Ptr += Count; 77d88c1a5aSDimitry Andric return Result; 78d88c1a5aSDimitry Andric } 79d88c1a5aSDimitry Andric 807a7e6055SDimitry Andric static StringRef readString(const uint8_t *&Ptr) { 81d88c1a5aSDimitry Andric uint32_t StringLen = readULEB128(Ptr); 82d88c1a5aSDimitry Andric StringRef Return = StringRef(reinterpret_cast<const char *>(Ptr), StringLen); 83d88c1a5aSDimitry Andric Ptr += StringLen; 84d88c1a5aSDimitry Andric return Return; 85d88c1a5aSDimitry Andric } 86d88c1a5aSDimitry Andric 877a7e6055SDimitry Andric static int64_t readLEB128(const uint8_t *&Ptr) { 887a7e6055SDimitry Andric unsigned Count; 897a7e6055SDimitry Andric uint64_t Result = decodeSLEB128(Ptr, &Count); 907a7e6055SDimitry Andric Ptr += Count; 917a7e6055SDimitry Andric return Result; 927a7e6055SDimitry Andric } 937a7e6055SDimitry Andric 947a7e6055SDimitry Andric static uint8_t readVaruint1(const uint8_t *&Ptr) { 957a7e6055SDimitry Andric int64_t result = readLEB128(Ptr); 967a7e6055SDimitry Andric assert(result <= VARUINT1_MAX && result >= 0); 977a7e6055SDimitry Andric return result; 987a7e6055SDimitry Andric } 997a7e6055SDimitry Andric 1007a7e6055SDimitry Andric static int8_t readVarint7(const uint8_t *&Ptr) { 1017a7e6055SDimitry Andric int64_t result = readLEB128(Ptr); 1027a7e6055SDimitry Andric assert(result <= VARINT7_MAX && result >= VARINT7_MIN); 1037a7e6055SDimitry Andric return result; 1047a7e6055SDimitry Andric } 1057a7e6055SDimitry Andric 1067a7e6055SDimitry Andric static uint8_t readVaruint7(const uint8_t *&Ptr) { 1077a7e6055SDimitry Andric uint64_t result = readULEB128(Ptr); 1087a7e6055SDimitry Andric assert(result <= VARUINT7_MAX); 1097a7e6055SDimitry Andric return result; 1107a7e6055SDimitry Andric } 1117a7e6055SDimitry Andric 1127a7e6055SDimitry Andric static int32_t readVarint32(const uint8_t *&Ptr) { 1137a7e6055SDimitry Andric int64_t result = readLEB128(Ptr); 1147a7e6055SDimitry Andric assert(result <= INT32_MAX && result >= INT32_MIN); 1157a7e6055SDimitry Andric return result; 1167a7e6055SDimitry Andric } 1177a7e6055SDimitry Andric 1187a7e6055SDimitry Andric static uint32_t readVaruint32(const uint8_t *&Ptr) { 1197a7e6055SDimitry Andric uint64_t result = readULEB128(Ptr); 1207a7e6055SDimitry Andric assert(result <= UINT32_MAX); 1217a7e6055SDimitry Andric return result; 1227a7e6055SDimitry Andric } 1237a7e6055SDimitry Andric 1247a7e6055SDimitry Andric static int64_t readVarint64(const uint8_t *&Ptr) { 1257a7e6055SDimitry Andric return readLEB128(Ptr); 1267a7e6055SDimitry Andric } 1277a7e6055SDimitry Andric 1287a7e6055SDimitry Andric static uint8_t readOpcode(const uint8_t *&Ptr) { 1297a7e6055SDimitry Andric return readUint8(Ptr); 1307a7e6055SDimitry Andric } 1317a7e6055SDimitry Andric 1327a7e6055SDimitry Andric static Error readInitExpr(wasm::WasmInitExpr &Expr, const uint8_t *&Ptr) { 1337a7e6055SDimitry Andric Expr.Opcode = readOpcode(Ptr); 1347a7e6055SDimitry Andric 1357a7e6055SDimitry Andric switch (Expr.Opcode) { 1367a7e6055SDimitry Andric case wasm::WASM_OPCODE_I32_CONST: 1377a7e6055SDimitry Andric Expr.Value.Int32 = readVarint32(Ptr); 1387a7e6055SDimitry Andric break; 1397a7e6055SDimitry Andric case wasm::WASM_OPCODE_I64_CONST: 1407a7e6055SDimitry Andric Expr.Value.Int64 = readVarint64(Ptr); 1417a7e6055SDimitry Andric break; 1427a7e6055SDimitry Andric case wasm::WASM_OPCODE_F32_CONST: 1437a7e6055SDimitry Andric Expr.Value.Float32 = readFloat32(Ptr); 1447a7e6055SDimitry Andric break; 1457a7e6055SDimitry Andric case wasm::WASM_OPCODE_F64_CONST: 1467a7e6055SDimitry Andric Expr.Value.Float64 = readFloat64(Ptr); 1477a7e6055SDimitry Andric break; 1487a7e6055SDimitry Andric case wasm::WASM_OPCODE_GET_GLOBAL: 14951690af2SDimitry Andric Expr.Value.Global = readULEB128(Ptr); 1507a7e6055SDimitry Andric break; 1517a7e6055SDimitry Andric default: 1527a7e6055SDimitry Andric return make_error<GenericBinaryError>("Invalid opcode in init_expr", 1537a7e6055SDimitry Andric object_error::parse_failed); 1547a7e6055SDimitry Andric } 1557a7e6055SDimitry Andric 1567a7e6055SDimitry Andric uint8_t EndOpcode = readOpcode(Ptr); 1577a7e6055SDimitry Andric if (EndOpcode != wasm::WASM_OPCODE_END) { 1587a7e6055SDimitry Andric return make_error<GenericBinaryError>("Invalid init_expr", 1597a7e6055SDimitry Andric object_error::parse_failed); 1607a7e6055SDimitry Andric } 1617a7e6055SDimitry Andric return Error::success(); 1627a7e6055SDimitry Andric } 1637a7e6055SDimitry Andric 1647a7e6055SDimitry Andric static wasm::WasmLimits readLimits(const uint8_t *&Ptr) { 1657a7e6055SDimitry Andric wasm::WasmLimits Result; 1667a7e6055SDimitry Andric Result.Flags = readVaruint1(Ptr); 1677a7e6055SDimitry Andric Result.Initial = readVaruint32(Ptr); 1687a7e6055SDimitry Andric if (Result.Flags & wasm::WASM_LIMITS_FLAG_HAS_MAX) 1697a7e6055SDimitry Andric Result.Maximum = readVaruint32(Ptr); 1707a7e6055SDimitry Andric return Result; 1717a7e6055SDimitry Andric } 1727a7e6055SDimitry Andric 1735517e702SDimitry Andric static wasm::WasmTable readTable(const uint8_t *&Ptr) { 1745517e702SDimitry Andric wasm::WasmTable Table; 1755517e702SDimitry Andric Table.ElemType = readVarint7(Ptr); 1765517e702SDimitry Andric Table.Limits = readLimits(Ptr); 1775517e702SDimitry Andric return Table; 1785517e702SDimitry Andric } 1795517e702SDimitry Andric 1807a7e6055SDimitry Andric static Error readSection(WasmSection &Section, const uint8_t *&Ptr, 181d88c1a5aSDimitry Andric const uint8_t *Start) { 182d88c1a5aSDimitry Andric // TODO(sbc): Avoid reading past EOF in the case of malformed files. 183d88c1a5aSDimitry Andric Section.Offset = Ptr - Start; 1847a7e6055SDimitry Andric Section.Type = readVaruint7(Ptr); 1857a7e6055SDimitry Andric uint32_t Size = readVaruint32(Ptr); 186d88c1a5aSDimitry Andric if (Size == 0) 187d88c1a5aSDimitry Andric return make_error<StringError>("Zero length section", 188d88c1a5aSDimitry Andric object_error::parse_failed); 189d88c1a5aSDimitry Andric Section.Content = ArrayRef<uint8_t>(Ptr, Size); 190d88c1a5aSDimitry Andric Ptr += Size; 191d88c1a5aSDimitry Andric return Error::success(); 192d88c1a5aSDimitry Andric } 193d88c1a5aSDimitry Andric 194d88c1a5aSDimitry Andric WasmObjectFile::WasmObjectFile(MemoryBufferRef Buffer, Error &Err) 19551690af2SDimitry Andric : ObjectFile(Binary::ID_Wasm, Buffer) { 196d88c1a5aSDimitry Andric ErrorAsOutParameter ErrAsOutParam(&Err); 197d88c1a5aSDimitry Andric Header.Magic = getData().substr(0, 4); 198d88c1a5aSDimitry Andric if (Header.Magic != StringRef("\0asm", 4)) { 199d88c1a5aSDimitry Andric Err = make_error<StringError>("Bad magic number", 200d88c1a5aSDimitry Andric object_error::parse_failed); 201d88c1a5aSDimitry Andric return; 202d88c1a5aSDimitry Andric } 203d88c1a5aSDimitry Andric const uint8_t *Ptr = getPtr(4); 204d88c1a5aSDimitry Andric Header.Version = readUint32(Ptr); 205d88c1a5aSDimitry Andric if (Header.Version != wasm::WasmVersion) { 206d88c1a5aSDimitry Andric Err = make_error<StringError>("Bad version number", 207d88c1a5aSDimitry Andric object_error::parse_failed); 208d88c1a5aSDimitry Andric return; 209d88c1a5aSDimitry Andric } 210d88c1a5aSDimitry Andric 211d88c1a5aSDimitry Andric const uint8_t *Eof = getPtr(getData().size()); 2127a7e6055SDimitry Andric WasmSection Sec; 213d88c1a5aSDimitry Andric while (Ptr < Eof) { 214d88c1a5aSDimitry Andric if ((Err = readSection(Sec, Ptr, getPtr(0)))) 215d88c1a5aSDimitry Andric return; 2167a7e6055SDimitry Andric if ((Err = parseSection(Sec))) 217d88c1a5aSDimitry Andric return; 2187a7e6055SDimitry Andric 219d88c1a5aSDimitry Andric Sections.push_back(Sec); 220d88c1a5aSDimitry Andric } 221d88c1a5aSDimitry Andric } 222d88c1a5aSDimitry Andric 2237a7e6055SDimitry Andric Error WasmObjectFile::parseSection(WasmSection &Sec) { 2247a7e6055SDimitry Andric const uint8_t* Start = Sec.Content.data(); 2257a7e6055SDimitry Andric const uint8_t* End = Start + Sec.Content.size(); 2267a7e6055SDimitry Andric switch (Sec.Type) { 2277a7e6055SDimitry Andric case wasm::WASM_SEC_CUSTOM: 2287a7e6055SDimitry Andric return parseCustomSection(Sec, Start, End); 2297a7e6055SDimitry Andric case wasm::WASM_SEC_TYPE: 2307a7e6055SDimitry Andric return parseTypeSection(Start, End); 2317a7e6055SDimitry Andric case wasm::WASM_SEC_IMPORT: 2327a7e6055SDimitry Andric return parseImportSection(Start, End); 2337a7e6055SDimitry Andric case wasm::WASM_SEC_FUNCTION: 2347a7e6055SDimitry Andric return parseFunctionSection(Start, End); 2357a7e6055SDimitry Andric case wasm::WASM_SEC_TABLE: 2367a7e6055SDimitry Andric return parseTableSection(Start, End); 2377a7e6055SDimitry Andric case wasm::WASM_SEC_MEMORY: 2387a7e6055SDimitry Andric return parseMemorySection(Start, End); 2397a7e6055SDimitry Andric case wasm::WASM_SEC_GLOBAL: 2407a7e6055SDimitry Andric return parseGlobalSection(Start, End); 2417a7e6055SDimitry Andric case wasm::WASM_SEC_EXPORT: 2427a7e6055SDimitry Andric return parseExportSection(Start, End); 2437a7e6055SDimitry Andric case wasm::WASM_SEC_START: 2447a7e6055SDimitry Andric return parseStartSection(Start, End); 2457a7e6055SDimitry Andric case wasm::WASM_SEC_ELEM: 2467a7e6055SDimitry Andric return parseElemSection(Start, End); 2477a7e6055SDimitry Andric case wasm::WASM_SEC_CODE: 2487a7e6055SDimitry Andric return parseCodeSection(Start, End); 2497a7e6055SDimitry Andric case wasm::WASM_SEC_DATA: 2507a7e6055SDimitry Andric return parseDataSection(Start, End); 2517a7e6055SDimitry Andric default: 2527a7e6055SDimitry Andric return make_error<GenericBinaryError>("Bad section type", 2537a7e6055SDimitry Andric object_error::parse_failed); 2547a7e6055SDimitry Andric } 2557a7e6055SDimitry Andric } 2567a7e6055SDimitry Andric 2577a7e6055SDimitry Andric Error WasmObjectFile::parseNameSection(const uint8_t *Ptr, const uint8_t *End) { 2587a7e6055SDimitry Andric while (Ptr < End) { 2597a7e6055SDimitry Andric uint8_t Type = readVarint7(Ptr); 2607a7e6055SDimitry Andric uint32_t Size = readVaruint32(Ptr); 261edd7eaddSDimitry Andric const uint8_t *SubSectionEnd = Ptr + Size; 2627a7e6055SDimitry Andric switch (Type) { 2637a7e6055SDimitry Andric case wasm::WASM_NAMES_FUNCTION: { 2647a7e6055SDimitry Andric uint32_t Count = readVaruint32(Ptr); 2657a7e6055SDimitry Andric while (Count--) { 2660f5676f4SDimitry Andric uint32_t Index = readVaruint32(Ptr); 2677a7e6055SDimitry Andric StringRef Name = readString(Ptr); 26851690af2SDimitry Andric if (!Name.empty()) 2697a7e6055SDimitry Andric Symbols.emplace_back(Name, 2700f5676f4SDimitry Andric WasmSymbol::SymbolType::DEBUG_FUNCTION_NAME, 2710f5676f4SDimitry Andric Sections.size(), Index); 2727a7e6055SDimitry Andric } 2737a7e6055SDimitry Andric break; 2747a7e6055SDimitry Andric } 2757a7e6055SDimitry Andric // Ignore local names for now 2767a7e6055SDimitry Andric case wasm::WASM_NAMES_LOCAL: 2777a7e6055SDimitry Andric default: 2787a7e6055SDimitry Andric Ptr += Size; 2797a7e6055SDimitry Andric break; 2807a7e6055SDimitry Andric } 281edd7eaddSDimitry Andric if (Ptr != SubSectionEnd) 282edd7eaddSDimitry Andric return make_error<GenericBinaryError>("Name sub-section ended prematurely", 283edd7eaddSDimitry Andric object_error::parse_failed); 2847a7e6055SDimitry Andric } 2857a7e6055SDimitry Andric 2867a7e6055SDimitry Andric if (Ptr != End) 2877a7e6055SDimitry Andric return make_error<GenericBinaryError>("Name section ended prematurely", 2887a7e6055SDimitry Andric object_error::parse_failed); 2897a7e6055SDimitry Andric return Error::success(); 2907a7e6055SDimitry Andric } 2917a7e6055SDimitry Andric 292edd7eaddSDimitry Andric Error WasmObjectFile::parseLinkingSection(const uint8_t *Ptr, 293edd7eaddSDimitry Andric const uint8_t *End) { 294edd7eaddSDimitry Andric while (Ptr < End) { 295edd7eaddSDimitry Andric uint8_t Type = readVarint7(Ptr); 296edd7eaddSDimitry Andric uint32_t Size = readVaruint32(Ptr); 297edd7eaddSDimitry Andric const uint8_t *SubSectionEnd = Ptr + Size; 298edd7eaddSDimitry Andric switch (Type) { 299edd7eaddSDimitry Andric case wasm::WASM_SYMBOL_INFO: { 300edd7eaddSDimitry Andric uint32_t Count = readVaruint32(Ptr); 301edd7eaddSDimitry Andric while (Count--) { 302edd7eaddSDimitry Andric StringRef Symbol = readString(Ptr); 303edd7eaddSDimitry Andric DEBUG(dbgs() << "reading syminfo: " << Symbol << "\n"); 304edd7eaddSDimitry Andric uint32_t Flags = readVaruint32(Ptr); 305edd7eaddSDimitry Andric auto iter = SymbolMap.find(Symbol); 306edd7eaddSDimitry Andric if (iter == SymbolMap.end()) { 307edd7eaddSDimitry Andric return make_error<GenericBinaryError>( 308edd7eaddSDimitry Andric "Invalid symbol name in linking section", 309edd7eaddSDimitry Andric object_error::parse_failed); 310edd7eaddSDimitry Andric } 311edd7eaddSDimitry Andric uint32_t SymIndex = iter->second; 312edd7eaddSDimitry Andric assert(SymIndex < Symbols.size()); 313edd7eaddSDimitry Andric Symbols[SymIndex].Flags = Flags; 314edd7eaddSDimitry Andric DEBUG(dbgs() << "Set symbol flags index:" 315edd7eaddSDimitry Andric << SymIndex << " name:" 316edd7eaddSDimitry Andric << Symbols[SymIndex].Name << " exptected:" 317edd7eaddSDimitry Andric << Symbol << " flags: " << Flags << "\n"); 318edd7eaddSDimitry Andric } 319edd7eaddSDimitry Andric break; 320edd7eaddSDimitry Andric } 321edd7eaddSDimitry Andric case wasm::WASM_STACK_POINTER: 322edd7eaddSDimitry Andric default: 323edd7eaddSDimitry Andric Ptr += Size; 324edd7eaddSDimitry Andric break; 325edd7eaddSDimitry Andric } 326edd7eaddSDimitry Andric if (Ptr != SubSectionEnd) 327edd7eaddSDimitry Andric return make_error<GenericBinaryError>( 328edd7eaddSDimitry Andric "Linking sub-section ended prematurely", object_error::parse_failed); 329edd7eaddSDimitry Andric } 330edd7eaddSDimitry Andric if (Ptr != End) 331edd7eaddSDimitry Andric return make_error<GenericBinaryError>("Linking section ended prematurely", 332edd7eaddSDimitry Andric object_error::parse_failed); 333edd7eaddSDimitry Andric return Error::success(); 334edd7eaddSDimitry Andric } 335edd7eaddSDimitry Andric 3367a7e6055SDimitry Andric WasmSection* WasmObjectFile::findCustomSectionByName(StringRef Name) { 3377a7e6055SDimitry Andric for (WasmSection& Section : Sections) { 3387a7e6055SDimitry Andric if (Section.Type == wasm::WASM_SEC_CUSTOM && Section.Name == Name) 3397a7e6055SDimitry Andric return &Section; 3407a7e6055SDimitry Andric } 3417a7e6055SDimitry Andric return nullptr; 3427a7e6055SDimitry Andric } 3437a7e6055SDimitry Andric 3447a7e6055SDimitry Andric WasmSection* WasmObjectFile::findSectionByType(uint32_t Type) { 3457a7e6055SDimitry Andric assert(Type != wasm::WASM_SEC_CUSTOM); 3467a7e6055SDimitry Andric for (WasmSection& Section : Sections) { 3477a7e6055SDimitry Andric if (Section.Type == Type) 3487a7e6055SDimitry Andric return &Section; 3497a7e6055SDimitry Andric } 3507a7e6055SDimitry Andric return nullptr; 3517a7e6055SDimitry Andric } 3527a7e6055SDimitry Andric 3537a7e6055SDimitry Andric Error WasmObjectFile::parseRelocSection(StringRef Name, const uint8_t *Ptr, 3547a7e6055SDimitry Andric const uint8_t *End) { 3557a7e6055SDimitry Andric uint8_t SectionCode = readVarint7(Ptr); 3567a7e6055SDimitry Andric WasmSection* Section = nullptr; 3577a7e6055SDimitry Andric if (SectionCode == wasm::WASM_SEC_CUSTOM) { 3587a7e6055SDimitry Andric StringRef Name = readString(Ptr); 3597a7e6055SDimitry Andric Section = findCustomSectionByName(Name); 3607a7e6055SDimitry Andric } else { 3617a7e6055SDimitry Andric Section = findSectionByType(SectionCode); 3627a7e6055SDimitry Andric } 3637a7e6055SDimitry Andric if (!Section) 3647a7e6055SDimitry Andric return make_error<GenericBinaryError>("Invalid section code", 3657a7e6055SDimitry Andric object_error::parse_failed); 3667a7e6055SDimitry Andric uint32_t RelocCount = readVaruint32(Ptr); 3677a7e6055SDimitry Andric while (RelocCount--) { 3687a7e6055SDimitry Andric wasm::WasmRelocation Reloc; 3697a7e6055SDimitry Andric memset(&Reloc, 0, sizeof(Reloc)); 3707a7e6055SDimitry Andric Reloc.Type = readVaruint32(Ptr); 3717a7e6055SDimitry Andric Reloc.Offset = readVaruint32(Ptr); 3727a7e6055SDimitry Andric Reloc.Index = readVaruint32(Ptr); 3737a7e6055SDimitry Andric switch (Reloc.Type) { 3747a7e6055SDimitry Andric case wasm::R_WEBASSEMBLY_FUNCTION_INDEX_LEB: 3757a7e6055SDimitry Andric case wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB: 3767a7e6055SDimitry Andric case wasm::R_WEBASSEMBLY_TABLE_INDEX_I32: 37751690af2SDimitry Andric case wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB: 378edd7eaddSDimitry Andric case wasm::R_WEBASSEMBLY_GLOBAL_INDEX_LEB: 3797a7e6055SDimitry Andric break; 3807a7e6055SDimitry Andric case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_LEB: 3817a7e6055SDimitry Andric case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_SLEB: 3827a7e6055SDimitry Andric case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_I32: 38351690af2SDimitry Andric Reloc.Addend = readVarint32(Ptr); 3847a7e6055SDimitry Andric break; 3857a7e6055SDimitry Andric default: 386edd7eaddSDimitry Andric return make_error<GenericBinaryError>("Bad relocation type: " + 387edd7eaddSDimitry Andric Twine(Reloc.Type), 3887a7e6055SDimitry Andric object_error::parse_failed); 3897a7e6055SDimitry Andric } 3907a7e6055SDimitry Andric Section->Relocations.push_back(Reloc); 3917a7e6055SDimitry Andric } 3927a7e6055SDimitry Andric if (Ptr != End) 3937a7e6055SDimitry Andric return make_error<GenericBinaryError>("Reloc section ended prematurely", 3947a7e6055SDimitry Andric object_error::parse_failed); 3957a7e6055SDimitry Andric return Error::success(); 3967a7e6055SDimitry Andric } 3977a7e6055SDimitry Andric 3987a7e6055SDimitry Andric Error WasmObjectFile::parseCustomSection(WasmSection &Sec, 3997a7e6055SDimitry Andric const uint8_t *Ptr, const uint8_t *End) { 400d88c1a5aSDimitry Andric Sec.Name = readString(Ptr); 4017a7e6055SDimitry Andric if (Sec.Name == "name") { 4027a7e6055SDimitry Andric if (Error Err = parseNameSection(Ptr, End)) 4037a7e6055SDimitry Andric return Err; 404edd7eaddSDimitry Andric } else if (Sec.Name == "linking") { 405edd7eaddSDimitry Andric if (Error Err = parseLinkingSection(Ptr, End)) 406edd7eaddSDimitry Andric return Err; 4077a7e6055SDimitry Andric } else if (Sec.Name.startswith("reloc.")) { 4087a7e6055SDimitry Andric if (Error Err = parseRelocSection(Sec.Name, Ptr, End)) 4097a7e6055SDimitry Andric return Err; 4107a7e6055SDimitry Andric } 4117a7e6055SDimitry Andric return Error::success(); 4127a7e6055SDimitry Andric } 4137a7e6055SDimitry Andric 4147a7e6055SDimitry Andric Error WasmObjectFile::parseTypeSection(const uint8_t *Ptr, const uint8_t *End) { 4157a7e6055SDimitry Andric uint32_t Count = readVaruint32(Ptr); 4167a7e6055SDimitry Andric Signatures.reserve(Count); 4177a7e6055SDimitry Andric while (Count--) { 4187a7e6055SDimitry Andric wasm::WasmSignature Sig; 4197a7e6055SDimitry Andric Sig.ReturnType = wasm::WASM_TYPE_NORESULT; 4207a7e6055SDimitry Andric int8_t Form = readVarint7(Ptr); 4217a7e6055SDimitry Andric if (Form != wasm::WASM_TYPE_FUNC) { 4227a7e6055SDimitry Andric return make_error<GenericBinaryError>("Invalid signature type", 4237a7e6055SDimitry Andric object_error::parse_failed); 4247a7e6055SDimitry Andric } 4257a7e6055SDimitry Andric uint32_t ParamCount = readVaruint32(Ptr); 4267a7e6055SDimitry Andric Sig.ParamTypes.reserve(ParamCount); 4277a7e6055SDimitry Andric while (ParamCount--) { 4287a7e6055SDimitry Andric uint32_t ParamType = readVarint7(Ptr); 4297a7e6055SDimitry Andric Sig.ParamTypes.push_back(ParamType); 4307a7e6055SDimitry Andric } 4317a7e6055SDimitry Andric uint32_t ReturnCount = readVaruint32(Ptr); 4327a7e6055SDimitry Andric if (ReturnCount) { 4337a7e6055SDimitry Andric if (ReturnCount != 1) { 4347a7e6055SDimitry Andric return make_error<GenericBinaryError>( 4357a7e6055SDimitry Andric "Multiple return types not supported", object_error::parse_failed); 4367a7e6055SDimitry Andric } 4377a7e6055SDimitry Andric Sig.ReturnType = readVarint7(Ptr); 4387a7e6055SDimitry Andric } 4397a7e6055SDimitry Andric Signatures.push_back(Sig); 4407a7e6055SDimitry Andric } 4417a7e6055SDimitry Andric if (Ptr != End) 4427a7e6055SDimitry Andric return make_error<GenericBinaryError>("Type section ended prematurely", 4437a7e6055SDimitry Andric object_error::parse_failed); 4447a7e6055SDimitry Andric return Error::success(); 4457a7e6055SDimitry Andric } 4467a7e6055SDimitry Andric 4477a7e6055SDimitry Andric Error WasmObjectFile::parseImportSection(const uint8_t *Ptr, const uint8_t *End) { 4487a7e6055SDimitry Andric uint32_t Count = readVaruint32(Ptr); 4497a7e6055SDimitry Andric Imports.reserve(Count); 4500f5676f4SDimitry Andric for (uint32_t i = 0; i < Count; i++) { 4517a7e6055SDimitry Andric wasm::WasmImport Im; 4527a7e6055SDimitry Andric Im.Module = readString(Ptr); 4537a7e6055SDimitry Andric Im.Field = readString(Ptr); 4547a7e6055SDimitry Andric Im.Kind = readUint8(Ptr); 4557a7e6055SDimitry Andric switch (Im.Kind) { 4567a7e6055SDimitry Andric case wasm::WASM_EXTERNAL_FUNCTION: 4577a7e6055SDimitry Andric Im.SigIndex = readVaruint32(Ptr); 458edd7eaddSDimitry Andric SymbolMap.try_emplace(Im.Field, Symbols.size()); 4590f5676f4SDimitry Andric Symbols.emplace_back(Im.Field, WasmSymbol::SymbolType::FUNCTION_IMPORT, 4600f5676f4SDimitry Andric Sections.size(), i); 461edd7eaddSDimitry Andric DEBUG(dbgs() << "Adding import: " << Symbols.back() 462edd7eaddSDimitry Andric << " sym index:" << Symbols.size() << "\n"); 4637a7e6055SDimitry Andric break; 4647a7e6055SDimitry Andric case wasm::WASM_EXTERNAL_GLOBAL: 4655517e702SDimitry Andric Im.Global.Type = readVarint7(Ptr); 4665517e702SDimitry Andric Im.Global.Mutable = readVaruint1(Ptr); 467edd7eaddSDimitry Andric SymbolMap.try_emplace(Im.Field, Symbols.size()); 4680f5676f4SDimitry Andric Symbols.emplace_back(Im.Field, WasmSymbol::SymbolType::GLOBAL_IMPORT, 4690f5676f4SDimitry Andric Sections.size(), i); 470edd7eaddSDimitry Andric DEBUG(dbgs() << "Adding import: " << Symbols.back() 471edd7eaddSDimitry Andric << " sym index:" << Symbols.size() << "\n"); 4727a7e6055SDimitry Andric break; 4735517e702SDimitry Andric case wasm::WASM_EXTERNAL_MEMORY: 4745517e702SDimitry Andric Im.Memory = readLimits(Ptr); 4755517e702SDimitry Andric break; 4765517e702SDimitry Andric case wasm::WASM_EXTERNAL_TABLE: 4775517e702SDimitry Andric Im.Table = readTable(Ptr); 4785517e702SDimitry Andric if (Im.Table.ElemType != wasm::WASM_TYPE_ANYFUNC) { 4795517e702SDimitry Andric return make_error<GenericBinaryError>("Invalid table element type", 4805517e702SDimitry Andric object_error::parse_failed); 4815517e702SDimitry Andric } 4825517e702SDimitry Andric break; 4837a7e6055SDimitry Andric default: 4847a7e6055SDimitry Andric return make_error<GenericBinaryError>( 4857a7e6055SDimitry Andric "Unexpected import kind", object_error::parse_failed); 4867a7e6055SDimitry Andric } 4877a7e6055SDimitry Andric Imports.push_back(Im); 4887a7e6055SDimitry Andric } 4897a7e6055SDimitry Andric if (Ptr != End) 4907a7e6055SDimitry Andric return make_error<GenericBinaryError>("Import section ended prematurely", 4917a7e6055SDimitry Andric object_error::parse_failed); 4927a7e6055SDimitry Andric return Error::success(); 4937a7e6055SDimitry Andric } 4947a7e6055SDimitry Andric 4957a7e6055SDimitry Andric Error WasmObjectFile::parseFunctionSection(const uint8_t *Ptr, const uint8_t *End) { 4967a7e6055SDimitry Andric uint32_t Count = readVaruint32(Ptr); 4977a7e6055SDimitry Andric FunctionTypes.reserve(Count); 4987a7e6055SDimitry Andric while (Count--) { 4997a7e6055SDimitry Andric FunctionTypes.push_back(readVaruint32(Ptr)); 5007a7e6055SDimitry Andric } 5017a7e6055SDimitry Andric if (Ptr != End) 5027a7e6055SDimitry Andric return make_error<GenericBinaryError>("Function section ended prematurely", 5037a7e6055SDimitry Andric object_error::parse_failed); 5047a7e6055SDimitry Andric return Error::success(); 5057a7e6055SDimitry Andric } 5067a7e6055SDimitry Andric 5077a7e6055SDimitry Andric Error WasmObjectFile::parseTableSection(const uint8_t *Ptr, const uint8_t *End) { 5087a7e6055SDimitry Andric uint32_t Count = readVaruint32(Ptr); 5097a7e6055SDimitry Andric Tables.reserve(Count); 5107a7e6055SDimitry Andric while (Count--) { 5115517e702SDimitry Andric Tables.push_back(readTable(Ptr)); 5125517e702SDimitry Andric if (Tables.back().ElemType != wasm::WASM_TYPE_ANYFUNC) { 5137a7e6055SDimitry Andric return make_error<GenericBinaryError>("Invalid table element type", 5147a7e6055SDimitry Andric object_error::parse_failed); 5157a7e6055SDimitry Andric } 5167a7e6055SDimitry Andric } 5177a7e6055SDimitry Andric if (Ptr != End) 5187a7e6055SDimitry Andric return make_error<GenericBinaryError>("Table section ended prematurely", 5197a7e6055SDimitry Andric object_error::parse_failed); 5207a7e6055SDimitry Andric return Error::success(); 5217a7e6055SDimitry Andric } 5227a7e6055SDimitry Andric 5237a7e6055SDimitry Andric Error WasmObjectFile::parseMemorySection(const uint8_t *Ptr, const uint8_t *End) { 5247a7e6055SDimitry Andric uint32_t Count = readVaruint32(Ptr); 5257a7e6055SDimitry Andric Memories.reserve(Count); 5267a7e6055SDimitry Andric while (Count--) { 5277a7e6055SDimitry Andric Memories.push_back(readLimits(Ptr)); 5287a7e6055SDimitry Andric } 5297a7e6055SDimitry Andric if (Ptr != End) 5307a7e6055SDimitry Andric return make_error<GenericBinaryError>("Memory section ended prematurely", 5317a7e6055SDimitry Andric object_error::parse_failed); 5327a7e6055SDimitry Andric return Error::success(); 5337a7e6055SDimitry Andric } 5347a7e6055SDimitry Andric 5357a7e6055SDimitry Andric Error WasmObjectFile::parseGlobalSection(const uint8_t *Ptr, const uint8_t *End) { 5367a7e6055SDimitry Andric uint32_t Count = readVaruint32(Ptr); 5377a7e6055SDimitry Andric Globals.reserve(Count); 5387a7e6055SDimitry Andric while (Count--) { 5397a7e6055SDimitry Andric wasm::WasmGlobal Global; 5407a7e6055SDimitry Andric Global.Type = readVarint7(Ptr); 5417a7e6055SDimitry Andric Global.Mutable = readVaruint1(Ptr); 5427a7e6055SDimitry Andric if (Error Err = readInitExpr(Global.InitExpr, Ptr)) 5437a7e6055SDimitry Andric return Err; 5447a7e6055SDimitry Andric Globals.push_back(Global); 5457a7e6055SDimitry Andric } 5467a7e6055SDimitry Andric if (Ptr != End) 5477a7e6055SDimitry Andric return make_error<GenericBinaryError>("Global section ended prematurely", 5487a7e6055SDimitry Andric object_error::parse_failed); 5497a7e6055SDimitry Andric return Error::success(); 5507a7e6055SDimitry Andric } 5517a7e6055SDimitry Andric 5527a7e6055SDimitry Andric Error WasmObjectFile::parseExportSection(const uint8_t *Ptr, const uint8_t *End) { 5537a7e6055SDimitry Andric uint32_t Count = readVaruint32(Ptr); 5547a7e6055SDimitry Andric Exports.reserve(Count); 5550f5676f4SDimitry Andric for (uint32_t i = 0; i < Count; i++) { 5567a7e6055SDimitry Andric wasm::WasmExport Ex; 5577a7e6055SDimitry Andric Ex.Name = readString(Ptr); 5587a7e6055SDimitry Andric Ex.Kind = readUint8(Ptr); 5597a7e6055SDimitry Andric Ex.Index = readVaruint32(Ptr); 5607a7e6055SDimitry Andric switch (Ex.Kind) { 5617a7e6055SDimitry Andric case wasm::WASM_EXTERNAL_FUNCTION: 562edd7eaddSDimitry Andric SymbolMap.try_emplace(Ex.Name, Symbols.size()); 5630f5676f4SDimitry Andric Symbols.emplace_back(Ex.Name, WasmSymbol::SymbolType::FUNCTION_EXPORT, 5640f5676f4SDimitry Andric Sections.size(), i); 565edd7eaddSDimitry Andric DEBUG(dbgs() << "Adding export: " << Symbols.back() 566edd7eaddSDimitry Andric << " sym index:" << Symbols.size() << "\n"); 5677a7e6055SDimitry Andric break; 5687a7e6055SDimitry Andric case wasm::WASM_EXTERNAL_GLOBAL: 569edd7eaddSDimitry Andric SymbolMap.try_emplace(Ex.Name, Symbols.size()); 5700f5676f4SDimitry Andric Symbols.emplace_back(Ex.Name, WasmSymbol::SymbolType::GLOBAL_EXPORT, 5710f5676f4SDimitry Andric Sections.size(), i); 572edd7eaddSDimitry Andric DEBUG(dbgs() << "Adding export: " << Symbols.back() 573edd7eaddSDimitry Andric << " sym index:" << Symbols.size() << "\n"); 5747a7e6055SDimitry Andric break; 5755517e702SDimitry Andric case wasm::WASM_EXTERNAL_MEMORY: 5765517e702SDimitry Andric case wasm::WASM_EXTERNAL_TABLE: 5775517e702SDimitry Andric break; 5787a7e6055SDimitry Andric default: 5797a7e6055SDimitry Andric return make_error<GenericBinaryError>( 5807a7e6055SDimitry Andric "Unexpected export kind", object_error::parse_failed); 5817a7e6055SDimitry Andric } 582edd7eaddSDimitry Andric Exports.push_back(Ex); 5837a7e6055SDimitry Andric } 5847a7e6055SDimitry Andric if (Ptr != End) 5857a7e6055SDimitry Andric return make_error<GenericBinaryError>("Export section ended prematurely", 5867a7e6055SDimitry Andric object_error::parse_failed); 5877a7e6055SDimitry Andric return Error::success(); 5887a7e6055SDimitry Andric } 5897a7e6055SDimitry Andric 5907a7e6055SDimitry Andric Error WasmObjectFile::parseStartSection(const uint8_t *Ptr, const uint8_t *End) { 5917a7e6055SDimitry Andric StartFunction = readVaruint32(Ptr); 5925517e702SDimitry Andric if (StartFunction >= FunctionTypes.size()) 5937a7e6055SDimitry Andric return make_error<GenericBinaryError>("Invalid start function", 5947a7e6055SDimitry Andric object_error::parse_failed); 5957a7e6055SDimitry Andric return Error::success(); 5967a7e6055SDimitry Andric } 5977a7e6055SDimitry Andric 5987a7e6055SDimitry Andric Error WasmObjectFile::parseCodeSection(const uint8_t *Ptr, const uint8_t *End) { 5997a7e6055SDimitry Andric uint32_t FunctionCount = readVaruint32(Ptr); 6007a7e6055SDimitry Andric if (FunctionCount != FunctionTypes.size()) { 6017a7e6055SDimitry Andric return make_error<GenericBinaryError>("Invalid function count", 6027a7e6055SDimitry Andric object_error::parse_failed); 6037a7e6055SDimitry Andric } 6047a7e6055SDimitry Andric 6057a7e6055SDimitry Andric CodeSection = ArrayRef<uint8_t>(Ptr, End - Ptr); 6067a7e6055SDimitry Andric 6077a7e6055SDimitry Andric while (FunctionCount--) { 6087a7e6055SDimitry Andric wasm::WasmFunction Function; 6097a7e6055SDimitry Andric uint32_t FunctionSize = readVaruint32(Ptr); 6107a7e6055SDimitry Andric const uint8_t *FunctionEnd = Ptr + FunctionSize; 6117a7e6055SDimitry Andric 6127a7e6055SDimitry Andric uint32_t NumLocalDecls = readVaruint32(Ptr); 6137a7e6055SDimitry Andric Function.Locals.reserve(NumLocalDecls); 6147a7e6055SDimitry Andric while (NumLocalDecls--) { 6157a7e6055SDimitry Andric wasm::WasmLocalDecl Decl; 6167a7e6055SDimitry Andric Decl.Count = readVaruint32(Ptr); 6177a7e6055SDimitry Andric Decl.Type = readVarint7(Ptr); 6187a7e6055SDimitry Andric Function.Locals.push_back(Decl); 6197a7e6055SDimitry Andric } 6207a7e6055SDimitry Andric 6217a7e6055SDimitry Andric uint32_t BodySize = FunctionEnd - Ptr; 6227a7e6055SDimitry Andric Function.Body = ArrayRef<uint8_t>(Ptr, BodySize); 6237a7e6055SDimitry Andric Ptr += BodySize; 6247a7e6055SDimitry Andric assert(Ptr == FunctionEnd); 6257a7e6055SDimitry Andric Functions.push_back(Function); 6267a7e6055SDimitry Andric } 6277a7e6055SDimitry Andric if (Ptr != End) 6287a7e6055SDimitry Andric return make_error<GenericBinaryError>("Code section ended prematurely", 6297a7e6055SDimitry Andric object_error::parse_failed); 6307a7e6055SDimitry Andric return Error::success(); 6317a7e6055SDimitry Andric } 6327a7e6055SDimitry Andric 6337a7e6055SDimitry Andric Error WasmObjectFile::parseElemSection(const uint8_t *Ptr, const uint8_t *End) { 6347a7e6055SDimitry Andric uint32_t Count = readVaruint32(Ptr); 6357a7e6055SDimitry Andric ElemSegments.reserve(Count); 6367a7e6055SDimitry Andric while (Count--) { 6377a7e6055SDimitry Andric wasm::WasmElemSegment Segment; 6387a7e6055SDimitry Andric Segment.TableIndex = readVaruint32(Ptr); 6397a7e6055SDimitry Andric if (Segment.TableIndex != 0) { 6407a7e6055SDimitry Andric return make_error<GenericBinaryError>("Invalid TableIndex", 6417a7e6055SDimitry Andric object_error::parse_failed); 6427a7e6055SDimitry Andric } 6437a7e6055SDimitry Andric if (Error Err = readInitExpr(Segment.Offset, Ptr)) 6447a7e6055SDimitry Andric return Err; 6457a7e6055SDimitry Andric uint32_t NumElems = readVaruint32(Ptr); 6467a7e6055SDimitry Andric while (NumElems--) { 6477a7e6055SDimitry Andric Segment.Functions.push_back(readVaruint32(Ptr)); 6487a7e6055SDimitry Andric } 6497a7e6055SDimitry Andric ElemSegments.push_back(Segment); 6507a7e6055SDimitry Andric } 6517a7e6055SDimitry Andric if (Ptr != End) 6527a7e6055SDimitry Andric return make_error<GenericBinaryError>("Elem section ended prematurely", 6537a7e6055SDimitry Andric object_error::parse_failed); 6547a7e6055SDimitry Andric return Error::success(); 6557a7e6055SDimitry Andric } 6567a7e6055SDimitry Andric 6577a7e6055SDimitry Andric Error WasmObjectFile::parseDataSection(const uint8_t *Ptr, const uint8_t *End) { 6587a7e6055SDimitry Andric uint32_t Count = readVaruint32(Ptr); 6597a7e6055SDimitry Andric DataSegments.reserve(Count); 6607a7e6055SDimitry Andric while (Count--) { 6617a7e6055SDimitry Andric wasm::WasmDataSegment Segment; 6627a7e6055SDimitry Andric Segment.Index = readVaruint32(Ptr); 6637a7e6055SDimitry Andric if (Error Err = readInitExpr(Segment.Offset, Ptr)) 6647a7e6055SDimitry Andric return Err; 6657a7e6055SDimitry Andric uint32_t Size = readVaruint32(Ptr); 6667a7e6055SDimitry Andric Segment.Content = ArrayRef<uint8_t>(Ptr, Size); 6677a7e6055SDimitry Andric Ptr += Size; 6687a7e6055SDimitry Andric DataSegments.push_back(Segment); 6697a7e6055SDimitry Andric } 6707a7e6055SDimitry Andric if (Ptr != End) 6717a7e6055SDimitry Andric return make_error<GenericBinaryError>("Data section ended prematurely", 6727a7e6055SDimitry Andric object_error::parse_failed); 673d88c1a5aSDimitry Andric return Error::success(); 674d88c1a5aSDimitry Andric } 675d88c1a5aSDimitry Andric 676d88c1a5aSDimitry Andric const uint8_t *WasmObjectFile::getPtr(size_t Offset) const { 677d88c1a5aSDimitry Andric return reinterpret_cast<const uint8_t *>(getData().substr(Offset, 1).data()); 678d88c1a5aSDimitry Andric } 679d88c1a5aSDimitry Andric 680d88c1a5aSDimitry Andric const wasm::WasmObjectHeader &WasmObjectFile::getHeader() const { 681d88c1a5aSDimitry Andric return Header; 682d88c1a5aSDimitry Andric } 683d88c1a5aSDimitry Andric 6847a7e6055SDimitry Andric void WasmObjectFile::moveSymbolNext(DataRefImpl &Symb) const { Symb.d.a++; } 685d88c1a5aSDimitry Andric 686d88c1a5aSDimitry Andric uint32_t WasmObjectFile::getSymbolFlags(DataRefImpl Symb) const { 6870f5676f4SDimitry Andric uint32_t Result = SymbolRef::SF_None; 6887a7e6055SDimitry Andric const WasmSymbol &Sym = getWasmSymbol(Symb); 6890f5676f4SDimitry Andric 690edd7eaddSDimitry Andric DEBUG(dbgs() << "getSymbolFlags: ptr=" << &Sym << " " << Sym << "\n"); 691edd7eaddSDimitry Andric if (Sym.Flags & wasm::WASM_SYMBOL_FLAG_WEAK) 692edd7eaddSDimitry Andric Result |= SymbolRef::SF_Weak; 693edd7eaddSDimitry Andric 6947a7e6055SDimitry Andric switch (Sym.Type) { 6957a7e6055SDimitry Andric case WasmSymbol::SymbolType::FUNCTION_IMPORT: 6960f5676f4SDimitry Andric Result |= SymbolRef::SF_Undefined | SymbolRef::SF_Executable; 6970f5676f4SDimitry Andric break; 6987a7e6055SDimitry Andric case WasmSymbol::SymbolType::FUNCTION_EXPORT: 6990f5676f4SDimitry Andric Result |= SymbolRef::SF_Global | SymbolRef::SF_Executable; 7000f5676f4SDimitry Andric break; 7017a7e6055SDimitry Andric case WasmSymbol::SymbolType::DEBUG_FUNCTION_NAME: 7020f5676f4SDimitry Andric Result |= SymbolRef::SF_Executable; 703edd7eaddSDimitry Andric Result |= SymbolRef::SF_FormatSpecific; 7040f5676f4SDimitry Andric break; 7057a7e6055SDimitry Andric case WasmSymbol::SymbolType::GLOBAL_IMPORT: 7060f5676f4SDimitry Andric Result |= SymbolRef::SF_Undefined; 7070f5676f4SDimitry Andric break; 7087a7e6055SDimitry Andric case WasmSymbol::SymbolType::GLOBAL_EXPORT: 7090f5676f4SDimitry Andric Result |= SymbolRef::SF_Global; 7100f5676f4SDimitry Andric break; 7117a7e6055SDimitry Andric } 7120f5676f4SDimitry Andric 7130f5676f4SDimitry Andric return Result; 714d88c1a5aSDimitry Andric } 715d88c1a5aSDimitry Andric 716d88c1a5aSDimitry Andric basic_symbol_iterator WasmObjectFile::symbol_begin() const { 7177a7e6055SDimitry Andric DataRefImpl Ref; 7187a7e6055SDimitry Andric Ref.d.a = 0; 7197a7e6055SDimitry Andric return BasicSymbolRef(Ref, this); 720d88c1a5aSDimitry Andric } 721d88c1a5aSDimitry Andric 722d88c1a5aSDimitry Andric basic_symbol_iterator WasmObjectFile::symbol_end() const { 7237a7e6055SDimitry Andric DataRefImpl Ref; 7247a7e6055SDimitry Andric Ref.d.a = Symbols.size(); 7257a7e6055SDimitry Andric return BasicSymbolRef(Ref, this); 7267a7e6055SDimitry Andric } 7277a7e6055SDimitry Andric 7285517e702SDimitry Andric const WasmSymbol &WasmObjectFile::getWasmSymbol(const DataRefImpl &Symb) const { 7297a7e6055SDimitry Andric return Symbols[Symb.d.a]; 730d88c1a5aSDimitry Andric } 731d88c1a5aSDimitry Andric 7325517e702SDimitry Andric const WasmSymbol &WasmObjectFile::getWasmSymbol(const SymbolRef &Symb) const { 7335517e702SDimitry Andric return getWasmSymbol(Symb.getRawDataRefImpl()); 7345517e702SDimitry Andric } 7355517e702SDimitry Andric 736d88c1a5aSDimitry Andric Expected<StringRef> WasmObjectFile::getSymbolName(DataRefImpl Symb) const { 737edd7eaddSDimitry Andric return getWasmSymbol(Symb).Name; 738d88c1a5aSDimitry Andric } 739d88c1a5aSDimitry Andric 740d88c1a5aSDimitry Andric Expected<uint64_t> WasmObjectFile::getSymbolAddress(DataRefImpl Symb) const { 7410f5676f4SDimitry Andric return getSymbolValue(Symb); 742d88c1a5aSDimitry Andric } 743d88c1a5aSDimitry Andric 744d88c1a5aSDimitry Andric uint64_t WasmObjectFile::getSymbolValueImpl(DataRefImpl Symb) const { 7450f5676f4SDimitry Andric const WasmSymbol& Sym = getWasmSymbol(Symb); 746edd7eaddSDimitry Andric switch (Sym.Type) { 747edd7eaddSDimitry Andric case WasmSymbol::SymbolType::FUNCTION_IMPORT: 748edd7eaddSDimitry Andric case WasmSymbol::SymbolType::GLOBAL_IMPORT: 749edd7eaddSDimitry Andric return 0; 750edd7eaddSDimitry Andric case WasmSymbol::SymbolType::FUNCTION_EXPORT: 751edd7eaddSDimitry Andric case WasmSymbol::SymbolType::GLOBAL_EXPORT: 752edd7eaddSDimitry Andric return Exports[Sym.ElementIndex].Index; 753edd7eaddSDimitry Andric case WasmSymbol::SymbolType::DEBUG_FUNCTION_NAME: 7540f5676f4SDimitry Andric return Sym.ElementIndex; 755d88c1a5aSDimitry Andric } 756edd7eaddSDimitry Andric llvm_unreachable("invalid symbol type"); 757edd7eaddSDimitry Andric } 758d88c1a5aSDimitry Andric 759d88c1a5aSDimitry Andric uint32_t WasmObjectFile::getSymbolAlignment(DataRefImpl Symb) const { 760d88c1a5aSDimitry Andric llvm_unreachable("not yet implemented"); 761d88c1a5aSDimitry Andric return 0; 762d88c1a5aSDimitry Andric } 763d88c1a5aSDimitry Andric 764d88c1a5aSDimitry Andric uint64_t WasmObjectFile::getCommonSymbolSizeImpl(DataRefImpl Symb) const { 765d88c1a5aSDimitry Andric llvm_unreachable("not yet implemented"); 766d88c1a5aSDimitry Andric return 0; 767d88c1a5aSDimitry Andric } 768d88c1a5aSDimitry Andric 769d88c1a5aSDimitry Andric Expected<SymbolRef::Type> 770d88c1a5aSDimitry Andric WasmObjectFile::getSymbolType(DataRefImpl Symb) const { 7710f5676f4SDimitry Andric const WasmSymbol &Sym = getWasmSymbol(Symb); 7720f5676f4SDimitry Andric 7730f5676f4SDimitry Andric switch (Sym.Type) { 7740f5676f4SDimitry Andric case WasmSymbol::SymbolType::FUNCTION_IMPORT: 7750f5676f4SDimitry Andric case WasmSymbol::SymbolType::FUNCTION_EXPORT: 7760f5676f4SDimitry Andric case WasmSymbol::SymbolType::DEBUG_FUNCTION_NAME: 7770f5676f4SDimitry Andric return SymbolRef::ST_Function; 7780f5676f4SDimitry Andric case WasmSymbol::SymbolType::GLOBAL_IMPORT: 7790f5676f4SDimitry Andric case WasmSymbol::SymbolType::GLOBAL_EXPORT: 7800f5676f4SDimitry Andric return SymbolRef::ST_Data; 7810f5676f4SDimitry Andric } 7820f5676f4SDimitry Andric 7830f5676f4SDimitry Andric llvm_unreachable("Unknown WasmSymbol::SymbolType"); 7840f5676f4SDimitry Andric return SymbolRef::ST_Other; 785d88c1a5aSDimitry Andric } 786d88c1a5aSDimitry Andric 787d88c1a5aSDimitry Andric Expected<section_iterator> 788d88c1a5aSDimitry Andric WasmObjectFile::getSymbolSection(DataRefImpl Symb) const { 7890f5676f4SDimitry Andric DataRefImpl Ref; 7900f5676f4SDimitry Andric Ref.d.a = getWasmSymbol(Symb).Section; 7910f5676f4SDimitry Andric return section_iterator(SectionRef(Ref, this)); 792d88c1a5aSDimitry Andric } 793d88c1a5aSDimitry Andric 794d88c1a5aSDimitry Andric void WasmObjectFile::moveSectionNext(DataRefImpl &Sec) const { Sec.d.a++; } 795d88c1a5aSDimitry Andric 796d88c1a5aSDimitry Andric std::error_code WasmObjectFile::getSectionName(DataRefImpl Sec, 797d88c1a5aSDimitry Andric StringRef &Res) const { 7987a7e6055SDimitry Andric const WasmSection &S = Sections[Sec.d.a]; 799d88c1a5aSDimitry Andric #define ECase(X) \ 800d88c1a5aSDimitry Andric case wasm::WASM_SEC_##X: \ 801d88c1a5aSDimitry Andric Res = #X; \ 802d88c1a5aSDimitry Andric break 803d88c1a5aSDimitry Andric switch (S.Type) { 804d88c1a5aSDimitry Andric ECase(TYPE); 805d88c1a5aSDimitry Andric ECase(IMPORT); 806d88c1a5aSDimitry Andric ECase(FUNCTION); 807d88c1a5aSDimitry Andric ECase(TABLE); 808d88c1a5aSDimitry Andric ECase(MEMORY); 809d88c1a5aSDimitry Andric ECase(GLOBAL); 810d88c1a5aSDimitry Andric ECase(EXPORT); 811d88c1a5aSDimitry Andric ECase(START); 812d88c1a5aSDimitry Andric ECase(ELEM); 813d88c1a5aSDimitry Andric ECase(CODE); 814d88c1a5aSDimitry Andric ECase(DATA); 8157a7e6055SDimitry Andric case wasm::WASM_SEC_CUSTOM: 816d88c1a5aSDimitry Andric Res = S.Name; 817d88c1a5aSDimitry Andric break; 818d88c1a5aSDimitry Andric default: 819d88c1a5aSDimitry Andric return object_error::invalid_section_index; 820d88c1a5aSDimitry Andric } 821d88c1a5aSDimitry Andric #undef ECase 822d88c1a5aSDimitry Andric return std::error_code(); 823d88c1a5aSDimitry Andric } 824d88c1a5aSDimitry Andric 825d88c1a5aSDimitry Andric uint64_t WasmObjectFile::getSectionAddress(DataRefImpl Sec) const { return 0; } 826d88c1a5aSDimitry Andric 827302affcbSDimitry Andric uint64_t WasmObjectFile::getSectionIndex(DataRefImpl Sec) const { 828302affcbSDimitry Andric return Sec.d.a; 829302affcbSDimitry Andric } 830302affcbSDimitry Andric 831d88c1a5aSDimitry Andric uint64_t WasmObjectFile::getSectionSize(DataRefImpl Sec) const { 8327a7e6055SDimitry Andric const WasmSection &S = Sections[Sec.d.a]; 833d88c1a5aSDimitry Andric return S.Content.size(); 834d88c1a5aSDimitry Andric } 835d88c1a5aSDimitry Andric 836d88c1a5aSDimitry Andric std::error_code WasmObjectFile::getSectionContents(DataRefImpl Sec, 837d88c1a5aSDimitry Andric StringRef &Res) const { 8387a7e6055SDimitry Andric const WasmSection &S = Sections[Sec.d.a]; 839d88c1a5aSDimitry Andric // This will never fail since wasm sections can never be empty (user-sections 840d88c1a5aSDimitry Andric // must have a name and non-user sections each have a defined structure). 841d88c1a5aSDimitry Andric Res = StringRef(reinterpret_cast<const char *>(S.Content.data()), 842d88c1a5aSDimitry Andric S.Content.size()); 843d88c1a5aSDimitry Andric return std::error_code(); 844d88c1a5aSDimitry Andric } 845d88c1a5aSDimitry Andric 846d88c1a5aSDimitry Andric uint64_t WasmObjectFile::getSectionAlignment(DataRefImpl Sec) const { 847d88c1a5aSDimitry Andric return 1; 848d88c1a5aSDimitry Andric } 849d88c1a5aSDimitry Andric 850d88c1a5aSDimitry Andric bool WasmObjectFile::isSectionCompressed(DataRefImpl Sec) const { 851d88c1a5aSDimitry Andric return false; 852d88c1a5aSDimitry Andric } 853d88c1a5aSDimitry Andric 854d88c1a5aSDimitry Andric bool WasmObjectFile::isSectionText(DataRefImpl Sec) const { 8557a7e6055SDimitry Andric return getWasmSection(Sec).Type == wasm::WASM_SEC_CODE; 856d88c1a5aSDimitry Andric } 857d88c1a5aSDimitry Andric 858d88c1a5aSDimitry Andric bool WasmObjectFile::isSectionData(DataRefImpl Sec) const { 8597a7e6055SDimitry Andric return getWasmSection(Sec).Type == wasm::WASM_SEC_DATA; 860d88c1a5aSDimitry Andric } 861d88c1a5aSDimitry Andric 862d88c1a5aSDimitry Andric bool WasmObjectFile::isSectionBSS(DataRefImpl Sec) const { return false; } 863d88c1a5aSDimitry Andric 864d88c1a5aSDimitry Andric bool WasmObjectFile::isSectionVirtual(DataRefImpl Sec) const { return false; } 865d88c1a5aSDimitry Andric 866d88c1a5aSDimitry Andric bool WasmObjectFile::isSectionBitcode(DataRefImpl Sec) const { return false; } 867d88c1a5aSDimitry Andric 8687a7e6055SDimitry Andric relocation_iterator WasmObjectFile::section_rel_begin(DataRefImpl Ref) const { 8697a7e6055SDimitry Andric DataRefImpl RelocRef; 8707a7e6055SDimitry Andric RelocRef.d.a = Ref.d.a; 8717a7e6055SDimitry Andric RelocRef.d.b = 0; 8727a7e6055SDimitry Andric return relocation_iterator(RelocationRef(RelocRef, this)); 873d88c1a5aSDimitry Andric } 874d88c1a5aSDimitry Andric 8757a7e6055SDimitry Andric relocation_iterator WasmObjectFile::section_rel_end(DataRefImpl Ref) const { 8767a7e6055SDimitry Andric const WasmSection &Sec = getWasmSection(Ref); 8777a7e6055SDimitry Andric DataRefImpl RelocRef; 8787a7e6055SDimitry Andric RelocRef.d.a = Ref.d.a; 8797a7e6055SDimitry Andric RelocRef.d.b = Sec.Relocations.size(); 8807a7e6055SDimitry Andric return relocation_iterator(RelocationRef(RelocRef, this)); 881d88c1a5aSDimitry Andric } 882d88c1a5aSDimitry Andric 883d88c1a5aSDimitry Andric void WasmObjectFile::moveRelocationNext(DataRefImpl &Rel) const { 8847a7e6055SDimitry Andric Rel.d.b++; 885d88c1a5aSDimitry Andric } 886d88c1a5aSDimitry Andric 8877a7e6055SDimitry Andric uint64_t WasmObjectFile::getRelocationOffset(DataRefImpl Ref) const { 8887a7e6055SDimitry Andric const wasm::WasmRelocation &Rel = getWasmRelocation(Ref); 8897a7e6055SDimitry Andric return Rel.Offset; 890d88c1a5aSDimitry Andric } 891d88c1a5aSDimitry Andric 892d88c1a5aSDimitry Andric symbol_iterator WasmObjectFile::getRelocationSymbol(DataRefImpl Rel) const { 893d88c1a5aSDimitry Andric llvm_unreachable("not yet implemented"); 894d88c1a5aSDimitry Andric SymbolRef Ref; 895d88c1a5aSDimitry Andric return symbol_iterator(Ref); 896d88c1a5aSDimitry Andric } 897d88c1a5aSDimitry Andric 8987a7e6055SDimitry Andric uint64_t WasmObjectFile::getRelocationType(DataRefImpl Ref) const { 8997a7e6055SDimitry Andric const wasm::WasmRelocation &Rel = getWasmRelocation(Ref); 9007a7e6055SDimitry Andric return Rel.Type; 901d88c1a5aSDimitry Andric } 902d88c1a5aSDimitry Andric 903d88c1a5aSDimitry Andric void WasmObjectFile::getRelocationTypeName( 9047a7e6055SDimitry Andric DataRefImpl Ref, SmallVectorImpl<char> &Result) const { 9057a7e6055SDimitry Andric const wasm::WasmRelocation& Rel = getWasmRelocation(Ref); 9067a7e6055SDimitry Andric StringRef Res = "Unknown"; 9077a7e6055SDimitry Andric 9087a7e6055SDimitry Andric #define WASM_RELOC(name, value) \ 9097a7e6055SDimitry Andric case wasm::name: \ 9107a7e6055SDimitry Andric Res = #name; \ 9117a7e6055SDimitry Andric break; 9127a7e6055SDimitry Andric 9137a7e6055SDimitry Andric switch (Rel.Type) { 914db17bf38SDimitry Andric #include "llvm/BinaryFormat/WasmRelocs/WebAssembly.def" 9157a7e6055SDimitry Andric } 9167a7e6055SDimitry Andric 9177a7e6055SDimitry Andric #undef WASM_RELOC 9187a7e6055SDimitry Andric 9197a7e6055SDimitry Andric Result.append(Res.begin(), Res.end()); 920d88c1a5aSDimitry Andric } 921d88c1a5aSDimitry Andric 922d88c1a5aSDimitry Andric section_iterator WasmObjectFile::section_begin() const { 923d88c1a5aSDimitry Andric DataRefImpl Ref; 924d88c1a5aSDimitry Andric Ref.d.a = 0; 925d88c1a5aSDimitry Andric return section_iterator(SectionRef(Ref, this)); 926d88c1a5aSDimitry Andric } 927d88c1a5aSDimitry Andric 928d88c1a5aSDimitry Andric section_iterator WasmObjectFile::section_end() const { 929d88c1a5aSDimitry Andric DataRefImpl Ref; 930d88c1a5aSDimitry Andric Ref.d.a = Sections.size(); 931d88c1a5aSDimitry Andric return section_iterator(SectionRef(Ref, this)); 932d88c1a5aSDimitry Andric } 933d88c1a5aSDimitry Andric 934d88c1a5aSDimitry Andric uint8_t WasmObjectFile::getBytesInAddress() const { return 4; } 935d88c1a5aSDimitry Andric 936d88c1a5aSDimitry Andric StringRef WasmObjectFile::getFileFormatName() const { return "WASM"; } 937d88c1a5aSDimitry Andric 938d88c1a5aSDimitry Andric unsigned WasmObjectFile::getArch() const { return Triple::wasm32; } 939d88c1a5aSDimitry Andric 940d88c1a5aSDimitry Andric SubtargetFeatures WasmObjectFile::getFeatures() const { 941d88c1a5aSDimitry Andric return SubtargetFeatures(); 942d88c1a5aSDimitry Andric } 943d88c1a5aSDimitry Andric 944d88c1a5aSDimitry Andric bool WasmObjectFile::isRelocatableObject() const { return false; } 945d88c1a5aSDimitry Andric 9467a7e6055SDimitry Andric const WasmSection &WasmObjectFile::getWasmSection(DataRefImpl Ref) const { 9477a7e6055SDimitry Andric assert(Ref.d.a < Sections.size()); 9487a7e6055SDimitry Andric return Sections[Ref.d.a]; 949d88c1a5aSDimitry Andric } 950d88c1a5aSDimitry Andric 9517a7e6055SDimitry Andric const WasmSection & 9527a7e6055SDimitry Andric WasmObjectFile::getWasmSection(const SectionRef &Section) const { 9537a7e6055SDimitry Andric return getWasmSection(Section.getRawDataRefImpl()); 9547a7e6055SDimitry Andric } 9557a7e6055SDimitry Andric 9567a7e6055SDimitry Andric const wasm::WasmRelocation & 9577a7e6055SDimitry Andric WasmObjectFile::getWasmRelocation(const RelocationRef &Ref) const { 9587a7e6055SDimitry Andric return getWasmRelocation(Ref.getRawDataRefImpl()); 9597a7e6055SDimitry Andric } 9607a7e6055SDimitry Andric 9617a7e6055SDimitry Andric const wasm::WasmRelocation & 9627a7e6055SDimitry Andric WasmObjectFile::getWasmRelocation(DataRefImpl Ref) const { 9637a7e6055SDimitry Andric assert(Ref.d.a < Sections.size()); 9647a7e6055SDimitry Andric const WasmSection& Sec = Sections[Ref.d.a]; 9657a7e6055SDimitry Andric assert(Ref.d.b < Sec.Relocations.size()); 9667a7e6055SDimitry Andric return Sec.Relocations[Ref.d.b]; 9677a7e6055SDimitry Andric } 968