Skip to content

Commit 86e7875

Browse files
committed
Auto merge of #128793 - matthiaskrgr:rollup-ork16t0, r=matthiaskrgr
Rollup of 4 pull requests Successful merges: - #128363 (Migrate `pdb-buildinfo-cl-cmd` and `pgo-indirect-call-promotion` `run-make` tests to rmake) - #128384 (Add tests to ensure MTE tags are preserved across FFI boundaries) - #128636 (migrate `thumb-none-cortex-m` to rmake) - #128696 (Migrate `staticlib-dylib-linkage` `run-make` test to rmake) Failed merges: - #128407 (Migrate `min-global-align` and `no-alloc-shim` `run-make` tests to rmake) - #128639 (migrate `thumb-none-qemu` to rmake) r? `@ghost` `@rustbot` modify labels: rollup
2 parents 8b38707 + 26787a8 commit 86e7875

File tree

21 files changed

+511
-103
lines changed

21 files changed

+511
-103
lines changed

src/tools/compiletest/src/command-list.rs

+2
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[
170170
"only-32bit",
171171
"only-64bit",
172172
"only-aarch64",
173+
"only-aarch64-unknown-linux-gnu",
173174
"only-apple",
174175
"only-arm",
175176
"only-avr",
@@ -204,6 +205,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[
204205
"only-watchos",
205206
"only-windows",
206207
"only-windows-gnu",
208+
"only-windows-msvc",
207209
"only-x86",
208210
"only-x86_64",
209211
"only-x86_64-fortanix-unknown-sgx",

src/tools/tidy/src/allowed_run_make_makefiles.txt

-4
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,12 @@ run-make/macos-deployment-target/Makefile
1616
run-make/min-global-align/Makefile
1717
run-make/native-link-modifier-bundle/Makefile
1818
run-make/no-alloc-shim/Makefile
19-
run-make/pdb-buildinfo-cl-cmd/Makefile
20-
run-make/pgo-indirect-call-promotion/Makefile
2119
run-make/remap-path-prefix-dwarf/Makefile
2220
run-make/reproducible-build/Makefile
2321
run-make/rlib-format-packed-bundled-libs/Makefile
2422
run-make/split-debuginfo/Makefile
25-
run-make/staticlib-dylib-linkage/Makefile
2623
run-make/symbol-mangling-hashed/Makefile
2724
run-make/sysroot-crates-are-unstable/Makefile
28-
run-make/thumb-none-cortex-m/Makefile
2925
run-make/thumb-none-qemu/Makefile
3026
run-make/translation/Makefile
3127
run-make/x86_64-fortanix-unknown-sgx-lvi/Makefile

tests/run-make/mte-ffi/bar.h

+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
#ifndef __BAR_H
2+
#define __BAR_H
3+
4+
#include <sys/mman.h>
5+
#include <sys/auxv.h>
6+
#include <sys/prctl.h>
7+
#include <unistd.h>
8+
#include <stdio.h>
9+
10+
// Set the allocation tag on the destination address using the STG instruction.
11+
#define set_tag(tagged_addr) do { \
12+
asm volatile("stg %0, [%0]" : : "r" (tagged_addr) : "memory"); \
13+
} while (0)
14+
15+
int mte_enabled() {
16+
return (getauxval(AT_HWCAP2)) & HWCAP2_MTE;
17+
}
18+
19+
void *alloc_page() {
20+
// Enable MTE with synchronous checking
21+
if (prctl(PR_SET_TAGGED_ADDR_CTRL,
22+
PR_TAGGED_ADDR_ENABLE | PR_MTE_TCF_SYNC | (0xfffe << PR_MTE_TAG_SHIFT),
23+
0, 0, 0))
24+
{
25+
perror("prctl() failed");
26+
}
27+
28+
// Using `mmap` allows us to ensure that, on systems which support MTE, the allocated
29+
// memory is 16-byte aligned for MTE.
30+
// This also allows us to explicitly specify whether the region should be protected by
31+
// MTE or not.
32+
if (mte_enabled()) {
33+
void *ptr = mmap(NULL, sysconf(_SC_PAGESIZE),
34+
PROT_READ | PROT_WRITE | PROT_MTE, MAP_PRIVATE | MAP_ANONYMOUS,
35+
-1, 0);
36+
} else {
37+
void *ptr = mmap(NULL, sysconf(_SC_PAGESIZE),
38+
PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS,
39+
-1, 0);
40+
}
41+
}
42+
43+
#endif // __BAR_H

tests/run-make/mte-ffi/bar_float.c

+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
#include <stdio.h>
2+
#include <stdlib.h>
3+
#include <stdint.h>
4+
#include "bar.h"
5+
6+
extern void foo(char*);
7+
8+
void bar(char *ptr) {
9+
if (((uintptr_t)ptr >> 56) != 0x1f) {
10+
fprintf(stderr, "Top byte corrupted on Rust -> C FFI boundary!\n");
11+
exit(1);
12+
}
13+
}
14+
15+
int main(void)
16+
{
17+
float *ptr = alloc_page();
18+
if (ptr == MAP_FAILED)
19+
{
20+
perror("mmap() failed");
21+
return EXIT_FAILURE;
22+
}
23+
24+
// Store an arbitrary tag in bits 56-59 of the pointer (where an MTE tag may be),
25+
// and a different value in the ignored top 4 bits.
26+
ptr = (float *)((uintptr_t)ptr | 0x1fl << 56);
27+
28+
if (mte_enabled()) {
29+
set_tag(ptr);
30+
}
31+
32+
ptr[0] = 2.0f;
33+
ptr[1] = 1.5f;
34+
35+
foo(ptr); // should change the contents of the page and call `bar`
36+
37+
if (ptr[0] != 0.5f || ptr[1] != 0.2f) {
38+
fprintf(stderr, "invalid data in memory; expected '0.5 0.2', got '%f %f'\n",
39+
ptr[0], ptr[1]);
40+
return EXIT_FAILURE;
41+
}
42+
43+
return 0;
44+
}

tests/run-make/mte-ffi/bar_function.c

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
#include <stdio.h>
2+
#include <stdlib.h>
3+
#include <stdint.h>
4+
#include "bar.h"
5+
6+
typedef void (*fp)(int (*)());
7+
8+
extern void foo(fp);
9+
10+
void bar(int (*ptr)()) {
11+
if (((uintptr_t)ptr >> 56) != 0x2f) {
12+
fprintf(stderr, "Top byte corrupted on Rust -> C FFI boundary!\n");
13+
exit(1);
14+
}
15+
16+
int r = (*ptr)();
17+
if (r != 32) {
18+
fprintf(stderr, "invalid return value; expected 32, got '%d'\n", r);
19+
exit(1);
20+
}
21+
}
22+
23+
int main(void)
24+
{
25+
fp ptr = alloc_page();
26+
if (ptr == MAP_FAILED)
27+
{
28+
perror("mmap() failed");
29+
return EXIT_FAILURE;
30+
}
31+
32+
// Store an arbitrary tag in bits 56-59 of the pointer (where an MTE tag may be),
33+
// and a different value in the ignored top 4 bits.
34+
ptr = (fp)((uintptr_t)&bar | 0x1fl << 56);
35+
36+
foo(ptr);
37+
38+
return 0;
39+
}

tests/run-make/mte-ffi/bar_int.c

+47
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
#include <stdio.h>
2+
#include <stdlib.h>
3+
#include <stdint.h>
4+
#include "bar.h"
5+
6+
extern void foo(unsigned int *);
7+
8+
void bar(char *ptr) {
9+
if (((uintptr_t)ptr >> 56) != 0x1f) {
10+
fprintf(stderr, "Top byte corrupted on Rust -> C FFI boundary!\n");
11+
exit(1);
12+
}
13+
}
14+
15+
int main(void)
16+
{
17+
// Construct a pointer with an arbitrary tag in bits 56-59, simulating an MTE tag.
18+
// It's only necessary that the tag is preserved across FFI bounds for this test.
19+
unsigned int *ptr;
20+
21+
ptr = alloc_page();
22+
if (ptr == MAP_FAILED)
23+
{
24+
perror("mmap() failed");
25+
return EXIT_FAILURE;
26+
}
27+
28+
// Store an arbitrary tag in bits 56-59 of the pointer (where an MTE tag may be),
29+
// and a different value in the ignored top 4 bits.
30+
ptr = (unsigned int *)((uintptr_t)ptr | 0x1fl << 56);
31+
32+
if (mte_enabled()) {
33+
set_tag(ptr);
34+
}
35+
36+
ptr[0] = 61;
37+
ptr[1] = 62;
38+
39+
foo(ptr); // should change the contents of the page to start with 0x63 0x64 and call `bar`
40+
41+
if (ptr[0] != 0x63 || ptr[1] != 0x64) {
42+
fprintf(stderr, "invalid data in memory; expected '63 64', got '%d %d'\n", ptr[0], ptr[1]);
43+
return EXIT_FAILURE;
44+
}
45+
46+
return 0;
47+
}

tests/run-make/mte-ffi/bar_string.c

+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
#include <stdio.h>
2+
#include <stdlib.h>
3+
#include <stdint.h>
4+
#include "bar.h"
5+
6+
extern void foo(char*);
7+
8+
void bar(char *ptr) {
9+
if (((uintptr_t)ptr >> 56) != 0x2f) {
10+
fprintf(stderr, "Top byte corrupted on Rust -> C FFI boundary!\n");
11+
exit(1);
12+
}
13+
14+
if (strcmp(ptr, "cd")) {
15+
fprintf(stderr, "invalid data in memory; expected 'cd', got '%s'\n", ptr);
16+
exit(1);
17+
}
18+
}
19+
20+
int main(void)
21+
{
22+
// Construct a pointer with an arbitrary tag in bits 56-59, simulating an MTE tag.
23+
// It's only necessary that the tag is preserved across FFI bounds for this test.
24+
char *ptr;
25+
26+
ptr = alloc_page();
27+
if (ptr == MAP_FAILED)
28+
{
29+
perror("mmap() failed");
30+
return EXIT_FAILURE;
31+
}
32+
33+
// Store an arbitrary tag in bits 56-59 of the pointer (where an MTE tag may be),
34+
// and a different value in the ignored top 4 bits.
35+
ptr = (unsigned int *)((uintptr_t)ptr | 0x1fl << 56);
36+
37+
if (mte_enabled()) {
38+
set_tag(ptr);
39+
}
40+
41+
ptr[0] = 'a';
42+
ptr[1] = 'b';
43+
ptr[2] = '\0';
44+
45+
foo(ptr);
46+
47+
return 0;
48+
}

tests/run-make/mte-ffi/foo_float.rs

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#![crate_type = "cdylib"]
2+
#![crate_name = "foo"]
3+
4+
use std::os::raw::c_float;
5+
6+
extern "C" {
7+
fn bar(ptr: *const c_float);
8+
}
9+
10+
#[no_mangle]
11+
pub extern "C" fn foo(ptr: *mut c_float) {
12+
assert_eq!((ptr as usize) >> 56, 0x1f);
13+
14+
unsafe {
15+
*ptr = 0.5;
16+
*ptr.wrapping_add(1) = 0.2;
17+
bar(ptr);
18+
}
19+
}
+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#![crate_type = "cdylib"]
2+
#![crate_name = "foo"]
3+
4+
extern "C" fn ret32() -> i32 {
5+
32
6+
}
7+
8+
#[no_mangle]
9+
pub extern "C" fn foo(ptr: extern "C" fn(extern "C" fn() -> i32)) {
10+
assert_eq!((ptr as usize) >> 56, 0x1f);
11+
12+
// Store an arbitrary tag in the tag bits, and convert back to the correct pointer type.
13+
let p = ((ret32 as usize) | (0x2f << 56)) as *const ();
14+
let p: extern "C" fn() -> i32 = unsafe { std::mem::transmute(p) };
15+
16+
unsafe { ptr(p) }
17+
}

tests/run-make/mte-ffi/foo_int.rs

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#![crate_type = "cdylib"]
2+
#![crate_name = "foo"]
3+
4+
use std::os::raw::c_uint;
5+
6+
extern "C" {
7+
fn bar(ptr: *const c_uint);
8+
}
9+
10+
#[no_mangle]
11+
pub extern "C" fn foo(ptr: *mut c_uint) {
12+
assert_eq!((ptr as usize) >> 56, 0x1f);
13+
14+
unsafe {
15+
*ptr = 0x63;
16+
*ptr.wrapping_add(1) = 0x64;
17+
bar(ptr);
18+
}
19+
}

tests/run-make/mte-ffi/foo_string.rs

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#![crate_type = "cdylib"]
2+
#![crate_name = "foo"]
3+
4+
use std::arch::asm;
5+
use std::ffi::{CStr, CString};
6+
use std::os::raw::c_char;
7+
8+
extern "C" {
9+
fn bar(ptr: *const c_char);
10+
}
11+
12+
#[no_mangle]
13+
pub extern "C" fn foo(ptr: *const c_char) {
14+
assert_eq!((ptr as usize) >> 56, 0x1f);
15+
16+
let s = unsafe { CStr::from_ptr(ptr) };
17+
assert_eq!(s.to_str().unwrap(), "ab");
18+
19+
let s = CString::from_vec_with_nul("cd\0".into()).unwrap();
20+
let mut p = ((s.as_ptr() as usize) | (0x2f << 56)) as *const c_char;
21+
unsafe {
22+
#[cfg(target_feature = "mte")]
23+
asm!("stg {p}, [{p}]", p = inout(reg) p);
24+
25+
bar(p);
26+
}
27+
}

tests/run-make/mte-ffi/rmake.rs

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
// Tests that MTE tags and values stored in the top byte of a pointer (TBI) are
2+
// preserved across FFI boundaries (C <-> Rust).
3+
// This test does not require MTE: whilst the test will use MTE if available, if it is not,
4+
// arbitrary tag bits are set using TBI.
5+
6+
// This test is only valid for AArch64.
7+
// The linker must be explicitly specified when cross-compiling, so it is limited to
8+
// `aarch64-unknown-linux-gnu`.
9+
//@ only-aarch64-unknown-linux-gnu
10+
11+
use run_make_support::{cc, dynamic_lib_name, extra_c_flags, run, rustc, target};
12+
13+
fn main() {
14+
run_test("int");
15+
run_test("float");
16+
run_test("string");
17+
run_test("function");
18+
}
19+
20+
fn run_test(variant: &str) {
21+
let flags = {
22+
let mut flags = extra_c_flags();
23+
flags.push("-march=armv8.5-a+memtag");
24+
flags
25+
};
26+
println!("{variant} test...");
27+
rustc()
28+
.input(format!("foo_{variant}.rs"))
29+
.target(target())
30+
.linker("aarch64-linux-gnu-gcc")
31+
.run();
32+
cc().input(format!("bar_{variant}.c"))
33+
.input(dynamic_lib_name("foo"))
34+
.out_exe("test")
35+
.args(&flags)
36+
.run();
37+
run("test");
38+
}

0 commit comments

Comments
 (0)