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