Skip to content

Commit 368db7c

Browse files
committed
Teach bootstrap how to build rust_test_helpers for pauthtest
Also: * update tests to force dynamic library when targetting pauthtest * various test fixes * introduce end-to-end tests for pauthtest (in run-make)
1 parent 9abfac6 commit 368db7c

53 files changed

Lines changed: 527 additions & 66 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

src/bootstrap/src/core/build_steps/test.rs

Lines changed: 54 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use std::collections::HashSet;
1010
use std::env::split_paths;
1111
use std::ffi::{OsStr, OsString};
1212
use std::path::{Path, PathBuf};
13+
use std::process::Command;
1314
use std::{env, fs, iter};
1415

1516
use build_helper::exit;
@@ -2197,7 +2198,12 @@ Please disable assertions with `rust.debug-assertions = false`.
21972198
"-Lnative={}",
21982199
builder.test_helpers_out(test_compiler.host).display()
21992200
));
2200-
targetflags.push(format!("-Lnative={}", builder.test_helpers_out(target).display()));
2201+
let target_helpers = builder.test_helpers_out(target);
2202+
targetflags.push(format!("-Lnative={}", target_helpers.display()));
2203+
if target.triple.contains("pauthtest") {
2204+
// Embed rpath to the shared object
2205+
targetflags.push(format!("-Clink-arg=-Wl,-rpath,{}", target_helpers.display()));
2206+
}
22012207
}
22022208

22032209
for flag in hostflags {
@@ -3812,32 +3818,58 @@ impl Step for TestHelpers {
38123818
};
38133819
let dst = builder.test_helpers_out(target);
38143820
let src = builder.src.join("tests/auxiliary/rust_test_helpers.c");
3815-
if up_to_date(&src, &dst.join("librust_test_helpers.a")) {
3816-
return;
3817-
}
3818-
38193821
let _guard = builder.msg_unstaged(Kind::Build, "test helpers", target);
38203822
t!(fs::create_dir_all(&dst));
3821-
let mut cfg = cc::Build::new();
38223823

3823-
// We may have found various cross-compilers a little differently due to our
3824-
// extra configuration, so inform cc of these compilers. Note, though, that
3825-
// on MSVC we still need cc's detection of env vars (ugh).
3826-
if !target.is_msvc() {
3827-
if let Some(ar) = builder.ar(target) {
3828-
cfg.archiver(ar);
3824+
if !up_to_date(&src, &dst.join("librust_test_helpers.a")) {
3825+
let mut cfg = cc::Build::new();
3826+
3827+
// We may have found various cross-compilers a little differently due to our
3828+
// extra configuration, so inform cc of these compilers. Note, though, that
3829+
// on MSVC we still need cc's detection of env vars (ugh).
3830+
if !target.is_msvc() {
3831+
if let Some(ar) = builder.ar(target) {
3832+
cfg.archiver(ar);
3833+
}
3834+
cfg.compiler(builder.cc(target));
3835+
}
3836+
cfg.cargo_metadata(false)
3837+
.out_dir(&dst)
3838+
.target(&target.triple)
3839+
.host(&builder.config.host_target.triple)
3840+
.opt_level(0)
3841+
.warnings(false)
3842+
.debug(false)
3843+
.file(builder.src.join("tests/auxiliary/rust_test_helpers.c"))
3844+
.compile("rust_test_helpers");
3845+
}
3846+
if target.triple.contains("pauthtest") {
3847+
let so = dst.join("librust_test_helpers.so");
3848+
if up_to_date(&src, &so) {
3849+
return;
3850+
}
3851+
3852+
let pauthtest_sysroot = std::env::var("PAUTHTEST_SYSROOT").unwrap_or_default();
3853+
let status = Command::new("clang")
3854+
.arg("-target")
3855+
.arg(target.triple)
3856+
.arg("-fuse-ld=lld")
3857+
.arg(format!("--sysroot={}", pauthtest_sysroot))
3858+
.arg("-nostdlib")
3859+
.arg("-march=armv8.3-a")
3860+
.arg("-fPIC")
3861+
.arg("-shared")
3862+
.arg("-O0") // Use O0 to match what static library is compiled at.
3863+
.arg("-o")
3864+
.arg(&so)
3865+
.arg(&src)
3866+
.status()
3867+
.expect("Failed to run pauthtest clang for librust_test_helpers.so");
3868+
3869+
if !status.success() {
3870+
panic!("Linking of pauthtest librust_test_helpers.so failed");
38293871
}
3830-
cfg.compiler(builder.cc(target));
38313872
}
3832-
cfg.cargo_metadata(false)
3833-
.out_dir(&dst)
3834-
.target(&target.triple)
3835-
.host(&builder.config.host_target.triple)
3836-
.opt_level(0)
3837-
.warnings(false)
3838-
.debug(false)
3839-
.file(builder.src.join("tests/auxiliary/rust_test_helpers.c"))
3840-
.compile("rust_test_helpers");
38413873
}
38423874
}
38433875

tests/incremental/auxiliary/issue-54059.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,8 @@ proc_macro_expr_impl! {
4040
}
4141
}
4242

