1 use super::prelude::*; 2 use crate::protocol::commands::ext::{ReverseCont, ReverseStep}; 3 4 use crate::arch::Arch; 5 use crate::common::Tid; 6 use crate::protocol::SpecificIdKind; 7 use crate::target::ext::base::reverse_exec::{ 8 ReverseCont as ReverseContTrait, ReverseStep as ReverseStepTrait, 9 }; 10 use crate::target::ext::base::ResumeOps; 11 12 macro_rules! defn_ops { 13 ($name:ident, $reverse_trait:ident, $f:ident) => { 14 enum $name<'a, A: Arch, E> { 15 SingleThread(&'a mut dyn $reverse_trait<(), Arch = A, Error = E>), 16 MultiThread(&'a mut dyn $reverse_trait<Tid, Arch = A, Error = E>), 17 } 18 19 impl<'a, A, E> $name<'a, A, E> 20 where 21 A: Arch, 22 { 23 #[inline(always)] 24 fn from_target<T>(target: &mut T) -> Option<$name<'_, T::Arch, T::Error>> 25 where 26 T: Target, 27 { 28 let ops = match target.base_ops().resume_ops()? { 29 ResumeOps::SingleThread(ops) => $name::SingleThread(ops.$f()?), 30 ResumeOps::MultiThread(ops) => $name::MultiThread(ops.$f()?), 31 }; 32 Some(ops) 33 } 34 } 35 }; 36 } 37 38 defn_ops!(ReverseContOps, ReverseContTrait, support_reverse_cont); 39 defn_ops!(ReverseStepOps, ReverseStepTrait, support_reverse_step); 40 41 impl<T: Target, C: Connection> GdbStubImpl<T, C> { handle_reverse_cont( &mut self, _res: &mut ResponseWriter<'_, C>, target: &mut T, command: ReverseCont, ) -> Result<HandlerStatus, Error<T::Error, C::Error>>42 pub(crate) fn handle_reverse_cont( 43 &mut self, 44 _res: &mut ResponseWriter<'_, C>, 45 target: &mut T, 46 command: ReverseCont, 47 ) -> Result<HandlerStatus, Error<T::Error, C::Error>> { 48 let ops = match ReverseContOps::<'_, T::Arch, T::Error>::from_target(target) { 49 Some(ops) => ops, 50 None => return Ok(HandlerStatus::Handled), 51 }; 52 53 crate::__dead_code_marker!("reverse_cont", "impl"); 54 55 let handler_status = match command { 56 ReverseCont::bc(_) => { 57 match ops { 58 ReverseContOps::MultiThread(ops) => { 59 ops.reverse_cont().map_err(Error::TargetError)? 60 } 61 ReverseContOps::SingleThread(ops) => { 62 ops.reverse_cont().map_err(Error::TargetError)? 63 } 64 } 65 66 HandlerStatus::DeferredStopReason 67 } 68 }; 69 70 Ok(handler_status) 71 } 72 73 // FIXME: De-duplicate with above code? handle_reverse_step( &mut self, _res: &mut ResponseWriter<'_, C>, target: &mut T, command: ReverseStep, ) -> Result<HandlerStatus, Error<T::Error, C::Error>>74 pub(crate) fn handle_reverse_step( 75 &mut self, 76 _res: &mut ResponseWriter<'_, C>, 77 target: &mut T, 78 command: ReverseStep, 79 ) -> Result<HandlerStatus, Error<T::Error, C::Error>> { 80 let ops = match ReverseStepOps::<'_, T::Arch, T::Error>::from_target(target) { 81 Some(ops) => ops, 82 None => return Ok(HandlerStatus::Handled), 83 }; 84 85 crate::__dead_code_marker!("reverse_step", "impl"); 86 87 let handler_status = match command { 88 ReverseStep::bs(_) => { 89 let tid = match self.current_resume_tid { 90 // NOTE: Can't single-step all cores. 91 SpecificIdKind::All => return Err(Error::PacketUnexpected), 92 SpecificIdKind::WithId(tid) => tid, 93 }; 94 95 match ops { 96 ReverseStepOps::MultiThread(ops) => { 97 ops.reverse_step(tid).map_err(Error::TargetError)? 98 } 99 ReverseStepOps::SingleThread(ops) => { 100 ops.reverse_step(()).map_err(Error::TargetError)? 101 } 102 } 103 104 HandlerStatus::DeferredStopReason 105 } 106 }; 107 108 Ok(handler_status) 109 } 110 } 111