1
Fork 0

Enable inline stack probes on PowerPC and SystemZ

This commit is contained in:
Josh Stone 2022-09-26 13:40:24 -07:00
parent e1d7dec558
commit ad8f519ed7
23 changed files with 107 additions and 48 deletions

View file

@ -1,11 +1,12 @@
use crate::abi::Endian; use crate::abi::Endian;
use crate::spec::{LinkerFlavor, Target, TargetOptions}; use crate::spec::{LinkerFlavor, StackProbeType, Target, TargetOptions};
pub fn target() -> Target { pub fn target() -> Target {
let mut base = super::freebsd_base::opts(); let mut base = super::freebsd_base::opts();
base.cpu = "ppc64".into(); base.cpu = "ppc64".into();
base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]); base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]);
base.max_atomic_width = Some(64); base.max_atomic_width = Some(64);
base.stack_probes = StackProbeType::Inline;
Target { Target {
llvm_target: "powerpc64-unknown-freebsd".into(), llvm_target: "powerpc64-unknown-freebsd".into(),

View file

@ -1,11 +1,12 @@
use crate::abi::Endian; use crate::abi::Endian;
use crate::spec::{LinkerFlavor, Target, TargetOptions}; use crate::spec::{LinkerFlavor, StackProbeType, Target, TargetOptions};
pub fn target() -> Target { pub fn target() -> Target {
let mut base = super::linux_gnu_base::opts(); let mut base = super::linux_gnu_base::opts();
base.cpu = "ppc64".into(); base.cpu = "ppc64".into();
base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]); base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]);
base.max_atomic_width = Some(64); base.max_atomic_width = Some(64);
base.stack_probes = StackProbeType::Inline;
Target { Target {
llvm_target: "powerpc64-unknown-linux-gnu".into(), llvm_target: "powerpc64-unknown-linux-gnu".into(),

View file

@ -1,11 +1,12 @@
use crate::abi::Endian; use crate::abi::Endian;
use crate::spec::{LinkerFlavor, Target, TargetOptions}; use crate::spec::{LinkerFlavor, StackProbeType, Target, TargetOptions};
pub fn target() -> Target { pub fn target() -> Target {
let mut base = super::linux_musl_base::opts(); let mut base = super::linux_musl_base::opts();
base.cpu = "ppc64".into(); base.cpu = "ppc64".into();
base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]); base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]);
base.max_atomic_width = Some(64); base.max_atomic_width = Some(64);
base.stack_probes = StackProbeType::Inline;
Target { Target {
llvm_target: "powerpc64-unknown-linux-musl".into(), llvm_target: "powerpc64-unknown-linux-musl".into(),

View file

@ -1,11 +1,12 @@
use crate::abi::Endian; use crate::abi::Endian;
use crate::spec::{LinkerFlavor, Target, TargetOptions}; use crate::spec::{LinkerFlavor, StackProbeType, Target, TargetOptions};
pub fn target() -> Target { pub fn target() -> Target {
let mut base = super::openbsd_base::opts(); let mut base = super::openbsd_base::opts();
base.cpu = "ppc64".into(); base.cpu = "ppc64".into();
base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]); base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]);
base.max_atomic_width = Some(64); base.max_atomic_width = Some(64);
base.stack_probes = StackProbeType::Inline;
Target { Target {
llvm_target: "powerpc64-unknown-openbsd".into(), llvm_target: "powerpc64-unknown-openbsd".into(),

View file

@ -1,11 +1,12 @@
use crate::abi::Endian; use crate::abi::Endian;
use crate::spec::{LinkerFlavor, Target, TargetOptions}; use crate::spec::{LinkerFlavor, StackProbeType, Target, TargetOptions};
pub fn target() -> Target { pub fn target() -> Target {
let mut base = super::vxworks_base::opts(); let mut base = super::vxworks_base::opts();
base.cpu = "ppc64".into(); base.cpu = "ppc64".into();
base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]); base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]);
base.max_atomic_width = Some(64); base.max_atomic_width = Some(64);
base.stack_probes = StackProbeType::Inline;
Target { Target {
llvm_target: "powerpc64-unknown-linux-gnu".into(), llvm_target: "powerpc64-unknown-linux-gnu".into(),

View file

@ -1,10 +1,11 @@
use crate::spec::{LinkerFlavor, Target, TargetOptions}; use crate::spec::{LinkerFlavor, StackProbeType, Target, TargetOptions};
pub fn target() -> Target { pub fn target() -> Target {
let mut base = super::freebsd_base::opts(); let mut base = super::freebsd_base::opts();
base.cpu = "ppc64le".into(); base.cpu = "ppc64le".into();
base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]); base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]);
base.max_atomic_width = Some(64); base.max_atomic_width = Some(64);
base.stack_probes = StackProbeType::Inline;
Target { Target {
llvm_target: "powerpc64le-unknown-freebsd".into(), llvm_target: "powerpc64le-unknown-freebsd".into(),

View file

@ -1,10 +1,11 @@
use crate::spec::{LinkerFlavor, Target, TargetOptions}; use crate::spec::{LinkerFlavor, StackProbeType, Target, TargetOptions};
pub fn target() -> Target { pub fn target() -> Target {
let mut base = super::linux_gnu_base::opts(); let mut base = super::linux_gnu_base::opts();
base.cpu = "ppc64le".into(); base.cpu = "ppc64le".into();
base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]); base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]);
base.max_atomic_width = Some(64); base.max_atomic_width = Some(64);
base.stack_probes = StackProbeType::Inline;
Target { Target {
llvm_target: "powerpc64le-unknown-linux-gnu".into(), llvm_target: "powerpc64le-unknown-linux-gnu".into(),

View file

@ -1,10 +1,11 @@
use crate::spec::{LinkerFlavor, Target, TargetOptions}; use crate::spec::{LinkerFlavor, StackProbeType, Target, TargetOptions};
pub fn target() -> Target { pub fn target() -> Target {
let mut base = super::linux_musl_base::opts(); let mut base = super::linux_musl_base::opts();
base.cpu = "ppc64le".into(); base.cpu = "ppc64le".into();
base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]); base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]);
base.max_atomic_width = Some(64); base.max_atomic_width = Some(64);
base.stack_probes = StackProbeType::Inline;
Target { Target {
llvm_target: "powerpc64le-unknown-linux-musl".into(), llvm_target: "powerpc64le-unknown-linux-musl".into(),

View file

@ -1,11 +1,12 @@
use crate::abi::Endian; use crate::abi::Endian;
use crate::spec::{LinkerFlavor, Target, TargetOptions}; use crate::spec::{LinkerFlavor, StackProbeType, Target, TargetOptions};
pub fn target() -> Target { pub fn target() -> Target {
let mut base = super::freebsd_base::opts(); let mut base = super::freebsd_base::opts();
// Extra hint to linker that we are generating secure-PLT code. // Extra hint to linker that we are generating secure-PLT code.
base.add_pre_link_args(LinkerFlavor::Gcc, &["-m32", "--target=powerpc-unknown-freebsd13.0"]); base.add_pre_link_args(LinkerFlavor::Gcc, &["-m32", "--target=powerpc-unknown-freebsd13.0"]);
base.max_atomic_width = Some(32); base.max_atomic_width = Some(32);
base.stack_probes = StackProbeType::Inline;
Target { Target {
llvm_target: "powerpc-unknown-freebsd13.0".into(), llvm_target: "powerpc-unknown-freebsd13.0".into(),

View file

@ -1,10 +1,11 @@
use crate::abi::Endian; use crate::abi::Endian;
use crate::spec::{LinkerFlavor, Target, TargetOptions}; use crate::spec::{LinkerFlavor, StackProbeType, Target, TargetOptions};
pub fn target() -> Target { pub fn target() -> Target {
let mut base = super::linux_gnu_base::opts(); let mut base = super::linux_gnu_base::opts();
base.add_pre_link_args(LinkerFlavor::Gcc, &["-m32"]); base.add_pre_link_args(LinkerFlavor::Gcc, &["-m32"]);
base.max_atomic_width = Some(32); base.max_atomic_width = Some(32);
base.stack_probes = StackProbeType::Inline;
Target { Target {
llvm_target: "powerpc-unknown-linux-gnu".into(), llvm_target: "powerpc-unknown-linux-gnu".into(),

View file

@ -1,10 +1,11 @@
use crate::abi::Endian; use crate::abi::Endian;
use crate::spec::{LinkerFlavor, Target, TargetOptions}; use crate::spec::{LinkerFlavor, StackProbeType, Target, TargetOptions};
pub fn target() -> Target { pub fn target() -> Target {
let mut base = super::linux_gnu_base::opts(); let mut base = super::linux_gnu_base::opts();
base.add_pre_link_args(LinkerFlavor::Gcc, &["-mspe"]); base.add_pre_link_args(LinkerFlavor::Gcc, &["-mspe"]);
base.max_atomic_width = Some(32); base.max_atomic_width = Some(32);
base.stack_probes = StackProbeType::Inline;
Target { Target {
llvm_target: "powerpc-unknown-linux-gnuspe".into(), llvm_target: "powerpc-unknown-linux-gnuspe".into(),

View file

@ -1,10 +1,11 @@
use crate::abi::Endian; use crate::abi::Endian;
use crate::spec::{LinkerFlavor, Target, TargetOptions}; use crate::spec::{LinkerFlavor, StackProbeType, Target, TargetOptions};
pub fn target() -> Target { pub fn target() -> Target {
let mut base = super::linux_musl_base::opts(); let mut base = super::linux_musl_base::opts();
base.add_pre_link_args(LinkerFlavor::Gcc, &["-m32"]); base.add_pre_link_args(LinkerFlavor::Gcc, &["-m32"]);
base.max_atomic_width = Some(32); base.max_atomic_width = Some(32);
base.stack_probes = StackProbeType::Inline;
Target { Target {
llvm_target: "powerpc-unknown-linux-musl".into(), llvm_target: "powerpc-unknown-linux-musl".into(),

View file

@ -1,10 +1,11 @@
use crate::abi::Endian; use crate::abi::Endian;
use crate::spec::{LinkerFlavor, Target, TargetOptions}; use crate::spec::{LinkerFlavor, StackProbeType, Target, TargetOptions};
pub fn target() -> Target { pub fn target() -> Target {
let mut base = super::netbsd_base::opts(); let mut base = super::netbsd_base::opts();
base.add_pre_link_args(LinkerFlavor::Gcc, &["-m32"]); base.add_pre_link_args(LinkerFlavor::Gcc, &["-m32"]);
base.max_atomic_width = Some(32); base.max_atomic_width = Some(32);
base.stack_probes = StackProbeType::Inline;
Target { Target {
llvm_target: "powerpc-unknown-netbsd".into(), llvm_target: "powerpc-unknown-netbsd".into(),

View file

@ -1,10 +1,11 @@
use crate::abi::Endian; use crate::abi::Endian;
use crate::spec::Target; use crate::spec::{StackProbeType, Target};
pub fn target() -> Target { pub fn target() -> Target {
let mut base = super::openbsd_base::opts(); let mut base = super::openbsd_base::opts();
base.endian = Endian::Big; base.endian = Endian::Big;
base.max_atomic_width = Some(32); base.max_atomic_width = Some(32);
base.stack_probes = StackProbeType::Inline;
Target { Target {
llvm_target: "powerpc-unknown-openbsd".into(), llvm_target: "powerpc-unknown-openbsd".into(),

View file

@ -1,10 +1,11 @@
use crate::abi::Endian; use crate::abi::Endian;
use crate::spec::{LinkerFlavor, Target, TargetOptions}; use crate::spec::{LinkerFlavor, StackProbeType, Target, TargetOptions};
pub fn target() -> Target { pub fn target() -> Target {
let mut base = super::vxworks_base::opts(); let mut base = super::vxworks_base::opts();
base.add_pre_link_args(LinkerFlavor::Gcc, &["-m32", "--secure-plt"]); base.add_pre_link_args(LinkerFlavor::Gcc, &["-m32", "--secure-plt"]);
base.max_atomic_width = Some(32); base.max_atomic_width = Some(32);
base.stack_probes = StackProbeType::Inline;
Target { Target {
llvm_target: "powerpc-unknown-linux-gnu".into(), llvm_target: "powerpc-unknown-linux-gnu".into(),

View file

@ -1,10 +1,11 @@
use crate::abi::Endian; use crate::abi::Endian;
use crate::spec::{LinkerFlavor, Target, TargetOptions}; use crate::spec::{LinkerFlavor, StackProbeType, Target, TargetOptions};
pub fn target() -> Target { pub fn target() -> Target {
let mut base = super::vxworks_base::opts(); let mut base = super::vxworks_base::opts();
base.add_pre_link_args(LinkerFlavor::Gcc, &["-mspe", "--secure-plt"]); base.add_pre_link_args(LinkerFlavor::Gcc, &["-mspe", "--secure-plt"]);
base.max_atomic_width = Some(32); base.max_atomic_width = Some(32);
base.stack_probes = StackProbeType::Inline;
Target { Target {
llvm_target: "powerpc-unknown-linux-gnuspe".into(), llvm_target: "powerpc-unknown-linux-gnuspe".into(),

View file

@ -1,5 +1,5 @@
use crate::abi::Endian; use crate::abi::Endian;
use crate::spec::Target; use crate::spec::{StackProbeType, Target};
pub fn target() -> Target { pub fn target() -> Target {
let mut base = super::linux_gnu_base::opts(); let mut base = super::linux_gnu_base::opts();
@ -12,6 +12,7 @@ pub fn target() -> Target {
base.features = "-vector".into(); base.features = "-vector".into();
base.max_atomic_width = Some(64); base.max_atomic_width = Some(64);
base.min_global_align = Some(16); base.min_global_align = Some(16);
base.stack_probes = StackProbeType::Inline;
Target { Target {
llvm_target: "s390x-unknown-linux-gnu".into(), llvm_target: "s390x-unknown-linux-gnu".into(),

View file

@ -1,5 +1,5 @@
use crate::abi::Endian; use crate::abi::Endian;
use crate::spec::Target; use crate::spec::{StackProbeType, Target};
pub fn target() -> Target { pub fn target() -> Target {
let mut base = super::linux_musl_base::opts(); let mut base = super::linux_musl_base::opts();
@ -13,6 +13,7 @@ pub fn target() -> Target {
base.max_atomic_width = Some(64); base.max_atomic_width = Some(64);
base.min_global_align = Some(16); base.min_global_align = Some(16);
base.static_position_independent_executables = true; base.static_position_independent_executables = true;
base.stack_probes = StackProbeType::Inline;
Target { Target {
llvm_target: "s390x-unknown-linux-musl".into(), llvm_target: "s390x-unknown-linux-musl".into(),

View file

@ -0,0 +1,22 @@
// Check the "probe-stack" attribute for targets with `StackProbeType::Call`,
// or `StackProbeType::InlineOrCall` when running on older LLVM.
// compile-flags: -C no-prepopulate-passes
// revisions: i686 x86_64
//[i686] compile-flags: --target i686-unknown-linux-gnu
//[i686] needs-llvm-components: x86
//[x86_64] compile-flags: --target x86_64-unknown-linux-gnu
//[x86_64] needs-llvm-components: x86
#![crate_type = "rlib"]
#![feature(no_core, lang_items)]
#![no_core]
#[lang = "sized"]
trait Sized {}
#[no_mangle]
pub fn foo() {
// CHECK: @foo() unnamed_addr #0
// CHECK: attributes #0 = { {{.*}}"probe-stack"="__rust_probestack"{{.*}} }
}

View file

@ -0,0 +1,26 @@
// Check the "probe-stack" attribute for targets with `StackProbeType::Inline`,
// or `StackProbeType::InlineOrCall` when running on newer LLVM.
// compile-flags: -C no-prepopulate-passes
// revisions: powerpc powerpc64 powerpc64le s390x
//[powerpc] compile-flags: --target powerpc-unknown-linux-gnu
//[powerpc] needs-llvm-components: powerpc
//[powerpc64] compile-flags: --target powerpc64-unknown-linux-gnu
//[powerpc64] needs-llvm-components: powerpc
//[powerpc64le] compile-flags: --target powerpc64le-unknown-linux-gnu
//[powerpc64le] needs-llvm-components: powerpc
//[s390x] compile-flags: --target s390x-unknown-linux-gnu
//[s390x] needs-llvm-components: systemz
#![crate_type = "rlib"]
#![feature(no_core, lang_items)]
#![no_core]
#[lang = "sized"]
trait Sized {}
#[no_mangle]
pub fn foo() {
// CHECK: @foo() unnamed_addr #0
// CHECK: attributes #0 = { {{.*}}"probe-stack"="inline-asm"{{.*}} }
}

View file

@ -1,22 +0,0 @@
// ignore-arm
// ignore-aarch64
// ignore-mips
// ignore-mips64
// ignore-powerpc
// ignore-powerpc64
// ignore-powerpc64le
// ignore-riscv64
// ignore-s390x
// ignore-sparc
// ignore-sparc64
// ignore-wasm
// ignore-emscripten
// ignore-windows
// compile-flags: -C no-prepopulate-passes
#![crate_type = "lib"]
#[no_mangle]
pub fn foo() {
// CHECK: @foo() unnamed_addr #0
}

View file

@ -3,8 +3,6 @@
// ignore-aarch64 // ignore-aarch64
// ignore-mips // ignore-mips
// ignore-mips64 // ignore-mips64
// ignore-powerpc
// ignore-s390x
// ignore-sparc // ignore-sparc
// ignore-sparc64 // ignore-sparc64
// ignore-wasm // ignore-wasm

View file

@ -3,8 +3,6 @@
// ignore-aarch64 // ignore-aarch64
// ignore-mips // ignore-mips
// ignore-mips64 // ignore-mips64
// ignore-powerpc
// ignore-s390x
// ignore-sparc // ignore-sparc
// ignore-sparc64 // ignore-sparc64
// ignore-wasm // ignore-wasm
@ -27,8 +25,9 @@ fn main() {
let args = env::args().skip(1).collect::<Vec<_>>(); let args = env::args().skip(1).collect::<Vec<_>>();
if args.len() > 0 { if args.len() > 0 {
match &args[0][..] { match &args[0][..] {
"main-thread" => recurse(&MaybeUninit::uninit()), "main-recurse" => overflow_recurse(),
"child-thread" => thread::spawn(|| recurse(&MaybeUninit::uninit())).join().unwrap(), "child-recurse" => thread::spawn(overflow_recurse).join().unwrap(),
"child-frame" => overflow_frame(),
_ => panic!(), _ => panic!(),
} }
return; return;
@ -41,9 +40,10 @@ fn main() {
// that we report stack overflow on the main thread, see #43052 for some // that we report stack overflow on the main thread, see #43052 for some
// details // details
if cfg!(not(target_os = "linux")) { if cfg!(not(target_os = "linux")) {
assert_overflow(Command::new(&me).arg("main-thread")); assert_overflow(Command::new(&me).arg("main-recurse"));
} }
assert_overflow(Command::new(&me).arg("child-thread")); assert_overflow(Command::new(&me).arg("child-recurse"));
assert_overflow(Command::new(&me).arg("child-frame"));
} }
#[allow(unconditional_recursion)] #[allow(unconditional_recursion)]
@ -55,6 +55,23 @@ fn recurse(array: &MaybeUninit<[u64; 1024]>) {
recurse(&local); recurse(&local);
} }
#[inline(never)]
fn overflow_recurse() {
recurse(&MaybeUninit::uninit());
}
fn overflow_frame() {
// By using a 1MiB stack frame with only 512KiB stack, we'll jump over any
// guard page, even with 64K pages -- but stack probes should catch it.
const STACK_SIZE: usize = 512 * 1024;
thread::Builder::new().stack_size(STACK_SIZE).spawn(|| {
let local: MaybeUninit<[u8; 2 * STACK_SIZE]> = MaybeUninit::uninit();
unsafe {
black_box(local.as_ptr() as u64);
}
}).unwrap().join().unwrap();
}
fn assert_overflow(cmd: &mut Command) { fn assert_overflow(cmd: &mut Command) {
let output = cmd.output().unwrap(); let output = cmd.output().unwrap();
assert!(!output.status.success()); assert!(!output.status.success());