about summary refs log tree commit diff
path: root/tests/run-make/static-pie/rmake.rs
blob: cb24c0495be8fecd55b88c69d39f8f60fdaeb06b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
// 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")
        .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");
}