Skip to content

Commit

Permalink
add 'read register' command of the RSP protocol
Browse files Browse the repository at this point in the history
In some architecture, Gdb will actually query single registers, for ex.
on RISC-V. This commit introduces support for this command.

To support this, the trait Target gained a new 'read_register' function,
which is made optional to avoid breaking existing implementations.
  • Loading branch information
thomashk0 committed Aug 30, 2020
1 parent 893c5cb commit 7bd3f92
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 1 deletion.
12 changes: 12 additions & 0 deletions src/gdbstub_impl/mod.rs
Expand Up @@ -402,6 +402,18 @@ impl<T: Target, C: Connection> GdbStubImpl<T, C> {
Some(false) => res.write_str("E22")?, // value of 22 grafted from QEMU
}
}
Command::p(p) => {
let mut dst = [0u8; 16];
let r = target
.read_register(&mut dst, p.reg_number as usize)
.maybe_missing_impl()?;
match r {
None => res.write_str("E01")?,
Some(n) => {
res.write_hex_buf(&dst[0..n])?;
}
}
}
Command::vCont(cmd) => {
use crate::protocol::_vCont::VContKind;

Expand Down
2 changes: 1 addition & 1 deletion src/protocol/commands.rs
Expand Up @@ -102,7 +102,7 @@ commands! {
"T" => _t_upcase::T,
"z" => _z::z,
"Z" => _z_upcase::Z,

"p" => _p::p,
// Order Matters (because of prefix matching)
"vCont?" => vCont_question_mark::vContQuestionMark,
"vCont" => _vCont::vCont<'a>,
Expand Down
16 changes: 16 additions & 0 deletions src/protocol/commands/_p.rs
@@ -0,0 +1,16 @@
use super::prelude::*;

#[derive(PartialEq, Eq, Debug)]
pub struct p {
pub reg_number: u32,
}

impl<'a> ParseCommand<'a> for p {
fn from_packet(buf: PacketBuf<'a>) -> Option<Self> {
let body = buf.as_body();
let reg_number = decode_hex(body).ok()?;
Some(p {
reg_number
})
}
}
26 changes: 26 additions & 0 deletions src/target.rs
Expand Up @@ -105,6 +105,24 @@ pub trait Target {
check_gdb_interrupt: &mut dyn FnMut() -> bool,
) -> Result<(Tid, StopReason<<Self::Arch as Arch>::Usize>), Self::Error>;

/// Read a single register on the target.
///
/// The register number is given by GDB and is target-dependent.
///
/// If implemented, it should return the size (in bytes) of the register
/// written in `dst`.
///
/// On multi-threaded systems, this method **must** respect the currently
/// selected thread (set via the `set_current_thread` method).
fn read_register(
&mut self,
dst: &mut [u8],
reg_number: usize,
) -> OptResult<usize, Self::Error> {
let _ = (dst, reg_number);
Err(MaybeUnimpl::no_impl())
}

/// Read the target's registers.
///
/// On multi-threaded systems, this method **must** respect the currently
Expand Down Expand Up @@ -377,6 +395,14 @@ macro_rules! impl_dyn_target {
(**self).resume(actions, check_gdb_interrupt)
}

fn read_register(
&mut self,
dst: &mut [u8],
reg_number: usize,
) -> OptResult<usize, Self::Error> {
(**self).read_register(dst, reg_number)
}

fn read_registers(
&mut self,
regs: &mut <Self::Arch as Arch>::Registers,
Expand Down

0 comments on commit 7bd3f92

Please sign in to comment.