From d94759e59263c2df61f933fc53ed6fd6ff8227a5 Mon Sep 17 00:00:00 2001 From: novafacing Date: Wed, 10 Jan 2024 00:33:43 -0800 Subject: [PATCH 1/4] Bump version --- .github/workflows/ci.yml | 5 +- Cargo.toml | 8 +- README.md | 2 +- qemu-plugin-sys/generate-bindings.rs | 2 +- qemu-plugin/Cargo.toml | 2 +- qemu-plugin/README.md | 2 +- qemu-plugin/src/lib.rs | 2 +- qemu/README.md | 6 +- qemu/build.rs | 2 +- qemu/src/lib.rs | 206 ++++++++++++++++++--------- 10 files changed, 154 insertions(+), 83 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fbe1ad9..744ee11 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -42,8 +42,9 @@ jobs: name: Build and Test Plugins (Windows) runs-on: windows-latest env: - # QEMU 8.1.0 - QEMU_URL: "https://qemu.weilnetz.de/w64/2023/qemu-w64-setup-20230822.exe" + # QEMU 8.2.0 + # NOTE: This installer does not work headless + # QEMU_URL: "https://qemu.weilnetz.de/w64/2023/qemu-w64-setup-20231224.exe" RUSTUP_URL: "https://win.rustup.rs/x86_64" FEDORA_CLOUDIMG_URL: "https://download.fedoraproject.org/pub/fedora/linux/releases/39/Cloud/x86_64/images/Fedora-Cloud-Base-39-1.5.x86_64.qcow2" diff --git a/Cargo.toml b/Cargo.toml index 83106af..edd3c26 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,7 +8,7 @@ license = "GPL-2.0-only" publish = true readme = "README.md" repository = "https://github.com/novafacing/qemu-rs" -version = "8.1.3-v4" +version = "8.2.0-v1" [workspace] resolver = "2" @@ -23,6 +23,6 @@ members = [ default-members = ["qemu-plugin", "qemu-plugin-sys"] [workspace.dependencies] -qemu-plugin-sys = { version = "8.1.3-v4", path = "qemu-plugin-sys" } -qemu-plugin = { version = "8.1.3-v4", path = "qemu-plugin" } -qemu = { version = "8.1.3-v4", path = "qemu" } +qemu-plugin-sys = { version = "8.2.0-v1", path = "qemu-plugin-sys" } +qemu-plugin = { version = "8.2.0-v1", path = "qemu-plugin" } +qemu = { version = "8.2.0-v1", path = "qemu" } diff --git a/README.md b/README.md index d3570b0..4beb7f2 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ installs Rust wrappers for QEMU as binaries. You can install QEMU with (add any additional features you need, e.g. `plugins`): ```sh -cargo install qemu@8.1.3-v3 --features=binaries +cargo install qemu@8.2.0-v1 --features=binaries ``` On some systems, particularly BTRFS systems, `/tmp` may not be large enough for the diff --git a/qemu-plugin-sys/generate-bindings.rs b/qemu-plugin-sys/generate-bindings.rs index 8be0987..2e3b388 100755 --- a/qemu-plugin-sys/generate-bindings.rs +++ b/qemu-plugin-sys/generate-bindings.rs @@ -28,7 +28,7 @@ use tar::Archive; use xz2::read::XzDecoder; const QEMU_SRC_URL_BASE: &str = "https://download.qemu.org/"; -const QEMU_VERSION: &str = "8.1.3"; +const QEMU_VERSION: &str = "8.2.0"; fn qemu_src_url() -> String { format!("{}qemu-{}.tar.xz", QEMU_SRC_URL_BASE, QEMU_VERSION) diff --git a/qemu-plugin/Cargo.toml b/qemu-plugin/Cargo.toml index b0c0c52..b43d098 100644 --- a/qemu-plugin/Cargo.toml +++ b/qemu-plugin/Cargo.toml @@ -14,7 +14,7 @@ version.workspace = true [dependencies] anyhow = "1.0.75" once_cell = "1.19.0" -qemu-plugin-sys = { version = "8.1.3-v3", workspace = true } +qemu-plugin-sys = { version = "8.2.0-v1", workspace = true } thiserror = "1.0.51" [target.'cfg(windows)'.dependencies.windows] diff --git a/qemu-plugin/README.md b/qemu-plugin/README.md index df947e6..94d1470 100644 --- a/qemu-plugin/README.md +++ b/qemu-plugin/README.md @@ -65,7 +65,7 @@ edition = "2021" crate-type = ["cdylib"] [dependencies] -qemu-plugin = "8.1.3-v1" +qemu-plugin = "8.2.0-v1" anyhow = "1.0.75" ffi = "0.1.0" ctor = "0.2.6" diff --git a/qemu-plugin/src/lib.rs b/qemu-plugin/src/lib.rs index 1f2b8e5..31d8c0c 100644 --- a/qemu-plugin/src/lib.rs +++ b/qemu-plugin/src/lib.rs @@ -64,7 +64,7 @@ //! crate-type = ["cdylib"] //! //! [dependencies] -//! qemu-plugin = "8.1.3-v1" +//! qemu-plugin = "8.2.0-v1" //! anyhow = "1.0.75" //! ffi = "0.1.0" //! ctor = "0.2.6" diff --git a/qemu/README.md b/qemu/README.md index 9d6489a..4a1b313 100644 --- a/qemu/README.md +++ b/qemu/README.md @@ -78,7 +78,7 @@ license = "MIT" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] memfd-exec = "2.1.0" -qemu = { version = "8.1.3", features = ["qemu-aarch64"] } +qemu = { version = "8.2.0", features = ["qemu-aarch64"] } ``` ```rust @@ -115,7 +115,7 @@ to configure this crate as a dependency: This will make the `qemu-x86_64` binary available. ```toml -qemu = { version = "8.1.3", features = ["qemu-x86_64"] } +qemu = { version = "8.2.0", features = ["qemu-x86_64"] } ``` ### Install an optimized qemu-x86_64 usermode emulator @@ -124,7 +124,7 @@ This will also make the `qemu-x86_64` binary available, but will strip and optim with `lto`. ```toml -qemu = { version = "8.1.3", features = ["qemu-x86_64", "lto", "strip"] +qemu = { version = "8.2.0", features = ["qemu-x86_64", "lto", "strip"] ``` ### Install qemu-system-arm emulator with customized options diff --git a/qemu/build.rs b/qemu/build.rs index 5caa5f7..695957d 100644 --- a/qemu/build.rs +++ b/qemu/build.rs @@ -14,7 +14,7 @@ use tar::Archive; use xz2::read::XzDecoder; const QEMU_SRC_URL_BASE: &str = "https://download.qemu.org/"; -const QEMU_VERSION: &str = "8.1.3"; +const QEMU_VERSION: &str = "8.2.0"; pub struct ConfigureArgs(Vec); diff --git a/qemu/src/lib.rs b/qemu/src/lib.rs index 8edb562..4efffbd 100644 --- a/qemu/src/lib.rs +++ b/qemu/src/lib.rs @@ -20,271 +20,341 @@ //! write it to disk and run it, or you can be very efficient and use something like //! [memfd-exec](https://crates.io/crates/memfd-exec) to run it from memory directly, or on //! a separate thread, whatever! -//! +//! //! To install with binaries, `cargo install qemu --features=binaries,plugins,lto` -pub const QEMU_VERSION: &str = "8.1.3"; +pub const QEMU_VERSION: &str = "8.2.0"; #[cfg(all(feature = "aarch64-linux-user", not(docs_rs)))] /// QEMU binary for qemu-aarch64 -pub const QEMU_AARCH64_LINUX_USER: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-aarch64")); +pub const QEMU_AARCH64_LINUX_USER: &[u8] = + include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-aarch64")); #[cfg(all(feature = "aarch64_be-linux-user", not(docs_rs)))] /// QEMU binary for qemu-aarch64_be -pub const QEMU_AARCH64_BE_LINUX_USER: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-aarch64_be")); +pub const QEMU_AARCH64_BE_LINUX_USER: &[u8] = + include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-aarch64_be")); #[cfg(all(feature = "alpha-linux-user", not(docs_rs)))] /// QEMU binary for qemu-alpha -pub const QEMU_ALPHA_LINUX_USER: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-alpha")); +pub const QEMU_ALPHA_LINUX_USER: &[u8] = + include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-alpha")); #[cfg(all(feature = "arm-linux-user", not(docs_rs)))] /// QEMU binary for qemu-arm -pub const QEMU_ARM_LINUX_USER: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-arm")); +pub const QEMU_ARM_LINUX_USER: &[u8] = + include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-arm")); #[cfg(all(feature = "armeb-linux-user", not(docs_rs)))] /// QEMU binary for qemu-armeb -pub const QEMU_ARMEB_LINUX_USER: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-armeb")); +pub const QEMU_ARMEB_LINUX_USER: &[u8] = + include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-armeb")); #[cfg(all(feature = "cris-linux-user", not(docs_rs)))] /// QEMU binary for qemu-cris -pub const QEMU_CRIS_LINUX_USER: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-cris")); +pub const QEMU_CRIS_LINUX_USER: &[u8] = + include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-cris")); #[cfg(all(feature = "hexagon-linux-user", not(docs_rs)))] /// QEMU binary for qemu-hexagon -pub const QEMU_HEXAGON_LINUX_USER: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-hexagon")); +pub const QEMU_HEXAGON_LINUX_USER: &[u8] = + include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-hexagon")); #[cfg(all(feature = "hppa-linux-user", not(docs_rs)))] /// QEMU binary for qemu-hppa -pub const QEMU_HPPA_LINUX_USER: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-hppa")); +pub const QEMU_HPPA_LINUX_USER: &[u8] = + include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-hppa")); #[cfg(all(feature = "i386-linux-user", not(docs_rs)))] /// QEMU binary for qemu-i386 -pub const QEMU_I386_LINUX_USER: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-i386")); +pub const QEMU_I386_LINUX_USER: &[u8] = + include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-i386")); #[cfg(all(feature = "loongarch64-linux-user", not(docs_rs)))] /// QEMU binary for qemu-loongarch64 -pub const QEMU_LOONGARCH64_LINUX_USER: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-loongarch64")); +pub const QEMU_LOONGARCH64_LINUX_USER: &[u8] = + include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-loongarch64")); #[cfg(all(feature = "m68k-linux-user", not(docs_rs)))] /// QEMU binary for qemu-m68k -pub const QEMU_M68K_LINUX_USER: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-m68k")); +pub const QEMU_M68K_LINUX_USER: &[u8] = + include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-m68k")); #[cfg(all(feature = "microblaze-linux-user", not(docs_rs)))] /// QEMU binary for qemu-microblaze -pub const QEMU_MICROBLAZE_LINUX_USER: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-microblaze")); +pub const QEMU_MICROBLAZE_LINUX_USER: &[u8] = + include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-microblaze")); #[cfg(all(feature = "microblazeel-linux-user", not(docs_rs)))] /// QEMU binary for qemu-microblazeel -pub const QEMU_MICROBLAZEEL_LINUX_USER: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-microblazeel")); +pub const QEMU_MICROBLAZEEL_LINUX_USER: &[u8] = + include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-microblazeel")); #[cfg(all(feature = "mips-linux-user", not(docs_rs)))] /// QEMU binary for qemu-mips -pub const QEMU_MIPS_LINUX_USER: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-mips")); +pub const QEMU_MIPS_LINUX_USER: &[u8] = + include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-mips")); #[cfg(all(feature = "mips64-linux-user", not(docs_rs)))] /// QEMU binary for qemu-mips64 -pub const QEMU_MIPS64_LINUX_USER: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-mips64")); +pub const QEMU_MIPS64_LINUX_USER: &[u8] = + include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-mips64")); #[cfg(all(feature = "mips64el-linux-user", not(docs_rs)))] /// QEMU binary for qemu-mips64el -pub const QEMU_MIPS64EL_LINUX_USER: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-mips64el")); +pub const QEMU_MIPS64EL_LINUX_USER: &[u8] = + include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-mips64el")); #[cfg(all(feature = "mipsel-linux-user", not(docs_rs)))] /// QEMU binary for qemu-mipsel -pub const QEMU_MIPSEL_LINUX_USER: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-mipsel")); +pub const QEMU_MIPSEL_LINUX_USER: &[u8] = + include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-mipsel")); #[cfg(all(feature = "mipsn32-linux-user", not(docs_rs)))] /// QEMU binary for qemu-mipsn32 -pub const QEMU_MIPSN32_LINUX_USER: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-mipsn32")); +pub const QEMU_MIPSN32_LINUX_USER: &[u8] = + include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-mipsn32")); #[cfg(all(feature = "mipsn32el-linux-user", not(docs_rs)))] /// QEMU binary for qemu-mipsn32el -pub const QEMU_MIPSN32EL_LINUX_USER: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-mipsn32el")); +pub const QEMU_MIPSN32EL_LINUX_USER: &[u8] = + include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-mipsn32el")); #[cfg(all(feature = "nios2-linux-user", not(docs_rs)))] /// QEMU binary for qemu-nios2 -pub const QEMU_NIOS2_LINUX_USER: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-nios2")); +pub const QEMU_NIOS2_LINUX_USER: &[u8] = + include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-nios2")); #[cfg(all(feature = "or1k-linux-user", not(docs_rs)))] /// QEMU binary for qemu-or1k -pub const QEMU_OR1K_LINUX_USER: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-or1k")); +pub const QEMU_OR1K_LINUX_USER: &[u8] = + include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-or1k")); #[cfg(all(feature = "ppc-linux-user", not(docs_rs)))] /// QEMU binary for qemu-ppc -pub const QEMU_PPC_LINUX_USER: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-ppc")); +pub const QEMU_PPC_LINUX_USER: &[u8] = + include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-ppc")); #[cfg(all(feature = "ppc64-linux-user", not(docs_rs)))] /// QEMU binary for qemu-ppc64 -pub const QEMU_PPC64_LINUX_USER: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-ppc64")); +pub const QEMU_PPC64_LINUX_USER: &[u8] = + include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-ppc64")); #[cfg(all(feature = "ppc64le-linux-user", not(docs_rs)))] /// QEMU binary for qemu-ppc64le -pub const QEMU_PPC64LE_LINUX_USER: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-ppc64le")); +pub const QEMU_PPC64LE_LINUX_USER: &[u8] = + include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-ppc64le")); #[cfg(all(feature = "riscv32-linux-user", not(docs_rs)))] /// QEMU binary for qemu-riscv32 -pub const QEMU_RISCV32_LINUX_USER: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-riscv32")); +pub const QEMU_RISCV32_LINUX_USER: &[u8] = + include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-riscv32")); #[cfg(all(feature = "riscv64-linux-user", not(docs_rs)))] /// QEMU binary for qemu-riscv64 -pub const QEMU_RISCV64_LINUX_USER: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-riscv64")); +pub const QEMU_RISCV64_LINUX_USER: &[u8] = + include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-riscv64")); #[cfg(all(feature = "s390x-linux-user", not(docs_rs)))] /// QEMU binary for qemu-s390x -pub const QEMU_S390X_LINUX_USER: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-s390x")); +pub const QEMU_S390X_LINUX_USER: &[u8] = + include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-s390x")); #[cfg(all(feature = "sh4-linux-user", not(docs_rs)))] /// QEMU binary for qemu-sh4 -pub const QEMU_SH4_LINUX_USER: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-sh4")); +pub const QEMU_SH4_LINUX_USER: &[u8] = + include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-sh4")); #[cfg(all(feature = "sh4eb-linux-user", not(docs_rs)))] /// QEMU binary for qemu-sh4eb -pub const QEMU_SH4EB_LINUX_USER: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-sh4eb")); +pub const QEMU_SH4EB_LINUX_USER: &[u8] = + include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-sh4eb")); #[cfg(all(feature = "sparc-linux-user", not(docs_rs)))] /// QEMU binary for qemu-sparc -pub const QEMU_SPARC_LINUX_USER: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-sparc")); +pub const QEMU_SPARC_LINUX_USER: &[u8] = + include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-sparc")); #[cfg(all(feature = "sparc32plus-linux-user", not(docs_rs)))] /// QEMU binary for qemu-sparc32plus -pub const QEMU_SPARC32PLUS_LINUX_USER: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-sparc32plus")); +pub const QEMU_SPARC32PLUS_LINUX_USER: &[u8] = + include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-sparc32plus")); #[cfg(all(feature = "sparc64-linux-user", not(docs_rs)))] /// QEMU binary for qemu-sparc64 -pub const QEMU_SPARC64_LINUX_USER: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-sparc64")); +pub const QEMU_SPARC64_LINUX_USER: &[u8] = + include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-sparc64")); #[cfg(all(feature = "x86_64-linux-user", not(docs_rs)))] /// QEMU binary for qemu-x86_64 -pub const QEMU_X86_64_LINUX_USER: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-x86_64")); +pub const QEMU_X86_64_LINUX_USER: &[u8] = + include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-x86_64")); #[cfg(all(feature = "xtensa-linux-user", not(docs_rs)))] /// QEMU binary for qemu-xtensa -pub const QEMU_XTENSA_LINUX_USER: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-xtensa")); +pub const QEMU_XTENSA_LINUX_USER: &[u8] = + include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-xtensa")); #[cfg(all(feature = "xtensaeb-linux-user", not(docs_rs)))] /// QEMU binary for qemu-xtensaeb -pub const QEMU_XTENSAEB_LINUX_USER: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-xtensaeb")); +pub const QEMU_XTENSAEB_LINUX_USER: &[u8] = + include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-xtensaeb")); #[cfg(all(feature = "aarch64-softmmu", not(docs_rs)))] /// QEMU binary for qemu-system-aarch64 -pub const QEMU_AARCH64_SOFTMMU: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-system-aarch64")); +pub const QEMU_AARCH64_SOFTMMU: &[u8] = + include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-system-aarch64")); #[cfg(all(feature = "alpha-softmmu", not(docs_rs)))] /// QEMU binary for qemu-system-alpha -pub const QEMU_ALPHA_SOFTMMU: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-system-alpha")); +pub const QEMU_ALPHA_SOFTMMU: &[u8] = + include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-system-alpha")); #[cfg(all(feature = "arm-softmmu", not(docs_rs)))] /// QEMU binary for qemu-system-arm -pub const QEMU_ARM_SOFTMMU: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-system-arm")); +pub const QEMU_ARM_SOFTMMU: &[u8] = + include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-system-arm")); #[cfg(all(feature = "avr-softmmu", not(docs_rs)))] /// QEMU binary for qemu-system-avr -pub const QEMU_AVR_SOFTMMU: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-system-avr")); +pub const QEMU_AVR_SOFTMMU: &[u8] = + include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-system-avr")); #[cfg(all(feature = "cris-softmmu", not(docs_rs)))] /// QEMU binary for qemu-system-cris -pub const QEMU_CRIS_SOFTMMU: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-system-cris")); +pub const QEMU_CRIS_SOFTMMU: &[u8] = + include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-system-cris")); #[cfg(all(feature = "hppa-softmmu", not(docs_rs)))] /// QEMU binary for qemu-system-hppa -pub const QEMU_HPPA_SOFTMMU: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-system-hppa")); +pub const QEMU_HPPA_SOFTMMU: &[u8] = + include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-system-hppa")); #[cfg(all(feature = "i386-softmmu", not(docs_rs)))] /// QEMU binary for qemu-system-i386 -pub const QEMU_I386_SOFTMMU: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-system-i386")); +pub const QEMU_I386_SOFTMMU: &[u8] = + include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-system-i386")); #[cfg(all(feature = "loongarch64-softmmu", not(docs_rs)))] /// QEMU binary for qemu-system-loongarch64 -pub const QEMU_LOONGARCH64_SOFTMMU: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-system-loongarch64")); +pub const QEMU_LOONGARCH64_SOFTMMU: &[u8] = include_bytes!(concat!( + env!("OUT_DIR"), + "/qemu/bin/qemu-system-loongarch64" +)); #[cfg(all(feature = "m68k-softmmu", not(docs_rs)))] /// QEMU binary for qemu-system-m68k -pub const QEMU_M68K_SOFTMMU: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-system-m68k")); +pub const QEMU_M68K_SOFTMMU: &[u8] = + include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-system-m68k")); #[cfg(all(feature = "microblaze-softmmu", not(docs_rs)))] /// QEMU binary for qemu-system-microblaze -pub const QEMU_MICROBLAZE_SOFTMMU: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-system-microblaze")); +pub const QEMU_MICROBLAZE_SOFTMMU: &[u8] = + include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-system-microblaze")); #[cfg(all(feature = "microblazeel-softmmu", not(docs_rs)))] /// QEMU binary for qemu-system-microblazeel -pub const QEMU_MICROBLAZEEL_SOFTMMU: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-system-microblazeel")); +pub const QEMU_MICROBLAZEEL_SOFTMMU: &[u8] = include_bytes!(concat!( + env!("OUT_DIR"), + "/qemu/bin/qemu-system-microblazeel" +)); #[cfg(all(feature = "mips-softmmu", not(docs_rs)))] /// QEMU binary for qemu-system-mips -pub const QEMU_MIPS_SOFTMMU: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-system-mips")); +pub const QEMU_MIPS_SOFTMMU: &[u8] = + include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-system-mips")); #[cfg(all(feature = "mips64-softmmu", not(docs_rs)))] /// QEMU binary for qemu-system-mips64 -pub const QEMU_MIPS64_SOFTMMU: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-system-mips64")); +pub const QEMU_MIPS64_SOFTMMU: &[u8] = + include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-system-mips64")); #[cfg(all(feature = "mips64el-softmmu", not(docs_rs)))] /// QEMU binary for qemu-system-mips64el -pub const QEMU_MIPS64EL_SOFTMMU: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-system-mips64el")); +pub const QEMU_MIPS64EL_SOFTMMU: &[u8] = + include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-system-mips64el")); #[cfg(all(feature = "mipsel-softmmu", not(docs_rs)))] /// QEMU binary for qemu-system-mipsel -pub const QEMU_MIPSEL_SOFTMMU: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-system-mipsel")); +pub const QEMU_MIPSEL_SOFTMMU: &[u8] = + include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-system-mipsel")); #[cfg(all(feature = "nios2-softmmu", not(docs_rs)))] /// QEMU binary for qemu-system-nios2 -pub const QEMU_NIOS2_SOFTMMU: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-system-nios2")); +pub const QEMU_NIOS2_SOFTMMU: &[u8] = + include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-system-nios2")); #[cfg(all(feature = "or1k-softmmu", not(docs_rs)))] /// QEMU binary for qemu-system-or1k -pub const QEMU_OR1K_SOFTMMU: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-system-or1k")); +pub const QEMU_OR1K_SOFTMMU: &[u8] = + include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-system-or1k")); #[cfg(all(feature = "ppc-softmmu", not(docs_rs)))] /// QEMU binary for qemu-system-ppc -pub const QEMU_PPC_SOFTMMU: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-system-ppc")); +pub const QEMU_PPC_SOFTMMU: &[u8] = + include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-system-ppc")); #[cfg(all(feature = "ppc64-softmmu", not(docs_rs)))] /// QEMU binary for qemu-system-ppc64 -pub const QEMU_PPC64_SOFTMMU: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-system-ppc64")); +pub const QEMU_PPC64_SOFTMMU: &[u8] = + include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-system-ppc64")); #[cfg(all(feature = "riscv32-softmmu", not(docs_rs)))] /// QEMU binary for qemu-system-riscv32 -pub const QEMU_RISCV32_SOFTMMU: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-system-riscv32")); +pub const QEMU_RISCV32_SOFTMMU: &[u8] = + include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-system-riscv32")); #[cfg(all(feature = "riscv64-softmmu", not(docs_rs)))] /// QEMU binary for qemu-system-riscv64 -pub const QEMU_RISCV64_SOFTMMU: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-system-riscv64")); +pub const QEMU_RISCV64_SOFTMMU: &[u8] = + include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-system-riscv64")); #[cfg(all(feature = "rx-softmmu", not(docs_rs)))] /// QEMU binary for qemu-system-rx -pub const QEMU_RX_SOFTMMU: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-system-rx")); +pub const QEMU_RX_SOFTMMU: &[u8] = + include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-system-rx")); #[cfg(all(feature = "s390x-softmmu", not(docs_rs)))] /// QEMU binary for qemu-system-s390x -pub const QEMU_S390X_SOFTMMU: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-system-s390x")); +pub const QEMU_S390X_SOFTMMU: &[u8] = + include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-system-s390x")); #[cfg(all(feature = "sh4-softmmu", not(docs_rs)))] /// QEMU binary for qemu-system-sh4 -pub const QEMU_SH4_SOFTMMU: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-system-sh4")); +pub const QEMU_SH4_SOFTMMU: &[u8] = + include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-system-sh4")); #[cfg(all(feature = "sh4eb-softmmu", not(docs_rs)))] /// QEMU binary for qemu-system-sh4eb -pub const QEMU_SH4EB_SOFTMMU: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-system-sh4eb")); +pub const QEMU_SH4EB_SOFTMMU: &[u8] = + include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-system-sh4eb")); #[cfg(all(feature = "sparc-softmmu", not(docs_rs)))] /// QEMU binary for qemu-system-sparc -pub const QEMU_SPARC_SOFTMMU: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-system-sparc")); +pub const QEMU_SPARC_SOFTMMU: &[u8] = + include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-system-sparc")); #[cfg(all(feature = "sparc64-softmmu", not(docs_rs)))] /// QEMU binary for qemu-system-sparc64 -pub const QEMU_SPARC64_SOFTMMU: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-system-sparc64")); +pub const QEMU_SPARC64_SOFTMMU: &[u8] = + include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-system-sparc64")); #[cfg(all(feature = "tricore-softmmu", not(docs_rs)))] /// QEMU binary for qemu-system-tricore -pub const QEMU_TRICORE_SOFTMMU: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-system-tricore")); +pub const QEMU_TRICORE_SOFTMMU: &[u8] = + include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-system-tricore")); #[cfg(all(feature = "x86_64-softmmu", not(docs_rs)))] /// QEMU binary for qemu-system-x86_64 -pub const QEMU_X86_64_SOFTMMU: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-system-x86_64")); +pub const QEMU_X86_64_SOFTMMU: &[u8] = + include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-system-x86_64")); #[cfg(all(feature = "xtensa-softmmu", not(docs_rs)))] /// QEMU binary for qemu-system-xtensa -pub const QEMU_XTENSA_SOFTMMU: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-system-xtensa")); +pub const QEMU_XTENSA_SOFTMMU: &[u8] = + include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-system-xtensa")); #[cfg(all(feature = "xtensaeb-softmmu", not(docs_rs)))] /// QEMU binary for qemu-system-xtensaeb -pub const QEMU_XTENSAEB_SOFTMMU: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-system-xtensaeb")); +pub const QEMU_XTENSAEB_SOFTMMU: &[u8] = + include_bytes!(concat!(env!("OUT_DIR"), "/qemu/bin/qemu-system-xtensaeb")); From dcb23b8f735ef580b7d8197bccc496702a9e267e Mon Sep 17 00:00:00 2001 From: novafacing Date: Wed, 10 Jan 2024 01:24:46 -0800 Subject: [PATCH 2/4] Refactor delay linking --- qemu-plugin/src/lib.rs | 15 ++++++-- qemu-plugin/src/win_link_hook/mod.rs | 57 ++++++++++++++++++++++------ 2 files changed, 56 insertions(+), 16 deletions(-) diff --git a/qemu-plugin/src/lib.rs b/qemu-plugin/src/lib.rs index 31d8c0c..b20d8d4 100644 --- a/qemu-plugin/src/lib.rs +++ b/qemu-plugin/src/lib.rs @@ -107,6 +107,14 @@ extern "C" { } #[cfg(windows)] +/// Define g_free, because on Windows we cannot delay link it +/// +/// # Safety +/// +/// `g_free` must *only* be used to deallocate values allocated with `g_malloc`, regardless of +/// its documented guarantees about wrapping the system allocator. QEMU plugin APIs which return +/// such values are documented to do so, and it is safe to call `g_free` on these values +/// provided they are not used afterward. unsafe fn g_free(mem: *mut c_void) { //TODO: We would really like to call g_free in the qemu binary here //but we can't, because windows doesn't export symbols unless you explicitly export them @@ -115,10 +123,9 @@ unsafe fn g_free(mem: *mut c_void) { // NOTE: glib 2.46 g_malloc always uses system malloc implementation: // https://docs.gtk.org/glib/func.mem_is_system_malloc.html // So it is safe to call libc free to free a `g_malloc`-ed object - unsafe { - if !mem.is_null() { - free(mem) - } + if !mem.is_null() { + // SAFETY: `mem` is non-null. + unsafe { free(mem) } } } diff --git a/qemu-plugin/src/win_link_hook/mod.rs b/qemu-plugin/src/win_link_hook/mod.rs index 65d6582..c7a99d7 100644 --- a/qemu-plugin/src/win_link_hook/mod.rs +++ b/qemu-plugin/src/win_link_hook/mod.rs @@ -2,24 +2,57 @@ use windows::core::PCSTR; use windows::Win32::Foundation::HMODULE; -use windows::Win32::System::LibraryLoader::GetModuleHandleA; +use windows::Win32::System::LibraryLoader::GetModuleHandleExA; use windows::Win32::System::WindowsProgramming::DELAYLOAD_INFO; -type FailureHook = unsafe extern "C" fn(dli_notify: u32, pdli: DELAYLOAD_INFO) -> HMODULE; +/// The helper function for linker-supported delayed loading which is what actually +/// loads the DLL at runtime. +type DelayHook = unsafe extern "C" fn(dli_notify: u32, pdli: DELAYLOAD_INFO) -> HMODULE; #[no_mangle] -/// Callback invoked by Windows loader to complete linking against QEMU symbols -pub static __pfnDliFailureHook2: FailureHook = delaylink_hook; +/// Helper function invoked when failures occur in delay linking (as opposed to +/// notifications) +pub static __pfnDliFailureHook2: DelayHook = delaylink_hook; -extern "C" fn delaylink_hook(dli_notify: u32, pdli: DELAYLOAD_INFO) -> HMODULE { - if dli_notify == 3 { +#[repr(C)] +/// Delay load import hook notifications +/// +enum DliNotify { + /// Used to bypass + DliNoteStartProcessing = 0, + /// Called just before LoadLibrary, can override w/ new HMODULE return val + DliNotePreLoadLibrary, + /// Called just before GetProcAddress, override w/ new FARPROC return value + DliNotePreGetProcAddress, + /// Failed to load library, fix it by + /// returning a valid HMODULE + DliFailLoadLib, + /// Failed to get proc address, fix it by + /// returning a valid FARPROC + DliFailGetProc, + /// Called after all processing is done, no bypass possible at this point except by + /// longjmp()/throw()/RaiseException. + DliNoteEndProcessing, +}; + +/// Helper function invoked when notifications or failures occur in delay linking +/// +/// # Arguments +/// +/// * `dli_notify` - The +extern "C" fn delaylink_hook(dli_notify: DliNotify, pdli: DELAYLOAD_INFO) -> HMODULE { + if let DliNofiy::DliFailLoadLib = dli_notify { + // SAFETY: Conversion of `PCSTR` to String is not safe because it involves an unchecked + // nul-byte dependent `strcpy`. In this instance, it is safe because let name = unsafe { pdli.TargetDllName.to_string() }.unwrap_or_default(); - if name == "qemu.exe" { - match unsafe { GetModuleHandleA(PCSTR::null()) } { - Ok(h) => return h, - Err(e) => { - eprintln!("Error loading top level qemu module: {e:?}"); - } + let mut module = HMODULE::default(); + + // NOTE: QEMU executables on windows are named qemu-system.*.exe + if name.starts_with("qemu") { + /// SAFETY: + match unsafe { GetModuleHandleExA(0, PCSTR::null(), &mut module as *mut HMODULE) } { + Ok(_) => return module, + Err(e) => panic!("Failed to open QEMU module: {e:?}"), } } } From c5c4c5314905fcec56573e7996c88de034835b92 Mon Sep 17 00:00:00 2001 From: novafacing Date: Wed, 10 Jan 2024 10:06:07 -0800 Subject: [PATCH 3/4] Fix a couple issues --- qemu-plugin/src/win_link_hook/mod.rs | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/qemu-plugin/src/win_link_hook/mod.rs b/qemu-plugin/src/win_link_hook/mod.rs index c7a99d7..289dcc3 100644 --- a/qemu-plugin/src/win_link_hook/mod.rs +++ b/qemu-plugin/src/win_link_hook/mod.rs @@ -6,8 +6,8 @@ use windows::Win32::System::LibraryLoader::GetModuleHandleExA; use windows::Win32::System::WindowsProgramming::DELAYLOAD_INFO; /// The helper function for linker-supported delayed loading which is what actually -/// loads the DLL at runtime. -type DelayHook = unsafe extern "C" fn(dli_notify: u32, pdli: DELAYLOAD_INFO) -> HMODULE; +/// loads the DLL at runtime. +type DelayHook = unsafe extern "C" fn(dli_notify: DliNofiy, pdli: DELAYLOAD_INFO) -> HMODULE; #[no_mangle] /// Helper function invoked when failures occur in delay linking (as opposed to @@ -33,23 +33,24 @@ enum DliNotify { /// Called after all processing is done, no bypass possible at this point except by /// longjmp()/throw()/RaiseException. DliNoteEndProcessing, -}; +} /// Helper function invoked when notifications or failures occur in delay linking -/// +/// /// # Arguments -/// -/// * `dli_notify` - The +/// +/// * `dli_notify` - The extern "C" fn delaylink_hook(dli_notify: DliNotify, pdli: DELAYLOAD_INFO) -> HMODULE { - if let DliNofiy::DliFailLoadLib = dli_notify { + if let DliNotify::DliFailLoadLib = dli_notify { // SAFETY: Conversion of `PCSTR` to String is not safe because it involves an unchecked - // nul-byte dependent `strcpy`. In this instance, it is safe because + // nul-byte dependent `strcpy`. In this instance, it is safe because let name = unsafe { pdli.TargetDllName.to_string() }.unwrap_or_default(); let mut module = HMODULE::default(); // NOTE: QEMU executables on windows are named qemu-system.*.exe if name.starts_with("qemu") { - /// SAFETY: + // SAFETY: Getting the module handle for NULL is safe and does not dereference any + // pointers except to write the `module` argument which we know is alive here. match unsafe { GetModuleHandleExA(0, PCSTR::null(), &mut module as *mut HMODULE) } { Ok(_) => return module, Err(e) => panic!("Failed to open QEMU module: {e:?}"), From c57db71cfe69c05e7bf72b0ae5604592858b2854 Mon Sep 17 00:00:00 2001 From: novafacing Date: Wed, 10 Jan 2024 10:51:12 -0800 Subject: [PATCH 4/4] Fix typo --- qemu-plugin/src/win_link_hook/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qemu-plugin/src/win_link_hook/mod.rs b/qemu-plugin/src/win_link_hook/mod.rs index 289dcc3..0e2a528 100644 --- a/qemu-plugin/src/win_link_hook/mod.rs +++ b/qemu-plugin/src/win_link_hook/mod.rs @@ -7,7 +7,7 @@ use windows::Win32::System::WindowsProgramming::DELAYLOAD_INFO; /// The helper function for linker-supported delayed loading which is what actually /// loads the DLL at runtime. -type DelayHook = unsafe extern "C" fn(dli_notify: DliNofiy, pdli: DELAYLOAD_INFO) -> HMODULE; +type DelayHook = unsafe extern "C" fn(dli_notify: DliNotify, pdli: DELAYLOAD_INFO) -> HMODULE; #[no_mangle] /// Helper function invoked when failures occur in delay linking (as opposed to