Skip to content

Commit 958bd01

Browse files
committed
organize Windows shims and limit them to libstd where possible
1 parent eba85a6 commit 958bd01

File tree

3 files changed

+69
-52
lines changed

3 files changed

+69
-52
lines changed

src/shims/foreign_items/posix/linux.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
4242
this.write_scalar(Scalar::from_int(result, dest.layout.size), dest)?;
4343
}
4444

45-
// Thread stack metadata
45+
// Querying system information
4646
"pthread_attr_getstack" => {
4747
// We don't support "pthread_attr_setstack", so we just pretend all stacks have the same values here.
4848
let _attr_place = this.deref_operand(args[0])?;

src/shims/foreign_items/posix/macos.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,15 +60,15 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
6060
this.write_scalar(Scalar::from_uint(result, dest.layout.size), dest)?;
6161
}
6262

63-
// Access to command-line arguments.
63+
// Access to command-line arguments
6464
"_NSGetArgc" => {
6565
this.write_scalar(this.machine.argc.expect("machine must be initialized"), dest)?;
6666
}
6767
"_NSGetArgv" => {
6868
this.write_scalar(this.machine.argv.expect("machine must be initialized"), dest)?;
6969
}
7070

71-
// Thread stack metadata
71+
// Querying system information
7272
"pthread_get_stackaddr_np" => {
7373
let _thread = this.read_scalar(args[0])?.not_undef()?;
7474
let stack_addr = Scalar::from_uint(STACK_ADDR, dest.layout.size);

src/shims/foreign_items/windows.rs

Lines changed: 66 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
1515
let this = self.eval_context_mut();
1616
let tcx = &{ this.tcx.tcx };
1717

18+
// Windows API stubs.
19+
// HANDLE = isize
20+
// DWORD = ULONG = u32
21+
// BOOL = i32
1822
match link_name {
19-
// Windows API stubs.
20-
// HANDLE = isize
21-
// DWORD = ULONG = u32
22-
// BOOL = i32
23-
2423
// Environment related shims
2524
"GetEnvironmentVariableW" => {
2625
// args[0] : LPCWSTR lpName (32-bit ptr to a const string of 16-bit Unicode chars)
@@ -42,6 +41,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
4241
}
4342

4443
// File related shims
44+
"GetStdHandle" => {
45+
let which = this.read_scalar(args[0])?.to_i32()?;
46+
// We just make this the identity function, so we know later in `WriteFile`
47+
// which one it is.
48+
this.write_scalar(Scalar::from_int(which, this.pointer_size()), dest)?;
49+
}
4550
"WriteFile" => {
4651
let handle = this.read_scalar(args[0])?.to_machine_isize(this)?;
4752
let buf = this.read_scalar(args[1])?.not_undef()?;
@@ -61,9 +66,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
6166
};
6267
res.ok().map(|n| n as u32)
6368
} else {
64-
eprintln!("Miri: Ignored output to handle {}", handle);
65-
// Pretend it all went well.
66-
Some(n)
69+
throw_unsup_format!("on Windows, writing to anything except stdout/stderr is not supported")
6770
};
6871
// If there was no error, write back how much was written.
6972
if let Some(n) = written {
@@ -76,11 +79,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
7679
)?;
7780
}
7881

79-
// Other shims
80-
"GetProcessHeap" => {
81-
// Just fake a HANDLE
82-
this.write_scalar(Scalar::from_int(1, this.pointer_size()), dest)?;
83-
}
82+
// Allocation
8483
"HeapAlloc" => {
8584
let _handle = this.read_scalar(args[0])?.to_machine_isize(this)?;
8685
let flags = this.read_scalar(args[1])?.to_u32()?;
@@ -105,6 +104,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
105104
this.write_scalar(res, dest)?;
106105
}
107106

107+
// errno
108108
"SetLastError" => {
109109
this.set_last_error(this.read_scalar(args[0])?.not_undef()?)?;
110110
}
@@ -113,30 +113,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
113113
this.write_scalar(last_error, dest)?;
114114
}
115115

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)?;
119-
}
120-
121-
| "InitializeCriticalSection"
122-
| "EnterCriticalSection"
123-
| "LeaveCriticalSection"
124-
| "DeleteCriticalSection"
125-
=> {
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.)
129-
}
130-
131-
| "GetModuleHandleW"
132-
| "GetProcAddress"
133-
| "GetConsoleScreenBufferInfo"
134-
| "SetConsoleTextAttribute"
135-
=> {
136-
// Pretend these do not exist / nothing happened, by returning zero.
137-
this.write_null(dest)?;
138-
}
139-
116+
// Querying system information
140117
"GetSystemInfo" => {
141118
let system_info = this.deref_operand(args[0])?;
142119
// Initialize with `0`.
@@ -150,6 +127,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
150127
this.write_scalar(Scalar::from_int(NUM_CPUS, dword_size), num_cpus.into())?;
151128
}
152129

