retour\detours/raw.rs
1use crate::arch::Detour;
2use crate::error::Result;
3
4/// A raw detour.
5///
6/// # Example
7///
8/// ```rust
9/// # use retour::Result;
10/// use retour::RawDetour;
11/// use std::mem;
12///
13/// fn add5(val: i32) -> i32 {
14/// val + 5
15/// }
16///
17/// fn add10(val: i32) -> i32 {
18/// val + 10
19/// }
20///
21/// # fn main() -> Result<()> {
22/// let mut hook = unsafe { RawDetour::new(add5 as *const (), add10 as *const ())? };
23///
24/// assert_eq!(add5(5), 10);
25/// assert_eq!(hook.is_enabled(), false);
26///
27/// unsafe { hook.enable()? };
28/// assert!(hook.is_enabled());
29///
30/// let original: fn(i32) -> i32 = unsafe { mem::transmute(hook.trampoline()) };
31///
32/// assert_eq!(add5(5), 15);
33/// assert_eq!(original(5), 10);
34///
35/// unsafe { hook.disable()? };
36/// assert_eq!(add5(5), 10);
37/// # Ok(())
38/// # }
39/// ```
40#[derive(Debug)]
41pub struct RawDetour(Detour);
42
43// TODO: stop all threads in target during patch?
44impl RawDetour {
45 /// Constructs a new inline detour patcher.
46 ///
47 /// The hook is disabled by default. Even when this function is succesful,
48 /// there is no guaranteee that the detour function will actually get called
49 /// when the target function gets called. An invocation of the target
50 /// function might for example get inlined in which case it is impossible to
51 /// hook at runtime.
52 pub unsafe fn new(target: *const (), detour: *const ()) -> Result<Self> {
53 Detour::new(target, detour).map(RawDetour)
54 }
55
56 /// Enables the detour.
57 pub unsafe fn enable(&self) -> Result<()> {
58 self.0.enable()
59 }
60
61 /// Disables the detour.
62 pub unsafe fn disable(&self) -> Result<()> {
63 self.0.disable()
64 }
65
66 /// Returns whether the detour is enabled or not.
67 pub fn is_enabled(&self) -> bool {
68 self.0.is_enabled()
69 }
70
71 /// Returns a reference to the generated trampoline.
72 pub fn trampoline(&self) -> &() {
73 self.0.trampoline()
74 }
75}