1 use super::prelude::*; 2 use crate::common::Signal; 3 use crate::protocol::common::hex::HexString; 4 use crate::protocol::common::thread_id::SpecificThreadId; 5 use crate::protocol::common::thread_id::ThreadId; 6 use crate::protocol::IdKind; 7 8 // TODO?: instead of lazily parsing data, parse the strings into a compressed 9 // binary representations that can be stuffed back into the packet buffer and 10 // return an iterator over the binary data that's _guaranteed_ to be valid. This 11 // would clean up some of the code in the vCont handler. 12 // 13 // The interesting part would be to see whether or not the simplified error 14 // handing code will compensate for all the new code required to pre-validate 15 // the data... 16 #[derive(Debug)] 17 pub enum vCont<'a> { 18 Query, 19 Actions(Actions<'a>), 20 } 21 22 impl<'a> ParseCommand<'a> for vCont<'a> { 23 #[inline(always)] from_packet(buf: PacketBuf<'a>) -> Option<Self>24 fn from_packet(buf: PacketBuf<'a>) -> Option<Self> { 25 let body = buf.into_body(); 26 match body as &[u8] { 27 b"?" => Some(vCont::Query), 28 _ => Some(vCont::Actions(Actions::new_from_buf(body))), 29 } 30 } 31 } 32 33 #[derive(Debug)] 34 pub enum Actions<'a> { 35 Buf(ActionsBuf<'a>), 36 FixedStep(SpecificThreadId), 37 FixedCont(SpecificThreadId), 38 } 39 40 impl<'a> Actions<'a> { new_from_buf(buf: &'a [u8]) -> Actions<'a>41 fn new_from_buf(buf: &'a [u8]) -> Actions<'a> { 42 Actions::Buf(ActionsBuf(buf)) 43 } 44 45 #[inline(always)] new_step(tid: SpecificThreadId) -> Actions<'a>46 pub fn new_step(tid: SpecificThreadId) -> Actions<'a> { 47 Actions::FixedStep(tid) 48 } 49 50 #[inline(always)] new_continue(tid: SpecificThreadId) -> Actions<'a>51 pub fn new_continue(tid: SpecificThreadId) -> Actions<'a> { 52 Actions::FixedCont(tid) 53 } 54 iter(&self) -> impl Iterator<Item = Option<VContAction<'a>>> + '_55 pub fn iter(&self) -> impl Iterator<Item = Option<VContAction<'a>>> + '_ { 56 match self { 57 Actions::Buf(x) => EitherIter::A(x.iter()), 58 Actions::FixedStep(x) => EitherIter::B(core::iter::once(Some(VContAction { 59 kind: VContKind::Step, 60 thread: Some(*x), 61 }))), 62 Actions::FixedCont(x) => EitherIter::B(core::iter::once(Some(VContAction { 63 kind: VContKind::Continue, 64 thread: Some(*x), 65 }))), 66 } 67 } 68 } 69 70 #[derive(Debug)] 71 pub struct ActionsBuf<'a>(&'a [u8]); 72 73 impl<'a> ActionsBuf<'a> { iter(&self) -> impl Iterator<Item = Option<VContAction<'a>>> + '_74 fn iter(&self) -> impl Iterator<Item = Option<VContAction<'a>>> + '_ { 75 self.0.split(|b| *b == b';').skip(1).map(|act| { 76 let mut s = act.split(|b| *b == b':'); 77 let kind = s.next()?; 78 let thread = match s.next() { 79 Some(s) => { 80 let mut tid = ThreadId::try_from(s).ok()?; 81 82 // Based on my (somewhat superficial) readings of the 83 // `gdbserver` and `gdb` codebases, it doesn't seem like 84 // there's any consensus on how vCont packets with a TID of 85 // `Any` should be be handled. 86 // 87 // `gdbserver` delegates the handling of this packet to 88 // individual targets, and in-turn, it seems most targets 89 // don't actually do any special handling of the 'Any' TID. 90 // They'll explicitly check for the 'All' TID, but then 91 // proceed to erroneously treat the 'Any' TID as though it 92 // was simply a request for a TID with ID of '0' to be 93 // resumed (which is prohibited by the GDB RSP spec). 94 // 95 // This behavior makes sense, given the context that AFAIK, 96 // upstream GDB never actually sends vCont packets with a 97 // 'Any' TID! Instead, upstream GDB will first query the 98 // remote to obtain a list of valid TIDs, and then send over 99 // a vCont packet with a specific TID selected. 100 101 // So, with all that said - how should `gdbstub` handle 102 // these sorts of packets? 103 // 104 // Unfortunately, it seems like there are some weird 105 // third-party GDB clients out there that do in-fact send an 106 // 'Any' TID as part of a vCont packet. 107 // 108 // See issue #150 for more info. 109 // 110 // As a workaround for these weird GDB clients, `gdbstub` 111 // takes the pragmatic approach of treating this request as 112 // though it the client requested _all_ threads to be 113 // resumed. 114 // 115 // If this turns out to be wrong... `gdbstub` can explore a 116 // more involved fix, whereby we bubble-up this `Any` 117 // request to the stub code itself, whereupon the stub can 118 // attempt to pick a "reasonable" TID to individually 119 // resume. 120 if tid.tid == IdKind::Any { 121 tid.tid = IdKind::All; 122 } 123 124 Some(SpecificThreadId::try_from(tid).ok()?) 125 } 126 None => None, 127 }; 128 129 Some(VContAction { 130 kind: VContKind::from_bytes(kind)?, 131 thread, 132 }) 133 }) 134 } 135 } 136 137 #[derive(Debug, Copy, Clone)] 138 pub struct VContAction<'a> { 139 pub kind: VContKind<'a>, 140 pub thread: Option<SpecificThreadId>, 141 } 142 143 #[derive(Debug, Copy, Clone)] 144 pub enum VContKind<'a> { 145 Continue, 146 ContinueWithSig(Signal), 147 RangeStep(HexString<'a>, HexString<'a>), 148 Step, 149 StepWithSig(Signal), 150 Stop, 151 } 152 153 impl<'a> VContKind<'a> { 154 #[inline(always)] from_bytes(s: &[u8]) -> Option<VContKind<'_>>155 fn from_bytes(s: &[u8]) -> Option<VContKind<'_>> { 156 use self::VContKind::*; 157 158 let res = match s { 159 [b'c'] => Continue, 160 [b's'] => Step, 161 [b't'] => Stop, 162 [b'C', sig @ ..] => ContinueWithSig(Signal(decode_hex(sig).ok()?)), 163 [b'S', sig @ ..] => StepWithSig(Signal(decode_hex(sig).ok()?)), 164 [b'r', range @ ..] => { 165 let mut range = range.split(|b| *b == b','); 166 RangeStep(HexString(range.next()?), HexString(range.next()?)) 167 } 168 _ => return None, 169 }; 170 171 Some(res) 172 } 173 } 174 175 /// Helper type to unify iterators that output the same type. Returned as an 176 /// opaque type from `Actions::iter()`. 177 enum EitherIter<A, B> { 178 A(A), 179 B(B), 180 } 181 182 impl<A, B, T> Iterator for EitherIter<A, B> 183 where 184 A: Iterator<Item = T>, 185 B: Iterator<Item = T>, 186 { 187 type Item = T; 188 189 #[inline(always)] next(&mut self) -> Option<T>190 fn next(&mut self) -> Option<T> { 191 match self { 192 EitherIter::A(a) => a.next(), 193 EitherIter::B(b) => b.next(), 194 } 195 } 196 } 197