@@ -45,7 +45,7 @@ pub enum EmitterError {
4545unsafe fn emit_backtrace_by_frames (
4646 w : & mut impl Write ,
4747 resolve_frames : StacktraceCollection ,
48- fault_rsp : usize ,
48+ fault_ip : usize ,
4949) -> Result < ( ) , EmitterError > {
5050 // https://docs.rs/backtrace/latest/backtrace/index.html
5151 writeln ! ( w, "{DD_CRASHTRACK_BEGIN_STACKTRACE}" ) ?;
@@ -61,57 +61,68 @@ unsafe fn emit_backtrace_by_frames(
6161 Ok ( ( ) )
6262 }
6363
64- backtrace:: trace_unsynchronized ( |frame| {
65- // Skip all stack frames whose stack pointer is less than to the determined crash stack
66- // pointer (fault_rsp). These frames belong exclusively to the crash tracker and the
67- // backtrace functionality and are therefore not relevant for troubleshooting.
68- let sp = frame. sp ( ) ;
69- println ! ( "Inside a stack frame. sp was {sp:?}" ) ;
70- if !sp. is_null ( ) && ( sp as usize ) < fault_rsp {
71- return true ;
72- }
73- if resolve_frames == StacktraceCollection :: EnabledWithInprocessSymbols {
74- backtrace:: resolve_frame_unsynchronized ( frame, |symbol| {
75- #[ allow( clippy:: unwrap_used) ]
76- write ! ( w, "{{" ) . unwrap ( ) ;
77- #[ allow( clippy:: unwrap_used) ]
78- emit_absolute_addresses ( w, frame) . unwrap ( ) ;
79- if let Some ( column) = symbol. colno ( ) {
64+ let mut ip_found = false ;
65+ loop {
66+ backtrace:: trace_unsynchronized ( |frame| {
67+ // Skip all stack frames until we encounter the determined crash instruction pointer
68+ // (fault_ip). These initial frames belong exclusively to the crash tracker and the
69+ // backtrace functionality and are therefore not relevant for troubleshooting.
70+ let ip = frame. ip ( ) ;
71+ if ip as usize == fault_ip {
72+ ip_found = true ;
73+ }
74+ if !ip_found {
75+ return true ;
76+ }
77+ if resolve_frames == StacktraceCollection :: EnabledWithInprocessSymbols {
78+ backtrace:: resolve_frame_unsynchronized ( frame, |symbol| {
8079 #[ allow( clippy:: unwrap_used) ]
81- write ! ( w, ", \" column\" : {column}" ) . unwrap ( ) ;
82- }
83- if let Some ( file) = symbol. filename ( ) {
84- // The debug printer for path already wraps it in `"` marks.
80+ write ! ( w, "{{" ) . unwrap ( ) ;
8581 #[ allow( clippy:: unwrap_used) ]
86- write ! ( w, ", \" file\" : {file:?}" ) . unwrap ( ) ;
87- }
88- if let Some ( function) = symbol. name ( ) {
82+ emit_absolute_addresses ( w, frame) . unwrap ( ) ;
83+ if let Some ( column) = symbol. colno ( ) {
84+ #[ allow( clippy:: unwrap_used) ]
85+ write ! ( w, ", \" column\" : {column}" ) . unwrap ( ) ;
86+ }
87+ if let Some ( file) = symbol. filename ( ) {
88+ // The debug printer for path already wraps it in `"` marks.
89+ #[ allow( clippy:: unwrap_used) ]
90+ write ! ( w, ", \" file\" : {file:?}" ) . unwrap ( ) ;
91+ }
92+ if let Some ( function) = symbol. name ( ) {
93+ #[ allow( clippy:: unwrap_used) ]
94+ write ! ( w, ", \" function\" : \" {function}\" " ) . unwrap ( ) ;
95+ }
96+ if let Some ( line) = symbol. lineno ( ) {
97+ #[ allow( clippy:: unwrap_used) ]
98+ write ! ( w, ", \" line\" : {line}" ) . unwrap ( ) ;
99+ }
89100 #[ allow( clippy:: unwrap_used) ]
90- write ! ( w, ", \" function \" : \" {function} \" " ) . unwrap ( ) ;
91- }
92- if let Some ( line ) = symbol . lineno ( ) {
101+ writeln ! ( w, "}} " ) . unwrap ( ) ;
102+ // Flush eagerly to ensure that each frame gets emitted even if the next one
103+ // fails
93104 #[ allow( clippy:: unwrap_used) ]
94- write ! ( w, ", \" line\" : {line}" ) . unwrap ( ) ;
95- }
105+ w. flush ( ) . unwrap ( ) ;
106+ } ) ;
107+ } else {
108+ #[ allow( clippy:: unwrap_used) ]
109+ write ! ( w, "{{" ) . unwrap ( ) ;
110+ #[ allow( clippy:: unwrap_used) ]
111+ emit_absolute_addresses ( w, frame) . unwrap ( ) ;
96112 #[ allow( clippy:: unwrap_used) ]
97113 writeln ! ( w, "}}" ) . unwrap ( ) ;
98114 // Flush eagerly to ensure that each frame gets emitted even if the next one fails
99115 #[ allow( clippy:: unwrap_used) ]
100116 w. flush ( ) . unwrap ( ) ;
101- } ) ;
102- } else {
103- #[ allow( clippy:: unwrap_used) ]
104- write ! ( w, "{{" ) . unwrap ( ) ;
105- #[ allow( clippy:: unwrap_used) ]
106- emit_absolute_addresses ( w, frame) . unwrap ( ) ;
107- #[ allow( clippy:: unwrap_used) ]
108- writeln ! ( w, "}}" ) . unwrap ( ) ;
109- // Flush eagerly to ensure that each frame gets emitted even if the next one fails
110- #[ allow( clippy:: unwrap_used) ]
111- w. flush ( ) . unwrap ( ) ;
117+ }
118+ true // keep going to the next frame
119+ } ) ;
120+ if ip_found {
121+ break ;
112122 }
113- true // keep going to the next frame
114- } ) ;
123+ // emit anything at all, if the crashing frame is not found for some reason
124+ ip_found = true ;
125+ }
115126 writeln ! ( w, "{DD_CRASHTRACK_END_STACKTRACE}" ) ?;
116127 w. flush ( ) ?;
117128 Ok ( ( ) )
@@ -146,8 +157,8 @@ pub(crate) fn emit_crashreport(
146157 // https://doc.rust-lang.org/src/std/backtrace.rs.html#332
147158 // Do this last, so even if it crashes, we still get the other info.
148159 if config. resolve_frames ( ) != StacktraceCollection :: Disabled {
149- let fault_rsp = extract_rsp ( ucontext) ;
150- unsafe { emit_backtrace_by_frames ( pipe, config. resolve_frames ( ) , fault_rsp ) ? } ;
160+ let fault_ip = extract_ip ( ucontext) ;
161+ unsafe { emit_backtrace_by_frames ( pipe, config. resolve_frames ( ) , fault_ip ) ? } ;
151162 }
152163 writeln ! ( pipe, "{DD_CRASHTRACK_DONE}" ) ?;
153164 pipe. flush ( ) ?;
@@ -308,17 +319,17 @@ fn emit_text_file(w: &mut impl Write, path: &str) -> Result<(), EmitterError> {
308319 Ok ( ( ) )
309320}
310321
311- fn extract_rsp ( ucontext : * const ucontext_t ) -> usize {
322+ fn extract_ip ( ucontext : * const ucontext_t ) -> usize {
312323 unsafe {
313324 #[ cfg( all( target_os = "macos" , target_arch = "x86_64" ) ) ]
314- return ( * ( * ucontext) . uc_mcontext ) . __ss . __rsp as usize ;
325+ return ( * ( * ucontext) . uc_mcontext ) . __ss . __rip as usize ;
315326 #[ cfg( all( target_os = "macos" , target_arch = "aarch64" ) ) ]
316- return ( * ( * ucontext) . uc_mcontext ) . __ss . __sp as usize ;
327+ return ( * ( * ucontext) . uc_mcontext ) . __ss . __pc as usize ;
317328
318329 #[ cfg( all( target_os = "linux" , target_arch = "x86_64" ) ) ]
319- return ( * ucontext) . uc_mcontext . gregs [ libc:: REG_RSP as usize ] as usize ;
330+ return ( * ucontext) . uc_mcontext . gregs [ libc:: REG_RIP as usize ] as usize ;
320331 #[ cfg( all( target_os = "linux" , target_arch = "aarch64" ) ) ]
321- return ( * ucontext) . uc_mcontext . sp as usize ;
332+ return ( * ucontext) . uc_mcontext . pc as usize ;
322333 }
323334}
324335
@@ -327,14 +338,28 @@ mod tests {
327338 use super :: * ;
328339 use std:: str;
329340
330- #[ test]
331- #[ cfg_attr( miri, ignore) ]
332- fn test_emit_backtrace_disabled ( ) {
341+ #[ inline( never) ]
342+ fn inner_test_emit_backtrace_with_symbols ( collection : StacktraceCollection ) -> Vec < u8 > {
343+ let mut ip_of_test_fn = 0 ;
344+ let mut skip = 3 ;
345+ unsafe {
346+ backtrace:: trace_unsynchronized ( |frame| {
347+ ip_of_test_fn = frame. ip ( ) as usize ;
348+ skip -= 1 ;
349+ skip > 0
350+ } )
351+ } ;
333352 let mut buf = Vec :: new ( ) ;
334353 unsafe {
335- emit_backtrace_by_frames ( & mut buf, StacktraceCollection :: Disabled , 0 )
336- . expect ( "to work ;-)" ) ;
354+ emit_backtrace_by_frames ( & mut buf, collection, ip_of_test_fn) . expect ( "to work ;-)" ) ;
337355 }
356+ buf
357+ }
358+
359+ #[ test]
360+ #[ cfg_attr( miri, ignore) ]
361+ fn test_emit_backtrace_disabled ( ) {
362+ let buf = inner_test_emit_backtrace_with_symbols ( StacktraceCollection :: Disabled ) ;
338363 let out = str:: from_utf8 ( & buf) . expect ( "to be valid UTF8" ) ;
339364 assert ! ( out. contains( "BEGIN_STACKTRACE" ) ) ;
340365 assert ! ( out. contains( "END_STACKTRACE" ) ) ;
@@ -354,18 +379,10 @@ mod tests {
354379 #[ test]
355380 #[ cfg_attr( miri, ignore) ]
356381 fn test_emit_backtrace_with_symbols ( ) {
357- let dummy = 0u8 ;
382+ let buf = inner_test_emit_backtrace_with_symbols (
383+ StacktraceCollection :: EnabledWithInprocessSymbols ,
384+ ) ;
358385 // retrieve stack pointer for this function
359- let sp_of_test_fn = & dummy as * const u8 as usize ;
360- let mut buf = Vec :: new ( ) ;
361- unsafe {
362- emit_backtrace_by_frames (
363- & mut buf,
364- StacktraceCollection :: EnabledWithInprocessSymbols ,
365- sp_of_test_fn,
366- )
367- . expect ( "to work ;-)" ) ;
368- }
369386 let out = str:: from_utf8 ( & buf) . expect ( "to be valid UTF8" ) ;
370387 assert ! ( out. contains( "BEGIN_STACKTRACE" ) ) ;
371388 assert ! ( out. contains( "END_STACKTRACE" ) ) ;
0 commit comments