Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support read auxv #86

Merged
merged 2 commits into from
Sep 27, 2021
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
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ Of course, most use-cases will want to support additional debugging features as
- Get target memory map
- Perform Host I/O operations
- Get target exec file
- Get target auxiliary vector

_Note:_ GDB features are implemented on an as-needed basis by `gdbstub`'s contributors. If there's a missing GDB feature that you'd like `gdbstub` to implement, please file an issue and/or open a PR!

Expand Down
12 changes: 12 additions & 0 deletions examples/armv4t/gdb/auxv.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
use gdbstub::target;
use gdbstub::target::TargetResult;

use super::copy_range_to_buf;
use crate::emu::Emu;

impl target::ext::auxv::Auxv for Emu {
fn get_auxv(&self, offset: u64, length: usize, buf: &mut [u8]) -> TargetResult<usize, Self> {
let auxv = b"\x00\x00\x00\x00\x00\x00\x00\x00";
Ok(copy_range_to_buf(auxv, offset, length, buf))
}
}
6 changes: 6 additions & 0 deletions examples/armv4t/gdb/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use crate::emu::{Emu, Event};

// Additional GDB extensions

mod auxv;
mod breakpoints;
mod catch_syscalls;
mod exec_file;
Expand Down Expand Up @@ -122,6 +123,11 @@ impl Target for Emu {
fn exec_file(&mut self) -> Option<target::ext::exec_file::ExecFileOps<Self>> {
Some(self)
}

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

impl Emu {
Expand Down
36 changes: 36 additions & 0 deletions src/gdbstub_impl/ext/auxv.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
use super::prelude::*;
use crate::protocol::commands::ext::Auxv;

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

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

let handler_status = match command {
Auxv::qXferAuxvRead(cmd) => {
let ret = ops
.get_auxv(cmd.offset, cmd.length, cmd.buf)
.handle_error()?;
if ret == 0 {
res.write_str("l")?;
} else {
res.write_str("m")?;
// TODO: add more specific error variant?
res.write_binary(cmd.buf.get(..ret).ok_or(Error::PacketBufferOverflow)?)?;
}
HandlerStatus::Handled
}
};

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

if target.auxv().is_some() {
res.write_str(";qXfer:auxv:read+")?;
}

HandlerStatus::Handled
}
Base::QStartNoAckMode(_) => {
Expand Down
1 change: 1 addition & 0 deletions src/gdbstub_impl/ext/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ mod prelude {
pub(super) use super::super::{DisconnectReason, GdbStubImpl, HandlerStatus};
}

mod auxv;
mod base;
mod breakpoints;
mod catch_syscalls;
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 @@ -579,6 +579,7 @@ impl<T: Target, C: Connection> GdbStubImpl<T, C> {
Command::MemoryMap(cmd) => self.handle_memory_map(res, target, cmd),
Command::HostIo(cmd) => self.handle_host_io(res, target, cmd),
Command::ExecFile(cmd) => self.handle_exec_file(res, target, cmd),
Command::Auxv(cmd) => self.handle_auxv(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 @@ -225,6 +225,10 @@ commands! {
"qXfer:memory-map:read" => _qXfer_memory_map::qXferMemoryMapRead<'a>,
}

auxv use 'a {
"qXfer:auxv:read" => _qXfer_auxv_read::qXferAuxvRead<'a>,
}

exec_file use 'a {
"qXfer:exec-file:read" => _qXfer_exec_file::qXferExecFileRead<'a>,
}
Expand Down
34 changes: 34 additions & 0 deletions src/protocol/commands/_qXfer_auxv_read.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
use super::prelude::*;

#[derive(Debug)]
pub struct qXferAuxvRead<'a> {
pub offset: u64,
pub length: usize,

pub buf: &'a mut [u8],
}

impl<'a> ParseCommand<'a> for qXferAuxvRead<'a> {
fn from_packet(buf: PacketBuf<'a>) -> Option<Self> {
let (buf, body_range) = buf.into_raw_buf();
let body = buf.get_mut(body_range.start..body_range.end)?;

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 length = decode_hex(body.next()?).ok()?;

drop(body);

Some(qXferAuxvRead { offset, length, buf })
}
}
2 changes: 1 addition & 1 deletion src/protocol/commands/_qXfer_exec_file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,6 @@ impl<'a> ParseCommand<'a> for qXferExecFileRead<'a> {

drop(body);

Some(qXferExecFileRead {pid, offset, length, buf})
Some(qXferExecFileRead { pid, offset, length, buf })
Copy link
Owner

Choose a reason for hiding this comment

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

fascinating... I ran cargo +nightly fmt --all -v -- --check -v, and it seems none of the files under commands are being checked for formatting! I assume this has something to do with the auto-generated nature of the modules...

