1use crate::{NullableHandle, Process, Status, Thread, ok, sys};
8
9#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
14#[repr(transparent)]
15pub struct Exception(NullableHandle);
16impl_handle_based!(Exception);
17
18impl Exception {
19 pub fn get_thread(&self) -> Result<Thread, Status> {
25 let mut handle = 0;
26 let status = unsafe { sys::zx_exception_get_thread(self.raw_handle(), &mut handle) };
27 ok(status)?;
28 unsafe { Ok(Thread::from(NullableHandle::from_raw(handle))) }
29 }
30
31 pub fn get_process(&self) -> Result<Process, Status> {
37 let mut handle = 0;
38 let status = unsafe { sys::zx_exception_get_process(self.raw_handle(), &mut handle) };
39 ok(status)?;
40 unsafe { Ok(Process::from(NullableHandle::from_raw(handle))) }
41 }
42}
43
44unsafe_handle_properties!(object: Exception,
45 props: [
46 {query_ty: EXCEPTION_STATE, tag: ExceptionStateTag, prop_ty: sys::zx_exception_state_t, get: get_exception_state, set: set_exception_state},
47 ]
48);
49
50#[derive(Debug, Copy, Clone)]
52pub struct ExceptionReport {
53 pub ty: ExceptionType,
55 pub arch: ExceptionArchData,
57}
58
59impl ExceptionReport {
60 pub unsafe fn from_raw(raw: sys::zx_exception_report_t) -> Self {
65 debug_assert_eq!(
66 raw.header.size as usize,
67 std::mem::size_of::<sys::zx_exception_report_t>()
68 );
69 let ty = ExceptionType::from_raw(
70 raw.header.type_,
71 raw.context.synth_code,
72 raw.context.synth_data,
73 );
74
75 #[cfg(target_arch = "x86_64")]
78 let arch = unsafe { ExceptionArchData::from_raw(raw.context.arch.x86_64) };
79 #[cfg(target_arch = "aarch64")]
80 let arch = unsafe { ExceptionArchData::from_raw(raw.context.arch.arm_64) };
81 #[cfg(target_arch = "riscv64")]
82 let arch = unsafe { ExceptionArchData::from_raw(raw.context.arch.riscv_64) };
83
84 Self { ty, arch }
85 }
86}
87
88#[derive(Debug, Copy, Clone)]
90#[cfg(target_arch = "x86_64")]
91pub struct ExceptionArchData {
92 pub vector: u64,
93 pub err_code: u64,
94 pub cr2: u64,
95}
96
97#[cfg(target_arch = "x86_64")]
98impl ExceptionArchData {
99 fn from_raw(raw: sys::zx_x86_64_exc_data_t) -> Self {
100 Self { vector: raw.vector, err_code: raw.err_code, cr2: raw.cr2 }
101 }
102}
103
104#[derive(Debug, Copy, Clone)]
106#[cfg(target_arch = "aarch64")]
107pub struct ExceptionArchData {
108 pub esr: u32,
109 pub far: u64,
110}
111
112#[cfg(target_arch = "aarch64")]
113impl ExceptionArchData {
114 fn from_raw(raw: sys::zx_arm64_exc_data_t) -> Self {
115 Self { esr: raw.esr, far: raw.far }
116 }
117}
118
119#[derive(Debug, Copy, Clone)]
121#[cfg(target_arch = "riscv64")]
122pub struct ExceptionArchData {
123 pub cause: u64,
124 pub tval: u64,
125}
126
127#[cfg(target_arch = "riscv64")]
128impl ExceptionArchData {
129 fn from_raw(raw: sys::zx_riscv64_exc_data_t) -> Self {
130 Self { cause: raw.cause, tval: raw.tval }
131 }
132}
133
134#[derive(Debug, Copy, Clone)]
136pub enum ExceptionType {
137 General,
139
140 FatalPageFault {
142 status: Status,
144 },
145
146 UndefinedInstruction,
148
149 SoftwareBreakpoint,
151
152 HardwareBreakpoint,
154
155 UnalignedAccess,
157
158 ThreadStarting,
164
165 ThreadExiting,
175
176 PolicyError(PolicyCode),
184
185 ProcessStarting,
192
193 ProcessNameChanged,
195
196 UnknownUserGenerated { code: u32, data: u32 },
198
199 Unknown { ty: u32, code: u32, data: u32 },
201}
202
203impl ExceptionType {
204 fn from_raw(raw: sys::zx_excp_type_t, code: u32, data: u32) -> Self {
205 match raw {
206 sys::ZX_EXCP_GENERAL => Self::General,
207 sys::ZX_EXCP_FATAL_PAGE_FAULT => {
208 Self::FatalPageFault { status: Status::from_raw(code as i32) }
209 }
210 sys::ZX_EXCP_UNDEFINED_INSTRUCTION => Self::UndefinedInstruction,
211 sys::ZX_EXCP_SW_BREAKPOINT => Self::SoftwareBreakpoint,
212 sys::ZX_EXCP_HW_BREAKPOINT => Self::HardwareBreakpoint,
213 sys::ZX_EXCP_UNALIGNED_ACCESS => Self::UnalignedAccess,
214 sys::ZX_EXCP_THREAD_STARTING => Self::ThreadStarting,
215 sys::ZX_EXCP_THREAD_EXITING => Self::ThreadExiting,
216 sys::ZX_EXCP_POLICY_ERROR => Self::PolicyError(PolicyCode::from_raw(code, data)),
217 sys::ZX_EXCP_PROCESS_STARTING => Self::ProcessStarting,
218 sys::ZX_EXCP_USER => match code {
219 sys::ZX_EXCP_USER_CODE_PROCESS_NAME_CHANGED => Self::ProcessNameChanged,
220 _ => Self::UnknownUserGenerated { code, data },
221 },
222 other => Self::Unknown { ty: other, code, data },
223 }
224 }
225}
226
227#[derive(Clone, Copy, Debug)]
228pub enum PolicyCode {
229 BadHandle,
230 WrongObject,
231 VmarWriteExecutable,
232 NewAny,
233 NewVmo,
234 NewChannel,
235 NewEvent,
236 NewEventPair,
237 NewPort,
238 NewSocket,
239 NewFifo,
240 NewTimer,
241 NewProcess,
242 NewProfile,
243 NewPager,
244 AmbientMarkVmoExecutable,
245 ChannelFullWrite,
246 PortTooManyPackets,
247 BadSyscall {
248 number: u32,
249 },
250 PortTooManyObservers,
251
252 HandleLeak,
257 NewIob,
258
259 Unknown {
261 code: u32,
262 data: u32,
263 },
264}
265
266impl PolicyCode {
267 fn from_raw(code: u32, data: u32) -> Self {
268 match code {
269 sys::ZX_EXCP_POLICY_CODE_BAD_HANDLE => Self::BadHandle,
270 sys::ZX_EXCP_POLICY_CODE_WRONG_OBJECT => Self::WrongObject,
271 sys::ZX_EXCP_POLICY_CODE_VMAR_WX => Self::VmarWriteExecutable,
272 sys::ZX_EXCP_POLICY_CODE_NEW_ANY => Self::NewAny,
273 sys::ZX_EXCP_POLICY_CODE_NEW_VMO => Self::NewVmo,
274 sys::ZX_EXCP_POLICY_CODE_NEW_CHANNEL => Self::NewChannel,
275 sys::ZX_EXCP_POLICY_CODE_NEW_EVENT => Self::NewEvent,
276 sys::ZX_EXCP_POLICY_CODE_NEW_EVENTPAIR => Self::NewEventPair,
277 sys::ZX_EXCP_POLICY_CODE_NEW_PORT => Self::NewPort,
278 sys::ZX_EXCP_POLICY_CODE_NEW_SOCKET => Self::NewSocket,
279 sys::ZX_EXCP_POLICY_CODE_NEW_FIFO => Self::NewFifo,
280 sys::ZX_EXCP_POLICY_CODE_NEW_TIMER => Self::NewTimer,
281 sys::ZX_EXCP_POLICY_CODE_NEW_PROCESS => Self::NewProcess,
282 sys::ZX_EXCP_POLICY_CODE_NEW_PROFILE => Self::NewProfile,
283 sys::ZX_EXCP_POLICY_CODE_NEW_PAGER => Self::NewPager,
284 sys::ZX_EXCP_POLICY_CODE_AMBIENT_MARK_VMO_EXEC => Self::AmbientMarkVmoExecutable,
285 sys::ZX_EXCP_POLICY_CODE_CHANNEL_FULL_WRITE => Self::ChannelFullWrite,
286 sys::ZX_EXCP_POLICY_CODE_PORT_TOO_MANY_PACKETS => Self::PortTooManyPackets,
287 sys::ZX_EXCP_POLICY_CODE_BAD_SYSCALL => Self::BadSyscall { number: data },
288 sys::ZX_EXCP_POLICY_CODE_PORT_TOO_MANY_OBSERVERS => Self::PortTooManyObservers,
289 sys::ZX_EXCP_POLICY_CODE_HANDLE_LEAK => Self::HandleLeak,
290 sys::ZX_EXCP_POLICY_CODE_NEW_IOB => Self::NewIob,
291 _ => Self::Unknown { code, data },
292 }
293 }
294}