libinject/drwrap.rs
1use crate::ffi;
2use crate::utils::Boolean;
3use std::os::raw::{c_int, c_void};
4
5/// Return value type for dr_wrap functions (e.g. `skip_call` and `set_retval`).
6///
7/// Not all functions return an `int`, this enum will be extended if/when new functions are wrapped
8/// that do not return an `int` (e.g. "gethostbyaddr returns a pointer to the hostent structure" or
9/// "accept returns a value of type SOCKET that is a descriptor for the new socket", quotes from
10/// the winsock2 docs, https://learn.microsoft.com/en-us/windows/win32/api/winsock2).
11#[derive(Debug, Clone)]
12pub enum Retval {
13 Int(i32),
14}
15
16impl Into<*mut c_void> for Retval {
17 fn into(self) -> *mut c_void {
18 match self {
19 Retval::Int(int) => int as *mut c_void,
20 }
21 }
22}
23
24/// Sets the return value for a function that is being wrapped with the dynamorio drwrap extension.
25/// May only be called from within a drwrap-pre or drwrap-post callback.
26pub fn set_retval(wrapctx: *mut c_void, retval: Retval) -> bool {
27 unsafe { ffi::drwrap_set_retval(wrapctx, retval.into()).as_bool() }
28}
29
30/// May only be called from a \p drwrap_wrap pre-function callback.
31/// Skips execution of the original function and returns to the function's caller with a return value of \p retval.
32///
33/// The post-function callback will not be invoked; nor will any pre-function callbacks (if multiple were registered) that have not yet been called. If the original function uses the "stdcall" calling convention, the total size of its arguments must be supplied. The return value is set regardless of whether the original function officially returns a value or not. Further state changes may be made with drwrap_get_mcontext() and drwrap_set_mcontext() prior to calling this function.
34///
35/// Note: It is up to the client to ensure that the application behaves as desired when the original function is skipped.
36///
37/// Returns whether successful.
38pub unsafe fn skip_call(wrapctx: *mut c_void, retval: Retval, stdcall_args_size: usize) -> bool {
39 unsafe { ffi::drwrap_skip_call(wrapctx, retval.into(), stdcall_args_size).as_bool() }
40}
41
42pub fn get_arg(wrapctx: *mut c_void, idx: u8) -> *mut c_void {
43 unsafe { ffi::drwrap_get_arg(wrapctx, idx as c_int) }
44}