From 47171e0c500e791280e269a73c382bfac15148b2 Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Sun, 6 Nov 2022 21:24:20 +0000 Subject: [PATCH 1/7] Use `landingpad filter` to encode aborting landing pad --- compiler/rustc_codegen_gcc/src/builder.rs | 4 ++++ compiler/rustc_codegen_llvm/src/builder.rs | 7 +++++++ compiler/rustc_codegen_ssa/src/mir/block.rs | 2 +- compiler/rustc_codegen_ssa/src/traits/builder.rs | 1 + 4 files changed, 13 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_codegen_gcc/src/builder.rs b/compiler/rustc_codegen_gcc/src/builder.rs index a66ddb6a09f2b..5fba09d795ce8 100644 --- a/compiler/rustc_codegen_gcc/src/builder.rs +++ b/compiler/rustc_codegen_gcc/src/builder.rs @@ -1227,6 +1227,10 @@ 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>) { + 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 2fd6db8cbfeab..10da8cc4c2552 100644 --- a/compiler/rustc_codegen_llvm/src/builder.rs +++ b/compiler/rustc_codegen_llvm/src/builder.rs @@ -992,6 +992,13 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { (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 /* FIXME should this be 0? */); + 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 c1613a9640a8b..a832999225ab6 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 57de7e9620e87..853c6934c2c24 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 From 62237536da0e17fdaa5c03965563a200296c6e12 Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Sun, 6 Nov 2022 21:32:55 +0000 Subject: [PATCH 2/7] Parse catch filter in personality function --- library/std/src/personality/dwarf/eh.rs | 5 ++++- library/std/src/personality/gcc.rs | 8 ++++---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/library/std/src/personality/dwarf/eh.rs b/library/std/src/personality/dwarf/eh.rs index 87585a8fcd0d7..79624703a4cf7 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 0421b47be024e..4c29c332b75a8 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,7 @@ cfg_if::cfg_if! { } else { match eh_action { EHAction::None => return continue_unwind(exception_object, context), - EHAction::Cleanup(lpad) | EHAction::Catch(lpad) => { + EHAction::Cleanup(lpad) | EHAction::Catch(lpad) | EHAction::Filter(lpad) => { uw::_Unwind_SetGR( context, UNWIND_DATA_REG.0, @@ -201,13 +201,13 @@ 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) => { + EHAction::Cleanup(lpad) | EHAction::Catch(lpad) | EHAction::Filter(lpad) => { uw::_Unwind_SetGR( context, UNWIND_DATA_REG.0, From 37f7d322b8cd9e9712c3cc9cf3a550371bd164e0 Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Sun, 6 Nov 2022 21:35:10 +0000 Subject: [PATCH 3/7] Prevent aborting guard from aborting the process in a forced unwind --- library/std/src/personality/gcc.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/library/std/src/personality/gcc.rs b/library/std/src/personality/gcc.rs index 4c29c332b75a8..82edb11cbd146 100644 --- a/library/std/src/personality/gcc.rs +++ b/library/std/src/personality/gcc.rs @@ -147,6 +147,7 @@ cfg_if::cfg_if! { } else { match eh_action { EHAction::None => return continue_unwind(exception_object, context), + 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, @@ -207,6 +208,8 @@ cfg_if::cfg_if! { } else { match eh_action { EHAction::None => uw::_URC_CONTINUE_UNWIND, + // 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, From ecd04fd1b553c06e3e48c0f8485de46758e51636 Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Fri, 7 Apr 2023 17:15:41 +0100 Subject: [PATCH 4/7] Add test for unwinding past terminating POF --- .../forced-unwind-terminate-pof/Makefile | 9 +++++++++ .../run-make/forced-unwind-terminate-pof/foo.rs | 17 +++++++++++++++++ 2 files changed, 26 insertions(+) create mode 100644 tests/run-make/forced-unwind-terminate-pof/Makefile create mode 100644 tests/run-make/forced-unwind-terminate-pof/foo.rs 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 0000000000000..871621520b910 --- /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 0000000000000..0a51287313f6e --- /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(); +} From 97926360e755547dc4663ab75af1e37e9a68e58b Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Fri, 7 Apr 2023 20:11:19 +0100 Subject: [PATCH 5/7] Fix num reserved clauses for landing pad --- compiler/rustc_codegen_llvm/src/builder.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs index 10da8cc4c2552..4d0bcd53d1562 100644 --- a/compiler/rustc_codegen_llvm/src/builder.rs +++ b/compiler/rustc_codegen_llvm/src/builder.rs @@ -985,7 +985,7 @@ 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); } @@ -994,7 +994,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { 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 /* FIXME should this be 0? */); + 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)) } From 91afde57a28b1619f140fbe8463d150ce7c8adca Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Sat, 8 Apr 2023 13:12:24 +0100 Subject: [PATCH 6/7] Add todo for filter landing pad --- compiler/rustc_codegen_gcc/src/builder.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/compiler/rustc_codegen_gcc/src/builder.rs b/compiler/rustc_codegen_gcc/src/builder.rs index 5fba09d795ce8..869344ce92d7d 100644 --- a/compiler/rustc_codegen_gcc/src/builder.rs +++ b/compiler/rustc_codegen_gcc/src/builder.rs @@ -1228,6 +1228,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { } 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) } From 16abe6c83d2c9eba8f54be8fbe25ed49791e1e45 Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Sun, 9 Apr 2023 12:05:35 +0100 Subject: [PATCH 7/7] Fix codegen test --- tests/codegen/vec-shrink-panik.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/codegen/vec-shrink-panik.rs b/tests/codegen/vec-shrink-panik.rs index b3c3483fea982..4e5d8dc063241 100644 --- a/tests/codegen/vec-shrink-panik.rs +++ b/tests/codegen/vec-shrink-panik.rs @@ -25,7 +25,7 @@ pub fn issue71861(vec: Vec) -> 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