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