Skip to content

Commit d9192b9

Browse files
bet4itDrChat
andcommitted
Dynamic RegId Support
Co-authored-by: Dr. Chat <[email protected]>
1 parent 2638ea0 commit d9192b9

File tree

8 files changed

+61
-31
lines changed

8 files changed

+61
-31
lines changed

examples/armv4t/gdb/mod.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,8 @@ impl target::ext::base::singlethread::SingleThreadRangeStepping for Emu {
367367
}
368368

369369
mod custom_arch {
370+
use core::num::NonZeroUsize;
371+
370372
use gdbstub::arch::{Arch, RegId, Registers};
371373

372374
use gdbstub_arch::arm::reg::id::ArmCoreRegId;
@@ -451,7 +453,7 @@ mod custom_arch {
451453
}
452454

453455
impl RegId for ArmCoreRegIdCustom {
454-
fn from_raw_id(id: usize) -> Option<(Self, usize)> {
456+
fn from_raw_id(id: usize) -> Option<(Self, Option<NonZeroUsize>)> {
455457
let reg = match id {
456458
26 => Self::Custom,
457459
27 => Self::Time,
@@ -460,7 +462,7 @@ mod custom_arch {
460462
return Some((Self::Core(reg), size));
461463
}
462464
};
463-
Some((reg, 4))
465+
Some((reg, Some(NonZeroUsize::new(4)?)))
464466
}
465467
}
466468

gdbstub_arch/src/arm/reg/id.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use core::num::NonZeroUsize;
2+
13
use gdbstub::arch::RegId;
24

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

2325
impl RegId for ArmCoreRegId {
24-
fn from_raw_id(id: usize) -> Option<(Self, usize)> {
26+
fn from_raw_id(id: usize) -> Option<(Self, Option<NonZeroUsize>)> {
2527
let reg = match id {
2628
0..=12 => Self::Gpr(id as u8),
2729
13 => Self::Sp,
@@ -31,6 +33,6 @@ impl RegId for ArmCoreRegId {
3133
25 => Self::Cpsr,
3234
_ => return None,
3335
};
34-
Some((reg, 4))
36+
Some((reg, Some(NonZeroUsize::new(4)?)))
3537
}
3638
}

gdbstub_arch/src/mips/reg/id.rs

+8-6
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use core::num::NonZeroUsize;
2+
13
use gdbstub::arch::RegId;
24

35
/// MIPS register identifier.
@@ -44,7 +46,7 @@ pub enum MipsRegId<U> {
4446
_Size(U),
4547
}
4648

47-
fn from_raw_id<U>(id: usize) -> Option<(MipsRegId<U>, usize)> {
49+
fn from_raw_id<U>(id: usize) -> Option<(MipsRegId<U>, Option<NonZeroUsize>)> {
4850
let reg = match id {
4951
0..=31 => MipsRegId::Gpr(id as u8),
5052
32 => MipsRegId::Status,
@@ -63,23 +65,23 @@ fn from_raw_id<U>(id: usize) -> Option<(MipsRegId<U>, usize)> {
6365
76 => MipsRegId::Hi3,
6466
77 => MipsRegId::Lo3,
6567
// `MipsRegId::Dspctl` is the only register that will always be 4 bytes wide
66-
78 => return Some((MipsRegId::Dspctl, 4)),
68+
78 => return Some((MipsRegId::Dspctl, Some(NonZeroUsize::new(4)?))),
6769
79 => MipsRegId::Restart,
6870
_ => return None,
6971
};
7072

7173
let ptrsize = core::mem::size_of::<U>();
72-
Some((reg, ptrsize))
74+
Some((reg, Some(NonZeroUsize::new(ptrsize)?)))
7375
}
7476

7577
impl RegId for MipsRegId<u32> {
76-
fn from_raw_id(id: usize) -> Option<(Self, usize)> {
78+
fn from_raw_id(id: usize) -> Option<(Self, Option<NonZeroUsize>)> {
7779
from_raw_id::<u32>(id)
7880
}
7981
}
8082

8183
impl RegId for MipsRegId<u64> {
82-
fn from_raw_id(id: usize) -> Option<(Self, usize)> {
84+
fn from_raw_id(id: usize) -> Option<(Self, Option<NonZeroUsize>)> {
8385
from_raw_id::<u64>(id)
8486
}
8587
}
@@ -104,7 +106,7 @@ mod tests {
104106
let mut i = 0;
105107
let mut sum_reg_sizes = 0;
106108
while let Some((_, size)) = RId::from_raw_id(i) {
107-
sum_reg_sizes += size;
109+
sum_reg_sizes += size.unwrap().get();
108110
i += 1;
109111
}
110112

gdbstub_arch/src/msp430/reg/id.rs

+7-5
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use core::num::NonZeroUsize;
2+
13
use gdbstub::arch::RegId;
24

35
/// TI-MSP430 register identifier.
@@ -21,7 +23,7 @@ pub enum Msp430RegId<U> {
2123
_Size(U),
2224
}
2325

24-
fn from_raw_id<U>(id: usize) -> Option<(Msp430RegId<U>, usize)> {
26+
fn from_raw_id<U>(id: usize) -> Option<(Msp430RegId<U>, Option<NonZeroUsize>)> {
2527
let reg = match id {
2628
0 => Msp430RegId::Pc,
2729
1 => Msp430RegId::Sp,
@@ -32,17 +34,17 @@ fn from_raw_id<U>(id: usize) -> Option<(Msp430RegId<U>, usize)> {
3234
};
3335

3436
let ptrsize = core::mem::size_of::<U>();
35-
Some((reg, ptrsize))
37+
Some((reg, Some(NonZeroUsize::new(ptrsize)?)))
3638
}
3739

3840
impl RegId for Msp430RegId<u16> {
39-
fn from_raw_id(id: usize) -> Option<(Self, usize)> {
41+
fn from_raw_id(id: usize) -> Option<(Self, Option<NonZeroUsize>)> {
4042
from_raw_id::<u16>(id)
4143
}
4244
}
4345

4446
impl RegId for Msp430RegId<u32> {
45-
fn from_raw_id(id: usize) -> Option<(Self, usize)> {
47+
fn from_raw_id(id: usize) -> Option<(Self, Option<NonZeroUsize>)> {
4648
from_raw_id::<u32>(id)
4749
}
4850
}
@@ -71,7 +73,7 @@ mod tests {
7173
let mut i = 0;
7274
let mut sum_reg_sizes = 0;
7375
while let Some((_, size)) = RId::from_raw_id(i) {
74-
sum_reg_sizes += size;
76+
sum_reg_sizes += size.unwrap().get();
7577
i += 1;
7678
}
7779

gdbstub_arch/src/riscv/reg/id.rs

+6-3
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use core::num::NonZeroUsize;
2+
13
use gdbstub::arch::RegId;
24

35
/// RISC-V Register identifier.
@@ -22,18 +24,19 @@ pub enum RiscvRegId<U> {
2224
macro_rules! impl_riscv_reg_id {
2325
($usize:ty) => {
2426
impl RegId for RiscvRegId<$usize> {
25-
fn from_raw_id(id: usize) -> Option<(Self, usize)> {
27+
fn from_raw_id(id: usize) -> Option<(Self, Option<NonZeroUsize>)> {
2628
const USIZE: usize = core::mem::size_of::<$usize>();
2729

28-
let reg_size = match id {
30+
let (id, size) = match id {
2931
0..=31 => (Self::Gpr(id as u8), USIZE),
3032
32 => (Self::Pc, USIZE),
3133
33..=64 => (Self::Fpr((id - 33) as u8), USIZE),
3234
65..=4160 => (Self::Csr((id - 65) as u16), USIZE),
3335
4161 => (Self::Priv, 1),
3436
_ => return None,
3537
};
36-
Some(reg_size)
38+
39+
Some((id, Some(NonZeroUsize::new(size)?)))
3740
}
3841
}
3942
};

gdbstub_arch/src/x86/reg/id.rs

+11-7
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use core::num::NonZeroUsize;
2+
13
use gdbstub::arch::RegId;
24

35
/// FPU register identifier.
@@ -115,10 +117,10 @@ pub enum X86CoreRegId {
115117
}
116118

117119
impl RegId for X86CoreRegId {
118-
fn from_raw_id(id: usize) -> Option<(Self, usize)> {
120+
fn from_raw_id(id: usize) -> Option<(Self, Option<NonZeroUsize>)> {
119121
use self::X86CoreRegId::*;
120122

121-
let r = match id {
123+
let (r, sz): (X86CoreRegId, usize) = match id {
122124
0 => (Eax, 4),
123125
1 => (Ecx, 4),
124126
2 => (Edx, 4),
@@ -136,7 +138,8 @@ impl RegId for X86CoreRegId {
136138
40 => (Mxcsr, 4),
137139
_ => return None,
138140
};
139-
Some(r)
141+
142+
Some((r, Some(NonZeroUsize::new(sz)?)))
140143
}
141144
}
142145

@@ -167,10 +170,10 @@ pub enum X86_64CoreRegId {
167170
}
168171

169172
impl RegId for X86_64CoreRegId {
170-
fn from_raw_id(id: usize) -> Option<(Self, usize)> {
173+
fn from_raw_id(id: usize) -> Option<(Self, Option<NonZeroUsize>)> {
171174
use self::X86_64CoreRegId::*;
172175

173-
let r = match id {
176+
let (r, sz): (X86_64CoreRegId, usize) = match id {
174177
0..=15 => (Gpr(id as u8), 8),
175178
16 => (Rip, 8),
176179
17 => (Eflags, 4),
@@ -181,7 +184,8 @@ impl RegId for X86_64CoreRegId {
181184
56 => (Mxcsr, 4),
182185
_ => return None,
183186
};
184-
Some(r)
187+
188+
Some((r, Some(NonZeroUsize::new(sz)?)))
185189
}
186190
}
187191

@@ -208,7 +212,7 @@ mod tests {
208212
let mut i = 0;
209213
let mut sum_reg_sizes = 0;
210214
while let Some((_, size)) = RId::from_raw_id(i) {
211-
sum_reg_sizes += size;
215+
sum_reg_sizes += size.unwrap().get();
212216
i += 1;
213217
}
214218

src/arch.rs

+9-4
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
//! > Having community-created `Arch` implementations distributed in a separate
1616
//! crate helps minimize any unnecessary "version churn" in `gdbstub` core.
1717
18-
use core::fmt::Debug;
18+
use core::{fmt::Debug, num::NonZeroUsize};
1919

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

@@ -28,15 +28,20 @@ use crate::internal::{BeBytes, LeBytes};
2828
///
2929
/// [single register accesses]: crate::target::ext::base::SingleRegisterAccess
3030
pub trait RegId: Sized + Debug {
31-
/// Map raw GDB register number corresponding `RegId` and register size.
31+
/// Map raw GDB register number to a corresponding `RegId` and optional
32+
/// register size.
33+
///
34+
/// If the register size is specified here, gdbstub will include a runtime
35+
/// check that ensures target implementations do not send back more
36+
/// bytes than the register allows.
3237
///
3338
/// Returns `None` if the register is not available.
34-
fn from_raw_id(id: usize) -> Option<(Self, usize)>;
39+
fn from_raw_id(id: usize) -> Option<(Self, Option<NonZeroUsize>)>;
3540
}
3641

3742
/// Stub implementation -- Returns `None` for all raw IDs.
3843
impl RegId for () {
39-
fn from_raw_id(_id: usize) -> Option<(Self, usize)> {
44+
fn from_raw_id(_id: usize) -> Option<(Self, Option<NonZeroUsize>)> {
4045
None
4146
}
4247
}

src/gdbstub_impl/ext/single_register_access.rs

+12-2
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,20 @@ impl<T: Target, C: Connection> GdbStubImpl<T, C> {
1919
None => return Ok(HandlerStatus::Handled),
2020
Some(v) => v,
2121
};
22-
let buf = &mut p.buf[0..reg_size];
22+
let mut buf = p.buf;
23+
if let Some(size) = reg_size {
24+
buf = &mut buf[0..size.get()];
25+
}
26+
2327
let len = ops.read_register(id, reg_id, buf).handle_error()?;
2428

25-
let buf = &mut buf[0..len];
29+
if let Some(size) = reg_size {
30+
if size.get() != len {
31+
return Err(Error::TargetMismatch);
32+
}
33+
} else {
34+
buf = &mut buf[0..len];
35+
}
2636
res.write_hex_buf(buf)?;
2737
HandlerStatus::Handled
2838
}

0 commit comments

Comments
 (0)