Skip to content

Commit

Permalink
Toggle support for QStartNoAckMode (#135)
Browse files Browse the repository at this point in the history
* Toggle support for `QStartNoAckMode`

* Compile-out packet parsing if mode is disabled
  • Loading branch information
bet4it committed Apr 13, 2023
1 parent 3c00732 commit e47ed4f
Show file tree
Hide file tree
Showing 6 changed files with 60 additions and 10 deletions.
6 changes: 6 additions & 0 deletions example_no_std/src/gdb.rs
Expand Up @@ -22,6 +22,12 @@ impl Target for DummyTarget {
target::ext::base::BaseOps::MultiThread(self)
}

// disable `QStartNoAckMode` in order to save space
#[inline(always)]
fn use_no_ack_mode(&self) -> bool {
false
}

// disable X packet optimization in order to save space
#[inline(always)]
fn use_x_upcase_packet(&self) -> bool {
Expand Down
14 changes: 13 additions & 1 deletion src/protocol/commands.rs
Expand Up @@ -91,6 +91,7 @@ macro_rules! commands {
fn support_single_register_access(&mut self) -> Option<()>;
fn support_reverse_step(&mut self) -> Option<()>;
fn support_reverse_cont(&mut self) -> Option<()>;
fn support_no_ack_mode(&mut self) -> Option<()>;
fn support_x_upcase_packet(&mut self) -> Option<()>;
fn support_thread_extra_info(&mut self) -> Option<()>;
}
Expand Down Expand Up @@ -160,6 +161,14 @@ macro_rules! commands {
}
}

fn support_no_ack_mode(&mut self) -> Option<()> {
if self.use_no_ack_mode() {
Some(())
} else {
None
}
}

fn support_thread_extra_info(&mut self) -> Option<()> {
use crate::target::ext::base::BaseOps;
match self.base_ops() {
Expand Down Expand Up @@ -228,7 +237,6 @@ commands! {
"M" => _m_upcase::M<'a>,
"qAttached" => _qAttached::qAttached,
"qfThreadInfo" => _qfThreadInfo::qfThreadInfo,
"QStartNoAckMode" => _QStartNoAckMode::QStartNoAckMode,
"qsThreadInfo" => _qsThreadInfo::qsThreadInfo,
"qSupported" => _qSupported::qSupported<'a>,
"T" => _t_upcase::T,
Expand All @@ -249,6 +257,10 @@ commands! {
"X" => _x_upcase::X<'a>,
}

no_ack_mode {
"QStartNoAckMode" => _QStartNoAckMode::QStartNoAckMode,
}

single_register_access use 'a {
"p" => _p::p<'a>,
"P" => _p_upcase::P<'a>,
Expand Down
2 changes: 2 additions & 0 deletions src/stub/core_impl.rs
Expand Up @@ -31,6 +31,7 @@ mod host_io;
mod lldb_register_info;
mod memory_map;
mod monitor_cmd;
mod no_ack_mode;
mod resume;
mod reverse_exec;
mod section_offsets;
Expand Down Expand Up @@ -194,6 +195,7 @@ impl<T: Target, C: Connection> GdbStubImpl<T, C> {
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::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)
Expand Down
14 changes: 5 additions & 9 deletions src/stub/core_impl/base.rs
Expand Up @@ -109,11 +109,11 @@ impl<T: Target, C: Connection> GdbStubImpl<T, C> {
res.write_num(cmd.packet_buffer_len)?;

// these are the few features that gdbstub unconditionally supports
res.write_str(concat!(
";vContSupported+",
";multiprocess+",
";QStartNoAckMode+",
))?;
res.write_str(concat!(";vContSupported+", ";multiprocess+",))?;

if target.use_no_ack_mode() {
res.write_str(";QStartNoAckMode+")?;
}

if let Some(resume_ops) = target.base_ops().resume_ops() {
let (reverse_cont, reverse_step) = match resume_ops {
Expand Down Expand Up @@ -193,10 +193,6 @@ impl<T: Target, C: Connection> GdbStubImpl<T, C> {

HandlerStatus::Handled
}
Base::QStartNoAckMode(_) => {
self.features.set_no_ack_mode(true);
HandlerStatus::NeedsOk
}

// -------------------- "Core" Functionality -------------------- //
Base::QuestionMark(_) => {
Expand Down
25 changes: 25 additions & 0 deletions src/stub/core_impl/no_ack_mode.rs
@@ -0,0 +1,25 @@
use super::prelude::*;
use crate::protocol::commands::ext::NoAckMode;

impl<T: Target, C: Connection> GdbStubImpl<T, C> {
pub(crate) fn handle_no_ack_mode(
&mut self,
_res: &mut ResponseWriter<'_, C>,
target: &mut T,
command: NoAckMode,
) -> Result<HandlerStatus, Error<T::Error, C::Error>> {
if !target.use_no_ack_mode() {
return Ok(HandlerStatus::Handled);
}

crate::__dead_code_marker!("no_ack_mode", "impl");

let handler_status = match command {
NoAckMode::QStartNoAckMode(_) => {
self.features.set_no_ack_mode(true);
HandlerStatus::NeedsOk
}
};
Ok(handler_status)
}
}
9 changes: 9 additions & 0 deletions src/target/mod.rs
Expand Up @@ -530,6 +530,14 @@ pub trait Target {
<Self::Arch as Arch>::single_step_gdb_behavior()
}

/// Enable/disable `QStartNoAckMode`
///
/// By default, this method returns `true`.
#[inline(always)]
fn use_no_ack_mode(&self) -> bool {
true
}

/// Enable/disable using the more efficient `X` packet to write to target
/// memory (as opposed to the basic `M` packet).
///
Expand Down Expand Up @@ -727,6 +735,7 @@ macro_rules! impl_dyn_target {
__delegate!(fn guard_rail_implicit_sw_breakpoints(&self) -> bool);
__delegate!(fn guard_rail_single_step_gdb_behavior(&self) -> SingleStepGdbBehavior);

__delegate!(fn use_no_ack_mode(&self) -> bool);
__delegate!(fn use_x_upcase_packet(&self) -> bool);
__delegate!(fn use_resume_stub(&self) -> bool);
__delegate!(fn use_rle(&self) -> bool);
Expand Down

0 comments on commit e47ed4f

Please sign in to comment.