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

Provided by KDAB

Privacy Policy
Learn Rust with the experts
Find out more