1 /* Copyright 2018 Mozilla Foundation 2 * 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 use core::result; 17 use std::boxed::Box; 18 use std::fmt; 19 20 #[cfg(feature = "std")] 21 use std::error::Error; 22 23 #[derive(Debug, Copy, Clone)] 24 pub struct BinaryReaderError { 25 pub message: &'static str, 26 pub offset: usize, 27 } 28 29 pub type Result<T> = result::Result<T, BinaryReaderError>; 30 31 #[cfg(feature = "std")] 32 impl Error for BinaryReaderError {} 33 34 impl fmt::Display for BinaryReaderError { fmt(&self, f: &mut fmt::Formatter) -> fmt::Result35 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 36 write!(f, "{} (at offset {})", self.message, self.offset) 37 } 38 } 39 40 #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] 41 pub enum CustomSectionKind { 42 Unknown, 43 Name, 44 Producers, 45 SourceMappingURL, 46 Reloc, 47 Linking, 48 } 49 50 /// Section code as defined [here]. 51 /// 52 /// [here]: https://webassembly.github.io/spec/core/binary/modules.html#sections 53 #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] 54 pub enum SectionCode<'a> { 55 Custom { 56 name: &'a str, 57 kind: CustomSectionKind, 58 }, 59 Type, // Function signature declarations 60 Import, // Import declarations 61 Function, // Function declarations 62 Table, // Indirect function table and other tables 63 Memory, // Memory attributes 64 Global, // Global declarations 65 Export, // Exports 66 Start, // Start function declaration 67 Element, // Elements section 68 Code, // Function bodies (code) 69 Data, // Data segments 70 DataCount, // Count of passive data segments 71 } 72 73 /// Types as defined [here]. 74 /// 75 /// [here]: https://webassembly.github.io/spec/core/syntax/types.html#types 76 #[derive(Debug, Copy, Clone, PartialEq, Eq)] 77 pub enum Type { 78 I32, 79 I64, 80 F32, 81 F64, 82 V128, 83 AnyFunc, 84 AnyRef, 85 Func, 86 EmptyBlockType, 87 Null, 88 } 89 90 /// Either a value type or a function type. 91 #[derive(Debug, Copy, Clone, PartialEq, Eq)] 92 pub enum TypeOrFuncType { 93 /// A value type. 94 /// 95 /// When used as the type for a block, this type is the optional result 96 /// type: `[] -> [t?]`. 97 Type(Type), 98 99 /// A function type (referenced as an index into the types section). 100 FuncType(u32), 101 } 102 103 /// External types as defined [here]. 104 /// 105 /// [here]: https://webassembly.github.io/spec/core/syntax/types.html#external-types 106 #[derive(Debug, Copy, Clone)] 107 pub enum ExternalKind { 108 Function, 109 Table, 110 Memory, 111 Global, 112 } 113 114 #[derive(Debug, Clone)] 115 pub struct FuncType { 116 pub form: Type, 117 pub params: Box<[Type]>, 118 pub returns: Box<[Type]>, 119 } 120 121 #[derive(Debug, Copy, Clone)] 122 pub struct ResizableLimits { 123 pub initial: u32, 124 pub maximum: Option<u32>, 125 } 126 127 #[derive(Debug, Copy, Clone)] 128 pub struct TableType { 129 pub element_type: Type, 130 pub limits: ResizableLimits, 131 } 132 133 #[derive(Debug, Copy, Clone)] 134 pub struct MemoryType { 135 pub limits: ResizableLimits, 136 pub shared: bool, 137 } 138 139 #[derive(Debug, Copy, Clone)] 140 pub struct GlobalType { 141 pub content_type: Type, 142 pub mutable: bool, 143 } 144 145 #[derive(Debug, Copy, Clone)] 146 pub enum ImportSectionEntryType { 147 Function(u32), 148 Table(TableType), 149 Memory(MemoryType), 150 Global(GlobalType), 151 } 152 153 #[derive(Debug)] 154 pub struct MemoryImmediate { 155 pub flags: u32, 156 pub offset: u32, 157 } 158 159 #[derive(Debug, Copy, Clone)] 160 pub struct Naming<'a> { 161 pub index: u32, 162 pub name: &'a str, 163 } 164 165 #[derive(Debug, Copy, Clone)] 166 pub enum NameType { 167 Module, 168 Function, 169 Local, 170 } 171 172 #[derive(Debug, Copy, Clone)] 173 pub enum LinkingType { 174 StackPointer(u32), 175 } 176 177 #[derive(Debug, Copy, Clone)] 178 pub enum RelocType { 179 FunctionIndexLEB, 180 TableIndexSLEB, 181 TableIndexI32, 182 GlobalAddrLEB, 183 GlobalAddrSLEB, 184 GlobalAddrI32, 185 TypeIndexLEB, 186 GlobalIndexLEB, 187 } 188 189 /// A br_table entries representation. 190 #[derive(Debug)] 191 pub struct BrTable<'a> { 192 pub(crate) buffer: &'a [u8], 193 pub(crate) cnt: usize, 194 } 195 196 /// An IEEE binary32 immediate floating point value, represented as a u32 197 /// containing the bitpattern. 198 /// 199 /// All bit patterns are allowed. 200 #[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)] 201 pub struct Ieee32(pub(crate) u32); 202 203 impl Ieee32 { bits(self) -> u32204 pub fn bits(self) -> u32 { 205 self.0 206 } 207 } 208 209 /// An IEEE binary64 immediate floating point value, represented as a u64 210 /// containing the bitpattern. 211 /// 212 /// All bit patterns are allowed. 213 #[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)] 214 pub struct Ieee64(pub(crate) u64); 215 216 impl Ieee64 { bits(self) -> u64217 pub fn bits(self) -> u64 { 218 self.0 219 } 220 } 221 222 #[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)] 223 pub struct V128(pub(crate) [u8; 16]); 224 225 impl V128 { bytes(&self) -> &[u8; 16]226 pub fn bytes(&self) -> &[u8; 16] { 227 &self.0 228 } 229 } 230 231 pub type SIMDLaneIndex = u8; 232 233 /// Instructions as defined [here]. 234 /// 235 /// [here]: https://webassembly.github.io/spec/core/binary/instructions.html 236 #[derive(Debug)] 237 pub enum Operator<'a> { 238 Unreachable, 239 Nop, 240 Block { ty: TypeOrFuncType }, 241 Loop { ty: TypeOrFuncType }, 242 If { ty: TypeOrFuncType }, 243 Else, 244 End, 245 Br { relative_depth: u32 }, 246 BrIf { relative_depth: u32 }, 247 BrTable { table: BrTable<'a> }, 248 Return, 249 Call { function_index: u32 }, 250 CallIndirect { index: u32, table_index: u32 }, 251 Drop, 252 Select, 253 GetLocal { local_index: u32 }, 254 SetLocal { local_index: u32 }, 255 TeeLocal { local_index: u32 }, 256 GetGlobal { global_index: u32 }, 257 SetGlobal { global_index: u32 }, 258 I32Load { memarg: MemoryImmediate }, 259 I64Load { memarg: MemoryImmediate }, 260 F32Load { memarg: MemoryImmediate }, 261 F64Load { memarg: MemoryImmediate }, 262 I32Load8S { memarg: MemoryImmediate }, 263 I32Load8U { memarg: MemoryImmediate }, 264 I32Load16S { memarg: MemoryImmediate }, 265 I32Load16U { memarg: MemoryImmediate }, 266 I64Load8S { memarg: MemoryImmediate }, 267 I64Load8U { memarg: MemoryImmediate }, 268 I64Load16S { memarg: MemoryImmediate }, 269 I64Load16U { memarg: MemoryImmediate }, 270 I64Load32S { memarg: MemoryImmediate }, 271 I64Load32U { memarg: MemoryImmediate }, 272 I32Store { memarg: MemoryImmediate }, 273 I64Store { memarg: MemoryImmediate }, 274 F32Store { memarg: MemoryImmediate }, 275 F64Store { memarg: MemoryImmediate }, 276 I32Store8 { memarg: MemoryImmediate }, 277 I32Store16 { memarg: MemoryImmediate }, 278 I64Store8 { memarg: MemoryImmediate }, 279 I64Store16 { memarg: MemoryImmediate }, 280 I64Store32 { memarg: MemoryImmediate }, 281 MemorySize { reserved: u32 }, 282 MemoryGrow { reserved: u32 }, 283 I32Const { value: i32 }, 284 I64Const { value: i64 }, 285 F32Const { value: Ieee32 }, 286 F64Const { value: Ieee64 }, 287 RefNull, 288 RefIsNull, 289 I32Eqz, 290 I32Eq, 291 I32Ne, 292 I32LtS, 293 I32LtU, 294 I32GtS, 295 I32GtU, 296 I32LeS, 297 I32LeU, 298 I32GeS, 299 I32GeU, 300 I64Eqz, 301 I64Eq, 302 I64Ne, 303 I64LtS, 304 I64LtU, 305 I64GtS, 306 I64GtU, 307 I64LeS, 308 I64LeU, 309 I64GeS, 310 I64GeU, 311 F32Eq, 312 F32Ne, 313 F32Lt, 314 F32Gt, 315 F32Le, 316 F32Ge, 317 F64Eq, 318 F64Ne, 319 F64Lt, 320 F64Gt, 321 F64Le, 322 F64Ge, 323 I32Clz, 324 I32Ctz, 325 I32Popcnt, 326 I32Add, 327 I32Sub, 328 I32Mul, 329 I32DivS, 330 I32DivU, 331 I32RemS, 332 I32RemU, 333 I32And, 334 I32Or, 335 I32Xor, 336 I32Shl, 337 I32ShrS, 338 I32ShrU, 339 I32Rotl, 340 I32Rotr, 341 I64Clz, 342 I64Ctz, 343 I64Popcnt, 344 I64Add, 345 I64Sub, 346 I64Mul, 347 I64DivS, 348 I64DivU, 349 I64RemS, 350 I64RemU, 351 I64And, 352 I64Or, 353 I64Xor, 354 I64Shl, 355 I64ShrS, 356 I64ShrU, 357 I64Rotl, 358 I64Rotr, 359 F32Abs, 360 F32Neg, 361 F32Ceil, 362 F32Floor, 363 F32Trunc, 364 F32Nearest, 365 F32Sqrt, 366 F32Add, 367 F32Sub, 368 F32Mul, 369 F32Div, 370 F32Min, 371 F32Max, 372 F32Copysign, 373 F64Abs, 374 F64Neg, 375 F64Ceil, 376 F64Floor, 377 F64Trunc, 378 F64Nearest, 379 F64Sqrt, 380 F64Add, 381 F64Sub, 382 F64Mul, 383 F64Div, 384 F64Min, 385 F64Max, 386 F64Copysign, 387 I32WrapI64, 388 I32TruncSF32, 389 I32TruncUF32, 390 I32TruncSF64, 391 I32TruncUF64, 392 I64ExtendSI32, 393 I64ExtendUI32, 394 I64TruncSF32, 395 I64TruncUF32, 396 I64TruncSF64, 397 I64TruncUF64, 398 F32ConvertSI32, 399 F32ConvertUI32, 400 F32ConvertSI64, 401 F32ConvertUI64, 402 F32DemoteF64, 403 F64ConvertSI32, 404 F64ConvertUI32, 405 F64ConvertSI64, 406 F64ConvertUI64, 407 F64PromoteF32, 408 I32ReinterpretF32, 409 I64ReinterpretF64, 410 F32ReinterpretI32, 411 F64ReinterpretI64, 412 I32Extend8S, 413 I32Extend16S, 414 I64Extend8S, 415 I64Extend16S, 416 I64Extend32S, 417 418 // 0xFC operators 419 // Non-trapping Float-to-int Conversions 420 I32TruncSSatF32, 421 I32TruncUSatF32, 422 I32TruncSSatF64, 423 I32TruncUSatF64, 424 I64TruncSSatF32, 425 I64TruncUSatF32, 426 I64TruncSSatF64, 427 I64TruncUSatF64, 428 429 // 0xFC operators 430 // bulk memory https://github.com/WebAssembly/bulk-memory-operations/blob/master/proposals/bulk-memory-operations/Overview.md 431 MemoryInit { segment: u32 }, 432 DataDrop { segment: u32 }, 433 MemoryCopy, 434 MemoryFill, 435 TableInit { segment: u32 }, 436 ElemDrop { segment: u32 }, 437 TableCopy, 438 TableGet { table: u32 }, 439 TableSet { table: u32 }, 440 TableGrow { table: u32 }, 441 TableSize { table: u32 }, 442 443 // 0xFE operators 444 // https://github.com/WebAssembly/threads/blob/master/proposals/threads/Overview.md 445 Wake { memarg: MemoryImmediate }, 446 I32Wait { memarg: MemoryImmediate }, 447 I64Wait { memarg: MemoryImmediate }, 448 Fence { flags: u8 }, 449 I32AtomicLoad { memarg: MemoryImmediate }, 450 I64AtomicLoad { memarg: MemoryImmediate }, 451 I32AtomicLoad8U { memarg: MemoryImmediate }, 452 I32AtomicLoad16U { memarg: MemoryImmediate }, 453 I64AtomicLoad8U { memarg: MemoryImmediate }, 454 I64AtomicLoad16U { memarg: MemoryImmediate }, 455 I64AtomicLoad32U { memarg: MemoryImmediate }, 456 I32AtomicStore { memarg: MemoryImmediate }, 457 I64AtomicStore { memarg: MemoryImmediate }, 458 I32AtomicStore8 { memarg: MemoryImmediate }, 459 I32AtomicStore16 { memarg: MemoryImmediate }, 460 I64AtomicStore8 { memarg: MemoryImmediate }, 461 I64AtomicStore16 { memarg: MemoryImmediate }, 462 I64AtomicStore32 { memarg: MemoryImmediate }, 463 I32AtomicRmwAdd { memarg: MemoryImmediate }, 464 I64AtomicRmwAdd { memarg: MemoryImmediate }, 465 I32AtomicRmw8UAdd { memarg: MemoryImmediate }, 466 I32AtomicRmw16UAdd { memarg: MemoryImmediate }, 467 I64AtomicRmw8UAdd { memarg: MemoryImmediate }, 468 I64AtomicRmw16UAdd { memarg: MemoryImmediate }, 469 I64AtomicRmw32UAdd { memarg: MemoryImmediate }, 470 I32AtomicRmwSub { memarg: MemoryImmediate }, 471 I64AtomicRmwSub { memarg: MemoryImmediate }, 472 I32AtomicRmw8USub { memarg: MemoryImmediate }, 473 I32AtomicRmw16USub { memarg: MemoryImmediate }, 474 I64AtomicRmw8USub { memarg: MemoryImmediate }, 475 I64AtomicRmw16USub { memarg: MemoryImmediate }, 476 I64AtomicRmw32USub { memarg: MemoryImmediate }, 477 I32AtomicRmwAnd { memarg: MemoryImmediate }, 478 I64AtomicRmwAnd { memarg: MemoryImmediate }, 479 I32AtomicRmw8UAnd { memarg: MemoryImmediate }, 480 I32AtomicRmw16UAnd { memarg: MemoryImmediate }, 481 I64AtomicRmw8UAnd { memarg: MemoryImmediate }, 482 I64AtomicRmw16UAnd { memarg: MemoryImmediate }, 483 I64AtomicRmw32UAnd { memarg: MemoryImmediate }, 484 I32AtomicRmwOr { memarg: MemoryImmediate }, 485 I64AtomicRmwOr { memarg: MemoryImmediate }, 486 I32AtomicRmw8UOr { memarg: MemoryImmediate }, 487 I32AtomicRmw16UOr { memarg: MemoryImmediate }, 488 I64AtomicRmw8UOr { memarg: MemoryImmediate }, 489 I64AtomicRmw16UOr { memarg: MemoryImmediate }, 490 I64AtomicRmw32UOr { memarg: MemoryImmediate }, 491 I32AtomicRmwXor { memarg: MemoryImmediate }, 492 I64AtomicRmwXor { memarg: MemoryImmediate }, 493 I32AtomicRmw8UXor { memarg: MemoryImmediate }, 494 I32AtomicRmw16UXor { memarg: MemoryImmediate }, 495 I64AtomicRmw8UXor { memarg: MemoryImmediate }, 496 I64AtomicRmw16UXor { memarg: MemoryImmediate }, 497 I64AtomicRmw32UXor { memarg: MemoryImmediate }, 498 I32AtomicRmwXchg { memarg: MemoryImmediate }, 499 I64AtomicRmwXchg { memarg: MemoryImmediate }, 500 I32AtomicRmw8UXchg { memarg: MemoryImmediate }, 501 I32AtomicRmw16UXchg { memarg: MemoryImmediate }, 502 I64AtomicRmw8UXchg { memarg: MemoryImmediate }, 503 I64AtomicRmw16UXchg { memarg: MemoryImmediate }, 504 I64AtomicRmw32UXchg { memarg: MemoryImmediate }, 505 I32AtomicRmwCmpxchg { memarg: MemoryImmediate }, 506 I64AtomicRmwCmpxchg { memarg: MemoryImmediate }, 507 I32AtomicRmw8UCmpxchg { memarg: MemoryImmediate }, 508 I32AtomicRmw16UCmpxchg { memarg: MemoryImmediate }, 509 I64AtomicRmw8UCmpxchg { memarg: MemoryImmediate }, 510 I64AtomicRmw16UCmpxchg { memarg: MemoryImmediate }, 511 I64AtomicRmw32UCmpxchg { memarg: MemoryImmediate }, 512 513 // 0xFD operators 514 // SIMD https://github.com/WebAssembly/simd/blob/master/proposals/simd/BinarySIMD.md 515 V128Load { memarg: MemoryImmediate }, 516 V128Store { memarg: MemoryImmediate }, 517 V128Const { value: V128 }, 518 I8x16Splat, 519 I8x16ExtractLaneS { lane: SIMDLaneIndex }, 520 I8x16ExtractLaneU { lane: SIMDLaneIndex }, 521 I8x16ReplaceLane { lane: SIMDLaneIndex }, 522 I16x8Splat, 523 I16x8ExtractLaneS { lane: SIMDLaneIndex }, 524 I16x8ExtractLaneU { lane: SIMDLaneIndex }, 525 I16x8ReplaceLane { lane: SIMDLaneIndex }, 526 I32x4Splat, 527 I32x4ExtractLane { lane: SIMDLaneIndex }, 528 I32x4ReplaceLane { lane: SIMDLaneIndex }, 529 I64x2Splat, 530 I64x2ExtractLane { lane: SIMDLaneIndex }, 531 I64x2ReplaceLane { lane: SIMDLaneIndex }, 532 F32x4Splat, 533 F32x4ExtractLane { lane: SIMDLaneIndex }, 534 F32x4ReplaceLane { lane: SIMDLaneIndex }, 535 F64x2Splat, 536 F64x2ExtractLane { lane: SIMDLaneIndex }, 537 F64x2ReplaceLane { lane: SIMDLaneIndex }, 538 I8x16Eq, 539 I8x16Ne, 540 I8x16LtS, 541 I8x16LtU, 542 I8x16GtS, 543 I8x16GtU, 544 I8x16LeS, 545 I8x16LeU, 546 I8x16GeS, 547 I8x16GeU, 548 I16x8Eq, 549 I16x8Ne, 550 I16x8LtS, 551 I16x8LtU, 552 I16x8GtS, 553 I16x8GtU, 554 I16x8LeS, 555 I16x8LeU, 556 I16x8GeS, 557 I16x8GeU, 558 I32x4Eq, 559 I32x4Ne, 560 I32x4LtS, 561 I32x4LtU, 562 I32x4GtS, 563 I32x4GtU, 564 I32x4LeS, 565 I32x4LeU, 566 I32x4GeS, 567 I32x4GeU, 568 F32x4Eq, 569 F32x4Ne, 570 F32x4Lt, 571 F32x4Gt, 572 F32x4Le, 573 F32x4Ge, 574 F64x2Eq, 575 F64x2Ne, 576 F64x2Lt, 577 F64x2Gt, 578 F64x2Le, 579 F64x2Ge, 580 V128Not, 581 V128And, 582 V128Or, 583 V128Xor, 584 V128Bitselect, 585 I8x16Neg, 586 I8x16AnyTrue, 587 I8x16AllTrue, 588 I8x16Shl, 589 I8x16ShrS, 590 I8x16ShrU, 591 I8x16Add, 592 I8x16AddSaturateS, 593 I8x16AddSaturateU, 594 I8x16Sub, 595 I8x16SubSaturateS, 596 I8x16SubSaturateU, 597 I8x16Mul, 598 I16x8Neg, 599 I16x8AnyTrue, 600 I16x8AllTrue, 601 I16x8Shl, 602 I16x8ShrS, 603 I16x8ShrU, 604 I16x8Add, 605 I16x8AddSaturateS, 606 I16x8AddSaturateU, 607 I16x8Sub, 608 I16x8SubSaturateS, 609 I16x8SubSaturateU, 610 I16x8Mul, 611 I32x4Neg, 612 I32x4AnyTrue, 613 I32x4AllTrue, 614 I32x4Shl, 615 I32x4ShrS, 616 I32x4ShrU, 617 I32x4Add, 618 I32x4Sub, 619 I32x4Mul, 620 I64x2Neg, 621 I64x2AnyTrue, 622 I64x2AllTrue, 623 I64x2Shl, 624 I64x2ShrS, 625 I64x2ShrU, 626 I64x2Add, 627 I64x2Sub, 628 F32x4Abs, 629 F32x4Neg, 630 F32x4Sqrt, 631 F32x4Add, 632 F32x4Sub, 633 F32x4Mul, 634 F32x4Div, 635 F32x4Min, 636 F32x4Max, 637 F64x2Abs, 638 F64x2Neg, 639 F64x2Sqrt, 640 F64x2Add, 641 F64x2Sub, 642 F64x2Mul, 643 F64x2Div, 644 F64x2Min, 645 F64x2Max, 646 I32x4TruncSF32x4Sat, 647 I32x4TruncUF32x4Sat, 648 I64x2TruncSF64x2Sat, 649 I64x2TruncUF64x2Sat, 650 F32x4ConvertSI32x4, 651 F32x4ConvertUI32x4, 652 F64x2ConvertSI64x2, 653 F64x2ConvertUI64x2, 654 V8x16Swizzle, 655 V8x16Shuffle { lanes: [SIMDLaneIndex; 16] }, 656 I8x16LoadSplat { memarg: MemoryImmediate }, 657 I16x8LoadSplat { memarg: MemoryImmediate }, 658 I32x4LoadSplat { memarg: MemoryImmediate }, 659 I64x2LoadSplat { memarg: MemoryImmediate }, 660 } 661