瀏覽代碼

Move IO Initialization to .init_array section

Most shared object in linux have their initialization in a separate
.init_array section. but glibc does not have the same behavour. Instead
the initialization is part of crt0. which (as it seams to me) run after
.init_array section. As such, this patch move IO initialization to
separate function that is marked as .init_array member and then the crt0
call this function only if init_array was never invoked (as in
statically linked binaries).
oddcoder 5 年之前
父節點
當前提交
b717f6cf5a
共有 1 個文件被更改,包括 21 次插入5 次删除
  1. 21 5
      src/start.rs

+ 21 - 5
src/start.rs

@@ -60,6 +60,24 @@ pub unsafe fn relibc_verify_host() {
         intrinsics::abort();
     }
 }
+#[link_section = ".init_array"]
+#[used]
+static INIT_ARRAY: [extern "C" fn(); 1] = [init_array];
+
+static mut init_complete: bool = false;
+
+extern "C" fn init_array() {
+    io_init();
+    unsafe { init_complete = true };
+}
+fn io_init() {
+    unsafe {
+        // 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();
+    }
+}
 
 #[inline(never)]
 #[no_mangle]
@@ -95,11 +113,9 @@ pub unsafe extern "C" fn relibc_start(sp: &'static Stack) -> ! {
     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();
-
+    if !init_complete {
+        init_array();
+    }
     pthread_init();
 
     // Run preinit array