From d9a0fdd3d230f0182609afb2c4539781ca5d0328 Mon Sep 17 00:00:00 2001 From: Sidong Yang Date: Thu, 2 Jan 2025 11:21:31 +0900 Subject: [PATCH 1/6] use maybe_async that supports async traits for breakpoint --- Cargo.toml | 3 +++ src/stub/core_impl.rs | 10 ++++++---- src/stub/core_impl/breakpoints.rs | 17 +++++++++++++---- src/stub/mod.rs | 8 +++++--- src/stub/state_machine.rs | 13 +++++++++---- src/target/ext/breakpoints.rs | 6 ++++-- 6 files changed, 40 insertions(+), 17 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 1adf736..1beb003 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,10 +14,12 @@ categories = ["development-tools::debugging", "embedded", "emulators", "network- exclude = ["examples/**/*.elf", "examples/**/*.o"] [dependencies] +async-trait = "0.1.83" bitflags = "2.3.1" cfg-if = "1.0" log = "0.4" managed = { version = "0.8", default-features = false } +maybe-async = { version = "0.2.10" } num-traits = { version = "0.2", default-features = false } paste = "1.0" @@ -35,6 +37,7 @@ std = ["alloc"] trace-pkt = ["alloc"] paranoid_unsafe = [] core_error = [] +sync = ["maybe-async/is_sync"] # INTERNAL: enables the `__dead_code_marker!` macro. # used as part of the `scripts/test_dead_code_elim.sh` diff --git a/src/stub/core_impl.rs b/src/stub/core_impl.rs index 2ea3bc8..824cb44 100644 --- a/src/stub/core_impl.rs +++ b/src/stub/core_impl.rs @@ -44,6 +44,7 @@ mod target_xml; mod thread_extra_info; mod x_upcase_packet; +use maybe_async::maybe_async; pub(crate) use resume::FinishExecStatus; pub(crate) mod target_result_ext { @@ -113,6 +114,7 @@ pub enum HandlerStatus { Disconnect(DisconnectReason), } +#[maybe_async] impl GdbStubImpl { pub fn new() -> GdbStubImpl { GdbStubImpl { @@ -133,7 +135,7 @@ impl GdbStubImpl { } } - pub fn handle_packet( + pub async fn handle_packet( &mut self, target: &mut T, conn: &mut C, @@ -153,7 +155,7 @@ impl GdbStubImpl { } let mut res = ResponseWriter::new(conn, target.use_rle()); - let disconnect_reason = match self.handle_command(&mut res, target, command) { + let disconnect_reason = match self.handle_command(&mut res, target, command).await { Ok(HandlerStatus::Handled) => None, Ok(HandlerStatus::NeedsOk) => { res.write_str("OK")?; @@ -188,7 +190,7 @@ impl GdbStubImpl { } } - fn handle_command( + async fn handle_command( &mut self, res: &mut ResponseWriter<'_, C>, target: &mut T, @@ -204,7 +206,7 @@ impl GdbStubImpl { Command::SingleRegisterAccess(cmd) => { self.handle_single_register_access(res, target, cmd) } - Command::Breakpoints(cmd) => self.handle_breakpoints(res, target, cmd), + Command::Breakpoints(cmd) => self.handle_breakpoints(res, target, cmd).await, Command::CatchSyscalls(cmd) => self.handle_catch_syscalls(res, target, cmd), Command::ExtendedMode(cmd) => self.handle_extended_mode(res, target, cmd), Command::MonitorCmd(cmd) => self.handle_monitor_cmd(res, target, cmd), diff --git a/src/stub/core_impl/breakpoints.rs b/src/stub/core_impl/breakpoints.rs index 3b45eff..4413211 100644 --- a/src/stub/core_impl/breakpoints.rs +++ b/src/stub/core_impl/breakpoints.rs @@ -2,15 +2,17 @@ use super::prelude::*; use crate::arch::Arch; use crate::arch::BreakpointKind; use crate::protocol::commands::ext::Breakpoints; +use maybe_async::maybe_async; enum CmdKind { Add, Remove, } +#[maybe_async] impl GdbStubImpl { #[inline(always)] - fn handle_breakpoint_common( + async fn handle_breakpoint_common( &mut self, ops: crate::target::ext::breakpoints::BreakpointsOps<'_, T>, cmd: crate::protocol::commands::breakpoint::BasicBreakpoint<'_>, @@ -35,6 +37,7 @@ impl GdbStubImpl { CmdKind::Add => ops.add_sw_breakpoint(addr, bp_kind), CmdKind::Remove => ops.remove_sw_breakpoint(addr, bp_kind), } + .await } 1 if ops.support_hw_breakpoint().is_some() => { let ops = ops.support_hw_breakpoint().unwrap(); @@ -76,7 +79,7 @@ impl GdbStubImpl { } } - pub(crate) fn handle_breakpoints( + pub(crate) async fn handle_breakpoints( &mut self, _res: &mut ResponseWriter<'_, C>, target: &mut T, @@ -90,8 +93,14 @@ impl GdbStubImpl { crate::__dead_code_marker!("breakpoints", "impl"); let handler_status = match command { - Breakpoints::z(cmd) => self.handle_breakpoint_common(ops, cmd, CmdKind::Remove)?, - Breakpoints::Z(cmd) => self.handle_breakpoint_common(ops, cmd, CmdKind::Add)?, + Breakpoints::z(cmd) => { + self.handle_breakpoint_common(ops, cmd, CmdKind::Remove) + .await? + } + Breakpoints::Z(cmd) => { + self.handle_breakpoint_common(ops, cmd, CmdKind::Add) + .await? + } // TODO: handle ZWithBytecode once agent expressions are implemented _ => HandlerStatus::Handled, }; diff --git a/src/stub/mod.rs b/src/stub/mod.rs index b98c190..cc53344 100644 --- a/src/stub/mod.rs +++ b/src/stub/mod.rs @@ -5,6 +5,7 @@ pub use builder::GdbStubBuilder; pub use builder::GdbStubBuilderError; pub use core_impl::DisconnectReason; pub use error::GdbStubError; +use maybe_async::maybe_async; pub use stop_reason::BaseStopReason; pub use stop_reason::IntoStopReason; pub use stop_reason::MultiThreadStopReason; @@ -154,7 +155,8 @@ impl<'a, T: Target, C: Connection> GdbStub<'a, T, C> { /// etc...) you will need to interface with the underlying /// [`GdbStubStateMachine`](state_machine::GdbStubStateMachine) API /// directly. - pub fn run_blocking( + #[maybe_async] + pub async fn run_blocking( self, target: &mut T, ) -> Result> @@ -168,7 +170,7 @@ impl<'a, T: Target, C: Connection> GdbStub<'a, T, C> { state_machine::GdbStubStateMachine::Idle(mut gdb) => { // needs more data, so perform a blocking read on the connection let byte = gdb.borrow_conn().read().map_err(InternalError::conn_read)?; - gdb.incoming_data(target, byte)? + gdb.incoming_data(target, byte).await? } state_machine::GdbStubStateMachine::Disconnected(gdb) => { @@ -196,7 +198,7 @@ impl<'a, T: Target, C: Connection> GdbStub<'a, T, C> { } Ok(BlockingEventLoopEvent::IncomingData(byte)) => { - gdb.incoming_data(target, byte)? + gdb.incoming_data(target, byte).await? } Err(WaitForStopReasonError::Target(e)) => { diff --git a/src/stub/state_machine.rs b/src/stub/state_machine.rs index 4a41aaf..a907f3d 100644 --- a/src/stub/state_machine.rs +++ b/src/stub/state_machine.rs @@ -46,6 +46,7 @@ use crate::stub::error::InternalError; use crate::stub::stop_reason::IntoStopReason; use crate::target::Target; use managed::ManagedSlice; +use maybe_async::maybe_async; /// State-machine interface to `GdbStub`. /// @@ -208,7 +209,8 @@ impl<'a, T: Target, C: Connection> GdbStubStateMachineInner<'a, state::Idle, } /// Pass a byte to the GDB stub. - pub fn incoming_data( + #[maybe_async] + pub async fn incoming_data( mut self, target: &mut T, byte: u8, @@ -222,7 +224,8 @@ impl<'a, T: Target, C: Connection> GdbStubStateMachineInner<'a, state::Idle, let state = self .i .inner - .handle_packet(target, &mut self.i.conn, packet)?; + .handle_packet(target, &mut self.i.conn, packet) + .await?; Ok(match state { State::Pump => self.into(), State::Disconnect(reason) => self.transition(state::Disconnected { reason }).into(), @@ -248,6 +251,7 @@ impl<'a, T: Target, C: Connection> GdbStubStateMachineInner<'a, state::Idle, /// Methods which can only be called from the /// [`GdbStubStateMachine::Running`] state. +#[maybe_async] impl<'a, T: Target, C: Connection> GdbStubStateMachineInner<'a, state::Running, T, C> { /// Report a target stop reason back to GDB. pub fn report_stop( @@ -272,7 +276,7 @@ impl<'a, T: Target, C: Connection> GdbStubStateMachineInner<'a, state::Running, } /// Pass a byte to the GDB stub. - pub fn incoming_data( + pub async fn incoming_data( mut self, target: &mut T, byte: u8, @@ -286,7 +290,8 @@ impl<'a, T: Target, C: Connection> GdbStubStateMachineInner<'a, state::Running, let state = self .i .inner - .handle_packet(target, &mut self.i.conn, packet)?; + .handle_packet(target, &mut self.i.conn, packet) + .await?; Ok(match state { State::Pump => self.transition(state::Running {}).into(), State::Disconnect(reason) => self.transition(state::Disconnected { reason }).into(), diff --git a/src/target/ext/breakpoints.rs b/src/target/ext/breakpoints.rs index cd44d99..19f2f48 100644 --- a/src/target/ext/breakpoints.rs +++ b/src/target/ext/breakpoints.rs @@ -3,6 +3,7 @@ use crate::arch::Arch; use crate::target::Target; use crate::target::TargetResult; +use maybe_async::maybe_async; /// Target Extension - Set/Remove Breakpoints. pub trait Breakpoints: Target { @@ -36,11 +37,12 @@ define_ext!(BreakpointsOps, Breakpoints); /// using an _interpreted_ CPU (as opposed to a JIT), the simplest way to /// implement "software" breakpoints would be to check the `PC` value after each /// CPU cycle, ignoring the specified breakpoint `kind` entirely. +#[maybe_async] pub trait SwBreakpoint: Target + Breakpoints { /// Add a new software breakpoint. /// /// Return `Ok(false)` if the operation could not be completed. - fn add_sw_breakpoint( + async fn add_sw_breakpoint( &mut self, addr: ::Usize, kind: ::BreakpointKind, @@ -49,7 +51,7 @@ pub trait SwBreakpoint: Target + Breakpoints { /// Remove an existing software breakpoint. /// /// Return `Ok(false)` if the operation could not be completed. - fn remove_sw_breakpoint( + async fn remove_sw_breakpoint( &mut self, addr: ::Usize, kind: ::BreakpointKind, From e7d638b3c50e614ed5ea1db199a156fc2fe90dba Mon Sep 17 00:00:00 2001 From: Sidong Yang Date: Fri, 3 Jan 2025 00:58:26 +0900 Subject: [PATCH 2/6] impl async hw breakpoint, singlethread resume --- src/stub/core_impl.rs | 2 +- src/stub/core_impl/breakpoints.rs | 8 ++++---- src/stub/core_impl/resume.rs | 17 +++++++++++------ src/target/ext/base/singlethread.rs | 4 +++- src/target/ext/breakpoints.rs | 10 ++++++---- 5 files changed, 25 insertions(+), 16 deletions(-) diff --git a/src/stub/core_impl.rs b/src/stub/core_impl.rs index 824cb44..b2ece55 100644 --- a/src/stub/core_impl.rs +++ b/src/stub/core_impl.rs @@ -200,7 +200,7 @@ impl GdbStubImpl { // `handle_X` methods are defined in the `ext` module Command::Base(cmd) => self.handle_base(res, target, cmd), Command::TargetXml(cmd) => self.handle_target_xml(res, target, cmd), - Command::Resume(cmd) => self.handle_stop_resume(res, target, cmd), + Command::Resume(cmd) => self.handle_stop_resume(res, target, cmd).await, Command::NoAckMode(cmd) => self.handle_no_ack_mode(res, target, cmd), Command::XUpcasePacket(cmd) => self.handle_x_upcase_packet(res, target, cmd), Command::SingleRegisterAccess(cmd) => { diff --git a/src/stub/core_impl/breakpoints.rs b/src/stub/core_impl/breakpoints.rs index 4413211..30f53b8 100644 --- a/src/stub/core_impl/breakpoints.rs +++ b/src/stub/core_impl/breakpoints.rs @@ -43,8 +43,8 @@ impl GdbStubImpl { let ops = ops.support_hw_breakpoint().unwrap(); let bp_kind = bp_kind!(); match cmd_kind { - CmdKind::Add => ops.add_hw_breakpoint(addr, bp_kind), - CmdKind::Remove => ops.remove_hw_breakpoint(addr, bp_kind), + CmdKind::Add => ops.add_hw_breakpoint(addr, bp_kind).await, + CmdKind::Remove => ops.remove_hw_breakpoint(addr, bp_kind).await, } } 2 | 3 | 4 if ops.support_hw_watchpoint().is_some() => { @@ -60,8 +60,8 @@ impl GdbStubImpl { .ok_or(Error::TargetMismatch)?; let ops = ops.support_hw_watchpoint().unwrap(); match cmd_kind { - CmdKind::Add => ops.add_hw_watchpoint(addr, len, kind), - CmdKind::Remove => ops.remove_hw_watchpoint(addr, len, kind), + CmdKind::Add => ops.add_hw_watchpoint(addr, len, kind).await, + CmdKind::Remove => ops.remove_hw_watchpoint(addr, len, kind).await, } } // explicitly handle unguarded variants of known breakpoint types diff --git a/src/stub/core_impl/resume.rs b/src/stub/core_impl/resume.rs index 38a046c..aa6aa4d 100644 --- a/src/stub/core_impl/resume.rs +++ b/src/stub/core_impl/resume.rs @@ -12,8 +12,11 @@ use crate::target::ext::base::reverse_exec::ReplayLogPosition; use crate::target::ext::base::ResumeOps; use crate::target::ext::catch_syscalls::CatchSyscallPosition; +use maybe_async::maybe_async; + impl GdbStubImpl { - pub(crate) fn handle_stop_resume( + #[maybe_async] + pub(crate) async fn handle_stop_resume( &mut self, res: &mut ResponseWriter<'_, C>, target: &mut T, @@ -77,10 +80,11 @@ impl GdbStubImpl { } }; - self.do_vcont(ops, actions) + self.do_vcont(ops, actions).await } - fn do_vcont_single_thread( + #[maybe_async] + async fn do_vcont_single_thread( ops: &mut dyn crate::target::ext::base::singlethread::SingleThreadResume< Arch = T::Arch, Error = T::Error, @@ -122,7 +126,7 @@ impl GdbStubImpl { _ => None, }; - ops.resume(signal).map_err(Error::TargetError)?; + ops.resume(signal).await.map_err(Error::TargetError)?; Ok(()) } VContKind::Step | VContKind::StepWithSig(_) if ops.support_single_step().is_some() => { @@ -254,13 +258,14 @@ impl GdbStubImpl { ops.resume().map_err(Error::TargetError) } - fn do_vcont( + #[maybe_async] + async fn do_vcont( &mut self, ops: ResumeOps<'_, T::Arch, T::Error>, actions: Actions<'_>, ) -> Result> { match ops { - ResumeOps::SingleThread(ops) => Self::do_vcont_single_thread(ops, &actions)?, + ResumeOps::SingleThread(ops) => Self::do_vcont_single_thread(ops, &actions).await?, ResumeOps::MultiThread(ops) => Self::do_vcont_multi_thread(ops, &actions)?, }; diff --git a/src/target/ext/base/singlethread.rs b/src/target/ext/base/singlethread.rs index 40b002e..298c514 100644 --- a/src/target/ext/base/singlethread.rs +++ b/src/target/ext/base/singlethread.rs @@ -4,6 +4,7 @@ use crate::arch::Arch; use crate::common::Signal; use crate::target::Target; use crate::target::TargetResult; +use maybe_async::maybe_async; /// Base required debugging operations for single threaded targets. pub trait SingleThreadBase: Target { @@ -71,6 +72,7 @@ pub trait SingleThreadBase: Target { } /// Target extension - support for resuming single threaded targets. +#[maybe_async] pub trait SingleThreadResume: Target { /// Resume execution on the target. /// @@ -92,7 +94,7 @@ pub trait SingleThreadResume: Target { /// /// Omitting PC adjustment may result in unexpected execution flow and/or /// breakpoints not appearing to work correctly. - fn resume(&mut self, signal: Option) -> Result<(), Self::Error>; + async fn resume(&mut self, signal: Option) -> Result<(), Self::Error>; /// Support for optimized [single stepping]. /// diff --git a/src/target/ext/breakpoints.rs b/src/target/ext/breakpoints.rs index 19f2f48..f35e693 100644 --- a/src/target/ext/breakpoints.rs +++ b/src/target/ext/breakpoints.rs @@ -69,11 +69,12 @@ define_ext!(SwBreakpointOps, SwBreakpoint); /// using an _interpreted_ CPU (as opposed to a JIT), there shouldn't be any /// reason to implement this extension (as software breakpoints are likely to be /// just-as-fast). +#[maybe_async] pub trait HwBreakpoint: Target + Breakpoints { /// Add a new hardware breakpoint. /// /// Return `Ok(false)` if the operation could not be completed. - fn add_hw_breakpoint( + async fn add_hw_breakpoint( &mut self, addr: ::Usize, kind: ::BreakpointKind, @@ -82,7 +83,7 @@ pub trait HwBreakpoint: Target + Breakpoints { /// Remove an existing hardware breakpoint. /// /// Return `Ok(false)` if the operation could not be completed. - fn remove_hw_breakpoint( + async fn remove_hw_breakpoint( &mut self, addr: ::Usize, kind: ::BreakpointKind, @@ -111,12 +112,13 @@ pub enum WatchKind { /// _software watchpoints_, which tend to be excruciatingly slow (as hey are /// implemented by single-stepping the system, and reading the watched memory /// location after each step). +#[maybe_async] pub trait HwWatchpoint: Target + Breakpoints { /// Add a new hardware watchpoint. /// The number of bytes to watch is specified by `len`. /// /// Return `Ok(false)` if the operation could not be completed. - fn add_hw_watchpoint( + async fn add_hw_watchpoint( &mut self, addr: ::Usize, len: ::Usize, @@ -127,7 +129,7 @@ pub trait HwWatchpoint: Target + Breakpoints { /// The number of bytes to watch is specified by `len`. /// /// Return `Ok(false)` if the operation could not be completed. - fn remove_hw_watchpoint( + async fn remove_hw_watchpoint( &mut self, addr: ::Usize, len: ::Usize, From b5b6a3669ae25e92ef8a3d6fe81bdf33936419b8 Mon Sep 17 00:00:00 2001 From: Sidong Yang Date: Mon, 6 Jan 2025 03:37:37 +0000 Subject: [PATCH 3/6] use sync as default feature --- Cargo.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 1beb003..69b3c5d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,7 +19,7 @@ bitflags = "2.3.1" cfg-if = "1.0" log = "0.4" managed = { version = "0.8", default-features = false } -maybe-async = { version = "0.2.10" } +maybe-async = { version = "0.2.10", default-features = false } num-traits = { version = "0.2", default-features = false } paste = "1.0" @@ -31,7 +31,7 @@ pretty_env_logger = "0.4" goblin = "0.4" [features] -default = ["std", "trace-pkt"] +default = ["std", "trace-pkt", "sync"] alloc = ["managed/alloc"] std = ["alloc"] trace-pkt = ["alloc"] From a91ab2e100149cf10cbe1c222695420c0aebaf85 Mon Sep 17 00:00:00 2001 From: Sidong Yang Date: Mon, 6 Jan 2025 03:38:39 +0000 Subject: [PATCH 4/6] use maybe_async on examples --- Cargo.toml | 1 + examples/armv4t/gdb/breakpoints.rs | 11 +++++++---- examples/armv4t/gdb/mod.rs | 4 +++- examples/armv4t/main.rs | 9 ++++++++- examples/armv4t_multicore/gdb.rs | 11 +++++++---- examples/armv4t_multicore/main.rs | 8 +++++++- 6 files changed, 33 insertions(+), 11 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 69b3c5d..b25ba6e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -29,6 +29,7 @@ gdbstub_arch = { path = "./gdbstub_arch/" } armv4t_emu = "0.1" pretty_env_logger = "0.4" goblin = "0.4" +tokio = { version = "1.42.0", features = ["full"] } [features] default = ["std", "trace-pkt", "sync"] diff --git a/examples/armv4t/gdb/breakpoints.rs b/examples/armv4t/gdb/breakpoints.rs index 9d6d90d..973940b 100644 --- a/examples/armv4t/gdb/breakpoints.rs +++ b/examples/armv4t/gdb/breakpoints.rs @@ -2,6 +2,7 @@ use crate::emu::Emu; use gdbstub::target; use gdbstub::target::ext::breakpoints::WatchKind; use gdbstub::target::TargetResult; +use maybe_async::maybe_async; impl target::ext::breakpoints::Breakpoints for Emu { #[inline(always)] @@ -19,8 +20,9 @@ impl target::ext::breakpoints::Breakpoints for Emu { } } +#[maybe_async] impl target::ext::breakpoints::SwBreakpoint for Emu { - fn add_sw_breakpoint( + async fn add_sw_breakpoint( &mut self, addr: u32, _kind: gdbstub_arch::arm::ArmBreakpointKind, @@ -29,7 +31,7 @@ impl target::ext::breakpoints::SwBreakpoint for Emu { Ok(true) } - fn remove_sw_breakpoint( + async fn remove_sw_breakpoint( &mut self, addr: u32, _kind: gdbstub_arch::arm::ArmBreakpointKind, @@ -43,8 +45,9 @@ impl target::ext::breakpoints::SwBreakpoint for Emu { } } +#[maybe_async] impl target::ext::breakpoints::HwWatchpoint for Emu { - fn add_hw_watchpoint( + async fn add_hw_watchpoint( &mut self, addr: u32, len: u32, @@ -61,7 +64,7 @@ impl target::ext::breakpoints::HwWatchpoint for Emu { Ok(true) } - fn remove_hw_watchpoint( + async fn remove_hw_watchpoint( &mut self, addr: u32, len: u32, diff --git a/examples/armv4t/gdb/mod.rs b/examples/armv4t/gdb/mod.rs index d4190dc..c1d2dfb 100644 --- a/examples/armv4t/gdb/mod.rs +++ b/examples/armv4t/gdb/mod.rs @@ -11,6 +11,7 @@ use gdbstub::target::Target; use gdbstub::target::TargetError; use gdbstub::target::TargetResult; use gdbstub_arch::arm::reg::id::ArmCoreRegId; +use maybe_async::maybe_async; // Additional GDB extensions @@ -231,8 +232,9 @@ impl SingleThreadBase for Emu { } } +#[maybe_async] impl SingleThreadResume for Emu { - fn resume(&mut self, signal: Option) -> Result<(), Self::Error> { + async fn resume(&mut self, signal: Option) -> Result<(), Self::Error> { // Upon returning from the `resume` method, the target being debugged should be // configured to run according to whatever resume actions the GDB client has // specified (as specified by `set_resume_action`, `resume_range_step`, diff --git a/examples/armv4t/main.rs b/examples/armv4t/main.rs index ab15f9b..44ad334 100644 --- a/examples/armv4t/main.rs +++ b/examples/armv4t/main.rs @@ -167,7 +167,14 @@ fn main() -> DynResult<()> { let gdb = GdbStub::new(connection); - match gdb.run_blocking::(&mut emu) { + #[cfg(feature = "sync")] + let run = gdb.run_blocking::(&mut emu); + #[cfg(not(feature = "sync"))] + let run = tokio::runtime::Runtime::new() + .unwrap() + .block_on(gdb.run_blocking::(&mut emu)); + + match run { Ok(disconnect_reason) => match disconnect_reason { DisconnectReason::Disconnect => { println!("GDB client has disconnected. Running to completion..."); diff --git a/examples/armv4t_multicore/gdb.rs b/examples/armv4t_multicore/gdb.rs index 11ed1e3..c4b346f 100644 --- a/examples/armv4t_multicore/gdb.rs +++ b/examples/armv4t_multicore/gdb.rs @@ -12,6 +12,7 @@ use gdbstub::target::ext::breakpoints::WatchKind; use gdbstub::target::Target; use gdbstub::target::TargetError; use gdbstub::target::TargetResult; +use maybe_async::maybe_async; pub fn cpuid_to_tid(id: CpuId) -> Tid { match id { @@ -217,8 +218,9 @@ impl target::ext::breakpoints::Breakpoints for Emu { } } +#[maybe_async] impl target::ext::breakpoints::SwBreakpoint for Emu { - fn add_sw_breakpoint( + async fn add_sw_breakpoint( &mut self, addr: u32, _kind: gdbstub_arch::arm::ArmBreakpointKind, @@ -227,7 +229,7 @@ impl target::ext::breakpoints::SwBreakpoint for Emu { Ok(true) } - fn remove_sw_breakpoint( + async fn remove_sw_breakpoint( &mut self, addr: u32, _kind: gdbstub_arch::arm::ArmBreakpointKind, @@ -241,8 +243,9 @@ impl target::ext::breakpoints::SwBreakpoint for Emu { } } +#[maybe_async] impl target::ext::breakpoints::HwWatchpoint for Emu { - fn add_hw_watchpoint( + async fn add_hw_watchpoint( &mut self, addr: u32, _len: u32, // TODO: properly handle `len` parameter @@ -260,7 +263,7 @@ impl target::ext::breakpoints::HwWatchpoint for Emu { Ok(true) } - fn remove_hw_watchpoint( + async fn remove_hw_watchpoint( &mut self, addr: u32, _len: u32, // TODO: properly handle `len` parameter diff --git a/examples/armv4t_multicore/main.rs b/examples/armv4t_multicore/main.rs index c24f795..7d80c09 100644 --- a/examples/armv4t_multicore/main.rs +++ b/examples/armv4t_multicore/main.rs @@ -169,7 +169,13 @@ fn main() -> DynResult<()> { let gdb = GdbStub::new(connection); - match gdb.run_blocking::(&mut emu) { + #[cfg(feature = "sync")] + let run = gdb.run_blocking::(&mut emu); + #[cfg(not(feature = "sync"))] + let run = tokio::runtime::Runtime::new() + .unwrap() + .block_on(gdb.run_blocking::(&mut emu)); + match run { Ok(disconnect_reason) => match disconnect_reason { DisconnectReason::Disconnect => { println!("GDB client has disconnected. Running to completion..."); From 326b98e2f0431ac370fb592001cf79c58d6326f0 Mon Sep 17 00:00:00 2001 From: Sidong Yang Date: Tue, 7 Jan 2025 08:39:02 +0000 Subject: [PATCH 5/6] use sync for no std example --- example_no_std/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/example_no_std/Cargo.toml b/example_no_std/Cargo.toml index 87a0db1..e5677e4 100644 --- a/example_no_std/Cargo.toml +++ b/example_no_std/Cargo.toml @@ -5,7 +5,7 @@ authors = ["Daniel Prilik "] edition = "2018" [dependencies] -gdbstub = { path = "../", default-features = false } +gdbstub = { path = "../", default-features = false, features = ["sync"] } gdbstub_arch = { path = "../gdbstub_arch", default-features = false } libc = { version = "0.2", default-features = false } From 9fea11d37cf2e76e720bbcdfc501c759e74b9f8c Mon Sep 17 00:00:00 2001 From: Sidong Yang Date: Mon, 13 Jan 2025 09:19:50 +0000 Subject: [PATCH 6/6] use AFIT for maybe_async --- examples/armv4t/Cargo.toml~ | 0 examples/armv4t/gdb/breakpoints.rs | 7 ++++--- examples/armv4t/gdb/mod.rs | 2 +- examples/armv4t_multicore/gdb.rs | 4 ++-- src/stub/core_impl.rs | 2 +- src/stub/core_impl/breakpoints.rs | 2 +- src/stub/core_impl/resume.rs | 6 +++--- src/stub/mod.rs | 2 +- src/stub/state_machine.rs | 4 ++-- src/target/ext/base/singlethread.rs | 2 +- src/target/ext/breakpoints.rs | 6 +++--- 11 files changed, 19 insertions(+), 18 deletions(-) create mode 100644 examples/armv4t/Cargo.toml~ diff --git a/examples/armv4t/Cargo.toml~ b/examples/armv4t/Cargo.toml~ new file mode 100644 index 0000000..e69de29 diff --git a/examples/armv4t/gdb/breakpoints.rs b/examples/armv4t/gdb/breakpoints.rs index 973940b..8b196ec 100644 --- a/examples/armv4t/gdb/breakpoints.rs +++ b/examples/armv4t/gdb/breakpoints.rs @@ -9,7 +9,8 @@ impl target::ext::breakpoints::Breakpoints for Emu { fn support_sw_breakpoint( &mut self, ) -> Option> { - Some(self) + // Some(self) + None } #[inline(always)] @@ -20,7 +21,7 @@ impl target::ext::breakpoints::Breakpoints for Emu { } } -#[maybe_async] +#[maybe_async(AFIT)] impl target::ext::breakpoints::SwBreakpoint for Emu { async fn add_sw_breakpoint( &mut self, @@ -45,7 +46,7 @@ impl target::ext::breakpoints::SwBreakpoint for Emu { } } -#[maybe_async] +#[maybe_async(AFIT)] impl target::ext::breakpoints::HwWatchpoint for Emu { async fn add_hw_watchpoint( &mut self, diff --git a/examples/armv4t/gdb/mod.rs b/examples/armv4t/gdb/mod.rs index c1d2dfb..7b9fffc 100644 --- a/examples/armv4t/gdb/mod.rs +++ b/examples/armv4t/gdb/mod.rs @@ -232,7 +232,7 @@ impl SingleThreadBase for Emu { } } -#[maybe_async] +#[maybe_async(AFIT)] impl SingleThreadResume for Emu { async fn resume(&mut self, signal: Option) -> Result<(), Self::Error> { // Upon returning from the `resume` method, the target being debugged should be diff --git a/examples/armv4t_multicore/gdb.rs b/examples/armv4t_multicore/gdb.rs index c4b346f..1f96907 100644 --- a/examples/armv4t_multicore/gdb.rs +++ b/examples/armv4t_multicore/gdb.rs @@ -218,7 +218,7 @@ impl target::ext::breakpoints::Breakpoints for Emu { } } -#[maybe_async] +#[maybe_async(AFIT)] impl target::ext::breakpoints::SwBreakpoint for Emu { async fn add_sw_breakpoint( &mut self, @@ -243,7 +243,7 @@ impl target::ext::breakpoints::SwBreakpoint for Emu { } } -#[maybe_async] +#[maybe_async(AFIT)] impl target::ext::breakpoints::HwWatchpoint for Emu { async fn add_hw_watchpoint( &mut self, diff --git a/src/stub/core_impl.rs b/src/stub/core_impl.rs index b2ece55..c43a4ad 100644 --- a/src/stub/core_impl.rs +++ b/src/stub/core_impl.rs @@ -114,7 +114,7 @@ pub enum HandlerStatus { Disconnect(DisconnectReason), } -#[maybe_async] +#[maybe_async(AFIT)] impl GdbStubImpl { pub fn new() -> GdbStubImpl { GdbStubImpl { diff --git a/src/stub/core_impl/breakpoints.rs b/src/stub/core_impl/breakpoints.rs index 30f53b8..36b6b7e 100644 --- a/src/stub/core_impl/breakpoints.rs +++ b/src/stub/core_impl/breakpoints.rs @@ -9,7 +9,7 @@ enum CmdKind { Remove, } -#[maybe_async] +#[maybe_async(AFIT)] impl GdbStubImpl { #[inline(always)] async fn handle_breakpoint_common( diff --git a/src/stub/core_impl/resume.rs b/src/stub/core_impl/resume.rs index aa6aa4d..ad3a92f 100644 --- a/src/stub/core_impl/resume.rs +++ b/src/stub/core_impl/resume.rs @@ -15,7 +15,7 @@ use crate::target::ext::catch_syscalls::CatchSyscallPosition; use maybe_async::maybe_async; impl GdbStubImpl { - #[maybe_async] + #[maybe_async(AFIT)] pub(crate) async fn handle_stop_resume( &mut self, res: &mut ResponseWriter<'_, C>, @@ -83,7 +83,7 @@ impl GdbStubImpl { self.do_vcont(ops, actions).await } - #[maybe_async] + #[maybe_async(AFIT)] async fn do_vcont_single_thread( ops: &mut dyn crate::target::ext::base::singlethread::SingleThreadResume< Arch = T::Arch, @@ -258,7 +258,7 @@ impl GdbStubImpl { ops.resume().map_err(Error::TargetError) } - #[maybe_async] + #[maybe_async(AFIT)] async fn do_vcont( &mut self, ops: ResumeOps<'_, T::Arch, T::Error>, diff --git a/src/stub/mod.rs b/src/stub/mod.rs index cc53344..2d00d42 100644 --- a/src/stub/mod.rs +++ b/src/stub/mod.rs @@ -155,7 +155,7 @@ impl<'a, T: Target, C: Connection> GdbStub<'a, T, C> { /// etc...) you will need to interface with the underlying /// [`GdbStubStateMachine`](state_machine::GdbStubStateMachine) API /// directly. - #[maybe_async] + #[maybe_async(AFIT)] pub async fn run_blocking( self, target: &mut T, diff --git a/src/stub/state_machine.rs b/src/stub/state_machine.rs index a907f3d..d6e9459 100644 --- a/src/stub/state_machine.rs +++ b/src/stub/state_machine.rs @@ -209,7 +209,7 @@ impl<'a, T: Target, C: Connection> GdbStubStateMachineInner<'a, state::Idle, } /// Pass a byte to the GDB stub. - #[maybe_async] + #[maybe_async(AFIT)] pub async fn incoming_data( mut self, target: &mut T, @@ -251,7 +251,7 @@ impl<'a, T: Target, C: Connection> GdbStubStateMachineInner<'a, state::Idle, /// Methods which can only be called from the /// [`GdbStubStateMachine::Running`] state. -#[maybe_async] +#[maybe_async(AFIT)] impl<'a, T: Target, C: Connection> GdbStubStateMachineInner<'a, state::Running, T, C> { /// Report a target stop reason back to GDB. pub fn report_stop( diff --git a/src/target/ext/base/singlethread.rs b/src/target/ext/base/singlethread.rs index 298c514..6e2d447 100644 --- a/src/target/ext/base/singlethread.rs +++ b/src/target/ext/base/singlethread.rs @@ -72,7 +72,7 @@ pub trait SingleThreadBase: Target { } /// Target extension - support for resuming single threaded targets. -#[maybe_async] +#[maybe_async(AFIT)] pub trait SingleThreadResume: Target { /// Resume execution on the target. /// diff --git a/src/target/ext/breakpoints.rs b/src/target/ext/breakpoints.rs index f35e693..7be9155 100644 --- a/src/target/ext/breakpoints.rs +++ b/src/target/ext/breakpoints.rs @@ -37,7 +37,7 @@ define_ext!(BreakpointsOps, Breakpoints); /// using an _interpreted_ CPU (as opposed to a JIT), the simplest way to /// implement "software" breakpoints would be to check the `PC` value after each /// CPU cycle, ignoring the specified breakpoint `kind` entirely. -#[maybe_async] +#[maybe_async(AFIT)] pub trait SwBreakpoint: Target + Breakpoints { /// Add a new software breakpoint. /// @@ -69,7 +69,7 @@ define_ext!(SwBreakpointOps, SwBreakpoint); /// using an _interpreted_ CPU (as opposed to a JIT), there shouldn't be any /// reason to implement this extension (as software breakpoints are likely to be /// just-as-fast). -#[maybe_async] +#[maybe_async(AFIT)] pub trait HwBreakpoint: Target + Breakpoints { /// Add a new hardware breakpoint. /// @@ -112,7 +112,7 @@ pub enum WatchKind { /// _software watchpoints_, which tend to be excruciatingly slow (as hey are /// implemented by single-stepping the system, and reading the watched memory /// location after each step). -#[maybe_async] +#[maybe_async(AFIT)] pub trait HwWatchpoint: Target + Breakpoints { /// Add a new hardware watchpoint. /// The number of bytes to watch is specified by `len`.