Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bytecodealliance
GitHub Repository: bytecodealliance/wasmtime
Path: blob/main/tests/all/coredump.rs
3079 views
1
use wasmtime::bail;
2
use wasmtime::*;
3
4
#[test]
5
#[cfg_attr(miri, ignore)]
6
fn coredump_attached_to_error() -> Result<()> {
7
let mut config = Config::default();
8
config.coredump_on_trap(true);
9
let engine = Engine::new(&config).unwrap();
10
let mut store = Store::<()>::new(&engine, ());
11
12
let wat = r#"
13
(module
14
(func $hello (import "" "hello"))
15
(func (export "run") (call $hello))
16
)
17
"#;
18
19
let module = Module::new(store.engine(), wat)?;
20
let hello_type = FuncType::new(store.engine(), None, None);
21
let hello_func = Func::new(&mut store, hello_type, |_, _, _| bail!("test 123"));
22
23
let instance = Instance::new(&mut store, &module, &[hello_func.into()])?;
24
let run_func = instance.get_typed_func::<(), ()>(&mut store, "run")?;
25
26
let e = run_func.call(&mut store, ()).unwrap_err();
27
assert!(format!("{e:?}").contains("test 123"));
28
29
assert!(
30
e.downcast_ref::<WasmCoreDump>().is_some(),
31
"error should contain a WasmCoreDump"
32
);
33
34
Ok(())
35
}
36
37
#[test]
38
#[cfg_attr(miri, ignore)]
39
fn coredump_has_stack() -> Result<()> {
40
let _ = env_logger::try_init();
41
let mut config = Config::default();
42
config.coredump_on_trap(true);
43
let engine = Engine::new(&config).unwrap();
44
let mut store = Store::<()>::new(&engine, ());
45
46
let wat = r#"
47
(module
48
(func $a (export "a")
49
call $b
50
)
51
(func $b
52
call $c
53
)
54
(func $c
55
unreachable
56
)
57
)
58
"#;
59
60
let module = Module::new(store.engine(), wat)?;
61
let instance = Instance::new(&mut store, &module, &[])?;
62
let a_func = instance.get_typed_func::<(), ()>(&mut store, "a")?;
63
64
let e = a_func.call(&mut store, ()).unwrap_err();
65
let cd = e.downcast_ref::<WasmCoreDump>().unwrap();
66
assert_eq!(cd.frames().len(), 3);
67
assert_eq!(cd.frames()[0].func_name().unwrap(), "c");
68
assert_eq!(cd.frames()[1].func_name().unwrap(), "b");
69
assert_eq!(cd.frames()[2].func_name().unwrap(), "a");
70
let _ = cd.serialize(&mut store, "stack");
71
Ok(())
72
}
73
74
#[test]
75
#[cfg_attr(miri, ignore)]
76
fn coredump_has_modules_and_instances() -> Result<()> {
77
let mut config = Config::default();
78
config.coredump_on_trap(true);
79
let engine = Engine::new(&config).unwrap();
80
let mut linker = Linker::new(&engine);
81
let mut store = Store::<()>::new(&engine, ());
82
83
let wat1 = r#"
84
(module $foo
85
(import "bar" "b" (func $b))
86
(func (export "a")
87
call $b
88
)
89
)
90
"#;
91
let wat2 = r#"
92
(module $bar
93
(func (export "b")
94
unreachable
95
)
96
)
97
"#;
98
let module1 = Module::new(store.engine(), wat1)?;
99
let module2 = Module::new(store.engine(), wat2)?;
100
let linking2 = linker.instantiate(&mut store, &module2)?;
101
linker.instance(&mut store, "bar", linking2)?;
102
103
let linking1 = linker.instantiate(&mut store, &module1)?;
104
let a_func = linking1.get_typed_func::<(), ()>(&mut store, "a")?;
105
106
let e = a_func.call(&mut store, ()).unwrap_err();
107
let cd = e.downcast_ref::<WasmCoreDump>().unwrap();
108
assert_eq!(cd.modules().len(), 2);
109
assert_eq!(cd.instances().len(), 2);
110
let _ = cd.serialize(&mut store, "modules-and-instances");
111
Ok(())
112
}
113
114
#[test]
115
#[cfg_attr(miri, ignore)]
116
fn coredump_has_host_globals_and_memory() -> Result<()> {
117
let mut config = Config::default();
118
config.coredump_on_trap(true);
119
let engine = Engine::new(&config).unwrap();
120
121
let module = Module::new(
122
&engine,
123
r#"
124
(module
125
(import "memory" "memory" (memory 1))
126
(global $myglobal (import "global" "global") (mut i32))
127
(func (export "a") (result i32)
128
unreachable
129
)
130
(export "memory" (memory 0))
131
(export "global" (global 0))
132
)
133
"#,
134
)?;
135
136
let mut store = Store::<()>::new(&engine, ());
137
let mut linker = Linker::new(&engine);
138
139
let memory = Memory::new(&mut store, MemoryType::new(1, None))?;
140
linker.define(&mut store, "memory", "memory", memory)?;
141
142
let global = Global::new(
143
&mut store,
144
GlobalType::new(ValType::I32, Mutability::Var),
145
Val::I32(0),
146
)?;
147
linker.define(&mut store, "global", "global", global)?;
148
149
let instance = linker.instantiate(&mut store, &module)?;
150
151
// Each time we extract the exports, it puts them in the `StoreData`. Our
152
// core dumps need to be robust to duplicate entries in the `StoreData`.
153
for _ in 0..10 {
154
let _ = instance.get_global(&mut store, "global").unwrap();
155
let _ = instance.get_memory(&mut store, "memory").unwrap();
156
}
157
158
let a_func = instance.get_typed_func::<(), i32>(&mut store, "a")?;
159
let err = a_func.call(&mut store, ()).unwrap_err();
160
let core_dump = err.downcast_ref::<WasmCoreDump>().unwrap();
161
assert_eq!(core_dump.globals().len(), 1);
162
assert_eq!(core_dump.memories().len(), 1);
163
assert_eq!(core_dump.instances().len(), 1);
164
let _ = core_dump.serialize(&mut store, "host-globals-and-memory");
165
166
Ok(())
167
}
168
169
#[test]
170
#[cfg_attr(miri, ignore)]
171
fn coredump_has_defined_globals_and_memory() -> Result<()> {
172
let mut config = Config::default();
173
config.coredump_on_trap(true);
174
let engine = Engine::new(&config).unwrap();
175
176
let module = Module::new(
177
&engine,
178
r#"
179
(module
180
(global (mut i32) (i32.const 42))
181
(memory 1)
182
(func (export "a")
183
unreachable
184
)
185
)
186
"#,
187
)?;
188
189
let mut store = Store::<()>::new(&engine, ());
190
let instance = Instance::new(&mut store, &module, &[])?;
191
192
let a_func = instance.get_typed_func::<(), ()>(&mut store, "a")?;
193
let err = a_func.call(&mut store, ()).unwrap_err();
194
let core_dump = err.downcast_ref::<WasmCoreDump>().unwrap();
195
assert_eq!(core_dump.globals().len(), 1);
196
assert_eq!(core_dump.memories().len(), 1);
197
assert_eq!(core_dump.instances().len(), 1);
198
let _ = core_dump.serialize(&mut store, "defined-globals-and-memory");
199
200
Ok(())
201
}
202
203
#[test]
204
#[cfg_attr(miri, ignore)]
205
fn multiple_globals_memories_and_instances() -> Result<()> {
206
let mut config = Config::default();
207
config.wasm_multi_memory(true);
208
config.coredump_on_trap(true);
209
let engine = Engine::new(&config).unwrap();
210
let mut store = Store::<()>::new(&engine, ());
211
let mut linker = Linker::new(&engine);
212
213
let memory = Memory::new(&mut store, MemoryType::new(1, None))?;
214
linker.define(&mut store, "host", "memory", memory)?;
215
216
let global = Global::new(
217
&mut store,
218
GlobalType::new(ValType::I32, Mutability::Var),
219
Val::I32(0),
220
)?;
221
linker.define(&mut store, "host", "global", global)?;
222
223
let module_a = Module::new(
224
&engine,
225
r#"
226
(module
227
(memory (export "memory") 1)
228
(global (export "global") (mut i32) (i32.const 0))
229
)
230
"#,
231
)?;
232
let instance_a = linker.instantiate(&mut store, &module_a)?;
233
linker.instance(&mut store, "a", instance_a)?;
234
235
let module_b = Module::new(
236
&engine,
237
r#"
238
(module
239
(import "host" "memory" (memory 1))
240
(import "host" "global" (global (mut i32)))
241
(import "a" "memory" (memory 1))
242
(import "a" "global" (global (mut i32)))
243
244
(func (export "trap")
245
unreachable
246
)
247
)
248
"#,
249
)?;
250
let instance_b = linker.instantiate(&mut store, &module_b)?;
251
252
let trap_func = instance_b.get_typed_func::<(), ()>(&mut store, "trap")?;
253
let err = trap_func.call(&mut store, ()).unwrap_err();
254
let core_dump = err.downcast_ref::<WasmCoreDump>().unwrap();
255
assert_eq!(core_dump.globals().len(), 2);
256
assert_eq!(core_dump.memories().len(), 2);
257
assert_eq!(core_dump.instances().len(), 2);
258
let _ = core_dump.serialize(&mut store, "multi");
259
260
Ok(())
261
}
262
263
#[test]
264
#[cfg_attr(miri, ignore)]
265
fn core_dump_with_shared_memory() -> Result<()> {
266
if super::threads::engine().is_none() {
267
return Ok(());
268
}
269
let mut config = Config::new();
270
config.coredump_on_trap(true);
271
config.shared_memory(true);
272
let engine = Engine::new(&config)?;
273
let mut store = Store::new(&engine, ());
274
let wat = r#"(module
275
(memory 1 1 shared)
276
(func (export "foo") unreachable)
277
(data (i32.const 0) "a")
278
)"#;
279
let module = Module::new(&engine, wat)?;
280
let instance = Instance::new(&mut store, &module, &[])?;
281
let foo = instance.get_typed_func::<(), ()>(&mut store, "foo")?;
282
let err = foo.call(&mut store, ()).unwrap_err();
283
let coredump = err.downcast_ref::<WasmCoreDump>().unwrap();
284
assert!(coredump.memories().is_empty());
285
286
let bytes = coredump.serialize(&mut store, "howdy");
287
for payload in wasmparser::Parser::new(0).parse_all(&bytes) {
288
let payload = payload?;
289
if let wasmparser::Payload::DataSection(s) = payload {
290
assert_eq!(s.count(), 0);
291
}
292
}
293
294
Ok(())
295
}
296
297