1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
use backtrace::{BytesOrWideString, PrintFmt};
use std::fmt::{self, Write};
#[inline(never)]
pub(crate) fn print(w: &mut dyn std::io::Write) -> Result<(), std::io::Error> {
write!(
w,
"{:?}",
Print {
print_fn_address: print as usize,
}
)
}
struct Print {
print_fn_address: usize,
}
impl fmt::Debug for Print {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
unsafe {
let mut print_fn_frame = 0;
let mut frame_count = 0;
backtrace::trace_unsynchronized(|frame| {
let found = frame.symbol_address() as usize == self.print_fn_address;
if found {
print_fn_frame = frame_count;
}
frame_count += 1;
!found
});
let mode = PrintFmt::Short;
let mut p = print_path;
let mut f = backtrace::BacktraceFmt::new(fmt, mode, &mut p);
f.add_context()?;
let mut result = Ok(());
let mut frame_count = 0;
backtrace::trace_unsynchronized(|frame| {
let skip = frame_count < print_fn_frame;
frame_count += 1;
if skip {
return true;
}
let mut frame_fmt = f.frame();
let mut any_symbol = false;
backtrace::resolve_frame_unsynchronized(frame, |symbol| {
any_symbol = true;
if let Err(e) = frame_fmt.symbol(frame, symbol) {
result = Err(e)
}
});
if !any_symbol {
if let Err(e) = frame_fmt.print_raw(frame.ip(), None, None, None) {
result = Err(e)
}
}
result.is_ok()
});
result?;
f.finish()
}
}
}
fn print_path(fmt: &mut fmt::Formatter, path: BytesOrWideString) -> fmt::Result {
match path {
BytesOrWideString::Bytes(mut bytes) => loop {
match std::str::from_utf8(bytes) {
Ok(s) => {
fmt.write_str(s)?;
break;
},
Err(err) => {
fmt.write_char(std::char::REPLACEMENT_CHARACTER)?;
match err.error_len() {
Some(len) => bytes = &bytes[err.valid_up_to() + len..],
None => break,
}
},
}
},
BytesOrWideString::Wide(wide) => {
for c in std::char::decode_utf16(wide.iter().cloned()) {
fmt.write_char(c.unwrap_or(std::char::REPLACEMENT_CHARACTER))?
}
},
}
Ok(())
}