1use std::fmt::{self, Display};
4use std::io;
5use std::string::FromUtf16Error;
6
7use crate::gxa::{Gpa, Gva};
8use crate::structs::{DUMP_HEADER64_EXPECTED_SIGNATURE, DUMP_HEADER64_EXPECTED_VALID_DUMP};
9pub type Result<R> = std::result::Result<R, Error>;
10
11#[derive(Debug, Clone, Copy, PartialEq, Eq)]
13pub enum PxeKind {
14 Pml4e,
15 Pdpte,
16 Pde,
17 Pte,
18}
19
20impl Display for PxeKind {
21 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
22 match self {
23 PxeKind::Pml4e => write!(f, "PML4E"),
24 PxeKind::Pdpte => write!(f, "PDPTE"),
25 PxeKind::Pde => write!(f, "PDE"),
26 PxeKind::Pte => write!(f, "PTE"),
27 }
28 }
29}
30
31#[derive(Debug, Clone)]
33pub enum PageReadError {
34 NotPresent { gva: Gva, which_pxe: PxeKind },
37 NotInDump {
39 gva: Option<(Gva, Option<PxeKind>)>,
40 gpa: Gpa,
41 },
42}
43
44impl std::error::Error for PageReadError {}
45
46impl Display for PageReadError {
73 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
74 match self {
75 PageReadError::NotPresent { gva, which_pxe } => {
76 write!(f, "{gva} isn't present at the {which_pxe} level")
77 }
78 PageReadError::NotInDump { gva, gpa } => match gva {
79 Some((gva, Some(which_pxe))) => write!(
80 f,
81 "{gpa} was needed while translating {gva} at the {which_pxe} level but is missing from the dump)"
82 ),
83 Some((gva, None)) => write!(f, "{gpa} backs {gva} but is missing from the dump)"),
84 None => {
85 write!(f, "{gpa} is missing from the dump)")
86 }
87 },
88 }
89 }
90}
91
92#[derive(Debug)]
93pub enum Error {
94 InvalidUnicodeString,
95 Utf16(FromUtf16Error),
96 Overflow(&'static str),
97 Io(io::Error),
98 InvalidData(&'static str),
99 UnknownDumpType(u32),
100 DuplicateGpa(Gpa),
101 InvalidSignature(u32),
102 InvalidValidDump(u32),
103 PhysAddrOverflow(u32, u64),
104 PageOffsetOverflow(u32, u64),
105 BitmapPageOffsetOverflow(u64, usize),
106 PartialRead {
107 expected_amount: usize,
108 actual_amount: usize,
109 reason: PageReadError,
110 },
111 PageRead(PageReadError),
112}
113
114impl From<io::Error> for Error {
115 fn from(value: io::Error) -> Self {
116 Self::Io(value)
117 }
118}
119
120impl From<FromUtf16Error> for Error {
121 fn from(value: FromUtf16Error) -> Self {
122 Self::Utf16(value)
123 }
124}
125
126impl From<PageReadError> for Error {
127 fn from(value: PageReadError) -> Self {
128 Self::PageRead(value)
129 }
130}
131
132impl Display for Error {
133 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
134 match self {
135 Self::InvalidUnicodeString => write!(f, "invalid UNICODE_STRING"),
136 Self::Utf16(_) => write!(f, "utf16"),
137 Self::Overflow(o) => write!(f, "overflow: {o}"),
138 Self::Io(_) => write!(f, "io"),
139 Self::InvalidData(i) => write!(f, "invalid data: {i}"),
140 Self::UnknownDumpType(u) => write!(f, "unsupported dump type {u:#x}"),
141 Self::DuplicateGpa(gpa) => {
142 write!(f, "duplicate gpa found in physmem map for {gpa}")
143 }
144 Self::InvalidSignature(sig) => write!(
145 f,
146 "header's signature looks wrong: {sig:#x} vs {DUMP_HEADER64_EXPECTED_SIGNATURE:#x}"
147 ),
148 Self::InvalidValidDump(dump) => write!(
149 f,
150 "header's valid dump looks wrong: {dump:#x} vs {DUMP_HEADER64_EXPECTED_VALID_DUMP:#x}"
151 ),
152 Self::PhysAddrOverflow(run, page) => {
153 write!(f, "overflow for phys addr w/ run {run} page {page}")
154 }
155 Self::PageOffsetOverflow(run, page) => {
156 write!(f, "overflow for page offset w/ run {run} page {page}")
157 }
158 Self::BitmapPageOffsetOverflow(bitmap_idx, bit_idx) => write!(
159 f,
160 "overflow for page offset w/ bitmap_idx {bitmap_idx} bit_idx {bit_idx}"
161 ),
162 Self::PartialRead {
163 expected_amount,
164 actual_amount,
165 reason,
166 } => write!(
167 f,
168 "partially read {actual_amount} bytes out of {expected_amount} because of {reason}"
169 ),
170 Self::PageRead(p) => write!(f, "page read: {p}"),
171 }
172 }
173}
174
175impl std::error::Error for Error {
176 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
177 match self {
178 Self::Utf16(u) => Some(u),
179 Self::Io(e) => Some(e),
180 Self::PartialRead { reason, .. } => Some(reason),
181 _ => None,
182 }
183 }
184}