• 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 crate::internal::BeBytes;
19 use crate::internal::LeBytes;
20 use core::fmt::Debug;
21 use core::num::NonZeroUsize;
22 use num_traits::FromPrimitive;
23 use num_traits::PrimInt;
24 use num_traits::Unsigned;
25 
26 /// Register identifier for target registers.
27 ///
28 /// These identifiers are used by GDB to signal which register to read/wite when
29 /// performing [single register accesses].
30 ///
31 /// [single register accesses]:
32 /// crate::target::ext::base::single_register_access::SingleRegisterAccess
33 pub trait RegId: Sized + Debug {
34     /// Map raw GDB register number to a corresponding `RegId` and optional
35     /// register size.
36     ///
37     /// If the register size is specified here, gdbstub will include a runtime
38     /// check that ensures target implementations do not send back more
39     /// bytes than the register allows.
40     ///
41     /// Returns `None` if the register is not available.
from_raw_id(id: usize) -> Option<(Self, Option<NonZeroUsize>)>42     fn from_raw_id(id: usize) -> Option<(Self, Option<NonZeroUsize>)>;
43 }
44 
45 /// Stub implementation -- Returns `None` for all raw IDs.
46 impl RegId for () {
from_raw_id(_id: usize) -> Option<(Self, Option<NonZeroUsize>)>47     fn from_raw_id(_id: usize) -> Option<(Self, Option<NonZeroUsize>)> {
48         None
49     }
50 }
51 
52 /// Methods to read/write architecture-specific registers.
53 ///
54 /// Registers must be de/serialized in the order specified by the architecture's
55 /// `<target>.xml` in the GDB source tree.
56 ///
57 /// e.g: for ARM:
58 /// github.com/bminor/binutils-gdb/blob/master/gdb/features/arm/arm-core.xml
59 // TODO: add way to de/serialize arbitrary "missing"/"uncollected" registers.
60 pub trait Registers: Default + Debug + Clone + PartialEq {
61     /// The type of the architecture's program counter / instruction pointer.
62     /// Must match with the corresponding `Arch::Usize`.
63     type ProgramCounter: Copy;
64 
65     /// Return the value of the program counter / instruction pointer.
pc(&self) -> Self::ProgramCounter66     fn pc(&self) -> Self::ProgramCounter;
67 
68     /// Serialize `self` into a GDB register bytestream.
69     ///
70     /// Missing registers are serialized by passing `None` to write_byte.
gdb_serialize(&self, write_byte: impl FnMut(Option<u8>))71     fn gdb_serialize(&self, write_byte: impl FnMut(Option<u8>));
72 
73     /// Deserialize a GDB register bytestream into `self`.
74     #[allow(clippy::result_unit_err)]
gdb_deserialize(&mut self, bytes: &[u8]) -> Result<(), ()>75     fn gdb_deserialize(&mut self, bytes: &[u8]) -> Result<(), ()>;
76 }
77 
78 /// Breakpoint kind for specific architectures.
79 ///
80 /// This trait corresponds to the _kind_ field of the "z" and "Z" breakpoint
81 /// packets, as documented [here](https://sourceware.org/gdb/onlinedocs/gdb/Packets.html#insert-breakpoint-or-watchpoint-packet).
82 ///
83 /// A breakpoint "kind" is architecture-specific and typically indicates the
84 /// size of the breakpoint in bytes that should be inserted. As such, most
85 /// architectures will set `BreakpointKind = usize`.
86 ///
87 /// Some architectures, such as ARM and MIPS, have additional meanings for
88 /// _kind_. See the [Architecture-Specific Protocol Details](https://sourceware.org/gdb/current/onlinedocs/gdb/Architecture_002dSpecific-Protocol-Details.html#Architecture_002dSpecific-Protocol-Details)
89 /// section of the GBD documentation for more details.
90 ///
91 /// If no architecture-specific value is being used, _kind_ should be set to
92 /// '0', and the `BreakpointKind` associated type should be `()`.
93 pub trait BreakpointKind: Sized + Debug {
94     /// Parse `Self` from a raw usize.
from_usize(kind: usize) -> Option<Self>95     fn from_usize(kind: usize) -> Option<Self>;
96 }
97 
98 impl BreakpointKind for () {
from_usize(kind: usize) -> Option<Self>99     fn from_usize(kind: usize) -> Option<Self> {
100         if kind != 0 {
101             None
102         } else {
103             Some(())
104         }
105     }
106 }
107 
108 impl BreakpointKind for usize {
109     #[allow(clippy::wrong_self_convention)]
from_usize(kind: usize) -> Option<Self>110     fn from_usize(kind: usize) -> Option<Self> {
111         Some(kind)
112     }
113 }
114 
115 /// Encodes architecture-specific information, such as pointer size, register
116 /// layout, etc...
117 ///
118 /// Types implementing `Arch` should be
119 /// [Zero-variant Enums](https://doc.rust-lang.org/reference/items/enumerations.html#zero-variant-enums),
120 /// as `Arch` impls are only ever used at the type level, and should never be
121 /// explicitly instantiated.
122 pub trait Arch {
123     /// The architecture's pointer size (e.g: `u32` on a 32-bit system).
124     type Usize: Debug + FromPrimitive + PrimInt + Unsigned + BeBytes + LeBytes;
125 
126     /// The architecture's register file. See [`Registers`] for more details.
127     type Registers: Registers<ProgramCounter = Self::Usize>;
128 
129     /// The architecture's breakpoint "kind", used to determine the "size"
130     /// of breakpoint to set. See [`BreakpointKind`] for more details.
131     type BreakpointKind: BreakpointKind;
132 
133     /// Register identifier enum/struct.
134     ///
135     /// Used to access individual registers via `Target::read/write_register`.
136     ///
137     /// > NOTE: An arch's `RegId` type is not strictly required to have a 1:1
138     /// correspondence with the `Registers` type, and may include register
139     /// identifiers which are separate from the main `Registers` structure.
140     /// (e.g: the RISC-V Control and Status registers)
141     type RegId: RegId;
142 
143     /// (optional) Return the arch's description XML file (`target.xml`).
144     ///
145     /// Implementing this method enables GDB to automatically detect the
146     /// target's architecture, saving the hassle of having to run `set
147     /// architecture <arch>` when starting a debugging session.
148     ///
149     /// These descriptions can be quite succinct. For example, the target
150     /// description for an `armv4t` target can be as simple as:
151     ///
152     /// ```
153     /// r#"<target version="1.0"><architecture>armv4t</architecture></target>"#;
154     /// ```
155     ///
156     /// See the [GDB docs](https://sourceware.org/gdb/current/onlinedocs/gdb/Target-Description-Format.html)
157     /// for details on the target description XML format.
158     #[inline(always)]
target_description_xml() -> Option<&'static str>159     fn target_description_xml() -> Option<&'static str> {
160         None
161     }
162 
163     /// (optional) (LLDB extension) Return register info for the specified
164     /// register.
165     ///
166     /// Implementing this method enables LLDB to dynamically query the target's
167     /// register information one by one.
168     ///
169     /// Some targets don't have register context in the compiled version of the
170     /// debugger. Help the debugger by dynamically supplying the register info
171     /// from the target. The debugger will request the register info in a
172     /// sequential manner till an error packet is received. In LLDB, the
173     /// register info search has the following
174     /// [order](https://github.com/llvm/llvm-project/blob/369ce54bb302f209239b8ebc77ad824add9df089/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp#L397-L402):
175     ///
176     /// 1. Use the target definition python file if one is specified.
177     /// 2. If the target definition doesn't have any of the info from the
178     ///    target.xml (registers) then proceed to read the `target.xml`.
179     /// 3. Fall back on the `qRegisterInfo` packets.
180     /// 4. Use hardcoded defaults if available.
181     ///
182     /// See the LLDB [gdb-remote docs](https://github.com/llvm-mirror/lldb/blob/d01083a850f577b85501a0902b52fd0930de72c7/docs/lldb-gdb-remote.txt#L396)
183     /// for more details on the available information that a single register can
184     /// be described by and [#99](https://github.com/daniel5151/gdbstub/issues/99)
185     /// for more information on LLDB compatibility.
186     #[inline(always)]
lldb_register_info(reg_id: usize) -> Option<lldb::RegisterInfo<'static>>187     fn lldb_register_info(reg_id: usize) -> Option<lldb::RegisterInfo<'static>> {
188         let _ = reg_id;
189         None
190     }
191 }
192 
193 /// LLDB-specific types supporting [`Arch::lldb_register_info`] and
194 /// [`LldbRegisterInfoOverride`] APIs.
195 ///
196 /// [`LldbRegisterInfoOverride`]: crate::target::ext::lldb_register_info_override::LldbRegisterInfoOverride
197 pub mod lldb {
198     /// The architecture's register information of a single register.
199     pub enum RegisterInfo<'a> {
200         /// The register info of a single register that should be written.
201         Register(Register<'a>),
202         /// The `qRegisterInfo` query shall be concluded.
203         Done,
204     }
205 
206     /// Describes the register info for a single register of
207     /// the target.
208     pub struct Register<'a> {
209         /// The primary register name.
210         pub name: &'a str,
211         /// An alternate name for the register.
212         pub alt_name: Option<&'a str>,
213         /// Size in bits of a register.
214         pub bitsize: usize,
215         /// The offset within the 'g' and 'G' packet of the register data for
216         /// this register.
217         pub offset: usize,
218         /// The encoding type of the register.
219         pub encoding: Encoding,
220         /// The preferred format for display of this register.
221         pub format: Format,
222         /// The register set name this register belongs to.
223         pub set: &'a str,
224         /// The GCC compiler registers number for this register.
225         ///
226         /// _Note:_ This denotes the same `KEY:VALUE;` pair as `ehframe:VALUE;`.
227         /// See the LLDB [source](https://github.com/llvm/llvm-project/blob/b92436efcb7813fc481b30f2593a4907568d917a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp#L493).
228         pub gcc: Option<usize>,
229         /// The DWARF register number for this register that is used for this
230         /// register in the debug information.
231         pub dwarf: Option<usize>,
232         /// Specify as a generic register.
233         pub generic: Option<Generic>,
234         /// Other concrete register values this register is contained in.
235         pub container_regs: Option<&'a [usize]>,
236         /// Specifies which register values should be invalidated when this
237         /// register is modified.
238         pub invalidate_regs: Option<&'a [usize]>,
239     }
240 
241     /// Describes the encoding type of the register.
242     #[non_exhaustive]
243     pub enum Encoding {
244         /// Unsigned integer
245         Uint,
246         /// Signed integer
247         Sint,
248         /// IEEE 754 float
249         IEEE754,
250         /// Vector register
251         Vector,
252     }
253 
254     /// Describes the preferred format for display of this register.
255     #[non_exhaustive]
256     pub enum Format {
257         /// Binary format
258         Binary,
259         /// Decimal format
260         Decimal,
261         /// Hexadecimal format
262         Hex,
263         /// Floating point format
264         Float,
265         /// 8 bit signed int vector
266         VectorSInt8,
267         /// 8 bit unsigned int vector
268         VectorUInt8,
269         /// 16 bit signed int vector
270         VectorSInt16,
271         /// 16 bit unsigned int vector
272         VectorUInt16,
273         /// 32 bit signed int vector
274         VectorSInt32,
275         /// 32 bit unsigned int vector
276         VectorUInt32,
277         /// 32 bit floating point vector
278         VectorFloat32,
279         /// 128 bit unsigned int vector
280         VectorUInt128,
281     }
282 
283     /// Describes the generic types that most CPUs have.
284     #[non_exhaustive]
285     pub enum Generic {
286         /// Program counter register
287         Pc,
288         /// Stack pointer register
289         Sp,
290         /// Frame pointer register
291         Fp,
292         /// Return address register
293         Ra,
294         /// CPU flags register
295         Flags,
296         /// Function argument 1
297         Arg1,
298         /// Function argument 2
299         Arg2,
300         /// Function argument 3
301         Arg3,
302         /// Function argument 4
303         Arg4,
304         /// Function argument 5
305         Arg5,
306         /// Function argument 6
307         Arg6,
308         /// Function argument 7
309         Arg7,
310         /// Function argument 8
311         Arg8,
312     }
313 }
314