diff options
Diffstat (limited to 'third_party/rust/mach/examples')
-rw-r--r-- | third_party/rust/mach/examples/dump_process_registers.rs | 136 |
1 files changed, 136 insertions, 0 deletions
diff --git a/third_party/rust/mach/examples/dump_process_registers.rs b/third_party/rust/mach/examples/dump_process_registers.rs new file mode 100644 index 0000000000..c426e583e0 --- /dev/null +++ b/third_party/rust/mach/examples/dump_process_registers.rs @@ -0,0 +1,136 @@ +//! A script to read and dump to stdout the current register values of a +//! process. + +extern crate libc; +extern crate mach; + +use std::io; +use std::mem; +use std::ptr; + +use mach::kern_return::KERN_SUCCESS; +use mach::mach_types::{task_t, thread_act_array_t}; +use mach::message::mach_msg_type_number_t; +use mach::port::mach_port_name_t; +use mach::structs::x86_thread_state64_t; +use mach::task::{task_resume, task_suspend, task_threads}; +use mach::thread_act::thread_get_state; +use mach::thread_status::x86_THREAD_STATE64; +use mach::traps::{mach_task_self, task_for_pid}; + +use std::io::prelude::*; + +fn read_int() -> Result<::libc::c_int, ()> { + let stdin = io::stdin(); + let mut line = String::new(); + + stdin.read_line(&mut line).ok().unwrap(); + let mut value: ::libc::c_int = 0; + + for c in line.chars().take_while(|&c| c != '\n') { + if let Some(d) = c.to_digit(10) { + value = value * 10 + (d as ::libc::c_int); + } else { + return Err(()); + } + } + return Ok(value); +} + +fn resume(task: task_t) { + unsafe { + let kret = task_resume(task); + if kret != KERN_SUCCESS { + println!("Did not succeed in resuming task."); + println!("kern_return_t error {}", kret); + panic!(); + } + } +} + +fn main() { + print!("Enter pid: "); + io::stdout().flush().ok(); + + let pid = match read_int() { + Ok(v) => v, + Err(_) => { + println!("Bad pid!"); + return; + } + }; + + println!("pid = {}", &pid); + + let task: mach_port_name_t = 0; + unsafe { + let kret = task_for_pid( + mach_task_self() as mach_port_name_t, + pid, + mem::transmute(&task), + ); + if kret != KERN_SUCCESS { + println!("Did not succeed in getting task for pid {}", pid); + println!("kern_return_t error {}", kret); + println!(""); + println!("Did you forget to run with 'sudo'? This script will"); + println!("probably fail without it."); + return; + } + } + + println!("task = 0x{:x}", &task); + + unsafe { + let kret = task_suspend(task as task_t); + if kret != KERN_SUCCESS { + println!("Did not succeed in suspending task."); + println!("kern_return_t error {}", kret); + return; + } + } + + let thread_list: thread_act_array_t = ptr::null_mut(); + let thread_count: mach_msg_type_number_t = 0; + unsafe { + let kret = task_threads( + task as task_t, + mem::transmute(&thread_list), + mem::transmute(&thread_count), + ); + if kret != KERN_SUCCESS { + println!("Did not succeed in getting task's threads"); + println!("kern_return_t error {}", kret); + resume(task as task_t); + return; + } + } + + println!("Task is running {} threads", &thread_count); + + unsafe { + let threads = + Vec::from_raw_parts(thread_list, thread_count as usize, thread_count as usize); + let state = x86_thread_state64_t::new(); + let state_count = x86_thread_state64_t::count(); + for (idx, &thread) in threads.iter().enumerate() { + println!("Thread {}:", idx); + let kret = thread_get_state( + thread, + x86_THREAD_STATE64, + mem::transmute(&state), + mem::transmute(&state_count), + ); + if kret != KERN_SUCCESS { + println!("Did not succeed in getting task's thread state"); + println!("kern_return_t error {}", kret); + continue; + } + + println!("{:?}", state); + } + } + + resume(task as task_t); + println!("Success!"); +} |