130+
// Thread-local storage
153131
"TlsAlloc" => {
154132
// This just creates a key; Windows does not natively support TLS destructors.
155133

@@ -170,33 +148,72 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
170148
// Return success (`1`).
171149
this.write_scalar(Scalar::from_int(1, dest.layout.size), dest)?;
172150
}
173-
"GetStdHandle" => {
174-
let which = this.read_scalar(args[0])?.to_i32()?;
175-
// We just make this the identity function, so we know later in `WriteFile`
176-
// which one it is.
177-
this.write_scalar(Scalar::from_int(which, this.pointer_size()), dest)?;
178-
}
179-
"GetConsoleMode" => {
180-
// Everything is a pipe.
181-
this.write_null(dest)?;
182-
}
151+
152+
// Access to command-line arguments
183153
"GetCommandLineW" => {
184154
this.write_scalar(
185155
this.machine.cmd_line.expect("machine must be initialized"),
186156
dest,
187157
)?;
188158
}
189-
// The actual name of 'RtlGenRandom'
159+
160+
// Miscellaneous
190161
"SystemFunction036" => {
162+
// The actual name of 'RtlGenRandom'
191163
let ptr = this.read_scalar(args[0])?.not_undef()?;
192164
let len = this.read_scalar(args[1])?.to_u32()?;
193165
this.gen_random(ptr, len.into())?;
194166
this.write_scalar(Scalar::from_bool(true), dest)?;
195167
}
196-
// We don't support threading.
168+
"GetConsoleScreenBufferInfo" => {
169+
// `term` needs this, so we fake it.
170+
let _console = this.read_scalar(args[0])?.to_machine_isize(this)?;
171+
let _buffer_info = this.deref_operand(args[1])?;
172+
// Indicate an error.
173+
// FIXME: we should set last_error, but to what?
174+
this.write_null(dest)?;
175+
}
176+
"GetConsoleMode" => {
177+
// Windows "isatty" (in libtest) needs this, so we fake it.
178+
let _console = this.read_scalar(args[0])?.to_machine_isize(this)?;
179+
let _mode = this.deref_operand(args[1])?;
180+
// Indicate an error.
181+
// FIXME: we should set last_error, but to what?
182+
this.write_null(dest)?;
183+
}
184+
185+
// Better error for attempts to create a thread
197186
"CreateThread" => {
198187
throw_unsup_format!("Miri does not support threading");
199188
}
189+
190+
// Incomplete shims that we "stub out" just to get pre-main initialziation code to work.
191+
// These shims are enabled only when the caller is in the standard library.
192+
"GetProcessHeap" if this.frame().instance.to_string().starts_with("std::sys::windows::") => {
193+
// Just fake a HANDLE
194+
this.write_scalar(Scalar::from_int(1, this.pointer_size()), dest)?;
195+
}
196+
| "GetModuleHandleW"
197+
| "GetProcAddress"
198+
| "SetConsoleTextAttribute" if this.frame().instance.to_string().starts_with("std::sys::windows::")
199+
=> {
200+
// Pretend these do not exist / nothing happened, by returning zero.
201+
this.write_null(dest)?;
202+
}
203+
"AddVectoredExceptionHandler" if this.frame().instance.to_string().starts_with("std::sys::windows::") => {
204+
// Any non zero value works for the stdlib. This is just used for stack overflows anyway.
205+
this.write_scalar(Scalar::from_int(1, dest.layout.size), dest)?;
206+
}
207+
| "InitializeCriticalSection"
208+
| "EnterCriticalSection"
209+
| "LeaveCriticalSection"
210+
| "DeleteCriticalSection" if this.frame().instance.to_string().starts_with("std::sys::windows::")
211+
=> {
212+
// Nothing to do, not even a return value.
213+
// (Windows locks are reentrant, and we have only 1 thread,
214+
// so not doing any futher checks here is at least not incorrect.)
215+
}
216+
200217
_ => throw_unsup_format!("can't call foreign function: {}", link_name),
201218
}
202219

0 commit comments

Comments
 (0)