Program loader loads ld.so now
This commit is contained in:
parent
13974315ad
commit
33739cc00b
@ -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<ProcessVM, Error> {
|
||||
pub fn do_init(
|
||||
elf_file: &ElfFile,
|
||||
elf_buf: &[u8],
|
||||
ldso_elf_file: &ElfFile,
|
||||
ldso_elf_buf: &[u8]
|
||||
) -> Result<ProcessVM, Error> {
|
||||
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<ProcessVM, Error> {
|
||||
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)?;
|
||||
|
@ -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<P: AsRef<Path>>(
|
||||
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)?;
|
||||
|
@ -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<usize>,
|
||||
}
|
||||
|
||||
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) {
|
||||
|
@ -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(
|
||||
|
@ -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<usize>,
|
||||
ldso_data_size: Option<usize>,
|
||||
heap_size: Option<usize>,
|
||||
stack_size: Option<usize>,
|
||||
mmap_size: Option<usize>,
|
||||
}
|
||||
|
||||
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<ProcessVM, Error> {
|
||||
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<ProcessVM, Error> {
|
||||
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
|
||||
}
|
||||
|
@ -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) \
|
||||
|
Loading…
Reference in New Issue
Block a user