Skip to content

Commit

Permalink
Store files in Vec
Browse files Browse the repository at this point in the history
  • Loading branch information
bet4it committed Aug 16, 2021
1 parent 72b9ce2 commit 74a8afd
Show file tree
Hide file tree
Showing 5 changed files with 89 additions and 88 deletions.
6 changes: 2 additions & 4 deletions examples/armv4t/emu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ use crate::mem_sniffer::{AccessKind, MemSniffer};
use crate::DynResult;

const HLE_RETURN_ADDR: u32 = 0x12345678;
pub const FD_MAX: u32 = 256;

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

pub(crate) watchpoints: Vec<u32>,
pub(crate) breakpoints: Vec<u32>,
pub(crate) files: [Option<std::fs::File>; FD_MAX as usize],
pub(crate) files: Vec<Option<std::fs::File>>,
}

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

watchpoints: Vec::new(),
breakpoints: Vec::new(),
files: [FILE_INIT; FD_MAX as usize],
files: Vec::new(),
})
}

Expand Down
97 changes: 51 additions & 46 deletions examples/armv4t/gdb/host_io.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
use gdbstub::target;
use std::io::{Read, Seek, Write};

use crate::emu::{Emu, FD_MAX};

use gdbstub::target::ext::host_io::{
FsKind, HostIoErrno, HostIoError, HostIoOpenFlags, HostIoOpenMode, HostIoOutput, HostIoResult,
HostIoStat, HostIoToken,
};
use std::io::{Read, Seek, Write};

use crate::emu::Emu;

