Skip to content

Commit

Permalink
Wrap raw read_register callback, and introduce a weird compiler error
Browse files Browse the repository at this point in the history
  • Loading branch information
DrChat committed Jun 1, 2021
1 parent 272090e commit 37c82ec
Show file tree
Hide file tree
Showing 4 changed files with 34 additions and 10 deletions.
5 changes: 3 additions & 2 deletions examples/armv4t/gdb/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use gdbstub::target::ext::base::singlethread::{
GdbInterrupt, ResumeAction, SingleThreadOps, SingleThreadReverseContOps,
SingleThreadReverseStepOps, StopReason,
};
use gdbstub::target::ext::base::SendRegisterOutput;
use gdbstub::target::ext::breakpoints::WatchKind;
use gdbstub::target::{Target, TargetError, TargetResult};
use gdbstub_arch::arm::reg::id::ArmCoreRegId;
Expand Down Expand Up @@ -212,11 +213,11 @@ impl target::ext::base::SingleRegisterAccess<()> for Emu {
&mut self,
_tid: (),
reg_id: gdbstub_arch::arm::reg::id::ArmCoreRegId,
output: &mut dyn FnMut(&[u8]),
mut output: SendRegisterOutput,
) -> TargetResult<(), Self> {
if let Some(i) = cpu_reg_id(reg_id) {
let w = self.cpu.reg_get(self.cpu.mode(), i);
output(&w.to_le_bytes());
output.write(&w.to_le_bytes());
Ok(())
} else {
Err(().into())
Expand Down
17 changes: 11 additions & 6 deletions src/gdbstub_impl/ext/single_register_access.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use super::prelude::*;
use crate::protocol::commands::ext::SingleRegisterAccess;

use crate::arch::{Arch, RegId};
use crate::target::ext::base::BaseOps;
use crate::target::ext::base::{BaseOps, SendRegisterOutput};

impl<T: Target, C: Connection> GdbStubImpl<T, C> {
fn inner<Id>(
Expand All @@ -20,14 +20,19 @@ impl<T: Target, C: Connection> GdbStubImpl<T, C> {
Some(v) => v,
};

let mut err = Ok(());

// 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),
})
ops.read_register(
id,
reg_id,
SendRegisterOutput::new(&mut |buf| match res.write_hex_buf(buf) {
Ok(_) => {}
Err(e) => err = Err(e),
}),
)
.handle_error()?;

err?;
Expand Down
4 changes: 3 additions & 1 deletion src/target/ext/base/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ pub mod singlethread;

mod single_register_access;

pub use single_register_access::{SingleRegisterAccess, SingleRegisterAccessOps};
pub use single_register_access::{
SendRegisterOutput, SingleRegisterAccess, SingleRegisterAccessOps,
};

/// Base operations for single/multi threaded targets.
pub enum BaseOps<'a, A, E> {
Expand Down
18 changes: 17 additions & 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,
output: &mut dyn FnMut(&[u8]),
output: SendRegisterOutput<'_>,
) -> TargetResult<(), Self>;

/// Write from a single register on the target.
Expand Down Expand Up @@ -65,3 +65,19 @@ pub trait SingleRegisterAccess<Id>: Target {
/// See [`SingleRegisterAccess`]
pub type SingleRegisterAccessOps<'a, Id, T> =
&'a mut dyn SingleRegisterAccess<Id, Arch = <T as Target>::Arch, Error = <T as Target>::Error>;

/// An interface to send register data to the GDB remote debugger.
pub struct SendRegisterOutput<'a> {
inner: &'a mut dyn FnMut(&[u8]),
}

impl<'a> SendRegisterOutput<'a> {
pub(crate) fn new(inner: &'a mut dyn FnMut(&[u8])) -> Self {
Self { inner }
}

/// Write out raw register bytes to the GDB debugger.
pub fn write(&mut self, data: &[u8]) {
(self.inner)(data)
}
}

0 comments on commit 37c82ec

Please sign in to comment.