From 33739cc00b53f1ad0457c802968f23b3b70f155f Mon Sep 17 00:00:00 2001 From: "Tate, Hongliang Tian" Date: Sat, 6 Jul 2019 12:41:00 +0000 Subject: [PATCH] Program loader loads ld.so now --- src/libos/src/process/spawn/init_vm.rs | 37 ++--- src/libos/src/process/spawn/mod.rs | 24 +++- src/libos/src/process/spawn/segment.rs | 20 +-- src/libos/src/vm/mod.rs | 2 +- src/libos/src/vm/process_vm.rs | 180 +++++++++++++++++-------- test/Makefile | 1 + 6 files changed, 173 insertions(+), 91 deletions(-) diff --git a/src/libos/src/process/spawn/init_vm.rs b/src/libos/src/process/spawn/init_vm.rs index 802bad02..c4653979 100644 --- a/src/libos/src/process/spawn/init_vm.rs +++ b/src/libos/src/process/spawn/init_vm.rs @@ -3,13 +3,16 @@ use super::*; 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 = 8 * 1024 * 1024; -pub const DEFAULT_MMAP_SIZE: usize = 8 * 1024 * 1024; - -pub fn do_init(elf_file: &ElfFile, elf_buf: &[u8]) -> Result { +pub fn do_init( + elf_file: &ElfFile, + elf_buf: &[u8], + ldso_elf_file: &ElfFile, + ldso_elf_buf: &[u8] +) -> Result { let mut code_seg = get_code_segment(elf_file)?; let mut data_seg = get_data_segment(elf_file)?; + let mut ldso_code_seg = get_code_segment(ldso_elf_file)?; + let mut ldso_data_seg = get_data_segment(ldso_elf_file)?; // Alloc all virtual memory areas let code_start = 0; @@ -18,24 +21,22 @@ pub fn do_init(elf_file: &ElfFile, elf_buf: &[u8]) -> Result { let data_end = align_up(data_seg.get_mem_addr() + data_seg.get_mem_size(), 4096); let code_size = code_end - code_start; let data_size = data_end - data_start; - 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)?; - - // Calculate the "real" addresses - let process_base_addr = process_vm.get_base_addr(); - let code_start = code_start + process_base_addr; - let code_end = code_end + process_base_addr; - let data_start = data_start + process_base_addr; - let data_end = data_end + process_base_addr; - code_seg.set_runtime_info(process_base_addr, code_start, code_end); - data_seg.set_runtime_info(process_base_addr, data_start, data_end); + let mut process_vm = ProcessVMBuilder::new(code_size, data_size).build()?; // Load code and data + let process_base_addr = process_vm.get_code_range().start(); + code_seg.set_runtime_base(process_base_addr); + data_seg.set_runtime_base(process_base_addr); code_seg.load_from_file(elf_buf); data_seg.load_from_file(elf_buf); + // Load code and data of ld.so + let ldso_base_addr = process_vm.get_ldso_code_range().start(); + ldso_code_seg.set_runtime_base(ldso_base_addr); + ldso_data_seg.set_runtime_base(ldso_base_addr); + ldso_code_seg.load_from_file(ldso_elf_buf); + ldso_data_seg.load_from_file(ldso_elf_buf); + // Relocate symbols reloc_symbols(process_base_addr, elf_file)?; //link_syscalls(process_base_addr, elf_file)?; diff --git a/src/libos/src/process/spawn/mod.rs b/src/libos/src/process/spawn/mod.rs index fa47d26d..f90bec31 100644 --- a/src/libos/src/process/spawn/mod.rs +++ b/src/libos/src/process/spawn/mod.rs @@ -6,7 +6,7 @@ use misc::ResourceLimitsRef; use std::ffi::{CStr, CString}; use std::path::Path; use std::sgxfs::SgxFile; -use vm::{ProcessVM}; +use vm::{ProcessVM, ProcessVMBuilder}; use super::task::Task; use super::*; @@ -58,9 +58,29 @@ pub fn do_spawn>( elf_file }; + let mut ldso_elf_buf = { + let ldso_path = "/ld.so"; + let ldso_inode = ROOT_INODE.lookup(ldso_path)?; + ldso_inode.read_as_vec()? + }; + + let ldso_elf_file = { + let ldso_elf_file = + ElfFile::new(&ldso_elf_buf).map_err(|e| (Errno::ENOEXEC, "Failed to parse the ELF file"))?; + header::sanity_check(&ldso_elf_file) + .map_err(|e| (Errno::ENOEXEC, "Failed to parse the ELF file"))?; + /* + elf_helper::print_program_headers(&elf_file)?; + elf_helper::print_sections(&elf_file)?; + elf_helper::print_pltrel_section(&elf_file)?; + */ + ldso_elf_file + }; + let (new_pid, new_process_ref) = { let cwd = parent_ref.lock().unwrap().get_cwd().to_owned(); - let vm = init_vm::do_init(&elf_file, &elf_buf[..])?; + let vm = init_vm::do_init(&elf_file, &elf_buf[..], + &ldso_elf_file, &ldso_elf_buf[..])?; let base_addr = vm.get_base_addr(); let program_entry = { let program_entry = base_addr + elf_helper::get_start_address(&elf_file)?; diff --git a/src/libos/src/process/spawn/segment.rs b/src/libos/src/process/spawn/segment.rs index 59947aff..ff4b4390 100644 --- a/src/libos/src/process/spawn/segment.rs +++ b/src/libos/src/process/spawn/segment.rs @@ -11,9 +11,7 @@ pub struct Segment { file_offset: usize, file_size: usize, // Runtime info after loaded - process_base_addr: usize, - start_addr: usize, - end_addr: usize, + runtime_base_addr: Option, } pub const PERM_R: u32 = 0x1; @@ -42,8 +40,7 @@ impl Segment { return Err(( Errno::EINVAL, "Memory address and file offset is not equal, per modulo", - ) - .into()); + ).into()); } if ph64.mem_size < ph64.file_size { return Err((Errno::EINVAL, "Memory size must be greater than file size").into()); @@ -65,7 +62,7 @@ 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.runtime_base_addr.unwrap() + self.mem_addr) as *mut u8, self.mem_size, ) }; @@ -77,15 +74,8 @@ impl Segment { } } - 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; + pub fn set_runtime_base(&mut self, runtime_base_addr: usize) { + self.runtime_base_addr = Some(runtime_base_addr); } pub fn mprotect(&mut self, perm: u32) { diff --git a/src/libos/src/vm/mod.rs b/src/libos/src/vm/mod.rs index 630953f9..4567b770 100644 --- a/src/libos/src/vm/mod.rs +++ b/src/libos/src/vm/mod.rs @@ -7,7 +7,7 @@ mod vm_manager; mod user_space_vm; mod process_vm; -pub use self::process_vm::{ProcessVM, MMapFlags, VMPerms}; +pub use self::process_vm::{ProcessVM, ProcessVMBuilder, MMapFlags, VMPerms}; pub use self::vm_manager::{VMRange}; pub fn do_mmap( diff --git a/src/libos/src/vm/process_vm.rs b/src/libos/src/vm/process_vm.rs index 96093d82..04b81507 100644 --- a/src/libos/src/vm/process_vm.rs +++ b/src/libos/src/vm/process_vm.rs @@ -3,12 +3,121 @@ use super::vm_manager::{VMRange, VMManager, VMMapOptionsBuilder, VMMapOptions, V use super::user_space_vm::{UserSpaceVMManager, UserSpaceVMRange, USER_SPACE_VM_MANAGER}; use std::slice; + +#[derive(Debug, Default)] +pub struct ProcessVMBuilder { + code_size: usize, + data_size: usize, + ldso_code_size: Option, + ldso_data_size: Option, + heap_size: Option, + stack_size: Option, + mmap_size: Option, +} + +macro_rules! impl_setter_for_process_vm_builder { + ($field: ident) => { + pub fn $field(mut self, size: usize) -> Self { + self.$field = Some(size); + self + } + } +} + +impl ProcessVMBuilder { + pub const DEFAULT_STACK_SIZE: usize = 1 * 1024 * 1024; + pub const DEFAULT_HEAP_SIZE: usize = 8 * 1024 * 1024; + pub const DEFAULT_MMAP_SIZE: usize = 8 * 1024 * 1024; + + pub fn new(code_size: usize, data_size: usize) -> ProcessVMBuilder { + ProcessVMBuilder { + code_size, + data_size, + ..ProcessVMBuilder::default() + } + } + + impl_setter_for_process_vm_builder!(ldso_data_size); + impl_setter_for_process_vm_builder!(ldso_code_size); + impl_setter_for_process_vm_builder!(heap_size); + impl_setter_for_process_vm_builder!(stack_size); + impl_setter_for_process_vm_builder!(mmap_size); + + pub fn build(self) -> Result { + self.validate()?; + + let code_size = self.code_size; + let data_size = self.data_size; + let ldso_code_size = self.ldso_code_size.unwrap_or(0); + let ldso_data_size = self.ldso_data_size.unwrap_or(0); + let heap_size = self.heap_size.unwrap_or(ProcessVMBuilder::DEFAULT_HEAP_SIZE); + let stack_size = self.stack_size.unwrap_or(ProcessVMBuilder::DEFAULT_STACK_SIZE); + let mmap_size = self.mmap_size.unwrap_or(ProcessVMBuilder::DEFAULT_MMAP_SIZE); + let range_sizes = vec![ + code_size, data_size, + ldso_code_size, ldso_data_size, + heap_size, stack_size, + mmap_size + ]; + + let process_range = { + let total_size = range_sizes.iter().sum(); + USER_SPACE_VM_MANAGER.alloc(total_size)? + }; + + let vm_ranges = { + let mut curr_addr = process_range.range().start(); + let mut vm_ranges = Vec::new(); + for range_size in &range_sizes { + let range_start = curr_addr; + let range_end = curr_addr + range_size; + let range = VMRange::from(range_start, range_end)?; + vm_ranges.push(range); + + curr_addr = range_end; + } + vm_ranges + }; + let code_range = *&vm_ranges[0]; + let data_range = *&vm_ranges[1]; + let ldso_code_range = *&vm_ranges[2]; + let ldso_data_range = *&vm_ranges[3]; + let heap_range = *&vm_ranges[4]; + let stack_range = *&vm_ranges[5]; + let mmap_range = *&vm_ranges[6]; + + let brk = heap_range.start(); + + let mmap_manager = VMManager::from(mmap_range.start(), mmap_range.size())?; + + Ok(ProcessVM { + process_range, + code_range, + data_range, + ldso_code_range, + ldso_data_range, + heap_range, + stack_range, + brk, + mmap_manager, + }) + } + + // TODO: implement this! + fn validate(&self) -> Result<(), Error> { + Ok(()) + } +} + + /// The per-process virtual memory #[derive(Debug)] pub struct ProcessVM { process_range: UserSpaceVMRange, code_range: VMRange, data_range: VMRange, + ldso_code_range: VMRange, + ldso_data_range: VMRange, heap_range: VMRange, stack_range: VMRange, brk: usize, @@ -19,66 +128,19 @@ impl Default for ProcessVM { fn default() -> ProcessVM { ProcessVM { process_range: USER_SPACE_VM_MANAGER.alloc_dummy(), - code_range: VMRange::default(), - data_range: VMRange::default(), - heap_range: VMRange::default(), - stack_range: VMRange::default(), - brk: 0, - mmap_manager: VMManager::default(), + code_range: Default::default(), + data_range: Default::default(), + heap_range: Default::default(), + ldso_code_range: Default::default(), + ldso_data_range: Default::default(), + stack_range: Default::default(), + brk: Default::default(), + mmap_manager: Default::default(), } } } impl ProcessVM { - pub fn new( - code_size: usize, - data_size: usize, - heap_size: usize, - stack_size: usize, - mmap_size: usize, - ) -> Result { - let process_range = { - let vm_range_size = code_size + data_size + heap_size + stack_size + mmap_size; - USER_SPACE_VM_MANAGER.alloc(vm_range_size)? - }; - let process_addr = process_range.range().start(); - - let range_sizes = vec![code_size, data_size, heap_size, stack_size]; - let mut curr_addr = process_addr; - let mut ranges = Vec::new(); - for range_size in &range_sizes { - let range_start = curr_addr; - let range_end = curr_addr + range_size; - let range = VMRange::from(range_start, range_end)?; - ranges.push(range); - - curr_addr = range_end; - } - let code_range = *&ranges[0]; - let data_range = *&ranges[1]; - let heap_range = *&ranges[2]; - let stack_range = *&ranges[3]; - unsafe { - fill_zeros(code_range.start(), code_range.size()); - fill_zeros(data_range.start(), data_range.size()); - } - - let brk = heap_range.start(); - - let mmap_addr = stack_range.end(); - let mmap_manager = VMManager::from(mmap_addr, mmap_size)?; - - Ok(ProcessVM { - process_range, - code_range, - data_range, - heap_range, - stack_range, - brk, - mmap_manager, - }) - } - pub fn get_process_range(&self) -> &VMRange { self.process_range.range() } @@ -91,6 +153,14 @@ impl ProcessVM { &self.data_range } + pub fn get_ldso_code_range(&self) -> &VMRange { + &self.ldso_code_range + } + + pub fn get_ldso_data_range(&self) -> &VMRange { + &self.ldso_data_range + } + pub fn get_heap_range(&self) -> &VMRange { &self.heap_range } diff --git a/test/Makefile b/test/Makefile index f27fd1fc..e70384c3 100644 --- a/test/Makefile +++ b/test/Makefile @@ -45,6 +45,7 @@ $(BUILD_TARGETS): %: sefs: @$(RM) -rf $(SEFS_PATH) + @cp ~/Workspace/occlum/musl.old/lib/libc.so $(FS_PATH)/ld.so @cd $(PROJECT_DIR)/deps/sefs/sefs-fuse/bin/ && \ ./app \ $(CUR_DIR)/$(SEFS_PATH) \