start.rs 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. // Start code adapted from https://gitlab.redox-os.org/redox-os/relibc/blob/master/src/start.rs
  2. use alloc::{borrow::ToOwned, boxed::Box, collections::BTreeMap, string::String, vec::Vec};
  3. use crate::{
  4. c_str::CStr, header::unistd, platform::types::c_char, start::Stack, sync::mutex::Mutex,
  5. };
  6. use super::{linker::Linker, tcb::Tcb};
  7. use crate::header::sys_auxv::AT_ENTRY;
  8. unsafe fn get_argv(mut ptr: *const usize) -> (Vec<String>, *const usize) {
  9. //traverse the stack and collect argument vector
  10. let mut argv = Vec::new();
  11. while *ptr != 0 {
  12. let arg = *ptr;
  13. match CStr::from_ptr(arg as *const c_char).to_str() {
  14. Ok(arg_str) => argv.push(arg_str.to_owned()),
  15. _ => {
  16. eprintln!("ld.so: failed to parse argv[{}]", argv.len());
  17. unistd::_exit(1);
  18. loop {}
  19. }
  20. }
  21. ptr = ptr.add(1);
  22. }
  23. return (argv, ptr);
  24. }
  25. unsafe fn get_env(mut ptr: *const usize) -> (BTreeMap<String, String>, *const usize) {
  26. //traverse the stack and collect argument environment variables
  27. let mut envs = BTreeMap::new();
  28. while *ptr != 0 {
  29. let env = *ptr;
  30. if let Ok(arg_str) = CStr::from_ptr(env as *const c_char).to_str() {
  31. let mut parts = arg_str.splitn(2, '=');
  32. if let Some(key) = parts.next() {
  33. if let Some(value) = parts.next() {
  34. envs.insert(key.to_owned(), value.to_owned());
  35. }
  36. }
  37. }
  38. ptr = ptr.add(1);
  39. }
  40. return (envs, ptr);
  41. }
  42. unsafe fn get_auxv(mut ptr: *const usize) -> BTreeMap<usize, usize> {
  43. //traverse the stack and collect argument environment variables
  44. let mut auxv = BTreeMap::new();
  45. while *ptr != 0 {
  46. let kind = *ptr;
  47. ptr = ptr.add(1);
  48. let value = *ptr;
  49. ptr = ptr.add(1);
  50. auxv.insert(kind, value);
  51. }
  52. return auxv;
  53. }
  54. unsafe fn adjust_stack(sp: &'static mut Stack) {
  55. let mut argv = sp.argv() as *mut usize;
  56. // Move arguments
  57. loop {
  58. let next_argv = argv.add(1);
  59. let arg = *next_argv;
  60. *argv = arg;
  61. argv = next_argv;
  62. if arg == 0 {
  63. break;
  64. }
  65. }
  66. // Move environment
  67. loop {
  68. let next_argv = argv.add(1);
  69. let arg = *next_argv;
  70. *argv = arg;
  71. argv = next_argv;
  72. if arg == 0 {
  73. break;
  74. }
  75. if let Ok(arg_str) = CStr::from_ptr(arg as *const c_char).to_str() {
  76. let mut parts = arg_str.splitn(2, '=');
  77. if let Some(key) = parts.next() {
  78. if let Some(value) = parts.next() {
  79. if let "LD_LIBRARY_PATH" = key {
  80. //library_path = value
  81. }
  82. }
  83. }
  84. }
  85. }
  86. // Move auxiliary vectors
  87. loop {
  88. let next_argv = argv.add(1);
  89. let kind = *next_argv;
  90. *argv = kind;
  91. argv = next_argv;
  92. let next_argv = argv.add(1);
  93. let value = *next_argv;
  94. *argv = value;
  95. argv = next_argv;
  96. if kind == 0 {
  97. break;
  98. }
  99. }
  100. sp.argc -= 1;
  101. }
  102. #[no_mangle]
  103. pub extern "C" fn relibc_ld_so_start(sp: &'static mut Stack, ld_entry: usize) -> usize {
  104. // first we get the arguments, the environment, and the auxilary vector
  105. let (argv, envs, auxv) = unsafe {
  106. let argv_start = sp.argv() as *mut usize;
  107. let (argv, argv_end) = get_argv(argv_start);
  108. let (envs, envs_end) = get_env(argv_end.add(1));
  109. let auxv = get_auxv(envs_end.add(1));
  110. (argv, envs, auxv)
  111. };
  112. let img_entry = *auxv.get(&AT_ENTRY).unwrap_or_else(|| {
  113. eprintln!("failed to find AT_ENTRY");
  114. unistd::_exit(1);
  115. loop {}
  116. });
  117. // Some variables that will be overridden by environment and auxiliary vectors
  118. let library_path = match envs.get("LD_LIBRARY_PATH") {
  119. Some(lib_path) => lib_path,
  120. None => "/lib",
  121. };
  122. let path;
  123. let is_manual = img_entry == ld_entry;
  124. if is_manual {
  125. // ld.so is run directly by user and not via execve() or similar systemcall
  126. println!("argv: {:#?}", argv);
  127. println!("envs: {:#?}", envs);
  128. println!("auxv: {:#x?}", auxv);
  129. if sp.argc < 2 {
  130. eprintln!("ld.so [executable] [arguments...]");
  131. unistd::_exit(1);
  132. loop {}
  133. }
  134. unsafe { adjust_stack(sp) };
  135. path = &argv[1];
  136. } else {
  137. path = &argv[0];
  138. }
  139. let mut linker = Linker::new(library_path, is_manual);
  140. match linker.load(&path, &path) {
  141. Ok(()) => (),
  142. Err(err) => {
  143. eprintln!("ld.so: failed to load '{}': {}", path, err);
  144. unistd::_exit(1);
  145. loop {}
  146. }
  147. }
  148. let entry = match linker.link(Some(&path)) {
  149. Ok(ok) => match ok {
  150. Some(some) => some,
  151. None => {
  152. eprintln!("ld.so: failed to link '{}': missing entry", path);
  153. unistd::_exit(1);
  154. loop {}
  155. }
  156. },
  157. Err(err) => {
  158. eprintln!("ld.so: failed to link '{}': {}", path, err);
  159. unistd::_exit(1);
  160. loop {}
  161. }
  162. };
  163. if let Some(tcb) = unsafe { Tcb::current() } {
  164. tcb.linker_ptr = Box::into_raw(Box::new(Mutex::new(linker)));
  165. }
  166. if is_manual {
  167. eprintln!("ld.so: entry '{}': {:#x}", path, entry);
  168. }
  169. entry
  170. }