diff options
| author | Jubilee Young <workingjubilee@gmail.com> | 2023-07-10 01:45:31 -0700 |
|---|---|---|
| committer | Jubilee Young <workingjubilee@gmail.com> | 2023-07-10 12:05:16 -0700 |
| commit | 094cb1a9fbb6b2c9b6094cd6424139f70f8912cc (patch) | |
| tree | 46769cc5b814c702243ff94cb9d2df0d6ad89d20 /compiler/rustc_driver_impl | |
| parent | 71f71a5397c42fec01f5c1045c638d961fa9f7ca (diff) | |
| download | rust-094cb1a9fbb6b2c9b6094cd6424139f70f8912cc.tar.gz rust-094cb1a9fbb6b2c9b6094cd6424139f70f8912cc.zip | |
Dynamically size sigaltstk in rustc
rustc installs a signal stack that assumes that MINSIGSTKSZ is a constant, unchanging value. Newer hardware undermines that assumption greatly, with register files larger than MINSIGSTKZ. Properly handle this so that it is correct on all supported Linux versions with all CPUs.
Diffstat (limited to 'compiler/rustc_driver_impl')
| -rw-r--r-- | compiler/rustc_driver_impl/src/lib.rs | 27 |
1 files changed, 22 insertions, 5 deletions
diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 9352fe3147e..2e26ce111f0 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -1453,13 +1453,13 @@ mod signal_handler { /// When an error signal (such as SIGABRT or SIGSEGV) is delivered to the /// process, print a stack trace and then exit. pub(super) fn install() { + use std::alloc::{alloc, Layout}; + unsafe { - const ALT_STACK_SIZE: usize = libc::MINSIGSTKSZ + 64 * 1024; + let alt_stack_size: usize = min_sigstack_size() + 64 * 1024; let mut alt_stack: libc::stack_t = std::mem::zeroed(); - alt_stack.ss_sp = - std::alloc::alloc(std::alloc::Layout::from_size_align(ALT_STACK_SIZE, 1).unwrap()) - as *mut libc::c_void; - alt_stack.ss_size = ALT_STACK_SIZE; + alt_stack.ss_sp = alloc(Layout::from_size_align(alt_stack_size, 1).unwrap()).cast(); + alt_stack.ss_size = alt_stack_size; libc::sigaltstack(&alt_stack, std::ptr::null_mut()); let mut sa: libc::sigaction = std::mem::zeroed(); @@ -1469,6 +1469,23 @@ mod signal_handler { libc::sigaction(libc::SIGSEGV, &sa, std::ptr::null_mut()); } } + + /// Modern kernels on modern hardware can have dynamic signal stack sizes. + #[cfg(any(target_os = "linux", target_os = "android"))] + fn min_sigstack_size() -> usize { + const AT_MINSIGSTKSZ: core::ffi::c_ulong = 51; + let dynamic_sigstksz = unsafe { libc::getauxval(AT_MINSIGSTKSZ) }; + // If getauxval couldn't find the entry, it returns 0, + // so take the higher of the "constant" and auxval. + // This transparently supports older kernels which don't provide AT_MINSIGSTKSZ + libc::MINSIGSTKSZ.max(dynamic_sigstksz as _) + } + + /// Not all OS support hardware where this is needed. + #[cfg(not(any(target_os = "linux", target_os = "android")))] + fn min_sigstack_size() -> usize { + libc::MINSIGSTKSZ + } } #[cfg(not(all(unix, any(target_env = "gnu", target_os = "macos"))))] |
