use alloc::vec::Vec; use core::ptr; use header::{stdio, stdlib}; use platform; use platform::types::*; #[repr(C)] pub struct Stack { argc: isize, argv0: *const c_char, } impl Stack { fn argc(&self) -> isize { self.argc } fn argv(&self) -> *const *const c_char { &self.argv0 as *const _ } fn envp(&self) -> *const *const c_char { unsafe { self.argv().offset(self.argc() + 1) } } } #[inline(never)] #[no_mangle] pub unsafe extern "C" fn relibc_start(sp: &'static Stack) -> ! { extern "C" { static __preinit_array_start: extern "C" fn(); static __preinit_array_end: extern "C" fn(); static __init_array_start: extern "C" fn(); static __init_array_end: extern "C" fn(); fn _init(); fn main(argc: isize, argv: *const *const c_char, envp: *const *const c_char) -> c_int; } let argc = sp.argc(); let argv = sp.argv(); let envp = sp.envp(); let mut len = 0; while *envp.offset(len) != ptr::null() { len += 1; } platform::inner_environ = Vec::with_capacity(len as usize + 1); for i in 0..len { let mut item = *envp.offset(i); let mut len = 0; while *item.offset(len) != 0 { len += 1; } let buf = platform::alloc(len as usize + 1) as *mut c_char; for i in 0..=len { *buf.offset(i) = *item.offset(i); } platform::inner_environ.push(buf); } platform::inner_environ.push(ptr::null_mut()); platform::environ = platform::inner_environ.as_mut_ptr(); // Initialize stdin/stdout/stderr, see https://github.com/rust-lang/rust/issues/51718 stdio::stdin = stdio::default_stdin.get(); stdio::stdout = stdio::default_stdout.get(); stdio::stderr = stdio::default_stderr.get(); _init(); // Look for the neighbor functions in memory until the end let mut f = &__preinit_array_start as *const _; while f < &__preinit_array_end { (*f)(); f = f.offset(1); } f = &__init_array_start as *const _; while f < &__init_array_end { (*f)(); f = f.offset(1); } stdlib::exit(main( argc, argv, // not envp, because programs like bash try to modify this *const* // pointer :| platform::environ as *const *const c_char, )); unreachable!(); }