1use crate::PrintFmt;
2use crate::{resolve, resolve_frame, trace, BacktraceFmt, Symbol, SymbolName};
3use std::ffi::c_void;
4use std::fmt;
5use std::path::{Path, PathBuf};
6use std::prelude::v1::*;
7
8#[cfg(feature = "serde")]
9use serde::{Deserialize, Serialize};
10
11/// Representation of an owned and self-contained backtrace.
12///
13/// This structure can be used to capture a backtrace at various points in a
14/// program and later used to inspect what the backtrace was at that time.
15///
16/// `Backtrace` supports pretty-printing of backtraces through its `Debug`
17/// implementation.
18///
19/// # Required features
20///
21/// This function requires the `std` feature of the `backtrace` crate to be
22/// enabled, and the `std` feature is enabled by default.
23#[derive(Clone)]
24#[cfg_attr(feature = "serialize-rustc", derive(RustcDecodable, RustcEncodable))]
25#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
26pub struct Backtrace {
27 // Frames here are listed from top-to-bottom of the stack
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}
33
34fn _assert_send_sync() {
35 fn _assert<T: Send + Sync>() {}
36 _assert::<Backtrace>();
37}
38
39/// Captured version of a frame in a backtrace.
40///
41/// This type is returned as a list from `Backtrace::frames` and represents one
42/// stack frame in a captured backtrace.
43///
44/// # Required features
45///
46/// This function requires the `std` feature of the `backtrace` crate to be
47/// enabled, and the `std` feature is enabled by default.
48#[derive(Clone)]
49pub struct BacktraceFrame {
50 frame: Frame,
51 symbols: Option<Vec<BacktraceSymbol>>,
52}
53
54#[derive(Clone)]
55enum Frame {
56 Raw(crate::Frame),
57 #[allow(dead_code)]
58 Deserialized {
59 ip: usize,
60 symbol_address: usize,
61 module_base_address: Option<usize>,
62 },
63}
64
65impl Frame {
66 fn ip(&self) -> *mut c_void {
67 match *self {
68 Frame::Raw(ref f) => f.ip(),
69 Frame::Deserialized { ip, .. } => ip as *mut c_void,
70 }
71 }
72
73 fn symbol_address(&self) -> *mut c_void {
74 match *self {
75 Frame::Raw(ref f) => f.symbol_address(),
76 Frame::Deserialized { symbol_address, .. } => symbol_address as *mut c_void,
77 }
78 }
79
80 fn module_base_address(&self) -> Option<*mut c_void> {
81 match *self {
82 Frame::Raw(ref f) => f.module_base_address(),
83 Frame::Deserialized {
84 module_base_address,
85 ..
86 } => module_base_address.map(|addr| addr as *mut c_void),
87 }
88 }
89}
90
91/// Captured version of a symbol in a backtrace.
92///
93/// This type is returned as a list from `BacktraceFrame::symbols` and
94/// represents the metadata for a symbol in a backtrace.
95///
96/// # Required features
97///
98/// This function requires the `std` feature of the `backtrace` crate to be
99/// enabled, and the `std` feature is enabled by default.
100#[derive(Clone)]
101#[cfg_attr(feature = "serialize-rustc", derive(RustcDecodable, RustcEncodable))]
102#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
103pub struct BacktraceSymbol {
104 name: Option<Vec<u8>>,
105 addr: Option<usize>,
106 filename: Option<PathBuf>,
107 lineno: Option<u32>,
108 colno: Option<u32>,
109}
110
111impl Backtrace {
112 /// Captures a backtrace at the callsite of this function, returning an
113 /// owned representation.
114 ///
115 /// This function is useful for representing a backtrace as an object in
116 /// Rust. This returned value can be sent across threads and printed
117 /// elsewhere, and the purpose of this value is to be entirely self
118 /// contained.
119 ///
120 /// Note that on some platforms acquiring a full backtrace and resolving it
121 /// can be extremely expensive. If the cost is too much for your application
122 /// it's recommended to instead use `Backtrace::new_unresolved()` which
123 /// avoids the symbol resolution step (which typically takes the longest)
124 /// and allows deferring that to a later date.
125 ///
126 /// # Examples
127 ///
128 /// ```
129 /// use backtrace::Backtrace;
130 ///
131 /// let current_backtrace = Backtrace::new();
132 /// ```
133 ///
134 /// # Required features
135 ///
136 /// This function requires the `std` feature of the `backtrace` crate to be
137 /// enabled, and the `std` feature is enabled by default.
138 #[inline(never)] // want to make sure there's a frame here to remove
139 pub fn new() -> Backtrace {
140 let mut bt = Self::create(Self::new as usize);
141 bt.resolve();
142 bt
143 }
144
145 /// Similar to `new` except that this does not resolve any symbols, this
146 /// simply captures the backtrace as a list of addresses.
147 ///
148 /// At a later time the `resolve` function can be called to resolve this
149 /// backtrace's symbols into readable names. This function exists because
150 /// the resolution process can sometimes take a significant amount of time
151 /// whereas any one backtrace may only be rarely printed.
152 ///
153 /// # Examples
154 ///
155 /// ```
156 /// use backtrace::Backtrace;
157 ///
158 /// let mut current_backtrace = Backtrace::new_unresolved();
159 /// println!("{:?}", current_backtrace); // no symbol names
160 /// current_backtrace.resolve();
161 /// println!("{:?}", current_backtrace); // symbol names now present
162 /// ```
163 ///
164 /// # Required features
165 ///
166 /// This function requires the `std` feature of the `backtrace` crate to be
167 /// enabled, and the `std` feature is enabled by default.
168 #[inline(never)] // want to make sure there's a frame here to remove
169 pub fn new_unresolved() -> Backtrace {
170 Self::create(Self::new_unresolved as usize)
171 }
172
173 fn create(ip: usize) -> Backtrace {
174 let mut frames = Vec::new();
175 let mut actual_start_index = None;
176 trace(|frame| {
177 frames.push(BacktraceFrame {
178 frame: Frame::Raw(frame.clone()),
179 symbols: None,
180 });
181
182 if frame.symbol_address() as usize == ip && actual_start_index.is_none() {
183 actual_start_index = Some(frames.len());
184 }
185 true
186 });
187
188 Backtrace {
189 frames,
190 actual_start_index: actual_start_index.unwrap_or(0),
191 }
192 }
193
194 /// Returns the frames from when this backtrace was captured.
195 ///
196 /// The first entry of this slice is likely the function `Backtrace::new`,
197 /// and the last frame is likely something about how this thread or the main
198 /// function started.
199 ///
200 /// # Required features
201 ///
202 /// This function requires the `std` feature of the `backtrace` crate to be
203 /// enabled, and the `std` feature is enabled by default.
204 pub fn frames(&self) -> &[BacktraceFrame] {
205 &self.frames[self.actual_start_index..]
206 }
207
208 /// If this backtrace was created from `new_unresolved` then this function
209 /// will resolve all addresses in the backtrace to their symbolic names.
210 ///
211 /// If this backtrace has been previously resolved or was created through
212 /// `new`, this function does nothing.
213 ///
214 /// # Required features
215 ///
216 /// This function requires the `std` feature of the `backtrace` crate to be
217 /// enabled, and the `std` feature is enabled by default.
218 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 }
240 }
241}
242
243impl From<Vec<BacktraceFrame>> for Backtrace {
244 fn from(frames: Vec<BacktraceFrame>) -> Self {
245 Backtrace {
246 frames,
247 actual_start_index: 0,
248 }
249 }
250}
251
252impl From<crate::Frame> for BacktraceFrame {
253 fn from(frame: crate::Frame) -> BacktraceFrame {
254 BacktraceFrame {
255 frame: Frame::Raw(frame),
256 symbols: None,
257 }
258 }
259}
260
261impl Into<Vec<BacktraceFrame>> for Backtrace {
262 fn into(self) -> Vec<BacktraceFrame> {
263 self.frames
264 }
265}
266
267impl BacktraceFrame {
268 /// Same as `Frame::ip`
269 ///
270 /// # Required features
271 ///
272 /// This function requires the `std` feature of the `backtrace` crate to be
273 /// enabled, and the `std` feature is enabled by default.
274 pub fn ip(&self) -> *mut c_void {
275 self.frame.ip() as *mut c_void
276 }
277
278 /// Same as `Frame::symbol_address`
279 ///
280 /// # Required features
281 ///
282 /// This function requires the `std` feature of the `backtrace` crate to be
283 /// enabled, and the `std` feature is enabled by default.
284 pub fn symbol_address(&self) -> *mut c_void {
285 self.frame.symbol_address() as *mut c_void
286 }
287
288 /// Same as `Frame::module_base_address`
289 ///
290 /// # Required features
291 ///
292 /// This function requires the `std` feature of the `backtrace` crate to be
293 /// enabled, and the `std` feature is enabled by default.
294 pub fn module_base_address(&self) -> Option<*mut c_void> {
295 self.frame
296 .module_base_address()
297 .map(|addr| addr as *mut c_void)
298 }
299
300 /// Returns the list of symbols that this frame corresponds to.
301 ///
302 /// Normally there is only one symbol per frame, but sometimes if a number
303 /// of functions are inlined into one frame then multiple symbols will be
304 /// returned. The first symbol listed is the "innermost function", whereas
305 /// the last symbol is the outermost (last caller).
306 ///
307 /// Note that if this frame came from an unresolved backtrace then this will
308 /// return an empty list.
309 ///
310 /// # Required features
311 ///
312 /// This function requires the `std` feature of the `backtrace` crate to be
313 /// enabled, and the `std` feature is enabled by default.
314 pub fn symbols(&self) -> &[BacktraceSymbol] {
315 self.symbols.as_ref().map(|s| &s[..]).unwrap_or(&[])
316 }
317}
318
319impl BacktraceSymbol {
320 /// Same as `Symbol::name`
321 ///
322 /// # Required features
323 ///
324 /// This function requires the `std` feature of the `backtrace` crate to be
325 /// enabled, and the `std` feature is enabled by default.
326 pub fn name(&self) -> Option<SymbolName<'_>> {
327 self.name.as_ref().map(|s| SymbolName::new(s))
328 }
329
330 /// Same as `Symbol::addr`
331 ///
332 /// # Required features
333 ///
334 /// This function requires the `std` feature of the `backtrace` crate to be
335 /// enabled, and the `std` feature is enabled by default.
336 pub fn addr(&self) -> Option<*mut c_void> {
337 self.addr.map(|s| s as *mut c_void)
338 }
339
340 /// Same as `Symbol::filename`
341 ///
342 /// # Required features
343 ///
344 /// This function requires the `std` feature of the `backtrace` crate to be
345 /// enabled, and the `std` feature is enabled by default.
346 pub fn filename(&self) -> Option<&Path> {
347 self.filename.as_ref().map(|p| &**p)
348 }
349
350 /// Same as `Symbol::lineno`
351 ///
352 /// # Required features
353 ///
354 /// This function requires the `std` feature of the `backtrace` crate to be
355 /// enabled, and the `std` feature is enabled by default.
356 pub fn lineno(&self) -> Option<u32> {
357 self.lineno
358 }
359
360 /// Same as `Symbol::colno`
361 ///
362 /// # Required features
363 ///
364 /// This function requires the `std` feature of the `backtrace` crate to be
365 /// enabled, and the `std` feature is enabled by default.
366 pub fn colno(&self) -> Option<u32> {
367 self.colno
368 }
369}
370
371impl fmt::Debug for Backtrace {
372 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)
376 } else {
377 (&self.frames[self.actual_start_index..], PrintFmt::Short)
378 };
379
380 // When printing paths we try to strip the cwd if it exists, otherwise
381 // we just print the path as-is. Note that we also only do this for the
382 // short format, because if it's full we presumably want to print
383 // everything.
384 let cwd = std::env::current_dir();
385 let mut print_path =
386 move |fmt: &mut fmt::Formatter<'_>, path: crate::BytesOrWideString<'_>| {
387 let path = path.into_path_buf();
388 if !full {
389 if let Ok(cwd) = &cwd {
390 if let Ok(suffix) = path.strip_prefix(cwd) {
391 return fmt::Display::fmt(&suffix.display(), fmt);
392 }
393 }
394 }
395 fmt::Display::fmt(&path.display(), fmt)
396 };
397
398 let mut f = BacktraceFmt::new(fmt, style, &mut print_path);
399 f.add_context()?;
400 for frame in frames {
401 f.frame().backtrace_frame(frame)?;
402 }
403 f.finish()?;
404 Ok(())
405 }
406}
407
408impl Default for Backtrace {
409 fn default() -> Backtrace {
410 Backtrace::new()
411 }
412}
413
414impl fmt::Debug for BacktraceFrame {
415 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
416 fmt&mut DebugStruct<'_, '_>.debug_struct("BacktraceFrame")
417 .field("ip", &self.ip())
418 .field(name:"symbol_address", &self.symbol_address())
419 .finish()
420 }
421}
422
423impl fmt::Debug for BacktraceSymbol {
424 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
425 fmt&mut DebugStruct<'_, '_>.debug_struct("BacktraceSymbol")
426 .field("name", &self.name())
427 .field("addr", &self.addr())
428 .field("filename", &self.filename())
429 .field("lineno", &self.lineno())
430 .field(name:"colno", &self.colno())
431 .finish()
432 }
433}
434
435#[cfg(feature = "serialize-rustc")]
436mod rustc_serialize_impls {
437 use super::*;
438 use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
439
440 #[derive(RustcEncodable, RustcDecodable)]
441 struct SerializedFrame {
442 ip: usize,
443 symbol_address: usize,
444 module_base_address: Option<usize>,
445 symbols: Option<Vec<BacktraceSymbol>>,
446 }
447
448 impl Decodable for BacktraceFrame {
449 fn decode<D>(d: &mut D) -> Result<Self, D::Error>
450 where
451 D: Decoder,
452 {
453 let frame: SerializedFrame = SerializedFrame::decode(d)?;
454 Ok(BacktraceFrame {
455 frame: Frame::Deserialized {
456 ip: frame.ip,
457 symbol_address: frame.symbol_address,
458 module_base_address: frame.module_base_address,
459 },
460 symbols: frame.symbols,
461 })
462 }
463 }
464
465 impl Encodable for BacktraceFrame {
466 fn encode<E>(&self, e: &mut E) -> Result<(), E::Error>
467 where
468 E: Encoder,
469 {
470 let BacktraceFrame { frame, symbols } = self;
471 SerializedFrame {
472 ip: frame.ip() as usize,
473 symbol_address: frame.symbol_address() as usize,
474 module_base_address: frame.module_base_address().map(|addr| addr as usize),
475 symbols: symbols.clone(),
476 }
477 .encode(e)
478 }
479 }
480}
481
482#[cfg(feature = "serde")]
483mod serde_impls {
484 use super::*;
485 use serde::de::Deserializer;
486 use serde::ser::Serializer;
487 use serde::{Deserialize, Serialize};
488
489 #[derive(Serialize, Deserialize)]
490 struct SerializedFrame {
491 ip: usize,
492 symbol_address: usize,
493 module_base_address: Option<usize>,
494 symbols: Option<Vec<BacktraceSymbol>>,
495 }
496
497 impl Serialize for BacktraceFrame {
498 fn serialize<S>(&self, s: S) -> Result<S::Ok, S::Error>
499 where
500 S: Serializer,
501 {
502 let BacktraceFrame { frame, symbols } = self;
503 SerializedFrame {
504 ip: frame.ip() as usize,
505 symbol_address: frame.symbol_address() as usize,
506 module_base_address: frame.module_base_address().map(|addr| addr as usize),
507 symbols: symbols.clone(),
508 }
509 .serialize(s)
510 }
511 }
512
513 impl<'a> Deserialize<'a> for BacktraceFrame {
514 fn deserialize<D>(d: D) -> Result<Self, D::Error>
515 where
516 D: Deserializer<'a>,
517 {
518 let frame: SerializedFrame = SerializedFrame::deserialize(d)?;
519 Ok(BacktraceFrame {
520 frame: Frame::Deserialized {
521 ip: frame.ip,
522 symbol_address: frame.symbol_address,
523 module_base_address: frame.module_base_address,
524 },
525 symbols: frame.symbols,
526 })
527 }
528 }
529}
530
531#[cfg(test)]
532mod tests {
533 use super::*;
534
535 #[test]
536 fn test_frame_conversion() {
537 let mut frames = vec![];
538 crate::trace(|frame| {
539 let converted = BacktraceFrame::from(frame.clone());
540 frames.push(converted);
541 true
542 });
543
544 let mut manual = Backtrace::from(frames);
545 manual.resolve();
546 let frames = manual.frames();
547
548 for frame in frames {
549 println!("{:?}", frame.ip());
550 println!("{:?}", frame.symbol_address());
551 println!("{:?}", frame.module_base_address());
552 println!("{:?}", frame.symbols());
553 }
554 }
555}
556