Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 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,
}
8 changes: 8 additions & 0 deletions src/protocol/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -366,4 +366,12 @@ commands! {
"qTfV" => _qTfV::qTfV,
"qTsV" => _qTsV::qTsV,
}

host_info {
"qHostInfo" => _qHostInfo::qHostInfo,
}

process_info {
"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)
}
}
5 changes: 5 additions & 0 deletions src/stub/core_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,15 @@ mod catch_syscalls;
mod exec_file;
mod extended_mode;
mod flash;
mod host_info;
mod host_io;
mod info_response;
mod libraries;
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 +226,8 @@ 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::HostInfo(cmd) => self.handle_host_info(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
39 changes: 39 additions & 0 deletions src/stub/core_impl/host_info.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
use super::prelude::*;
use crate::protocol::commands::ext::HostInfo;

use super::info_response::InfoResponse;
use crate::target::ext::host_info::InfoResponse as HostInfoResponse;

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

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

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

match command {
HostInfo::qHostInfo(_cmd) => {
ops.host_info(&mut write_info).map_err(Error::TargetError)?;
result?;
}
};

Ok(HandlerStatus::Handled)
}
}
65 changes: 65 additions & 0 deletions src/stub/core_impl/info_response.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
use super::prelude::*;
use crate::common::Endianness;
use crate::common::Pid;
use crate::protocol::ResponseWriterError;

pub(crate) enum InfoResponse<'a> {
Pid(Pid),
Triple(&'a str),
Endianness(Endianness),
PointerSize(usize),
}

impl<'a> InfoResponse<'a> {
pub(crate) 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<'a> From<&crate::target::ext::host_info::InfoResponse<'a>> for InfoResponse<'a> {
fn from(resp: &crate::target::ext::host_info::InfoResponse<'a>) -> Self {
use crate::target::ext::host_info::InfoResponse as R;
match *resp {
R::Triple(s) => InfoResponse::Triple(s),
R::Endianness(e) => InfoResponse::Endianness(e),
R::PointerSize(p) => InfoResponse::PointerSize(p),
}
}
}

impl<'a> From<&crate::target::ext::process_info::InfoResponse<'a>> for InfoResponse<'a> {
fn from(resp: &crate::target::ext::process_info::InfoResponse<'a>) -> Self {
use crate::target::ext::process_info::InfoResponse as R;
match *resp {
R::Pid(pid) => InfoResponse::Pid(pid),
R::Triple(s) => InfoResponse::Triple(s),
R::Endianness(e) => InfoResponse::Endianness(e),
R::PointerSize(p) => InfoResponse::PointerSize(p),
}
}
}
40 changes: 40 additions & 0 deletions src/stub/core_impl/process_info.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
use super::prelude::*;
use crate::protocol::commands::ext::ProcessInfo;

use super::info_response::InfoResponse;
use crate::target::ext::process_info::InfoResponse as ProcessInfoResponse;

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: &ProcessInfoResponse<'_>| {
if result.is_ok() {
if let Err(e) = InfoResponse::from(info).write_response(res) {
result = Err(e);
}
}
};

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

Ok(HandlerStatus::Handled)
}
}
42 changes: 42 additions & 0 deletions src/target/ext/host_info.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
//! Provide host information to the debugger.
//!
//! This allows for reporting key-value metadata, for example the
//! target triple, endianness, and pointer size.
//!
//! This corresponds to the `qHostInfo` command in the LLDB
//! extensions.

use crate::common::Endianness;
use crate::target::Target;

/// A response key-value pair to a qHostInfo query.
///
/// A response consists of a list of key-value pairs, each of which is
/// represented by one instance of this enum.
///
/// The allowed responses are documented in the [LLDB extension
/// documentation]. Not all supported responses are currently
/// represented in this enum. If you need another one, please feel
/// free to send a PR!
///
/// [LLDB extension documentation]: https://lldb.llvm.org/resources/lldbplatformpackets.html
#[derive(Clone, Copy)]
#[non_exhaustive]
pub enum InfoResponse<'a> {
/// The target triple for the debuggee, as a string.
Triple(&'a str),
/// The target endianness.
Endianness(Endianness),
/// The pointer size.
PointerSize(usize),
}

/// Target Extension - Provide host information.
pub trait HostInfo: Target {
/// Write a response to a host-info query (LLDB extension).
Copy link
Owner

Choose a reason for hiding this comment

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

Suggested change
/// Write a response to a host-info query (LLDB extension).
/// Write a response to a host-info query.

(since it'd be present on the trait itself)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done!

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

define_ext!(HostInfoOps, HostInfo);
2 changes: 2 additions & 0 deletions src/target/ext/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -265,11 +265,13 @@ pub mod catch_syscalls;
pub mod exec_file;
pub mod extended_mode;
pub mod flash;
pub mod host_info;
pub mod host_io;
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
48 changes: 48 additions & 0 deletions src/target/ext/process_info.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
//! Provide process information to the debugger.
//!
//! This allows for reporting key-value metadata, for example the
//! current PID, target triple, endianness, and pointer size.
//!
//! This corresponds to the `qHostInfo` command in the LLDB
//! extensions.

use crate::common::Endianness;
use crate::common::Pid;
use crate::target::Target;

/// A response key-value pair to a qProcessInfo query.
///
/// A response consists of a list of key-value pairs, each of which is
/// represented by one instance of this enum.
///
/// The allowed responses are documented in the [LLDB extension
/// documentation]. Not all supported responses are currently
/// represented in this enum. If you need another one, please feel
/// free to send a PR!
///
/// [LLDB extension documentation]: https://lldb.llvm.org/resources/lldbplatformpackets.html
#[derive(Clone, Copy)]
#[non_exhaustive]
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),
}

/// Target Extension - Provide process information.
pub trait ProcessInfo: Target {
/// Write the response to process-info query (LLDB extension).
///
/// 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);
12 changes: 12 additions & 0 deletions src/target/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -746,6 +746,18 @@ pub trait Target {
fn support_libraries(&mut self) -> Option<ext::libraries::LibrariesOps<'_, Self>> {
None
}

/// Support for host information (qHostInfo).
#[inline(always)]
fn support_host_info(&mut self) -> Option<ext::host_info::HostInfoOps<'_, Self>> {
None
}

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

macro_rules! __delegate {
Expand Down
Loading