2 use rustc_target::abi::Size;
3 use rustc_target::spec::abi::Abi;
7 use crate::helpers::check_arg_count;
10 #[derive(Debug, Copy, Clone)]
16 // Returns an error for unsupported symbols, and None if this symbol
17 // should become a NULL pointer (pretend it does not exist).
18 pub fn from_str(name: &str) -> InterpResult<'static, Option<Dlsym>> {
20 "GetSystemTimePreciseAsFileTime" => None,
21 "NtWriteFile" => Some(Dlsym::NtWriteFile),
22 _ => throw_unsup_format!("unsupported Windows dlsym: {}", name),
27 impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {}
28 pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx> {
33 args: &[OpTy<'tcx, Tag>],
34 ret: Option<(&PlaceTy<'tcx, Tag>, mir::BasicBlock)>,
35 ) -> InterpResult<'tcx> {
36 let this = self.eval_context_mut();
37 let (dest, ret) = ret.expect("we don't support any diverging dlsym");
38 assert!(this.tcx.sess.target.os == "windows");
40 this.check_abi(abi, Abi::System { unwind: false })?;
43 Dlsym::NtWriteFile => {
44 if !this.frame_in_std() {
46 "NtWriteFile support is crude and just enough for stdout to work"
60 ] = check_arg_count(args)?;
61 let handle = this.read_scalar(handle)?.to_machine_isize(this)?;
62 let buf = this.read_pointer(buf)?;
63 let n = this.read_scalar(n)?.to_u32()?;
64 let byte_offset = this.read_scalar(byte_offset)?.to_machine_usize(this)?; // is actually a pointer
65 let io_status_block = this.deref_operand(io_status_block)?;
69 "NtWriteFile ByteOffset paremeter is non-null, which is unsupported"
73 let written = if handle == -11 || handle == -12 {
75 use std::io::{self, Write};
77 let buf_cont = this.read_bytes_ptr(buf, Size::from_bytes(u64::from(n)))?;
78 let res = if handle == -11 {
79 io::stdout().write(buf_cont)
81 io::stderr().write(buf_cont)
83 res.ok().map(|n| n as u32)
86 "on Windows, writing to anything except stdout/stderr is not supported"
89 // We have to put the result into io_status_block.
90 if let Some(n) = written {
91 let io_status_information =
92 this.mplace_field_named(&io_status_block, "Information")?;
94 Scalar::from_machine_usize(n.into(), this),
95 &io_status_information.into(),
98 // Return whether this was a success. >= 0 is success.
99 // For the error code we arbitrarily pick 0xC0000185, STATUS_IO_DEVICE_ERROR.
101 Scalar::from_i32(if written.is_some() { 0 } else { 0xC0000185u32 as i32 }),
107 trace!("{:?}", this.dump_place(**dest));
108 this.go_to_block(ret);