xref: /wasmtime-44.0.1/examples/coredump.rs (revision 9ce3ffe1)
1 //! An example of how to configure capturing core dumps when the guest Wasm
2 //! traps that can then be passed to external tools for post-mortem analysis.
3 
4 // You can execute this example with `cargo run --example coredump`.
5 
6 use wasmtime::*;
7 
main() -> Result<()>8 fn main() -> Result<()> {
9     println!("Configure core dumps to be captured on trap.");
10     let mut config = Config::new();
11     config.coredump_on_trap(true);
12     let engine = Engine::new(&config)?;
13     let mut store = Store::new(&engine, ());
14 
15     println!("Define a Wasm module that will mutate local state and then trap.");
16     let module = Module::new(
17         store.engine(),
18         r#"
19             (module $trapper
20                 (memory 10)
21                 (global $g (mut i32) (i32.const 0))
22 
23                 (func (export "run")
24                     call $a
25                 )
26 
27                 (func $a
28                     i32.const 0x1234
29                     i64.const 42
30                     i64.store
31                     call $b
32                 )
33 
34                 (func $b
35                     i32.const 36
36                     global.set $g
37                     call $c
38                 )
39 
40                 (func $c
41                     unreachable
42                 )
43             )
44         "#,
45     )?;
46 
47     println!("Instantiate the module.");
48     let instance = Instance::new(&mut store, &module, &[])?;
49 
50     println!("Invoke its 'run' function.");
51     let run = instance
52         .get_func(&mut store, "run")
53         .expect("should have 'run' export");
54     let args = &[];
55     let results = &mut [];
56     let ok = run.call(&mut store, args, results);
57 
58     println!("Calling that function trapped.");
59     assert!(ok.is_err());
60     let err = ok.unwrap_err();
61     assert!(err.is::<Trap>());
62 
63     println!("Extract the captured core dump.");
64     let dump = err
65         .downcast_ref::<WasmCoreDump>()
66         .expect("should have an attached core dump, since we configured core dumps on");
67 
68     println!(
69         "Number of memories in the core dump: {}",
70         dump.memories().len()
71     );
72     for (i, mem) in dump.memories().iter().enumerate() {
73         if let Some(addr) = mem.data(&store).iter().position(|byte| *byte != 0) {
74             let val = mem.data(&store)[addr];
75             println!("  First nonzero byte for memory {i}: {val} @ {addr:#x}");
76         } else {
77             println!("  Memory {i} is all zeroes.");
78         }
79     }
80 
81     println!(
82         "Number of globals in the core dump: {}",
83         dump.globals().len()
84     );
85     for (i, global) in dump.globals().iter().enumerate() {
86         let val = global.get(&mut store);
87         println!("  Global {i} = {val:?}");
88     }
89 
90     println!("Serialize the core dump and write it to ./example.coredump");
91     let serialized = dump.serialize(&mut store, "trapper.wasm");
92     std::fs::write("./example.coredump", serialized)?;
93 
94     Ok(())
95 }
96