1use isr_macros::Field;
2use zerocopy::{FromBytes, Immutable, IntoBytes};
3
4use super::session::VmiSession;
5use crate::{
6 AccessContext, AddressContext, Architecture, Pa, Registers as _, Va, VmiCore, VmiDriver,
7 VmiError,
8 os::{NoOS, VmiOs},
9};
10
11pub struct VmiState<'a, Driver, Os = NoOS>
17where
18 Driver: VmiDriver,
19 Os: VmiOs<Driver>,
20{
21 session: VmiSession<'a, Driver, Os>,
23
24 registers: &'a <Driver::Architecture as Architecture>::Registers,
26}
27
28impl<Driver, Os> Clone for VmiState<'_, Driver, Os>
29where
30 Driver: VmiDriver,
31 Os: VmiOs<Driver>,
32{
33 fn clone(&self) -> Self {
34 *self
35 }
36}
37
38impl<Driver, Os> Copy for VmiState<'_, Driver, Os>
39where
40 Driver: VmiDriver,
41 Os: VmiOs<Driver>,
42{
43}
44
45impl<'a, Driver, Os> std::ops::Deref for VmiState<'a, Driver, Os>
46where
47 Driver: VmiDriver,
48 Os: VmiOs<Driver>,
49{
50 type Target = VmiSession<'a, Driver, Os>;
51
52 fn deref(&self) -> &Self::Target {
53 &self.session
54 }
55}
56
57impl<'a, Driver, Os> VmiState<'a, Driver, Os>
58where
59 Driver: VmiDriver,
60 Os: VmiOs<Driver>,
61{
62 pub fn new(
64 session: &'a VmiSession<'a, Driver, Os>,
65 registers: &'a <Driver::Architecture as Architecture>::Registers,
66 ) -> Self {
67 Self {
68 session: *session,
69 registers,
70 }
71 }
72
73 pub fn with_registers(
75 &'a self,
76 registers: &'a <Driver::Architecture as Architecture>::Registers,
77 ) -> Self {
78 Self {
79 session: self.session,
80 registers,
81 }
82 }
83
84 pub fn without_os(&self) -> VmiState<'a, Driver, NoOS> {
86 VmiState {
87 session: self.session.without_os(),
88 registers: self.registers,
89 }
90 }
91
92 pub fn session(&self) -> &VmiSession<'a, Driver, Os> {
96 &self.session
97 }
98
99 pub fn registers(&self) -> &'a <Driver::Architecture as Architecture>::Registers {
101 self.registers
102 }
103
104 pub fn os(&self) -> VmiOsState<'a, Driver, Os> {
106 VmiOsState(*self)
107 }
108
109 pub fn access_context(&self, address: Va) -> AccessContext {
111 self.registers().access_context(address)
112 }
113
114 pub fn address_context(&self, address: Va) -> AddressContext {
116 self.registers().address_context(address)
117 }
118
119 pub fn translation_root(&self, va: Va) -> Pa {
122 self.registers().translation_root(va)
123 }
124
125 pub fn return_address(&self) -> Result<Va, VmiError> {
127 self.registers().return_address(self.core())
128 }
129
130 pub fn translate_address(&self, va: Va) -> Result<Pa, VmiError> {
132 self.core().translate_address(self.address_context(va))
133 }
134
135 pub fn read(&self, address: Va, buffer: &mut [u8]) -> Result<(), VmiError> {
139 self.read_in(self.access_context(address), buffer)
140 }
141
142 pub fn write(&self, address: Va, buffer: &[u8]) -> Result<(), VmiError> {
144 self.write_in(self.access_context(address), buffer)
145 }
146
147 pub fn read_u8(&self, address: Va) -> Result<u8, VmiError> {
149 self.read_u8_in(self.access_context(address))
150 }
151
152 pub fn read_u16(&self, address: Va) -> Result<u16, VmiError> {
154 self.read_u16_in(self.access_context(address))
155 }
156
157 pub fn read_u32(&self, address: Va) -> Result<u32, VmiError> {
159 self.read_u32_in(self.access_context(address))
160 }
161
162 pub fn read_u64(&self, address: Va) -> Result<u64, VmiError> {
164 self.read_u64_in(self.access_context(address))
165 }
166
167 pub fn read_uint(&self, address: Va, size: usize) -> Result<u64, VmiError> {
175 self.read_uint_in(self.access_context(address), size)
176 }
177
178 pub fn read_field(&self, base_address: Va, field: &Field) -> Result<u64, VmiError> {
187 self.read_field_in(self.access_context(base_address), field)
188 }
189
190 pub fn read_address(&self, address: Va) -> Result<u64, VmiError> {
192 self.read_address_in(self.access_context(address))
193 }
194
195 pub fn read_address_native(&self, address: Va) -> Result<u64, VmiError> {
197 self.read_address_native_in(self.access_context(address))
198 }
199
200 pub fn read_address32(&self, address: Va) -> Result<u64, VmiError> {
202 self.read_address32_in(self.access_context(address))
203 }
204
205 pub fn read_address64(&self, address: Va) -> Result<u64, VmiError> {
207 self.read_address64_in(self.access_context(address))
208 }
209
210 pub fn read_va(&self, address: Va) -> Result<Va, VmiError> {
212 self.read_va_in(self.access_context(address))
213 }
214
215 pub fn read_va_native(&self, address: Va) -> Result<Va, VmiError> {
217 self.read_va_native_in(self.access_context(address))
218 }
219
220 pub fn read_va32(&self, address: Va) -> Result<Va, VmiError> {
222 self.read_va32_in(self.access_context(address))
223 }
224
225 pub fn read_va64(&self, address: Va) -> Result<Va, VmiError> {
227 self.read_va64_in(self.access_context(address))
228 }
229
230 pub fn read_string_bytes_limited(
233 &self,
234 address: Va,
235 limit: usize,
236 ) -> Result<Vec<u8>, VmiError> {
237 self.read_string_bytes_limited_in(self.access_context(address), limit)
238 }
239
240 pub fn read_string_bytes(&self, address: Va) -> Result<Vec<u8>, VmiError> {
242 self.read_string_bytes_in(self.access_context(address))
243 }
244
245 pub fn read_wstring_bytes_limited(
248 &self,
249 address: Va,
250 limit: usize,
251 ) -> Result<Vec<u16>, VmiError> {
252 self.read_wstring_bytes_limited_in(self.access_context(address), limit)
253 }
254
255 pub fn read_wstring_bytes(&self, address: Va) -> Result<Vec<u16>, VmiError> {
257 self.read_wstring_bytes_in(self.access_context(address))
258 }
259
260 pub fn read_string_limited(&self, address: Va, limit: usize) -> Result<String, VmiError> {
263 self.read_string_limited_in(self.access_context(address), limit)
264 }
265
266 pub fn read_string(&self, address: Va) -> Result<String, VmiError> {
268 self.read_string_in(self.access_context(address))
269 }
270
271 pub fn read_wstring_limited(&self, address: Va, limit: usize) -> Result<String, VmiError> {
274 self.read_wstring_limited_in(self.access_context(address), limit)
275 }
276
277 pub fn read_wstring(&self, address: Va) -> Result<String, VmiError> {
279 self.read_wstring_in(self.access_context(address))
280 }
281
282 pub fn read_struct<T>(&self, address: Va) -> Result<T, VmiError>
284 where
285 T: IntoBytes + FromBytes,
286 {
287 self.read_struct_in(self.access_context(address))
288 }
289
290 pub fn read_in(
296 &self,
297 ctx: impl Into<AccessContext>,
298 buffer: &mut [u8],
299 ) -> Result<(), VmiError> {
300 self.core().read(ctx, buffer)
301 }
302
303 pub fn write_in(&self, ctx: impl Into<AccessContext>, buffer: &[u8]) -> Result<(), VmiError> {
305 self.core().write(ctx, buffer)
306 }
307
308 pub fn read_u8_in(&self, ctx: impl Into<AccessContext>) -> Result<u8, VmiError> {
310 self.core().read_u8(ctx)
311 }
312
313 pub fn read_u16_in(&self, ctx: impl Into<AccessContext>) -> Result<u16, VmiError> {
315 self.core().read_u16(ctx)
316 }
317
318 pub fn read_u32_in(&self, ctx: impl Into<AccessContext>) -> Result<u32, VmiError> {
320 self.core().read_u32(ctx)
321 }
322
323 pub fn read_u64_in(&self, ctx: impl Into<AccessContext>) -> Result<u64, VmiError> {
325 self.core().read_u64(ctx)
326 }
327
328 pub fn read_uint_in(
336 &self,
337 ctx: impl Into<AccessContext>,
338 size: usize,
339 ) -> Result<u64, VmiError> {
340 self.core().read_uint(ctx, size)
341 }
342
343 pub fn read_field_in(
352 &self,
353 ctx: impl Into<AccessContext>,
354 field: &Field,
355 ) -> Result<u64, VmiError> {
356 self.core().read_field(ctx, field)
357 }
358
359 pub fn read_address_in(&self, ctx: impl Into<AccessContext>) -> Result<u64, VmiError> {
361 self.core()
362 .read_address(ctx, self.registers().effective_address_width())
363 }
364
365 pub fn read_address_native_in(&self, ctx: impl Into<AccessContext>) -> Result<u64, VmiError> {
367 self.core()
368 .read_address(ctx, self.registers().address_width())
369 }
370
371 pub fn read_address32_in(&self, ctx: impl Into<AccessContext>) -> Result<u64, VmiError> {
373 self.core().read_address32(ctx)
374 }
375
376 pub fn read_address64_in(&self, ctx: impl Into<AccessContext>) -> Result<u64, VmiError> {
378 self.core().read_address64(ctx)
379 }
380
381 pub fn read_va_in(&self, ctx: impl Into<AccessContext>) -> Result<Va, VmiError> {
383 self.core()
384 .read_va(ctx, self.registers().effective_address_width())
385 }
386
387 pub fn read_va_native_in(&self, ctx: impl Into<AccessContext>) -> Result<Va, VmiError> {
389 self.core().read_va(ctx, self.registers().address_width())
390 }
391
392 pub fn read_va32_in(&self, ctx: impl Into<AccessContext>) -> Result<Va, VmiError> {
394 self.core().read_va32(ctx)
395 }
396
397 pub fn read_va64_in(&self, ctx: impl Into<AccessContext>) -> Result<Va, VmiError> {
399 self.core().read_va64(ctx)
400 }
401
402 pub fn read_string_bytes_limited_in(
405 &self,
406 ctx: impl Into<AccessContext>,
407 limit: usize,
408 ) -> Result<Vec<u8>, VmiError> {
409 self.core().read_string_bytes_limited(ctx, limit)
410 }
411
412 pub fn read_string_bytes_in(&self, ctx: impl Into<AccessContext>) -> Result<Vec<u8>, VmiError> {
414 self.core().read_string_bytes(ctx)
415 }
416
417 pub fn read_wstring_bytes_limited_in(
420 &self,
421 ctx: impl Into<AccessContext>,
422 limit: usize,
423 ) -> Result<Vec<u16>, VmiError> {
424 self.core().read_wstring_bytes_limited(ctx, limit)
425 }
426
427 pub fn read_wstring_bytes_in(
429 &self,
430 ctx: impl Into<AccessContext>,
431 ) -> Result<Vec<u16>, VmiError> {
432 self.core().read_wstring_bytes(ctx)
433 }
434
435 pub fn read_string_limited_in(
438 &self,
439 ctx: impl Into<AccessContext>,
440 limit: usize,
441 ) -> Result<String, VmiError> {
442 self.core().read_string_limited(ctx, limit)
443 }
444
445 pub fn read_string_in(&self, ctx: impl Into<AccessContext>) -> Result<String, VmiError> {
447 self.core().read_string(ctx)
448 }
449
450 pub fn read_wstring_limited_in(
453 &self,
454 ctx: impl Into<AccessContext>,
455 limit: usize,
456 ) -> Result<String, VmiError> {
457 self.core().read_wstring_limited(ctx, limit)
458 }
459
460 pub fn read_wstring_in(&self, ctx: impl Into<AccessContext>) -> Result<String, VmiError> {
462 self.core().read_wstring(ctx)
463 }
464
465 pub fn read_struct_in<T>(&self, ctx: impl Into<AccessContext>) -> Result<T, VmiError>
467 where
468 T: IntoBytes + FromBytes,
469 {
470 self.core().read_struct(ctx)
471 }
472
473 pub fn write_u8(&self, address: Va, value: u8) -> Result<(), VmiError> {
477 self.core().write_u8(self.access_context(address), value)
478 }
479
480 pub fn write_u16(&self, address: Va, value: u16) -> Result<(), VmiError> {
482 self.core().write_u16(self.access_context(address), value)
483 }
484
485 pub fn write_u32(&self, address: Va, value: u32) -> Result<(), VmiError> {
487 self.core().write_u32(self.access_context(address), value)
488 }
489
490 pub fn write_u64(&self, address: Va, value: u64) -> Result<(), VmiError> {
492 self.core().write_u64(self.access_context(address), value)
493 }
494
495 pub fn write_struct<T>(&self, address: Va, value: T) -> Result<(), VmiError>
497 where
498 T: FromBytes + IntoBytes + Immutable,
499 {
500 self.core()
501 .write_struct(self.access_context(address), value)
502 }
503}
504
505pub struct VmiOsState<'a, Driver, Os>(VmiState<'a, Driver, Os>)
507where
508 Driver: VmiDriver,
509 Os: VmiOs<Driver>;
510
511impl<'a, Driver, Os> VmiOsState<'a, Driver, Os>
512where
513 Driver: VmiDriver,
514 Os: VmiOs<Driver>,
515{
516 pub fn core(&self) -> &'a VmiCore<Driver> {
518 self.0.core()
519 }
520
521 pub fn underlying_os(&self) -> &'a Os {
523 self.0.underlying_os()
524 }
525
526 pub fn session(&self) -> &VmiSession<'a, Driver, Os> {
528 self.0.session()
529 }
530
531 pub fn state(&self) -> VmiState<'a, Driver, Os> {
533 self.0
534 }
535
536 pub fn registers(&self) -> &<Driver::Architecture as Architecture>::Registers {
538 self.0.registers()
539 }
540
541 pub fn function_argument_for_registers(
544 &self,
545 registers: &<Driver::Architecture as Architecture>::Registers,
546 index: u64,
547 ) -> Result<u64, VmiError> {
548 Os::function_argument(self.0.with_registers(registers), index)
549 }
550
551 pub fn function_return_value_for_registers(
553 &self,
554 registers: &<Driver::Architecture as Architecture>::Registers,
555 ) -> Result<u64, VmiError> {
556 Os::function_return_value(self.0.with_registers(registers))
557 }
558}