From af55bee46fc22f8c4a8b3aae60d14de160a49c7b Mon Sep 17 00:00:00 2001 From: "Dr. Chat" Date: Tue, 16 Mar 2021 13:22:37 -0500 Subject: [PATCH] Allow `Target` to override `Arch`'s target description --- src/gdbstub_impl/mod.rs | 21 +++++++++++++++++---- src/target/ext/base/description.rs | 15 +++++++++++++++ src/target/ext/base/mod.rs | 5 +++++ src/target/mod.rs | 5 +++++ 4 files changed, 42 insertions(+), 4 deletions(-) create mode 100644 src/target/ext/base/description.rs diff --git a/src/gdbstub_impl/mod.rs b/src/gdbstub_impl/mod.rs index c0f714c8..9c54bc79 100644 --- a/src/gdbstub_impl/mod.rs +++ b/src/gdbstub_impl/mod.rs @@ -303,7 +303,9 @@ impl GdbStubImpl { // TODO: implement conditional breakpoint support (since that's kool). // res.write_str("ConditionalBreakpoints+;")?; - if T::Arch::target_description_xml().is_some() { + if target.target_description().is_some() + || ::target_description_xml().is_some() + { res.write_str(";qXfer:features:read+")?; } @@ -314,7 +316,17 @@ impl GdbStubImpl { HandlerStatus::NeedsOK } ext::Base::qXferFeaturesRead(cmd) => { - match T::Arch::target_description_xml() { + // Query the target description ops for the target's description. + let xml = { + // Target gets the first chance to override the XML description. + target + .target_description() + .map_or(::target_description_xml(), |v| { + Some(v.target_description_xml()) + }) + }; + + match xml { Some(xml) => { let xml = xml.trim(); if cmd.offset >= xml.len() { @@ -331,10 +343,11 @@ impl GdbStubImpl { } } // If the target hasn't provided their own XML, then the initial response to - // "qSupported" wouldn't have included "qXfer:features:read", and gdb wouldn't - // send this packet unless it was explicitly marked as supported. + // "qSupported" wouldn't have included "qXfer:features:read", and gdb + // wouldn't send this packet unless it was explicitly marked as supported. None => return Err(Error::PacketUnexpected), } + HandlerStatus::Handled } diff --git a/src/target/ext/base/description.rs b/src/target/ext/base/description.rs new file mode 100644 index 00000000..b5868ee2 --- /dev/null +++ b/src/target/ext/base/description.rs @@ -0,0 +1,15 @@ +use crate::arch::Arch; +use crate::target::Target; + +/// Basic operation to return an XML-formatted target description string +/// to the GDB client. +pub trait TargetDescription: Target { + /// Returns an optional XML description for the target to GDB. + fn target_description_xml(&self) -> &'static str { + ::target_description_xml().unwrap() + } +} + +/// See [`TargetDescription`] +pub type TargetDescriptionOps<'a, T> = + &'a mut dyn TargetDescription::Arch, Error = ::Error>; diff --git a/src/target/ext/base/mod.rs b/src/target/ext/base/mod.rs index 3c3c293f..3e984b8c 100644 --- a/src/target/ext/base/mod.rs +++ b/src/target/ext/base/mod.rs @@ -7,6 +7,11 @@ pub mod multithread; pub mod singlethread; +mod description; + +pub use description::TargetDescription; +pub use description::TargetDescriptionOps; + /// Base operations for single/multi threaded targets. pub enum BaseOps<'a, A, E> { /// Single-threaded target diff --git a/src/target/mod.rs b/src/target/mod.rs index c027824e..742aa408 100644 --- a/src/target/mod.rs +++ b/src/target/mod.rs @@ -239,6 +239,11 @@ pub trait Target { fn section_offsets(&mut self) -> Option> { None } + + /// Handle requests for the target's XML description for GDB. + fn target_description(&mut self) -> Option> { + None + } } macro_rules! impl_dyn_target {