From 004edb27cf319b3d844f3bce397aa1079235a390 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Fri, 22 Nov 2024 08:08:34 +0000 Subject: [PATCH] sysconf interception fix for solarish systems. also adding the `_SC_PAGESIZE` alias `_SC_PAGE_SIZE` supported by Linux, macOS and FreeBSD. close #4050 --- src/tools/miri/ci/ci.sh | 2 +- .../src/shims/unix/android/foreign_items.rs | 9 +++ .../miri/src/shims/unix/foreign_items.rs | 58 +++++++++---------- .../src/shims/unix/freebsd/foreign_items.rs | 9 +++ .../src/shims/unix/linux/foreign_items.rs | 9 +++ .../src/shims/unix/macos/foreign_items.rs | 8 +++ .../src/shims/unix/solarish/foreign_items.rs | 8 +++ .../miri/tests/pass-dep/libc/libc-sysconf.rs | 17 ++++++ 8 files changed, 90 insertions(+), 30 deletions(-) create mode 100644 src/tools/miri/tests/pass-dep/libc/libc-sysconf.rs diff --git a/src/tools/miri/ci/ci.sh b/src/tools/miri/ci/ci.sh index 9b020d029a684..0356d7ecf1015 100755 --- a/src/tools/miri/ci/ci.sh +++ b/src/tools/miri/ci/ci.sh @@ -153,7 +153,7 @@ case $HOST_TARGET in TEST_TARGET=x86_64-unknown-freebsd run_tests_minimal $BASIC $UNIX time hashmap random threadname pthread fs libc-pipe TEST_TARGET=i686-unknown-freebsd run_tests_minimal $BASIC $UNIX time hashmap random threadname pthread fs libc-pipe TEST_TARGET=x86_64-unknown-illumos run_tests_minimal $BASIC $UNIX time hashmap random thread sync available-parallelism tls libc-pipe - # TEST_TARGET=x86_64-pc-solaris run_tests_minimal $BASIC $UNIX time hashmap random thread sync available-parallelism tls libc-pipe + TEST_TARGET=x86_64-pc-solaris run_tests_minimal $BASIC $UNIX time hashmap random thread sync available-parallelism tls libc-pipe TEST_TARGET=aarch64-linux-android run_tests_minimal $BASIC $UNIX time hashmap random sync threadname pthread TEST_TARGET=wasm32-wasip2 run_tests_minimal $BASIC wasm TEST_TARGET=wasm32-unknown-unknown run_tests_minimal no_std empty_main wasm # this target doesn't really have std diff --git a/src/tools/miri/src/shims/unix/android/foreign_items.rs b/src/tools/miri/src/shims/unix/android/foreign_items.rs index 80ad40e1624f7..6c5a61437aff8 100644 --- a/src/tools/miri/src/shims/unix/android/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/android/foreign_items.rs @@ -2,6 +2,7 @@ use rustc_abi::ExternAbi; use rustc_span::Symbol; use crate::shims::unix::android::thread::prctl; +use crate::shims::unix::foreign_items::EvalContextExt as _; use crate::shims::unix::linux::syscall::syscall; use crate::*; @@ -20,6 +21,14 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { ) -> InterpResult<'tcx, EmulateItemResult> { let this = self.eval_context_mut(); match link_name.as_str() { + // Querying system information + "sysconf" => { + let [val] = + this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let result = this.sysconf(val)?; + this.write_scalar(result, dest)?; + } + // Miscellaneous "__errno" => { let [] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; diff --git a/src/tools/miri/src/shims/unix/foreign_items.rs b/src/tools/miri/src/shims/unix/foreign_items.rs index 55202a0814922..a50ac1be77ea1 100644 --- a/src/tools/miri/src/shims/unix/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/foreign_items.rs @@ -39,6 +39,35 @@ pub fn is_dyn_sym(name: &str, target_os: &str) -> bool { impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {} pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { + // Querying system information + fn sysconf(&mut self, val: &OpTy<'tcx>) -> InterpResult<'tcx, Scalar> { + let this = self.eval_context_mut(); + + let name = this.read_scalar(val)?.to_i32()?; + // FIXME: Which of these are POSIX, and which are GNU/Linux? + // At least the names seem to all also exist on macOS. + let sysconfs: &[(&str, fn(&MiriInterpCx<'_>) -> Scalar)] = &[ + ("_SC_PAGESIZE", |this| Scalar::from_int(this.machine.page_size, this.pointer_size())), + ("_SC_PAGE_SIZE", |this| Scalar::from_int(this.machine.page_size, this.pointer_size())), + ("_SC_NPROCESSORS_CONF", |this| { + Scalar::from_int(this.machine.num_cpus, this.pointer_size()) + }), + ("_SC_NPROCESSORS_ONLN", |this| { + Scalar::from_int(this.machine.num_cpus, this.pointer_size()) + }), + // 512 seems to be a reasonable default. The value is not critical, in + // the sense that getpwuid_r takes and checks the buffer length. + ("_SC_GETPW_R_SIZE_MAX", |this| Scalar::from_int(512, this.pointer_size())), + ]; + for &(sysconf_name, value) in sysconfs { + let sysconf_name = this.eval_libc_i32(sysconf_name); + if sysconf_name == name { + return interp_ok(value(this)); + } + } + throw_unsup_format!("unimplemented sysconf name: {}", name) + } + fn emulate_foreign_item_inner( &mut self, link_name: Symbol, @@ -393,35 +422,6 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } } - // Querying system information - "sysconf" => { - let [name] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; - let name = this.read_scalar(name)?.to_i32()?; - // FIXME: Which of these are POSIX, and which are GNU/Linux? - // At least the names seem to all also exist on macOS. - let sysconfs: &[(&str, fn(&MiriInterpCx<'_>) -> Scalar)] = &[ - ("_SC_PAGESIZE", |this| Scalar::from_int(this.machine.page_size, this.pointer_size())), - ("_SC_NPROCESSORS_CONF", |this| Scalar::from_int(this.machine.num_cpus, this.pointer_size())), - ("_SC_NPROCESSORS_ONLN", |this| Scalar::from_int(this.machine.num_cpus, this.pointer_size())), - // 512 seems to be a reasonable default. The value is not critical, in - // the sense that getpwuid_r takes and checks the buffer length. - ("_SC_GETPW_R_SIZE_MAX", |this| Scalar::from_int(512, this.pointer_size())) - ]; - let mut result = None; - for &(sysconf_name, value) in sysconfs { - let sysconf_name = this.eval_libc_i32(sysconf_name); - if sysconf_name == name { - result = Some(value(this)); - break; - } - } - if let Some(result) = result { - this.write_scalar(result, dest)?; - } else { - throw_unsup_format!("unimplemented sysconf name: {}", name) - } - } - // Thread-local storage "pthread_key_create" => { let [key, dtor] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; diff --git a/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs b/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs index 1346d8de7eaa2..ddea9ecc294dd 100644 --- a/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/freebsd/foreign_items.rs @@ -1,6 +1,7 @@ use rustc_abi::ExternAbi; use rustc_span::Symbol; +use crate::shims::unix::foreign_items::EvalContextExt as _; use crate::shims::unix::*; use crate::*; @@ -75,6 +76,14 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.write_scalar(result, dest)?; } + // Querying system information + "sysconf" => { + let [val] = + this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let result = this.sysconf(val)?; + this.write_scalar(result, dest)?; + } + // Miscellaneous "__error" => { let [] = this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; diff --git a/src/tools/miri/src/shims/unix/linux/foreign_items.rs b/src/tools/miri/src/shims/unix/linux/foreign_items.rs index 85f0d6e13307f..75b0afcac0039 100644 --- a/src/tools/miri/src/shims/unix/linux/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/linux/foreign_items.rs @@ -6,6 +6,7 @@ use self::shims::unix::linux::eventfd::EvalContextExt as _; use self::shims::unix::linux::mem::EvalContextExt as _; use self::shims::unix::linux::syscall::syscall; use crate::machine::{SIGRTMAX, SIGRTMIN}; +use crate::shims::unix::foreign_items::EvalContextExt as _; use crate::shims::unix::*; use crate::*; @@ -124,6 +125,14 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.write_scalar(result, dest)?; } + // Querying system information + "sysconf" => { + let [val] = + this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let result = this.sysconf(val)?; + this.write_scalar(result, dest)?; + } + // Dynamically invoked syscalls "syscall" => { syscall(this, link_name, abi, args, dest)?; diff --git a/src/tools/miri/src/shims/unix/macos/foreign_items.rs b/src/tools/miri/src/shims/unix/macos/foreign_items.rs index 003025916cd42..7f67a2cab369a 100644 --- a/src/tools/miri/src/shims/unix/macos/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/macos/foreign_items.rs @@ -2,6 +2,7 @@ use rustc_abi::ExternAbi; use rustc_span::Symbol; use super::sync::EvalContextExt as _; +use crate::shims::unix::foreign_items::EvalContextExt as _; use crate::shims::unix::*; use crate::*; @@ -167,6 +168,13 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.write_scalar(stack_size, dest)?; } + "sysconf" => { + let [val] = + this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let result = this.sysconf(val)?; + this.write_scalar(result, dest)?; + } + // Threading "pthread_setname_np" => { let [name] = diff --git a/src/tools/miri/src/shims/unix/solarish/foreign_items.rs b/src/tools/miri/src/shims/unix/solarish/foreign_items.rs index 526b64cff695a..2eeab38e35cd9 100644 --- a/src/tools/miri/src/shims/unix/solarish/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/solarish/foreign_items.rs @@ -1,6 +1,7 @@ use rustc_abi::ExternAbi; use rustc_span::Symbol; +use crate::shims::unix::foreign_items::EvalContextExt as _; use crate::shims::unix::*; use crate::*; @@ -112,6 +113,13 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.write_null(dest)?; } + "sysconf" | "__sysconf_xpg7" => { + let [val] = + this.check_shim(abi, ExternAbi::C { unwind: false }, link_name, args)?; + let result = this.sysconf(val)?; + this.write_scalar(result, dest)?; + } + _ => return interp_ok(EmulateItemResult::NotSupported), } interp_ok(EmulateItemResult::NeedsReturn) diff --git a/src/tools/miri/tests/pass-dep/libc/libc-sysconf.rs b/src/tools/miri/tests/pass-dep/libc/libc-sysconf.rs new file mode 100644 index 0000000000000..34d5b1e38a631 --- /dev/null +++ b/src/tools/miri/tests/pass-dep/libc/libc-sysconf.rs @@ -0,0 +1,17 @@ +//@ignore-target: windows # Supported only on unixes + +fn test_sysconfbasic() { + unsafe { + let ncpus = libc::sysconf(libc::_SC_NPROCESSORS_CONF); + assert!(ncpus >= 1); + let psz = libc::sysconf(libc::_SC_PAGESIZE); + assert!(psz % 4096 == 0); + // note that in reality it can return -1 (no hard limit) on some platforms. + let gwmax = libc::sysconf(libc::_SC_GETPW_R_SIZE_MAX); + assert!(gwmax >= 512); + } +} + +fn main() { + test_sysconfbasic(); +}