xref: /wasmtime-44.0.1/tests/all/debug.rs (revision bedbcd85)
1 //! Tests for instrumentation-based debugging.
2 
3 use wasmtime::{Caller, Config, Engine, Extern, Func, Instance, Module, Store};
4 
5 fn test_stack_values<C: Fn(&mut Config), F: Fn(Caller<'_, ()>) + Send + Sync + 'static>(
6     wat: &str,
7     c: C,
8     f: F,
9 ) -> anyhow::Result<()> {
10     let mut config = Config::default();
11     config.guest_debug(true);
12     config.wasm_exceptions(true);
13     c(&mut config);
14     let engine = Engine::new(&config)?;
15     let module = Module::new(&engine, wat)?;
16 
17     let mut store = Store::new(&engine, ());
18     let func = Func::wrap(&mut store, move |caller: Caller<'_, ()>| {
19         f(caller);
20     });
21     let instance = Instance::new(&mut store, &module, &[Extern::Func(func)])?;
22     let mut results = [];
23     instance
24         .get_func(&mut store, "main")
25         .unwrap()
26         .call(&mut store, &[], &mut results)?;
27 
28     Ok(())
29 }
30 
31 #[test]
32 #[cfg_attr(miri, ignore)]
33 fn stack_values_two_frames() -> anyhow::Result<()> {
34     let _ = env_logger::try_init();
35 
36     for inlining in [false, true] {
37         test_stack_values(
38             r#"
39     (module
40       (import "" "host" (func))
41       (func (export "main")
42         i32.const 1
43         i32.const 2
44         call 2
45         drop)
46       (func (param i32 i32) (result i32)
47         local.get 0
48         local.get 1
49         call 0
50         i32.add))
51     "#,
52             |config| {
53                 config.compiler_inlining(inlining);
54                 if inlining {
55                     unsafe {
56                         config.cranelift_flag_set("wasmtime_inlining_intra_module", "true");
57                     }
58                 }
59             },
60             |mut caller: Caller<'_, ()>| {
61                 let mut stack = caller.debug_frames().unwrap();
62                 assert!(!stack.done());
63                 assert_eq!(stack.wasm_function_index_and_pc().unwrap().0.as_u32(), 1);
64                 assert_eq!(stack.wasm_function_index_and_pc().unwrap().1, 65);
65 
66                 assert_eq!(stack.num_locals(), 2);
67                 assert_eq!(stack.num_stacks(), 2);
68                 assert_eq!(stack.local(0).unwrap_i32(), 1);
69                 assert_eq!(stack.local(1).unwrap_i32(), 2);
70                 assert_eq!(stack.stack(0).unwrap_i32(), 1);
71                 assert_eq!(stack.stack(1).unwrap_i32(), 2);
72 
73                 stack.move_to_parent();
74                 assert!(!stack.done());
75                 assert_eq!(stack.wasm_function_index_and_pc().unwrap().0.as_u32(), 0);
76                 assert_eq!(stack.wasm_function_index_and_pc().unwrap().1, 55);
77 
78                 stack.move_to_parent();
79                 assert!(stack.done());
80             },
81         )?;
82     }
83     Ok(())
84 }
85 
86 #[test]
87 #[cfg_attr(miri, ignore)]
88 fn stack_values_exceptions() -> anyhow::Result<()> {
89     test_stack_values(
90         r#"
91     (module
92       (tag $t (param i32))
93       (import "" "host" (func))
94       (func (export "main")
95         (block $b (result i32)
96           (try_table (catch $t $b)
97             (throw $t (i32.const 42)))
98           i32.const 0)
99         (call 0)
100         (drop)))
101     "#,
102         |_config| {},
103         |mut caller: Caller<'_, ()>| {
104             let mut stack = caller.debug_frames().unwrap();
105             assert!(!stack.done());
106             assert_eq!(stack.num_stacks(), 1);
107             assert_eq!(stack.stack(0).unwrap_i32(), 42);
108             stack.move_to_parent();
109             assert!(stack.done());
110         },
111     )
112 }
113 
114 #[test]
115 #[cfg_attr(miri, ignore)]
116 fn stack_values_dead_gc_ref() -> anyhow::Result<()> {
117     test_stack_values(
118         r#"
119     (module
120       (type $s (struct))
121       (import "" "host" (func))
122       (func (export "main")
123         (struct.new $s)
124         (call 0)
125         (drop)))
126     "#,
127         |config| {
128             config.wasm_gc(true);
129         },
130         |mut caller: Caller<'_, ()>| {
131             let mut stack = caller.debug_frames().unwrap();
132             assert!(!stack.done());
133             assert_eq!(stack.num_stacks(), 1);
134             assert!(stack.stack(0).unwrap_anyref().is_some());
135             stack.move_to_parent();
136             assert!(stack.done());
137         },
138     )
139 }
140