wasm_parser/
lib.rs

1use core_wasm_ast as ast;
2use log::{debug, warn};
3use nom::bytes::complete::take;
4use std::collections::HashMap;
5use std::sync::Arc;
6use std::sync::Mutex;
7
8mod coredump;
9#[cfg(test)]
10mod test;
11
12type BoxError = Box<dyn std::error::Error>;
13
14#[derive(Debug)]
15pub(crate) struct ParserError(String);
16pub const CONTINUATION_BIT: u8 = 1 << 7;
17pub const SIGN_BIT: u8 = 1 << 6;
18
19#[inline]
20pub fn low_bits_of_byte(byte: u8) -> u8 {
21    byte & !CONTINUATION_BIT
22}
23
24impl<I> nom::error::ParseError<I> for ParserError {
25    fn from_error_kind(_input: I, kind: nom::error::ErrorKind) -> Self {
26        ParserError(format!("error {:?}", kind))
27    }
28    fn append(_input: I, _kind: nom::error::ErrorKind, _other: Self) -> Self {
29        todo!()
30    }
31    fn from_char(_input: I, _: char) -> Self {
32        todo!()
33    }
34    fn or(self, _other: Self) -> Self {
35        todo!()
36    }
37}
38
39pub(crate) type IResult<I, O, E = ParserError> = Result<(I, O), nom::Err<E>>;
40
41#[derive(Debug, Clone)]
42pub(crate) struct InputContext<'a> {
43    input: &'a [u8],
44    offset: usize,
45}
46
47impl<'a> InputContext<'a> {
48    fn read_u32(self) -> IResult<InputContext<'a>, u32> {
49        let (input, bytes) = self.read_bytes(4usize)?;
50        let value = u32::from_le_bytes(bytes.try_into().unwrap());
51        Ok((input, value))
52    }
53
54    fn read_i32(self) -> IResult<InputContext<'a>, i32> {
55        let (input, bytes) = self.read_bytes(4usize)?;
56        let value = i32::from_le_bytes(bytes.try_into().unwrap());
57        Ok((input, value))
58    }
59
60    fn read_i64(self) -> IResult<InputContext<'a>, i64> {
61        let (input, bytes) = self.read_bytes(8usize)?;
62        let value = i64::from_le_bytes(bytes.try_into().unwrap());
63        Ok((input, value))
64    }
65
66    fn read_u8(self) -> IResult<InputContext<'a>, u8> {
67        let (input, bytes) = self.read_bytes(1usize)?;
68        let value = u8::from_le_bytes(bytes.try_into().unwrap());
69        Ok((input, value))
70    }
71
72    fn read_leb128(self) -> IResult<InputContext<'a>, u32> {
73        let mut result = 0;
74        let mut shift = 0;
75
76        let mut ctx = self;
77        loop {
78            let ret = ctx.read_u8()?;
79            ctx = ret.0;
80            let mut buf = ret.1;
81
82            if shift == 63 && buf != 0x00 && buf != 0x01 {
83                while buf & CONTINUATION_BIT != 0 {
84                    let ret = ctx.read_u8()?;
85                    ctx = ret.0;
86                    buf = ret.1;
87                }
88                panic!("overflow");
89            }
90
91            let low_bits = low_bits_of_byte(buf) as u64;
92            result |= low_bits << shift;
93
94            if buf & CONTINUATION_BIT == 0 {
95                return Ok((ctx, result as u32));
96            }
97
98            shift += 7;
99        }
100    }
101
102    fn read_f32(self) -> IResult<InputContext<'a>, f32> {
103        let (ctx, bytes) = self.read_bytes(4)?;
104        let v = f32::from_le_bytes(bytes[0..4].try_into().unwrap());
105        Ok((ctx, v))
106    }
107
108    fn read_f64(self) -> IResult<InputContext<'a>, f64> {
109        let (ctx, bytes) = self.read_bytes(8)?;
110        let v = f64::from_le_bytes(bytes[0..8].try_into().unwrap());
111        Ok((ctx, v))
112    }
113
114    fn read_leb128_signed(self) -> IResult<InputContext<'a>, i64> {
115        let mut result = 0;
116        let mut shift = 0;
117        let size = 64;
118        let mut byte;
119
120        let mut ctx = self;
121        loop {
122            let ret = ctx.read_u8()?;
123            ctx = ret.0;
124            let mut buf = ret.1;
125
126            byte = buf;
127            if shift == 63 && byte != 0x00 && byte != 0x7f {
128                while buf & CONTINUATION_BIT != 0 {
129                    let ret = ctx.read_u8()?;
130                    ctx = ret.0;
131                    buf = ret.1;
132                }
133                panic!("overflow");
134            }
135
136            let low_bits = low_bits_of_byte(byte) as i64;
137            result |= low_bits << shift;
138            shift += 7;
139
140            if byte & CONTINUATION_BIT == 0 {
141                break;
142            }
143        }
144
145        if shift < size && (SIGN_BIT & byte) == SIGN_BIT {
146            // Sign extend the result.
147            result |= !0 << shift;
148        }
149
150        Ok((ctx, result as i64))
151    }
152
153    fn read_bytes(self, n: usize) -> IResult<InputContext<'a>, &'a [u8]> {
154        let (input, bytes) = take(n)(self.input)?;
155
156        Ok((
157            Self {
158                input,
159                offset: self.offset + n,
160            },
161            bytes,
162        ))
163    }
164
165    fn peak_u8(self) -> IResult<InputContext<'a>, u8> {
166        let (_input, byte) = take(1usize)(self.input)?;
167        Ok((self, byte[0]))
168    }
169}
170
171pub fn parse<'a>(input: &'a [u8]) -> Result<ast::Module, BoxError> {
172    let input = InputContext { input, offset: 0 };
173    match decode_module(input) {
174        Ok((_, module)) => Ok(module),
175        Err(err) => Err(format!("failed to decode: {}", err).into()),
176    }
177}
178
179pub fn parse_custom_section_name<'a>(input: &'a [u8]) -> Result<ast::DebugNames, BoxError> {
180    let input = InputContext { input, offset: 0 };
181    match decode_section_custom_name(input) {
182        Ok((_, names)) => Ok(names),
183        Err(err) => Err(format!("failed to decode name section: {}", err).into()),
184    }
185}
186
187pub fn parse_custom_section_build_id<'a>(input: &'a [u8]) -> Result<Vec<u8>, BoxError> {
188    let input = InputContext { input, offset: 0 };
189    match decode_section_custom_build_id(input) {
190        Ok((_, id)) => Ok(id),
191        Err(err) => Err(format!("failed to decode name section: {}", err).into()),
192    }
193}
194
195fn decode_module<'a>(ctx: InputContext<'a>) -> IResult<InputContext<'a>, ast::Module> {
196    let (ctx, magic) = ctx.read_bytes(4)?;
197    if magic != b"\0asm" {
198        panic!("unsupported header: {:?}", magic)
199    }
200    assert_eq!(ctx.offset, 4);
201    let (ctx, version) = ctx.read_u32()?;
202    if version != 1 {
203        panic!("unsupported version: {:?}", version)
204    }
205    assert_eq!(ctx.offset, 8);
206
207    let mut ctx = ctx;
208
209    let mut sections = vec![];
210    loop {
211        let start_offset = ctx.offset;
212        let res = decode_section(ctx)?;
213        ctx = res.0;
214        let end_offset = ctx.offset;
215
216        let value = ast::Value {
217            start_offset,
218            value: res.1,
219            end_offset,
220        };
221
222        sections.push(value);
223
224        if ctx.input.is_empty() {
225            break;
226        }
227    }
228
229    let module = ast::Module {
230        sections: Arc::new(Mutex::new(sections)),
231    };
232    Ok((ctx, module))
233}
234
235fn decode_section_memory<'a>(ctx: InputContext<'a>) -> IResult<InputContext<'a>, Vec<ast::Memory>> {
236    decode_vec(ctx, decode_memory)
237}
238
239fn decode_section_global<'a>(ctx: InputContext<'a>) -> IResult<InputContext<'a>, Vec<ast::Global>> {
240    decode_vec(ctx, decode_global)
241}
242
243fn decode_section_export<'a>(ctx: InputContext<'a>) -> IResult<InputContext<'a>, Vec<ast::Export>> {
244    decode_vec(ctx, decode_export)
245}
246
247fn decode_section_element<'a>(
248    ctx: InputContext<'a>,
249) -> IResult<InputContext<'a>, Vec<ast::Element>> {
250    decode_vec(ctx, decode_element)
251}
252
253fn decode_section_data<'a>(
254    ctx: InputContext<'a>,
255) -> IResult<InputContext<'a>, Vec<ast::DataSegment>> {
256    decode_vec(ctx, decode_data)
257}
258
259fn decode_section_type<'a>(ctx: InputContext<'a>) -> IResult<InputContext<'a>, Vec<ast::Type>> {
260    decode_vec(ctx, decode_type)
261}
262
263fn decode_section_custom<'a>(
264    ctx: InputContext<'a>,
265) -> IResult<InputContext<'a>, ast::CustomSection> {
266    let (ctx, name) = decode_name(ctx)?;
267    log::debug!("parse custom section: {:?}", name);
268    Ok(match name.as_str() {
269        "name" => {
270            let (ctx, content) = decode_section_custom_name(ctx)?;
271            (ctx, ast::CustomSection::Name(content))
272        }
273        "build_id" => {
274            let (ctx, content) = decode_section_custom_build_id(ctx)?;
275            (ctx, ast::CustomSection::BuildId(content))
276        }
277        "core" => {
278            let (ctx, content) = coredump::decode_process_info(ctx)?;
279            (ctx, ast::CustomSection::CoredumpCore(content))
280        }
281        "corestack" => {
282            let (ctx, content) = coredump::decode_core_stack(ctx)?;
283            (ctx, ast::CustomSection::CoredumpCoreStack(content))
284        }
285        _ => {
286            debug!("unknown custom section: {}", name);
287            (
288                ctx.clone(),
289                ast::CustomSection::Unknown(name, ctx.input.to_vec()),
290            )
291        }
292    })
293}
294
295fn decode_section_custom_build_id<'a>(ctx: InputContext<'a>) -> IResult<InputContext<'a>, Vec<u8>> {
296    let (ctx, size) = ctx.read_leb128()?;
297    let (ctx, bytes) = ctx.read_bytes(size as usize)?;
298    Ok((ctx, bytes.to_owned()))
299}
300
301fn decode_section_custom_name<'a>(
302    ctx: InputContext<'a>,
303) -> IResult<InputContext<'a>, ast::DebugNames> {
304    let module = None;
305    let mut func_names = None;
306    let mut global_names = HashMap::new();
307    let func_local_names = None;
308
309    let mut ctx = ctx;
310
311    loop {
312        if ctx.input.is_empty() {
313            break;
314        }
315        let ret = ctx.read_u8()?;
316        ctx = ret.0;
317        let subsection = ret.1;
318
319        let ret = ctx.read_leb128()?;
320        ctx = ret.0;
321        let size = ret.1;
322
323        debug!("parsing name subsection: {}", subsection);
324
325        match subsection {
326            // 0 => {
327            //     let ret = decode_name(ctx)?;
328            //     ctx = ret.0;
329            //     module = ret.1;
330            // }
331            1 => {
332                let ret = decode_namemap(ctx)?;
333                ctx = ret.0;
334                func_names = Some(Arc::new(Mutex::new(ret.1)));
335            }
336            // 2 => {
337            //     let ret = ctx.read_leb128()?;
338            //     ctx = ret.0;
339            //     let n = ret.1;
340
341            //     for i in 0..n {
342            //         let ret = decode_namemap(ctx)?;
343            //         ctx = ret.0;
344            //         func_local_names.insert(i, ret.1);
345            //     }
346            // }
347            7 => {
348                let ret = decode_namemap(ctx)?;
349                ctx = ret.0;
350                global_names = ret.1;
351            }
352            _ => {
353                warn!(
354                    "ignoring custom name subsection: {} ({} byte(s))",
355                    subsection, size
356                );
357                let ret = ctx.read_bytes(size as usize)?;
358                ctx = ret.0;
359            }
360        }
361    }
362
363    let debug_names = ast::DebugNames {
364        module,
365        func_names,
366        func_local_names,
367        global_names: Arc::new(Mutex::new(global_names)),
368    };
369    Ok((ctx, debug_names))
370}
371
372fn decode_namemap<'a>(ctx: InputContext<'a>) -> IResult<InputContext<'a>, HashMap<u32, String>> {
373    let mut map = HashMap::new();
374
375    let (ctx, n) = ctx.read_leb128()?;
376    let mut ctx = ctx;
377    for _ in 0..n {
378        let ret = ctx.read_leb128()?;
379        ctx = ret.0;
380        let funcidx = ret.1;
381
382        let ret = decode_name(ctx)?;
383        ctx = ret.0;
384        let name = ret.1;
385
386        map.insert(funcidx, name);
387    }
388
389    Ok((ctx, map))
390}
391
392fn decode_section_func<'a>(ctx: InputContext<'a>) -> IResult<InputContext<'a>, Vec<u32>> {
393    decode_vec(ctx, |ctx| ctx.read_leb128())
394}
395
396fn decode_section_table<'a>(ctx: InputContext<'a>) -> IResult<InputContext<'a>, Vec<ast::Table>> {
397    decode_vec(ctx, decode_table)
398}
399
400fn decode_section_import<'a>(ctx: InputContext<'a>) -> IResult<InputContext<'a>, Vec<ast::Import>> {
401    decode_vec(ctx, decode_import)
402}
403
404fn decode_section_code<'a>(ctx: InputContext<'a>) -> IResult<InputContext<'a>, Vec<ast::Code>> {
405    decode_vec(ctx, decode_code)
406}
407
408fn decode_reftype<'a>(ctx: InputContext<'a>) -> IResult<InputContext<'a>, ast::Reftype> {
409    let (ctx, t) = ctx.read_u8()?;
410    Ok((
411        ctx,
412        match t {
413            0x70 => ast::Reftype::Func,
414            0x6F => ast::Reftype::Extern,
415            _ => unimplemented!("unsupported reftype: {}", t),
416        },
417    ))
418}
419
420fn decode_limits<'a>(ctx: InputContext<'a>) -> IResult<InputContext<'a>, ast::Limits> {
421    let (ctx, t) = ctx.read_u8()?;
422    Ok(match t {
423        0x00 => {
424            let (ctx, min) = ctx.read_leb128()?;
425            (ctx, ast::Limits { min, max: None })
426        }
427        0x01 => {
428            let (ctx, min) = ctx.read_leb128()?;
429            let (ctx, max) = ctx.read_leb128()?;
430            (
431                ctx,
432                ast::Limits {
433                    min,
434                    max: Some(max),
435                },
436            )
437        }
438        _ => unimplemented!("unsupported limit: {}", t),
439    })
440}
441
442fn decode_table<'a>(ctx: InputContext<'a>) -> IResult<InputContext<'a>, ast::Table> {
443    let (ctx, reftype) = decode_reftype(ctx)?;
444    let (ctx, limits) = decode_limits(ctx)?;
445    let table = ast::Table { reftype, limits };
446    Ok((ctx, table))
447}
448
449fn decode_import<'a>(ctx: InputContext<'a>) -> IResult<InputContext<'a>, ast::Import> {
450    let (ctx, module) = decode_name(ctx)?;
451    let (ctx, name) = decode_name(ctx)?;
452
453    let (ctx, descr_t) = ctx.read_u8()?;
454    let (ctx, import_type) = match descr_t {
455        0x00 => {
456            let (ctx, typeidx) = ctx.read_leb128()?;
457            (ctx, ast::ImportType::Func(typeidx))
458        }
459        0x01 => {
460            let (ctx, tabletype) = decode_table(ctx)?;
461            (ctx, ast::ImportType::Table(tabletype))
462        }
463        0x02 => {
464            let (ctx, memtype) = decode_memory(ctx)?;
465            (ctx, ast::ImportType::Memory(memtype))
466        }
467        0x03 => {
468            let (ctx, globaltype) = decode_global_type(ctx)?;
469            (ctx, ast::ImportType::Global(globaltype))
470        }
471        _ => unimplemented!("import description: {:x}", descr_t),
472    };
473
474    let import = ast::Import {
475        module,
476        name,
477        import_type,
478    };
479    Ok((ctx, import))
480}
481
482pub(crate) fn decode_name<'a>(ctx: InputContext<'a>) -> IResult<InputContext<'a>, String> {
483    let (ctx, bytes) = decode_vec(ctx, |ctx| ctx.read_u8())?;
484    let v = String::from_utf8_lossy(&bytes).to_string();
485    Ok((ctx, v))
486}
487
488fn decode_code<'a>(ctx: InputContext<'a>) -> IResult<InputContext<'a>, ast::Code> {
489    let start_offset = ctx.offset;
490    let (ctx, size) = ctx.read_leb128()?;
491
492    let code_size_node = ast::Value {
493        start_offset,
494        value: size,
495        end_offset: ctx.offset,
496    };
497
498    // let code_start_offset = ctx.offset;
499    let code_start_offset = start_offset;
500    let (ctx, code_bytes) = ctx.read_bytes(size as usize)?;
501
502    let code = {
503        let ctx = InputContext {
504            input: code_bytes,
505            offset: code_start_offset,
506        };
507
508        let (ctx, locals) = decode_vec(ctx, decode_code_local)?;
509        let (_ctx, body) = decode_expr(ctx, ast::Instr::end)?;
510        let body = Arc::new(Mutex::new(body));
511
512        // Bytes are split before, no need to propagate this context.
513        ast::Code {
514            size: code_size_node,
515            locals,
516            body,
517        }
518    };
519
520    Ok((ctx, code))
521}
522
523fn decode_instr<'a>(ctx: InputContext<'a>) -> IResult<InputContext<'a>, ast::Value<ast::Instr>> {
524    let start_offset = ctx.offset;
525    let (ctx, id) = ctx.read_u8()?;
526
527    macro_rules! decode_instr {
528        ($byte:expr, $instr:ident) => {
529            if id == $byte {
530                let end_offset = ctx.offset;
531                let value = ast::Value {
532                    start_offset,
533                    value: ast::Instr::$instr,
534                    end_offset,
535                };
536                return Ok((ctx, value));
537            }
538        };
539        ($byte:expr, $instr:ident(u8)) => {
540            if id == $byte {
541                let (ctx, arg0) = ctx.read_u8()?;
542                let end_offset = ctx.offset;
543
544                let value = ast::Value {
545                    start_offset,
546                    value: ast::Instr::$instr(arg0),
547                    end_offset,
548                };
549                return Ok((ctx, value));
550            }
551        };
552
553        ($byte:expr, $instr:ident(f32)) => {
554            if id == $byte {
555                let (ctx, arg0) = ctx.read_f32()?;
556                let end_offset = ctx.offset;
557
558                let value = ast::Value {
559                    start_offset,
560                    value: ast::Instr::$instr(arg0),
561                    end_offset,
562                };
563                return Ok((ctx, value));
564            }
565        };
566
567        ($byte:expr, $instr:ident(f64)) => {
568            if id == $byte {
569                let (ctx, arg0) = ctx.read_f64()?;
570                let end_offset = ctx.offset;
571
572                let value = ast::Value {
573                    start_offset,
574                    value: ast::Instr::$instr(arg0),
575                    end_offset,
576                };
577                return Ok((ctx, value));
578            }
579        };
580
581        ($byte:expr, $instr:ident(i32)) => {
582            if id == $byte {
583                let (ctx, arg0) = ctx.read_leb128_signed()?;
584                let end_offset = ctx.offset;
585
586                let value = ast::Value {
587                    start_offset,
588                    value: ast::Instr::$instr(arg0),
589                    end_offset,
590                };
591                return Ok((ctx, value));
592            }
593        };
594
595        ($byte:expr, $instr:ident(i64)) => {
596            if id == $byte {
597                let (ctx, arg0) = ctx.read_leb128_signed()?;
598                let end_offset = ctx.offset;
599
600                let value = ast::Value {
601                    start_offset,
602                    value: ast::Instr::$instr(arg0),
603                    end_offset,
604                };
605                return Ok((ctx, value));
606            }
607        };
608
609        ($byte:expr, $instr:ident(u32)) => {
610            if id == $byte {
611                let (ctx, arg0) = ctx.read_leb128()?;
612                let end_offset = ctx.offset;
613
614                let value = ast::Value {
615                    start_offset,
616                    value: ast::Instr::$instr(arg0),
617                    end_offset,
618                };
619                return Ok((ctx, value));
620            }
621        };
622
623        ($byte:expr, $instr:ident(MutableValue<u32>)) => {
624            if id == $byte {
625                let arg_start_offset = ctx.offset;
626                let (ctx, arg0) = ctx.read_leb128()?;
627                let end_offset = ctx.offset;
628
629                let arg0 = ast::Value {
630                    start_offset: arg_start_offset,
631                    value: arg0,
632                    end_offset,
633                };
634
635                let value = ast::Value {
636                    start_offset,
637                    value: ast::Instr::$instr(Arc::new(Mutex::new(arg0))),
638                    end_offset,
639                };
640                return Ok((ctx, value));
641            }
642        };
643
644        ($byte:expr, $instr:ident(u32, u32)) => {
645            if id == $byte {
646                let (ctx, arg0) = ctx.read_leb128()?;
647                let (ctx, arg1) = ctx.read_leb128()?;
648                let end_offset = ctx.offset;
649
650                let value = ast::Value {
651                    start_offset,
652                    value: ast::Instr::$instr(arg0, arg1),
653                    end_offset,
654                };
655                return Ok((ctx, value));
656            }
657        };
658
659        ($byte:expr, $instr:ident(MutableValue<u32>, u32)) => {
660            if id == $byte {
661                let start_offset = ctx.offset;
662                let (ctx, arg0) = ctx.read_leb128()?;
663                let end_offset = ctx.offset;
664                let arg0 = Arc::new(Mutex::new(ast::Value {
665                    start_offset,
666                    value: arg0,
667                    end_offset,
668                }));
669
670                let (ctx, arg1) = ctx.read_leb128()?;
671                let end_offset = ctx.offset;
672
673                let value = ast::Value {
674                    start_offset,
675                    value: ast::Instr::$instr(arg0, arg1),
676                    end_offset,
677                };
678                return Ok((ctx, value));
679            }
680        };
681
682        ($byte:expr, $instr:ident(Vec<u32>, u32)) => {
683            if id == $byte {
684                let (ctx, arg0) = decode_vec(ctx, |ctx| ctx.read_leb128())?;
685                let (ctx, arg1) = ctx.read_leb128()?;
686                let end_offset = ctx.offset;
687
688                let value = ast::Value {
689                    start_offset,
690                    value: ast::Instr::$instr(arg0, arg1),
691                    end_offset,
692                };
693                return Ok((ctx, value));
694            }
695        };
696    }
697
698    decode_instr!(0x00, unreachable);
699    decode_instr!(0x01, nop);
700
701    if id == 0x02 {
702        let (ctx, block_type) = decode_blocktype(ctx)?;
703        let (ctx, body) = decode_expr(ctx, ast::Instr::end)?;
704        let end_offset = ctx.offset;
705
706        let value = ast::Value {
707            start_offset,
708            value: ast::Instr::Block(block_type, Arc::new(Mutex::new(body))),
709            end_offset,
710        };
711        return Ok((ctx, value));
712    }
713    if id == 0x03 {
714        let (ctx, block_type) = decode_blocktype(ctx)?;
715        let (ctx, body) = decode_expr(ctx, ast::Instr::end)?;
716        let end_offset = ctx.offset;
717
718        let value = ast::Value {
719            start_offset,
720            value: ast::Instr::Loop(block_type, Arc::new(Mutex::new(body))),
721            end_offset,
722        };
723        return Ok((ctx, value));
724    }
725    if id == 0x04 {
726        let (ctx, block_type) = decode_blocktype(ctx)?;
727        // let (ctx, consequent) = decode_expr(ctx, ast::Instr::else_end)?;
728        // FIXME: support IfElse, If will contain both
729        let (ctx, body) = decode_expr(ctx, ast::Instr::end)?;
730        let end_offset = ctx.offset;
731
732        let value = ast::Value {
733            start_offset,
734            value: ast::Instr::If(block_type, Arc::new(Mutex::new(body))),
735            end_offset,
736        };
737        return Ok((ctx, value));
738    }
739
740    decode_instr!(0xc, br(u32));
741    decode_instr!(0xd, br_if(u32));
742    decode_instr!(0x0b, end);
743    decode_instr!(0x05, else_end);
744    decode_instr!(0x0e, br_table(Vec<u32>, u32));
745    decode_instr!(0x0f, Return);
746    decode_instr!(0x10, call(MutableValue<u32>));
747    decode_instr!(0x11, call_indirect(u32, u32));
748
749    decode_instr!(0x1a, drop);
750    decode_instr!(0x1b, select);
751    // decode_instr!(0x1c, select);
752
753    decode_instr!(0x20, local_get(u32));
754    decode_instr!(0x21, local_set(u32));
755    decode_instr!(0x22, local_tee(u32));
756    decode_instr!(0x23, global_get(u32));
757    decode_instr!(0x24, global_set(u32));
758    decode_instr!(0x25, table_get(u32));
759    decode_instr!(0x26, table_set(u32));
760
761    decode_instr!(0x28, i32_load(MutableValue<u32>, u32));
762    decode_instr!(0x29, i64_load(MutableValue<u32>, u32));
763    decode_instr!(0x2a, f32_load(MutableValue<u32>, u32));
764    decode_instr!(0x2b, f64_load(MutableValue<u32>, u32));
765    decode_instr!(0x2c, i32_load8_s(MutableValue<u32>, u32));
766    decode_instr!(0x2d, i32_load8_u(MutableValue<u32>, u32));
767    decode_instr!(0x2e, i32_load16_s(MutableValue<u32>, u32));
768    decode_instr!(0x2f, i32_load16_u(MutableValue<u32>, u32));
769    decode_instr!(0x30, i64_load8_s(MutableValue<u32>, u32));
770    decode_instr!(0x31, i64_load8_u(MutableValue<u32>, u32));
771    decode_instr!(0x32, i64_load16_s(MutableValue<u32>, u32));
772    decode_instr!(0x33, i64_load16_u(MutableValue<u32>, u32));
773    decode_instr!(0x34, i64_load32_s(MutableValue<u32>, u32));
774    decode_instr!(0x35, i64_load32_u(MutableValue<u32>, u32));
775
776    decode_instr!(0x36, i32_store(MutableValue<u32>, u32));
777    decode_instr!(0x37, i64_store(MutableValue<u32>, u32));
778    decode_instr!(0x38, f32_store(MutableValue<u32>, u32));
779    decode_instr!(0x39, f64_store(MutableValue<u32>, u32));
780    decode_instr!(0x3a, i32_store8(MutableValue<u32>, u32));
781    decode_instr!(0x3b, i32_store16(MutableValue<u32>, u32));
782    decode_instr!(0x3c, i64_store8(MutableValue<u32>, u32));
783    decode_instr!(0x3d, i64_store16(MutableValue<u32>, u32));
784    decode_instr!(0x3e, i64_store32(MutableValue<u32>, u32));
785
786    decode_instr!(0x3f, memory_size(u8));
787    decode_instr!(0x40, memory_grow(u8));
788
789    decode_instr!(0x41, i32_const(i32));
790    decode_instr!(0x42, i64_const(i64));
791    decode_instr!(0x43, f32_const(f32));
792    decode_instr!(0x44, f64_const(f64));
793
794    decode_instr!(0x45, i32_eqz);
795    decode_instr!(0x46, i32_eq);
796    decode_instr!(0x47, i32_ne);
797    decode_instr!(0x48, i32_lt_s);
798    decode_instr!(0x49, i32_lt_u);
799    decode_instr!(0x4a, i32_gt_s);
800    decode_instr!(0x4b, i32_gt_u);
801    decode_instr!(0x4c, i32_le_s);
802    decode_instr!(0x4d, i32_le_u);
803    decode_instr!(0x4e, i32_ge_s);
804    decode_instr!(0x4f, i32_ge_u);
805
806    decode_instr!(0x50, i64_eqz);
807    decode_instr!(0x51, i64_eq);
808    decode_instr!(0x52, i64_ne);
809    decode_instr!(0x53, i64_lt_s);
810    decode_instr!(0x54, i64_lt_u);
811    decode_instr!(0x55, i64_gt_s);
812    decode_instr!(0x56, i64_gt_u);
813    decode_instr!(0x57, i64_le_s);
814    decode_instr!(0x58, i64_le_u);
815    decode_instr!(0x59, i64_ge_s);
816    decode_instr!(0x5a, i64_ge_u);
817
818    decode_instr!(0x5b, f32_eq);
819    decode_instr!(0x5c, f32_ne);
820    decode_instr!(0x5d, f32_lt);
821    decode_instr!(0x5e, f32_gt);
822    decode_instr!(0x5f, f32_le);
823    decode_instr!(0x60, f32_ge);
824
825    decode_instr!(0x61, f64_eq);
826    decode_instr!(0x62, f64_ne);
827    decode_instr!(0x63, f64_lt);
828    decode_instr!(0x64, f64_gt);
829    decode_instr!(0x65, f64_le);
830    decode_instr!(0x66, f64_ge);
831
832    decode_instr!(0x67, i32_clz);
833    decode_instr!(0x68, i32_ctz);
834    decode_instr!(0x69, i32_popcnt);
835    decode_instr!(0x6a, i32_add);
836    decode_instr!(0x6b, i32_sub);
837    decode_instr!(0x6c, i32_mul);
838    decode_instr!(0x6d, i32_div_s);
839    decode_instr!(0x6e, i32_div_u);
840    decode_instr!(0x6f, i32_rem_s);
841    decode_instr!(0x70, i32_rem_u);
842    decode_instr!(0x71, i32_and);
843    decode_instr!(0x72, i32_or);
844    decode_instr!(0x73, i32_xor);
845    decode_instr!(0x74, i32_shl);
846    decode_instr!(0x75, i32_shr_s);
847    decode_instr!(0x76, i32_shr_u);
848    decode_instr!(0x77, i32_rotl);
849    decode_instr!(0x78, i32_rotr);
850
851    decode_instr!(0x79, i64_clz);
852    decode_instr!(0x7a, i64_ctz);
853    decode_instr!(0x7b, i64_popcnt);
854    decode_instr!(0x7c, i64_add);
855    decode_instr!(0x7d, i64_sub);
856    decode_instr!(0x7e, i64_mul);
857    decode_instr!(0x7f, i64_div_s);
858    decode_instr!(0x80, i64_div_u);
859    decode_instr!(0x81, i64_rem_s);
860    decode_instr!(0x82, i64_rem_u);
861    decode_instr!(0x83, i64_and);
862    decode_instr!(0x84, i64_or);
863    decode_instr!(0x85, i64_xor);
864    decode_instr!(0x86, i64_shl);
865    decode_instr!(0x87, i64_shr_s);
866    decode_instr!(0x88, i64_shr_u);
867    decode_instr!(0x89, i64_rotl);
868    decode_instr!(0x8a, i64_rotr);
869
870    decode_instr!(0x8b, f32_abs);
871    decode_instr!(0x8c, f32_neg);
872    decode_instr!(0x8d, f32_ceil);
873    decode_instr!(0x8e, f32_floor);
874    decode_instr!(0x8f, f32_trunc);
875    decode_instr!(0x90, f32_nearest);
876    decode_instr!(0x91, f32_sqrt);
877    decode_instr!(0x92, f32_add);
878    decode_instr!(0x93, f32_sub);
879    decode_instr!(0x94, f32_mul);
880    decode_instr!(0x95, f32_div);
881    decode_instr!(0x96, f32_min);
882    decode_instr!(0x97, f32_max);
883    decode_instr!(0x98, f32_copysign);
884
885    decode_instr!(0x99, f64_abs);
886    decode_instr!(0x9a, f64_neg);
887    decode_instr!(0x9b, f64_ceil);
888    decode_instr!(0x9c, f64_floor);
889    decode_instr!(0x9d, f64_trunc);
890    decode_instr!(0x9e, f64_nearest);
891    decode_instr!(0x9f, f64_sqrt);
892    decode_instr!(0xa0, f64_add);
893    decode_instr!(0xa1, f64_sub);
894    decode_instr!(0xa2, f64_mul);
895    decode_instr!(0xa3, f64_div);
896    decode_instr!(0xa4, f64_min);
897    decode_instr!(0xa5, f64_max);
898    decode_instr!(0xa6, f64_copysign);
899
900    decode_instr!(0xa7, i32_wrap_i64);
901    decode_instr!(0xa8, i32_trunc_f32_s);
902    decode_instr!(0xa9, i32_trunc_f32_u);
903    decode_instr!(0xaa, i32_trunc_f64_s);
904    decode_instr!(0xab, i32_trunc_f64_u);
905    decode_instr!(0xac, i64_extend_i32_s);
906    decode_instr!(0xad, i64_extend_i32_u);
907    decode_instr!(0xae, i64_trunc_f32_s);
908    decode_instr!(0xaf, i64_trunc_f32_u);
909    decode_instr!(0xb0, i64_trunc_f64_s);
910    decode_instr!(0xb1, i64_trunc_f64_u);
911    decode_instr!(0xb2, f32_convert_i32_s);
912    decode_instr!(0xb3, f32_convert_i32_u);
913    decode_instr!(0xb4, f32_convert_i64_s);
914    decode_instr!(0xb5, f32_convert_i64_u);
915    decode_instr!(0xb6, f32_demote_f64);
916    decode_instr!(0xb7, f64_convert_i32_s);
917    decode_instr!(0xb8, f64_convert_i32_u);
918    decode_instr!(0xb9, f64_convert_i64_s);
919    decode_instr!(0xba, f64_convert_i64_u);
920    decode_instr!(0xbb, f64_promote_f32);
921
922    decode_instr!(0xbc, i32_reinterpret_f32);
923    decode_instr!(0xbd, i64_reinterpret_f64);
924    decode_instr!(0xbe, f32_reinterpret_i32);
925    decode_instr!(0xbf, f64_reinterpret_i64);
926
927    decode_instr!(0xc0, i32_extend8_s);
928    decode_instr!(0xc1, i32_extend16_s);
929    decode_instr!(0xc2, i64_extend8_s);
930    decode_instr!(0xc3, i64_extend16_s);
931    decode_instr!(0xc4, i64_extend32_s);
932
933    if id == 0xfc {
934        let (ctx, b) = ctx.read_u8()?;
935        let end_offset = ctx.offset;
936
937        match b {
938            // https://webassembly.github.io/spec/core/binary/instructions.html#numeric-instructions
939            // saturating truncation instructions
940            0 => {
941                let value = ast::Value {
942                    start_offset,
943                    value: ast::Instr::i32_trunc_sat_f32_s,
944                    end_offset,
945                };
946                return Ok((ctx, value));
947            }
948            1 => {
949                let value = ast::Value {
950                    start_offset,
951                    value: ast::Instr::i32_trunc_sat_f32_u,
952                    end_offset,
953                };
954                return Ok((ctx, value));
955            }
956            2 => {
957                let value = ast::Value {
958                    start_offset,
959                    value: ast::Instr::i32_trunc_sat_f64_s,
960                    end_offset,
961                };
962                return Ok((ctx, value));
963            }
964            3 => {
965                let value = ast::Value {
966                    start_offset,
967                    value: ast::Instr::i32_trunc_sat_f64_u,
968                    end_offset,
969                };
970                return Ok((ctx, value));
971            }
972            4 => {
973                let value = ast::Value {
974                    start_offset,
975                    value: ast::Instr::i64_trunc_sat_f32_s,
976                    end_offset,
977                };
978                return Ok((ctx, value));
979            }
980            5 => {
981                let value = ast::Value {
982                    start_offset,
983                    value: ast::Instr::i64_trunc_sat_f32_u,
984                    end_offset,
985                };
986                return Ok((ctx, value));
987            }
988            6 => {
989                let value = ast::Value {
990                    start_offset,
991                    value: ast::Instr::i64_trunc_sat_f64_s,
992                    end_offset,
993                };
994                return Ok((ctx, value));
995            }
996            7 => {
997                let value = ast::Value {
998                    start_offset,
999                    value: ast::Instr::i64_trunc_sat_f64_u,
1000                    end_offset,
1001                };
1002                return Ok((ctx, value));
1003            }
1004
1005            // other instructions
1006            10 => {
1007                let (ctx, imm0) = ctx.read_u8()?;
1008                let (ctx, imm1) = ctx.read_u8()?;
1009                let value = ast::Value {
1010                    start_offset,
1011                    value: ast::Instr::memory_copy(imm0, imm1),
1012                    end_offset,
1013                };
1014                return Ok((ctx, value));
1015            }
1016            11 => {
1017                let (ctx, imm0) = ctx.read_u8()?;
1018                let value = ast::Value {
1019                    start_offset,
1020                    value: ast::Instr::memory_fill(imm0),
1021                    end_offset,
1022                };
1023                return Ok((ctx, value));
1024            }
1025            b => {
1026                unimplemented!("unknown 0xfc operation {}", b)
1027            }
1028        }
1029    }
1030
1031    unimplemented!("unknown instruction: {:#x}", id);
1032}
1033
1034fn decode_expr<'a>(
1035    ctx: InputContext<'a>,
1036    _end_instr: ast::Instr,
1037) -> IResult<InputContext<'a>, ast::Expr> {
1038    let start_offset = ctx.offset;
1039
1040    let mut ctx = ctx;
1041    let mut vec = Vec::new();
1042    loop {
1043        let ret = decode_instr(ctx)?;
1044        ctx = ret.0;
1045        vec.push(ret.1.clone());
1046        if matches!(ret.1.value, ast::Instr::end) {
1047            break;
1048        }
1049    }
1050
1051    let end_offset = ctx.offset;
1052    let value = ast::Value {
1053        start_offset,
1054        value: vec,
1055        end_offset,
1056    };
1057    Ok((ctx, value))
1058}
1059
1060fn decode_code_local<'a>(ctx: InputContext<'a>) -> IResult<InputContext<'a>, ast::CodeLocal> {
1061    let (ctx, count) = ctx.read_leb128()?;
1062    let (ctx, value_type) = decode_valtype(ctx)?;
1063    let code_local = ast::CodeLocal { count, value_type };
1064    Ok((ctx, code_local))
1065}
1066
1067fn decode_valtype<'a>(ctx: InputContext<'a>) -> IResult<InputContext<'a>, ast::ValueType> {
1068    let (ctx, id) = ctx.read_u8()?;
1069    Ok((
1070        ctx,
1071        match id {
1072            0x7F => ast::ValueType::NumType(ast::NumType::I32),
1073            0x7E => ast::ValueType::NumType(ast::NumType::I64),
1074            0x7D => ast::ValueType::NumType(ast::NumType::F32),
1075            0x7C => ast::ValueType::NumType(ast::NumType::F64),
1076            e => unimplemented!("unsupported type: {:x}", e),
1077        },
1078    ))
1079}
1080
1081fn decode_type<'a>(ctx: InputContext<'a>) -> IResult<InputContext<'a>, ast::Type> {
1082    let (ctx, b) = ctx.read_u8()?;
1083    if b != 0x60 {
1084        panic!("unexpected type: {}", b);
1085    }
1086    let (ctx, params) = decode_vec(ctx, decode_valtype)?;
1087    let (ctx, results) = decode_vec(ctx, decode_valtype)?;
1088
1089    let t = ast::Type { params, results };
1090    Ok((ctx, t))
1091}
1092
1093fn decode_data<'a>(ctx: InputContext<'a>) -> IResult<InputContext<'a>, ast::DataSegment> {
1094    let (ctx, t) = ctx.read_leb128()?;
1095
1096    match t {
1097        0 => {
1098            let (ctx, expr) = decode_expr(ctx, ast::Instr::end)?;
1099            let (ctx, bytes) = decode_vec(ctx, |ctx| ctx.read_u8())?;
1100            let data_segment = ast::DataSegment {
1101                mode: ast::DataSegmentMode::Active,
1102                offset: Some(expr),
1103                bytes,
1104            };
1105            Ok((ctx, data_segment))
1106        }
1107        1 => {
1108            let (ctx, bytes) = decode_vec(ctx, |ctx| ctx.read_u8())?;
1109            let data_segment = ast::DataSegment {
1110                mode: ast::DataSegmentMode::Passive,
1111                offset: None,
1112                bytes,
1113            };
1114            Ok((ctx, data_segment))
1115        }
1116        _ => unimplemented!("data segment of type: {}", t),
1117    }
1118}
1119
1120fn decode_element<'a>(ctx: InputContext<'a>) -> IResult<InputContext<'a>, ast::Element> {
1121    let (ctx, t) = ctx.read_leb128()?;
1122    Ok(match t {
1123        0 => {
1124            let (ctx, expr) = decode_expr(ctx, ast::Instr::end)?;
1125            let (ctx, elements) = decode_vec(ctx, |ctx| ctx.read_leb128())?;
1126            (
1127                ctx,
1128                ast::Element::FuncActive(expr, Arc::new(Mutex::new(elements))),
1129            )
1130        }
1131        _ => unimplemented!("element segment of type: {}", t),
1132    })
1133}
1134
1135fn decode_export<'a>(ctx: InputContext<'a>) -> IResult<InputContext<'a>, ast::Export> {
1136    let (ctx, name) = decode_name(ctx)?;
1137    let (ctx, descr) = decode_export_desc(ctx)?;
1138    let export = ast::Export { name, descr };
1139    Ok((ctx, export))
1140}
1141
1142fn decode_export_desc<'a>(ctx: InputContext<'a>) -> IResult<InputContext<'a>, ast::ExportDescr> {
1143    let (ctx, t) = ctx.read_u8()?;
1144    Ok(match t {
1145        0x00 => {
1146            let (ctx, idx) = ctx.read_leb128()?;
1147            (ctx, ast::ExportDescr::Func(Arc::new(Mutex::new(idx))))
1148        }
1149        0x01 => {
1150            let (ctx, idx) = ctx.read_leb128()?;
1151            (ctx, ast::ExportDescr::Table(Arc::new(Mutex::new(idx))))
1152        }
1153        0x02 => {
1154            let (ctx, idx) = ctx.read_leb128()?;
1155            (ctx, ast::ExportDescr::Mem(Arc::new(Mutex::new(idx))))
1156        }
1157        0x03 => {
1158            let (ctx, idx) = ctx.read_leb128()?;
1159            (ctx, ast::ExportDescr::Global(Arc::new(Mutex::new(idx))))
1160        }
1161        _ => unimplemented!("unsupported export descr"),
1162    })
1163}
1164
1165fn decode_global<'a>(ctx: InputContext<'a>) -> IResult<InputContext<'a>, ast::Global> {
1166    let (ctx, global_type) = decode_global_type(ctx)?;
1167    let (ctx, expr) = decode_expr(ctx, ast::Instr::end)?;
1168    let global = ast::Global { global_type, expr };
1169    Ok((ctx, global))
1170}
1171
1172fn decode_global_type<'a>(ctx: InputContext<'a>) -> IResult<InputContext<'a>, ast::GlobalType> {
1173    let (ctx, valtype) = decode_valtype(ctx)?;
1174    let (ctx, mutable) = ctx.read_u8()?;
1175
1176    let global_type = ast::GlobalType {
1177        valtype,
1178        mutable: mutable == 1,
1179    };
1180
1181    Ok((ctx, global_type))
1182}
1183
1184fn decode_memory<'a>(ctx: InputContext<'a>) -> IResult<InputContext<'a>, ast::Memory> {
1185    let (ctx, t) = ctx.read_u8()?;
1186
1187    let start_offset = ctx.offset;
1188    let (ctx, min) = ctx.read_leb128()?;
1189    let end_offset = ctx.offset;
1190    let min = ast::Value {
1191        start_offset,
1192        value: min,
1193        end_offset,
1194    };
1195
1196    let (ctx, mem) = match t {
1197        0 => (ctx, ast::Memory { min, max: None }),
1198        1 => {
1199            let (ctx, max) = ctx.read_leb128()?;
1200            (
1201                ctx,
1202                ast::Memory {
1203                    min,
1204                    max: Some(max),
1205                },
1206            )
1207        }
1208        e => unimplemented!("unsupported memory type: {}", e),
1209    };
1210
1211    Ok((ctx, mem))
1212}
1213
1214fn decode_section<'a>(ctx: InputContext<'a>) -> IResult<InputContext<'a>, ast::Section> {
1215    let (ctx, id) = ctx.read_u8()?;
1216
1217    let size_start_offset = ctx.offset;
1218    let (ctx, size) = ctx.read_leb128()?;
1219    let size_end_offset = ctx.offset;
1220
1221    let section_size = ast::Value {
1222        start_offset: size_start_offset,
1223        value: size,
1224        end_offset: size_end_offset,
1225    };
1226
1227    let section_start_offset = ctx.offset;
1228    debug!(
1229        "decoding section {} ({} byte(s)) @ {}",
1230        id, size, section_start_offset
1231    );
1232    let (ctx, section_bytes) = ctx.read_bytes(size as usize)?;
1233
1234    let section_bytes = InputContext {
1235        input: section_bytes,
1236        offset: section_start_offset,
1237    };
1238
1239    let section = match id {
1240        0 => match decode_section_custom(section_bytes.clone()) {
1241            Ok((_, res)) => ast::Section::Custom((section_size, Arc::new(Mutex::new(res)))),
1242            Err(err) => {
1243                eprintln!("failed to parse custom section: {}. Ignoring.", err);
1244                ast::Section::Unknown((id, size, section_bytes.input.to_vec()))
1245            }
1246        },
1247        1 => {
1248            let (_, res) = decode_section_type(section_bytes)?;
1249            ast::Section::Type((section_size, Arc::new(Mutex::new(res))))
1250        }
1251        2 => {
1252            let (_, res) = decode_section_import(section_bytes)?;
1253            ast::Section::Import((section_size, Arc::new(Mutex::new(res))))
1254        }
1255        3 => {
1256            let (_, res) = decode_section_func(section_bytes)?;
1257            ast::Section::Func((section_size, Arc::new(Mutex::new(res))))
1258        }
1259        4 => {
1260            let (_, res) = decode_section_table(section_bytes)?;
1261            ast::Section::Table((section_size, Arc::new(Mutex::new(res))))
1262        }
1263        5 => {
1264            let (_, res) = decode_section_memory(section_bytes)?;
1265            ast::Section::Memory((section_size, res))
1266        }
1267        6 => {
1268            let (_, res) = decode_section_global(section_bytes)?;
1269            ast::Section::Global((section_size, Arc::new(Mutex::new(res))))
1270        }
1271        7 => {
1272            let (_, res) = decode_section_export(section_bytes)?;
1273            ast::Section::Export((section_size, Arc::new(Mutex::new(res))))
1274        }
1275        9 => {
1276            let (_, res) = decode_section_element(section_bytes)?;
1277            ast::Section::Element((section_size, Arc::new(Mutex::new(res))))
1278        }
1279        10 => {
1280            let (_, res) = decode_section_code(section_bytes)?;
1281            let end_offset = ctx.offset;
1282
1283            let value = ast::Value {
1284                start_offset: section_start_offset,
1285                value: res,
1286                end_offset,
1287            };
1288            ast::Section::Code((section_size, Arc::new(Mutex::new(value))))
1289        }
1290        11 => {
1291            let (_, res) = decode_section_data(section_bytes)?;
1292            ast::Section::Data((section_size, Arc::new(Mutex::new(res))))
1293        }
1294        id => {
1295            warn!("unknown section with id {}", id);
1296            ast::Section::Unknown((id, size, section_bytes.input.to_vec()))
1297        }
1298    };
1299    Ok((ctx, section))
1300}
1301
1302type DecodeItem<'a, T> = fn(InputContext<'a>) -> IResult<InputContext<'a>, T>;
1303
1304pub(crate) fn decode_vec<'a, T>(
1305    ctx: InputContext<'a>,
1306    decode_item_fn: DecodeItem<'a, T>,
1307) -> IResult<InputContext<'a>, Vec<T>> {
1308    let (ctx, n) = ctx.read_leb128()?;
1309
1310    let mut items: Vec<T> = Vec::new();
1311    let mut ctx = ctx;
1312    for _ in 0..n {
1313        let res = decode_item_fn(ctx)?;
1314        ctx = res.0;
1315        items.push(res.1);
1316    }
1317
1318    Ok((ctx, items))
1319}
1320
1321fn decode_blocktype<'a>(ctx: InputContext<'a>) -> IResult<InputContext<'a>, ast::BlockType> {
1322    let (ctx, next) = ctx.peak_u8()?;
1323    if next == 0x40 {
1324        // actually read what we peaked
1325        let (ctx, _) = ctx.read_u8()?;
1326        Ok((ctx, ast::BlockType::Empty))
1327    } else {
1328        if let Ok((ctx, valtype)) = decode_valtype(ctx.clone()) {
1329            Ok((ctx, ast::BlockType::ValueType(valtype)))
1330        } else {
1331            let (ctx, typeidx) = ctx.read_leb128()?;
1332            Ok((ctx, ast::BlockType::Typeidx(typeidx)))
1333        }
1334    }
1335}