Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions examples/armv4t/gdb/memory_map.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
use gdbstub::target;

use crate::emu::Emu;

impl target::ext::memory_map::MemoryMap for Emu {
fn memory_map_xml(&self) -> &str {
// Sample memory map, with RAM coverying the whole
// memory space.
r#"<?xml version="1.0"?>
<!DOCTYPE memory-map
PUBLIC "+//IDN gnu.org//DTD GDB Memory Map V1.0//EN"
"http://sourceware.org/gdb/gdb-memory-map.dtd">
<memory-map>
<memory type="ram" start="0x0" length="0x100000000"/>
</memory-map>"#
}
}
6 changes: 6 additions & 0 deletions examples/armv4t/gdb/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ use crate::emu::{Emu, Event};

mod breakpoints;
mod extended_mode;
mod memory_map;
mod monitor_cmd;
mod section_offsets;
mod target_description_xml_override;
Expand Down Expand Up @@ -73,6 +74,11 @@ impl Target for Emu {
{
Some(self)
}

#[inline(always)]
fn memory_map(&mut self) -> Option<target::ext::memory_map::MemoryMapOps<Self>> {
Some(self)
}
}

impl Emu {
Expand Down
4 changes: 4 additions & 0 deletions src/gdbstub_impl/ext/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,10 @@ impl<T: Target, C: Connection> GdbStubImpl<T, C> {
res.write_str(";qXfer:features:read+")?;
}

if target.memory_map().is_some() {
res.write_str(";qXfer:memory-map:read+")?;
}

HandlerStatus::Handled
}
Base::QStartNoAckMode(_) => {
Expand Down
40 changes: 40 additions & 0 deletions src/gdbstub_impl/ext/memory_map.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
use super::prelude::*;
use crate::protocol::commands::ext::MemoryMap;

impl<T: Target, C: Connection> GdbStubImpl<T, C> {
pub(crate) fn handle_memory_map(
&mut self,
res: &mut ResponseWriter<C>,
target: &mut T,
command: MemoryMap,
) -> Result<HandlerStatus, Error<T::Error, C::Error>> {
let ops = match target.memory_map() {
Some(ops) => ops,
None => return Ok(HandlerStatus::Handled),
};

crate::__dead_code_marker!("memory_map", "impl");

let handler_status = match command {
MemoryMap::qXferMemoryMapRead(cmd) => {
let xml = ops.memory_map_xml().trim();
if cmd.offset >= xml.len() {
// no more data
res.write_str("l")?;
} else if cmd.offset + cmd.len >= xml.len() {
// last little bit of data
res.write_str("l")?;
res.write_binary(&xml.as_bytes()[cmd.offset..])?
} else {
// still more data
res.write_str("m")?;
res.write_binary(&xml.as_bytes()[cmd.offset..(cmd.offset + cmd.len)])?
}

HandlerStatus::Handled
}
};

Ok(handler_status)
}
}
1 change: 1 addition & 0 deletions src/gdbstub_impl/ext/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ mod prelude {
mod base;
mod breakpoints;
mod extended_mode;
mod memory_map;
mod monitor_cmd;
mod reverse_exec;
mod section_offsets;
Expand Down
1 change: 1 addition & 0 deletions src/gdbstub_impl/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,7 @@ impl<T: Target, C: Connection> GdbStubImpl<T, C> {
Command::SectionOffsets(cmd) => self.handle_section_offsets(res, target, cmd),
Command::ReverseCont(cmd) => self.handle_reverse_cont(res, target, cmd),
Command::ReverseStep(cmd) => self.handle_reverse_step(res, target, cmd),
Command::MemoryMap(cmd) => self.handle_memory_map(res, target, cmd),
}
}
}
4 changes: 4 additions & 0 deletions src/protocol/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -216,4 +216,8 @@ commands! {
reverse_step {
"bs" => _bs::bs,
}

memory_map {
"qXfer:memory-map:read" => _qXfer_memory_map::qXferMemoryMapRead,
}
}
29 changes: 29 additions & 0 deletions src/protocol/commands/_qXfer_memory_map.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
use super::prelude::*;

#[derive(Debug)]
pub struct qXferMemoryMapRead {
pub offset: usize,
pub len: usize,
}

impl<'a> ParseCommand<'a> for qXferMemoryMapRead {
fn from_packet(buf: PacketBuf<'a>) -> Option<Self> {
let body = buf.into_body();

if body.is_empty() {
return None;
}

let mut body = body.split(|b| *b == b':').skip(1);
let annex = body.next()?;
if annex != b"" {
return None;
}

let mut body = body.next()?.split(|b| *b == b',');
let offset = decode_hex(body.next()?).ok()?;
let len = decode_hex(body.next()?).ok()?;

Some(qXferMemoryMapRead { offset, len })
}
}
14 changes: 14 additions & 0 deletions src/target/ext/memory_map.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
//! Provide a memory map for the target.
use crate::target::Target;

/// Target Extension - Provide a target memory map.
pub trait MemoryMap: Target {
/// Return the target memory map XML file.
///
/// See the [GDB Documentation] for a description of the format.
///
/// [GDB Documentation]: https://sourceware.org/gdb/onlinedocs/gdb/Memory-Map-Format.html
fn memory_map_xml(&self) -> &str;
}

define_ext!(MemoryMapOps, MemoryMap);
1 change: 1 addition & 0 deletions src/target/ext/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,7 @@ macro_rules! define_ext {
pub mod base;
pub mod breakpoints;
pub mod extended_mode;
pub mod memory_map;
pub mod monitor_cmd;
pub mod section_offsets;
pub mod target_description_xml_override;
6 changes: 6 additions & 0 deletions src/target/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,12 @@ pub trait Target {
) -> Option<ext::target_description_xml_override::TargetDescriptionXmlOverrideOps<Self>> {
None
}

/// Provide a target memory map.
#[inline(always)]
fn memory_map(&mut self) -> Option<ext::memory_map::MemoryMapOps<Self>> {
None
}
}

macro_rules! impl_dyn_target {
Expand Down