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