• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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