• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //! Traits to encode architecture-specific target information.
2 //!
3 //! # Community created `Arch` Implementations
4 //!
5 //! Before getting your hands dirty and implementing a new `Arch` from scratch,
6 //! make sure to check out [`gdbstub_arch`](https://docs.rs/gdbstub_arch), a
7 //! companion crate to `gdbstub` which aggregates community-created `Arch`
8 //! implementations for most common architectures!
9 //!
10 //! > _Note:_ Prior to `gdbstub 0.5`, `Arch` implementations were distributed as
11 //! a part of the main `gdbstub` crate (under the `gdbstub::arch` module). This
12 //! wasn't ideal, any `gdbstub::arch`-level breaking-changes forced the _entire_
13 //! `gdbstub` crate to release a new (potentially breaking!) version.
14 //!
15 //! > Having community-created `Arch` implementations distributed in a separate
16 //! crate helps minimize any unnecessary "version churn" in `gdbstub` core.
17 
18 use core::fmt::Debug;
19 use core::num::NonZeroUsize;
20 
21 use num_traits::{FromPrimitive, PrimInt, Unsigned};
22 
23 use crate::internal::{BeBytes, LeBytes};
24 
25 /// Register identifier for target registers.
26 ///
27 /// These identifiers are used by GDB to signal which register to read/wite when
28 /// performing [single register accesses].
29 ///
30 /// [single register accesses]:
31 /// crate::target::ext::base::single_register_access::SingleRegisterAccess
32 pub trait RegId: Sized + Debug {
33     /// Map raw GDB register number to a corresponding `RegId` and optional
34     /// register size.
35     ///
36     /// If the register size is specified here, gdbstub will include a runtime
37     /// check that ensures target implementations do not send back more
38     /// bytes than the register allows.
39     ///
40     /// Returns `None` if the register is not available.
from_raw_id(id: usize) -> Option<(Self, Option<NonZeroUsize>)>41     fn from_raw_id(id: usize) -> Option<(Self, Option<NonZeroUsize>)>;
42 }
43 
44 /// Stub implementation -- Returns `None` for all raw IDs.
45 impl RegId for () {
from_raw_id(_id: usize) -> Option<(Self, Option<NonZeroUsize>)>46     fn from_raw_id(_id: usize) -> Option<(Self, Option<NonZeroUsize>)> {
47         None
48     }
49 }
50 
51 /// Methods to read/write architecture-specific registers.
52 ///
53 /// Registers must be de/serialized in the order specified by the architecture's
54 /// `<target>.xml` in the GDB source tree.
55 ///
56 /// e.g: for ARM:
57 /// github.com/bminor/binutils-gdb/blob/master/gdb/features/arm/arm-core.xml
58 // TODO: add way to de/serialize arbitrary "missing"/"uncollected" registers.
59 pub trait Registers: Default + Debug + Clone + PartialEq {
60     /// The type of the architecture's program counter / instruction pointer.
61     /// Must match with the corresponding `Arch::Usize`.
62     type ProgramCounter: Copy;
63 
64     /// Return the value of the program counter / instruction pointer.
pc(&self) -> Self::ProgramCounter65     fn pc(&self) -> Self::ProgramCounter;
66 
67     /// Serialize `self` into a GDB register bytestream.
68     ///
69     /// Missing registers are serialized by passing `None` to write_byte.
gdb_serialize(&self, write_byte: impl FnMut(Option<u8>))70     fn gdb_serialize(&self, write_byte: impl FnMut(Option<u8>));
71 
72     /// Deserialize a GDB register bytestream into `self`.
73     #[allow(clippy::result_unit_err)]
gdb_deserialize(&mut self, bytes: &[u8]) -> Result<(), ()>74     fn gdb_deserialize(&mut self, bytes: &[u8]) -> Result<(), ()>;
75 }
76 
77 /// Breakpoint kind for specific architectures.
78 ///
79 /// This trait corresponds to the _kind_ field of the "z" and "Z" breakpoint
80 /// packets, as documented [here](https://sourceware.org/gdb/onlinedocs/gdb/Packets.html#insert-breakpoint-or-watchpoint-packet).
81 ///
82 /// A breakpoint "kind" is architecture-specific and typically indicates the
83 /// size of the breakpoint in bytes that should be inserted. As such, most
84 /// architectures will set `BreakpointKind = usize`.
85 ///
86 /// Some architectures, such as ARM and MIPS, have additional meanings for
87 /// _kind_. See the [Architecture-Specific Protocol Details](https://sourceware.org/gdb/current/onlinedocs/gdb/Architecture_002dSpecific-Protocol-Details.html#Architecture_002dSpecific-Protocol-Details)
88 /// section of the GBD documentation for more details.
89 ///
90 /// If no architecture-specific value is being used, _kind_ should be set to
91 /// '0', and the `BreakpointKind` associated type should be `()`.
92 pub trait BreakpointKind: Sized + Debug {
93     /// Parse `Self` from a raw usize.
from_usize(kind: usize) -> Option<Self>94     fn from_usize(kind: usize) -> Option<Self>;
95 }
96 
97 impl BreakpointKind for () {
from_usize(kind: usize) -> Option<Self>98     fn from_usize(kind: usize) -> Option<Self> {
99         if kind != 0 {
100             None
101         } else {
102             Some(())
103         }
104     }
105 }
106 
107 impl BreakpointKind for usize {
108     #[allow(clippy::wrong_self_convention)]
from_usize(kind: usize) -> Option<Self>109     fn from_usize(kind: usize) -> Option<Self> {
110         Some(kind)
111     }
112 }
113 
114 /// Encodes architecture-specific information, such as pointer size, register
115 /// layout, etc...
116 ///
117 /// Types implementing `Arch` should be
118 /// [Zero-variant Enums](https://doc.rust-lang.org/reference/items/enumerations.html#zero-variant-enums),
119 /// as `Arch` impls are only ever used at the type level, and should never be
120 /// explicitly instantiated.
121 pub trait Arch {
122     /// The architecture's pointer size (e.g: `u32` on a 32-bit system).
123     type Usize: Debug + FromPrimitive + PrimInt + Unsigned + BeBytes + LeBytes;
124 
125     /// The architecture's register file. See [`Registers`] for more details.
126     type Registers: Registers<ProgramCounter = Self::Usize>;
127 
128     /// The architecture's breakpoint "kind", used to determine the "size"
129     /// of breakpoint to set. See [`BreakpointKind`] for more details.
130     type BreakpointKind: BreakpointKind;
131 
132     /// Register identifier enum/struct.
133     ///
134     /// Used to access individual registers via `Target::read/write_register`.
135     ///
136     /// > NOTE: An arch's `RegId` type is not strictly required to have a 1:1
137     /// correspondence with the `Registers` type, and may include register
138     /// identifiers which are separate from the main `Registers` structure.
139     /// (e.g: the RISC-V Control and Status registers)
140     type RegId: RegId;
141 
142     /// (optional) Return the arch's description XML file (`target.xml`).
143     ///
144     /// Implementing this method enables GDB to automatically detect the
145     /// target's architecture, saving the hassle of having to run `set
146     /// architecture <arch>` when starting a debugging session.
147     ///
148     /// These descriptions can be quite succinct. For example, the target
149     /// description for an `armv4t` target can be as simple as:
150     ///
151     /// ```
152     /// r#"<target version="1.0"><architecture>armv4t</architecture></target>"#;
153     /// ```
154     ///
155     /// See the [GDB docs](https://sourceware.org/gdb/current/onlinedocs/gdb/Target-Description-Format.html)
156     /// for details on the target description XML format.
157     #[inline(always)]
target_description_xml() -> Option<&'static str>158     fn target_description_xml() -> Option<&'static str> {
159         None
160     }
161 
162     /// (optional) (LLDB extension) Return register info for the specified
163     /// register.
164     ///
165     /// Implementing this method enables LLDB to dynamically query the target's
166     /// register information one by one.
167     ///
168     /// Some targets don't have register context in the compiled version of the
169     /// debugger. Help the debugger by dynamically supplying the register info
170     /// from the target. The debugger will request the register info in a
171     /// sequential manner till an error packet is received. In LLDB, the
172     /// register info search has the following
173     /// [order](https://github.com/llvm/llvm-project/blob/369ce54bb302f209239b8ebc77ad824add9df089/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp#L397-L402):
174     ///
175     /// 1. Use the target definition python file if one is specified.
176     /// 2. If the target definition doesn't have any of the info from the
177     ///    target.xml (registers) then proceed to read the `target.xml`.
178     /// 3. Fall back on the `qRegisterInfo` packets.
179     /// 4. Use hardcoded defaults if available.
180     ///
181     /// See the LLDB [gdb-remote docs](https://github.com/llvm-mirror/lldb/blob/d01083a850f577b85501a0902b52fd0930de72c7/docs/lldb-gdb-remote.txt#L396)
182     /// for more details on the available information that a single register can
183     /// be described by and [#99](https://github.com/daniel5151/gdbstub/issues/99)
184     /// for more information on LLDB compatibility.
185     #[inline(always)]
lldb_register_info(reg_id: usize) -> Option<lldb::RegisterInfo<'static>>186     fn lldb_register_info(reg_id: usize) -> Option<lldb::RegisterInfo<'static>> {
187         let _ = reg_id;
188         None
189     }
190 
191     /// Encode how the mainline GDB client handles target support for
192     /// single-step on this particular architecture.
193     ///
194     /// # Context
195     ///
196     /// According to the spec, supporting single step _should_ be quite
197     /// straightforward:
198     ///
199     /// - The GDB client sends a `vCont?` packet to enumerate supported
200     ///   resumption modes
201     /// - If the target supports single-step, it responds with the `s;S`
202     ///   capability as part of the response, omitting it if it is not
203     ///   supported.
204     /// - Later, when the user attempts to `stepi`, the GDB client sends a `s`
205     ///   resumption reason if it is supported, falling back to setting a
206     ///   temporary breakpoint + continue to "emulate" the single step.
207     ///
208     /// Unfortunately, the reality is that the mainline GDB client does _not_ do
209     /// this on all architectures...
210     ///
211     /// - On certain architectures (e.g: x86), GDB will _unconditionally_ assume
212     ///   single-step support, regardless whether or not the target reports
213     ///   supports it.
214     /// - On certain architectures (e.g: MIPS), GDB will _never_ use single-step
215     ///   support, even in the target has explicitly reported support for it.
216     ///
217     /// This is a bug, and has been reported at
218     /// <https://sourceware.org/bugzilla/show_bug.cgi?id=28440>.
219     ///
220     /// For a easy repro of this behavior, also see
221     /// <https://github.com/daniel5151/gdb-optional-step-bug>.
222     ///
223     /// # Implications
224     ///
225     /// Unfortunately, even if these idiosyncratic behaviors get fixed in the
226     /// mainline GDB client, it will be quite a while until the typical
227     /// user's distro-provided GDB client includes this bugfix.
228     ///
229     /// As such, `gdbstub` has opted to include this method as a "guard rail" to
230     /// preemptively detect cases of this idiosyncratic behavior, and throw a
231     /// pre-init error that informs the user of the potential issues they may
232     /// run into.
233     ///
234     /// # Writing a proper implementation
235     ///
236     /// To check whether or not a particular architecture exhibits this
237     /// behavior, an implementation should temporarily override this method to
238     /// return [`SingleStepGdbBehavior::Optional`], toggle target support for
239     /// single-step on/off, and observe the behavior of the GDB client after
240     /// invoking `stepi`.
241     ///
242     /// If single-stepping was **disabled**, yet the client nonetheless sent a
243     /// `vCont` packet with a `s` resume action, then this architecture
244     /// _does not_ support optional single stepping, and this method should
245     /// return [`SingleStepGdbBehavior::Required`].
246     ///
247     /// If single-stepping was **disabled**, and the client attempted to set a
248     /// temporary breakpoint (using the `z` packet), and then sent a `vCont`
249     /// packet with a `c` resume action, then this architecture _does_
250     /// support optional single stepping, and this method should return
251     /// [`SingleStepGdbBehavior::Optional`].
252     ///
253     /// If single-stepping was **enabled**, yet the client did _not_ send a
254     /// `vCont` packet with a `s` resume action, then this architecture
255     /// _ignores_ single stepping entirely, and this method should return
256     /// [`SingleStepGdbBehavior::Ignored`].
single_step_gdb_behavior() -> SingleStepGdbBehavior257     fn single_step_gdb_behavior() -> SingleStepGdbBehavior;
258 }
259 
260 /// Encodes how the mainline GDB client handles target support for single-step
261 /// on a particular architecture.
262 ///
263 /// See [Arch::single_step_gdb_behavior] for details.
264 #[non_exhaustive]
265 #[derive(Debug, Clone, Copy)]
266 pub enum SingleStepGdbBehavior {
267     /// GDB will use single-stepping if available, falling back to using
268     /// a temporary breakpoint + continue if unsupported.
269     ///
270     /// e.g: ARM
271     Optional,
272     /// GDB will unconditionally send single-step packets, _requiring_ the
273     /// target to handle these requests.
274     ///
275     /// e.g: x86/x64
276     Required,
277     /// GDB will never use single-stepping, regardless if it's supported by the
278     /// stub. It will always use a temporary breakpoint + continue.
279     ///
280     /// e.g: MIPS
281     Ignored,
282     /// Unknown behavior - no one has tested this platform yet. If possible,
283     /// please conduct a test + upstream your findings to `gdbstub_arch`.
284     #[doc(hidden)]
285     Unknown,
286 }
287 
288 /// LLDB-specific types supporting [`Arch::lldb_register_info`] and
289 /// [`LldbRegisterInfoOverride`] APIs.
290 ///
291 /// [`LldbRegisterInfoOverride`]: crate::target::ext::lldb_register_info_override::LldbRegisterInfoOverride
292 pub mod lldb {
293     /// The architecture's register information of a single register.
294     pub enum RegisterInfo<'a> {
295         /// The register info of a single register that should be written.
296         Register(Register<'a>),
297         /// The `qRegisterInfo` query shall be concluded.
298         Done,
299     }
300 
301     /// Describes the register info for a single register of
302     /// the target.
303     pub struct Register<'a> {
304         /// The primary register name.
305         pub name: &'a str,
306         /// An alternate name for the register.
307         pub alt_name: Option<&'a str>,
308         /// Size in bits of a register.
309         pub bitsize: usize,
310         /// The offset within the 'g' and 'G' packet of the register data for
311         /// this register.
312         pub offset: usize,
313         /// The encoding type of the register.
314         pub encoding: Encoding,
315         /// The preferred format for display of this register.
316         pub format: Format,
317         /// The register set name this register belongs to.
318         pub set: &'a str,
319         /// The GCC compiler registers number for this register.
320         ///
321         /// _Note:_ This denotes the same `KEY:VALUE;` pair as `ehframe:VALUE;`.
322         /// See the LLDB [source](https://github.com/llvm/llvm-project/blob/b92436efcb7813fc481b30f2593a4907568d917a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp#L493).
323         pub gcc: Option<usize>,
324         /// The DWARF register number for this register that is used for this
325         /// register in the debug information.
326         pub dwarf: Option<usize>,
327         /// Specify as a generic register.
328         pub generic: Option<Generic>,
329         /// Other concrete register values this register is contained in.
330         pub container_regs: Option<&'a [usize]>,
331         /// Specifies which register values should be invalidated when this
332         /// register is modified.
333         pub invalidate_regs: Option<&'a [usize]>,
334     }
335 
336     /// Describes the encoding type of the register.
337     #[non_exhaustive]
338     pub enum Encoding {
339         /// Unsigned integer
340         Uint,
341         /// Signed integer
342         Sint,
343         /// IEEE 754 float
344         IEEE754,
345         /// Vector register
346         Vector,
347     }
348 
349     /// Describes the preferred format for display of this register.
350     #[non_exhaustive]
351     pub enum Format {
352         /// Binary format
353         Binary,
354         /// Decimal format
355         Decimal,
356         /// Hexadecimal format
357         Hex,
358         /// Floating point format
359         Float,
360         /// 8 bit signed int vector
361         VectorSInt8,
362         /// 8 bit unsigned int vector
363         VectorUInt8,
364         /// 16 bit signed int vector
365         VectorSInt16,
366         /// 16 bit unsigned int vector
367         VectorUInt16,
368         /// 32 bit signed int vector
369         VectorSInt32,
370         /// 32 bit unsigned int vector
371         VectorUInt32,
372         /// 32 bit floating point vector
373         VectorFloat32,
374         /// 128 bit unsigned int vector
375         VectorUInt128,
376     }
377 
378     /// Describes the generic types that most CPUs have.
379     #[non_exhaustive]
380     pub enum Generic {
381         /// Program counter register
382         Pc,
383         /// Stack pointer register
384         Sp,
385         /// Frame pointer register
386         Fp,
387         /// Return address register
388         Ra,
389         /// CPU flags register
390         Flags,
391         /// Function argument 1
392         Arg1,
393         /// Function argument 2
394         Arg2,
395         /// Function argument 3
396         Arg3,
397         /// Function argument 4
398         Arg4,
399         /// Function argument 5
400         Arg5,
401         /// Function argument 6
402         Arg6,
403         /// Function argument 7
404         Arg7,
405         /// Function argument 8
406         Arg8,
407     }
408 }
409