From b717f6cf5ab82583afaa103d73a7d0bf5f57df47 Mon Sep 17 00:00:00 2001 From: oddcoder <ahmedsoliman@oddcoder.com> Date: Sun, 19 Apr 2020 12:07:41 +0200 Subject: [PATCH] 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). --- src/start.rs | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/src/start.rs b/src/start.rs index ade155b9..3dd856f5 100644 --- a/src/start.rs +++ b/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 -- GitLab