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
106
107
108
109
110
111
112
113
114
115
116
117
118
use panic::PanicInfo;
use backtrace::{Backtrace, BacktraceFrame};
use sha2::Digest;
use std::panic;
use std::thread;
use serde::{Serialize, Deserialize};
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct CyfsPanicInfo {
pub msg: String,
pub msg_with_symbol: String,
pub hash: String,
}
impl CyfsPanicInfo {
pub fn new(backtrace: Backtrace, info: &PanicInfo) -> Self {
let backtrace_msg = Self::format_backtrace(&backtrace);
let msg = Self::format_info(info, &backtrace_msg);
let backtrace_msg = Self::format_backtrace_with_symbol(&backtrace);
let msg_with_symbol = Self::format_info(info, &backtrace_msg);
let hash = Self::calc_hash(&backtrace);
let ret = Self {
msg,
msg_with_symbol,
hash,
};
info!("{}", ret.msg);
info!("{}", ret.msg_with_symbol);
ret
}
fn format_info(info: &PanicInfo, backtrace: &str) -> String {
let thread = thread::current();
let thread = thread.name().unwrap_or("unnamed");
let msg = match info.payload().downcast_ref::<&'static str>() {
Some(s) => *s,
None => match info.payload().downcast_ref::<String>() {
Some(s) => &**s,
None => "Box<Any>",
},
};
let msg = match info.location() {
Some(location) => {
format!(
"thread '{}' panicked at '{}': {}:{}\n{}",
thread,
msg,
location.file(),
location.line(),
backtrace,
)
}
None => {
format!(
"thread '{}' panicked at '{}'\n{}",
thread,
msg,
backtrace.clone()
)
}
};
msg
}
fn format_backtrace_with_symbol(backtrace: &Backtrace) -> String {
format!("{:?}", backtrace)
}
fn format_backtrace(backtrace: &Backtrace) -> String {
let frames: Vec<BacktraceFrame> = backtrace.clone().into();
let mut values = Vec::new();
for (i, frame) in frames.into_iter().enumerate() {
if let Some(mod_addr) = frame.module_base_address() {
let offset = frame.symbol_address() as isize - mod_addr as isize;
values.push(format!("{}: {:#018x} {:#018p}", i, offset, mod_addr));
} else {
values.push(format!("{}: {:#018p}", i, frame.symbol_address()));
}
}
values.join("\n")
}
fn calc_hash(backtrace: &Backtrace) -> String {
let mut sha256 = sha2::Sha256::new();
let frames: Vec<BacktraceFrame> = backtrace.clone().into();
let mut values = Vec::new();
for (i, frame) in frames.into_iter().enumerate() {
if let Some(mod_addr) = frame.module_base_address() {
let offset = frame.symbol_address() as isize - mod_addr as isize;
values.push(format!("{}:{}", i, offset));
} else {
values.push(format!("{}:{:p}", i, frame.symbol_address()));
}
}
let all = values.join("\n");
sha256.input(all);
let ret = sha256.result();
let hash = hex::encode(ret);
let hash = hash[..32].to_owned();
info!("stack_hash=\n{}", hash);
hash
}
}