Convert Windows to use check_shim_sig instead of check_shim_sig_lenient
This commit is contained in:
parent
ff2acf0eca
commit
c5f67830c2
4 changed files with 497 additions and 129 deletions
|
|
@ -17,11 +17,14 @@ pub struct ShimSig<'tcx, const ARGS: usize> {
|
|||
|
||||
/// Construct a `ShimSig` with convenient syntax:
|
||||
/// ```rust,ignore
|
||||
/// shim_sig!(this, extern "C" fn (*const T, i32) -> usize)
|
||||
/// shim_sig!(extern "C" fn (*const T, i32) -> usize)
|
||||
/// ```
|
||||
///
|
||||
/// In type position, `winapi::` can be used as a shorthand for the full path used by
|
||||
/// `windows_ty_layout`.
|
||||
#[macro_export]
|
||||
macro_rules! shim_sig {
|
||||
(extern $abi:literal fn($($arg:ty),*) -> $ret:ty) => {
|
||||
(extern $abi:literal fn($($arg:ty),* $(,)?) -> $ret:ty) => {
|
||||
|this| $crate::shims::sig::ShimSig {
|
||||
abi: std::str::FromStr::from_str($abi).expect("incorrect abi specified"),
|
||||
args: [$(shim_sig_arg!(this, $arg)),*],
|
||||
|
|
@ -53,7 +56,9 @@ macro_rules! shim_sig_arg {
|
|||
"*const _" => $this.machine.layouts.const_raw_ptr.ty,
|
||||
"*mut _" => $this.machine.layouts.mut_raw_ptr.ty,
|
||||
ty if let Some(libc_ty) = ty.strip_prefix("libc::") => $this.libc_ty_layout(libc_ty).ty,
|
||||
ty => panic!("unsupported signature type {ty:?}"),
|
||||
ty if let Some(win_ty) = ty.strip_prefix("winapi::") =>
|
||||
$this.windows_ty_layout(win_ty).ty,
|
||||
ty => helpers::path_ty_layout($this, &ty.split("::").collect::<Vec<_>>()).ty,
|
||||
}
|
||||
}};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,11 +2,11 @@ use std::ffi::OsStr;
|
|||
use std::path::{self, Path, PathBuf};
|
||||
use std::{io, iter, str};
|
||||
|
||||
use rustc_abi::{Align, CanonAbi, Size, X86Call};
|
||||
use rustc_abi::{Align, Size};
|
||||
use rustc_middle::ty::Ty;
|
||||
use rustc_span::Symbol;
|
||||
use rustc_target::callconv::FnAbi;
|
||||
use rustc_target::spec::{Arch, Env};
|
||||
use rustc_target::spec::Env;
|
||||
|
||||
use self::shims::windows::handle::{Handle, PseudoHandle};
|
||||
use crate::shims::os_str::bytes_to_os_str;
|
||||
|
|
@ -137,65 +137,93 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
|||
) -> InterpResult<'tcx, EmulateItemResult> {
|
||||
let this = self.eval_context_mut();
|
||||
|
||||
// According to
|
||||
// https://github.com/rust-lang/rust/blob/fb00adbdb69266f10df95a4527b767b0ad35ea48/compiler/rustc_target/src/spec/mod.rs#L2766-L2768,
|
||||
// x86-32 Windows uses a different calling convention than other Windows targets
|
||||
// for the "system" ABI.
|
||||
let sys_conv = if this.tcx.sess.target.arch == Arch::X86 {
|
||||
CanonAbi::X86(X86Call::Stdcall)
|
||||
} else {
|
||||
CanonAbi::C
|
||||
};
|
||||
|
||||
// See `fn emulate_foreign_item_inner` in `shims/foreign_items.rs` for the general pattern.
|
||||
|
||||
// Windows API stubs.
|
||||
// HANDLE = isize
|
||||
// NTSTATUS = LONH = i32
|
||||
// HANDLE = *mut c_void (formerly: isize)
|
||||
// NTSTATUS = LONG = i32
|
||||
// DWORD = ULONG = u32
|
||||
// BOOL = i32
|
||||
// BOOLEAN = u8
|
||||
match link_name.as_str() {
|
||||
// Environment related shims
|
||||
"GetEnvironmentVariableW" => {
|
||||
let [name, buf, size] =
|
||||
this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?;
|
||||
let [name, buf, size] = this.check_shim_sig(
|
||||
shim_sig!(extern "system" fn(*const _, *mut _, u32) -> u32),
|
||||
link_name,
|
||||
abi,
|
||||
args,
|
||||
)?;
|
||||
let result = this.GetEnvironmentVariableW(name, buf, size)?;
|
||||
this.write_scalar(result, dest)?;
|
||||
}
|
||||
"SetEnvironmentVariableW" => {
|
||||
let [name, value] = this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?;
|
||||
let [name, value] = this.check_shim_sig(
|
||||
shim_sig!(extern "system" fn(*const _, *const _) -> winapi::BOOL),
|
||||
link_name,
|
||||
abi,
|
||||
args,
|
||||
)?;
|
||||
let result = this.SetEnvironmentVariableW(name, value)?;
|
||||
this.write_scalar(result, dest)?;
|
||||
}
|
||||
"GetEnvironmentStringsW" => {
|
||||
let [] = this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?;
|
||||
let [] = this.check_shim_sig(
|
||||
shim_sig!(extern "system" fn() -> *mut _),
|
||||
link_name,
|
||||
abi,
|
||||
args,
|
||||
)?;
|
||||
let result = this.GetEnvironmentStringsW()?;
|
||||
this.write_pointer(result, dest)?;
|
||||
}
|
||||
"FreeEnvironmentStringsW" => {
|
||||
let [env_block] = this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?;
|
||||
let [env_block] = this.check_shim_sig(
|
||||
shim_sig!(extern "system" fn(*mut _) -> winapi::BOOL),
|
||||
link_name,
|
||||
abi,
|
||||
args,
|
||||
)?;
|
||||
let result = this.FreeEnvironmentStringsW(env_block)?;
|
||||
this.write_scalar(result, dest)?;
|
||||
}
|
||||
"GetCurrentDirectoryW" => {
|
||||
let [size, buf] = this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?;
|
||||
let [size, buf] = this.check_shim_sig(
|
||||
shim_sig!(extern "system" fn(u32, *mut _) -> u32),
|
||||
link_name,
|
||||
abi,
|
||||
args,
|
||||
)?;
|
||||
let result = this.GetCurrentDirectoryW(size, buf)?;
|
||||
this.write_scalar(result, dest)?;
|
||||
}
|
||||
"SetCurrentDirectoryW" => {
|
||||
let [path] = this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?;
|
||||
let [path] = this.check_shim_sig(
|
||||
shim_sig!(extern "system" fn(*const _) -> winapi::BOOL),
|
||||
link_name,
|
||||
abi,
|
||||
args,
|
||||
)?;
|
||||
let result = this.SetCurrentDirectoryW(path)?;
|
||||
this.write_scalar(result, dest)?;
|
||||
}
|
||||
"GetUserProfileDirectoryW" => {
|
||||
let [token, buf, size] =
|
||||
this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?;
|
||||
let [token, buf, size] = this.check_shim_sig(
|
||||
shim_sig!(extern "system" fn(winapi::HANDLE, *mut _, *mut _) -> winapi::BOOL),
|
||||
link_name,
|
||||
abi,
|
||||
args,
|
||||
)?;
|
||||
let result = this.GetUserProfileDirectoryW(token, buf, size)?;
|
||||
this.write_scalar(result, dest)?;
|
||||
}
|
||||
"GetCurrentProcessId" => {
|
||||
let [] = this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?;
|
||||
let [] = this.check_shim_sig(
|
||||
shim_sig!(extern "system" fn() -> u32),
|
||||
link_name,
|
||||
abi,
|
||||
args,
|
||||
)?;
|
||||
let result = this.GetCurrentProcessId()?;
|
||||
this.write_scalar(result, dest)?;
|
||||
}
|
||||
|
|
@ -212,7 +240,24 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
|||
n,
|
||||
byte_offset,
|
||||
key,
|
||||
] = this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?;
|
||||
] = this.check_shim_sig(
|
||||
shim_sig!(
|
||||
extern "system" fn(
|
||||
winapi::HANDLE,
|
||||
winapi::HANDLE,
|
||||
*mut _,
|
||||
*mut _,
|
||||
*mut _,
|
||||
*mut _,
|
||||
u32,
|
||||
*mut _,
|
||||
*mut _,
|
||||
) -> i32
|
||||
),
|
||||
link_name,
|
||||
abi,
|
||||
args,
|
||||
)?;
|
||||
this.NtWriteFile(
|
||||
handle,
|
||||
event,
|
||||
|
|
@ -237,7 +282,24 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
|||
n,
|
||||
byte_offset,
|
||||
key,
|
||||
] = this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?;
|
||||
] = this.check_shim_sig(
|
||||
shim_sig!(
|
||||
extern "system" fn(
|
||||
winapi::HANDLE,
|
||||
winapi::HANDLE,
|
||||
*mut _,
|
||||
*mut _,
|
||||
*mut _,
|
||||
*mut _,
|
||||
u32,
|
||||
*mut _,
|
||||
*mut _,
|
||||
) -> i32
|
||||
),
|
||||
link_name,
|
||||
abi,
|
||||
args,
|
||||
)?;
|
||||
this.NtReadFile(
|
||||
handle,
|
||||
event,
|
||||
|
|
@ -252,8 +314,12 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
|||
)?;
|
||||
}
|
||||
"GetFullPathNameW" => {
|
||||
let [filename, size, buffer, filepart] =
|
||||
this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?;
|
||||
let [filename, size, buffer, filepart] = this.check_shim_sig(
|
||||
shim_sig!(extern "system" fn(*const _, u32, *mut _, *mut _) -> u32),
|
||||
link_name,
|
||||
abi,
|
||||
args,
|
||||
)?;
|
||||
this.check_no_isolation("`GetFullPathNameW`")?;
|
||||
|
||||
let filename = this.read_pointer(filename)?;
|
||||
|
|
@ -290,7 +356,22 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
|||
creation_disposition,
|
||||
flags_and_attributes,
|
||||
template_file,
|
||||
] = this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?;
|
||||
] = this.check_shim_sig(
|
||||
shim_sig!(
|
||||
extern "system" fn(
|
||||
*const _,
|
||||
u32,
|
||||
u32,
|
||||
*mut _,
|
||||
u32,
|
||||
u32,
|
||||
winapi::HANDLE,
|
||||
) -> winapi::HANDLE
|
||||
),
|
||||
link_name,
|
||||
abi,
|
||||
args,
|
||||
)?;
|
||||
let handle = this.CreateFileW(
|
||||
file_name,
|
||||
desired_access,
|
||||
|
|
@ -303,29 +384,60 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
|||
this.write_scalar(handle.to_scalar(this), dest)?;
|
||||
}
|
||||
"GetFileInformationByHandle" => {
|
||||
let [handle, info] = this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?;
|
||||
let [handle, info] = this.check_shim_sig(
|
||||
shim_sig!(extern "system" fn(winapi::HANDLE, *mut _) -> winapi::BOOL),
|
||||
link_name,
|
||||
abi,
|
||||
args,
|
||||
)?;
|
||||
let res = this.GetFileInformationByHandle(handle, info)?;
|
||||
this.write_scalar(res, dest)?;
|
||||
}
|
||||
"SetFileInformationByHandle" => {
|
||||
let [handle, class, info, size] =
|
||||
this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?;
|
||||
let [handle, class, info, size] = this.check_shim_sig(
|
||||
shim_sig!(
|
||||
extern "system" fn(
|
||||
winapi::HANDLE,
|
||||
winapi::FILE_INFO_BY_HANDLE_CLASS,
|
||||
*mut _,
|
||||
u32,
|
||||
) -> winapi::BOOL
|
||||
),
|
||||
link_name,
|
||||
abi,
|
||||
args,
|
||||
)?;
|
||||
let res = this.SetFileInformationByHandle(handle, class, info, size)?;
|
||||
this.write_scalar(res, dest)?;
|
||||
}
|
||||
"FlushFileBuffers" => {
|
||||
let [handle] = this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?;
|
||||
let [handle] = this.check_shim_sig(
|
||||
shim_sig!(extern "system" fn(winapi::HANDLE) -> winapi::BOOL),
|
||||
link_name,
|
||||
abi,
|
||||
args,
|
||||
)?;
|
||||
let res = this.FlushFileBuffers(handle)?;
|
||||
this.write_scalar(res, dest)?;
|
||||
}
|
||||
"DeleteFileW" => {
|
||||
let [file_name] = this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?;
|
||||
let [file_name] = this.check_shim_sig(
|
||||
shim_sig!(extern "system" fn(*const _) -> winapi::BOOL),
|
||||
link_name,
|
||||
abi,
|
||||
args,
|
||||
)?;
|
||||
let res = this.DeleteFileW(file_name)?;
|
||||
this.write_scalar(res, dest)?;
|
||||
}
|
||||
"SetFilePointerEx" => {
|
||||
let [file, distance_to_move, new_file_pointer, move_method] =
|
||||
this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?;
|
||||
let [file, distance_to_move, new_file_pointer, move_method] = this.check_shim_sig(
|
||||
// i64 is actually a LARGE_INTEGER union of {u32, i32} and {i64}
|
||||
shim_sig!(extern "system" fn(winapi::HANDLE, i64, *mut _, u32) -> winapi::BOOL),
|
||||
link_name,
|
||||
abi,
|
||||
args,
|
||||
)?;
|
||||
let res =
|
||||
this.SetFilePointerEx(file, distance_to_move, new_file_pointer, move_method)?;
|
||||
this.write_scalar(res, dest)?;
|
||||
|
|
@ -333,8 +445,12 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
|||
|
||||
// Allocation
|
||||
"HeapAlloc" => {
|
||||
let [handle, flags, size] =
|
||||
this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?;
|
||||
let [handle, flags, size] = this.check_shim_sig(
|
||||
shim_sig!(extern "system" fn(winapi::HANDLE, u32, usize) -> *mut _),
|
||||
link_name,
|
||||
abi,
|
||||
args,
|
||||
)?;
|
||||
this.read_target_isize(handle)?;
|
||||
let flags = this.read_scalar(flags)?.to_u32()?;
|
||||
let size = this.read_target_usize(size)?;
|
||||
|
|
@ -356,8 +472,12 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
|||
this.write_pointer(ptr, dest)?;
|
||||
}
|
||||
"HeapFree" => {
|
||||
let [handle, flags, ptr] =
|
||||
this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?;
|
||||
let [handle, flags, ptr] = this.check_shim_sig(
|
||||
shim_sig!(extern "system" fn(winapi::HANDLE, u32, *mut _) -> winapi::BOOL),
|
||||
link_name,
|
||||
abi,
|
||||
args,
|
||||
)?;
|
||||
this.read_target_isize(handle)?;
|
||||
this.read_scalar(flags)?.to_u32()?;
|
||||
let ptr = this.read_pointer(ptr)?;
|
||||
|
|
@ -369,8 +489,12 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
|||
this.write_scalar(Scalar::from_i32(1), dest)?;
|
||||
}
|
||||
"HeapReAlloc" => {
|
||||
let [handle, flags, old_ptr, size] =
|
||||
this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?;
|
||||
let [handle, flags, old_ptr, size] = this.check_shim_sig(
|
||||
shim_sig!(extern "system" fn(winapi::HANDLE, u32, *mut _, usize) -> *mut _),
|
||||
link_name,
|
||||
abi,
|
||||
args,
|
||||
)?;
|
||||
this.read_target_isize(handle)?;
|
||||
this.read_scalar(flags)?.to_u32()?;
|
||||
let old_ptr = this.read_pointer(old_ptr)?;
|
||||
|
|
@ -390,7 +514,12 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
|||
this.write_pointer(new_ptr, dest)?;
|
||||
}
|
||||
"LocalFree" => {
|
||||
let [ptr] = this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?;
|
||||
let [ptr] = this.check_shim_sig(
|
||||
shim_sig!(extern "system" fn(winapi::HLOCAL) -> winapi::HLOCAL),
|
||||
link_name,
|
||||
abi,
|
||||
args,
|
||||
)?;
|
||||
let ptr = this.read_pointer(ptr)?;
|
||||
// "If the hMem parameter is NULL, LocalFree ignores the parameter and returns NULL."
|
||||
// (https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-localfree)
|
||||
|
|
@ -402,17 +531,32 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
|||
|
||||
// errno
|
||||
"SetLastError" => {
|
||||
let [error] = this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?;
|
||||
let [error] = this.check_shim_sig(
|
||||
shim_sig!(extern "system" fn(u32) -> ()),
|
||||
link_name,
|
||||
abi,
|
||||
args,
|
||||
)?;
|
||||
let error = this.read_scalar(error)?;
|
||||
this.set_last_error(error)?;
|
||||
}
|
||||
"GetLastError" => {
|
||||
let [] = this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?;
|
||||
let [] = this.check_shim_sig(
|
||||
shim_sig!(extern "system" fn() -> u32),
|
||||
link_name,
|
||||
abi,
|
||||
args,
|
||||
)?;
|
||||
let last_error = this.get_last_error()?;
|
||||
this.write_scalar(last_error, dest)?;
|
||||
}
|
||||
"RtlNtStatusToDosError" => {
|
||||
let [status] = this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?;
|
||||
let [status] = this.check_shim_sig(
|
||||
shim_sig!(extern "system" fn(i32) -> u32),
|
||||
link_name,
|
||||
abi,
|
||||
args,
|
||||
)?;
|
||||
let status = this.read_scalar(status)?.to_u32()?;
|
||||
let err = match status {
|
||||
// STATUS_MEDIA_WRITE_PROTECTED => ERROR_WRITE_PROTECT
|
||||
|
|
@ -434,7 +578,12 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
|||
// Querying system information
|
||||
"GetSystemInfo" => {
|
||||
// Also called from `page_size` crate.
|
||||
let [system_info] = this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?;
|
||||
let [system_info] = this.check_shim_sig(
|
||||
shim_sig!(extern "system" fn(*mut _) -> ()),
|
||||
link_name,
|
||||
abi,
|
||||
args,
|
||||
)?;
|
||||
let system_info =
|
||||
this.deref_pointer_as(system_info, this.windows_ty_layout("SYSTEM_INFO"))?;
|
||||
// Initialize with `0`.
|
||||
|
|
@ -457,19 +606,34 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
|||
// This just creates a key; Windows does not natively support TLS destructors.
|
||||
|
||||
// Create key and return it.
|
||||
let [] = this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?;
|
||||
let [] = this.check_shim_sig(
|
||||
shim_sig!(extern "system" fn() -> u32),
|
||||
link_name,
|
||||
abi,
|
||||
args,
|
||||
)?;
|
||||
let key = this.machine.tls.create_tls_key(None, dest.layout.size)?;
|
||||
this.write_scalar(Scalar::from_uint(key, dest.layout.size), dest)?;
|
||||
}
|
||||
"TlsGetValue" => {
|
||||
let [key] = this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?;
|
||||
let [key] = this.check_shim_sig(
|
||||
shim_sig!(extern "system" fn(u32) -> *mut _),
|
||||
link_name,
|
||||
abi,
|
||||
args,
|
||||
)?;
|
||||
let key = u128::from(this.read_scalar(key)?.to_u32()?);
|
||||
let active_thread = this.active_thread();
|
||||
let ptr = this.machine.tls.load_tls(key, active_thread, this)?;
|
||||
this.write_scalar(ptr, dest)?;
|
||||
}
|
||||
"TlsSetValue" => {
|
||||
let [key, new_ptr] = this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?;
|
||||
let [key, new_ptr] = this.check_shim_sig(
|
||||
shim_sig!(extern "system" fn(u32, *mut _) -> winapi::BOOL),
|
||||
link_name,
|
||||
abi,
|
||||
args,
|
||||
)?;
|
||||
let key = u128::from(this.read_scalar(key)?.to_u32()?);
|
||||
let active_thread = this.active_thread();
|
||||
let new_data = this.read_scalar(new_ptr)?;
|
||||
|
|
@ -479,7 +643,12 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
|||
this.write_int(1, dest)?;
|
||||
}
|
||||
"TlsFree" => {
|
||||
let [key] = this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?;
|
||||
let [key] = this.check_shim_sig(
|
||||
shim_sig!(extern "system" fn(u32) -> winapi::BOOL),
|
||||
link_name,
|
||||
abi,
|
||||
args,
|
||||
)?;
|
||||
let key = u128::from(this.read_scalar(key)?.to_u32()?);
|
||||
this.machine.tls.delete_tls_key(key)?;
|
||||
|
||||
|
|
@ -489,7 +658,12 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
|||
|
||||
// Access to command-line arguments
|
||||
"GetCommandLineW" => {
|
||||
let [] = this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?;
|
||||
let [] = this.check_shim_sig(
|
||||
shim_sig!(extern "system" fn() -> *mut _),
|
||||
link_name,
|
||||
abi,
|
||||
args,
|
||||
)?;
|
||||
this.write_pointer(
|
||||
this.machine.cmd_line.expect("machine must be initialized"),
|
||||
dest,
|
||||
|
|
@ -498,31 +672,51 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
|||
|
||||
// Time related shims
|
||||
"GetSystemTimeAsFileTime" | "GetSystemTimePreciseAsFileTime" => {
|
||||
#[allow(non_snake_case)]
|
||||
let [LPFILETIME] = this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?;
|
||||
this.GetSystemTimeAsFileTime(link_name.as_str(), LPFILETIME)?;
|
||||
let [filetime] = this.check_shim_sig(
|
||||
shim_sig!(extern "system" fn(*mut _) -> ()),
|
||||
link_name,
|
||||
abi,
|
||||
args,
|
||||
)?;
|
||||
this.GetSystemTimeAsFileTime(link_name.as_str(), filetime)?;
|
||||
}
|
||||
"QueryPerformanceCounter" => {
|
||||
#[allow(non_snake_case)]
|
||||
let [lpPerformanceCount] =
|
||||
this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?;
|
||||
let result = this.QueryPerformanceCounter(lpPerformanceCount)?;
|
||||
let [performance_count] = this.check_shim_sig(
|
||||
shim_sig!(extern "system" fn(*mut _) -> winapi::BOOL),
|
||||
link_name,
|
||||
abi,
|
||||
args,
|
||||
)?;
|
||||
let result = this.QueryPerformanceCounter(performance_count)?;
|
||||
this.write_scalar(result, dest)?;
|
||||
}
|
||||
"QueryPerformanceFrequency" => {
|
||||
#[allow(non_snake_case)]
|
||||
let [lpFrequency] = this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?;
|
||||
let result = this.QueryPerformanceFrequency(lpFrequency)?;
|
||||
let [frequency] = this.check_shim_sig(
|
||||
shim_sig!(extern "system" fn(*mut _) -> winapi::BOOL),
|
||||
link_name,
|
||||
abi,
|
||||
args,
|
||||
)?;
|
||||
let result = this.QueryPerformanceFrequency(frequency)?;
|
||||
this.write_scalar(result, dest)?;
|
||||
}
|
||||
"Sleep" => {
|
||||
let [timeout] = this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?;
|
||||
let [timeout] = this.check_shim_sig(
|
||||
shim_sig!(extern "system" fn(u32) -> ()),
|
||||
link_name,
|
||||
abi,
|
||||
args,
|
||||
)?;
|
||||
|
||||
this.Sleep(timeout)?;
|
||||
}
|
||||
"CreateWaitableTimerExW" => {
|
||||
let [attributes, name, flags, access] =
|
||||
this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?;
|
||||
let [attributes, name, flags, access] = this.check_shim_sig(
|
||||
shim_sig!(extern "system" fn(*mut _, *const _, u32, u32) -> winapi::HANDLE),
|
||||
link_name,
|
||||
abi,
|
||||
args,
|
||||
)?;
|
||||
this.read_pointer(attributes)?;
|
||||
this.read_pointer(name)?;
|
||||
this.read_scalar(flags)?.to_u32()?;
|
||||
|
|
@ -535,40 +729,66 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
|||
|
||||
// Synchronization primitives
|
||||
"InitOnceBeginInitialize" => {
|
||||
let [ptr, flags, pending, context] =
|
||||
this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?;
|
||||
let [ptr, flags, pending, context] = this.check_shim_sig(
|
||||
shim_sig!(extern "system" fn(*mut _, u32, *mut _, *mut _) -> winapi::BOOL),
|
||||
link_name,
|
||||
abi,
|
||||
args,
|
||||
)?;
|
||||
this.InitOnceBeginInitialize(ptr, flags, pending, context, dest)?;
|
||||
}
|
||||
"InitOnceComplete" => {
|
||||
let [ptr, flags, context] =
|
||||
this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?;
|
||||
let [ptr, flags, context] = this.check_shim_sig(
|
||||
shim_sig!(extern "system" fn(*mut _, u32, *mut _) -> winapi::BOOL),
|
||||
link_name,
|
||||
abi,
|
||||
args,
|
||||
)?;
|
||||
let result = this.InitOnceComplete(ptr, flags, context)?;
|
||||
this.write_scalar(result, dest)?;
|
||||
}
|
||||
"WaitOnAddress" => {
|
||||
let [ptr_op, compare_op, size_op, timeout_op] =
|
||||
this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?;
|
||||
let [ptr_op, compare_op, size_op, timeout_op] = this.check_shim_sig(
|
||||
// First pointer is volatile
|
||||
shim_sig!(extern "system" fn(*mut _, *mut _, usize, u32) -> winapi::BOOL),
|
||||
link_name,
|
||||
abi,
|
||||
args,
|
||||
)?;
|
||||
|
||||
this.WaitOnAddress(ptr_op, compare_op, size_op, timeout_op, dest)?;
|
||||
}
|
||||
"WakeByAddressSingle" => {
|
||||
let [ptr_op] = this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?;
|
||||
let [ptr_op] = this.check_shim_sig(
|
||||
shim_sig!(extern "system" fn(*mut _) -> ()),
|
||||
link_name,
|
||||
abi,
|
||||
args,
|
||||
)?;
|
||||
|
||||
this.WakeByAddressSingle(ptr_op)?;
|
||||
}
|
||||
"WakeByAddressAll" => {
|
||||
let [ptr_op] = this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?;
|
||||
let [ptr_op] = this.check_shim_sig(
|
||||
shim_sig!(extern "system" fn(*mut _) -> ()),
|
||||
link_name,
|
||||
abi,
|
||||
args,
|
||||
)?;
|
||||
|
||||
this.WakeByAddressAll(ptr_op)?;
|
||||
}
|
||||
|
||||
// Dynamic symbol loading
|
||||
"GetProcAddress" => {
|
||||
#[allow(non_snake_case)]
|
||||
let [hModule, lpProcName] =
|
||||
this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?;
|
||||
this.read_target_isize(hModule)?;
|
||||
let name = this.read_c_str(this.read_pointer(lpProcName)?)?;
|
||||
let [module, proc_name] = this.check_shim_sig(
|
||||
shim_sig!(extern "system" fn(winapi::HMODULE, *const _) -> winapi::FARPROC),
|
||||
link_name,
|
||||
abi,
|
||||
args,
|
||||
)?;
|
||||
this.read_target_isize(module)?;
|
||||
let name = this.read_c_str(this.read_pointer(proc_name)?)?;
|
||||
if let Ok(name) = str::from_utf8(name)
|
||||
&& is_dyn_sym(name)
|
||||
{
|
||||
|
|
@ -581,8 +801,21 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
|||
|
||||
// Threading
|
||||
"CreateThread" => {
|
||||
let [security, stacksize, start, arg, flags, thread] =
|
||||
this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?;
|
||||
let [security, stacksize, start, arg, flags, thread] = this.check_shim_sig(
|
||||
shim_sig!(
|
||||
extern "system" fn(
|
||||
*mut _,
|
||||
usize,
|
||||
*mut _,
|
||||
*mut _,
|
||||
u32,
|
||||
*mut _,
|
||||
) -> winapi::HANDLE
|
||||
),
|
||||
link_name,
|
||||
abi,
|
||||
args,
|
||||
)?;
|
||||
|
||||
let thread_id =
|
||||
this.CreateThread(security, stacksize, start, arg, flags, thread)?;
|
||||
|
|
@ -590,13 +823,22 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
|||
this.write_scalar(Handle::Thread(thread_id).to_scalar(this), dest)?;
|
||||
}
|
||||
"WaitForSingleObject" => {
|
||||
let [handle, timeout] =
|
||||
this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?;
|
||||
let [handle, timeout] = this.check_shim_sig(
|
||||
shim_sig!(extern "system" fn(winapi::HANDLE, u32) -> u32),
|
||||
link_name,
|
||||
abi,
|
||||
args,
|
||||
)?;
|
||||
|
||||
this.WaitForSingleObject(handle, timeout, dest)?;
|
||||
}
|
||||
"GetCurrentProcess" => {
|
||||
let [] = this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?;
|
||||
let [] = this.check_shim_sig(
|
||||
shim_sig!(extern "system" fn() -> winapi::HANDLE),
|
||||
link_name,
|
||||
abi,
|
||||
args,
|
||||
)?;
|
||||
|
||||
this.write_scalar(
|
||||
Handle::Pseudo(PseudoHandle::CurrentProcess).to_scalar(this),
|
||||
|
|
@ -604,7 +846,12 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
|||
)?;
|
||||
}
|
||||
"GetCurrentThread" => {
|
||||
let [] = this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?;
|
||||
let [] = this.check_shim_sig(
|
||||
shim_sig!(extern "system" fn() -> winapi::HANDLE),
|
||||
link_name,
|
||||
abi,
|
||||
args,
|
||||
)?;
|
||||
|
||||
this.write_scalar(
|
||||
Handle::Pseudo(PseudoHandle::CurrentThread).to_scalar(this),
|
||||
|
|
@ -612,7 +859,12 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
|||
)?;
|
||||
}
|
||||
"SetThreadDescription" => {
|
||||
let [handle, name] = this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?;
|
||||
let [handle, name] = this.check_shim_sig(
|
||||
shim_sig!(extern "system" fn(winapi::HANDLE, *const _) -> i32),
|
||||
link_name,
|
||||
abi,
|
||||
args,
|
||||
)?;
|
||||
|
||||
let handle = this.read_handle(handle, "SetThreadDescription")?;
|
||||
let name = this.read_wide_str(this.read_pointer(name)?)?;
|
||||
|
|
@ -627,8 +879,12 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
|||
this.write_scalar(Scalar::from_u32(0), dest)?;
|
||||
}
|
||||
"GetThreadDescription" => {
|
||||
let [handle, name_ptr] =
|
||||
this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?;
|
||||
let [handle, name_ptr] = this.check_shim_sig(
|
||||
shim_sig!(extern "system" fn(winapi::HANDLE, *mut _) -> i32),
|
||||
link_name,
|
||||
abi,
|
||||
args,
|
||||
)?;
|
||||
|
||||
let handle = this.read_handle(handle, "GetThreadDescription")?;
|
||||
let name_ptr = this.deref_pointer_as(name_ptr, this.machine.layouts.mut_raw_ptr)?; // the pointer where we should store the ptr to the name
|
||||
|
|
@ -651,7 +907,12 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
|||
this.write_scalar(res, dest)?;
|
||||
}
|
||||
"GetThreadId" => {
|
||||
let [handle] = this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?;
|
||||
let [handle] = this.check_shim_sig(
|
||||
shim_sig!(extern "system" fn(winapi::HANDLE) -> u32),
|
||||
link_name,
|
||||
abi,
|
||||
args,
|
||||
)?;
|
||||
let handle = this.read_handle(handle, "GetThreadId")?;
|
||||
let thread = match handle {
|
||||
Handle::Thread(thread) => thread,
|
||||
|
|
@ -662,7 +923,12 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
|||
this.write_scalar(Scalar::from_u32(tid), dest)?;
|
||||
}
|
||||
"GetCurrentThreadId" => {
|
||||
let [] = this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?;
|
||||
let [] = this.check_shim_sig(
|
||||
shim_sig!(extern "system" fn() -> u32),
|
||||
link_name,
|
||||
abi,
|
||||
args,
|
||||
)?;
|
||||
let thread = this.active_thread();
|
||||
let tid = this.get_tid(thread);
|
||||
this.write_scalar(Scalar::from_u32(tid), dest)?;
|
||||
|
|
@ -670,7 +936,12 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
|||
|
||||
// Miscellaneous
|
||||
"ExitProcess" => {
|
||||
let [code] = this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?;
|
||||
let [code] = this.check_shim_sig(
|
||||
shim_sig!(extern "system" fn(u32) -> ()),
|
||||
link_name,
|
||||
abi,
|
||||
args,
|
||||
)?;
|
||||
// Windows technically uses u32, but we unify everything to a Unix-style i32.
|
||||
let code = this.read_scalar(code)?.to_i32()?;
|
||||
throw_machine_stop!(TerminationInfo::Exit { code, leak_check: false });
|
||||
|
|
@ -678,7 +949,13 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
|||
"SystemFunction036" => {
|
||||
// used by getrandom 0.1
|
||||
// This is really 'RtlGenRandom'.
|
||||
let [ptr, len] = this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?;
|
||||
let [ptr, len] = this.check_shim_sig(
|
||||
// Returns winapi::BOOLEAN, which is a byte
|
||||
shim_sig!(extern "system" fn(*mut _, u32) -> u8),
|
||||
link_name,
|
||||
abi,
|
||||
args,
|
||||
)?;
|
||||
let ptr = this.read_pointer(ptr)?;
|
||||
let len = this.read_scalar(len)?.to_u32()?;
|
||||
this.gen_random(ptr, len.into())?;
|
||||
|
|
@ -686,7 +963,12 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
|||
}
|
||||
"ProcessPrng" => {
|
||||
// used by `std`
|
||||
let [ptr, len] = this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?;
|
||||
let [ptr, len] = this.check_shim_sig(
|
||||
shim_sig!(extern "system" fn(*mut _, usize) -> winapi::BOOL),
|
||||
link_name,
|
||||
abi,
|
||||
args,
|
||||
)?;
|
||||
let ptr = this.read_pointer(ptr)?;
|
||||
let len = this.read_target_usize(len)?;
|
||||
this.gen_random(ptr, len)?;
|
||||
|
|
@ -694,8 +976,12 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
|||
}
|
||||
"BCryptGenRandom" => {
|
||||
// used by getrandom 0.2
|
||||
let [algorithm, ptr, len, flags] =
|
||||
this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?;
|
||||
let [algorithm, ptr, len, flags] = this.check_shim_sig(
|
||||
shim_sig!(extern "system" fn(*mut _, *mut _, u32, u32) -> i32),
|
||||
link_name,
|
||||
abi,
|
||||
args,
|
||||
)?;
|
||||
let algorithm = this.read_scalar(algorithm)?;
|
||||
let algorithm = algorithm.to_target_usize(this)?;
|
||||
let ptr = this.read_pointer(ptr)?;
|
||||
|
|
@ -729,8 +1015,12 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
|||
}
|
||||
"GetConsoleScreenBufferInfo" => {
|
||||
// `term` needs this, so we fake it.
|
||||
let [console, buffer_info] =
|
||||
this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?;
|
||||
let [console, buffer_info] = this.check_shim_sig(
|
||||
shim_sig!(extern "system" fn(winapi::HANDLE, *mut _) -> winapi::BOOL),
|
||||
link_name,
|
||||
abi,
|
||||
args,
|
||||
)?;
|
||||
this.read_target_isize(console)?;
|
||||
// FIXME: this should use deref_pointer_as, but CONSOLE_SCREEN_BUFFER_INFO is not in std
|
||||
this.deref_pointer(buffer_info)?;
|
||||
|
|
@ -739,13 +1029,33 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
|||
this.write_null(dest)?;
|
||||
}
|
||||
"GetStdHandle" => {
|
||||
let [which] = this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?;
|
||||
let [which] = this.check_shim_sig(
|
||||
shim_sig!(extern "system" fn(u32) -> winapi::HANDLE),
|
||||
link_name,
|
||||
abi,
|
||||
args,
|
||||
)?;
|
||||
let res = this.GetStdHandle(which)?;
|
||||
this.write_scalar(res, dest)?;
|
||||
}
|
||||
"DuplicateHandle" => {
|
||||
let [src_proc, src_handle, target_proc, target_handle, access, inherit, options] =
|
||||
this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?;
|
||||
this.check_shim_sig(
|
||||
shim_sig!(
|
||||
extern "system" fn(
|
||||
winapi::HANDLE,
|
||||
winapi::HANDLE,
|
||||
winapi::HANDLE,
|
||||
*mut _,
|
||||
u32,
|
||||
winapi::BOOL,
|
||||
u32,
|
||||
) -> winapi::BOOL
|
||||
),
|
||||
link_name,
|
||||
abi,
|
||||
args,
|
||||
)?;
|
||||
let res = this.DuplicateHandle(
|
||||
src_proc,
|
||||
src_handle,
|
||||
|
|
@ -758,15 +1068,24 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
|||
this.write_scalar(res, dest)?;
|
||||
}
|
||||
"CloseHandle" => {
|
||||
let [handle] = this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?;
|
||||
let [handle] = this.check_shim_sig(
|
||||
shim_sig!(extern "system" fn(winapi::HANDLE) -> winapi::BOOL),
|
||||
link_name,
|
||||
abi,
|
||||
args,
|
||||
)?;
|
||||
|
||||
let ret = this.CloseHandle(handle)?;
|
||||
|
||||
this.write_scalar(ret, dest)?;
|
||||
}
|
||||
"GetModuleFileNameW" => {
|
||||
let [handle, filename, size] =
|
||||
this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?;
|
||||
let [handle, filename, size] = this.check_shim_sig(
|
||||
shim_sig!(extern "system" fn(winapi::HMODULE, *mut _, u32) -> u32),
|
||||
link_name,
|
||||
abi,
|
||||
args,
|
||||
)?;
|
||||
this.check_no_isolation("`GetModuleFileNameW`")?;
|
||||
|
||||
let handle = this.read_handle(handle, "GetModuleFileNameW")?;
|
||||
|
|
@ -799,8 +1118,15 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
|||
}
|
||||
}
|
||||
"FormatMessageW" => {
|
||||
let [flags, module, message_id, language_id, buffer, size, arguments] =
|
||||
this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?;
|
||||
let [flags, module, message_id, language_id, buffer, size, arguments] = this
|
||||
.check_shim_sig(
|
||||
shim_sig!(
|
||||
extern "system" fn(u32, *const _, u32, u32, *mut _, u32, *mut _) -> u32
|
||||
),
|
||||
link_name,
|
||||
abi,
|
||||
args,
|
||||
)?;
|
||||
|
||||
let flags = this.read_scalar(flags)?.to_u32()?;
|
||||
let _module = this.read_pointer(module)?; // seems to contain a module name
|
||||
|
|
@ -843,7 +1169,12 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
|||
);
|
||||
}
|
||||
// This function looks and behaves excatly like miri_start_unwind.
|
||||
let [payload] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
|
||||
let [payload] = this.check_shim_sig(
|
||||
shim_sig!(extern "C" fn(*mut _) -> unwind::libunwind::_Unwind_Reason_Code),
|
||||
link_name,
|
||||
abi,
|
||||
args,
|
||||
)?;
|
||||
this.handle_miri_start_unwind(payload)?;
|
||||
return interp_ok(EmulateItemResult::NeedsUnwind);
|
||||
}
|
||||
|
|
@ -851,56 +1182,86 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
|||
// Incomplete shims that we "stub out" just to get pre-main initialization code to work.
|
||||
// These shims are enabled only when the caller is in the standard library.
|
||||
"GetProcessHeap" if this.frame_in_std() => {
|
||||
let [] = this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?;
|
||||
let [] = this.check_shim_sig(
|
||||
shim_sig!(extern "system" fn() -> winapi::HANDLE),
|
||||
link_name,
|
||||
abi,
|
||||
args,
|
||||
)?;
|
||||
// Just fake a HANDLE
|
||||
// It's fine to not use the Handle type here because its a stub
|
||||
this.write_int(1, dest)?;
|
||||
}
|
||||
"GetModuleHandleA" if this.frame_in_std() => {
|
||||
#[allow(non_snake_case)]
|
||||
let [_lpModuleName] =
|
||||
this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?;
|
||||
let [_module_name] = this.check_shim_sig(
|
||||
shim_sig!(extern "system" fn(*const _) -> winapi::HMODULE),
|
||||
link_name,
|
||||
abi,
|
||||
args,
|
||||
)?;
|
||||
// We need to return something non-null here to make `compat_fn!` work.
|
||||
this.write_int(1, dest)?;
|
||||
}
|
||||
"SetConsoleTextAttribute" if this.frame_in_std() => {
|
||||
#[allow(non_snake_case)]
|
||||
let [_hConsoleOutput, _wAttribute] =
|
||||
this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?;
|
||||
let [_console_output, _attribute] = this.check_shim_sig(
|
||||
shim_sig!(extern "system" fn(winapi::HANDLE, u16) -> winapi::BOOL),
|
||||
link_name,
|
||||
abi,
|
||||
args,
|
||||
)?;
|
||||
// Pretend these does not exist / nothing happened, by returning zero.
|
||||
this.write_null(dest)?;
|
||||
}
|
||||
"GetConsoleMode" if this.frame_in_std() => {
|
||||
let [console, mode] =
|
||||
this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?;
|
||||
let [console, mode] = this.check_shim_sig(
|
||||
shim_sig!(extern "system" fn(winapi::HANDLE, *mut _) -> winapi::BOOL),
|
||||
link_name,
|
||||
abi,
|
||||
args,
|
||||
)?;
|
||||
this.read_target_isize(console)?;
|
||||
this.deref_pointer_as(mode, this.machine.layouts.u32)?;
|
||||
// Indicate an error.
|
||||
this.write_null(dest)?;
|
||||
}
|
||||
"GetFileType" if this.frame_in_std() => {
|
||||
#[allow(non_snake_case)]
|
||||
let [_hFile] = this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?;
|
||||
let [_file] = this.check_shim_sig(
|
||||
shim_sig!(extern "system" fn(winapi::HANDLE) -> u32),
|
||||
link_name,
|
||||
abi,
|
||||
args,
|
||||
)?;
|
||||
// Return unknown file type.
|
||||
this.write_null(dest)?;
|
||||
}
|
||||
"AddVectoredExceptionHandler" if this.frame_in_std() => {
|
||||
#[allow(non_snake_case)]
|
||||
let [_First, _Handler] =
|
||||
this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?;
|
||||
let [_first, _handler] = this.check_shim_sig(
|
||||
shim_sig!(extern "system" fn(u32, *mut _) -> *mut _),
|
||||
link_name,
|
||||
abi,
|
||||
args,
|
||||
)?;
|
||||
// Any non zero value works for the stdlib. This is just used for stack overflows anyway.
|
||||
this.write_int(1, dest)?;
|
||||
}
|
||||
"SetThreadStackGuarantee" if this.frame_in_std() => {
|
||||
#[allow(non_snake_case)]
|
||||
let [_StackSizeInBytes] =
|
||||
this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?;
|
||||
let [_stack_size_in_bytes] = this.check_shim_sig(
|
||||
shim_sig!(extern "system" fn(*mut _) -> winapi::BOOL),
|
||||
link_name,
|
||||
abi,
|
||||
args,
|
||||
)?;
|
||||
// Any non zero value works for the stdlib. This is just used for stack overflows anyway.
|
||||
this.write_int(1, dest)?;
|
||||
}
|
||||
// this is only callable from std because we know that std ignores the return value
|
||||
"SwitchToThread" if this.frame_in_std() => {
|
||||
let [] = this.check_shim_sig_lenient(abi, sys_conv, link_name, args)?;
|
||||
let [] = this.check_shim_sig(
|
||||
shim_sig!(extern "system" fn() -> winapi::BOOL),
|
||||
link_name,
|
||||
abi,
|
||||
args,
|
||||
)?;
|
||||
|
||||
this.yield_active_thread();
|
||||
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@ fn main() {
|
|||
#[cfg(not(target_os = "solaris"))]
|
||||
getrandom_01::getrandom(&mut data).unwrap();
|
||||
|
||||
// On Windows, getrandom 0.2 uses the wrong return type for BCryptGenRandom
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
getrandom_02::getrandom(&mut data).unwrap();
|
||||
|
||||
getrandom_03::fill(&mut data).unwrap();
|
||||
|
|
|
|||
|
|
@ -5,14 +5,14 @@ use std::ptr;
|
|||
|
||||
extern "system" {
|
||||
fn TlsAlloc() -> u32;
|
||||
fn TlsSetValue(key: u32, val: *mut c_void) -> bool;
|
||||
fn TlsSetValue(key: u32, val: *mut c_void) -> i32;
|
||||
fn TlsGetValue(key: u32) -> *mut c_void;
|
||||
fn TlsFree(key: u32) -> bool;
|
||||
fn TlsFree(key: u32) -> i32;
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let key = unsafe { TlsAlloc() };
|
||||
assert!(unsafe { TlsSetValue(key, ptr::without_provenance_mut(1)) });
|
||||
assert!(unsafe { TlsSetValue(key, ptr::without_provenance_mut(1)) != 0 });
|
||||
assert_eq!(unsafe { TlsGetValue(key).addr() }, 1);
|
||||
assert!(unsafe { TlsFree(key) });
|
||||
assert!(unsafe { TlsFree(key) != 0 });
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue