@@ -26,9 +26,6 @@ use serde::{Deserialize, Serialize};
26
26
pub struct Backtrace {
27
27
// Frames here are listed from top-to-bottom of the stack
28
28
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 ,
32
29
}
33
30
34
31
fn _assert_send_sync ( ) {
@@ -86,6 +83,27 @@ impl Frame {
86
83
} => module_base_address. map ( |addr| addr as * mut c_void ) ,
87
84
}
88
85
}
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
+ }
89
107
}
90
108
91
109
/// Captured version of a symbol in a backtrace.
@@ -172,23 +190,22 @@ impl Backtrace {
172
190
173
191
fn create ( ip : usize ) -> Backtrace {
174
192
let mut frames = Vec :: new ( ) ;
175
- let mut actual_start_index = None ;
176
193
trace ( |frame| {
177
194
frames. push ( BacktraceFrame {
178
195
frame : Frame :: Raw ( frame. clone ( ) ) ,
179
196
symbols : None ,
180
197
} ) ;
181
198
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 ( ) ;
184
202
}
203
+
185
204
true
186
205
} ) ;
206
+ frames. shrink_to_fit ( ) ;
187
207
188
- Backtrace {
189
- frames,
190
- actual_start_index : actual_start_index. unwrap_or ( 0 ) ,
191
- }
208
+ Backtrace { frames }
192
209
}
193
210
194
211
/// Returns the frames from when this backtrace was captured.
@@ -202,7 +219,7 @@ impl Backtrace {
202
219
/// This function requires the `std` feature of the `backtrace` crate to be
203
220
/// enabled, and the `std` feature is enabled by default.
204
221
pub fn frames ( & self ) -> & [ BacktraceFrame ] {
205
- & self . frames [ self . actual_start_index .. ]
222
+ self . frames . as_slice ( )
206
223
}
207
224
208
225
/// If this backtrace was created from `new_unresolved` then this function
@@ -216,48 +233,28 @@ impl Backtrace {
216
233
/// This function requires the `std` feature of the `backtrace` crate to be
217
234
/// enabled, and the `std` feature is enabled by default.
218
235
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) ;
240
237
}
241
238
}
242
239
243
240
impl From < Vec < BacktraceFrame > > for Backtrace {
244
241
fn from ( frames : Vec < BacktraceFrame > ) -> Self {
245
- Backtrace {
246
- frames,
247
- actual_start_index : 0 ,
248
- }
242
+ Backtrace { frames }
249
243
}
250
244
}
251
245
252
246
impl From < crate :: Frame > for BacktraceFrame {
253
- fn from ( frame : crate :: Frame ) -> BacktraceFrame {
247
+ fn from ( frame : crate :: Frame ) -> Self {
254
248
BacktraceFrame {
255
249
frame : Frame :: Raw ( frame) ,
256
250
symbols : None ,
257
251
}
258
252
}
259
253
}
260
254
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
261
258
impl Into < Vec < BacktraceFrame > > for Backtrace {
262
259
fn into ( self ) -> Vec < BacktraceFrame > {
263
260
self . frames
@@ -314,6 +311,20 @@ impl BacktraceFrame {
314
311
pub fn symbols ( & self ) -> & [ BacktraceSymbol ] {
315
312
self . symbols . as_ref ( ) . map ( |s| & s[ ..] ) . unwrap_or ( & [ ] )
316
313
}
314
+
315
+ /// Resolve all addresses in this frame to their symbolic names.
316
+ ///
317
+ /// If this frame has been previously resolved, this function does nothing.
318
+ ///
319
+ /// # Required features
320
+ ///
321
+ /// This function requires the `std` feature of the `backtrace` crate to be
322
+ /// enabled, and the `std` feature is enabled by default.
323
+ pub fn resolve ( & mut self ) {
324
+ if self . symbols . is_none ( ) {
325
+ self . symbols = Some ( self . frame . resolve_symbols ( ) ) ;
326
+ }
327
+ }
317
328
}
318
329
319
330
impl BacktraceSymbol {
@@ -370,11 +381,10 @@ impl BacktraceSymbol {
370
381
371
382
impl fmt:: Debug for Backtrace {
372
383
fn fmt ( & self , fmt : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
373
- let full = fmt. alternate ( ) ;
374
- let ( frames, style) = if full {
375
- ( & self . frames [ ..] , PrintFmt :: Full )
384
+ let style = if fmt. alternate ( ) {
385
+ PrintFmt :: Full
376
386
} else {
377
- ( & self . frames [ self . actual_start_index .. ] , PrintFmt :: Short )
387
+ PrintFmt :: Short
378
388
} ;
379
389
380
390
// When printing paths we try to strip the cwd if it exists, otherwise
@@ -385,7 +395,7 @@ impl fmt::Debug for Backtrace {
385
395
let mut print_path =
386
396
move |fmt : & mut fmt:: Formatter < ' _ > , path : crate :: BytesOrWideString < ' _ > | {
387
397
let path = path. into_path_buf ( ) ;
388
- if !full {
398
+ if style == PrintFmt :: Full {
389
399
if let Ok ( cwd) = & cwd {
390
400
if let Ok ( suffix) = path. strip_prefix ( cwd) {
391
401
return fmt:: Display :: fmt ( & suffix. display ( ) , fmt) ;
@@ -397,7 +407,7 @@ impl fmt::Debug for Backtrace {
397
407
398
408
let mut f = BacktraceFmt :: new ( fmt, style, & mut print_path) ;
399
409
f. add_context ( ) ?;
400
- for frame in frames {
410
+ for frame in & self . frames {
401
411
f. frame ( ) . backtrace_frame ( frame) ?;
402
412
}
403
413
f. finish ( ) ?;
0 commit comments