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 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 1 => {
332 let ret = decode_namemap(ctx)?;
333 ctx = ret.0;
334 func_names = Some(Arc::new(Mutex::new(ret.1)));
335 }
336 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 = 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 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, 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!(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 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 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 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}