diff --git a/src/libos/src/entry.rs b/src/libos/src/entry.rs index 6d1a1e60..0cf5cd0d 100644 --- a/src/libos/src/entry.rs +++ b/src/libos/src/entry.rs @@ -79,7 +79,10 @@ fn do_boot(path_str: &str, argv: &Vec) -> Result<(), Error> { // info!("boot: path: {:?}, argv: {:?}", path_str, argv); util::mpx_util::mpx_enable()?; - let envp = std::vec::Vec::new(); + // The default environment variables + let envp = vec![ + CString::new("OCCLUM=yes").unwrap() + ]; let file_actions = Vec::new(); let parent = &process::IDLE_PROCESS; process::do_spawn(&path_str, argv, &envp, &file_actions, parent)?; diff --git a/src/libos/src/prelude.rs b/src/libos/src/prelude.rs index a4c80b5f..09f05ec2 100644 --- a/src/libos/src/prelude.rs +++ b/src/libos/src/prelude.rs @@ -67,10 +67,12 @@ macro_rules! try_libc { } pub fn align_up(addr: usize, align: usize) -> usize { - (addr + (align - 1)) / align * align + debug_assert!(align != 0 && align.is_power_of_two()); + align_down(addr + (align - 1), align) } pub fn align_down(addr: usize, align: usize) -> usize { + debug_assert!(align != 0 && align.is_power_of_two()); addr & !(align - 1) } diff --git a/src/libos/src/process/spawn/init_stack.rs b/src/libos/src/process/spawn/init_stack.rs index e2338460..3034a2ce 100644 --- a/src/libos/src/process/spawn/init_stack.rs +++ b/src/libos/src/process/spawn/init_stack.rs @@ -86,17 +86,13 @@ impl StackBuf { }) } - pub fn put(&self, val: T) -> Result<*const T, Error> - where - T: Copy, + pub fn put(&self, val: u64) -> Result<*const u64, Error> { - let val_size = mem::size_of::(); - let val_align = mem::align_of::(); - let val_ptr = self.alloc(val_size, val_align)? as *mut T; + let val_ptr = self.alloc(8, 8)? as *mut u64; unsafe { ptr::write(val_ptr, val); } - Ok(val_ptr as *const T) + Ok(val_ptr as *const u64) } pub fn put_slice(&self, vals: &[T]) -> Result<*const T, Error> @@ -164,12 +160,12 @@ fn clone_cstrings_on_stack<'a, 'b>( } 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 + // For every key-value pair, dump the value first, then the key + stack.put(0 as u64); stack.put(AuxKey::AT_NULL as u64); - stack.put(AuxKey::AT_NULL as u64); - for (aux_key, aux_val) in auxtbl { - stack.put(aux_val); - stack.put(aux_key as u64); + for (aux_key, aux_val) in auxtbl.table() { + stack.put(*aux_val as u64); + stack.put(*aux_key as u64); } Ok(()) } @@ -188,7 +184,7 @@ fn dump_cstrptrs_on_stack<'a, 'b>( /* Symbolic values for the entries in the auxiliary table put on the initial stack */ #[allow(non_camel_case_types)] -#[derive(Clone, Copy, Debug, PartialEq)] +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] pub enum AuxKey { AT_NULL = 0, /* end of vector */ AT_IGNORE = 1, /* entry should be ignored */ @@ -210,122 +206,53 @@ pub enum AuxKey { AT_CLKTCK = 17, /* frequency at which times() increments */ /* 18...22 not used */ - AT_SECURE = 23, /* secure mode boolean */ + AT_SECURE = 23, /* secure mode boolean */ AT_BASE_PLATFORM = 24, /* string identifying real platform, may * differ from AT_PLATFORM. */ - AT_RANDOM = 25, /* address of 16 random bytes */ - AT_HWCAP2 = 26, /* extension of AT_HWCAP */ + AT_RANDOM = 25, /* address of 16 random bytes */ + AT_HWCAP2 = 26, /* extension of AT_HWCAP */ /* 28...30 not used */ - AT_EXECFN = 31, /* filename of program */ + AT_EXECFN = 31, /* filename of program */ + AT_SYSINFO = 32, + + /* Occlum-specific entries */ + AT_OCCLUM_ENTRY = 48, /* the entry point of Occlum, i.e., syscall */ } -static AUX_KEYS: &'static [AuxKey] = &[ - AuxKey::AT_NULL, - AuxKey::AT_IGNORE, - AuxKey::AT_EXECFD, - AuxKey::AT_PHDR, - AuxKey::AT_PHENT, - AuxKey::AT_PHNUM, - AuxKey::AT_PAGESZ, - AuxKey::AT_BASE, - AuxKey::AT_FLAGS, - AuxKey::AT_ENTRY, - AuxKey::AT_NOTELF, - AuxKey::AT_UID, - AuxKey::AT_EUID, - AuxKey::AT_GID, - AuxKey::AT_EGID, - AuxKey::AT_PLATFORM, - AuxKey::AT_HWCAP, - AuxKey::AT_CLKTCK, - AuxKey::AT_SECURE, - AuxKey::AT_BASE_PLATFORM, - AuxKey::AT_RANDOM, - AuxKey::AT_HWCAP2, - AuxKey::AT_EXECFN, -]; - -impl AuxKey { - pub const MAX: usize = 32; - - pub fn next(&self) -> Option { - let self_idx = AUX_KEYS.iter().position(|x| *x == *self).unwrap(); - let next_idx = self_idx + 1; - if next_idx < AUX_KEYS.len() { - Some(AUX_KEYS[next_idx]) - } else { - None - } - } -} - -#[derive(Clone, Default, Copy, Debug)] +#[derive(Clone, Default, Debug)] pub struct AuxTable { - values: [Option; AuxKey::MAX], + table: HashMap, } impl AuxTable { pub fn new() -> AuxTable { AuxTable { - values: [None; AuxKey::MAX], + table: HashMap::new(), } } +} - pub fn set_val(&mut self, key: AuxKey, val: u64) -> Result<(), Error> { +impl AuxTable { + pub fn set(&mut self, key: AuxKey, val: u64) -> Result<(), Error> { if key == AuxKey::AT_NULL || key == AuxKey::AT_IGNORE { return errno!(EINVAL, "Illegal key"); } - self.values[key as usize] = Some(val); + self.table.entry(key) + .and_modify(|val_mut| *val_mut = val) + .or_insert(val); Ok(()) } - pub fn get_val(&self, key: AuxKey) -> Option { - self.values[key as usize] + pub fn get(&self, key: AuxKey) -> Option { + self.table.get(&key).map(|val_ref| *val_ref) } - pub fn del_val(&mut self, key: AuxKey) { - self.values[key as usize] = None; + pub fn del(&mut self, key: AuxKey) -> Option{ + self.table.remove(&key) } - pub fn iter<'a>(&'a self) -> AuxTableIter<'a> { - AuxTableIter { - tbl: self, - key: Some(AuxKey::AT_NULL), - } - } -} - -impl<'a> IntoIterator for &'a AuxTable { - type Item = (AuxKey, u64); - type IntoIter = AuxTableIter<'a>; - - fn into_iter(self) -> Self::IntoIter { - self.iter() - } -} - -pub struct AuxTableIter<'a> { - tbl: &'a AuxTable, - key: Option, -} - -impl<'a> Iterator for AuxTableIter<'a> { - type Item = (AuxKey, u64); - - fn next(&mut self) -> Option<(AuxKey, u64)> { - loop { - if self.key == None { - return None; - } - let key = self.key.unwrap(); - - let item = self.tbl.get_val(key).map(|val| (key, val)); - self.key = key.next(); - - if item != None { - return item; - } - } + pub fn table(&self) -> &HashMap { + &self.table } } diff --git a/src/libos/src/process/spawn/init_vm.rs b/src/libos/src/process/spawn/init_vm.rs index 9a0fc11e..802bad02 100644 --- a/src/libos/src/process/spawn/init_vm.rs +++ b/src/libos/src/process/spawn/init_vm.rs @@ -38,7 +38,7 @@ pub fn do_init(elf_file: &ElfFile, elf_buf: &[u8]) -> Result { // Relocate symbols reloc_symbols(process_base_addr, elf_file)?; - link_syscalls(process_base_addr, elf_file)?; + //link_syscalls(process_base_addr, elf_file)?; Ok(process_vm) } @@ -69,7 +69,7 @@ fn reloc_symbols(process_base_addr: usize, elf_file: &ElfFile) -> Result<(), Err } Ok(()) } - +/* fn link_syscalls(process_base_addr: usize, elf_file: &ElfFile) -> Result<(), Error> { let syscall_addr = __occlum_syscall as *const () as usize; @@ -92,7 +92,7 @@ fn link_syscalls(process_base_addr: usize, elf_file: &ElfFile) -> Result<(), Err Ok(()) } - +*/ extern "C" { fn __occlum_syscall(num: i32, arg0: u64, arg1: u64, arg2: u64, arg3: u64, arg4: u64) -> i64; } diff --git a/src/libos/src/process/spawn/mod.rs b/src/libos/src/process/spawn/mod.rs index e29d2ae2..fa47d26d 100644 --- a/src/libos/src/process/spawn/mod.rs +++ b/src/libos/src/process/spawn/mod.rs @@ -152,19 +152,24 @@ fn init_auxtbl( elf_file: &ElfFile, ) -> Result { let mut auxtbl = AuxTable::new(); - auxtbl.set_val(AuxKey::AT_PAGESZ, 4096)?; - auxtbl.set_val(AuxKey::AT_UID, 0)?; - auxtbl.set_val(AuxKey::AT_GID, 0)?; - auxtbl.set_val(AuxKey::AT_EUID, 0)?; - auxtbl.set_val(AuxKey::AT_EGID, 0)?; - auxtbl.set_val(AuxKey::AT_SECURE, 0)?; + auxtbl.set(AuxKey::AT_PAGESZ, 4096)?; + auxtbl.set(AuxKey::AT_UID, 0)?; + auxtbl.set(AuxKey::AT_GID, 0)?; + auxtbl.set(AuxKey::AT_EUID, 0)?; + auxtbl.set(AuxKey::AT_EGID, 0)?; + auxtbl.set(AuxKey::AT_SECURE, 0)?; let ph = elf_helper::get_program_header_info(elf_file)?; - auxtbl.set_val(AuxKey::AT_PHDR, (base_addr + ph.addr) as u64)?; - auxtbl.set_val(AuxKey::AT_PHENT, ph.entry_size as u64)?; - auxtbl.set_val(AuxKey::AT_PHNUM, ph.entry_num as u64)?; + auxtbl.set(AuxKey::AT_PHDR, (base_addr + ph.addr) as u64)?; + auxtbl.set(AuxKey::AT_PHENT, ph.entry_size as u64)?; + auxtbl.set(AuxKey::AT_PHNUM, ph.entry_num as u64)?; - auxtbl.set_val(AuxKey::AT_ENTRY, program_entry as u64)?; + auxtbl.set(AuxKey::AT_ENTRY, program_entry as u64)?; + + auxtbl.set(AuxKey::AT_SYSINFO, 123)?; + + let syscall_addr = __occlum_syscall as *const () as u64; + auxtbl.set(AuxKey::AT_OCCLUM_ENTRY, syscall_addr)?; // TODO: init AT_EXECFN // auxtbl.set_val(AuxKey::AT_EXECFN, "program_name")?; @@ -177,3 +182,7 @@ fn parent_adopts_new_child(parent_ref: &ProcessRef, child_ref: &ProcessRef) { parent.children.push(Arc::downgrade(child_ref)); child.parent = Some(parent_ref.clone()); } + +extern "C" { + fn __occlum_syscall(num: i32, arg0: u64, arg1: u64, arg2: u64, arg3: u64, arg4: u64) -> i64; +} diff --git a/test/Makefile b/test/Makefile index 930bfda1..f27fd1fc 100644 --- a/test/Makefile +++ b/test/Makefile @@ -4,7 +4,7 @@ PROJECT_DIR := $(realpath $(CUR_DIR)/../) # Dependencies: need to be compiled but not to run by any Makefile target TEST_DEPS := dev_null # Tests: need to be compiled and run by test-% target -TESTS := empty argv hello_world malloc mmap file getpid spawn pipe time \ +TESTS := empty env hello_world malloc mmap file getpid spawn pipe time \ truncate readdir mkdir link tls pthread uname rlimit client server \ server_epoll unix_socket cout hostfs cpuid rdtsc device # Benchmarks: need to be compiled and run by bench-% target diff --git a/test/argv/main.c b/test/argv/main.c deleted file mode 100644 index d6bbb6b6..00000000 --- a/test/argv/main.c +++ /dev/null @@ -1,30 +0,0 @@ -#include -#include - -// Expected arguments are given by Makefile throught macro ARGC, ARG1, ARG2 and -// ARG3 -const char* expected_argv[EXPECTED_ARGC] = { - "argv", - EXPECTED_ARG1, - EXPECTED_ARG2, - EXPECTED_ARG3, -}; - -int main(int argc, const 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; -} diff --git a/test/argv/Makefile b/test/env/Makefile similarity index 100% rename from test/argv/Makefile rename to test/env/Makefile diff --git a/test/env/main.c b/test/env/main.c new file mode 100644 index 00000000..c20b693d --- /dev/null +++ b/test/env/main.c @@ -0,0 +1,57 @@ +#include +#include +#include +#include +#include +#include + +// Expected arguments are given by Makefile throught macro ARGC, ARG1, ARG2 and +// ARG3 +const char* expected_argv[EXPECTED_ARGC] = { + "env", + EXPECTED_ARG1, + EXPECTED_ARG2, + EXPECTED_ARG3, +}; + +int main(int argc, const char* argv[]) { + // Test argc + if (argc != EXPECTED_ARGC) { + printf("ERROR: expect %d arguments, but %d are given\n", EXPECTED_ARGC, argc); + return -1; + } + + // Test argv + for (int arg_i = 0; arg_i < argc; arg_i++) { + printf("arg[%d] = %s\n", arg_i, argv[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); + return -1; + } + } + + // Test envp + // Occlum LibOS by default passes an environment OCCLUM=yes + const char* env_val = getenv("OCCLUM"); + if (env_val == 0) { + printf("ERROR: cannot find environment variable OCCLUM\n"); + return -1; + } + else if (strcmp(env_val, "yes") != 0) { + printf("ERROR: environment variable OCCLUM=yes expected, but given %s\n", + env_val); + return -1; + } + + // Test aux + unsigned long page_size = getauxval(AT_PAGESZ); + if (errno != 0 || page_size != 4096) { + printf("ERROR: auxilary vector does not pass correct the value\n"); + return -1; + } + + return 0; +} diff --git a/test/test_common.mk b/test/test_common.mk index 3213d6f5..ef4fe249 100644 --- a/test/test_common.mk +++ b/test/test_common.mk @@ -21,7 +21,7 @@ LLVM_PATH := $(abspath $(dir $(CLANG_BIN_PATH))../) C_FLAGS = -Wall -I../include -O2 -fPIC $(EXTRA_C_FLAGS) C_FLAGS += -Xclang -load -Xclang $(LLVM_PATH)/lib/LLVMMDSFIIRInserter.so -LINK_FLAGS = $(C_FLAGS) -pie -locclum_stub $(EXTRA_LINK_FLAGS) +LINK_FLAGS = $(C_FLAGS) -pie $(EXTRA_LINK_FLAGS) .PHONY: all test debug clean