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