Skip to content

Commit 6c7cb68

Browse files
committed
Refactoring and removing of one dependency.
1 parent 876e513 commit 6c7cb68

File tree

6 files changed

+241
-141
lines changed

6 files changed

+241
-141
lines changed

Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,5 @@ assert_matches = { version = "1" }
3030

3131
[dependencies]
3232
backtrace = { version = "0.3" }
33-
lazy_static = { version = "1" }
3433
libc = { version = "0.2" }
3534
smallvec = { version = "1" }

src/errors.rs

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,12 @@ pub enum ErrorKind {
2222
/// Virtual memory address range contains too many pages.
2323
TooManyVMPages,
2424

25+
/// Failed to query the system page size.
26+
UnknownPageSize,
27+
28+
/// Invalid system page size.
29+
InvalidPageSize(u64),
30+
2531
/// Some [`io::Error`](std::io::Error) occurred.
2632
#[non_exhaustive]
2733
Io {
@@ -87,6 +93,12 @@ impl fmt::Display for Error {
8793
ErrorKind::TooManyVMPages => {
8894
write!(f, "virtual memory address range contains too many pages")
8995
}
96+
ErrorKind::UnknownPageSize => {
97+
write!(f, "failed to query the system page size")
98+
}
99+
ErrorKind::InvalidPageSize(size) => {
100+
write!(f, "invalid system page size: {size} bytes")
101+
}
90102
ErrorKind::Io {
91103
operation,
92104
error,
@@ -104,7 +116,10 @@ impl core::error::Error for Error {
104116
fn source(&self) -> Option<&(dyn core::error::Error + 'static)> {
105117
match &self.0.kind {
106118
// Errors that are self-descriptive.
107-
ErrorKind::TooManyVMPages | ErrorKind::Io { .. } => None,
119+
ErrorKind::TooManyVMPages
120+
| ErrorKind::UnknownPageSize
121+
| ErrorKind::InvalidPageSize(_)
122+
| ErrorKind::Io { .. } => None,
108123

109124
// Errors that defer description to the inner error.
110125
ErrorKind::IntegerCast(err) => Some(err),
@@ -160,7 +175,11 @@ impl Error {
160175
#[must_use]
161176
pub fn os_error_code(&self) -> Option<c_int> {
162177
match &self.0.kind {
163-
ErrorKind::TooManyVMPages { .. } | ErrorKind::IntegerCast { .. } => None,
178+
ErrorKind::TooManyVMPages { .. }
179+
| ErrorKind::UnknownPageSize
180+
| ErrorKind::InvalidPageSize(_)
181+
| ErrorKind::IntegerCast { .. } => None,
182+
164183
ErrorKind::Io { error, .. } => error.raw_os_error(),
165184
}
166185
}

src/lib.rs

Lines changed: 46 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -52,50 +52,25 @@
5252
mod errors;
5353
#[cfg(test)]
5454
mod tests;
55+
mod utils;
5556

5657
extern crate alloc;
5758

5859
use errors::Result;
5960
pub use errors::{Error, ErrorKind};
6061

62+
use core::cmp;
6163
use core::ffi::c_void;
62-
use core::num::NonZero;
63-
use core::{cmp, slice};
6464
use std::io::{IoSlice, IoSliceMut, Read, Seek, SeekFrom, Write};
6565
use std::os::raw::c_ulong;
6666
use std::{io, panic};
6767

68-
use lazy_static::lazy_static;
6968
use smallvec::SmallVec;
7069

71-
lazy_static! {
72-
/// Size in bytes of the smallest possible virtual memory page.
73-
///
74-
/// Failure to fetch the information will result in a size
75-
/// of `u64::max_value()`.
76-
static ref MIN_SYSTEM_PAGE_SIZE: NonZero<u64> =
77-
match unsafe { libc::sysconf(libc::_SC_PAGE_SIZE) } {
78-
-1 => NonZero::<u64>::MAX,
79-
0 => unsafe { NonZero::<u64>::new_unchecked(4096) },
80-
result => unsafe { NonZero::<u64>::new_unchecked(result as u64) },
81-
};
82-
83-
/// Maximum number of the `iovec` structures that can be provided to
84-
/// one system call.
85-
///
86-
/// Failure to fetch the information will result in a count of `1`.
87-
static ref SYSTEM_IOV_MAX: usize =
88-
match unsafe { libc::sysconf(libc::_SC_IOV_MAX) } {
89-
-1 => 1,
90-
result => result as usize,
91-
};
92-
}
93-
94-
/// Align a given number down to a specified alignment boundary.
95-
const fn align_down(n: u64, alignment: NonZero<u64>) -> u64 {
96-
// Notice that the calculation below never causes an overflow.
97-
n & !alignment.get().saturating_sub(1)
98-
}
70+
use crate::utils::{
71+
align_down, ensure_process_exists, io_vectors_from_io_slices, io_vectors_from_io_slices_mut,
72+
min_system_page_size, system_iov_max,
73+
};
9974

10075
/// Prototype of the APIs `process_vm_readv()` and `process_vm_writev()`.
10176
type ProcessVMReadVProc = unsafe extern "C" fn(
@@ -124,17 +99,17 @@ struct PageAwareAddressRange {
12499
impl PageAwareAddressRange {
125100
/// Convert a plain address range into an address range which is split,
126101
/// at page boundaries, over multiple sections.
127-
fn new(start_address: u64, mut size: u64) -> Self {
102+
fn new(start_address: u64, mut size: u64) -> Result<Self> {
128103
if size == 0 {
129-
return Self {
104+
return Ok(Self {
130105
start_address,
131106
size_in_first_page: 0,
132107
size_of_inner_pages: 0,
133108
size_in_last_page: 0,
134-
};
109+
});
135110
}
136111

137-
let min_page_size = *MIN_SYSTEM_PAGE_SIZE;
112+
let min_page_size = min_system_page_size()?;
138113
let distance_to_preceeding_page_boundary =
139114
start_address - align_down(start_address, min_page_size);
140115

@@ -145,19 +120,19 @@ impl PageAwareAddressRange {
145120
// | -- distance_to_preceeding_page_boundary -- v ---- size ---- v |
146121
// preceeding_page_boundary --> start_address --> end_address --> next_page_boundary
147122
return if distance_to_preceeding_page_boundary == 0 && size == min_page_size.get() {
148-
Self {
123+
Ok(Self {
149124
start_address,
150125
size_in_first_page: 0,
151126
size_of_inner_pages: size,
152127
size_in_last_page: 0,
153-
}
128+
})
154129
} else {
155-
Self {
130+
Ok(Self {
156131
start_address,
157132
size_in_first_page: size,
158133
size_of_inner_pages: 0,
159134
size_in_last_page: 0,
160-
}
135+
})
161136
};
162137
}
163138

@@ -180,12 +155,12 @@ impl PageAwareAddressRange {
180155
let size_of_inner_pages = align_down(size, min_page_size);
181156
let size_in_last_page = size - size_of_inner_pages;
182157

183-
Self {
158+
Ok(Self {
184159
start_address,
185160
size_in_first_page,
186161
size_of_inner_pages,
187162
size_in_last_page,
188-
}
163+
})
189164
}
190165

191166
/// Transform this address range into a vector of `iovec`s.
@@ -196,8 +171,8 @@ impl PageAwareAddressRange {
196171
/// (if any) is also returned. Returning a vector of `iovec`s that covers
197172
/// only a prefix of this address range is not considered a failure.
198173
fn into_iov_buffers(mut self) -> Result<(SmallVec<[libc::iovec; 3]>, u64)> {
199-
let min_page_size = MIN_SYSTEM_PAGE_SIZE.get();
200-
let max_iov_count = *SYSTEM_IOV_MAX;
174+
let min_page_size = min_system_page_size()?.get();
175+
let max_iov_count = system_iov_max().get();
201176
let mut size_of_not_covered_suffix = 0;
202177

203178
let mut inner_pages_count = usize::try_from(self.size_of_inner_pages / min_page_size)?;
@@ -342,7 +317,7 @@ impl ProcessVirtualMemoryIO {
342317
));
343318
}
344319

345-
Self::ensure_process_exists(process_id)?;
320+
ensure_process_exists(process_id)?;
346321

347322
Ok(Self {
348323
process_id,
@@ -356,28 +331,12 @@ impl ProcessVirtualMemoryIO {
356331
self.process_id as u32
357332
}
358333

359-
/// Ensure that the process, identified by the given process identifier,
360-
/// currently exists in the system.
361-
fn ensure_process_exists(process_id: libc::pid_t) -> Result<()> {
362-
if unsafe { libc::kill(process_id, 0) } != -1 {
363-
return Ok(());
364-
}
365-
366-
let mut err = io::Error::last_os_error();
367-
err = match err.raw_os_error() {
368-
Some(libc::ESRCH) => io::Error::from(io::ErrorKind::NotFound),
369-
Some(libc::EINVAL) => io::Error::from(io::ErrorKind::InvalidInput),
370-
Some(libc::EPERM) => io::Error::from(io::ErrorKind::PermissionDenied),
371-
_ => err,
372-
};
373-
Err(Error::from_io3(err, "kill", process_id))
374-
}
375-
376334
/// Perform vectored (i.e., scatter/gather) I/O on the virtual memory of the
377335
/// target process.
378336
fn io_vectored(
379337
&mut self,
380338
process_vm_io_v: ProcessVMReadVProc,
339+
process_vm_io_v_name: &'static str,
381340
local_io_vectors: &[libc::iovec],
382341
mut byte_count: u64,
383342
) -> Result<usize> {
@@ -392,7 +351,7 @@ impl ProcessVirtualMemoryIO {
392351
byte_count = cmp::min(byte_count, max_remaining_bytes);
393352

394353
let (remote_io_vectors, _size_of_not_covered_suffix) =
395-
PageAwareAddressRange::new(address, byte_count).into_iov_buffers()?;
354+
PageAwareAddressRange::new(address, byte_count)?.into_iov_buffers()?;
396355

397356
let transferred_bytes_count = unsafe {
398357
process_vm_io_v(
@@ -408,7 +367,7 @@ impl ProcessVirtualMemoryIO {
408367
if transferred_bytes_count == -1 {
409368
return Err(Error::from_io3(
410369
io::Error::last_os_error(),
411-
"process_vm_readv/process_vm_writev",
370+
process_vm_io_v_name,
412371
self.process_id,
413372
));
414373
}
@@ -470,16 +429,25 @@ impl Read for ProcessVirtualMemoryIO {
470429
iov_len: buf.len(),
471430
};
472431

473-
self.io_vectored(libc::process_vm_readv, &[local_io_vector], buf.len() as u64)
474-
.map_err(|err| io::Error::new(io::ErrorKind::Other, err))
432+
self.io_vectored(
433+
libc::process_vm_readv,
434+
"process_vm_readv",
435+
&[local_io_vector],
436+
buf.len() as u64,
437+
)
438+
.map_err(|err| io::Error::new(io::ErrorKind::Other, err))
475439
}
476440

477441
fn read_vectored(&mut self, bufs: &mut [IoSliceMut]) -> io::Result<usize> {
478-
let bytes_to_read = bufs.iter().map(|buf| buf.len() as u64).sum();
479-
let local_io_vectors = unsafe { slice::from_raw_parts(bufs.as_ptr().cast(), bufs.len()) };
442+
let (byte_count, local_io_vectors) = io_vectors_from_io_slices_mut(bufs);
480443

481-
self.io_vectored(libc::process_vm_readv, local_io_vectors, bytes_to_read)
482-
.map_err(|err| io::Error::new(io::ErrorKind::Other, err))
444+
self.io_vectored(
445+
libc::process_vm_readv,
446+
"process_vm_readv",
447+
local_io_vectors,
448+
byte_count,
449+
)
450+
.map_err(|err| io::Error::new(io::ErrorKind::Other, err))
483451
}
484452
}
485453

@@ -492,18 +460,23 @@ impl Write for ProcessVirtualMemoryIO {
492460

493461
self.io_vectored(
494462
libc::process_vm_writev,
463+
"process_vm_writev",
495464
&[local_io_vector],
496465
buf.len() as u64,
497466
)
498467
.map_err(|err| io::Error::new(io::ErrorKind::Other, err))
499468
}
500469

501470
fn write_vectored(&mut self, bufs: &[IoSlice]) -> io::Result<usize> {
502-
let bytes_to_write = bufs.iter().map(|buf| buf.len() as u64).sum();
503-
let local_io_vectors = unsafe { slice::from_raw_parts(bufs.as_ptr().cast(), bufs.len()) };
471+
let (byte_count, local_io_vectors) = io_vectors_from_io_slices(bufs);
504472

505-
self.io_vectored(libc::process_vm_writev, local_io_vectors, bytes_to_write)
506-
.map_err(|err| io::Error::new(io::ErrorKind::Other, err))
473+
self.io_vectored(
474+
libc::process_vm_writev,
475+
"process_vm_writev",
476+
local_io_vectors,
477+
byte_count,
478+
)
479+
.map_err(|err| io::Error::new(io::ErrorKind::Other, err))
507480
}
508481

509482
fn flush(&mut self) -> io::Result<()> {

0 commit comments

Comments
 (0)