@@ -14,6 +14,7 @@ use {trace, resolve, SymbolName};
14
14
#[ cfg_attr( feature = "serialize-serde" , derive( Deserialize , Serialize ) ) ]
15
15
pub struct Backtrace {
16
16
frames : Vec < BacktraceFrame > ,
17
+ ext_index : Option < usize > ,
17
18
}
18
19
19
20
/// Captured version of a frame in a backtrace.
@@ -60,9 +61,7 @@ impl Backtrace {
60
61
/// let current_backtrace = Backtrace::new();
61
62
/// ```
62
63
pub fn new ( ) -> Backtrace {
63
- let mut bt = Backtrace :: new_unresolved ( ) ;
64
- bt. resolve ( ) ;
65
- return bt
64
+ Self :: create ( Self :: new as usize ) . resolved ( )
66
65
}
67
66
68
67
/// Similar to `new` except that this does not resolve any symbols, this
@@ -84,17 +83,38 @@ impl Backtrace {
84
83
/// println!("{:?}", current_backtrace); // symbol names now present
85
84
/// ```
86
85
pub fn new_unresolved ( ) -> Backtrace {
86
+ Self :: create ( Self :: new_unresolved as usize )
87
+ }
88
+
89
+ fn create ( ip : usize ) -> Backtrace {
90
+ let ip_range: ( usize , usize ) = ( ip, ip + 128 ) ;
91
+
87
92
let mut frames = Vec :: new ( ) ;
93
+ let mut ext_index = None ;
88
94
trace ( |frame| {
95
+ let ip = frame. ip ( ) as usize ;
89
96
frames. push ( BacktraceFrame {
90
- ip : frame . ip ( ) as usize ,
97
+ ip,
91
98
symbol_address : frame. symbol_address ( ) as usize ,
92
99
symbols : None ,
93
100
} ) ;
101
+
102
+ if cfg ! ( not( all( target_os = "windows" , target_arch = "x86" ) ) ) && ip >= ip_range. 0 && ip <= ip_range. 1 {
103
+ ext_index = Some ( frames. len ( ) ) ;
104
+ }
94
105
true
95
106
} ) ;
96
107
97
- Backtrace { frames : frames }
108
+ Backtrace {
109
+ frames,
110
+ ext_index,
111
+ }
112
+ }
113
+
114
+ #[ inline( always) ]
115
+ fn resolved ( mut self ) -> Backtrace {
116
+ self . resolve ( ) ;
117
+ self
98
118
}
99
119
100
120
/// Returns the frames from when this backtrace was captured.
@@ -106,6 +126,41 @@ impl Backtrace {
106
126
& self . frames
107
127
}
108
128
129
+ /// Returns the frames from when this backtrace was captured, omitting frames from within this
130
+ /// crate itself, if possible (see `ext_index()`)
131
+ pub fn ext_frames ( & self ) -> & [ BacktraceFrame ] {
132
+ if let Some ( i) = self . ext_index {
133
+ & self . frames [ i..]
134
+ } else {
135
+ & self . frames
136
+ }
137
+ }
138
+
139
+ /// Returns the index of the first "external" frame (i.e. the call-site of one of the
140
+ /// public constructors `new` or `new_unresolved`), if known. Backtrace frames up to this index
141
+ /// are from within this crate itself, and usually do not present useful information when used
142
+ /// from other crates, and as such can be skipped from displaying.
143
+ ///
144
+ /// This index is used when backtrace is displayed in the default debug format `{:?}`.
145
+ /// Full backtrace can be still displayed using alternative debug format `{:#?}`.
146
+ ///
147
+ /// If this function returns `None`, either debug formats will display full backtrace.
148
+ ///
149
+ /// # Examples
150
+ ///
151
+ /// ```
152
+ /// use backtrace::Backtrace;
153
+ ///
154
+ /// let backtrace = Backtrace::new();
155
+ /// println!("{:?}", backtrace); // prints backtrace skipping frames from within this crate
156
+ ///
157
+ /// println!("{:#?}", backtrace); // prints full backtrace
158
+ /// ```
159
+ /// *Note*: currently this always return `None` on Windows x86 (32-bit) targets
160
+ pub fn ext_index ( & self ) -> Option < usize > {
161
+ self . ext_index
162
+ }
163
+
109
164
/// If this backtrace was created from `new_unresolved` then this function
110
165
/// will resolve all addresses in the backtrace to their symbolic names.
111
166
///
@@ -130,7 +185,8 @@ impl Backtrace {
130
185
impl From < Vec < BacktraceFrame > > for Backtrace {
131
186
fn from ( frames : Vec < BacktraceFrame > ) -> Self {
132
187
Backtrace {
133
- frames : frames
188
+ frames,
189
+ ext_index : None ,
134
190
}
135
191
}
136
192
}
@@ -192,36 +248,42 @@ impl fmt::Debug for Backtrace {
192
248
fn fmt ( & self , fmt : & mut fmt:: Formatter ) -> fmt:: Result {
193
249
let hex_width = mem:: size_of :: < usize > ( ) * 2 + 2 ;
194
250
195
- try!( write ! ( fmt, "stack backtrace:" ) ) ;
251
+ write ! ( fmt, "stack backtrace:" ) ?;
252
+
253
+ let iter = if fmt. alternate ( ) {
254
+ self . frames ( )
255
+ } else {
256
+ self . ext_frames ( )
257
+ } . iter ( ) ;
196
258
197
- for ( idx, frame) in self . frames ( ) . iter ( ) . enumerate ( ) {
259
+ for ( idx, frame) in iter. enumerate ( ) {
198
260
let ip = frame. ip ( ) ;
199
- try! ( write ! ( fmt, "\n {:4}: {:2$?}" , idx, ip, hex_width) ) ;
261
+ write ! ( fmt, "\n {:4}: {:2$?}" , idx, ip, hex_width) ? ;
200
262
201
263
let symbols = match frame. symbols {
202
264
Some ( ref s) => s,
203
265
None => {
204
- try! ( write ! ( fmt, " - <unresolved>" ) ) ;
266
+ write ! ( fmt, " - <unresolved>" ) ? ;
205
267
continue
206
268
}
207
269
} ;
208
270
if symbols. len ( ) == 0 {
209
- try! ( write ! ( fmt, " - <no info>" ) ) ;
271
+ write ! ( fmt, " - <no info>" ) ? ;
210
272
}
211
273
212
274
for ( idx, symbol) in symbols. iter ( ) . enumerate ( ) {
213
275
if idx != 0 {
214
- try! ( write ! ( fmt, "\n {:1$}" , "" , hex_width) ) ;
276
+ write ! ( fmt, "\n {:1$}" , "" , hex_width) ? ;
215
277
}
216
278
217
279
if let Some ( name) = symbol. name ( ) {
218
- try! ( write ! ( fmt, " - {}" , name) ) ;
280
+ write ! ( fmt, " - {}" , name) ? ;
219
281
} else {
220
- try! ( write ! ( fmt, " - <unknown>" ) ) ;
282
+ write ! ( fmt, " - <unknown>" ) ? ;
221
283
}
222
284
223
285
if let ( Some ( file) , Some ( line) ) = ( symbol. filename ( ) , symbol. lineno ( ) ) {
224
- try! ( write ! ( fmt, "\n {:3$}at {}:{}" , "" , file. display( ) , line, hex_width) ) ;
286
+ write ! ( fmt, "\n {:3$}at {}:{}" , "" , file. display( ) , line, hex_width) ? ;
225
287
}
226
288
}
227
289
}
0 commit comments