Skip to content

Commit 58ad911

Browse files
authored
Update how traps are rendered (bytecodealliance#10523)
* Add 2 more columns to the default address width. * Print newlines between inline symbols which accidentally weren't present.
1 parent 6f6e641 commit 58ad911

File tree

3 files changed

+66
-85
lines changed

3 files changed

+66
-85
lines changed

crates/wasmtime/src/runtime/trap.rs

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -362,7 +362,7 @@ impl fmt::Display for WasmBacktrace {
362362
write!(f, " {i:>3}: ")?;
363363

364364
if let Some(offset) = frame.module_offset() {
365-
write!(f, "{offset:#6x} - ")?;
365+
write!(f, "{offset:#8x} - ")?;
366366
}
367367

368368
let write_raw_func_name = |f: &mut fmt::Formatter<'_>| {
@@ -374,7 +374,12 @@ impl fmt::Display for WasmBacktrace {
374374
} else {
375375
for (i, symbol) in frame.symbols().iter().enumerate() {
376376
if i > 0 {
377-
write!(f, " - ")?;
377+
if needs_newline {
378+
writeln!(f, "")?;
379+
} else {
380+
needs_newline = true;
381+
}
382+
write!(f, " - ")?;
378383
} else {
379384
// ...
380385
}
@@ -397,7 +402,11 @@ impl fmt::Display for WasmBacktrace {
397402
}
398403
}
399404
if self.hint_wasm_backtrace_details_env {
400-
write!(f, "\nnote: using the `WASMTIME_BACKTRACE_DETAILS=1` environment variable may show more debugging information")?;
405+
write!(
406+
f,
407+
"\nnote: using the `WASMTIME_BACKTRACE_DETAILS=1` \
408+
environment variable may show more debugging information"
409+
)?;
401410
}
402411
Ok(())
403412
}

tests/all/main.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,6 @@ impl ErrorExt for anyhow::Error {
129129
return;
130130
}
131131

132-
panic!("failed to find {msg:?} within error message {self:?}")
132+
panic!("failed to find:\n{msg}\n\nwithin error message:\n{self:?}")
133133
}
134134
}

tests/all/traps.rs

Lines changed: 53 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#![cfg(not(miri))]
22

