1use std::collections::{HashMap, HashSet};
2
3use crate::types::*;
4
5#[derive(Debug)]
11pub struct CrashRustler {
12 pub pid: i32,
15 pub ppid: i32,
17 pub uid: u32,
19 pub task: u32,
21 pub process_name: Option<String>,
23 pub executable_path: Option<String>,
25 pub parent_process_name: Option<String>,
27 pub parent_executable_path: Option<String>,
29 pub responsible_process_name: Option<String>,
31 pub r_process_pid: i32,
33 pub date: Option<String>,
35
36 pub exception_type: i32,
39 pub exception_code: Vec<i64>,
41 pub exception_code_count: u32,
43 pub signal: u32,
45 pub crashing_address: u64,
47
48 pub thread: u32,
51 pub thread_id: Option<u64>,
53 pub crashed_thread_number: i32,
55 pub thread_state: ThreadState,
57 pub exception_state: ExceptionState,
59 pub thread_exception_state: Vec<u32>,
61 pub thread_exception_state_count: u32,
63 pub backtraces: Vec<ThreadBacktrace>,
65
66 pub cpu_type: CpuType,
69 pub is_64_bit: bool,
71 pub is_native: bool,
73 pub architecture: u64,
75
76 pub binary_images: Vec<BinaryImage>,
79 pub binary_image_hints: Vec<String>,
81 pub binary_uuid: Option<String>,
83 pub current_binary_image: Option<String>,
85 pub attempted_binary_images: HashSet<String>,
87 pub binary_image_error_count: u32,
89 pub binary_image_post_processing_complete: bool,
91 pub completed_all_binary_images: bool,
93 pub max_binary_identifier_length: u32,
95
96 pub environment: HashMap<String, String>,
99 pub notes: Option<String>,
101 pub process_version_dictionary: HashMap<String, String>,
103 pub build_version_dictionary: HashMap<String, String>,
105 pub os_version_dictionary: HashMap<String, String>,
107 pub adam_id: Option<String>,
109 pub software_version_external_identifier: Option<String>,
111 pub reopen_path: Option<String>,
113 pub ls_application_information: Option<HashMap<String, String>>,
116 pub has_receipt: bool,
118 pub is_translocated_process: bool,
120
121 pub application_specific_info: Option<String>,
124 pub application_specific_backtraces: Vec<String>,
126 pub application_specific_signature_strings: Vec<String>,
128 pub application_specific_dialog_mode: Option<String>,
130
131 pub internal_error: Option<String>,
134 pub rosetta_info: Option<String>,
136 pub dyld_error_string: Option<String>,
138 pub dyld_error_info: Option<String>,
140 pub extract_legacy_dyld_error_string: bool,
142 pub fatal_dyld_error_on_launch: bool,
144 pub exec_failure_error: Option<String>,
146
147 pub cs_status: u32,
150 pub code_sign_invalid_messages_description: Option<String>,
152
153 pub ext_mod_info: ExternalModInfo,
156
157 pub awake_system_uptime: u64,
160 pub sleep_wake_uuid: Option<String>,
162
163 pub sandbox_container: Option<String>,
166
167 pub vm_map_string: Option<String>,
170 pub vm_summary_string: Option<String>,
172
173 pub objc_selector_name: Option<String>,
176
177 pub third_party_bundle_path: Option<String>,
180 pub anon_uuid: Option<String>,
182 pub performing_autopsy: bool,
184 pub executable_path_needs_correction: bool,
186 pub process_name_needs_correction: bool,
188 pub in_update_previous_os_build: Option<String>,
190 pub item_info_record: Option<Vec<u8>>,
192 pub exit_snapshot: Option<Vec<u8>>,
194 pub exit_snapshot_length: u32,
196 pub exit_payload: Option<Vec<u8>>,
198 pub exit_payload_length: u32,
200 pub work_queue_limits: Option<WorkQueueLimits>,
202 pub terminator_pid: i32,
204 pub terminator_proc: Option<String>,
206 pub terminator_reason: Option<String>,
208}
209
210impl Default for CrashRustler {
211 fn default() -> Self {
212 Self {
213 pid: 0,
214 ppid: 0,
215 uid: 0,
216 task: 0,
217 process_name: None,
218 executable_path: None,
219 parent_process_name: None,
220 parent_executable_path: None,
221 responsible_process_name: None,
222 r_process_pid: 0,
223 date: None,
224 exception_type: 0,
225 exception_code: Vec::new(),
226 exception_code_count: 0,
227 signal: 0,
228 crashing_address: 0,
229 thread: 0,
230 thread_id: None,
231 crashed_thread_number: -1,
232 thread_state: ThreadState {
233 flavor: 0,
234 registers: Vec::new(),
235 },
236 exception_state: ExceptionState {
237 state: Vec::new(),
238 count: 0,
239 },
240 thread_exception_state: Vec::new(),
241 thread_exception_state_count: 0,
242 backtraces: Vec::new(),
243 cpu_type: CpuType(0),
244 is_64_bit: false,
245 is_native: false,
246 architecture: 0,
247 binary_images: Vec::new(),
248 binary_image_hints: Vec::new(),
249 binary_uuid: None,
250 current_binary_image: None,
251 attempted_binary_images: HashSet::new(),
252 binary_image_error_count: 0,
253 binary_image_post_processing_complete: false,
254 completed_all_binary_images: false,
255 max_binary_identifier_length: 0,
256 environment: HashMap::new(),
257 notes: None,
258 process_version_dictionary: HashMap::new(),
259 build_version_dictionary: HashMap::new(),
260 os_version_dictionary: HashMap::new(),
261 adam_id: None,
262 software_version_external_identifier: None,
263 reopen_path: None,
264 ls_application_information: None,
265 has_receipt: false,
266 is_translocated_process: false,
267 application_specific_info: None,
268 application_specific_backtraces: Vec::new(),
269 application_specific_signature_strings: Vec::new(),
270 application_specific_dialog_mode: None,
271 internal_error: None,
272 rosetta_info: None,
273 dyld_error_string: None,
274 dyld_error_info: None,
275 extract_legacy_dyld_error_string: false,
276 fatal_dyld_error_on_launch: false,
277 exec_failure_error: None,
278 cs_status: 0,
279 code_sign_invalid_messages_description: None,
280 ext_mod_info: ExternalModInfo {
281 description: None,
282 warnings: None,
283 dictionary: HashMap::new(),
284 },
285 awake_system_uptime: 0,
286 sleep_wake_uuid: None,
287 sandbox_container: None,
288 vm_map_string: None,
289 vm_summary_string: None,
290 objc_selector_name: None,
291 third_party_bundle_path: None,
292 anon_uuid: None,
293 performing_autopsy: false,
294 executable_path_needs_correction: false,
295 process_name_needs_correction: false,
296 in_update_previous_os_build: None,
297 item_info_record: None,
298 exit_snapshot: None,
299 exit_snapshot_length: 0,
300 exit_payload: None,
301 exit_payload_length: 0,
302 work_queue_limits: None,
303 terminator_pid: 0,
304 terminator_proc: None,
305 terminator_reason: None,
306 }
307 }
308}
309
310pub(crate) fn mac_roman_to_char(b: u8) -> char {
314 if b < 0x80 {
315 return b as char;
316 }
317 const MAC_ROMAN_HIGH: [u16; 128] = [
319 0x00C4, 0x00C5, 0x00C7, 0x00C9, 0x00D1, 0x00D6, 0x00DC, 0x00E1, 0x00E0, 0x00E2, 0x00E4, 0x00E3, 0x00E5, 0x00E7, 0x00E9, 0x00E8, 0x00EA, 0x00EB, 0x00ED, 0x00EC, 0x00EE, 0x00EF, 0x00F1, 0x00F3, 0x00F2, 0x00F4, 0x00F6, 0x00F5, 0x00FA, 0x00F9, 0x00FB, 0x00FC, 0x2020, 0x00B0, 0x00A2, 0x00A3, 0x00A7, 0x2022, 0x00B6, 0x00DF, 0x00AE, 0x00A9, 0x2122, 0x00B4, 0x00A8, 0x2260, 0x00C6, 0x00D8, 0x221E, 0x00B1, 0x2264, 0x2265, 0x00A5, 0x00B5, 0x2202, 0x2211, 0x220F, 0x03C0, 0x222B, 0x00AA, 0x00BA, 0x03A9, 0x00E6, 0x00F8, 0x00BF, 0x00A1, 0x00AC, 0x221A, 0x0192, 0x2248, 0x2206, 0x00AB, 0x00BB, 0x2026, 0x00A0, 0x00C0, 0x00C3, 0x00D5, 0x0152, 0x0153, 0x2013, 0x2014, 0x201C, 0x201D, 0x2018, 0x2019, 0x00F7, 0x25CA, 0x00FF, 0x0178, 0x2044, 0x20AC, 0x2039, 0x203A, 0xFB01, 0xFB02, 0x2021, 0x00B7, 0x201A, 0x201E, 0x2030, 0x00C2, 0x00CA, 0x00C1, 0x00CB, 0x00C8, 0x00CD, 0x00CE, 0x00CF, 0x00CC, 0x00D3, 0x00D4, 0xF8FF, 0x00D2, 0x00DA, 0x00DB, 0x00D9, 0x0131, 0x02C6, 0x02DC, 0x00AF, 0x02D8, 0x02D9, 0x02DA, 0x00B8, 0x02DD, 0x02DB, 0x02C7, ];
336 char::from_u32(MAC_ROMAN_HIGH[(b - 0x80) as usize] as u32).unwrap_or('?')
337}
338
339#[cfg(test)]
340mod tests {
341 use crate::*;
342
343 mod default_impl {
344 use super::*;
345
346 #[test]
347 fn all_fields_initialized() {
348 let cr = CrashRustler::default();
349 assert_eq!(cr.pid, 0);
350 assert_eq!(cr.ppid, 0);
351 assert_eq!(cr.uid, 0);
352 assert_eq!(cr.task, 0);
353 assert!(cr.process_name.is_none());
354 assert!(cr.executable_path.is_none());
355 assert!(cr.parent_process_name.is_none());
356 assert!(cr.parent_executable_path.is_none());
357 assert!(cr.responsible_process_name.is_none());
358 assert_eq!(cr.r_process_pid, 0);
359 assert!(cr.date.is_none());
360 assert_eq!(cr.exception_type, 0);
361 assert!(cr.exception_code.is_empty());
362 assert_eq!(cr.exception_code_count, 0);
363 assert_eq!(cr.signal, 0);
364 assert_eq!(cr.crashing_address, 0);
365 assert_eq!(cr.thread, 0);
366 assert!(cr.thread_id.is_none());
367 assert_eq!(cr.crashed_thread_number, -1);
368 assert_eq!(cr.thread_state.flavor, 0);
369 assert!(cr.thread_state.registers.is_empty());
370 assert!(cr.exception_state.state.is_empty());
371 assert_eq!(cr.exception_state.count, 0);
372 assert!(cr.backtraces.is_empty());
373 assert_eq!(cr.cpu_type, CpuType(0));
374 assert!(!cr.is_64_bit);
375 assert!(!cr.is_native);
376 assert_eq!(cr.architecture, 0);
377 assert!(cr.binary_images.is_empty());
378 assert!(cr.binary_image_hints.is_empty());
379 assert!(cr.binary_uuid.is_none());
380 assert!(cr.current_binary_image.is_none());
381 assert!(cr.attempted_binary_images.is_empty());
382 assert_eq!(cr.binary_image_error_count, 0);
383 assert!(!cr.binary_image_post_processing_complete);
384 assert!(!cr.completed_all_binary_images);
385 assert_eq!(cr.max_binary_identifier_length, 0);
386 assert!(cr.environment.is_empty());
387 assert!(cr.notes.is_none());
388 assert!(cr.process_version_dictionary.is_empty());
389 assert!(cr.build_version_dictionary.is_empty());
390 assert!(cr.os_version_dictionary.is_empty());
391 assert!(cr.adam_id.is_none());
392 assert!(cr.software_version_external_identifier.is_none());
393 assert!(cr.reopen_path.is_none());
394 assert!(cr.ls_application_information.is_none());
395 assert!(!cr.has_receipt);
396 assert!(!cr.is_translocated_process);
397 assert!(cr.application_specific_info.is_none());
398 assert!(cr.application_specific_backtraces.is_empty());
399 assert!(cr.application_specific_signature_strings.is_empty());
400 assert!(cr.application_specific_dialog_mode.is_none());
401 assert!(cr.internal_error.is_none());
402 assert!(cr.rosetta_info.is_none());
403 assert!(cr.dyld_error_string.is_none());
404 assert!(cr.dyld_error_info.is_none());
405 assert!(!cr.extract_legacy_dyld_error_string);
406 assert!(!cr.fatal_dyld_error_on_launch);
407 assert!(cr.exec_failure_error.is_none());
408 assert_eq!(cr.cs_status, 0);
409 assert!(cr.code_sign_invalid_messages_description.is_none());
410 assert!(cr.ext_mod_info.description.is_none());
411 assert!(cr.ext_mod_info.warnings.is_none());
412 assert!(cr.ext_mod_info.dictionary.is_empty());
413 assert_eq!(cr.awake_system_uptime, 0);
414 assert!(cr.sleep_wake_uuid.is_none());
415 assert!(cr.sandbox_container.is_none());
416 assert!(cr.vm_map_string.is_none());
417 assert!(cr.vm_summary_string.is_none());
418 assert!(cr.objc_selector_name.is_none());
419 assert!(cr.third_party_bundle_path.is_none());
420 assert!(cr.anon_uuid.is_none());
421 assert!(!cr.performing_autopsy);
422 assert!(!cr.executable_path_needs_correction);
423 assert!(!cr.process_name_needs_correction);
424 assert!(cr.in_update_previous_os_build.is_none());
425 assert!(cr.item_info_record.is_none());
426 assert!(cr.exit_snapshot.is_none());
427 assert_eq!(cr.exit_snapshot_length, 0);
428 assert!(cr.exit_payload.is_none());
429 assert_eq!(cr.exit_payload_length, 0);
430 assert!(cr.work_queue_limits.is_none());
431 assert_eq!(cr.terminator_pid, 0);
432 assert!(cr.terminator_proc.is_none());
433 assert!(cr.terminator_reason.is_none());
434 }
435 }
436}