Skip to content

Commit

Permalink
Allow variable register sizes for SingleRegisterAccess
Browse files Browse the repository at this point in the history
  • Loading branch information
DrChat committed May 27, 2021
1 parent 456952e commit a4ff570
Show file tree
Hide file tree
Showing 9 changed files with 90 additions and 54 deletions.
4 changes: 2 additions & 2 deletions examples/armv4t/gdb/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -212,11 +212,11 @@ impl target::ext::base::SingleRegisterAccess<()> for Emu {
&mut self,
_tid: (),
reg_id: gdbstub_arch::arm::reg::id::ArmCoreRegId,
dst: &mut [u8],
output: &mut dyn FnMut(&[u8]),
) -> TargetResult<(), Self> {
if let Some(i) = cpu_reg_id(reg_id) {
let w = self.cpu.reg_get(self.cpu.mode(), i);
dst.copy_from_slice(&w.to_le_bytes());
output(&w.to_le_bytes());
Ok(())
} else {
Err(().into())
Expand Down
6 changes: 4 additions & 2 deletions gdbstub_arch/src/arm/reg/id.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use core::num::NonZeroUsize;

use gdbstub::arch::RegId;

/// 32-bit ARM core register identifier.
Expand All @@ -21,7 +23,7 @@ pub enum ArmCoreRegId {
}

impl RegId for ArmCoreRegId {
fn from_raw_id(id: usize) -> Option<(Self, usize)> {
fn from_raw_id(id: usize) -> Option<(Self, Option<NonZeroUsize>)> {
let reg = match id {
0..=12 => Self::Gpr(id as u8),
13 => Self::Sp,
Expand All @@ -31,6 +33,6 @@ impl RegId for ArmCoreRegId {
25 => Self::Cpsr,
_ => return None,
};
Some((reg, 4))
Some((reg, Some(NonZeroUsize::new(4).unwrap())))
}
}
14 changes: 8 additions & 6 deletions gdbstub_arch/src/mips/reg/id.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use core::num::NonZeroUsize;

use gdbstub::arch::RegId;

/// MIPS register identifier.
Expand Down Expand Up @@ -44,7 +46,7 @@ pub enum MipsRegId<U> {
_Size(U),
}

fn from_raw_id<U>(id: usize) -> Option<(MipsRegId<U>, usize)> {
fn from_raw_id<U>(id: usize) -> Option<(MipsRegId<U>, Option<NonZeroUsize>)> {
let reg = match id {
0..=31 => MipsRegId::Gpr(id as u8),
32 => MipsRegId::Status,
Expand All @@ -63,23 +65,23 @@ fn from_raw_id<U>(id: usize) -> Option<(MipsRegId<U>, usize)> {
76 => MipsRegId::Hi3,
77 => MipsRegId::Lo3,
// `MipsRegId::Dspctl` is the only register that will always be 4 bytes wide
78 => return Some((MipsRegId::Dspctl, 4)),
78 => return Some((MipsRegId::Dspctl, Some(NonZeroUsize::new(4).unwrap()))),
79 => MipsRegId::Restart,
_ => return None,
};

let ptrsize = core::mem::size_of::<U>();
Some((reg, ptrsize))
Some((reg, Some(NonZeroUsize::new(ptrsize).unwrap())))
}

impl RegId for MipsRegId<u32> {
fn from_raw_id(id: usize) -> Option<(Self, usize)> {
fn from_raw_id(id: usize) -> Option<(Self, Option<NonZeroUsize>)> {
from_raw_id::<u32>(id)
}
}

impl RegId for MipsRegId<u64> {
fn from_raw_id(id: usize) -> Option<(Self, usize)> {
fn from_raw_id(id: usize) -> Option<(Self, Option<NonZeroUsize>)> {
from_raw_id::<u64>(id)
}
}
Expand All @@ -104,7 +106,7 @@ mod tests {
let mut i = 0;
let mut sum_reg_sizes = 0;
while let Some((_, size)) = RId::from_raw_id(i) {
sum_reg_sizes += size;
sum_reg_sizes += size.unwrap().get();
i += 1;
}

Expand Down
8 changes: 5 additions & 3 deletions gdbstub_arch/src/msp430/reg/id.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use core::num::NonZeroUsize;

use gdbstub::arch::RegId;

/// TI-MSP430 register identifier.
Expand All @@ -20,7 +22,7 @@ pub enum Msp430RegId {
}

impl RegId for Msp430RegId {
fn from_raw_id(id: usize) -> Option<(Self, usize)> {
fn from_raw_id(id: usize) -> Option<(Self, Option<NonZeroUsize>)> {
let reg = match id {
0 => Self::Pc,
1 => Self::Sp,
Expand All @@ -29,7 +31,7 @@ impl RegId for Msp430RegId {
4..=15 => Self::Gpr((id as u8) - 4),
_ => return None,
};
Some((reg, 2))
Some((reg, Some(NonZeroUsize::new(2).unwrap())))
}
}

Expand Down Expand Up @@ -57,7 +59,7 @@ mod tests {
let mut i = 0;
let mut sum_reg_sizes = 0;
while let Some((_, size)) = RId::from_raw_id(i) {
sum_reg_sizes += size;
sum_reg_sizes += size.unwrap().get();
i += 1;
}

Expand Down
20 changes: 14 additions & 6 deletions gdbstub_arch/src/riscv/reg/id.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use core::num::NonZeroUsize;

use gdbstub::arch::RegId;

/// RISC-V Register identifier.
Expand All @@ -22,15 +24,21 @@ pub enum RiscvRegId<U> {
macro_rules! impl_riscv_reg_id {
($usize:ty) => {
impl RegId for RiscvRegId<$usize> {
fn from_raw_id(id: usize) -> Option<(Self, usize)> {
fn from_raw_id(id: usize) -> Option<(Self, Option<NonZeroUsize>)> {
const USIZE: usize = core::mem::size_of::<$usize>();

let reg_size = match id {
0..=31 => (Self::Gpr(id as u8), USIZE),
32 => (Self::Pc, USIZE),
33..=64 => (Self::Fpr((id - 33) as u8), USIZE),
65..=4160 => (Self::Csr((id - 65) as u16), USIZE),
4161 => (Self::Priv, 1),
0..=31 => (Self::Gpr(id as u8), Some(NonZeroUsize::new(USIZE).unwrap())),
32 => (Self::Pc, Some(NonZeroUsize::new(USIZE).unwrap())),
33..=64 => (
Self::Fpr((id - 33) as u8),
Some(NonZeroUsize::new(USIZE).unwrap()),
),
65..=4160 => (
Self::Csr((id - 65) as u16),
Some(NonZeroUsize::new(USIZE).unwrap()),
),
4161 => (Self::Priv, Some(NonZeroUsize::new(1).unwrap())),
_ => return None,
};
Some(reg_size)
Expand Down
66 changes: 40 additions & 26 deletions gdbstub_arch/src/x86/reg/id.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use core::num::NonZeroUsize;

use gdbstub::arch::RegId;

/// FPU register identifier.
Expand Down Expand Up @@ -115,25 +117,31 @@ pub enum X86CoreRegId {
}

impl RegId for X86CoreRegId {
fn from_raw_id(id: usize) -> Option<(Self, usize)> {
fn from_raw_id(id: usize) -> Option<(Self, Option<NonZeroUsize>)> {
use self::X86CoreRegId::*;

let r = match id {
0 => (Eax, 4),
1 => (Ecx, 4),
2 => (Edx, 4),
3 => (Ebx, 4),
4 => (Esp, 4),
5 => (Ebp, 4),
6 => (Esi, 4),
7 => (Edi, 4),
8 => (Eip, 4),
9 => (Eflags, 4),
10..=15 => (Segment(X86SegmentRegId::from_u8(id as u8 - 10)?), 4),
16..=23 => (St(id as u8 - 16), 10),
24..=31 => (Fpu(X87FpuInternalRegId::from_u8(id as u8 - 24)?), 4),
32..=39 => (Xmm(id as u8 - 32), 16),
40 => (Mxcsr, 4),
0 => (Eax, Some(NonZeroUsize::new(4).unwrap())),
1 => (Ecx, Some(NonZeroUsize::new(4).unwrap())),
2 => (Edx, Some(NonZeroUsize::new(4).unwrap())),
3 => (Ebx, Some(NonZeroUsize::new(4).unwrap())),
4 => (Esp, Some(NonZeroUsize::new(4).unwrap())),
5 => (Ebp, Some(NonZeroUsize::new(4).unwrap())),
6 => (Esi, Some(NonZeroUsize::new(4).unwrap())),
7 => (Edi, Some(NonZeroUsize::new(4).unwrap())),
8 => (Eip, Some(NonZeroUsize::new(4).unwrap())),
9 => (Eflags, Some(NonZeroUsize::new(4).unwrap())),
10..=15 => (
Segment(X86SegmentRegId::from_u8(id as u8 - 10)?),
Some(NonZeroUsize::new(4).unwrap()),
),
16..=23 => (St(id as u8 - 16), Some(NonZeroUsize::new(10).unwrap())),
24..=31 => (
Fpu(X87FpuInternalRegId::from_u8(id as u8 - 24)?),
Some(NonZeroUsize::new(4).unwrap()),
),
32..=39 => (Xmm(id as u8 - 32), Some(NonZeroUsize::new(16).unwrap())),
40 => (Mxcsr, Some(NonZeroUsize::new(4).unwrap())),
_ => return None,
};
Some(r)
Expand Down Expand Up @@ -167,18 +175,24 @@ pub enum X86_64CoreRegId {
}

impl RegId for X86_64CoreRegId {
fn from_raw_id(id: usize) -> Option<(Self, usize)> {
fn from_raw_id(id: usize) -> Option<(Self, Option<NonZeroUsize>)> {
use self::X86_64CoreRegId::*;

let r = match id {
0..=15 => (Gpr(id as u8), 8),
16 => (Rip, 4),
17 => (Eflags, 8),
18..=23 => (Segment(X86SegmentRegId::from_u8(id as u8 - 18)?), 4),
24..=31 => (St(id as u8 - 24), 10),
32..=39 => (Fpu(X87FpuInternalRegId::from_u8(id as u8 - 32)?), 4),
40..=55 => (Xmm(id as u8 - 40), 16),
56 => (Mxcsr, 4),
0..=15 => (Gpr(id as u8), Some(NonZeroUsize::new(8).unwrap())),
16 => (Rip, Some(NonZeroUsize::new(4).unwrap())),
17 => (Eflags, Some(NonZeroUsize::new(8).unwrap())),
18..=23 => (
Segment(X86SegmentRegId::from_u8(id as u8 - 18)?),
Some(NonZeroUsize::new(4).unwrap()),
),
24..=31 => (St(id as u8 - 24), Some(NonZeroUsize::new(10).unwrap())),
32..=39 => (
Fpu(X87FpuInternalRegId::from_u8(id as u8 - 32)?),
Some(NonZeroUsize::new(4).unwrap()),
),
40..=55 => (Xmm(id as u8 - 40), Some(NonZeroUsize::new(16).unwrap())),
56 => (Mxcsr, Some(NonZeroUsize::new(4).unwrap())),
_ => return None,
};
Some(r)
Expand Down Expand Up @@ -208,7 +222,7 @@ mod tests {
let mut i = 0;
let mut sum_reg_sizes = 0;
while let Some((_, size)) = RId::from_raw_id(i) {
sum_reg_sizes += size;
sum_reg_sizes += size.unwrap().get();
i += 1;
}

Expand Down
6 changes: 3 additions & 3 deletions src/arch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
//! > Having community-created `Arch` implementations distributed in a separate
//! crate helps minimize any unnecessary "version churn" in `gdbstub` core.
use core::fmt::Debug;
use core::{fmt::Debug, num::NonZeroUsize};

use num_traits::{FromPrimitive, PrimInt, Unsigned};

Expand All @@ -31,12 +31,12 @@ 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)>;
fn from_raw_id(id: usize) -> Option<(Self, Option<NonZeroUsize>)>;
}

/// Stub implementation -- Returns `None` for all raw IDs.
impl RegId for () {
fn from_raw_id(_id: usize) -> Option<(Self, usize)> {
fn from_raw_id(_id: usize) -> Option<(Self, Option<NonZeroUsize>)> {
None
}
}
Expand Down
18 changes: 13 additions & 5 deletions src/gdbstub_impl/ext/single_register_access.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,25 @@ impl<T: Target, C: Connection> GdbStubImpl<T, C> {
) -> Result<HandlerStatus, Error<T::Error, C::Error>> {
let handler_status = match command {
SingleRegisterAccess::p(p) => {
let mut dst = [0u8; 32]; // enough for 256-bit registers
let reg = <T::Arch as Arch>::RegId::from_raw_id(p.reg_id);
let (reg_id, reg_size) = match reg {
let (reg_id, _reg_size) = match reg {
// empty packet indicates unrecognized query
None => return Ok(HandlerStatus::Handled),
Some(v) => v,
};
let dst = &mut dst[0..reg_size];
ops.read_register(id, reg_id, dst).handle_error()?;

res.write_hex_buf(dst)?;
// TODO: Limit the number of bytes transferred on the wire to the register size
// (if specified). Maybe pad the register if the callee does not
// send enough data?
let mut err = Ok(());
ops.read_register(id, reg_id, &mut |buf| match res.write_hex_buf(buf) {
Ok(_) => {}
Err(e) => err = Err(e),
})
.handle_error()?;

err?;

HandlerStatus::Handled
}
SingleRegisterAccess::P(p) => {
Expand Down
2 changes: 1 addition & 1 deletion src/target/ext/base/single_register_access.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ pub trait SingleRegisterAccess<Id>: Target {
&mut self,
tid: Id,
reg_id: <Self::Arch as Arch>::RegId,
dst: &mut [u8],
output: &mut dyn FnMut(&[u8]),
) -> TargetResult<(), Self>;

/// Write from a single register on the target.
Expand Down

0 comments on commit a4ff570

Please sign in to comment.