Implemented errno in custom clib wrapper

This commit is contained in:
Elnath 2025-05-19 20:17:47 +02:00
parent 77a7197718
commit cc385b7252
3 changed files with 50 additions and 17 deletions

View File

@ -1,11 +1,44 @@
use std::ffi::c_long; use std::ffi::{c_char, c_int, CStr};
pub mod ptrace; pub mod ptrace;
type Pid = i32; type Pid = i32;
#[derive(Debug, thiserror::Error)] unsafe extern "C" {
#[error("Some kind of error when calling into C code: return code {error_code}")] fn __errno_location() -> *mut c_int;
pub struct CError { fn strerror(errnum: c_int) -> *const c_char;
error_code: c_long, fn strerrorname_np(errnum: c_int) -> *const c_char;
}
unsafe fn errno() -> c_int {
unsafe { *__errno_location() }
}
#[derive(Debug, thiserror::Error)]
#[error("{}", self.error_message())]
pub struct ErrnoError {
errno: i32,
}
impl ErrnoError {
pub unsafe fn from_current_errno() -> Self {
unsafe { Self { errno: errno() } }
}
fn error_message(&self) -> String {
unsafe {
let error_name = {
let c_error_name = strerrorname_np(self.errno);
if c_error_name.is_null() {
"???"
} else {
&CStr::from_ptr(c_error_name).to_string_lossy().into_owned()
}
};
let error_message = {
let c_str = strerror(self.errno);
CStr::from_ptr(c_str).to_string_lossy().into_owned()
};
format!("{}: {}", error_name, error_message)
}
}
} }

View File

@ -1,4 +1,4 @@
use crate::clibwrap::{CError, Pid}; use crate::clibwrap::{ErrnoError, Pid};
use bitflags::bitflags; use bitflags::bitflags;
use std::ffi::{c_long, c_void}; use std::ffi::{c_long, c_void};
@ -15,30 +15,30 @@ unsafe extern "C" {
fn ptrace(request: PTraceRequest, pid: Pid, addr: *mut c_void, data: *mut c_void) -> c_long; fn ptrace(request: PTraceRequest, pid: Pid, addr: *mut c_void, data: *mut c_void) -> c_long;
} }
pub fn cont(pid: Pid) -> Result<(), CError> { pub fn cont(pid: Pid) -> Result<(), ErrnoError> {
let return_code = unsafe { ptrace(PTraceRequest::PTRACE_CONT, pid, 0 as _, 0 as _) }; let return_code = unsafe { ptrace(PTraceRequest::PTRACE_CONT, pid, 0 as _, 0 as _) };
if return_code == 0 { if return_code == 0 {
Ok(()) Ok(())
} else { } else {
Err(CError { error_code: return_code }) unsafe { Err(ErrnoError::from_current_errno()) }
} }
} }
pub fn single_step(pid: Pid) -> Result<(), CError> { pub fn single_step(pid: Pid) -> Result<(), ErrnoError> {
let return_code = unsafe { ptrace(PTraceRequest::PTRACE_SINGLESTEP, pid, 0 as _, 0 as _) }; let return_code = unsafe { ptrace(PTraceRequest::PTRACE_SINGLESTEP, pid, 0 as _, 0 as _) };
if return_code == 0 { if return_code == 0 {
Ok(()) Ok(())
} else { } else {
Err(CError { error_code: return_code }) unsafe { Err(ErrnoError::from_current_errno()) }
} }
} }
pub fn syscall(pid: Pid) -> Result<(), CError> { pub fn syscall(pid: Pid) -> Result<(), ErrnoError> {
let return_code = unsafe { ptrace(PTraceRequest::PTRACE_SYSCALL, pid, 0 as _, 0 as _) }; let return_code = unsafe { ptrace(PTraceRequest::PTRACE_SYSCALL, pid, 0 as _, 0 as _) };
if return_code == 0 { if return_code == 0 {
Ok(()) Ok(())
} else { } else {
Err(CError { error_code: return_code }) unsafe { Err(ErrnoError::from_current_errno()) }
} }
} }
@ -50,11 +50,11 @@ bitflags! {
} }
} }
pub fn set_options(pid: Pid, options: PTraceOptions) -> Result<(), CError> { pub fn set_options(pid: Pid, options: PTraceOptions) -> Result<(), ErrnoError> {
let return_code = unsafe { ptrace(PTraceRequest::PTRACE_SETOPTIONS, pid, 0 as _, options.bits() as _) }; let return_code = unsafe { ptrace(PTraceRequest::PTRACE_SETOPTIONS, pid, 0 as _, options.bits() as _) };
if return_code == 0 { if return_code == 0 {
Ok(()) Ok(())
} else { } else {
Err(CError { error_code: return_code }) unsafe { Err(ErrnoError::from_current_errno()) }
} }
} }

View File

@ -11,8 +11,8 @@ pub use stopped_target::*;
pub struct PTraceError(#[from] nix::errno::Errno); pub struct PTraceError(#[from] nix::errno::Errno);
#[derive(thiserror::Error, Debug)] #[derive(thiserror::Error, Debug)]
#[error(transparent)] #[error("Error when calling ptrace: {0}")]
pub struct CustomPTraceError(#[from] clibwrap::CError); pub struct CustomPTraceError(#[from] clibwrap::ErrnoError);
#[derive(thiserror::Error, Debug)] #[derive(thiserror::Error, Debug)]
#[error("Error when waiting on child process: {0}")] #[error("Error when waiting on child process: {0}")]