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
use core::fmt::Debug; use num_traits::{PrimInt, Unsigned}; use crate::internal::{BeBytes, LeBytes}; /// Register identifier for target registers. /// /// These identifiers are used by GDB for single register operations. pub trait RegId: Sized + Debug { /// Map raw GDB register number corresponding `RegId` and register size. /// /// Returns `None` if the register is not available. fn from_raw_id(id: usize) -> Option<(Self, usize)>; } /// Stub implementation -- Returns `None` for all raw IDs. impl RegId for () { fn from_raw_id(_id: usize) -> Option<(Self, usize)> { None } } /// Methods to read/write architecture-specific registers. /// /// Registers must be de/serialized in the order specified by the architecture's /// `<target>.xml` in the GDB source tree. /// /// e.g: for ARM: /// github.com/bminor/binutils-gdb/blob/master/gdb/features/arm/arm-core.xml // TODO: add way to de/serialize arbitrary "missing"/"uncollected" registers. pub trait Registers: Default + Debug + Clone + PartialEq { /// Serialize `self` into a GDB register bytestream. /// /// Missing registers are serialized by passing `None` to write_byte. fn gdb_serialize(&self, write_byte: impl FnMut(Option<u8>)); /// Deserialize a GDB register bytestream into `self`. fn gdb_deserialize(&mut self, bytes: &[u8]) -> Result<(), ()>; } /// Encodes architecture-specific information, such as pointer size, register /// layout, etc... /// /// Types implementing `Arch` should be /// [Zero-variant Enums](https://doc.rust-lang.org/reference/items/enumerations.html#zero-variant-enums), /// as they are only ever used at the type level, and should never be /// instantiated. pub trait Arch { /// The architecture's pointer size (e.g: `u32` on a 32-bit system). type Usize: PrimInt + Unsigned + BeBytes + LeBytes; /// The architecture's register file. type Registers: Registers; /// Register identifier enum/struct. /// /// Used to access individual registers via `Target::read/write_register`. /// /// NOTE: The `RegId` type is not required to have a 1:1 correspondence with /// the `Registers` type, and may include register identifiers which are /// separate from the main `Registers` structure. type RegId: RegId; /// (optional) Return the platform's `features.xml` file. /// /// Implementing this method enables `gdb` to automatically detect the /// target's architecture, saving the hassle of having to run `set /// architecture <arch>` when starting a debugging session. /// /// These descriptions can be quite succinct. For example, the target /// description for an `armv4t` platform can be as simple as: /// /// ``` /// r#"<target version="1.0"><architecture>armv4t</architecture></target>"# /// # ; /// ``` /// /// See the [GDB docs](https://sourceware.org/gdb/current/onlinedocs/gdb/Target-Description-Format.html) /// for details on the target description XML format. fn target_description_xml() -> Option<&'static str> { None } }