Custom ptrace: added peek/poke data
This commit is contained in:
parent
29e463aced
commit
e61f62487b
|
|
@ -13,6 +13,10 @@ unsafe fn errno() -> c_int {
|
||||||
unsafe { *__errno_location() }
|
unsafe { *__errno_location() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsafe fn set_errno(errno: c_int) {
|
||||||
|
unsafe { *__errno_location() = errno; }
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, thiserror::Error)]
|
#[derive(Debug, thiserror::Error)]
|
||||||
#[error("{}", self.error_message())]
|
#[error("{}", self.error_message())]
|
||||||
pub struct ErrnoError {
|
pub struct ErrnoError {
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::clibwrap::{ErrnoError, Pid};
|
use crate::clibwrap::{errno, set_errno, ErrnoError, Pid};
|
||||||
use bitflags::bitflags;
|
use bitflags::bitflags;
|
||||||
use std::ffi::{c_long, c_ulonglong, c_void};
|
use std::ffi::{c_long, c_ulonglong, c_void};
|
||||||
use std::mem::MaybeUninit;
|
use std::mem::MaybeUninit;
|
||||||
|
|
@ -6,6 +6,8 @@ use std::mem::MaybeUninit;
|
||||||
#[allow(non_camel_case_types)]
|
#[allow(non_camel_case_types)]
|
||||||
#[repr(u32)]
|
#[repr(u32)]
|
||||||
enum PTraceRequest {
|
enum PTraceRequest {
|
||||||
|
PTRACE_PEEKDATA = 2,
|
||||||
|
PTRACE_POKEDATA = 5,
|
||||||
PTRACE_CONT = 7,
|
PTRACE_CONT = 7,
|
||||||
PTRACE_SINGLESTEP = 9,
|
PTRACE_SINGLESTEP = 9,
|
||||||
PTRACE_GETREGS = 12,
|
PTRACE_GETREGS = 12,
|
||||||
|
|
@ -140,3 +142,25 @@ pub fn set_regs(pid: Pid, registers: registers) -> Result<(), ErrnoError> {
|
||||||
unsafe { Err(ErrnoError::from_current_errno()) }
|
unsafe { Err(ErrnoError::from_current_errno()) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn peek_data(pid: Pid, address: u64) -> Result<c_long, ErrnoError> {
|
||||||
|
unsafe {
|
||||||
|
set_errno(0);
|
||||||
|
let data = ptrace(PTraceRequest::PTRACE_PEEKDATA, pid, address as _, 0 as _);
|
||||||
|
let errno = errno();
|
||||||
|
if errno != 0 {
|
||||||
|
Err(ErrnoError::from_current_errno())
|
||||||
|
} else {
|
||||||
|
Ok(data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn poke_data(pid: Pid, address: u64, data: c_long) -> Result<(), ErrnoError> {
|
||||||
|
let return_code = unsafe { ptrace(PTraceRequest::PTRACE_POKEDATA, pid, address as _, data as _) };
|
||||||
|
if return_code == 0 {
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
unsafe { Err(ErrnoError::from_current_errno()) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,10 @@
|
||||||
use crate::clibwrap;
|
use crate::clibwrap;
|
||||||
use crate::debug_target::{CustomPTraceError, DebugError, PTraceError, RunningTarget, WaitError};
|
use crate::debug_target::{CustomPTraceError, DebugError, RunningTarget, WaitError};
|
||||||
use crate::syscall_info::{syscall_info, SyscallInfo, SyscallInfoError};
|
use crate::syscall_info::{syscall_info, SyscallInfo, SyscallInfoError};
|
||||||
use libc::c_long;
|
use libc::c_long;
|
||||||
use nix::sys::wait::{waitid, Id, WaitPidFlag};
|
use nix::sys::wait::{waitid, Id, WaitPidFlag};
|
||||||
use nix::unistd::Pid;
|
use nix::unistd::Pid;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::ffi::c_void;
|
|
||||||
|
|
||||||
pub struct StoppedTarget {
|
pub struct StoppedTarget {
|
||||||
pub pid: Pid,
|
pub pid: Pid,
|
||||||
|
|
@ -76,10 +75,10 @@ impl StoppedTarget {
|
||||||
if self.breakpoints.contains_key(&address) {
|
if self.breakpoints.contains_key(&address) {
|
||||||
return Err(DebugError::DuplicateBreakpoint { address });
|
return Err(DebugError::DuplicateBreakpoint { address });
|
||||||
}
|
}
|
||||||
let orig_bytes = nix::sys::ptrace::read(self.pid, address as *mut c_void).map_err(PTraceError)?;
|
let orig_bytes = clibwrap::ptrace::peek_data(self.pid.as_raw(), address).map_err(CustomPTraceError)?;
|
||||||
let target_byte: u8 = (orig_bytes & 0xFF as c_long) as u8;
|
let target_byte: u8 = (orig_bytes & 0xFF as c_long) as u8;
|
||||||
let new_content = (orig_bytes & (!0xff as c_long)) | (0xCC as c_long);
|
let new_content = (orig_bytes & (!0xff as c_long)) | (0xCC as c_long);
|
||||||
nix::sys::ptrace::write(self.pid, address as *mut c_void, new_content).map_err(PTraceError)?;
|
clibwrap::ptrace::poke_data(self.pid.as_raw(), address, new_content).map_err(CustomPTraceError)?;
|
||||||
|
|
||||||
self.breakpoints.insert(address, target_byte);
|
self.breakpoints.insert(address, target_byte);
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
@ -90,9 +89,9 @@ impl StoppedTarget {
|
||||||
match self.breakpoints.remove(&address) {
|
match self.breakpoints.remove(&address) {
|
||||||
None => Err(DebugError::NonExistingBreakpoint { address }),
|
None => Err(DebugError::NonExistingBreakpoint { address }),
|
||||||
Some(original_byte) => {
|
Some(original_byte) => {
|
||||||
let content = nix::sys::ptrace::read(self.pid, address as *mut c_void).map_err(PTraceError)?;
|
let content = clibwrap::ptrace::peek_data(self.pid.as_raw(), address).map_err(CustomPTraceError)?;
|
||||||
let new_content = (content & (!0xff as c_long)) | (original_byte as c_long);
|
let new_content = (content & (!0xff as c_long)) | (original_byte as c_long);
|
||||||
nix::sys::ptrace::write(self.pid, address as *mut c_void, new_content).map_err(PTraceError)?;
|
clibwrap::ptrace::poke_data(self.pid.as_raw(), address, new_content).map_err(CustomPTraceError)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue