about summary refs log tree commit diff
diff options
context:
space:
mode:
authorDaniel Paoliello <danpao@microsoft.com>2024-08-02 13:53:09 -0700
committerDaniel Paoliello <danpao@microsoft.com>2024-08-08 13:51:58 -0700
commit2756bd6ff77232a198adeb6e4083866484a469f3 (patch)
tree303bc656dd063923386a2d0b22c335cde7418780
parentfdc6a5562b07192992592577a49333766b104bf1 (diff)
downloadrust-2756bd6ff77232a198adeb6e4083866484a469f3.tar.gz
rust-2756bd6ff77232a198adeb6e4083866484a469f3.zip
Add support for raw-dylib
-rw-r--r--Cargo.lock14
-rw-r--r--Cargo.toml1
-rw-r--r--build_system/tests.rs1
-rw-r--r--config.txt1
-rw-r--r--example/raw-dylib.rs31
-rw-r--r--patches/0029-stdlib-rawdylib-processprng.patch47
-rw-r--r--patches/0030-stdlib-Revert-use-raw-dylib-for-Windows-futex-APIs.patch37
-rw-r--r--src/archive.rs79
8 files changed, 120 insertions, 91 deletions
diff --git a/Cargo.lock b/Cargo.lock
index b065720c9ce..741a1748fec 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -21,6 +21,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da"
 
 [[package]]
+name = "ar_archive_writer"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3f2bcb7cf51decfbbfc7ef476e28b0775b13e5eb1190f8b7df145cd53d4f4374"
+dependencies = [
+ "object",
+]
+
+[[package]]
 name = "arbitrary"
 version = "1.3.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -289,9 +298,9 @@ checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
 
 [[package]]
 name = "object"
-version = "0.36.1"
+version = "0.36.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "081b846d1d56ddfc18fdf1a922e4f6e07a11768ea1b92dec44e42b72712ccfce"
+checksum = "3f203fa8daa7bb185f760ae12bd8e097f63d17041dcdcaf675ac54cdf863170e"
 dependencies = [
  "crc32fast",
  "hashbrown 0.14.5",
@@ -358,6 +367,7 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
 name = "rustc_codegen_cranelift"
 version = "0.1.0"
 dependencies = [
+ "ar_archive_writer",
  "cranelift-codegen",
  "cranelift-frontend",
  "cranelift-jit",
diff --git a/Cargo.toml b/Cargo.toml
index a0df502dadc..c86919dcdfb 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -17,6 +17,7 @@ cranelift-object = { version = "0.110.1" }
 target-lexicon = "0.12.0"
 gimli = { version = "0.28", default-features = false, features = ["write"]}
 object = { version = "0.36", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] }
+ar_archive_writer = "0.3"
 
 indexmap = "2.0.0"
 libloading = { version = "0.8.0", optional = true }
diff --git a/build_system/tests.rs b/build_system/tests.rs
index afc8a923863..3a88824bf36 100644
--- a/build_system/tests.rs
+++ b/build_system/tests.rs
@@ -106,6 +106,7 @@ const BASE_SYSROOT_SUITE: &[TestCase] = &[
         ]);
         runner.run_out_command("gen_block_iterate", &[]);
     }),
