1use rustc_middle::ty::Ty;
2use rustc_span::Symbol;
3use rustc_target::callconv::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_sig(
27 shim_sig!(extern "C" fn(libc::pthread_t, *_) -> i32),
28 (link_name, abi, args),
29 )?;
30 let max_len = u64::MAX; let res = match this.pthread_setname_np(
32 this.read_scalar(thread)?,
33 this.read_scalar(name)?,
34 max_len,
35 false,
36 )? {
37 ThreadNameResult::Ok => Scalar::from_u32(0),
38 ThreadNameResult::NameTooLong => unreachable!(),
39 };
40 this.write_scalar(res, dest)?;
41 }
42 "pthread_getname_np" => {
43 let [thread, name, len] = &this.check_shim_sig(
44 shim_sig!(extern "C" fn(libc::pthread_t, *_, usize) -> i32),
45 (link_name, abi, args),
46 )?;
47 let res = match this.pthread_getname_np(
51 this.read_scalar(thread)?,
52 this.read_scalar(name)?,
53 this.read_scalar(len)?,
54 true,
55 )? {
56 ThreadNameResult::Ok => Scalar::from_u32(0),
57 ThreadNameResult::NameTooLong => Scalar::from_u32(0),
59 };
60 this.write_scalar(res, dest)?;
61 }
62 "pthread_getthreadid_np" => {
63 let [] = &this
64 .check_shim_sig(shim_sig!(extern "C" fn() -> i32), (link_name, abi, args))?;
65 let result = this.unix_gettid(link_name.as_str())?;
66 this.write_scalar(result, dest)?;
67 }
68
69 "cpuset_getaffinity" => {
70 let [level, which, id, set_size, mask] = &this.check_shim_sig(
72 shim_sig!(extern "C" fn(i32, i32, i64, usize, *_) -> i32),
73 (link_name, abi, args),
74 )?;
75
76 let level = this.read_scalar(level)?.to_i32()?;
77 let which = this.read_scalar(which)?.to_i32()?;
78 let id = this.read_scalar(id)?.to_i64()?;
79 let set_size = this.read_target_usize(set_size)?; let mask = this.read_pointer(mask)?;
81
82 if this.machine.thread_cpu_affinity.is_none() {
83 throw_unsup_format!(
84 "`cpuset_getaffinity` is not supported on #![no_core] programs"
85 )
86 }
87
88 let _level_root = this.eval_libc_i32("CPU_LEVEL_ROOT");
89 let _level_cpuset = this.eval_libc_i32("CPU_LEVEL_CPUSET");
90 let level_which = this.eval_libc_i32("CPU_LEVEL_WHICH");
91
92 let _which_tid = this.eval_libc_i32("CPU_WHICH_TID");
93 let which_pid = this.eval_libc_i32("CPU_WHICH_PID");
94 let _which_jail = this.eval_libc_i32("CPU_WHICH_JAIL");
95 let _which_cpuset = this.eval_libc_i32("CPU_WHICH_CPUSET");
96 let _which_irq = this.eval_libc_i32("CPU_WHICH_IRQ");
97
98 let id = match id {
101 -1 => this.active_thread(),
102 _ =>
103 throw_unsup_format!(
104 "`cpuset_getaffinity` is only supported with a pid of -1 (indicating the current thread)"
105 ),
106 };
107
108 if this.ptr_is_null(mask)? {
109 this.set_errno_and_return_neg1(LibcError("EFAULT"), dest)?;
110 }
111 else if level != level_which || which != which_pid {
114 throw_unsup_format!(
115 "`cpuset_getaffinity` is only supported with `level` set to CPU_LEVEL_WHICH and `which` set to CPU_WHICH_PID."
116 );
117 } else if let Some(cpuset) =
118 this.machine.thread_cpu_affinity.as_ref().unwrap().get(&id)
119 {
120 if set_size < u64::from(this.machine.num_cpus).div_ceil(8) {
126 this.set_errno_and_return_neg1(LibcError("ERANGE"), dest)?;
127 } else {
128 let cpuset = cpuset.clone();
129 let byte_count =
130 Ord::min(cpuset.as_slice().len(), set_size.try_into().unwrap());
131 this.write_bytes_ptr(
132 mask,
133 cpuset.as_slice()[..byte_count].iter().copied(),
134 )?;
135 this.write_int(0, dest)?;
136 }
137 } else {
138 unreachable!();
140 }
141 }
142
143 "_umtx_op" => {
145 let [obj, op, val, uaddr, uaddr2] = &this.check_shim_sig(
146 shim_sig!(extern "C" fn(*_, i32, usize, *_, *_) -> i32),
147 (link_name, abi, args),
148 )?;
149 this._umtx_op(obj, op, val, uaddr, uaddr2, dest)?;
150 }
151
152 "__error" => {
154 let [] = &this
155 .check_shim_sig(shim_sig!(extern "C" fn() -> *_), (link_name, abi, args))?;
156 let errno_place = this.last_error_place()?;
157 this.write_scalar(errno_place.to_ref(this).to_scalar(), dest)?;
158 }
159 "__xuname" => {
160 let [size, uname] = &this.check_shim_sig(
164 shim_sig!(extern "C" fn(i32, *libc::utsname) -> i32),
165 (link_name, abi, args),
166 )?;
167 let result = this.uname(uname, Some(size))?;
168 this.write_scalar(result, dest)?;
169 }
170
171 "pthread_attr_get_np" if this.frame_in_std() => {
174 let [_thread, _attr] = &this.check_shim_sig(
175 shim_sig!(extern "C" fn(libc::pthread_t, *_) -> i32),
176 (link_name, abi, args),
177 )?;
178 this.write_int(0, dest)?;
179 }
180
181 _ => return interp_ok(EmulateItemResult::NotSupported),
182 }
183 interp_ok(EmulateItemResult::NeedsReturn)
184 }
185}