|
|
@ -1,7 +1,7 @@
|
|
|
|
use alloc::String;
|
|
|
|
use alloc::String;
|
|
|
|
use arch::interrupt::*;
|
|
|
|
use arch::interrupt::*;
|
|
|
|
use memory::{MemoryArea, MemoryAttr, MemorySet};
|
|
|
|
use memory::{MemoryArea, MemoryAttr, MemorySet};
|
|
|
|
use xmas_elf::{ElfFile, header::HeaderPt2, program::{Flags, ProgramHeader}};
|
|
|
|
use xmas_elf::{ElfFile, header, program::{Flags, ProgramHeader, Type}};
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct Process {
|
|
|
|
pub struct Process {
|
|
|
@ -55,16 +55,15 @@ impl Process {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// Make a new user thread
|
|
|
|
/// Make a new user thread from ELF data
|
|
|
|
/// The program elf data is placed at [begin, end)
|
|
|
|
|
|
|
|
/// uCore x86 32bit program is planned to be supported.
|
|
|
|
|
|
|
|
pub fn new_user(data: &[u8]) -> Self {
|
|
|
|
pub fn new_user(data: &[u8]) -> Self {
|
|
|
|
// Parse elf
|
|
|
|
// Parse elf
|
|
|
|
let elf = ElfFile::new(data).expect("failed to read elf");
|
|
|
|
let elf = ElfFile::new(data).expect("failed to read elf");
|
|
|
|
let is32 = match elf.header.pt2 {
|
|
|
|
let is32 = match elf.header.pt2 {
|
|
|
|
HeaderPt2::Header32(_) => true,
|
|
|
|
header::HeaderPt2::Header32(_) => true,
|
|
|
|
HeaderPt2::Header64(_) => false,
|
|
|
|
header::HeaderPt2::Header64(_) => false,
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
assert_eq!(elf.header.pt2.type_().as_type(), header::Type::Executable, "ELF is not executable");
|
|
|
|
|
|
|
|
|
|
|
|
// User stack
|
|
|
|
// User stack
|
|
|
|
use consts::{USER_STACK_OFFSET, USER_STACK_SIZE, USER32_STACK_OFFSET};
|
|
|
|
use consts::{USER_STACK_OFFSET, USER_STACK_SIZE, USER32_STACK_OFFSET};
|
|
|
@ -78,19 +77,15 @@ impl Process {
|
|
|
|
memory_set.push(MemoryArea::new(user_stack_buttom, user_stack_top, MemoryAttr::default().user(), "user_stack"));
|
|
|
|
memory_set.push(MemoryArea::new(user_stack_buttom, user_stack_top, MemoryAttr::default().user(), "user_stack"));
|
|
|
|
trace!("{:#x?}", memory_set);
|
|
|
|
trace!("{:#x?}", memory_set);
|
|
|
|
|
|
|
|
|
|
|
|
let entry_addr = match elf.header.pt2 {
|
|
|
|
let entry_addr = elf.header.pt2.entry_point() as usize;
|
|
|
|
HeaderPt2::Header32(header) => header.entry_point as usize,
|
|
|
|
|
|
|
|
HeaderPt2::Header64(header) => header.entry_point as usize,
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Temporary switch to it, in order to copy data
|
|
|
|
// Temporary switch to it, in order to copy data
|
|
|
|
unsafe {
|
|
|
|
unsafe {
|
|
|
|
memory_set.with(|| {
|
|
|
|
memory_set.with(|| {
|
|
|
|
for ph in elf.program_iter() {
|
|
|
|
for ph in elf.program_iter() {
|
|
|
|
let (virt_addr, offset, file_size) = match ph {
|
|
|
|
let virt_addr = ph.virtual_addr() as usize;
|
|
|
|
ProgramHeader::Ph32(ph) => (ph.virtual_addr as usize, ph.offset as usize, ph.file_size as usize),
|
|
|
|
let offset = ph.offset() as usize;
|
|
|
|
ProgramHeader::Ph64(ph) => (ph.virtual_addr as usize, ph.offset as usize, ph.file_size as usize),
|
|
|
|
let file_size = ph.file_size() as usize;
|
|
|
|
};
|
|
|
|
|
|
|
|
use core::slice;
|
|
|
|
use core::slice;
|
|
|
|
let target = unsafe { slice::from_raw_parts_mut(virt_addr as *mut u8, file_size) };
|
|
|
|
let target = unsafe { slice::from_raw_parts_mut(virt_addr as *mut u8, file_size) };
|
|
|
|
target.copy_from_slice(&data[offset..offset + file_size]);
|
|
|
|
target.copy_from_slice(&data[offset..offset + file_size]);
|
|
|
@ -166,6 +161,9 @@ impl Process {
|
|
|
|
fn memory_set_from<'a>(elf: &'a ElfFile<'a>) -> MemorySet {
|
|
|
|
fn memory_set_from<'a>(elf: &'a ElfFile<'a>) -> MemorySet {
|
|
|
|
let mut set = MemorySet::new();
|
|
|
|
let mut set = MemorySet::new();
|
|
|
|
for ph in elf.program_iter() {
|
|
|
|
for ph in elf.program_iter() {
|
|
|
|
|
|
|
|
if ph.get_type() != Ok(Type::Load) {
|
|
|
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
}
|
|
|
|
let (virt_addr, mem_size, flags) = match ph {
|
|
|
|
let (virt_addr, mem_size, flags) = match ph {
|
|
|
|
ProgramHeader::Ph32(ph) => (ph.virtual_addr as usize, ph.mem_size as usize, ph.flags),
|
|
|
|
ProgramHeader::Ph32(ph) => (ph.virtual_addr as usize, ph.mem_size as usize, ph.flags),
|
|
|
|
ProgramHeader::Ph64(ph) => (ph.virtual_addr as usize, ph.mem_size as usize, ph.flags),
|
|
|
|
ProgramHeader::Ph64(ph) => (ph.virtual_addr as usize, ph.mem_size as usize, ph.flags),
|
|
|
|