start.rs 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. use alloc::vec::Vec;
  2. use core::{intrinsics, ptr};
  3. use header::{stdio, stdlib};
  4. use ld_so;
  5. use platform;
  6. use platform::types::*;
  7. use platform::{Pal, Sys};
  8. #[repr(C)]
  9. pub struct Stack {
  10. pub argc: isize,
  11. pub argv0: *const c_char,
  12. }
  13. impl Stack {
  14. pub fn argv(&self) -> *const *const c_char {
  15. &self.argv0 as *const _
  16. }
  17. pub fn envp(&self) -> *const *const c_char {
  18. unsafe { self.argv().offset(self.argc + 1) }
  19. }
  20. pub fn auxv(&self) -> *const (usize, usize) {
  21. unsafe {
  22. let mut envp = self.envp();
  23. while !(*envp).is_null() {
  24. envp = envp.add(1);
  25. }
  26. envp.add(1) as *const (usize, usize)
  27. }
  28. }
  29. }
  30. unsafe fn copy_string_array(array: *const *const c_char, len: usize) -> Vec<*mut c_char> {
  31. let mut vec = Vec::with_capacity(len + 1);
  32. for i in 0..len {
  33. let item = *array.add(i);
  34. let mut len = 0;
  35. while *item.add(len) != 0 {
  36. len += 1;
  37. }
  38. let buf = platform::alloc(len + 1) as *mut c_char;
  39. for i in 0..=len {
  40. *buf.add(i) = *item.add(i);
  41. }
  42. vec.push(buf);
  43. }
  44. vec.push(ptr::null_mut());
  45. vec
  46. }
  47. // Since Redox and Linux are so similar, it is easy to accidentally run a binary from one on the
  48. // other. This will test that the current system is compatible with the current binary
  49. #[no_mangle]
  50. pub unsafe fn relibc_verify_host() {
  51. if !Sys::verify() {
  52. intrinsics::abort();
  53. }
  54. }
  55. #[inline(never)]
  56. #[no_mangle]
  57. pub unsafe extern "C" fn relibc_start(sp: &'static Stack) -> ! {
  58. extern "C" {
  59. static __preinit_array_start: extern "C" fn();
  60. static __preinit_array_end: extern "C" fn();
  61. static __init_array_start: extern "C" fn();
  62. static __init_array_end: extern "C" fn();
  63. fn pthread_init();
  64. fn _init();
  65. fn main(argc: isize, argv: *mut *mut c_char, envp: *mut *mut c_char) -> c_int;
  66. }
  67. // Ensure correct host system before executing more system calls
  68. relibc_verify_host();
  69. ld_so::init(sp);
  70. // Set up argc and argv
  71. let argc = sp.argc;
  72. let argv = sp.argv();
  73. platform::inner_argv = copy_string_array(argv, argc as usize);
  74. platform::argv = platform::inner_argv.as_mut_ptr();
  75. // Set up envp
  76. let envp = sp.envp();
  77. let mut len = 0;
  78. while !(*envp.add(len)).is_null() {
  79. len += 1;
  80. }
  81. platform::inner_environ = copy_string_array(envp, len);
  82. platform::environ = platform::inner_environ.as_mut_ptr();
  83. // Initialize stdin/stdout/stderr, see https://github.com/rust-lang/rust/issues/51718
  84. stdio::stdin = stdio::default_stdin.get();
  85. stdio::stdout = stdio::default_stdout.get();
  86. stdio::stderr = stdio::default_stderr.get();
  87. pthread_init();
  88. // Run preinit array
  89. {
  90. let mut f = &__preinit_array_start as *const _;
  91. #[allow(clippy::op_ref)]
  92. while f < &__preinit_array_end {
  93. (*f)();
  94. f = f.offset(1);
  95. }
  96. }
  97. // Call init section
  98. _init();
  99. // Run init array
  100. {
  101. let mut f = &__init_array_start as *const _;
  102. #[allow(clippy::op_ref)]
  103. while f < &__init_array_end {
  104. (*f)();
  105. f = f.offset(1);
  106. }
  107. }
  108. // not argv or envp, because programs like bash try to modify this *const* pointer :|
  109. stdlib::exit(main(argc, platform::argv, platform::environ));
  110. unreachable!();
  111. }