Skip to content

Commit b9ed1c6

Browse files
committed
Support read exec-file
1 parent 9227dfd commit b9ed1c6

16 files changed

Lines changed: 162 additions & 8 deletions

File tree

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ Of course, most use-cases will want to support additional debugging features as
7777
- Extend the GDB protocol with custom debug commands using GDB's `monitor` command
7878
- Get target memory map
7979
- Perform Host I/O operations
80+
- Get target exec file
8081

8182
_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!
8283

examples/armv4t/gdb/exec_file.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
use gdbstub::common::Pid;
2+
use gdbstub::target;
3+
4+
use crate::emu::Emu;
5+
6+
impl target::ext::exec_file::ExecFile for Emu {
7+
fn get_exec_file(&self, _pid: Option<Pid>) -> &[u8] {
8+
b"/test.elf"
9+
}
10+
}

examples/armv4t/gdb/host_io.rs

Lines changed: 52 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use std::io::{Read, Seek, Write};
22

3+
use crate::TEST_PROGRAM_ELF;
34
use gdbstub::target;
45
use gdbstub::target::ext::host_io::{
56
FsKind, HostIoErrno, HostIoError, HostIoOpenFlags, HostIoOpenMode, HostIoOutput, HostIoResult,
@@ -8,6 +9,8 @@ use gdbstub::target::ext::host_io::{
89

910
use crate::emu::Emu;
1011

12+
const FD_RESERVED: u32 = 1;
13+
1114
impl target::ext::host_io::HostIo for Emu {
1215
#[inline(always)]
1316
fn enable_open(&mut self) -> Option<target::ext::host_io::HostIoOpenOps<Self>> {
@@ -61,6 +64,10 @@ impl target::ext::host_io::HostIoOpen for Emu {
6164
return Err(HostIoError::Errno(HostIoErrno::ENOENT));
6265
}
6366

67+
if filename == b"/test.elf" {
68+
return Ok(0);
69+
}
70+
6471
let path =
6572
std::str::from_utf8(filename).map_err(|_| HostIoError::Errno(HostIoErrno::ENOENT))?;
6673

@@ -95,13 +102,17 @@ impl target::ext::host_io::HostIoOpen for Emu {
95102
}
96103
};
97104

98-
Ok(n as u32)
105+
Ok(n as u32 + FD_RESERVED)
99106
}
100107
}
101108

102109
impl target::ext::host_io::HostIoClose for Emu {
103110
fn close(&mut self, fd: u32) -> HostIoResult<(), Self> {
104-
let file = match self.files.get_mut(fd as usize) {
111+
if fd < FD_RESERVED {
112+
return Ok(());
113+
}
114+
115+
let file = match self.files.get_mut((fd - FD_RESERVED) as usize) {
105116
Some(file) => file,
106117
_ => return Err(HostIoError::Errno(HostIoErrno::EBADF)),
107118
};
@@ -122,7 +133,18 @@ impl target::ext::host_io::HostIoPread for Emu {
122133
offset: u32,
123134
output: HostIoOutput<'a>,
124135
) -> HostIoResult<HostIoToken<'a>, Self> {
125-
let file = match self.files.get_mut(fd as usize) {
136+
if fd < FD_RESERVED {
137+
if fd == 0 {
138+
let len = TEST_PROGRAM_ELF.len();
139+
return Ok(output.write(
140+
&TEST_PROGRAM_ELF[len.min(offset as usize)..len.min((offset + count) as usize)],
141+
));
142+
} else {
143+
return Err(HostIoError::Errno(HostIoErrno::EBADF));
144+
}
145+
}
146+
147+
let file = match self.files.get_mut((fd - FD_RESERVED) as usize) {
126148
Some(Some(file)) => file,
127149
_ => return Err(HostIoError::Errno(HostIoErrno::EBADF)),
128150
};
@@ -136,7 +158,11 @@ impl target::ext::host_io::HostIoPread for Emu {
136158

137159
impl target::ext::host_io::HostIoPwrite for Emu {
138160
fn pwrite(&mut self, fd: u32, offset: u32, data: &[u8]) -> HostIoResult<u32, Self> {
139-
let file = match self.files.get_mut(fd as usize) {
161+
if fd < FD_RESERVED {
162+
return Err(HostIoError::Errno(HostIoErrno::EACCES));
163+
}
164+
165+
let file = match self.files.get_mut((fd - FD_RESERVED) as usize) {
140166
Some(Some(file)) => file,
141167
_ => return Err(HostIoError::Errno(HostIoErrno::EBADF)),
142168
};
@@ -149,7 +175,28 @@ impl target::ext::host_io::HostIoPwrite for Emu {
149175

150176
impl target::ext::host_io::HostIoFstat for Emu {
151177
fn fstat(&mut self, fd: u32) -> HostIoResult<HostIoStat, Self> {
152-
let metadata = match self.files.get(fd as usize) {
178+
if fd < FD_RESERVED {
179+
if fd == 0 {
180+
return Ok(HostIoStat {
181+
st_dev: 0,
182+
st_ino: 0,
183+
st_mode: HostIoOpenMode::empty(),
184+
st_nlink: 0,
185+
st_uid: 0,
186+
st_gid: 0,
187+
st_rdev: 0,
188+
st_size: TEST_PROGRAM_ELF.len() as u64,
189+
st_blksize: 0,
190+
st_blocks: 0,
191+
st_atime: 0,
192+
st_mtime: 0,
193+
st_ctime: 0,
194+
});
195+
} else {
196+
return Err(HostIoError::Errno(HostIoErrno::EBADF));
197+
}
198+
}
199+
let metadata = match self.files.get((fd - FD_RESERVED) as usize) {
153200
Some(Some(file)) => file.metadata()?,
154201
_ => return Err(HostIoError::Errno(HostIoErrno::EBADF)),
155202
};

examples/armv4t/gdb/mod.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ use crate::emu::{Emu, Event};
1616

1717
mod breakpoints;
1818
mod catch_syscalls;
19+
mod exec_file;
1920
mod extended_mode;
2021
mod host_io;
2122
mod memory_map;
@@ -100,6 +101,11 @@ impl Target for Emu {
100101
fn host_io(&mut self) -> Option<target::ext::host_io::HostIoOps<Self>> {
101102
Some(self)
102103
}
104+
105+
#[inline(always)]
106+
fn exec_file(&mut self) -> Option<target::ext::exec_file::ExecFileOps<Self>> {
107+
Some(self)
108+
}
103109
}
104110

105111
impl Emu {

examples/armv4t/main.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use gdbstub::{target::Target, ConnectionExt, DisconnectReason, GdbStub};
99

1010
pub type DynResult<T> = Result<T, Box<dyn std::error::Error>>;
1111

12-
static TEST_PROGRAM_ELF: &[u8] = include_bytes!("test_bin/test.elf");
12+
pub static TEST_PROGRAM_ELF: &[u8] = include_bytes!("test_bin/test.elf");
1313

1414
mod emu;
1515
mod gdb;

examples/armv4t/test_bin/.gdbinit

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1 @@
1-
file test.elf
21
target extended-remote :9001

src/gdbstub_impl/ext/base.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,10 @@ impl<T: Target, C: Connection> GdbStubImpl<T, C> {
115115
res.write_str(";qXfer:memory-map:read+")?;
116116
}
117117

118+
if target.exec_file().is_some() {
119+
res.write_str(";qXfer:exec-file:read+")?;
120+
}
121+
118122
HandlerStatus::Handled
119123
}
120124
Base::QStartNoAckMode(_) => {

src/gdbstub_impl/ext/exec_file.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
use super::prelude::*;
2+
use crate::protocol::commands::ext::ExecFile;
3+
4+
impl<T: Target, C: Connection> GdbStubImpl<T, C> {
5+
pub(crate) fn handle_exec_file(
6+
&mut self,
7+
res: &mut ResponseWriter<C>,
8+
target: &mut T,
9+
command: ExecFile,
10+
) -> Result<HandlerStatus, Error<T::Error, C::Error>> {
11+
let ops = match target.exec_file() {
12+
Some(ops) => ops,
13+
None => return Ok(HandlerStatus::Handled),
14+
};
15+
16+
crate::__dead_code_marker!("exec_file", "impl");
17+
18+
let handler_status = match command {
19+
ExecFile::qXferExecFileRead(cmd) => {
20+
let filename = ops.get_exec_file(cmd.pid);
21+
res.write_binary_range(filename, cmd.offset, cmd.len)?;
22+
HandlerStatus::Handled
23+
}
24+
};
25+
26+
Ok(handler_status)
27+
}
28+
}

src/gdbstub_impl/ext/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ mod prelude {
1414
mod base;
1515
mod breakpoints;
1616
mod catch_syscalls;
17+
mod exec_file;
1718
mod extended_mode;
1819
mod host_io;
1920
mod memory_map;

src/gdbstub_impl/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -578,6 +578,7 @@ impl<T: Target, C: Connection> GdbStubImpl<T, C> {
578578
Command::ReverseStep(cmd) => self.handle_reverse_step(res, target, cmd),
579579
Command::MemoryMap(cmd) => self.handle_memory_map(res, target, cmd),
580580
Command::HostIo(cmd) => self.handle_host_io(res, target, cmd),
581+
Command::ExecFile(cmd) => self.handle_exec_file(res, target, cmd),
581582
}
582583
}
583584
}

0 commit comments

Comments
 (0)