I should probably file a issue upstream about this.

}
}
2 changes: 1 addition & 1 deletion src/protocol/commands/_vFile_close.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ impl<'a> ParseCommand<'a> for vFileClose {
match body {
[b':', body @ ..] => {
let fd = decode_hex(body).ok()?;
Some(vFileClose{fd})
Some(vFileClose { fd })
},
_ => None,
}
Expand Down
2 changes: 1 addition & 1 deletion src/protocol/commands/_vFile_fstat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ impl<'a> ParseCommand<'a> for vFileFstat {
match body {
[b':', body @ ..] => {
let fd = decode_hex(body).ok()?;
Some(vFileFstat{fd})
Some(vFileFstat { fd })
},
_ => None,
}
Expand Down
2 changes: 1 addition & 1 deletion src/protocol/commands/_vFile_open.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ impl<'a> ParseCommand<'a> for vFileOpen<'a> {
let filename = decode_hex_buf(body.next()?).ok()?;
let flags = HostIoOpenFlags::from_bits(decode_hex(body.next()?).ok()?)?;
let mode = HostIoOpenMode::from_bits(decode_hex(body.next()?).ok()?)?;
Some(vFileOpen{filename, flags, mode})
Some(vFileOpen { filename, flags, mode })
},
_ => None,
}
Expand Down
2 changes: 1 addition & 1 deletion src/protocol/commands/_vFile_pread.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ impl<'a> ParseCommand<'a> for vFilePread<'a> {

drop(body);

Some(vFilePread{fd, count, offset, buf})
Some(vFilePread { fd, count, offset, buf })
},
_ => None,
}
Expand Down
2 changes: 1 addition & 1 deletion src/protocol/commands/_vFile_pwrite.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ impl<'a> ParseCommand<'a> for vFilePwrite<'a> {
let fd = decode_hex(body.next()?).ok()?;
let offset = decode_hex_buf(body.next()?).ok()?;
let data = decode_bin_buf(body.next()?).ok()?;
Some(vFilePwrite{fd, offset, data})
Some(vFilePwrite { fd, offset, data })
},
_ => None,
}
Expand Down
2 changes: 1 addition & 1 deletion src/protocol/commands/_vFile_readlink.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ impl<'a> ParseCommand<'a> for vFileReadlink<'a> {
match body {
[b':', body @ ..] => {
let filename = decode_hex_buf(body).ok()?;
Some(vFileReadlink{filename, buf})
Some(vFileReadlink { filename, buf })
},
_ => None,
}
Expand Down
2 changes: 1 addition & 1 deletion src/protocol/commands/_vFile_setfs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ impl<'a> ParseCommand<'a> for vFileSetfs {
None => FsKind::Stub,
Some(pid) => FsKind::Pid(pid),
};
Some(vFileSetfs{fs})
Some(vFileSetfs { fs })
},
_ => None,
}
Expand Down
2 changes: 1 addition & 1 deletion src/protocol/commands/_vFile_unlink.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ impl<'a> ParseCommand<'a> for vFileUnlink<'a> {
match body {
[b':', body @ ..] => {
let filename = decode_hex_buf(body).ok()?;
Some(vFileUnlink{filename})
Some(vFileUnlink { filename })
},
_ => None,
}
Expand Down
16 changes: 16 additions & 0 deletions src/target/ext/auxv.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
//! Access the target’s auxiliary vector.
use crate::target::{Target, TargetResult};

/// Target Extension - Access the target’s auxiliary vector.
pub trait Auxv: Target {
/// Get auxiliary vector from the target.
///
/// Return the number of bytes written into `buf` (which may be less than
/// `length`).
///
/// If `offset` is greater than the length of the underlying data, return
/// `Ok(0)`.
fn get_auxv(&self, offset: u64, length: usize, buf: &mut [u8]) -> TargetResult<usize, Self>;
}

define_ext!(AuxvOps, Auxv);
8 changes: 7 additions & 1 deletion src/target/ext/memory_map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,17 @@ use crate::target::{Target, TargetResult};

/// Target Extension - Provide a target memory map.
pub trait MemoryMap: Target {
/// Return the target memory map XML file.
/// Get memory map XML file from the target.
///
/// See the [GDB Documentation] for a description of the format.
///
/// [GDB Documentation]: https://sourceware.org/gdb/onlinedocs/gdb/Memory-Map-Format.html
///
/// Return the number of bytes written into `buf` (which may be less than
/// `length`).
///
/// If `offset` is greater than the length of the underlying data, return
/// `Ok(0)`.
fn memory_map_xml(
&self,
offset: u64,
Expand Down
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 auxv;
pub mod base;
pub mod breakpoints;
pub mod catch_syscalls;
Expand Down
6 changes: 6 additions & 0 deletions src/target/ext/target_description_xml_override.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@ pub trait TargetDescriptionXmlOverride: Target {
/// Refer to the
/// [target_description_xml](crate::arch::Arch::target_description_xml)
/// docs for more info.
///
/// Return the number of bytes written into `buf` (which may be less than
/// `length`).
///
/// If `offset` is greater than the length of the underlying data, return
/// `Ok(0)`.
fn target_description_xml(
&self,
offset: u64,
Expand Down
10 changes: 10 additions & 0 deletions src/target/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -369,6 +369,11 @@ pub trait Target {
fn exec_file(&mut self) -> Option<ext::exec_file::ExecFileOps<Self>> {
None
}

/// Provide auxv
fn auxv(&mut self) -> Option<ext::auxv::AuxvOps<Self>> {
None
}
}

macro_rules! impl_dyn_target {
Expand Down Expand Up @@ -420,6 +425,11 @@ macro_rules! impl_dyn_target {
(**self).memory_map()
}

#[inline(always)]
fn auxv(&mut self) -> Option<ext::auxv::AuxvOps<Self>> {
(**self).auxv()
}

#[inline(always)]
fn section_offsets(&mut self) -> Option<ext::section_offsets::SectionOffsetsOps<Self>> {
(**self).section_offsets()
Expand Down