• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //! Stop reasons reported back to the GDB client.
2 
3 use crate::arch::Arch;
4 use crate::common::Signal;
5 use crate::common::Tid;
6 use crate::target::ext::base::reverse_exec::ReplayLogPosition;
7 use crate::target::ext::breakpoints::WatchKind;
8 use crate::target::ext::catch_syscalls::CatchSyscallPosition;
9 use crate::target::Target;
10 
11 /// Describes why a thread stopped.
12 ///
13 /// Single threaded targets should set `Tid` to `()`, whereas multi threaded
14 /// targets should set `Tid` to [`Tid`]. To make things easier, it is
15 /// recommended to use the [`SingleThreadStopReason`] and
16 /// [`MultiThreadStopReason`] when possible.
17 ///
18 ///
19 ///
20 /// Targets MUST only respond with stop reasons that correspond to IDETs that
21 /// target has implemented. Not doing so will result in a runtime error.
22 ///
23 /// e.g: A target which has not implemented the [`HwBreakpoint`] IDET must not
24 /// return a `HwBreak` stop reason. While this is not enforced at compile time,
25 /// doing so will result in a runtime `UnsupportedStopReason` error.
26 ///
27 /// [`HwBreakpoint`]: crate::target::ext::breakpoints::HwBreakpoint
28 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
29 #[non_exhaustive]
30 pub enum BaseStopReason<Tid, U> {
31     /// Completed the single-step request.
32     DoneStep,
33     /// The process exited with the specified exit status.
34     Exited(u8),
35     /// The process terminated with the specified signal number.
36     Terminated(Signal),
37     /// The program received a signal.
38     Signal(Signal),
39     /// A specific thread received a signal.
40     SignalWithThread {
41         /// Tid of the associated thread
42         tid: Tid,
43         /// The signal
44         signal: Signal,
45     },
46     /// A thread hit a software breakpoint (e.g. due to a trap instruction).
47     ///
48     /// Requires: [`SwBreakpoint`].
49     ///
50     /// NOTE: This does not necessarily have to be a breakpoint configured by
51     /// the client/user of the current GDB session.
52     ///
53     /// [`SwBreakpoint`]: crate::target::ext::breakpoints::SwBreakpoint
54     SwBreak(Tid),
55     /// A thread hit a hardware breakpoint.
56     ///
57     /// Requires: [`HwBreakpoint`].
58     ///
59     /// [`HwBreakpoint`]: crate::target::ext::breakpoints::HwBreakpoint
60     HwBreak(Tid),
61     /// A thread hit a watchpoint.
62     ///
63     /// Requires: [`HwWatchpoint`].
64     ///
65     /// [`HwWatchpoint`]: crate::target::ext::breakpoints::HwWatchpoint
66     Watch {
67         /// Tid of the associated thread
68         tid: Tid,
69         /// Kind of watchpoint that was hit
70         kind: WatchKind,
71         /// Address of watched memory
72         addr: U,
73     },
74     /// The program has reached the end of the logged replay events.
75     ///
76     /// Requires: [`ReverseCont`] or [`ReverseStep`].
77     ///
78     /// This is used for GDB's reverse execution. When playing back a recording,
79     /// you may hit the end of the buffer of recorded events, and as such no
80     /// further execution can be done. This stop reason tells GDB that this has
81     /// occurred.
82     ///
83     /// [`ReverseCont`]: crate::target::ext::base::reverse_exec::ReverseCont
84     /// [`ReverseStep`]: crate::target::ext::base::reverse_exec::ReverseStep
85     ReplayLog {
86         /// (optional) Tid of the associated thread.
87         tid: Option<Tid>,
88         /// The point reached in a replay log (i.e: beginning vs. end).
89         pos: ReplayLogPosition,
90     },
91     /// The program has reached a syscall entry or return location.
92     ///
93     /// Requires: [`CatchSyscalls`].
94     ///
95     /// [`CatchSyscalls`]: crate::target::ext::catch_syscalls::CatchSyscalls
96     CatchSyscall {
97         /// (optional) Tid of the associated thread.
98         tid: Option<Tid>,
99         /// The syscall number.
100         number: U,
101         /// The location the event occurred at.
102         position: CatchSyscallPosition,
103     },
104 }
105 
106 /// A stop reason for a single threaded target.
107 ///
108 /// Threads are identified using the unit type `()` (as there is only a single
109 /// possible thread-id).
110 pub type SingleThreadStopReason<U> = BaseStopReason<(), U>;
111 
112 /// A stop reason for a multi threaded target.
113 ///
114 /// Threads are identified using a [`Tid`].
115 pub type MultiThreadStopReason<U> = BaseStopReason<Tid, U>;
116 
117 impl<U> From<BaseStopReason<(), U>> for BaseStopReason<Tid, U> {
from(st_stop_reason: BaseStopReason<(), U>) -> BaseStopReason<Tid, U>118     fn from(st_stop_reason: BaseStopReason<(), U>) -> BaseStopReason<Tid, U> {
119         match st_stop_reason {
120             BaseStopReason::DoneStep => BaseStopReason::DoneStep,
121             BaseStopReason::Exited(code) => BaseStopReason::Exited(code),
122             BaseStopReason::Terminated(sig) => BaseStopReason::Terminated(sig),
123             BaseStopReason::SignalWithThread { signal, .. } => BaseStopReason::SignalWithThread {
124                 tid: crate::SINGLE_THREAD_TID,
125                 signal,
126             },
127             BaseStopReason::SwBreak(_) => BaseStopReason::SwBreak(crate::SINGLE_THREAD_TID),
128             BaseStopReason::HwBreak(_) => BaseStopReason::HwBreak(crate::SINGLE_THREAD_TID),
129             BaseStopReason::Watch { kind, addr, .. } => BaseStopReason::Watch {
130                 tid: crate::SINGLE_THREAD_TID,
131                 kind,
132                 addr,
133             },
134             BaseStopReason::Signal(sig) => BaseStopReason::Signal(sig),
135             BaseStopReason::ReplayLog { pos, .. } => BaseStopReason::ReplayLog { tid: None, pos },
136             BaseStopReason::CatchSyscall {
137                 number, position, ..
138             } => BaseStopReason::CatchSyscall {
139                 tid: None,
140                 number,
141                 position,
142             },
143         }
144     }
145 }
146 
147 mod private {
148     pub trait Sealed {}
149 
150     impl<U> Sealed for super::SingleThreadStopReason<U> {}
151     impl<U> Sealed for super::MultiThreadStopReason<U> {}
152 }
153 
154 /// A marker trait implemented by [`SingleThreadStopReason`] and
155 /// [`MultiThreadStopReason`].
156 pub trait IntoStopReason<T: Target>:
157     private::Sealed + Into<MultiThreadStopReason<<<T as Target>::Arch as Arch>::Usize>>
158 {
159 }
160 
161 impl<T: Target> IntoStopReason<T> for SingleThreadStopReason<<<T as Target>::Arch as Arch>::Usize> {}
162 impl<T: Target> IntoStopReason<T> for MultiThreadStopReason<<<T as Target>::Arch as Arch>::Usize> {}
163