cyfs_debug/panic/
panic.rs1use panic::PanicInfo;
2
3use backtrace::{Backtrace, BacktraceFrame};
4use sha2::Digest;
5use std::panic;
6use std::thread;
7use serde::{Serialize, Deserialize};
8
9#[derive(Clone, Debug, Serialize, Deserialize)]
10pub struct CyfsPanicInfo {
11 pub msg: String,
12 pub msg_with_symbol: String,
13 pub hash: String,
14}
15
16impl CyfsPanicInfo {
17 pub fn new(backtrace: Backtrace, info: &PanicInfo) -> Self {
18 let backtrace_msg = Self::format_backtrace(&backtrace);
19 let msg = Self::format_info(info, &backtrace_msg);
20
21 let backtrace_msg = Self::format_backtrace_with_symbol(&backtrace);
22 let msg_with_symbol = Self::format_info(info, &backtrace_msg);
23
24 let hash = Self::calc_hash(&backtrace);
25 let ret = Self {
26 msg,
27 msg_with_symbol,
28 hash,
29 };
30
31 warn!("{}", ret.msg);
32 warn!("{}", ret.msg_with_symbol);
33 ret
34 }
35
36 fn format_info(info: &PanicInfo, backtrace: &str) -> String {
37 let thread = thread::current();
38 let thread = thread.name().unwrap_or("unnamed");
39
40 let msg = match info.payload().downcast_ref::<&'static str>() {
41 Some(s) => *s,
42 None => match info.payload().downcast_ref::<String>() {
43 Some(s) => &**s,
44 None => "Box<Any>",
45 },
46 };
47
48 let msg = match info.location() {
49 Some(location) => {
50 format!(
51 "thread '{}' panicked at '{}': {}:{}\n{}",
52 thread,
53 msg,
54 location.file(),
55 location.line(),
56 backtrace,
57 )
58 }
59 None => {
60 format!(
61 "thread '{}' panicked at '{}'\n{}",
62 thread,
63 msg,
64 backtrace.clone()
65 )
66 }
67 };
68
69 msg
70 }
71
72 fn format_backtrace_with_symbol(backtrace: &Backtrace) -> String {
73 format!("{:?}", backtrace)
74 }
75
76 fn format_backtrace(backtrace: &Backtrace) -> String {
77 let frames: Vec<BacktraceFrame> = backtrace.clone().into();
78 let mut values = Vec::new();
79 for (i, frame) in frames.into_iter().enumerate() {
80 if let Some(mod_addr) = frame.module_base_address() {
81 let offset = frame.symbol_address() as isize - mod_addr as isize;
82 values.push(format!("{}: {:#018x} {:#018p}", i, offset, mod_addr));
83 } else {
84 values.push(format!("{}: {:#018p}", i, frame.symbol_address()));
85 }
86 }
87
88 values.join("\n")
89 }
90
91 fn calc_hash(backtrace: &Backtrace) -> String {
92 let mut sha256 = sha2::Sha256::new();
93
94 let frames: Vec<BacktraceFrame> = backtrace.clone().into();
95 let mut values = Vec::new();
96 for (i, frame) in frames.into_iter().enumerate() {
97 if let Some(mod_addr) = frame.module_base_address() {
98 let offset = frame.symbol_address() as isize - mod_addr as isize;
99 values.push(format!("{}:{}", i, offset));
100 } else {
101 values.push(format!("{}:{:p}", i, frame.symbol_address()));
102 }
103 }
104
105 let all = values.join("\n");
106
107 sha256.input(all);
108 let ret = sha256.result();
109 let hash = hex::encode(ret);
110
111 let hash = hash[..32].to_owned();
113
114 info!("stack_hash=\n{}", hash);
115
116 hash
117 }
118}