Add argc and argv support
This commit is contained in:
		
							parent
							
								
									ae063cbf90
								
							
						
					
					
						commit
						ad704c421f
					
				| @ -7,7 +7,7 @@ enclave { | ||||
| 
 | ||||
|     trusted { | ||||
|         /* define ECALLs here. */ | ||||
|         public int libos_boot([in, string] const char* executable_path); | ||||
|         public int libos_boot([in, string] const char* executable_path, [user_check] char** argv); | ||||
|         public int libos_run(void); | ||||
|     }; | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										82
									
								
								src/libos/src/entry.rs
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										82
									
								
								src/libos/src/entry.rs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,82 @@ | ||||
| use super::{*}; | ||||
| use util::mem_util::from_untrusted::*; | ||||
| use std::ffi::{CStr, CString, OsString}; | ||||
| use std::path::{Path}; | ||||
| 
 | ||||
| #[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 | ||||
|         }, | ||||
|         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) { | ||||
|                 Ok(()) => 0, | ||||
|                 Err(err) => 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() { | ||||
|                 Ok(exit_status) => exit_status, | ||||
|                 Err(err) => 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; | ||||
| 
 | ||||
| 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() | ||||
|             .ok_or_else(|| Error::new(Errno::EINVAL, "Invalid path"))?; | ||||
|         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"))? | ||||
|     }; | ||||
| 
 | ||||
|     let mut args = clone_cstrings_safely(argv)?; | ||||
|     args.insert(0, program_cstring); | ||||
|     Ok((path_string, args)) | ||||
| } | ||||
| 
 | ||||
| // TODO: make sure do_boot can only be called once
 | ||||
| fn do_boot(path_str: &str, argv: &Vec<CString>) -> Result<(), Error> { | ||||
|     util::mpx_util::mpx_enable()?; | ||||
| 
 | ||||
|     let envp = std::vec::Vec::new(); | ||||
|     let file_actions = Vec::new(); | ||||
|     let parent = &process::IDLE_PROCESS; | ||||
|     process::do_spawn(&path_str, argv, &envp, &file_actions, parent)?; | ||||
| 
 | ||||
|     Ok(()) | ||||
| } | ||||
| 
 | ||||
| // TODO: make sure do_run() cannot be called after do_boot()
 | ||||
| fn do_run() -> Result<i32, Error> { | ||||
|     let exit_status = process::run_task()?; | ||||
|     Ok(exit_status) | ||||
| } | ||||
| @ -1,5 +1,5 @@ | ||||
| use super::*; | ||||
| use util::{new_ring_buf, RingBufReader, RingBufWriter}; | ||||
| use util::ring_buf::{*}; | ||||
| 
 | ||||
| // TODO: Use Waiter and WaitQueue infrastructure to sleep when blocking
 | ||||
| 
 | ||||
