1 //! A script to read and dump to stdout the current register values of a
2 //! process.
3 
4 extern crate libc;
5 extern crate mach;
6 
7 use std::io;
8 use std::mem;
9 use std::ptr;
10 
11 use mach::kern_return::KERN_SUCCESS;
12 use mach::mach_types::{task_t, thread_act_array_t};
13 use mach::message::mach_msg_type_number_t;
14 use mach::port::mach_port_name_t;
15 use mach::structs::x86_thread_state64_t;
16 use mach::task::{task_resume, task_suspend, task_threads};
17 use mach::thread_act::thread_get_state;
18 use mach::thread_status::x86_THREAD_STATE64;
19 use mach::traps::{mach_task_self, task_for_pid};
20 
21 use std::io::prelude::*;
22 
read_int() -> Result<::libc::c_int, ()>23 fn read_int() -> Result<::libc::c_int, ()> {
24     let stdin = io::stdin();
25     let mut line = String::new();
26 
27     stdin.read_line(&mut line).ok().unwrap();
28     let mut value: ::libc::c_int = 0;
29 
30     for c in line.chars().take_while(|&c| c != '\n') {
31         if let Some(d) = c.to_digit(10) {
32             value = value * 10 + (d as ::libc::c_int);
33         } else {
34             return Err(());
35         }
36     }
37     return Ok(value);
38 }
39 
resume(task: task_t)40 fn resume(task: task_t) {
41     unsafe {
42         let kret = task_resume(task);
43         if kret != KERN_SUCCESS {
44             println!("Did not succeed in resuming task.");
45             println!("kern_return_t error {}", kret);
46             panic!();
47         }
48     }
49 }
50 
main()51 fn main() {
52     print!("Enter pid: ");
53     io::stdout().flush().ok();
54 
55     let pid = match read_int() {
56         Ok(v) => v,
57         Err(_) => {
58             println!("Bad pid!");
59             return;
60         }
61     };
62 
63     println!("pid = {}", &pid);
64 
65     let task: mach_port_name_t = 0;
66     unsafe {
67         let kret = task_for_pid(
68             mach_task_self() as mach_port_name_t,
69             pid,
70             mem::transmute(&task),
71         );
72         if kret != KERN_SUCCESS {
73             println!("Did not succeed in getting task for pid {}", pid);
74             println!("kern_return_t error {}", kret);
75             println!("");
76             println!("Did you forget to run with 'sudo'? This script will");
77             println!("probably fail without it.");
78             return;
79         }
80     }
81 
82     println!("task = 0x{:x}", &task);
83 
84     unsafe {
85         let kret = task_suspend(task as task_t);
86         if kret != KERN_SUCCESS {
87             println!("Did not succeed in suspending task.");
88             println!("kern_return_t error {}", kret);
89             return;
90         }
91     }
92 
93     let thread_list: thread_act_array_t = ptr::null_mut();
94     let thread_count: mach_msg_type_number_t = 0;
95     unsafe {
96         let kret = task_threads(
97             task as task_t,
98             mem::transmute(&thread_list),
99             mem::transmute(&thread_count),
100         );
101         if kret != KERN_SUCCESS {
102             println!("Did not succeed in getting task's threads");
103             println!("kern_return_t error {}", kret);
104             resume(task as task_t);
105             return;
106         }
107     }
108 
109     println!("Task is running {} threads", &thread_count);
110 
111     unsafe {
112         let threads =
113             Vec::from_raw_parts(thread_list, thread_count as usize, thread_count as usize);
114         let state = x86_thread_state64_t::new();
115         let state_count = x86_thread_state64_t::count();
116         for (idx, &thread) in threads.iter().enumerate() {
117             println!("Thread {}:", idx);
118             let kret = thread_get_state(
119                 thread,
120                 x86_THREAD_STATE64,
121                 mem::transmute(&state),
122                 mem::transmute(&state_count),
123             );
124             if kret != KERN_SUCCESS {
125                 println!("Did not succeed in getting task's thread state");
126                 println!("kern_return_t error {}", kret);
127                 continue;
128             }
129 
130             println!("{:?}", state);
131         }
132     }
133 
134     resume(task as task_t);
135     println!("Success!");
136 }
137