1use crate::debugger::error::Error;
2use crate::debugger::error::Error::{Ptrace, RegisterNotFound};
3use gimli::Register as DwarfRegister;
4use nix::libc::user_regs_struct;
5use nix::sys;
6use nix::unistd::Pid;
7use smallvec::{SmallVec, smallvec};
8use strum_macros::Display;
9use strum_macros::EnumString;
10
11#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, EnumString, Display)]
13#[strum(serialize_all = "snake_case")]
14pub enum Register {
15 Rax,
16 Rbx,
17 Rcx,
18 Rdx,
19 Rdi,
20 Rsi,
21 Rbp,
22 Rsp,
23 R8,
24 R9,
25 R10,
26 R11,
27 R12,
28 R13,
29 R14,
30 R15,
31 Rip,
32 Eflags,
33 Cs,
34 OrigRax,
35 FsBase,
36 GsBase,
37 Fs,
38 Gs,
39 Ss,
40 Ds,
41 Es,
42}
43
44impl Register {
45 pub fn dwarf_register(self) -> Option<DwarfRegister> {
46 let register = match self {
47 Register::Rax => 0,
48 Register::Rdx => 1,
49 Register::Rcx => 2,
50 Register::Rbx => 3,
51 Register::Rsi => 4,
52 Register::Rdi => 5,
53 Register::Rbp => 6,
54 Register::Rsp => 7,
55 Register::R8 => 8,
56 Register::R9 => 9,
57 Register::R10 => 10,
58 Register::R11 => 11,
59 Register::R12 => 12,
60 Register::R13 => 13,
61 Register::R14 => 14,
62 Register::R15 => 15,
63 Register::Rip => 16,
64 Register::Eflags => 49,
65 Register::Es => 50,
66 Register::Cs => 51,
67 Register::Ss => 52,
68 Register::Ds => 53,
69 Register::Fs => 54,
70 Register::Gs => 55,
71 Register::FsBase => 58,
72 Register::GsBase => 59,
73 Register::OrigRax => return None,
74 };
75 Some(DwarfRegister(register))
76 }
77}
78
79impl From<gimli::Register> for Register {
80 fn from(value: gimli::Register) -> Self {
81 match value.0 as i32 {
82 -1 => Register::Rip,
83 0 => Register::Rax,
85 1 => Register::Rdx,
86 2 => Register::Rcx,
87 3 => Register::Rbx,
88 4 => Register::Rsi,
89 5 => Register::Rdi,
90 6 => Register::Rbp,
91 7 => Register::Rsp,
92 8 => Register::R8,
93 9 => Register::R9,
94 10 => Register::R10,
95 11 => Register::R11,
96 12 => Register::R12,
97 13 => Register::R13,
98 14 => Register::R14,
99 15 => Register::R15,
100 49 => Register::Eflags,
101 50 => Register::Es,
102 51 => Register::Cs,
103 52 => Register::Ss,
104 53 => Register::Ds,
105 54 => Register::Fs,
106 55 => Register::Gs,
107 58 => Register::FsBase,
108 59 => Register::GsBase,
109 _ => {
110 panic!("unknown dwarf register number");
111 }
112 }
113 }
114}
115
116#[derive(Debug, Clone)]
118pub struct RegisterMap {
119 rax: u64,
120 rbx: u64,
121 rcx: u64,
122 rdx: u64,
123 rdi: u64,
124 rsi: u64,
125 rbp: u64,
126 rsp: u64,
127 r8: u64,
128 r9: u64,
129 r10: u64,
130 r11: u64,
131 r12: u64,
132 r13: u64,
133 r14: u64,
134 r15: u64,
135 rip: u64,
136 eflags: u64,
137 cs: u64,
138 orig_rax: u64,
139 fs_base: u64,
140 gs_base: u64,
141 fs: u64,
142 gs: u64,
143 ss: u64,
144 ds: u64,
145 es: u64,
146}
147
148impl From<user_regs_struct> for RegisterMap {
149 fn from(value: user_regs_struct) -> Self {
150 Self {
151 rax: value.rax,
152 rbx: value.rbx,
153 rcx: value.rcx,
154 rdx: value.rdx,
155 rdi: value.rdi,
156 rsi: value.rsi,
157 rbp: value.rbp,
158 rsp: value.rsp,
159 r8: value.r8,
160 r9: value.r9,
161 r10: value.r10,
162 r11: value.r11,
163 r12: value.r12,
164 r13: value.r13,
165 r14: value.r14,
166 r15: value.r15,
167 rip: value.rip,
168 eflags: value.eflags,
169 cs: value.cs,
170 orig_rax: value.orig_rax,
171 fs_base: value.fs_base,
172 gs_base: value.gs_base,
173 fs: value.fs,
174 gs: value.gs,
175 ss: value.ss,
176 ds: value.ds,
177 es: value.es,
178 }
179 }
180}
181
182impl From<RegisterMap> for user_regs_struct {
183 fn from(reg_map: RegisterMap) -> user_regs_struct {
184 user_regs_struct {
185 rax: reg_map.rax,
186 rbx: reg_map.rbx,
187 rcx: reg_map.rcx,
188 rdx: reg_map.rdx,
189 rdi: reg_map.rdi,
190 rsi: reg_map.rsi,
191 rbp: reg_map.rbp,
192 rsp: reg_map.rsp,
193 r8: reg_map.r8,
194 r9: reg_map.r9,
195 r10: reg_map.r10,
196 r11: reg_map.r11,
197 r12: reg_map.r12,
198 r13: reg_map.r13,
199 r14: reg_map.r14,
200 r15: reg_map.r15,
201 rip: reg_map.rip,
202 eflags: reg_map.eflags,
203 cs: reg_map.cs,
204 orig_rax: reg_map.orig_rax,
205 fs_base: reg_map.fs_base,
206 gs_base: reg_map.gs_base,
207 fs: reg_map.fs,
208 gs: reg_map.gs,
209 ss: reg_map.ss,
210 ds: reg_map.ds,
211 es: reg_map.es,
212 }
213 }
214}
215
216impl RegisterMap {
217 pub fn current(pid: Pid) -> Result<Self, Error> {
223 let regs = sys::ptrace::getregs(pid).map_err(Ptrace)?;
224 Ok(regs.into())
225 }
226
227 pub fn value(&self, register: impl Into<Register>) -> u64 {
233 let register = register.into();
234 match register {
235 Register::Rax => self.rax,
236 Register::Rbx => self.rbx,
237 Register::Rcx => self.rcx,
238 Register::Rdx => self.rdx,
239 Register::Rdi => self.rdi,
240 Register::Rsi => self.rsi,
241 Register::Rbp => self.rbp,
242 Register::Rsp => self.rsp,
243 Register::R8 => self.r8,
244 Register::R9 => self.r9,
245 Register::R10 => self.r10,
246 Register::R11 => self.r11,
247 Register::R12 => self.r12,
248 Register::R13 => self.r13,
249 Register::R14 => self.r14,
250 Register::R15 => self.r15,
251 Register::Rip => self.rip,
252 Register::Eflags => self.eflags,
253 Register::Cs => self.cs,
254 Register::OrigRax => self.orig_rax,
255 Register::FsBase => self.fs_base,
256 Register::GsBase => self.gs_base,
257 Register::Fs => self.fs,
258 Register::Gs => self.gs,
259 Register::Ss => self.ss,
260 Register::Ds => self.ds,
261 Register::Es => self.es,
262 }
263 }
264
265 pub fn update(&mut self, register: impl Into<Register>, value: u64) {
272 match register.into() {
273 Register::Rax => self.rax = value,
274 Register::Rbx => self.rbx = value,
275 Register::Rcx => self.rcx = value,
276 Register::Rdx => self.rdx = value,
277 Register::Rdi => self.rdi = value,
278 Register::Rsi => self.rsi = value,
279 Register::Rbp => self.rbp = value,
280 Register::Rsp => self.rsp = value,
281 Register::R8 => self.r8 = value,
282 Register::R9 => self.r9 = value,
283 Register::R10 => self.r10 = value,
284 Register::R11 => self.r11 = value,
285 Register::R12 => self.r12 = value,
286 Register::R13 => self.r13 = value,
287 Register::R14 => self.r14 = value,
288 Register::R15 => self.r15 = value,
289 Register::Rip => self.rip = value,
290 Register::Eflags => self.eflags = value,
291 Register::Cs => self.cs = value,
292 Register::OrigRax => self.orig_rax = value,
293 Register::FsBase => self.fs_base = value,
294 Register::GsBase => self.gs_base = value,
295 Register::Fs => self.fs = value,
296 Register::Gs => self.gs = value,
297 Register::Ss => self.ss = value,
298 Register::Ds => self.ds = value,
299 Register::Es => self.es = value,
300 };
301 }
302
303 pub fn persist(self, pid: Pid) -> Result<(), Error> {
309 sys::ptrace::setregs(pid, self.into()).map_err(Ptrace)
310 }
311}
312
313#[derive(Debug, Clone)]
315pub struct DwarfRegisterMap(SmallVec<[Option<u64>; 0x80]>);
316
317impl DwarfRegisterMap {
318 pub fn value(&self, register: gimli::Register) -> Result<u64, Error> {
324 self.0
325 .get(register.0 as usize)
326 .copied()
327 .and_then(|v| v)
328 .ok_or(RegisterNotFound(register))
329 }
330
331 pub fn update(&mut self, register: gimli::Register, value: u64) {
338 self.0[register.0 as usize] = Some(value);
339 }
340
341 pub fn update_from(&mut self, other: &Self) {
348 for (idx, value) in other.0.iter().enumerate() {
349 if let Some(value) = value {
350 self.0[idx] = Some(*value);
351 }
352 }
353 }
354}
355
356impl From<RegisterMap> for DwarfRegisterMap {
359 fn from(map: RegisterMap) -> Self {
360 let mut dwarf_map = smallvec![None; 0x80];
361 dwarf_map.insert(0, Some(map.rax));
362 dwarf_map.insert(1, Some(map.rdx));
363 dwarf_map.insert(2, Some(map.rcx));
364 dwarf_map.insert(3, Some(map.rbx));
365 dwarf_map.insert(4, Some(map.rsi));
366 dwarf_map.insert(5, Some(map.rdi));
367 dwarf_map.insert(6, Some(map.rbp));
368 dwarf_map.insert(7, Some(map.rsp));
369 dwarf_map.insert(8, Some(map.r8));
370 dwarf_map.insert(9, Some(map.r9));
371 dwarf_map.insert(10, Some(map.r10));
372 dwarf_map.insert(11, Some(map.r11));
373 dwarf_map.insert(12, Some(map.r12));
374 dwarf_map.insert(13, Some(map.r13));
375 dwarf_map.insert(14, Some(map.r14));
376 dwarf_map.insert(15, Some(map.r15));
377 dwarf_map.insert(16, Some(map.rip));
378 dwarf_map.insert(49, Some(map.eflags));
379 dwarf_map.insert(50, Some(map.es));
380 dwarf_map.insert(51, Some(map.cs));
381 dwarf_map.insert(52, Some(map.ss));
382 dwarf_map.insert(53, Some(map.ds));
383 dwarf_map.insert(54, Some(map.fs));
384 dwarf_map.insert(55, Some(map.gs));
385 dwarf_map.insert(58, Some(map.fs_base));
386 dwarf_map.insert(59, Some(map.gs_base));
387 DwarfRegisterMap(dwarf_map)
388 }
389}
390
391pub mod debug {
392 use crate::debugger::Error;
393 use crate::debugger::Error::Ptrace;
394 use bit_field::BitField;
395 use nix::sys;
396 use nix::sys::ptrace::AddressType;
397 use nix::unistd::Pid;
398 use std::ffi::c_void;
399 use std::fmt::{Display, Formatter};
400 use std::mem::offset_of;
401 use strum_macros::FromRepr;
402
403 #[repr(usize)]
405 #[derive(Clone, Copy, Debug, PartialEq, FromRepr)]
406 pub enum DebugRegisterNumber {
407 DR0,
408 DR1,
409 DR2,
410 DR3,
411 }
412
413 pub type DebugAddressRegister = usize;
414
415 #[derive(Clone, Copy, PartialEq, Debug)]
416 pub struct DebugStatusRegister(usize);
417
418 macro_rules! impl_trap {
419 ($fn_name: ident, $trap: path) => {
420 #[doc = "Return true if breakpoint X condition was detected."]
421 #[doc = "Reset the corresponding flag."]
422 pub fn $fn_name(&mut self) -> bool {
423 let is_set = (self.0 & $trap) == $trap;
424 self.0 &= !$trap;
425 is_set
426 }
427 };
428 }
429
430 impl DebugStatusRegister {
431 const TRAP0: usize = 1;
433 const TRAP1: usize = 1 << 1;
435 const TRAP2: usize = 1 << 2;
437 const TRAP3: usize = 1 << 3;
439
440 impl_trap!(trap0, Self::TRAP0);
441 impl_trap!(trap1, Self::TRAP1);
442 impl_trap!(trap2, Self::TRAP2);
443 impl_trap!(trap3, Self::TRAP3);
444
445 pub fn detect_and_flush(&mut self) -> Option<DebugRegisterNumber> {
447 let dr = if self.trap0() {
448 DebugRegisterNumber::DR0
449 } else if self.trap1() {
450 DebugRegisterNumber::DR1
451 } else if self.trap2() {
452 DebugRegisterNumber::DR2
453 } else if self.trap3() {
454 DebugRegisterNumber::DR3
455 } else {
456 return None;
457 };
458 Some(dr)
459 }
460 }
461
462 #[derive(Clone, Copy, PartialEq, Debug)]
463 pub struct DebugControlRegister(usize);
464
465 impl DebugControlRegister {
466 const LOCAL_EXACT_BREAKPOINT_ENABLE_BIT: usize = 8;
470 const GLOBAL_EXACT_BREAKPOINT_ENABLE_BIT: usize = 9;
474
475 #[inline(always)]
482 pub fn dr_enabled(&self, dr: DebugRegisterNumber, global: bool) -> bool {
483 let dr = dr as usize;
484 let idx = if global { dr * 2 + 1 } else { dr * 2 };
485 debug_assert!(idx <= 7);
486 self.0.get_bit(idx)
487 }
488
489 #[inline(always)]
497 pub fn configure_bp(
498 &mut self,
499 dr: DebugRegisterNumber,
500 cond: BreakCondition,
501 size: BreakSize,
502 ) {
503 let dr = dr as usize;
504 let idx = 16 + (dr * 4);
506 self.0.set_bits(idx..=idx + 1, cond as usize);
507 let idx = 18 + (dr * 4);
509 self.0.set_bits(idx..=idx + 1, size as usize);
510 }
511
512 #[inline(always)]
519 pub fn set_dr(&mut self, dr: DebugRegisterNumber, global: bool, enable: bool) {
520 let dr = dr as usize;
521 let idx = if global { dr * 2 + 1 } else { dr * 2 };
522 self.0.set_bit(idx, enable);
523
524 let detection_bit = if global {
525 Self::GLOBAL_EXACT_BREAKPOINT_ENABLE_BIT
526 } else {
527 Self::LOCAL_EXACT_BREAKPOINT_ENABLE_BIT
528 };
529
530 if enable {
531 self.0.set_bit(detection_bit, true);
532 } else {
533 let all_disabled = [0, 1, 2, 3].iter().all(|&n| {
534 !self.dr_enabled(
535 DebugRegisterNumber::from_repr(n).expect("infallible"),
536 global,
537 )
538 });
539 if all_disabled {
540 self.0.set_bit(detection_bit, false);
541 }
542 }
543 }
544 }
545
546 #[derive(PartialEq, Debug)]
547 pub struct HardwareDebugState {
548 pub address_regs: [DebugAddressRegister; 4],
550 pub dr6: DebugStatusRegister,
552 pub dr7: DebugControlRegister,
554 }
555
556 impl HardwareDebugState {
557 pub fn current(pid: Pid) -> Result<Self, Error> {
563 use nix::libc::user;
564
565 fn get_dr(pid: Pid, num: usize) -> Result<usize, Error> {
566 let offset = offset_of!(user, u_debugreg) + num * 8;
567 Ok(sys::ptrace::read_user(pid, offset as AddressType).map_err(Ptrace)? as usize)
568 }
569
570 Ok(Self {
571 address_regs: [
572 get_dr(pid, 0)?,
573 get_dr(pid, 1)?,
574 get_dr(pid, 2)?,
575 get_dr(pid, 3)?,
576 ],
577 dr6: DebugStatusRegister(get_dr(pid, 6)?),
578 dr7: DebugControlRegister(get_dr(pid, 7)?),
579 })
580 }
581
582 pub fn sync(&self, pid: Pid) -> Result<(), Error> {
588 fn set_dr(pid: Pid, num: usize, data: usize) -> Result<(), Error> {
589 let offset = offset_of!(nix::libc::user, u_debugreg);
590 let offset = offset + num * 8;
591 unsafe {
592 sys::ptrace::write_user(pid, offset as AddressType, data as *mut c_void)
593 .map_err(Ptrace)
594 }
595 }
596
597 for (reg_num, val) in self.address_regs.iter().enumerate() {
598 set_dr(pid, reg_num, *val)?;
599 }
600 set_dr(pid, 6, self.dr6.0)?;
601 set_dr(pid, 7, self.dr7.0)?;
602 Ok(())
603 }
604 }
605
606 #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd)]
610 pub enum BreakCondition {
611 DataWrites = 0b01,
613 DataReadsWrites = 0b11,
615 }
616
617 impl Display for BreakCondition {
618 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
619 match self {
620 BreakCondition::DataWrites => f.write_str("w"),
621 BreakCondition::DataReadsWrites => f.write_str("rw"),
622 }
623 }
624 }
625
626 #[derive(Debug, Copy, Clone, PartialEq, Eq)]
629 pub enum BreakSize {
630 Bytes1 = 0b00,
632 Bytes2 = 0b01,
634 Bytes8 = 0b10,
636 Bytes4 = 0b11,
638 }
639
640 impl TryFrom<u8> for BreakSize {
641 type Error = Error;
642
643 fn try_from(value: u8) -> Result<Self, Self::Error> {
644 let size = match value {
645 1 => BreakSize::Bytes1,
646 2 => BreakSize::Bytes2,
647 4 => BreakSize::Bytes4,
648 8 => BreakSize::Bytes8,
649 _ => return Err(Error::WatchpointWrongSize),
650 };
651 Ok(size)
652 }
653 }
654
655 impl Display for BreakSize {
656 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
657 match self {
658 BreakSize::Bytes1 => f.write_str("1b"),
659 BreakSize::Bytes2 => f.write_str("2b"),
660 BreakSize::Bytes8 => f.write_str("8b"),
661 BreakSize::Bytes4 => f.write_str("4b"),
662 }
663 }
664 }
665}