9292// a backtrace or actually symbolizing it.
9393
9494use crate :: env;
95+ use crate :: ffi:: c_void;
9596use crate :: fmt;
9697use crate :: sync:: atomic:: { AtomicUsize , Ordering :: SeqCst } ;
9798use crate :: sync:: Mutex ;
@@ -144,10 +145,16 @@ fn _assert_send_sync() {
144145}
145146
146147struct BacktraceFrame {
147- frame : backtrace :: Frame ,
148+ frame : RawFrame ,
148149 symbols : Vec < BacktraceSymbol > ,
149150}
150151
152+ enum RawFrame {
153+ Actual ( backtrace:: Frame ) ,
154+ #[ cfg( test) ]
155+ Fake ,
156+ }
157+
151158struct BacktraceSymbol {
152159 name : Option < Vec < u8 > > ,
153160 filename : Option < BytesOrWide > ,
@@ -162,8 +169,8 @@ enum BytesOrWide {
162169impl fmt:: Debug for Backtrace {
163170 fn fmt ( & self , fmt : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
164171 let mut capture = match & self . inner {
165- Inner :: Unsupported => return fmt. write_str ( "unsupported backtrace " ) ,
166- Inner :: Disabled => return fmt. write_str ( "disabled backtrace " ) ,
172+ Inner :: Unsupported => return fmt. write_str ( "< unsupported> " ) ,
173+ Inner :: Disabled => return fmt. write_str ( "< disabled> " ) ,
167174 Inner :: Captured ( c) => c. lock ( ) . unwrap ( ) ,
168175 } ;
169176 capture. resolve ( ) ;
@@ -193,11 +200,11 @@ impl fmt::Debug for BacktraceSymbol {
193200 if let Some ( fn_name) = self . name . as_ref ( ) . map ( |b| backtrace:: SymbolName :: new ( b) ) {
194201 write ! ( fmt, "fn: \" {:#}\" " , fn_name) ?;
195202 } else {
196- write ! ( fmt, "fn: \" <unknown>\" " ) ?;
203+ write ! ( fmt, "fn: <unknown>" ) ?;
197204 }
198205
199206 if let Some ( fname) = self . filename . as_ref ( ) {
200- write ! ( fmt, ", file: {:?}" , fname) ?;
207+ write ! ( fmt, ", file: \" {:?}\" " , fname) ?;
201208 }
202209
203210 if let Some ( line) = self . lineno . as_ref ( ) {
@@ -293,7 +300,10 @@ impl Backtrace {
293300 let mut actual_start = None ;
294301 unsafe {
295302 backtrace:: trace_unsynchronized ( |frame| {
296- frames. push ( BacktraceFrame { frame : frame. clone ( ) , symbols : Vec :: new ( ) } ) ;
303+ frames. push ( BacktraceFrame {
304+ frame : RawFrame :: Actual ( frame. clone ( ) ) ,
305+ symbols : Vec :: new ( ) ,
306+ } ) ;
297307 if frame. symbol_address ( ) as usize == ip && actual_start. is_none ( ) {
298308 actual_start = Some ( frames. len ( ) ) ;
299309 }
@@ -393,8 +403,13 @@ impl Capture {
393403 let _lock = lock ( ) ;
394404 for frame in self . frames . iter_mut ( ) {
395405 let symbols = & mut frame. symbols ;
406+ let frame = match & frame. frame {
407+ RawFrame :: Actual ( frame) => frame,
408+ #[ cfg( test) ]
409+ RawFrame :: Fake => unimplemented ! ( ) ,
410+ } ;
396411 unsafe {
397- backtrace:: resolve_frame_unsynchronized ( & frame . frame , |symbol| {
412+ backtrace:: resolve_frame_unsynchronized ( frame, |symbol| {
398413 symbols. push ( BacktraceSymbol {
399414 name : symbol. name ( ) . map ( |m| m. as_bytes ( ) . to_vec ( ) ) ,
400415 filename : symbol. filename_raw ( ) . map ( |b| match b {
@@ -408,3 +423,65 @@ impl Capture {
408423 }
409424 }
410425}
426+
427+ impl RawFrame {
428+ fn ip ( & self ) -> * mut c_void {
429+ match self {
430+ RawFrame :: Actual ( frame) => frame. ip ( ) ,
431+ #[ cfg( test) ]
432+ RawFrame :: Fake => 1 as * mut c_void ,
433+ }
434+ }
435+ }
436+
437+ #[ test]
438+ fn test_debug ( ) {
439+ let backtrace = Backtrace {
440+ inner : Inner :: Captured ( Mutex :: new ( Capture {
441+ actual_start : 1 ,
442+ resolved : true ,
443+ frames : vec ! [
444+ BacktraceFrame {
445+ frame: RawFrame :: Fake ,
446+ symbols: vec![ BacktraceSymbol {
447+ name: Some ( b"std::backtrace::Backtrace::create" . to_vec( ) ) ,
448+ filename: Some ( BytesOrWide :: Bytes ( b"rust/backtrace.rs" . to_vec( ) ) ) ,
449+ lineno: Some ( 100 ) ,
450+ } ] ,
451+ } ,
452+ BacktraceFrame {
453+ frame: RawFrame :: Fake ,
454+ symbols: vec![ BacktraceSymbol {
455+ name: Some ( b"__rust_maybe_catch_panic" . to_vec( ) ) ,
456+ filename: None ,
457+ lineno: None ,
458+ } ] ,
459+ } ,
460+ BacktraceFrame {
461+ frame: RawFrame :: Fake ,
462+ symbols: vec![
463+ BacktraceSymbol {
464+ name: Some ( b"std::rt::lang_start_internal" . to_vec( ) ) ,
465+ filename: Some ( BytesOrWide :: Bytes ( b"rust/rt.rs" . to_vec( ) ) ) ,
466+ lineno: Some ( 300 ) ,
467+ } ,
468+ BacktraceSymbol {
469+ name: Some ( b"std::rt::lang_start" . to_vec( ) ) ,
470+ filename: Some ( BytesOrWide :: Bytes ( b"rust/rt.rs" . to_vec( ) ) ) ,
471+ lineno: Some ( 400 ) ,
472+ } ,
473+ ] ,
474+ } ,
475+ ] ,
476+ } ) ) ,
477+ } ;
478+
479+ #[ rustfmt:: skip]
480+ let expected = "Backtrace [\
481+ \n { fn: \" __rust_maybe_catch_panic\" },\
482+ \n { fn: \" std::rt::lang_start_internal\" , file: \" rust/rt.rs\" , line: 300 },\
483+ \n { fn: \" std::rt::lang_start\" , file: \" rust/rt.rs\" , line: 400 },\
484+ \n ]";
485+
486+ assert_eq ! ( format!( "{:#?}" , backtrace) , expected) ;
487+ }
0 commit comments