From e5635f4bc98367f68e2d17d37907163ee0c05ee1 Mon Sep 17 00:00:00 2001 From: whitequark Date: Thu, 21 May 2020 18:56:20 +0000 Subject: [PATCH] winx: do not link directly to ntdll.dll. (#1739) The documentation for RtlNtStatusToDosError explicitly tells to call it via GetProcAddress. The documentation for NtQueryInformationFile does not, but similar considerations apply because there is normally no import library for ntdll. The main reason to use GetProcAddress though is because MinGW does include an import library for ntdll, this import library contains a definition of setjmp, and because of the way rustc orders linker arguments, this definition of setjmp conflicts with and gets picked over the one in msvcrt. Using setjmp from ntdll is undesirable as it is an undocumented API and it is missing from wine, making it harder to develop wasmtime using a cross-compiler. Fixes #1738. --- crates/wasi-common/winx/src/ntdll.rs | 37 +++++++++++++++++++++++----- 1 file changed, 31 insertions(+), 6 deletions(-) diff --git a/crates/wasi-common/winx/src/ntdll.rs b/crates/wasi-common/winx/src/ntdll.rs index 2948aee79a..110c80fa33 100644 --- a/crates/wasi-common/winx/src/ntdll.rs +++ b/crates/wasi-common/winx/src/ntdll.rs @@ -6,7 +6,9 @@ use std::ffi::c_void; use std::os::raw::c_ulong; use std::os::windows::prelude::RawHandle; +use std::sync::atomic::{AtomicUsize, Ordering}; use winapi::shared::ntdef::NTSTATUS; +use winapi::um::libloaderapi::{GetModuleHandleA, GetProcAddress}; use winapi::um::winnt::ACCESS_MASK; #[repr(C)] @@ -49,17 +51,40 @@ impl Default for IO_STATUS_BLOCK { } } -#[link(name = "ntdll")] -extern "C" { +macro_rules! ntdll_import { + { fn $name:ident($($arg:ident: $argty:ty),*) -> $retty:ty; $($tail:tt)* } => { + pub(crate) unsafe fn $name($($arg: $argty),*) -> $retty { + static ADDRESS: AtomicUsize = AtomicUsize::new(0); + let address = match ADDRESS.load(Ordering::Relaxed) { + 0 => { + let ntdll = GetModuleHandleA("ntdll\0".as_ptr() as *const i8); + let address = GetProcAddress( + ntdll, + concat!(stringify!($name), "\0").as_ptr() as *const i8, + ) as usize; + assert!(address != 0); + ADDRESS.store(address, Ordering::Relaxed); + address + } + address => address + }; + let func: unsafe fn($($argty),*) -> $retty = std::mem::transmute(address); + func($($arg),*) + } + ntdll_import! { $($tail)* } + }; + {} => {}; +} + +ntdll_import! { // https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/ntifs/nf-ntifs-ntqueryinformationfile - pub(crate) fn NtQueryInformationFile( + fn NtQueryInformationFile( FileHandle: RawHandle, IoStatusBlock: *mut IO_STATUS_BLOCK, FileInformation: *mut c_void, Length: c_ulong, - FileInformationClass: FILE_INFORMATION_CLASS, + FileInformationClass: FILE_INFORMATION_CLASS ) -> NTSTATUS; - // https://docs.microsoft.com/en-us/windows/win32/api/winternl/nf-winternl-rtlntstatustodoserror - pub(crate) fn RtlNtStatusToDosError(status: NTSTATUS) -> c_ulong; + fn RtlNtStatusToDosError(status: NTSTATUS) -> c_ulong; }