123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132 |
- use alloc::vec::Vec;
- use core::{intrinsics, ptr};
- use header::{stdio, stdlib};
- use ld_so;
- use platform;
- use platform::types::*;
- use platform::{Pal, Sys};
- #[repr(C)]
- pub struct Stack {
- pub argc: isize,
- pub argv0: *const c_char,
- }
- impl Stack {
- pub fn argv(&self) -> *const *const c_char {
- &self.argv0 as *const _
- }
- pub fn envp(&self) -> *const *const c_char {
- unsafe { self.argv().offset(self.argc + 1) }
- }
- pub fn auxv(&self) -> *const (usize, usize) {
- unsafe {
- let mut envp = self.envp();
- while !(*envp).is_null() {
- envp = envp.add(1);
- }
- envp.add(1) as *const (usize, usize)
- }
- }
- }
- unsafe fn copy_string_array(array: *const *const c_char, len: usize) -> Vec<*mut c_char> {
- let mut vec = Vec::with_capacity(len + 1);
- for i in 0..len {
- let item = *array.add(i);
- let mut len = 0;
- while *item.add(len) != 0 {
- len += 1;
- }
- let buf = platform::alloc(len + 1) as *mut c_char;
- for i in 0..=len {
- *buf.add(i) = *item.add(i);
- }
- vec.push(buf);
- }
- vec.push(ptr::null_mut());
- vec
- }
- // Since Redox and Linux are so similar, it is easy to accidentally run a binary from one on the
- // other. This will test that the current system is compatible with the current binary
- #[no_mangle]
- pub unsafe fn relibc_verify_host() {
- if !Sys::verify() {
- intrinsics::abort();
- }
- }
- #[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 pthread_init();
- fn _init();
- fn main(argc: isize, argv: *mut *mut c_char, envp: *mut *mut c_char) -> c_int;
- }
- // Ensure correct host system before executing more system calls
- relibc_verify_host();
- ld_so::init(sp);
- // Set up argc and argv
- let argc = sp.argc;
- let argv = sp.argv();
- platform::inner_argv = copy_string_array(argv, argc as usize);
- platform::argv = platform::inner_argv.as_mut_ptr();
- // Set up envp
- let envp = sp.envp();
- let mut len = 0;
- while !(*envp.add(len)).is_null() {
- len += 1;
- }
- platform::inner_environ = copy_string_array(envp, len);
- 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();
- pthread_init();
- // Run preinit array
- {
- let mut f = &__preinit_array_start as *const _;
- #[allow(clippy::op_ref)]
- while f < &__preinit_array_end {
- (*f)();
- f = f.offset(1);
- }
- }
- // Call init section
- _init();
- // Run init array
- {
- let mut f = &__init_array_start as *const _;
- #[allow(clippy::op_ref)]
- while f < &__init_array_end {
- (*f)();
- f = f.offset(1);
- }
- }
- // not argv or envp, because programs like bash try to modify this *const* pointer :|
- stdlib::exit(main(argc, platform::argv, platform::environ));
- unreachable!();
- }
|