From 5af318bd563345c0205dfd1060e90c0368054dc6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hugo=20Beauz=C3=A9e-Luyssen?= Date: Mon, 27 May 2019 15:51:44 +0200 Subject: [PATCH 01/13] rustc: codegen: Build import library for all windows targets So far it is assumed that using a DLL as a -l parameter argument is ok, but the assumption doesn't hold when compiling the native code with llvm. In which case, an import library is required, so let's build one This also requires the cargo counterpart to add the import library in the stamp files, at least when compiling libstd. Otherwise, the files don't get uplifted --- src/bootstrap/compile.rs | 1 + src/librustc_codegen_ssa/back/linker.rs | 20 +++++++++++++++++++ .../output-type-permutations/Makefile | 6 +++--- 3 files changed, 24 insertions(+), 3 deletions(-) diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index 9ced04a5c808a..60138e701bdbb 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -1126,6 +1126,7 @@ pub fn run_cargo(builder: &Builder<'_>, // Skip files like executables if !filename.ends_with(".rlib") && !filename.ends_with(".lib") && + !filename.ends_with(".a") && !is_dylib(&filename) && !(is_check && filename.ends_with(".rmeta")) { continue; diff --git a/src/librustc_codegen_ssa/back/linker.rs b/src/librustc_codegen_ssa/back/linker.rs index 882963f9174ec..cb8870d0be90c 100644 --- a/src/librustc_codegen_ssa/back/linker.rs +++ b/src/librustc_codegen_ssa/back/linker.rs @@ -368,6 +368,26 @@ impl<'a> Linker for GccLinker<'a> { } } else { self.cmd.arg("-shared"); + if self.sess.target.target.options.is_like_windows { + // The output filename already contains `dll_suffix` so + // the resulting import library will have a name in the + // form of libfoo.dll.a + let implib_name = out_filename + .file_name() + .and_then(|file| file.to_str()) + .map(|file| format!("{}{}{}", + self.sess.target.target.options.staticlib_prefix, + file, + self.sess.target.target.options.staticlib_suffix)); + if let Some(implib_name) = implib_name { + let implib = out_filename + .parent() + .map(|dir| dir.join(&implib_name)); + if let Some(implib) = implib { + self.linker_arg(&format!("--out-implib,{}", (*implib).to_str().unwrap())); + } + } + } } } diff --git a/src/test/run-make-fulldeps/output-type-permutations/Makefile b/src/test/run-make-fulldeps/output-type-permutations/Makefile index c2715027bc1f9..ffd3e6da25633 100644 --- a/src/test/run-make-fulldeps/output-type-permutations/Makefile +++ b/src/test/run-make-fulldeps/output-type-permutations/Makefile @@ -5,7 +5,7 @@ all: $(call REMOVE_RLIBS,bar) $(call REMOVE_DYLIBS,bar) rm $(call STATICLIB,bar) - rm -f $(TMPDIR)/bar.{dll.exp,dll.lib,pdb} + rm -f $(TMPDIR)/{lib,}bar.{dll.exp,dll.lib,pdb,dll.a} # Check that $(TMPDIR) is empty. [ "$$(ls -1 $(TMPDIR) | wc -l)" -eq "0" ] @@ -78,8 +78,8 @@ all: rm $(TMPDIR)/$(call BIN,foo) $(RUSTC) foo.rs --crate-type=dylib --emit=link=$(TMPDIR)/$(call BIN,foo) rm $(TMPDIR)/$(call BIN,foo) - rm -f $(TMPDIR)/foo.{dll.exp,dll.lib,pdb} - [ "$$(ls -1 $(TMPDIR) | wc -l)" -eq "0" ] + rm -f $(TMPDIR)/{lib,}foo.{dll.exp,dll.lib,pdb,dll.a,exe.lib} + [ "$$(ls -1 $(TMPDIR) | wc -l)" -eq "0" ] || (ls -1 $(TMPDIR) && exit 1) $(RUSTC) foo.rs --crate-type=staticlib -o $(TMPDIR)/foo rm $(TMPDIR)/foo From e34bcdbc57651e97736dcdf1b25cbec4a32d755c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hugo=20Beauz=C3=A9e-Luyssen?= Date: Mon, 27 May 2019 15:55:06 +0200 Subject: [PATCH 02/13] libstd: windows: compat: Allow use of attributes --- src/libstd/sys/windows/compat.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/libstd/sys/windows/compat.rs b/src/libstd/sys/windows/compat.rs index 748c1616d1d32..544b2087f92e0 100644 --- a/src/libstd/sys/windows/compat.rs +++ b/src/libstd/sys/windows/compat.rs @@ -37,12 +37,14 @@ pub fn store_func(ptr: &AtomicUsize, module: &str, symbol: &str, macro_rules! compat_fn { ($module:ident: $( + $(#[$meta:meta])* pub fn $symbol:ident($($argname:ident: $argtype:ty),*) -> $rettype:ty { $($body:expr);* } )*) => ($( #[allow(unused_variables)] + $(#[$meta])* pub unsafe fn $symbol($($argname: $argtype),*) -> $rettype { use crate::sync::atomic::{AtomicUsize, Ordering}; use crate::mem; From ce315cd2fe84def8c65e321161a98ce073472ecb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hugo=20Beauz=C3=A9e-Luyssen?= Date: Mon, 27 May 2019 16:32:00 +0200 Subject: [PATCH 03/13] bootstrap: Build startup object for all windows-gnu target So that uwp-windows-gnu also gets its startup objects built --- src/bootstrap/compile.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index 60138e701bdbb..4cd793adaf574 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -325,7 +325,7 @@ impl Step for StartupObjects { fn run(self, builder: &Builder<'_>) { let for_compiler = self.compiler; let target = self.target; - if !target.contains("pc-windows-gnu") { + if !target.contains("windows-gnu") { return } From 3becaf4b9bbcfad476c9c6bfbe103fa0dbbea0cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hugo=20Beauz=C3=A9e-Luyssen?= Date: Mon, 27 May 2019 16:33:00 +0200 Subject: [PATCH 04/13] std: Link UWP with allowed libraries only --- src/libstd/build.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/libstd/build.rs b/src/libstd/build.rs index 7a6c97ebaa226..1071cfbf6ef11 100644 --- a/src/libstd/build.rs +++ b/src/libstd/build.rs @@ -39,6 +39,8 @@ fn main() { println!("cargo:rustc-link-lib=framework=Security"); println!("cargo:rustc-link-lib=framework=Foundation"); println!("cargo:rustc-link-lib=resolv"); + } else if target.contains("uwp") { + println!("cargo:rustc-link-lib=ws2_32"); } else if target.contains("windows") { println!("cargo:rustc-link-lib=advapi32"); println!("cargo:rustc-link-lib=ws2_32"); From 642f8cd9c2625ea0c838442d973718ea92c14de8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hugo=20Beauz=C3=A9e-Luyssen?= Date: Mon, 27 May 2019 16:38:21 +0200 Subject: [PATCH 05/13] libunwind: Use libunwind when targeting UWP libgcc's support is using forbidden functions --- src/libunwind/build.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/libunwind/build.rs b/src/libunwind/build.rs index e92c68f5b0c57..3545a691a1515 100644 --- a/src/libunwind/build.rs +++ b/src/libunwind/build.rs @@ -30,9 +30,11 @@ fn main() { println!("cargo:rustc-link-lib=gcc_s"); } else if target.contains("dragonfly") { println!("cargo:rustc-link-lib=gcc_pic"); - } else if target.contains("windows-gnu") { + } else if target.contains("pc-windows-gnu") { println!("cargo:rustc-link-lib=static-nobundle=gcc_eh"); println!("cargo:rustc-link-lib=static-nobundle=pthread"); + } else if target.contains("uwp-windows-gnu") { + println!("cargo:rustc-link-lib=unwind"); } else if target.contains("fuchsia") { println!("cargo:rustc-link-lib=unwind"); } else if target.contains("haiku") { From 9407ed759fd31fca3c32c1bc3b3e2f26313c462f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hugo=20Beauz=C3=A9e-Luyssen?= Date: Mon, 27 May 2019 16:41:52 +0200 Subject: [PATCH 06/13] std: rand: Use BCrypt on UWP As Rtl* functions are not allowed there --- src/libstd/build.rs | 2 ++ src/libstd/sys/windows/c.rs | 25 +++++++++++++++++++++++-- src/libstd/sys/windows/rand.rs | 18 ++++++++++++++++++ 3 files changed, 43 insertions(+), 2 deletions(-) diff --git a/src/libstd/build.rs b/src/libstd/build.rs index 1071cfbf6ef11..20397369387cb 100644 --- a/src/libstd/build.rs +++ b/src/libstd/build.rs @@ -41,6 +41,8 @@ fn main() { println!("cargo:rustc-link-lib=resolv"); } else if target.contains("uwp") { println!("cargo:rustc-link-lib=ws2_32"); + // For BCryptGenRandom + println!("cargo:rustc-link-lib=bcrypt"); } else if target.contains("windows") { println!("cargo:rustc-link-lib=advapi32"); println!("cargo:rustc-link-lib=ws2_32"); diff --git a/src/libstd/sys/windows/c.rs b/src/libstd/sys/windows/c.rs index 6ad338660c338..9738c9daf7c7e 100644 --- a/src/libstd/sys/windows/c.rs +++ b/src/libstd/sys/windows/c.rs @@ -655,6 +655,29 @@ pub struct timeval { pub tv_usec: c_long, } +// Functions forbidden when targeting UWP +cfg_if::cfg_if! { +if #[cfg(not(target_vendor = "uwp"))] { + extern "system" { + #[link_name = "SystemFunction036"] + pub fn RtlGenRandom(RandomBuffer: *mut u8, RandomBufferLength: ULONG) -> BOOLEAN; + } +} +} + +// UWP specific functions & types +cfg_if::cfg_if! { +if #[cfg(target_vendor = "uwp")] { + pub const BCRYPT_USE_SYSTEM_PREFERRED_RNG: DWORD = 0x00000002; + + extern "system" { + pub fn BCryptGenRandom(hAlgorithm: LPVOID, pBuffer: *mut u8, + cbBuffer: ULONG, dwFlags: ULONG) -> LONG; + } +} +} + +// Shared between Desktop & UWP extern "system" { pub fn WSAStartup(wVersionRequested: WORD, lpWSAData: LPWSADATA) -> c_int; @@ -950,8 +973,6 @@ extern "system" { exceptfds: *mut fd_set, timeout: *const timeval) -> c_int; - #[link_name = "SystemFunction036"] - pub fn RtlGenRandom(RandomBuffer: *mut u8, RandomBufferLength: ULONG) -> BOOLEAN; pub fn GetProcessHeap() -> HANDLE; pub fn HeapAlloc(hHeap: HANDLE, dwFlags: DWORD, dwBytes: SIZE_T) -> LPVOID; diff --git a/src/libstd/sys/windows/rand.rs b/src/libstd/sys/windows/rand.rs index 0193f4defa1ff..c9bcb5d741514 100644 --- a/src/libstd/sys/windows/rand.rs +++ b/src/libstd/sys/windows/rand.rs @@ -2,6 +2,7 @@ use crate::io; use crate::mem; use crate::sys::c; +#[cfg(not(target_vendor = "uwp"))] pub fn hashmap_random_keys() -> (u64, u64) { let mut v = (0, 0); let ret = unsafe { @@ -14,3 +15,20 @@ pub fn hashmap_random_keys() -> (u64, u64) { } return v } + +#[cfg(target_vendor = "uwp")] +pub fn hashmap_random_keys() -> (u64, u64) { + use crate::ptr; + + let mut v = (0, 0); + let ret = unsafe { + c::BCryptGenRandom(ptr::null_mut(), &mut v as *mut _ as *mut u8, + mem::size_of_val(&v) as c::ULONG, + c::BCRYPT_USE_SYSTEM_PREFERRED_RNG) + }; + if ret != 0 { + panic!("couldn't generate random bytes: {}", + io::Error::last_os_error()); + } + return v +} From a713a0399a6e63de1c8009a390ae964ff03f4067 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hugo=20Beauz=C3=A9e-Luyssen?= Date: Mon, 27 May 2019 16:51:29 +0200 Subject: [PATCH 07/13] std: win: Don't use SetHandleInformation on UWP Attempt to create sockets with the WSA_FLAG_NO_HANDLE_INHERIT flag, and handle the potential error gracefully (as the flag isn't support on Windows 7 before SP1) --- src/libstd/sys/windows/c.rs | 13 +++++--- src/libstd/sys/windows/net.rs | 51 ++++++++++++++++++++++++++----- src/libstd/sys/windows/pipe.rs | 9 +++++- src/libstd/sys/windows/process.rs | 7 +---- 4 files changed, 61 insertions(+), 19 deletions(-) diff --git a/src/libstd/sys/windows/c.rs b/src/libstd/sys/windows/c.rs index 9738c9daf7c7e..2cec96e0016a5 100644 --- a/src/libstd/sys/windows/c.rs +++ b/src/libstd/sys/windows/c.rs @@ -121,6 +121,7 @@ impl Clone for WIN32_FIND_DATAW { } pub const WSA_FLAG_OVERLAPPED: DWORD = 0x01; +pub const WSA_FLAG_NO_HANDLE_INHERIT: DWORD = 0x80; pub const WSADESCRIPTION_LEN: usize = 256; pub const WSASYS_STATUS_LEN: usize = 128; @@ -130,6 +131,7 @@ pub const INVALID_SOCKET: SOCKET = !0; pub const WSAEACCES: c_int = 10013; pub const WSAEINVAL: c_int = 10022; pub const WSAEWOULDBLOCK: c_int = 10035; +pub const WSAEPROTOTYPE: c_int = 10041; pub const WSAEADDRINUSE: c_int = 10048; pub const WSAEADDRNOTAVAIL: c_int = 10049; pub const WSAECONNABORTED: c_int = 10053; @@ -157,8 +159,6 @@ pub const STD_INPUT_HANDLE: DWORD = -10i32 as DWORD; pub const STD_OUTPUT_HANDLE: DWORD = -11i32 as DWORD; pub const STD_ERROR_HANDLE: DWORD = -12i32 as DWORD; -pub const HANDLE_FLAG_INHERIT: DWORD = 0x00000001; - pub const PROGRESS_CONTINUE: DWORD = 0; pub const ERROR_FILE_NOT_FOUND: DWORD = 2; @@ -658,9 +658,15 @@ pub struct timeval { // Functions forbidden when targeting UWP cfg_if::cfg_if! { if #[cfg(not(target_vendor = "uwp"))] { + pub const HANDLE_FLAG_INHERIT: DWORD = 0x00000001; + extern "system" { #[link_name = "SystemFunction036"] pub fn RtlGenRandom(RandomBuffer: *mut u8, RandomBufferLength: ULONG) -> BOOLEAN; + + pub fn SetHandleInformation(hObject: HANDLE, + dwMask: DWORD, + dwFlags: DWORD) -> BOOL; } } } @@ -772,9 +778,6 @@ extern "system" { pub fn GetUserProfileDirectoryW(hToken: HANDLE, lpProfileDir: LPWSTR, lpcchSize: *mut DWORD) -> BOOL; - pub fn SetHandleInformation(hObject: HANDLE, - dwMask: DWORD, - dwFlags: DWORD) -> BOOL; pub fn CopyFileExW(lpExistingFileName: LPCWSTR, lpNewFileName: LPCWSTR, lpProgressRoutine: LPPROGRESS_ROUTINE, diff --git a/src/libstd/sys/windows/net.rs b/src/libstd/sys/windows/net.rs index 7dd1af5441bfb..32f4011fb3219 100644 --- a/src/libstd/sys/windows/net.rs +++ b/src/libstd/sys/windows/net.rs @@ -97,12 +97,26 @@ impl Socket { }; let socket = unsafe { match c::WSASocketW(fam, ty, 0, ptr::null_mut(), 0, - c::WSA_FLAG_OVERLAPPED) { - c::INVALID_SOCKET => Err(last_error()), + c::WSA_FLAG_OVERLAPPED | c::WSA_FLAG_NO_HANDLE_INHERIT) { + c::INVALID_SOCKET => { + match c::WSAGetLastError() { + c::WSAEPROTOTYPE => { + match c::WSASocketW(fam, ty, 0, ptr::null_mut(), 0, + c::WSA_FLAG_OVERLAPPED) { + c::INVALID_SOCKET => Err(last_error()), + n => { + let s = Socket(n); + s.set_no_inherit()?; + Ok(s) + }, + } + }, + n => Err(io::Error::from_raw_os_error(n)), + } + }, n => Ok(Socket(n)), } }?; - socket.set_no_inherit()?; Ok(socket) } @@ -168,7 +182,6 @@ impl Socket { n => Ok(Socket(n)), } }?; - socket.set_no_inherit()?; Ok(socket) } @@ -178,16 +191,34 @@ impl Socket { cvt(c::WSADuplicateSocketW(self.0, c::GetCurrentProcessId(), &mut info))?; + match c::WSASocketW(info.iAddressFamily, info.iSocketType, info.iProtocol, &mut info, 0, - c::WSA_FLAG_OVERLAPPED) { - c::INVALID_SOCKET => Err(last_error()), + c::WSA_FLAG_OVERLAPPED | c::WSA_FLAG_NO_HANDLE_INHERIT) { + c::INVALID_SOCKET => { + match c::WSAGetLastError() { + c::WSAEPROTOTYPE => { + match c::WSASocketW(info.iAddressFamily, + info.iSocketType, + info.iProtocol, + &mut info, 0, + c::WSA_FLAG_OVERLAPPED) { + c::INVALID_SOCKET => Err(last_error()), + n => { + let s = Socket(n); + s.set_no_inherit()?; + Ok(s) + }, + } + }, + n => Err(io::Error::from_raw_os_error(n)), + } + }, n => Ok(Socket(n)), } }?; - socket.set_no_inherit()?; Ok(socket) } @@ -312,6 +343,7 @@ impl Socket { } } + #[cfg(not(target_vendor = "uwp"))] fn set_no_inherit(&self) -> io::Result<()> { sys::cvt(unsafe { c::SetHandleInformation(self.0 as c::HANDLE, @@ -319,6 +351,11 @@ impl Socket { }).map(|_| ()) } + #[cfg(target_vendor = "uwp")] + fn set_no_inherit(&self) -> io::Result<()> { + Err(io::Error::new(io::ErrorKind::Other, "Unavailable on UWP")) + } + pub fn shutdown(&self, how: Shutdown) -> io::Result<()> { let how = match how { Shutdown::Write => c::SD_SEND, diff --git a/src/libstd/sys/windows/pipe.rs b/src/libstd/sys/windows/pipe.rs index c77f30dfc7109..041d5385eb69b 100644 --- a/src/libstd/sys/windows/pipe.rs +++ b/src/libstd/sys/windows/pipe.rs @@ -45,7 +45,7 @@ pub struct Pipes { /// mode. This means that technically speaking it should only ever be used /// with `OVERLAPPED` instances, but also works out ok if it's only ever used /// once at a time (which we do indeed guarantee). -pub fn anon_pipe(ours_readable: bool) -> io::Result { +pub fn anon_pipe(ours_readable: bool, their_handle_inheritable: bool) -> io::Result { // Note that we specifically do *not* use `CreatePipe` here because // unfortunately the anonymous pipes returned do not support overlapped // operations. Instead, we create a "hopefully unique" name and create a @@ -137,6 +137,13 @@ pub fn anon_pipe(ours_readable: bool) -> io::Result { opts.write(ours_readable); opts.read(!ours_readable); opts.share_mode(0); + let size = mem::size_of::(); + let mut sa = c::SECURITY_ATTRIBUTES { + nLength: size as c::DWORD, + lpSecurityDescriptor: ptr::null_mut(), + bInheritHandle: their_handle_inheritable as i32, + }; + opts.security_attributes(&mut sa); let theirs = File::open(Path::new(&name), &opts)?; let theirs = AnonPipe { inner: theirs.into_handle() }; diff --git a/src/libstd/sys/windows/process.rs b/src/libstd/sys/windows/process.rs index e39b7ae889025..05e0ca6706453 100644 --- a/src/libstd/sys/windows/process.rs +++ b/src/libstd/sys/windows/process.rs @@ -267,13 +267,8 @@ impl Stdio { Stdio::MakePipe => { let ours_readable = stdio_id != c::STD_INPUT_HANDLE; - let pipes = pipe::anon_pipe(ours_readable)?; + let pipes = pipe::anon_pipe(ours_readable, true)?; *pipe = Some(pipes.ours); - cvt(unsafe { - c::SetHandleInformation(pipes.theirs.handle().raw(), - c::HANDLE_FLAG_INHERIT, - c::HANDLE_FLAG_INHERIT) - })?; Ok(pipes.theirs.into_handle()) } From ef267284e8a2d021afe70f00eabcbbf7d076d56f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hugo=20Beauz=C3=A9e-Luyssen?= Date: Mon, 27 May 2019 16:44:06 +0200 Subject: [PATCH 08/13] std: win: Don't expose link() on UWP Or rather expose it, but always return an error --- src/libstd/sys/windows/c.rs | 8 ++++---- src/libstd/sys/windows/fs.rs | 7 +++++++ 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/libstd/sys/windows/c.rs b/src/libstd/sys/windows/c.rs index 2cec96e0016a5..05fff046b652b 100644 --- a/src/libstd/sys/windows/c.rs +++ b/src/libstd/sys/windows/c.rs @@ -667,6 +667,10 @@ if #[cfg(not(target_vendor = "uwp"))] { pub fn SetHandleInformation(hObject: HANDLE, dwMask: DWORD, dwFlags: DWORD) -> BOOL; + pub fn CreateHardLinkW(lpSymlinkFileName: LPCWSTR, + lpTargetFileName: LPCWSTR, + lpSecurityAttributes: LPSECURITY_ATTRIBUTES) + -> BOOL; } } } @@ -883,10 +887,6 @@ extern "system" { lpOverlapped: LPOVERLAPPED) -> BOOL; pub fn CloseHandle(hObject: HANDLE) -> BOOL; - pub fn CreateHardLinkW(lpSymlinkFileName: LPCWSTR, - lpTargetFileName: LPCWSTR, - lpSecurityAttributes: LPSECURITY_ATTRIBUTES) - -> BOOL; pub fn MoveFileExW(lpExistingFileName: LPCWSTR, lpNewFileName: LPCWSTR, dwFlags: DWORD) diff --git a/src/libstd/sys/windows/fs.rs b/src/libstd/sys/windows/fs.rs index d5cb205c85f52..f6f64a008bbfe 100644 --- a/src/libstd/sys/windows/fs.rs +++ b/src/libstd/sys/windows/fs.rs @@ -670,6 +670,7 @@ pub fn symlink_inner(src: &Path, dst: &Path, dir: bool) -> io::Result<()> { Ok(()) } +#[cfg(not(target_vendor = "uwp"))] pub fn link(src: &Path, dst: &Path) -> io::Result<()> { let src = to_u16s(src)?; let dst = to_u16s(dst)?; @@ -679,6 +680,12 @@ pub fn link(src: &Path, dst: &Path) -> io::Result<()> { Ok(()) } +#[cfg(target_vendor = "uwp")] +pub fn link(_src: &Path, _dst: &Path) -> io::Result<()> { + return Err(io::Error::new(io::ErrorKind::Other, + "hard link are not supported on UWP")); +} + pub fn stat(path: &Path) -> io::Result { let mut opts = OpenOptions::new(); // No read or write permissions are necessary From a24be59b4693d41634ad22815b4d973440ff0b30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hugo=20Beauz=C3=A9e-Luyssen?= Date: Mon, 27 May 2019 17:07:33 +0200 Subject: [PATCH 09/13] std: win: Don't use GetUserProfileDirectoryW on UWP --- src/libstd/sys/windows/c.rs | 16 +++++++++------- src/libstd/sys/windows/os.rs | 23 +++++++++++++++++------ 2 files changed, 26 insertions(+), 13 deletions(-) diff --git a/src/libstd/sys/windows/c.rs b/src/libstd/sys/windows/c.rs index 05fff046b652b..bfaa22906033c 100644 --- a/src/libstd/sys/windows/c.rs +++ b/src/libstd/sys/windows/c.rs @@ -143,7 +143,6 @@ pub const WSAECONNREFUSED: c_int = 10061; pub const MAX_PROTOCOL_CHAIN: DWORD = 7; -pub const TOKEN_READ: DWORD = 0x20008; pub const MAXIMUM_REPARSE_DATA_BUFFER_SIZE: usize = 16 * 1024; pub const FSCTL_GET_REPARSE_POINT: DWORD = 0x900a8; pub const IO_REPARSE_TAG_SYMLINK: DWORD = 0xa000000c; @@ -660,10 +659,19 @@ cfg_if::cfg_if! { if #[cfg(not(target_vendor = "uwp"))] { pub const HANDLE_FLAG_INHERIT: DWORD = 0x00000001; + pub const TOKEN_READ: DWORD = 0x20008; + extern "system" { #[link_name = "SystemFunction036"] pub fn RtlGenRandom(RandomBuffer: *mut u8, RandomBufferLength: ULONG) -> BOOLEAN; + // Allowed but unused by UWP + pub fn OpenProcessToken(ProcessHandle: HANDLE, + DesiredAccess: DWORD, + TokenHandle: *mut HANDLE) -> BOOL; + pub fn GetUserProfileDirectoryW(hToken: HANDLE, + lpProfileDir: LPWSTR, + lpcchSize: *mut DWORD) -> BOOL; pub fn SetHandleInformation(hObject: HANDLE, dwMask: DWORD, dwFlags: DWORD) -> BOOL; @@ -752,9 +760,6 @@ extern "system" { pub fn GetCommandLineW() -> *mut LPCWSTR; pub fn GetTempPathW(nBufferLength: DWORD, lpBuffer: LPCWSTR) -> DWORD; - pub fn OpenProcessToken(ProcessHandle: HANDLE, - DesiredAccess: DWORD, - TokenHandle: *mut HANDLE) -> BOOL; pub fn GetCurrentProcess() -> HANDLE; pub fn GetCurrentThread() -> HANDLE; pub fn GetStdHandle(which: DWORD) -> HANDLE; @@ -779,9 +784,6 @@ extern "system" { pub fn SwitchToThread() -> BOOL; pub fn Sleep(dwMilliseconds: DWORD); pub fn GetProcessId(handle: HANDLE) -> DWORD; - pub fn GetUserProfileDirectoryW(hToken: HANDLE, - lpProfileDir: LPWSTR, - lpcchSize: *mut DWORD) -> BOOL; pub fn CopyFileExW(lpExistingFileName: LPCWSTR, lpNewFileName: LPCWSTR, lpProgressRoutine: LPPROGRESS_ROUTINE, diff --git a/src/libstd/sys/windows/os.rs b/src/libstd/sys/windows/os.rs index 4e50b5521eb04..7c400dce686f3 100644 --- a/src/libstd/sys/windows/os.rs +++ b/src/libstd/sys/windows/os.rs @@ -13,7 +13,6 @@ use crate::path::{self, PathBuf}; use crate::ptr; use crate::slice; use crate::sys::{c, cvt}; -use crate::sys::handle::Handle; use super::to_u16s; @@ -284,10 +283,11 @@ pub fn temp_dir() -> PathBuf { }, super::os2path).unwrap() } -pub fn home_dir() -> Option { - crate::env::var_os("HOME").or_else(|| { - crate::env::var_os("USERPROFILE") - }).map(PathBuf::from).or_else(|| unsafe { +#[cfg(not(target_vendor = "uwp"))] +fn home_dir_crt() -> Option { + unsafe { + use crate::sys::handle::Handle; + let me = c::GetCurrentProcess(); let mut token = ptr::null_mut(); if c::OpenProcessToken(me, c::TOKEN_READ, &mut token) == 0 { @@ -301,7 +301,18 @@ pub fn home_dir() -> Option { _ => sz - 1, // sz includes the null terminator } }, super::os2path).ok() - }) + } +} + +#[cfg(target_vendor = "uwp")] +fn home_dir_crt() -> Option { + None +} + +pub fn home_dir() -> Option { + crate::env::var_os("HOME").or_else(|| { + crate::env::var_os("USERPROFILE") + }).map(PathBuf::from).or_else(|| home_dir_crt()) } pub fn exit(code: i32) -> ! { From 4c05073d1d64b82ad10478324b87816cec16d74c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hugo=20Beauz=C3=A9e-Luyssen?= Date: Mon, 27 May 2019 17:13:04 +0200 Subject: [PATCH 10/13] std: win: Don't use GetFileInformationByHandle on UWP --- src/libstd/sys/windows/c.rs | 51 ++++++++++++++++++++++-------------- src/libstd/sys/windows/fs.rs | 44 +++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+), 19 deletions(-) diff --git a/src/libstd/sys/windows/c.rs b/src/libstd/sys/windows/c.rs index bfaa22906033c..6b4d6d9e23b81 100644 --- a/src/libstd/sys/windows/c.rs +++ b/src/libstd/sys/windows/c.rs @@ -34,7 +34,6 @@ pub type ULONG = c_ulong; pub type LPBOOL = *mut BOOL; pub type LPBYTE = *mut BYTE; -pub type LPBY_HANDLE_FILE_INFORMATION = *mut BY_HANDLE_FILE_INFORMATION; pub type LPCSTR = *const CHAR; pub type LPCVOID = *const c_void; pub type LPCWSTR = *const WCHAR; @@ -341,20 +340,6 @@ pub struct WIN32_FILE_ATTRIBUTE_DATA { pub nFileSizeLow: DWORD, } -#[repr(C)] -pub struct BY_HANDLE_FILE_INFORMATION { - pub dwFileAttributes: DWORD, - pub ftCreationTime: FILETIME, - pub ftLastAccessTime: FILETIME, - pub ftLastWriteTime: FILETIME, - pub dwVolumeSerialNumber: DWORD, - pub nFileSizeHigh: DWORD, - pub nFileSizeLow: DWORD, - pub nNumberOfLinks: DWORD, - pub nFileIndexHigh: DWORD, - pub nFileIndexLow: DWORD, -} - #[repr(C)] #[allow(dead_code)] // we only use some variants pub enum FILE_INFO_BY_HANDLE_CLASS { @@ -657,6 +642,22 @@ pub struct timeval { // Functions forbidden when targeting UWP cfg_if::cfg_if! { if #[cfg(not(target_vendor = "uwp"))] { + #[repr(C)] + pub struct BY_HANDLE_FILE_INFORMATION { + pub dwFileAttributes: DWORD, + pub ftCreationTime: FILETIME, + pub ftLastAccessTime: FILETIME, + pub ftLastWriteTime: FILETIME, + pub dwVolumeSerialNumber: DWORD, + pub nFileSizeHigh: DWORD, + pub nFileSizeLow: DWORD, + pub nNumberOfLinks: DWORD, + pub nFileIndexHigh: DWORD, + pub nFileIndexLow: DWORD, + } + + pub type LPBY_HANDLE_FILE_INFORMATION = *mut BY_HANDLE_FILE_INFORMATION; + pub const HANDLE_FLAG_INHERIT: DWORD = 0x00000001; pub const TOKEN_READ: DWORD = 0x20008; @@ -672,6 +673,9 @@ if #[cfg(not(target_vendor = "uwp"))] { pub fn GetUserProfileDirectoryW(hToken: HANDLE, lpProfileDir: LPWSTR, lpcchSize: *mut DWORD) -> BOOL; + pub fn GetFileInformationByHandle(hFile: HANDLE, + lpFileInformation: LPBY_HANDLE_FILE_INFORMATION) + -> BOOL; pub fn SetHandleInformation(hObject: HANDLE, dwMask: DWORD, dwFlags: DWORD) -> BOOL; @@ -688,7 +692,20 @@ cfg_if::cfg_if! { if #[cfg(target_vendor = "uwp")] { pub const BCRYPT_USE_SYSTEM_PREFERRED_RNG: DWORD = 0x00000002; + #[repr(C)] + pub struct FILE_STANDARD_INFO { + pub AllocationSize: LARGE_INTEGER, + pub EndOfFile: LARGE_INTEGER, + pub NumberOfLink: DWORD, + pub DeletePending: BOOLEAN, + pub Directory: BOOLEAN, + } + extern "system" { + pub fn GetFileInformationByHandleEx(hFile: HANDLE, + fileInfoClass: FILE_INFO_BY_HANDLE_CLASS, + lpFileInformation: LPVOID, + dwBufferSize: DWORD) -> BOOL; pub fn BCryptGenRandom(hAlgorithm: LPVOID, pBuffer: *mut u8, cbBuffer: ULONG, dwFlags: ULONG) -> LONG; } @@ -752,10 +769,6 @@ extern "system" { pub fn RemoveDirectoryW(lpPathName: LPCWSTR) -> BOOL; pub fn SetFileAttributesW(lpFileName: LPCWSTR, dwFileAttributes: DWORD) -> BOOL; - pub fn GetFileInformationByHandle(hFile: HANDLE, - lpFileInformation: LPBY_HANDLE_FILE_INFORMATION) - -> BOOL; - pub fn SetLastError(dwErrCode: DWORD); pub fn GetCommandLineW() -> *mut LPCWSTR; pub fn GetTempPathW(nBufferLength: DWORD, diff --git a/src/libstd/sys/windows/fs.rs b/src/libstd/sys/windows/fs.rs index f6f64a008bbfe..2f158c014060b 100644 --- a/src/libstd/sys/windows/fs.rs +++ b/src/libstd/sys/windows/fs.rs @@ -287,6 +287,7 @@ impl File { Ok(()) } + #[cfg(not(target_vendor = "uwp"))] pub fn file_attr(&self) -> io::Result { unsafe { let mut info: c::BY_HANDLE_FILE_INFORMATION = mem::zeroed(); @@ -310,6 +311,49 @@ impl File { } } + #[cfg(target_vendor = "uwp")] + pub fn file_attr(&self) -> io::Result { + unsafe { + let mut info: c::FILE_BASIC_INFO = mem::zeroed(); + let size = mem::size_of_val(&info); + cvt(c::GetFileInformationByHandleEx(self.handle.raw(), + c::FileBasicInfo, + &mut info as *mut _ as *mut libc::c_void, + size as c::DWORD))?; + let mut attr = FileAttr { + attributes: info.FileAttributes, + creation_time: c::FILETIME { + dwLowDateTime: info.CreationTime as c::DWORD, + dwHighDateTime: (info.CreationTime >> 32) as c::DWORD, + }, + last_access_time: c::FILETIME { + dwLowDateTime: info.LastAccessTime as c::DWORD, + dwHighDateTime: (info.LastAccessTime >> 32) as c::DWORD, + }, + last_write_time: c::FILETIME { + dwLowDateTime: info.LastWriteTime as c::DWORD, + dwHighDateTime: (info.LastWriteTime >> 32) as c::DWORD, + }, + file_size: 0, + reparse_tag: 0, + }; + let mut info: c::FILE_STANDARD_INFO = mem::zeroed(); + let size = mem::size_of_val(&info); + cvt(c::GetFileInformationByHandleEx(self.handle.raw(), + c::FileStandardInfo, + &mut info as *mut _ as *mut libc::c_void, + size as c::DWORD))?; + attr.file_size = info.AllocationSize as u64; + if attr.is_reparse_point() { + let mut b = [0; c::MAXIMUM_REPARSE_DATA_BUFFER_SIZE]; + if let Ok((_, buf)) = self.reparse_point(&mut b) { + attr.reparse_tag = buf.ReparseTag; + } + } + Ok(attr) + } + } + pub fn read(&self, buf: &mut [u8]) -> io::Result { self.handle.read(buf) } From 668f0d3495101d547602249785dc175fc11e5fe7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hugo=20Beauz=C3=A9e-Luyssen?= Date: Mon, 27 May 2019 17:15:27 +0200 Subject: [PATCH 11/13] std: win: Don't use console APIs on UWP --- src/libstd/sys/windows/c.rs | 51 ++++++++--------- src/libstd/sys/windows/mod.rs | 9 ++- src/libstd/sys/windows/stdio_uwp.rs | 85 +++++++++++++++++++++++++++++ 3 files changed, 119 insertions(+), 26 deletions(-) create mode 100644 src/libstd/sys/windows/stdio_uwp.rs diff --git a/src/libstd/sys/windows/c.rs b/src/libstd/sys/windows/c.rs index 6b4d6d9e23b81..9d7f3a89d6fdc 100644 --- a/src/libstd/sys/windows/c.rs +++ b/src/libstd/sys/windows/c.rs @@ -35,7 +35,6 @@ pub type ULONG = c_ulong; pub type LPBOOL = *mut BOOL; pub type LPBYTE = *mut BYTE; pub type LPCSTR = *const CHAR; -pub type LPCVOID = *const c_void; pub type LPCWSTR = *const WCHAR; pub type LPDWORD = *mut DWORD; pub type LPHANDLE = *mut HANDLE; @@ -609,16 +608,6 @@ pub enum EXCEPTION_DISPOSITION { ExceptionCollidedUnwind } -#[repr(C)] -#[derive(Copy, Clone)] -pub struct CONSOLE_READCONSOLE_CONTROL { - pub nLength: ULONG, - pub nInitialChars: ULONG, - pub dwCtrlWakeupMask: ULONG, - pub dwControlKeyState: ULONG, -} -pub type PCONSOLE_READCONSOLE_CONTROL = *mut CONSOLE_READCONSOLE_CONTROL; - #[repr(C)] #[derive(Copy)] pub struct fd_set { @@ -642,6 +631,17 @@ pub struct timeval { // Functions forbidden when targeting UWP cfg_if::cfg_if! { if #[cfg(not(target_vendor = "uwp"))] { + #[repr(C)] + #[derive(Copy, Clone)] + pub struct CONSOLE_READCONSOLE_CONTROL { + pub nLength: ULONG, + pub nInitialChars: ULONG, + pub dwCtrlWakeupMask: ULONG, + pub dwControlKeyState: ULONG, + } + + pub type PCONSOLE_READCONSOLE_CONTROL = *mut CONSOLE_READCONSOLE_CONTROL; + #[repr(C)] pub struct BY_HANDLE_FILE_INFORMATION { pub dwFileAttributes: DWORD, @@ -657,6 +657,7 @@ if #[cfg(not(target_vendor = "uwp"))] { } pub type LPBY_HANDLE_FILE_INFORMATION = *mut BY_HANDLE_FILE_INFORMATION; + pub type LPCVOID = *const c_void; pub const HANDLE_FLAG_INHERIT: DWORD = 0x00000001; @@ -666,6 +667,20 @@ if #[cfg(not(target_vendor = "uwp"))] { #[link_name = "SystemFunction036"] pub fn RtlGenRandom(RandomBuffer: *mut u8, RandomBufferLength: ULONG) -> BOOLEAN; + pub fn ReadConsoleW(hConsoleInput: HANDLE, + lpBuffer: LPVOID, + nNumberOfCharsToRead: DWORD, + lpNumberOfCharsRead: LPDWORD, + pInputControl: PCONSOLE_READCONSOLE_CONTROL) -> BOOL; + + pub fn WriteConsoleW(hConsoleOutput: HANDLE, + lpBuffer: LPCVOID, + nNumberOfCharsToWrite: DWORD, + lpNumberOfCharsWritten: LPDWORD, + lpReserved: LPVOID) -> BOOL; + + pub fn GetConsoleMode(hConsoleHandle: HANDLE, + lpMode: LPDWORD) -> BOOL; // Allowed but unused by UWP pub fn OpenProcessToken(ProcessHandle: HANDLE, DesiredAccess: DWORD, @@ -752,20 +767,6 @@ extern "system" { pub fn LeaveCriticalSection(CriticalSection: *mut CRITICAL_SECTION); pub fn DeleteCriticalSection(CriticalSection: *mut CRITICAL_SECTION); - pub fn ReadConsoleW(hConsoleInput: HANDLE, - lpBuffer: LPVOID, - nNumberOfCharsToRead: DWORD, - lpNumberOfCharsRead: LPDWORD, - pInputControl: PCONSOLE_READCONSOLE_CONTROL) -> BOOL; - - pub fn WriteConsoleW(hConsoleOutput: HANDLE, - lpBuffer: LPCVOID, - nNumberOfCharsToWrite: DWORD, - lpNumberOfCharsWritten: LPDWORD, - lpReserved: LPVOID) -> BOOL; - - pub fn GetConsoleMode(hConsoleHandle: HANDLE, - lpMode: LPDWORD) -> BOOL; pub fn RemoveDirectoryW(lpPathName: LPCWSTR) -> BOOL; pub fn SetFileAttributesW(lpFileName: LPCWSTR, dwFileAttributes: DWORD) -> BOOL; diff --git a/src/libstd/sys/windows/mod.rs b/src/libstd/sys/windows/mod.rs index 36fb1fb5ff68d..95465db089fab 100644 --- a/src/libstd/sys/windows/mod.rs +++ b/src/libstd/sys/windows/mod.rs @@ -37,7 +37,14 @@ pub mod stack_overflow; pub mod thread; pub mod thread_local; pub mod time; -pub mod stdio; +cfg_if::cfg_if! { + if #[cfg(not(target_vendor = "uwp"))] { + pub mod stdio; + } else { + pub mod stdio_uwp; + pub use self::stdio_uwp as stdio; + } +} #[cfg(not(test))] pub fn init() { diff --git a/src/libstd/sys/windows/stdio_uwp.rs b/src/libstd/sys/windows/stdio_uwp.rs new file mode 100644 index 0000000000000..489d3df28600b --- /dev/null +++ b/src/libstd/sys/windows/stdio_uwp.rs @@ -0,0 +1,85 @@ +#![unstable(issue = "0", feature = "windows_stdio")] + +use crate::io; +use crate::sys::c; +use crate::sys::handle::Handle; +use crate::mem::ManuallyDrop; + +pub struct Stdin { +} +pub struct Stdout; +pub struct Stderr; + +const MAX_BUFFER_SIZE: usize = 8192; +pub const STDIN_BUF_SIZE: usize = MAX_BUFFER_SIZE / 2 * 3; + +pub fn get_handle(handle_id: c::DWORD) -> io::Result { + let handle = unsafe { c::GetStdHandle(handle_id) }; + if handle == c::INVALID_HANDLE_VALUE { + Err(io::Error::last_os_error()) + } else if handle.is_null() { + Err(io::Error::from_raw_os_error(c::ERROR_INVALID_HANDLE as i32)) + } else { + Ok(handle) + } +} + +fn write(handle_id: c::DWORD, data: &[u8]) -> io::Result { + let handle = get_handle(handle_id)?; + let handle = Handle::new(handle); + ManuallyDrop::new(handle).write(data) +} + +impl Stdin { + pub fn new() -> io::Result { + Ok(Stdin { }) + } +} + +impl io::Read for Stdin { + fn read(&mut self, buf: &mut [u8]) -> io::Result { + let handle = get_handle(c::STD_INPUT_HANDLE)?; + let handle = Handle::new(handle); + ManuallyDrop::new(handle).read(buf) + } +} + +impl Stdout { + pub fn new() -> io::Result { + Ok(Stdout) + } +} + +impl io::Write for Stdout { + fn write(&mut self, buf: &[u8]) -> io::Result { + write(c::STD_OUTPUT_HANDLE, buf) + } + + fn flush(&mut self) -> io::Result<()> { + Ok(()) + } +} + +impl Stderr { + pub fn new() -> io::Result { + Ok(Stderr) + } +} + +impl io::Write for Stderr { + fn write(&mut self, buf: &[u8]) -> io::Result { + write(c::STD_ERROR_HANDLE, buf) + } + + fn flush(&mut self) -> io::Result<()> { + Ok(()) + } +} + +pub fn is_ebadf(err: &io::Error) -> bool { + err.raw_os_error() == Some(c::ERROR_INVALID_HANDLE as i32) +} + +pub fn panic_output() -> Option { + Stderr::new().ok() +} From e88a4cee52ba62aef0632d6d61d12584be30f84f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hugo=20Beauz=C3=A9e-Luyssen?= Date: Mon, 27 May 2019 17:16:20 +0200 Subject: [PATCH 12/13] std: win: Disable stack overflow handling on UWP The required functions are not available, so hope for the best --- src/libstd/sys/windows/c.rs | 57 ++++++++++---------- src/libstd/sys/windows/mod.rs | 4 +- src/libstd/sys/windows/stack_overflow_uwp.rs | 13 +++++ 3 files changed, 45 insertions(+), 29 deletions(-) create mode 100644 src/libstd/sys/windows/stack_overflow_uwp.rs diff --git a/src/libstd/sys/windows/c.rs b/src/libstd/sys/windows/c.rs index 9d7f3a89d6fdc..f706709c9ccf4 100644 --- a/src/libstd/sys/windows/c.rs +++ b/src/libstd/sys/windows/c.rs @@ -256,10 +256,6 @@ pub const WAIT_OBJECT_0: DWORD = 0x00000000; pub const WAIT_TIMEOUT: DWORD = 258; pub const WAIT_FAILED: DWORD = 0xFFFFFFFF; -pub const EXCEPTION_CONTINUE_SEARCH: LONG = 0; -pub const EXCEPTION_STACK_OVERFLOW: DWORD = 0xc00000fd; -pub const EXCEPTION_MAXIMUM_PARAMETERS: usize = 15; - pub const PIPE_ACCESS_INBOUND: DWORD = 0x00000001; pub const PIPE_ACCESS_OUTBOUND: DWORD = 0x00000002; pub const FILE_FLAG_FIRST_PIPE_INSTANCE: DWORD = 0x00080000; @@ -444,25 +440,6 @@ pub struct REPARSE_MOUNTPOINT_DATA_BUFFER { pub ReparseTarget: WCHAR, } -#[repr(C)] -pub struct EXCEPTION_RECORD { - pub ExceptionCode: DWORD, - pub ExceptionFlags: DWORD, - pub ExceptionRecord: *mut EXCEPTION_RECORD, - pub ExceptionAddress: LPVOID, - pub NumberParameters: DWORD, - pub ExceptionInformation: [LPVOID; EXCEPTION_MAXIMUM_PARAMETERS] -} - -#[repr(C)] -pub struct EXCEPTION_POINTERS { - pub ExceptionRecord: *mut EXCEPTION_RECORD, - pub ContextRecord: *mut CONTEXT, -} - -pub type PVECTORED_EXCEPTION_HANDLER = extern "system" - fn(ExceptionInfo: *mut EXCEPTION_POINTERS) -> LONG; - #[repr(C)] pub struct GUID { pub Data1: DWORD, @@ -545,8 +522,6 @@ pub enum ADDRESS_MODE { AddrModeFlat, } -pub enum CONTEXT {} - #[repr(C)] pub struct SOCKADDR_STORAGE_LH { pub ss_family: ADDRESS_FAMILY, @@ -631,6 +606,31 @@ pub struct timeval { // Functions forbidden when targeting UWP cfg_if::cfg_if! { if #[cfg(not(target_vendor = "uwp"))] { + pub const EXCEPTION_CONTINUE_SEARCH: LONG = 0; + pub const EXCEPTION_STACK_OVERFLOW: DWORD = 0xc00000fd; + pub const EXCEPTION_MAXIMUM_PARAMETERS: usize = 15; + + #[repr(C)] + pub struct EXCEPTION_RECORD { + pub ExceptionCode: DWORD, + pub ExceptionFlags: DWORD, + pub ExceptionRecord: *mut EXCEPTION_RECORD, + pub ExceptionAddress: LPVOID, + pub NumberParameters: DWORD, + pub ExceptionInformation: [LPVOID; EXCEPTION_MAXIMUM_PARAMETERS] + } + + pub enum CONTEXT {} + + #[repr(C)] + pub struct EXCEPTION_POINTERS { + pub ExceptionRecord: *mut EXCEPTION_RECORD, + pub ContextRecord: *mut CONTEXT, + } + + pub type PVECTORED_EXCEPTION_HANDLER = extern "system" + fn(ExceptionInfo: *mut EXCEPTION_POINTERS) -> LONG; + #[repr(C)] #[derive(Copy, Clone)] pub struct CONSOLE_READCONSOLE_CONTROL { @@ -694,6 +694,9 @@ if #[cfg(not(target_vendor = "uwp"))] { pub fn SetHandleInformation(hObject: HANDLE, dwMask: DWORD, dwFlags: DWORD) -> BOOL; + pub fn AddVectoredExceptionHandler(FirstHandler: ULONG, + VectoredHandler: PVECTORED_EXCEPTION_HANDLER) + -> LPVOID; pub fn CreateHardLinkW(lpSymlinkFileName: LPCWSTR, lpTargetFileName: LPCWSTR, lpSecurityAttributes: LPSECURITY_ATTRIBUTES) @@ -804,9 +807,6 @@ extern "system" { lpData: LPVOID, pbCancel: LPBOOL, dwCopyFlags: DWORD) -> BOOL; - pub fn AddVectoredExceptionHandler(FirstHandler: ULONG, - VectoredHandler: PVECTORED_EXCEPTION_HANDLER) - -> LPVOID; pub fn FormatMessageW(flags: DWORD, lpSrc: LPVOID, msgId: DWORD, @@ -1015,6 +1015,7 @@ compat_fn! { _dwFlags: DWORD) -> DWORD { SetLastError(ERROR_CALL_NOT_IMPLEMENTED as DWORD); 0 } + #[cfg(not(target_vendor = "uwp"))] pub fn SetThreadStackGuarantee(_size: *mut c_ulong) -> BOOL { SetLastError(ERROR_CALL_NOT_IMPLEMENTED as DWORD); 0 } diff --git a/src/libstd/sys/windows/mod.rs b/src/libstd/sys/windows/mod.rs index 95465db089fab..d59ac5959a678 100644 --- a/src/libstd/sys/windows/mod.rs +++ b/src/libstd/sys/windows/mod.rs @@ -33,16 +33,18 @@ pub mod pipe; pub mod process; pub mod rand; pub mod rwlock; -pub mod stack_overflow; pub mod thread; pub mod thread_local; pub mod time; cfg_if::cfg_if! { if #[cfg(not(target_vendor = "uwp"))] { pub mod stdio; + pub mod stack_overflow; } else { pub mod stdio_uwp; + pub mod stack_overflow_uwp; pub use self::stdio_uwp as stdio; + pub use self::stack_overflow_uwp as stack_overflow; } } diff --git a/src/libstd/sys/windows/stack_overflow_uwp.rs b/src/libstd/sys/windows/stack_overflow_uwp.rs new file mode 100644 index 0000000000000..e7236cf359cd5 --- /dev/null +++ b/src/libstd/sys/windows/stack_overflow_uwp.rs @@ -0,0 +1,13 @@ +#![cfg_attr(test, allow(dead_code))] + +pub struct Handler; + +impl Handler { + pub fn new() -> Handler { + Handler + } +} + +pub unsafe fn init() {} + +pub unsafe fn cleanup() {} From 7ed5c36934c8023a0e55c8708dec87774212ca23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hugo=20Beauz=C3=A9e-Luyssen?= Date: Mon, 27 May 2019 17:18:14 +0200 Subject: [PATCH 13/13] Add UWP mingw targets --- .../spec/i686_uwp_windows_gnu.rs | 27 ++++++++ src/librustc_target/spec/mod.rs | 3 + src/librustc_target/spec/windows_uwp_base.rs | 64 +++++++++++++++++++ .../spec/x86_64_uwp_windows_gnu.rs | 22 +++++++ 4 files changed, 116 insertions(+) create mode 100644 src/librustc_target/spec/i686_uwp_windows_gnu.rs create mode 100644 src/librustc_target/spec/windows_uwp_base.rs create mode 100644 src/librustc_target/spec/x86_64_uwp_windows_gnu.rs diff --git a/src/librustc_target/spec/i686_uwp_windows_gnu.rs b/src/librustc_target/spec/i686_uwp_windows_gnu.rs new file mode 100644 index 0000000000000..3ad77525eb37d --- /dev/null +++ b/src/librustc_target/spec/i686_uwp_windows_gnu.rs @@ -0,0 +1,27 @@ +use crate::spec::{LinkerFlavor, Target, TargetResult}; + +pub fn target() -> TargetResult { + let mut base = super::windows_uwp_base::opts(); + base.cpu = "pentium4".to_string(); + base.max_atomic_width = Some(64); + base.eliminate_frame_pointer = false; // Required for backtraces + + // Mark all dynamic libraries and executables as compatible with the larger 4GiB address + // space available to x86 Windows binaries on x86_64. + base.pre_link_args + .get_mut(&LinkerFlavor::Gcc).unwrap().push("-Wl,--large-address-aware".to_string()); + + Ok(Target { + llvm_target: "i686-pc-windows-gnu".to_string(), + target_endian: "little".to_string(), + target_pointer_width: "32".to_string(), + target_c_int_width: "32".to_string(), + data_layout: "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32".to_string(), + arch: "x86".to_string(), + target_os: "windows".to_string(), + target_env: "gnu".to_string(), + target_vendor: "uwp".to_string(), + linker_flavor: LinkerFlavor::Gcc, + options: base, + }) +} diff --git a/src/librustc_target/spec/mod.rs b/src/librustc_target/spec/mod.rs index 34b580acbd5c0..f80e58f953899 100644 --- a/src/librustc_target/spec/mod.rs +++ b/src/librustc_target/spec/mod.rs @@ -60,6 +60,7 @@ mod solaris_base; mod uefi_base; mod windows_base; mod windows_msvc_base; +mod windows_uwp_base; mod thumb_base; mod l4re_base; mod fuchsia_base; @@ -434,6 +435,8 @@ supported_targets! { ("x86_64-pc-windows-gnu", x86_64_pc_windows_gnu), ("i686-pc-windows-gnu", i686_pc_windows_gnu), + ("i686-uwp-windows-gnu", i686_uwp_windows_gnu), + ("x86_64-uwp-windows-gnu", x86_64_uwp_windows_gnu), ("aarch64-pc-windows-msvc", aarch64_pc_windows_msvc), ("x86_64-pc-windows-msvc", x86_64_pc_windows_msvc), diff --git a/src/librustc_target/spec/windows_uwp_base.rs b/src/librustc_target/spec/windows_uwp_base.rs new file mode 100644 index 0000000000000..108dbc417cbb3 --- /dev/null +++ b/src/librustc_target/spec/windows_uwp_base.rs @@ -0,0 +1,64 @@ +use crate::spec::{LinkArgs, LinkerFlavor, TargetOptions}; +use std::default::Default; + +pub fn opts() -> TargetOptions { + let mut pre_link_args = LinkArgs::new(); + pre_link_args.insert(LinkerFlavor::Gcc, vec![ + // Tell GCC to avoid linker plugins, because we are not bundling + // them with Windows installer, and Rust does its own LTO anyways. + "-fno-use-linker-plugin".to_string(), + + // Always enable DEP (NX bit) when it is available + "-Wl,--nxcompat".to_string(), + ]); + + let mut late_link_args = LinkArgs::new(); + late_link_args.insert(LinkerFlavor::Gcc, vec![ + //"-lwinstorecompat".to_string(), + //"-lmingwex".to_string(), + //"-lwinstorecompat".to_string(), + "-lwinstorecompat".to_string(), + "-lruntimeobject".to_string(), + "-lsynchronization".to_string(), + "-lvcruntime140_app".to_string(), + "-lucrt".to_string(), + "-lwindowsapp".to_string(), + "-lmingwex".to_string(), + "-lmingw32".to_string(), + ]); + + TargetOptions { + // FIXME(#13846) this should be enabled for windows + function_sections: false, + linker: Some("gcc".to_string()), + dynamic_linking: true, + executables: false, + dll_prefix: String::new(), + dll_suffix: ".dll".to_string(), + exe_suffix: ".exe".to_string(), + staticlib_prefix: "lib".to_string(), + staticlib_suffix: ".a".to_string(), + no_default_libraries: true, + target_family: Some("windows".to_string()), + is_like_windows: true, + allows_weak_linkage: false, + pre_link_args, + pre_link_objects_exe: vec![ + "rsbegin.o".to_string(), // Rust compiler runtime initialization, see rsbegin.rs + ], + pre_link_objects_dll: vec![ + "rsbegin.o".to_string(), + ], + late_link_args, + post_link_objects: vec![ + "rsend.o".to_string(), + ], + custom_unwind_resume: true, + abi_return_struct_as_int: true, + emit_debug_gdb_scripts: false, + requires_uwtable: true, + limit_rdylib_exports: false, + + .. Default::default() + } +} diff --git a/src/librustc_target/spec/x86_64_uwp_windows_gnu.rs b/src/librustc_target/spec/x86_64_uwp_windows_gnu.rs new file mode 100644 index 0000000000000..da0c324e48618 --- /dev/null +++ b/src/librustc_target/spec/x86_64_uwp_windows_gnu.rs @@ -0,0 +1,22 @@ +use crate::spec::{LinkerFlavor, Target, TargetResult}; + +pub fn target() -> TargetResult { + let mut base = super::windows_uwp_base::opts(); + base.cpu = "x86-64".to_string(); + base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string()); + base.max_atomic_width = Some(64); + + Ok(Target { + llvm_target: "x86_64-pc-windows-gnu".to_string(), + target_endian: "little".to_string(), + target_pointer_width: "64".to_string(), + target_c_int_width: "32".to_string(), + data_layout: "e-m:w-i64:64-f80:128-n8:16:32:64-S128".to_string(), + arch: "x86_64".to_string(), + target_os: "windows".to_string(), + target_env: "gnu".to_string(), + target_vendor: "uwp".to_string(), + linker_flavor: LinkerFlavor::Gcc, + options: base, + }) +}