22//! signalhandling mechanisms.
33
44mod backtrace;
5+ mod coredump;
56
67use crate :: { Instance , VMContext , VMRuntimeLimits } ;
78use anyhow:: Error ;
@@ -12,6 +13,7 @@ use std::ptr;
1213use std:: sync:: Once ;
1314
1415pub use self :: backtrace:: { Backtrace , Frame } ;
16+ pub use self :: coredump:: CoreDumpStack ;
1517pub use self :: tls:: { tls_eager_initialize, AsyncWasmCallState , PreviousAsyncWasmCallState } ;
1618
1719cfg_if:: cfg_if! {
@@ -172,6 +174,8 @@ pub struct Trap {
172174 pub reason : TrapReason ,
173175 /// Wasm backtrace of the trap, if any.
174176 pub backtrace : Option < Backtrace > ,
177+ /// The Wasm Coredump, if any.
178+ pub coredumpstack : Option < CoreDumpStack > ,
175179}
176180
177181/// Enumeration of different methods of raising a trap.
@@ -251,6 +255,7 @@ impl From<wasmtime_environ::Trap> for TrapReason {
251255pub unsafe fn catch_traps < ' a , F > (
252256 signal_handler : Option < * const SignalHandler < ' static > > ,
253257 capture_backtrace : bool ,
258+ capture_coredump : bool ,
254259 caller : * mut VMContext ,
255260 mut closure : F ,
256261) -> Result < ( ) , Box < Trap > >
@@ -259,19 +264,24 @@ where
259264{
260265 let limits = Instance :: from_vmctx ( caller, |i| i. runtime_limits ( ) ) ;
261266
262- let result = CallThreadState :: new ( signal_handler, capture_backtrace, * limits) . with ( |cx| {
263- wasmtime_setjmp (
264- cx. jmp_buf . as_ptr ( ) ,
265- call_closure :: < F > ,
266- & mut closure as * mut F as * mut u8 ,
267- caller,
268- )
269- } ) ;
267+ let result = CallThreadState :: new ( signal_handler, capture_backtrace, capture_coredump, * limits)
268+ . with ( |cx| {
269+ wasmtime_setjmp (
270+ cx. jmp_buf . as_ptr ( ) ,
271+ call_closure :: < F > ,
272+ & mut closure as * mut F as * mut u8 ,
273+ caller,
274+ )
275+ } ) ;
270276
271277 return match result {
272278 Ok ( x) => Ok ( x) ,
273- Err ( ( UnwindReason :: Trap ( reason) , backtrace) ) => Err ( Box :: new ( Trap { reason, backtrace } ) ) ,
274- Err ( ( UnwindReason :: Panic ( panic) , _) ) => std:: panic:: resume_unwind ( panic) ,
279+ Err ( ( UnwindReason :: Trap ( reason) , backtrace, coredumpstack) ) => Err ( Box :: new ( Trap {
280+ reason,
281+ backtrace,
282+ coredumpstack,
283+ } ) ) ,
284+ Err ( ( UnwindReason :: Panic ( panic) , _, _) ) => std:: panic:: resume_unwind ( panic) ,
275285 } ;
276286
277287 extern "C" fn call_closure < F > ( payload : * mut u8 , caller : * mut VMContext )
@@ -290,10 +300,12 @@ mod call_thread_state {
290300 /// Temporary state stored on the stack which is registered in the `tls` module
291301 /// below for calls into wasm.
292302 pub struct CallThreadState {
293- pub ( super ) unwind : UnsafeCell < MaybeUninit < ( UnwindReason , Option < Backtrace > ) > > ,
303+ pub ( super ) unwind :
304+ UnsafeCell < MaybeUninit < ( UnwindReason , Option < Backtrace > , Option < CoreDumpStack > ) > > ,
294305 pub ( super ) jmp_buf : Cell < * const u8 > ,
295306 pub ( super ) signal_handler : Option < * const SignalHandler < ' static > > ,
296307 pub ( super ) capture_backtrace : bool ,
308+ pub ( super ) capture_coredump : bool ,
297309
298310 pub ( crate ) limits : * const VMRuntimeLimits ,
299311
@@ -327,13 +339,15 @@ mod call_thread_state {
327339 pub ( super ) fn new (
328340 signal_handler : Option < * const SignalHandler < ' static > > ,
329341 capture_backtrace : bool ,
342+ capture_coredump : bool ,
330343 limits : * const VMRuntimeLimits ,
331344 ) -> CallThreadState {
332345 CallThreadState {
333346 unwind : UnsafeCell :: new ( MaybeUninit :: uninit ( ) ) ,
334347 jmp_buf : Cell :: new ( ptr:: null ( ) ) ,
335348 signal_handler,
336349 capture_backtrace,
350+ capture_coredump,
337351 limits,
338352 prev : Cell :: new ( ptr:: null ( ) ) ,
339353 old_last_wasm_exit_fp : Cell :: new ( unsafe { * ( * limits) . last_wasm_exit_fp . get ( ) } ) ,
@@ -385,7 +399,7 @@ impl CallThreadState {
385399 fn with (
386400 mut self ,
387401 closure : impl FnOnce ( & CallThreadState ) -> i32 ,
388- ) -> Result < ( ) , ( UnwindReason , Option < Backtrace > ) > {
402+ ) -> Result < ( ) , ( UnwindReason , Option < Backtrace > , Option < CoreDumpStack > ) > {
389403 let ret = tls:: set ( & mut self , |me| closure ( me) ) ;
390404 if ret != 0 {
391405 Ok ( ( ) )
@@ -395,12 +409,12 @@ impl CallThreadState {
395409 }
396410
397411 #[ cold]
398- unsafe fn read_unwind ( & self ) -> ( UnwindReason , Option < Backtrace > ) {
412+ unsafe fn read_unwind ( & self ) -> ( UnwindReason , Option < Backtrace > , Option < CoreDumpStack > ) {
399413 ( * self . unwind . get ( ) ) . as_ptr ( ) . read ( )
400414 }
401415
402416 fn unwind_with ( & self , reason : UnwindReason ) -> ! {
403- let backtrace = match reason {
417+ let ( backtrace, coredump ) = match reason {
404418 // Panics don't need backtraces. There is nowhere to attach the
405419 // hypothetical backtrace to and it doesn't really make sense to try
406420 // in the first place since this is a Rust problem rather than a
@@ -412,11 +426,13 @@ impl CallThreadState {
412426 | UnwindReason :: Trap ( TrapReason :: User {
413427 needs_backtrace : false ,
414428 ..
415- } ) => None ,
416- UnwindReason :: Trap ( _) => self . capture_backtrace ( self . limits , None ) ,
429+ } ) => ( None , None ) ,
430+ UnwindReason :: Trap ( _) => ( self . capture_backtrace ( self . limits , None ) , self . capture_coredump ( self . limits , None ) ) ,
417431 } ;
418432 unsafe {
419- ( * self . unwind . get ( ) ) . as_mut_ptr ( ) . write ( ( reason, backtrace) ) ;
433+ ( * self . unwind . get ( ) )
434+ . as_mut_ptr ( )
435+ . write ( ( reason, backtrace, coredump) ) ;
420436 wasmtime_longjmp ( self . jmp_buf . get ( ) ) ;
421437 }
422438 }
@@ -468,13 +484,15 @@ impl CallThreadState {
468484
469485 fn set_jit_trap ( & self , pc : * const u8 , fp : usize , faulting_addr : Option < usize > ) {
470486 let backtrace = self . capture_backtrace ( self . limits , Some ( ( pc as usize , fp) ) ) ;
487+ let coredump = self . capture_coredump ( self . limits , Some ( ( pc as usize , fp) ) ) ;
471488 unsafe {
472489 ( * self . unwind . get ( ) ) . as_mut_ptr ( ) . write ( (
473490 UnwindReason :: Trap ( TrapReason :: Jit {
474491 pc : pc as usize ,
475492 faulting_addr,
476493 } ) ,
477494 backtrace,
495+ coredump,
478496 ) ) ;
479497 }
480498 }
@@ -491,6 +509,17 @@ impl CallThreadState {
491509 Some ( unsafe { Backtrace :: new_with_trap_state ( limits, self , trap_pc_and_fp) } )
492510 }
493511
512+ fn capture_coredump (
513+ & self ,
514+ limits : * const VMRuntimeLimits ,
515+ trap_pc_and_fp : Option < ( usize , usize ) > ,
516+ ) -> Option < CoreDumpStack > {
517+ if !self . capture_coredump {
518+ return None ;
519+ }
520+ Some ( CoreDumpStack :: new ( & self , limits, trap_pc_and_fp) )
521+ }
522+
494523 pub ( crate ) fn iter < ' a > ( & ' a self ) -> impl Iterator < Item = & Self > + ' a {
495524 let mut state = Some ( self ) ;
496525 std:: iter:: from_fn ( move || {
0 commit comments