diff --git a/.github/workflows/Crate-publishing.yml b/.github/workflows/Crate-publishing.yml index c3cdfec7..fcd5552b 100644 --- a/.github/workflows/Crate-publishing.yml +++ b/.github/workflows/Crate-publishing.yml @@ -15,7 +15,7 @@ on: pull_request: env: - UNICORN_VERSION: ${{ github.sha }} + CI: true jobs: build: @@ -28,7 +28,7 @@ jobs: - { os: windows-latest, arch: x64, - name: 'Windows x84_64' + name: 'Windows x86_64' } - { os: windows-latest, @@ -43,7 +43,7 @@ jobs: - { os: macos-latest, arch: x64, - name: 'macos x86_64' + name: 'macOS x86_64' } steps: - uses: actions/checkout@v2 @@ -54,7 +54,18 @@ jobs: toolchain: stable override: true default: true - componets: rustfmt, clippy + + - name: '🛠️ Add msbuild to PATH' + if: contains(matrix.config.name, 'win') + uses: microsoft/setup-msbuild@v1.0.3 + with: + vs-version: '16.5' + + - name: '🛠️ Win build dependencies' + if: contains(matrix.config.name, 'win') + shell: bash + run: | + choco install ninja cmake - name: '🚧 Cargo test' run: | diff --git a/bindings/rust/build.rs b/bindings/rust/build.rs index a122faab..c128ef14 100644 --- a/bindings/rust/build.rs +++ b/bindings/rust/build.rs @@ -5,28 +5,50 @@ fn main() { let out_dir = env::var("OUT_DIR").unwrap(); let profile = env::var("PROFILE").unwrap(); let mut version = String::from("dev"); - if let Result::Ok(version_env) = env::var("UNICORN_VERISON") { + if let Result::Ok(version_env) = env::var("UNICORN_BRANCH") { version = version_env; } - let unicorn_dir = format!("{}/unicorn_git", out_dir); + let unicorn_dir; + if let Result::Ok(_) = env::var("CI") { + unicorn_dir = format!("../.."); + } else { + unicorn_dir = format!("{}/unicorn_git", out_dir); - Command::new("rm").arg("-rf").arg(&unicorn_dir); + Command::new("rm").arg("-rf").arg(&unicorn_dir); - Command::new("git") - .arg("clone") - .arg("git@github.com:unicorn-engine/unicorn.git") - .arg("-b") - .arg(version) - .arg(&unicorn_dir) - .output() - .expect("Fail to clone Unicorn repository."); + Command::new("git") + .arg("clone") + .arg("git@github.com:unicorn-engine/unicorn.git") + .arg("-b") + .arg(version) + .arg(&unicorn_dir) + .output() + .expect("Fail to clone Unicorn repository."); + } println!("cargo:rerun-if-changed={}", &unicorn_dir); // We don't use TARGET since we can't cross-build. if env::consts::OS == "windows" { // Windows + let mut cmd = Command::new("cmake"); + cmd.current_dir(&unicorn_dir) + .arg("-B") + .arg("rust_build") + .arg("-DUNICORN_BUILD_SHARED=off") + .arg("-G") + .arg("Visual Studio 16 2019"); + + if profile == "debug" { + cmd.arg("-DCMAKE_BUILD_TYPE=Debug"); + } else { + cmd.arg("-DCMAKE_BUILD_TYPE=Release"); + } + + cmd.output() + .expect("Fail to create build directory on Windows."); + let mut platform = "x64"; let mut conf = "Release"; if std::mem::size_of::() == 4 { @@ -37,16 +59,16 @@ fn main() { } Command::new("msbuild") - .current_dir(format!("{}/msvc", &unicorn_dir)) + .current_dir(format!("{}/rust_build", &unicorn_dir)) .arg("unicorn.sln") .arg("-m") - .arg("-p:Platform".to_owned() + platform) - .arg("-p:Configuration".to_owned() + conf) + .arg("-p:Platform=".to_owned() + platform) + .arg("-p:Configuration=".to_owned() + conf) .output() .expect("Fail to build unicorn on Win32."); println!( - "cargo:rustc-link-lib=static={}/msvc/{}/{}/unicorn.lib", - unicorn_dir, platform, conf + "cargo:rustc-link-search={}/rust_build/{}", + unicorn_dir, conf ); } else { // Most Unix-like systems @@ -70,35 +92,37 @@ fn main() { .arg("-j6") .output() .expect("Fail to build unicorn on *nix."); - // This is a workaround for Unicorn static link since libunicorn.a is also linked again lib*-softmmu.a. - // Static libs is just a bundle of objects files. The link relation defined in CMakeLists is only - // valid within the cmake project scope and cmake would help link again sub static libs automatically. - // - // Why do I stick to static link? See: https://github.com/rust-lang/cargo/issues/5077 - println!("cargo:rustc-link-lib=unicorn"); - for arch in [ - "x86_64", - "arm", - "armeb", - "aarch64", - "aarch64eb", - "riscv32", - "riscv64", - "mips", - "mipsel", - "mips64", - "mips64el", - "sparc", - "sparc64", - "m68k", - "ppc", - "ppc64", - ] - .iter() - { - println!("cargo:rustc-link-lib={}-softmmu", arch); - } - println!("cargo:rustc-link-lib=unicorn-common"); + println!("cargo:rustc-link-search={}/rust_build", unicorn_dir); } + + // This is a workaround for Unicorn static link since libunicorn.a is also linked again lib*-softmmu.a. + // Static libs is just a bundle of objects files. The link relation defined in CMakeLists is only + // valid within the cmake project scope and cmake would help link again sub static libs automatically. + // + // Lazymio(@wtdcode): Why do I stick to static link? See: https://github.com/rust-lang/cargo/issues/5077 + println!("cargo:rustc-link-lib=unicorn"); + for arch in [ + "x86_64", + "arm", + "armeb", + "aarch64", + "aarch64eb", + "riscv32", + "riscv64", + "mips", + "mipsel", + "mips64", + "mips64el", + "sparc", + "sparc64", + "m68k", + "ppc", + "ppc64", + ] + .iter() + { + println!("cargo:rustc-link-lib={}-softmmu", arch); + } + println!("cargo:rustc-link-lib=unicorn-common"); } diff --git a/qemu/target/ppc/cpu.h b/qemu/target/ppc/cpu.h index 0357a4ca..26ed1680 100644 --- a/qemu/target/ppc/cpu.h +++ b/qemu/target/ppc/cpu.h @@ -2018,9 +2018,13 @@ enum { PPC_MEM_TLBIA = 0x0000000010000000ULL, PPC_MEM_TLBIE = 0x0000000020000000ULL, PPC_MEM_TLBSYNC = 0x0000000040000000ULL, + +// The enum in msvc is 32bit **signed**. +// https://godbolt.org/z/nYbvWPWET +#ifndef _MSC_VER /* sync instruction */ PPC_MEM_SYNC = 0x0000000080000000ULL, -#ifndef _MSC_VER + /* eieio instruction */ PPC_MEM_EIEIO = 0x0000000100000000ULL, @@ -2084,6 +2088,7 @@ enum { /* popcntw and popcntd instructions */ PPC_POPCNTWD = 0x8000000000000000ULL, #else +#define PPC_MEM_SYNC 0x0000000080000000ULL #define PPC_MEM_EIEIO 0x0000000100000000ULL #define PPC_CACHE 0x0000000200000000ULL #define PPC_CACHE_ICBI 0x0000000400000000ULL diff --git a/tests/unit/test_ppc.c b/tests/unit/test_ppc.c index 972d24c6..c457bd70 100644 --- a/tests/unit/test_ppc.c +++ b/tests/unit/test_ppc.c @@ -3,6 +3,34 @@ const uint64_t code_start = 0x1000; const uint64_t code_len = 0x4000; +static void uc_common_setup(uc_engine** uc, uc_arch arch, uc_mode mode, const char* code, uint64_t size) { + OK(uc_open(arch, mode, uc)); + OK(uc_mem_map(*uc, code_start, code_len, UC_PROT_ALL)); + OK(uc_mem_write(*uc, code_start, code, size)); +} + +static void test_ppc32_add() { + uc_engine* uc; + char code[] = "\x7f\x46\x1a\x14"; // ADD 26, 6, 3 + int reg; + + uc_common_setup(&uc, UC_ARCH_PPC, UC_MODE_32 | UC_MODE_BIG_ENDIAN, code, sizeof(code) - 1); + + reg = 42; + OK(uc_reg_write(uc, UC_PPC_REG_3, ®)); + reg = 1337; + OK(uc_reg_write(uc, UC_PPC_REG_6, ®)); + + OK(uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 0)); + + OK(uc_reg_read(uc, UC_PPC_REG_26, ®)); + + TEST_CHECK(reg == 1379); + + OK(uc_close(uc)); +} + TEST_LIST = { - { NULL, NULL } + { "test_ppc32_add", test_ppc32_add }, + { NULL, NULL} }; \ No newline at end of file