1mod arch;
4
5use std::path::Path;
6
7use kdmp_parser::{gxa::Gpa, map::MappedFileReader, parse::KernelDumpParser, phys::Reader};
8use vmi_core::{
9 Gfn, Pa, Va, VcpuId, VmiDriver, VmiError, VmiInfo, VmiMappedPage,
10 driver::{VmiQueryRegisters, VmiRead},
11};
12
13pub use self::arch::{
14 ArchAdapter,
15 header64::{ExceptionRecord64, Header64},
16};
17
18pub struct VmiKdmpDriver<Arch>
20where
21 Arch: ArchAdapter,
22{
23 pub(crate) dump: KernelDumpParser,
24 _marker: std::marker::PhantomData<Arch>,
25}
26
27impl<Arch> VmiKdmpDriver<Arch>
28where
29 Arch: ArchAdapter,
30{
31 pub fn new(path: impl AsRef<Path>) -> Result<Self, VmiError> {
33 let reader = MappedFileReader::new(path)?;
34 let dump = KernelDumpParser::with_reader(reader).map_err(map_kdmp_error)?;
35
36 Ok(Self {
37 dump,
38 _marker: std::marker::PhantomData,
39 })
40 }
41
42 pub fn header(&self) -> Arch::Header {
44 Arch::header(self)
45 }
46}
47
48impl<Arch> VmiDriver for VmiKdmpDriver<Arch>
49where
50 Arch: ArchAdapter,
51{
52 type Architecture = Arch;
53
54 fn info(&self) -> Result<VmiInfo, VmiError> {
55 Ok(VmiInfo {
56 page_size: 4096,
57 page_shift: 12,
58 max_gfn: Gfn(0),
59 vcpus: 0,
60 })
61 }
62}
63
64impl<Arch> VmiRead for VmiKdmpDriver<Arch>
65where
66 Arch: ArchAdapter,
67{
68 fn read_page(&self, gfn: Gfn) -> Result<VmiMappedPage, VmiError> {
69 let reader = Reader::new(&self.dump);
70
71 let mut content = [0u8; 4096];
72 reader
73 .read_exact(Gpa::new(gfn.0 << 12), &mut content)
74 .map_err(map_kdmp_error)?;
75
76 Ok(VmiMappedPage::new(Vec::from(content)))
77 }
78}
79
80impl<Arch> VmiQueryRegisters for VmiKdmpDriver<Arch>
81where
82 Arch: ArchAdapter,
83{
84 fn registers(&self, vcpu: VcpuId) -> Result<Arch::Registers, VmiError> {
85 Arch::registers(self, vcpu)
86 }
87}
88
89pub(crate) fn map_kdmp_error(err: kdmp_parser::error::Error) -> VmiError {
93 match err {
94 kdmp_parser::error::Error::PageRead(kdmp_parser::error::PageReadError::NotPresent {
95 gva,
96 ..
97 }) => VmiError::translation((Va(u64::from(gva)), Pa(0))),
98 kdmp_parser::error::Error::PageRead(kdmp_parser::error::PageReadError::NotInDump {
99 gva: Some((gva, _)),
100 ..
101 }) => VmiError::translation((Va(u64::from(gva)), Pa(0))),
102 other => VmiError::driver(other),
103 }
104}