+    TestCase::build_bin_and_run("aot.raw-dylib", "example/raw-dylib.rs", &[]),
 ];
 
 pub(crate) static RAND_REPO: GitRepo = GitRepo::github(
diff --git a/config.txt b/config.txt
index 0b7cac18837..527ec5303b6 100644
--- a/config.txt
+++ b/config.txt
@@ -45,6 +45,7 @@ aot.issue-59326
 aot.polymorphize_coroutine
 aot.neon
 aot.gen_block_iterate
+aot.raw-dylib
 
 testsuite.extended_sysroot
 test.rust-random/rand
diff --git a/example/raw-dylib.rs b/example/raw-dylib.rs
new file mode 100644
index 00000000000..4711884f76a
--- /dev/null
+++ b/example/raw-dylib.rs
@@ -0,0 +1,31 @@
+// Tests the raw-dylib feature for Windows.
+// https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute
+
+fn main() {
+    #[cfg(windows)]
+    {
+        #[link(name = "kernel32", kind = "raw-dylib")]
+        extern "C" {
+            fn GetModuleFileNameA(
+                module: *mut std::ffi::c_void,
+                filename: *mut u8,
+                size: u32,
+            ) -> u32;
+        }
+
+        // Get the filename of the current executable....
+        let mut buffer = [0u8; 1024];
+        let size = unsafe {
+            GetModuleFileNameA(core::ptr::null_mut(), buffer.as_mut_ptr(), buffer.len() as u32)
+        };
+        if size == 0 {
+            eprintln!("failed to get module file name: {}", std::io::Error::last_os_error());
+            return;
+        } else {
+            // ...and make sure that it matches the test name.
+            let filename =
+                std::ffi::CStr::from_bytes_with_nul(&buffer[..size as usize + 1]).unwrap();
+            assert!(filename.to_str().unwrap().ends_with("raw-dylib.exe"));
+        }
+    }
+}
diff --git a/patches/0029-stdlib-rawdylib-processprng.patch b/patches/0029-stdlib-rawdylib-processprng.patch
deleted file mode 100644
index 584dbdb647f..00000000000
--- a/patches/0029-stdlib-rawdylib-processprng.patch
+++ /dev/null
@@ -1,47 +0,0 @@
-From 9f65e742ba3e41474e6126c6c4469c48eaa6ca7e Mon Sep 17 00:00:00 2001
-From: Chris Denton <chris@chrisdenton.dev>
-Date: Tue, 20 Feb 2024 16:01:40 -0300
-Subject: [PATCH] Don't use raw-dylib in std
-
----
- library/std/src/sys/pal/windows/c.rs    | 2 +-
- library/std/src/sys/pal/windows/rand.rs | 3 +--
- 2 files changed, 2 insertions(+), 3 deletions(-)
-
-diff --git a/library/std/src/sys/pal/windows/c.rs b/library/std/src/sys/pal/windows/c.rs
-index ad8e01bfa9b..9ca8e4c16ce 100644
---- a/library/std/src/sys/pal/windows/c.rs
-+++ b/library/std/src/sys/pal/windows/c.rs
-@@ -312,7 +312,7 @@ pub unsafe fn NtWriteFile(
- 
- // Use raw-dylib to import ProcessPrng as we can't rely on there being an import library.
- cfg_if::cfg_if! {
--if #[cfg(not(target_vendor = "win7"))] {
-+if #[cfg(any())] {
-     #[cfg(target_arch = "x86")]
-     #[link(name = "bcryptprimitives", kind = "raw-dylib", import_name_type = "undecorated")]
-     extern "system" {
-diff --git a/library/std/src/sys/pal/windows/rand.rs b/library/std/src/sys/pal/windows/rand.rs
-index e427546222a..f2fe42a4d51 100644
---- a/library/std/src/sys/pal/windows/rand.rs
-+++ b/library/std/src/sys/pal/windows/rand.rs
-@@ -2,7 +2,7 @@
- 
- use crate::sys::c;
- 
--#[cfg(not(target_vendor = "win7"))]
-+#[cfg(any())]
- #[inline]
- pub fn hashmap_random_keys() -> (u64, u64) {
-     let mut v = (0, 0);
-@@ -13,7 +13,6 @@ pub fn hashmap_random_keys() -> (u64, u64) {
-     v
- }
- 
--#[cfg(target_vendor = "win7")]
- pub fn hashmap_random_keys() -> (u64, u64) {
-     use crate::ffi::c_void;
-     use crate::io;
--- 
-2.42.0.windows.2
-
diff --git a/patches/0030-stdlib-Revert-use-raw-dylib-for-Windows-futex-APIs.patch b/patches/0030-stdlib-Revert-use-raw-dylib-for-Windows-futex-APIs.patch
deleted file mode 100644
index 21f5ee9cc6e..00000000000
--- a/patches/0030-stdlib-Revert-use-raw-dylib-for-Windows-futex-APIs.patch
+++ /dev/null
@@ -1,37 +0,0 @@
-From 0d741cf82c3c908616abd39dc84ebf7d8702e0c3 Mon Sep 17 00:00:00 2001
-From: Chris Denton <chris@chrisdenton.dev>
-Date: Tue, 16 Apr 2024 15:51:34 +0000
-Subject: [PATCH] Revert use raw-dylib for Windows futex APIs
-
----
- library/std/src/sys/pal/windows/c.rs | 14 +-------------
- 1 file changed, 1 insertion(+), 13 deletions(-)
-
-diff --git a/library/std/src/sys/pal/windows/c.rs b/library/std/src/sys/pal/windows/c.rs
-index 9d58ce05f01..1c828bac4b6 100644
---- a/library/std/src/sys/pal/windows/c.rs
-+++ b/library/std/src/sys/pal/windows/c.rs
-@@ -357,19 +357,7 @@ pub fn GetTempPath2W(bufferlength: u32, buffer: PWSTR) -> u32 {
- }
- 
- #[cfg(not(target_vendor = "win7"))]
--// Use raw-dylib to import synchronization functions to workaround issues with the older mingw import library.
--#[cfg_attr(
--    target_arch = "x86",
--    link(
--        name = "api-ms-win-core-synch-l1-2-0",
--        kind = "raw-dylib",
--        import_name_type = "undecorated"
--    )
--)]
--#[cfg_attr(
--    not(target_arch = "x86"),
--    link(name = "api-ms-win-core-synch-l1-2-0", kind = "raw-dylib")
--)]
-+#[link(name = "synchronization")]
- extern "system" {
-     pub fn WaitOnAddress(
-         address: *const c_void,
--- 
-2.42.0.windows.2
-
diff --git a/src/archive.rs b/src/archive.rs
index 084654af09d..5eedab4f2cb 100644
--- a/src/archive.rs
+++ b/src/archive.rs
@@ -1,8 +1,13 @@
+use std::borrow::Borrow;
+use std::fs;
 use std::path::Path;
 
+use ar_archive_writer::{COFFShortExport, MachineTypes};
 use rustc_codegen_ssa::back::archive::{
-    ArArchiveBuilder, ArchiveBuilder, ArchiveBuilderBuilder, DEFAULT_OBJECT_READER,
+    create_mingw_dll_import_lib, ArArchiveBuilder, ArchiveBuilder, ArchiveBuilderBuilder,
+    DEFAULT_OBJECT_READER,
 };
+use rustc_codegen_ssa::common::is_mingw_gnu_toolchain;
 use rustc_session::Session;
 
 pub(crate) struct ArArchiveBuilderBuilder;
@@ -15,10 +20,74 @@ impl ArchiveBuilderBuilder for ArArchiveBuilderBuilder {
     fn create_dll_import_lib(
         &self,
         sess: &Session,
-        _lib_name: &str,
-        _import_name_and_ordinal_vector: Vec<(String, Option<u16>)>,
-        _output_path: &Path,
+        lib_name: &str,
+        import_name_and_ordinal_vector: Vec<(String, Option<u16>)>,
+        output_path: &Path,
     ) {
-        sess.dcx().fatal("raw-dylib is not yet supported by rustc_codegen_cranelift");
+        if is_mingw_gnu_toolchain(&sess.target) {
+            // The binutils linker used on -windows-gnu targets cannot read the import
+            // libraries generated by LLVM: in our attempts, the linker produced an .EXE
+            // that loaded but crashed with an AV upon calling one of the imported
+            // functions. Therefore, use binutils to create the import library instead,
+            // by writing a .DEF file to the temp dir and calling binutils's dlltool.
+            create_mingw_dll_import_lib(
+                sess,
+                lib_name,
+                import_name_and_ordinal_vector,
+                output_path,
+            );
+        } else {
+            let mut file =
+                match fs::OpenOptions::new().write(true).create_new(true).open(&output_path) {
+                    Ok(file) => file,
+                    Err(error) => {
+                        sess.dcx().fatal(format!(
+                            "failed to create import library file `{path}`: {error}",
+                            path = output_path.display(),
+                        ));
+                    }
+                };
+
+            let machine = match sess.target.arch.borrow() {
+                "x86" => MachineTypes::I386,
+                "x86_64" => MachineTypes::AMD64,
+                "arm" => MachineTypes::ARMNT,
+                "aarch64" => MachineTypes::ARM64,
+                _ => {
+                    sess.dcx().fatal(format!(
+                        "unsupported target architecture `{arch}`",
+                        arch = sess.target.arch,
+                    ));
+                }
+            };
+
+            let exports = import_name_and_ordinal_vector
+                .iter()
+                .map(|(name, ordinal)| COFFShortExport {
+                    name: name.to_string(),
+                    ext_name: None,
+                    symbol_name: None,
+                    alias_target: None,
+                    ordinal: ordinal.unwrap_or(0),
+                    noname: ordinal.is_some(),
+                    data: false,
+                    private: false,
+                    constant: false,
+                })
+                .collect::<Vec<_>>();
+
+            if let Err(error) = ar_archive_writer::write_import_library(
+                &mut file,
+                lib_name,
+                &exports,
+                machine,
+                !sess.target.is_like_msvc,
+            ) {
+                sess.dcx().fatal(format!(
+                    "failed to create import library `{path}`: `{error}`",
+                    path = output_path.display(),
+                ));
+            }
+        }
     }
 }