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
12 changes: 12 additions & 0 deletions src/common/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,15 @@ pub type Tid = core::num::NonZeroUsize;

/// Process ID
pub type Pid = core::num::NonZeroUsize;

/// Endinanness.
///
/// This is used to report target endianness to the debugger as a
/// response to certain commands.
#[derive(Clone, Copy, Debug)]
pub enum Endianness {
/// Big-endian.
Big,
/// Little-endian.
Little,
}
5 changes: 5 additions & 0 deletions src/protocol/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -366,4 +366,9 @@ commands! {
"qTfV" => _qTfV::qTfV,
"qTsV" => _qTsV::qTsV,
}

process_info {
"qHostInfo" => _qHostInfo::qHostInfo,
"qProcessInfo" => _qProcessInfo::qProcessInfo,
}
}
14 changes: 14 additions & 0 deletions src/protocol/commands/_qHostInfo.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
use super::prelude::*;

#[derive(Debug)]
pub struct qHostInfo;

impl<'a> ParseCommand<'a> for qHostInfo {
#[inline(always)]
fn from_packet(buf: PacketBuf<'a>) -> Option<Self> {
if !buf.into_body().is_empty() {
return None;
}
Some(qHostInfo)
}
}
14 changes: 14 additions & 0 deletions src/protocol/commands/_qProcessInfo.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
use super::prelude::*;

#[derive(Debug)]
pub struct qProcessInfo;

impl<'a> ParseCommand<'a> for qProcessInfo {
#[inline(always)]
fn from_packet(buf: PacketBuf<'a>) -> Option<Self> {
if !buf.into_body().is_empty() {
return None;
}
Some(qProcessInfo)
}
}
2 changes: 2 additions & 0 deletions src/stub/core_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ mod lldb_register_info;
mod memory_map;
mod monitor_cmd;
mod no_ack_mode;
mod process_info;
mod resume;
mod reverse_exec;
mod section_offsets;
Expand Down Expand Up @@ -223,6 +224,7 @@ impl<T: Target, C: Connection> GdbStubImpl<T, C> {
Command::LibrariesSvr4(cmd) => self.handle_libraries_svr4(res, target, cmd),
Command::Libraries(cmd) => self.handle_libraries(res, target, cmd),
Command::Tracepoints(cmd) => self.handle_tracepoints(res, target, cmd),
Command::ProcessInfo(cmd) => self.handle_process_info(res, target, cmd),
// in the worst case, the command could not be parsed...
Command::Unknown(cmd) => {
// HACK: if the user accidentally sends a resume command to a
Expand Down
77 changes: 77 additions & 0 deletions src/stub/core_impl/process_info.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
use super::prelude::*;
use crate::common::Endianness;
use crate::protocol::commands::ext::ProcessInfo;
use crate::protocol::ResponseWriterError;
use crate::target::ext::process_info::InfoResponse;

impl<'a> InfoResponse<'a> {
fn write_response<C: Connection>(
&self,
res: &mut ResponseWriter<'_, C>,
) -> Result<(), ResponseWriterError<C::Error>> {
match self {
InfoResponse::Pid(pid) => {
res.write_str("pid:")?;
res.write_dec(usize::from(*pid))?;
}
InfoResponse::Triple(triple) => {
res.write_str("triple:")?;
res.write_hex_buf(triple.as_bytes())?;
}
InfoResponse::Endianness(endian) => {
res.write_str("endian:")?;
res.write_str(match endian {
Endianness::Big => "big;",
Endianness::Little => "little;",
})?;
}
InfoResponse::PointerSize(p) => {
res.write_str("ptrsize:")?;
res.write_dec(*p)?;
}
}
res.write_str(";")?;
Ok(())
}
}

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

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

let mut result = Ok(());
let mut write_info = |info: &InfoResponse<'_>| {
if result.is_ok() {
if let Err(e) = info.write_response(res) {
result = Err(e);
}
}
};

let handler_status = match command {
ProcessInfo::qHostInfo(_cmd) => {
ops.host_info(&mut write_info).map_err(Error::TargetError)?;
result?;
HandlerStatus::Handled
}
ProcessInfo::qProcessInfo(_cmd) => {
ops.process_info(&mut write_info)
.map_err(Error::TargetError)?;
result?;
HandlerStatus::Handled
}
};

Ok(handler_status)
}
}
1 change: 1 addition & 0 deletions src/target/ext/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,7 @@ pub mod libraries;
pub mod lldb_register_info_override;
pub mod memory_map;
pub mod monitor_cmd;
pub mod process_info;
pub mod section_offsets;
pub mod target_description_xml_override;
pub mod thread_extra_info;
Expand Down
46 changes: 46 additions & 0 deletions src/target/ext/process_info.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
//! Provide host and process information to the debugger.
//!
//! These correspond to the `qHostInfo` and `qProcessInfo` commands.
//! They report key-value metadata such as the target triple,
//! endianness, pointer size, and process ID. We take the information
//! that we can return as responses to this commands in the
//! [`HostInfoResponse`] and [`ProcessInfoResponse`] structs,

Check failure on line 7 in src/target/ext/process_info.rs

View workflow job for this annotation

GitHub Actions / clippy + tests + docs

unresolved link to `ProcessInfoResponse`

Check failure on line 7 in src/target/ext/process_info.rs

View workflow job for this annotation

GitHub Actions / clippy + tests + docs

unresolved link to `HostInfoResponse`
//! respectively.

use crate::common::{Endianness, Pid};

/// A response key-value pair to a qProcessInfo or qHostInfo query.
///
/// A response to either of these commands consists of a list of
/// key-value pairs, each of which is represented by one instance of
/// this enum.
pub enum InfoResponse<'a> {
/// The current process PID.
Pid(Pid),
/// The target triple for the debuggee, as a string.
Triple(&'a str),
/// The target endianness.
Endianness(Endianness),
/// The pointer size.
PointerSize(usize),
}

use crate::target::Target;

/// Target Extension - Provide host and process information.
pub trait ProcessInfo: Target {
/// Write a response to `qHostInfo`.
///
/// Call `write_item` with each `InfoResponse` you wish to send.
fn host_info(&self, write_item: &mut dyn FnMut(&InfoResponse<'_>)) -> Result<(), Self::Error>;

/// Write the response to `qProcessInfo`.
///
/// Call `write_item` with each `InfoResponse` you wish to send.
fn process_info(
&self,
write_item: &mut dyn FnMut(&InfoResponse<'_>),
) -> Result<(), Self::Error>;
}

define_ext!(ProcessInfoOps, ProcessInfo);
6 changes: 6 additions & 0 deletions src/target/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -746,6 +746,12 @@ pub trait Target {
fn support_libraries(&mut self) -> Option<ext::libraries::LibrariesOps<'_, Self>> {
None
}

/// Support for host and process information (qHostInfo / qProcessInfo).
#[inline(always)]
fn support_process_info(&mut self) -> Option<ext::process_info::ProcessInfoOps<'_, Self>> {
None
}
}

macro_rules! __delegate {
Expand Down
Loading