Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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
28 changes: 28 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 Expand Up @@ -143,6 +147,30 @@ impl<T: Target, C: Connection> GdbStubImpl<T, C> {
}
HandlerStatus::Handled
}
Base::qXferMemoryMapRead(cmd) => {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You'll have to move this hander out into a separate ext mod.

(meta): once this PR is merged, I'll pop-open a tracking task for myself to de-dupe the qXfer logic between the two packets. some copy-paste is fine for now, but I know that there'll be more of these packets coming down the line, and there'll need to be some way to keep the code DRY.

match target.memory_map().map(|ops| ops.memory_map_xml()) {
Some(xml) => {
let xml = 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)])?
}
}
None => return Err(Error::PacketUnexpected),
}
// If the target hasn't provided a memory map, then the initial response to
// "qSupported" wouldn't have included "qXfer:features:memory-map", and gdb wouldn't
// send this packet unless it was explicitly marked as supported.
HandlerStatus::Handled
}

// -------------------- "Core" Functionality -------------------- //
// TODO: Improve the '?' response based on last-sent stop reason.
Expand Down
1 change: 1 addition & 0 deletions src/protocol/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,7 @@ commands! {
"qsThreadInfo" => _qsThreadInfo::qsThreadInfo,
"qSupported" => _qSupported::qSupported<'a>,
"qXfer:features:read" => _qXfer_features_read::qXferFeaturesRead,
"qXfer:memory-map:read" => _qXfer_memory_map::qXferMemoryMapRead,
"s" => _s::s<'a>,
"T" => _t_upcase::T,
"vCont" => _vCont::vCont<'a>,
Expand Down
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) -> String;
}

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