From d8b6be9b1ffad1bff1eebe0905b60b35a234ebee Mon Sep 17 00:00:00 2001 From: leo60228 Date: Thu, 21 Nov 2019 08:21:14 -0500 Subject: Use .init_array section on glibc --- src/libstd/sys/unix/args.rs | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'src/libstd') diff --git a/src/libstd/sys/unix/args.rs b/src/libstd/sys/unix/args.rs index 82ef35ea7b5..4dd331d3130 100644 --- a/src/libstd/sys/unix/args.rs +++ b/src/libstd/sys/unix/args.rs @@ -78,6 +78,26 @@ mod imp { ARGV = argv; } + #[cfg(all(target_os = "linux", target_env = "gnu"))] + #[used] + #[link_section = ".init_array"] + static ARGV_INIT_ARRAY: extern "C" fn( + crate::os::raw::c_int, + *const *const u8, + *const *const u8, + ) = { + extern "C" fn init_wrapper( + argc: crate::os::raw::c_int, + argv: *const *const u8, + _envp: *const *const u8, + ) { + unsafe { + init(argc as isize, argv); + } + } + init_wrapper + }; + pub unsafe fn cleanup() { let _guard = LOCK.lock(); ARGC = 0; -- cgit 1.4.1-3-g733a5 From 1ff055d875d0a3b19e0567a7e1cc6a2ee1a7921a Mon Sep 17 00:00:00 2001 From: leo60228 Date: Thu, 21 Nov 2019 11:44:22 -0500 Subject: Set .init_array priority I'm not entirely sure *why*, but this fixed a problem I was having. --- src/libstd/sys/unix/args.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/libstd') diff --git a/src/libstd/sys/unix/args.rs b/src/libstd/sys/unix/args.rs index 4dd331d3130..209c5c542bc 100644 --- a/src/libstd/sys/unix/args.rs +++ b/src/libstd/sys/unix/args.rs @@ -80,7 +80,7 @@ mod imp { #[cfg(all(target_os = "linux", target_env = "gnu"))] #[used] - #[link_section = ".init_array"] + #[link_section = ".init_array.00099"] static ARGV_INIT_ARRAY: extern "C" fn( crate::os::raw::c_int, *const *const u8, -- cgit 1.4.1-3-g733a5 From e282b2227f4dac70bf805c59fc4c90e5a4e2c0ef Mon Sep 17 00:00:00 2001 From: leo60228 Date: Thu, 21 Nov 2019 11:47:01 -0500 Subject: Document ARGV_INIT_ARRAY --- src/libstd/sys/unix/args.rs | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/libstd') diff --git a/src/libstd/sys/unix/args.rs b/src/libstd/sys/unix/args.rs index 209c5c542bc..58fa305a819 100644 --- a/src/libstd/sys/unix/args.rs +++ b/src/libstd/sys/unix/args.rs @@ -78,6 +78,8 @@ mod imp { ARGV = argv; } + /// glibc passes argc, argv, and envp to functions in .init_array, as a non-standard extension. + /// This allows `std::env::args` to work even in a `cdylib`, as it does on macOS and Windows. #[cfg(all(target_os = "linux", target_env = "gnu"))] #[used] #[link_section = ".init_array.00099"] -- cgit 1.4.1-3-g733a5 From 55fe6d8d5875f1378747ea1681deac64536ef9dc Mon Sep 17 00:00:00 2001 From: leo60228 Date: Thu, 21 Nov 2019 13:34:31 -0500 Subject: Add documentation to `std::env::args[_os]` --- src/libstd/env.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'src/libstd') diff --git a/src/libstd/env.rs b/src/libstd/env.rs index b8989369269..651010d1366 100644 --- a/src/libstd/env.rs +++ b/src/libstd/env.rs @@ -702,6 +702,11 @@ pub struct ArgsOs { inner: sys::args::Args } /// (such as `*` and `?`). On Windows this is not done, and such arguments are /// passed as-is. /// +/// On glibc Linux, arguments are retrieved by placing a function in .init_array. +/// glibc passes argc, argv, and envp to functions in .init_array, as a non-standard extension. +/// This allows `std::env::args` to work even in a `cdylib` or `staticlib`, as it does on macOS +/// and Windows. +/// /// # Panics /// /// The returned iterator will panic during iteration if any argument to the @@ -732,6 +737,11 @@ pub fn args() -> Args { /// set to arbitrary text, and it may not even exist, so this property should /// not be relied upon for security purposes. /// +/// On glibc Linux, arguments are retrieved by placing a function in .init_array. +/// glibc passes argc, argv, and envp to functions in .init_array, as a non-standard extension. +/// This allows `std::env::args` to work even in a `cdylib` or `staticlib`, as it does on macOS +/// and Windows. +/// /// # Examples /// /// ``` -- cgit 1.4.1-3-g733a5 From d448ab0cf10a6c822b209f208a87ce200efd0772 Mon Sep 17 00:00:00 2001 From: leo60228 Date: Thu, 21 Nov 2019 13:42:25 -0500 Subject: Make std::sys::unix::args::init a no-op on glibc Linux --- src/libstd/sys/unix/args.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'src/libstd') diff --git a/src/libstd/sys/unix/args.rs b/src/libstd/sys/unix/args.rs index 58fa305a819..15dafb1bcf9 100644 --- a/src/libstd/sys/unix/args.rs +++ b/src/libstd/sys/unix/args.rs @@ -72,12 +72,18 @@ mod imp { // acquire this mutex reentrantly! static LOCK: Mutex = Mutex::new(); - pub unsafe fn init(argc: isize, argv: *const *const u8) { + unsafe fn really_init(argc: isize, argv: *const *const u8) { let _guard = LOCK.lock(); ARGC = argc; ARGV = argv; } + #[inline(always)] + pub unsafe fn init(_argc: isize, _argv: *const *const u8) { + #[cfg(not(all(target_os = "linux", target_env = "gnu")))] + really_init(_argc, _argv); + } + /// glibc passes argc, argv, and envp to functions in .init_array, as a non-standard extension. /// This allows `std::env::args` to work even in a `cdylib`, as it does on macOS and Windows. #[cfg(all(target_os = "linux", target_env = "gnu"))] @@ -94,7 +100,7 @@ mod imp { _envp: *const *const u8, ) { unsafe { - init(argc as isize, argv); + really_init(argc as isize, argv); } } init_wrapper -- cgit 1.4.1-3-g733a5