about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2023-05-08 09:30:21 -0700
committerGitHub <noreply@github.com>2023-05-08 09:30:21 -0700
commitfcb275f85e0e64bf3bb488cbd518bb085040c0cf (patch)
treec62c22848dc08ee15f1e32860a44c72ca4f6c737
parentce042889f7f0d687368a9704eff64cf9542bac6d (diff)
parent16abe6c83d2c9eba8f54be8fbe25ed49791e1e45 (diff)
downloadrust-fcb275f85e0e64bf3bb488cbd518bb085040c0cf.tar.gz
rust-fcb275f85e0e64bf3bb488cbd518bb085040c0cf.zip
Rollup merge of #104070 - nbdd0121:unwind, r=Amanieu
Prevent aborting guard from aborting the process in a forced unwind

Fix #101469
-rw-r--r--compiler/rustc_codegen_gcc/src/builder.rs5
-rw-r--r--compiler/rustc_codegen_llvm/src/builder.rs9
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/block.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/traits/builder.rs1
-rw-r--r--library/std/src/personality/dwarf/eh.rs5
-rw-r--r--library/std/src/personality/gcc.rs11
-rw-r--r--tests/codegen/vec-shrink-panik.rs4
-rw-r--r--tests/run-make/forced-unwind-terminate-pof/Makefile9
-rw-r--r--tests/run-make/forced-unwind-terminate-pof/foo.rs17
9 files changed, 54 insertions, 9 deletions
diff --git a/compiler/rustc_codegen_gcc/src/builder.rs b/compiler/rustc_codegen_gcc/src/builder.rs
index a66ddb6a09f..869344ce92d 100644
--- a/compiler/rustc_codegen_gcc/src/builder.rs
+++ b/compiler/rustc_codegen_gcc/src/builder.rs
@@ -1227,6 +1227,11 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
         (value1, value2)
     }
 
+    fn filter_landing_pad(&mut self, pers_fn: RValue<'gcc>) -> (RValue<'gcc>, RValue<'gcc>) {
+        // TODO(antoyo): generate the correct landing pad
+        self.cleanup_landing_pad(pers_fn)
+    }
+
     #[cfg(feature="master")]
     fn resume(&mut self, exn0: RValue<'gcc>, _exn1: RValue<'gcc>) {
         let exn_type = exn0.get_type();
diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs
index 2fd6db8cbfe..4d0bcd53d15 100644
--- a/compiler/rustc_codegen_llvm/src/builder.rs
+++ b/compiler/rustc_codegen_llvm/src/builder.rs
@@ -985,13 +985,20 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
 
     fn cleanup_landing_pad(&mut self, pers_fn: &'ll Value) -> (&'ll Value, &'ll Value) {
         let ty = self.type_struct(&[self.type_i8p(), self.type_i32()], false);
-        let landing_pad = self.landing_pad(ty, pers_fn, 1 /* FIXME should this be 0? */);
+        let landing_pad = self.landing_pad(ty, pers_fn, 0);
         unsafe {
             llvm::LLVMSetCleanup(landing_pad, llvm::True);
         }
         (self.extract_value(landing_pad, 0), self.extract_value(landing_pad, 1))
     }
 
+    fn filter_landing_pad(&mut self, pers_fn: &'ll Value) -> (&'ll Value, &'ll Value) {
+        let ty = self.type_struct(&[self.type_i8p(), self.type_i32()], false);
+        let landing_pad = self.landing_pad(ty, pers_fn, 1);
+        self.add_clause(landing_pad, self.const_array(self.type_i8p(), &[]));
+        (self.extract_value(landing_pad, 0), self.extract_value(landing_pad, 1))
+    }
+
     fn resume(&mut self, exn0: &'ll Value, exn1: &'ll Value) {
         let ty = self.type_struct(&[self.type_i8p(), self.type_i32()], false);
         let mut exn = self.const_poison(ty);
diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs
index c1613a9640a..a832999225a 100644
--- a/compiler/rustc_codegen_ssa/src/mir/block.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/block.rs
@@ -1600,7 +1600,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                 bx = Bx::build(self.cx, llbb);
 
                 let llpersonality = self.cx.eh_personality();
-                bx.cleanup_landing_pad(llpersonality);
+                bx.filter_landing_pad(llpersonality);
 
                 funclet = None;
             }
diff --git a/compiler/rustc_codegen_ssa/src/traits/builder.rs b/compiler/rustc_codegen_ssa/src/traits/builder.rs
index 57de7e9620e..853c6934c2c 100644
--- a/compiler/rustc_codegen_ssa/src/traits/builder.rs
+++ b/compiler/rustc_codegen_ssa/src/traits/builder.rs
@@ -274,6 +274,7 @@ pub trait BuilderMethods<'a, 'tcx>:
 
     // These are used by everyone except msvc
     fn cleanup_landing_pad(&mut self, pers_fn: Self::Value) -> (Self::Value, Self::Value);
+    fn filter_landing_pad(&mut self, pers_fn: Self::Value) -> (Self::Value, Self::Value);
     fn resume(&mut self, exn0: Self::Value, exn1: Self::Value);
 
     // These are used only by msvc
diff --git a/library/std/src/personality/dwarf/eh.rs b/library/std/src/personality/dwarf/eh.rs
index 87585a8fcd0..79624703a4c 100644
--- a/library/std/src/personality/dwarf/eh.rs
+++ b/library/std/src/personality/dwarf/eh.rs
@@ -47,6 +47,7 @@ pub enum EHAction {
     None,
     Cleanup(usize),
     Catch(usize),
+    Filter(usize),
     Terminate,
 }
 
@@ -142,9 +143,11 @@ unsafe fn interpret_cs_action(
         let ttype_index = action_reader.read_sleb128();
         if ttype_index == 0 {
             EHAction::Cleanup(lpad)
-        } else {
+        } else if ttype_index > 0 {
             // Stop unwinding Rust panics at catch_unwind.
             EHAction::Catch(lpad)
+        } else {
+            EHAction::Filter(lpad)
         }
     }
 }
