Added syscall and options to custom ptrace wrapper

This commit is contained in:
Elnath 2025-05-18 23:33:44 +02:00
parent c7bf8c341c
commit 77a7197718
5 changed files with 44 additions and 9 deletions

5
Cargo.lock generated
View File

@ -36,6 +36,7 @@ dependencies = [
name = "bdb"
version = "0.0.0"
dependencies = [
"bitflags",
"color-eyre",
"derive_more",
"either",
@ -46,9 +47,9 @@ dependencies = [
[[package]]
name = "bitflags"
version = "2.9.0"
version = "2.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd"
checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967"
[[package]]
name = "cc"

View File

@ -11,6 +11,7 @@ color-eyre = "0.6.3"
either = "1.15.0"
libc = "0.2.172"
derive_more = { version = "2.0.1", features = ["debug"] }
bitflags = "2.9.1"
[build-dependencies]
color-eyre = "0.6.3"

View File

@ -1,4 +1,5 @@
use crate::clibwrap::{CError, Pid};
use bitflags::bitflags;
use std::ffi::{c_long, c_void};
#[allow(non_camel_case_types)]
@ -6,6 +7,8 @@ use std::ffi::{c_long, c_void};
enum PTraceRequest {
PTRACE_CONT = 7,
PTRACE_SINGLESTEP = 9,
PTRACE_SYSCALL = 24,
PTRACE_SETOPTIONS = 0x4200,
}
unsafe extern "C" {
@ -29,3 +32,29 @@ pub fn single_step(pid: Pid) -> Result<(), CError> {
Err(CError { error_code: return_code })
}
}
pub fn syscall(pid: Pid) -> Result<(), CError> {
let return_code = unsafe { ptrace(PTraceRequest::PTRACE_SYSCALL, pid, 0 as _, 0 as _) };
if return_code == 0 {
Ok(())
} else {
Err(CError { error_code: return_code })
}
}
bitflags! {
#[derive(Debug)]
pub struct PTraceOptions: u32 {
const PTRACE_O_TRACESYSGOOD = 1;
// Other variants not implemented
}
}
pub fn set_options(pid: Pid, options: PTraceOptions) -> Result<(), CError> {
let return_code = unsafe { ptrace(PTraceRequest::PTRACE_SETOPTIONS, pid, 0 as _, options.bits() as _) };
if return_code == 0 {
Ok(())
} else {
Err(CError { error_code: return_code })
}
}

View File

@ -10,6 +10,10 @@ pub use stopped_target::*;
#[error("Error when calling ptrace: {0}")]
pub struct PTraceError(#[from] nix::errno::Errno);
#[derive(thiserror::Error, Debug)]
#[error(transparent)]
pub struct CustomPTraceError(#[from] clibwrap::CError);
#[derive(thiserror::Error, Debug)]
#[error("Error when waiting on child process: {0}")]
pub struct WaitError(#[from] nix::errno::Errno);
@ -20,7 +24,7 @@ pub enum DebugError {
PTraceError(#[from] PTraceError),
#[error(transparent)]
CustomPTraceError(#[from] clibwrap::CError),
CustomPTraceError(#[from] CustomPTraceError),
#[error(transparent)]
WaitError(#[from] WaitError),

View File

@ -1,5 +1,5 @@
use crate::clibwrap;
use crate::debug_target::{DebugError, PTraceError, RunningTarget, WaitError};
use crate::debug_target::{CustomPTraceError, DebugError, PTraceError, RunningTarget, WaitError};
use crate::syscall_info::{syscall_info, SyscallInfo, SyscallInfoError};
use libc::{c_long, user_regs_struct};
use nix::sys::wait::{waitid, Id, WaitPidFlag};
@ -22,7 +22,7 @@ impl StoppedTarget {
pub fn new(pid: Pid) -> Result<Self, DebugError> {
waitid(Id::Pid(pid), WaitPidFlag::WSTOPPED).map_err(WaitError)?;
// Needed for waiting on syscalls and apparently also for getting syscall info (can not get it to work without this)
nix::sys::ptrace::setoptions(pid, nix::sys::ptrace::Options::PTRACE_O_TRACESYSGOOD).map_err(PTraceError)?;
clibwrap::ptrace::set_options(pid.as_raw(), clibwrap::ptrace::PTraceOptions::PTRACE_O_TRACESYSGOOD).map_err(CustomPTraceError)?;
Ok(Self { pid, breakpoints: HashMap::new() })
}
@ -43,7 +43,7 @@ impl StoppedTarget {
if self.on_breakpoint()? {
self.breakpoint_remove_and_rewind()?;
}
clibwrap::ptrace::cont(self.pid.as_raw())?;
clibwrap::ptrace::cont(self.pid.as_raw()).map_err(CustomPTraceError)?;
Ok(self.to_running())
}
@ -51,7 +51,7 @@ impl StoppedTarget {
if self.on_breakpoint()? {
self.breakpoint_remove_and_rewind()?;
}
clibwrap::ptrace::single_step(self.pid.as_raw())?;
clibwrap::ptrace::single_step(self.pid.as_raw()).map_err(CustomPTraceError)?;
Ok(self.to_running())
}
@ -59,7 +59,7 @@ impl StoppedTarget {
if self.on_breakpoint()? {
self.breakpoint_remove_and_rewind()?;
}
nix::sys::ptrace::syscall(self.pid, None).map_err(PTraceError)?;
clibwrap::ptrace::syscall(self.pid.as_raw()).map_err(CustomPTraceError)?;
Ok(self.to_running())
}