Eugene Zelenko | 3a124c0 | 2017-02-09 01:09:54 +0000 | [diff] [blame] | 1 | //===- WasmObjectFile.cpp - Wasm object file implementation ---------------===// |
Derek Schuff | 7a578c9 | 2016-11-30 16:49:11 +0000 | [diff] [blame] | 2 | // |
| 3 | // The LLVM Compiler Infrastructure |
| 4 | // |
| 5 | // This file is distributed under the University of Illinois Open Source |
| 6 | // License. See LICENSE.TXT for details. |
| 7 | // |
| 8 | //===----------------------------------------------------------------------===// |
| 9 | |
Eugene Zelenko | 3a124c0 | 2017-02-09 01:09:54 +0000 | [diff] [blame] | 10 | #include "llvm/ADT/ArrayRef.h" |
Sam Clegg | d4e08e1 | 2018-01-12 02:11:31 +0000 | [diff] [blame] | 11 | #include "llvm/ADT/DenseSet.h" |
Eugene Zelenko | 3a124c0 | 2017-02-09 01:09:54 +0000 | [diff] [blame] | 12 | #include "llvm/ADT/STLExtras.h" |
| 13 | #include "llvm/ADT/StringRef.h" |
Sam Clegg | e92250a | 2018-01-09 23:43:14 +0000 | [diff] [blame] | 14 | #include "llvm/ADT/StringSet.h" |
Eugene Zelenko | 3a124c0 | 2017-02-09 01:09:54 +0000 | [diff] [blame] | 15 | #include "llvm/ADT/Triple.h" |
Zachary Turner | 19ca2b0 | 2017-06-07 03:48:56 +0000 | [diff] [blame] | 16 | #include "llvm/BinaryFormat/Wasm.h" |
Eugene Zelenko | 903f87e | 2017-04-21 22:03:05 +0000 | [diff] [blame] | 17 | #include "llvm/MC/SubtargetFeature.h" |
Eugene Zelenko | 3a124c0 | 2017-02-09 01:09:54 +0000 | [diff] [blame] | 18 | #include "llvm/Object/Binary.h" |
| 19 | #include "llvm/Object/Error.h" |
| 20 | #include "llvm/Object/ObjectFile.h" |
| 21 | #include "llvm/Object/SymbolicFile.h" |
Derek Schuff | 7a578c9 | 2016-11-30 16:49:11 +0000 | [diff] [blame] | 22 | #include "llvm/Object/Wasm.h" |
| 23 | #include "llvm/Support/Endian.h" |
Eugene Zelenko | 3a124c0 | 2017-02-09 01:09:54 +0000 | [diff] [blame] | 24 | #include "llvm/Support/Error.h" |
| 25 | #include "llvm/Support/ErrorHandling.h" |
Derek Schuff | 7a578c9 | 2016-11-30 16:49:11 +0000 | [diff] [blame] | 26 | #include "llvm/Support/LEB128.h" |
Heejin Ahn | e2f3e50 | 2018-12-15 00:58:12 +0000 | [diff] [blame] | 27 | #include "llvm/Support/ScopedPrinter.h" |
Eugene Zelenko | 3a124c0 | 2017-02-09 01:09:54 +0000 | [diff] [blame] | 28 | #include <algorithm> |
Eugene Zelenko | 903f87e | 2017-04-21 22:03:05 +0000 | [diff] [blame] | 29 | #include <cassert> |
Eugene Zelenko | 3a124c0 | 2017-02-09 01:09:54 +0000 | [diff] [blame] | 30 | #include <cstdint> |
Eugene Zelenko | 903f87e | 2017-04-21 22:03:05 +0000 | [diff] [blame] | 31 | #include <cstring> |
Eugene Zelenko | 3a124c0 | 2017-02-09 01:09:54 +0000 | [diff] [blame] | 32 | #include <system_error> |
Derek Schuff | 7a578c9 | 2016-11-30 16:49:11 +0000 | [diff] [blame] | 33 | |
Sam Clegg | 1e975c1 | 2017-06-20 04:04:59 +0000 | [diff] [blame] | 34 | #define DEBUG_TYPE "wasm-object" |
| 35 | |
Eugene Zelenko | 3a124c0 | 2017-02-09 01:09:54 +0000 | [diff] [blame] | 36 | using namespace llvm; |
| 37 | using namespace object; |
Derek Schuff | 7a578c9 | 2016-11-30 16:49:11 +0000 | [diff] [blame] | 38 | |
JF Bastien | 62014b8 | 2018-05-16 21:24:03 +0000 | [diff] [blame] | 39 | void WasmSymbol::print(raw_ostream &Out) const { |
| 40 | Out << "Name=" << Info.Name |
Heejin Ahn | 581d231 | 2018-09-05 01:27:38 +0000 | [diff] [blame] | 41 | << ", Kind=" << toString(wasm::WasmSymbolType(Info.Kind)) |
| 42 | << ", Flags=" << Info.Flags; |
JF Bastien | 62014b8 | 2018-05-16 21:24:03 +0000 | [diff] [blame] | 43 | if (!isTypeData()) { |
| 44 | Out << ", ElemIndex=" << Info.ElementIndex; |
| 45 | } else if (isDefined()) { |
| 46 | Out << ", Segment=" << Info.DataRef.Segment; |
| 47 | Out << ", Offset=" << Info.DataRef.Offset; |
| 48 | Out << ", Size=" << Info.DataRef.Size; |
| 49 | } |
| 50 | } |
| 51 | |
JF Bastien | 2a77a18 | 2018-05-16 22:31:42 +0000 | [diff] [blame] | 52 | #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) |
| 53 | LLVM_DUMP_METHOD void WasmSymbol::dump() const { print(dbgs()); } |
| 54 | #endif |
| 55 | |
Derek Schuff | 7a578c9 | 2016-11-30 16:49:11 +0000 | [diff] [blame] | 56 | Expected<std::unique_ptr<WasmObjectFile>> |
| 57 | ObjectFile::createWasmObjectFile(MemoryBufferRef Buffer) { |
| 58 | Error Err = Error::success(); |
| 59 | auto ObjectFile = llvm::make_unique<WasmObjectFile>(Buffer, Err); |
| 60 | if (Err) |
| 61 | return std::move(Err); |
| 62 | |
| 63 | return std::move(ObjectFile); |
| 64 | } |
| 65 | |
Heejin Ahn | 581d231 | 2018-09-05 01:27:38 +0000 | [diff] [blame] | 66 | #define VARINT7_MAX ((1 << 7) - 1) |
| 67 | #define VARINT7_MIN (-(1 << 7)) |
| 68 | #define VARUINT7_MAX (1 << 7) |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 69 | #define VARUINT1_MAX (1) |
| 70 | |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 71 | static uint8_t readUint8(WasmObjectFile::ReadContext &Ctx) { |
| 72 | if (Ctx.Ptr == Ctx.End) |
| 73 | report_fatal_error("EOF while reading uint8"); |
| 74 | return *Ctx.Ptr++; |
| 75 | } |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 76 | |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 77 | static uint32_t readUint32(WasmObjectFile::ReadContext &Ctx) { |
| 78 | if (Ctx.Ptr + 4 > Ctx.End) |
| 79 | report_fatal_error("EOF while reading uint32"); |
| 80 | uint32_t Result = support::endian::read32le(Ctx.Ptr); |
| 81 | Ctx.Ptr += 4; |
Derek Schuff | 7a578c9 | 2016-11-30 16:49:11 +0000 | [diff] [blame] | 82 | return Result; |
| 83 | } |
| 84 | |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 85 | static int32_t readFloat32(WasmObjectFile::ReadContext &Ctx) { |
Jonas Devlieghere | 1dc4181 | 2018-08-31 14:54:01 +0000 | [diff] [blame] | 86 | if (Ctx.Ptr + 4 > Ctx.End) |
| 87 | report_fatal_error("EOF while reading float64"); |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 88 | int32_t Result = 0; |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 89 | memcpy(&Result, Ctx.Ptr, sizeof(Result)); |
| 90 | Ctx.Ptr += sizeof(Result); |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 91 | return Result; |
| 92 | } |
| 93 | |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 94 | static int64_t readFloat64(WasmObjectFile::ReadContext &Ctx) { |
Jonas Devlieghere | 1dc4181 | 2018-08-31 14:54:01 +0000 | [diff] [blame] | 95 | if (Ctx.Ptr + 8 > Ctx.End) |
| 96 | report_fatal_error("EOF while reading float64"); |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 97 | int64_t Result = 0; |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 98 | memcpy(&Result, Ctx.Ptr, sizeof(Result)); |
| 99 | Ctx.Ptr += sizeof(Result); |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 100 | return Result; |
| 101 | } |
| 102 | |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 103 | static uint64_t readULEB128(WasmObjectFile::ReadContext &Ctx) { |
Derek Schuff | 7a578c9 | 2016-11-30 16:49:11 +0000 | [diff] [blame] | 104 | unsigned Count; |
Heejin Ahn | 581d231 | 2018-09-05 01:27:38 +0000 | [diff] [blame] | 105 | const char *Error = nullptr; |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 106 | uint64_t Result = decodeULEB128(Ctx.Ptr, &Count, Ctx.End, &Error); |
| 107 | if (Error) |
| 108 | report_fatal_error(Error); |
| 109 | Ctx.Ptr += Count; |
Derek Schuff | 7a578c9 | 2016-11-30 16:49:11 +0000 | [diff] [blame] | 110 | return Result; |
| 111 | } |
| 112 | |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 113 | static StringRef readString(WasmObjectFile::ReadContext &Ctx) { |
| 114 | uint32_t StringLen = readULEB128(Ctx); |
| 115 | if (Ctx.Ptr + StringLen > Ctx.End) |
| 116 | report_fatal_error("EOF while reading string"); |
| 117 | StringRef Return = |
| 118 | StringRef(reinterpret_cast<const char *>(Ctx.Ptr), StringLen); |
| 119 | Ctx.Ptr += StringLen; |
Derek Schuff | 7a578c9 | 2016-11-30 16:49:11 +0000 | [diff] [blame] | 120 | return Return; |
| 121 | } |
| 122 | |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 123 | static int64_t readLEB128(WasmObjectFile::ReadContext &Ctx) { |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 124 | unsigned Count; |
Heejin Ahn | 581d231 | 2018-09-05 01:27:38 +0000 | [diff] [blame] | 125 | const char *Error = nullptr; |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 126 | uint64_t Result = decodeSLEB128(Ctx.Ptr, &Count, Ctx.End, &Error); |
| 127 | if (Error) |
| 128 | report_fatal_error(Error); |
| 129 | Ctx.Ptr += Count; |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 130 | return Result; |
| 131 | } |
| 132 | |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 133 | static uint8_t readVaruint1(WasmObjectFile::ReadContext &Ctx) { |
| 134 | int64_t result = readLEB128(Ctx); |
Sam Clegg | d0adb14 | 2018-05-18 21:08:26 +0000 | [diff] [blame] | 135 | if (result > VARUINT1_MAX || result < 0) |
| 136 | report_fatal_error("LEB is outside Varuint1 range"); |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 137 | return result; |
| 138 | } |
| 139 | |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 140 | static int32_t readVarint32(WasmObjectFile::ReadContext &Ctx) { |
| 141 | int64_t result = readLEB128(Ctx); |
Sam Clegg | d0adb14 | 2018-05-18 21:08:26 +0000 | [diff] [blame] | 142 | if (result > INT32_MAX || result < INT32_MIN) |
| 143 | report_fatal_error("LEB is outside Varint32 range"); |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 144 | return result; |
| 145 | } |
| 146 | |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 147 | static uint32_t readVaruint32(WasmObjectFile::ReadContext &Ctx) { |
| 148 | uint64_t result = readULEB128(Ctx); |
Sam Clegg | d0adb14 | 2018-05-18 21:08:26 +0000 | [diff] [blame] | 149 | if (result > UINT32_MAX) |
| 150 | report_fatal_error("LEB is outside Varuint32 range"); |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 151 | return result; |
| 152 | } |
| 153 | |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 154 | static int64_t readVarint64(WasmObjectFile::ReadContext &Ctx) { |
| 155 | return readLEB128(Ctx); |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 156 | } |
| 157 | |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 158 | static uint8_t readOpcode(WasmObjectFile::ReadContext &Ctx) { |
| 159 | return readUint8(Ctx); |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 160 | } |
| 161 | |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 162 | static Error readInitExpr(wasm::WasmInitExpr &Expr, |
| 163 | WasmObjectFile::ReadContext &Ctx) { |
| 164 | Expr.Opcode = readOpcode(Ctx); |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 165 | |
| 166 | switch (Expr.Opcode) { |
| 167 | case wasm::WASM_OPCODE_I32_CONST: |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 168 | Expr.Value.Int32 = readVarint32(Ctx); |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 169 | break; |
| 170 | case wasm::WASM_OPCODE_I64_CONST: |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 171 | Expr.Value.Int64 = readVarint64(Ctx); |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 172 | break; |
| 173 | case wasm::WASM_OPCODE_F32_CONST: |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 174 | Expr.Value.Float32 = readFloat32(Ctx); |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 175 | break; |
| 176 | case wasm::WASM_OPCODE_F64_CONST: |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 177 | Expr.Value.Float64 = readFloat64(Ctx); |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 178 | break; |
Thomas Lively | 37a984b | 2019-01-08 06:25:55 +0000 | [diff] [blame] | 179 | case wasm::WASM_OPCODE_GLOBAL_GET: |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 180 | Expr.Value.Global = readULEB128(Ctx); |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 181 | break; |
| 182 | default: |
| 183 | return make_error<GenericBinaryError>("Invalid opcode in init_expr", |
| 184 | object_error::parse_failed); |
| 185 | } |
| 186 | |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 187 | uint8_t EndOpcode = readOpcode(Ctx); |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 188 | if (EndOpcode != wasm::WASM_OPCODE_END) { |
| 189 | return make_error<GenericBinaryError>("Invalid init_expr", |
| 190 | object_error::parse_failed); |
| 191 | } |
| 192 | return Error::success(); |
| 193 | } |
| 194 | |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 195 | static wasm::WasmLimits readLimits(WasmObjectFile::ReadContext &Ctx) { |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 196 | wasm::WasmLimits Result; |
Derek Schuff | 992cf17 | 2018-11-06 17:27:25 +0000 | [diff] [blame] | 197 | Result.Flags = readVaruint32(Ctx); |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 198 | Result.Initial = readVaruint32(Ctx); |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 199 | if (Result.Flags & wasm::WASM_LIMITS_FLAG_HAS_MAX) |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 200 | Result.Maximum = readVaruint32(Ctx); |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 201 | return Result; |
| 202 | } |
| 203 | |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 204 | static wasm::WasmTable readTable(WasmObjectFile::ReadContext &Ctx) { |
Sam Clegg | 65e284e | 2017-05-09 23:48:41 +0000 | [diff] [blame] | 205 | wasm::WasmTable Table; |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 206 | Table.ElemType = readUint8(Ctx); |
| 207 | Table.Limits = readLimits(Ctx); |
Sam Clegg | 65e284e | 2017-05-09 23:48:41 +0000 | [diff] [blame] | 208 | return Table; |
| 209 | } |
| 210 | |
Heejin Ahn | e2f3e50 | 2018-12-15 00:58:12 +0000 | [diff] [blame] | 211 | static Error readSection(WasmSection &Section, WasmObjectFile::ReadContext &Ctx, |
| 212 | WasmSectionOrderChecker &Checker) { |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 213 | Section.Offset = Ctx.Ptr - Ctx.Start; |
| 214 | Section.Type = readUint8(Ctx); |
Sam Clegg | cb12250 | 2018-05-29 20:16:47 +0000 | [diff] [blame] | 215 | LLVM_DEBUG(dbgs() << "readSection type=" << Section.Type << "\n"); |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 216 | uint32_t Size = readVaruint32(Ctx); |
Derek Schuff | 7a578c9 | 2016-11-30 16:49:11 +0000 | [diff] [blame] | 217 | if (Size == 0) |
| 218 | return make_error<StringError>("Zero length section", |
| 219 | object_error::parse_failed); |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 220 | if (Ctx.Ptr + Size > Ctx.End) |
Vedant Kumar | f9ce75b | 2017-10-23 18:04:34 +0000 | [diff] [blame] | 221 | return make_error<StringError>("Section too large", |
| 222 | object_error::parse_failed); |
Sam Clegg | b068ce9 | 2018-04-12 20:31:12 +0000 | [diff] [blame] | 223 | if (Section.Type == wasm::WASM_SEC_CUSTOM) { |
Jonas Devlieghere | 7689b8d | 2018-08-08 16:34:03 +0000 | [diff] [blame] | 224 | WasmObjectFile::ReadContext SectionCtx; |
| 225 | SectionCtx.Start = Ctx.Ptr; |
| 226 | SectionCtx.Ptr = Ctx.Ptr; |
| 227 | SectionCtx.End = Ctx.Ptr + Size; |
| 228 | |
| 229 | Section.Name = readString(SectionCtx); |
| 230 | |
| 231 | uint32_t SectionNameSize = SectionCtx.Ptr - SectionCtx.Start; |
| 232 | Ctx.Ptr += SectionNameSize; |
| 233 | Size -= SectionNameSize; |
Sam Clegg | b068ce9 | 2018-04-12 20:31:12 +0000 | [diff] [blame] | 234 | } |
Heejin Ahn | e2f3e50 | 2018-12-15 00:58:12 +0000 | [diff] [blame] | 235 | |
| 236 | if (!Checker.isValidSectionOrder(Section.Type, Section.Name)) { |
| 237 | return make_error<StringError>("Out of order section type: " + |
| 238 | llvm::to_string(Section.Type), |
| 239 | object_error::parse_failed); |
| 240 | } |
| 241 | |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 242 | Section.Content = ArrayRef<uint8_t>(Ctx.Ptr, Size); |
| 243 | Ctx.Ptr += Size; |
Derek Schuff | 7a578c9 | 2016-11-30 16:49:11 +0000 | [diff] [blame] | 244 | return Error::success(); |
| 245 | } |
Derek Schuff | 7a578c9 | 2016-11-30 16:49:11 +0000 | [diff] [blame] | 246 | |
| 247 | WasmObjectFile::WasmObjectFile(MemoryBufferRef Buffer, Error &Err) |
Eugene Zelenko | 903f87e | 2017-04-21 22:03:05 +0000 | [diff] [blame] | 248 | : ObjectFile(Binary::ID_Wasm, Buffer) { |
Derek Schuff | 7a578c9 | 2016-11-30 16:49:11 +0000 | [diff] [blame] | 249 | ErrorAsOutParameter ErrAsOutParam(&Err); |
| 250 | Header.Magic = getData().substr(0, 4); |
| 251 | if (Header.Magic != StringRef("\0asm", 4)) { |
Heejin Ahn | 581d231 | 2018-09-05 01:27:38 +0000 | [diff] [blame] | 252 | Err = |
| 253 | make_error<StringError>("Bad magic number", object_error::parse_failed); |
Derek Schuff | 7a578c9 | 2016-11-30 16:49:11 +0000 | [diff] [blame] | 254 | return; |
| 255 | } |
Jonas Devlieghere | e69aa18 | 2017-08-23 21:36:04 +0000 | [diff] [blame] | 256 | |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 257 | ReadContext Ctx; |
| 258 | Ctx.Start = getPtr(0); |
| 259 | Ctx.Ptr = Ctx.Start + 4; |
| 260 | Ctx.End = Ctx.Start + getData().size(); |
Jonas Devlieghere | e69aa18 | 2017-08-23 21:36:04 +0000 | [diff] [blame] | 261 | |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 262 | if (Ctx.Ptr + 4 > Ctx.End) { |
Jonas Devlieghere | e69aa18 | 2017-08-23 21:36:04 +0000 | [diff] [blame] | 263 | Err = make_error<StringError>("Missing version number", |
| 264 | object_error::parse_failed); |
| 265 | return; |
| 266 | } |
| 267 | |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 268 | Header.Version = readUint32(Ctx); |
Derek Schuff | 7a578c9 | 2016-11-30 16:49:11 +0000 | [diff] [blame] | 269 | if (Header.Version != wasm::WasmVersion) { |
| 270 | Err = make_error<StringError>("Bad version number", |
| 271 | object_error::parse_failed); |
| 272 | return; |
| 273 | } |
| 274 | |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 275 | WasmSection Sec; |
Heejin Ahn | e2f3e50 | 2018-12-15 00:58:12 +0000 | [diff] [blame] | 276 | WasmSectionOrderChecker Checker; |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 277 | while (Ctx.Ptr < Ctx.End) { |
Heejin Ahn | e2f3e50 | 2018-12-15 00:58:12 +0000 | [diff] [blame] | 278 | if ((Err = readSection(Sec, Ctx, Checker))) |
Derek Schuff | 7a578c9 | 2016-11-30 16:49:11 +0000 | [diff] [blame] | 279 | return; |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 280 | if ((Err = parseSection(Sec))) |
| 281 | return; |
| 282 | |
Derek Schuff | 7a578c9 | 2016-11-30 16:49:11 +0000 | [diff] [blame] | 283 | Sections.push_back(Sec); |
| 284 | } |
| 285 | } |
| 286 | |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 287 | Error WasmObjectFile::parseSection(WasmSection &Sec) { |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 288 | ReadContext Ctx; |
| 289 | Ctx.Start = Sec.Content.data(); |
| 290 | Ctx.End = Ctx.Start + Sec.Content.size(); |
| 291 | Ctx.Ptr = Ctx.Start; |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 292 | switch (Sec.Type) { |
| 293 | case wasm::WASM_SEC_CUSTOM: |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 294 | return parseCustomSection(Sec, Ctx); |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 295 | case wasm::WASM_SEC_TYPE: |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 296 | return parseTypeSection(Ctx); |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 297 | case wasm::WASM_SEC_IMPORT: |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 298 | return parseImportSection(Ctx); |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 299 | case wasm::WASM_SEC_FUNCTION: |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 300 | return parseFunctionSection(Ctx); |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 301 | case wasm::WASM_SEC_TABLE: |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 302 | return parseTableSection(Ctx); |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 303 | case wasm::WASM_SEC_MEMORY: |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 304 | return parseMemorySection(Ctx); |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 305 | case wasm::WASM_SEC_GLOBAL: |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 306 | return parseGlobalSection(Ctx); |
Heejin Ahn | 8bcdd04 | 2018-11-14 02:46:21 +0000 | [diff] [blame] | 307 | case wasm::WASM_SEC_EVENT: |
| 308 | return parseEventSection(Ctx); |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 309 | case wasm::WASM_SEC_EXPORT: |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 310 | return parseExportSection(Ctx); |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 311 | case wasm::WASM_SEC_START: |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 312 | return parseStartSection(Ctx); |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 313 | case wasm::WASM_SEC_ELEM: |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 314 | return parseElemSection(Ctx); |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 315 | case wasm::WASM_SEC_CODE: |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 316 | return parseCodeSection(Ctx); |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 317 | case wasm::WASM_SEC_DATA: |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 318 | return parseDataSection(Ctx); |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 319 | default: |
| 320 | return make_error<GenericBinaryError>("Bad section type", |
| 321 | object_error::parse_failed); |
| 322 | } |
| 323 | } |
| 324 | |
Sam Clegg | 45c215a | 2018-11-14 18:36:24 +0000 | [diff] [blame] | 325 | Error WasmObjectFile::parseDylinkSection(ReadContext &Ctx) { |
| 326 | // See https://github.com/WebAssembly/tool-conventions/blob/master/DynamicLinking.md |
| 327 | DylinkInfo.MemorySize = readVaruint32(Ctx); |
| 328 | DylinkInfo.MemoryAlignment = readVaruint32(Ctx); |
| 329 | DylinkInfo.TableSize = readVaruint32(Ctx); |
| 330 | DylinkInfo.TableAlignment = readVaruint32(Ctx); |
Sam Clegg | 559201d | 2018-12-12 23:40:58 +0000 | [diff] [blame] | 331 | uint32_t Count = readVaruint32(Ctx); |
| 332 | while (Count--) { |
| 333 | DylinkInfo.Needed.push_back(readString(Ctx)); |
| 334 | } |
Sam Clegg | 45c215a | 2018-11-14 18:36:24 +0000 | [diff] [blame] | 335 | if (Ctx.Ptr != Ctx.End) |
| 336 | return make_error<GenericBinaryError>("dylink section ended prematurely", |
| 337 | object_error::parse_failed); |
| 338 | return Error::success(); |
| 339 | } |
| 340 | |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 341 | Error WasmObjectFile::parseNameSection(ReadContext &Ctx) { |
Sam Clegg | d4e08e1 | 2018-01-12 02:11:31 +0000 | [diff] [blame] | 342 | llvm::DenseSet<uint64_t> Seen; |
Sam Clegg | eb7fd73 | 2018-01-17 19:28:43 +0000 | [diff] [blame] | 343 | if (Functions.size() != FunctionTypes.size()) { |
| 344 | return make_error<GenericBinaryError>("Names must come after code section", |
| 345 | object_error::parse_failed); |
| 346 | } |
Sam Clegg | d4e08e1 | 2018-01-12 02:11:31 +0000 | [diff] [blame] | 347 | |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 348 | while (Ctx.Ptr < Ctx.End) { |
| 349 | uint8_t Type = readUint8(Ctx); |
| 350 | uint32_t Size = readVaruint32(Ctx); |
| 351 | const uint8_t *SubSectionEnd = Ctx.Ptr + Size; |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 352 | switch (Type) { |
| 353 | case wasm::WASM_NAMES_FUNCTION: { |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 354 | uint32_t Count = readVaruint32(Ctx); |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 355 | while (Count--) { |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 356 | uint32_t Index = readVaruint32(Ctx); |
Sam Clegg | d4e08e1 | 2018-01-12 02:11:31 +0000 | [diff] [blame] | 357 | if (!Seen.insert(Index).second) |
| 358 | return make_error<GenericBinaryError>("Function named more than once", |
| 359 | object_error::parse_failed); |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 360 | StringRef Name = readString(Ctx); |
Sam Clegg | eb7fd73 | 2018-01-17 19:28:43 +0000 | [diff] [blame] | 361 | if (!isValidFunctionIndex(Index) || Name.empty()) |
| 362 | return make_error<GenericBinaryError>("Invalid name entry", |
| 363 | object_error::parse_failed); |
| 364 | DebugNames.push_back(wasm::WasmFunctionName{Index, Name}); |
Nicholas Wilson | bb03300 | 2018-04-20 17:07:24 +0000 | [diff] [blame] | 365 | if (isDefinedFunctionIndex(Index)) |
| 366 | getDefinedFunction(Index).DebugName = Name; |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 367 | } |
| 368 | break; |
| 369 | } |
| 370 | // Ignore local names for now |
| 371 | case wasm::WASM_NAMES_LOCAL: |
| 372 | default: |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 373 | Ctx.Ptr += Size; |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 374 | break; |
| 375 | } |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 376 | if (Ctx.Ptr != SubSectionEnd) |
Heejin Ahn | 581d231 | 2018-09-05 01:27:38 +0000 | [diff] [blame] | 377 | return make_error<GenericBinaryError>( |
| 378 | "Name sub-section ended prematurely", object_error::parse_failed); |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 379 | } |
| 380 | |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 381 | if (Ctx.Ptr != Ctx.End) |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 382 | return make_error<GenericBinaryError>("Name section ended prematurely", |
| 383 | object_error::parse_failed); |
| 384 | return Error::success(); |
| 385 | } |
| 386 | |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 387 | Error WasmObjectFile::parseLinkingSection(ReadContext &Ctx) { |
Sam Clegg | 08da5c5 | 2017-06-27 20:40:53 +0000 | [diff] [blame] | 388 | HasLinkingSection = true; |
Sam Clegg | eb7fd73 | 2018-01-17 19:28:43 +0000 | [diff] [blame] | 389 | if (Functions.size() != FunctionTypes.size()) { |
| 390 | return make_error<GenericBinaryError>( |
Heejin Ahn | 581d231 | 2018-09-05 01:27:38 +0000 | [diff] [blame] | 391 | "Linking data must come after code section", |
| 392 | object_error::parse_failed); |
Sam Clegg | eb7fd73 | 2018-01-17 19:28:43 +0000 | [diff] [blame] | 393 | } |
Sam Clegg | 9f8cb47 | 2017-09-06 22:05:41 +0000 | [diff] [blame] | 394 | |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 395 | LinkingData.Version = readVaruint32(Ctx); |
Sam Clegg | 14598cb | 2018-04-26 18:15:32 +0000 | [diff] [blame] | 396 | if (LinkingData.Version != wasm::WasmMetadataVersion) { |
| 397 | return make_error<GenericBinaryError>( |
| 398 | "Unexpected metadata version: " + Twine(LinkingData.Version) + |
| 399 | " (Expected: " + Twine(wasm::WasmMetadataVersion) + ")", |
| 400 | object_error::parse_failed); |
| 401 | } |
| 402 | |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 403 | const uint8_t *OrigEnd = Ctx.End; |
| 404 | while (Ctx.Ptr < OrigEnd) { |
| 405 | Ctx.End = OrigEnd; |
| 406 | uint8_t Type = readUint8(Ctx); |
| 407 | uint32_t Size = readVaruint32(Ctx); |
Sam Clegg | cb12250 | 2018-05-29 20:16:47 +0000 | [diff] [blame] | 408 | LLVM_DEBUG(dbgs() << "readSubsection type=" << int(Type) << " size=" << Size |
| 409 | << "\n"); |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 410 | Ctx.End = Ctx.Ptr + Size; |
Sam Clegg | 1e975c1 | 2017-06-20 04:04:59 +0000 | [diff] [blame] | 411 | switch (Type) { |
Sam Clegg | d578479 | 2018-02-23 05:08:34 +0000 | [diff] [blame] | 412 | case wasm::WASM_SYMBOL_TABLE: |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 413 | if (Error Err = parseLinkingSectionSymtab(Ctx)) |
Sam Clegg | d578479 | 2018-02-23 05:08:34 +0000 | [diff] [blame] | 414 | return Err; |
Sam Clegg | 1e975c1 | 2017-06-20 04:04:59 +0000 | [diff] [blame] | 415 | break; |
Sam Clegg | e286417 | 2017-09-29 16:50:08 +0000 | [diff] [blame] | 416 | case wasm::WASM_SEGMENT_INFO: { |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 417 | uint32_t Count = readVaruint32(Ctx); |
Sam Clegg | 81e3824 | 2017-09-20 19:03:35 +0000 | [diff] [blame] | 418 | if (Count > DataSegments.size()) |
| 419 | return make_error<GenericBinaryError>("Too many segment names", |
| 420 | object_error::parse_failed); |
Sam Clegg | e286417 | 2017-09-29 16:50:08 +0000 | [diff] [blame] | 421 | for (uint32_t i = 0; i < Count; i++) { |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 422 | DataSegments[i].Data.Name = readString(Ctx); |
| 423 | DataSegments[i].Data.Alignment = readVaruint32(Ctx); |
| 424 | DataSegments[i].Data.Flags = readVaruint32(Ctx); |
Sam Clegg | e286417 | 2017-09-29 16:50:08 +0000 | [diff] [blame] | 425 | } |
Sam Clegg | 81e3824 | 2017-09-20 19:03:35 +0000 | [diff] [blame] | 426 | break; |
| 427 | } |
Sam Clegg | e1acb56 | 2017-12-14 21:10:03 +0000 | [diff] [blame] | 428 | case wasm::WASM_INIT_FUNCS: { |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 429 | uint32_t Count = readVaruint32(Ctx); |
Sam Clegg | e1acb56 | 2017-12-14 21:10:03 +0000 | [diff] [blame] | 430 | LinkingData.InitFunctions.reserve(Count); |
| 431 | for (uint32_t i = 0; i < Count; i++) { |
| 432 | wasm::WasmInitFunc Init; |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 433 | Init.Priority = readVaruint32(Ctx); |
| 434 | Init.Symbol = readVaruint32(Ctx); |
Nicholas Wilson | e0316ce | 2018-03-05 13:32:38 +0000 | [diff] [blame] | 435 | if (!isValidFunctionSymbol(Init.Symbol)) |
Sam Clegg | d578479 | 2018-02-23 05:08:34 +0000 | [diff] [blame] | 436 | return make_error<GenericBinaryError>("Invalid function symbol: " + |
| 437 | Twine(Init.Symbol), |
Sam Clegg | e1acb56 | 2017-12-14 21:10:03 +0000 | [diff] [blame] | 438 | object_error::parse_failed); |
| 439 | LinkingData.InitFunctions.emplace_back(Init); |
| 440 | } |
| 441 | break; |
| 442 | } |
Sam Clegg | e92250a | 2018-01-09 23:43:14 +0000 | [diff] [blame] | 443 | case wasm::WASM_COMDAT_INFO: |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 444 | if (Error Err = parseLinkingSectionComdat(Ctx)) |
Sam Clegg | e92250a | 2018-01-09 23:43:14 +0000 | [diff] [blame] | 445 | return Err; |
| 446 | break; |
Sam Clegg | 1e975c1 | 2017-06-20 04:04:59 +0000 | [diff] [blame] | 447 | default: |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 448 | Ctx.Ptr += Size; |
Sam Clegg | 1e975c1 | 2017-06-20 04:04:59 +0000 | [diff] [blame] | 449 | break; |
| 450 | } |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 451 | if (Ctx.Ptr != Ctx.End) |
Sam Clegg | 1e975c1 | 2017-06-20 04:04:59 +0000 | [diff] [blame] | 452 | return make_error<GenericBinaryError>( |
| 453 | "Linking sub-section ended prematurely", object_error::parse_failed); |
| 454 | } |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 455 | if (Ctx.Ptr != OrigEnd) |
Sam Clegg | 1e975c1 | 2017-06-20 04:04:59 +0000 | [diff] [blame] | 456 | return make_error<GenericBinaryError>("Linking section ended prematurely", |
| 457 | object_error::parse_failed); |
| 458 | return Error::success(); |
| 459 | } |
| 460 | |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 461 | Error WasmObjectFile::parseLinkingSectionSymtab(ReadContext &Ctx) { |
| 462 | uint32_t Count = readVaruint32(Ctx); |
Sam Clegg | d578479 | 2018-02-23 05:08:34 +0000 | [diff] [blame] | 463 | LinkingData.SymbolTable.reserve(Count); |
| 464 | Symbols.reserve(Count); |
| 465 | StringSet<> SymbolNames; |
| 466 | |
| 467 | std::vector<wasm::WasmImport *> ImportedGlobals; |
| 468 | std::vector<wasm::WasmImport *> ImportedFunctions; |
Heejin Ahn | 8bcdd04 | 2018-11-14 02:46:21 +0000 | [diff] [blame] | 469 | std::vector<wasm::WasmImport *> ImportedEvents; |
Sam Clegg | d578479 | 2018-02-23 05:08:34 +0000 | [diff] [blame] | 470 | ImportedGlobals.reserve(Imports.size()); |
| 471 | ImportedFunctions.reserve(Imports.size()); |
Heejin Ahn | 8bcdd04 | 2018-11-14 02:46:21 +0000 | [diff] [blame] | 472 | ImportedEvents.reserve(Imports.size()); |
Sam Clegg | d578479 | 2018-02-23 05:08:34 +0000 | [diff] [blame] | 473 | for (auto &I : Imports) { |
| 474 | if (I.Kind == wasm::WASM_EXTERNAL_FUNCTION) |
| 475 | ImportedFunctions.emplace_back(&I); |
| 476 | else if (I.Kind == wasm::WASM_EXTERNAL_GLOBAL) |
| 477 | ImportedGlobals.emplace_back(&I); |
Heejin Ahn | 8bcdd04 | 2018-11-14 02:46:21 +0000 | [diff] [blame] | 478 | else if (I.Kind == wasm::WASM_EXTERNAL_EVENT) |
| 479 | ImportedEvents.emplace_back(&I); |
Sam Clegg | d578479 | 2018-02-23 05:08:34 +0000 | [diff] [blame] | 480 | } |
| 481 | |
| 482 | while (Count--) { |
| 483 | wasm::WasmSymbolInfo Info; |
Heejin Ahn | 0123db8 | 2018-12-08 06:16:13 +0000 | [diff] [blame] | 484 | const wasm::WasmSignature *Signature = nullptr; |
Sam Clegg | d578479 | 2018-02-23 05:08:34 +0000 | [diff] [blame] | 485 | const wasm::WasmGlobalType *GlobalType = nullptr; |
Heejin Ahn | 8bcdd04 | 2018-11-14 02:46:21 +0000 | [diff] [blame] | 486 | const wasm::WasmEventType *EventType = nullptr; |
Sam Clegg | d578479 | 2018-02-23 05:08:34 +0000 | [diff] [blame] | 487 | |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 488 | Info.Kind = readUint8(Ctx); |
| 489 | Info.Flags = readVaruint32(Ctx); |
Sam Clegg | d578479 | 2018-02-23 05:08:34 +0000 | [diff] [blame] | 490 | bool IsDefined = (Info.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0; |
| 491 | |
| 492 | switch (Info.Kind) { |
| 493 | case wasm::WASM_SYMBOL_TYPE_FUNCTION: |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 494 | Info.ElementIndex = readVaruint32(Ctx); |
Sam Clegg | d578479 | 2018-02-23 05:08:34 +0000 | [diff] [blame] | 495 | if (!isValidFunctionIndex(Info.ElementIndex) || |
| 496 | IsDefined != isDefinedFunctionIndex(Info.ElementIndex)) |
| 497 | return make_error<GenericBinaryError>("invalid function symbol index", |
| 498 | object_error::parse_failed); |
| 499 | if (IsDefined) { |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 500 | Info.Name = readString(Ctx); |
Sam Clegg | d578479 | 2018-02-23 05:08:34 +0000 | [diff] [blame] | 501 | unsigned FuncIndex = Info.ElementIndex - NumImportedFunctions; |
Heejin Ahn | 0123db8 | 2018-12-08 06:16:13 +0000 | [diff] [blame] | 502 | Signature = &Signatures[FunctionTypes[FuncIndex]]; |
Nicholas Wilson | 5476767 | 2018-03-05 12:16:32 +0000 | [diff] [blame] | 503 | wasm::WasmFunction &Function = Functions[FuncIndex]; |
Nicholas Wilson | bb03300 | 2018-04-20 17:07:24 +0000 | [diff] [blame] | 504 | if (Function.SymbolName.empty()) |
| 505 | Function.SymbolName = Info.Name; |
Sam Clegg | d578479 | 2018-02-23 05:08:34 +0000 | [diff] [blame] | 506 | } else { |
| 507 | wasm::WasmImport &Import = *ImportedFunctions[Info.ElementIndex]; |
Hans Wennborg | 831b204 | 2019-02-12 12:27:08 +0000 | [diff] [blame] | 508 | if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0) |
| 509 | Info.Name = readString(Ctx); |
| 510 | else |
| 511 | Info.Name = Import.Field; |
Heejin Ahn | 0123db8 | 2018-12-08 06:16:13 +0000 | [diff] [blame] | 512 | Signature = &Signatures[Import.SigIndex]; |
Hans Wennborg | 831b204 | 2019-02-12 12:27:08 +0000 | [diff] [blame] | 513 | Info.ImportName = Import.Field; |
| 514 | Info.ImportModule = Import.Module; |
Sam Clegg | d578479 | 2018-02-23 05:08:34 +0000 | [diff] [blame] | 515 | } |
| 516 | break; |
| 517 | |
| 518 | case wasm::WASM_SYMBOL_TYPE_GLOBAL: |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 519 | Info.ElementIndex = readVaruint32(Ctx); |
Sam Clegg | d578479 | 2018-02-23 05:08:34 +0000 | [diff] [blame] | 520 | if (!isValidGlobalIndex(Info.ElementIndex) || |
| 521 | IsDefined != isDefinedGlobalIndex(Info.ElementIndex)) |
| 522 | return make_error<GenericBinaryError>("invalid global symbol index", |
| 523 | object_error::parse_failed); |
Heejin Ahn | 581d231 | 2018-09-05 01:27:38 +0000 | [diff] [blame] | 524 | if (!IsDefined && (Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) == |
| 525 | wasm::WASM_SYMBOL_BINDING_WEAK) |
Nicholas Wilson | 44818a3 | 2018-03-09 16:30:44 +0000 | [diff] [blame] | 526 | return make_error<GenericBinaryError>("undefined weak global symbol", |
| 527 | object_error::parse_failed); |
Sam Clegg | d578479 | 2018-02-23 05:08:34 +0000 | [diff] [blame] | 528 | if (IsDefined) { |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 529 | Info.Name = readString(Ctx); |
Sam Clegg | d578479 | 2018-02-23 05:08:34 +0000 | [diff] [blame] | 530 | unsigned GlobalIndex = Info.ElementIndex - NumImportedGlobals; |
Nicholas Wilson | 5476767 | 2018-03-05 12:16:32 +0000 | [diff] [blame] | 531 | wasm::WasmGlobal &Global = Globals[GlobalIndex]; |
| 532 | GlobalType = &Global.Type; |
Nicholas Wilson | bb03300 | 2018-04-20 17:07:24 +0000 | [diff] [blame] | 533 | if (Global.SymbolName.empty()) |
| 534 | Global.SymbolName = Info.Name; |
Sam Clegg | d578479 | 2018-02-23 05:08:34 +0000 | [diff] [blame] | 535 | } else { |
| 536 | wasm::WasmImport &Import = *ImportedGlobals[Info.ElementIndex]; |
Hans Wennborg | 831b204 | 2019-02-12 12:27:08 +0000 | [diff] [blame] | 537 | if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0) |
| 538 | Info.Name = readString(Ctx); |
| 539 | else |
| 540 | Info.Name = Import.Field; |
Sam Clegg | d578479 | 2018-02-23 05:08:34 +0000 | [diff] [blame] | 541 | GlobalType = &Import.Global; |
Hans Wennborg | 831b204 | 2019-02-12 12:27:08 +0000 | [diff] [blame] | 542 | Info.ImportName = Import.Field; |
| 543 | Info.ImportModule = Import.Module; |
Sam Clegg | d578479 | 2018-02-23 05:08:34 +0000 | [diff] [blame] | 544 | } |
| 545 | break; |
| 546 | |
| 547 | case wasm::WASM_SYMBOL_TYPE_DATA: |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 548 | Info.Name = readString(Ctx); |
Sam Clegg | d578479 | 2018-02-23 05:08:34 +0000 | [diff] [blame] | 549 | if (IsDefined) { |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 550 | uint32_t Index = readVaruint32(Ctx); |
Sam Clegg | d578479 | 2018-02-23 05:08:34 +0000 | [diff] [blame] | 551 | if (Index >= DataSegments.size()) |
| 552 | return make_error<GenericBinaryError>("invalid data symbol index", |
| 553 | object_error::parse_failed); |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 554 | uint32_t Offset = readVaruint32(Ctx); |
| 555 | uint32_t Size = readVaruint32(Ctx); |
Sam Clegg | d578479 | 2018-02-23 05:08:34 +0000 | [diff] [blame] | 556 | if (Offset + Size > DataSegments[Index].Data.Content.size()) |
Nicholas Wilson | c28e949 | 2018-02-28 14:03:18 +0000 | [diff] [blame] | 557 | return make_error<GenericBinaryError>("invalid data symbol offset", |
Sam Clegg | d578479 | 2018-02-23 05:08:34 +0000 | [diff] [blame] | 558 | object_error::parse_failed); |
| 559 | Info.DataRef = wasm::WasmDataReference{Index, Offset, Size}; |
| 560 | } |
| 561 | break; |
| 562 | |
Sam Clegg | db15975 | 2018-04-26 19:27:28 +0000 | [diff] [blame] | 563 | case wasm::WASM_SYMBOL_TYPE_SECTION: { |
Sam Clegg | bfeca0b | 2018-04-27 00:17:21 +0000 | [diff] [blame] | 564 | if ((Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) != |
| 565 | wasm::WASM_SYMBOL_BINDING_LOCAL) |
Sam Clegg | 4f72fc1 | 2018-04-27 00:17:24 +0000 | [diff] [blame] | 566 | return make_error<GenericBinaryError>( |
| 567 | "Section symbols must have local binding", |
| 568 | object_error::parse_failed); |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 569 | Info.ElementIndex = readVaruint32(Ctx); |
Sam Clegg | db15975 | 2018-04-26 19:27:28 +0000 | [diff] [blame] | 570 | // Use somewhat unique section name as symbol name. |
| 571 | StringRef SectionName = Sections[Info.ElementIndex].Name; |
| 572 | Info.Name = SectionName; |
| 573 | break; |
| 574 | } |
| 575 | |
Heejin Ahn | 8bcdd04 | 2018-11-14 02:46:21 +0000 | [diff] [blame] | 576 | case wasm::WASM_SYMBOL_TYPE_EVENT: { |
| 577 | Info.ElementIndex = readVaruint32(Ctx); |
| 578 | if (!isValidEventIndex(Info.ElementIndex) || |
| 579 | IsDefined != isDefinedEventIndex(Info.ElementIndex)) |
| 580 | return make_error<GenericBinaryError>("invalid event symbol index", |
| 581 | object_error::parse_failed); |
| 582 | if (!IsDefined && (Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) == |
| 583 | wasm::WASM_SYMBOL_BINDING_WEAK) |
| 584 | return make_error<GenericBinaryError>("undefined weak global symbol", |
| 585 | object_error::parse_failed); |
| 586 | if (IsDefined) { |
| 587 | Info.Name = readString(Ctx); |
| 588 | unsigned EventIndex = Info.ElementIndex - NumImportedEvents; |
| 589 | wasm::WasmEvent &Event = Events[EventIndex]; |
Heejin Ahn | 0123db8 | 2018-12-08 06:16:13 +0000 | [diff] [blame] | 590 | Signature = &Signatures[Event.Type.SigIndex]; |
Heejin Ahn | 8bcdd04 | 2018-11-14 02:46:21 +0000 | [diff] [blame] | 591 | EventType = &Event.Type; |
| 592 | if (Event.SymbolName.empty()) |
| 593 | Event.SymbolName = Info.Name; |
| 594 | |
| 595 | } else { |
| 596 | wasm::WasmImport &Import = *ImportedEvents[Info.ElementIndex]; |
Hans Wennborg | 831b204 | 2019-02-12 12:27:08 +0000 | [diff] [blame] | 597 | if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0) |
| 598 | Info.Name = readString(Ctx); |
| 599 | else |
| 600 | Info.Name = Import.Field; |
Heejin Ahn | 8bcdd04 | 2018-11-14 02:46:21 +0000 | [diff] [blame] | 601 | EventType = &Import.Event; |
Heejin Ahn | 0123db8 | 2018-12-08 06:16:13 +0000 | [diff] [blame] | 602 | Signature = &Signatures[EventType->SigIndex]; |
Hans Wennborg | 831b204 | 2019-02-12 12:27:08 +0000 | [diff] [blame] | 603 | Info.ImportName = Import.Field; |
| 604 | Info.ImportModule = Import.Module; |
Heejin Ahn | 8bcdd04 | 2018-11-14 02:46:21 +0000 | [diff] [blame] | 605 | } |
| 606 | break; |
| 607 | } |
| 608 | |
Sam Clegg | d578479 | 2018-02-23 05:08:34 +0000 | [diff] [blame] | 609 | default: |
| 610 | return make_error<GenericBinaryError>("Invalid symbol type", |
| 611 | object_error::parse_failed); |
| 612 | } |
| 613 | |
| 614 | if ((Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) != |
| 615 | wasm::WASM_SYMBOL_BINDING_LOCAL && |
| 616 | !SymbolNames.insert(Info.Name).second) |
| 617 | return make_error<GenericBinaryError>("Duplicate symbol name " + |
| 618 | Twine(Info.Name), |
| 619 | object_error::parse_failed); |
| 620 | LinkingData.SymbolTable.emplace_back(Info); |
Heejin Ahn | 0123db8 | 2018-12-08 06:16:13 +0000 | [diff] [blame] | 621 | Symbols.emplace_back(LinkingData.SymbolTable.back(), GlobalType, EventType, |
| 622 | Signature); |
Nicola Zaghen | 0818e78 | 2018-05-14 12:53:11 +0000 | [diff] [blame] | 623 | LLVM_DEBUG(dbgs() << "Adding symbol: " << Symbols.back() << "\n"); |
Sam Clegg | d578479 | 2018-02-23 05:08:34 +0000 | [diff] [blame] | 624 | } |
| 625 | |
| 626 | return Error::success(); |
| 627 | } |
| 628 | |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 629 | Error WasmObjectFile::parseLinkingSectionComdat(ReadContext &Ctx) { |
| 630 | uint32_t ComdatCount = readVaruint32(Ctx); |
Sam Clegg | e92250a | 2018-01-09 23:43:14 +0000 | [diff] [blame] | 631 | StringSet<> ComdatSet; |
Nicholas Wilson | dc84b5c | 2018-03-14 15:44:45 +0000 | [diff] [blame] | 632 | for (unsigned ComdatIndex = 0; ComdatIndex < ComdatCount; ++ComdatIndex) { |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 633 | StringRef Name = readString(Ctx); |
Sam Clegg | e92250a | 2018-01-09 23:43:14 +0000 | [diff] [blame] | 634 | if (Name.empty() || !ComdatSet.insert(Name).second) |
Heejin Ahn | 581d231 | 2018-09-05 01:27:38 +0000 | [diff] [blame] | 635 | return make_error<GenericBinaryError>("Bad/duplicate COMDAT name " + |
| 636 | Twine(Name), |
Sam Clegg | e92250a | 2018-01-09 23:43:14 +0000 | [diff] [blame] | 637 | object_error::parse_failed); |
Nicholas Wilson | dc84b5c | 2018-03-14 15:44:45 +0000 | [diff] [blame] | 638 | LinkingData.Comdats.emplace_back(Name); |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 639 | uint32_t Flags = readVaruint32(Ctx); |
Sam Clegg | e92250a | 2018-01-09 23:43:14 +0000 | [diff] [blame] | 640 | if (Flags != 0) |
| 641 | return make_error<GenericBinaryError>("Unsupported COMDAT flags", |
| 642 | object_error::parse_failed); |
| 643 | |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 644 | uint32_t EntryCount = readVaruint32(Ctx); |
Sam Clegg | e92250a | 2018-01-09 23:43:14 +0000 | [diff] [blame] | 645 | while (EntryCount--) { |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 646 | unsigned Kind = readVaruint32(Ctx); |
| 647 | unsigned Index = readVaruint32(Ctx); |
Sam Clegg | e92250a | 2018-01-09 23:43:14 +0000 | [diff] [blame] | 648 | switch (Kind) { |
| 649 | default: |
| 650 | return make_error<GenericBinaryError>("Invalid COMDAT entry type", |
| 651 | object_error::parse_failed); |
| 652 | case wasm::WASM_COMDAT_DATA: |
| 653 | if (Index >= DataSegments.size()) |
Heejin Ahn | 581d231 | 2018-09-05 01:27:38 +0000 | [diff] [blame] | 654 | return make_error<GenericBinaryError>( |
| 655 | "COMDAT data index out of range", object_error::parse_failed); |
Nicholas Wilson | dc84b5c | 2018-03-14 15:44:45 +0000 | [diff] [blame] | 656 | if (DataSegments[Index].Data.Comdat != UINT32_MAX) |
Sam Clegg | e92250a | 2018-01-09 23:43:14 +0000 | [diff] [blame] | 657 | return make_error<GenericBinaryError>("Data segment in two COMDATs", |
| 658 | object_error::parse_failed); |
Nicholas Wilson | dc84b5c | 2018-03-14 15:44:45 +0000 | [diff] [blame] | 659 | DataSegments[Index].Data.Comdat = ComdatIndex; |
Sam Clegg | e92250a | 2018-01-09 23:43:14 +0000 | [diff] [blame] | 660 | break; |
| 661 | case wasm::WASM_COMDAT_FUNCTION: |
Sam Clegg | 9a49b21c | 2018-01-24 01:27:17 +0000 | [diff] [blame] | 662 | if (!isDefinedFunctionIndex(Index)) |
Heejin Ahn | 581d231 | 2018-09-05 01:27:38 +0000 | [diff] [blame] | 663 | return make_error<GenericBinaryError>( |
| 664 | "COMDAT function index out of range", object_error::parse_failed); |
Nicholas Wilson | dc84b5c | 2018-03-14 15:44:45 +0000 | [diff] [blame] | 665 | if (getDefinedFunction(Index).Comdat != UINT32_MAX) |
Sam Clegg | e92250a | 2018-01-09 23:43:14 +0000 | [diff] [blame] | 666 | return make_error<GenericBinaryError>("Function in two COMDATs", |
| 667 | object_error::parse_failed); |
Nicholas Wilson | dc84b5c | 2018-03-14 15:44:45 +0000 | [diff] [blame] | 668 | getDefinedFunction(Index).Comdat = ComdatIndex; |
Sam Clegg | e92250a | 2018-01-09 23:43:14 +0000 | [diff] [blame] | 669 | break; |
| 670 | } |
| 671 | } |
| 672 | } |
| 673 | return Error::success(); |
| 674 | } |
| 675 | |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 676 | Error WasmObjectFile::parseRelocSection(StringRef Name, ReadContext &Ctx) { |
| 677 | uint32_t SectionIndex = readVaruint32(Ctx); |
Sam Clegg | 194a4e0 | 2018-04-24 18:11:36 +0000 | [diff] [blame] | 678 | if (SectionIndex >= Sections.size()) |
| 679 | return make_error<GenericBinaryError>("Invalid section index", |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 680 | object_error::parse_failed); |
Heejin Ahn | 581d231 | 2018-09-05 01:27:38 +0000 | [diff] [blame] | 681 | WasmSection &Section = Sections[SectionIndex]; |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 682 | uint32_t RelocCount = readVaruint32(Ctx); |
Sam Clegg | 194a4e0 | 2018-04-24 18:11:36 +0000 | [diff] [blame] | 683 | uint32_t EndOffset = Section.Content.size(); |
Sam Clegg | b4dc85b | 2018-08-22 17:27:31 +0000 | [diff] [blame] | 684 | uint32_t PreviousOffset = 0; |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 685 | while (RelocCount--) { |
Nicholas Wilson | e0316ce | 2018-03-05 13:32:38 +0000 | [diff] [blame] | 686 | wasm::WasmRelocation Reloc = {}; |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 687 | Reloc.Type = readVaruint32(Ctx); |
| 688 | Reloc.Offset = readVaruint32(Ctx); |
Sam Clegg | b4dc85b | 2018-08-22 17:27:31 +0000 | [diff] [blame] | 689 | if (Reloc.Offset < PreviousOffset) |
| 690 | return make_error<GenericBinaryError>("Relocations not in offset order", |
| 691 | object_error::parse_failed); |
| 692 | PreviousOffset = Reloc.Offset; |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 693 | Reloc.Index = readVaruint32(Ctx); |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 694 | switch (Reloc.Type) { |
| 695 | case wasm::R_WEBASSEMBLY_FUNCTION_INDEX_LEB: |
| 696 | case wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB: |
| 697 | case wasm::R_WEBASSEMBLY_TABLE_INDEX_I32: |
Nicholas Wilson | e0316ce | 2018-03-05 13:32:38 +0000 | [diff] [blame] | 698 | if (!isValidFunctionSymbol(Reloc.Index)) |
| 699 | return make_error<GenericBinaryError>("Bad relocation function index", |
| 700 | object_error::parse_failed); |
| 701 | break; |
Sam Clegg | d420e40 | 2017-04-26 00:02:31 +0000 | [diff] [blame] | 702 | case wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB: |
Nicholas Wilson | e0316ce | 2018-03-05 13:32:38 +0000 | [diff] [blame] | 703 | if (Reloc.Index >= Signatures.size()) |
| 704 | return make_error<GenericBinaryError>("Bad relocation type index", |
| 705 | object_error::parse_failed); |
| 706 | break; |
Sam Clegg | 46016f2 | 2017-06-16 23:59:10 +0000 | [diff] [blame] | 707 | case wasm::R_WEBASSEMBLY_GLOBAL_INDEX_LEB: |
Nicholas Wilson | e0316ce | 2018-03-05 13:32:38 +0000 | [diff] [blame] | 708 | if (!isValidGlobalSymbol(Reloc.Index)) |
| 709 | return make_error<GenericBinaryError>("Bad relocation global index", |
| 710 | object_error::parse_failed); |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 711 | break; |
Heejin Ahn | 8bcdd04 | 2018-11-14 02:46:21 +0000 | [diff] [blame] | 712 | case wasm::R_WEBASSEMBLY_EVENT_INDEX_LEB: |
| 713 | if (!isValidEventSymbol(Reloc.Index)) |
| 714 | return make_error<GenericBinaryError>("Bad relocation event index", |
| 715 | object_error::parse_failed); |
| 716 | break; |
Sam Clegg | 8b020d7 | 2017-09-01 17:32:01 +0000 | [diff] [blame] | 717 | case wasm::R_WEBASSEMBLY_MEMORY_ADDR_LEB: |
| 718 | case wasm::R_WEBASSEMBLY_MEMORY_ADDR_SLEB: |
| 719 | case wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32: |
Nicholas Wilson | e0316ce | 2018-03-05 13:32:38 +0000 | [diff] [blame] | 720 | if (!isValidDataSymbol(Reloc.Index)) |
| 721 | return make_error<GenericBinaryError>("Bad relocation data index", |
| 722 | object_error::parse_failed); |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 723 | Reloc.Addend = readVarint32(Ctx); |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 724 | break; |
Sam Clegg | db15975 | 2018-04-26 19:27:28 +0000 | [diff] [blame] | 725 | case wasm::R_WEBASSEMBLY_FUNCTION_OFFSET_I32: |
| 726 | if (!isValidFunctionSymbol(Reloc.Index)) |
| 727 | return make_error<GenericBinaryError>("Bad relocation function index", |
| 728 | object_error::parse_failed); |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 729 | Reloc.Addend = readVarint32(Ctx); |
Sam Clegg | db15975 | 2018-04-26 19:27:28 +0000 | [diff] [blame] | 730 | break; |
| 731 | case wasm::R_WEBASSEMBLY_SECTION_OFFSET_I32: |
| 732 | if (!isValidSectionSymbol(Reloc.Index)) |
| 733 | return make_error<GenericBinaryError>("Bad relocation section index", |
| 734 | object_error::parse_failed); |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 735 | Reloc.Addend = readVarint32(Ctx); |
Sam Clegg | db15975 | 2018-04-26 19:27:28 +0000 | [diff] [blame] | 736 | break; |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 737 | default: |
Sam Clegg | 46016f2 | 2017-06-16 23:59:10 +0000 | [diff] [blame] | 738 | return make_error<GenericBinaryError>("Bad relocation type: " + |
| 739 | Twine(Reloc.Type), |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 740 | object_error::parse_failed); |
| 741 | } |
Nicholas Wilson | e0316ce | 2018-03-05 13:32:38 +0000 | [diff] [blame] | 742 | |
| 743 | // Relocations must fit inside the section, and must appear in order. They |
| 744 | // also shouldn't overlap a function/element boundary, but we don't bother |
| 745 | // to check that. |
| 746 | uint64_t Size = 5; |
| 747 | if (Reloc.Type == wasm::R_WEBASSEMBLY_TABLE_INDEX_I32 || |
Sam Clegg | db15975 | 2018-04-26 19:27:28 +0000 | [diff] [blame] | 748 | Reloc.Type == wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32 || |
| 749 | Reloc.Type == wasm::R_WEBASSEMBLY_SECTION_OFFSET_I32 || |
| 750 | Reloc.Type == wasm::R_WEBASSEMBLY_FUNCTION_OFFSET_I32) |
Nicholas Wilson | e0316ce | 2018-03-05 13:32:38 +0000 | [diff] [blame] | 751 | Size = 4; |
Sam Clegg | 068c05a | 2018-03-06 07:13:10 +0000 | [diff] [blame] | 752 | if (Reloc.Offset + Size > EndOffset) |
Nicholas Wilson | e0316ce | 2018-03-05 13:32:38 +0000 | [diff] [blame] | 753 | return make_error<GenericBinaryError>("Bad relocation offset", |
| 754 | object_error::parse_failed); |
Nicholas Wilson | e0316ce | 2018-03-05 13:32:38 +0000 | [diff] [blame] | 755 | |
Sam Clegg | 194a4e0 | 2018-04-24 18:11:36 +0000 | [diff] [blame] | 756 | Section.Relocations.push_back(Reloc); |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 757 | } |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 758 | if (Ctx.Ptr != Ctx.End) |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 759 | return make_error<GenericBinaryError>("Reloc section ended prematurely", |
| 760 | object_error::parse_failed); |
| 761 | return Error::success(); |
| 762 | } |
| 763 | |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 764 | Error WasmObjectFile::parseCustomSection(WasmSection &Sec, ReadContext &Ctx) { |
Sam Clegg | 45c215a | 2018-11-14 18:36:24 +0000 | [diff] [blame] | 765 | if (Sec.Name == "dylink") { |
| 766 | if (Error Err = parseDylinkSection(Ctx)) |
| 767 | return Err; |
| 768 | } else if (Sec.Name == "name") { |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 769 | if (Error Err = parseNameSection(Ctx)) |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 770 | return Err; |
Sam Clegg | 1e975c1 | 2017-06-20 04:04:59 +0000 | [diff] [blame] | 771 | } else if (Sec.Name == "linking") { |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 772 | if (Error Err = parseLinkingSection(Ctx)) |
Sam Clegg | 1e975c1 | 2017-06-20 04:04:59 +0000 | [diff] [blame] | 773 | return Err; |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 774 | } else if (Sec.Name.startswith("reloc.")) { |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 775 | if (Error Err = parseRelocSection(Sec.Name, Ctx)) |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 776 | return Err; |
| 777 | } |
| 778 | return Error::success(); |
| 779 | } |
| 780 | |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 781 | Error WasmObjectFile::parseTypeSection(ReadContext &Ctx) { |
| 782 | uint32_t Count = readVaruint32(Ctx); |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 783 | Signatures.reserve(Count); |
| 784 | while (Count--) { |
| 785 | wasm::WasmSignature Sig; |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 786 | uint8_t Form = readUint8(Ctx); |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 787 | if (Form != wasm::WASM_TYPE_FUNC) { |
| 788 | return make_error<GenericBinaryError>("Invalid signature type", |
| 789 | object_error::parse_failed); |
| 790 | } |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 791 | uint32_t ParamCount = readVaruint32(Ctx); |
Derek Schuff | ab9755b | 2018-10-03 22:22:48 +0000 | [diff] [blame] | 792 | Sig.Params.reserve(ParamCount); |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 793 | while (ParamCount--) { |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 794 | uint32_t ParamType = readUint8(Ctx); |
Derek Schuff | ab9755b | 2018-10-03 22:22:48 +0000 | [diff] [blame] | 795 | Sig.Params.push_back(wasm::ValType(ParamType)); |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 796 | } |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 797 | uint32_t ReturnCount = readVaruint32(Ctx); |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 798 | if (ReturnCount) { |
| 799 | if (ReturnCount != 1) { |
| 800 | return make_error<GenericBinaryError>( |
| 801 | "Multiple return types not supported", object_error::parse_failed); |
| 802 | } |
Derek Schuff | ab9755b | 2018-10-03 22:22:48 +0000 | [diff] [blame] | 803 | Sig.Returns.push_back(wasm::ValType(readUint8(Ctx))); |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 804 | } |
Derek Schuff | ab9755b | 2018-10-03 22:22:48 +0000 | [diff] [blame] | 805 | Signatures.push_back(std::move(Sig)); |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 806 | } |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 807 | if (Ctx.Ptr != Ctx.End) |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 808 | return make_error<GenericBinaryError>("Type section ended prematurely", |
| 809 | object_error::parse_failed); |
| 810 | return Error::success(); |
| 811 | } |
| 812 | |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 813 | Error WasmObjectFile::parseImportSection(ReadContext &Ctx) { |
| 814 | uint32_t Count = readVaruint32(Ctx); |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 815 | Imports.reserve(Count); |
Sam Clegg | 740b80d | 2017-05-04 19:32:43 +0000 | [diff] [blame] | 816 | for (uint32_t i = 0; i < Count; i++) { |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 817 | wasm::WasmImport Im; |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 818 | Im.Module = readString(Ctx); |
| 819 | Im.Field = readString(Ctx); |
| 820 | Im.Kind = readUint8(Ctx); |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 821 | switch (Im.Kind) { |
| 822 | case wasm::WASM_EXTERNAL_FUNCTION: |
Sam Clegg | 209d3c2 | 2017-08-31 21:43:45 +0000 | [diff] [blame] | 823 | NumImportedFunctions++; |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 824 | Im.SigIndex = readVaruint32(Ctx); |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 825 | break; |
| 826 | case wasm::WASM_EXTERNAL_GLOBAL: |
Sam Clegg | 209d3c2 | 2017-08-31 21:43:45 +0000 | [diff] [blame] | 827 | NumImportedGlobals++; |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 828 | Im.Global.Type = readUint8(Ctx); |
| 829 | Im.Global.Mutable = readVaruint1(Ctx); |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 830 | break; |
Sam Clegg | 65e284e | 2017-05-09 23:48:41 +0000 | [diff] [blame] | 831 | case wasm::WASM_EXTERNAL_MEMORY: |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 832 | Im.Memory = readLimits(Ctx); |
Sam Clegg | 65e284e | 2017-05-09 23:48:41 +0000 | [diff] [blame] | 833 | break; |
| 834 | case wasm::WASM_EXTERNAL_TABLE: |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 835 | Im.Table = readTable(Ctx); |
Thomas Lively | 37a984b | 2019-01-08 06:25:55 +0000 | [diff] [blame] | 836 | if (Im.Table.ElemType != wasm::WASM_TYPE_FUNCREF) |
Sam Clegg | 65e284e | 2017-05-09 23:48:41 +0000 | [diff] [blame] | 837 | return make_error<GenericBinaryError>("Invalid table element type", |
| 838 | object_error::parse_failed); |
Sam Clegg | 65e284e | 2017-05-09 23:48:41 +0000 | [diff] [blame] | 839 | break; |
Heejin Ahn | 8bcdd04 | 2018-11-14 02:46:21 +0000 | [diff] [blame] | 840 | case wasm::WASM_EXTERNAL_EVENT: |
| 841 | NumImportedEvents++; |
| 842 | Im.Event.Attribute = readVarint32(Ctx); |
| 843 | Im.Event.SigIndex = readVarint32(Ctx); |
| 844 | break; |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 845 | default: |
Heejin Ahn | 581d231 | 2018-09-05 01:27:38 +0000 | [diff] [blame] | 846 | return make_error<GenericBinaryError>("Unexpected import kind", |
| 847 | object_error::parse_failed); |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 848 | } |
| 849 | Imports.push_back(Im); |
| 850 | } |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 851 | if (Ctx.Ptr != Ctx.End) |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 852 | return make_error<GenericBinaryError>("Import section ended prematurely", |
| 853 | object_error::parse_failed); |
| 854 | return Error::success(); |
| 855 | } |
| 856 | |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 857 | Error WasmObjectFile::parseFunctionSection(ReadContext &Ctx) { |
| 858 | uint32_t Count = readVaruint32(Ctx); |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 859 | FunctionTypes.reserve(Count); |
Nicholas Wilson | 22b62da | 2018-03-02 14:35:29 +0000 | [diff] [blame] | 860 | uint32_t NumTypes = Signatures.size(); |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 861 | while (Count--) { |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 862 | uint32_t Type = readVaruint32(Ctx); |
Nicholas Wilson | 22b62da | 2018-03-02 14:35:29 +0000 | [diff] [blame] | 863 | if (Type >= NumTypes) |
| 864 | return make_error<GenericBinaryError>("Invalid function type", |
| 865 | object_error::parse_failed); |
| 866 | FunctionTypes.push_back(Type); |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 867 | } |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 868 | if (Ctx.Ptr != Ctx.End) |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 869 | return make_error<GenericBinaryError>("Function section ended prematurely", |
| 870 | object_error::parse_failed); |
| 871 | return Error::success(); |
| 872 | } |
| 873 | |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 874 | Error WasmObjectFile::parseTableSection(ReadContext &Ctx) { |
| 875 | uint32_t Count = readVaruint32(Ctx); |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 876 | Tables.reserve(Count); |
| 877 | while (Count--) { |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 878 | Tables.push_back(readTable(Ctx)); |
Thomas Lively | 37a984b | 2019-01-08 06:25:55 +0000 | [diff] [blame] | 879 | if (Tables.back().ElemType != wasm::WASM_TYPE_FUNCREF) { |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 880 | return make_error<GenericBinaryError>("Invalid table element type", |
| 881 | object_error::parse_failed); |
| 882 | } |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 883 | } |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 884 | if (Ctx.Ptr != Ctx.End) |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 885 | return make_error<GenericBinaryError>("Table section ended prematurely", |
| 886 | object_error::parse_failed); |
| 887 | return Error::success(); |
| 888 | } |
| 889 | |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 890 | Error WasmObjectFile::parseMemorySection(ReadContext &Ctx) { |
| 891 | uint32_t Count = readVaruint32(Ctx); |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 892 | Memories.reserve(Count); |
| 893 | while (Count--) { |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 894 | Memories.push_back(readLimits(Ctx)); |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 895 | } |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 896 | if (Ctx.Ptr != Ctx.End) |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 897 | return make_error<GenericBinaryError>("Memory section ended prematurely", |
| 898 | object_error::parse_failed); |
| 899 | return Error::success(); |
| 900 | } |
| 901 | |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 902 | Error WasmObjectFile::parseGlobalSection(ReadContext &Ctx) { |
Sam Clegg | d578479 | 2018-02-23 05:08:34 +0000 | [diff] [blame] | 903 | GlobalSection = Sections.size(); |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 904 | uint32_t Count = readVaruint32(Ctx); |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 905 | Globals.reserve(Count); |
| 906 | while (Count--) { |
| 907 | wasm::WasmGlobal Global; |
Sam Clegg | 6b54fc3 | 2018-01-09 21:38:53 +0000 | [diff] [blame] | 908 | Global.Index = NumImportedGlobals + Globals.size(); |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 909 | Global.Type.Type = readUint8(Ctx); |
| 910 | Global.Type.Mutable = readVaruint1(Ctx); |
| 911 | if (Error Err = readInitExpr(Global.InitExpr, Ctx)) |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 912 | return Err; |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 913 | Globals.push_back(Global); |
| 914 | } |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 915 | if (Ctx.Ptr != Ctx.End) |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 916 | return make_error<GenericBinaryError>("Global section ended prematurely", |
| 917 | object_error::parse_failed); |
| 918 | return Error::success(); |
| 919 | } |
| 920 | |
Heejin Ahn | 8bcdd04 | 2018-11-14 02:46:21 +0000 | [diff] [blame] | 921 | Error WasmObjectFile::parseEventSection(ReadContext &Ctx) { |
| 922 | EventSection = Sections.size(); |
| 923 | uint32_t Count = readVarint32(Ctx); |
| 924 | Events.reserve(Count); |
| 925 | while (Count--) { |
| 926 | wasm::WasmEvent Event; |
| 927 | Event.Index = NumImportedEvents + Events.size(); |
| 928 | Event.Type.Attribute = readVaruint32(Ctx); |
| 929 | Event.Type.SigIndex = readVarint32(Ctx); |
| 930 | Events.push_back(Event); |
| 931 | } |
| 932 | |
| 933 | if (Ctx.Ptr != Ctx.End) |
| 934 | return make_error<GenericBinaryError>("Event section ended prematurely", |
| 935 | object_error::parse_failed); |
| 936 | return Error::success(); |
| 937 | } |
| 938 | |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 939 | Error WasmObjectFile::parseExportSection(ReadContext &Ctx) { |
| 940 | uint32_t Count = readVaruint32(Ctx); |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 941 | Exports.reserve(Count); |
Sam Clegg | 740b80d | 2017-05-04 19:32:43 +0000 | [diff] [blame] | 942 | for (uint32_t i = 0; i < Count; i++) { |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 943 | wasm::WasmExport Ex; |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 944 | Ex.Name = readString(Ctx); |
| 945 | Ex.Kind = readUint8(Ctx); |
| 946 | Ex.Index = readVaruint32(Ctx); |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 947 | switch (Ex.Kind) { |
| 948 | case wasm::WASM_EXTERNAL_FUNCTION: |
Sam Clegg | 9a49b21c | 2018-01-24 01:27:17 +0000 | [diff] [blame] | 949 | if (!isValidFunctionIndex(Ex.Index)) |
Sam Clegg | 209d3c2 | 2017-08-31 21:43:45 +0000 | [diff] [blame] | 950 | return make_error<GenericBinaryError>("Invalid function export", |
| 951 | object_error::parse_failed); |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 952 | break; |
Sam Clegg | d578479 | 2018-02-23 05:08:34 +0000 | [diff] [blame] | 953 | case wasm::WASM_EXTERNAL_GLOBAL: |
| 954 | if (!isValidGlobalIndex(Ex.Index)) |
Sam Clegg | 209d3c2 | 2017-08-31 21:43:45 +0000 | [diff] [blame] | 955 | return make_error<GenericBinaryError>("Invalid global export", |
| 956 | object_error::parse_failed); |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 957 | break; |
Heejin Ahn | 8bcdd04 | 2018-11-14 02:46:21 +0000 | [diff] [blame] | 958 | case wasm::WASM_EXTERNAL_EVENT: |
| 959 | if (!isValidEventIndex(Ex.Index)) |
| 960 | return make_error<GenericBinaryError>("Invalid event export", |
| 961 | object_error::parse_failed); |
| 962 | break; |
Sam Clegg | 65e284e | 2017-05-09 23:48:41 +0000 | [diff] [blame] | 963 | case wasm::WASM_EXTERNAL_MEMORY: |
| 964 | case wasm::WASM_EXTERNAL_TABLE: |
| 965 | break; |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 966 | default: |
Heejin Ahn | 581d231 | 2018-09-05 01:27:38 +0000 | [diff] [blame] | 967 | return make_error<GenericBinaryError>("Unexpected export kind", |
| 968 | object_error::parse_failed); |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 969 | } |
Sam Clegg | 1e975c1 | 2017-06-20 04:04:59 +0000 | [diff] [blame] | 970 | Exports.push_back(Ex); |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 971 | } |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 972 | if (Ctx.Ptr != Ctx.End) |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 973 | return make_error<GenericBinaryError>("Export section ended prematurely", |
| 974 | object_error::parse_failed); |
| 975 | return Error::success(); |
| 976 | } |
| 977 | |
Sam Clegg | e1acb56 | 2017-12-14 21:10:03 +0000 | [diff] [blame] | 978 | bool WasmObjectFile::isValidFunctionIndex(uint32_t Index) const { |
Sam Clegg | d578479 | 2018-02-23 05:08:34 +0000 | [diff] [blame] | 979 | return Index < NumImportedFunctions + FunctionTypes.size(); |
Sam Clegg | e1acb56 | 2017-12-14 21:10:03 +0000 | [diff] [blame] | 980 | } |
| 981 | |
Sam Clegg | 9a49b21c | 2018-01-24 01:27:17 +0000 | [diff] [blame] | 982 | bool WasmObjectFile::isDefinedFunctionIndex(uint32_t Index) const { |
| 983 | return Index >= NumImportedFunctions && isValidFunctionIndex(Index); |
| 984 | } |
| 985 | |
Sam Clegg | d578479 | 2018-02-23 05:08:34 +0000 | [diff] [blame] | 986 | bool WasmObjectFile::isValidGlobalIndex(uint32_t Index) const { |
| 987 | return Index < NumImportedGlobals + Globals.size(); |
| 988 | } |
| 989 | |
| 990 | bool WasmObjectFile::isDefinedGlobalIndex(uint32_t Index) const { |
| 991 | return Index >= NumImportedGlobals && isValidGlobalIndex(Index); |
| 992 | } |
| 993 | |
Heejin Ahn | 8bcdd04 | 2018-11-14 02:46:21 +0000 | [diff] [blame] | 994 | bool WasmObjectFile::isValidEventIndex(uint32_t Index) const { |
| 995 | return Index < NumImportedEvents + Events.size(); |
| 996 | } |
| 997 | |
| 998 | bool WasmObjectFile::isDefinedEventIndex(uint32_t Index) const { |
| 999 | return Index >= NumImportedEvents && isValidEventIndex(Index); |
| 1000 | } |
| 1001 | |
Nicholas Wilson | e0316ce | 2018-03-05 13:32:38 +0000 | [diff] [blame] | 1002 | bool WasmObjectFile::isValidFunctionSymbol(uint32_t Index) const { |
Sam Clegg | d578479 | 2018-02-23 05:08:34 +0000 | [diff] [blame] | 1003 | return Index < Symbols.size() && Symbols[Index].isTypeFunction(); |
| 1004 | } |
| 1005 | |
Nicholas Wilson | e0316ce | 2018-03-05 13:32:38 +0000 | [diff] [blame] | 1006 | bool WasmObjectFile::isValidGlobalSymbol(uint32_t Index) const { |
| 1007 | return Index < Symbols.size() && Symbols[Index].isTypeGlobal(); |
| 1008 | } |
| 1009 | |
Heejin Ahn | 8bcdd04 | 2018-11-14 02:46:21 +0000 | [diff] [blame] | 1010 | bool WasmObjectFile::isValidEventSymbol(uint32_t Index) const { |
| 1011 | return Index < Symbols.size() && Symbols[Index].isTypeEvent(); |
| 1012 | } |
| 1013 | |
Nicholas Wilson | e0316ce | 2018-03-05 13:32:38 +0000 | [diff] [blame] | 1014 | bool WasmObjectFile::isValidDataSymbol(uint32_t Index) const { |
| 1015 | return Index < Symbols.size() && Symbols[Index].isTypeData(); |
| 1016 | } |
| 1017 | |
Sam Clegg | db15975 | 2018-04-26 19:27:28 +0000 | [diff] [blame] | 1018 | bool WasmObjectFile::isValidSectionSymbol(uint32_t Index) const { |
| 1019 | return Index < Symbols.size() && Symbols[Index].isTypeSection(); |
| 1020 | } |
| 1021 | |
Sam Clegg | d578479 | 2018-02-23 05:08:34 +0000 | [diff] [blame] | 1022 | wasm::WasmFunction &WasmObjectFile::getDefinedFunction(uint32_t Index) { |
Sam Clegg | 9a49b21c | 2018-01-24 01:27:17 +0000 | [diff] [blame] | 1023 | assert(isDefinedFunctionIndex(Index)); |
| 1024 | return Functions[Index - NumImportedFunctions]; |
| 1025 | } |
| 1026 | |
Sam Clegg | d578479 | 2018-02-23 05:08:34 +0000 | [diff] [blame] | 1027 | wasm::WasmGlobal &WasmObjectFile::getDefinedGlobal(uint32_t Index) { |
| 1028 | assert(isDefinedGlobalIndex(Index)); |
| 1029 | return Globals[Index - NumImportedGlobals]; |
| 1030 | } |
| 1031 | |
Heejin Ahn | 8bcdd04 | 2018-11-14 02:46:21 +0000 | [diff] [blame] | 1032 | wasm::WasmEvent &WasmObjectFile::getDefinedEvent(uint32_t Index) { |
| 1033 | assert(isDefinedEventIndex(Index)); |
| 1034 | return Events[Index - NumImportedEvents]; |
| 1035 | } |
| 1036 | |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 1037 | Error WasmObjectFile::parseStartSection(ReadContext &Ctx) { |
| 1038 | StartFunction = readVaruint32(Ctx); |
Sam Clegg | e1acb56 | 2017-12-14 21:10:03 +0000 | [diff] [blame] | 1039 | if (!isValidFunctionIndex(StartFunction)) |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 1040 | return make_error<GenericBinaryError>("Invalid start function", |
| 1041 | object_error::parse_failed); |
| 1042 | return Error::success(); |
| 1043 | } |
| 1044 | |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 1045 | Error WasmObjectFile::parseCodeSection(ReadContext &Ctx) { |
Sam Clegg | b39f411 | 2018-02-09 20:21:50 +0000 | [diff] [blame] | 1046 | CodeSection = Sections.size(); |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 1047 | uint32_t FunctionCount = readVaruint32(Ctx); |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 1048 | if (FunctionCount != FunctionTypes.size()) { |
| 1049 | return make_error<GenericBinaryError>("Invalid function count", |
| 1050 | object_error::parse_failed); |
| 1051 | } |
| 1052 | |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 1053 | while (FunctionCount--) { |
| 1054 | wasm::WasmFunction Function; |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 1055 | const uint8_t *FunctionStart = Ctx.Ptr; |
| 1056 | uint32_t Size = readVaruint32(Ctx); |
| 1057 | const uint8_t *FunctionEnd = Ctx.Ptr + Size; |
Sam Clegg | 6e6de69 | 2017-12-17 17:50:07 +0000 | [diff] [blame] | 1058 | |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 1059 | Function.CodeOffset = Ctx.Ptr - FunctionStart; |
Sam Clegg | 6b54fc3 | 2018-01-09 21:38:53 +0000 | [diff] [blame] | 1060 | Function.Index = NumImportedFunctions + Functions.size(); |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 1061 | Function.CodeSectionOffset = FunctionStart - Ctx.Start; |
Sam Clegg | 6e6de69 | 2017-12-17 17:50:07 +0000 | [diff] [blame] | 1062 | Function.Size = FunctionEnd - FunctionStart; |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 1063 | |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 1064 | uint32_t NumLocalDecls = readVaruint32(Ctx); |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 1065 | Function.Locals.reserve(NumLocalDecls); |
| 1066 | while (NumLocalDecls--) { |
| 1067 | wasm::WasmLocalDecl Decl; |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 1068 | Decl.Count = readVaruint32(Ctx); |
| 1069 | Decl.Type = readUint8(Ctx); |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 1070 | Function.Locals.push_back(Decl); |
| 1071 | } |
| 1072 | |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 1073 | uint32_t BodySize = FunctionEnd - Ctx.Ptr; |
| 1074 | Function.Body = ArrayRef<uint8_t>(Ctx.Ptr, BodySize); |
Nicholas Wilson | dc84b5c | 2018-03-14 15:44:45 +0000 | [diff] [blame] | 1075 | // This will be set later when reading in the linking metadata section. |
| 1076 | Function.Comdat = UINT32_MAX; |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 1077 | Ctx.Ptr += BodySize; |
| 1078 | assert(Ctx.Ptr == FunctionEnd); |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 1079 | Functions.push_back(Function); |
| 1080 | } |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 1081 | if (Ctx.Ptr != Ctx.End) |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 1082 | return make_error<GenericBinaryError>("Code section ended prematurely", |
| 1083 | object_error::parse_failed); |
| 1084 | return Error::success(); |
| 1085 | } |
| 1086 | |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 1087 | Error WasmObjectFile::parseElemSection(ReadContext &Ctx) { |
| 1088 | uint32_t Count = readVaruint32(Ctx); |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 1089 | ElemSegments.reserve(Count); |
| 1090 | while (Count--) { |
| 1091 | wasm::WasmElemSegment Segment; |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 1092 | Segment.TableIndex = readVaruint32(Ctx); |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 1093 | if (Segment.TableIndex != 0) { |
| 1094 | return make_error<GenericBinaryError>("Invalid TableIndex", |
| 1095 | object_error::parse_failed); |
| 1096 | } |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 1097 | if (Error Err = readInitExpr(Segment.Offset, Ctx)) |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 1098 | return Err; |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 1099 | uint32_t NumElems = readVaruint32(Ctx); |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 1100 | while (NumElems--) { |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 1101 | Segment.Functions.push_back(readVaruint32(Ctx)); |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 1102 | } |
| 1103 | ElemSegments.push_back(Segment); |
| 1104 | } |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 1105 | if (Ctx.Ptr != Ctx.End) |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 1106 | return make_error<GenericBinaryError>("Elem section ended prematurely", |
| 1107 | object_error::parse_failed); |
| 1108 | return Error::success(); |
| 1109 | } |
| 1110 | |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 1111 | Error WasmObjectFile::parseDataSection(ReadContext &Ctx) { |
Sam Clegg | b39f411 | 2018-02-09 20:21:50 +0000 | [diff] [blame] | 1112 | DataSection = Sections.size(); |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 1113 | uint32_t Count = readVaruint32(Ctx); |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 1114 | DataSegments.reserve(Count); |
| 1115 | while (Count--) { |
Sam Clegg | c9c28d9 | 2017-07-12 00:24:54 +0000 | [diff] [blame] | 1116 | WasmSegment Segment; |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 1117 | Segment.Data.MemoryIndex = readVaruint32(Ctx); |
| 1118 | if (Error Err = readInitExpr(Segment.Data.Offset, Ctx)) |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 1119 | return Err; |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 1120 | uint32_t Size = readVaruint32(Ctx); |
Simon Pilgrim | be2419a | 2018-06-26 10:02:12 +0000 | [diff] [blame] | 1121 | if (Size > (size_t)(Ctx.End - Ctx.Ptr)) |
Sam Clegg | d0adb14 | 2018-05-18 21:08:26 +0000 | [diff] [blame] | 1122 | return make_error<GenericBinaryError>("Invalid segment size", |
| 1123 | object_error::parse_failed); |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 1124 | Segment.Data.Content = ArrayRef<uint8_t>(Ctx.Ptr, Size); |
Nicholas Wilson | dc84b5c | 2018-03-14 15:44:45 +0000 | [diff] [blame] | 1125 | // The rest of these Data fields are set later, when reading in the linking |
| 1126 | // metadata section. |
Sam Clegg | e286417 | 2017-09-29 16:50:08 +0000 | [diff] [blame] | 1127 | Segment.Data.Alignment = 0; |
| 1128 | Segment.Data.Flags = 0; |
Nicholas Wilson | dc84b5c | 2018-03-14 15:44:45 +0000 | [diff] [blame] | 1129 | Segment.Data.Comdat = UINT32_MAX; |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 1130 | Segment.SectionOffset = Ctx.Ptr - Ctx.Start; |
| 1131 | Ctx.Ptr += Size; |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 1132 | DataSegments.push_back(Segment); |
| 1133 | } |
Sam Clegg | 50617cf | 2018-05-29 19:58:59 +0000 | [diff] [blame] | 1134 | if (Ctx.Ptr != Ctx.End) |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 1135 | return make_error<GenericBinaryError>("Data section ended prematurely", |
| 1136 | object_error::parse_failed); |
Derek Schuff | 7a578c9 | 2016-11-30 16:49:11 +0000 | [diff] [blame] | 1137 | return Error::success(); |
| 1138 | } |
| 1139 | |
| 1140 | const uint8_t *WasmObjectFile::getPtr(size_t Offset) const { |
Sam Clegg | 4548453 | 2018-05-30 03:37:26 +0000 | [diff] [blame] | 1141 | return reinterpret_cast<const uint8_t *>(getData().data() + Offset); |
Derek Schuff | 7a578c9 | 2016-11-30 16:49:11 +0000 | [diff] [blame] | 1142 | } |
| 1143 | |
| 1144 | const wasm::WasmObjectHeader &WasmObjectFile::getHeader() const { |
| 1145 | return Header; |
| 1146 | } |
| 1147 | |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 1148 | void WasmObjectFile::moveSymbolNext(DataRefImpl &Symb) const { Symb.d.a++; } |
Derek Schuff | 7a578c9 | 2016-11-30 16:49:11 +0000 | [diff] [blame] | 1149 | |
| 1150 | uint32_t WasmObjectFile::getSymbolFlags(DataRefImpl Symb) const { |
Sam Clegg | 740b80d | 2017-05-04 19:32:43 +0000 | [diff] [blame] | 1151 | uint32_t Result = SymbolRef::SF_None; |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 1152 | const WasmSymbol &Sym = getWasmSymbol(Symb); |
Sam Clegg | 740b80d | 2017-05-04 19:32:43 +0000 | [diff] [blame] | 1153 | |
Nicola Zaghen | 0818e78 | 2018-05-14 12:53:11 +0000 | [diff] [blame] | 1154 | LLVM_DEBUG(dbgs() << "getSymbolFlags: ptr=" << &Sym << " " << Sym << "\n"); |
Sam Clegg | bfa1dc6 | 2018-01-31 19:50:14 +0000 | [diff] [blame] | 1155 | if (Sym.isBindingWeak()) |
Sam Clegg | 1e975c1 | 2017-06-20 04:04:59 +0000 | [diff] [blame] | 1156 | Result |= SymbolRef::SF_Weak; |
Sam Clegg | bfa1dc6 | 2018-01-31 19:50:14 +0000 | [diff] [blame] | 1157 | if (!Sym.isBindingLocal()) |
Sam Clegg | b1dd7d6 | 2017-09-20 21:17:04 +0000 | [diff] [blame] | 1158 | Result |= SymbolRef::SF_Global; |
Sam Clegg | 1f4bd62 | 2017-12-03 01:19:23 +0000 | [diff] [blame] | 1159 | if (Sym.isHidden()) |
| 1160 | Result |= SymbolRef::SF_Hidden; |
Sam Clegg | d578479 | 2018-02-23 05:08:34 +0000 | [diff] [blame] | 1161 | if (!Sym.isDefined()) |
Sam Clegg | 740b80d | 2017-05-04 19:32:43 +0000 | [diff] [blame] | 1162 | Result |= SymbolRef::SF_Undefined; |
Sam Clegg | d578479 | 2018-02-23 05:08:34 +0000 | [diff] [blame] | 1163 | if (Sym.isTypeFunction()) |
| 1164 | Result |= SymbolRef::SF_Executable; |
Sam Clegg | 740b80d | 2017-05-04 19:32:43 +0000 | [diff] [blame] | 1165 | return Result; |
Derek Schuff | 7a578c9 | 2016-11-30 16:49:11 +0000 | [diff] [blame] | 1166 | } |
| 1167 | |
| 1168 | basic_symbol_iterator WasmObjectFile::symbol_begin() const { |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 1169 | DataRefImpl Ref; |
| 1170 | Ref.d.a = 0; |
| 1171 | return BasicSymbolRef(Ref, this); |
Derek Schuff | 7a578c9 | 2016-11-30 16:49:11 +0000 | [diff] [blame] | 1172 | } |
| 1173 | |
| 1174 | basic_symbol_iterator WasmObjectFile::symbol_end() const { |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 1175 | DataRefImpl Ref; |
| 1176 | Ref.d.a = Symbols.size(); |
| 1177 | return BasicSymbolRef(Ref, this); |
| 1178 | } |
| 1179 | |
Sam Clegg | 65e284e | 2017-05-09 23:48:41 +0000 | [diff] [blame] | 1180 | const WasmSymbol &WasmObjectFile::getWasmSymbol(const DataRefImpl &Symb) const { |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 1181 | return Symbols[Symb.d.a]; |
Derek Schuff | 7a578c9 | 2016-11-30 16:49:11 +0000 | [diff] [blame] | 1182 | } |
| 1183 | |
Sam Clegg | 65e284e | 2017-05-09 23:48:41 +0000 | [diff] [blame] | 1184 | const WasmSymbol &WasmObjectFile::getWasmSymbol(const SymbolRef &Symb) const { |
| 1185 | return getWasmSymbol(Symb.getRawDataRefImpl()); |
| 1186 | } |
| 1187 | |
Derek Schuff | 7a578c9 | 2016-11-30 16:49:11 +0000 | [diff] [blame] | 1188 | Expected<StringRef> WasmObjectFile::getSymbolName(DataRefImpl Symb) const { |
Sam Clegg | d578479 | 2018-02-23 05:08:34 +0000 | [diff] [blame] | 1189 | return getWasmSymbol(Symb).Info.Name; |
Derek Schuff | 7a578c9 | 2016-11-30 16:49:11 +0000 | [diff] [blame] | 1190 | } |
| 1191 | |
| 1192 | Expected<uint64_t> WasmObjectFile::getSymbolAddress(DataRefImpl Symb) const { |
Sam Clegg | 740b80d | 2017-05-04 19:32:43 +0000 | [diff] [blame] | 1193 | return getSymbolValue(Symb); |
Derek Schuff | 7a578c9 | 2016-11-30 16:49:11 +0000 | [diff] [blame] | 1194 | } |
| 1195 | |
Heejin Ahn | 581d231 | 2018-09-05 01:27:38 +0000 | [diff] [blame] | 1196 | uint64_t WasmObjectFile::getWasmSymbolValue(const WasmSymbol &Sym) const { |
Sam Clegg | d578479 | 2018-02-23 05:08:34 +0000 | [diff] [blame] | 1197 | switch (Sym.Info.Kind) { |
| 1198 | case wasm::WASM_SYMBOL_TYPE_FUNCTION: |
| 1199 | case wasm::WASM_SYMBOL_TYPE_GLOBAL: |
Heejin Ahn | 8bcdd04 | 2018-11-14 02:46:21 +0000 | [diff] [blame] | 1200 | case wasm::WASM_SYMBOL_TYPE_EVENT: |
Sam Clegg | d578479 | 2018-02-23 05:08:34 +0000 | [diff] [blame] | 1201 | return Sym.Info.ElementIndex; |
| 1202 | case wasm::WASM_SYMBOL_TYPE_DATA: { |
| 1203 | // The value of a data symbol is the segment offset, plus the symbol |
| 1204 | // offset within the segment. |
| 1205 | uint32_t SegmentIndex = Sym.Info.DataRef.Segment; |
| 1206 | const wasm::WasmDataSegment &Segment = DataSegments[SegmentIndex].Data; |
| 1207 | assert(Segment.Offset.Opcode == wasm::WASM_OPCODE_I32_CONST); |
| 1208 | return Segment.Offset.Value.Int32 + Sym.Info.DataRef.Offset; |
Sam Clegg | 3ccf551 | 2017-08-31 23:22:44 +0000 | [diff] [blame] | 1209 | } |
Sam Clegg | db15975 | 2018-04-26 19:27:28 +0000 | [diff] [blame] | 1210 | case wasm::WASM_SYMBOL_TYPE_SECTION: |
| 1211 | return 0; |
Sam Clegg | 1e975c1 | 2017-06-20 04:04:59 +0000 | [diff] [blame] | 1212 | } |
Sam Clegg | ad60de3 | 2017-06-20 04:47:58 +0000 | [diff] [blame] | 1213 | llvm_unreachable("invalid symbol type"); |
Derek Schuff | 7a578c9 | 2016-11-30 16:49:11 +0000 | [diff] [blame] | 1214 | } |
| 1215 | |
Sam Clegg | b1dd7d6 | 2017-09-20 21:17:04 +0000 | [diff] [blame] | 1216 | uint64_t WasmObjectFile::getSymbolValueImpl(DataRefImpl Symb) const { |
| 1217 | return getWasmSymbolValue(getWasmSymbol(Symb)); |
| 1218 | } |
| 1219 | |
Derek Schuff | 7a578c9 | 2016-11-30 16:49:11 +0000 | [diff] [blame] | 1220 | uint32_t WasmObjectFile::getSymbolAlignment(DataRefImpl Symb) const { |
| 1221 | llvm_unreachable("not yet implemented"); |
| 1222 | return 0; |
| 1223 | } |
| 1224 | |
| 1225 | uint64_t WasmObjectFile::getCommonSymbolSizeImpl(DataRefImpl Symb) const { |
| 1226 | llvm_unreachable("not yet implemented"); |
| 1227 | return 0; |
| 1228 | } |
| 1229 | |
| 1230 | Expected<SymbolRef::Type> |
| 1231 | WasmObjectFile::getSymbolType(DataRefImpl Symb) const { |
Sam Clegg | 740b80d | 2017-05-04 19:32:43 +0000 | [diff] [blame] | 1232 | const WasmSymbol &Sym = getWasmSymbol(Symb); |
| 1233 | |
Sam Clegg | d578479 | 2018-02-23 05:08:34 +0000 | [diff] [blame] | 1234 | switch (Sym.Info.Kind) { |
| 1235 | case wasm::WASM_SYMBOL_TYPE_FUNCTION: |
Sam Clegg | 740b80d | 2017-05-04 19:32:43 +0000 | [diff] [blame] | 1236 | return SymbolRef::ST_Function; |
Sam Clegg | d578479 | 2018-02-23 05:08:34 +0000 | [diff] [blame] | 1237 | case wasm::WASM_SYMBOL_TYPE_GLOBAL: |
| 1238 | return SymbolRef::ST_Other; |
| 1239 | case wasm::WASM_SYMBOL_TYPE_DATA: |
Sam Clegg | 740b80d | 2017-05-04 19:32:43 +0000 | [diff] [blame] | 1240 | return SymbolRef::ST_Data; |
Sam Clegg | db15975 | 2018-04-26 19:27:28 +0000 | [diff] [blame] | 1241 | case wasm::WASM_SYMBOL_TYPE_SECTION: |
| 1242 | return SymbolRef::ST_Debug; |
Heejin Ahn | 8bcdd04 | 2018-11-14 02:46:21 +0000 | [diff] [blame] | 1243 | case wasm::WASM_SYMBOL_TYPE_EVENT: |
| 1244 | return SymbolRef::ST_Other; |
Sam Clegg | 740b80d | 2017-05-04 19:32:43 +0000 | [diff] [blame] | 1245 | } |
| 1246 | |
| 1247 | llvm_unreachable("Unknown WasmSymbol::SymbolType"); |
| 1248 | return SymbolRef::ST_Other; |
Derek Schuff | 7a578c9 | 2016-11-30 16:49:11 +0000 | [diff] [blame] | 1249 | } |
| 1250 | |
| 1251 | Expected<section_iterator> |
| 1252 | WasmObjectFile::getSymbolSection(DataRefImpl Symb) const { |
Heejin Ahn | 581d231 | 2018-09-05 01:27:38 +0000 | [diff] [blame] | 1253 | const WasmSymbol &Sym = getWasmSymbol(Symb); |
Sam Clegg | d578479 | 2018-02-23 05:08:34 +0000 | [diff] [blame] | 1254 | if (Sym.isUndefined()) |
Sam Clegg | b39f411 | 2018-02-09 20:21:50 +0000 | [diff] [blame] | 1255 | return section_end(); |
Sam Clegg | d578479 | 2018-02-23 05:08:34 +0000 | [diff] [blame] | 1256 | |
| 1257 | DataRefImpl Ref; |
| 1258 | switch (Sym.Info.Kind) { |
| 1259 | case wasm::WASM_SYMBOL_TYPE_FUNCTION: |
| 1260 | Ref.d.a = CodeSection; |
| 1261 | break; |
| 1262 | case wasm::WASM_SYMBOL_TYPE_GLOBAL: |
| 1263 | Ref.d.a = GlobalSection; |
| 1264 | break; |
| 1265 | case wasm::WASM_SYMBOL_TYPE_DATA: |
| 1266 | Ref.d.a = DataSection; |
| 1267 | break; |
Heejin Ahn | 8bcdd04 | 2018-11-14 02:46:21 +0000 | [diff] [blame] | 1268 | case wasm::WASM_SYMBOL_TYPE_SECTION: |
Sam Clegg | db15975 | 2018-04-26 19:27:28 +0000 | [diff] [blame] | 1269 | Ref.d.a = Sym.Info.ElementIndex; |
| 1270 | break; |
Heejin Ahn | 8bcdd04 | 2018-11-14 02:46:21 +0000 | [diff] [blame] | 1271 | case wasm::WASM_SYMBOL_TYPE_EVENT: |
| 1272 | Ref.d.a = EventSection; |
| 1273 | break; |
Sam Clegg | d578479 | 2018-02-23 05:08:34 +0000 | [diff] [blame] | 1274 | default: |
| 1275 | llvm_unreachable("Unknown WasmSymbol::SymbolType"); |
| 1276 | } |
Sam Clegg | 740b80d | 2017-05-04 19:32:43 +0000 | [diff] [blame] | 1277 | return section_iterator(SectionRef(Ref, this)); |
Derek Schuff | 7a578c9 | 2016-11-30 16:49:11 +0000 | [diff] [blame] | 1278 | } |
| 1279 | |
| 1280 | void WasmObjectFile::moveSectionNext(DataRefImpl &Sec) const { Sec.d.a++; } |
| 1281 | |
| 1282 | std::error_code WasmObjectFile::getSectionName(DataRefImpl Sec, |
| 1283 | StringRef &Res) const { |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 1284 | const WasmSection &S = Sections[Sec.d.a]; |
Derek Schuff | 7a578c9 | 2016-11-30 16:49:11 +0000 | [diff] [blame] | 1285 | #define ECase(X) \ |
| 1286 | case wasm::WASM_SEC_##X: \ |
| 1287 | Res = #X; \ |
| 1288 | break |
| 1289 | switch (S.Type) { |
| 1290 | ECase(TYPE); |
| 1291 | ECase(IMPORT); |
| 1292 | ECase(FUNCTION); |
| 1293 | ECase(TABLE); |
| 1294 | ECase(MEMORY); |
| 1295 | ECase(GLOBAL); |
Heejin Ahn | 8bcdd04 | 2018-11-14 02:46:21 +0000 | [diff] [blame] | 1296 | ECase(EVENT); |
Derek Schuff | 7a578c9 | 2016-11-30 16:49:11 +0000 | [diff] [blame] | 1297 | ECase(EXPORT); |
| 1298 | ECase(START); |
| 1299 | ECase(ELEM); |
| 1300 | ECase(CODE); |
| 1301 | ECase(DATA); |
Derek Schuff | c20099f | 2017-01-30 23:30:52 +0000 | [diff] [blame] | 1302 | case wasm::WASM_SEC_CUSTOM: |
Derek Schuff | 7a578c9 | 2016-11-30 16:49:11 +0000 | [diff] [blame] | 1303 | Res = S.Name; |
| 1304 | break; |
| 1305 | default: |
| 1306 | return object_error::invalid_section_index; |
| 1307 | } |
| 1308 | #undef ECase |
| 1309 | return std::error_code(); |
| 1310 | } |
| 1311 | |
| 1312 | uint64_t WasmObjectFile::getSectionAddress(DataRefImpl Sec) const { return 0; } |
| 1313 | |
George Rimar | b5ac700 | 2017-05-27 18:10:23 +0000 | [diff] [blame] | 1314 | uint64_t WasmObjectFile::getSectionIndex(DataRefImpl Sec) const { |
| 1315 | return Sec.d.a; |
| 1316 | } |
| 1317 | |
Derek Schuff | 7a578c9 | 2016-11-30 16:49:11 +0000 | [diff] [blame] | 1318 | uint64_t WasmObjectFile::getSectionSize(DataRefImpl Sec) const { |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 1319 | const WasmSection &S = Sections[Sec.d.a]; |
Derek Schuff | 7a578c9 | 2016-11-30 16:49:11 +0000 | [diff] [blame] | 1320 | return S.Content.size(); |
| 1321 | } |
| 1322 | |
| 1323 | std::error_code WasmObjectFile::getSectionContents(DataRefImpl Sec, |
| 1324 | StringRef &Res) const { |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 1325 | const WasmSection &S = Sections[Sec.d.a]; |
Derek Schuff | 7a578c9 | 2016-11-30 16:49:11 +0000 | [diff] [blame] | 1326 | // This will never fail since wasm sections can never be empty (user-sections |
| 1327 | // must have a name and non-user sections each have a defined structure). |
| 1328 | Res = StringRef(reinterpret_cast<const char *>(S.Content.data()), |
| 1329 | S.Content.size()); |
| 1330 | return std::error_code(); |
| 1331 | } |
| 1332 | |
| 1333 | uint64_t WasmObjectFile::getSectionAlignment(DataRefImpl Sec) const { |
| 1334 | return 1; |
| 1335 | } |
| 1336 | |
| 1337 | bool WasmObjectFile::isSectionCompressed(DataRefImpl Sec) const { |
| 1338 | return false; |
| 1339 | } |
| 1340 | |
| 1341 | bool WasmObjectFile::isSectionText(DataRefImpl Sec) const { |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 1342 | return getWasmSection(Sec).Type == wasm::WASM_SEC_CODE; |
Derek Schuff | 7a578c9 | 2016-11-30 16:49:11 +0000 | [diff] [blame] | 1343 | } |
| 1344 | |
| 1345 | bool WasmObjectFile::isSectionData(DataRefImpl Sec) const { |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 1346 | return getWasmSection(Sec).Type == wasm::WASM_SEC_DATA; |
Derek Schuff | 7a578c9 | 2016-11-30 16:49:11 +0000 | [diff] [blame] | 1347 | } |
| 1348 | |
| 1349 | bool WasmObjectFile::isSectionBSS(DataRefImpl Sec) const { return false; } |
| 1350 | |
| 1351 | bool WasmObjectFile::isSectionVirtual(DataRefImpl Sec) const { return false; } |
| 1352 | |
| 1353 | bool WasmObjectFile::isSectionBitcode(DataRefImpl Sec) const { return false; } |
| 1354 | |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 1355 | relocation_iterator WasmObjectFile::section_rel_begin(DataRefImpl Ref) const { |
| 1356 | DataRefImpl RelocRef; |
| 1357 | RelocRef.d.a = Ref.d.a; |
| 1358 | RelocRef.d.b = 0; |
| 1359 | return relocation_iterator(RelocationRef(RelocRef, this)); |
Derek Schuff | 7a578c9 | 2016-11-30 16:49:11 +0000 | [diff] [blame] | 1360 | } |
| 1361 | |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 1362 | relocation_iterator WasmObjectFile::section_rel_end(DataRefImpl Ref) const { |
| 1363 | const WasmSection &Sec = getWasmSection(Ref); |
| 1364 | DataRefImpl RelocRef; |
| 1365 | RelocRef.d.a = Ref.d.a; |
| 1366 | RelocRef.d.b = Sec.Relocations.size(); |
| 1367 | return relocation_iterator(RelocationRef(RelocRef, this)); |
Derek Schuff | 7a578c9 | 2016-11-30 16:49:11 +0000 | [diff] [blame] | 1368 | } |
| 1369 | |
Heejin Ahn | 581d231 | 2018-09-05 01:27:38 +0000 | [diff] [blame] | 1370 | void WasmObjectFile::moveRelocationNext(DataRefImpl &Rel) const { Rel.d.b++; } |
Derek Schuff | 7a578c9 | 2016-11-30 16:49:11 +0000 | [diff] [blame] | 1371 | |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 1372 | uint64_t WasmObjectFile::getRelocationOffset(DataRefImpl Ref) const { |
| 1373 | const wasm::WasmRelocation &Rel = getWasmRelocation(Ref); |
| 1374 | return Rel.Offset; |
Derek Schuff | 7a578c9 | 2016-11-30 16:49:11 +0000 | [diff] [blame] | 1375 | } |
| 1376 | |
Sam Clegg | 588fa1c | 2018-04-26 16:41:51 +0000 | [diff] [blame] | 1377 | symbol_iterator WasmObjectFile::getRelocationSymbol(DataRefImpl Ref) const { |
| 1378 | const wasm::WasmRelocation &Rel = getWasmRelocation(Ref); |
| 1379 | if (Rel.Type == wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB) |
| 1380 | return symbol_end(); |
| 1381 | DataRefImpl Sym; |
| 1382 | Sym.d.a = Rel.Index; |
| 1383 | Sym.d.b = 0; |
| 1384 | return symbol_iterator(SymbolRef(Sym, this)); |
Derek Schuff | 7a578c9 | 2016-11-30 16:49:11 +0000 | [diff] [blame] | 1385 | } |
| 1386 | |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 1387 | uint64_t WasmObjectFile::getRelocationType(DataRefImpl Ref) const { |
| 1388 | const wasm::WasmRelocation &Rel = getWasmRelocation(Ref); |
| 1389 | return Rel.Type; |
Derek Schuff | 7a578c9 | 2016-11-30 16:49:11 +0000 | [diff] [blame] | 1390 | } |
| 1391 | |
| 1392 | void WasmObjectFile::getRelocationTypeName( |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 1393 | DataRefImpl Ref, SmallVectorImpl<char> &Result) const { |
Heejin Ahn | 581d231 | 2018-09-05 01:27:38 +0000 | [diff] [blame] | 1394 | const wasm::WasmRelocation &Rel = getWasmRelocation(Ref); |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 1395 | StringRef Res = "Unknown"; |
| 1396 | |
Heejin Ahn | 581d231 | 2018-09-05 01:27:38 +0000 | [diff] [blame] | 1397 | #define WASM_RELOC(name, value) \ |
| 1398 | case wasm::name: \ |
| 1399 | Res = #name; \ |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 1400 | break; |
| 1401 | |
| 1402 | switch (Rel.Type) { |
Sam Clegg | ead036a | 2017-12-21 03:16:34 +0000 | [diff] [blame] | 1403 | #include "llvm/BinaryFormat/WasmRelocs.def" |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 1404 | } |
| 1405 | |
| 1406 | #undef WASM_RELOC |
| 1407 | |
| 1408 | Result.append(Res.begin(), Res.end()); |
Derek Schuff | 7a578c9 | 2016-11-30 16:49:11 +0000 | [diff] [blame] | 1409 | } |
| 1410 | |
| 1411 | section_iterator WasmObjectFile::section_begin() const { |
| 1412 | DataRefImpl Ref; |
| 1413 | Ref.d.a = 0; |
| 1414 | return section_iterator(SectionRef(Ref, this)); |
| 1415 | } |
| 1416 | |
| 1417 | section_iterator WasmObjectFile::section_end() const { |
| 1418 | DataRefImpl Ref; |
| 1419 | Ref.d.a = Sections.size(); |
| 1420 | return section_iterator(SectionRef(Ref, this)); |
| 1421 | } |
| 1422 | |
| 1423 | uint8_t WasmObjectFile::getBytesInAddress() const { return 4; } |
| 1424 | |
| 1425 | StringRef WasmObjectFile::getFileFormatName() const { return "WASM"; } |
| 1426 | |
Zachary Turner | ece9b23 | 2017-12-14 22:07:03 +0000 | [diff] [blame] | 1427 | Triple::ArchType WasmObjectFile::getArch() const { return Triple::wasm32; } |
Derek Schuff | 7a578c9 | 2016-11-30 16:49:11 +0000 | [diff] [blame] | 1428 | |
| 1429 | SubtargetFeatures WasmObjectFile::getFeatures() const { |
| 1430 | return SubtargetFeatures(); |
| 1431 | } |
| 1432 | |
Heejin Ahn | 581d231 | 2018-09-05 01:27:38 +0000 | [diff] [blame] | 1433 | bool WasmObjectFile::isRelocatableObject() const { return HasLinkingSection; } |
Derek Schuff | 7a578c9 | 2016-11-30 16:49:11 +0000 | [diff] [blame] | 1434 | |
Sam Clegg | 559201d | 2018-12-12 23:40:58 +0000 | [diff] [blame] | 1435 | bool WasmObjectFile::isSharedObject() const { return HasDylinkSection; } |
| 1436 | |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 1437 | const WasmSection &WasmObjectFile::getWasmSection(DataRefImpl Ref) const { |
Davide Italiano | 084c1ea | 2017-04-01 19:47:52 +0000 | [diff] [blame] | 1438 | assert(Ref.d.a < Sections.size()); |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 1439 | return Sections[Ref.d.a]; |
| 1440 | } |
| 1441 | |
| 1442 | const WasmSection & |
Derek Schuff | 7a578c9 | 2016-11-30 16:49:11 +0000 | [diff] [blame] | 1443 | WasmObjectFile::getWasmSection(const SectionRef &Section) const { |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 1444 | return getWasmSection(Section.getRawDataRefImpl()); |
| 1445 | } |
| 1446 | |
| 1447 | const wasm::WasmRelocation & |
| 1448 | WasmObjectFile::getWasmRelocation(const RelocationRef &Ref) const { |
| 1449 | return getWasmRelocation(Ref.getRawDataRefImpl()); |
| 1450 | } |
| 1451 | |
| 1452 | const wasm::WasmRelocation & |
| 1453 | WasmObjectFile::getWasmRelocation(DataRefImpl Ref) const { |
Davide Italiano | 084c1ea | 2017-04-01 19:47:52 +0000 | [diff] [blame] | 1454 | assert(Ref.d.a < Sections.size()); |
Heejin Ahn | 581d231 | 2018-09-05 01:27:38 +0000 | [diff] [blame] | 1455 | const WasmSection &Sec = Sections[Ref.d.a]; |
Davide Italiano | 084c1ea | 2017-04-01 19:47:52 +0000 | [diff] [blame] | 1456 | assert(Ref.d.b < Sec.Relocations.size()); |
Derek Schuff | 349a48f | 2017-03-30 19:44:09 +0000 | [diff] [blame] | 1457 | return Sec.Relocations[Ref.d.b]; |
Derek Schuff | 7a578c9 | 2016-11-30 16:49:11 +0000 | [diff] [blame] | 1458 | } |
Heejin Ahn | e2f3e50 | 2018-12-15 00:58:12 +0000 | [diff] [blame] | 1459 | |
| 1460 | int WasmSectionOrderChecker::getSectionOrder(unsigned ID, |
| 1461 | StringRef CustomSectionName) { |
| 1462 | switch (ID) { |
| 1463 | case wasm::WASM_SEC_CUSTOM: |
| 1464 | return StringSwitch<unsigned>(CustomSectionName) |
| 1465 | .Case("dylink", WASM_SEC_ORDER_DYLINK) |
| 1466 | .Case("linking", WASM_SEC_ORDER_LINKING) |
| 1467 | .StartsWith("reloc.", WASM_SEC_ORDER_RELOC) |
| 1468 | .Case("name", WASM_SEC_ORDER_NAME) |
| 1469 | .Case("producers", WASM_SEC_ORDER_PRODUCERS) |
| 1470 | .Default(-1); |
| 1471 | case wasm::WASM_SEC_TYPE: |
| 1472 | return WASM_SEC_ORDER_TYPE; |
| 1473 | case wasm::WASM_SEC_IMPORT: |
| 1474 | return WASM_SEC_ORDER_IMPORT; |
| 1475 | case wasm::WASM_SEC_FUNCTION: |
| 1476 | return WASM_SEC_ORDER_FUNCTION; |
| 1477 | case wasm::WASM_SEC_TABLE: |
| 1478 | return WASM_SEC_ORDER_TABLE; |
| 1479 | case wasm::WASM_SEC_MEMORY: |
| 1480 | return WASM_SEC_ORDER_MEMORY; |
| 1481 | case wasm::WASM_SEC_GLOBAL: |
| 1482 | return WASM_SEC_ORDER_GLOBAL; |
| 1483 | case wasm::WASM_SEC_EXPORT: |
| 1484 | return WASM_SEC_ORDER_EXPORT; |
| 1485 | case wasm::WASM_SEC_START: |
| 1486 | return WASM_SEC_ORDER_START; |
| 1487 | case wasm::WASM_SEC_ELEM: |
| 1488 | return WASM_SEC_ORDER_ELEM; |
| 1489 | case wasm::WASM_SEC_CODE: |
| 1490 | return WASM_SEC_ORDER_CODE; |
| 1491 | case wasm::WASM_SEC_DATA: |
| 1492 | return WASM_SEC_ORDER_DATA; |
| 1493 | case wasm::WASM_SEC_DATACOUNT: |
| 1494 | return WASM_SEC_ORDER_DATACOUNT; |
| 1495 | case wasm::WASM_SEC_EVENT: |
| 1496 | return WASM_SEC_ORDER_EVENT; |
| 1497 | default: |
| 1498 | llvm_unreachable("invalid section"); |
| 1499 | } |
| 1500 | } |
| 1501 | |
| 1502 | bool WasmSectionOrderChecker::isValidSectionOrder(unsigned ID, |
| 1503 | StringRef CustomSectionName) { |
| 1504 | int Order = getSectionOrder(ID, CustomSectionName); |
| 1505 | if (Order == -1) // Skip unknown sections |
| 1506 | return true; |
| 1507 | // There can be multiple "reloc." sections. Otherwise there shouldn't be any |
| 1508 | // duplicate section orders. |
| 1509 | bool IsValid = (LastOrder == Order && Order == WASM_SEC_ORDER_RELOC) || |
| 1510 | LastOrder < Order; |
| 1511 | LastOrder = Order; |
| 1512 | return IsValid; |
| 1513 | } |