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