Skip to content

Commit 8dc063c

Browse files
committed
Auto merge of #3559 - RalfJung:weak-extern-static, r=RalfJung
add helper function to declare an extern static for a weak symbol and use it to make `statx` a regular function and get rid of the syscall
2 parents 5748d79 + 99f77ac commit 8dc063c

File tree

8 files changed

+50
-36
lines changed

8 files changed

+50
-36
lines changed

src/tools/miri/src/shims/extern_static.rs

+20-9
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> {
1616

1717
/// Zero-initialized pointer-sized extern statics are pretty common.
1818
/// Most of them are for weak symbols, which we all set to null (indicating that the
19-
/// symbol is not supported, and triggering fallback code which ends up calling a
20-
/// syscall that we do support).
19+
/// symbol is not supported, and triggering fallback code which ends up calling
20+
/// some other shim that we do support).
2121
fn null_ptr_extern_statics(
2222
this: &mut MiriInterpCx<'mir, 'tcx>,
2323
names: &[&str],
@@ -29,6 +29,21 @@ impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> {
2929
Ok(())
3030
}
3131

32+
/// Extern statics that are initialized with function pointers to the symbols of the same name.
33+
fn weak_symbol_extern_statics(
34+
this: &mut MiriInterpCx<'mir, 'tcx>,
35+
names: &[&str],
36+
) -> InterpResult<'tcx> {
37+
for name in names {
38+
assert!(this.is_dyn_sym(name), "{name} is not a dynamic symbol");
39+
let layout = this.machine.layouts.const_raw_ptr;
40+
let ptr = this.fn_ptr(FnVal::Other(DynSym::from_str(name)));
41+
let val = ImmTy::from_scalar(Scalar::from_pointer(ptr, this), layout);
42+
Self::alloc_extern_static(this, name, val)?;
43+
}
44+
Ok(())
45+
}
46+
3247
/// Sets up the "extern statics" for this machine.
3348
pub fn init_extern_statics(this: &mut MiriInterpCx<'mir, 'tcx>) -> InterpResult<'tcx> {
3449
// "__rust_no_alloc_shim_is_unstable"
@@ -44,8 +59,9 @@ impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> {
4459
"linux" => {
4560
Self::null_ptr_extern_statics(
4661
this,
47-
&["__cxa_thread_atexit_impl", "getrandom", "statx", "__clock_gettime64"],
62+
&["__cxa_thread_atexit_impl", "__clock_gettime64"],
4863
)?;
64+
Self::weak_symbol_extern_statics(this, &["getrandom", "statx"])?;
4965
// "environ"
5066
let environ = this.machine.env_vars.unix().environ();
5167
Self::add_extern_static(this, "environ", environ);
@@ -58,12 +74,7 @@ impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> {
5874
}
5975
"android" => {
6076
Self::null_ptr_extern_statics(this, &["bsd_signal"])?;
61-
// "signal" -- just needs a non-zero pointer value (function does not even get called),
62-
// but we arrange for this to call the `signal` function anyway.
63-
let layout = this.machine.layouts.const_raw_ptr;
64-
let ptr = this.fn_ptr(FnVal::Other(DynSym::from_str("signal")));
65-
let val = ImmTy::from_scalar(Scalar::from_pointer(ptr, this), layout);
66-
Self::alloc_extern_static(this, "signal", val)?;
77+
Self::weak_symbol_extern_statics(this, &["signal"])?;
6778
}
6879
"windows" => {
6980
// "_tls_used"

src/tools/miri/src/shims/foreign_items.rs

+9
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,15 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
151151
Ok(None)
152152
}
153153

154+
fn is_dyn_sym(&self, name: &str) -> bool {
155+
let this = self.eval_context_ref();
156+
match this.tcx.sess.target.os.as_ref() {
157+
os if this.target_os_is_unix() => shims::unix::foreign_items::is_dyn_sym(name, os),
158+
"windows" => shims::windows::foreign_items::is_dyn_sym(name),
159+
_ => false,
160+
}
161+
}
162+
154163
/// Emulates a call to a `DynSym`.
155164
fn emulate_dyn_sym(
156165
&mut self,

src/tools/miri/src/shims/unix/fd.rs

+4
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ use crate::*;
1717
pub trait FileDescription: std::fmt::Debug + Any {
1818
fn name(&self) -> &'static str;
1919

20+
/// Reads as much as possible into the given buffer, and returns the number of bytes read.
2021
fn read<'tcx>(
2122
&mut self,
2223
_communicate_allowed: bool,
@@ -26,6 +27,7 @@ pub trait FileDescription: std::fmt::Debug + Any {
2627
throw_unsup_format!("cannot read from {}", self.name());
2728
}
2829

30+
/// Writes as much as possible from the given buffer, and returns the number of bytes written.
2931
fn write<'tcx>(
3032
&mut self,
3133
_communicate_allowed: bool,
@@ -35,6 +37,8 @@ pub trait FileDescription: std::fmt::Debug + Any {
3537
throw_unsup_format!("cannot write to {}", self.name());
3638
}
3739

40+
/// Seeks to the given offset (which can be relative to the beginning, end, or current position).
41+
/// Returns the new position from the start of the stream.
3842
fn seek<'tcx>(
3943
&mut self,
4044
_communicate_allowed: bool,

src/tools/miri/src/shims/unix/foreign_items.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use shims::unix::freebsd::foreign_items as freebsd;
1515
use shims::unix::linux::foreign_items as linux;
1616
use shims::unix::macos::foreign_items as macos;
1717

18-
fn is_dyn_sym(name: &str, target_os: &str) -> bool {
18+
pub fn is_dyn_sym(name: &str, target_os: &str) -> bool {
1919
match name {
2020
// Used for tests.
2121
"isatty" => true,

src/tools/miri/src/shims/unix/linux/foreign_items.rs

+8-19
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use shims::unix::linux::mem::EvalContextExt as _;
1212
use shims::unix::linux::sync::futex;
1313

1414
pub fn is_dyn_sym(name: &str) -> bool {
15-
matches!(name, "getrandom")
15+
matches!(name, "getrandom" | "statx")
1616
}
1717

1818
impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
@@ -29,7 +29,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
2929
// See `fn emulate_foreign_item_inner` in `shims/foreign_items.rs` for the general pattern.
3030

3131
match link_name.as_str() {
32-
// File related shims (but also see "syscall" below for statx)
32+
// File related shims
3333
"readdir64" => {
3434
let [dirp] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
3535
let result = this.linux_readdir64(dirp)?;
@@ -41,6 +41,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
4141
let result = this.sync_file_range(fd, offset, nbytes, flags)?;
4242
this.write_scalar(result, dest)?;
4343
}
44+
"statx" => {
45+
let [dirfd, pathname, flags, mask, statxbuf] =
46+
this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
47+
let result = this.linux_statx(dirfd, pathname, flags, mask, statxbuf)?;
48+
this.write_scalar(Scalar::from_i32(result), dest)?;
49+
}
4450

4551
// epoll, eventfd
4652
"epoll_create1" => {
@@ -113,9 +119,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
113119
// have the right type.
114120

115121
let sys_getrandom = this.eval_libc("SYS_getrandom").to_target_usize(this)?;
116-
117-
let sys_statx = this.eval_libc("SYS_statx").to_target_usize(this)?;
118-
119122
let sys_futex = this.eval_libc("SYS_futex").to_target_usize(this)?;
120123

121124
if args.is_empty() {
@@ -136,20 +139,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
136139
}
137140
getrandom(this, &args[1], &args[2], &args[3], dest)?;
138141
}
139-
// `statx` is used by `libstd` to retrieve metadata information on `linux`
140-
// instead of using `stat`,`lstat` or `fstat` as on `macos`.
141-
id if id == sys_statx => {
142-
// The first argument is the syscall id, so skip over it.
143-
if args.len() < 6 {
144-
throw_ub_format!(
145-
"incorrect number of arguments for `statx` syscall: got {}, expected at least 6",
146-
args.len()
147-
);
148-
}
149-
let result =
150-
this.linux_statx(&args[1], &args[2], &args[3], &args[4], &args[5])?;
151-
this.write_scalar(Scalar::from_target_isize(result.into(), this), dest)?;
152-
}
153142
// `futex` is used by some synchronization primitives.
154143
id if id == sys_futex => {
155144
futex(this, &args[1..], dest)?;

src/tools/miri/src/shims/windows/foreign_items.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use crate::*;
1515
use shims::foreign_items::EmulateForeignItemResult;
1616
use shims::windows::handle::{Handle, PseudoHandle};
1717

18-
fn is_dyn_sym(name: &str) -> bool {
18+
pub fn is_dyn_sym(name: &str) -> bool {
1919
// std does dynamic detection for these symbols
2020
matches!(
2121
name,

src/tools/miri/tests/pass/alloc-access-tracking.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
#![feature(start)]
22
#![no_std]
3-
//@compile-flags: -Zmiri-track-alloc-id=18 -Zmiri-track-alloc-accesses -Cpanic=abort
4-
//@only-target-linux: alloc IDs differ between OSes for some reason
3+
//@compile-flags: -Zmiri-track-alloc-id=20 -Zmiri-track-alloc-accesses -Cpanic=abort
4+
//@normalize-stderr-test: "id 20" -> "id $$ALLOC"
5+
//@only-target-linux: alloc IDs differ between OSes (due to extern static allocations)
56

67
extern "Rust" {
78
fn miri_alloc(size: usize, align: usize) -> *mut u8;

src/tools/miri/tests/pass/alloc-access-tracking.stderr

+4-4
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ note: tracking was triggered
22
--> $DIR/alloc-access-tracking.rs:LL:CC
33
|
44
LL | let ptr = miri_alloc(123, 1);
5-
| ^^^^^^^^^^^^^^^^^^ created Miri bare-metal heap allocation of 123 bytes (alignment ALIGN bytes) with id 18
5+
| ^^^^^^^^^^^^^^^^^^ created Miri bare-metal heap allocation of 123 bytes (alignment ALIGN bytes) with id $ALLOC
66
|
77
= note: BACKTRACE:
88
= note: inside `start` at $DIR/alloc-access-tracking.rs:LL:CC
@@ -11,7 +11,7 @@ note: tracking was triggered
1111
--> $DIR/alloc-access-tracking.rs:LL:CC
1212
|
1313
LL | *ptr = 42; // Crucially, only a write is printed here, no read!
14-
| ^^^^^^^^^ write access to allocation with id 18
14+
| ^^^^^^^^^ write access to allocation with id $ALLOC
1515
|
1616
= note: BACKTRACE:
1717
= note: inside `start` at $DIR/alloc-access-tracking.rs:LL:CC
@@ -20,7 +20,7 @@ note: tracking was triggered
2020
--> $DIR/alloc-access-tracking.rs:LL:CC
2121
|
2222
LL | assert_eq!(*ptr, 42);
23-
| ^^^^^^^^^^^^^^^^^^^^ read access to allocation with id 18
23+
| ^^^^^^^^^^^^^^^^^^^^ read access to allocation with id $ALLOC
2424
|
2525
= note: BACKTRACE:
2626
= note: inside `start` at RUSTLIB/core/src/macros/mod.rs:LL:CC
@@ -30,7 +30,7 @@ note: tracking was triggered
3030
--> $DIR/alloc-access-tracking.rs:LL:CC
3131
|
3232
LL | miri_dealloc(ptr, 123, 1);
33-
| ^^^^^^^^^^^^^^^^^^^^^^^^^ freed allocation with id 18
33+
| ^^^^^^^^^^^^^^^^^^^^^^^^^ freed allocation with id $ALLOC
3434
|
3535
= note: BACKTRACE:
3636
= note: inside `start` at $DIR/alloc-access-tracking.rs:LL:CC

0 commit comments

Comments
 (0)