1use crate::crash_rustler::CrashRustler;
2use crate::types::*;
3
4impl CrashRustler {
5 pub fn new(params: CrashParams) -> Self {
13 let exception_code_count = params.exception_codes.len() as u32;
14 let mut cr = Self {
15 task: params.task,
16 pid: params.pid,
17 ppid: params.ppid,
18 uid: params.uid,
19 is_64_bit: params.is_64_bit,
20 thread: params.thread,
21 thread_state: params.thread_state,
22 exception_state: params.exception_state,
23 process_name: params.process_name,
24 executable_path: params.executable_path,
25 r_process_pid: params.r_process_pid,
26 date: params.date,
27 awake_system_uptime: params.awake_system_uptime,
28 cpu_type: params.cpu_type,
29 crashed_thread_number: -1,
30 performing_autopsy: false,
31 is_native: true,
32 exception_type: params.exception_type,
33 exception_code_count,
34 exception_code: params.exception_codes,
35 ..Default::default()
36 };
37
38 if cr.exception_type == 10 && !cr.exception_code.is_empty() {
41 let code0 = cr.exception_code[0] as u64;
42 let embedded_type = ((code0 >> 20) & 0xf) as i32;
43 if embedded_type != 0 {
44 cr.exception_type = embedded_type;
45 }
46 cr.signal = ((code0 >> 24) & 0xff) as u32;
47 cr.exception_code[0] = (cr.exception_code[0] as u64 & 0xf_ffff) as i64;
49 }
50
51 cr
52 }
53
54 #[allow(clippy::too_many_arguments)]
58 pub fn new_from_corpse(
59 _corpse: u64,
60 _length: u64,
61 _task: u32,
62 _exception_type: i32,
63 _exception_codes: &[i64],
64 _thread: u32,
65 _thread_state_flavor: u32,
66 _thread_state: &[u32],
67 ) -> Option<Self> {
68 None
70 }
71}
72
73#[cfg(test)]
74mod tests {
75 use super::*;
76
77 fn make_params() -> CrashParams {
78 CrashParams {
79 task: 100,
80 pid: 1234,
81 ppid: 1,
82 uid: 501,
83 is_64_bit: true,
84 thread: 200,
85 thread_state: ThreadState {
86 flavor: 6,
87 registers: vec![],
88 },
89 exception_state: ExceptionState {
90 state: vec![],
91 count: 0,
92 },
93 process_name: Some("test".to_string()),
94 executable_path: Some("/usr/bin/test".to_string()),
95 r_process_pid: 0,
96 date: Some("2026-03-23".to_string()),
97 awake_system_uptime: 1000,
98 cpu_type: CpuType::ARM64,
99 exception_type: 1, exception_codes: vec![2, 0x42],
101 }
102 }
103
104 #[test]
105 fn new_populates_basic_fields() {
106 let params = make_params();
107 let cr = CrashRustler::new(params);
108 assert_eq!(cr.task, 100);
109 assert_eq!(cr.pid, 1234);
110 assert_eq!(cr.ppid, 1);
111 assert_eq!(cr.uid, 501);
112 assert!(cr.is_64_bit);
113 assert_eq!(cr.thread, 200);
114 assert_eq!(cr.process_name, Some("test".to_string()));
115 assert_eq!(cr.executable_path, Some("/usr/bin/test".to_string()));
116 assert_eq!(cr.cpu_type, CpuType::ARM64);
117 assert_eq!(cr.exception_type, 1);
118 assert_eq!(cr.exception_code, vec![2, 0x42]);
119 assert_eq!(cr.exception_code_count, 2);
120 }
121
122 #[test]
123 fn new_sets_defaults_for_derived_fields() {
124 let cr = CrashRustler::new(make_params());
125 assert_eq!(cr.crashed_thread_number, -1);
126 assert!(!cr.performing_autopsy);
127 assert!(cr.is_native);
128 assert_eq!(cr.signal, 0);
129 }
130
131 #[test]
132 fn new_exc_crash_extracts_embedded_type() {
133 let mut params = make_params();
134 params.exception_type = 10; params.exception_codes = vec![((11i64 << 24) | (1i64 << 20) | 0x42), 0];
138 let cr = CrashRustler::new(params);
139 assert_eq!(cr.exception_type, 1); assert_eq!(cr.signal, 11); assert_eq!(cr.exception_code[0], 0x42); }
143
144 #[test]
145 fn new_exc_crash_zero_embedded_type_preserves_type_10() {
146 let mut params = make_params();
147 params.exception_type = 10;
148 params.exception_codes = vec![((6i64 << 24) | 0), 0];
150 let cr = CrashRustler::new(params);
151 assert_eq!(cr.exception_type, 10);
152 assert_eq!(cr.signal, 6); }
154
155 #[test]
156 fn new_exc_crash_empty_codes_no_panic() {
157 let mut params = make_params();
158 params.exception_type = 10;
159 params.exception_codes = vec![];
160 let cr = CrashRustler::new(params);
161 assert_eq!(cr.exception_type, 10); }
163
164 #[test]
165 fn new_non_crash_exception_no_signal_extraction() {
166 let mut params = make_params();
167 params.exception_type = 1; params.exception_codes = vec![0x0b10_0042, 0]; let cr = CrashRustler::new(params);
170 assert_eq!(cr.exception_type, 1); assert_eq!(cr.signal, 0); assert_eq!(cr.exception_code[0], 0x0b10_0042); }
174
175 #[test]
176 fn new_from_corpse_returns_none() {
177 let result = CrashRustler::new_from_corpse(0, 0, 0, 0, &[], 0, 0, &[]);
178 assert!(result.is_none());
179 }
180}