Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

use maybe_async that supports async traits for breakpoint #161

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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", default-features = false }
num-traits = { version = "0.2", default-features = false }
paste = "1.0"

Expand All @@ -27,14 +29,16 @@ 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"]
default = ["std", "trace-pkt", "sync"]
alloc = ["managed/alloc"]
std = ["alloc"]
trace-pkt = ["alloc"]
paranoid_unsafe = []
core_error = []
sync = ["maybe-async/is_sync"]
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Whether or not gdbstub should present a sync vs. async API by default is an interesting question. I suppose that's a judgement call we can make later, if we decide that maybe-async is the basis of the approach we take.


# INTERNAL: enables the `__dead_code_marker!` macro.
# used as part of the `scripts/test_dead_code_elim.sh`
Expand Down
2 changes: 1 addition & 1 deletion example_no_std/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ authors = ["Daniel Prilik <[email protected]>"]
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 }
Expand Down
11 changes: 7 additions & 4 deletions examples/armv4t/gdb/breakpoints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand All @@ -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,
Expand All @@ -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,
Expand All @@ -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,
Expand All @@ -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,
Expand Down
4 changes: 3 additions & 1 deletion examples/armv4t/gdb/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -231,8 +232,9 @@ impl SingleThreadBase for Emu {
}
}

#[maybe_async]
impl SingleThreadResume for Emu {
fn resume(&mut self, signal: Option<Signal>) -> Result<(), Self::Error> {
async fn resume(&mut self, signal: Option<Signal>) -> 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`,
Expand Down
9 changes: 8 additions & 1 deletion examples/armv4t/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,14 @@ fn main() -> DynResult<()> {

let gdb = GdbStub::new(connection);

match gdb.run_blocking::<EmuGdbEventLoop>(&mut emu) {
#[cfg(feature = "sync")]
let run = gdb.run_blocking::<EmuGdbEventLoop>(&mut emu);
#[cfg(not(feature = "sync"))]
let run = tokio::runtime::Runtime::new()
.unwrap()
.block_on(gdb.run_blocking::<EmuGdbEventLoop>(&mut emu));

match run {
Ok(disconnect_reason) => match disconnect_reason {
DisconnectReason::Disconnect => {
println!("GDB client has disconnected. Running to completion...");
Expand Down
11 changes: 7 additions & 4 deletions examples/armv4t_multicore/gdb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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,
Expand All @@ -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,
Expand All @@ -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
Expand All @@ -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
Expand Down
8 changes: 7 additions & 1 deletion examples/armv4t_multicore/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,13 @@ fn main() -> DynResult<()> {

let gdb = GdbStub::new(connection);

match gdb.run_blocking::<EmuGdbEventLoop>(&mut emu) {
#[cfg(feature = "sync")]
let run = gdb.run_blocking::<EmuGdbEventLoop>(&mut emu);
#[cfg(not(feature = "sync"))]
let run = tokio::runtime::Runtime::new()
.unwrap()
.block_on(gdb.run_blocking::<EmuGdbEventLoop>(&mut emu));
match run {
Ok(disconnect_reason) => match disconnect_reason {
DisconnectReason::Disconnect => {
println!("GDB client has disconnected. Running to completion...");
Expand Down
12 changes: 7 additions & 5 deletions src/stub/core_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -113,6 +114,7 @@ pub enum HandlerStatus {
Disconnect(DisconnectReason),
}

#[maybe_async]
impl<T: Target, C: Connection> GdbStubImpl<T, C> {
pub fn new() -> GdbStubImpl<T, C> {
GdbStubImpl {
Expand All @@ -133,7 +135,7 @@ impl<T: Target, C: Connection> GdbStubImpl<T, C> {
}
}

pub fn handle_packet(
pub async fn handle_packet(
&mut self,
target: &mut T,
conn: &mut C,
Expand All @@ -153,7 +155,7 @@ impl<T: Target, C: Connection> GdbStubImpl<T, C> {
}

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")?;
Expand Down Expand Up @@ -188,7 +190,7 @@ impl<T: Target, C: Connection> GdbStubImpl<T, C> {
}
}

fn handle_command(
async fn handle_command(
&mut self,
res: &mut ResponseWriter<'_, C>,
target: &mut T,
Expand All @@ -198,13 +200,13 @@ impl<T: Target, C: Connection> GdbStubImpl<T, C> {
// `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) => {
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),
Expand Down
25 changes: 17 additions & 8 deletions src/stub/core_impl/breakpoints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<T: Target, C: Connection> GdbStubImpl<T, C> {
#[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<'_>,
Expand All @@ -35,13 +37,14 @@ impl<T: Target, C: Connection> GdbStubImpl<T, C> {
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();
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() => {
Expand All @@ -57,8 +60,8 @@ impl<T: Target, C: Connection> GdbStubImpl<T, C> {
.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
Expand All @@ -76,7 +79,7 @@ impl<T: Target, C: Connection> GdbStubImpl<T, C> {
}
}

pub(crate) fn handle_breakpoints(
pub(crate) async fn handle_breakpoints(
&mut self,
_res: &mut ResponseWriter<'_, C>,
target: &mut T,
Expand All @@ -90,8 +93,14 @@ impl<T: Target, C: Connection> GdbStubImpl<T, C> {
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,
};
Expand Down
17 changes: 11 additions & 6 deletions src/stub/core_impl/resume.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<T: Target, C: Connection> GdbStubImpl<T, C> {
pub(crate) fn handle_stop_resume(
#[maybe_async]
pub(crate) async fn handle_stop_resume(
&mut self,
res: &mut ResponseWriter<'_, C>,
target: &mut T,
Expand Down Expand Up @@ -77,10 +80,11 @@ impl<T: Target, C: Connection> GdbStubImpl<T, C> {
}
};

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,
Expand Down Expand Up @@ -122,7 +126,7 @@ impl<T: Target, C: Connection> GdbStubImpl<T, C> {
_ => 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() => {
Expand Down Expand Up @@ -254,13 +258,14 @@ impl<T: Target, C: Connection> GdbStubImpl<T, C> {
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<HandlerStatus, Error<T::Error, C::Error>> {
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)?,
};

Expand Down
Loading
Loading