1pub trait RegDisplay {
13 fn display(&self) -> Display<'_> {
15 self.display_with_options(Default::default())
16 }
17
18 fn display_with_options(&self, options: RegDisplayOptions) -> Display<'_>;
21}
22
23impl RegDisplay for libc::user_regs_struct {
24 fn display_with_options(&self, options: RegDisplayOptions) -> Display<'_> {
25 Display {
26 options,
27 regs: self,
28 }
29 }
30}
31
32#[derive(Default)]
35pub struct RegDisplayOptions {
36 pub multiline: bool,
38}
39
40pub struct Display<'a> {
44 options: RegDisplayOptions,
45 regs: &'a libc::user_regs_struct,
46}
47
48impl<'a> Display<'a> {
49 #[cfg(target_arch = "x86_64")]
50 fn fmt_single_line_x86(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
51 write!(
52 f,
53 "rax {:#x} rbx {:#x} rcx {:#x} rdx {:#x}",
54 self.regs.rax, self.regs.rbx, self.regs.rcx, self.regs.rdx
55 )?;
56 write!(
57 f,
58 " rsi {:#x} rdi {:#x} rbp {:#x} rsp {:#x}",
59 self.regs.rsi, self.regs.rdi, self.regs.rbp, self.regs.rsp
60 )?;
61 write!(
62 f,
63 " r8 {:#x} r9 {:#x} r10 {:#x} r11 {:#x}",
64 self.regs.r8, self.regs.r9, self.regs.r10, self.regs.r11
65 )?;
66 write!(
67 f,
68 " r12 {:#x} r13 {:#x} r14 {:#x} r15 {:#x}",
69 self.regs.r12, self.regs.r13, self.regs.r14, self.regs.r15
70 )?;
71 write!(
72 f,
73 " rip {:#x} eflags {:#x}",
74 self.regs.rip, self.regs.eflags
75 )?;
76 write!(
77 f,
78 " cs {:#x} ss {:#x} ds {:#x} es {:#x}",
79 self.regs.cs, self.regs.ss, self.regs.ds, self.regs.es,
80 )?;
81 write!(f, " fs {:#x} gs {:#x}", self.regs.fs, self.regs.gs)
82 }
83 #[cfg(target_arch = "x86_64")]
84 fn fmt_multi_line_x86(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
85 writeln!(
86 f,
87 " rax {:#16x} rbx {:#16x} rcx {:#16x} rdx {:#16x}",
88 self.regs.rax, self.regs.rbx, self.regs.rcx, self.regs.rdx
89 )?;
90 writeln!(
91 f,
92 " rsi {:#16x} rdi {:#16x} rbp {:#16x} rsp {:#16x}",
93 self.regs.rsi, self.regs.rdi, self.regs.rbp, self.regs.rsp
94 )?;
95 writeln!(
96 f,
97 " r8 {:#16x} r9 {:#16x} r10 {:#16x} r11 {:#16x}",
98 self.regs.r8, self.regs.r9, self.regs.r10, self.regs.r11
99 )?;
100 writeln!(
101 f,
102 " r12 {:#16x} r13 {:#16x} r14 {:#16x} r15 {:#16x}",
103 self.regs.r12, self.regs.r13, self.regs.r14, self.regs.r15
104 )?;
105 writeln!(
106 f,
107 " rip {:#16x} eflags {:#16x}",
108 self.regs.rip, self.regs.eflags
109 )?;
110 writeln!(
111 f,
112 " cs {:#16x} ss {:#16x} ds {:#16x} es {:#16x}",
113 self.regs.cs, self.regs.ss, self.regs.ds, self.regs.es,
114 )?;
115 writeln!(f, " fs {:#16x} gs {:#16x}", self.regs.fs, self.regs.gs)
116 }
117}
118
119#[cfg(target_arch = "x86_64")]
120impl<'a> std::fmt::Display for Display<'a> {
121 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
122 if self.options.multiline {
123 self.fmt_multi_line_x86(f)
124 } else {
125 self.fmt_single_line_x86(f)
126 }
127 }
128}
129
130#[cfg(target_arch = "aarch64")]
131impl<'a> std::fmt::Display for Display<'a> {
132 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
133 write!(f, "{:?}", self.regs)
134 }
135}
136
137#[cfg(test)]
138mod tests {
139 use super::*;
140
141 #[test]
142 #[cfg(target_arch = "x86_64")]
143 fn test_single_line_x86() {
144 let mut regs: libc::user_regs_struct = unsafe { std::mem::zeroed() };
145 regs.rax = 255;
146 let result = format!("{}", regs.display());
147 assert_eq!(
148 result,
149 "rax 0xff rbx 0x0 rcx 0x0 rdx 0x0 rsi 0x0 rdi 0x0 rbp 0x0 rsp 0x0 r8 0x0 r9 0x0 r10 0x0 r11 0x0 r12 0x0 r13 0x0 r14 0x0 r15 0x0 rip 0x0 eflags 0x0 cs 0x0 ss 0x0 ds 0x0 es 0x0 fs 0x0 gs 0x0"
150 );
151 }
152
153 #[test]
154 #[cfg(target_arch = "x86_64")]
155 fn test_multi_line_x86() {
156 let mut regs: libc::user_regs_struct = unsafe { std::mem::zeroed() };
157 regs.rax = 255;
158 let result = format!(
159 "{}",
160 regs.display_with_options(RegDisplayOptions { multiline: true })
161 );
162 let lines = vec![
163 " rax 0xff rbx 0x0 rcx 0x0 rdx 0x0",
164 " rsi 0x0 rdi 0x0 rbp 0x0 rsp 0x0",
165 " r8 0x0 r9 0x0 r10 0x0 r11 0x0",
166 " r12 0x0 r13 0x0 r14 0x0 r15 0x0",
167 " rip 0x0 eflags 0x0",
168 " cs 0x0 ss 0x0 ds 0x0 es 0x0",
169 " fs 0x0 gs 0x0",
170 ];
171
172 assert_eq!(result.lines().collect::<Vec<&str>>(), lines);
173 }
174}