Skip to content

Commit 74a8afd

Browse files
committed
Store files in Vec
1 parent 72b9ce2 commit 74a8afd

File tree

5 files changed

+89
-88
lines changed

5 files changed

+89
-88
lines changed

examples/armv4t/emu.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ use crate::mem_sniffer::{AccessKind, MemSniffer};
44
use crate::DynResult;
55

66
const HLE_RETURN_ADDR: u32 = 0x12345678;
7-
pub const FD_MAX: u32 = 256;
87

98
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
109
pub enum Event {
@@ -26,12 +25,11 @@ pub struct Emu {
2625

2726
pub(crate) watchpoints: Vec<u32>,
2827
pub(crate) breakpoints: Vec<u32>,
29-
pub(crate) files: [Option<std::fs::File>; FD_MAX as usize],
28+
pub(crate) files: Vec<Option<std::fs::File>>,
3029
}
3130

3231
impl Emu {
3332
pub fn new(program_elf: &[u8]) -> DynResult<Emu> {
34-
const FILE_INIT: Option<std::fs::File> = None;
3533
// set up emulated system
3634
let mut cpu = Cpu::new();
3735
let mut mem = ExampleMem::new();
@@ -75,7 +73,7 @@ impl Emu {
7573

7674
watchpoints: Vec::new(),
7775
breakpoints: Vec::new(),
78-
files: [FILE_INIT; FD_MAX as usize],
76+
files: Vec::new(),
7977
})
8078
}
8179

examples/armv4t/gdb/host_io.rs

Lines changed: 51 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
11
use gdbstub::target;
2-
use std::io::{Read, Seek, Write};
3-
4-
use crate::emu::{Emu, FD_MAX};
5-
62
use gdbstub::target::ext::host_io::{
73
FsKind, HostIoErrno, HostIoError, HostIoOpenFlags, HostIoOpenMode, HostIoOutput, HostIoResult,
84
HostIoStat, HostIoToken,
95
};
6+
use std::io::{Read, Seek, Write};
7+
8+
use crate::emu::Emu;
109

1110
impl target::ext::host_io::HostIo for Emu {
1211
#[inline(always)]
@@ -52,10 +51,12 @@ impl target::ext::host_io::HostIoOpen for Emu {
5251
flags: HostIoOpenFlags,
5352
_mode: HostIoOpenMode,
5453
) -> HostIoResult<u32, Self> {
55-
let path = match std::str::from_utf8(filename) {
56-
Ok(v) => v,
57-
Err(_) => return Err(HostIoError::Errno(HostIoErrno::ENOENT)),
58-
};
54+
if filename.starts_with(b"/proc") {
55+
return Err(HostIoError::Errno(HostIoErrno::ENOENT));
56+
}
57+
58+
let path =
59+
std::str::from_utf8(filename).map_err(|_| HostIoError::Errno(HostIoErrno::ENOENT))?;
5960

6061
let mut read = false;
6162
let mut write = false;
@@ -77,27 +78,32 @@ impl target::ext::host_io::HostIoOpen for Emu {
7778
.create_new(flags.contains(HostIoOpenFlags::O_EXCL))
7879
.open(path)?;
7980

80-
let n = 0;
81-
for n in 0..FD_MAX {
82-
if self.files[n as usize].is_none() {
83-
break;
81+
let n = match self.files.iter_mut().enumerate().find(|(_, f)| f.is_none()) {
82+
Some((n, free_file)) => {
83+
*free_file = Some(file);
84+
n
8485
}
85-
}
86-
if n == FD_MAX {
87-
return Err(HostIoError::Errno(HostIoErrno::ENFILE));
88-
}
86+
None => {
87+
self.files.push(Some(file));
88+
self.files.len() - 1
89+
}
90+
};
8991

90-
self.files[n as usize] = Some(file);
91-
Ok(n)
92+
Ok(n as u32)
9293
}
9394
}
9495

9596
impl target::ext::host_io::HostIoClose for Emu {
9697
fn close(&mut self, fd: u32) -> HostIoResult<(), Self> {
97-
if fd < FD_MAX {
98-
self.files[fd as usize]
99-
.take()
100-
.ok_or(HostIoError::Errno(HostIoErrno::EBADF))?;
98+
let fd: usize = fd as usize;
99+
if fd < self.files.len() {
100+
if fd == self.files.len() - 1 {
101+
self.files.pop();
102+
} else {
103+
self.files[fd]
104+
.take()
105+
.ok_or(HostIoError::Errno(HostIoErrno::EBADF))?;
106+
}
101107
Ok(())
102108
} else {
103109
Err(HostIoError::Errno(HostIoErrno::EBADF))
@@ -113,8 +119,9 @@ impl target::ext::host_io::HostIoPread for Emu {
113119
offset: u32,
114120
output: HostIoOutput<'a>,
115121
) -> HostIoResult<HostIoToken<'a>, Self> {
116-
if fd < FD_MAX {
117-
if let Some(ref mut file) = self.files[fd as usize] {
122+
let fd: usize = fd as usize;
123+
if fd < self.files.len() {
124+
if let Some(ref mut file) = self.files[fd] {
118125
let mut buffer = vec![0; count as usize];
119126
file.seek(std::io::SeekFrom::Start(offset as u64))?;
120127
let n = file.read(&mut buffer)?;
@@ -130,8 +137,9 @@ impl target::ext::host_io::HostIoPread for Emu {
130137

131138
impl target::ext::host_io::HostIoPwrite for Emu {
132139
fn pwrite(&mut self, fd: u32, offset: u32, data: &[u8]) -> HostIoResult<u32, Self> {
133-
if fd < FD_MAX {
134-
if let Some(ref mut file) = self.files[fd as usize] {
140+
let fd: usize = fd as usize;
141+
if fd < self.files.len() {
142+
if let Some(ref mut file) = self.files[fd] {
135143
file.seek(std::io::SeekFrom::Start(offset as u64))?;
136144
let n = file.write(data)?;
137145
Ok(n as u32)
@@ -146,27 +154,22 @@ impl target::ext::host_io::HostIoPwrite for Emu {
146154

147155
impl target::ext::host_io::HostIoFstat for Emu {
148156
fn fstat(&mut self, fd: u32) -> HostIoResult<HostIoStat, Self> {
149-
if fd < FD_MAX {
150-
if let Some(ref mut file) = self.files[fd as usize] {
157+
let fd: usize = fd as usize;
158+
if fd < self.files.len() {
159+
if let Some(ref mut file) = self.files[fd] {
151160
let metadata = file.metadata()?;
152-
let atime = metadata
153-
.accessed()
154-
.map_err(|_| HostIoError::Errno(HostIoErrno::EACCES))?
155-
.duration_since(std::time::SystemTime::UNIX_EPOCH)
156-
.map_err(|_| HostIoError::Errno(HostIoErrno::EACCES))?
157-
.as_secs() as u32;
158-
let mtime = metadata
159-
.modified()
160-
.map_err(|_| HostIoError::Errno(HostIoErrno::EACCES))?
161-
.duration_since(std::time::SystemTime::UNIX_EPOCH)
162-
.map_err(|_| HostIoError::Errno(HostIoErrno::EACCES))?
163-
.as_secs() as u32;
164-
let ctime = metadata
165-
.created()
166-
.map_err(|_| HostIoError::Errno(HostIoErrno::EACCES))?
167-
.duration_since(std::time::SystemTime::UNIX_EPOCH)
168-
.map_err(|_| HostIoError::Errno(HostIoErrno::EACCES))?
169-
.as_secs() as u32;
161+
macro_rules! time_to_secs {
162+
($time:expr) => {
163+
$time
164+
.map_err(|_| HostIoError::Errno(HostIoErrno::EACCES))?
165+
.duration_since(std::time::SystemTime::UNIX_EPOCH)
166+
.map_err(|_| HostIoError::Errno(HostIoErrno::EACCES))?
167+
.as_secs() as u32
168+
};
169+
}
170+
let atime = time_to_secs!(metadata.accessed());
171+
let mtime = time_to_secs!(metadata.modified());
172+
let ctime = time_to_secs!(metadata.created());
170173
Ok(HostIoStat {
171174
st_dev: 0,
172175
st_ino: 0,
@@ -214,6 +217,8 @@ impl target::ext::host_io::HostIoReadlink for Emu {
214217
} else if filename == b"/proc/1/cwd" {
215218
// Support `info proc cwd` command
216219
return Ok(output.write(b"/"));
220+
} else if filename.starts_with(b"/proc") {
221+
return Err(HostIoError::Errno(HostIoErrno::ENOENT));
217222
}
218223

219224
let path = match std::str::from_utf8(filename) {

src/gdbstub_impl/ext/host_io.rs

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use super::prelude::*;
2-
use crate::arch::Arch;
32
use crate::protocol::commands::ext::HostIo;
3+
4+
use crate::arch::Arch;
45
use crate::target::ext::host_io::{HostIoError, HostIoOutput, HostIoStat};
56
use crate::GdbStubError;
67

@@ -99,19 +100,19 @@ impl<T: Target, C: Connection> GdbStubImpl<T, C> {
99100
res.write_str("F")?;
100101
res.write_num(size)?;
101102
res.write_str(";")?;
102-
res.write_binary(&stat.st_dev.to_le_bytes())?;
103-
res.write_binary(&stat.st_ino.to_le_bytes())?;
104-
res.write_binary(&(stat.st_mode.bits()).to_le_bytes())?;
105-
res.write_binary(&stat.st_nlink.to_le_bytes())?;
106-
res.write_binary(&stat.st_uid.to_le_bytes())?;
107-
res.write_binary(&stat.st_gid.to_le_bytes())?;
108-
res.write_binary(&stat.st_rdev.to_le_bytes())?;
109-
res.write_binary(&stat.st_size.to_le_bytes())?;
110-
res.write_binary(&stat.st_blksize.to_le_bytes())?;
111-
res.write_binary(&stat.st_blocks.to_le_bytes())?;
112-
res.write_binary(&stat.st_atime.to_le_bytes())?;
113-
res.write_binary(&stat.st_mtime.to_le_bytes())?;
114-
res.write_binary(&stat.st_ctime.to_le_bytes())?;
103+
res.write_binary(&stat.st_dev.to_be_bytes())?;
104+
res.write_binary(&stat.st_ino.to_be_bytes())?;
105+
res.write_binary(&(stat.st_mode.bits()).to_be_bytes())?;
106+
res.write_binary(&stat.st_nlink.to_be_bytes())?;
107+
res.write_binary(&stat.st_uid.to_be_bytes())?;
108+
res.write_binary(&stat.st_gid.to_be_bytes())?;
109+
res.write_binary(&stat.st_rdev.to_be_bytes())?;
110+
res.write_binary(&stat.st_size.to_be_bytes())?;
111+
res.write_binary(&stat.st_blksize.to_be_bytes())?;
112+
res.write_binary(&stat.st_blocks.to_be_bytes())?;
113+
res.write_binary(&stat.st_atime.to_be_bytes())?;
114+
res.write_binary(&stat.st_mtime.to_be_bytes())?;
115+
res.write_binary(&stat.st_ctime.to_be_bytes())?;
115116
}
116117
};
117118
HandlerStatus::Handled

src/protocol/commands/_vFile_setfs.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use super::prelude::*;
2+
23
use crate::target::ext::host_io::FsKind;
3-
use core::num::NonZeroUsize;
44

55
#[derive(Debug)]
66
pub struct vFileSetfs {
@@ -16,7 +16,7 @@ impl<'a> ParseCommand<'a> for vFileSetfs {
1616

1717
match body {
1818
[b':', body @ ..] => {
19-
let fs = match NonZeroUsize::new(decode_hex(body).ok()?) {
19+
let fs = match core::num::NonZeroUsize::new(decode_hex(body).ok()?) {
2020
None => FsKind::Stub,
2121
Some(pid) => FsKind::Pid(pid),
2222
};

src/target/ext/host_io.rs

Lines changed: 19 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
//! Provide Host I/O operations for the target.
2+
use bitflags::bitflags;
3+
24
use crate::arch::Arch;
35
use crate::target::Target;
4-
use bitflags::bitflags;
56

67
bitflags! {
78
/// Host flags for opening files.
@@ -95,9 +96,9 @@ pub struct HostIoStat {
9596
/// command.
9697
#[derive(Debug)]
9798
pub enum FsKind {
98-
/// select the filesystem as seen by the remote stub
99+
/// Select the filesystem as seen by the remote stub.
99100
Stub,
100-
/// select the filesystem as seen by process pid
101+
/// Select the filesystem as seen by process pid.
101102
Pid(crate::common::Pid),
102103
}
103104

@@ -197,7 +198,7 @@ impl<E> From<std::io::Error> for HostIoError<E> {
197198
/// See [`HostIoError`] for more details.
198199
pub type HostIoResult<T, Tgt> = Result<T, HostIoError<<Tgt as Target>::Error>>;
199200

200-
/// Zero-sized type token that ensures HostIoOutput::write is called
201+
/// Zero-sized type token that ensures HostIoOutput::write is called.
201202
pub struct HostIoToken<'a>(core::marker::PhantomData<&'a *mut ()>);
202203

203204
/// An interface to send pread data back to the GDB client.
@@ -269,13 +270,12 @@ define_ext!(HostIoOps, HostIo);
269270

270271
/// Nested Target Extension - Host I/O open operation.
271272
pub trait HostIoOpen: HostIo {
272-
/// Open a file at filename and return a file descriptor for it, or return
273+
/// Open a file at `filename` and return a file descriptor for it, or return
273274
/// [`HostIoError::Errno`] if an error occurs.
274275
///
275-
/// The filename is a string, flags is an integer indicating a mask of open
276-
/// flags (see [`HostIoOpenFlags`]), and mode is an integer indicating a
277-
/// mask of mode bits to use if the file is created (see
278-
/// [`HostIoOpenMode`]).
276+
/// `flags` is the flags used when open (see [`HostIoOpenFlags`]), and
277+
/// `mode` is the mode used if the file is created
278+
/// (see [`HostIoOpenMode`]).
279279
fn open(
280280
&mut self,
281281
filename: &[u8],
@@ -288,17 +288,17 @@ define_ext!(HostIoOpenOps, HostIoOpen);
288288

289289
/// Nested Target Extension - Host I/O close operation.
290290
pub trait HostIoClose: HostIo {
291-
/// Close the open file corresponding to fd.
291+
/// Close the open file corresponding to `fd`.
292292
fn close(&mut self, fd: u32) -> HostIoResult<(), Self>;
293293
}
294294

295295
define_ext!(HostIoCloseOps, HostIoClose);
296296

297297
/// Nested Target Extension - Host I/O pread operation.
298298
pub trait HostIoPread: HostIo {
299-
/// Read data from the open file corresponding to fd.
299+
/// Read data from the open file corresponding to `fd`.
300300
///
301-
/// Up to count bytes will be read from the file, starting at offset
301+
/// Up to `count` bytes will be read from the file, starting at `offset`
302302
/// relative to the start of the file.
303303
///
304304
/// The data read _must_ be sent by calling [`HostIoOutput::write`], which
@@ -318,12 +318,9 @@ define_ext!(HostIoPreadOps, HostIoPread);
318318

319319
/// Nested Target Extension - Host I/O pwrite operation.
320320
pub trait HostIoPwrite: HostIo {
321-
/// Write data (a binary buffer) to the open file corresponding to fd.
321+
/// Write `data` to the open file corresponding to `fd`.
322322
///
323-
/// Start the write at offset from the start of the file.
324-
///
325-
/// Unlike many write system calls, there is no separate count argument; the
326-
/// length of data in the packet is used.
323+
/// Start the write at `offset` from the start of the file.
327324
///
328325
/// Return the number of bytes written, which may be shorter
329326
/// than the length of data, or [`HostIoError::Errno`] if an error occurred.
@@ -332,14 +329,14 @@ pub trait HostIoPwrite: HostIo {
332329
fd: u32,
333330
offset: <Self::Arch as Arch>::Usize,
334331
data: &[u8],
335-
) -> HostIoResult<u32, Self>;
332+
) -> HostIoResult<<Self::Arch as Arch>::Usize, Self>;
336333
}
337334

338335
define_ext!(HostIoPwriteOps, HostIoPwrite);
339336

340337
/// Nested Target Extension - Host I/O fstat operation.
341338
pub trait HostIoFstat: HostIo {
342-
/// Get information about the open file corresponding to fd.
339+
/// Get information about the open file corresponding to `fd`.
343340
///
344341
/// On success return a [`HostIoStat`] struct.
345342
/// Return [`HostIoError::Errno`] if an error occurs.
@@ -350,15 +347,15 @@ define_ext!(HostIoFstatOps, HostIoFstat);
350347

351348
/// Nested Target Extension - Host I/O unlink operation.
352349
pub trait HostIoUnlink: HostIo {
353-
/// Delete the file at filename on the target.
350+
/// Delete the file at `filename` on the target.
354351
fn unlink(&mut self, filename: &[u8]) -> HostIoResult<(), Self>;
355352
}
356353

357354
define_ext!(HostIoUnlinkOps, HostIoUnlink);
358355

359356
/// Nested Target Extension - Host I/O readlink operation.
360357
pub trait HostIoReadlink: HostIo {
361-
/// Read value of symbolic link filename on the target.
358+
/// Read value of symbolic link `filename` on the target.
362359
///
363360
/// The data read _must_ be sent by calling [`HostIoOutput::write`], which
364361
/// will consume the `output` object and return a [`HostIoToken`]. This
@@ -380,7 +377,7 @@ pub trait HostIoSetfs: HostIo {
380377
/// remote targets where the remote stub does not share a common filesystem
381378
/// with the inferior(s).
382379
///
383-
/// See [`FsKind`] for the meaning of argument.
380+
/// See [`FsKind`] for the meaning of `fs`.
384381
///
385382
/// If setfs indicates success, the selected filesystem remains selected
386383
/// until the next successful setfs operation.

0 commit comments

Comments
 (0)