From 37c82eca11da6bc6738ed9262cfc664004946cb3 Mon Sep 17 00:00:00 2001 From: "Dr. Chat" Date: Tue, 1 Jun 2021 14:14:13 -0500 Subject: [PATCH] Wrap raw `read_register` callback, and introduce a weird compiler error --- examples/armv4t/gdb/mod.rs | 5 +++-- src/gdbstub_impl/ext/single_register_access.rs | 17 +++++++++++------ src/target/ext/base/mod.rs | 4 +++- src/target/ext/base/single_register_access.rs | 18 +++++++++++++++++- 4 files changed, 34 insertions(+), 10 deletions(-) diff --git a/examples/armv4t/gdb/mod.rs b/examples/armv4t/gdb/mod.rs index 464544f9..34f2b85b 100644 --- a/examples/armv4t/gdb/mod.rs +++ b/examples/armv4t/gdb/mod.rs @@ -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; @@ -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()) diff --git a/src/gdbstub_impl/ext/single_register_access.rs b/src/gdbstub_impl/ext/single_register_access.rs index cedea5e5..f5648ef8 100644 --- a/src/gdbstub_impl/ext/single_register_access.rs +++ b/src/gdbstub_impl/ext/single_register_access.rs @@ -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 GdbStubImpl { fn inner( @@ -20,14 +20,19 @@ impl GdbStubImpl { 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?; diff --git a/src/target/ext/base/mod.rs b/src/target/ext/base/mod.rs index 04bcbd95..2335b33f 100644 --- a/src/target/ext/base/mod.rs +++ b/src/target/ext/base/mod.rs @@ -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> { diff --git a/src/target/ext/base/single_register_access.rs b/src/target/ext/base/single_register_access.rs index 56d4518f..f3b72249 100644 --- a/src/target/ext/base/single_register_access.rs +++ b/src/target/ext/base/single_register_access.rs @@ -35,7 +35,7 @@ pub trait SingleRegisterAccess: Target { &mut self, tid: Id, reg_id: ::RegId, - output: &mut dyn FnMut(&[u8]), + output: SendRegisterOutput<'_>, ) -> TargetResult<(), Self>; /// Write from a single register on the target. @@ -65,3 +65,19 @@ pub trait SingleRegisterAccess: Target { /// See [`SingleRegisterAccess`] pub type SingleRegisterAccessOps<'a, Id, T> = &'a mut dyn SingleRegisterAccess::Arch, Error = ::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) + } +}