| // 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_buf(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"); |
| } |