Reformat Rust code using cargo fmt
This commit is contained in:
parent
be64e45d15
commit
602fef10f8
@ -1,61 +1,59 @@
|
||||
use super::{*};
|
||||
use util::mem_util::from_untrusted::*;
|
||||
use super::*;
|
||||
use std::ffi::{CStr, CString, OsString};
|
||||
use std::path::{Path};
|
||||
use std::path::Path;
|
||||
use util::mem_util::from_untrusted::*;
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn libos_boot(path_buf: *const c_char, argv: *const *const c_char) -> i32 {
|
||||
let (path, args) = match parse_arguments(path_buf, argv) {
|
||||
Ok(path_and_args) => {
|
||||
path_and_args
|
||||
},
|
||||
Ok(path_and_args) => path_and_args,
|
||||
Err(_) => {
|
||||
return EXIT_STATUS_INTERNAL_ERROR;
|
||||
}
|
||||
};
|
||||
|
||||
let _ = backtrace::enable_backtrace("libocclum.signed.so", PrintFormat::Short);
|
||||
panic::catch_unwind(||{
|
||||
backtrace::__rust_begin_short_backtrace(||{
|
||||
match do_boot(&path, &args) {
|
||||
panic::catch_unwind(|| {
|
||||
backtrace::__rust_begin_short_backtrace(|| match do_boot(&path, &args) {
|
||||
Ok(()) => 0,
|
||||
Err(err) => EXIT_STATUS_INTERNAL_ERROR,
|
||||
}
|
||||
})
|
||||
}).unwrap_or(EXIT_STATUS_INTERNAL_ERROR)
|
||||
})
|
||||
.unwrap_or(EXIT_STATUS_INTERNAL_ERROR)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn libos_run() -> i32 {
|
||||
let _ = backtrace::enable_backtrace("libocclum.signed.so", PrintFormat::Short);
|
||||
panic::catch_unwind(||{
|
||||
backtrace::__rust_begin_short_backtrace(||{
|
||||
match do_run() {
|
||||
panic::catch_unwind(|| {
|
||||
backtrace::__rust_begin_short_backtrace(|| match do_run() {
|
||||
Ok(exit_status) => exit_status,
|
||||
Err(err) => EXIT_STATUS_INTERNAL_ERROR,
|
||||
}
|
||||
})
|
||||
}).unwrap_or(EXIT_STATUS_INTERNAL_ERROR)
|
||||
})
|
||||
.unwrap_or(EXIT_STATUS_INTERNAL_ERROR)
|
||||
}
|
||||
|
||||
// Use 127 as a special value to indicate internal error from libos, not from
|
||||
// user programs, although it is completely ok for a user program to return 127.
|
||||
const EXIT_STATUS_INTERNAL_ERROR : i32 = 127;
|
||||
const EXIT_STATUS_INTERNAL_ERROR: i32 = 127;
|
||||
|
||||
fn parse_arguments(path_buf: *const c_char, argv: *const *const c_char)
|
||||
-> Result<(String, Vec<CString>), Error>
|
||||
{
|
||||
fn parse_arguments(
|
||||
path_buf: *const c_char,
|
||||
argv: *const *const c_char,
|
||||
) -> Result<(String, Vec<CString>), Error> {
|
||||
let path_string = {
|
||||
let path_cstring = clone_cstring_safely(path_buf)?;
|
||||
path_cstring.to_string_lossy().into_owned()
|
||||
};
|
||||
let program_cstring = {
|
||||
let program_osstr= Path::new(&path_string).file_name()
|
||||
let program_osstr = Path::new(&path_string)
|
||||
.file_name()
|
||||
.ok_or_else(|| Error::new(Errno::EINVAL, "Invalid path"))?;
|
||||
let program_str = program_osstr.to_str()
|
||||
let program_str = program_osstr
|
||||
.to_str()
|
||||
.ok_or_else(|| Error::new(Errno::EINVAL, "Invalid path"))?;
|
||||
CString::new(program_str)
|
||||
.or_else(|_| errno!(EINVAL, "Invalid path"))?
|
||||
CString::new(program_str).or_else(|_| errno!(EINVAL, "Invalid path"))?
|
||||
};
|
||||
|
||||
let mut args = clone_cstrings_safely(argv)?;
|
||||
|
@ -1,5 +1,5 @@
|
||||
use prelude::*;
|
||||
use std::{fmt, error, convert,};
|
||||
use std::{convert, error, fmt};
|
||||
|
||||
// TODO: remove errno.h
|
||||
|
||||
@ -11,20 +11,14 @@ pub struct Error {
|
||||
|
||||
impl Error {
|
||||
pub fn new(errno: Errno, desc: &'static str) -> Error {
|
||||
let ret = Error {
|
||||
errno,
|
||||
desc,
|
||||
};
|
||||
let ret = Error { errno, desc };
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
impl convert::From<(Errno, &'static str)> for Error {
|
||||
fn from(info: (Errno, &'static str)) -> Error {
|
||||
Error::new(
|
||||
info.0,
|
||||
info.1,
|
||||
)
|
||||
Error::new(info.0, info.1)
|
||||
}
|
||||
}
|
||||
|
||||
@ -88,13 +82,15 @@ pub enum Errno {
|
||||
|
||||
impl Errno {
|
||||
pub fn as_retval(&self) -> i32 {
|
||||
- (*self as i32)
|
||||
-(*self as i32)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Errno {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "errno = {}, \"{}\"",
|
||||
write!(
|
||||
f,
|
||||
"errno = {}, \"{}\"",
|
||||
*self as u32,
|
||||
match *self {
|
||||
Errno::EPERM => "Operation not permitted",
|
||||
@ -139,5 +135,3 @@ impl fmt::Display for Errno {
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,10 +1,9 @@
|
||||
use super::*;
|
||||
use {std};
|
||||
use std::{fmt};
|
||||
use std;
|
||||
use std::borrow::BorrowMut;
|
||||
use std::fmt;
|
||||
|
||||
|
||||
pub trait File : Debug + Sync + Send {
|
||||
pub trait File: Debug + Sync + Send {
|
||||
fn read(&self, buf: &mut [u8]) -> Result<usize, Error>;
|
||||
fn write(&self, buf: &[u8]) -> Result<usize, Error>;
|
||||
fn readv<'a, 'b>(&self, bufs: &'a mut [&'b mut [u8]]) -> Result<usize, Error>;
|
||||
@ -21,10 +20,12 @@ pub struct SgxFile {
|
||||
}
|
||||
|
||||
impl SgxFile {
|
||||
pub fn new(file: Arc<SgxMutex<fs_impl::SgxFile>>,
|
||||
is_readable: bool, is_writable: bool, is_append: bool)
|
||||
-> Result<SgxFile, Error>
|
||||
{
|
||||
pub fn new(
|
||||
file: Arc<SgxMutex<fs_impl::SgxFile>>,
|
||||
is_readable: bool,
|
||||
is_writable: bool,
|
||||
is_append: bool,
|
||||
) -> Result<SgxFile, Error> {
|
||||
if !is_readable && !is_writable {
|
||||
return Err(Error::new(Errno::EINVAL, "Invalid permissions"));
|
||||
}
|
||||
@ -76,7 +77,7 @@ impl File for SgxFile {
|
||||
#[derive(Clone)]
|
||||
#[repr(C)]
|
||||
struct SgxFileInner {
|
||||
// perms: FilePerms,
|
||||
// perms: FilePerms,
|
||||
pos: usize,
|
||||
file: Arc<SgxMutex<fs_impl::SgxFile>>,
|
||||
is_readable: bool,
|
||||
@ -99,12 +100,12 @@ impl SgxFileInner {
|
||||
SeekFrom::End(0)
|
||||
};
|
||||
// TODO: recover from error
|
||||
file.seek(seek_pos).map_err(
|
||||
|e| Error::new(Errno::EINVAL, "Failed to seek to a position"))?;
|
||||
file.seek(seek_pos)
|
||||
.map_err(|e| Error::new(Errno::EINVAL, "Failed to seek to a position"))?;
|
||||
|
||||
let write_len = {
|
||||
file.write(buf).map_err(
|
||||
|e| Error::new(Errno::EINVAL, "Failed to write"))?
|
||||
file.write(buf)
|
||||
.map_err(|e| Error::new(Errno::EINVAL, "Failed to write"))?
|
||||
};
|
||||
|
||||
if !self.is_append {
|
||||
@ -122,12 +123,12 @@ impl SgxFileInner {
|
||||
let file = file_guard.borrow_mut();
|
||||
|
||||
let seek_pos = SeekFrom::Start(self.pos as u64);
|
||||
file.seek(seek_pos).map_err(
|
||||
|e| Error::new(Errno::EINVAL, "Failed to seek to a position"))?;
|
||||
file.seek(seek_pos)
|
||||
.map_err(|e| Error::new(Errno::EINVAL, "Failed to seek to a position"))?;
|
||||
|
||||
let read_len = {
|
||||
file.read(buf).map_err(
|
||||
|e| Error::new(Errno::EINVAL, "Failed to write"))?
|
||||
file.read(buf)
|
||||
.map_err(|e| Error::new(Errno::EINVAL, "Failed to write"))?
|
||||
};
|
||||
|
||||
self.pos += read_len;
|
||||
@ -139,29 +140,26 @@ impl SgxFileInner {
|
||||
let file = file_guard.borrow_mut();
|
||||
|
||||
let pos = match pos {
|
||||
SeekFrom::Start(absolute_offset) => {
|
||||
pos
|
||||
}
|
||||
SeekFrom::End(relative_offset) => {
|
||||
pos
|
||||
}
|
||||
SeekFrom::Start(absolute_offset) => pos,
|
||||
SeekFrom::End(relative_offset) => pos,
|
||||
SeekFrom::Current(relative_offset) => {
|
||||
if relative_offset >= 0 {
|
||||
SeekFrom::Start((self.pos + relative_offset as usize) as u64)
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
let backward_offset = (-relative_offset) as usize;
|
||||
if self.pos < backward_offset { // underflow
|
||||
return Err(Error::new(Errno::EINVAL,
|
||||
"Invalid seek position"));
|
||||
if self.pos < backward_offset {
|
||||
// underflow
|
||||
return Err(Error::new(Errno::EINVAL, "Invalid seek position"));
|
||||
}
|
||||
SeekFrom::Start((self.pos - backward_offset) as u64)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
self.pos = file.seek(pos).map_err(
|
||||
|e| Error::new(Errno::EINVAL, "Failed to seek to a position"))? as usize;
|
||||
self.pos = file
|
||||
.seek(pos)
|
||||
.map_err(|e| Error::new(Errno::EINVAL, "Failed to seek to a position"))?
|
||||
as usize;
|
||||
Ok(self.pos as off_t)
|
||||
}
|
||||
|
||||
@ -178,15 +176,17 @@ impl SgxFileInner {
|
||||
} else {
|
||||
SeekFrom::End(0)
|
||||
};
|
||||
file.seek(seek_pos).map_err(
|
||||
|e| Error::new(Errno::EINVAL, "Failed to seek to a position"))?;
|
||||
file.seek(seek_pos)
|
||||
.map_err(|e| Error::new(Errno::EINVAL, "Failed to seek to a position"))?;
|
||||
|
||||
let mut total_bytes = 0;
|
||||
for buf in bufs {
|
||||
match file.write(buf) {
|
||||
Ok(this_bytes) => {
|
||||
total_bytes += this_bytes;
|
||||
if this_bytes < buf.len() { break; }
|
||||
if this_bytes < buf.len() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
match total_bytes {
|
||||
@ -212,15 +212,17 @@ impl SgxFileInner {
|
||||
let file = file_guard.borrow_mut();
|
||||
|
||||
let seek_pos = SeekFrom::Start(self.pos as u64);
|
||||
file.seek(seek_pos).map_err(
|
||||
|e| Error::new(Errno::EINVAL, "Failed to seek to a position"))?;
|
||||
file.seek(seek_pos)
|
||||
.map_err(|e| Error::new(Errno::EINVAL, "Failed to seek to a position"))?;
|
||||
|
||||
let mut total_bytes = 0;
|
||||
for buf in bufs {
|
||||
match file.read(buf) {
|
||||
Ok(this_bytes) => {
|
||||
total_bytes += this_bytes;
|
||||
if this_bytes < buf.len() { break; }
|
||||
if this_bytes < buf.len() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
match total_bytes {
|
||||
@ -262,8 +264,10 @@ impl StdoutFile {
|
||||
impl File for StdoutFile {
|
||||
fn write(&self, buf: &[u8]) -> Result<usize, Error> {
|
||||
let write_len = {
|
||||
self.inner.lock().write(buf).map_err(|e| (Errno::EINVAL,
|
||||
"Failed to write"))?
|
||||
self.inner
|
||||
.lock()
|
||||
.write(buf)
|
||||
.map_err(|e| (Errno::EINVAL, "Failed to write"))?
|
||||
};
|
||||
Ok(write_len)
|
||||
}
|
||||
@ -279,7 +283,9 @@ impl File for StdoutFile {
|
||||
match guard.write(buf) {
|
||||
Ok(this_len) => {
|
||||
total_bytes += this_len;
|
||||
if this_len < buf.len() { break; }
|
||||
if this_len < buf.len() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
match total_bytes {
|
||||
@ -327,8 +333,10 @@ impl StdinFile {
|
||||
impl File for StdinFile {
|
||||
fn read(&self, buf: &mut [u8]) -> Result<usize, Error> {
|
||||
let read_len = {
|
||||
self.inner.lock().read(buf).map_err(|e| (Errno::EINVAL,
|
||||
"Failed to read"))?
|
||||
self.inner
|
||||
.lock()
|
||||
.read(buf)
|
||||
.map_err(|e| (Errno::EINVAL, "Failed to read"))?
|
||||
};
|
||||
Ok(read_len)
|
||||
}
|
||||
@ -348,7 +356,9 @@ impl File for StdinFile {
|
||||
match guard.read(buf) {
|
||||
Ok(this_len) => {
|
||||
total_bytes += this_len;
|
||||
if this_len < buf.len() { break; }
|
||||
if this_len < buf.len() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
match total_bytes {
|
||||
|
@ -1,6 +1,6 @@
|
||||
use super::*;
|
||||
use super::file::{File, FileRef};
|
||||
use {std};
|
||||
use super::*;
|
||||
use std;
|
||||
|
||||
pub type FileDesc = u32;
|
||||
|
||||
@ -17,7 +17,6 @@ struct FileTableEntry {
|
||||
close_on_spawn: bool,
|
||||
}
|
||||
|
||||
|
||||
impl FileTable {
|
||||
pub fn new() -> FileTable {
|
||||
FileTable {
|
||||
@ -30,15 +29,18 @@ impl FileTable {
|
||||
let mut table = &mut self.table;
|
||||
|
||||
let min_free_fd = if self.num_fds < table.len() {
|
||||
table.iter().enumerate().find(|&(idx, opt)| opt.is_none())
|
||||
.unwrap().0
|
||||
table
|
||||
.iter()
|
||||
.enumerate()
|
||||
.find(|&(idx, opt)| opt.is_none())
|
||||
.unwrap()
|
||||
.0
|
||||
} else {
|
||||
table.push(None);
|
||||
table.len() - 1
|
||||
};
|
||||
|
||||
table[min_free_fd as usize] = Some(FileTableEntry::new(file,
|
||||
close_on_spawn));
|
||||
table[min_free_fd as usize] = Some(FileTableEntry::new(file, close_on_spawn));
|
||||
self.num_fds += 1;
|
||||
|
||||
min_free_fd as FileDesc
|
||||
@ -80,7 +82,7 @@ impl FileTable {
|
||||
Some(del_table_entry) => {
|
||||
self.num_fds -= 1;
|
||||
Ok(del_table_entry.file)
|
||||
},
|
||||
}
|
||||
None => errno!(EBADF, "Invalid file descriptor"),
|
||||
}
|
||||
}
|
||||
@ -90,20 +92,20 @@ impl Clone for FileTable {
|
||||
fn clone(&self) -> FileTable {
|
||||
// Only clone file descriptors that are not close-on-spawn
|
||||
let mut num_cloned_fds = 0;
|
||||
let cloned_table = self.table.iter().map(|entry| {
|
||||
match entry {
|
||||
Some(file_table_entry) => {
|
||||
match file_table_entry.close_on_spawn {
|
||||
let cloned_table = self
|
||||
.table
|
||||
.iter()
|
||||
.map(|entry| match entry {
|
||||
Some(file_table_entry) => match file_table_entry.close_on_spawn {
|
||||
false => {
|
||||
num_cloned_fds += 1;
|
||||
Some(file_table_entry.clone())
|
||||
}
|
||||
true => None
|
||||
}
|
||||
true => None,
|
||||
},
|
||||
None => None
|
||||
}
|
||||
}).collect();
|
||||
None => None,
|
||||
})
|
||||
.collect();
|
||||
|
||||
FileTable {
|
||||
table: cloned_table,
|
||||
@ -112,7 +114,6 @@ impl Clone for FileTable {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl FileTableEntry {
|
||||
fn new(file: FileRef, close_on_spawn: bool) -> FileTableEntry {
|
||||
FileTableEntry {
|
||||
|
@ -1,7 +1,7 @@
|
||||
use super::*;
|
||||
use prelude::*;
|
||||
use {std, process};
|
||||
use std::sgxfs as fs_impl;
|
||||
use {process, std};
|
||||
|
||||
mod file;
|
||||
mod file_table;
|
||||
@ -9,14 +9,14 @@ mod pipe;
|
||||
|
||||
pub use self::file::{File, FileRef, SgxFile, StdinFile, StdoutFile};
|
||||
pub use self::file_table::{FileDesc, FileTable};
|
||||
pub use self::pipe::{Pipe};
|
||||
pub use self::pipe::Pipe;
|
||||
|
||||
pub const O_RDONLY : u32 = 0x00000000;
|
||||
pub const O_WRONLY : u32 = 0x00000001;
|
||||
pub const O_RDWR : u32 = 0x00000002;
|
||||
pub const O_CREAT : u32 = 0x00000040;
|
||||
pub const O_TRUNC : u32 = 0x00000200;
|
||||
pub const O_APPEND : u32 = 0x00000400;
|
||||
pub const O_RDONLY: u32 = 0x00000000;
|
||||
pub const O_WRONLY: u32 = 0x00000001;
|
||||
pub const O_RDWR: u32 = 0x00000002;
|
||||
pub const O_CREAT: u32 = 0x00000040;
|
||||
pub const O_TRUNC: u32 = 0x00000200;
|
||||
pub const O_APPEND: u32 = 0x00000400;
|
||||
pub const O_CLOEXEC: u32 = 0x00080000;
|
||||
|
||||
// TODO: use the type defined in Rust libc.
|
||||
@ -32,8 +32,7 @@ pub fn do_open(path: &str, flags: u32, mode: u32) -> Result<FileDesc, Error> {
|
||||
|
||||
if ((flags & O_TRUNC) != 0 || (flags & O_CREAT) != 0) {
|
||||
open_options.write(true);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
open_options.read(true);
|
||||
}
|
||||
open_options.update(true).binary(true);
|
||||
@ -42,18 +41,23 @@ pub fn do_open(path: &str, flags: u32, mode: u32) -> Result<FileDesc, Error> {
|
||||
};
|
||||
|
||||
let mut sgx_file = {
|
||||
let key : sgx_key_128bit_t = [0 as uint8_t; 16];
|
||||
let key: sgx_key_128bit_t = [0 as uint8_t; 16];
|
||||
// TODO: what if two processes open the same underlying SGX file?
|
||||
let sgx_file = open_options.open_ex(path, &key)
|
||||
.map_err(|e| (Errno::ENOENT, "Failed to open the SGX-protected file") )?;
|
||||
let sgx_file = open_options
|
||||
.open_ex(path, &key)
|
||||
.map_err(|e| (Errno::ENOENT, "Failed to open the SGX-protected file"))?;
|
||||
Arc::new(SgxMutex::new(sgx_file))
|
||||
};
|
||||
|
||||
let is_readable = (flags & O_WRONLY) == 0;
|
||||
let is_writable = (flags & O_WRONLY != 0) || (flags & O_RDWR != 0);
|
||||
let is_append = (flags & O_APPEND != 0);
|
||||
let file_ref : Arc<Box<File>> = Arc::new(Box::new(
|
||||
SgxFile::new(sgx_file, is_readable, is_writable, is_append)?));
|
||||
let file_ref: Arc<Box<File>> = Arc::new(Box::new(SgxFile::new(
|
||||
sgx_file,
|
||||
is_readable,
|
||||
is_writable,
|
||||
is_append,
|
||||
)?));
|
||||
|
||||
let fd = {
|
||||
let current_ref = process::get_current();
|
||||
@ -114,10 +118,8 @@ pub fn do_pipe2(flags: u32) -> Result<[FileDesc; 2], Error> {
|
||||
|
||||
let mut file_table = current.get_files_mut();
|
||||
let close_on_spawn = flags & O_CLOEXEC != 0;
|
||||
let reader_fd = file_table.put(Arc::new(Box::new(pipe.reader)),
|
||||
close_on_spawn);
|
||||
let writer_fd = file_table.put(Arc::new(Box::new(pipe.writer)),
|
||||
close_on_spawn);
|
||||
let reader_fd = file_table.put(Arc::new(Box::new(pipe.reader)), close_on_spawn);
|
||||
let writer_fd = file_table.put(Arc::new(Box::new(pipe.writer)), close_on_spawn);
|
||||
Ok([reader_fd, writer_fd])
|
||||
}
|
||||
|
||||
@ -155,10 +157,12 @@ pub fn do_dup3(old_fd: FileDesc, new_fd: FileDesc, flags: u32) -> Result<FileDes
|
||||
}
|
||||
|
||||
pub fn do_sync() -> Result<(), Error> {
|
||||
unsafe { ocall_sync(); }
|
||||
unsafe {
|
||||
ocall_sync();
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
extern {
|
||||
extern "C" {
|
||||
fn ocall_sync() -> sgx_status_t;
|
||||
}
|
||||
|
@ -1,9 +1,9 @@
|
||||
use super::*;
|
||||
use util::ring_buf::{*};
|
||||
use util::ring_buf::*;
|
||||
|
||||
// TODO: Use Waiter and WaitQueue infrastructure to sleep when blocking
|
||||
|
||||
pub const PIPE_BUF_SIZE : usize = 2 * 1024 * 1024;
|
||||
pub const PIPE_BUF_SIZE: usize = 2 * 1024 * 1024;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Pipe {
|
||||
@ -20,12 +20,11 @@ impl Pipe {
|
||||
},
|
||||
writer: PipeWriter {
|
||||
inner: SgxMutex::new(ring_buf.writer),
|
||||
}
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct PipeReader {
|
||||
inner: SgxMutex<RingBufReader>,
|
||||
@ -44,7 +43,9 @@ impl File for PipeReader {
|
||||
match ringbuf.read(buf) {
|
||||
Ok(this_len) => {
|
||||
total_bytes += this_len;
|
||||
if this_len < buf.len() { break; }
|
||||
if this_len < buf.len() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
match total_bytes {
|
||||
@ -60,11 +61,17 @@ impl File for PipeReader {
|
||||
}
|
||||
|
||||
fn write(&self, buf: &[u8]) -> Result<usize, Error> {
|
||||
Err(Error::new(Errno::EBADF, "PipeReader does not support write"))
|
||||
Err(Error::new(
|
||||
Errno::EBADF,
|
||||
"PipeReader does not support write",
|
||||
))
|
||||
}
|
||||
|
||||
fn writev<'a, 'b>(&self, bufs: &'a [&'b [u8]]) -> Result<usize, Error> {
|
||||
Err(Error::new(Errno::EBADF, "PipeReader does not support write"))
|
||||
Err(Error::new(
|
||||
Errno::EBADF,
|
||||
"PipeReader does not support write",
|
||||
))
|
||||
}
|
||||
|
||||
fn seek(&self, pos: SeekFrom) -> Result<off_t, Error> {
|
||||
@ -75,7 +82,6 @@ impl File for PipeReader {
|
||||
unsafe impl Send for PipeReader {}
|
||||
unsafe impl Sync for PipeReader {}
|
||||
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct PipeWriter {
|
||||
inner: SgxMutex<RingBufWriter>,
|
||||
@ -94,7 +100,9 @@ impl File for PipeWriter {
|
||||
match ringbuf.write(buf) {
|
||||
Ok(this_len) => {
|
||||
total_bytes += this_len;
|
||||
if this_len < buf.len() { break; }
|
||||
if this_len < buf.len() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
match total_bytes {
|
||||
|
@ -1,8 +1,6 @@
|
||||
#![allow(unused)]
|
||||
|
||||
#![crate_name = "occlum_rs"]
|
||||
#![crate_type = "staticlib"]
|
||||
|
||||
#![cfg_attr(not(target_env = "sgx"), no_std)]
|
||||
#![cfg_attr(target_env = "sgx", feature(rustc_private))]
|
||||
#![feature(allocator_api)]
|
||||
@ -18,11 +16,11 @@ extern crate xmas_elf;
|
||||
#[macro_use]
|
||||
extern crate lazy_static;
|
||||
|
||||
use std::ffi::CStr; // a borrowed C string
|
||||
use std::backtrace::{self, PrintFormat};
|
||||
use std::panic;
|
||||
use sgx_types::*;
|
||||
use sgx_trts::libc;
|
||||
use sgx_types::*;
|
||||
use std::backtrace::{self, PrintFormat};
|
||||
use std::ffi::CStr; // a borrowed C string
|
||||
use std::panic;
|
||||
|
||||
#[macro_use]
|
||||
mod prelude;
|
||||
@ -31,9 +29,9 @@ mod errno;
|
||||
mod fs;
|
||||
mod process;
|
||||
mod syscall;
|
||||
mod vm;
|
||||
mod util;
|
||||
mod time;
|
||||
mod util;
|
||||
mod vm;
|
||||
|
||||
use prelude::*;
|
||||
|
||||
|
@ -1,29 +1,30 @@
|
||||
use std;
|
||||
pub use sgx_types::*;
|
||||
pub use sgx_trts::libc;
|
||||
pub use sgx_types::*;
|
||||
use std;
|
||||
|
||||
//pub use {elf_helper, errno, file, file_table, fs, mm, process, syscall, vma, };
|
||||
|
||||
pub use std::marker::{Sync, Send};
|
||||
pub use std::sync::{Arc, SgxMutex, SgxMutexGuard, SgxRwLock,
|
||||
SgxRwLockReadGuard, SgxRwLockWriteGuard};
|
||||
pub use std::cell::{Cell, RefCell};
|
||||
pub use std::marker::{Send, Sync};
|
||||
pub use std::result::Result;
|
||||
pub use std::sync::{
|
||||
Arc, SgxMutex, SgxMutexGuard, SgxRwLock, SgxRwLockReadGuard, SgxRwLockWriteGuard,
|
||||
};
|
||||
//pub use std::borrow::BorrowMut;
|
||||
pub use std::borrow::ToOwned;
|
||||
pub use std::boxed::Box;
|
||||
pub use std::vec::Vec;
|
||||
pub use std::string::{String};
|
||||
pub use std::cmp::{Ordering, PartialOrd};
|
||||
pub use std::collections::{HashMap, VecDeque};
|
||||
pub use std::fmt::{Debug, Display};
|
||||
pub use std::io::{Read, Write, Seek, SeekFrom};
|
||||
pub use std::rc::{Rc};
|
||||
pub use std::iter::{Iterator};
|
||||
pub use std::cmp::{Ordering, PartialOrd};
|
||||
pub use std::borrow::{ToOwned};
|
||||
pub use std::io::{Read, Seek, SeekFrom, Write};
|
||||
pub use std::iter::Iterator;
|
||||
pub use std::rc::Rc;
|
||||
pub use std::string::String;
|
||||
pub use std::vec::Vec;
|
||||
|
||||
pub use errno::Error as Error;
|
||||
pub use errno::Errno;
|
||||
pub use errno::Errno::{*};
|
||||
pub use errno::Errno::*;
|
||||
pub use errno::Error;
|
||||
|
||||
pub use fs::off_t;
|
||||
|
||||
@ -34,12 +35,16 @@ macro_rules! debug_trace {
|
||||
}
|
||||
|
||||
macro_rules! errno {
|
||||
($errno: ident, $msg: expr) => {
|
||||
{
|
||||
println!("ERROR: {} ({}, line {} in file {})", $errno, $msg, line!(), file!());
|
||||
($errno: ident, $msg: expr) => {{
|
||||
println!(
|
||||
"ERROR: {} ({}, line {} in file {})",
|
||||
$errno,
|
||||
$msg,
|
||||
line!(),
|
||||
file!()
|
||||
);
|
||||
Err(Error::new($errno, $msg))
|
||||
}
|
||||
}
|
||||
}};
|
||||
}
|
||||
|
||||
pub fn align_up(addr: usize, align: usize) -> usize {
|
||||
|
@ -1,4 +1,4 @@
|
||||
use super::{*};
|
||||
use super::*;
|
||||
|
||||
// TODO: make sure Processes are released eventually
|
||||
|
||||
@ -11,7 +11,6 @@ pub enum ChildProcessFilter {
|
||||
|
||||
unsafe impl Send for ChildProcessFilter {}
|
||||
|
||||
|
||||
pub fn do_exit(exit_status: i32) {
|
||||
let current_ref = get_current();
|
||||
let mut current = current_ref.lock().unwrap();
|
||||
@ -35,30 +34,29 @@ pub fn do_exit(exit_status: i32) {
|
||||
lock_two_in_order(&parent_ref, ¤t_ref)
|
||||
};
|
||||
// Wake up the parent if it is waiting on this child
|
||||
if parent.waiting_children.is_none() { return; }
|
||||
if parent.waiting_children.is_none() {
|
||||
return;
|
||||
}
|
||||
let mut wait_queue = parent.waiting_children.as_mut().unwrap();
|
||||
wait_queue.del_and_wake_one_waiter(|waiter_data| -> Option<pid_t> {
|
||||
match waiter_data {
|
||||
ChildProcessFilter::WithAnyPID => {
|
||||
},
|
||||
ChildProcessFilter::WithAnyPID => {}
|
||||
ChildProcessFilter::WithPID(required_pid) => {
|
||||
if current.get_pid() != *required_pid {
|
||||
return None;
|
||||
}
|
||||
},
|
||||
}
|
||||
ChildProcessFilter::WithPGID(required_pgid) => {
|
||||
if current.get_pgid() != *required_pgid {
|
||||
return None;
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
Some(current.get_pid())
|
||||
});
|
||||
}
|
||||
|
||||
pub fn do_wait4(child_filter: &ChildProcessFilter, exit_status: &mut i32)
|
||||
-> Result<pid_t, Error>
|
||||
{
|
||||
pub fn do_wait4(child_filter: &ChildProcessFilter, exit_status: &mut i32) -> Result<pid_t, Error> {
|
||||
let current_ref = get_current();
|
||||
let waiter = {
|
||||
let mut current = current_ref.lock().unwrap();
|
||||
@ -69,17 +67,13 @@ pub fn do_wait4(child_filter: &ChildProcessFilter, exit_status: &mut i32)
|
||||
let child = child_ref.lock().unwrap();
|
||||
|
||||
let may_wait_for = match child_filter {
|
||||
ChildProcessFilter::WithAnyPID => {
|
||||
true
|
||||
},
|
||||
ChildProcessFilter::WithPID(required_pid) => {
|
||||
child.get_pid() == *required_pid
|
||||
},
|
||||
ChildProcessFilter::WithPGID(required_pgid) => {
|
||||
child.get_pgid() == *required_pgid
|
||||
}
|
||||
ChildProcessFilter::WithAnyPID => true,
|
||||
ChildProcessFilter::WithPID(required_pid) => child.get_pid() == *required_pid,
|
||||
ChildProcessFilter::WithPGID(required_pgid) => child.get_pgid() == *required_pgid,
|
||||
};
|
||||
if !may_wait_for { continue; }
|
||||
if !may_wait_for {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Return immediately as a child that we wait for has alreay exited
|
||||
if child.status == Status::ZOMBIE {
|
||||
@ -88,7 +82,9 @@ pub fn do_wait4(child_filter: &ChildProcessFilter, exit_status: &mut i32)
|
||||
|
||||
any_child_to_wait_for = true;
|
||||
}
|
||||
if !any_child_to_wait_for { return errno!(ECHILD, "No such child"); }
|
||||
if !any_child_to_wait_for {
|
||||
return errno!(ECHILD, "No such child");
|
||||
}
|
||||
|
||||
let waiter = Waiter::new(child_filter);
|
||||
let mut wait_queue = WaitQueue::new();
|
||||
@ -107,7 +103,9 @@ pub fn do_wait4(child_filter: &ChildProcessFilter, exit_status: &mut i32)
|
||||
for (child_i, child_weak) in current.children.iter().enumerate() {
|
||||
let child_ref = child_weak.upgrade().unwrap();
|
||||
let child = child_ref.lock().unwrap();
|
||||
if child.get_pid() != child_pid { continue; }
|
||||
if child.get_pid() != child_pid {
|
||||
continue;
|
||||
}
|
||||
|
||||
if child.get_status() != Status::ZOMBIE {
|
||||
panic!("THIS SHOULD NEVER HAPPEN!");
|
||||
@ -126,9 +124,9 @@ pub fn do_wait4(child_filter: &ChildProcessFilter, exit_status: &mut i32)
|
||||
Ok(child_pid)
|
||||
}
|
||||
|
||||
fn lock_two_in_order<'a>(first_ref: &'a ProcessRef, second_ref: &'a ProcessRef) ->
|
||||
(SgxMutexGuard<'a, Process>, SgxMutexGuard<'a, Process>)
|
||||
{
|
||||
fn lock_two_in_order<'a>(
|
||||
first_ref: &'a ProcessRef,
|
||||
second_ref: &'a ProcessRef,
|
||||
) -> (SgxMutexGuard<'a, Process>, SgxMutexGuard<'a, Process>) {
|
||||
(first_ref.lock().unwrap(), second_ref.lock().unwrap())
|
||||
}
|
||||
|
||||
|
@ -1,11 +1,11 @@
|
||||
pub use self::process::{Status, IDLE_PROCESS};
|
||||
pub use self::task::{get_current, run_task};
|
||||
pub mod table {
|
||||
pub use super::process_table::{get};
|
||||
pub use super::process_table::get;
|
||||
}
|
||||
pub use self::spawn::{do_spawn, FileAction};
|
||||
pub use self::exit::{do_exit, do_wait4, ChildProcessFilter};
|
||||
pub use self::wait::{Waiter, WaitQueue};
|
||||
pub use self::spawn::{do_spawn, FileAction};
|
||||
pub use self::wait::{WaitQueue, Waiter};
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
pub type pid_t = u32;
|
||||
@ -51,14 +51,14 @@ pub fn do_getppid() -> pid_t {
|
||||
parent.get_pid()
|
||||
}
|
||||
|
||||
mod task;
|
||||
mod exit;
|
||||
mod process;
|
||||
mod process_table;
|
||||
mod spawn;
|
||||
mod task;
|
||||
mod wait;
|
||||
mod exit;
|
||||
|
||||
use super::{*};
|
||||
use self::task::Task;
|
||||
use super::*;
|
||||
use fs::{File, FileRef, FileTable};
|
||||
use vm::{ProcessVM, VMRangeTrait};
|
||||
use fs::{FileTable, File, FileRef};
|
||||
use self::task::{Task};
|
||||
|
@ -1,7 +1,7 @@
|
||||
use super::task::Task;
|
||||
use super::*;
|
||||
use super::task::{Task};
|
||||
use fs::{File, FileRef, FileTable};
|
||||
use vm::{ProcessVM, VMRangeTrait};
|
||||
use fs::{FileTable, File, FileRef};
|
||||
|
||||
lazy_static! {
|
||||
// Dummy object to make all processes having a parent
|
||||
@ -24,9 +24,12 @@ lazy_static! {
|
||||
}
|
||||
|
||||
impl Process {
|
||||
pub fn new(exec_path: &str, task: Task, vm: ProcessVM, file_table: FileTable)
|
||||
-> Result<(pid_t, ProcessRef), Error>
|
||||
{
|
||||
pub fn new(
|
||||
exec_path: &str,
|
||||
task: Task,
|
||||
vm: ProcessVM,
|
||||
file_table: FileTable,
|
||||
) -> Result<(pid_t, ProcessRef), Error> {
|
||||
let new_pid = process_table::alloc_pid();
|
||||
let new_process_ref = Arc::new(SgxMutex::new(Process {
|
||||
task: task,
|
||||
@ -45,20 +48,48 @@ impl Process {
|
||||
Ok((new_pid, new_process_ref))
|
||||
}
|
||||
|
||||
pub fn get_task(&self) -> &Task { &self.task }
|
||||
pub fn get_task_mut(&mut self) -> &mut Task { &mut self.task }
|
||||
pub fn get_pid(&self) -> pid_t { self.pid }
|
||||
pub fn get_pgid(&self) -> pid_t { self.pgid }
|
||||
pub fn get_tgid(&self) -> pid_t { self.tgid }
|
||||
pub fn get_status(&self) -> Status { self.status }
|
||||
pub fn get_exit_status(&self) -> i32 { self.exit_status }
|
||||
pub fn get_exec_path(&self) -> &str { &self.exec_path }
|
||||
pub fn get_vm(&self) -> &ProcessVM { &self.vm }
|
||||
pub fn get_vm_mut(&mut self) -> &mut ProcessVM { &mut self.vm }
|
||||
pub fn get_files(&self) -> &FileTable { &self.file_table }
|
||||
pub fn get_files_mut(&mut self) -> &mut FileTable { &mut self.file_table }
|
||||
pub fn get_parent(&self) -> &ProcessRef { self.parent.as_ref().unwrap() }
|
||||
pub fn get_children(&self) -> &[ProcessWeakRef] { &self.children }
|
||||
pub fn get_task(&self) -> &Task {
|
||||
&self.task
|
||||
}
|
||||
pub fn get_task_mut(&mut self) -> &mut Task {
|
||||
&mut self.task
|
||||
}
|
||||
pub fn get_pid(&self) -> pid_t {
|
||||
self.pid
|
||||
}
|
||||
pub fn get_pgid(&self) -> pid_t {
|
||||
self.pgid
|
||||
}
|
||||
pub fn get_tgid(&self) -> pid_t {
|
||||
self.tgid
|
||||
}
|
||||
pub fn get_status(&self) -> Status {
|
||||
self.status
|
||||
}
|
||||
pub fn get_exit_status(&self) -> i32 {
|
||||
self.exit_status
|
||||
}
|
||||
pub fn get_exec_path(&self) -> &str {
|
||||
&self.exec_path
|
||||
}
|
||||
pub fn get_vm(&self) -> &ProcessVM {
|
||||
&self.vm
|
||||
}
|
||||
pub fn get_vm_mut(&mut self) -> &mut ProcessVM {
|
||||
&mut self.vm
|
||||
}
|
||||
pub fn get_files(&self) -> &FileTable {
|
||||
&self.file_table
|
||||
}
|
||||
pub fn get_files_mut(&mut self) -> &mut FileTable {
|
||||
&mut self.file_table
|
||||
}
|
||||
pub fn get_parent(&self) -> &ProcessRef {
|
||||
self.parent.as_ref().unwrap()
|
||||
}
|
||||
pub fn get_children(&self) -> &[ProcessWeakRef] {
|
||||
&self.children
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Process {
|
||||
@ -67,7 +98,6 @@ impl Drop for Process {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
pub enum Status {
|
||||
RUNNING,
|
||||
|
@ -2,9 +2,8 @@ use super::*;
|
||||
use std::sync::atomic::{AtomicU32, Ordering};
|
||||
|
||||
lazy_static! {
|
||||
static ref PROCESS_TABLE: SgxMutex<HashMap<pid_t, ProcessRef>> = {
|
||||
SgxMutex::new(HashMap::new())
|
||||
};
|
||||
static ref PROCESS_TABLE: SgxMutex<HashMap<pid_t, ProcessRef>> =
|
||||
{ SgxMutex::new(HashMap::new()) };
|
||||
}
|
||||
|
||||
pub fn put(pid: pid_t, process: ProcessRef) {
|
||||
@ -19,8 +18,7 @@ pub fn get(pid: pid_t) -> Option<ProcessRef> {
|
||||
PROCESS_TABLE.lock().unwrap().get(&pid).map(|pr| pr.clone())
|
||||
}
|
||||
|
||||
|
||||
static NEXT_PID : AtomicU32 = AtomicU32::new(1);
|
||||
static NEXT_PID: AtomicU32 = AtomicU32::new(1);
|
||||
|
||||
pub fn alloc_pid() -> u32 {
|
||||
NEXT_PID.fetch_add(1, Ordering::SeqCst)
|
||||
@ -28,7 +26,8 @@ pub fn alloc_pid() -> u32 {
|
||||
|
||||
pub fn free_pid(pid: u32) {
|
||||
// PID 0 is reserved for idle thread, thus no need to free
|
||||
if pid == 0 { return; }
|
||||
if pid == 0 {
|
||||
return;
|
||||
}
|
||||
// TODO:
|
||||
}
|
||||
|
||||
|
@ -1,18 +1,17 @@
|
||||
use super::*;
|
||||
|
||||
use xmas_elf::{sections, ElfFile, program, P64};
|
||||
use xmas_elf::symbol_table::{Entry64, DynEntry64};
|
||||
use xmas_elf::program::{ProgramHeader};
|
||||
use xmas_elf::sections::{Rela};
|
||||
use xmas_elf::program::ProgramHeader;
|
||||
use xmas_elf::sections::Rela;
|
||||
use xmas_elf::symbol_table::Entry;
|
||||
use xmas_elf::symbol_table::{DynEntry64, Entry64};
|
||||
use xmas_elf::{program, sections, ElfFile, P64};
|
||||
|
||||
pub fn print_program_headers(elf_file: &ElfFile) -> Result<(), Error> {
|
||||
println!("Program headers:");
|
||||
let ph_iter = elf_file.program_iter();
|
||||
for sect in ph_iter {
|
||||
program::sanity_check(sect, &elf_file)
|
||||
.map_err(|e| (Errno::ENOEXEC,
|
||||
"Sanity check for program header failed"))?;
|
||||
.map_err(|e| (Errno::ENOEXEC, "Sanity check for program header failed"))?;
|
||||
println!("\t{:?}", sect.get_type());
|
||||
}
|
||||
Ok(())
|
||||
@ -24,11 +23,10 @@ pub fn print_sections(elf_file: &ElfFile) -> Result<(), Error> {
|
||||
sect_iter.next(); // Skip the first, dummy section
|
||||
for sect in sect_iter {
|
||||
sections::sanity_check(sect, &elf_file)
|
||||
.map_err(|e| (Errno::ENOEXEC,
|
||||
"Sanity check for program header failed"))?;
|
||||
let sec_name = sect.get_name(&elf_file)
|
||||
.map_err(|e| (Errno::ENOEXEC,
|
||||
"Failed to get section name"))?;
|
||||
.map_err(|e| (Errno::ENOEXEC, "Sanity check for program header failed"))?;
|
||||
let sec_name = sect
|
||||
.get_name(&elf_file)
|
||||
.map_err(|e| (Errno::ENOEXEC, "Failed to get section name"))?;
|
||||
println!("\t{}\n{:?}", sec_name, sect);
|
||||
}
|
||||
Ok(())
|
||||
@ -36,107 +34,107 @@ pub fn print_sections(elf_file: &ElfFile) -> Result<(), Error> {
|
||||
|
||||
pub fn print_rela_plt_section(elf_file: &ElfFile) -> Result<(), Error> {
|
||||
let rela_entries = get_rela_entries(elf_file, ".rela.plt")
|
||||
.map_err(|e| (Errno::ENOEXEC,
|
||||
"Failed to get .pltrel entries"))?;
|
||||
.map_err(|e| (Errno::ENOEXEC, "Failed to get .pltrel entries"))?;
|
||||
let dynsym_entries = get_dynsym_entries(elf_file)
|
||||
.map_err(|e| (Errno::ENOEXEC,
|
||||
"Failed to get .dynsym entries"))?;
|
||||
.map_err(|e| (Errno::ENOEXEC, "Failed to get .dynsym entries"))?;
|
||||
|
||||
println!(".rela.plt section:");
|
||||
for entry in rela_entries {
|
||||
println!("\toffset: {}, symbol index: {}, type: {}, addend: {}",
|
||||
println!(
|
||||
"\toffset: {}, symbol index: {}, type: {}, addend: {}",
|
||||
entry.get_offset(),
|
||||
entry.get_symbol_table_index(),
|
||||
entry.get_type(),
|
||||
entry.get_addend());
|
||||
entry.get_addend()
|
||||
);
|
||||
|
||||
let symidx = entry.get_symbol_table_index() as usize;
|
||||
let dynsym_entry = &dynsym_entries[symidx];
|
||||
let dynsym_name = dynsym_entry.get_name(&elf_file)
|
||||
.map_err(|e| (Errno::ENOEXEC,
|
||||
"Failed to get the name of a dynamic symbol"))?;
|
||||
let dynsym_name = dynsym_entry
|
||||
.get_name(&elf_file)
|
||||
.map_err(|e| (Errno::ENOEXEC, "Failed to get the name of a dynamic symbol"))?;
|
||||
println!("\t\t{} = {:?}", dynsym_name, dynsym_entry);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn get_data_program_header<'b, 'a: 'b>(elf_file: &'b ElfFile<'a>)
|
||||
-> Result<ProgramHeader<'a>, Error>
|
||||
{
|
||||
pub fn get_data_program_header<'b, 'a: 'b>(
|
||||
elf_file: &'b ElfFile<'a>,
|
||||
) -> Result<ProgramHeader<'a>, Error> {
|
||||
let mut ph_iter = elf_file.program_iter();
|
||||
ph_iter.find(|&ph| ph.get_type() == Ok(program::Type::Load) &&
|
||||
!ph.flags().is_execute() &&
|
||||
ph.flags().is_write() &&
|
||||
ph.flags().is_read())
|
||||
ph_iter
|
||||
.find(|&ph| {
|
||||
ph.get_type() == Ok(program::Type::Load)
|
||||
&& !ph.flags().is_execute()
|
||||
&& ph.flags().is_write()
|
||||
&& ph.flags().is_read()
|
||||
})
|
||||
.ok_or_else(|| (Errno::ENOEXEC, "Failed to get the data segment").into())
|
||||
}
|
||||
|
||||
pub fn get_code_program_header<'b, 'a: 'b>(elf_file: &'b ElfFile<'a>)
|
||||
-> Result<ProgramHeader<'a>, Error>
|
||||
{
|
||||
pub fn get_code_program_header<'b, 'a: 'b>(
|
||||
elf_file: &'b ElfFile<'a>,
|
||||
) -> Result<ProgramHeader<'a>, Error> {
|
||||
let mut ph_iter = elf_file.program_iter();
|
||||
ph_iter.find(|&ph| ph.get_type() == Ok(program::Type::Load) &&
|
||||
ph.flags().is_execute() &&
|
||||
!ph.flags().is_write() &&
|
||||
ph.flags().is_read())
|
||||
ph_iter
|
||||
.find(|&ph| {
|
||||
ph.get_type() == Ok(program::Type::Load)
|
||||
&& ph.flags().is_execute()
|
||||
&& !ph.flags().is_write()
|
||||
&& ph.flags().is_read()
|
||||
})
|
||||
.ok_or_else(|| (Errno::ENOEXEC, "Failed to get the code segment").into())
|
||||
}
|
||||
|
||||
pub fn get_start_address<'b, 'a: 'b>(elf_file: &'b ElfFile<'a>)
|
||||
-> Result<usize, Error>
|
||||
{
|
||||
pub fn get_start_address<'b, 'a: 'b>(elf_file: &'b ElfFile<'a>) -> Result<usize, Error> {
|
||||
let sym_entries = get_sym_entries(elf_file)?;
|
||||
|
||||
for sym_entry in sym_entries {
|
||||
let sym_str = sym_entry.get_name(elf_file)
|
||||
.map_err(|e| Error::new(Errno::ENOEXEC,
|
||||
"Failed to get the name of a symbol"))?;
|
||||
let sym_str = sym_entry
|
||||
.get_name(elf_file)
|
||||
.map_err(|e| Error::new(Errno::ENOEXEC, "Failed to get the name of a symbol"))?;
|
||||
if sym_str == "_start" {
|
||||
return Ok(sym_entry.value() as usize)
|
||||
return Ok(sym_entry.value() as usize);
|
||||
}
|
||||
}
|
||||
|
||||
Err((Errno::ENOEXEC, "Failed to get the _start symbol").into())
|
||||
}
|
||||
|
||||
pub fn get_sym_entries<'b, 'a: 'b>(elf_file: &'b ElfFile<'a>)
|
||||
-> Result<&'a [Entry64], Error>
|
||||
{
|
||||
elf_file.find_section_by_name(".symtab")
|
||||
.and_then(|symtab_section| {
|
||||
symtab_section.get_data(&elf_file).ok()
|
||||
}).and_then(|symbol_table| {
|
||||
match symbol_table {
|
||||
pub fn get_sym_entries<'b, 'a: 'b>(elf_file: &'b ElfFile<'a>) -> Result<&'a [Entry64], Error> {
|
||||
elf_file
|
||||
.find_section_by_name(".symtab")
|
||||
.and_then(|symtab_section| symtab_section.get_data(&elf_file).ok())
|
||||
.and_then(|symbol_table| match symbol_table {
|
||||
sections::SectionData::SymbolTable64(entries) => Some(entries),
|
||||
_ => None,
|
||||
}
|
||||
}).ok_or_else(|| (Errno::ENOEXEC, "Failed get the symbol entries").into())
|
||||
})
|
||||
.ok_or_else(|| (Errno::ENOEXEC, "Failed get the symbol entries").into())
|
||||
}
|
||||
|
||||
pub fn get_rela_entries<'b, 'a: 'b>(elf_file: &'b ElfFile<'a>, sec_name: &'b str)
|
||||
-> Result<&'a [Rela<P64>], Error>
|
||||
{
|
||||
elf_file.find_section_by_name(sec_name)
|
||||
.and_then(|plt_rela_section| {
|
||||
plt_rela_section.get_data(&elf_file).ok()
|
||||
}).and_then(|rela_table| {
|
||||
match rela_table {
|
||||
pub fn get_rela_entries<'b, 'a: 'b>(
|
||||
elf_file: &'b ElfFile<'a>,
|
||||
sec_name: &'b str,
|
||||
) -> Result<&'a [Rela<P64>], Error> {
|
||||
elf_file
|
||||
.find_section_by_name(sec_name)
|
||||
.and_then(|plt_rela_section| plt_rela_section.get_data(&elf_file).ok())
|
||||
.and_then(|rela_table| match rela_table {
|
||||
sections::SectionData::Rela64(entries) => Some(entries),
|
||||
_ => None,
|
||||
}
|
||||
}).ok_or_else(|| (Errno::ENOEXEC, "Failed to get .rela.plt entries").into())
|
||||
})
|
||||
.ok_or_else(|| (Errno::ENOEXEC, "Failed to get .rela.plt entries").into())
|
||||
}
|
||||
|
||||
pub fn get_dynsym_entries<'b, 'a: 'b>(elf_file: &'b ElfFile<'a>)
|
||||
-> Result<&'a [DynEntry64], Error>
|
||||
{
|
||||
elf_file.find_section_by_name(".dynsym")
|
||||
.and_then(|dynamic_section| {
|
||||
dynamic_section.get_data(&elf_file).ok()
|
||||
}).and_then(|dynamic_table| {
|
||||
match dynamic_table {
|
||||
pub fn get_dynsym_entries<'b, 'a: 'b>(
|
||||
elf_file: &'b ElfFile<'a>,
|
||||
) -> Result<&'a [DynEntry64], Error> {
|
||||
elf_file
|
||||
.find_section_by_name(".dynsym")
|
||||
.and_then(|dynamic_section| dynamic_section.get_data(&elf_file).ok())
|
||||
.and_then(|dynamic_table| match dynamic_table {
|
||||
sections::SectionData::DynSymbolTable64(entries) => Some(entries),
|
||||
_ => None,
|
||||
}
|
||||
}).ok_or_else(|| (Errno::ENOEXEC, "Failed to get .dynsym entries").into())
|
||||
})
|
||||
.ok_or_else(|| (Errno::ENOEXEC, "Failed to get .dynsym entries").into())
|
||||
}
|
||||
|
@ -1,8 +1,8 @@
|
||||
use super::*;
|
||||
|
||||
use {std, std::mem, std::ptr};
|
||||
use std::ffi::{CStr, CString};
|
||||
use std::os::raw::c_char;
|
||||
use {std, std::mem, std::ptr};
|
||||
|
||||
/*
|
||||
* The initial stack of a process looks like below:
|
||||
@ -47,10 +47,13 @@ use std::os::raw::c_char;
|
||||
*
|
||||
*/
|
||||
|
||||
pub fn do_init(stack_top: usize, init_area_size: usize,
|
||||
argv: &[CString], envp: &[CString], auxtbl: &AuxTable)
|
||||
-> Result<usize, Error>
|
||||
{
|
||||
pub fn do_init(
|
||||
stack_top: usize,
|
||||
init_area_size: usize,
|
||||
argv: &[CString],
|
||||
envp: &[CString],
|
||||
auxtbl: &AuxTable,
|
||||
) -> Result<usize, Error> {
|
||||
let stack_buf = unsafe { StackBuf::new(stack_top, init_area_size)? };
|
||||
let envp_cloned = clone_cstrings_on_stack(&stack_buf, envp)?;
|
||||
let argv_cloned = clone_cstrings_on_stack(&stack_buf, argv)?;
|
||||
@ -73,7 +76,7 @@ pub struct StackBuf {
|
||||
}
|
||||
|
||||
impl StackBuf {
|
||||
pub unsafe fn new(stack_top: usize, stack_size: usize) -> Result<StackBuf, Error>{
|
||||
pub unsafe fn new(stack_top: usize, stack_size: usize) -> Result<StackBuf, Error> {
|
||||
if stack_top % 16 != 0 || stack_size == 0 || stack_top < stack_size {
|
||||
return errno!(EINVAL, "Invalid stack range");
|
||||
};
|
||||
@ -85,30 +88,38 @@ impl StackBuf {
|
||||
}
|
||||
|
||||
pub fn put<T>(&self, val: T) -> Result<*const T, Error>
|
||||
where T : Copy
|
||||
where
|
||||
T: Copy,
|
||||
{
|
||||
let val_size = mem::size_of::<T>();
|
||||
let val_align = mem::align_of::<T>();
|
||||
let val_ptr = self.alloc(val_size, val_align)? as *mut T;
|
||||
unsafe { ptr::write(val_ptr, val); }
|
||||
unsafe {
|
||||
ptr::write(val_ptr, val);
|
||||
}
|
||||
Ok(val_ptr as *const T)
|
||||
}
|
||||
|
||||
pub fn put_slice<T>(&self, vals: &[T]) -> Result<*const T, Error>
|
||||
where T: Copy
|
||||
where
|
||||
T: Copy,
|
||||
{
|
||||
let val_size = mem::size_of::<T>();
|
||||
let val_align = mem::align_of::<T>();
|
||||
let total_size = {
|
||||
let num_vals = vals.len();
|
||||
if num_vals == 0 { return Ok(self.get_pos() as *const T); }
|
||||
if num_vals == 0 {
|
||||
return Ok(self.get_pos() as *const T);
|
||||
}
|
||||
val_size * num_vals
|
||||
};
|
||||
let base_ptr = self.alloc(total_size, val_align)? as *mut T;
|
||||
|
||||
let mut val_ptr = base_ptr;
|
||||
for v in vals {
|
||||
unsafe { ptr::write(val_ptr, *v); }
|
||||
unsafe {
|
||||
ptr::write(val_ptr, *v);
|
||||
}
|
||||
val_ptr = unsafe { val_ptr.offset(1) };
|
||||
}
|
||||
|
||||
@ -139,26 +150,21 @@ impl StackBuf {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fn clone_cstrings_on_stack<'a, 'b>(stack: &'a StackBuf,
|
||||
cstrings: &'b [CString])
|
||||
-> Result<Vec<&'a CStr>, Error>
|
||||
{
|
||||
fn clone_cstrings_on_stack<'a, 'b>(
|
||||
stack: &'a StackBuf,
|
||||
cstrings: &'b [CString],
|
||||
) -> Result<Vec<&'a CStr>, Error> {
|
||||
let mut cstrs_cloned = Vec::new();
|
||||
for cs in cstrings.iter().rev() {
|
||||
let cstrp_cloned = stack.put_cstr(cs)?;
|
||||
let cstr_cloned = unsafe {
|
||||
CStr::from_ptr::<'a>(cstrp_cloned as *const c_char)
|
||||
};
|
||||
let cstr_cloned = unsafe { CStr::from_ptr::<'a>(cstrp_cloned as *const c_char) };
|
||||
cstrs_cloned.push(cstr_cloned);
|
||||
}
|
||||
cstrs_cloned.reverse();
|
||||
Ok(cstrs_cloned)
|
||||
}
|
||||
|
||||
fn dump_auxtbl_on_stack<'a, 'b>(stack: &'a StackBuf, auxtbl: &'b AuxTable)
|
||||
-> Result<(), Error>
|
||||
{
|
||||
fn dump_auxtbl_on_stack<'a, 'b>(stack: &'a StackBuf, auxtbl: &'b AuxTable) -> Result<(), Error> {
|
||||
// For every key-value pari, dump the value first, then the key
|
||||
stack.put(AuxKey::AT_NULL as u64);
|
||||
stack.put(AuxKey::AT_NULL as u64);
|
||||
@ -169,9 +175,10 @@ fn dump_auxtbl_on_stack<'a, 'b>(stack: &'a StackBuf, auxtbl: &'b AuxTable)
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn dump_cstrptrs_on_stack<'a, 'b>(stack: &'a StackBuf, strptrs: &'b [&'a CStr])
|
||||
-> Result<(), Error>
|
||||
{
|
||||
fn dump_cstrptrs_on_stack<'a, 'b>(
|
||||
stack: &'a StackBuf,
|
||||
strptrs: &'b [&'a CStr],
|
||||
) -> Result<(), Error> {
|
||||
stack.put(0 as u64); // End with a NULL pointer
|
||||
for sp in strptrs.iter().rev() {
|
||||
stack.put(sp.as_ptr() as u64);
|
||||
@ -179,9 +186,8 @@ fn dump_cstrptrs_on_stack<'a, 'b>(stack: &'a StackBuf, strptrs: &'b [&'a CStr])
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
/* Symbolic values for the entries in the auxiliary table
|
||||
put on the initial stack */
|
||||
put on the initial stack */
|
||||
#[allow(non_camel_case_types)]
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
pub enum AuxKey {
|
||||
@ -205,7 +211,6 @@ pub enum AuxKey {
|
||||
AT_CLKTCK = 17, /* frequency at which times() increments */
|
||||
|
||||
/* 18...22 not used */
|
||||
|
||||
AT_SECURE = 23, /* secure mode boolean */
|
||||
AT_BASE_PLATFORM = 24, /* string identifying real platform, may
|
||||
* differ from AT_PLATFORM. */
|
||||
@ -213,11 +218,9 @@ pub enum AuxKey {
|
||||
AT_HWCAP2 = 26, /* extension of AT_HWCAP */
|
||||
|
||||
/* 28...30 not used */
|
||||
|
||||
AT_EXECFN = 31, /* filename of program */
|
||||
}
|
||||
|
||||
|
||||
static AUX_KEYS: &'static [AuxKey] = &[
|
||||
AuxKey::AT_NULL,
|
||||
AuxKey::AT_IGNORE,
|
||||
@ -252,14 +255,12 @@ impl AuxKey {
|
||||
let next_idx = self_idx + 1;
|
||||
if next_idx < AUX_KEYS.len() {
|
||||
Some(AUX_KEYS[next_idx])
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[derive(Clone, Default, Copy, Debug)]
|
||||
pub struct AuxTable {
|
||||
values: [Option<u64>; AuxKey::MAX],
|
||||
@ -268,11 +269,11 @@ pub struct AuxTable {
|
||||
impl AuxTable {
|
||||
pub fn new() -> AuxTable {
|
||||
AuxTable {
|
||||
values: [None; AuxKey::MAX]
|
||||
values: [None; AuxKey::MAX],
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_val(&mut self, key: AuxKey, val: u64) -> Result<(), Error>{
|
||||
pub fn set_val(&mut self, key: AuxKey, val: u64) -> Result<(), Error> {
|
||||
if key == AuxKey::AT_NULL || key == AuxKey::AT_IGNORE {
|
||||
return Err(Error::new(Errno::EINVAL, "Illegal key"));
|
||||
}
|
||||
@ -315,10 +316,12 @@ impl<'a> Iterator for AuxTableIter<'a> {
|
||||
|
||||
fn next(&mut self) -> Option<(AuxKey, u64)> {
|
||||
loop {
|
||||
if self.key == None { return None; }
|
||||
if self.key == None {
|
||||
return None;
|
||||
}
|
||||
let key = self.key.unwrap();
|
||||
|
||||
let item = self.tbl.get_val(key).map(|val| (key, val) );
|
||||
let item = self.tbl.get_val(key).map(|val| (key, val));
|
||||
self.key = key.next();
|
||||
|
||||
if item != None {
|
||||
|
@ -1,11 +1,11 @@
|
||||
use self::segment::*;
|
||||
use super::*;
|
||||
use std::{ptr};
|
||||
use xmas_elf::{ElfFile, header, program, sections};
|
||||
use self::segment::{*};
|
||||
use std::ptr;
|
||||
use xmas_elf::{header, program, sections, ElfFile};
|
||||
|
||||
pub const DEFAULT_STACK_SIZE : usize = 1 * 1024 * 1024;
|
||||
pub const DEFAULT_HEAP_SIZE : usize = 2 * 1024 * 1024;
|
||||
pub const DEFAULT_MMAP_SIZE : usize = 2 * 1024 * 1024;
|
||||
pub const DEFAULT_STACK_SIZE: usize = 1 * 1024 * 1024;
|
||||
pub const DEFAULT_HEAP_SIZE: usize = 2 * 1024 * 1024;
|
||||
pub const DEFAULT_MMAP_SIZE: usize = 2 * 1024 * 1024;
|
||||
|
||||
pub fn do_init(elf_file: &ElfFile, elf_buf: &[u8]) -> Result<ProcessVM, Error> {
|
||||
let mut code_seg = get_code_segment(elf_file)?;
|
||||
@ -21,8 +21,7 @@ pub fn do_init(elf_file: &ElfFile, elf_buf: &[u8]) -> Result<ProcessVM, Error> {
|
||||
let stack_size = DEFAULT_STACK_SIZE;
|
||||
let heap_size = DEFAULT_HEAP_SIZE;
|
||||
let mmap_size = DEFAULT_MMAP_SIZE;
|
||||
let mut process_vm = ProcessVM::new(code_size, data_size, heap_size,
|
||||
stack_size, mmap_size)?;
|
||||
let mut process_vm = ProcessVM::new(code_size, data_size, heap_size, stack_size, mmap_size)?;
|
||||
|
||||
// Calculate the "real" addresses
|
||||
let process_base_addr = process_vm.get_base_addr();
|
||||
@ -44,9 +43,7 @@ pub fn do_init(elf_file: &ElfFile, elf_buf: &[u8]) -> Result<ProcessVM, Error> {
|
||||
Ok(process_vm)
|
||||
}
|
||||
|
||||
fn reloc_symbols(process_base_addr: usize, elf_file: &ElfFile)
|
||||
-> Result<(), Error>
|
||||
{
|
||||
fn reloc_symbols(process_base_addr: usize, elf_file: &ElfFile) -> Result<(), Error> {
|
||||
let rela_entries = elf_helper::get_rela_entries(elf_file, ".rela.dyn")?;
|
||||
for rela_entry in rela_entries {
|
||||
/*
|
||||
@ -67,15 +64,13 @@ fn reloc_symbols(process_base_addr: usize, elf_file: &ElfFile)
|
||||
}
|
||||
}
|
||||
// TODO: need to handle other relocation types
|
||||
_ => { }
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn link_syscalls(process_base_addr: usize, elf_file: &ElfFile)
|
||||
-> Result<(), Error>
|
||||
{
|
||||
fn link_syscalls(process_base_addr: usize, elf_file: &ElfFile) -> Result<(), Error> {
|
||||
let syscall_addr = __occlum_syscall as *const () as usize;
|
||||
|
||||
let rela_entries = elf_helper::get_rela_entries(elf_file, ".rela.plt")?;
|
||||
@ -83,9 +78,9 @@ fn link_syscalls(process_base_addr: usize, elf_file: &ElfFile)
|
||||
for rela_entry in rela_entries {
|
||||
let dynsym_idx = rela_entry.get_symbol_table_index() as usize;
|
||||
let dynsym_entry = &dynsym_entries[dynsym_idx];
|
||||
let dynsym_str = dynsym_entry.get_name(elf_file)
|
||||
.map_err(|e| Error::new(Errno::ENOEXEC,
|
||||
"Failed to get the name of dynamic symbol"))?;
|
||||
let dynsym_str = dynsym_entry
|
||||
.get_name(elf_file)
|
||||
.map_err(|e| Error::new(Errno::ENOEXEC, "Failed to get the name of dynamic symbol"))?;
|
||||
|
||||
if dynsym_str == "__occlum_syscall" {
|
||||
let rela_addr = process_base_addr + rela_entry.get_offset() as usize;
|
||||
@ -98,6 +93,6 @@ fn link_syscalls(process_base_addr: usize, elf_file: &ElfFile)
|
||||
Ok(())
|
||||
}
|
||||
|
||||
extern {
|
||||
extern "C" {
|
||||
fn __occlum_syscall(num: i32, arg0: u64, arg1: u64, arg2: u64, arg3: u64, arg4: u64) -> i64;
|
||||
}
|
||||
|
@ -1,17 +1,17 @@
|
||||
use super::*;
|
||||
use fs::{File, FileDesc, StdinFile, StdoutFile/*, StderrFile*/, FileTable};
|
||||
use std::path::Path;
|
||||
use std::ffi::{CStr, CString};
|
||||
use std::sgxfs::SgxFile;
|
||||
use xmas_elf::{ElfFile, header, program, sections};
|
||||
use xmas_elf::symbol_table::Entry;
|
||||
use self::init_stack::{AuxKey, AuxTable};
|
||||
use super::task::{Task};
|
||||
use super::task::Task;
|
||||
use super::*;
|
||||
use fs::{File, FileDesc, FileTable, StdinFile, StdoutFile /*, StderrFile*/};
|
||||
use std::ffi::{CStr, CString};
|
||||
use std::path::Path;
|
||||
use std::sgxfs::SgxFile;
|
||||
use vm::{ProcessVM, VMRangeTrait};
|
||||
use xmas_elf::symbol_table::Entry;
|
||||
use xmas_elf::{header, program, sections, ElfFile};
|
||||
|
||||
mod elf_helper;
|
||||
mod init_stack;
|
||||
mod init_vm;
|
||||
mod elf_helper;
|
||||
mod segment;
|
||||
|
||||
#[derive(Debug)]
|
||||
@ -22,12 +22,15 @@ pub enum FileAction {
|
||||
Close(FileDesc),
|
||||
}
|
||||
|
||||
pub fn do_spawn<P: AsRef<Path>>(elf_path: &P, argv: &[CString], envp: &[CString],
|
||||
file_actions: &[FileAction], parent_ref: &ProcessRef)
|
||||
-> Result<u32, Error>
|
||||
{
|
||||
pub fn do_spawn<P: AsRef<Path>>(
|
||||
elf_path: &P,
|
||||
argv: &[CString],
|
||||
envp: &[CString],
|
||||
file_actions: &[FileAction],
|
||||
parent_ref: &ProcessRef,
|
||||
) -> Result<u32, Error> {
|
||||
let mut elf_buf = {
|
||||
let key : sgx_key_128bit_t = [0 as uint8_t; 16];
|
||||
let key: sgx_key_128bit_t = [0 as uint8_t; 16];
|
||||
let mut sgx_file = SgxFile::open_ex(elf_path, &key)
|
||||
.map_err(|e| (Errno::ENOENT, "Failed to open the SGX-protected file"))?;
|
||||
|
||||
@ -37,8 +40,8 @@ pub fn do_spawn<P: AsRef<Path>>(elf_path: &P, argv: &[CString], envp: &[CString]
|
||||
};
|
||||
|
||||
let elf_file = {
|
||||
let elf_file = ElfFile::new(&elf_buf)
|
||||
.map_err(|e| (Errno::ENOEXEC, "Failed to parse the ELF file"))?;
|
||||
let elf_file =
|
||||
ElfFile::new(&elf_buf).map_err(|e| (Errno::ENOEXEC, "Failed to parse the ELF file"))?;
|
||||
header::sanity_check(&elf_file)
|
||||
.map_err(|e| (Errno::ENOEXEC, "Failed to parse the ELF file"))?;
|
||||
/*
|
||||
@ -53,8 +56,7 @@ pub fn do_spawn<P: AsRef<Path>>(elf_path: &P, argv: &[CString], envp: &[CString]
|
||||
let vm = init_vm::do_init(&elf_file, &elf_buf[..])?;
|
||||
let task = {
|
||||
let program_entry = {
|
||||
let program_entry = vm.get_base_addr() +
|
||||
elf_helper::get_start_address(&elf_file)?;
|
||||
let program_entry = vm.get_base_addr() + elf_helper::get_start_address(&elf_file)?;
|
||||
if !vm.get_code_vma().contains_obj(program_entry, 16) {
|
||||
return Err(Error::new(Errno::EINVAL, "Invalid program entry"));
|
||||
}
|
||||
@ -73,9 +75,7 @@ pub fn do_spawn<P: AsRef<Path>>(elf_path: &P, argv: &[CString], envp: &[CString]
|
||||
Ok(new_pid)
|
||||
}
|
||||
|
||||
fn init_files(parent_ref: &ProcessRef, file_actions: &[FileAction])
|
||||
-> Result<FileTable, Error>
|
||||
{
|
||||
fn init_files(parent_ref: &ProcessRef, file_actions: &[FileAction]) -> Result<FileTable, Error> {
|
||||
// Usually, we just inherit the file table from the parent
|
||||
let parent = parent_ref.lock().unwrap();
|
||||
let should_inherit_file_table = parent.get_pid() > 0;
|
||||
@ -89,7 +89,7 @@ fn init_files(parent_ref: &ProcessRef, file_actions: &[FileAction])
|
||||
if old_fd != new_fd {
|
||||
cloned_file_table.put_at(*new_fd, file, false);
|
||||
}
|
||||
},
|
||||
}
|
||||
FileAction::Close(fd) => {
|
||||
cloned_file_table.del(*fd)?;
|
||||
}
|
||||
@ -101,8 +101,8 @@ fn init_files(parent_ref: &ProcessRef, file_actions: &[FileAction])
|
||||
|
||||
// But, for init process, we initialize file table for it
|
||||
let mut file_table = FileTable::new();
|
||||
let stdin : Arc<Box<File>> = Arc::new(Box::new(StdinFile::new()));
|
||||
let stdout : Arc<Box<File>> = Arc::new(Box::new(StdoutFile::new()));
|
||||
let stdin: Arc<Box<File>> = Arc::new(Box::new(StdinFile::new()));
|
||||
let stdout: Arc<Box<File>> = Arc::new(Box::new(StdoutFile::new()));
|
||||
// TODO: implement and use a real stderr
|
||||
let stderr = stdout.clone();
|
||||
file_table.put(stdin, false);
|
||||
@ -111,21 +111,21 @@ fn init_files(parent_ref: &ProcessRef, file_actions: &[FileAction])
|
||||
Ok(file_table)
|
||||
}
|
||||
|
||||
fn init_task(user_entry: usize, stack_top: usize,
|
||||
argv: &[CString], envp: &[CString])
|
||||
-> Result<Task, Error>
|
||||
{
|
||||
fn init_task(
|
||||
user_entry: usize,
|
||||
stack_top: usize,
|
||||
argv: &[CString],
|
||||
envp: &[CString],
|
||||
) -> Result<Task, Error> {
|
||||
let user_stack = init_stack(stack_top, argv, envp)?;
|
||||
Ok(Task {
|
||||
user_stack_addr: user_stack,
|
||||
user_entry_addr: user_entry,
|
||||
.. Default::default()
|
||||
..Default::default()
|
||||
})
|
||||
}
|
||||
|
||||
fn init_stack(stack_top: usize, argv: &[CString], envp: &[CString])
|
||||
-> Result<usize, Error>
|
||||
{
|
||||
fn init_stack(stack_top: usize, argv: &[CString], envp: &[CString]) -> Result<usize, Error> {
|
||||
let mut auxtbl = AuxTable::new();
|
||||
auxtbl.set_val(AuxKey::AT_PAGESZ, 4096)?;
|
||||
auxtbl.set_val(AuxKey::AT_UID, 0)?;
|
||||
@ -137,8 +137,7 @@ fn init_stack(stack_top: usize, argv: &[CString], envp: &[CString])
|
||||
init_stack::do_init(stack_top, 4096, argv, envp, &auxtbl)
|
||||
}
|
||||
|
||||
fn parent_adopts_new_child(parent_ref: &ProcessRef, child_ref: &ProcessRef)
|
||||
{
|
||||
fn parent_adopts_new_child(parent_ref: &ProcessRef, child_ref: &ProcessRef) {
|
||||
let mut parent = parent_ref.lock().unwrap();
|
||||
let mut child = child_ref.lock().unwrap();
|
||||
parent.children.push(Arc::downgrade(child_ref));
|
||||
|
@ -1,7 +1,6 @@
|
||||
use super::*;
|
||||
use std::{slice};
|
||||
use xmas_elf::program::{ProgramHeader};
|
||||
|
||||
use std::slice;
|
||||
use xmas_elf::program::ProgramHeader;
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct Segment {
|
||||
@ -22,31 +21,35 @@ pub const PERM_W: u32 = 0x2;
|
||||
pub const PERM_X: u32 = 0x4;
|
||||
|
||||
impl Segment {
|
||||
pub fn get_mem_addr(&self) -> usize { self.mem_addr }
|
||||
pub fn get_mem_align(&self) -> usize { self.mem_align }
|
||||
pub fn get_mem_size(&self) -> usize { self.mem_size }
|
||||
pub fn get_mem_addr(&self) -> usize {
|
||||
self.mem_addr
|
||||
}
|
||||
pub fn get_mem_align(&self) -> usize {
|
||||
self.mem_align
|
||||
}
|
||||
pub fn get_mem_size(&self) -> usize {
|
||||
self.mem_size
|
||||
}
|
||||
|
||||
pub fn from_program_header(ph: &ProgramHeader) -> Result<Segment, Error> {
|
||||
let ph64 = match ph {
|
||||
ProgramHeader::Ph32(ph) => {
|
||||
return Err((Errno::ENOEXEC, "Not support 32-bit ELF").into())
|
||||
}
|
||||
ProgramHeader::Ph64(ph64) => {
|
||||
ph64
|
||||
return Err((Errno::ENOEXEC, "Not support 32-bit ELF").into());
|
||||
}
|
||||
ProgramHeader::Ph64(ph64) => ph64,
|
||||
};
|
||||
if ph64.align > 1 && ((ph64.offset % ph64.align) !=
|
||||
(ph64.virtual_addr % ph64.align)) {
|
||||
return Err((Errno::EINVAL,
|
||||
"Memory address and file offset is not equal, per modulo").into());
|
||||
if ph64.align > 1 && ((ph64.offset % ph64.align) != (ph64.virtual_addr % ph64.align)) {
|
||||
return Err((
|
||||
Errno::EINVAL,
|
||||
"Memory address and file offset is not equal, per modulo",
|
||||
)
|
||||
.into());
|
||||
}
|
||||
if ph64.mem_size < ph64.file_size {
|
||||
return Err((Errno::EINVAL,
|
||||
"Memory size must be greater than file size").into());
|
||||
return Err((Errno::EINVAL, "Memory size must be greater than file size").into());
|
||||
}
|
||||
if !ph64.align.is_power_of_two() {
|
||||
return Err((Errno::EINVAL,
|
||||
"Memory alignment must be a power of two").into());
|
||||
return Err((Errno::EINVAL, "Memory alignment must be a power of two").into());
|
||||
}
|
||||
|
||||
Ok(Segment {
|
||||
@ -61,16 +64,20 @@ impl Segment {
|
||||
|
||||
pub fn load_from_file(&self, elf_buf: &[u8]) {
|
||||
let mut target_buf = unsafe {
|
||||
slice::from_raw_parts_mut((self.process_base_addr + self.mem_addr)
|
||||
as *mut u8,
|
||||
self.file_size)
|
||||
slice::from_raw_parts_mut(
|
||||
(self.process_base_addr + self.mem_addr) as *mut u8,
|
||||
self.file_size,
|
||||
)
|
||||
};
|
||||
target_buf.copy_from_slice(&elf_buf[self.file_offset..
|
||||
(self.file_offset + self.file_size)]);
|
||||
target_buf.copy_from_slice(&elf_buf[self.file_offset..(self.file_offset + self.file_size)]);
|
||||
}
|
||||
|
||||
pub fn set_runtime_info(&mut self, process_base_addr: usize,
|
||||
start_addr: usize, end_addr: usize) {
|
||||
pub fn set_runtime_info(
|
||||
&mut self,
|
||||
process_base_addr: usize,
|
||||
start_addr: usize,
|
||||
end_addr: usize,
|
||||
) {
|
||||
self.process_base_addr = process_base_addr;
|
||||
self.start_addr = start_addr;
|
||||
self.end_addr = end_addr;
|
||||
@ -100,7 +107,7 @@ pub fn get_data_segment(elf_file: &ElfFile) -> Result<Segment, Error> {
|
||||
}
|
||||
|
||||
#[link(name = "sgx_trts")]
|
||||
extern {
|
||||
extern "C" {
|
||||
// XXX: trts_mprotect is a private SGX function that is not supposed to be
|
||||
// used by external users. At least, this is the case for SGX v2.2. To use
|
||||
// this function, we need to modify Intel SGX SDK slightly. I suppose
|
||||
|
@ -1,5 +1,5 @@
|
||||
use super::*;
|
||||
use std::{mem};
|
||||
use std::mem;
|
||||
|
||||
/// Note: this definition must be in sync with task.h
|
||||
#[derive(Clone, Debug, Default)]
|
||||
@ -13,11 +13,9 @@ pub struct Task {
|
||||
pub saved_state: usize, // struct jmpbuf*
|
||||
}
|
||||
|
||||
|
||||
lazy_static! {
|
||||
static ref new_process_queue: SgxMutex<VecDeque<ProcessRef>> = {
|
||||
SgxMutex::new(VecDeque::new())
|
||||
};
|
||||
static ref new_process_queue: SgxMutex<VecDeque<ProcessRef>> =
|
||||
{ SgxMutex::new(VecDeque::new()) };
|
||||
}
|
||||
|
||||
pub fn enqueue_task(new_process: ProcessRef) {
|
||||
@ -34,10 +32,9 @@ fn dequeue_task() -> Option<ProcessRef> {
|
||||
new_process_queue.lock().unwrap().pop_front()
|
||||
}
|
||||
|
||||
|
||||
pub fn run_task() -> Result<i32, Error> {
|
||||
let new_process : ProcessRef = dequeue_task()
|
||||
.ok_or_else(|| (Errno::EAGAIN, "No new processes to run"))?;
|
||||
let new_process: ProcessRef =
|
||||
dequeue_task().ok_or_else(|| (Errno::EAGAIN, "No new processes to run"))?;
|
||||
set_current(&new_process);
|
||||
|
||||
let (pid, task) = {
|
||||
@ -105,10 +102,12 @@ fn reset_current() {
|
||||
});
|
||||
|
||||
// Prevent memory leakage
|
||||
unsafe { drop(Arc::from_raw(process_ptr)); }
|
||||
unsafe {
|
||||
drop(Arc::from_raw(process_ptr));
|
||||
}
|
||||
}
|
||||
|
||||
extern {
|
||||
extern "C" {
|
||||
fn ocall_run_new_task(ret: *mut i32) -> sgx_status_t;
|
||||
fn do_run_task(task: *mut Task) -> i32;
|
||||
}
|
||||
|
@ -1,18 +1,27 @@
|
||||
use super::{*};
|
||||
use super::*;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Waiter<D, R>
|
||||
where D: Sized + Copy, R: Sized + Copy
|
||||
where
|
||||
D: Sized + Copy,
|
||||
R: Sized + Copy,
|
||||
{
|
||||
inner: Arc<SgxMutex<WaiterInner<D, R>>>,
|
||||
thread: *const c_void,
|
||||
}
|
||||
|
||||
unsafe impl<D, R> Send for Waiter<D, R> where D: Sized + Copy, R: Sized + Copy {}
|
||||
unsafe impl<D, R> Send for Waiter<D, R>
|
||||
where
|
||||
D: Sized + Copy,
|
||||
R: Sized + Copy,
|
||||
{
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct WaiterInner<D, R>
|
||||
where D: Sized + Copy, R: Sized + Copy
|
||||
where
|
||||
D: Sized + Copy,
|
||||
R: Sized + Copy,
|
||||
{
|
||||
is_woken: bool,
|
||||
data: D,
|
||||
@ -20,7 +29,9 @@ struct WaiterInner<D, R>
|
||||
}
|
||||
|
||||
impl<D, R> Waiter<D, R>
|
||||
where D: Sized + Copy, R: Sized + Copy
|
||||
where
|
||||
D: Sized + Copy,
|
||||
R: Sized + Copy,
|
||||
{
|
||||
pub fn new(data: &D) -> Waiter<D, R> {
|
||||
Waiter {
|
||||
@ -50,17 +61,19 @@ impl<D, R> Waiter<D, R>
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct WaitQueue<D, R>
|
||||
where D: Sized + Copy, R: Sized + Copy
|
||||
where
|
||||
D: Sized + Copy,
|
||||
R: Sized + Copy,
|
||||
{
|
||||
waiters: Vec<Waiter<D, R>>,
|
||||
}
|
||||
|
||||
|
||||
impl<D, R> WaitQueue<D, R>
|
||||
where D: Sized + Copy, R: Sized + Copy
|
||||
where
|
||||
D: Sized + Copy,
|
||||
R: Sized + Copy,
|
||||
{
|
||||
pub fn new() -> WaitQueue<D, R>
|
||||
{
|
||||
pub fn new() -> WaitQueue<D, R> {
|
||||
WaitQueue {
|
||||
waiters: Vec::new(),
|
||||
}
|
||||
@ -74,7 +87,8 @@ impl<D, R> WaitQueue<D, R>
|
||||
}
|
||||
|
||||
pub fn del_and_wake_one_waiter<F>(&mut self, cond: F) -> usize
|
||||
where F: Fn(&D) -> Option<R>
|
||||
where
|
||||
F: Fn(&D) -> Option<R>,
|
||||
{
|
||||
let mut waiters = &mut self.waiters;
|
||||
let del_waiter_i = {
|
||||
@ -84,12 +98,13 @@ impl<D, R> WaitQueue<D, R>
|
||||
waiter_inner.is_woken = true;
|
||||
waiter_inner.result = Some(waiter_result);
|
||||
true
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
false
|
||||
}
|
||||
});
|
||||
if waiter_i.is_none() { return 0; }
|
||||
if waiter_i.is_none() {
|
||||
return 0;
|
||||
}
|
||||
waiter_i.unwrap()
|
||||
};
|
||||
let del_waiter = waiters.swap_remove(del_waiter_i);
|
||||
@ -99,8 +114,8 @@ impl<D, R> WaitQueue<D, R>
|
||||
}
|
||||
|
||||
fn wait_event(thread: *const c_void) {
|
||||
let mut ret : c_int = 0;
|
||||
let mut sgx_ret : c_int = 0;
|
||||
let mut ret: c_int = 0;
|
||||
let mut sgx_ret: c_int = 0;
|
||||
unsafe {
|
||||
sgx_ret = sgx_thread_wait_untrusted_event_ocall(&mut ret as *mut c_int, thread);
|
||||
}
|
||||
@ -110,8 +125,8 @@ fn wait_event(thread: *const c_void) {
|
||||
}
|
||||
|
||||
fn set_event(thread: *const c_void) {
|
||||
let mut ret : c_int = 0;
|
||||
let mut sgx_ret : c_int = 0;
|
||||
let mut ret: c_int = 0;
|
||||
let mut sgx_ret: c_int = 0;
|
||||
unsafe {
|
||||
sgx_ret = sgx_thread_set_untrusted_event_ocall(&mut ret as *mut c_int, thread);
|
||||
}
|
||||
@ -120,20 +135,27 @@ fn set_event(thread: *const c_void) {
|
||||
}
|
||||
}
|
||||
|
||||
extern {
|
||||
extern "C" {
|
||||
fn sgx_thread_get_self() -> *const c_void;
|
||||
|
||||
/* Go outside and wait on my untrusted event */
|
||||
fn sgx_thread_wait_untrusted_event_ocall(ret: *mut c_int, self_thread: *const c_void) -> c_int;
|
||||
|
||||
/* Wake a thread waiting on its untrusted event */
|
||||
fn sgx_thread_set_untrusted_event_ocall(ret: *mut c_int, waiter_thread: *const c_void) -> c_int;
|
||||
fn sgx_thread_set_untrusted_event_ocall(ret: *mut c_int, waiter_thread: *const c_void)
|
||||
-> c_int;
|
||||
|
||||
/* Wake a thread waiting on its untrusted event, and wait on my untrusted event */
|
||||
fn sgx_thread_setwait_untrusted_events_ocall(ret: *mut c_int,
|
||||
waiter_thread: *const c_void, self_thread: *const c_void) -> c_int;
|
||||
fn sgx_thread_setwait_untrusted_events_ocall(
|
||||
ret: *mut c_int,
|
||||
waiter_thread: *const c_void,
|
||||
self_thread: *const c_void,
|
||||
) -> c_int;
|
||||
|
||||
/* Wake multiple threads waiting on their untrusted events */
|
||||
fn sgx_thread_set_multiple_untrusted_events_ocall(ret: *mut c_int,
|
||||
waiter_threads: *const *const c_void, total: size_t ) -> c_int;
|
||||
fn sgx_thread_set_multiple_untrusted_events_ocall(
|
||||
ret: *mut c_int,
|
||||
waiter_threads: *const *const c_void,
|
||||
total: size_t,
|
||||
) -> c_int;
|
||||
}
|
||||
|
@ -1,13 +1,13 @@
|
||||
use super::*;
|
||||
use prelude::*;
|
||||
use {std, fs, process, vm};
|
||||
use std::{ptr};
|
||||
use std::ffi::{CStr, CString};
|
||||
use fs::{off_t, FileDesc};
|
||||
use vm::{VMAreaFlags, VMResizeOptions};
|
||||
use prelude::*;
|
||||
use process::{pid_t, ChildProcessFilter, FileAction};
|
||||
use time::{timeval_t};
|
||||
use util::mem_util::from_user::{*};
|
||||
use std::ffi::{CStr, CString};
|
||||
use std::ptr;
|
||||
use time::timeval_t;
|
||||
use util::mem_util::from_user::*;
|
||||
use vm::{VMAreaFlags, VMResizeOptions};
|
||||
use {fs, process, std, vm};
|
||||
// Use the internal syscall wrappers from sgx_tstd
|
||||
//use std::libc_fs as fs;
|
||||
//use std::libc_io as io;
|
||||
@ -18,14 +18,13 @@ pub struct iovec_t {
|
||||
len: size_t,
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* This Rust-version of fdop correspond to the C-version one in Occlum.
|
||||
* See <path_to_musl_libc>/src/process/fdop.h.
|
||||
*/
|
||||
const FDOP_CLOSE : u32 = 1;
|
||||
const FDOP_DUP2 : u32 = 2;
|
||||
const FDOP_OPEN : u32 = 3;
|
||||
const FDOP_CLOSE: u32 = 1;
|
||||
const FDOP_DUP2: u32 = 2;
|
||||
const FDOP_OPEN: u32 = 3;
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug)]
|
||||
@ -41,9 +40,7 @@ pub struct FdOp {
|
||||
path: *const u8,
|
||||
}
|
||||
|
||||
fn clone_file_actions_safely(fdop_ptr: *const FdOp)
|
||||
-> Result<Vec<FileAction>, Error>
|
||||
{
|
||||
fn clone_file_actions_safely(fdop_ptr: *const FdOp) -> Result<Vec<FileAction>, Error> {
|
||||
let mut file_actions = Vec::new();
|
||||
|
||||
let mut fdop_ptr = fdop_ptr;
|
||||
@ -52,18 +49,14 @@ fn clone_file_actions_safely(fdop_ptr: *const FdOp)
|
||||
let fdop = unsafe { &*fdop_ptr };
|
||||
|
||||
let file_action = match fdop.cmd {
|
||||
FDOP_CLOSE => {
|
||||
FileAction::Close(fdop.fd)
|
||||
},
|
||||
FDOP_DUP2 => {
|
||||
FileAction::Dup2(fdop.srcfd, fdop.fd)
|
||||
},
|
||||
FDOP_CLOSE => FileAction::Close(fdop.fd),
|
||||
FDOP_DUP2 => FileAction::Dup2(fdop.srcfd, fdop.fd),
|
||||
FDOP_OPEN => {
|
||||
return errno!(EINVAL, "Not implemented");
|
||||
},
|
||||
}
|
||||
_ => {
|
||||
return errno!(EINVAL, "Unknown file action command");
|
||||
},
|
||||
}
|
||||
};
|
||||
file_actions.push(file_action);
|
||||
|
||||
@ -73,14 +66,13 @@ fn clone_file_actions_safely(fdop_ptr: *const FdOp)
|
||||
Ok(file_actions)
|
||||
}
|
||||
|
||||
fn do_spawn(child_pid_ptr: *mut c_uint,
|
||||
fn do_spawn(
|
||||
child_pid_ptr: *mut c_uint,
|
||||
path: *const c_char,
|
||||
argv: *const *const c_char,
|
||||
envp: *const *const c_char,
|
||||
fdop_list: *const FdOp,
|
||||
)
|
||||
-> Result<(), Error>
|
||||
{
|
||||
) -> Result<(), Error> {
|
||||
check_mut_ptr(child_pid_ptr)?;
|
||||
let path = clone_cstring_safely(path)?.to_string_lossy().into_owned();
|
||||
let argv = clone_cstrings_safely(argv)?;
|
||||
@ -94,9 +86,7 @@ fn do_spawn(child_pid_ptr: *mut c_uint,
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn do_read(fd: c_int, buf: *mut c_void, size: size_t)
|
||||
-> Result<size_t, Error>
|
||||
{
|
||||
fn do_read(fd: c_int, buf: *mut c_void, size: size_t) -> Result<size_t, Error> {
|
||||
let fd = fd as FileDesc;
|
||||
let safe_buf = {
|
||||
let buf = buf as *mut u8;
|
||||
@ -107,9 +97,7 @@ fn do_read(fd: c_int, buf: *mut c_void, size: size_t)
|
||||
fs::do_read(fd, safe_buf)
|
||||
}
|
||||
|
||||
fn do_write(fd: c_int, buf: *const c_void, size: size_t)
|
||||
-> Result<size_t, Error>
|
||||
{
|
||||
fn do_write(fd: c_int, buf: *const c_void, size: size_t) -> Result<size_t, Error> {
|
||||
let fd = fd as FileDesc;
|
||||
let safe_buf = {
|
||||
let buf = buf as *mut u8;
|
||||
@ -120,9 +108,7 @@ fn do_write(fd: c_int, buf: *const c_void, size: size_t)
|
||||
fs::do_write(fd, safe_buf)
|
||||
}
|
||||
|
||||
fn do_writev(fd: c_int, iov: *const iovec_t, count: c_int)
|
||||
-> Result<size_t, Error>
|
||||
{
|
||||
fn do_writev(fd: c_int, iov: *const iovec_t, count: c_int) -> Result<size_t, Error> {
|
||||
let fd = fd as FileDesc;
|
||||
|
||||
let count = {
|
||||
@ -138,9 +124,7 @@ fn do_writev(fd: c_int, iov: *const iovec_t, count: c_int)
|
||||
for iov_i in 0..count {
|
||||
let iov_ptr = unsafe { iov.offset(iov_i as isize) };
|
||||
let iov = unsafe { &*iov_ptr };
|
||||
let buf = unsafe {
|
||||
std::slice::from_raw_parts(iov.base as * const u8, iov.len)
|
||||
};
|
||||
let buf = unsafe { std::slice::from_raw_parts(iov.base as *const u8, iov.len) };
|
||||
bufs_vec.push(buf);
|
||||
}
|
||||
bufs_vec
|
||||
@ -150,9 +134,7 @@ fn do_writev(fd: c_int, iov: *const iovec_t, count: c_int)
|
||||
fs::do_writev(fd, bufs)
|
||||
}
|
||||
|
||||
fn do_readv(fd: c_int, iov: *mut iovec_t, count: c_int)
|
||||
-> Result<size_t, Error>
|
||||
{
|
||||
fn do_readv(fd: c_int, iov: *mut iovec_t, count: c_int) -> Result<size_t, Error> {
|
||||
let fd = fd as FileDesc;
|
||||
|
||||
let count = {
|
||||
@ -168,9 +150,7 @@ fn do_readv(fd: c_int, iov: *mut iovec_t, count: c_int)
|
||||
for iov_i in 0..count {
|
||||
let iov_ptr = unsafe { iov.offset(iov_i as isize) };
|
||||
let iov = unsafe { &*iov_ptr };
|
||||
let buf = unsafe {
|
||||
std::slice::from_raw_parts_mut(iov.base as * mut u8, iov.len)
|
||||
};
|
||||
let buf = unsafe { std::slice::from_raw_parts_mut(iov.base as *mut u8, iov.len) };
|
||||
bufs_vec.push(buf);
|
||||
}
|
||||
bufs_vec
|
||||
@ -180,23 +160,23 @@ fn do_readv(fd: c_int, iov: *mut iovec_t, count: c_int)
|
||||
fs::do_readv(fd, bufs)
|
||||
}
|
||||
|
||||
|
||||
pub fn do_lseek(fd: c_int, offset: off_t, whence: c_int) -> Result<off_t, Error>
|
||||
{
|
||||
|
||||
pub fn do_lseek(fd: c_int, offset: off_t, whence: c_int) -> Result<off_t, Error> {
|
||||
let fd = fd as FileDesc;
|
||||
|
||||
let seek_from = match whence {
|
||||
0 => { // SEEK_SET
|
||||
0 => {
|
||||
// SEEK_SET
|
||||
if offset < 0 {
|
||||
return Err(Error::new(Errno::EINVAL, "Invalid offset"));
|
||||
}
|
||||
SeekFrom::Start(offset as u64)
|
||||
}
|
||||
1 => { // SEEK_CUR
|
||||
1 => {
|
||||
// SEEK_CUR
|
||||
SeekFrom::Current(offset)
|
||||
}
|
||||
2 => { // SEEK_END
|
||||
2 => {
|
||||
// SEEK_END
|
||||
SeekFrom::End(offset)
|
||||
}
|
||||
_ => {
|
||||
@ -207,10 +187,14 @@ pub fn do_lseek(fd: c_int, offset: off_t, whence: c_int) -> Result<off_t, Error>
|
||||
fs::do_lseek(fd, seek_from)
|
||||
}
|
||||
|
||||
fn do_mmap(addr: *const c_void, size: size_t, prot: c_int,
|
||||
flags: c_int, fd: c_int, offset: off_t)
|
||||
-> Result<*const c_void, Error>
|
||||
{
|
||||
fn do_mmap(
|
||||
addr: *const c_void,
|
||||
size: size_t,
|
||||
prot: c_int,
|
||||
flags: c_int,
|
||||
fd: c_int,
|
||||
offset: off_t,
|
||||
) -> Result<*const c_void, Error> {
|
||||
let addr = addr as usize;
|
||||
let size = size as usize;
|
||||
let flags = VMAreaFlags(prot as u32);
|
||||
@ -223,16 +207,18 @@ fn do_munmap(addr: *const c_void, size: size_t) -> Result<(), Error> {
|
||||
vm::do_munmap(addr, size)
|
||||
}
|
||||
|
||||
fn do_mremap(old_addr: *const c_void, old_size: size_t,
|
||||
new_size: size_t, flags: c_int, new_addr: *const c_void)
|
||||
-> Result<*const c_void, Error>
|
||||
{
|
||||
fn do_mremap(
|
||||
old_addr: *const c_void,
|
||||
old_size: size_t,
|
||||
new_size: size_t,
|
||||
flags: c_int,
|
||||
new_addr: *const c_void,
|
||||
) -> Result<*const c_void, Error> {
|
||||
let old_addr = old_addr as usize;
|
||||
let old_size = old_size as usize;
|
||||
let mut options = VMResizeOptions::new(new_size)?;
|
||||
// TODO: handle flags and new_addr
|
||||
vm::do_mremap(old_addr, old_size, &options)
|
||||
.map(|ret_addr| ret_addr as *const c_void)
|
||||
vm::do_mremap(old_addr, old_size, &options).map(|ret_addr| ret_addr as *const c_void)
|
||||
}
|
||||
|
||||
fn do_brk(new_brk_addr: *const c_void) -> Result<*const c_void, Error> {
|
||||
@ -246,19 +232,13 @@ fn do_wait4(pid: c_int, _exit_status: *mut c_int) -> Result<pid_t, Error> {
|
||||
}
|
||||
|
||||
let child_process_filter = match pid {
|
||||
pid if pid < -1 => {
|
||||
process::ChildProcessFilter::WithPGID((-pid) as pid_t)
|
||||
},
|
||||
-1 => {
|
||||
process::ChildProcessFilter::WithAnyPID
|
||||
},
|
||||
pid if pid < -1 => process::ChildProcessFilter::WithPGID((-pid) as pid_t),
|
||||
-1 => process::ChildProcessFilter::WithAnyPID,
|
||||
0 => {
|
||||
let gpid = process::do_getgpid();
|
||||
process::ChildProcessFilter::WithPGID(gpid)
|
||||
},
|
||||
pid if pid > 0 => {
|
||||
process::ChildProcessFilter::WithPID(pid as pid_t)
|
||||
},
|
||||
}
|
||||
pid if pid > 0 => process::ChildProcessFilter::WithPID(pid as pid_t),
|
||||
_ => {
|
||||
panic!("THIS SHOULD NEVER HAPPEN!");
|
||||
}
|
||||
@ -267,13 +247,13 @@ fn do_wait4(pid: c_int, _exit_status: *mut c_int) -> Result<pid_t, Error> {
|
||||
match process::do_wait4(&child_process_filter, &mut exit_status) {
|
||||
Ok(pid) => {
|
||||
if _exit_status != 0 as *mut c_int {
|
||||
unsafe { *_exit_status = exit_status; }
|
||||
unsafe {
|
||||
*_exit_status = exit_status;
|
||||
}
|
||||
}
|
||||
Ok(pid)
|
||||
}
|
||||
Err(e) => {
|
||||
Err(e)
|
||||
}
|
||||
Err(e) => Err(e),
|
||||
}
|
||||
}
|
||||
|
||||
@ -291,49 +271,56 @@ fn do_pipe2(fds_u: *mut c_int, flags: c_int) -> Result<(), Error> {
|
||||
fn do_gettimeofday(tv_u: *mut timeval_t) -> Result<(), Error> {
|
||||
check_mut_ptr(tv_u)?;
|
||||
let tv = time::do_gettimeofday();
|
||||
unsafe { *tv_u = tv; }
|
||||
unsafe {
|
||||
*tv_u = tv;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
const MAP_FAILED : *const c_void = ((-1) as i64) as *const c_void;
|
||||
const MAP_FAILED: *const c_void = ((-1) as i64) as *const c_void;
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn occlum_mmap(addr: *const c_void, length: size_t, prot: c_int,
|
||||
flags: c_int, fd: c_int, offset: off_t)
|
||||
-> *const c_void
|
||||
{
|
||||
pub extern "C" fn occlum_mmap(
|
||||
addr: *const c_void,
|
||||
length: size_t,
|
||||
prot: c_int,
|
||||
flags: c_int,
|
||||
fd: c_int,
|
||||
offset: off_t,
|
||||
) -> *const c_void {
|
||||
match do_mmap(addr, length, prot, flags, fd, offset) {
|
||||
Ok(ret_addr) => { ret_addr },
|
||||
Err(e) => { MAP_FAILED }
|
||||
Ok(ret_addr) => ret_addr,
|
||||
Err(e) => MAP_FAILED,
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn occlum_munmap(addr: *const c_void, length: size_t) -> c_int {
|
||||
match do_munmap(addr, length) {
|
||||
Ok(()) => { 0 },
|
||||
Err(e) => { -1 }
|
||||
Ok(()) => 0,
|
||||
Err(e) => -1,
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn occlum_mremap(old_addr: *const c_void, old_size: size_t,
|
||||
new_size: size_t, flags: c_int,
|
||||
new_addr: *const c_void)
|
||||
-> *const c_void
|
||||
{
|
||||
pub extern "C" fn occlum_mremap(
|
||||
old_addr: *const c_void,
|
||||
old_size: size_t,
|
||||
new_size: size_t,
|
||||
flags: c_int,
|
||||
new_addr: *const c_void,
|
||||
) -> *const c_void {
|
||||
match do_mremap(old_addr, old_size, new_size, flags, new_addr) {
|
||||
Ok(ret_addr) => { ret_addr },
|
||||
Err(e) => { MAP_FAILED }
|
||||
Ok(ret_addr) => ret_addr,
|
||||
Err(e) => MAP_FAILED,
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn occlum_brk(addr: *const c_void) -> *const c_void {
|
||||
match do_brk(addr) {
|
||||
Ok(ret_addr) => { ret_addr },
|
||||
Err(e) => { MAP_FAILED }
|
||||
Ok(ret_addr) => ret_addr,
|
||||
Err(e) => MAP_FAILED,
|
||||
}
|
||||
}
|
||||
|
||||
@ -345,96 +332,68 @@ pub extern "C" fn occlum_pipe(fds: *mut c_int) -> c_int {
|
||||
#[no_mangle]
|
||||
pub extern "C" fn occlum_pipe2(fds: *mut c_int, flags: c_int) -> c_int {
|
||||
match do_pipe2(fds, flags) {
|
||||
Ok(()) => {
|
||||
0
|
||||
},
|
||||
Err(e) => {
|
||||
e.errno.as_retval()
|
||||
}
|
||||
Ok(()) => 0,
|
||||
Err(e) => e.errno.as_retval(),
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn occlum_open(path_buf: * const c_char, flags: c_int, mode: c_int) -> c_int {
|
||||
pub extern "C" fn occlum_open(path_buf: *const c_char, flags: c_int, mode: c_int) -> c_int {
|
||||
let path = unsafe {
|
||||
CStr::from_ptr(path_buf as * const i8).to_string_lossy().into_owned()
|
||||
CStr::from_ptr(path_buf as *const i8)
|
||||
.to_string_lossy()
|
||||
.into_owned()
|
||||
};
|
||||
match fs::do_open(&path, flags as u32, mode as u32) {
|
||||
Ok(fd) => {
|
||||
fd as c_int
|
||||
},
|
||||
Err(e) => {
|
||||
e.errno.as_retval()
|
||||
}
|
||||
Ok(fd) => fd as c_int,
|
||||
Err(e) => e.errno.as_retval(),
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn occlum_close(fd: c_int) -> c_int {
|
||||
match fs::do_close(fd as FileDesc) {
|
||||
Ok(()) => {
|
||||
0
|
||||
},
|
||||
Err(e) => {
|
||||
e.errno.as_retval()
|
||||
}
|
||||
Ok(()) => 0,
|
||||
Err(e) => e.errno.as_retval(),
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn occlum_read(fd: c_int, buf: * mut c_void, size: size_t) -> ssize_t {
|
||||
pub extern "C" fn occlum_read(fd: c_int, buf: *mut c_void, size: size_t) -> ssize_t {
|
||||
match do_read(fd, buf, size) {
|
||||
Ok(read_len) => {
|
||||
read_len as ssize_t
|
||||
},
|
||||
Err(e) => {
|
||||
e.errno.as_retval() as ssize_t
|
||||
}
|
||||
Ok(read_len) => read_len as ssize_t,
|
||||
Err(e) => e.errno.as_retval() as ssize_t,
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn occlum_write(fd: c_int, buf: * const c_void, size: size_t) -> ssize_t {
|
||||
pub extern "C" fn occlum_write(fd: c_int, buf: *const c_void, size: size_t) -> ssize_t {
|
||||
match do_write(fd, buf, size) {
|
||||
Ok(write_len) => {
|
||||
write_len as ssize_t
|
||||
},
|
||||
Err(e) => {
|
||||
e.errno.as_retval() as ssize_t
|
||||
}
|
||||
Ok(write_len) => write_len as ssize_t,
|
||||
Err(e) => e.errno.as_retval() as ssize_t,
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn occlum_readv(fd: c_int, iov: * mut iovec_t, count: c_int) -> ssize_t {
|
||||
pub extern "C" fn occlum_readv(fd: c_int, iov: *mut iovec_t, count: c_int) -> ssize_t {
|
||||
match do_readv(fd, iov, count) {
|
||||
Ok(read_len) => {
|
||||
read_len as ssize_t
|
||||
},
|
||||
Err(e) => {
|
||||
e.errno.as_retval() as ssize_t
|
||||
}
|
||||
Ok(read_len) => read_len as ssize_t,
|
||||
Err(e) => e.errno.as_retval() as ssize_t,
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn occlum_writev(fd: c_int, iov: * const iovec_t, count: c_int) -> ssize_t {
|
||||
pub extern "C" fn occlum_writev(fd: c_int, iov: *const iovec_t, count: c_int) -> ssize_t {
|
||||
match do_writev(fd, iov, count) {
|
||||
Ok(write_len) => {
|
||||
write_len as ssize_t
|
||||
},
|
||||
Err(e) => {
|
||||
e.errno.as_retval() as ssize_t
|
||||
}
|
||||
Ok(write_len) => write_len as ssize_t,
|
||||
Err(e) => e.errno.as_retval() as ssize_t,
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn occlum_lseek(fd: c_int, offset: off_t, whence: c_int) -> off_t {
|
||||
match do_lseek(fd, offset, whence) {
|
||||
Ok(ret) => {
|
||||
ret
|
||||
},
|
||||
Ok(ret) => ret,
|
||||
Err(e) => {
|
||||
-1 as off_t // this special value indicates error
|
||||
}
|
||||
@ -442,26 +401,22 @@ pub extern "C" fn occlum_lseek(fd: c_int, offset: off_t, whence: c_int) -> off_t
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn occlum_getpid() -> c_uint
|
||||
{
|
||||
pub extern "C" fn occlum_getpid() -> c_uint {
|
||||
process::do_getpid()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn occlum_getppid() -> c_uint
|
||||
{
|
||||
pub extern "C" fn occlum_getppid() -> c_uint {
|
||||
process::do_getppid()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn occlum_exit(status: i32)
|
||||
{
|
||||
pub extern "C" fn occlum_exit(status: i32) {
|
||||
process::do_exit(status);
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn occlum_unknown(num: u32)
|
||||
{
|
||||
pub extern "C" fn occlum_unknown(num: u32) {
|
||||
if cfg!(debug_assertions) {
|
||||
//println!("[WARNING] Unknown syscall (num = {})", num);
|
||||
}
|
||||
@ -469,100 +424,73 @@ pub extern "C" fn occlum_unknown(num: u32)
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn occlum_spawn(
|
||||
child_pid: *mut c_uint, path: *const c_char,
|
||||
argv: *const *const c_char, envp: *const *const c_char,
|
||||
fdop_list: *const FdOp) -> c_int
|
||||
{
|
||||
child_pid: *mut c_uint,
|
||||
path: *const c_char,
|
||||
argv: *const *const c_char,
|
||||
envp: *const *const c_char,
|
||||
fdop_list: *const FdOp,
|
||||
) -> c_int {
|
||||
match do_spawn(child_pid, path, argv, envp, fdop_list) {
|
||||
Ok(()) => 0,
|
||||
Err(e) => { e.errno.as_retval() }
|
||||
Err(e) => e.errno.as_retval(),
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn occlum_wait4(child_pid: c_int, exit_status: *mut c_int,
|
||||
options: c_int/*, rusage: *mut Rusage*/) -> c_int
|
||||
{
|
||||
pub extern "C" fn occlum_wait4(
|
||||
child_pid: c_int,
|
||||
exit_status: *mut c_int,
|
||||
options: c_int, /*, rusage: *mut Rusage*/
|
||||
) -> c_int {
|
||||
match do_wait4(child_pid, exit_status) {
|
||||
Ok(pid) => {
|
||||
pid as c_int
|
||||
}
|
||||
Err(e) => {
|
||||
e.errno.as_retval()
|
||||
}
|
||||
Ok(pid) => pid as c_int,
|
||||
Err(e) => e.errno.as_retval(),
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn occlum_dup(old_fd: c_int) -> c_int
|
||||
{
|
||||
pub extern "C" fn occlum_dup(old_fd: c_int) -> c_int {
|
||||
let old_fd = old_fd as FileDesc;
|
||||
match fs::do_dup(old_fd) {
|
||||
Ok(new_fd) => {
|
||||
new_fd as c_int
|
||||
}
|
||||
Err(e) => {
|
||||
e.errno.as_retval()
|
||||
}
|
||||
Ok(new_fd) => new_fd as c_int,
|
||||
Err(e) => e.errno.as_retval(),
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn occlum_dup2(old_fd: c_int, new_fd: c_int)
|
||||
-> c_int
|
||||
{
|
||||
pub extern "C" fn occlum_dup2(old_fd: c_int, new_fd: c_int) -> c_int {
|
||||
let old_fd = old_fd as FileDesc;
|
||||
let new_fd = new_fd as FileDesc;
|
||||
match fs::do_dup2(old_fd, new_fd) {
|
||||
Ok(new_fd) => {
|
||||
new_fd as c_int
|
||||
}
|
||||
Err(e) => {
|
||||
e.errno.as_retval()
|
||||
}
|
||||
Ok(new_fd) => new_fd as c_int,
|
||||
Err(e) => e.errno.as_retval(),
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn occlum_dup3(old_fd: c_int, new_fd: c_int, flags: c_int)
|
||||
-> c_int
|
||||
{
|
||||
pub extern "C" fn occlum_dup3(old_fd: c_int, new_fd: c_int, flags: c_int) -> c_int {
|
||||
let old_fd = old_fd as FileDesc;
|
||||
let new_fd = new_fd as FileDesc;
|
||||
let flags = flags as u32;
|
||||
match fs::do_dup3(old_fd, new_fd, flags) {
|
||||
Ok(new_fd) => {
|
||||
new_fd as c_int
|
||||
}
|
||||
Err(e) => {
|
||||
e.errno.as_retval()
|
||||
}
|
||||
Ok(new_fd) => new_fd as c_int,
|
||||
Err(e) => e.errno.as_retval(),
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn occlum_sync() -> c_int
|
||||
{
|
||||
pub extern "C" fn occlum_sync() -> c_int {
|
||||
match fs::do_sync() {
|
||||
Ok(()) => {
|
||||
0 as c_int
|
||||
}
|
||||
Err(e) => {
|
||||
e.errno.as_retval()
|
||||
}
|
||||
Ok(()) => 0 as c_int,
|
||||
Err(e) => e.errno.as_retval(),
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: handle tz: timezone_t
|
||||
#[no_mangle]
|
||||
pub extern "C" fn occlum_gettimeofday(tv: *mut timeval_t) -> c_int
|
||||
{
|
||||
pub extern "C" fn occlum_gettimeofday(tv: *mut timeval_t) -> c_int {
|
||||
match do_gettimeofday(tv) {
|
||||
Ok(()) => {
|
||||
0
|
||||
}
|
||||
Err(e) => {
|
||||
e.errno.as_retval()
|
||||
}
|
||||
Ok(()) => 0,
|
||||
Err(e) => e.errno.as_retval(),
|
||||
}
|
||||
}
|
||||
|
@ -14,14 +14,13 @@ pub struct timeval_t {
|
||||
}
|
||||
|
||||
pub fn do_gettimeofday() -> timeval_t {
|
||||
let mut tv : timeval_t = Default::default();
|
||||
let mut tv: timeval_t = Default::default();
|
||||
unsafe {
|
||||
ocall_gettimeofday(&mut tv.sec as *mut time_t,
|
||||
&mut tv.usec as *mut suseconds_t);
|
||||
ocall_gettimeofday(&mut tv.sec as *mut time_t, &mut tv.usec as *mut suseconds_t);
|
||||
}
|
||||
tv
|
||||
}
|
||||
|
||||
extern {
|
||||
extern "C" {
|
||||
fn ocall_gettimeofday(sec: *mut time_t, usec: *mut suseconds_t) -> sgx_status_t;
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
use super::*;
|
||||
use std::ffi::{CStr, CString};
|
||||
use std::{ptr};
|
||||
use std::ptr;
|
||||
|
||||
/// Memory utilities that deals with primitive types passed from user process
|
||||
/// running inside enclave
|
||||
@ -28,9 +28,7 @@ pub mod from_user {
|
||||
}
|
||||
|
||||
/// Clone a C-string from the user process safely
|
||||
pub fn clone_cstring_safely(out_ptr: *const c_char)
|
||||
-> Result<CString, Error>
|
||||
{
|
||||
pub fn clone_cstring_safely(out_ptr: *const c_char) -> Result<CString, Error> {
|
||||
check_ptr(out_ptr)?;
|
||||
// TODO: using from_ptr directly is not safe
|
||||
let cstr = unsafe { CStr::from_ptr(out_ptr) };
|
||||
@ -41,18 +39,20 @@ pub mod from_user {
|
||||
/// Clone a C-string array (const char*[]) from the user process safely
|
||||
///
|
||||
/// This array must be ended with a NULL pointer.
|
||||
pub fn clone_cstrings_safely(user_ptr: *const *const c_char)
|
||||
-> Result<Vec<CString>, Error>
|
||||
{
|
||||
pub fn clone_cstrings_safely(user_ptr: *const *const c_char) -> Result<Vec<CString>, Error> {
|
||||
let mut cstrings = Vec::new();
|
||||
if user_ptr == ptr::null() { return Ok(cstrings); }
|
||||
if user_ptr == ptr::null() {
|
||||
return Ok(cstrings);
|
||||
}
|
||||
|
||||
let mut user_ptr = user_ptr;
|
||||
loop {
|
||||
check_ptr(user_ptr);
|
||||
let cstr_ptr = {
|
||||
let cstr_ptr = unsafe { *user_ptr };
|
||||
if cstr_ptr == ptr::null() { break; }
|
||||
if cstr_ptr == ptr::null() {
|
||||
break;
|
||||
}
|
||||
check_ptr(cstr_ptr);
|
||||
cstr_ptr
|
||||
};
|
||||
@ -80,9 +80,7 @@ pub mod from_untrusted {
|
||||
}
|
||||
|
||||
/// Clone a C-string from outside the enclave
|
||||
pub fn clone_cstring_safely(out_ptr: *const c_char)
|
||||
-> Result<CString, Error>
|
||||
{
|
||||
pub fn clone_cstring_safely(out_ptr: *const c_char) -> Result<CString, Error> {
|
||||
check_ptr(out_ptr)?;
|
||||
// TODO: using from_ptr directly is not safe
|
||||
let cstr = unsafe { CStr::from_ptr(out_ptr) };
|
||||
@ -93,18 +91,20 @@ pub mod from_untrusted {
|
||||
/// Clone a C-string array (const char*[]) from outside the enclave
|
||||
///
|
||||
/// This array must be ended with a NULL pointer.
|
||||
pub fn clone_cstrings_safely(out_ptr: *const *const c_char)
|
||||
-> Result<Vec<CString>, Error>
|
||||
{
|
||||
pub fn clone_cstrings_safely(out_ptr: *const *const c_char) -> Result<Vec<CString>, Error> {
|
||||
let mut cstrings = Vec::new();
|
||||
if out_ptr == ptr::null() { return Ok(cstrings); }
|
||||
if out_ptr == ptr::null() {
|
||||
return Ok(cstrings);
|
||||
}
|
||||
|
||||
let mut out_ptr = out_ptr;
|
||||
loop {
|
||||
check_ptr(out_ptr);
|
||||
let cstr_ptr = {
|
||||
let cstr_ptr = unsafe { *out_ptr };
|
||||
if cstr_ptr == ptr::null() { break; }
|
||||
if cstr_ptr == ptr::null() {
|
||||
break;
|
||||
}
|
||||
check_ptr(cstr_ptr);
|
||||
cstr_ptr
|
||||
};
|
||||
@ -116,4 +116,3 @@ pub mod from_untrusted {
|
||||
Ok(cstrings)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
use super::*;
|
||||
|
||||
pub mod mem_util;
|
||||
pub mod mpx_util;
|
||||
pub mod ring_buf;
|
||||
pub mod mem_util;
|
||||
|
@ -1,9 +1,9 @@
|
||||
use super::*;
|
||||
|
||||
pub fn mpx_enable() -> Result<(), Error> {
|
||||
match unsafe { __mpx_enable () } {
|
||||
0 => { Ok(()) }
|
||||
_ => { errno!(EPERM, "MPX cannot be enabled") }
|
||||
match unsafe { __mpx_enable() } {
|
||||
0 => Ok(()),
|
||||
_ => errno!(EPERM, "MPX cannot be enabled"),
|
||||
}
|
||||
}
|
||||
|
||||
@ -47,8 +47,7 @@ pub fn mpx_bndcu(bndreg: MpxReg, addr: usize) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
extern {
|
||||
extern "C" {
|
||||
// See mpx_util.h
|
||||
fn __mpx_enable() -> i32;
|
||||
fn __mpx_bndmk0(base: usize, size: usize);
|
||||
|
@ -1,8 +1,8 @@
|
||||
use super::{*};
|
||||
use super::*;
|
||||
use std::cmp::{max, min};
|
||||
use std::ptr;
|
||||
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
|
||||
use std::sync::Arc;
|
||||
use std::sync::atomic::{AtomicUsize, AtomicBool, Ordering};
|
||||
use std::cmp::{min, max};
|
||||
use std::{ptr};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct RingBuf {
|
||||
@ -13,9 +13,14 @@ pub struct RingBuf {
|
||||
impl RingBuf {
|
||||
pub fn new(capacity: usize) -> RingBuf {
|
||||
let inner = Arc::new(RingBufInner::new(capacity));
|
||||
let reader = RingBufReader { inner: inner.clone() };
|
||||
let reader = RingBufReader {
|
||||
inner: inner.clone(),
|
||||
};
|
||||
let writer = RingBufWriter { inner: inner };
|
||||
RingBuf { reader: reader, writer: writer }
|
||||
RingBuf {
|
||||
reader: reader,
|
||||
writer: writer,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -108,7 +113,6 @@ impl Drop for RingBufInner {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl RingBufReader {
|
||||
pub fn read(&self, buf: &mut [u8]) -> Result<usize, Error> {
|
||||
let mut tail = self.inner.get_tail();
|
||||
@ -123,7 +127,9 @@ impl RingBufReader {
|
||||
} else {
|
||||
self.inner.capacity - tail
|
||||
};
|
||||
if may_read_nbytes == 0 { break; }
|
||||
if may_read_nbytes == 0 {
|
||||
break;
|
||||
}
|
||||
|
||||
min(may_read_nbytes, buf_remain)
|
||||
};
|
||||
@ -150,7 +156,6 @@ impl Drop for RingBufReader {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl RingBufWriter {
|
||||
pub fn write(&self, buf: &[u8]) -> Result<usize, Error> {
|
||||
if self.inner.is_closed() {
|
||||
@ -169,7 +174,9 @@ impl RingBufWriter {
|
||||
} else {
|
||||
tail - head - 1
|
||||
};
|
||||
if may_write_nbytes == 0 { break; }
|
||||
if may_write_nbytes == 0 {
|
||||
break;
|
||||
}
|
||||
|
||||
min(may_write_nbytes, buf_remain)
|
||||
};
|
||||
|
@ -1,25 +1,23 @@
|
||||
use prelude::*;
|
||||
use std::{fmt};
|
||||
use fs::{off_t, FileDesc};
|
||||
use process::{Process, ProcessRef, get_current};
|
||||
use prelude::*;
|
||||
use process::{get_current, Process, ProcessRef};
|
||||
use std::fmt;
|
||||
|
||||
// TODO: Rename VMSpace to VMUniverse
|
||||
|
||||
#[macro_use]
|
||||
mod vm_range;
|
||||
mod vm_space;
|
||||
mod vm_domain;
|
||||
mod vm_area;
|
||||
mod process_vm;
|
||||
mod vm_area;
|
||||
mod vm_domain;
|
||||
mod vm_space;
|
||||
|
||||
pub use self::process_vm::ProcessVM;
|
||||
pub use self::vm_range::{VMRange, VMRangeTrait};
|
||||
pub use self::process_vm::{ProcessVM};
|
||||
|
||||
// TODO: separate proc and flags
|
||||
// TODO: accept fd and offset
|
||||
pub fn do_mmap(addr: usize, size: usize, flags: VMAreaFlags)
|
||||
-> Result<usize, Error>
|
||||
{
|
||||
pub fn do_mmap(addr: usize, size: usize, flags: VMAreaFlags) -> Result<usize, Error> {
|
||||
let current_ref = get_current();
|
||||
let mut current_process = current_ref.lock().unwrap();
|
||||
let current_vm = current_process.get_vm_mut();
|
||||
@ -34,9 +32,11 @@ pub fn do_munmap(addr: usize, size: usize) -> Result<(), Error> {
|
||||
}
|
||||
|
||||
// TODO: accept flags
|
||||
pub fn do_mremap(old_addr: usize, old_size: usize, options: &VMResizeOptions)
|
||||
-> Result<usize, Error>
|
||||
{
|
||||
pub fn do_mremap(
|
||||
old_addr: usize,
|
||||
old_size: usize,
|
||||
options: &VMResizeOptions,
|
||||
) -> Result<usize, Error> {
|
||||
let current_ref = get_current();
|
||||
let mut current_process = current_ref.lock().unwrap();
|
||||
let current_vm = current_process.get_vm_mut();
|
||||
@ -50,8 +50,7 @@ pub fn do_brk(addr: usize) -> Result<usize, Error> {
|
||||
current_vm.brk(addr)
|
||||
}
|
||||
|
||||
|
||||
pub const PAGE_SIZE : usize = 4096;
|
||||
pub const PAGE_SIZE: usize = 4096;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct VMSpace {
|
||||
@ -70,7 +69,6 @@ pub struct VMArea {
|
||||
flags: VMAreaFlags,
|
||||
}
|
||||
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
pub enum VMGuardAreaType {
|
||||
None,
|
||||
@ -78,7 +76,6 @@ pub enum VMGuardAreaType {
|
||||
Dynamic { size: usize },
|
||||
}
|
||||
|
||||
|
||||
#[derive(Copy, Clone, Debug, Default, PartialEq)]
|
||||
pub struct VMAreaFlags(pub u32);
|
||||
|
||||
@ -100,8 +97,6 @@ impl VMAreaFlags {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
#[derive(Clone, Copy, PartialEq)]
|
||||
pub struct VMAllocOptions {
|
||||
size: usize,
|
||||
@ -114,7 +109,10 @@ impl VMAllocOptions {
|
||||
if size % PAGE_SIZE != 0 {
|
||||
return Err(Error::new(Errno::EINVAL, "Size is not page-aligned"));
|
||||
}
|
||||
Ok(VMAllocOptions { size, ..Default::default() })
|
||||
Ok(VMAllocOptions {
|
||||
size,
|
||||
..Default::default()
|
||||
})
|
||||
}
|
||||
|
||||
pub fn addr(&mut self, addr: VMAddrOption) -> Result<&mut Self, Error> {
|
||||
@ -133,13 +131,16 @@ impl VMAllocOptions {
|
||||
|
||||
impl fmt::Debug for VMAllocOptions {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "VMAllocOptions {{ size: 0x{:X?}, addr: {:?}, growth: {:?} }}",
|
||||
self.size, self.addr, self.growth)
|
||||
write!(
|
||||
f,
|
||||
"VMAllocOptions {{ size: 0x{:X?}, addr: {:?}, growth: {:?} }}",
|
||||
self.size, self.addr, self.growth
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for VMAllocOptions {
|
||||
fn default() -> VMAllocOptions{
|
||||
fn default() -> VMAllocOptions {
|
||||
VMAllocOptions {
|
||||
size: 0,
|
||||
addr: VMAddrOption::Any,
|
||||
@ -148,7 +149,6 @@ impl Default for VMAllocOptions {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
pub enum VMAddrOption {
|
||||
Any, // Free to choose any address
|
||||
@ -167,15 +167,14 @@ impl VMAddrOption {
|
||||
|
||||
pub fn get_addr(&self) -> usize {
|
||||
match self {
|
||||
VMAddrOption::Hint(addr) |
|
||||
VMAddrOption::Fixed(addr) |
|
||||
VMAddrOption::Beyond(addr) => *addr,
|
||||
VMAddrOption::Hint(addr) | VMAddrOption::Fixed(addr) | VMAddrOption::Beyond(addr) => {
|
||||
*addr
|
||||
}
|
||||
VMAddrOption::Any => panic!("No address given"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// How VMRange may grow:
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
pub enum VMGrowthType {
|
||||
@ -184,7 +183,6 @@ pub enum VMGrowthType {
|
||||
Fixed,
|
||||
}
|
||||
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct VMResizeOptions {
|
||||
new_size: usize,
|
||||
@ -196,7 +194,10 @@ impl VMResizeOptions {
|
||||
if new_size % PAGE_SIZE != 0 {
|
||||
return Err(Error::new(Errno::EINVAL, "Size is not page-aligned"));
|
||||
}
|
||||
Ok(VMResizeOptions { new_size, ..Default::default() })
|
||||
Ok(VMResizeOptions {
|
||||
new_size,
|
||||
..Default::default()
|
||||
})
|
||||
}
|
||||
|
||||
pub fn addr(&mut self, new_addr: VMAddrOption) -> &mut Self {
|
||||
@ -206,7 +207,7 @@ impl VMResizeOptions {
|
||||
}
|
||||
|
||||
impl Default for VMResizeOptions {
|
||||
fn default() -> VMResizeOptions{
|
||||
fn default() -> VMResizeOptions {
|
||||
VMResizeOptions {
|
||||
new_size: 0,
|
||||
new_addr: None,
|
||||
|
@ -5,8 +5,8 @@ use super::*;
|
||||
lazy_static! {
|
||||
static ref DATA_SPACE: SgxMutex<VMSpace> = {
|
||||
let (addr, size) = {
|
||||
let mut addr : usize = 0;
|
||||
let mut size : usize = 0;
|
||||
let mut addr: usize = 0;
|
||||
let mut size: usize = 0;
|
||||
unsafe { vm_get_prealloced_data_space(&mut addr, &mut size) };
|
||||
(addr, size)
|
||||
};
|
||||
@ -20,7 +20,7 @@ lazy_static! {
|
||||
};
|
||||
}
|
||||
|
||||
extern {
|
||||
extern "C" {
|
||||
pub fn vm_get_prealloced_data_space(addr: &mut usize, size: &mut usize);
|
||||
}
|
||||
|
||||
@ -37,18 +37,23 @@ pub struct ProcessVM {
|
||||
}
|
||||
|
||||
impl ProcessVM {
|
||||
pub fn new(code_size: usize, data_size: usize,
|
||||
heap_size: usize, stack_size: usize,
|
||||
mmap_size: usize)
|
||||
-> Result<ProcessVM, Error>
|
||||
{
|
||||
pub fn new(
|
||||
code_size: usize,
|
||||
data_size: usize,
|
||||
heap_size: usize,
|
||||
stack_size: usize,
|
||||
mmap_size: usize,
|
||||
) -> Result<ProcessVM, Error> {
|
||||
let data_domain_size = code_size + data_size + heap_size + stack_size + mmap_size;
|
||||
let mut data_domain = DATA_SPACE.lock().unwrap().
|
||||
alloc_domain(data_domain_size)?;
|
||||
let mut data_domain = DATA_SPACE.lock().unwrap().alloc_domain(data_domain_size)?;
|
||||
|
||||
let (code_vma, data_vma, heap_vma, stack_vma) =
|
||||
ProcessVM::alloc_vmas(&mut data_domain, code_size, data_size,
|
||||
heap_size, stack_size)?;
|
||||
let (code_vma, data_vma, heap_vma, stack_vma) = ProcessVM::alloc_vmas(
|
||||
&mut data_domain,
|
||||
code_size,
|
||||
data_size,
|
||||
heap_size,
|
||||
stack_size,
|
||||
)?;
|
||||
// Initial value of the program break
|
||||
let brk = heap_vma.get_start();
|
||||
// No mmapped vmas initially
|
||||
@ -66,14 +71,17 @@ impl ProcessVM {
|
||||
Ok(vm)
|
||||
}
|
||||
|
||||
fn alloc_vmas(data_domain: &mut VMDomain,
|
||||
code_size: usize, data_size: usize,
|
||||
heap_size: usize, stack_size: usize)
|
||||
-> Result<(VMArea, VMArea, VMArea, VMArea), Error>
|
||||
{
|
||||
fn alloc_vmas(
|
||||
data_domain: &mut VMDomain,
|
||||
code_size: usize,
|
||||
data_size: usize,
|
||||
heap_size: usize,
|
||||
stack_size: usize,
|
||||
) -> Result<(VMArea, VMArea, VMArea, VMArea), Error> {
|
||||
let mut addr = data_domain.get_start();
|
||||
|
||||
let mut alloc_vma_continuously = |addr: &mut usize, size, flags, growth| -> Result<_, Error> {
|
||||
let mut alloc_vma_continuously =
|
||||
|addr: &mut usize, size, flags, growth| -> Result<_, Error> {
|
||||
let mut options = VMAllocOptions::new(size)?;
|
||||
options.addr(VMAddrOption::Fixed(*addr))?.growth(growth)?;
|
||||
let new_vma = data_domain.alloc_area(&options, flags)?;
|
||||
@ -84,21 +92,14 @@ impl ProcessVM {
|
||||
let rx_flags = VMAreaFlags(VM_AREA_FLAG_R | VM_AREA_FLAG_X);
|
||||
let rw_flags = VMAreaFlags(VM_AREA_FLAG_R | VM_AREA_FLAG_W);
|
||||
|
||||
let code_vma = alloc_vma_continuously(&mut addr,
|
||||
code_size, rx_flags,
|
||||
VMGrowthType::Fixed)?;
|
||||
let data_vma = alloc_vma_continuously(&mut addr,
|
||||
data_size, rw_flags,
|
||||
VMGrowthType::Fixed)?;
|
||||
let heap_vma = alloc_vma_continuously(&mut addr,
|
||||
0, rw_flags,
|
||||
VMGrowthType::Upward)?;
|
||||
let code_vma = alloc_vma_continuously(&mut addr, code_size, rx_flags, VMGrowthType::Fixed)?;
|
||||
let data_vma = alloc_vma_continuously(&mut addr, data_size, rw_flags, VMGrowthType::Fixed)?;
|
||||
let heap_vma = alloc_vma_continuously(&mut addr, 0, rw_flags, VMGrowthType::Upward)?;
|
||||
// Preserve the space for heap
|
||||
addr += heap_size;
|
||||
// After the heap is the stack
|
||||
let stack_vma = alloc_vma_continuously(&mut addr,
|
||||
stack_size, rw_flags,
|
||||
VMGrowthType::Downward)?;
|
||||
let stack_vma =
|
||||
alloc_vma_continuously(&mut addr, stack_size, rw_flags, VMGrowthType::Downward)?;
|
||||
Ok((code_vma, data_vma, heap_vma, stack_vma))
|
||||
}
|
||||
|
||||
@ -143,25 +144,21 @@ impl ProcessVM {
|
||||
}
|
||||
|
||||
// TODO: support overriding the mmaping of already mmaped range
|
||||
pub fn mmap(&mut self, addr: usize, size: usize, flags: VMAreaFlags)
|
||||
-> Result<usize, Error>
|
||||
{
|
||||
pub fn mmap(&mut self, addr: usize, size: usize, flags: VMAreaFlags) -> Result<usize, Error> {
|
||||
let alloc_options = {
|
||||
let mmap_start_addr = self.get_mmap_start();
|
||||
|
||||
let mut alloc_options = VMAllocOptions::new(size)?;
|
||||
alloc_options.addr(
|
||||
if addr == 0 {
|
||||
alloc_options
|
||||
.addr(if addr == 0 {
|
||||
VMAddrOption::Beyond(mmap_start_addr)
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
if addr < mmap_start_addr {
|
||||
return Err(Error::new(Errno::EINVAL,
|
||||
"Beyond valid memory range"));
|
||||
return Err(Error::new(Errno::EINVAL, "Beyond valid memory range"));
|
||||
}
|
||||
VMAddrOption::Fixed(addr)
|
||||
}
|
||||
)?.growth(VMGrowthType::Upward)?;
|
||||
})?
|
||||
.growth(VMGrowthType::Upward)?;
|
||||
alloc_options
|
||||
};
|
||||
// TODO: when failed, try to resize data_domain
|
||||
@ -171,18 +168,19 @@ impl ProcessVM {
|
||||
Ok(addr)
|
||||
}
|
||||
|
||||
pub fn munmap(&mut self, addr: usize, size: usize)
|
||||
-> Result<(), Error>
|
||||
{
|
||||
pub fn munmap(&mut self, addr: usize, size: usize) -> Result<(), Error> {
|
||||
// TODO: handle the case when the given range [addr, addr + size)
|
||||
// does not match exactly with any vma. For example, when this range
|
||||
// cover multiple ranges or cover some range partially.
|
||||
|
||||
let mmap_vma_i = {
|
||||
let mmap_vma_i = self.get_mmap_vmas().iter().position(|vma| {
|
||||
vma.get_start() == addr && vma.get_end() == addr + size
|
||||
});
|
||||
if mmap_vma_i.is_none() { return Ok(()) }
|
||||
let mmap_vma_i = self
|
||||
.get_mmap_vmas()
|
||||
.iter()
|
||||
.position(|vma| vma.get_start() == addr && vma.get_end() == addr + size);
|
||||
if mmap_vma_i.is_none() {
|
||||
return Ok(());
|
||||
}
|
||||
mmap_vma_i.unwrap()
|
||||
};
|
||||
|
||||
@ -191,10 +189,12 @@ impl ProcessVM {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn mremap(&mut self, old_addr: usize, old_size: usize,
|
||||
options: &VMResizeOptions)
|
||||
-> Result<usize, Error>
|
||||
{
|
||||
pub fn mremap(
|
||||
&mut self,
|
||||
old_addr: usize,
|
||||
old_size: usize,
|
||||
options: &VMResizeOptions,
|
||||
) -> Result<usize, Error> {
|
||||
// TODO: Implement this!
|
||||
Err(Error::new(Errno::EINVAL, "Not implemented"))
|
||||
}
|
||||
@ -202,11 +202,9 @@ impl ProcessVM {
|
||||
pub fn brk(&mut self, new_brk: usize) -> Result<usize, Error> {
|
||||
if new_brk == 0 {
|
||||
return Ok(self.get_brk());
|
||||
}
|
||||
else if new_brk < self.heap_vma.get_start() {
|
||||
} else if new_brk < self.heap_vma.get_start() {
|
||||
return errno!(EINVAL, "New brk address is too low");
|
||||
}
|
||||
else if new_brk <= self.heap_vma.get_end() {
|
||||
} else if new_brk <= self.heap_vma.get_end() {
|
||||
self.brk = new_brk;
|
||||
return Ok(new_brk);
|
||||
}
|
||||
@ -219,12 +217,12 @@ impl ProcessVM {
|
||||
options.addr(VMAddrOption::Fixed(brk_start));
|
||||
options
|
||||
};
|
||||
self.data_domain.resize_area(&mut self.heap_vma, &resize_options)?;
|
||||
self.data_domain
|
||||
.resize_area(&mut self.heap_vma, &resize_options)?;
|
||||
Ok(new_brk)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl Drop for ProcessVM {
|
||||
fn drop(&mut self) {
|
||||
let data_domain = &mut self.data_domain;
|
||||
|
@ -1,7 +1,11 @@
|
||||
use super::*;
|
||||
|
||||
impl VMDomain {
|
||||
pub fn alloc_area(&mut self, options: &VMAllocOptions, flags: VMAreaFlags) -> Result<VMArea, Error> {
|
||||
pub fn alloc_area(
|
||||
&mut self,
|
||||
options: &VMAllocOptions,
|
||||
flags: VMAreaFlags,
|
||||
) -> Result<VMArea, Error> {
|
||||
let new_range = self.range.alloc_subrange(options)?;
|
||||
|
||||
// Init the memory area with all zeros
|
||||
@ -11,22 +15,27 @@ impl VMDomain {
|
||||
memset(mem_ptr, 0 as c_int, mem_size);
|
||||
}
|
||||
|
||||
Ok(VMArea { range: new_range, flags: flags })
|
||||
Ok(VMArea {
|
||||
range: new_range,
|
||||
flags: flags,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn dealloc_area(&mut self, area: &mut VMArea) {
|
||||
self.range.dealloc_subrange(&mut area.range)
|
||||
}
|
||||
|
||||
pub fn resize_area(&mut self, area: &mut VMArea, options: &VMResizeOptions)
|
||||
-> Result<(), Error>
|
||||
{
|
||||
pub fn resize_area(
|
||||
&mut self,
|
||||
area: &mut VMArea,
|
||||
options: &VMResizeOptions,
|
||||
) -> Result<(), Error> {
|
||||
// TODO: init memory with zeros when expanding!
|
||||
self.range.resize_subrange(&mut area.range, options)
|
||||
}
|
||||
}
|
||||
|
||||
#[link(name = "sgx_tstdc")]
|
||||
extern {
|
||||
extern "C" {
|
||||
pub fn memset(p: *mut c_void, c: c_int, n: size_t) -> *mut c_void;
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
use super::*;
|
||||
use std::{fmt};
|
||||
use std::fmt;
|
||||
|
||||
pub trait VMRangeTrait {
|
||||
fn get_start(&self) -> usize;
|
||||
@ -32,7 +32,7 @@ macro_rules! impl_vmrange_trait_for {
|
||||
self.$field.contains_obj(ptr, size)
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
impl_vmrange_trait_for!(VMRange, inner);
|
||||
@ -40,7 +40,6 @@ impl_vmrange_trait_for!(VMSpace, range);
|
||||
impl_vmrange_trait_for!(VMDomain, range);
|
||||
impl_vmrange_trait_for!(VMArea, range);
|
||||
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct VMRange {
|
||||
inner: VMRangeInner,
|
||||
@ -74,7 +73,7 @@ impl VMRange {
|
||||
// Find a free space for allocating a VMRange
|
||||
let free_space = {
|
||||
// Look for the minimal big-enough free space
|
||||
let mut min_big_enough_free_space : Option<FreeSpace> = None;
|
||||
let mut min_big_enough_free_space: Option<FreeSpace> = None;
|
||||
let sub_ranges = self.get_subranges();
|
||||
for (idx, range_pair) in sub_ranges.windows(2).enumerate() {
|
||||
let pre_range = &range_pair[0];
|
||||
@ -85,18 +84,24 @@ impl VMRange {
|
||||
let free_range_end = next_range.get_start();
|
||||
|
||||
let free_range_size = free_range_end - free_range_start;
|
||||
if free_range_size < size { continue }
|
||||
if free_range_size < size {
|
||||
continue;
|
||||
}
|
||||
|
||||
free_range_start..free_range_end
|
||||
};
|
||||
|
||||
match addr {
|
||||
VMAddrOption::Hint(addr) | VMAddrOption::Fixed(addr) => {
|
||||
if !free_range.contains(&addr) { continue }
|
||||
if !free_range.contains(&addr) {
|
||||
continue;
|
||||
}
|
||||
free_range.start = addr;
|
||||
}
|
||||
VMAddrOption::Beyond(addr) => {
|
||||
if free_range.start < addr { continue }
|
||||
if free_range.start < addr {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
@ -105,20 +110,18 @@ impl VMRange {
|
||||
index_in_subranges: idx + 1,
|
||||
start: free_range.start,
|
||||
end: free_range.end,
|
||||
may_neighbor_grow: (pre_range.growth == VMGrowthType::Upward,
|
||||
next_range.growth == VMGrowthType::Downward),
|
||||
may_neighbor_grow: (
|
||||
pre_range.growth == VMGrowthType::Upward,
|
||||
next_range.growth == VMGrowthType::Downward,
|
||||
),
|
||||
});
|
||||
|
||||
if min_big_enough_free_space == None ||
|
||||
free_space < min_big_enough_free_space
|
||||
{
|
||||
if min_big_enough_free_space == None || free_space < min_big_enough_free_space {
|
||||
min_big_enough_free_space = free_space;
|
||||
|
||||
match addr {
|
||||
VMAddrOption::Hint(addr) | VMAddrOption::Fixed(addr) => {
|
||||
break
|
||||
}
|
||||
_ => {},
|
||||
VMAddrOption::Hint(addr) | VMAddrOption::Fixed(addr) => break,
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -133,18 +136,14 @@ impl VMRange {
|
||||
let (new_subrange_start, new_subrange_end) = match addr {
|
||||
VMAddrOption::Any | VMAddrOption::Beyond(_) => {
|
||||
let should_no_gap_to_pre_domain =
|
||||
free_space.may_neighbor_grow.0 == false &&
|
||||
growth != VMGrowthType::Downward;
|
||||
free_space.may_neighbor_grow.0 == false && growth != VMGrowthType::Downward;
|
||||
let should_no_gap_to_next_domain =
|
||||
free_space.may_neighbor_grow.1 == false &&
|
||||
growth != VMGrowthType::Upward;
|
||||
free_space.may_neighbor_grow.1 == false && growth != VMGrowthType::Upward;
|
||||
let domain_start = if should_no_gap_to_pre_domain {
|
||||
free_space.start
|
||||
}
|
||||
else if should_no_gap_to_next_domain {
|
||||
} else if should_no_gap_to_next_domain {
|
||||
free_space.end - size
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
// We want to leave some space at both ends in case
|
||||
// this sub-range or neighbor sub-range needs to grow later.
|
||||
// As a simple heuristic, we put this sub-range near the
|
||||
@ -153,18 +152,15 @@ impl VMRange {
|
||||
};
|
||||
(domain_start, domain_start + size)
|
||||
}
|
||||
VMAddrOption::Fixed(addr) => {
|
||||
(addr, addr + size)
|
||||
}
|
||||
VMAddrOption::Fixed(addr) => (addr, addr + size),
|
||||
VMAddrOption::Hint(addr) => {
|
||||
return errno!(EINVAL, "Not implemented");
|
||||
}
|
||||
};
|
||||
|
||||
let new_subrange_inner = VMRangeInner::new(new_subrange_start,
|
||||
new_subrange_end, growth);
|
||||
self.get_subranges_mut().insert(free_space.index_in_subranges,
|
||||
new_subrange_inner);
|
||||
let new_subrange_inner = VMRangeInner::new(new_subrange_start, new_subrange_end, growth);
|
||||
self.get_subranges_mut()
|
||||
.insert(free_space.index_in_subranges, new_subrange_inner);
|
||||
// Although there are two copies of the newly created VMRangeInner obj,
|
||||
// we can keep them in sync as all mutation on VMRange object must
|
||||
// be carried out through dealloc_subrange() and resize_subrange() that
|
||||
@ -189,7 +185,8 @@ impl VMRange {
|
||||
self.get_subranges_mut().remove(domain_i);
|
||||
|
||||
// When all sub-ranges are removed, remove the sub-range array
|
||||
if self.get_subranges().len() == 2 { // two sentinel sub-ranges excluded
|
||||
if self.get_subranges().len() == 2 {
|
||||
// two sentinel sub-ranges excluded
|
||||
self.sub_ranges = None;
|
||||
}
|
||||
|
||||
@ -197,8 +194,11 @@ impl VMRange {
|
||||
subrange.mark_as_dealloced();
|
||||
}
|
||||
|
||||
pub fn resize_subrange(&mut self, subrange: &mut VMRange, options: &VMResizeOptions)
|
||||
-> Result<(), Error> {
|
||||
pub fn resize_subrange(
|
||||
&mut self,
|
||||
subrange: &mut VMRange,
|
||||
options: &VMResizeOptions,
|
||||
) -> Result<(), Error> {
|
||||
self.ensure_subrange_is_a_child(subrange);
|
||||
|
||||
// Get valid parameters from options
|
||||
@ -243,7 +243,10 @@ impl VMRange {
|
||||
|
||||
fn position_subrange(&self, subrange: &VMRange) -> usize {
|
||||
let sub_ranges = self.get_subranges();
|
||||
sub_ranges.iter().position(|d| d == &subrange.inner).unwrap()
|
||||
sub_ranges
|
||||
.iter()
|
||||
.position(|d| d == &subrange.inner)
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
fn get_subranges(&self) -> &Vec<VMRangeInner> {
|
||||
@ -258,9 +261,7 @@ impl VMRange {
|
||||
self.sub_ranges.is_some()
|
||||
}
|
||||
|
||||
fn shrink_subrange_to(&mut self, subrange: &mut VMRange, new_size: usize)
|
||||
-> Result<(), Error>
|
||||
{
|
||||
fn shrink_subrange_to(&mut self, subrange: &mut VMRange, new_size: usize) -> Result<(), Error> {
|
||||
let subrange_i = self.position_subrange(subrange);
|
||||
let subranges = self.get_subranges_mut();
|
||||
|
||||
@ -268,13 +269,10 @@ impl VMRange {
|
||||
// Can we do shrink?
|
||||
let min_new_size = match subrange.sub_ranges.as_mut() {
|
||||
Some(child_subranges) => {
|
||||
let child_last_subrange = &child_subranges[
|
||||
child_subranges.len() - 2];
|
||||
let child_last_subrange = &child_subranges[child_subranges.len() - 2];
|
||||
child_last_subrange.end - subrange.inner.start
|
||||
}
|
||||
None => {
|
||||
0
|
||||
}
|
||||
None => 0,
|
||||
};
|
||||
if new_size < min_new_size {
|
||||
return errno!(ENOMEM, "Cannot shrink to new size");
|
||||
@ -284,17 +282,15 @@ impl VMRange {
|
||||
subrange.inner.end = new_subrange_end;
|
||||
// Sync state
|
||||
subranges[subrange_i].end = new_subrange_end;
|
||||
}
|
||||
else { // self.growth == VMGrowthType::Downward
|
||||
} else {
|
||||
// self.growth == VMGrowthType::Downward
|
||||
// Can we do shrink?
|
||||
let min_new_size = match subrange.sub_ranges.as_mut() {
|
||||
Some(child_subranges) => {
|
||||
let child_first_subrange = &child_subranges[1];
|
||||
subrange.inner.end - child_first_subrange.start
|
||||
}
|
||||
None => {
|
||||
0
|
||||
}
|
||||
None => 0,
|
||||
};
|
||||
if new_size < min_new_size {
|
||||
return errno!(ENOMEM, "Cannot shrink to new size");
|
||||
@ -308,9 +304,7 @@ impl VMRange {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn grow_subrange_to(&mut self, subrange: &mut VMRange, new_size: usize)
|
||||
-> Result<(), Error>
|
||||
{
|
||||
fn grow_subrange_to(&mut self, subrange: &mut VMRange, new_size: usize) -> Result<(), Error> {
|
||||
let subrange_i = self.position_subrange(subrange);
|
||||
let subranges = self.get_subranges_mut();
|
||||
|
||||
@ -328,8 +322,8 @@ impl VMRange {
|
||||
subrange.inner.end = subrange_new_end;
|
||||
// Sync state
|
||||
subranges[subrange_i].end = subrange_new_end;
|
||||
}
|
||||
else { // self.growth == VMGrowthType::Downward
|
||||
} else {
|
||||
// self.growth == VMGrowthType::Downward
|
||||
// Can we grow?
|
||||
let max_new_size = {
|
||||
let pre_subrange = &subranges[subrange_i - 1];
|
||||
@ -395,7 +389,6 @@ impl Default for VMRange {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct VMRangeInner {
|
||||
start: usize,
|
||||
@ -404,8 +397,7 @@ pub struct VMRangeInner {
|
||||
}
|
||||
|
||||
impl VMRangeInner {
|
||||
pub fn new(start: usize, end: usize, growth: VMGrowthType) -> VMRangeInner
|
||||
{
|
||||
pub fn new(start: usize, end: usize, growth: VMGrowthType) -> VMRangeInner {
|
||||
VMRangeInner {
|
||||
start: start,
|
||||
end: end,
|
||||
@ -440,8 +432,14 @@ impl VMRangeTrait for VMRangeInner {
|
||||
|
||||
impl fmt::Debug for VMRangeInner {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "VMRangeInner {{ start: 0x{:X?}, end: 0x{:X?}, size: 0x{:X?}, growth: {:?} }}",
|
||||
self.start, self.end, self.get_size(), self.growth)
|
||||
write!(
|
||||
f,
|
||||
"VMRangeInner {{ start: 0x{:X?}, end: 0x{:X?}, size: 0x{:X?}, growth: {:?} }}",
|
||||
self.start,
|
||||
self.end,
|
||||
self.get_size(),
|
||||
self.growth
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ -449,14 +447,11 @@ impl PartialOrd for VMRangeInner {
|
||||
fn partial_cmp(&self, other: &VMRangeInner) -> Option<Ordering> {
|
||||
if self.end <= other.start {
|
||||
return Some(Ordering::Less);
|
||||
}
|
||||
else if self.start >= other.end {
|
||||
} else if self.start >= other.end {
|
||||
return Some(Ordering::Greater);
|
||||
}
|
||||
else if self.start == other.start && self.end == other.end {
|
||||
} else if self.start == other.start && self.end == other.end {
|
||||
return Some(Ordering::Equal);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
@ -468,7 +463,6 @@ impl PartialEq for VMRangeInner {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[derive(Debug)]
|
||||
struct FreeSpace {
|
||||
index_in_subranges: usize,
|
||||
@ -491,8 +485,8 @@ impl FreeSpace {
|
||||
|
||||
impl PartialEq for FreeSpace {
|
||||
fn eq(&self, other: &FreeSpace) -> bool {
|
||||
self.get_size() == other.get_size() &&
|
||||
self.get_neighbor_pressure() == other.get_neighbor_pressure()
|
||||
self.get_size() == other.get_size()
|
||||
&& self.get_neighbor_pressure() == other.get_neighbor_pressure()
|
||||
}
|
||||
}
|
||||
|
||||
@ -502,21 +496,17 @@ impl PartialOrd for FreeSpace {
|
||||
let other_size = other.get_size();
|
||||
if self_size < other_size {
|
||||
Some(Ordering::Less)
|
||||
}
|
||||
else if self_size > other_size {
|
||||
} else if self_size > other_size {
|
||||
Some(Ordering::Greater)
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
// The less neighbor pressure, the larger the free space
|
||||
let self_neighbor_pressure = self.get_neighbor_pressure();
|
||||
let other_neighbor_pressure = other.get_neighbor_pressure();
|
||||
if self_neighbor_pressure > other_neighbor_pressure {
|
||||
Some(Ordering::Less)
|
||||
}
|
||||
else if self_neighbor_pressure < other_neighbor_pressure {
|
||||
} else if self_neighbor_pressure < other_neighbor_pressure {
|
||||
Some(Ordering::Greater)
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
Some(Ordering::Equal)
|
||||
}
|
||||
}
|
||||
|
@ -1,12 +1,12 @@
|
||||
use super::*;
|
||||
|
||||
impl VMSpace {
|
||||
pub unsafe fn new(addr: usize, size: usize, guard_type: VMGuardAreaType)
|
||||
-> Result<VMSpace, Error>
|
||||
{
|
||||
let range = unsafe {
|
||||
VMRange::new(addr, addr + size, VMGrowthType::Fixed)?
|
||||
};
|
||||
pub unsafe fn new(
|
||||
addr: usize,
|
||||
size: usize,
|
||||
guard_type: VMGuardAreaType,
|
||||
) -> Result<VMSpace, Error> {
|
||||
let range = unsafe { VMRange::new(addr, addr + size, VMGrowthType::Fixed)? };
|
||||
Ok(VMSpace { range, guard_type })
|
||||
}
|
||||
|
||||
@ -14,25 +14,19 @@ impl VMSpace {
|
||||
self.guard_type
|
||||
}
|
||||
|
||||
pub fn alloc_domain(&mut self, size: usize)
|
||||
-> Result<VMDomain, Error>
|
||||
{
|
||||
pub fn alloc_domain(&mut self, size: usize) -> Result<VMDomain, Error> {
|
||||
let mut options = VMAllocOptions::new(size)?;
|
||||
options.growth(VMGrowthType::Upward)?;
|
||||
|
||||
let new_range = self.range.alloc_subrange(&options)?;
|
||||
Ok(VMDomain {
|
||||
range: new_range,
|
||||
})
|
||||
Ok(VMDomain { range: new_range })
|
||||
}
|
||||
|
||||
pub fn dealloc_domain(&mut self, domain: &mut VMDomain) {
|
||||
self.range.dealloc_subrange(&mut domain.range)
|
||||
}
|
||||
|
||||
pub fn resize_domain(&mut self, domain: &mut VMDomain, new_size: usize)
|
||||
-> Result<(), Error>
|
||||
{
|
||||
pub fn resize_domain(&mut self, domain: &mut VMDomain, new_size: usize) -> Result<(), Error> {
|
||||
let options = VMResizeOptions::new(new_size)?;
|
||||
self.range.resize_subrange(&mut domain.range, &options)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user