@@ -26,9 +26,6 @@ use serde::{Deserialize, Serialize};
2626pub struct Backtrace {
2727 // Frames here are listed from top-to-bottom of the stack
2828 frames : Vec < BacktraceFrame > ,
29- // The index we believe is the actual start of the backtrace, omitting
30- // frames like `Backtrace::new` and `backtrace::trace`.
31- actual_start_index : usize ,
3229}
3330
3431fn _assert_send_sync ( ) {
@@ -86,6 +83,27 @@ impl Frame {
8683 } => module_base_address. map ( |addr| addr as * mut c_void ) ,
8784 }
8885 }
86+
87+ /// Resolve all addresses in the frame to their symbolic names.
88+ fn resolve_symbols ( & self ) -> Vec < BacktraceSymbol > {
89+ let mut symbols = Vec :: new ( ) ;
90+ let sym = |symbol : & Symbol | {
91+ symbols. push ( BacktraceSymbol {
92+ name : symbol. name ( ) . map ( |m| m. as_bytes ( ) . to_vec ( ) ) ,
93+ addr : symbol. addr ( ) . map ( |a| a as usize ) ,
94+ filename : symbol. filename ( ) . map ( |m| m. to_owned ( ) ) ,
95+ lineno : symbol. lineno ( ) ,
96+ colno : symbol. colno ( ) ,
97+ } ) ;
98+ } ;
99+ match * self {
100+ Frame :: Raw ( ref f) => resolve_frame ( f, sym) ,
101+ Frame :: Deserialized { ip, .. } => {
102+ resolve ( ip as * mut c_void , sym) ;
103+ }
104+ }
105+ symbols
106+ }
89107}
90108
91109/// Captured version of a symbol in a backtrace.
@@ -172,23 +190,22 @@ impl Backtrace {
172190
173191 fn create ( ip : usize ) -> Backtrace {
174192 let mut frames = Vec :: new ( ) ;
175- let mut actual_start_index = None ;
176193 trace ( |frame| {
177194 frames. push ( BacktraceFrame {
178195 frame : Frame :: Raw ( frame. clone ( ) ) ,
179196 symbols : None ,
180197 } ) ;
181198
182- if frame. symbol_address ( ) as usize == ip && actual_start_index. is_none ( ) {
183- actual_start_index = Some ( frames. len ( ) ) ;
199+ // clear inner frames, and start with call site.
200+ if frame. symbol_address ( ) as usize == ip {
201+ frames. clear ( ) ;
184202 }
203+
185204 true
186205 } ) ;
206+ frames. shrink_to_fit ( ) ;
187207
188- Backtrace {
189- frames,
190- actual_start_index : actual_start_index. unwrap_or ( 0 ) ,
191- }
208+ Backtrace { frames }
192209 }
193210
194211 /// Returns the frames from when this backtrace was captured.
@@ -202,7 +219,7 @@ impl Backtrace {
202219 /// This function requires the `std` feature of the `backtrace` crate to be
203220 /// enabled, and the `std` feature is enabled by default.
204221 pub fn frames ( & self ) -> & [ BacktraceFrame ] {
205- & self . frames [ self . actual_start_index .. ]
222+ self . frames . as_slice ( )
206223 }
207224
208225 /// If this backtrace was created from `new_unresolved` then this function
@@ -216,48 +233,28 @@ impl Backtrace {
216233 /// This function requires the `std` feature of the `backtrace` crate to be
217234 /// enabled, and the `std` feature is enabled by default.
218235 pub fn resolve ( & mut self ) {
219- for frame in self . frames . iter_mut ( ) . filter ( |f| f. symbols . is_none ( ) ) {
220- let mut symbols = Vec :: new ( ) ;
221- {
222- let sym = |symbol : & Symbol | {
223- symbols. push ( BacktraceSymbol {
224- name : symbol. name ( ) . map ( |m| m. as_bytes ( ) . to_vec ( ) ) ,
225- addr : symbol. addr ( ) . map ( |a| a as usize ) ,
226- filename : symbol. filename ( ) . map ( |m| m. to_owned ( ) ) ,
227- lineno : symbol. lineno ( ) ,
228- colno : symbol. colno ( ) ,
229- } ) ;
230- } ;
231- match frame. frame {
232- Frame :: Raw ( ref f) => resolve_frame ( f, sym) ,
233- Frame :: Deserialized { ip, .. } => {
234- resolve ( ip as * mut c_void , sym) ;
235- }
236- }
237- }
238- frame. symbols = Some ( symbols) ;
239- }
236+ self . frames . iter_mut ( ) . for_each ( BacktraceFrame :: resolve) ;
240237 }
241238}
242239
243240impl From < Vec < BacktraceFrame > > for Backtrace {
244241 fn from ( frames : Vec < BacktraceFrame > ) -> Self {
245- Backtrace {
246- frames,
247- actual_start_index : 0 ,
248- }
242+ Backtrace { frames }
249243 }
250244}
251245
252246impl From < crate :: Frame > for BacktraceFrame {
253- fn from ( frame : crate :: Frame ) -> BacktraceFrame {
247+ fn from ( frame : crate :: Frame ) -> Self {
254248 BacktraceFrame {
255249 frame : Frame :: Raw ( frame) ,
256250 symbols : None ,
257251 }
258252 }
259253}
260254
255+ // we don't want implementing `impl From<Backtrace> for Vec<BacktraceFrame>` on purpose,
256+ // because "... additional directions for Vec<T> can weaken type inference ..."
257+ // more information on https://github.com/rust-lang/backtrace-rs/pull/526
261258impl Into < Vec < BacktraceFrame > > for Backtrace {
262259 fn into ( self ) -> Vec < BacktraceFrame > {
263260 self . frames
@@ -312,6 +309,20 @@ impl BacktraceFrame {
312309 pub fn symbols ( & self ) -> & [ BacktraceSymbol ] {
313310 self . symbols . as_ref ( ) . map ( |s| & s[ ..] ) . unwrap_or ( & [ ] )
314311 }
312+
313+ /// Resolve all addresses in this frame to their symbolic names.
314+ ///
315+ /// If this frame has been previously resolved, this function does nothing.
316+ ///
317+ /// # Required features
318+ ///
319+ /// This function requires the `std` feature of the `backtrace` crate to be
320+ /// enabled, and the `std` feature is enabled by default.
321+ pub fn resolve ( & mut self ) {
322+ if self . symbols . is_none ( ) {
323+ self . symbols = Some ( self . frame . resolve_symbols ( ) ) ;
324+ }
325+ }
315326}
316327
317328impl BacktraceSymbol {
@@ -368,11 +379,10 @@ impl BacktraceSymbol {
368379
369380impl fmt:: Debug for Backtrace {
370381 fn fmt ( & self , fmt : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
371- let full = fmt. alternate ( ) ;
372- let ( frames, style) = if full {
373- ( & self . frames [ ..] , PrintFmt :: Full )
382+ let style = if fmt. alternate ( ) {
383+ PrintFmt :: Full
374384 } else {
375- ( & self . frames [ self . actual_start_index .. ] , PrintFmt :: Short )
385+ PrintFmt :: Short
376386 } ;
377387
378388 // When printing paths we try to strip the cwd if it exists, otherwise
@@ -383,7 +393,7 @@ impl fmt::Debug for Backtrace {
383393 let mut print_path =
384394 move |fmt : & mut fmt:: Formatter < ' _ > , path : crate :: BytesOrWideString < ' _ > | {
385395 let path = path. into_path_buf ( ) ;
386- if !full {
396+ if style == PrintFmt :: Full {
387397 if let Ok ( cwd) = & cwd {
388398 if let Ok ( suffix) = path. strip_prefix ( cwd) {
389399 return fmt:: Display :: fmt ( & suffix. display ( ) , fmt) ;
@@ -395,7 +405,7 @@ impl fmt::Debug for Backtrace {
395405
396406 let mut f = BacktraceFmt :: new ( fmt, style, & mut print_path) ;
397407 f. add_context ( ) ?;
398- for frame in frames {
408+ for frame in & self . frames {
399409 f. frame ( ) . backtrace_frame ( frame) ?;
400410 }
401411 f. finish ( ) ?;
0 commit comments