fix process startup stack for musl libc

toolchain_update
WangRunji 6 years ago
parent a33d7632d6
commit 32e7f0ed52

@ -0,0 +1,62 @@
use alloc::string::String;
use alloc::vec::Vec;
use alloc::collections::btree_map::BTreeMap;
use core::ptr::null;
pub struct ProcInitInfo {
pub args: Vec<String>,
pub envs: BTreeMap<String, String>,
// pub auxv: Vec<String>,
}
impl ProcInitInfo {
pub unsafe fn push_at(&self, stack_top: usize) -> usize {
let mut writer = StackWriter { sp: stack_top };
// from stack_top:
// program name
writer.push_str(&self.args[0]);
// environment strings
let envs: Vec<_> = self.envs.iter().map(|(key, value)| {
writer.push_str(value.as_str());
writer.push_slice(&[b"="]);
writer.push_slice(key.as_bytes());
writer.sp
}).collect();
// argv strings
let argv: Vec<_> = self.args.iter().map(|arg| {
writer.push_str(arg.as_str());
writer.sp
}).collect();
// TODO: auxiliary vector entries
writer.push_slice(&[null::<u8>()]);
// envionment pointers
writer.push_slice(&[null::<u8>()]);
writer.push_slice(envs.as_slice());
// argv pointers
writer.push_slice(&[null::<u8>()]);
writer.push_slice(argv.as_slice());
// argc
writer.push_slice(&[argv.len()]);
writer.sp
}
}
struct StackWriter {
sp: usize,
}
impl StackWriter {
fn push_slice<T: Copy>(&mut self, vs: &[T]) {
use core::{mem::{size_of, align_of}, slice};
self.sp -= vs.len() * size_of::<T>();
self.sp -= self.sp % align_of::<T>();
unsafe { slice::from_raw_parts_mut(self.sp as *mut T, vs.len()) }
.copy_from_slice(vs);
}
fn push_str(&mut self, s: &str) {
self.push_slice(&[b'\0']);
self.push_slice(s.as_bytes());
}
}

@ -9,6 +9,8 @@ use xmas_elf::{ElfFile, header, program::{Flags, Type}};
use crate::arch::interrupt::{Context as ArchContext, TrapFrame}; use crate::arch::interrupt::{Context as ArchContext, TrapFrame};
use crate::memory::{ByFrame, GlobalFrameAlloc, KernelStack, MemoryAttr, MemorySet}; use crate::memory::{ByFrame, GlobalFrameAlloc, KernelStack, MemoryAttr, MemorySet};
use super::abi::ProcInitInfo;
// TODO: avoid pub // TODO: avoid pub
pub struct Process { pub struct Process {
pub arch: ArchContext, pub arch: ArchContext,
@ -86,8 +88,12 @@ impl Process {
#[cfg(feature = "no_mmu")] #[cfg(feature = "no_mmu")]
let mut ustack_top = memory_set.push(USER_STACK_SIZE).as_ptr() as usize + USER_STACK_SIZE; let mut ustack_top = memory_set.push(USER_STACK_SIZE).as_ptr() as usize + USER_STACK_SIZE;
let init_info = ProcInitInfo {
args: args.map(|s| String::from(s)).collect(),
envs: BTreeMap::new(),
};
unsafe { unsafe {
memory_set.with(|| { ustack_top = push_args_at_stack(args, ustack_top) }); memory_set.with(|| { ustack_top = init_info.push_at(ustack_top) });
} }
trace!("{:#x?}", memory_set); trace!("{:#x?}", memory_set);
@ -136,31 +142,6 @@ impl Process {
} }
} }
/// Push a slice at the stack. Return the new sp.
unsafe fn push_slice<T: Copy>(mut sp: usize, vs: &[T]) -> usize {
use core::{mem::{size_of, align_of}, slice};
sp -= vs.len() * size_of::<T>();
sp -= sp % align_of::<T>();
slice::from_raw_parts_mut(sp as *mut T, vs.len())
.copy_from_slice(vs);
sp
}
unsafe fn push_args_at_stack<'a, Iter>(args: Iter, stack_top: usize) -> usize
where Iter: Iterator<Item=&'a str>
{
let mut sp = stack_top;
let mut argv = Vec::new();
for arg in args {
sp = push_slice(sp, &[0u8]);
sp = push_slice(sp, arg.as_bytes());
argv.push(sp);
}
sp = push_slice(sp, argv.as_slice());
sp = push_slice(sp, &[argv.len()]);
sp
}
/// Generate a MemorySet according to the ELF file. /// Generate a MemorySet according to the ELF file.
/// Also return the real entry point address. /// Also return the real entry point address.

@ -6,6 +6,7 @@ use alloc::{boxed::Box, sync::Arc};
use log::*; use log::*;
pub mod context; pub mod context;
mod abi;
pub fn init() { pub fn init() {
// NOTE: max_time_slice <= 5 to ensure 'priority' test pass // NOTE: max_time_slice <= 5 to ensure 'priority' test pass

Loading…
Cancel
Save