From e47ed4faacf5b3147f7478dab2ac4138b639e6d5 Mon Sep 17 00:00:00 2001 From: Bet4 <0xbet4@gmail.com> Date: Thu, 13 Apr 2023 08:21:59 +0800 Subject: [PATCH] Toggle support for `QStartNoAckMode` (#135) * Toggle support for `QStartNoAckMode` * Compile-out packet parsing if mode is disabled --- example_no_std/src/gdb.rs | 6 ++++++ src/protocol/commands.rs | 14 +++++++++++++- src/stub/core_impl.rs | 2 ++ src/stub/core_impl/base.rs | 14 +++++--------- src/stub/core_impl/no_ack_mode.rs | 25 +++++++++++++++++++++++++ src/target/mod.rs | 9 +++++++++ 6 files changed, 60 insertions(+), 10 deletions(-) create mode 100644 src/stub/core_impl/no_ack_mode.rs diff --git a/example_no_std/src/gdb.rs b/example_no_std/src/gdb.rs index ea6612b..8bd9155 100644 --- a/example_no_std/src/gdb.rs +++ b/example_no_std/src/gdb.rs @@ -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 { diff --git a/src/protocol/commands.rs b/src/protocol/commands.rs index 5cf6d0f..525533a 100644 --- a/src/protocol/commands.rs +++ b/src/protocol/commands.rs @@ -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<()>; } @@ -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() { @@ -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, @@ -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>, diff --git a/src/stub/core_impl.rs b/src/stub/core_impl.rs index 31ab884..f52d739 100644 --- a/src/stub/core_impl.rs +++ b/src/stub/core_impl.rs @@ -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; @@ -194,6 +195,7 @@ impl GdbStubImpl { 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) diff --git a/src/stub/core_impl/base.rs b/src/stub/core_impl/base.rs index dbe9d64..2e95551 100644 --- a/src/stub/core_impl/base.rs +++ b/src/stub/core_impl/base.rs @@ -109,11 +109,11 @@ impl GdbStubImpl { 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 { @@ -193,10 +193,6 @@ impl GdbStubImpl { HandlerStatus::Handled } - Base::QStartNoAckMode(_) => { - self.features.set_no_ack_mode(true); - HandlerStatus::NeedsOk - } // -------------------- "Core" Functionality -------------------- // Base::QuestionMark(_) => { diff --git a/src/stub/core_impl/no_ack_mode.rs b/src/stub/core_impl/no_ack_mode.rs new file mode 100644 index 0000000..48b5173 --- /dev/null +++ b/src/stub/core_impl/no_ack_mode.rs @@ -0,0 +1,25 @@ +use super::prelude::*; +use crate::protocol::commands::ext::NoAckMode; + +impl GdbStubImpl { + pub(crate) fn handle_no_ack_mode( + &mut self, + _res: &mut ResponseWriter<'_, C>, + target: &mut T, + command: NoAckMode, + ) -> Result> { + 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) + } +} diff --git a/src/target/mod.rs b/src/target/mod.rs index 985eea6..9e1426a 100644 --- a/src/target/mod.rs +++ b/src/target/mod.rs @@ -530,6 +530,14 @@ pub trait Target { ::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). /// @@ -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);