Custom ptrace: added peek/poke data

This commit is contained in:
Elnath 2025-05-19 21:57:54 +02:00
parent 29e463aced
commit e61f62487b
3 changed files with 34 additions and 7 deletions

View File

@ -13,6 +13,10 @@ unsafe fn errno() -> c_int {
unsafe { *__errno_location() }
}
unsafe fn set_errno(errno: c_int) {
unsafe { *__errno_location() = errno; }
}
#[derive(Debug, thiserror::Error)]
#[error("{}", self.error_message())]
pub struct ErrnoError {

View File

@ -1,4 +1,4 @@
use crate::clibwrap::{ErrnoError, Pid};
use crate::clibwrap::{errno, set_errno, ErrnoError, Pid};
use bitflags::bitflags;
use std::ffi::{c_long, c_ulonglong, c_void};
use std::mem::MaybeUninit;
@ -6,6 +6,8 @@ use std::mem::MaybeUninit;
#[allow(non_camel_case_types)]
#[repr(u32)]
enum PTraceRequest {
PTRACE_PEEKDATA = 2,
PTRACE_POKEDATA = 5,
PTRACE_CONT = 7,
PTRACE_SINGLESTEP = 9,
PTRACE_GETREGS = 12,
@ -140,3 +142,25 @@ pub fn set_regs(pid: Pid, registers: registers) -> Result<(), ErrnoError> {
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()) }
}
}

View File

@ -1,11 +1,10 @@
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 libc::c_long;
use nix::sys::wait::{waitid, Id, WaitPidFlag};
use nix::unistd::Pid;
use std::collections::HashMap;
use std::ffi::c_void;
pub struct StoppedTarget {
pub pid: Pid,
@ -76,10 +75,10 @@ impl StoppedTarget {
if self.breakpoints.contains_key(&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 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);
Ok(())
@ -90,9 +89,9 @@ impl StoppedTarget {
match self.breakpoints.remove(&address) {
None => Err(DebugError::NonExistingBreakpoint { address }),
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);
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(())
}
}