@@ -15,12 +15,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
15
15
let this = self . eval_context_mut ( ) ;
16
16
let tcx = & { this. tcx . tcx } ;
17
17
18
+ // Windows API stubs.
19
+ // HANDLE = isize
20
+ // DWORD = ULONG = u32
21
+ // BOOL = i32
18
22
match link_name {
19
- // Windows API stubs.
20
- // HANDLE = isize
21
- // DWORD = ULONG = u32
22
- // BOOL = i32
23
-
24
23
// Environment related shims
25
24
"GetEnvironmentVariableW" => {
26
25
// 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
42
41
}
43
42
44
43
// 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
+ }
45
50
"WriteFile" => {
46
51
let handle = this. read_scalar ( args[ 0 ] ) ?. to_machine_isize ( this) ?;
47
52
let buf = this. read_scalar ( args[ 1 ] ) ?. not_undef ( ) ?;
@@ -61,9 +66,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
61
66
} ;
62
67
res. ok ( ) . map ( |n| n as u32 )
63
68
} 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" )
67
70
} ;
68
71
// If there was no error, write back how much was written.
69
72
if let Some ( n) = written {
@@ -76,11 +79,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
76
79
) ?;
77
80
}
78
81
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
84
83
"HeapAlloc" => {
85
84
let _handle = this. read_scalar ( args[ 0 ] ) ?. to_machine_isize ( this) ?;
86
85
let flags = this. read_scalar ( args[ 1 ] ) ?. to_u32 ( ) ?;
@@ -105,6 +104,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
105
104
this. write_scalar ( res, dest) ?;
106
105
}
107
106
107
+ // errno
108
108
"SetLastError" => {
109
109
this. set_last_error ( this. read_scalar ( args[ 0 ] ) ?. not_undef ( ) ?) ?;
110
110
}
@@ -113,30 +113,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
113
113
this. write_scalar ( last_error, dest) ?;
114
114
}
115
115
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
140
117
"GetSystemInfo" => {
141
118
let system_info = this. deref_operand ( args[ 0 ] ) ?;
142
119
// Initialize with `0`.
@@ -150,6 +127,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
150
127
this. write_scalar ( Scalar :: from_int ( NUM_CPUS , dword_size) , num_cpus. into ( ) ) ?;
151
128
}
152
129
130
+ // Thread-local storage
153
131
"TlsAlloc" => {
154
132
// This just creates a key; Windows does not natively support TLS destructors.
155
133
@@ -170,33 +148,72 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
170
148
// Return success (`1`).
171
149
this. write_scalar ( Scalar :: from_int ( 1 , dest. layout . size ) , dest) ?;
172
150
}
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
183
153
"GetCommandLineW" => {
184
154
this. write_scalar (
185
155
this. machine . cmd_line . expect ( "machine must be initialized" ) ,
186
156
dest,
187
157
) ?;
188
158
}
189
- // The actual name of 'RtlGenRandom'
159
+
160
+ // Miscellaneous
190
161
"SystemFunction036" => {
162
+ // The actual name of 'RtlGenRandom'
191
163
let ptr = this. read_scalar ( args[ 0 ] ) ?. not_undef ( ) ?;
192
164
let len = this. read_scalar ( args[ 1 ] ) ?. to_u32 ( ) ?;
193
165
this. gen_random ( ptr, len. into ( ) ) ?;
194
166
this. write_scalar ( Scalar :: from_bool ( true ) , dest) ?;
195
167
}
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
197
186
"CreateThread" => {
198
187
throw_unsup_format ! ( "Miri does not support threading" ) ;
199
188
}
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
+
200
217
_ => throw_unsup_format ! ( "can't call foreign function: {}" , link_name) ,
201
218
}
202
219
0 commit comments