• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use crate::protocol::common::hex::{decode_hex, decode_hex_buf};
2 
3 // Breakpoint packets are split up like this:
4 //
5 // Z0,addr,kind[;cond_list…][;cmds:persist,cmd_list…]
6 //  \_________/
7 //       |
8 //     BasicBreakpoint
9 //  \_______________________________________________/
10 //                          |
11 //                  BytecodeBreakpoint
12 //
13 // If the target does not implement the `Agent` extension, only the
14 // `BasicBreakpoint` part is parsed, which helps cut down on binary bloat.
15 
16 #[derive(Debug)]
17 pub struct BasicBreakpoint<'a> {
18     pub type_: u8,
19     pub addr: &'a [u8],
20     /// architecture dependent
21     pub kind: &'a [u8],
22 }
23 
24 impl<'a> BasicBreakpoint<'a> {
from_slice(body: &'a mut [u8]) -> Option<BasicBreakpoint<'a>>25     pub fn from_slice(body: &'a mut [u8]) -> Option<BasicBreakpoint<'a>> {
26         let mut body = body.splitn_mut(4, |b| matches!(*b, b',' | b';'));
27         let type_ = decode_hex(body.next()?).ok()?;
28         let addr = decode_hex_buf(body.next()?).ok()?;
29         let kind = decode_hex_buf(body.next()?).ok()?;
30 
31         Some(BasicBreakpoint { type_, addr, kind })
32     }
33 }
34 
35 #[derive(Debug)]
36 pub struct BytecodeBreakpoint<'a> {
37     pub base: BasicBreakpoint<'a>,
38     pub conds: Option<BytecodeList<'a>>,
39     pub cmds_persist: Option<(BytecodeList<'a>, bool)>,
40 }
41 
42 impl<'a> BytecodeBreakpoint<'a> {
from_slice(body: &'a mut [u8]) -> Option<BytecodeBreakpoint<'a>>43     pub fn from_slice(body: &'a mut [u8]) -> Option<BytecodeBreakpoint<'a>> {
44         let mut body = body.splitn_mut(2, |b| *b == b';');
45 
46         let base = BasicBreakpoint::from_slice(body.next()?)?;
47 
48         let mut conds = None;
49         let mut cmds_persist = None;
50 
51         if let Some(rest) = body.next() {
52             let mut s = rest.split_mut(|b| *b == b':');
53             let (raw_conds, raw_cmds) = match (s.next(), s.next()) {
54                 (Some(a), Some(b)) => (Some(strip_suffix_mut(a, b";cmds")?), Some(b)),
55                 (Some(a), None) => {
56                     if a.starts_with(b"cmds") {
57                         (None, Some(a))
58                     } else {
59                         (Some(a), None)
60                     }
61                 }
62                 _ => return None,
63             };
64 
65             if let Some(raw_conds) = raw_conds {
66                 conds = Some(BytecodeList(raw_conds));
67             }
68 
69             if let Some(raw_cmds) = raw_cmds {
70                 let mut raw_cmds = raw_cmds.split_mut(|b| *b == b',');
71                 let raw_persist = decode_hex::<u8>(raw_cmds.next()?).ok()? != 0;
72                 let raw_cmds = raw_cmds.next()?;
73 
74                 cmds_persist = Some((BytecodeList(raw_cmds), raw_persist));
75             }
76         }
77 
78         Some(BytecodeBreakpoint {
79             base,
80             conds,
81             cmds_persist,
82         })
83     }
84 }
85 
strip_suffix_mut<'a, T>(slice: &'a mut [T], suffix: &[T]) -> Option<&'a mut [T]> where T: PartialEq,86 fn strip_suffix_mut<'a, T>(slice: &'a mut [T], suffix: &[T]) -> Option<&'a mut [T]>
87 where
88     T: PartialEq,
89 {
90     let (len, n) = (slice.len(), suffix.len());
91     if n <= len {
92         let (head, tail) = slice.split_at_mut(len - n);
93         if tail == suffix {
94             return Some(head);
95         }
96     }
97     None
98 }
99 
100 /// A lazily evaluated iterator over a series of bytecode expressions.
101 #[derive(Debug)]
102 pub struct BytecodeList<'a>(&'a mut [u8]);
103 
104 impl<'a> BytecodeList<'a> {
105     #[allow(dead_code)]
into_iter(self) -> impl Iterator<Item = Option<&'a [u8]>> + 'a106     pub fn into_iter(self) -> impl Iterator<Item = Option<&'a [u8]>> + 'a {
107         self.0.split_mut(|b| *b == b'X').skip(1).map(|s| {
108             let mut s = s.split_mut(|b| *b == b',');
109             let _len = s.next()?;
110             let code = decode_hex_buf(s.next()?).ok()?;
111             Some(code as &[u8])
112         })
113     }
114 }
115