43-
#[link(name="rust_test_helpers")]
43+
#[cfg_attr(target_env = "pauthtest", link(name = "rust_test_helpers", kind = "dylib"))]
44+
#[cfg_attr(not(target_env = "pauthtest"), link(name = "rust_test_helpers"))]
4445
extern "C" {
4546
pub fn rust_dbg_extern_identity_u64(v: u64) -> u64;
4647
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
#include <stdint.h>
2+
#include <stdio.h>
3+
4+
#ifdef __cplusplus
5+
extern "C" {
6+
#endif
7+
8+
#define NUM_ELEMS 5
9+
10+
void quickSort(void *Base, size_t N, size_t Size,
11+
int (*Cmp)(const void *, const void *));
12+
13+
#ifdef __cplusplus
14+
}
15+
#endif
16+
17+
int cmpI32Ascending(const void *LHS, const void *RHS) {
18+
int32_t x = *(const int32_t *)LHS;
19+
int32_t y = *(const int32_t *)RHS;
20+
21+
if (x < y)
22+
return -1;
23+
else if (x > y)
24+
return 1;
25+
else
26+
return 0;
27+
}
28+
29+
int main() {
30+
int32_t Data[NUM_ELEMS] = {4, 2, 5, 3, 1};
31+
32+
printf("Before sorting: ");
33+
for (int i = 0; i < NUM_ELEMS; i++)
34+
printf("%d ", Data[i]);
35+
printf("\n");
36+
37+
quickSort(Data, NUM_ELEMS, sizeof(int32_t), cmpI32Ascending);
38+
39+
printf("After sorting: ");
40+
for (int i = 0; i < NUM_ELEMS; i++)
41+
printf("%d ", Data[i]);
42+
printf("\n");
43+
44+
for (size_t i = 1; i < NUM_ELEMS; i++)
45+
if (Data[i - 1] > Data[i])
46+
return 42;
47+
48+
return 0;
49+
}
50+
51+
#ifdef __cplusplus
52+
}
53+
#endif
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
use std::mem::size_of;
2+
use std::os::raw::{c_int, c_void};
3+
use std::ptr;
4+
5+
unsafe fn swap_i32(lhs: *mut i32, rhs: *mut i32) {
6+
ptr::swap(lhs, rhs);
7+
}
8+
9+
unsafe fn partition(
10+
arr: *mut i32,
11+
low: isize,
12+
high: isize,
13+
cmp: extern "C" fn(*const c_void, *const c_void) -> c_int,
14+
) -> isize {
15+
let pivot = arr.offset(low);
16+
let mut i = low;
17+
let mut j = high;
18+
19+
while i < j {
20+
while i <= high - 1 && cmp(arr.offset(i) as *const c_void, pivot as *const c_void) <= 0 {
21+
i += 1;
22+
}
23+
24+
while j >= low + 1 && cmp(arr.offset(j) as *const c_void, pivot as *const c_void) > 0 {
25+
j -= 1;
26+
}
27+
28+
if i < j {
29+
swap_i32(arr.offset(i), arr.offset(j));
30+
}
31+
}
32+
33+
swap_i32(arr.offset(low), arr.offset(j));
34+
j
35+
}
36+
37+
unsafe fn quicksort_rec(
38+
arr: *mut i32,
39+
low: isize,
40+
high: isize,
41+
cmp: extern "C" fn(*const c_void, *const c_void) -> c_int,
42+
) {
43+
if low < high {
44+
let part = partition(arr, low, high, cmp);
45+
quicksort_rec(arr, low, part - 1, cmp);
46+
quicksort_rec(arr, part + 1, high, cmp);
47+
}
48+
}
49+
50+
#[no_mangle]
51+
pub extern "C" fn quickSort(
52+
base: *mut c_void,
53+
n: usize,
54+
size: usize,
55+
cmp: extern "C" fn(*const c_void, *const c_void) -> c_int,
56+
) {
57+
if size != size_of::<i32>() {
58+
std::process::abort();
59+
}
60+
61+
if n > 1 {
62+
unsafe {
63+
quicksort_rec(base as *mut i32, 0, (n as isize) - 1, cmp);
64+
}
65+
}
66+
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
// Test compilation flow using custom pauth-enabled toolchain and signing extern "C" function
2+
// pointers used from within rust. Note that in order for the test to work the location of the
3+
// toolchain's sysroot has to be provided via env variable (`PAUTHTEST_SYSROOT`). The test assumes
4+
// that pauthtest-enabled `clang` is available on the path.
5+
// In this test rust is the driver - providing the data and the comparison function; while c -
6+
// provides the implementation of quicksort algorithm and is the user of the data and comparator.
7+
8+
//@ only-aarch64-unknown-linux-pauthtest
9+
10+
use run_make_support::{cc, rfs, run, run_fail, rustc};
11+
12+
fn main() {
13+
unsafe {
14+
std::env::set_var("CC", "clang");
15+
}
16+
let pauthtest_sysroot = std::env::var("PAUTHTEST_SYSROOT").unwrap_or_default();
17+
let dynamic_linker = format!("-Wl,--dynamic-linker={}/usr/lib/libc.so", pauthtest_sysroot);
18+
let rpath = format!("-Wl,--rpath={}/usr/lib", pauthtest_sysroot);
19+
20+
let rust_lib_name = "rust_quicksort";
21+
rustc()
22+
.target("aarch64-unknown-linux-pauthtest")
23+
.crate_type("cdylib")
24+
.input("quicksort.rs")
25+
.crate_name(rust_lib_name)
26+
.args(&[&dynamic_linker, &rpath])
27+
.run();
28+
29+
let exe_name = "main";
30+
cc().out_exe(exe_name)
31+
.input("main.c")
32+
.args(&[
33+
"-march=armv8.3-a",
34+
"-lc",
35+
"-nostdlib",
36+
"-target",
37+
"aarch64-unknown-linux-pauthtest",
38+
"-fuse-ld=lld".into(),
39+
&format!("--sysroot={}", pauthtest_sysroot),
40+
"-I",
41+
&format!("{}/usr/include", pauthtest_sysroot),
42+
&format!("-Wl,--rpath={}/usr/lib", pauthtest_sysroot),
43+
&format!("-Wl,{}/usr/lib/crt1.o", pauthtest_sysroot),
44+
&format!("-Wl,{}/usr/lib/crti.o", pauthtest_sysroot),
45+
&format!("-Wl,{}/usr/lib/crtn.o", pauthtest_sysroot),
46+
"-L.",
47+
&format!("-l{}", rust_lib_name),
48+
&dynamic_linker,
49+
&rpath,
50+
])
51+
.run();
52+
53+
run(exe_name);
54+
55+
rfs::remove_file(format!("{}{rust_lib_name}.{}", "lib", "so"));
56+
run_fail(exe_name);
57+
}
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
// Test compilation flow using custom pauth-enabled toolchain and signing extern "C" function
2+
// pointers used from within rust. Note that in order for the test to work the location of the
3+
// toolchain's sysroot has to be provided via env variable (`PAUTHTEST_SYSROOT`). The test assumes
4+
// that `clang` is available on the path.
5+
// In this test rust is the driver - providing the data and the comparison function; while c -
6+
// provides the implementation of quicksort algorithm and is the user of the data and comparator.
7+
8+
//@ only-aarch64-unknown-linux-pauthtest
9+
10+
use run_make_support::{cc, rfs, run, run_fail, rustc};
11+
12+
fn main() {
13+
let pauthtest_sysroot = std::env::var("PAUTHTEST_SYSROOT").unwrap_or_default();
14+
15+
unsafe {
16+
//std::env::set_var("CC", "/opt/llvm-pauth/bin/aarch64-linux-pauthtest-clang");
17+
std::env::set_var("CC", "clang");
18+
}
19+
let dynamic_linker =
20+
format!("-Wl,--dynamic-linker={}/usr/lib/libc.so", pauthtest_sysroot);
21+
let rpath = format!("-Wl,--rpath={}/usr/lib", pauthtest_sysroot);
22+
let rust_lib_name = "rust_quicksort";
23+
// rustc()
24+
// .target("aarch64-unknown-linux-pauthtest")
25+
// .crate_type("cdylib")
26+
// .input("quicksort.rs")
27+
// .crate_name(rust_lib_name)
28+
// .args(&[&dynamic_linker, &rpath, "-C", "link-arg=-fuse-ld=lld"])
29+
// .run();
30+
rustc()
31+
.target("aarch64-unknown-linux-pauthtest")
32+
.crate_type("cdylib")
33+
.input("quicksort.rs")
34+
.crate_name(rust_lib_name)
35+
.args(&[
36+
"-C", "link-arg=-fuse-ld=lld",
37+
"-C", &format!("link-arg=--sysroot={}", pauthtest_sysroot),
38+
"-C", &format!("link-arg=-Wl,--dynamic-linker={}/usr/lib/libc.so", pauthtest_sysroot),
39+
"-C", &format!("link-arg=-Wl,--rpath={}/usr/lib", pauthtest_sysroot),
40+
])
41+
.run();
42+
43+
let exe_name = "main";
44+
cc().out_exe(exe_name)
45+
.input("main.c")
46+
.args(&[
47+
"-v",
48+
"-march=armv8.3-a",
49+
"-target", "aarch64-unknown-linux-pauthtest",
50+
&format!("--sysroot={}", pauthtest_sysroot), // <<< important
51+
"-fuse-ld=lld",
52+
"-L.",
53+
&format!("-l{}", rust_lib_name),
54+
&dynamic_linker,
55+
&rpath,
56+
])
57+
.run();
58+
// cc().out_exe(exe_name)
59+
// .input("main.c")
60+
// .args(&[
61+
// "-march=armv8.3-a",
62+
// "-target",
63+
// "aarch64-unknown-linux-pauthtest",
64+
// "-fuse-ld=lld",
65+
// "-L.",
66+
// &format!("-l{}", rust_lib_name),
67+
// &dynamic_linker,
68+
// &rpath,
69+
// ])
70+
// .run();
71+
72+
run(exe_name);
73+
74+
rfs::remove_file(format!("{}{rust_lib_name}.{}", "lib", "so"));
75+
run_fail(exe_name);
76+
}

0 commit comments

Comments
 (0)