1use rustc_middle::ty::Ty;
2use rustc_span::Symbol;
3use rustc_target::callconv::FnAbi;
4
5use crate::shims::unix::env::EvalContextExt as _;
6use crate::shims::unix::linux_like::epoll::EvalContextExt as _;
7use crate::shims::unix::linux_like::eventfd::EvalContextExt as _;
8use crate::shims::unix::linux_like::syscall::syscall;
9use crate::shims::unix::linux_like::thread::prctl;
10use crate::shims::unix::*;
11use crate::*;
12
13pub fn is_dyn_sym(name: &str) -> bool {
14 matches!(name, "gettid")
15}
16
17impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
18pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
19 fn emulate_foreign_item_inner(
20 &mut self,
21 link_name: Symbol,
22 abi: &FnAbi<'tcx, Ty<'tcx>>,
23 args: &[OpTy<'tcx>],
24 dest: &MPlaceTy<'tcx>,
25 ) -> InterpResult<'tcx, EmulateItemResult> {
26 let ecx = self.eval_context_mut();
27 match link_name.as_str() {
28 "pread64" => {
30 let [fd, buf, count, offset] = &ecx.check_shim_sig(
31 shim_sig!(extern "C" fn(i32, *_, usize, libc::off64_t) -> isize),
32 (link_name, abi, args),
33 )?;
34 let fd = ecx.read_scalar(fd)?.to_i32()?;
35 let buf = ecx.read_pointer(buf)?;
36 let count = ecx.read_target_usize(count)?;
37 let offset = ecx.read_scalar(offset)?.to_int(offset.layout.size)?;
38 ecx.read(fd, buf, count, Some(offset), dest)?;
39 }
40 "pwrite64" => {
41 let [fd, buf, n, offset] = &ecx.check_shim_sig(
42 shim_sig!(extern "C" fn(i32, *_, usize, libc::off64_t) -> isize),
43 (link_name, abi, args),
44 )?;
45 let fd = ecx.read_scalar(fd)?.to_i32()?;
46 let buf = ecx.read_pointer(buf)?;
47 let count = ecx.read_target_usize(n)?;
48 let offset = ecx.read_scalar(offset)?.to_int(offset.layout.size)?;
49 trace!("Called pwrite64({:?}, {:?}, {:?}, {:?})", fd, buf, count, offset);
50 ecx.write(fd, buf, count, Some(offset), dest)?;
51 }
52 "lseek64" => {
53 let [fd, offset, whence] = &ecx.check_shim_sig(
54 shim_sig!(extern "C" fn(i32, libc::off64_t, i32) -> libc::off64_t),
55 (link_name, abi, args),
56 )?;
57 let fd = ecx.read_scalar(fd)?.to_i32()?;
58 let offset = ecx.read_scalar(offset)?.to_int(offset.layout.size)?;
59 let whence = ecx.read_scalar(whence)?.to_i32()?;
60 ecx.lseek(fd, offset, whence, dest)?;
61 }
62 "ftruncate64" => {
63 let [fd, length] = &ecx.check_shim_sig(
64 shim_sig!(extern "C" fn(i32, libc::off64_t) -> i32),
65 (link_name, abi, args),
66 )?;
67 let fd = ecx.read_scalar(fd)?.to_i32()?;
68 let length = ecx.read_scalar(length)?.to_int(length.layout.size)?;
69 let result = ecx.ftruncate64(fd, length)?;
70 ecx.write_scalar(result, dest)?;
71 }
72
73 "epoll_create1" => {
75 let [flag] = &ecx
76 .check_shim_sig(shim_sig!(extern "C" fn(i32) -> i32), (link_name, abi, args))?;
77 let result = ecx.epoll_create1(flag)?;
78 ecx.write_scalar(result, dest)?;
79 }
80 "epoll_ctl" => {
81 let [epfd, op, fd, event] = &ecx.check_shim_sig(
82 shim_sig!(extern "C" fn(i32, i32, i32, *libc::epoll_event) -> i32),
83 (link_name, abi, args),
84 )?;
85 let result = ecx.epoll_ctl(epfd, op, fd, event)?;
86 ecx.write_scalar(result, dest)?;
87 }
88 "epoll_wait" => {
89 let [epfd, events, maxevents, timeout] = &ecx.check_shim_sig(
90 shim_sig!(extern "C" fn(i32, *libc::epoll_event, i32, i32) -> i32),
91 (link_name, abi, args),
92 )?;
93 ecx.epoll_wait(epfd, events, maxevents, timeout, dest)?;
94 }
95 "eventfd" => {
96 let [val, flag] = &ecx.check_shim_sig(
97 shim_sig!(extern "C" fn(u32, i32) -> i32),
98 (link_name, abi, args),
99 )?;
100 let result = ecx.eventfd(val, flag)?;
101 ecx.write_scalar(result, dest)?;
102 }
103
104 "__errno" => {
106 let [] =
107 &ecx.check_shim_sig(shim_sig!(extern "C" fn() -> *_), (link_name, abi, args))?;
108 let errno_place = ecx.last_error_place()?;
109 ecx.write_scalar(errno_place.to_ref(ecx).to_scalar(), dest)?;
110 }
111
112 "gettid" => {
113 let [] = &ecx.check_shim_sig(
114 shim_sig!(extern "C" fn() -> libc::pid_t),
115 (link_name, abi, args),
116 )?;
117 let result = ecx.unix_gettid(link_name.as_str())?;
118 ecx.write_scalar(result, dest)?;
119 }
120
121 "syscall" => syscall(ecx, link_name, abi, args, dest)?,
123
124 "prctl" => prctl(ecx, link_name, abi, args, dest)?,
126
127 "sendfile" if ecx.frame_in_std() => {
129 let [_out_fd, _in_fd, _offset, _count] = &ecx.check_shim_sig(
130 shim_sig!(extern "C" fn(i32, i32, *libc::off_t, usize) -> isize),
131 (link_name, abi, args),
132 )?;
133 ecx.set_errno_and_return_neg1(LibcError("ENOSYS"), dest)?;
135 }
136
137 _ => return interp_ok(EmulateItemResult::NotSupported),
138 }
139 interp_ok(EmulateItemResult::NeedsReturn)
140 }
141}