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 let result = this.GetEnvironmentVariableW(args[0], args[1], args[2])?;
27 this.write_scalar(Scalar::from_uint(result, dest.layout.size), dest)?;
30 "SetEnvironmentVariableW" => {
31 let result = this.SetEnvironmentVariableW(args[0], args[1])?;
32 this.write_scalar(Scalar::from_int(result, dest.layout.size), dest)?;
35 "GetEnvironmentStringsW" => {
36 let result = this.GetEnvironmentStringsW()?;
37 this.write_scalar(result, dest)?;
40 "FreeEnvironmentStringsW" => {
41 let result = this.FreeEnvironmentStringsW(args[0])?;
42 this.write_scalar(Scalar::from_i32(result), dest)?;
47 let handle = this.read_scalar(args[0])?.to_machine_isize(this)?;
48 let buf = this.read_scalar(args[1])?.not_undef()?;
49 let n = this.read_scalar(args[2])?.to_u32()?;
50 let written_place = this.deref_operand(args[3])?;
51 // Spec says to always write `0` first.
52 this.write_null(written_place.into())?;
53 let written = if handle == -11 || handle == -12 {
55 use std::io::{self, Write};
57 let buf_cont = this.memory.read_bytes(buf, Size::from_bytes(u64::from(n)))?;
58 let res = if handle == -11 {
59 io::stdout().write(buf_cont)
61 io::stderr().write(buf_cont)
63 res.ok().map(|n| n as u32)
65 eprintln!("Miri: Ignored output to handle {}", handle);
66 // Pretend it all went well.
69 // If there was no error, write back how much was written.
70 if let Some(n) = written {
71 this.write_scalar(Scalar::from_u32(n), written_place.into())?;
73 // Return whether this was a success.
75 Scalar::from_int(if written.is_some() { 1 } else { 0 }, dest.layout.size),
83 this.write_scalar(Scalar::from_int(1, this.pointer_size()), dest)?;
86 let _handle = this.read_scalar(args[0])?.to_machine_isize(this)?;
87 let flags = this.read_scalar(args[1])?.to_u32()?;
88 let size = this.read_scalar(args[2])?.to_machine_usize(this)?;
89 let zero_init = (flags & 0x00000008) != 0; // HEAP_ZERO_MEMORY
90 let res = this.malloc(size, zero_init, MiriMemoryKind::WinHeap);
91 this.write_scalar(res, dest)?;
94 let _handle = this.read_scalar(args[0])?.to_machine_isize(this)?;
95 let _flags = this.read_scalar(args[1])?.to_u32()?;
96 let ptr = this.read_scalar(args[2])?.not_undef()?;
97 this.free(ptr, MiriMemoryKind::WinHeap)?;
98 this.write_scalar(Scalar::from_int(1, Size::from_bytes(4)), dest)?;
101 let _handle = this.read_scalar(args[0])?.to_machine_isize(this)?;
102 let _flags = this.read_scalar(args[1])?.to_u32()?;
103 let ptr = this.read_scalar(args[2])?.not_undef()?;
104 let size = this.read_scalar(args[3])?.to_machine_usize(this)?;
105 let res = this.realloc(ptr, size, MiriMemoryKind::WinHeap)?;
106 this.write_scalar(res, dest)?;
110 this.set_last_error(this.read_scalar(args[0])?.not_undef()?)?;
113 let last_error = this.get_last_error()?;
114 this.write_scalar(last_error, dest)?;
117 "AddVectoredExceptionHandler" => {
118 // Any non zero value works for the stdlib. This is just used for stack overflows anyway.
119 this.write_scalar(Scalar::from_int(1, dest.layout.size), dest)?;
122 | "InitializeCriticalSection"
123 | "EnterCriticalSection"
124 | "LeaveCriticalSection"
125 | "DeleteCriticalSection"
127 // Nothing to do, not even a return value.
128 // (Windows locks are reentrant, and we have only 1 thread,
129 // so not doing any futher checks here is at least not incorrect.)
134 | "GetConsoleScreenBufferInfo"
135 | "SetConsoleTextAttribute"
137 // Pretend these do not exist / nothing happened, by returning zero.
138 this.write_null(dest)?;
142 let system_info = this.deref_operand(args[0])?;
143 // Initialize with `0`.
144 this.memory.write_bytes(
146 iter::repeat(0u8).take(system_info.layout.size.bytes() as usize),
148 // Set number of processors.
149 let dword_size = Size::from_bytes(4);
150 let num_cpus = this.mplace_field(system_info, 6)?;
151 this.write_scalar(Scalar::from_int(NUM_CPUS, dword_size), num_cpus.into())?;
155 // This just creates a key; Windows does not natively support TLS destructors.
157 // Create key and return it.
158 let key = this.machine.tls.create_tls_key(None, dest.layout.size)?;
159 this.write_scalar(Scalar::from_uint(key, dest.layout.size), dest)?;
162 let key = u128::from(this.read_scalar(args[0])?.to_u32()?);
163 let ptr = this.machine.tls.load_tls(key, tcx)?;
164 this.write_scalar(ptr, dest)?;
167 let key = u128::from(this.read_scalar(args[0])?.to_u32()?);
168 let new_ptr = this.read_scalar(args[1])?.not_undef()?;
169 this.machine.tls.store_tls(key, this.test_null(new_ptr)?)?;
171 // Return success (`1`).
172 this.write_scalar(Scalar::from_int(1, dest.layout.size), dest)?;
175 let which = this.read_scalar(args[0])?.to_i32()?;
176 // We just make this the identity function, so we know later in `WriteFile`
178 this.write_scalar(Scalar::from_int(which, this.pointer_size()), dest)?;
180 "GetConsoleMode" => {
181 // Everything is a pipe.
182 this.write_null(dest)?;
184 "GetCommandLineW" => {
186 this.machine.cmd_line.expect("machine must be initialized"),
190 // The actual name of 'RtlGenRandom'
191 "SystemFunction036" => {
192 let ptr = this.read_scalar(args[0])?.not_undef()?;
193 let len = this.read_scalar(args[1])?.to_u32()?;
194 this.gen_random(ptr, len.into())?;
195 this.write_scalar(Scalar::from_bool(true), dest)?;
197 // We don't support threading.
199 throw_unsup_format!("Miri does not support threading");
201 _ => throw_unsup_format!("can't call foreign function: {}", link_name),