1use core::fmt;
2
3use libc::user_regs_struct;
4use nix::{sys::ptrace, unistd::Pid};
5
6use crate::diag::Result;
7
8pub struct Registers {
14 pid: Pid,
15 regs: user_regs_struct,
16}
17
18impl Registers {
19 pub fn read(pid: Pid) -> Result<Self> {
33 Ok(Self {
34 pid,
35 regs: ptrace::getregs(pid)?,
36 })
37 }
38
39 pub fn write(&self) -> Result<()> {
49 ptrace::setregs(self.pid, self.regs)?;
50 Ok(())
51 }
52
53 #[must_use]
54 pub fn rip(&self) -> u64 {
61 self.regs.rip
62 }
63
64 pub fn set_rip(&mut self, value: u64) {
70 self.regs.rip = value;
71 }
72
73 #[must_use]
74 pub fn rsp(&self) -> u64 {
80 self.regs.rsp
81 }
82
83 #[must_use]
84 pub fn rax(&self) -> u64 {
90 self.regs.rax
91 }
92
93 #[must_use]
94 pub fn orig_rax(&self) -> u64 {
100 self.regs.orig_rax
101 }
102
103 #[must_use]
104 pub fn function_params(&self) -> [u64; 6] {
112 [
113 self.regs.rdi,
114 self.regs.rsi,
115 self.regs.rdx,
116 self.regs.r10,
117 self.regs.r8,
118 self.regs.r9,
119 ]
120 }
121}
122
123impl fmt::Display for Registers {
124 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
125 writeln!(f, "rip: {:#x}", self.regs.rip)?;
126 writeln!(f, "rsp: {:#x}", self.regs.rsp)?;
127 writeln!(f, "rbp: {:#x}", self.regs.rbp)?;
128 writeln!(f, "eflags: {:#x}", self.regs.eflags)?;
129 writeln!(f, "orig_rax: {:#x}", self.regs.orig_rax)?;
130 writeln!(f, "rax: {:#x}", self.regs.rax)?;
131 writeln!(f, "rbx: {:#x}", self.regs.rbx)?;
132 writeln!(f, "rcx: {:#x}", self.regs.rcx)?;
133 writeln!(f, "rdx: {:#x}", self.regs.rdx)?;
134 writeln!(f, "rdi: {:#x}", self.regs.rdi)?;
135 writeln!(f, "rsi: {:#x}", self.regs.rsi)?;
136 writeln!(f, "r8: {:#x}", self.regs.r8)?;
137 writeln!(f, "r9: {:#x}", self.regs.r9)?;
138 writeln!(f, "r10: {:#x}", self.regs.r10)?;
139 writeln!(f, "r11: {:#x}", self.regs.r11)?;
140 writeln!(f, "r12: {:#x}", self.regs.r12)?;
141 writeln!(f, "r13: {:#x}", self.regs.r13)?;
142 writeln!(f, "r14: {:#x}", self.regs.r14)?;
143 writeln!(f, "r15: {:#x}", self.regs.r15)?;
144 writeln!(f, "cs: {:#x}", self.regs.cs)?;
145 writeln!(f, "ds: {:#x}", self.regs.ds)?;
146 writeln!(f, "es: {:#x}", self.regs.es)?;
147 writeln!(f, "fs: {:#x}", self.regs.fs)?;
148 writeln!(f, "gs: {:#x}", self.regs.gs)?;
149 writeln!(f, "ss: {:#x}", self.regs.ss)?;
150 writeln!(f, "fs_base: {:#x}", self.regs.fs_base)?;
151 write!(f, "gs_base: {:#x}", self.regs.gs_base)
152 }
153}
154
155#[cfg(test)]
156mod tests {
157 use super::*;
158
159 use libc::user_regs_struct;
160 use nix::unistd::Pid;
161
162 fn make_regs() -> user_regs_struct {
163 user_regs_struct {
164 r15: 0,
165 r14: 0,
166 r13: 0,
167 r12: 0,
168 rbp: 0x2000,
169 rbx: 0x3000,
170 r11: 0,
171 r10: 0,
172 r9: 0,
173 r8: 0,
174 rax: 1,
175 rcx: 2,
176 rdx: 3,
177 rsi: 4,
178 rdi: 5,
179 orig_rax: 0,
180 rip: 0x1000,
181 cs: 0,
182 eflags: 0,
183 rsp: 0x4000,
184 ss: 0,
185 fs_base: 0,
186 gs_base: 0,
187 ds: 0,
188 es: 0,
189 fs: 0,
190 gs: 0,
191 }
192 }
193
194 #[test]
195 fn test_registers_accessors_and_display() {
196 let regs = make_regs();
197 let r = Registers {
198 pid: Pid::from_raw(1),
199 regs,
200 };
201 assert_eq!(r.rip(), 0x1000);
202 assert_eq!(r.rsp(), 0x4000);
203 assert_eq!(r.rax(), 1);
204 assert_eq!(r.function_params()[0], 5);
205
206 let s = format!("{}", r);
207 assert!(s.contains("rip:"));
208 assert!(s.contains("rsp:"));
209 }
210}