From cc385b725286751324c8a411ad200cadc1417bb4 Mon Sep 17 00:00:00 2001 From: Elnath Date: Mon, 19 May 2025 20:17:47 +0200 Subject: [PATCH] Implemented errno in custom clib wrapper --- src/clibwrap/mod.rs | 45 +++++++++++++++++++++++++++++++++++------ src/clibwrap/ptrace.rs | 18 ++++++++--------- src/debug_target/mod.rs | 4 ++-- 3 files changed, 50 insertions(+), 17 deletions(-) diff --git a/src/clibwrap/mod.rs b/src/clibwrap/mod.rs index e613ce5..d8516f5 100644 --- a/src/clibwrap/mod.rs +++ b/src/clibwrap/mod.rs @@ -1,11 +1,44 @@ -use std::ffi::c_long; - +use std::ffi::{c_char, c_int, CStr}; pub mod ptrace; type Pid = i32; -#[derive(Debug, thiserror::Error)] -#[error("Some kind of error when calling into C code: return code {error_code}")] -pub struct CError { - error_code: c_long, +unsafe extern "C" { + fn __errno_location() -> *mut c_int; + fn strerror(errnum: c_int) -> *const c_char; + 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) + } + } } diff --git a/src/clibwrap/ptrace.rs b/src/clibwrap/ptrace.rs index fc20fa5..511caf4 100644 --- a/src/clibwrap/ptrace.rs +++ b/src/clibwrap/ptrace.rs @@ -1,4 +1,4 @@ -use crate::clibwrap::{CError, Pid}; +use crate::clibwrap::{ErrnoError, Pid}; use bitflags::bitflags; 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; } -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 _) }; if return_code == 0 { Ok(()) } 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 _) }; if return_code == 0 { Ok(()) } 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 _) }; if return_code == 0 { Ok(()) } 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 _) }; if return_code == 0 { Ok(()) } else { - Err(CError { error_code: return_code }) + unsafe { Err(ErrnoError::from_current_errno()) } } } diff --git a/src/debug_target/mod.rs b/src/debug_target/mod.rs index 1433eb5..f3495d2 100644 --- a/src/debug_target/mod.rs +++ b/src/debug_target/mod.rs @@ -11,8 +11,8 @@ pub use stopped_target::*; pub struct PTraceError(#[from] nix::errno::Errno); #[derive(thiserror::Error, Debug)] -#[error(transparent)] -pub struct CustomPTraceError(#[from] clibwrap::CError); +#[error("Error when calling ptrace: {0}")] +pub struct CustomPTraceError(#[from] clibwrap::ErrnoError); #[derive(thiserror::Error, Debug)] #[error("Error when waiting on child process: {0}")]