diff --git a/examples/armv4t/gdb/mod.rs b/examples/armv4t/gdb/mod.rs index 0831566..6c1ed51 100644 --- a/examples/armv4t/gdb/mod.rs +++ b/examples/armv4t/gdb/mod.rs @@ -314,6 +314,7 @@ impl target::ext::base::single_register_access::SingleRegisterAccess<()> for Emu ); Ok(buf.len()) } + custom_arch::ArmCoreRegIdCustom::Unavailable => Ok(0), } } @@ -341,6 +342,7 @@ impl target::ext::base::single_register_access::SingleRegisterAccess<()> for Emu Ok(()) } // ignore writes + custom_arch::ArmCoreRegIdCustom::Unavailable | custom_arch::ArmCoreRegIdCustom::Time => Ok(()), } } @@ -460,6 +462,8 @@ mod custom_arch { // not sent as part of `struct ArmCoreRegsCustom`, and only accessible via the single // register read/write functions Time, + /// This pseudo-register is valid but never available + Unavailable, } impl RegId for ArmCoreRegIdCustom { @@ -467,6 +471,7 @@ mod custom_arch { let reg = match id { 26 => Self::Custom, 27 => Self::Time, + 28 => Self::Unavailable, _ => { let (reg, size) = ArmCoreRegId::from_raw_id(id)?; return Some((Self::Core(reg), size)); @@ -530,6 +535,7 @@ mod custom_arch { ArmCoreRegIdCustom::Core(ArmCoreRegId::Fps) => "padding", ArmCoreRegIdCustom::Core(ArmCoreRegId::Cpsr) => "cpsr", ArmCoreRegIdCustom::Custom => "custom", + ArmCoreRegIdCustom::Unavailable => "Unavailable", _ => "unknown", }; let encoding = match r { @@ -537,6 +543,7 @@ mod custom_arch { ArmCoreRegIdCustom::Core(ArmCoreRegId::Sp) | ArmCoreRegIdCustom::Core(ArmCoreRegId::Pc) | ArmCoreRegIdCustom::Core(ArmCoreRegId::Cpsr) + | ArmCoreRegIdCustom::Unavailable | ArmCoreRegIdCustom::Custom => Encoding::Uint, _ => Encoding::Vector, }; @@ -545,6 +552,7 @@ mod custom_arch { ArmCoreRegIdCustom::Core(ArmCoreRegId::Sp) | ArmCoreRegIdCustom::Core(ArmCoreRegId::Pc) | ArmCoreRegIdCustom::Core(ArmCoreRegId::Cpsr) + | ArmCoreRegIdCustom::Unavailable | ArmCoreRegIdCustom::Custom => Format::Hex, _ => Format::VectorUInt8, }; @@ -555,6 +563,7 @@ mod custom_arch { ArmCoreRegIdCustom::Core(ArmCoreRegId::Sp) | ArmCoreRegIdCustom::Core(ArmCoreRegId::Pc) | ArmCoreRegIdCustom::Core(ArmCoreRegId::Cpsr) + | ArmCoreRegIdCustom::Unavailable | ArmCoreRegIdCustom::Custom => "General Purpose Registers", _ => "Floating Point Registers", }; diff --git a/examples/armv4t/gdb/target_description_xml_override.rs b/examples/armv4t/gdb/target_description_xml_override.rs index 294b513..2c5348c 100644 --- a/examples/armv4t/gdb/target_description_xml_override.rs +++ b/examples/armv4t/gdb/target_description_xml_override.rs @@ -96,5 +96,13 @@ const EXTRA_XML: &str = r#" this register via the 'p' and 'P' packets respectively --> + + + "#; diff --git a/src/protocol/response_writer.rs b/src/protocol/response_writer.rs index 3dea22a..1ef43ea 100644 --- a/src/protocol/response_writer.rs +++ b/src/protocol/response_writer.rs @@ -212,6 +212,14 @@ impl<'a, C: Connection + 'a> ResponseWriter<'a, C> { Ok(()) } + /// Marks data of 'size' bytes as unavailable. + pub fn write_x(&mut self, size: usize) -> Result<(), Error> { + for _ in 0..(size * 2) { + self.write(b'x')?; + } + Ok(()) + } + /// Write a number as a big-endian hex string using the most compact /// representation possible (i.e: trimming leading zeros). pub fn write_num(&mut self, digit: D) -> Result<(), Error> { diff --git a/src/stub/core_impl/single_register_access.rs b/src/stub/core_impl/single_register_access.rs index fd61c58..cace9d6 100644 --- a/src/stub/core_impl/single_register_access.rs +++ b/src/stub/core_impl/single_register_access.rs @@ -33,14 +33,22 @@ impl GdbStubImpl { let len = ops.read_register(id, reg_id, buf).handle_error()?; - if let Some(size) = reg_size { - if size.get() != len { + if len == 0 { + if let Some(size) = reg_size { + res.write_x(size.get())?; + } else { return Err(Error::TargetMismatch); } } else { - buf = buf.get_mut(..len).ok_or(Error::PacketBufferOverflow)?; + if let Some(size) = reg_size { + if size.get() != len { + return Err(Error::TargetMismatch); + } + } else { + buf = buf.get_mut(..len).ok_or(Error::PacketBufferOverflow)?; + } + res.write_hex_buf(buf)?; } - res.write_hex_buf(buf)?; HandlerStatus::Handled } SingleRegisterAccess::P(p) => { diff --git a/src/target/ext/base/single_register_access.rs b/src/target/ext/base/single_register_access.rs index f7a9b16..2887fef 100644 --- a/src/target/ext/base/single_register_access.rs +++ b/src/target/ext/base/single_register_access.rs @@ -29,7 +29,8 @@ where /// Implementations should write the value of the register using target's /// native byte order in the buffer `buf`. /// - /// Return the number of bytes written into `buf`. + /// Return the number of bytes written into `buf` or `0` if the register is + /// valid but unavailable. /// /// If the requested register could not be accessed, an appropriate /// non-fatal error should be returned.