diff --git a/library/std/src/personality/gcc.rs b/library/std/src/personality/gcc.rs
index 0421b47be02..82edb11cbd1 100644
--- a/library/std/src/personality/gcc.rs
+++ b/library/std/src/personality/gcc.rs
@@ -135,7 +135,7 @@ cfg_if::cfg_if! {
                     EHAction::None | EHAction::Cleanup(_) => {
                         return continue_unwind(exception_object, context);
                     }
-                    EHAction::Catch(_) => {
+                    EHAction::Catch(_) | EHAction::Filter(_) => {
                         // EHABI requires the personality routine to update the
                         // SP value in the barrier cache of the exception object.
                         (*exception_object).private[5] =
@@ -147,7 +147,8 @@ cfg_if::cfg_if! {
             } else {
                 match eh_action {
                     EHAction::None => return continue_unwind(exception_object, context),
-                    EHAction::Cleanup(lpad) | EHAction::Catch(lpad) => {
+                    EHAction::Filter(_) if state & uw::_US_FORCE_UNWIND as c_int != 0 => return continue_unwind(exception_object, context),
+                    EHAction::Cleanup(lpad) | EHAction::Catch(lpad) | EHAction::Filter(lpad) => {
                         uw::_Unwind_SetGR(
                             context,
                             UNWIND_DATA_REG.0,
@@ -201,13 +202,15 @@ cfg_if::cfg_if! {
             if actions as i32 & uw::_UA_SEARCH_PHASE as i32 != 0 {
                 match eh_action {
                     EHAction::None | EHAction::Cleanup(_) => uw::_URC_CONTINUE_UNWIND,
-                    EHAction::Catch(_) => uw::_URC_HANDLER_FOUND,
+                    EHAction::Catch(_) | EHAction::Filter(_) => uw::_URC_HANDLER_FOUND,
                     EHAction::Terminate => uw::_URC_FATAL_PHASE1_ERROR,
                 }
             } else {
                 match eh_action {
                     EHAction::None => uw::_URC_CONTINUE_UNWIND,
-                    EHAction::Cleanup(lpad) | EHAction::Catch(lpad) => {
+                    // Forced unwinding hits a terminate action.
+                    EHAction::Filter(_) if actions as i32 & uw::_UA_FORCE_UNWIND as i32 != 0 => uw::_URC_CONTINUE_UNWIND,
+                    EHAction::Cleanup(lpad) | EHAction::Catch(lpad) | EHAction::Filter(lpad) => {
                         uw::_Unwind_SetGR(
                             context,
                             UNWIND_DATA_REG.0,
diff --git a/tests/codegen/vec-shrink-panik.rs b/tests/codegen/vec-shrink-panik.rs
index b3c3483fea9..4e5d8dc0632 100644
--- a/tests/codegen/vec-shrink-panik.rs
+++ b/tests/codegen/vec-shrink-panik.rs
@@ -25,7 +25,7 @@ pub fn issue71861(vec: Vec<u32>) -> Box<[u32]> {
 
     // Call to panic_cannot_unwind in case of double-panic is expected
     // on LLVM 16 and older, but other panics are not.
-    // CHECK: cleanup
+    // CHECK: filter
     // old-NEXT: ; call core::panicking::panic_cannot_unwind
     // old-NEXT: panic_cannot_unwind
 
@@ -40,7 +40,7 @@ pub fn issue75636<'a>(iter: &[&'a str]) -> Box<[&'a str]> {
 
     // Call to panic_cannot_unwind in case of double-panic is expected,
     // on LLVM 16 and older, but other panics are not.
-    // CHECK: cleanup
+    // CHECK: filter
     // old-NEXT: ; call core::panicking::panic_cannot_unwind
     // old-NEXT: panic_cannot_unwind
 
diff --git a/tests/run-make/forced-unwind-terminate-pof/Makefile b/tests/run-make/forced-unwind-terminate-pof/Makefile
new file mode 100644
index 00000000000..871621520b9
--- /dev/null
+++ b/tests/run-make/forced-unwind-terminate-pof/Makefile
@@ -0,0 +1,9 @@
+# ignore-cross-compile
+# only-linux
+include ../tools.mk
+
+all: foo
+	$(call RUN,foo) | $(CGREP) -v "cannot unwind"
+
+foo: foo.rs
+	$(RUSTC) $<
diff --git a/tests/run-make/forced-unwind-terminate-pof/foo.rs b/tests/run-make/forced-unwind-terminate-pof/foo.rs
new file mode 100644
index 00000000000..0a51287313f
--- /dev/null
+++ b/tests/run-make/forced-unwind-terminate-pof/foo.rs
@@ -0,0 +1,17 @@
+// Tests that forced unwind through POF Rust frames wouldn't trigger our terminating guards.
+
+#![feature(c_unwind)]
+#![no_main]
+
+extern "C-unwind" {
+    fn pthread_exit(v: *mut core::ffi::c_void) -> !;
+}
+
+unsafe extern "C" fn call_pthread_exit() {
+    pthread_exit(core::ptr::null_mut());
+}
+
+#[no_mangle]
+unsafe extern "C-unwind" fn main(_argc: core::ffi::c_int, _argv: *mut *mut core::ffi::c_char) {
+    call_pthread_exit();
+}