impl target::ext::host_io::HostIo for Emu {
#[inline(always)]
Expand Down Expand Up @@ -52,10 +51,12 @@ impl target::ext::host_io::HostIoOpen for Emu {
flags: HostIoOpenFlags,
_mode: HostIoOpenMode,
) -> HostIoResult<u32, Self> {
let path = match std::str::from_utf8(filename) {
Ok(v) => v,
Err(_) => return Err(HostIoError::Errno(HostIoErrno::ENOENT)),
};
if filename.starts_with(b"/proc") {
return Err(HostIoError::Errno(HostIoErrno::ENOENT));
}

let path =
std::str::from_utf8(filename).map_err(|_| HostIoError::Errno(HostIoErrno::ENOENT))?;

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

let n = 0;
for n in 0..FD_MAX {
if self.files[n as usize].is_none() {
break;
let n = match self.files.iter_mut().enumerate().find(|(_, f)| f.is_none()) {
Some((n, free_file)) => {
*free_file = Some(file);
n
}
}
if n == FD_MAX {
return Err(HostIoError::Errno(HostIoErrno::ENFILE));
}
None => {
self.files.push(Some(file));
self.files.len() - 1
}
};

self.files[n as usize] = Some(file);
Ok(n)
Ok(n as u32)
}
}

impl target::ext::host_io::HostIoClose for Emu {
fn close(&mut self, fd: u32) -> HostIoResult<(), Self> {
if fd < FD_MAX {
self.files[fd as usize]
.take()
.ok_or(HostIoError::Errno(HostIoErrno::EBADF))?;
let fd: usize = fd as usize;
if fd < self.files.len() {
if fd == self.files.len() - 1 {
self.files.pop();
} else {
self.files[fd]
.take()
.ok_or(HostIoError::Errno(HostIoErrno::EBADF))?;
}
Ok(())
} else {
Err(HostIoError::Errno(HostIoErrno::EBADF))
Expand All @@ -113,8 +119,9 @@ impl target::ext::host_io::HostIoPread for Emu {
offset: u32,
output: HostIoOutput<'a>,
) -> HostIoResult<HostIoToken<'a>, Self> {
if fd < FD_MAX {
if let Some(ref mut file) = self.files[fd as usize] {
let fd: usize = fd as usize;
if fd < self.files.len() {
if let Some(ref mut file) = self.files[fd] {
let mut buffer = vec![0; count as usize];
file.seek(std::io::SeekFrom::Start(offset as u64))?;
let n = file.read(&mut buffer)?;
Expand All @@ -130,8 +137,9 @@ impl target::ext::host_io::HostIoPread for Emu {

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

impl target::ext::host_io::HostIoFstat for Emu {
fn fstat(&mut self, fd: u32) -> HostIoResult<HostIoStat, Self> {
if fd < FD_MAX {
if let Some(ref mut file) = self.files[fd as usize] {
let fd: usize = fd as usize;
if fd < self.files.len() {
if let Some(ref mut file) = self.files[fd] {
let metadata = file.metadata()?;
let atime = metadata
.accessed()
.map_err(|_| HostIoError::Errno(HostIoErrno::EACCES))?
.duration_since(std::time::SystemTime::UNIX_EPOCH)
.map_err(|_| HostIoError::Errno(HostIoErrno::EACCES))?
.as_secs() as u32;
let mtime = metadata
.modified()
.map_err(|_| HostIoError::Errno(HostIoErrno::EACCES))?
.duration_since(std::time::SystemTime::UNIX_EPOCH)
.map_err(|_| HostIoError::Errno(HostIoErrno::EACCES))?
.as_secs() as u32;
let ctime = metadata
.created()
.map_err(|_| HostIoError::Errno(HostIoErrno::EACCES))?
.duration_since(std::time::SystemTime::UNIX_EPOCH)
.map_err(|_| HostIoError::Errno(HostIoErrno::EACCES))?
.as_secs() as u32;
macro_rules! time_to_secs {
($time:expr) => {
$time
.map_err(|_| HostIoError::Errno(HostIoErrno::EACCES))?
.duration_since(std::time::SystemTime::UNIX_EPOCH)
.map_err(|_| HostIoError::Errno(HostIoErrno::EACCES))?
.as_secs() as u32
};
}
let atime = time_to_secs!(metadata.accessed());
let mtime = time_to_secs!(metadata.modified());
let ctime = time_to_secs!(metadata.created());
Ok(HostIoStat {
st_dev: 0,
st_ino: 0,
Expand Down Expand Up @@ -214,6 +217,8 @@ impl target::ext::host_io::HostIoReadlink for Emu {
} else if filename == b"/proc/1/cwd" {
// Support `info proc cwd` command
return Ok(output.write(b"/"));
} else if filename.starts_with(b"/proc") {
return Err(HostIoError::Errno(HostIoErrno::ENOENT));
}

let path = match std::str::from_utf8(filename) {
Expand Down
29 changes: 15 additions & 14 deletions src/gdbstub_impl/ext/host_io.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use super::prelude::*;
use crate::arch::Arch;
use crate::protocol::commands::ext::HostIo;

use crate::arch::Arch;
use crate::target::ext::host_io::{HostIoError, HostIoOutput, HostIoStat};
use crate::GdbStubError;

Expand Down Expand Up @@ -99,19 +100,19 @@ impl<T: Target, C: Connection> GdbStubImpl<T, C> {
res.write_str("F")?;
res.write_num(size)?;
res.write_str(";")?;
res.write_binary(&stat.st_dev.to_le_bytes())?;
res.write_binary(&stat.st_ino.to_le_bytes())?;
res.write_binary(&(stat.st_mode.bits()).to_le_bytes())?;
res.write_binary(&stat.st_nlink.to_le_bytes())?;
res.write_binary(&stat.st_uid.to_le_bytes())?;
res.write_binary(&stat.st_gid.to_le_bytes())?;
res.write_binary(&stat.st_rdev.to_le_bytes())?;
res.write_binary(&stat.st_size.to_le_bytes())?;
res.write_binary(&stat.st_blksize.to_le_bytes())?;
res.write_binary(&stat.st_blocks.to_le_bytes())?;
res.write_binary(&stat.st_atime.to_le_bytes())?;
res.write_binary(&stat.st_mtime.to_le_bytes())?;
res.write_binary(&stat.st_ctime.to_le_bytes())?;
res.write_binary(&stat.st_dev.to_be_bytes())?;
res.write_binary(&stat.st_ino.to_be_bytes())?;
res.write_binary(&(stat.st_mode.bits()).to_be_bytes())?;
res.write_binary(&stat.st_nlink.to_be_bytes())?;
res.write_binary(&stat.st_uid.to_be_bytes())?;
res.write_binary(&stat.st_gid.to_be_bytes())?;
res.write_binary(&stat.st_rdev.to_be_bytes())?;
res.write_binary(&stat.st_size.to_be_bytes())?;
res.write_binary(&stat.st_blksize.to_be_bytes())?;
res.write_binary(&stat.st_blocks.to_be_bytes())?;
res.write_binary(&stat.st_atime.to_be_bytes())?;
res.write_binary(&stat.st_mtime.to_be_bytes())?;
res.write_binary(&stat.st_ctime.to_be_bytes())?;
}
};
HandlerStatus::Handled
Expand Down
4 changes: 2 additions & 2 deletions src/protocol/commands/_vFile_setfs.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use super::prelude::*;

use crate::target::ext::host_io::FsKind;
use core::num::NonZeroUsize;

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

match body {
[b':', body @ ..] => {
let fs = match NonZeroUsize::new(decode_hex(body).ok()?) {
let fs = match core::num::NonZeroUsize::new(decode_hex(body).ok()?) {
None => FsKind::Stub,
Some(pid) => FsKind::Pid(pid),
};
Expand Down
41 changes: 19 additions & 22 deletions src/target/ext/host_io.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
//! Provide Host I/O operations for the target.
use bitflags::bitflags;

use crate::arch::Arch;
use crate::target::Target;
use bitflags::bitflags;

bitflags! {
/// Host flags for opening files.
Expand Down Expand Up @@ -95,9 +96,9 @@ pub struct HostIoStat {
/// command.
#[derive(Debug)]
pub enum FsKind {
/// select the filesystem as seen by the remote stub
/// Select the filesystem as seen by the remote stub.
Stub,
/// select the filesystem as seen by process pid
/// Select the filesystem as seen by process pid.
Pid(crate::common::Pid),
}

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

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

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

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

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

define_ext!(HostIoCloseOps, HostIoClose);

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

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

define_ext!(HostIoPwriteOps, HostIoPwrite);

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

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

define_ext!(HostIoUnlinkOps, HostIoUnlink);

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

0 comments on commit 74a8afd

Please sign in to comment.