1use rustc_abi::CanonAbi;
2use rustc_middle::ty::Ty;
3use rustc_span::Symbol;
4use rustc_target::callconv::FnAbi;
5
6use super::sync::EvalContextExt as _;
7use crate::shims::unix::*;
8use crate::*;
9
10pub fn is_dyn_sym(_name: &str) -> bool {
11 false
12}
13
14impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
15pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
16 fn emulate_foreign_item_inner(
17 &mut self,
18 link_name: Symbol,
19 abi: &FnAbi<'tcx, Ty<'tcx>>,
20 args: &[OpTy<'tcx>],
21 dest: &MPlaceTy<'tcx>,
22 ) -> InterpResult<'tcx, EmulateItemResult> {
23 let this = self.eval_context_mut();
24 match link_name.as_str() {
25 "pthread_setname_np" => {
27 let [thread, name] =
28 this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
29 let max_len = u64::MAX; let res = match this.pthread_setname_np(
31 this.read_scalar(thread)?,
32 this.read_scalar(name)?,
33 max_len,
34 false,
35 )? {
36 ThreadNameResult::Ok => Scalar::from_u32(0),
37 ThreadNameResult::NameTooLong => unreachable!(),
38 ThreadNameResult::ThreadNotFound => this.eval_libc("ESRCH"),
39 };
40 this.write_scalar(res, dest)?;
41 }
42 "pthread_getname_np" => {
43 let [thread, name, len] =
44 this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
45 let res = match this.pthread_getname_np(
49 this.read_scalar(thread)?,
50 this.read_scalar(name)?,
51 this.read_scalar(len)?,
52 true,
53 )? {
54 ThreadNameResult::Ok => Scalar::from_u32(0),
55 ThreadNameResult::NameTooLong => Scalar::from_u32(0),
57 ThreadNameResult::ThreadNotFound => this.eval_libc("ESRCH"),
58 };
59 this.write_scalar(res, dest)?;
60 }
61 "pthread_getthreadid_np" => {
62 let [] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
63 let result = this.unix_gettid(link_name.as_str())?;
64 this.write_scalar(result, dest)?;
65 }
66
67 "cpuset_getaffinity" => {
68 let [level, which, id, set_size, mask] =
70 this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
71
72 let level = this.read_scalar(level)?.to_i32()?;
73 let which = this.read_scalar(which)?.to_i32()?;
74 let id = this.read_scalar(id)?.to_i64()?;
75 let set_size = this.read_target_usize(set_size)?; let mask = this.read_pointer(mask)?;
77
78 if this.machine.thread_cpu_affinity.is_none() {
79 throw_unsup_format!(
80 "`cpuset_getaffinity` is not supported on #![no_core] programs"
81 )
82 }
83
84 let _level_root = this.eval_libc_i32("CPU_LEVEL_ROOT");
85 let _level_cpuset = this.eval_libc_i32("CPU_LEVEL_CPUSET");
86 let level_which = this.eval_libc_i32("CPU_LEVEL_WHICH");
87
88 let _which_tid = this.eval_libc_i32("CPU_WHICH_TID");
89 let which_pid = this.eval_libc_i32("CPU_WHICH_PID");
90 let _which_jail = this.eval_libc_i32("CPU_WHICH_JAIL");
91 let _which_cpuset = this.eval_libc_i32("CPU_WHICH_CPUSET");
92 let _which_irq = this.eval_libc_i32("CPU_WHICH_IRQ");
93
94 let id = match id {
97 -1 => this.active_thread(),
98 _ =>
99 throw_unsup_format!(
100 "`cpuset_getaffinity` is only supported with a pid of -1 (indicating the current thread)"
101 ),
102 };
103
104 if this.ptr_is_null(mask)? {
105 this.set_errno_and_return_neg1(LibcError("EFAULT"), dest)?;
106 }
107 else if level != level_which || which != which_pid {
110 throw_unsup_format!(
111 "`cpuset_getaffinity` is only supported with `level` set to CPU_LEVEL_WHICH and `which` set to CPU_WHICH_PID."
112 );
113 } else if let Some(cpuset) =
114 this.machine.thread_cpu_affinity.as_ref().unwrap().get(&id)
115 {
116 if set_size < u64::from(this.machine.num_cpus).div_ceil(8) {
122 this.set_errno_and_return_neg1(LibcError("ERANGE"), dest)?;
123 } else {
124 let cpuset = cpuset.clone();
125 let byte_count =
126 Ord::min(cpuset.as_slice().len(), set_size.try_into().unwrap());
127 this.write_bytes_ptr(
128 mask,
129 cpuset.as_slice()[..byte_count].iter().copied(),
130 )?;
131 this.write_null(dest)?;
132 }
133 } else {
134 unreachable!();
136 }
137 }
138
139 "_umtx_op" => {
141 let [obj, op, val, uaddr, uaddr2] =
142 this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
143 this._umtx_op(obj, op, val, uaddr, uaddr2, dest)?;
144 }
145
146 "stat@FBSD_1.0" => {
148 let [path, buf] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
149 let result = this.stat(path, buf)?;
150 this.write_scalar(result, dest)?;
151 }
152 "lstat@FBSD_1.0" => {
153 let [path, buf] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
154 let result = this.lstat(path, buf)?;
155 this.write_scalar(result, dest)?;
156 }
157 "fstat@FBSD_1.0" => {
158 let [fd, buf] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
159 let result = this.fstat(fd, buf)?;
160 this.write_scalar(result, dest)?;
161 }
162 "readdir@FBSD_1.0" => {
163 let [dirp] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
164 this.readdir(dirp, dest)?;
165 }
166 "__error" => {
168 let [] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
169 let errno_place = this.last_error_place()?;
170 this.write_scalar(errno_place.to_ref(this).to_scalar(), dest)?;
171 }
172 "__xuname" => {
173 let [size, uname] = this.check_shim_sig(
177 shim_sig!(extern "C" fn(i32, *mut _) -> i32),
178 link_name,
179 abi,
180 args,
181 )?;
182 let result = this.uname(uname, Some(size))?;
183 this.write_scalar(result, dest)?;
184 }
185
186 "pthread_attr_get_np" if this.frame_in_std() => {
189 let [_thread, _attr] =
190 this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
191 this.write_null(dest)?;
192 }
193
194 _ => return interp_ok(EmulateItemResult::NotSupported),
195 }
196 interp_ok(EmulateItemResult::NeedsReturn)
197 }
198}