3+
use crate::ErrorExt;
34
use anyhow::bail;
45
use std::panic::{self, AssertUnwindSafe};
56
use std::process::Command;
@@ -25,7 +26,7 @@ fn test_trap_return() -> Result<()> {
2526
let run_func = instance.get_typed_func::<(), ()>(&mut store, "run")?;
2627

2728
let e = run_func.call(&mut store, ()).unwrap_err();
28-
assert!(format!("{e:?}").contains("test 123"));
29+
e.assert_contains("test 123");
2930

3031
assert!(
3132
e.downcast_ref::<WasmBacktrace>().is_some(),
@@ -55,8 +56,7 @@ fn test_anyhow_error_return() -> Result<()> {
5556
let run_func = instance.get_typed_func::<(), ()>(&mut store, "run")?;
5657

5758
let e = run_func.call(&mut store, ()).unwrap_err();
58-
assert!(!e.to_string().contains("test 1234"));
59-
assert!(format!("{e:?}").contains("Caused by:\n test 1234"));
59+
e.assert_contains("test 1234");
6060

6161
assert!(e.downcast_ref::<Trap>().is_none());
6262
assert!(e.downcast_ref::<WasmBacktrace>().is_some());
@@ -96,11 +96,9 @@ fn test_trap_return_downcast() -> Result<()> {
9696
.call(&mut store, ())
9797
.err()
9898
.expect("error calling function");
99-
let dbg = format!("{e:?}");
100-
println!("{dbg}");
10199

102100
assert!(!e.to_string().contains("my trap"));
103-
assert!(dbg.contains("Caused by:\n my trap"));
101+
e.assert_contains("my trap");
104102

105103
e.downcast_ref::<MyTrap>()
106104
.expect("error downcasts to MyTrap");
@@ -259,7 +257,7 @@ fn test_trap_trace_cb() -> Result<()> {
259257
assert_eq!(trace[0].func_index(), 2);
260258
assert_eq!(trace[1].module().name().unwrap(), "hello_mod");
261259
assert_eq!(trace[1].func_index(), 1);
262-
assert!(format!("{e:?}").contains("cb throw"));
260+
e.assert_contains("cb throw");
263261

264262
Ok(())
265263
}
@@ -308,19 +306,16 @@ fn trap_display_pretty() -> Result<()> {
308306
let run_func = instance.get_typed_func::<(), ()>(&mut store, "bar")?;
309307

310308
let e = run_func.call(&mut store, ()).unwrap_err();
311-
let e = format!("{e:?}");
312-
assert!(e.contains(
309+
e.assert_contains(
313310
"\
314311
error while executing at wasm backtrace:
315-
0: 0x23 - m!die
316-
1: 0x27 - m!<wasm function 1>
317-
2: 0x2c - m!foo
318-
3: 0x31 - m!<wasm function 3>
319-
320-
Caused by:
321-
wasm trap: wasm `unreachable` instruction executed\
322-
"
323-
));
312+
0: 0x23 - m!die
313+
1: 0x27 - m!<wasm function 1>
314+
2: 0x2c - m!foo
315+
3: 0x31 - m!<wasm function 3>",
316+
);
317+
318+
e.assert_contains("wasm trap: wasm `unreachable` instruction executed");
324319
Ok(())
325320
}
326321

@@ -352,21 +347,17 @@ fn trap_display_multi_module() -> Result<()> {
352347
let bar2 = instance.get_typed_func::<(), ()>(&mut store, "bar2")?;
353348

354349
let e = bar2.call(&mut store, ()).unwrap_err();
355-
let e = format!("{e:?}");
356-
assert!(e.contains(
350+
e.assert_contains(
357351
"\
358352
error while executing at wasm backtrace:
359-
0: 0x23 - a!die
360-
1: 0x27 - a!<wasm function 1>
361-
2: 0x2c - a!foo
362-
3: 0x31 - a!<wasm function 3>
363-
4: 0x29 - b!middle
364-
5: 0x2e - b!<wasm function 2>
365-
366-
Caused by:
367-
wasm trap: wasm `unreachable` instruction executed\
368-
"
369-
));
353+
0: 0x23 - a!die
354+
1: 0x27 - a!<wasm function 1>
355+
2: 0x2c - a!foo
356+
3: 0x31 - a!<wasm function 3>
357+
4: 0x29 - b!middle
358+
5: 0x2e - b!<wasm function 2>",
359+
);
360+
e.assert_contains("wasm trap: wasm `unreachable` instruction executed");
370361
Ok(())
371362
}
372363

@@ -386,7 +377,7 @@ fn trap_start_function_import() -> Result<()> {
386377
let sig = FuncType::new(store.engine(), None, None);
387378
let func = Func::new(&mut store, sig, |_, _, _| bail!("user trap"));
388379
let err = Instance::new(&mut store, &module, &[func.into()]).unwrap_err();
389-
assert!(format!("{err:?}").contains("user trap"));
380+
err.assert_contains("user trap");
390381
Ok(())
391382
}
392383

@@ -533,9 +524,8 @@ fn mismatched_arguments() -> Result<()> {
533524
"expected 1 arguments, got 0"
534525
);
535526
let e = func.call(&mut store, &[Val::F32(0)], &mut []).unwrap_err();
536-
let e = format!("{e:?}");
537-
assert!(e.contains("argument type mismatch"));
538-
assert!(e.contains("expected i32, found f32"));
527+
e.assert_contains("argument type mismatch");
528+
e.assert_contains("expected i32, found f32");
539529
assert_eq!(
540530
func.call(&mut store, &[Val::I32(0), Val::I32(1)], &mut [])
541531
.unwrap_err()
@@ -564,14 +554,9 @@ fn call_signature_mismatch() -> Result<()> {
564554
)?;
565555

566556
let module = Module::new(store.engine(), &binary)?;
567-
let err = Instance::new(&mut store, &module, &[])
568-
.err()
569-
.unwrap()
570-
.downcast::<Trap>()
571-
.unwrap();
572-
assert!(err
573-
.to_string()
574-
.contains("wasm trap: indirect call type mismatch"));
557+
let err = Instance::new(&mut store, &module, &[]).err().unwrap();
558+
err.downcast_ref::<Trap>().unwrap();
559+
err.assert_contains("wasm trap: indirect call type mismatch");
575560
Ok(())
576561
}
577562

@@ -591,21 +576,19 @@ fn start_trap_pretty() -> Result<()> {
591576
let module = Module::new(store.engine(), wat)?;
592577
let e = match Instance::new(&mut store, &module, &[]) {
593578
Ok(_) => panic!("expected failure"),
594-
Err(e) => format!("{e:?}"),
579+
Err(e) => e,
595580
};
596581

597-
assert!(e.contains(
582+
e.assert_contains(
598583
"\
599584
error while executing at wasm backtrace:
600-
0: 0x1d - m!die
601-
1: 0x21 - m!<wasm function 1>
602-
2: 0x26 - m!foo
603-
3: 0x2b - m!start
604-
605-
Caused by:
606-
wasm trap: wasm `unreachable` instruction executed\
607-
"
608-
));
585+
0: 0x1d - m!die
586+
1: 0x21 - m!<wasm function 1>
587+
2: 0x26 - m!foo
588+
3: 0x2b - m!start",
589+
);
590+
591+
e.assert_contains("wasm trap: wasm `unreachable` instruction executed");
609592
Ok(())
610593
}
611594

@@ -793,17 +776,14 @@ fn no_hint_even_with_dwarf_info() -> Result<()> {
793776
"#,
794777
)?;
795778
let trap = Instance::new(&mut store, &module, &[]).unwrap_err();
796-
let trap = format!("{trap:?}");
797-
assert!(trap.contains(
779+
trap.assert_contains(
798780
"\
799781
error while executing at wasm backtrace:
800-
0: 0x1a - <unknown>!start
782+
0: 0x1a - <unknown>!start",
783+
);
801784

802-
Caused by:
803-
wasm trap: wasm `unreachable` instruction executed\
804-
"
805-
));
806-
assert!(!trap.contains("WASM_BACKTRACE_DETAILS"));
785+
trap.assert_contains("wasm trap: wasm `unreachable` instruction executed");
786+
assert!(!format!("{trap:?}").contains("WASM_BACKTRACE_DETAILS"));
807787
Ok(())
808788
}
809789

@@ -827,16 +807,12 @@ fn hint_with_dwarf_info() -> Result<()> {
827807
"#,
828808
)?;
829809
let trap = Instance::new(&mut store, &module, &[]).unwrap_err();
830-
let trap = format!("{trap:?}");
831-
assert!(trap.contains(
810+
trap.assert_contains(
832811
"\
833812
error while executing at wasm backtrace:
834-
0: 0x1a - <unknown>!start
835-
note: using the `WASMTIME_BACKTRACE_DETAILS=1` environment variable may show more debugging information
836-
837-
Caused by:
838-
wasm trap: wasm `unreachable` instruction executed"
839-
));
813+
0: 0x1a - <unknown>!start
814+
note: using the `WASMTIME_BACKTRACE_DETAILS=1` environment variable may show more debugging information");
815+
trap.assert_contains("wasm trap: wasm `unreachable` instruction executed");
840816
Ok(())
841817
}
842818

@@ -936,10 +912,7 @@ fn catch_trap_calling_across_stores() -> Result<()> {
936912
.expect("trap function should be exported");
937913

938914
let trap = func.call(&mut data.child_store, ()).unwrap_err();
939-
assert!(
940-
format!("{trap:?}").contains("unreachable"),
941-
"trap should contain 'unreachable', got: {trap:?}"
942-
);
915+
trap.assert_contains("unreachable");
943916

944917
let trace = trap.downcast_ref::<WasmBacktrace>().unwrap().frames();
945918

@@ -1394,8 +1367,7 @@ fn wasm_fault_address_reported_from_mpk_protected_memory() -> Result<()> {
13941367
// We expect an error here, not an abort; but we also check that the store
13951368
// can now calculate the correct Wasm address. If this test is failing with
13961369
// an abort, use `--nocapture` to see more details.
1397-
let err = format!("{err:?}");
1398-
assert!(err.contains("0xdeadbeef"), "bad error: {err}");
1370+
err.assert_contains("0xdeadbeef");
13991371
Ok(())
14001372
}
14011373

@@ -1547,7 +1519,7 @@ fn dont_see_stale_stack_walking_registers() -> Result<()> {
15471519
let get_trap = instance.get_func(&mut store, "get_trap").unwrap();
15481520

15491521
let err = get_trap.call(&mut store, &[], &mut []).unwrap_err();
1550-
assert!(err.to_string().contains("trap!!!"));
1522+
err.assert_contains("trap!!!");
15511523

15521524
Ok(())
15531525
}
@@ -1707,7 +1679,7 @@ fn tail_call_to_imported_function(config: &mut Config) -> Result<()> {
17071679

17081680
let run = instance.get_typed_func::<(), i32>(&mut store, "run")?;
17091681
let err = run.call(&mut store, ()).unwrap_err();
1710-
assert!(err.to_string().contains("whoopsie"));
1682+
err.assert_contains("whoopsie");
17111683

17121684
Ok(())
17131685
}
@@ -1734,7 +1706,7 @@ fn tail_call_to_imported_function_in_start_function(config: &mut Config) -> Resu
17341706
let mut store = Store::new(&engine, ());
17351707
let host_func = Func::wrap(&mut store, || -> Result<()> { bail!("whoopsie") });
17361708
let err = Instance::new(&mut store, &module, &[host_func.into()]).unwrap_err();
1737-
assert!(err.to_string().contains("whoopsie"));
1709+
err.assert_contains("whoopsie");
17381710

17391711
Ok(())
17401712
}
@@ -1761,7 +1733,7 @@ fn return_call_ref_to_imported_function(config: &mut Config) -> Result<()> {
17611733

17621734
let run = instance.get_typed_func::<Func, i32>(&mut store, "run")?;
17631735
let err = run.call(&mut store, host_func).unwrap_err();
1764-
assert!(err.to_string().contains("whoopsie"));
1736+
err.assert_contains("whoopsie");
17651737

17661738
Ok(())
17671739
}
@@ -1789,7 +1761,7 @@ fn return_call_indirect_to_imported_function(config: &mut Config) -> Result<()>
17891761

17901762
let run = instance.get_typed_func::<(), i32>(&mut store, "run")?;
17911763
let err = run.call(&mut store, ()).unwrap_err();
1792-
assert!(err.to_string().contains("whoopsie"));
1764+
err.assert_contains("whoopsie");
17931765

17941766
Ok(())
17951767
}

0 commit comments

Comments
 (0)