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