| @ -13,13 +13,13 @@ pub struct Pipe { | ||||
| 
 | ||||
| impl Pipe { | ||||
|     pub fn new() -> Result<Pipe, Error> { | ||||
|         let (reader, writer) = new_ring_buf(PIPE_BUF_SIZE); | ||||
|         let mut ring_buf = RingBuf::new(PIPE_BUF_SIZE); | ||||
|         Ok(Pipe { | ||||
|             reader: PipeReader { | ||||
|                 inner: SgxMutex::new(reader), | ||||
|                 inner: SgxMutex::new(ring_buf.reader), | ||||
|             }, | ||||
|             writer: PipeWriter { | ||||
|                 inner: SgxMutex::new(writer), | ||||
|                 inner: SgxMutex::new(ring_buf.writer), | ||||
|             } | ||||
|         }) | ||||
|     } | ||||
|  | ||||
| @ -26,6 +26,7 @@ use sgx_trts::libc; | ||||
| 
 | ||||
| #[macro_use] | ||||
| mod prelude; | ||||
| mod entry; | ||||
| mod errno; | ||||
| mod fs; | ||||
| mod process; | ||||
| @ -36,58 +37,7 @@ mod time; | ||||
| 
 | ||||
| use prelude::*; | ||||
| 
 | ||||
| /// Export system calls
 | ||||
| // Export system calls
 | ||||
| pub use syscall::*; | ||||
| 
 | ||||
| // TODO: return meaningful exit code
 | ||||
| #[no_mangle] | ||||
| pub extern "C" fn libos_boot(path_buf: *const i8) -> i32 { | ||||
|     let path_str = unsafe { | ||||
|         CStr::from_ptr(path_buf).to_string_lossy().into_owned() | ||||
|     }; | ||||
|     let _ = backtrace::enable_backtrace("libocclum.signed.so", PrintFormat::Short); | ||||
|     panic::catch_unwind(||{ | ||||
|         backtrace::__rust_begin_short_backtrace(||{ | ||||
|             match do_boot(&path_str) { | ||||
|                 Ok(()) => 0, | ||||
|                 Err(err) => 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() { | ||||
|                 Ok(exit_status) => exit_status, | ||||
|                 Err(err) => 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; | ||||
| 
 | ||||
| // TODO: make sure do_boot can only be called once
 | ||||
| fn do_boot(path_str: &str) -> Result<(), Error> { | ||||
|     util::mpx_enable()?; | ||||
| 
 | ||||
|     let argv = std::vec::Vec::new(); | ||||
|     let envp = std::vec::Vec::new(); | ||||
|     let file_actions = Vec::new(); | ||||
|     let parent = &process::IDLE_PROCESS; | ||||
|     process::do_spawn(&path_str, &argv, &envp, &file_actions, parent)?; | ||||
| 
 | ||||
|     Ok(()) | ||||
| } | ||||
| 
 | ||||
| // TODO: make sure do_run() cannot be called before do_boot()
 | ||||
| fn do_run() -> Result<i32, Error> { | ||||
|     let exit_status = process::run_task()?; | ||||
|     Ok(exit_status) | ||||
| } | ||||
| // Export ECalls
 | ||||
| pub use entry::*; | ||||
|  | ||||
| @ -7,6 +7,7 @@ use fs::{off_t, FileDesc}; | ||||
| use vm::{VMAreaFlags, VMResizeOptions}; | ||||
| use process::{pid_t, ChildProcessFilter, FileAction}; | ||||
| use time::{timeval_t}; | ||||
| use util::mem_util::from_user::{*}; | ||||
| // Use the internal syscall wrappers from sgx_tstd
 | ||||
| //use std::libc_fs as fs;
 | ||||
| //use std::libc_io as io;
 | ||||
| @ -17,39 +18,6 @@ pub struct iovec_t { | ||||
|     len: size_t, | ||||
| } | ||||
| 
 | ||||
| fn check_ptr_from_user<T>(user_ptr: *const T) -> Result<(), Error> { | ||||
|     Ok(()) | ||||
| } | ||||
| 
 | ||||
| fn check_mut_ptr_from_user<T>(user_ptr: *mut T) -> Result<(), Error> { | ||||
|     Ok(()) | ||||
| } | ||||
| 
 | ||||
| fn check_array_from_user<T>(user_buf: *const T, count: usize) -> Result<(), Error> { | ||||
|     Ok(()) | ||||
| } | ||||
| 
 | ||||
| fn check_mut_array_from_user<T>(user_buf: *mut T, count: usize) -> Result<(), Error> { | ||||
|     Ok(()) | ||||
| } | ||||
| 
 | ||||
| fn clone_cstring_from_user_safely(user_ptr: *const c_char) | ||||
|     -> Result<String, Error> | ||||
| { | ||||
|     check_ptr_from_user(user_ptr)?; | ||||
|     let string = unsafe { | ||||
|         CStr::from_ptr(user_ptr).to_string_lossy().into_owned() | ||||
|     }; | ||||
|     Ok(string) | ||||
| } | ||||
| 
 | ||||
| fn clone_cstrings_from_user_safely(user_ptr: *const *const c_char) | ||||
|     -> Result<Vec<CString>, Error> | ||||
| { | ||||
|     let cstrings = Vec::new(); | ||||
|     Ok(cstrings) | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /* | ||||
|  * This Rust-version of fdop correspond to the C-version one in Occlum. | ||||
| @ -73,14 +41,14 @@ pub struct FdOp { | ||||
|     path: *const u8, | ||||
| } | ||||
| 
 | ||||
| fn clone_file_actions_from_user_safely(fdop_ptr: *const FdOp) | ||||
| 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; | ||||
|     while fdop_ptr != ptr::null() { | ||||
|         check_ptr_from_user(fdop_ptr)?; | ||||
|         check_ptr(fdop_ptr)?; | ||||
|         let fdop = unsafe { &*fdop_ptr }; | ||||
| 
 | ||||
|         let file_action = match fdop.cmd { | ||||
| @ -113,11 +81,11 @@ fn do_spawn(child_pid_ptr: *mut c_uint, | ||||
|             ) | ||||
|     -> Result<(), Error> | ||||
| { | ||||
|     check_mut_ptr_from_user(child_pid_ptr)?; | ||||
|     let path = clone_cstring_from_user_safely(path)?; | ||||
|     let argv = clone_cstrings_from_user_safely(argv)?; | ||||
|     let envp = clone_cstrings_from_user_safely(envp)?; | ||||
|     let file_actions = clone_file_actions_from_user_safely(fdop_list)?; | ||||
|     check_mut_ptr(child_pid_ptr)?; | ||||
|     let path = clone_cstring_safely(path)?.to_string_lossy().into_owned(); | ||||
|     let argv = clone_cstrings_safely(argv)?; | ||||
|     let envp = clone_cstrings_safely(envp)?; | ||||
|     let file_actions = clone_file_actions_safely(fdop_list)?; | ||||
|     let parent = process::get_current(); | ||||
| 
 | ||||
|     let child_pid = process::do_spawn(&path, &argv, &envp, &file_actions, &parent)?; | ||||
| @ -133,7 +101,7 @@ fn do_read(fd: c_int, buf: *mut c_void, size: size_t) | ||||
|     let safe_buf = { | ||||
|         let buf = buf as *mut u8; | ||||
|         let size = size as usize; | ||||
|         check_mut_array_from_user(buf, size)?; | ||||
|         check_mut_array(buf, size)?; | ||||
|         unsafe { std::slice::from_raw_parts_mut(buf, size) } | ||||
|     }; | ||||
|     fs::do_read(fd, safe_buf) | ||||
| @ -146,7 +114,7 @@ fn do_write(fd: c_int, buf: *const c_void, size: size_t) | ||||
|     let safe_buf = { | ||||
|         let buf = buf as *mut u8; | ||||
|         let size = size as usize; | ||||
|         check_array_from_user(buf, size)?; | ||||
|         check_array(buf, size)?; | ||||
|         unsafe { std::slice::from_raw_parts(buf, size) } | ||||
|     }; | ||||
|     fs::do_write(fd, safe_buf) | ||||
| @ -164,7 +132,7 @@ fn do_writev(fd: c_int, iov: *const iovec_t, count: c_int) | ||||
|         count as usize | ||||
|     }; | ||||
| 
 | ||||
|     check_array_from_user(iov, count); | ||||
|     check_array(iov, count); | ||||
|     let bufs_vec = { | ||||
|         let mut bufs_vec = Vec::with_capacity(count); | ||||
|         for iov_i in 0..count { | ||||
| @ -194,7 +162,7 @@ fn do_readv(fd: c_int, iov: *mut iovec_t, count: c_int) | ||||
|         count as usize | ||||
|     }; | ||||
| 
 | ||||
|     check_array_from_user(iov, count); | ||||
|     check_array(iov, count); | ||||
|     let mut bufs_vec = { | ||||
|         let mut bufs_vec = Vec::with_capacity(count); | ||||
|         for iov_i in 0..count { | ||||
| @ -274,7 +242,7 @@ fn do_brk(new_brk_addr: *const c_void) -> Result<*const c_void, Error> { | ||||
| 
 | ||||
| fn do_wait4(pid: c_int, _exit_status: *mut c_int) -> Result<pid_t, Error> { | ||||
|     if _exit_status != 0 as *mut c_int { | ||||
|         check_mut_ptr_from_user(_exit_status)?; | ||||
|         check_mut_ptr(_exit_status)?; | ||||
|     } | ||||
| 
 | ||||
|     let child_process_filter = match pid { | ||||
| @ -310,7 +278,7 @@ fn do_wait4(pid: c_int, _exit_status: *mut c_int) -> Result<pid_t, Error> { | ||||
| } | ||||
| 
 | ||||
| fn do_pipe2(fds_u: *mut c_int, flags: c_int) -> Result<(), Error> { | ||||
|     check_mut_array_from_user(fds_u, 2)?; | ||||
|     check_mut_array(fds_u, 2)?; | ||||
|     // TODO: how to deal with open flags???
 | ||||
|     let fds = fs::do_pipe2(flags as u32)?; | ||||
|     unsafe { | ||||
| @ -321,7 +289,7 @@ 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_from_user(tv_u)?; | ||||
|     check_mut_ptr(tv_u)?; | ||||
|     let tv = time::do_gettimeofday(); | ||||
|     unsafe { *tv_u = tv; } | ||||
|     Ok(()) | ||||
|  | ||||
							
								
								
									
										110
									
								
								src/libos/src/util/mem_util.rs
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										110
									
								
								src/libos/src/util/mem_util.rs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,110 @@ | ||||
| use super::*; | ||||
| use std::ffi::{CStr, CString}; | ||||
| use std::{ptr}; | ||||
| 
 | ||||
| /// Memory utilities that deals with primitive types passed from user process
 | ||||
| /// running inside enclave
 | ||||
| pub mod from_user { | ||||
|     use super::*; | ||||
| 
 | ||||
|     /// Check the user pointer is within the readable memory range of the user process
 | ||||
|     pub fn check_ptr<T>(user_ptr: *const T) -> Result<(), Error> { | ||||
|         Ok(()) | ||||
|     } | ||||
| 
 | ||||
|     /// Check the mutable user pointer is within the writable memory of the user process
 | ||||
|     pub fn check_mut_ptr<T>(user_ptr: *mut T) -> Result<(), Error> { | ||||
|         Ok(()) | ||||
|     } | ||||
| 
 | ||||
|     /// Check the readonly array is within the readable memory of the user process
 | ||||
|     pub fn check_array<T>(user_buf: *const T, count: usize) -> Result<(), Error> { | ||||
|         Ok(()) | ||||
|     } | ||||
| 
 | ||||
|     /// Check the mutable array is within the writable memory of the user process
 | ||||
|     pub fn check_mut_array<T>(user_buf: *mut T, count: usize) -> Result<(), Error> { | ||||
|         Ok(()) | ||||
|     } | ||||
| 
 | ||||
|     /// Clone a C-string from the user process safely
 | ||||
|     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) }; | ||||
|         let cstring = CString::from(cstr); | ||||
|         Ok(cstring) | ||||
|     } | ||||
| 
 | ||||
|     /// 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> | ||||
|     { | ||||
|         let mut cstrings = Vec::new(); | ||||
|         let mut user_ptr = user_ptr; | ||||
|         while user_ptr != ptr::null() { | ||||
|             let cstr_ptr = unsafe { *user_ptr }; | ||||
|             let cstring = clone_cstring_safely(cstr_ptr)?; | ||||
|             cstrings.push(cstring); | ||||
|             user_ptr = unsafe { user_ptr.offset(1) }; | ||||
|         } | ||||
|         Ok(cstrings) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| /// Memory utilities that deals with primitive types passed from outside the enclave
 | ||||
| pub mod from_untrusted { | ||||
|     use super::*; | ||||
| 
 | ||||
|     /// Check the untrusted pointer is outside the enclave
 | ||||
|     pub fn check_ptr<T>(out_ptr: *const T) -> Result<(), Error> { | ||||
|         Ok(()) | ||||
|     } | ||||
| 
 | ||||
|     /// Check the untrusted array is outside the enclave
 | ||||
|     pub fn check_array<T>(out_ptr: *const T, count: usize) -> Result<(), Error> { | ||||
|         Ok(()) | ||||
|     } | ||||
| 
 | ||||
|     /// Clone a C-string from outside the enclave
 | ||||
|     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) }; | ||||
|         let cstring = CString::from(cstr); | ||||
|         Ok(cstring) | ||||
|     } | ||||
| 
 | ||||
|     /// 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> | ||||
|     { | ||||
|         let mut cstrings = Vec::new(); | ||||
|         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; } | ||||
|                 check_ptr(cstr_ptr); | ||||
|                 cstr_ptr | ||||
|             }; | ||||
|             let cstring = clone_cstring_safely(cstr_ptr)?; | ||||
|             cstrings.push(cstring); | ||||
| 
 | ||||
|             out_ptr = unsafe { out_ptr.offset(1) }; | ||||
|         } | ||||
|         Ok(cstrings) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| @ -1,8 +1,5 @@ | ||||
| use super::*; | ||||
| 
 | ||||
| pub use self::mpx_util::{*}; | ||||
| pub use self::ring_buf::{RingBufReader, RingBufWriter}; | ||||
| pub use self::ring_buf::with_fixed_capacity as new_ring_buf; | ||||
| 
 | ||||
| mod mpx_util; | ||||
| mod ring_buf; | ||||
| pub mod mpx_util; | ||||
| pub mod ring_buf; | ||||
| pub mod mem_util; | ||||
|  | ||||
| @ -4,11 +4,19 @@ use std::sync::atomic::{AtomicUsize, AtomicBool, Ordering}; | ||||
| use std::cmp::{min, max}; | ||||
| use std::{ptr}; | ||||
| 
 | ||||
| pub fn with_fixed_capacity(capacity: usize) -> (RingBufReader, RingBufWriter) { | ||||
|     let inner = Arc::new(RingBufInner::new(capacity)); | ||||
|     let reader = RingBufReader { inner: inner.clone() }; | ||||
|     let writer = RingBufWriter { inner: inner }; | ||||
|     (reader, writer) | ||||
| #[derive(Debug)] | ||||
| pub struct RingBuf { | ||||
|     pub reader: RingBufReader, | ||||
|     pub writer: RingBufWriter, | ||||
| } | ||||
| 
 | ||||
| impl RingBuf { | ||||
|     pub fn new(capacity: usize) -> RingBuf { | ||||
|         let inner = Arc::new(RingBufInner::new(capacity)); | ||||
|         let reader = RingBufReader { inner: inner.clone() }; | ||||
|         let writer = RingBufWriter { inner: inner }; | ||||
|         RingBuf { reader: reader, writer: writer } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #[derive(Debug)] | ||||
|  | ||||
| @ -214,9 +214,9 @@ int SGX_CDECL main(int argc, char *argv[]) | ||||
|     uint32_t sealed_log_size = 1024; | ||||
|     uint8_t sealed_log[1024] = {0}; | ||||
| 
 | ||||
|     if (argc != 2) { | ||||
|         printf("ERROR: The expected number of arguments is 1, but given %d\n\n", argc - 1); | ||||
|         printf("Usage: pal <path_to_executable>\n"); | ||||
|     if (argc < 2) { | ||||
|         printf("ERROR: at least one argument must be provided\n\n"); | ||||
|         printf("Usage: pal <executable> <arg1> <arg2>...\n"); | ||||
|         return -1; | ||||
|     } | ||||
|     const char* executable_path = argv[1]; | ||||
| @ -229,7 +229,7 @@ int SGX_CDECL main(int argc, char *argv[]) | ||||
|         return -1; | ||||
|     } | ||||
| 
 | ||||
|     sgx_ret = libos_boot(global_eid, &status, executable_path); | ||||
|     sgx_ret = libos_boot(global_eid, &status, executable_path, &argv[2]); | ||||
|     if(sgx_ret != SGX_SUCCESS) { | ||||
|         print_error_message(sgx_ret); | ||||
|         return status; | ||||
|  | ||||
| @ -1,7 +1,7 @@ | ||||
| CUR_DIR := $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST)))) | ||||
| PROJECT_DIR := $(realpath $(CUR_DIR)/../) | ||||
| 
 | ||||
| TEST_SUITES := empty hello_world malloc file getpid spawn pipe time | ||||
| TEST_SUITES := empty argv hello_world malloc file getpid spawn pipe time | ||||
| BUILD_TEST_SUITES := $(TEST_SUITES:%=%) | ||||
| RUN_TEST_SUITES := $(TEST_SUITES:%=test-%) | ||||
| CLEAN_TEST_SUITES := $(TEST_SUITES:%=clean-%) | ||||
|  | ||||
							
								
								
									
										14
									
								
								test/argv/Makefile
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										14
									
								
								test/argv/Makefile
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,14 @@ | ||||
| include ../test_common.mk | ||||
| 
 | ||||
| ARGC := 4 | ||||
| ARG1 := 1 | ||||
| ARG2 := arg2 | ||||
| ARG3 := this is a string with spaces | ||||
| 
 | ||||
| EXTRA_C_FLAGS := \
 | ||||
| 	-DEXPECTED_ARGC=$(ARGC) \
 | ||||
| 	-DEXPECTED_ARG1="\"$(ARG1)\"" \
 | ||||
| 	-DEXPECTED_ARG2="\"$(ARG2)\"" \
 | ||||
| 	-DEXPECTED_ARG3="\"$(ARG3)\"" | ||||
| EXTRA_LINK_FLAGS := | ||||
| BIN_ARGS := "$(ARG1)" "$(ARG2)" "$(ARG3)" | ||||
							
								
								
									
										30
									
								
								test/argv/main.c
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										30
									
								
								test/argv/main.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,30 @@ | ||||
| #include <string.h> | ||||
| #include <stdio.h> | ||||
| 
 | ||||
| // Expected arguments are given by Makefile throught macro ARGC, ARG1, ARG2 and
 | ||||
| // ARG3
 | ||||
| const char* expected_argv[EXPECTED_ARGC] = { | ||||
|     "bin.encrypted", | ||||
|     EXPECTED_ARG1, | ||||
|     EXPECTED_ARG2, | ||||
|     EXPECTED_ARG3, | ||||
| }; | ||||
| 
 | ||||
| int main(int argc, char* argv[]) { | ||||
|     if (argc != EXPECTED_ARGC) { | ||||
|         printf("ERROR: expect %d arguments, but %d are given\n", EXPECTED_ARGC, argc); | ||||
|         return -1; | ||||
|     } | ||||
| 
 | ||||
|     for (int arg_i = 0; arg_i < argc; arg_i++) { | ||||
|         const char* actual_arg = argv[arg_i]; | ||||
|         const char* expected_arg = expected_argv[arg_i]; | ||||
|         if (strcmp(actual_arg, expected_arg) != 0) { | ||||
|             printf("ERROR: expect argument %d is %s, but given %s\n", | ||||
|                     arg_i, expected_arg, actual_arg); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     printf("main()'s argc and argv are as expected\n"); | ||||
|     return 0; | ||||
| } | ||||
| @ -2,3 +2,4 @@ include ../test_common.mk | ||||
| 
 | ||||
| EXTRA_C_FLAGS := | ||||
| EXTRA_LINK_FLAGS := | ||||
| BIN_ARGS := | ||||
|  | ||||
| @ -2,3 +2,4 @@ include ../test_common.mk | ||||
| 
 | ||||
| EXTRA_C_FLAGS := | ||||
| EXTRA_LINK_FLAGS := | ||||
| BIN_ARGS := | ||||
|  | ||||
| @ -2,3 +2,4 @@ include ../test_common.mk | ||||
| 
 | ||||
| EXTRA_C_FLAGS := | ||||
| EXTRA_LINK_FLAGS := | ||||
| BIN_ARGS := | ||||
|  | ||||
| @ -2,3 +2,4 @@ include ../test_common.mk | ||||
| 
 | ||||
| EXTRA_C_FLAGS := | ||||
| EXTRA_LINK_FLAGS := | ||||
| BIN_ARGS := | ||||
|  | ||||
| @ -2,3 +2,4 @@ include ../test_common.mk | ||||
| 
 | ||||
| EXTRA_C_FLAGS := | ||||
| EXTRA_LINK_FLAGS := | ||||
| BIN_ARGS := | ||||
|  | ||||
| @ -2,3 +2,4 @@ include ../test_common.mk | ||||
| 
 | ||||
| EXTRA_C_FLAGS := | ||||
| EXTRA_LINK_FLAGS := | ||||
| BIN_ARGS := | ||||
|  | ||||
| @ -2,3 +2,4 @@ include ../test_common.mk | ||||
| 
 | ||||
| EXTRA_C_FLAGS := | ||||
| EXTRA_LINK_FLAGS := | ||||
| BIN_ARGS := | ||||
|  | ||||
| @ -56,7 +56,7 @@ $(C_OBJS): %.o: %.c | ||||
| #############################################################################
 | ||||
| 
 | ||||
| test: $(BIN_ENC_NAME) | ||||
| 	@cd ../ && RUST_BACKTRACE=1 ./pal $(CUR_DIR)/$(BIN_ENC_NAME) | ||||
| 	@cd ../ && RUST_BACKTRACE=1 ./pal $(CUR_DIR)/$(BIN_ENC_NAME) $(BIN_ARGS) | ||||
| 
 | ||||
| #############################################################################
 | ||||
| # Misc
 | ||||
|  | ||||
| @ -2,3 +2,4 @@ include ../test_common.mk | ||||
| 
 | ||||
| EXTRA_C_FLAGS := | ||||
| EXTRA_LINK_FLAGS := | ||||
| BIN_ARGS := | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user