1use rustc_abi::CanonAbi;
2use rustc_middle::ty::Ty;
3use rustc_span::Symbol;
4use rustc_target::callconv::FnAbi;
5
6use self::shims::unix::linux::mem::EvalContextExt as _;
7use self::shims::unix::linux_like::eventfd::EvalContextExt as _;
8use self::shims::unix::linux_like::syscall::syscall;
9use crate::machine::{SIGRTMAX, SIGRTMIN};
10use crate::shims::unix::foreign_items::EvalContextExt as _;
11use crate::shims::unix::*;
12use crate::*;
13
14const TASK_COMM_LEN: u64 = 16;
18
19pub fn is_dyn_sym(name: &str) -> bool {
20 matches!(name, "gettid" | "statx")
21}
22
23impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
24pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
25 fn emulate_foreign_item_inner(
26 &mut self,
27 link_name: Symbol,
28 abi: &FnAbi<'tcx, Ty<'tcx>>,
29 args: &[OpTy<'tcx>],
30 dest: &MPlaceTy<'tcx>,
31 ) -> InterpResult<'tcx, EmulateItemResult> {
32 let this = self.eval_context_mut();
33
34 match link_name.as_str() {
37 "open64" => {
39 let ([path_raw, flag], varargs) =
42 this.check_shim_sig_variadic_lenient(abi, CanonAbi::C, link_name, args)?;
43 let result = this.open(path_raw, flag, varargs)?;
44 this.write_scalar(result, dest)?;
45 }
46 "pread64" => {
47 let [fd, buf, count, offset] = this.check_shim_sig(
49 shim_sig!(extern "C" fn(i32, *mut _, usize, libc::off64_t) -> isize),
50 link_name,
51 abi,
52 args,
53 )?;
54 let fd = this.read_scalar(fd)?.to_i32()?;
55 let buf = this.read_pointer(buf)?;
56 let count = this.read_target_usize(count)?;
57 let offset = this.read_scalar(offset)?.to_int(offset.layout.size)?;
58 this.read(fd, buf, count, Some(offset), dest)?;
59 }
60 "pwrite64" => {
61 let [fd, buf, n, offset] = this.check_shim_sig(
63 shim_sig!(extern "C" fn(i32, *const _, usize, libc::off64_t) -> isize),
64 link_name,
65 abi,
66 args,
67 )?;
68 let fd = this.read_scalar(fd)?.to_i32()?;
69 let buf = this.read_pointer(buf)?;
70 let count = this.read_target_usize(n)?;
71 let offset = this.read_scalar(offset)?.to_int(offset.layout.size)?;
72 trace!("Called pwrite64({:?}, {:?}, {:?}, {:?})", fd, buf, count, offset);
73 this.write(fd, buf, count, Some(offset), dest)?;
74 }
75 "lseek64" => {
76 let [fd, offset, whence] = this.check_shim_sig(
78 shim_sig!(extern "C" fn(i32, libc::off64_t, i32) -> libc::off64_t),
79 link_name,
80 abi,
81 args,
82 )?;
83 let fd = this.read_scalar(fd)?.to_i32()?;
84 let offset = this.read_scalar(offset)?.to_int(offset.layout.size)?;
85 let whence = this.read_scalar(whence)?.to_i32()?;
86 this.lseek(fd, offset, whence, dest)?;
87 }
88 "ftruncate64" => {
89 let [fd, length] = this.check_shim_sig(
90 shim_sig!(extern "C" fn(i32, libc::off64_t) -> i32),
91 link_name,
92 abi,
93 args,
94 )?;
95 let fd = this.read_scalar(fd)?.to_i32()?;
96 let length = this.read_scalar(length)?.to_int(length.layout.size)?;
97 let result = this.ftruncate64(fd, length)?;
98 this.write_scalar(result, dest)?;
99 }
100 "posix_fallocate64" => {
101 let [fd, offset, len] = this.check_shim_sig(
102 shim_sig!(extern "C" fn(i32, libc::off64_t, libc::off64_t) -> i32),
103 link_name,
104 abi,
105 args,
106 )?;
107
108 let fd = this.read_scalar(fd)?.to_i32()?;
109 let offset = this.read_scalar(offset)?.to_i64()?;
110 let len = this.read_scalar(len)?.to_i64()?;
111
112 let result = this.posix_fallocate(fd, offset, len)?;
113 this.write_scalar(result, dest)?;
114 }
115 "readdir64" => {
116 let [dirp] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
117 this.readdir(dirp, dest)?;
118 }
119 "sync_file_range" => {
120 let [fd, offset, nbytes, flags] =
121 this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
122 let result = this.sync_file_range(fd, offset, nbytes, flags)?;
123 this.write_scalar(result, dest)?;
124 }
125 "statx" => {
126 let [dirfd, pathname, flags, mask, statxbuf] =
127 this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
128 let result = this.linux_statx(dirfd, pathname, flags, mask, statxbuf)?;
129 this.write_scalar(result, dest)?;
130 }
131 "epoll_create1" => {
133 let [flag] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
134 let result = this.epoll_create1(flag)?;
135 this.write_scalar(result, dest)?;
136 }
137 "epoll_ctl" => {
138 let [epfd, op, fd, event] =
139 this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
140 let result = this.epoll_ctl(epfd, op, fd, event)?;
141 this.write_scalar(result, dest)?;
142 }
143 "epoll_wait" => {
144 let [epfd, events, maxevents, timeout] =
145 this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
146 this.epoll_wait(epfd, events, maxevents, timeout, dest)?;
147 }
148 "eventfd" => {
149 let [val, flag] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
150 let result = this.eventfd(val, flag)?;
151 this.write_scalar(result, dest)?;
152 }
153
154 "pthread_setname_np" => {
156 let [thread, name] =
157 this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
158 let res = match this.pthread_setname_np(
159 this.read_scalar(thread)?,
160 this.read_scalar(name)?,
161 TASK_COMM_LEN,
162 false,
163 )? {
164 ThreadNameResult::Ok => Scalar::from_u32(0),
165 ThreadNameResult::NameTooLong => this.eval_libc("ERANGE"),
166 ThreadNameResult::ThreadNotFound => this.eval_libc("ENOENT"),
168 };
169 this.write_scalar(res, dest)?;
170 }
171 "pthread_getname_np" => {
172 let [thread, name, len] =
173 this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
174 let len = this.read_scalar(len)?;
178 let res = if len.to_target_usize(this)? >= TASK_COMM_LEN {
179 match this.pthread_getname_np(
180 this.read_scalar(thread)?,
181 this.read_scalar(name)?,
182 len,
183 false,
184 )? {
185 ThreadNameResult::Ok => Scalar::from_u32(0),
186 ThreadNameResult::NameTooLong => unreachable!(),
187 ThreadNameResult::ThreadNotFound => this.eval_libc("ENOENT"),
189 }
190 } else {
191 this.eval_libc("ERANGE")
192 };
193 this.write_scalar(res, dest)?;
194 }
195 "gettid" => {
196 let [] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
197 let result = this.unix_gettid(link_name.as_str())?;
198 this.write_scalar(result, dest)?;
199 }
200
201 "syscall" => {
203 syscall(this, link_name, abi, args, dest)?;
204 }
205
206 "mmap64" => {
208 let [addr, length, prot, flags, fd, offset] =
209 this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
210 let offset = this.read_scalar(offset)?.to_i64()?;
211 let ptr = this.mmap(addr, length, prot, flags, fd, offset.into())?;
212 this.write_scalar(ptr, dest)?;
213 }
214 "mremap" => {
215 let ([old_address, old_size, new_size, flags], _) =
216 this.check_shim_sig_variadic_lenient(abi, CanonAbi::C, link_name, args)?;
217 let ptr = this.mremap(old_address, old_size, new_size, flags)?;
218 this.write_scalar(ptr, dest)?;
219 }
220 "__xpg_strerror_r" => {
221 let [errnum, buf, buflen] =
222 this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
223 let result = this.strerror_r(errnum, buf, buflen)?;
224 this.write_scalar(result, dest)?;
225 }
226 "__errno_location" => {
227 let [] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
228 let errno_place = this.last_error_place()?;
229 this.write_scalar(errno_place.to_ref(this).to_scalar(), dest)?;
230 }
231 "__libc_current_sigrtmin" => {
232 let [] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
233
234 this.write_int(SIGRTMIN, dest)?;
235 }
236 "__libc_current_sigrtmax" => {
237 let [] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
238
239 this.write_int(SIGRTMAX, dest)?;
240 }
241
242 "pthread_getattr_np" if this.frame_in_std() => {
245 let [_thread, _attr] =
246 this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
247 this.write_null(dest)?;
248 }
249 "gnu_get_libc_version"
250 if this.frame_in_std()
251 && this.tcx.sess.target.env == rustc_target::spec::Env::Gnu =>
252 {
253 let [] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
254 let version = "2.26\0";
257 let version = this.allocate_str_dedup(version)?;
258 this.write_pointer(version.ptr(), dest)?;
259 }
260
261 _ => return interp_ok(EmulateItemResult::NotSupported),
262 };
263
264 interp_ok(EmulateItemResult::NeedsReturn)
265 }
266}