From 893c5cb7cff9a73826f749dcf22c2a2ca6177ee5 Mon Sep 17 00:00:00 2001 From: Thomas Hiscock Date: Sun, 30 Aug 2020 16:04:01 +0200 Subject: [PATCH 1/2] implement Arch for RISC-V 32/64 Introduces support for **integer** RISC-V ISA. --- src/arch/mod.rs | 1 + src/arch/riscv/mod.rs | 33 +++++++++++++++++ src/arch/riscv/reg/mod.rs | 5 +++ src/arch/riscv/reg/riscv.rs | 70 +++++++++++++++++++++++++++++++++++++ 4 files changed, 109 insertions(+) create mode 100644 src/arch/riscv/mod.rs create mode 100644 src/arch/riscv/reg/mod.rs create mode 100644 src/arch/riscv/reg/riscv.rs diff --git a/src/arch/mod.rs b/src/arch/mod.rs index edbd9e5f..8d9e972f 100644 --- a/src/arch/mod.rs +++ b/src/arch/mod.rs @@ -12,6 +12,7 @@ pub mod arm; pub mod mips; pub mod msp430; +pub mod riscv; mod traits; pub mod x86; diff --git a/src/arch/riscv/mod.rs b/src/arch/riscv/mod.rs new file mode 100644 index 00000000..3a9564e9 --- /dev/null +++ b/src/arch/riscv/mod.rs @@ -0,0 +1,33 @@ +//! Support for the [RISC-V](https://riscv.org/) architecture. +//! +//! *Note*: currently only supports integer version of the ISA + +use crate::arch::Arch; + +pub mod reg; + +/// Implements `Arch` for 32-bit RISC-V. +#[derive(Eq, PartialEq)] +pub struct Riscv32; + +/// Implements `Arch` for 64-bit RISC-V. +#[derive(Eq, PartialEq)] +pub struct Riscv64; + +impl Arch for Riscv32 { + type Usize = u32; + type Registers = reg::RiscvCoreRegs; + + fn target_description_xml() -> Option<&'static str> { + Some(r#"riscv"#) + } +} + +impl Arch for Riscv64 { + type Usize = u64; + type Registers = reg::RiscvCoreRegs; + + fn target_description_xml() -> Option<&'static str> { + Some(r#"riscv64"#) + } +} diff --git a/src/arch/riscv/reg/mod.rs b/src/arch/riscv/reg/mod.rs new file mode 100644 index 00000000..1ba7c5fd --- /dev/null +++ b/src/arch/riscv/reg/mod.rs @@ -0,0 +1,5 @@ +//! `GdbRegister` structs for RISC-V architectures. + +mod riscv; + +pub use riscv::RiscvCoreRegs; diff --git a/src/arch/riscv/reg/riscv.rs b/src/arch/riscv/reg/riscv.rs new file mode 100644 index 00000000..d57de81a --- /dev/null +++ b/src/arch/riscv/reg/riscv.rs @@ -0,0 +1,70 @@ +//! RISC-V Register Definitions. +//! +//! Useful links: +//! - [GNU binutils-gdb XML Descriptions](https://github.com/bminor/binutils-gdb/blob/master/gdb/features/riscv) +//! - [riscv-tdep.h](https://github.com/bminor/binutils-gdb/blob/master/gdb/riscv-tdep.h) +use crate::arch::Registers; +use crate::internal::LeBytes; +use num_traits::PrimInt; + +/// RISC-V Integer registers +/// +/// The register width is set to `u32` or `u64` based on the `` type. +#[derive(Default)] +pub struct RiscvCoreRegs { + /// General purpose registers (x0-x31) + pub r: [U; 32], + /// Program counter + pub pc: U, +} + +impl Registers for RiscvCoreRegs +where + U: PrimInt + LeBytes + Default, +{ + fn gdb_serialize(&self, mut write_byte: impl FnMut(Option)) { + macro_rules! write_le_bytes { + ($value:expr) => { + let mut buf = [0; 16]; + // infallible (unless digit is a >128 bit number) + let len = $value.to_le_bytes(&mut buf).unwrap(); + let buf = &buf[..len]; + for b in buf { + write_byte(Some(*b)); + } + }; + } + + // Write GPRs + for reg in self.r.iter() { + write_le_bytes!(reg); + } + + // Program Counter is regnum 33 + write_le_bytes!(&self.pc); + } + + fn gdb_deserialize(&mut self, bytes: &[u8]) -> Result<(), ()> { + let ptrsize = core::mem::size_of::(); + + // ensure bytes.chunks_exact(ptrsize) won't panic + if bytes.len() % ptrsize != 0 { + return Err(()); + } + + let mut regs = bytes + .chunks_exact(ptrsize) + .map(|c| U::from_le_bytes(c).unwrap()); + + // Read GPRs + for reg in self.r.iter_mut() { + *reg = regs.next().ok_or(())? + } + self.pc = regs.next().ok_or(())?; + + if regs.next().is_some() { + return Err(()); + } + Ok(()) + } +} From 5a7dac2a778c115629f73ba97e65f4b92271ad7d Mon Sep 17 00:00:00 2001 From: Thomas Hiscock Date: Mon, 31 Aug 2020 10:38:42 +0200 Subject: [PATCH 2/2] fix minor style issues in the riscv module --- src/arch/riscv/mod.rs | 2 +- src/arch/riscv/reg/riscv.rs | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/arch/riscv/mod.rs b/src/arch/riscv/mod.rs index 3a9564e9..a5a4f780 100644 --- a/src/arch/riscv/mod.rs +++ b/src/arch/riscv/mod.rs @@ -1,6 +1,6 @@ //! Support for the [RISC-V](https://riscv.org/) architecture. //! -//! *Note*: currently only supports integer version of the ISA +//! *Note*: currently only supports integer versions of the ISA. use crate::arch::Arch; diff --git a/src/arch/riscv/reg/riscv.rs b/src/arch/riscv/reg/riscv.rs index d57de81a..b20b8d77 100644 --- a/src/arch/riscv/reg/riscv.rs +++ b/src/arch/riscv/reg/riscv.rs @@ -1,19 +1,18 @@ -//! RISC-V Register Definitions. -//! -//! Useful links: -//! - [GNU binutils-gdb XML Descriptions](https://github.com/bminor/binutils-gdb/blob/master/gdb/features/riscv) -//! - [riscv-tdep.h](https://github.com/bminor/binutils-gdb/blob/master/gdb/riscv-tdep.h) use crate::arch::Registers; use crate::internal::LeBytes; use num_traits::PrimInt; -/// RISC-V Integer registers +/// RISC-V Integer registers. /// /// The register width is set to `u32` or `u64` based on the `` type. +/// +/// Useful links: +/// * [GNU binutils-gdb XML descriptions](https://github.com/bminor/binutils-gdb/blob/master/gdb/features/riscv) +/// * [riscv-tdep.h](https://github.com/bminor/binutils-gdb/blob/master/gdb/riscv-tdep.h) #[derive(Default)] pub struct RiscvCoreRegs { /// General purpose registers (x0-x31) - pub r: [U; 32], + pub x: [U; 32], /// Program counter pub pc: U, } @@ -36,7 +35,7 @@ where } // Write GPRs - for reg in self.r.iter() { + for reg in self.x.iter() { write_le_bytes!(reg); } @@ -57,7 +56,7 @@ where .map(|c| U::from_le_bytes(c).unwrap()); // Read GPRs - for reg in self.r.iter_mut() { + for reg in self.x.iter_mut() { *reg = regs.next().ok_or(())? } self.pc = regs.next().ok_or(())?; @@ -65,6 +64,7 @@ where if regs.next().is_some() { return Err(()); } + Ok(()) } }