Implemented errno in custom clib wrapper
This commit is contained in:
parent
77a7197718
commit
cc385b7252
|
|
@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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()) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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}")]
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue