1use rustc_middle::ty::Ty;
2use rustc_span::Symbol;
3use rustc_target::callconv::{Conv, FnAbi};
4
5use super::sync::EvalContextExt as _;
6use crate::shims::unix::*;
7use crate::*;
8
9pub fn is_dyn_sym(_name: &str) -> bool {
10 false
11}
12
13impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
14pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
15 fn emulate_foreign_item_inner(
16 &mut self,
17 link_name: Symbol,
18 abi: &FnAbi<'tcx, Ty<'tcx>>,
19 args: &[OpTy<'tcx>],
20 dest: &MPlaceTy<'tcx>,
21 ) -> InterpResult<'tcx, EmulateItemResult> {
22 let this = self.eval_context_mut();
23 match link_name.as_str() {
24 "pthread_setname_np" => {
26 let [thread, name] = this.check_shim(abi, Conv::C, link_name, args)?;
27 let max_len = u64::MAX; let res = match this.pthread_setname_np(
29 this.read_scalar(thread)?,
30 this.read_scalar(name)?,
31 max_len,
32 false,
33 )? {
34 ThreadNameResult::Ok => Scalar::from_u32(0),
35 ThreadNameResult::NameTooLong => unreachable!(),
36 ThreadNameResult::ThreadNotFound => this.eval_libc("ESRCH"),
37 };
38 this.write_scalar(res, dest)?;
39 }
40 "pthread_getname_np" => {
41 let [thread, name, len] = this.check_shim(abi, Conv::C, link_name, args)?;
42 let res = match this.pthread_getname_np(
46 this.read_scalar(thread)?,
47 this.read_scalar(name)?,
48 this.read_scalar(len)?,
49 true,
50 )? {
51 ThreadNameResult::Ok => Scalar::from_u32(0),
52 ThreadNameResult::NameTooLong => Scalar::from_u32(0),
54 ThreadNameResult::ThreadNotFound => this.eval_libc("ESRCH"),
55 };
56 this.write_scalar(res, dest)?;
57 }
58
59 "cpuset_getaffinity" => {
60 let [level, which, id, set_size, mask] =
62 this.check_shim(abi, Conv::C, link_name, args)?;
63
64 let level = this.read_scalar(level)?.to_i32()?;
65 let which = this.read_scalar(which)?.to_i32()?;
66 let id = this.read_scalar(id)?.to_i64()?;
67 let set_size = this.read_target_usize(set_size)?; let mask = this.read_pointer(mask)?;
69
70 let _level_root = this.eval_libc_i32("CPU_LEVEL_ROOT");
71 let _level_cpuset = this.eval_libc_i32("CPU_LEVEL_CPUSET");
72 let level_which = this.eval_libc_i32("CPU_LEVEL_WHICH");
73
74 let _which_tid = this.eval_libc_i32("CPU_WHICH_TID");
75 let which_pid = this.eval_libc_i32("CPU_WHICH_PID");
76 let _which_jail = this.eval_libc_i32("CPU_WHICH_JAIL");
77 let _which_cpuset = this.eval_libc_i32("CPU_WHICH_CPUSET");
78 let _which_irq = this.eval_libc_i32("CPU_WHICH_IRQ");
79
80 let id = match id {
83 -1 => this.active_thread(),
84 _ =>
85 throw_unsup_format!(
86 "`cpuset_getaffinity` is only supported with a pid of -1 (indicating the current thread)"
87 ),
88 };
89
90 if this.ptr_is_null(mask)? {
91 this.set_last_error_and_return(LibcError("EFAULT"), dest)?;
92 }
93 else if level != level_which || which != which_pid {
96 throw_unsup_format!(
97 "`cpuset_getaffinity` is only supported with `level` set to CPU_LEVEL_WHICH and `which` set to CPU_WHICH_PID."
98 );
99 } else if let Some(cpuset) = this.machine.thread_cpu_affinity.get(&id) {
100 if set_size < u64::from(this.machine.num_cpus).div_ceil(8) {
106 this.set_last_error_and_return(LibcError("ERANGE"), dest)?;
107 } else {
108 let cpuset = cpuset.clone();
109 let byte_count =
110 Ord::min(cpuset.as_slice().len(), set_size.try_into().unwrap());
111 this.write_bytes_ptr(
112 mask,
113 cpuset.as_slice()[..byte_count].iter().copied(),
114 )?;
115 this.write_null(dest)?;
116 }
117 } else {
118 unreachable!();
120 }
121 }
122
123 "_umtx_op" => {
125 let [obj, op, val, uaddr, uaddr2] =
126 this.check_shim(abi, Conv::C, link_name, args)?;
127 this._umtx_op(obj, op, val, uaddr, uaddr2, dest)?;
128 }
129
130 "stat" | "stat@FBSD_1.0" => {
134 let [path, buf] = this.check_shim(abi, Conv::C, link_name, args)?;
135 let result = this.macos_fbsd_solarish_stat(path, buf)?;
136 this.write_scalar(result, dest)?;
137 }
138 "lstat" | "lstat@FBSD_1.0" => {
139 let [path, buf] = this.check_shim(abi, Conv::C, link_name, args)?;
140 let result = this.macos_fbsd_solarish_lstat(path, buf)?;
141 this.write_scalar(result, dest)?;
142 }
143 "fstat" | "fstat@FBSD_1.0" => {
144 let [fd, buf] = this.check_shim(abi, Conv::C, link_name, args)?;
145 let result = this.macos_fbsd_solarish_fstat(fd, buf)?;
146 this.write_scalar(result, dest)?;
147 }
148 "readdir_r" | "readdir_r@FBSD_1.0" => {
149 let [dirp, entry, result] = this.check_shim(abi, Conv::C, link_name, args)?;
150 let result = this.macos_fbsd_readdir_r(dirp, entry, result)?;
151 this.write_scalar(result, dest)?;
152 }
153
154 "__error" => {
156 let [] = this.check_shim(abi, Conv::C, link_name, args)?;
157 let errno_place = this.last_error_place()?;
158 this.write_scalar(errno_place.to_ref(this).to_scalar(), dest)?;
159 }
160
161 "pthread_attr_get_np" if this.frame_in_std() => {
164 let [_thread, _attr] = this.check_shim(abi, Conv::C, link_name, args)?;
165 this.write_null(dest)?;
166 }
167
168 _ => return interp_ok(EmulateItemResult::NotSupported),
169 }
170 interp_ok(EmulateItemResult::NeedsReturn)
171 }
172}