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