Auto merge of #126715 - Rejyr:migrate-readelf-rmake, r=jieyouxu

Migrate `relro-levels`, `static-pie` to `rmake`

Part of #121876.

r? `@jieyouxu`

try-job: aarch64-gnu
try-job: arm-android
try-job: armhf-gnu
try-job: dist-i586-gnu-i586-i686-musl
try-job: dist-various-1
try-job: test-various
This commit is contained in:
bors 2024-06-23 03:43:25 +00:00
commit d4cc01c2f2
11 changed files with 126 additions and 87 deletions

View file

@ -36,8 +36,10 @@ pub fn new<P: AsRef<OsStr>>(program: P) -> Self {
Self { cmd: StdCommand::new(program), stdin: None, drop_bomb: DropBomb::arm(program) }
}
pub fn set_stdin(&mut self, stdin: Box<[u8]>) {
self.stdin = Some(stdin);
/// Specify a stdin input
pub fn stdin<I: AsRef<[u8]>>(&mut self, input: I) -> &mut Self {
self.stdin = Some(input.as_ref().to_vec().into_boxed_slice());
self
}
/// Specify an environment variable.

View file

@ -102,6 +102,24 @@ pub fn file_header(&mut self) -> &mut Self {
self
}
/// Pass `--program-headers` to display program headers.
pub fn program_headers(&mut self) -> &mut Self {
self.cmd.arg("--program-headers");
self
}
/// Pass `--symbols` to display the symbol.
pub fn symbols(&mut self) -> &mut Self {
self.cmd.arg("--symbols");
self
}
/// Pass `--dynamic-table` to display the dynamic symbol table.
pub fn dynamic_table(&mut self) -> &mut Self {
self.cmd.arg("--dynamic-table");
self
}
/// Specify the section to display.
pub fn section(&mut self, section: &str) -> &mut Self {
self.cmd.arg("--string-dump");
@ -153,7 +171,7 @@ pub fn new() -> Self {
/// Pipe a read file into standard input containing patterns that will be matched against the .patterns(path) call.
pub fn stdin<I: AsRef<[u8]>>(&mut self, input: I) -> &mut Self {
self.cmd.set_stdin(input.as_ref().to_vec().into_boxed_slice());
self.cmd.stdin(input);
self
}

View file

@ -244,7 +244,7 @@ pub fn link_args(&mut self, link_args: &str) -> &mut Self {
/// Specify a stdin input
pub fn stdin<I: AsRef<[u8]>>(&mut self, input: I) -> &mut Self {
self.cmd.set_stdin(input.as_ref().to_vec().into_boxed_slice());
self.cmd.stdin(input);
self
}

View file

@ -92,7 +92,7 @@ pub fn arg_file<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
/// Specify a stdin input
pub fn stdin<I: AsRef<[u8]>>(&mut self, input: I) -> &mut Self {
self.cmd.set_stdin(input.as_ref().to_vec().into_boxed_slice());
self.cmd.stdin(input);
self
}

View file

@ -151,7 +151,6 @@ run-make/raw-dylib-inline-cross-dylib/Makefile
run-make/raw-dylib-link-ordinal/Makefile
run-make/raw-dylib-stdcall-ordinal/Makefile
run-make/redundant-libs/Makefile
run-make/relro-levels/Makefile
run-make/remap-path-prefix-dwarf/Makefile
run-make/remap-path-prefix/Makefile
run-make/reproducible-build-2/Makefile
@ -177,7 +176,6 @@ run-make/split-debuginfo/Makefile
run-make/stable-symbol-names/Makefile
run-make/static-dylib-by-default/Makefile
run-make/static-extern-type/Makefile
run-make/static-pie/Makefile
run-make/staticlib-blank-lib/Makefile
run-make/staticlib-dylib-linkage/Makefile
run-make/std-core-cycle/Makefile

View file

@ -1,22 +0,0 @@
# ignore-cross-compile
include ../tools.mk
# only-linux
#
# This tests the different -Crelro-level values, and makes sure that they work properly.
all:
# Ensure that binaries built with the full relro level links them with both
# RELRO and BIND_NOW for doing eager symbol resolving.
$(RUSTC) -Crelro-level=full hello.rs
readelf -l $(TMPDIR)/hello | grep -q GNU_RELRO
readelf -d $(TMPDIR)/hello | grep -q BIND_NOW
$(RUSTC) -Crelro-level=partial hello.rs
readelf -l $(TMPDIR)/hello | grep -q GNU_RELRO
# Ensure that we're *not* built with RELRO when setting it to off. We do
# not want to check for BIND_NOW however, as the linker might have that
# enabled by default.
$(RUSTC) -Crelro-level=off hello.rs
! readelf -l $(TMPDIR)/hello | grep -q GNU_RELRO

View file

@ -0,0 +1,28 @@
// This tests the different -Crelro-level values, and makes sure that they work properly.
//@ only-linux
use run_make_support::llvm_readobj;
use run_make_support::rustc;
fn compile(relro_level: &str) {
rustc().arg(format!("-Crelro-level={relro_level}")).input("hello.rs").run();
}
fn main() {
// Ensure that binaries built with the full relro level links them with both
// RELRO and BIND_NOW for doing eager symbol resolving.
compile("full");
llvm_readobj().program_headers().input("hello").run().assert_stdout_contains("GNU_RELRO");
llvm_readobj().dynamic_table().input("hello").run().assert_stdout_contains("BIND_NOW");
compile("partial");
llvm_readobj().program_headers().input("hello").run().assert_stdout_contains("GNU_RELRO");
// Ensure that we're *not* built with RELRO when setting it to off. We do
// not want to check for BIND_NOW however, as the linker might have that
// enabled by default.
compile("off");
llvm_readobj().program_headers().input("hello").run().assert_stdout_not_contains("GNU_RELRO");
}

View file

@ -1,18 +0,0 @@
include ../tools.mk
# only-x86_64
# only-linux
# ignore-32bit
# How to manually run this
# $ ./x.py test --target x86_64-unknown-linux-[musl,gnu] tests/run-make/static-pie
all: test-clang test-gcc
test-%:
if ./check_$*_version.sh; then\
${RUSTC} -Clinker=$* -Clinker-flavor=gcc --target ${TARGET} -C target-feature=+crt-static test-aslr.rs; \
! readelf -l $(call RUN_BINFILE,test-aslr) | $(CGREP) INTERP; \
readelf -l $(call RUN_BINFILE,test-aslr) | $(CGREP) DYNAMIC; \
$(call RUN,test-aslr) --test-aslr; \
fi

View file

@ -1,20 +0,0 @@
#!/bin/bash
set -euo pipefail
if command -v clang > /dev/null
then
CLANG_VERSION=$(echo __clang_major__ | clang -E -x c - | grep -v -e '^#' )
echo "clang version $CLANG_VERSION detected"
if (( $CLANG_VERSION >= 9 ))
then
echo "clang supports -static-pie"
exit 0
else
echo "clang too old to support -static-pie, skipping test"
exit 1
fi
else
echo "No clang version detected"
exit 2
fi

View file

@ -1,20 +0,0 @@
#!/bin/bash
set -euo pipefail
if command -v gcc > /dev/null
then
GCC_VERSION=$(echo __GNUC__ | gcc -E -x c - | grep -v -e '^#' )
echo "gcc version $GCC_VERSION detected"
if (( $GCC_VERSION >= 8 ))
then
echo "gcc supports -static-pie"
exit 0
else
echo "gcc too old to support -static-pie, skipping test"
exit 1
fi
else
echo "No gcc version detected"
exit 2
fi

View file

@ -0,0 +1,73 @@
// 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::llvm_readobj;
use run_make_support::regex::Regex;
use run_make_support::rustc;
use run_make_support::{cmd, run_with_args, 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");
}