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