diff --git a/example_no_std/src/gdb.rs b/example_no_std/src/gdb.rs index ea6612b..976664c 100644 --- a/example_no_std/src/gdb.rs +++ b/example_no_std/src/gdb.rs @@ -71,10 +71,10 @@ impl MultiThreadBase for DummyTarget { _start_addr: u32, data: &mut [u8], _tid: Tid, // same address space for each core - ) -> TargetResult<(), Self> { + ) -> TargetResult { print_str("> read_addrs"); data.iter_mut().for_each(|b| *b = 0x55); - Ok(()) + Ok(data.len()) } #[inline(never)] diff --git a/examples/armv4t/gdb/mod.rs b/examples/armv4t/gdb/mod.rs index 97f7b2d..5df6b10 100644 --- a/examples/armv4t/gdb/mod.rs +++ b/examples/armv4t/gdb/mod.rs @@ -196,11 +196,22 @@ impl SingleThreadBase for Emu { Some(self) } - fn read_addrs(&mut self, start_addr: u32, data: &mut [u8]) -> TargetResult<(), Self> { - for (addr, val) in (start_addr..).zip(data.iter_mut()) { + fn read_addrs(&mut self, start_addr: u32, data: &mut [u8]) -> TargetResult { + // These values are taken from the link script. + const MEMORY_ORIGIN: u32 = 0x5555_0000; + const MEMORY_LENGTH: u32 = 0x1000_0000; + const MEMORY_END: u32 = MEMORY_ORIGIN + MEMORY_LENGTH; + + if !(MEMORY_ORIGIN..MEMORY_END).contains(&start_addr) { + return Err(TargetError::NonFatal); + } + + let end_addr = std::cmp::min(start_addr + data.len() as u32, MEMORY_END); + + for (addr, val) in (start_addr..end_addr).zip(data.iter_mut()) { *val = self.mem.r8(addr) } - Ok(()) + Ok((end_addr - start_addr) as usize) } fn write_addrs(&mut self, start_addr: u32, data: &[u8]) -> TargetResult<(), Self> { diff --git a/examples/armv4t_multicore/gdb.rs b/examples/armv4t_multicore/gdb.rs index 3c8cd75..2ad1462 100644 --- a/examples/armv4t_multicore/gdb.rs +++ b/examples/armv4t_multicore/gdb.rs @@ -92,11 +92,11 @@ impl MultiThreadBase for Emu { start_addr: u32, data: &mut [u8], _tid: Tid, // same address space for each core - ) -> TargetResult<(), Self> { + ) -> TargetResult { for (addr, val) in (start_addr..).zip(data.iter_mut()) { *val = self.mem.r8(addr) } - Ok(()) + Ok(data.len()) } fn write_addrs( diff --git a/src/stub/core_impl/base.rs b/src/stub/core_impl/base.rs index c0df01a..771dc08 100644 --- a/src/stub/core_impl/base.rs +++ b/src/stub/core_impl/base.rs @@ -238,7 +238,7 @@ impl GdbStubImpl { let addr = addr + NumCast::from(i).ok_or(Error::TargetMismatch)?; let data = &mut buf[..chunk_size]; - match target.base_ops() { + let data_len = match target.base_ops() { BaseOps::SingleThread(ops) => ops.read_addrs(addr, data), BaseOps::MultiThread(ops) => { ops.read_addrs(addr, data, self.current_mem_tid) @@ -249,6 +249,8 @@ impl GdbStubImpl { n -= chunk_size; i += chunk_size; + // TODO: add more specific error variant? + let data = data.get(..data_len).ok_or(Error::PacketBufferOverflow)?; res.write_hex_buf(data)?; } HandlerStatus::Handled diff --git a/src/target/ext/base/multithread.rs b/src/target/ext/base/multithread.rs index 693030e..4b993eb 100644 --- a/src/target/ext/base/multithread.rs +++ b/src/target/ext/base/multithread.rs @@ -43,17 +43,25 @@ pub trait MultiThreadBase: Target { None } - /// Read bytes from the specified address range. + /// Read bytes from the specified address range and return the number of + /// bytes that were read. /// - /// If the requested address range could not be accessed (e.g: due to - /// MMU protection, unhanded page fault, etc...), an appropriate non-fatal - /// error should be returned. + /// Implementations may return a number `n` that is less than `data.len()` + /// to indicate that memory starting at `start_addr + n` cannot be + /// accessed. + /// + /// Implemenations may also return an appropriate non-fatal if the requested + /// address range could not be accessed (e.g: due to MMU protection, + /// unhanded page fault, etc...). + /// + /// Implementations must guarantee that the returned number is less than or + /// equal `data.len()`. fn read_addrs( &mut self, start_addr: ::Usize, data: &mut [u8], tid: Tid, - ) -> TargetResult<(), Self>; + ) -> TargetResult; /// Write bytes to the specified address range. /// diff --git a/src/target/ext/base/singlethread.rs b/src/target/ext/base/singlethread.rs index c949886..1da1705 100644 --- a/src/target/ext/base/singlethread.rs +++ b/src/target/ext/base/singlethread.rs @@ -32,16 +32,24 @@ pub trait SingleThreadBase: Target { None } - /// Read bytes from the specified address range. + /// Read bytes from the specified address range and return the number of + /// bytes that were read. /// - /// If the requested address range could not be accessed (e.g: due to - /// MMU protection, unhanded page fault, etc...), an appropriate - /// non-fatal error should be returned. + /// Implementations may return a number `n` that is less than `data.len()` + /// to indicate that memory starting at `start_addr + n` cannot be + /// accessed. + /// + /// Implemenations may also return an appropriate non-fatal error if the + /// requested address range could not be accessed (e.g: due to MMU + /// protection, unhanded page fault, etc...). + /// + /// Implementations must guarantee that the returned number is less than or + /// equal `data.len()`. fn read_addrs( &mut self, start_addr: ::Usize, data: &mut [u8], - ) -> TargetResult<(), Self>; + ) -> TargetResult; /// Write bytes to the specified address range. /// diff --git a/src/target/mod.rs b/src/target/mod.rs index a5d912b..491264e 100644 --- a/src/target/mod.rs +++ b/src/target/mod.rs @@ -151,7 +151,7 @@ //! &mut self, //! start_addr: u32, //! data: &mut [u8], -//! ) -> TargetResult<(), Self> { todo!() } +//! ) -> TargetResult { todo!() } //! //! fn write_addrs( //! &mut self, @@ -409,7 +409,7 @@ pub trait Target { /// # &mut self, /// # start_addr: u32, /// # data: &mut [u8], - /// # ) -> TargetResult<(), Self> { todo!() } + /// # ) -> TargetResult { todo!() } /// # /// # fn write_addrs( /// # &mut self,