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<'tcx>(name: &str) -> InterpResult<'tcx, Option<Dlsym>> {
20 "GetSystemTimePreciseAsFileTime" => None,
21 "SetThreadDescription" => None,
22 "NtWriteFile" => Some(Dlsym::NtWriteFile),
23 _ => throw_unsup_format!("unsupported Windows dlsym: {}", name),
28 impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {}
29 pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx> {
34 args: &[OpTy<'tcx, Provenance>],
35 dest: &PlaceTy<'tcx, Provenance>,
36 ret: Option<mir::BasicBlock>,
37 ) -> InterpResult<'tcx> {
38 let this = self.eval_context_mut();
39 let ret = ret.expect("we don't support any diverging dlsym");
40 assert!(this.tcx.sess.target.os == "windows");
42 this.check_abi(abi, Abi::System { unwind: false })?;
45 Dlsym::NtWriteFile => {
46 if !this.frame_in_std() {
48 "NtWriteFile support is crude and just enough for stdout to work"
62 ] = check_arg_count(args)?;
63 let handle = this.read_scalar(handle)?.to_machine_isize(this)?;
64 let buf = this.read_pointer(buf)?;
65 let n = this.read_scalar(n)?.to_u32()?;
66 let byte_offset = this.read_scalar(byte_offset)?.to_machine_usize(this)?; // is actually a pointer
67 let io_status_block = this.deref_operand(io_status_block)?;
71 "NtWriteFile ByteOffset paremeter is non-null, which is unsupported"
75 let written = if handle == -11 || handle == -12 {
77 use std::io::{self, Write};
79 let buf_cont = this.read_bytes_ptr(buf, Size::from_bytes(u64::from(n)))?;
80 let res = if this.machine.mute_stdout_stderr {
82 } else if handle == -11 {
83 io::stdout().write(buf_cont)
85 io::stderr().write(buf_cont)
87 // We write at most `n` bytes, which is a `u32`, so we cannot have written more than that.
88 res.ok().map(|n| u32::try_from(n).unwrap())
91 "on Windows, writing to anything except stdout/stderr is not supported"
94 // We have to put the result into io_status_block.
95 if let Some(n) = written {
96 let io_status_information =
97 this.mplace_field_named(&io_status_block, "Information")?;
99 Scalar::from_machine_usize(n.into(), this),
100 &io_status_information.into(),
103 // Return whether this was a success. >= 0 is success.
104 // For the error code we arbitrarily pick 0xC0000185, STATUS_IO_DEVICE_ERROR.
106 Scalar::from_u32(if written.is_some() { 0 } else { 0xC0000185u32 }),
112 trace!("{:?}", this.dump_place(**dest));
113 this.go_to_block(ret);