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 std::ptr;
|
||||||
use xmas_elf::{header, program, sections, ElfFile};
|
use xmas_elf::{header, program, sections, ElfFile};
|
||||||
|
|
||||||
pub const DEFAULT_STACK_SIZE: usize = 1 * 1024 * 1024;
|
pub fn do_init(
|
||||||
pub const DEFAULT_HEAP_SIZE: usize = 8 * 1024 * 1024;
|
elf_file: &ElfFile,
|
||||||
pub const DEFAULT_MMAP_SIZE: usize = 8 * 1024 * 1024;
|
elf_buf: &[u8],
|
||||||
|
ldso_elf_file: &ElfFile,
|
||||||
pub fn do_init(elf_file: &ElfFile, elf_buf: &[u8]) -> Result<ProcessVM, Error> {
|
ldso_elf_buf: &[u8]
|
||||||
|
) -> Result<ProcessVM, Error> {
|
||||||
let mut code_seg = get_code_segment(elf_file)?;
|
let mut code_seg = get_code_segment(elf_file)?;
|
||||||
let mut data_seg = get_data_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
|
// Alloc all virtual memory areas
|
||||||
let code_start = 0;
|
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 data_end = align_up(data_seg.get_mem_addr() + data_seg.get_mem_size(), 4096);
|
||||||
let code_size = code_end - code_start;
|
let code_size = code_end - code_start;
|
||||||
let data_size = data_end - data_start;
|
let data_size = data_end - data_start;
|
||||||
let stack_size = DEFAULT_STACK_SIZE;
|
let mut process_vm = ProcessVMBuilder::new(code_size, data_size).build()?;
|
||||||
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);
|
|
||||||
|
|
||||||
// Load code and data
|
// 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);
|
code_seg.load_from_file(elf_buf);
|
||||||
data_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
|
// Relocate symbols
|
||||||
reloc_symbols(process_base_addr, elf_file)?;
|
reloc_symbols(process_base_addr, elf_file)?;
|
||||||
//link_syscalls(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::ffi::{CStr, CString};
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::sgxfs::SgxFile;
|
use std::sgxfs::SgxFile;
|
||||||
use vm::{ProcessVM};
|
use vm::{ProcessVM, ProcessVMBuilder};
|
||||||
|
|
||||||
use super::task::Task;
|
use super::task::Task;
|
||||||
use super::*;
|
use super::*;
|
||||||
@ -58,9 +58,29 @@ pub fn do_spawn<P: AsRef<Path>>(
|
|||||||
elf_file
|
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 (new_pid, new_process_ref) = {
|
||||||
let cwd = parent_ref.lock().unwrap().get_cwd().to_owned();
|
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 base_addr = vm.get_base_addr();
|
||||||
let program_entry = {
|
let program_entry = {
|
||||||
let program_entry = base_addr + elf_helper::get_start_address(&elf_file)?;
|
let program_entry = base_addr + elf_helper::get_start_address(&elf_file)?;
|
||||||
|
@ -11,9 +11,7 @@ pub struct Segment {
|
|||||||
file_offset: usize,
|
file_offset: usize,
|
||||||
file_size: usize,
|
file_size: usize,
|
||||||
// Runtime info after loaded
|
// Runtime info after loaded
|
||||||
process_base_addr: usize,
|
runtime_base_addr: Option<usize>,
|
||||||
start_addr: usize,
|
|
||||||
end_addr: usize,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const PERM_R: u32 = 0x1;
|
pub const PERM_R: u32 = 0x1;
|
||||||
@ -42,8 +40,7 @@ impl Segment {
|
|||||||
return Err((
|
return Err((
|
||||||
Errno::EINVAL,
|
Errno::EINVAL,
|
||||||
"Memory address and file offset is not equal, per modulo",
|
"Memory address and file offset is not equal, per modulo",
|
||||||
)
|
).into());
|
||||||
.into());
|
|
||||||
}
|
}
|
||||||
if ph64.mem_size < ph64.file_size {
|
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());
|
||||||
@ -65,7 +62,7 @@ impl Segment {
|
|||||||
pub fn load_from_file(&self, elf_buf: &[u8]) {
|
pub fn load_from_file(&self, elf_buf: &[u8]) {
|
||||||
let mut target_buf = unsafe {
|
let mut target_buf = unsafe {
|
||||||
slice::from_raw_parts_mut(
|
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,
|
self.mem_size,
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
@ -77,15 +74,8 @@ impl Segment {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_runtime_info(
|
pub fn set_runtime_base(&mut self, runtime_base_addr: usize) {
|
||||||
&mut self,
|
self.runtime_base_addr = Some(runtime_base_addr);
|
||||||
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 mprotect(&mut self, perm: u32) {
|
pub fn mprotect(&mut self, perm: u32) {
|
||||||
|
@ -7,7 +7,7 @@ mod vm_manager;
|
|||||||
mod user_space_vm;
|
mod user_space_vm;
|
||||||
mod process_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 use self::vm_manager::{VMRange};
|
||||||
|
|
||||||
pub fn do_mmap(
|
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 super::user_space_vm::{UserSpaceVMManager, UserSpaceVMRange, USER_SPACE_VM_MANAGER};
|
||||||
use std::slice;
|
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
|
/// The per-process virtual memory
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct ProcessVM {
|
pub struct ProcessVM {
|
||||||
process_range: UserSpaceVMRange,
|
process_range: UserSpaceVMRange,
|
||||||
code_range: VMRange,
|
code_range: VMRange,
|
||||||
data_range: VMRange,
|
data_range: VMRange,
|
||||||
|
ldso_code_range: VMRange,
|
||||||
|
ldso_data_range: VMRange,
|
||||||
heap_range: VMRange,
|
heap_range: VMRange,
|
||||||
stack_range: VMRange,
|
stack_range: VMRange,
|
||||||
brk: usize,
|
brk: usize,
|
||||||
@ -19,66 +128,19 @@ impl Default for ProcessVM {
|
|||||||
fn default() -> ProcessVM {
|
fn default() -> ProcessVM {
|
||||||
ProcessVM {
|
ProcessVM {
|
||||||
process_range: USER_SPACE_VM_MANAGER.alloc_dummy(),
|
process_range: USER_SPACE_VM_MANAGER.alloc_dummy(),
|
||||||
code_range: VMRange::default(),
|
code_range: Default::default(),
|
||||||
data_range: VMRange::default(),
|
data_range: Default::default(),
|
||||||
heap_range: VMRange::default(),
|
heap_range: Default::default(),
|
||||||
stack_range: VMRange::default(),
|
ldso_code_range: Default::default(),
|
||||||
brk: 0,
|
ldso_data_range: Default::default(),
|
||||||
mmap_manager: VMManager::default(),
|
stack_range: Default::default(),
|
||||||
|
brk: Default::default(),
|
||||||
|
mmap_manager: Default::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ProcessVM {
|
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 {
|
pub fn get_process_range(&self) -> &VMRange {
|
||||||
self.process_range.range()
|
self.process_range.range()
|
||||||
}
|
}
|
||||||
@ -91,6 +153,14 @@ impl ProcessVM {
|
|||||||
&self.data_range
|
&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 {
|
pub fn get_heap_range(&self) -> &VMRange {
|
||||||
&self.heap_range
|
&self.heap_range
|
||||||
}
|
}
|
||||||
|
@ -45,6 +45,7 @@ $(BUILD_TARGETS): %:
|
|||||||
|
|
||||||
sefs:
|
sefs:
|
||||||
@$(RM) -rf $(SEFS_PATH)
|
@$(RM) -rf $(SEFS_PATH)
|
||||||
|
@cp ~/Workspace/occlum/musl.old/lib/libc.so $(FS_PATH)/ld.so
|
||||||
@cd $(PROJECT_DIR)/deps/sefs/sefs-fuse/bin/ && \
|
@cd $(PROJECT_DIR)/deps/sefs/sefs-fuse/bin/ && \
|
||||||
./app \
|
./app \
|
||||||
$(CUR_DIR)/$(SEFS_PATH) \
|
$(CUR_DIR)/$(SEFS_PATH) \
|
||||||
|
Loading…
Reference in New Issue
Block a user