From 1593da26fe91805cddff6daf45012b052c2d7b53 Mon Sep 17 00:00:00 2001 From: Daniel Prilik Date: Fri, 19 Mar 2021 08:44:34 -0700 Subject: [PATCH] Add `TargetDescriptionXmlOverride` extension (#43) * add target description XML override extension * more consistent naming * doc tweaks --- examples/armv4t/gdb/mod.rs | 8 +++++++ .../gdb/target_description_xml_override.rs | 9 ++++++++ src/arch/traits.rs | 9 ++++---- src/gdbstub_impl/mod.rs | 12 ++++++++-- src/target/ext/mod.rs | 1 + .../ext/target_description_xml_override.rs | 22 +++++++++++++++++++ src/target/mod.rs | 14 ++++++++++++ 7 files changed, 68 insertions(+), 7 deletions(-) create mode 100644 examples/armv4t/gdb/target_description_xml_override.rs create mode 100644 src/target/ext/target_description_xml_override.rs diff --git a/examples/armv4t/gdb/mod.rs b/examples/armv4t/gdb/mod.rs index ae3cbd94..7decab97 100644 --- a/examples/armv4t/gdb/mod.rs +++ b/examples/armv4t/gdb/mod.rs @@ -15,6 +15,7 @@ use crate::emu::{Emu, Event}; mod extended_mode; mod monitor_cmd; mod section_offsets; +mod target_description_xml_override; /// Turn a `ArmCoreRegId` into an internal register number of `armv4t_emu`. fn cpu_reg_id(id: ArmCoreRegId) -> Option { @@ -55,6 +56,13 @@ impl Target for Emu { fn section_offsets(&mut self) -> Option> { Some(self) } + + fn target_description_xml_override( + &mut self, + ) -> Option> + { + Some(self) + } } impl SingleThreadOps for Emu { diff --git a/examples/armv4t/gdb/target_description_xml_override.rs b/examples/armv4t/gdb/target_description_xml_override.rs new file mode 100644 index 00000000..843697e1 --- /dev/null +++ b/examples/armv4t/gdb/target_description_xml_override.rs @@ -0,0 +1,9 @@ +use gdbstub::target; + +use crate::emu::Emu; + +impl target::ext::target_description_xml_override::TargetDescriptionXmlOverride for Emu { + fn target_description_xml(&self) -> &str { + r#"armv4t"# + } +} diff --git a/src/arch/traits.rs b/src/arch/traits.rs index 19037390..4af97ecd 100644 --- a/src/arch/traits.rs +++ b/src/arch/traits.rs @@ -63,18 +63,17 @@ pub trait Arch { /// separate from the main `Registers` structure. type RegId: RegId; - /// (optional) Return the platform's `features.xml` file. + /// (optional) Return the target's description XML file (`target.xml`). /// - /// Implementing this method enables `gdb` to automatically detect the + /// Implementing this method enables GDB to automatically detect the /// target's architecture, saving the hassle of having to run `set /// architecture ` when starting a debugging session. /// /// These descriptions can be quite succinct. For example, the target - /// description for an `armv4t` platform can be as simple as: + /// description for an `armv4t` target can be as simple as: /// /// ``` - /// r#"armv4t"# - /// # ; + /// r#"armv4t"#; /// ``` /// /// See the [GDB docs](https://sourceware.org/gdb/current/onlinedocs/gdb/Target-Description-Format.html) diff --git a/src/gdbstub_impl/mod.rs b/src/gdbstub_impl/mod.rs index c0f714c8..72572fbe 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 T::Arch::target_description_xml().is_some() + || target.target_description_xml_override().is_some() + { res.write_str(";qXfer:features:read+")?; } @@ -314,7 +316,13 @@ impl GdbStubImpl { HandlerStatus::NeedsOK } ext::Base::qXferFeaturesRead(cmd) => { - match T::Arch::target_description_xml() { + #[allow(clippy::redundant_closure)] + let xml = target + .target_description_xml_override() + .map(|ops| ops.target_description_xml()) + .or_else(|| T::Arch::target_description_xml()); + + match xml { Some(xml) => { let xml = xml.trim(); if cmd.offset >= xml.len() { diff --git a/src/target/ext/mod.rs b/src/target/ext/mod.rs index 09d9ded7..9289655d 100644 --- a/src/target/ext/mod.rs +++ b/src/target/ext/mod.rs @@ -250,3 +250,4 @@ pub mod breakpoints; pub mod extended_mode; pub mod monitor_cmd; pub mod section_offsets; +pub mod target_description_xml_override; diff --git a/src/target/ext/target_description_xml_override.rs b/src/target/ext/target_description_xml_override.rs new file mode 100644 index 00000000..7cac0340 --- /dev/null +++ b/src/target/ext/target_description_xml_override.rs @@ -0,0 +1,22 @@ +//! Override the target description XML specified by `Target::Arch`. +use crate::target::Target; + +/// Target Extension - Override the target description XML specified by +/// `Target::Arch`. +/// +/// _Note:_ Unless you're working with a particularly dynamic, +/// runtime-configurable target, it's unlikely that you'll need to implement +/// this extension. +pub trait TargetDescriptionXmlOverride: Target { + /// Return the target's description XML file (`target.xml`). + /// + /// Refer to the + /// [target_description_xml](crate::arch::Arch::target_description_xml) + /// docs for more info. + fn target_description_xml(&self) -> &str; +} + +define_ext!( + TargetDescriptionXmlOverrideOps, + TargetDescriptionXmlOverride +); diff --git a/src/target/mod.rs b/src/target/mod.rs index c027824e..e2139fbc 100644 --- a/src/target/mod.rs +++ b/src/target/mod.rs @@ -239,6 +239,13 @@ pub trait Target { fn section_offsets(&mut self) -> Option> { None } + + /// Override the target description XML specified by `Target::Arch`. + fn target_description_xml_override( + &mut self, + ) -> Option> { + None + } } macro_rules! impl_dyn_target { @@ -278,6 +285,13 @@ macro_rules! impl_dyn_target { fn section_offsets(&mut self) -> Option> { (**self).section_offsets() } + + fn target_description_xml_override( + &mut self, + ) -> Option> + { + (**self).target_description_xml_override() + } } }; }