vmi_core/core/
address_context.rs

1use serde::{Deserialize, Serialize};
2
3use super::{Pa, Va};
4
5/// A complete address context within a system for virtual to physical address
6/// translation.
7///
8/// In virtual machine introspection (VMI) and memory analysis, it's often
9/// necessary to work with addresses from different processes or memory spaces.
10/// The `AddressContext` struct encapsulates both a virtual address and the
11/// corresponding translation root, providing all the information needed to
12/// accurately translate the virtual address to a physical address.
13///
14/// The `AddressContext` is commonly used as an input to memory access or
15/// translation functions in VMI tools, ensuring that the correct translation
16/// context is applied for each memory operation.
17///
18/// # Example
19///
20/// ```no_run
21/// # use vmi_core::{AddressContext, Pa, Va};
22/// let user_space_address = AddressContext {
23///     va: Va(0x7ffe0000),
24///     root: Pa(0x1000000),  // CR3 value for a specific process
25/// };
26///
27/// let kernel_space_address = AddressContext {
28///     va: Va(0xfffff80000000000),
29///     root: Pa(0x2000000),  // CR3 value for kernel space
30/// };
31///
32/// // These contexts can then be used in memory operations
33/// // vmi.read(user_space_address, &mut buffer)?;
34/// // vmi.translate_address(kernel_space_address)?;
35/// ```
36#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
37pub struct AddressContext {
38    /// The virtual address.
39    pub va: Va,
40
41    /// The translation root, typically the base of the page table hierarchy
42    /// (e.g., CR3 in x86).
43    pub root: Pa,
44}
45
46impl AddressContext {
47    /// Creates a new `AddressContext` with the given virtual address and
48    /// translation root.
49    pub fn new(va: impl Into<Va>, root: impl Into<Pa>) -> Self {
50        Self {
51            va: va.into(),
52            root: root.into(),
53        }
54    }
55}
56
57//impl From<Va> for AddressContext {
58//    fn from(value: Va) -> Self {
59//        Self {
60//            va: value,
61//            root: None,
62//        }
63//    }
64//}
65
66impl From<(Va, Pa)> for AddressContext {
67    fn from(value: (Va, Pa)) -> Self {
68        Self {
69            va: value.0,
70            root: value.1,
71        }
72    }
73}
74
75impl ::std::ops::Add<u64> for AddressContext {
76    type Output = AddressContext;
77
78    fn add(self, rhs: u64) -> Self::Output {
79        Self {
80            va: self.va + rhs,
81            ..self
82        }
83    }
84}
85
86impl ::std::ops::Add<AddressContext> for AddressContext {
87    type Output = AddressContext;
88
89    fn add(self, rhs: AddressContext) -> Self::Output {
90        Self {
91            va: self.va + rhs.va,
92            ..self
93        }
94    }
95}
96
97impl ::std::ops::AddAssign<u64> for AddressContext {
98    fn add_assign(&mut self, rhs: u64) {
99        self.va += rhs;
100    }
101}
102
103impl ::std::ops::AddAssign<AddressContext> for AddressContext {
104    fn add_assign(&mut self, rhs: AddressContext) {
105        self.va += rhs.va;
106    }
107}
108
109impl ::std::ops::Sub<u64> for AddressContext {
110    type Output = AddressContext;
111
112    fn sub(self, rhs: u64) -> Self::Output {
113        Self {
114            va: self.va - rhs,
115            ..self
116        }
117    }
118}
119
120impl ::std::ops::Sub<AddressContext> for AddressContext {
121    type Output = AddressContext;
122
123    fn sub(self, rhs: AddressContext) -> Self::Output {
124        Self {
125            va: self.va - rhs.va,
126            ..self
127        }
128    }
129}
130
131impl ::std::ops::SubAssign<u64> for AddressContext {
132    fn sub_assign(&mut self, rhs: u64) {
133        self.va -= rhs;
134    }
135}
136
137impl ::std::ops::SubAssign<AddressContext> for AddressContext {
138    fn sub_assign(&mut self, rhs: AddressContext) {
139        self.va -= rhs.va;
140    }
141}
142
143impl ::std::ops::Mul<u64> for AddressContext {
144    type Output = AddressContext;
145
146    fn mul(self, rhs: u64) -> Self::Output {
147        Self {
148            va: self.va * rhs,
149            ..self
150        }
151    }
152}
153
154impl ::std::ops::Mul<AddressContext> for AddressContext {
155    type Output = AddressContext;
156
157    fn mul(self, rhs: AddressContext) -> Self::Output {
158        Self {
159            va: self.va * rhs.va,
160            ..self
161        }
162    }
163}
164
165impl ::std::ops::MulAssign<u64> for AddressContext {
166    fn mul_assign(&mut self, rhs: u64) {
167        self.va *= rhs;
168    }
169}
170
171impl ::std::ops::MulAssign<AddressContext> for AddressContext {
172    fn mul_assign(&mut self, rhs: AddressContext) {
173        self.va *= rhs.va;
174    }
175}
176
177impl ::std::ops::Div<u64> for AddressContext {
178    type Output = AddressContext;
179
180    fn div(self, rhs: u64) -> Self::Output {
181        Self {
182            va: self.va / rhs,
183            ..self
184        }
185    }
186}
187
188impl ::std::ops::Div<AddressContext> for AddressContext {
189    type Output = AddressContext;
190
191    fn div(self, rhs: AddressContext) -> Self::Output {
192        Self {
193            va: self.va / rhs.va,
194            ..self
195        }
196    }
197}
198
199impl ::std::ops::DivAssign<u64> for AddressContext {
200    fn div_assign(&mut self, rhs: u64) {
201        self.va /= rhs;
202    }
203}
204
205impl ::std::ops::DivAssign<AddressContext> for AddressContext {
206    fn div_assign(&mut self, rhs: AddressContext) {
207        self.va /= rhs.va;
208    }
209}
210
211impl ::std::ops::BitAnd<u64> for AddressContext {
212    type Output = AddressContext;
213
214    fn bitand(self, rhs: u64) -> Self::Output {
215        Self {
216            va: self.va & rhs,
217            ..self
218        }
219    }
220}
221
222impl ::std::ops::BitAndAssign<u64> for AddressContext {
223    fn bitand_assign(&mut self, rhs: u64) {
224        self.va &= rhs;
225    }
226}
227
228impl ::std::ops::BitOr<u64> for AddressContext {
229    type Output = AddressContext;
230
231    fn bitor(self, rhs: u64) -> Self::Output {
232        Self {
233            va: self.va | rhs,
234            ..self
235        }
236    }
237}
238
239impl ::std::ops::BitOrAssign<u64> for AddressContext {
240    fn bitor_assign(&mut self, rhs: u64) {
241        self.va |= rhs;
242    }
243}
244
245impl ::std::fmt::Display for AddressContext {
246    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
247        write!(f, "{} @ {}", self.va, self.root)
248    }
249}