Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 26 additions & 1 deletion lib/compiler/src/engine/unwind/systemv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,11 @@

//! Module for System V ABI unwind registry.

use core::sync::atomic::{AtomicUsize, Ordering::Relaxed};
use core::sync::atomic::{
AtomicBool, AtomicUsize,
Ordering::{self, Relaxed},
};
use std::sync::Once;

use crate::types::unwind::CompiledFunctionUnwindInfoReference;

Expand Down Expand Up @@ -139,6 +143,12 @@ impl UnwindRegistry {

#[allow(clippy::cast_ptr_alignment)]
unsafe fn register_frames(&mut self, eh_frame: &[u8]) {
// Register atexit handler that will tell us if exit has been called.
static INIT: Once = Once::new();
INIT.call_once(|| unsafe {
libc::atexit(atexit_handler);
});

#[cfg(all(target_os = "macos", target_arch = "aarch64"))]
{
// Special call for macOS on aarch64 to register the `.eh_frame` section.
Expand All @@ -151,6 +161,9 @@ impl UnwindRegistry {

#[cfg(not(all(target_os = "macos", target_arch = "aarch64")))]
{
// Leak the `.eh_frame` to ensure it lives long enough
let eh_frame: &mut [u8] = Box::leak(Box::from(eh_frame));

// Validate that the `.eh_frame` is well-formed before registering it.
// See https://refspecs.linuxfoundation.org/LSB_3.0.0/LSB-Core-generic/LSB-Core-generic/ehframechpt.html for more details.
// We put the frame records into a vector before registering them, because
Expand Down Expand Up @@ -237,6 +250,12 @@ impl UnwindRegistry {
}
}

static EXIT_CALLED: AtomicBool = AtomicBool::new(false);

extern "C" fn atexit_handler() {
EXIT_CALLED.store(true, Ordering::SeqCst);
}

impl Drop for UnwindRegistry {
fn drop(&mut self) {
if self.published {
Expand All @@ -258,6 +277,12 @@ impl Drop for UnwindRegistry {

#[cfg(not(all(target_os = "macos", target_arch = "aarch64")))]
{
// We don't want to deregister frames in UnwindRegistry::Drop as that could be called during
// program shutdown and can collide with release_registered_frames and lead to
// crashes.
if EXIT_CALLED.load(Ordering::SeqCst) {
return;
}
__deregister_frame(*registration as *const _);
}
}
Expand Down
Loading