// How to manually run this // $ ./x.py test --target x86_64-unknown-linux-[musl,gnu] tests/run-make/static-pie //@ only-x86_64 //@ only-linux //@ ignore-32bit use std::process::Command; use run_make_support::regex::Regex; use run_make_support::{cmd, llvm_readobj, run_with_args, rustc, target}; // Minimum major versions supporting -static-pie const GCC_VERSION: u32 = 8; const CLANG_VERSION: u32 = 9; // Return `true` if the `compiler` version supports `-static-pie`. fn ok_compiler_version(compiler: &str) -> bool { let (trigger, version_threshold) = match compiler { "clang" => ("__clang_major__", CLANG_VERSION), "gcc" => ("__GNUC__", GCC_VERSION), other => panic!("unexpected compiler '{other}', expected 'clang' or 'gcc'"), }; if Command::new(compiler).spawn().is_err() { eprintln!("No {compiler} version detected"); return false; } let compiler_output = cmd(compiler).stdin(trigger).arg("-").arg("-E").arg("-x").arg("c").run().stdout_utf8(); let re = Regex::new(r"(?m)^(\d+)").unwrap(); let version: u32 = re.captures(&compiler_output).unwrap().get(1).unwrap().as_str().parse().unwrap(); if version >= version_threshold { eprintln!("{compiler} supports -static-pie"); true } else { eprintln!("{compiler} too old to support -static-pie, skipping test"); false } } fn test(compiler: &str) { if !ok_compiler_version(compiler) { return; } rustc() .input("test-aslr.rs") .target(target()) .linker(compiler) .arg("-Clinker-flavor=gcc") .arg("-Ctarget-feature=+crt-static") .run(); llvm_readobj() .symbols() .input("test-aslr") .run() .assert_stdout_not_contains("INTERP") .assert_stdout_contains("DYNAMIC"); run_with_args("test-aslr", &["--test-aslr"]); } fn main() { test("clang"); test("gcc"); }