]> git.lizzy.rs Git - rust.git/blob - src/shims/posix/macos/foreign_items.rs
d54e1bfbe8195a4b74a70691f0afefe3e58c6cb0
[rust.git] / src / shims / posix / macos / foreign_items.rs
1 use rustc_middle::mir;
2 use rustc_target::spec::abi::Abi;
3
4 use crate::*;
5 use helpers::check_arg_count;
6 use shims::foreign_items::EmulateByNameResult;
7 use shims::posix::fs::EvalContextExt as _;
8 use shims::posix::thread::EvalContextExt as _;
9
10 impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {}
11 pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx> {
12     fn emulate_foreign_item_by_name(
13         &mut self,
14         link_name: &str,
15         abi: Abi,
16         args: &[OpTy<'tcx, Tag>],
17         dest: &PlaceTy<'tcx, Tag>,
18         _ret: mir::BasicBlock,
19     ) -> InterpResult<'tcx, EmulateByNameResult> {
20         let this = self.eval_context_mut();
21
22         match link_name {
23             // errno
24             "__error" => {
25                 this.check_abi(abi, Abi::C { unwind: false })?;
26                 let &[] = check_arg_count(args)?;
27                 let errno_place = this.last_error_place()?;
28                 this.write_scalar(errno_place.to_ref().to_scalar()?, dest)?;
29             }
30
31             // File related shims
32             "close" | "close$NOCANCEL" => {
33                 this.check_abi(abi, Abi::C { unwind: false })?;
34                 let &[ref result] = check_arg_count(args)?;
35                 let result = this.close(result)?;
36                 this.write_scalar(Scalar::from_i32(result), dest)?;
37             }
38             "stat" | "stat$INODE64" => {
39                 this.check_abi(abi, Abi::C { unwind: false })?;
40                 let &[ref path, ref buf] = check_arg_count(args)?;
41                 let result = this.macos_stat(path, buf)?;
42                 this.write_scalar(Scalar::from_i32(result), dest)?;
43             }
44             "lstat" | "lstat$INODE64" => {
45                 this.check_abi(abi, Abi::C { unwind: false })?;
46                 let &[ref path, ref buf] = check_arg_count(args)?;
47                 let result = this.macos_lstat(path, buf)?;
48                 this.write_scalar(Scalar::from_i32(result), dest)?;
49             }
50             "fstat" | "fstat$INODE64" => {
51                 this.check_abi(abi, Abi::C { unwind: false })?;
52                 let &[ref fd, ref buf] = check_arg_count(args)?;
53                 let result = this.macos_fstat(fd, buf)?;
54                 this.write_scalar(Scalar::from_i32(result), dest)?;
55             }
56             "opendir" | "opendir$INODE64" => {
57                 this.check_abi(abi, Abi::C { unwind: false })?;
58                 let &[ref name] = check_arg_count(args)?;
59                 let result = this.opendir(name)?;
60                 this.write_scalar(result, dest)?;
61             }
62             "readdir_r" | "readdir_r$INODE64" => {
63                 this.check_abi(abi, Abi::C { unwind: false })?;
64                 let &[ref dirp, ref entry, ref result] = check_arg_count(args)?;
65                 let result = this.macos_readdir_r(dirp, entry, result)?;
66                 this.write_scalar(Scalar::from_i32(result), dest)?;
67             }
68             "ftruncate" => {
69                 this.check_abi(abi, Abi::C { unwind: false })?;
70                 let &[ref fd, ref length] = check_arg_count(args)?;
71                 let result = this.ftruncate64(fd, length)?;
72                 this.write_scalar(Scalar::from_i32(result), dest)?;
73             }
74
75             // Environment related shims
76             "_NSGetEnviron" => {
77                 this.check_abi(abi, Abi::C { unwind: false })?;
78                 let &[] = check_arg_count(args)?;
79                 this.write_scalar(this.machine.env_vars.environ.unwrap().ptr, dest)?;
80             }
81
82             // Time related shims
83             "gettimeofday" => {
84                 this.check_abi(abi, Abi::C { unwind: false })?;
85                 let &[ref tv, ref tz] = check_arg_count(args)?;
86                 let result = this.gettimeofday(tv, tz)?;
87                 this.write_scalar(Scalar::from_i32(result), dest)?;
88             }
89             "mach_absolute_time" => {
90                 this.check_abi(abi, Abi::C { unwind: false })?;
91                 let &[] = check_arg_count(args)?;
92                 let result = this.mach_absolute_time()?;
93                 this.write_scalar(Scalar::from_u64(result), dest)?;
94             }
95
96             "mach_timebase_info" => {
97                 this.check_abi(abi, Abi::C { unwind: false })?;
98                 let &[ref info] = check_arg_count(args)?;
99                 let result = this.mach_timebase_info(info)?;
100                 this.write_scalar(Scalar::from_i32(result), dest)?;
101             }
102
103             // Access to command-line arguments
104             "_NSGetArgc" => {
105                 this.check_abi(abi, Abi::C { unwind: false })?;
106                 let &[] = check_arg_count(args)?;
107                 this.write_scalar(this.machine.argc.expect("machine must be initialized"), dest)?;
108             }
109             "_NSGetArgv" => {
110                 this.check_abi(abi, Abi::C { unwind: false })?;
111                 let &[] = check_arg_count(args)?;
112                 this.write_scalar(this.machine.argv.expect("machine must be initialized"), dest)?;
113             }
114
115             // Thread-local storage
116             "_tlv_atexit" => {
117                 this.check_abi(abi, Abi::C { unwind: false })?;
118                 let &[ref dtor, ref data] = check_arg_count(args)?;
119                 let dtor = this.read_scalar(dtor)?.check_init()?;
120                 let dtor = this.memory.get_fn(dtor)?.as_instance()?;
121                 let data = this.read_scalar(data)?.check_init()?;
122                 let active_thread = this.get_active_thread();
123                 this.machine.tls.set_macos_thread_dtor(active_thread, dtor, data)?;
124             }
125
126             // Querying system information
127             "pthread_get_stackaddr_np" => {
128                 this.check_abi(abi, Abi::C { unwind: false })?;
129                 let &[ref thread] = check_arg_count(args)?;
130                 this.read_scalar(thread)?.to_machine_usize(this)?;
131                 let stack_addr = Scalar::from_uint(STACK_ADDR, this.pointer_size());
132                 this.write_scalar(stack_addr, dest)?;
133             }
134             "pthread_get_stacksize_np" => {
135                 this.check_abi(abi, Abi::C { unwind: false })?;
136                 let &[ref thread] = check_arg_count(args)?;
137                 this.read_scalar(thread)?.to_machine_usize(this)?;
138                 let stack_size = Scalar::from_uint(STACK_SIZE, this.pointer_size());
139                 this.write_scalar(stack_size, dest)?;
140             }
141
142             // Threading
143             "pthread_setname_np" => {
144                 this.check_abi(abi, Abi::C { unwind: false })?;
145                 let &[ref name] = check_arg_count(args)?;
146                 let name = this.read_scalar(name)?.check_init()?;
147                 this.pthread_setname_np(name)?;
148             }
149
150             // Incomplete shims that we "stub out" just to get pre-main initialization code to work.
151             // These shims are enabled only when the caller is in the standard library.
152             "mmap" if this.frame().instance.to_string().starts_with("std::sys::unix::") => {
153                 this.check_abi(abi, Abi::C { unwind: false })?;
154                 // This is a horrible hack, but since the guard page mechanism calls mmap and expects a particular return value, we just give it that value.
155                 let &[ref addr, _, _, _, _, _] = check_arg_count(args)?;
156                 let addr = this.read_scalar(addr)?.check_init()?;
157                 this.write_scalar(addr, dest)?;
158             }
159
160             _ => return Ok(EmulateByNameResult::NotSupported),
161         };
162
163         Ok(EmulateByNameResult::NeedsJumping)
164     }
165 }