1use crate::{HeapRegs, RegisterStorage, RegisterStorageEnum};
6use starnix_uapi::errors::Errno;
7use starnix_uapi::{__NR_restart_syscall, error, user_regs_struct};
8
9const SYSCALL_INSTRUCTION_SIZE_BYTES: u64 = 2;
11
12#[derive(Default, Clone, Eq, PartialEq)]
18pub struct RegisterState<T: RegisterStorage> {
19 pub real_registers: T,
20
21 pub orig_rax: u64,
25}
26
27impl<T: RegisterStorage> RegisterState<T> {
28 pub fn to_user_regs_struct(&self) -> user_regs_struct {
29 user_regs_struct {
30 r15: self.r15,
31 r14: self.r14,
32 r13: self.r13,
33 r12: self.r12,
34 rbp: self.rbp,
35 rbx: self.rbx,
36 r11: self.r11,
37 r10: self.r10,
38 r9: self.r9,
39 r8: self.r8,
40 rax: self.rax,
41 rcx: self.rcx,
42 rdx: self.rdx,
43 rsi: self.rsi,
44 rdi: self.rdi,
45 orig_rax: self.orig_rax,
46 rip: self.ip,
47 cs: 0,
48 eflags: self.flags,
49 rsp: self.rsp,
50 ss: 0,
51 fs_base: self.fs_base,
52 gs_base: self.gs_base,
53 ds: 0,
54 es: 0,
55 fs: 0,
56 gs: 0,
57 }
58 }
59
60 pub fn to_user_regs_struct_arch32(&self) -> starnix_uapi::arch32::user_regs_struct {
61 unreachable!("arch32 not supported on x64")
62 }
63
64 pub fn from_user_regs_struct(&mut self, regs: &user_regs_struct) {
65 self.r15 = regs.r15;
66 self.r14 = regs.r14;
67 self.r13 = regs.r13;
68 self.r12 = regs.r12;
69 self.rbp = regs.rbp;
70 self.rbx = regs.rbx;
71 self.r11 = regs.r11;
72 self.r10 = regs.r10;
73 self.r9 = regs.r9;
74 self.r8 = regs.r8;
75 self.rax = regs.rax;
76 self.rcx = regs.rcx;
77 self.rdx = regs.rdx;
78 self.rsi = regs.rsi;
79 self.rdi = regs.rdi;
80 self.orig_rax = regs.orig_rax;
81 self.ip = regs.rip;
82 self.flags = regs.eflags;
83 self.rsp = regs.rsp;
84 self.fs_base = regs.fs_base;
85 self.gs_base = regs.gs_base;
86 }
87
88 pub fn from_user_regs_struct_arch32(&mut self, _regs: &starnix_uapi::arch32::user_regs_struct) {
89 unreachable!("arch32 not supported on x64")
90 }
91
92 pub fn save_registers_for_restart(&mut self, syscall_number: u64) {
94 self.rax = -(starnix_uapi::ENOSYS as i64) as u64;
99
100 self.orig_rax = syscall_number;
102 }
103
104 pub fn prepare_for_custom_restart(&mut self) {
106 self.rax = __NR_restart_syscall as u64;
107 }
108
109 pub fn restore_original_return_register(&mut self) {
111 self.rax = self.orig_rax;
112 }
113
114 pub fn instruction_pointer_register(&self) -> u64 {
117 self.ip
118 }
119
120 pub fn set_instruction_pointer_register(&mut self, new_ip: u64) {
123 self.ip = new_ip;
124 }
125
126 pub fn rewind_syscall_instruction(&mut self) {
128 self.ip -= SYSCALL_INSTRUCTION_SIZE_BYTES;
129 }
130
131 pub fn return_register(&self) -> u64 {
134 self.rax
135 }
136
137 pub fn set_return_register(&mut self, return_value: u64) {
140 self.rax = return_value;
141 }
142
143 pub fn stack_pointer_register(&self) -> u64 {
145 self.rsp
146 }
147
148 pub fn set_stack_pointer_register(&mut self, sp: u64) {
150 self.rsp = sp;
151 }
152
153 pub fn set_thread_pointer_register(&mut self, tp: u64) {
155 self.fs_base = tp;
156 }
157
158 pub fn set_arg0_register(&mut self, rdi: u64) {
160 self.rdi = rdi;
161 }
162
163 pub fn set_arg1_register(&mut self, rsi: u64) {
165 self.rsi = rsi;
166 }
167
168 pub fn set_arg2_register(&mut self, rdx: u64) {
170 self.rdx = rdx;
171 }
172
173 pub fn syscall_register(&self) -> u64 {
175 self.orig_rax
176 }
177
178 pub fn reset_flags(&mut self) {
180 self.flags = 0;
181 }
182
183 pub fn apply_user_register(
185 &mut self,
186 offset: usize,
187 f: &mut dyn FnMut(&mut u64),
188 ) -> Result<(), Errno> {
189 if offset == memoffset::offset_of!(user_regs_struct, r15) {
190 f(&mut self.r15);
191 } else if offset == memoffset::offset_of!(user_regs_struct, r14) {
192 f(&mut self.r14);
193 } else if offset == memoffset::offset_of!(user_regs_struct, r13) {
194 f(&mut self.r13);
195 } else if offset == memoffset::offset_of!(user_regs_struct, r12) {
196 f(&mut self.r12);
197 } else if offset == memoffset::offset_of!(user_regs_struct, rbp) {
198 f(&mut self.rbp);
199 } else if offset == memoffset::offset_of!(user_regs_struct, rbx) {
200 f(&mut self.rbx);
201 } else if offset == memoffset::offset_of!(user_regs_struct, r11) {
202 f(&mut self.r11);
203 } else if offset == memoffset::offset_of!(user_regs_struct, r10) {
204 f(&mut self.r10);
205 } else if offset == memoffset::offset_of!(user_regs_struct, r9) {
206 f(&mut self.r9);
207 } else if offset == memoffset::offset_of!(user_regs_struct, r8) {
208 f(&mut self.r8);
209 } else if offset == memoffset::offset_of!(user_regs_struct, rax) {
210 f(&mut self.rax);
211 } else if offset == memoffset::offset_of!(user_regs_struct, rcx) {
212 f(&mut self.rcx);
213 } else if offset == memoffset::offset_of!(user_regs_struct, rdx) {
214 f(&mut self.rdx);
215 } else if offset == memoffset::offset_of!(user_regs_struct, rsi) {
216 f(&mut self.rsi);
217 } else if offset == memoffset::offset_of!(user_regs_struct, rdi) {
218 f(&mut self.rdi);
219 } else if offset == memoffset::offset_of!(user_regs_struct, orig_rax) {
220 f(&mut self.orig_rax);
221 } else if offset == memoffset::offset_of!(user_regs_struct, rip) {
222 f(&mut self.ip);
223 } else if offset == memoffset::offset_of!(user_regs_struct, cs) {
224 let mut val = 0;
225 f(&mut val);
226 } else if offset == memoffset::offset_of!(user_regs_struct, eflags) {
227 f(&mut self.flags);
228 } else if offset == memoffset::offset_of!(user_regs_struct, rsp) {
229 f(&mut self.rsp);
230 } else if offset == memoffset::offset_of!(user_regs_struct, ss) {
231 let mut val = 0;
232 f(&mut val);
233 } else if offset == memoffset::offset_of!(user_regs_struct, fs_base) {
234 f(&mut self.fs_base);
235 } else if offset == memoffset::offset_of!(user_regs_struct, gs_base) {
236 f(&mut self.gs_base);
237 } else if offset == memoffset::offset_of!(user_regs_struct, ds) {
238 let mut val = 0;
239 f(&mut val);
240 } else if offset == memoffset::offset_of!(user_regs_struct, es) {
241 let mut val = 0;
242 f(&mut val);
243 } else if offset == memoffset::offset_of!(user_regs_struct, fs) {
244 let mut val = 0;
245 f(&mut val);
246 } else if offset == memoffset::offset_of!(user_regs_struct, gs) {
247 let mut val = 0;
248 f(&mut val);
249 } else {
250 return error!(EINVAL);
251 };
252 Ok(())
253 }
254
255 pub fn load(&mut self, regs: zx::sys::zx_restricted_state_t) {
256 *self.real_registers = regs;
257 self.sync_stack_ptr();
258 }
259
260 pub fn sync_stack_ptr(&mut self) {
261 self.orig_rax = self.rax;
262 }
263}
264
265impl<T: RegisterStorage> std::fmt::Debug for RegisterState<T> {
266 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
267 f.debug_struct("RegisterState")
268 .field("real_registers", &self.real_registers)
269 .field("orig_rax", &format_args!("{:#x}", &self.orig_rax))
270 .finish()
271 }
272}
273
274impl<T: RegisterStorage> std::ops::Deref for RegisterState<T> {
275 type Target = zx::sys::zx_restricted_state_t;
276
277 fn deref(&self) -> &Self::Target {
278 &*self.real_registers
279 }
280}
281
282impl<T: RegisterStorage> std::ops::DerefMut for RegisterState<T> {
283 fn deref_mut(&mut self) -> &mut Self::Target {
284 &mut *self.real_registers
285 }
286}
287
288impl From<RegisterState<HeapRegs>> for RegisterState<RegisterStorageEnum> {
289 fn from(regs: RegisterState<HeapRegs>) -> Self {
290 Self { real_registers: regs.real_registers.into(), orig_rax: regs.orig_rax }
291 }
292}
293
294impl From<RegisterState<RegisterStorageEnum>> for RegisterState<HeapRegs> {
295 fn from(regs: RegisterState<RegisterStorageEnum>) -> Self {
296 Self { real_registers: regs.real_registers.into(), orig_rax: regs.orig_rax }
297 }
298}