Skip to content

Commit 4834727

Browse files
authored
Debugging: add debug-tags to instrumented trap sites so we actually get PCs on traps. (#12802)
This was not exposed earlier by (i) lack of handling of trap events in the initial version of the gdbstub component in #12771, and (ii) lack of asserting some value for the PC on the top frame in the debug-event test for traps. We got the PC for the last opcode in the function body previously because, with no debug tags on the trapping path that calls raise() (sunk to the bottom of the machine code body as cold code), we scanned backward for the last tag metadata and found that instead. Adding metadata according to the current source location when emitting traps fixes this for all trapping events.
1 parent 97361cc commit 4834727

File tree

5 files changed

+22
-5
lines changed

5 files changed

+22
-5
lines changed

crates/cranelift/src/func_environ.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1391,6 +1391,10 @@ impl TranslateTrap for FuncEnvironment<'_> {
13911391
) -> ir::FuncRef {
13921392
self.builtin_functions.load_builtin(builder.func, index)
13931393
}
1394+
1395+
fn debug_tags(&self, srcloc: ir::SourceLoc) -> Vec<ir::DebugTag> {
1396+
FuncEnvironment::debug_tags(self, srcloc)
1397+
}
13941398
}
13951399

13961400
#[derive(Default)]

crates/cranelift/src/trap.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ pub trait TranslateTrap {
2020
builder: &mut FunctionBuilder<'_>,
2121
index: BuiltinFunctionIndex,
2222
) -> ir::FuncRef;
23+
fn debug_tags(&self, _srcloc: ir::SourceLoc) -> Vec<ir::DebugTag> {
24+
vec![]
25+
}
2326

2427
fn trap(&mut self, builder: &mut FunctionBuilder, trap: ir::TrapCode) {
2528
match (
@@ -36,12 +39,14 @@ pub trait TranslateTrap {
3639
// pass in our trap code. Leave a debug `unreachable` in place
3740
// afterwards as a defense-in-depth measure.
3841
(false, Some(trap)) => {
42+
let debug_tags = self.debug_tags(builder.srcloc());
3943
let trap_libcall = self.builtin_funcref(builder, BuiltinFunctionIndex::trap());
4044
let vmctx = self.vmctx_val(&mut builder.cursor());
4145
let trap_code = builder.ins().iconst(I8, i64::from(trap as u8));
4246
builder.ins().call(trap_libcall, &[vmctx, trap_code]);
4347
let raise_libcall = self.builtin_funcref(builder, BuiltinFunctionIndex::raise());
44-
builder.ins().call(raise_libcall, &[vmctx]);
48+
let inst = builder.ins().call(raise_libcall, &[vmctx]);
49+
builder.func.debug_tags.set(inst, debug_tags);
4550
builder.ins().trap(TRAP_INTERNAL_ASSERT);
4651
}
4752
}

tests/all/debug.rs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -694,18 +694,23 @@ async fn hostcall_trap_events() -> wasmtime::Result<()> {
694694
},
695695
r#"
696696
(module
697-
(func (export "main")
697+
(func (export "main") (result i32)
698698
i32.const 0
699699
i32.const 0
700700
i32.div_u
701-
drop))
701+
drop
702+
i32.const 42))
702703
"#,
703704
)?;
704705

705706
debug_event_checker!(
706707
D, store,
707708
{ 0 ;
708-
wasmtime::DebugEvent::Trap(wasmtime_environ::Trap::IntegerDivisionByZero) => {}
709+
wasmtime::DebugEvent::Trap(wasmtime_environ::Trap::IntegerDivisionByZero) => {
710+
let frame = store.debug_exit_frames().next().unwrap();
711+
let (_func, pc) = frame.wasm_function_index_and_pc(&mut store).unwrap().unwrap();
712+
assert_eq!(pc, 0x26);
713+
}
709714
}
710715
);
711716

@@ -714,7 +719,7 @@ async fn hostcall_trap_events() -> wasmtime::Result<()> {
714719

715720
let instance = Instance::new_async(&mut store, &module, &[]).await?;
716721
let func = instance.get_func(&mut store, "main").unwrap();
717-
let mut results = [];
722+
let mut results = [Val::I32(0)];
718723
let result = func.call_async(&mut store, &[], &mut results).await;
719724
assert!(result.is_err()); // Uncaught trap.
720725
assert_eq!(counter.load(Ordering::Relaxed), 1);

tests/disas/debug-exceptions.wat

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@
8989
;; bl #0x3dc
9090
;; ec: ldur x2, [sp, #0x10]
9191
;; bl #0x414
92+
;; ╰─╼ debug frame state (after previous inst): func key DefinedWasmFunction(StaticModuleIndex(0), DefinedFuncIndex(0)), wasm PC 66, slot at FP-0xc0, locals , stack I32 @ slot+0x8
9293
;; f4: .byte 0x1f, 0xc1, 0x00, 0x00
9394
;; mov x2, x0
9495
;; mov w3, w2
@@ -141,6 +142,7 @@
141142
;; 19c: bl #0x3dc
142143
;; 1a0: ldur x2, [sp, #0x10]
143144
;; 1a4: bl #0x414
145+
;; ╰─╼ debug frame state (after previous inst): func key DefinedWasmFunction(StaticModuleIndex(0), DefinedFuncIndex(0)), wasm PC 52, slot at FP-0xc0, locals , stack
144146
;; 1a8: .byte 0x1f, 0xc1, 0x00, 0x00
145147
;; 1ac: .byte 0x1f, 0xc1, 0x00, 0x00
146148
;; 1b0: .byte 0x1f, 0xc1, 0x00, 0x00

tests/disas/debug.wat

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
;; 67: callq 0x18c
4949
;; 6c: movq %r12, %rdi
5050
;; 6f: callq 0x1bd
51+
;; ╰─╼ debug frame state (after previous inst): func key DefinedWasmFunction(StaticModuleIndex(0), DefinedFuncIndex(0)), wasm PC 35, slot at FP-0x30, locals I32 @ slot+0x8, I32 @ slot+0xc, stack
5152
;; 74: ud2
5253
;;
5354
;; wasm[0]::array_to_wasm_trampoline[0]:

0 commit comments

Comments
 (0)