Coverage Report

Created: 2025-02-25 06:39

/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
}