3 use rustc::ty::layout::Size;
6 impl<'mir, 'tcx> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {}
7 pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx> {
8 fn emulate_foreign_item_by_name(
11 args: &[OpTy<'tcx, Tag>],
12 dest: PlaceTy<'tcx, Tag>,
13 _ret: mir::BasicBlock,
14 ) -> InterpResult<'tcx, bool> {
15 let this = self.eval_context_mut();
16 let tcx = &{ this.tcx.tcx };
21 // DWORD = ULONG = u32
24 // Environment related shims
25 "GetEnvironmentVariableW" => {
26 // args[0] : LPCWSTR lpName (32-bit ptr to a const string of 16-bit Unicode chars)
27 // args[1] : LPWSTR lpBuffer (32-bit pointer to a string of 16-bit Unicode chars)
28 // lpBuffer : ptr to buffer that receives contents of the env_var as a null-terminated string.
29 // Return `# of chars` stored in the buffer pointed to by lpBuffer, excluding null-terminator.
30 // Return 0 upon failure.
32 // This is not the env var you are looking for.
33 this.set_last_error(Scalar::from_u32(203))?; // ERROR_ENVVAR_NOT_FOUND
34 this.write_null(dest)?;
37 "SetEnvironmentVariableW" => {
38 // args[0] : LPCWSTR lpName (32-bit ptr to a const string of 16-bit Unicode chars)
39 // args[1] : LPCWSTR lpValue (32-bit ptr to a const string of 16-bit Unicode chars)
40 // Return nonzero if success, else return 0.
41 throw_unsup_format!("can't set environment variable on Windows");
46 let handle = this.read_scalar(args[0])?.to_machine_isize(this)?;
47 let buf = this.read_scalar(args[1])?.not_undef()?;
48 let n = this.read_scalar(args[2])?.to_u32()?;
49 let written_place = this.deref_operand(args[3])?;
50 // Spec says to always write `0` first.
51 this.write_null(written_place.into())?;
52 let written = if handle == -11 || handle == -12 {
54 use std::io::{self, Write};
56 let buf_cont = this.memory.read_bytes(buf, Size::from_bytes(u64::from(n)))?;
57 let res = if handle == -11 {
58 io::stdout().write(buf_cont)
60 io::stderr().write(buf_cont)
62 res.ok().map(|n| n as u32)
64 eprintln!("Miri: Ignored output to handle {}", handle);
65 // Pretend it all went well.
68 // If there was no error, write back how much was written.
69 if let Some(n) = written {
70 this.write_scalar(Scalar::from_u32(n), written_place.into())?;
72 // Return whether this was a success.
74 Scalar::from_int(if written.is_some() { 1 } else { 0 }, dest.layout.size),
82 this.write_scalar(Scalar::from_int(1, this.pointer_size()), dest)?;
85 let _handle = this.read_scalar(args[0])?.to_machine_isize(this)?;
86 let flags = this.read_scalar(args[1])?.to_u32()?;
87 let size = this.read_scalar(args[2])?.to_machine_usize(this)?;
88 let zero_init = (flags & 0x00000008) != 0; // HEAP_ZERO_MEMORY
89 let res = this.malloc(size, zero_init, MiriMemoryKind::WinHeap);
90 this.write_scalar(res, dest)?;
93 let _handle = this.read_scalar(args[0])?.to_machine_isize(this)?;
94 let _flags = this.read_scalar(args[1])?.to_u32()?;
95 let ptr = this.read_scalar(args[2])?.not_undef()?;
96 this.free(ptr, MiriMemoryKind::WinHeap)?;
97 this.write_scalar(Scalar::from_int(1, Size::from_bytes(4)), dest)?;
100 let _handle = this.read_scalar(args[0])?.to_machine_isize(this)?;
101 let _flags = this.read_scalar(args[1])?.to_u32()?;
102 let ptr = this.read_scalar(args[2])?.not_undef()?;
103 let size = this.read_scalar(args[3])?.to_machine_usize(this)?;
104 let res = this.realloc(ptr, size, MiriMemoryKind::WinHeap)?;
105 this.write_scalar(res, dest)?;
109 this.set_last_error(this.read_scalar(args[0])?.not_undef()?)?;
112 let last_error = this.get_last_error()?;
113 this.write_scalar(last_error, dest)?;
116 "AddVectoredExceptionHandler" => {
117 // Any non zero value works for the stdlib. This is just used for stack overflows anyway.
118 this.write_scalar(Scalar::from_int(1, dest.layout.size), dest)?;
121 | "InitializeCriticalSection"
122 | "EnterCriticalSection"
123 | "LeaveCriticalSection"
124 | "DeleteCriticalSection"
126 // Nothing to do, not even a return value.
127 // (Windows locks are reentrant, and we have only 1 thread,
128 // so not doing any futher checks here is at least not incorrect.)
133 | "GetConsoleScreenBufferInfo"
134 | "SetConsoleTextAttribute"
136 // Pretend these do not exist / nothing happened, by returning zero.
137 this.write_null(dest)?;
141 let system_info = this.deref_operand(args[0])?;
142 // Initialize with `0`.
143 this.memory.write_bytes(
145 iter::repeat(0u8).take(system_info.layout.size.bytes() as usize),
147 // Set number of processors.
148 let dword_size = Size::from_bytes(4);
149 let num_cpus = this.mplace_field(system_info, 6)?;
150 this.write_scalar(Scalar::from_int(NUM_CPUS, dword_size), num_cpus.into())?;
154 // This just creates a key; Windows does not natively support TLS destructors.
156 // Create key and return it.
157 let key = this.machine.tls.create_tls_key(None) as u128;
159 // Figure out how large a TLS key actually is. This is `c::DWORD`.
160 if dest.layout.size.bits() < 128
161 && key >= (1u128 << dest.layout.size.bits() as u128)
163 throw_unsup!(OutOfTls);
165 this.write_scalar(Scalar::from_uint(key, dest.layout.size), dest)?;
168 let key = u128::from(this.read_scalar(args[0])?.to_u32()?);
169 let ptr = this.machine.tls.load_tls(key, tcx)?;
170 this.write_scalar(ptr, dest)?;
173 let key = u128::from(this.read_scalar(args[0])?.to_u32()?);
174 let new_ptr = this.read_scalar(args[1])?.not_undef()?;
175 this.machine.tls.store_tls(key, this.test_null(new_ptr)?)?;
177 // Return success (`1`).
178 this.write_scalar(Scalar::from_int(1, dest.layout.size), dest)?;
181 let which = this.read_scalar(args[0])?.to_i32()?;
182 // We just make this the identity function, so we know later in `WriteFile`
184 this.write_scalar(Scalar::from_int(which, this.pointer_size()), dest)?;
186 "GetConsoleMode" => {
187 // Everything is a pipe.
188 this.write_null(dest)?;
190 "GetCommandLineW" => {
192 this.machine.cmd_line.expect("machine must be initialized"),
196 // The actual name of 'RtlGenRandom'
197 "SystemFunction036" => {
198 let ptr = this.read_scalar(args[0])?.not_undef()?;
199 let len = this.read_scalar(args[1])?.to_u32()?;
200 this.gen_random(ptr, len.into())?;
201 this.write_scalar(Scalar::from_bool(true), dest)?;
203 // We don't support threading.
205 throw_unsup_format!("Miri does not support threading");
207 _ => throw_unsup_format!("can't call foreign function: {}", link_name),