From 6fb7450e0f78f4245aa10d89dbd3f72f96e3ec1a Mon Sep 17 00:00:00 2001 From: momo5502 Date: Wed, 26 Mar 2025 14:36:03 +0100 Subject: [PATCH 01/20] Add rust code and cmake integration --- src/CMakeLists.txt | 2 + src/icicle-emulator/CMakeLists.txt | 18 + src/icicle-emulator/icicle_x64_emulator.cpp | 14 + src/icicle-emulator/icicle_x64_emulator.hpp | 19 + src/icicle/CMakeLists.txt | 38 + src/icicle/Cargo.lock | 958 ++++++++++++++++++++ src/icicle/Cargo.toml | 11 + src/icicle/src/lib.rs | 58 ++ 8 files changed, 1118 insertions(+) create mode 100644 src/icicle-emulator/CMakeLists.txt create mode 100644 src/icicle-emulator/icicle_x64_emulator.cpp create mode 100644 src/icicle-emulator/icicle_x64_emulator.hpp create mode 100644 src/icicle/CMakeLists.txt create mode 100644 src/icicle/Cargo.lock create mode 100644 src/icicle/Cargo.toml create mode 100644 src/icicle/src/lib.rs diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 72d8caa8..33519ddb 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -2,6 +2,8 @@ add_subdirectory(common) add_subdirectory(emulator) add_subdirectory(gdb-stub) add_subdirectory(unicorn-emulator) +add_subdirectory(icicle-emulator) +add_subdirectory(icicle) add_subdirectory(windows-emulator) add_subdirectory(windows-gdb-stub) diff --git a/src/icicle-emulator/CMakeLists.txt b/src/icicle-emulator/CMakeLists.txt new file mode 100644 index 00000000..8ee0ec84 --- /dev/null +++ b/src/icicle-emulator/CMakeLists.txt @@ -0,0 +1,18 @@ +file(GLOB_RECURSE SRC_FILES CONFIGURE_DEPENDS + *.cpp + *.hpp + *.rc +) + +list(SORT SRC_FILES) + +if(MOMO_BUILD_AS_LIBRARY) + add_library(icicle-emulator STATIC ${SRC_FILES}) +else() + add_library(icicle-emulator SHARED ${SRC_FILES}) +endif() + +target_include_directories(icicle-emulator INTERFACE "${CMAKE_CURRENT_LIST_DIR}") + +target_link_libraries(icicle-emulator PUBLIC emulator) +target_link_libraries(icicle-emulator PRIVATE emulator-common icicle) diff --git a/src/icicle-emulator/icicle_x64_emulator.cpp b/src/icicle-emulator/icicle_x64_emulator.cpp new file mode 100644 index 00000000..5a9dba17 --- /dev/null +++ b/src/icicle-emulator/icicle_x64_emulator.cpp @@ -0,0 +1,14 @@ +#define ICICLE_EMULATOR_IMPL +#include "icicle_x64_emulator.hpp" + +extern "C" void test_rust(); + +namespace icicle +{ + std::unique_ptr create_x64_emulator() + { + test_rust(); + + return {}; + } +} diff --git a/src/icicle-emulator/icicle_x64_emulator.hpp b/src/icicle-emulator/icicle_x64_emulator.hpp new file mode 100644 index 00000000..57b408db --- /dev/null +++ b/src/icicle-emulator/icicle_x64_emulator.hpp @@ -0,0 +1,19 @@ +#pragma once + +#include +#include +#include "platform/platform.hpp" + +#ifdef ICICLE_EMULATOR_IMPL +#define ICICLE_EMULATOR_DLL_STORAGE EXPORT_SYMBOL +#else +#define ICICLE_EMULATOR_DLL_STORAGE IMPORT_SYMBOL +#endif + +namespace icicle +{ +#if !MOMO_BUILD_AS_LIBRARY + ICICLE_EMULATOR_DLL_STORAGE +#endif + std::unique_ptr create_x64_emulator(); +} diff --git a/src/icicle/CMakeLists.txt b/src/icicle/CMakeLists.txt new file mode 100644 index 00000000..c50d4c30 --- /dev/null +++ b/src/icicle/CMakeLists.txt @@ -0,0 +1,38 @@ +include(ExternalProject) + +set(ICICLE_BUILD_DIR ${CMAKE_CURRENT_BINARY_DIR}/cargo-build) +set(ICICLE_ARTIFACT_DIR ${ICICLE_BUILD_DIR}/$,debug,release>) + +set(ICICLE_RUST_PROJECT_NAME "icicle") +set(ICICLE_RUST_LIB ${ICICLE_ARTIFACT_DIR}/lib${ICICLE_RUST_PROJECT_NAME}.a) + +if(MSVC) + set(ICICLE_RUST_LIB ${ICICLE_ARTIFACT_DIR}/${ICICLE_RUST_PROJECT_NAME}.lib) +endif() + +ExternalProject_Add( + icicle-rust-project + PREFIX ${CMAKE_CURRENT_BINARY_DIR} + SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR} + BINARY_DIR ${CMAKE_CURRENT_LIST_DIR} + CONFIGURE_COMMAND "" + BUILD_COMMAND ${CMAKE_COMMAND} -E env "CARGO_TARGET_DIR=${ICICLE_BUILD_DIR}" cargo build --all-targets $,--lib,--release> + INSTALL_COMMAND "" + USES_TERMINAL_CONFIGURE 1 + USES_TERMINAL_BUILD 1 + BUILD_ALWAYS 1 + BUILD_BYPRODUCTS ${ICICLE_RUST_LIB} +) + +add_library(icicle INTERFACE) +add_dependencies(icicle icicle-rust-project) +target_link_libraries(icicle INTERFACE ${ICICLE_RUST_LIB}) + +if(MSVC) + target_link_libraries(icicle INTERFACE + ws2_32.lib + Userenv.lib + ntdll.lib + Bcrypt.lib + ) +endif() \ No newline at end of file diff --git a/src/icicle/Cargo.lock b/src/icicle/Cargo.lock new file mode 100644 index 00000000..555e93a0 --- /dev/null +++ b/src/icicle/Cargo.lock @@ -0,0 +1,958 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "addr2line" +version = "0.24.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" +dependencies = [ + "cpp_demangle", + "fallible-iterator", + "gimli", + "memmap2", + "object", + "rustc-demangle", + "smallvec", + "typed-arena", +] + +[[package]] +name = "adler2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" + +[[package]] +name = "ahash" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" +dependencies = [ + "cfg-if", + "getrandom", + "once_cell", + "version_check", + "zerocopy", +] + +[[package]] +name = "anyhow" +version = "1.0.97" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcfed56ad506cb2c684a14971b8861fdc3baaaae314b9e5f9bb532cbe3ba7a4f" + +[[package]] +name = "arbitrary" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dde20b3d026af13f561bdd0f15edf01fc734f0dafcedbaf42bba506a9517f223" + +[[package]] +name = "autocfg" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" + +[[package]] +name = "base64" +version = "0.21.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd" +dependencies = [ + "serde", +] + +[[package]] +name = "bstr" +version = "1.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "531a9155a481e2ee699d4f98f43c0ca4ff8ee1bfd55c31e9e98fb29d2b176fe0" +dependencies = [ + "memchr", + "serde", +] + +[[package]] +name = "bumpalo" +version = "3.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf" + +[[package]] +name = "bytemuck" +version = "1.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6b1fc10dbac614ebc03540c9dbd60e83887fda27794998c6528f1782047d540" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "cpp_demangle" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96e58d342ad113c2b878f16d5d034c03be492ae460cdbc02b7f0f2284d310c7d" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "cranelift" +version = "0.113.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27711210499725bafe52c320a988e27283e6cf477ee8edac57e8275bef8ea550" +dependencies = [ + "cranelift-codegen", + "cranelift-frontend", + "cranelift-module", +] + +[[package]] +name = "cranelift-bforest" +version = "0.113.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "540b193ff98b825a1f250a75b3118911af918a734154c69d80bcfcf91e7e9522" +dependencies = [ + "cranelift-entity", +] + +[[package]] +name = "cranelift-bitset" +version = "0.113.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7cb269598b9557ab942d687d3c1086d77c4b50dcf35813f3a65ba306fd42279" + +[[package]] +name = "cranelift-codegen" +version = "0.113.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46566d7c83a8bff4150748d66020f4c7224091952aa4b4df1ec4959c39d937a1" +dependencies = [ + "bumpalo", + "cranelift-bforest", + "cranelift-bitset", + "cranelift-codegen-meta", + "cranelift-codegen-shared", + "cranelift-control", + "cranelift-entity", + "cranelift-isle", + "gimli", + "hashbrown 0.14.5", + "log", + "regalloc2", + "rustc-hash", + "smallvec", + "target-lexicon", +] + +[[package]] +name = "cranelift-codegen-meta" +version = "0.113.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2df8a86a34236cc75a8a6a271973da779c2aeb36c43b6e14da474cf931317082" +dependencies = [ + "cranelift-codegen-shared", +] + +[[package]] +name = "cranelift-codegen-shared" +version = "0.113.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf75340b6a57b7c7c1b74f10d3d90883ee6d43a554be8131a4046c2ebcf5eb65" + +[[package]] +name = "cranelift-control" +version = "0.113.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e84495bc5d23d86aad8c86f8ade4af765b94882af60d60e271d3153942f1978" +dependencies = [ + "arbitrary", +] + +[[package]] +name = "cranelift-entity" +version = "0.113.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "963c17147b80df351965e57c04d20dbedc85bcaf44c3436780a59a3f1ff1b1c2" +dependencies = [ + "cranelift-bitset", +] + +[[package]] +name = "cranelift-frontend" +version = "0.113.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "727f02acbc4b4cb2ba38a6637101d579db50190df1dd05168c68e762851a3dd5" +dependencies = [ + "cranelift-codegen", + "log", + "smallvec", + "target-lexicon", +] + +[[package]] +name = "cranelift-isle" +version = "0.113.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32b00cc2e03c748f2531eea01c871f502b909d30295fdcad43aec7bf5c5b4667" + +[[package]] +name = "cranelift-jit" +version = "0.113.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f74630af581f32b99c8f4e06ee45799383ecc0795e3ff8aa86b7584bb2d643fd" +dependencies = [ + "anyhow", + "cranelift-codegen", + "cranelift-control", + "cranelift-entity", + "cranelift-module", + "cranelift-native", + "libc", + "log", + "region", + "target-lexicon", + "wasmtime-jit-icache-coherence", + "windows-sys 0.59.0", +] + +[[package]] +name = "cranelift-module" +version = "0.113.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6aaa16c4f18a15be310df221ea544f516acc42fc58ca96e09a3d08651744efa1" +dependencies = [ + "anyhow", + "cranelift-codegen", + "cranelift-control", +] + +[[package]] +name = "cranelift-native" +version = "0.113.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbeaf978dc7c1a2de8bbb9162510ed218eb156697bc45590b8fbdd69bb08e8de" +dependencies = [ + "cranelift-codegen", + "libc", + "target-lexicon", +] + +[[package]] +name = "crc32fast" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crunchy" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43da5946c66ffcc7745f48db692ffbb10a83bfe0afd96235c5c2a4fb23994929" + +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + +[[package]] +name = "errno" +version = "0.3.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" +dependencies = [ + "libc", + "windows-sys 0.59.0", +] + +[[package]] +name = "fallible-iterator" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2acce4a10f12dc2fb14a218589d4f1f62ef011b2d0cc4b3cb1bba8e94da14649" + +[[package]] +name = "flate2" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11faaf5a5236997af9848be0bef4db95824b1d534ebc64d0f0c6cf3e67bd38dc" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + +[[package]] +name = "foldhash" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" + +[[package]] +name = "getrandom" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "gimli" +version = "0.31.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" +dependencies = [ + "fallible-iterator", + "indexmap", + "stable_deref_trait", +] + +[[package]] +name = "half" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7db2ff139bba50379da6aa0766b52fdcb62cb5b263009b09ed58ba604e14bbd1" +dependencies = [ + "cfg-if", + "crunchy", +] + +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" +dependencies = [ + "ahash", +] + +[[package]] +name = "hashbrown" +version = "0.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" +dependencies = [ + "foldhash", +] + +[[package]] +name = "icicle" +version = "0.1.0" +dependencies = [ + "icicle-vm", + "pcode", +] + +[[package]] +name = "icicle-cpu" +version = "0.1.0" +source = "git+https://github.com/icicle-emu/icicle-emu#6e9fd3e34aec440ac92c1f49f4a70fc288949de9" +dependencies = [ + "addr2line", + "ahash", + "anyhow", + "bitflags 2.9.0", + "bytemuck", + "gimli", + "half", + "icicle-mem", + "object", + "pcode", + "sleigh-runtime", + "target-lexicon", + "tracing", +] + +[[package]] +name = "icicle-jit" +version = "0.2.0" +source = "git+https://github.com/icicle-emu/icicle-emu#6e9fd3e34aec440ac92c1f49f4a70fc288949de9" +dependencies = [ + "cranelift", + "cranelift-codegen", + "cranelift-jit", + "cranelift-module", + "cranelift-native", + "icicle-cpu", + "memoffset", + "pcode", + "target-lexicon", + "tracing", + "wasmtime-jit-debug", +] + +[[package]] +name = "icicle-linux" +version = "0.1.0" +source = "git+https://github.com/icicle-emu/icicle-emu#6e9fd3e34aec440ac92c1f49f4a70fc288949de9" +dependencies = [ + "bitflags 2.9.0", + "bstr", + "bytemuck", + "icicle-cpu", + "object", + "pcode", + "sleigh-runtime", + "target-lexicon", + "tracing", +] + +[[package]] +name = "icicle-mem" +version = "0.3.0" +source = "git+https://github.com/icicle-emu/icicle-emu#6e9fd3e34aec440ac92c1f49f4a70fc288949de9" +dependencies = [ + "tracing", +] + +[[package]] +name = "icicle-vm" +version = "0.2.0" +source = "git+https://github.com/icicle-emu/icicle-emu#6e9fd3e34aec440ac92c1f49f4a70fc288949de9" +dependencies = [ + "anyhow", + "icicle-cpu", + "icicle-jit", + "icicle-linux", + "ihex", + "object", + "pcode", + "ron", + "serde", + "serde-xml-rs", + "sleigh-compile", + "sleigh-runtime", + "target-lexicon", + "tracing", +] + +[[package]] +name = "ihex" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "365a784774bb381e8c19edb91190a90d7f2625e057b55de2bc0f6b57bc779ff2" + +[[package]] +name = "indexmap" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3954d50fe15b02142bf25d3b8bdadb634ec3948f103d04ffe3031bc8fe9d7058" +dependencies = [ + "equivalent", + "hashbrown 0.15.2", +] + +[[package]] +name = "libc" +version = "0.2.171" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c19937216e9d3aa9956d9bb8dfc0b0c8beb6058fc4f7a4dc4d850edf86a237d6" + +[[package]] +name = "linux-raw-sys" +version = "0.4.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" + +[[package]] +name = "log" +version = "0.4.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" + +[[package]] +name = "mach2" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19b955cdeb2a02b9117f121ce63aa52d08ade45de53e48fe6a38b39c10f6f709" +dependencies = [ + "libc", +] + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "memmap2" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd3f7eed9d3848f8b98834af67102b720745c4ec028fcd0aa0239277e7de374f" +dependencies = [ + "libc", +] + +[[package]] +name = "memoffset" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" +dependencies = [ + "autocfg", +] + +[[package]] +name = "miniz_oxide" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e3e04debbb59698c15bacbb6d93584a8c0ca9cc3213cb423d31f760d8843ce5" +dependencies = [ + "adler2", +] + +[[package]] +name = "object" +version = "0.36.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" +dependencies = [ + "crc32fast", + "flate2", + "hashbrown 0.15.2", + "indexmap", + "memchr", + "ruzstd", +] + +[[package]] +name = "once_cell" +version = "1.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d75b0bedcc4fe52caa0e03d9f1151a323e4aa5e2d78ba3580400cd3c9e2bc4bc" + +[[package]] +name = "pcode" +version = "0.2.0" +source = "git+https://github.com/icicle-emu/icicle-emu#6e9fd3e34aec440ac92c1f49f4a70fc288949de9" + +[[package]] +name = "pin-project-lite" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" + +[[package]] +name = "proc-macro2" +version = "1.0.94" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "regalloc2" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12908dbeb234370af84d0579b9f68258a0f67e201412dd9a2814e6f45b2fc0f0" +dependencies = [ + "hashbrown 0.14.5", + "log", + "rustc-hash", + "slice-group-by", + "smallvec", +] + +[[package]] +name = "region" +version = "3.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6b6ebd13bc009aef9cd476c1310d49ac354d36e240cf1bd753290f3dc7199a7" +dependencies = [ + "bitflags 1.3.2", + "libc", + "mach2", + "windows-sys 0.52.0", +] + +[[package]] +name = "ron" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b91f7eff05f748767f183df4320a63d6936e9c6107d97c9e6bdd9784f4289c94" +dependencies = [ + "base64", + "bitflags 2.9.0", + "serde", + "serde_derive", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" + +[[package]] +name = "rustc-hash" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" + +[[package]] +name = "rustix" +version = "0.38.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" +dependencies = [ + "bitflags 2.9.0", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.59.0", +] + +[[package]] +name = "ruzstd" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fad02996bfc73da3e301efe90b1837be9ed8f4a462b6ed410aa35d00381de89f" +dependencies = [ + "twox-hash", +] + +[[package]] +name = "serde" +version = "1.0.219" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde-xml-rs" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb3aa78ecda1ebc9ec9847d5d3aba7d618823446a049ba2491940506da6e2782" +dependencies = [ + "log", + "serde", + "thiserror", + "xml-rs", +] + +[[package]] +name = "serde_derive" +version = "1.0.219" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "sleigh-compile" +version = "0.3.0" +source = "git+https://github.com/icicle-emu/icicle-emu#6e9fd3e34aec440ac92c1f49f4a70fc288949de9" +dependencies = [ + "pcode", + "serde", + "serde-xml-rs", + "serde_derive", + "sleigh-parse", + "sleigh-runtime", +] + +[[package]] +name = "sleigh-parse" +version = "0.3.0" +source = "git+https://github.com/icicle-emu/icicle-emu#6e9fd3e34aec440ac92c1f49f4a70fc288949de9" + +[[package]] +name = "sleigh-runtime" +version = "0.1.0" +source = "git+https://github.com/icicle-emu/icicle-emu#6e9fd3e34aec440ac92c1f49f4a70fc288949de9" +dependencies = [ + "pcode", + "sleigh-parse", +] + +[[package]] +name = "slice-group-by" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "826167069c09b99d56f31e9ae5c99049e932a98c9dc2dac47645b08dbbf76ba7" + +[[package]] +name = "smallvec" +version = "1.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fcf8323ef1faaee30a44a340193b1ac6814fd9b7b4e88e9d4519a3e4abe1cfd" + +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "syn" +version = "2.0.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "target-lexicon" +version = "0.12.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" + +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tracing" +version = "0.1.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" +dependencies = [ + "pin-project-lite", + "tracing-core", +] + +[[package]] +name = "tracing-core" +version = "0.1.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" + +[[package]] +name = "twox-hash" +version = "1.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675" +dependencies = [ + "cfg-if", + "static_assertions", +] + +[[package]] +name = "typed-arena" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6af6ae20167a9ece4bcb41af5b80f8a1f1df981f6391189ce00fd257af04126a" + +[[package]] +name = "unicode-ident" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasmtime-jit-debug" +version = "26.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f02a0118d471de665565ed200bc56673eaa10cc8e223dfe2cef5d50ed0d9d143" +dependencies = [ + "object", + "rustix", + "wasmtime-versioned-export-macros", +] + +[[package]] +name = "wasmtime-jit-icache-coherence" +version = "26.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da47fba49af72581bc0dc67c8faaf5ee550e6f106e285122a184a675193701a5" +dependencies = [ + "anyhow", + "cfg-if", + "libc", + "windows-sys 0.59.0", +] + +[[package]] +name = "wasmtime-versioned-export-macros" +version = "26.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db8efb877c9e5e67239d4553bb44dd2a34ae5cfb728f3cf2c5e64439c6ca6ee7" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "xml-rs" +version = "0.8.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5b940ebc25896e71dd073bad2dbaa2abfe97b0a391415e22ad1326d9c54e3c4" + +[[package]] +name = "zerocopy" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] diff --git a/src/icicle/Cargo.toml b/src/icicle/Cargo.toml new file mode 100644 index 00000000..021326a6 --- /dev/null +++ b/src/icicle/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "icicle" +version = "0.1.0" +edition = "2024" + +[lib] +crate-type = ["staticlib"] + +[dependencies] +icicle-vm = { git = "https://github.com/icicle-emu/icicle-emu" } +pcode = { git = "https://github.com/icicle-emu/icicle-emu" } diff --git a/src/icicle/src/lib.rs b/src/icicle/src/lib.rs new file mode 100644 index 00000000..5c1cc04b --- /dev/null +++ b/src/icicle/src/lib.rs @@ -0,0 +1,58 @@ +#[unsafe(no_mangle)] +pub fn test_rust() { + // Setup the CPU state for the target triple + let cpu_config = icicle_vm::cpu::Config::from_target_triple("x86_64-none"); + let mut vm = icicle_vm::build(&cpu_config).unwrap(); + + // Setup an environment to run inside of. + //let mut env = icicle_vm::env::build_auto(&mut vm).unwrap(); + // Load a binary into the environment. + //env.load(&mut vm.cpu, b"./test.elf").unwrap(); + //vm.env = env; + + let mapping = icicle_vm::cpu::mem::Mapping { perm: icicle_vm::cpu::mem::perm::ALL, value: 0x0 }; + + let alloc1 = + vm.cpu.mem.alloc_memory(icicle_vm::cpu::mem::AllocLayout { addr: Some(0x10000), size: 0x100, align: 0x100 }, mapping).unwrap(); + + // Add instrumentation + let counter = vm.cpu.trace.register_store(vec![0_u64]); + vm.add_injector(BlockCounter { counter }); + + // Run until the VM exits. + let exit = vm.run(); + println!("{exit:?}\n{}", icicle_vm::debug::current_disasm(&mut vm)); + + + // Read instrumentation data. + let blocks_hit = vm.cpu.trace[counter].as_any().downcast_ref::>().unwrap()[0]; + let blocks_executed = blocks_hit.saturating_sub(1); + println!("{blocks_executed} blocks were executed"); +} + +struct BlockCounter { + counter: icicle_vm::cpu::StoreRef, +} + +impl icicle_vm::CodeInjector for BlockCounter { + fn inject( + &mut self, + _cpu: &mut icicle_vm::cpu::Cpu, + group: &icicle_vm::cpu::BlockGroup, + code: &mut icicle_vm::BlockTable, + ) { + let store_id = self.counter.get_store_id(); + for block in &mut code.blocks[group.range()] { + // counter += 1 + let counter = block.pcode.alloc_tmp(8); + let instrumentation = [ + (counter, pcode::Op::Load(store_id), 0_u64).into(), + (counter, pcode::Op::IntAdd, (counter, 1_u64)).into(), + (pcode::Op::Store(store_id), (0_u64, counter)).into(), + ]; + + // Inject the instrumentation at the start of the block. + block.pcode.instructions.splice(..0, instrumentation); + } + } +} \ No newline at end of file From 448e11b73716f38c92a81b9641358dcc99e848d2 Mon Sep 17 00:00:00 2001 From: momo5502 Date: Wed, 26 Mar 2025 15:23:31 +0100 Subject: [PATCH 02/20] Support iOS --- .github/workflows/build.yml | 5 +++++ src/icicle/CMakeLists.txt | 8 +++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 2a7cd82e..b51ee6c4 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -180,6 +180,7 @@ jobs: clang-version: 20 - platform: iOS arm64 runner: macos-latest + rust-target: aarch64-apple-ios cmake-options: "-DCMAKE_TOOLCHAIN_FILE=$GITHUB_WORKSPACE/cmake/toolchain/ios.cmake" - platform: macOS arm64 runner: macos-latest @@ -202,6 +203,10 @@ jobs: - name: Install Ninja uses: seanmiddleditch/gha-setup-ninja@v6 + - name: Install Rust Target + if: "${{ matrix.rust-target }}" + run: rustup target add ${{ matrix.rust-target }} + - name: Install Clang if: "${{ matrix.platform == 'Linux x86_64 Clang' }}" run: | diff --git a/src/icicle/CMakeLists.txt b/src/icicle/CMakeLists.txt index c50d4c30..51ea08a0 100644 --- a/src/icicle/CMakeLists.txt +++ b/src/icicle/CMakeLists.txt @@ -10,13 +10,19 @@ if(MSVC) set(ICICLE_RUST_LIB ${ICICLE_ARTIFACT_DIR}/${ICICLE_RUST_PROJECT_NAME}.lib) endif() +set(CARGO_OPTIONS "") + +if(CMAKE_SYSTEM_NAME STREQUAL "iOS") + set(CARGO_OPTIONS "--target=aarch64-apple-ios") +endif() + ExternalProject_Add( icicle-rust-project PREFIX ${CMAKE_CURRENT_BINARY_DIR} SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR} BINARY_DIR ${CMAKE_CURRENT_LIST_DIR} CONFIGURE_COMMAND "" - BUILD_COMMAND ${CMAKE_COMMAND} -E env "CARGO_TARGET_DIR=${ICICLE_BUILD_DIR}" cargo build --all-targets $,--lib,--release> + BUILD_COMMAND ${CMAKE_COMMAND} -E env "CARGO_TARGET_DIR=${ICICLE_BUILD_DIR}" cargo build ${CARGO_OPTIONS} --all-targets $,--lib,--release> INSTALL_COMMAND "" USES_TERMINAL_CONFIGURE 1 USES_TERMINAL_BUILD 1 From 32ebda5fe7c748dbbb58c6bfd36404f38e541684 Mon Sep 17 00:00:00 2001 From: momo5502 Date: Wed, 26 Mar 2025 15:47:33 +0100 Subject: [PATCH 03/20] Support android --- .github/workflows/build.yml | 2 ++ src/icicle/CMakeLists.txt | 8 +++++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index b51ee6c4..d1c25e75 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -189,10 +189,12 @@ jobs: - platform: Android x86_64 runner: ubuntu-24.04 abi: x86_64 + rust-target: x86_64-linux-android cmake-options: "-DCMAKE_TOOLCHAIN_FILE=$GITHUB_WORKSPACE/cmake/toolchain/android-ndk.cmake" - platform: Android arm64-v8a runner: ubuntu-24.04 abi: arm64-v8a + rust-target: aarch64-linux-android cmake-options: "-DCMAKE_TOOLCHAIN_FILE=$GITHUB_WORKSPACE/cmake/toolchain/android-ndk.cmake" steps: - name: Checkout Source diff --git a/src/icicle/CMakeLists.txt b/src/icicle/CMakeLists.txt index 51ea08a0..79f07c8f 100644 --- a/src/icicle/CMakeLists.txt +++ b/src/icicle/CMakeLists.txt @@ -14,6 +14,12 @@ set(CARGO_OPTIONS "") if(CMAKE_SYSTEM_NAME STREQUAL "iOS") set(CARGO_OPTIONS "--target=aarch64-apple-ios") +elseif(CMAKE_SYSTEM_NAME STREQUAL "Android") + if(CMAKE_ANDROID_ARCH_ABI STREQUAL "arm64-v8a") + set(CARGO_OPTIONS "--target=aarch64-linux-android") + else() + set(CARGO_OPTIONS "--target=${CMAKE_ANDROID_ARCH_ABI}-linux-android") + endif() endif() ExternalProject_Add( @@ -22,7 +28,7 @@ ExternalProject_Add( SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR} BINARY_DIR ${CMAKE_CURRENT_LIST_DIR} CONFIGURE_COMMAND "" - BUILD_COMMAND ${CMAKE_COMMAND} -E env "CARGO_TARGET_DIR=${ICICLE_BUILD_DIR}" cargo build ${CARGO_OPTIONS} --all-targets $,--lib,--release> + BUILD_COMMAND ${CMAKE_COMMAND} -E env "CARGO_TARGET_DIR=${ICICLE_BUILD_DIR}" cargo build ${CARGO_OPTIONS} --lib $,-v,--release> INSTALL_COMMAND "" USES_TERMINAL_CONFIGURE 1 USES_TERMINAL_BUILD 1 From 985dd490595d259750ed5fd7ceb7fa6cae9c52da Mon Sep 17 00:00:00 2001 From: momo5502 Date: Wed, 26 Mar 2025 17:48:04 +0100 Subject: [PATCH 04/20] Fix cargo builds --- src/icicle/CMakeLists.txt | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/src/icicle/CMakeLists.txt b/src/icicle/CMakeLists.txt index 79f07c8f..747a9a7d 100644 --- a/src/icicle/CMakeLists.txt +++ b/src/icicle/CMakeLists.txt @@ -4,24 +4,33 @@ set(ICICLE_BUILD_DIR ${CMAKE_CURRENT_BINARY_DIR}/cargo-build) set(ICICLE_ARTIFACT_DIR ${ICICLE_BUILD_DIR}/$,debug,release>) set(ICICLE_RUST_PROJECT_NAME "icicle") -set(ICICLE_RUST_LIB ${ICICLE_ARTIFACT_DIR}/lib${ICICLE_RUST_PROJECT_NAME}.a) +set(ICICLE_RUST_LIBNAME "lib${ICICLE_RUST_PROJECT_NAME}.a") if(MSVC) - set(ICICLE_RUST_LIB ${ICICLE_ARTIFACT_DIR}/${ICICLE_RUST_PROJECT_NAME}.lib) + set(ICICLE_RUST_LIBNAME "${ICICLE_RUST_PROJECT_NAME}.lib") endif() -set(CARGO_OPTIONS "") +set(CARGO_TRIPLE) +set(CARGO_OPTIONS) if(CMAKE_SYSTEM_NAME STREQUAL "iOS") - set(CARGO_OPTIONS "--target=aarch64-apple-ios") + set(CARGO_TRIPLE "aarch64-apple-ios") elseif(CMAKE_SYSTEM_NAME STREQUAL "Android") if(CMAKE_ANDROID_ARCH_ABI STREQUAL "arm64-v8a") - set(CARGO_OPTIONS "--target=aarch64-linux-android") + set(CARGO_TRIPLE "aarch64-linux-android") else() - set(CARGO_OPTIONS "--target=${CMAKE_ANDROID_ARCH_ABI}-linux-android") + set(CARGO_TRIPLE "${CMAKE_ANDROID_ARCH_ABI}-linux-android") endif() endif() +if(CARGO_TRIPLE) + set(CARGO_OPTIONS ${CARGO_OPTIONS} "--target=${CARGO_TRIPLE}") + set(ICICLE_ARTIFACT_DIR ${ICICLE_BUILD_DIR}/${CARGO_TRIPLE}/$,debug,release>) +endif() + + +set(ICICLE_RUST_LIB ${ICICLE_ARTIFACT_DIR}/${ICICLE_RUST_LIBNAME}) + ExternalProject_Add( icicle-rust-project PREFIX ${CMAKE_CURRENT_BINARY_DIR} From 63f54df78c00e714db1c86f47df698e205d79991 Mon Sep 17 00:00:00 2001 From: Maurice Heumann Date: Thu, 27 Mar 2025 15:50:33 +0100 Subject: [PATCH 05/20] Icicle progress --- src/icicle-emulator/icicle_x64_emulator.cpp | 176 +++++++++++++++++++- src/icicle/src/icicle.rs | 65 ++++++++ src/icicle/src/lib.rs | 100 ++++++----- src/windows-emulator/CMakeLists.txt | 1 + 4 files changed, 286 insertions(+), 56 deletions(-) create mode 100644 src/icicle/src/icicle.rs diff --git a/src/icicle-emulator/icicle_x64_emulator.cpp b/src/icicle-emulator/icicle_x64_emulator.cpp index 5a9dba17..ad9321ad 100644 --- a/src/icicle-emulator/icicle_x64_emulator.cpp +++ b/src/icicle-emulator/icicle_x64_emulator.cpp @@ -1,14 +1,182 @@ #define ICICLE_EMULATOR_IMPL #include "icicle_x64_emulator.hpp" -extern "C" void test_rust(); +using icicle_emulator = struct icicle_emulator_; + +extern "C" +{ + icicle_emulator* icicle_create_emulator(); + int32_t icicle_map_memory(icicle_emulator*, uint64_t address, uint64_t length, uint8_t permissions); + int32_t icicle_unmap_memory(icicle_emulator*, uint64_t address, uint64_t length); + void icicle_destroy_emulator(icicle_emulator*); +} namespace icicle { + class icicle_x64_emulator : public x64_emulator + { + public: + icicle_x64_emulator() + : emu_(icicle_create_emulator()) + { + if (!this->emu_) + { + throw std::runtime_error("Failed to create icicle emulator instance"); + } + } + + ~icicle_x64_emulator() override + { + if (this->emu_) + { + icicle_destroy_emulator(this->emu_); + this->emu_ = nullptr; + } + } + + void start(const uint64_t start, const uint64_t end, std::chrono::nanoseconds timeout, + const size_t count) override + { + if (timeout.count() < 0) + { + timeout = {}; + } + } + + void stop() override + { + } + + size_t write_raw_register(const int reg, const void* value, const size_t size) override + { + throw std::runtime_error("Not implemented"); + } + + size_t read_raw_register(const int reg, void* value, const size_t size) override + { + throw std::runtime_error("Not implemented"); + } + + void map_mmio(const uint64_t address, const size_t size, mmio_read_callback read_cb, + mmio_write_callback write_cb) override + { + throw std::runtime_error("Not implemented"); + } + + void map_memory(const uint64_t address, const size_t size, memory_permission permissions) override + { + const auto res = icicle_map_memory(this->emu_, address, size, static_cast(permissions)); + if (!res) + { + throw std::runtime_error("Failed to map memory"); + } + } + + void unmap_memory(const uint64_t address, const size_t size) override + { + const auto res = icicle_unmap_memory(this->emu_, address, size); + if (!res) + { + throw std::runtime_error("Failed to map memory"); + } + } + + bool try_read_memory(const uint64_t address, void* data, const size_t size) const override + { + throw std::runtime_error("Not implemented"); + } + + void read_memory(const uint64_t address, void* data, const size_t size) const override + { + if (!this->try_read_memory(address, data, size)) + { + throw std::runtime_error("Failed to read memory"); + } + } + + void write_memory(const uint64_t address, const void* data, const size_t size) override + { + throw std::runtime_error("Not implemented"); + } + + void apply_memory_protection(const uint64_t address, const size_t size, memory_permission permissions) override + { + throw std::runtime_error("Not implemented"); + } + + emulator_hook* hook_instruction(int instruction_type, instruction_hook_callback callback) override + { + throw std::runtime_error("Not implemented"); + } + + emulator_hook* hook_basic_block(basic_block_hook_callback callback) override + { + throw std::runtime_error("Not implemented"); + } + + emulator_hook* hook_edge_generation(edge_generation_hook_callback callback) override + { + throw std::runtime_error("Not implemented"); + } + + emulator_hook* hook_interrupt(interrupt_hook_callback callback) override + { + throw std::runtime_error("Not implemented"); + } + + emulator_hook* hook_memory_violation(uint64_t address, size_t size, + memory_violation_hook_callback callback) override + { + throw std::runtime_error("Not implemented"); + } + + emulator_hook* hook_memory_access(const uint64_t address, const size_t size, const memory_operation filter, + complex_memory_hook_callback callback) override + { + if (filter == memory_permission::none) + { + return nullptr; + } + + throw std::runtime_error("Not implemented"); + } + + void delete_hook(emulator_hook* hook) override + { + throw std::runtime_error("Not implemented"); + } + + void serialize_state(utils::buffer_serializer& buffer, const bool is_snapshot) const override + { + throw std::runtime_error("Not implemented"); + } + + void deserialize_state(utils::buffer_deserializer& buffer, const bool is_snapshot) override + { + throw std::runtime_error("Not implemented"); + } + + std::vector save_registers() override + { + throw std::runtime_error("Not implemented"); + } + + void restore_registers(const std::vector& register_data) override + { + throw std::runtime_error("Not implemented"); + } + + bool has_violation() const override + { + return false; + } + + private: + icicle_emulator* emu_{}; + }; + std::unique_ptr create_x64_emulator() { - test_rust(); - - return {}; + return std::make_unique(); } } diff --git a/src/icicle/src/icicle.rs b/src/icicle/src/icicle.rs new file mode 100644 index 00000000..b9146cce --- /dev/null +++ b/src/icicle/src/icicle.rs @@ -0,0 +1,65 @@ +fn create_x64_vm() -> icicle_vm::Vm { + let cpu_config = icicle_vm::cpu::Config::from_target_triple("x86_64-none"); + let vm = icicle_vm::build(&cpu_config).unwrap(); + return vm; +} + +fn map_permissions(foreign_permissions: u8) -> u8 { + const FOREIGN_READ: u8 = 1 << 0; + const FOREIGN_WRITE: u8 = 1 << 1; + const FOREIGN_EXEC: u8 = 1 << 2; + + let mut permissions: u8 = 0; + + if (foreign_permissions & FOREIGN_READ) != 0 { + permissions |= icicle_vm::cpu::mem::perm::READ; + } + + if (foreign_permissions & FOREIGN_WRITE) != 0 { + permissions |= icicle_vm::cpu::mem::perm::WRITE; + } + + if (foreign_permissions & FOREIGN_EXEC) != 0 { + permissions |= icicle_vm::cpu::mem::perm::EXEC; + } + + return permissions; +} + +pub struct IcicleEmulator { + vm: icicle_vm::Vm, +} + +impl IcicleEmulator { + pub fn new() -> Self { + Self { + vm: create_x64_vm(), + } + } + + pub fn map_memory(&mut self, address: u64, length: u64, permissions: u8) -> bool { + const MAPPING_PERMISSIONS: u8 = icicle_vm::cpu::mem::perm::MAP + | icicle_vm::cpu::mem::perm::INIT + | icicle_vm::cpu::mem::perm::IN_CODE_CACHE; + + let native_permissions = map_permissions(permissions); + + let mapping = icicle_vm::cpu::mem::Mapping { + perm: native_permissions | MAPPING_PERMISSIONS, + value: 0x0, + }; + + let layout = icicle_vm::cpu::mem::AllocLayout { + addr: Some(address), + size: length, + align: 0x1000, + }; + + let res = self.vm.cpu.mem.alloc_memory(layout, mapping); + return res.is_ok(); + } + + pub fn unmap_memory(&mut self, address: u64, length: u64) -> bool { + return self.vm.cpu.mem.unmap_memory_len(address, length); + } +} diff --git a/src/icicle/src/lib.rs b/src/icicle/src/lib.rs index 5c1cc04b..a766834a 100644 --- a/src/icicle/src/lib.rs +++ b/src/icicle/src/lib.rs @@ -1,58 +1,54 @@ +mod icicle; + +use icicle::IcicleEmulator; +use std::os::raw::c_void; + #[unsafe(no_mangle)] -pub fn test_rust() { - // Setup the CPU state for the target triple - let cpu_config = icicle_vm::cpu::Config::from_target_triple("x86_64-none"); - let mut vm = icicle_vm::build(&cpu_config).unwrap(); - - // Setup an environment to run inside of. - //let mut env = icicle_vm::env::build_auto(&mut vm).unwrap(); - // Load a binary into the environment. - //env.load(&mut vm.cpu, b"./test.elf").unwrap(); - //vm.env = env; - - let mapping = icicle_vm::cpu::mem::Mapping { perm: icicle_vm::cpu::mem::perm::ALL, value: 0x0 }; - - let alloc1 = - vm.cpu.mem.alloc_memory(icicle_vm::cpu::mem::AllocLayout { addr: Some(0x10000), size: 0x100, align: 0x100 }, mapping).unwrap(); - - // Add instrumentation - let counter = vm.cpu.trace.register_store(vec![0_u64]); - vm.add_injector(BlockCounter { counter }); - - // Run until the VM exits. - let exit = vm.run(); - println!("{exit:?}\n{}", icicle_vm::debug::current_disasm(&mut vm)); - - - // Read instrumentation data. - let blocks_hit = vm.cpu.trace[counter].as_any().downcast_ref::>().unwrap()[0]; - let blocks_executed = blocks_hit.saturating_sub(1); - println!("{blocks_executed} blocks were executed"); +pub fn icicle_create_emulator() -> *mut c_void { + let emulator = Box::new(IcicleEmulator::new()); + return Box::into_raw(emulator) as *mut c_void; } -struct BlockCounter { - counter: icicle_vm::cpu::StoreRef, +#[unsafe(no_mangle)] +pub fn icicle_map_memory( + ptr: *mut c_void, + address: u64, + length: u64, + permissions: u8, +) -> i32 { + unsafe { + let emulator = &mut *(ptr as *mut IcicleEmulator); + let res = emulator.map_memory(address, length, permissions); + + if res { + return 1; + } + + return 0; + } } -impl icicle_vm::CodeInjector for BlockCounter { - fn inject( - &mut self, - _cpu: &mut icicle_vm::cpu::Cpu, - group: &icicle_vm::cpu::BlockGroup, - code: &mut icicle_vm::BlockTable, - ) { - let store_id = self.counter.get_store_id(); - for block in &mut code.blocks[group.range()] { - // counter += 1 - let counter = block.pcode.alloc_tmp(8); - let instrumentation = [ - (counter, pcode::Op::Load(store_id), 0_u64).into(), - (counter, pcode::Op::IntAdd, (counter, 1_u64)).into(), - (pcode::Op::Store(store_id), (0_u64, counter)).into(), - ]; +#[unsafe(no_mangle)] +pub fn icicle_unmap_memory(ptr: *mut c_void, address: u64, length: u64) -> i32 { + unsafe { + let emulator = &mut *(ptr as *mut IcicleEmulator); + let res = emulator.unmap_memory(address, length); - // Inject the instrumentation at the start of the block. - block.pcode.instructions.splice(..0, instrumentation); - } - } -} \ No newline at end of file + if res { + return 1; + } + + return 0; + } +} + +#[unsafe(no_mangle)] +pub fn icicle_destroy_emulator(ptr: *mut c_void) { + if ptr.is_null() { + return; + } + + unsafe { + let _ = Box::from_raw(ptr as *mut IcicleEmulator); + } +} diff --git a/src/windows-emulator/CMakeLists.txt b/src/windows-emulator/CMakeLists.txt index 0da4f6e6..53ee76c8 100644 --- a/src/windows-emulator/CMakeLists.txt +++ b/src/windows-emulator/CMakeLists.txt @@ -16,6 +16,7 @@ endif() target_link_libraries(windows-emulator PRIVATE unicorn-emulator + icicle-emulator ) target_link_libraries(windows-emulator PUBLIC emulator) From 65d0da70a0baa8616ccf5e360e835ac6f00b4295 Mon Sep 17 00:00:00 2001 From: momo5502 Date: Thu, 27 Mar 2025 20:15:55 +0100 Subject: [PATCH 06/20] Fix rust cmake --- src/icicle/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/icicle/CMakeLists.txt b/src/icicle/CMakeLists.txt index 747a9a7d..be4badc7 100644 --- a/src/icicle/CMakeLists.txt +++ b/src/icicle/CMakeLists.txt @@ -37,7 +37,7 @@ ExternalProject_Add( SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR} BINARY_DIR ${CMAKE_CURRENT_LIST_DIR} CONFIGURE_COMMAND "" - BUILD_COMMAND ${CMAKE_COMMAND} -E env "CARGO_TARGET_DIR=${ICICLE_BUILD_DIR}" cargo build ${CARGO_OPTIONS} --lib $,-v,--release> + BUILD_COMMAND ${CMAKE_COMMAND} -E env "CARGO_TARGET_DIR=${ICICLE_BUILD_DIR}" cargo build ${CARGO_OPTIONS} --lib --profile $,dev,release> INSTALL_COMMAND "" USES_TERMINAL_CONFIGURE 1 USES_TERMINAL_BUILD 1 From da6ba1a32904174d2ff624efe44f8872b6d00f36 Mon Sep 17 00:00:00 2001 From: momo5502 Date: Thu, 27 Mar 2025 20:57:04 +0100 Subject: [PATCH 07/20] Support reading and writing memory --- src/icicle-emulator/icicle_x64_emulator.cpp | 38 ++++++++------ src/icicle/.gitignore | 2 + src/icicle/src/icicle.rs | 24 ++++++++- src/icicle/src/lib.rs | 56 +++++++++++++++------ 4 files changed, 87 insertions(+), 33 deletions(-) create mode 100644 src/icicle/.gitignore diff --git a/src/icicle-emulator/icicle_x64_emulator.cpp b/src/icicle-emulator/icicle_x64_emulator.cpp index ad9321ad..076aed44 100644 --- a/src/icicle-emulator/icicle_x64_emulator.cpp +++ b/src/icicle-emulator/icicle_x64_emulator.cpp @@ -6,13 +6,27 @@ using icicle_emulator = struct icicle_emulator_; extern "C" { icicle_emulator* icicle_create_emulator(); + int32_t icicle_protect_memory(icicle_emulator*, uint64_t address, uint64_t length, uint8_t permissions); int32_t icicle_map_memory(icicle_emulator*, uint64_t address, uint64_t length, uint8_t permissions); int32_t icicle_unmap_memory(icicle_emulator*, uint64_t address, uint64_t length); + int32_t icicle_read_memory(icicle_emulator*, uint64_t address, void* data, size_t length); + int32_t icicle_write_memory(icicle_emulator*, uint64_t address, const void* data, size_t length); void icicle_destroy_emulator(icicle_emulator*); } namespace icicle { + namespace + { + void ice(const bool result, const std::string_view error) + { + if (!result) + { + throw std::runtime_error(std::string(error)); + } + } + } + class icicle_x64_emulator : public x64_emulator { public: @@ -66,42 +80,36 @@ namespace icicle void map_memory(const uint64_t address, const size_t size, memory_permission permissions) override { const auto res = icicle_map_memory(this->emu_, address, size, static_cast(permissions)); - if (!res) - { - throw std::runtime_error("Failed to map memory"); - } + ice(res, "Failed to map memory"); } void unmap_memory(const uint64_t address, const size_t size) override { const auto res = icicle_unmap_memory(this->emu_, address, size); - if (!res) - { - throw std::runtime_error("Failed to map memory"); - } + ice(res, "Failed to unmap memory"); } bool try_read_memory(const uint64_t address, void* data, const size_t size) const override { - throw std::runtime_error("Not implemented"); + return icicle_read_memory(this->emu_, address, data, size); } void read_memory(const uint64_t address, void* data, const size_t size) const override { - if (!this->try_read_memory(address, data, size)) - { - throw std::runtime_error("Failed to read memory"); - } + const auto res = this->try_read_memory(address, data, size); + ice(res, "Failed to read memory"); } void write_memory(const uint64_t address, const void* data, const size_t size) override { - throw std::runtime_error("Not implemented"); + const auto res = icicle_write_memory(this->emu_, address, data, size); + ice(res, "Failed to write memory"); } void apply_memory_protection(const uint64_t address, const size_t size, memory_permission permissions) override { - throw std::runtime_error("Not implemented"); + const auto res = icicle_protect_memory(this->emu_, address, size, static_cast(permissions)); + ice(res, "Failed to apply permissions"); } emulator_hook* hook_instruction(int instruction_type, instruction_hook_callback callback) override diff --git a/src/icicle/.gitignore b/src/icicle/.gitignore new file mode 100644 index 00000000..31aef32c --- /dev/null +++ b/src/icicle/.gitignore @@ -0,0 +1,2 @@ +/target +/Ghidra diff --git a/src/icicle/src/icicle.rs b/src/icicle/src/icicle.rs index b9146cce..f2322da9 100644 --- a/src/icicle/src/icicle.rs +++ b/src/icicle/src/icicle.rs @@ -37,6 +37,10 @@ impl IcicleEmulator { } } + fn get_mem(&mut self) -> &mut icicle_vm::cpu::Mmu { + return &mut self.vm.cpu.mem; + } + pub fn map_memory(&mut self, address: u64, length: u64, permissions: u8) -> bool { const MAPPING_PERMISSIONS: u8 = icicle_vm::cpu::mem::perm::MAP | icicle_vm::cpu::mem::perm::INIT @@ -55,11 +59,27 @@ impl IcicleEmulator { align: 0x1000, }; - let res = self.vm.cpu.mem.alloc_memory(layout, mapping); + let res = self.get_mem().alloc_memory(layout, mapping); return res.is_ok(); } pub fn unmap_memory(&mut self, address: u64, length: u64) -> bool { - return self.vm.cpu.mem.unmap_memory_len(address, length); + return self.get_mem().unmap_memory_len(address, length); + } + + pub fn protect_memory(&mut self, address: u64, length: u64, permissions: u8) -> bool { + let native_permissions = map_permissions(permissions); + let res = self.get_mem().update_perm(address, length, native_permissions); + return res.is_ok(); + } + + pub fn write_memory(&mut self, address: u64, data: &[u8]) -> bool { + let res = self.get_mem().write_bytes(address, data, icicle_vm::cpu::mem::perm::WRITE); + return res.is_ok(); + } + + pub fn read_memory(&mut self, address: u64, data: &mut [u8]) -> bool { + let res = self.get_mem().read_bytes(address, data, icicle_vm::cpu::mem::perm::READ); + return res.is_ok(); } } diff --git a/src/icicle/src/lib.rs b/src/icicle/src/lib.rs index a766834a..0e2ef681 100644 --- a/src/icicle/src/lib.rs +++ b/src/icicle/src/lib.rs @@ -3,6 +3,14 @@ mod icicle; use icicle::IcicleEmulator; use std::os::raw::c_void; +fn to_cbool(value: bool) -> i32 { + if value { + return 1; + } + + return 0; +} + #[unsafe(no_mangle)] pub fn icicle_create_emulator() -> *mut c_void { let emulator = Box::new(IcicleEmulator::new()); @@ -10,21 +18,11 @@ pub fn icicle_create_emulator() -> *mut c_void { } #[unsafe(no_mangle)] -pub fn icicle_map_memory( - ptr: *mut c_void, - address: u64, - length: u64, - permissions: u8, -) -> i32 { +pub fn icicle_map_memory(ptr: *mut c_void, address: u64, length: u64, permissions: u8) -> i32 { unsafe { let emulator = &mut *(ptr as *mut IcicleEmulator); let res = emulator.map_memory(address, length, permissions); - - if res { - return 1; - } - - return 0; + return to_cbool(res); } } @@ -33,12 +31,38 @@ pub fn icicle_unmap_memory(ptr: *mut c_void, address: u64, length: u64) -> i32 { unsafe { let emulator = &mut *(ptr as *mut IcicleEmulator); let res = emulator.unmap_memory(address, length); + return to_cbool(res); + } +} - if res { - return 1; - } +#[unsafe(no_mangle)] +pub fn icicle_protect_memory(ptr: *mut c_void, address: u64, length: u64, permissions: u8) -> i32 { + unsafe { + let emulator = &mut *(ptr as *mut IcicleEmulator); + let res = emulator.protect_memory(address, length, permissions); + return to_cbool(res); + } +} - return 0; +#[unsafe(no_mangle)] +pub fn icicle_write_memory(ptr: *mut c_void, address: u64, data: *const c_void, size: usize) -> i32 { + unsafe { + let emulator = &mut *(ptr as *mut IcicleEmulator); + let u8_ptr = data as *const u8; + let u8_slice = std::slice::from_raw_parts(u8_ptr, size); + let res = emulator.write_memory(address, u8_slice); + return to_cbool(res); + } +} + +#[unsafe(no_mangle)] +pub fn icicle_read_memory(ptr: *mut c_void, address: u64, data: *mut c_void, size: usize) -> i32 { + unsafe { + let emulator = &mut *(ptr as *mut IcicleEmulator); + let u8_ptr = data as *mut u8; + let u8_slice = std::slice::from_raw_parts_mut(u8_ptr, size); + let res = emulator.read_memory(address, u8_slice); + return to_cbool(res); } } From ab144de1251b7f384e65a4de59238ba31541a18f Mon Sep 17 00:00:00 2001 From: Maurice Heumann Date: Fri, 28 Mar 2025 08:57:02 +0100 Subject: [PATCH 08/20] Prepare register support --- src/icicle-emulator/icicle_x64_emulator.cpp | 6 +- src/icicle/Cargo.lock | 1 + src/icicle/Cargo.toml | 1 + src/icicle/src/icicle.rs | 994 +++++++++++++++++++- src/icicle/src/lib.rs | 26 +- 5 files changed, 1017 insertions(+), 11 deletions(-) diff --git a/src/icicle-emulator/icicle_x64_emulator.cpp b/src/icicle-emulator/icicle_x64_emulator.cpp index 076aed44..fc396e34 100644 --- a/src/icicle-emulator/icicle_x64_emulator.cpp +++ b/src/icicle-emulator/icicle_x64_emulator.cpp @@ -11,6 +11,8 @@ extern "C" int32_t icicle_unmap_memory(icicle_emulator*, uint64_t address, uint64_t length); int32_t icicle_read_memory(icicle_emulator*, uint64_t address, void* data, size_t length); int32_t icicle_write_memory(icicle_emulator*, uint64_t address, const void* data, size_t length); + size_t icicle_read_register(icicle_emulator*, int reg, void* data, size_t length); + size_t icicle_write_register(icicle_emulator*, int reg, const void* data, size_t length); void icicle_destroy_emulator(icicle_emulator*); } @@ -63,12 +65,12 @@ namespace icicle size_t write_raw_register(const int reg, const void* value, const size_t size) override { - throw std::runtime_error("Not implemented"); + return icicle_write_register(this->emu_, reg, value, size); } size_t read_raw_register(const int reg, void* value, const size_t size) override { - throw std::runtime_error("Not implemented"); + return icicle_read_register(this->emu_, reg, value, size); } void map_mmio(const uint64_t address, const size_t size, mmio_read_callback read_cb, diff --git a/src/icicle/Cargo.lock b/src/icicle/Cargo.lock index 555e93a0..93451e3b 100644 --- a/src/icicle/Cargo.lock +++ b/src/icicle/Cargo.lock @@ -362,6 +362,7 @@ dependencies = [ name = "icicle" version = "0.1.0" dependencies = [ + "icicle-cpu", "icicle-vm", "pcode", ] diff --git a/src/icicle/Cargo.toml b/src/icicle/Cargo.toml index 021326a6..8019c2b2 100644 --- a/src/icicle/Cargo.toml +++ b/src/icicle/Cargo.toml @@ -8,4 +8,5 @@ crate-type = ["staticlib"] [dependencies] icicle-vm = { git = "https://github.com/icicle-emu/icicle-emu" } +icicle-cpu = { git = "https://github.com/icicle-emu/icicle-emu" } pcode = { git = "https://github.com/icicle-emu/icicle-emu" } diff --git a/src/icicle/src/icicle.rs b/src/icicle/src/icicle.rs index f2322da9..e6be7e36 100644 --- a/src/icicle/src/icicle.rs +++ b/src/icicle/src/icicle.rs @@ -1,3 +1,5 @@ +use icicle_cpu::ValueSource; + fn create_x64_vm() -> icicle_vm::Vm { let cpu_config = icicle_vm::cpu::Config::from_target_triple("x86_64-none"); let vm = icicle_vm::build(&cpu_config).unwrap(); @@ -28,12 +30,15 @@ fn map_permissions(foreign_permissions: u8) -> u8 { pub struct IcicleEmulator { vm: icicle_vm::Vm, + reg: X64RegisterNodes, } impl IcicleEmulator { pub fn new() -> Self { + let vm_i = create_x64_vm(); Self { - vm: create_x64_vm(), + reg: X64RegisterNodes::new(&vm_i.cpu.arch), + vm: vm_i, } } @@ -69,17 +74,998 @@ impl IcicleEmulator { pub fn protect_memory(&mut self, address: u64, length: u64, permissions: u8) -> bool { let native_permissions = map_permissions(permissions); - let res = self.get_mem().update_perm(address, length, native_permissions); + let res = self + .get_mem() + .update_perm(address, length, native_permissions); return res.is_ok(); } pub fn write_memory(&mut self, address: u64, data: &[u8]) -> bool { - let res = self.get_mem().write_bytes(address, data, icicle_vm::cpu::mem::perm::WRITE); + let res = self + .get_mem() + .write_bytes(address, data, icicle_vm::cpu::mem::perm::NONE); return res.is_ok(); } pub fn read_memory(&mut self, address: u64, data: &mut [u8]) -> bool { - let res = self.get_mem().read_bytes(address, data, icicle_vm::cpu::mem::perm::READ); + let res = self + .get_mem() + .read_bytes(address, data, icicle_vm::cpu::mem::perm::NONE); return res.is_ok(); } + + pub fn read_register(&mut self, reg: X64Register, buffer: &mut [u8]) -> usize { + let reg_node = self.reg.get_node(reg); + + let res = self.vm.cpu.read_dynamic(pcode::Value::Var(reg_node)); + let bytes: [u8; 32] = res.zxt(); + + let len = std::cmp::min(bytes.len(), buffer.len()); + buffer[..len].copy_from_slice(&bytes[..len]); + + return reg_node.size.into(); + } + + pub fn write_register(&mut self, reg: X64Register, data: &[u8]) -> usize { + let reg_node = self.reg.get_node(reg); + + let mut buffer = [0u8; 32]; + let len = std::cmp::min(data.len(), buffer.len()); + buffer[..len].copy_from_slice(&data[..len]); + + self.vm.cpu.write_var(reg_node, buffer); + + return reg_node.size.into(); + } +} + +// ------------------------------ + +#[repr(i32)] +pub enum X64Register { + Invalid = 0, + Ah, + Al, + Ax, + Bh, + Bl, + Bp, + Bpl, + Bx, + Ch, + Cl, + Cs, + Cx, + Dh, + Di, + Dil, + Dl, + Ds, + Dx, + Eax, + Ebp, + Ebx, + Ecx, + Edi, + Edx, + Eflags, + Eip, + Es = 26 + 2, + Esi, + Esp, + Fpsw, + Fs, + Gs, + Ip, + Rax, + Rbp, + Rbx, + Rcx, + Rdi, + Rdx, + Rip, + Rsi = 41 + 2, + Rsp, + Si, + Sil, + Sp, + Spl, + Ss, + Cr0, + Cr1, + Cr2, + Cr3, + Cr4, + Cr8 = 54 + 4, + Dr0 = 58 + 8, + Dr1, + Dr2, + Dr3, + Dr4, + Dr5, + Dr6, + Dr7, + Fp0 = 73 + 9, + Fp1, + Fp2, + Fp3, + Fp4, + Fp5, + Fp6, + Fp7, + K0, + K1, + K2, + K3, + K4, + K5, + K6, + K7, + Mm0, + Mm1, + Mm2, + Mm3, + Mm4, + Mm5, + Mm6, + Mm7, + R8, + R9, + R10, + R11, + R12, + R13, + R14, + R15, + St0, + St1, + St2, + St3, + St4, + St5, + St6, + St7, + Xmm0, + Xmm1, + Xmm2, + Xmm3, + Xmm4, + Xmm5, + Xmm6, + Xmm7, + Xmm8, + Xmm9, + Xmm10, + Xmm11, + Xmm12, + Xmm13, + Xmm14, + Xmm15, + Xmm16, + Xmm17, + Xmm18, + Xmm19, + Xmm20, + Xmm21, + Xmm22, + Xmm23, + Xmm24, + Xmm25, + Xmm26, + Xmm27, + Xmm28, + Xmm29, + Xmm30, + Xmm31, + Ymm0, + Ymm1, + Ymm2, + Ymm3, + Ymm4, + Ymm5, + Ymm6, + Ymm7, + Ymm8, + Ymm9, + Ymm10, + Ymm11, + Ymm12, + Ymm13, + Ymm14, + Ymm15, + Ymm16, + Ymm17, + Ymm18, + Ymm19, + Ymm20, + Ymm21, + Ymm22, + Ymm23, + Ymm24, + Ymm25, + Ymm26, + Ymm27, + Ymm28, + Ymm29, + Ymm30, + Ymm31, + Zmm0, + Zmm1, + Zmm2, + Zmm3, + Zmm4, + Zmm5, + Zmm6, + Zmm7, + Zmm8, + Zmm9, + Zmm10, + Zmm11, + Zmm12, + Zmm13, + Zmm14, + Zmm15, + Zmm16, + Zmm17, + Zmm18, + Zmm19, + Zmm20, + Zmm21, + Zmm22, + Zmm23, + Zmm24, + Zmm25, + Zmm26, + Zmm27, + Zmm28, + Zmm29, + Zmm30, + Zmm31, + R8b, + R9b, + R10b, + R11b, + R12b, + R13b, + R14b, + R15b, + R8d, + R9d, + R10d, + R11d, + R12d, + R13d, + R14d, + R15d, + R8w, + R9w, + R10w, + R11w, + R12w, + R13w, + R14w, + R15w, + Idtr, + Gdtr, + Ldtr, + Tr, + Fpcw, + Fptag, + Msr, + Mxcsr, + FsBase, + GsBase, + Flags, + Rflags, + Fip, + Fcs, + Fdp, + Fds, + Fop, + End, // Must be last +} + +#[derive(Clone)] +struct X64RegisterNodes { + rax: pcode::VarNode, + rbx: pcode::VarNode, + rcx: pcode::VarNode, + rdx: pcode::VarNode, + rsi: pcode::VarNode, + rdi: pcode::VarNode, + rbp: pcode::VarNode, + rsp: pcode::VarNode, + r8: pcode::VarNode, + r9: pcode::VarNode, + r10: pcode::VarNode, + r11: pcode::VarNode, + r12: pcode::VarNode, + r13: pcode::VarNode, + r14: pcode::VarNode, + r15: pcode::VarNode, + rip: pcode::VarNode, + eflags: pcode::VarNode, + cs: pcode::VarNode, + ds: pcode::VarNode, + es: pcode::VarNode, + fs: pcode::VarNode, + gs: pcode::VarNode, + ss: pcode::VarNode, + ah: pcode::VarNode, + al: pcode::VarNode, + ax: pcode::VarNode, + bh: pcode::VarNode, + bl: pcode::VarNode, + bpl: pcode::VarNode, + ch: pcode::VarNode, + cl: pcode::VarNode, + cx: pcode::VarNode, + dh: pcode::VarNode, + dil: pcode::VarNode, + dl: pcode::VarNode, + dx: pcode::VarNode, + eax: pcode::VarNode, + ebp: pcode::VarNode, + ebx: pcode::VarNode, + ecx: pcode::VarNode, + edi: pcode::VarNode, + edx: pcode::VarNode, + esi: pcode::VarNode, + esp: pcode::VarNode, + fpsw: pcode::VarNode, + gdtr: pcode::VarNode, + idtr: pcode::VarNode, + ldtr: pcode::VarNode, + tr: pcode::VarNode, + cr0: pcode::VarNode, + cr1: pcode::VarNode, + cr2: pcode::VarNode, + cr3: pcode::VarNode, + cr4: pcode::VarNode, + cr8: pcode::VarNode, + dr0: pcode::VarNode, + dr1: pcode::VarNode, + dr2: pcode::VarNode, + dr3: pcode::VarNode, + dr4: pcode::VarNode, + dr5: pcode::VarNode, + dr6: pcode::VarNode, + dr7: pcode::VarNode, + fp0: pcode::VarNode, + fp1: pcode::VarNode, + fp2: pcode::VarNode, + fp3: pcode::VarNode, + fp4: pcode::VarNode, + fp5: pcode::VarNode, + fp6: pcode::VarNode, + fp7: pcode::VarNode, + /*k0: pcode::VarNode, + k1: pcode::VarNode, + k2: pcode::VarNode, + k3: pcode::VarNode, + k4: pcode::VarNode, + k5: pcode::VarNode, + k6: pcode::VarNode, + k7: pcode::VarNode,*/ + mm0: pcode::VarNode, + mm1: pcode::VarNode, + mm2: pcode::VarNode, + mm3: pcode::VarNode, + mm4: pcode::VarNode, + mm5: pcode::VarNode, + mm6: pcode::VarNode, + mm7: pcode::VarNode, + st0: pcode::VarNode, + st1: pcode::VarNode, + st2: pcode::VarNode, + st3: pcode::VarNode, + st4: pcode::VarNode, + st5: pcode::VarNode, + st6: pcode::VarNode, + st7: pcode::VarNode, + xmm0: pcode::VarNode, + xmm1: pcode::VarNode, + xmm2: pcode::VarNode, + xmm3: pcode::VarNode, + xmm4: pcode::VarNode, + xmm5: pcode::VarNode, + xmm6: pcode::VarNode, + xmm7: pcode::VarNode, + xmm8: pcode::VarNode, + xmm9: pcode::VarNode, + xmm10: pcode::VarNode, + xmm11: pcode::VarNode, + xmm12: pcode::VarNode, + xmm13: pcode::VarNode, + xmm14: pcode::VarNode, + xmm15: pcode::VarNode, + /*xmm16: pcode::VarNode, + xmm17: pcode::VarNode, + xmm18: pcode::VarNode, + xmm19: pcode::VarNode, + xmm20: pcode::VarNode, + xmm21: pcode::VarNode, + xmm22: pcode::VarNode, + xmm23: pcode::VarNode, + xmm24: pcode::VarNode, + xmm25: pcode::VarNode, + xmm26: pcode::VarNode, + xmm27: pcode::VarNode, + xmm28: pcode::VarNode, + xmm29: pcode::VarNode, + xmm30: pcode::VarNode, + xmm31: pcode::VarNode,*/ + ymm0: pcode::VarNode, + ymm1: pcode::VarNode, + ymm2: pcode::VarNode, + ymm3: pcode::VarNode, + ymm4: pcode::VarNode, + ymm5: pcode::VarNode, + ymm6: pcode::VarNode, + ymm7: pcode::VarNode, + ymm8: pcode::VarNode, + ymm9: pcode::VarNode, + ymm10: pcode::VarNode, + ymm11: pcode::VarNode, + ymm12: pcode::VarNode, + ymm13: pcode::VarNode, + ymm14: pcode::VarNode, + ymm15: pcode::VarNode, + /*ymm16: pcode::VarNode, + ymm17: pcode::VarNode, + ymm18: pcode::VarNode, + ymm19: pcode::VarNode, + ymm20: pcode::VarNode, + ymm21: pcode::VarNode, + ymm22: pcode::VarNode, + ymm23: pcode::VarNode, + ymm24: pcode::VarNode, + ymm25: pcode::VarNode, + ymm26: pcode::VarNode, + ymm27: pcode::VarNode, + ymm28: pcode::VarNode, + ymm29: pcode::VarNode, + ymm30: pcode::VarNode, + ymm31: pcode::VarNode,*/ + /*zmm0: pcode::VarNode, + zmm1: pcode::VarNode, + zmm2: pcode::VarNode, + zmm3: pcode::VarNode, + zmm4: pcode::VarNode, + zmm5: pcode::VarNode, + zmm6: pcode::VarNode, + zmm7: pcode::VarNode, + zmm8: pcode::VarNode, + zmm9: pcode::VarNode, + zmm10: pcode::VarNode, + zmm11: pcode::VarNode, + zmm12: pcode::VarNode, + zmm13: pcode::VarNode, + zmm14: pcode::VarNode, + zmm15: pcode::VarNode, + zmm16: pcode::VarNode, + zmm17: pcode::VarNode, + zmm18: pcode::VarNode, + zmm19: pcode::VarNode, + zmm20: pcode::VarNode, + zmm21: pcode::VarNode, + zmm22: pcode::VarNode, + zmm23: pcode::VarNode, + zmm24: pcode::VarNode, + zmm25: pcode::VarNode, + zmm26: pcode::VarNode, + zmm27: pcode::VarNode, + zmm28: pcode::VarNode, + zmm29: pcode::VarNode, + zmm30: pcode::VarNode, + zmm31: pcode::VarNode,*/ + r8b: pcode::VarNode, + r9b: pcode::VarNode, + r10b: pcode::VarNode, + r11b: pcode::VarNode, + r12b: pcode::VarNode, + r13b: pcode::VarNode, + r14b: pcode::VarNode, + r15b: pcode::VarNode, + r8d: pcode::VarNode, + r9d: pcode::VarNode, + r10d: pcode::VarNode, + r11d: pcode::VarNode, + r12d: pcode::VarNode, + r13d: pcode::VarNode, + r14d: pcode::VarNode, + r15d: pcode::VarNode, + r8w: pcode::VarNode, + r9w: pcode::VarNode, + r10w: pcode::VarNode, + r11w: pcode::VarNode, + r12w: pcode::VarNode, + r13w: pcode::VarNode, + r14w: pcode::VarNode, + r15w: pcode::VarNode, + fpcw: pcode::VarNode, + fptag: pcode::VarNode, + //msr: pcode::VarNode, + mxcsr: pcode::VarNode, + //fs_base: pcode::VarNode, + //gs_base: pcode::VarNode, + flags: pcode::VarNode, + rflags: pcode::VarNode, + fip: pcode::VarNode, + //fcs: pcode::VarNode, + fdp: pcode::VarNode, + //fds: pcode::VarNode, + fop: pcode::VarNode, +} + +impl X64RegisterNodes { + pub fn new(arch: &icicle_cpu::Arch) -> Self { + let r = |name: &str| arch.sleigh.get_reg(name).unwrap().var; + Self { + rax: r("RAX"), + rbx: r("RBX"), + rcx: r("RCX"), + rdx: r("RDX"), + rsi: r("RSI"), + rdi: r("RDI"), + rbp: r("RBP"), + rsp: r("RSP"), + r8: r("R8"), + r9: r("R9"), + r10: r("R10"), + r11: r("R11"), + r12: r("R12"), + r13: r("R13"), + r14: r("R14"), + r15: r("R15"), + rip: r("RIP"), + eflags: r("eflags"), + cs: r("CS"), + ds: r("DS"), + es: r("ES"), + fs: r("FS"), + gs: r("GS"), + ss: r("SS"), + ah: r("AH"), + al: r("AL"), + ax: r("AX"), + bh: r("BH"), + bl: r("BL"), + bpl: r("BPL"), + ch: r("CH"), + cl: r("CL"), + cx: r("CX"), + dh: r("DH"), + dil: r("DIL"), + dl: r("DL"), + dx: r("DX"), + eax: r("EAX"), + ebp: r("EBP"), + ebx: r("EBX"), + ecx: r("ECX"), + edi: r("EDI"), + edx: r("EDX"), + esi: r("ESI"), + esp: r("ESP"), + fpsw: r("FPUStatusWord"), + gdtr: r("GDTR"), + idtr: r("IDTR"), + ldtr: r("LDTR"), + tr: r("TR"), + cr0: r("CR0"), + cr1: r("CR1"), + cr2: r("CR2"), + cr3: r("CR3"), + cr4: r("CR4"), + cr8: r("CR8"), + dr0: r("DR0"), + dr1: r("DR1"), + dr2: r("DR2"), + dr3: r("DR3"), + dr4: r("DR4"), + dr5: r("DR5"), + dr6: r("DR6"), + dr7: r("DR7"), + fp0: r("ST0"), // ?? + fp1: r("ST1"), + fp2: r("ST2"), + fp3: r("ST3"), + fp4: r("ST4"), + fp5: r("ST5"), + fp6: r("ST6"), + fp7: r("ST7"), + /*k0: r("K0"), + k1: r("K1"), + k2: r("K2"), + k3: r("K3"), + k4: r("K4"), + k5: r("K5"), + k6: r("K6"), + k7: r("K7"),*/ + mm0: r("MM0"), + mm1: r("MM1"), + mm2: r("MM2"), + mm3: r("MM3"), + mm4: r("MM4"), + mm5: r("MM5"), + mm6: r("MM6"), + mm7: r("MM7"), + st0: r("ST0"), + st1: r("ST1"), + st2: r("ST2"), + st3: r("ST3"), + st4: r("ST4"), + st5: r("ST5"), + st6: r("ST6"), + st7: r("ST7"), + xmm0: r("XMM0"), + xmm1: r("XMM1"), + xmm2: r("XMM2"), + xmm3: r("XMM3"), + xmm4: r("XMM4"), + xmm5: r("XMM5"), + xmm6: r("XMM6"), + xmm7: r("XMM7"), + xmm8: r("XMM8"), + xmm9: r("XMM9"), + xmm10: r("XMM10"), + xmm11: r("XMM11"), + xmm12: r("XMM12"), + xmm13: r("XMM13"), + xmm14: r("XMM14"), + xmm15: r("XMM15"), + /*xmm16: r("XMM16"), + xmm17: r("XMM17"), + xmm18: r("XMM18"), + xmm19: r("XMM19"), + xmm20: r("XMM20"), + xmm21: r("XMM21"), + xmm22: r("XMM22"), + xmm23: r("XMM23"), + xmm24: r("XMM24"), + xmm25: r("XMM25"), + xmm26: r("XMM26"), + xmm27: r("XMM27"), + xmm28: r("XMM28"), + xmm29: r("XMM29"), + xmm30: r("XMM30"), + xmm31: r("XMM31"),*/ + ymm0: r("YMM0"), + ymm1: r("YMM1"), + ymm2: r("YMM2"), + ymm3: r("YMM3"), + ymm4: r("YMM4"), + ymm5: r("YMM5"), + ymm6: r("YMM6"), + ymm7: r("YMM7"), + ymm8: r("YMM8"), + ymm9: r("YMM9"), + ymm10: r("YMM10"), + ymm11: r("YMM11"), + ymm12: r("YMM12"), + ymm13: r("YMM13"), + ymm14: r("YMM14"), + ymm15: r("YMM15"), + /*ymm16: r("YMM16"), + ymm17: r("YMM17"), + ymm18: r("YMM18"), + ymm19: r("YMM19"), + ymm20: r("YMM20"), + ymm21: r("YMM21"), + ymm22: r("YMM22"), + ymm23: r("YMM23"), + ymm24: r("YMM24"), + ymm25: r("YMM25"), + ymm26: r("YMM26"), + ymm27: r("YMM27"), + ymm28: r("YMM28"), + ymm29: r("YMM29"), + ymm30: r("YMM30"), + ymm31: r("YMM31"),*/ + /*zmm0: r("ZMM0"), + zmm1: r("ZMM1"), + zmm2: r("ZMM2"), + zmm3: r("ZMM3"), + zmm4: r("ZMM4"), + zmm5: r("ZMM5"), + zmm6: r("ZMM6"), + zmm7: r("ZMM7"), + zmm8: r("ZMM8"), + zmm9: r("ZMM9"), + zmm10: r("ZMM10"), + zmm11: r("ZMM11"), + zmm12: r("ZMM12"), + zmm13: r("ZMM13"), + zmm14: r("ZMM14"), + zmm15: r("ZMM15"), + zmm16: r("ZMM16"), + zmm17: r("ZMM17"), + zmm18: r("ZMM18"), + zmm19: r("ZMM19"), + zmm20: r("ZMM20"), + zmm21: r("ZMM21"), + zmm22: r("ZMM22"), + zmm23: r("ZMM23"), + zmm24: r("ZMM24"), + zmm25: r("ZMM25"), + zmm26: r("ZMM26"), + zmm27: r("ZMM27"), + zmm28: r("ZMM28"), + zmm29: r("ZMM29"), + zmm30: r("ZMM30"), + zmm31: r("ZMM31"),*/ + r8b: r("R8B"), + r9b: r("R9B"), + r10b: r("R10B"), + r11b: r("R11B"), + r12b: r("R12B"), + r13b: r("R13B"), + r14b: r("R14B"), + r15b: r("R15B"), + r8d: r("R8D"), + r9d: r("R9D"), + r10d: r("R10D"), + r11d: r("R11D"), + r12d: r("R12D"), + r13d: r("R13D"), + r14d: r("R14D"), + r15d: r("R15D"), + r8w: r("R8W"), + r9w: r("R9W"), + r10w: r("R10W"), + r11w: r("R11W"), + r12w: r("R12W"), + r13w: r("R13W"), + r14w: r("R14W"), + r15w: r("R15W"), + fpcw: r("FPUControlWord"), + fptag: r("FPUTagWord"), + mxcsr: r("MXCSR"), + flags: r("flags"), + rflags: r("rflags"), + fip: r("FPUInstructionPointer"), + fdp: r("FPUDataPointer"), + fop: r("FPULastInstructionOpcode"), + /*fds: r("FDS"), + msr: r("MSR"), + fcs: r("FCS"), + fs_base: r("FSBASE"), + gs_base: r("GSBASE"),*/ + } + } + + pub fn get_node(&self, reg: X64Register) -> pcode::VarNode { + match reg { + X64Register::Rax => self.rax, + X64Register::Rbx => self.rbx, + X64Register::Rcx => self.rcx, + X64Register::Rdx => self.rdx, + X64Register::Rsi => self.rsi, + X64Register::Rdi => self.rdi, + X64Register::Rbp => self.rbp, + X64Register::Rsp => self.rsp, + X64Register::R8 => self.r8, + X64Register::R9 => self.r9, + X64Register::R10 => self.r10, + X64Register::R11 => self.r11, + X64Register::R12 => self.r12, + X64Register::R13 => self.r13, + X64Register::R14 => self.r14, + X64Register::R15 => self.r15, + X64Register::Rip => self.rip, + X64Register::Eflags => self.eflags, + X64Register::Cs => self.cs, + X64Register::Ds => self.ds, + X64Register::Es => self.es, + X64Register::Fs => self.fs, + X64Register::Gs => self.gs, + X64Register::Ss => self.ss, + X64Register::Ah => self.ah, + X64Register::Al => self.al, + X64Register::Ax => self.ax, + X64Register::Bh => self.bh, + X64Register::Bl => self.bl, + X64Register::Bpl => self.bpl, + X64Register::Ch => self.ch, + X64Register::Cl => self.cl, + X64Register::Cx => self.cx, + X64Register::Dh => self.dh, + X64Register::Dil => self.dil, + X64Register::Dl => self.dl, + X64Register::Dx => self.dx, + X64Register::Eax => self.eax, + X64Register::Ebp => self.ebp, + X64Register::Ebx => self.ebx, + X64Register::Ecx => self.ecx, + X64Register::Edi => self.edi, + X64Register::Edx => self.edx, + X64Register::Esi => self.esi, + X64Register::Esp => self.esp, + X64Register::Fpsw => self.fpsw, + X64Register::Gdtr => self.gdtr, + X64Register::Idtr => self.idtr, + X64Register::Ldtr => self.ldtr, + X64Register::Tr => self.tr, + X64Register::Cr0 => self.cr0, + X64Register::Cr1 => self.cr1, + X64Register::Cr2 => self.cr2, + X64Register::Cr3 => self.cr3, + X64Register::Cr4 => self.cr4, + X64Register::Cr8 => self.cr8, + X64Register::Dr0 => self.dr0, + X64Register::Dr1 => self.dr1, + X64Register::Dr2 => self.dr2, + X64Register::Dr3 => self.dr3, + X64Register::Dr4 => self.dr4, + X64Register::Dr5 => self.dr5, + X64Register::Dr6 => self.dr6, + X64Register::Dr7 => self.dr7, + X64Register::Fp0 => self.fp0, + X64Register::Fp1 => self.fp1, + X64Register::Fp2 => self.fp2, + X64Register::Fp3 => self.fp3, + X64Register::Fp4 => self.fp4, + X64Register::Fp5 => self.fp5, + X64Register::Fp6 => self.fp6, + X64Register::Fp7 => self.fp7, + /*X64Register::K0 => self.k0, + X64Register::K1 => self.k1, + X64Register::K2 => self.k2, + X64Register::K3 => self.k3, + X64Register::K4 => self.k4, + X64Register::K5 => self.k5, + X64Register::K6 => self.k6, + X64Register::K7 => self.k7,*/ + X64Register::Mm0 => self.mm0, + X64Register::Mm1 => self.mm1, + X64Register::Mm2 => self.mm2, + X64Register::Mm3 => self.mm3, + X64Register::Mm4 => self.mm4, + X64Register::Mm5 => self.mm5, + X64Register::Mm6 => self.mm6, + X64Register::Mm7 => self.mm7, + X64Register::St0 => self.st0, + X64Register::St1 => self.st1, + X64Register::St2 => self.st2, + X64Register::St3 => self.st3, + X64Register::St4 => self.st4, + X64Register::St5 => self.st5, + X64Register::St6 => self.st6, + X64Register::St7 => self.st7, + X64Register::Xmm0 => self.xmm0, + X64Register::Xmm1 => self.xmm1, + X64Register::Xmm2 => self.xmm2, + X64Register::Xmm3 => self.xmm3, + X64Register::Xmm4 => self.xmm4, + X64Register::Xmm5 => self.xmm5, + X64Register::Xmm6 => self.xmm6, + X64Register::Xmm7 => self.xmm7, + X64Register::Xmm8 => self.xmm8, + X64Register::Xmm9 => self.xmm9, + X64Register::Xmm10 => self.xmm10, + X64Register::Xmm11 => self.xmm11, + X64Register::Xmm12 => self.xmm12, + X64Register::Xmm13 => self.xmm13, + X64Register::Xmm14 => self.xmm14, + X64Register::Xmm15 => self.xmm15, + /*X64Register::Xmm16 => self.xmm16, + X64Register::Xmm17 => self.xmm17, + X64Register::Xmm18 => self.xmm18, + X64Register::Xmm19 => self.xmm19, + X64Register::Xmm20 => self.xmm20, + X64Register::Xmm21 => self.xmm21, + X64Register::Xmm22 => self.xmm22, + X64Register::Xmm23 => self.xmm23, + X64Register::Xmm24 => self.xmm24, + X64Register::Xmm25 => self.xmm25, + X64Register::Xmm26 => self.xmm26, + X64Register::Xmm27 => self.xmm27, + X64Register::Xmm28 => self.xmm28, + X64Register::Xmm29 => self.xmm29, + X64Register::Xmm30 => self.xmm30, + X64Register::Xmm31 => self.xmm31,*/ + X64Register::Ymm0 => self.ymm0, + X64Register::Ymm1 => self.ymm1, + X64Register::Ymm2 => self.ymm2, + X64Register::Ymm3 => self.ymm3, + X64Register::Ymm4 => self.ymm4, + X64Register::Ymm5 => self.ymm5, + X64Register::Ymm6 => self.ymm6, + X64Register::Ymm7 => self.ymm7, + X64Register::Ymm8 => self.ymm8, + X64Register::Ymm9 => self.ymm9, + X64Register::Ymm10 => self.ymm10, + X64Register::Ymm11 => self.ymm11, + X64Register::Ymm12 => self.ymm12, + X64Register::Ymm13 => self.ymm13, + X64Register::Ymm14 => self.ymm14, + X64Register::Ymm15 => self.ymm15, + /*X64Register::Ymm16 => self.ymm16, + X64Register::Ymm17 => self.ymm17, + X64Register::Ymm18 => self.ymm18, + X64Register::Ymm19 => self.ymm19, + X64Register::Ymm20 => self.ymm20, + X64Register::Ymm21 => self.ymm21, + X64Register::Ymm22 => self.ymm22, + X64Register::Ymm23 => self.ymm23, + X64Register::Ymm24 => self.ymm24, + X64Register::Ymm25 => self.ymm25, + X64Register::Ymm26 => self.ymm26, + X64Register::Ymm27 => self.ymm27, + X64Register::Ymm28 => self.ymm28, + X64Register::Ymm29 => self.ymm29, + X64Register::Ymm30 => self.ymm30, + X64Register::Ymm31 => self.ymm31,*/ + /*X64Register::Zmm0 => self.zmm0, + X64Register::Zmm1 => self.zmm1, + X64Register::Zmm2 => self.zmm2, + X64Register::Zmm3 => self.zmm3, + X64Register::Zmm4 => self.zmm4, + X64Register::Zmm5 => self.zmm5, + X64Register::Zmm6 => self.zmm6, + X64Register::Zmm7 => self.zmm7, + X64Register::Zmm8 => self.zmm8, + X64Register::Zmm9 => self.zmm9, + X64Register::Zmm10 => self.zmm10, + X64Register::Zmm11 => self.zmm11, + X64Register::Zmm12 => self.zmm12, + X64Register::Zmm13 => self.zmm13, + X64Register::Zmm14 => self.zmm14, + X64Register::Zmm15 => self.zmm15, + X64Register::Zmm16 => self.zmm16, + X64Register::Zmm17 => self.zmm17, + X64Register::Zmm18 => self.zmm18, + X64Register::Zmm19 => self.zmm19, + X64Register::Zmm20 => self.zmm20, + X64Register::Zmm21 => self.zmm21, + X64Register::Zmm22 => self.zmm22, + X64Register::Zmm23 => self.zmm23, + X64Register::Zmm24 => self.zmm24, + X64Register::Zmm25 => self.zmm25, + X64Register::Zmm26 => self.zmm26, + X64Register::Zmm27 => self.zmm27, + X64Register::Zmm28 => self.zmm28, + X64Register::Zmm29 => self.zmm29, + X64Register::Zmm30 => self.zmm30, + X64Register::Zmm31 => self.zmm31,*/ + X64Register::R8b => self.r8b, + X64Register::R9b => self.r9b, + X64Register::R10b => self.r10b, + X64Register::R11b => self.r11b, + X64Register::R12b => self.r12b, + X64Register::R13b => self.r13b, + X64Register::R14b => self.r14b, + X64Register::R15b => self.r15b, + X64Register::R8d => self.r8d, + X64Register::R9d => self.r9d, + X64Register::R10d => self.r10d, + X64Register::R11d => self.r11d, + X64Register::R12d => self.r12d, + X64Register::R13d => self.r13d, + X64Register::R14d => self.r14d, + X64Register::R15d => self.r15d, + X64Register::R8w => self.r8w, + X64Register::R9w => self.r9w, + X64Register::R10w => self.r10w, + X64Register::R11w => self.r11w, + X64Register::R12w => self.r12w, + X64Register::R13w => self.r13w, + X64Register::R14w => self.r14w, + X64Register::R15w => self.r15w, + X64Register::Fpcw => self.fpcw, + X64Register::Fptag => self.fptag, + //X64Register::Msr => self.msr, + X64Register::Mxcsr => self.mxcsr, + //X64Register::FsBase => self.fs_base, + //X64Register::GsBase => self.gs_base, + X64Register::Flags => self.flags, + X64Register::Rflags => self.rflags, + X64Register::Fip => self.fip, + //X64Register::Fcs => self.fcs, + X64Register::Fdp => self.fdp, + //X64Register::Fds => self.fds, + X64Register::Fop => self.fop, + _ => panic!("Unsupported register"), + } + } } diff --git a/src/icicle/src/lib.rs b/src/icicle/src/lib.rs index 0e2ef681..688b209c 100644 --- a/src/icicle/src/lib.rs +++ b/src/icicle/src/lib.rs @@ -1,6 +1,6 @@ mod icicle; -use icicle::IcicleEmulator; +use icicle::{IcicleEmulator, X64Register}; use std::os::raw::c_void; fn to_cbool(value: bool) -> i32 { @@ -48,8 +48,7 @@ pub fn icicle_protect_memory(ptr: *mut c_void, address: u64, length: u64, permis pub fn icicle_write_memory(ptr: *mut c_void, address: u64, data: *const c_void, size: usize) -> i32 { unsafe { let emulator = &mut *(ptr as *mut IcicleEmulator); - let u8_ptr = data as *const u8; - let u8_slice = std::slice::from_raw_parts(u8_ptr, size); + let u8_slice = std::slice::from_raw_parts(data as *const u8, size); let res = emulator.write_memory(address, u8_slice); return to_cbool(res); } @@ -59,13 +58,30 @@ pub fn icicle_write_memory(ptr: *mut c_void, address: u64, data: *const c_void, pub fn icicle_read_memory(ptr: *mut c_void, address: u64, data: *mut c_void, size: usize) -> i32 { unsafe { let emulator = &mut *(ptr as *mut IcicleEmulator); - let u8_ptr = data as *mut u8; - let u8_slice = std::slice::from_raw_parts_mut(u8_ptr, size); + let u8_slice = std::slice::from_raw_parts_mut(data as *mut u8, size); let res = emulator.read_memory(address, u8_slice); return to_cbool(res); } } +#[unsafe(no_mangle)] +pub fn icicle_read_register(ptr: *mut c_void, reg: X64Register, data: *mut c_void, size: usize) -> usize { + unsafe { + let emulator = &mut *(ptr as *mut IcicleEmulator); + let u8_slice = std::slice::from_raw_parts_mut(data as *mut u8, size); + return emulator.read_register(reg, u8_slice); + } +} + +#[unsafe(no_mangle)] +pub fn icicle_write_register(ptr: *mut c_void, reg: X64Register, data: *const c_void, size: usize) -> usize { + unsafe { + let emulator = &mut *(ptr as *mut IcicleEmulator); + let u8_slice = std::slice::from_raw_parts(data as *const u8, size); + return emulator.write_register(reg, u8_slice); + } +} + #[unsafe(no_mangle)] pub fn icicle_destroy_emulator(ptr: *mut c_void) { if ptr.is_null() { From dec66f051ddd13fe2aa9a924f93663211e2d818a Mon Sep 17 00:00:00 2001 From: Maurice Heumann Date: Sat, 29 Mar 2025 06:50:56 +0100 Subject: [PATCH 09/20] Test --- src/icicle-emulator/icicle_x64_emulator.cpp | 32 +++++++++++++-------- src/icicle/src/icicle.rs | 27 +++++++++++++++-- src/windows-emulator/process_context.cpp | 2 +- src/windows-emulator/windows_emulator.cpp | 3 +- 4 files changed, 47 insertions(+), 17 deletions(-) diff --git a/src/icicle-emulator/icicle_x64_emulator.cpp b/src/icicle-emulator/icicle_x64_emulator.cpp index fc396e34..845327ae 100644 --- a/src/icicle-emulator/icicle_x64_emulator.cpp +++ b/src/icicle-emulator/icicle_x64_emulator.cpp @@ -76,7 +76,8 @@ namespace icicle void map_mmio(const uint64_t address, const size_t size, mmio_read_callback read_cb, mmio_write_callback write_cb) override { - throw std::runtime_error("Not implemented"); + return; + // throw std::runtime_error("Not implemented"); } void map_memory(const uint64_t address, const size_t size, memory_permission permissions) override @@ -116,28 +117,33 @@ namespace icicle emulator_hook* hook_instruction(int instruction_type, instruction_hook_callback callback) override { - throw std::runtime_error("Not implemented"); + return nullptr; + // throw std::runtime_error("Not implemented"); } emulator_hook* hook_basic_block(basic_block_hook_callback callback) override { - throw std::runtime_error("Not implemented"); + return nullptr; + // throw std::runtime_error("Not implemented"); } emulator_hook* hook_edge_generation(edge_generation_hook_callback callback) override { - throw std::runtime_error("Not implemented"); + return nullptr; + // throw std::runtime_error("Not implemented"); } emulator_hook* hook_interrupt(interrupt_hook_callback callback) override { - throw std::runtime_error("Not implemented"); + return nullptr; + // throw std::runtime_error("Not implemented"); } emulator_hook* hook_memory_violation(uint64_t address, size_t size, memory_violation_hook_callback callback) override { - throw std::runtime_error("Not implemented"); + return nullptr; + // throw std::runtime_error("Not implemented"); } emulator_hook* hook_memory_access(const uint64_t address, const size_t size, const memory_operation filter, @@ -148,32 +154,34 @@ namespace icicle return nullptr; } - throw std::runtime_error("Not implemented"); + return nullptr; + // throw std::runtime_error("Not implemented"); } void delete_hook(emulator_hook* hook) override { - throw std::runtime_error("Not implemented"); + // throw std::runtime_error("Not implemented"); } void serialize_state(utils::buffer_serializer& buffer, const bool is_snapshot) const override { - throw std::runtime_error("Not implemented"); + // throw std::runtime_error("Not implemented"); } void deserialize_state(utils::buffer_deserializer& buffer, const bool is_snapshot) override { - throw std::runtime_error("Not implemented"); + // throw std::runtime_error("Not implemented"); } std::vector save_registers() override { - throw std::runtime_error("Not implemented"); + // throw std::runtime_error("Not implemented"); + return {}; } void restore_registers(const std::vector& register_data) override { - throw std::runtime_error("Not implemented"); + // throw std::runtime_error("Not implemented"); } bool has_violation() const override diff --git a/src/icicle/src/icicle.rs b/src/icicle/src/icicle.rs index e6be7e36..3cfbceba 100644 --- a/src/icicle/src/icicle.rs +++ b/src/icicle/src/icicle.rs @@ -96,7 +96,7 @@ impl IcicleEmulator { pub fn read_register(&mut self, reg: X64Register, buffer: &mut [u8]) -> usize { let reg_node = self.reg.get_node(reg); - + let res = self.vm.cpu.read_dynamic(pcode::Value::Var(reg_node)); let bytes: [u8; 32] = res.zxt(); @@ -113,7 +113,28 @@ impl IcicleEmulator { let len = std::cmp::min(data.len(), buffer.len()); buffer[..len].copy_from_slice(&data[..len]); - self.vm.cpu.write_var(reg_node, buffer); + //let value = icicle_cpu::regs::DynamicValue::new(buffer, reg_node.size.into()); + //self.vm.cpu.write_trunc(reg_node, value); + + match reg_node.size { + 1 => self.vm.cpu.write_var::<[u8; 1]>(reg_node, buffer[..1].try_into().expect("")), + 2 => self.vm.cpu.write_var::<[u8; 2]>(reg_node, buffer[..2].try_into().expect("")), + 3 => self.vm.cpu.write_var::<[u8; 3]>(reg_node, buffer[..3].try_into().expect("")), + 4 => self.vm.cpu.write_var::<[u8; 4]>(reg_node, buffer[..4].try_into().expect("")), + 5 => self.vm.cpu.write_var::<[u8; 5]>(reg_node, buffer[..5].try_into().expect("")), + 6 => self.vm.cpu.write_var::<[u8; 6]>(reg_node, buffer[..6].try_into().expect("")), + 7 => self.vm.cpu.write_var::<[u8; 7]>(reg_node, buffer[..7].try_into().expect("")), + 8 => self.vm.cpu.write_var::<[u8; 8]>(reg_node, buffer[..8].try_into().expect("")), + 9 => self.vm.cpu.write_var::<[u8; 9]>(reg_node, buffer[..9].try_into().expect("")), + 10 => self.vm.cpu.write_var::<[u8; 10]>(reg_node, buffer[..10].try_into().expect("")), + 11 => self.vm.cpu.write_var::<[u8; 11]>(reg_node, buffer[..11].try_into().expect("")), + 12 => self.vm.cpu.write_var::<[u8; 12]>(reg_node, buffer[..12].try_into().expect("")), + 13 => self.vm.cpu.write_var::<[u8; 13]>(reg_node, buffer[..13].try_into().expect("")), + 14 => self.vm.cpu.write_var::<[u8; 14]>(reg_node, buffer[..14].try_into().expect("")), + 15 => self.vm.cpu.write_var::<[u8; 15]>(reg_node, buffer[..15].try_into().expect("")), + 16 => self.vm.cpu.write_var::<[u8; 16]>(reg_node, buffer[..16].try_into().expect("")), + _ => panic!("invalid dynamic value size"), + } return reg_node.size.into(); } @@ -674,7 +695,7 @@ impl X64RegisterNodes { fp5: r("ST5"), fp6: r("ST6"), fp7: r("ST7"), - /*k0: r("K0"), + /*k0: r("K0"), k1: r("K1"), k2: r("K2"), k3: r("K3"), diff --git a/src/windows-emulator/process_context.cpp b/src/windows-emulator/process_context.cpp index fc9cb06b..4679a93a 100644 --- a/src/windows-emulator/process_context.cpp +++ b/src/windows-emulator/process_context.cpp @@ -33,7 +33,7 @@ void process_context::setup(x64_emulator& emu, memory_manager& memory, const app const mapped_module& executable, const mapped_module& ntdll, const apiset::container& apiset_container) { - setup_gdt(emu, memory); + // setup_gdt(emu, memory); this->kusd.setup(); diff --git a/src/windows-emulator/windows_emulator.cpp b/src/windows-emulator/windows_emulator.cpp index e7f85e1d..dfc7f97d 100644 --- a/src/windows-emulator/windows_emulator.cpp +++ b/src/windows-emulator/windows_emulator.cpp @@ -4,6 +4,7 @@ #include "cpu_context.hpp" #include +#include #include #include @@ -207,7 +208,7 @@ namespace std::unique_ptr create_default_x64_emulator() { - return unicorn::create_x64_emulator(); + return icicle::create_x64_emulator(); } windows_emulator::windows_emulator(application_settings app_settings, const emulator_settings& settings, From af6492be6d58ef25d458ba61cab7d45a2efc720b Mon Sep 17 00:00:00 2001 From: momo5502 Date: Sat, 29 Mar 2025 08:04:56 +0100 Subject: [PATCH 10/20] Unify setting segment base --- src/emulator/x64_emulator.hpp | 7 ++-- src/icicle-emulator/icicle_x64_emulator.cpp | 20 +++++++++++ src/icicle/src/icicle.rs | 22 +++++++++---- src/icicle/src/lib.rs | 33 ++++++++++++++++--- src/unicorn-emulator/unicorn_x64_emulator.cpp | 33 +++++++++++++++++++ src/windows-emulator/emulator_thread.cpp | 15 +-------- src/windows-emulator/process_context.hpp | 2 -- 7 files changed, 102 insertions(+), 30 deletions(-) diff --git a/src/emulator/x64_emulator.hpp b/src/emulator/x64_emulator.hpp index b77882b9..cdb0caaf 100644 --- a/src/emulator/x64_emulator.hpp +++ b/src/emulator/x64_emulator.hpp @@ -11,5 +11,8 @@ enum class x64_hookable_instructions rdtscp, }; -using x64_emulator = - typed_emulator; +struct x64_emulator + : typed_emulator +{ + virtual void set_segment_base(x64_register base, pointer_type value) = 0; +}; diff --git a/src/icicle-emulator/icicle_x64_emulator.cpp b/src/icicle-emulator/icicle_x64_emulator.cpp index 845327ae..062f0965 100644 --- a/src/icicle-emulator/icicle_x64_emulator.cpp +++ b/src/icicle-emulator/icicle_x64_emulator.cpp @@ -13,6 +13,7 @@ extern "C" int32_t icicle_write_memory(icicle_emulator*, uint64_t address, const void* data, size_t length); size_t icicle_read_register(icicle_emulator*, int reg, void* data, size_t length); size_t icicle_write_register(icicle_emulator*, int reg, const void* data, size_t length); + void icicle_start(icicle_emulator*); void icicle_destroy_emulator(icicle_emulator*); } @@ -57,12 +58,31 @@ namespace icicle { timeout = {}; } + + icicle_start(this->emu_); } void stop() override { } + void set_segment_base(const x64_register base, const pointer_type value) override + { + switch (base) + { + case x64_register::fs: + case x64_register::fs_base: + this->reg(x64_register::fs_base, value); + break; + case x64_register::gs: + case x64_register::gs_base: + this->reg(x64_register::gs_base, value); + break; + default: + break; + } + } + size_t write_raw_register(const int reg, const void* value, const size_t size) override { return icicle_write_register(this->emu_, reg, value, size); diff --git a/src/icicle/src/icicle.rs b/src/icicle/src/icicle.rs index 3cfbceba..60e77e82 100644 --- a/src/icicle/src/icicle.rs +++ b/src/icicle/src/icicle.rs @@ -46,6 +46,14 @@ impl IcicleEmulator { return &mut self.vm.cpu.mem; } + pub fn start(&mut self) { + self.vm.run(); + } + + pub fn stop(&mut self) { + //self.vm.stop(); + } + pub fn map_memory(&mut self, address: u64, length: u64, permissions: u8) -> bool { const MAPPING_PERMISSIONS: u8 = icicle_vm::cpu::mem::perm::MAP | icicle_vm::cpu::mem::perm::INIT @@ -608,8 +616,8 @@ struct X64RegisterNodes { fptag: pcode::VarNode, //msr: pcode::VarNode, mxcsr: pcode::VarNode, - //fs_base: pcode::VarNode, - //gs_base: pcode::VarNode, + fs_base: pcode::VarNode, + gs_base: pcode::VarNode, flags: pcode::VarNode, rflags: pcode::VarNode, fip: pcode::VarNode, @@ -849,9 +857,9 @@ impl X64RegisterNodes { fop: r("FPULastInstructionOpcode"), /*fds: r("FDS"), msr: r("MSR"), - fcs: r("FCS"), - fs_base: r("FSBASE"), - gs_base: r("GSBASE"),*/ + fcs: r("FCS"),*/ + fs_base: r("FS_OFFSET"), + gs_base: r("GS_OFFSET"), } } @@ -1077,8 +1085,8 @@ impl X64RegisterNodes { X64Register::Fptag => self.fptag, //X64Register::Msr => self.msr, X64Register::Mxcsr => self.mxcsr, - //X64Register::FsBase => self.fs_base, - //X64Register::GsBase => self.gs_base, + X64Register::FsBase => self.fs_base, + X64Register::GsBase => self.gs_base, X64Register::Flags => self.flags, X64Register::Rflags => self.rflags, X64Register::Fip => self.fip, diff --git a/src/icicle/src/lib.rs b/src/icicle/src/lib.rs index 688b209c..b11b022f 100644 --- a/src/icicle/src/lib.rs +++ b/src/icicle/src/lib.rs @@ -17,6 +17,14 @@ pub fn icicle_create_emulator() -> *mut c_void { return Box::into_raw(emulator) as *mut c_void; } +#[unsafe(no_mangle)] +pub fn icicle_start(ptr: *mut c_void) { + unsafe { + let emulator = &mut *(ptr as *mut IcicleEmulator); + emulator.start(); + } +} + #[unsafe(no_mangle)] pub fn icicle_map_memory(ptr: *mut c_void, address: u64, length: u64, permissions: u8) -> i32 { unsafe { @@ -45,7 +53,12 @@ pub fn icicle_protect_memory(ptr: *mut c_void, address: u64, length: u64, permis } #[unsafe(no_mangle)] -pub fn icicle_write_memory(ptr: *mut c_void, address: u64, data: *const c_void, size: usize) -> i32 { +pub fn icicle_write_memory( + ptr: *mut c_void, + address: u64, + data: *const c_void, + size: usize, +) -> i32 { unsafe { let emulator = &mut *(ptr as *mut IcicleEmulator); let u8_slice = std::slice::from_raw_parts(data as *const u8, size); @@ -65,20 +78,30 @@ pub fn icicle_read_memory(ptr: *mut c_void, address: u64, data: *mut c_void, siz } #[unsafe(no_mangle)] -pub fn icicle_read_register(ptr: *mut c_void, reg: X64Register, data: *mut c_void, size: usize) -> usize { +pub fn icicle_read_register( + ptr: *mut c_void, + reg: X64Register, + data: *mut c_void, + size: usize, +) -> usize { unsafe { let emulator = &mut *(ptr as *mut IcicleEmulator); let u8_slice = std::slice::from_raw_parts_mut(data as *mut u8, size); - return emulator.read_register(reg, u8_slice); + return emulator.read_register(reg, u8_slice); } } #[unsafe(no_mangle)] -pub fn icicle_write_register(ptr: *mut c_void, reg: X64Register, data: *const c_void, size: usize) -> usize { +pub fn icicle_write_register( + ptr: *mut c_void, + reg: X64Register, + data: *const c_void, + size: usize, +) -> usize { unsafe { let emulator = &mut *(ptr as *mut IcicleEmulator); let u8_slice = std::slice::from_raw_parts(data as *const u8, size); - return emulator.write_register(reg, u8_slice); + return emulator.write_register(reg, u8_slice); } } diff --git a/src/unicorn-emulator/unicorn_x64_emulator.cpp b/src/unicorn-emulator/unicorn_x64_emulator.cpp index b6ec8dfa..d301c10f 100644 --- a/src/unicorn-emulator/unicorn_x64_emulator.cpp +++ b/src/unicorn-emulator/unicorn_x64_emulator.cpp @@ -302,6 +302,39 @@ namespace unicorn uce(uc_emu_stop(*this)); } + void set_segment_base(const x64_register base, const pointer_type value) override + { + constexpr auto IA32_FS_BASE_MSR = 0xC0000100; + constexpr auto IA32_GS_BASE_MSR = 0xC0000101; + + struct msr_value + { + uint32_t id; + uint64_t value; + }; + + msr_value msr_val{ + .id = 0, + .value = value, + }; + + switch (base) + { + case x64_register::fs: + case x64_register::fs_base: + msr_val.id = IA32_FS_BASE_MSR; + break; + case x64_register::gs: + case x64_register::gs_base: + msr_val.id = IA32_GS_BASE_MSR; + break; + default: + return; + } + + this->write_register(x64_register::msr, &msr_val, sizeof(msr_val)); + } + size_t write_raw_register(const int reg, const void* value, const size_t size) override { auto result_size = size; diff --git a/src/windows-emulator/emulator_thread.cpp b/src/windows-emulator/emulator_thread.cpp index 1e9f6f58..144bcbcd 100644 --- a/src/windows-emulator/emulator_thread.cpp +++ b/src/windows-emulator/emulator_thread.cpp @@ -28,19 +28,6 @@ namespace emu.reg(x64_register::rsp, stack_end); } - void setup_gs_segment(x64_emulator& emu, const emulator_allocator& allocator) - { - struct msr_value - { - uint32_t id; - uint64_t value; - }; - - const msr_value value{IA32_GS_BASE_MSR, allocator.get_base()}; - - emu.write_register(x64_register::msr, &value, sizeof(value)); - } - bool is_object_signaled(process_context& c, const handle h, const uint32_t current_thread_id) { const auto type = h.value.type; @@ -228,7 +215,7 @@ void emulator_thread::setup_registers(x64_emulator& emu, const process_context& } setup_stack(emu, this->stack_base, this->stack_size); - setup_gs_segment(emu, *this->gs_segment); + emu.set_segment_base(x64_register::gs, this->gs_segment->get_base()); CONTEXT64 ctx{}; ctx.ContextFlags = CONTEXT64_ALL; diff --git a/src/windows-emulator/process_context.hpp b/src/windows-emulator/process_context.hpp index 73f844b2..7fa62bbb 100644 --- a/src/windows-emulator/process_context.hpp +++ b/src/windows-emulator/process_context.hpp @@ -19,8 +19,6 @@ #define PEB_SEGMENT_SIZE (20 << 20) // 20 MB #define GS_SEGMENT_SIZE (1 << 20) // 1 MB -#define IA32_GS_BASE_MSR 0xC0000101 - #define STACK_SIZE 0x40000ULL #define GDT_ADDR 0x30000 From 637ed75b8c775e352cccdc1f1f3d8837e9dd22e3 Mon Sep 17 00:00:00 2001 From: momo5502 Date: Sat, 29 Mar 2025 08:54:53 +0100 Subject: [PATCH 11/20] GDT fixes --- src/emulator/x64_emulator.hpp | 1 + src/icicle-emulator/icicle_x64_emulator.cpp | 15 +++++++++++++++ src/icicle/src/icicle.rs | 1 + src/unicorn-emulator/unicorn_x64_emulator.cpp | 8 ++++++++ src/windows-emulator/process_context.cpp | 6 ++---- 5 files changed, 27 insertions(+), 4 deletions(-) diff --git a/src/emulator/x64_emulator.hpp b/src/emulator/x64_emulator.hpp index cdb0caaf..5eeb1a3c 100644 --- a/src/emulator/x64_emulator.hpp +++ b/src/emulator/x64_emulator.hpp @@ -15,4 +15,5 @@ struct x64_emulator : typed_emulator { virtual void set_segment_base(x64_register base, pointer_type value) = 0; + virtual void load_gdt(pointer_type address, uint32_t limit) = 0; }; diff --git a/src/icicle-emulator/icicle_x64_emulator.cpp b/src/icicle-emulator/icicle_x64_emulator.cpp index 062f0965..ce50ca00 100644 --- a/src/icicle-emulator/icicle_x64_emulator.cpp +++ b/src/icicle-emulator/icicle_x64_emulator.cpp @@ -66,6 +66,21 @@ namespace icicle { } + void load_gdt(const pointer_type address, const uint32_t limit) override + { + struct gdtr + { + uint32_t padding{}; + uint32_t limit{}; + uint64_t address{}; + }; + + const gdtr entry{.limit = limit, .address = address}; + static_assert(sizeof(gdtr) - offsetof(gdtr, limit) == 12); + + this->write_register(x64_register::gdtr, &entry.limit, 12); + } + void set_segment_base(const x64_register base, const pointer_type value) override { switch (base) diff --git a/src/icicle/src/icicle.rs b/src/icicle/src/icicle.rs index 60e77e82..95df2ac9 100644 --- a/src/icicle/src/icicle.rs +++ b/src/icicle/src/icicle.rs @@ -151,6 +151,7 @@ impl IcicleEmulator { // ------------------------------ #[repr(i32)] +#[derive(PartialEq)] pub enum X64Register { Invalid = 0, Ah, diff --git a/src/unicorn-emulator/unicorn_x64_emulator.cpp b/src/unicorn-emulator/unicorn_x64_emulator.cpp index d301c10f..29e750ee 100644 --- a/src/unicorn-emulator/unicorn_x64_emulator.cpp +++ b/src/unicorn-emulator/unicorn_x64_emulator.cpp @@ -1,6 +1,8 @@ #define UNICORN_EMULATOR_IMPL #include "unicorn_x64_emulator.hpp" +#include + #include "unicorn_memory_regions.hpp" #include "unicorn_hook.hpp" @@ -302,6 +304,12 @@ namespace unicorn uce(uc_emu_stop(*this)); } + void load_gdt(const pointer_type address, const uint32_t limit) override + { + const std::array gdtr = {0, address, limit, 0}; + this->write_register(x64_register::gdtr, gdtr.data(), gdtr.size()); + } + void set_segment_base(const x64_register base, const pointer_type value) override { constexpr auto IA32_FS_BASE_MSR = 0xC0000100; diff --git a/src/windows-emulator/process_context.cpp b/src/windows-emulator/process_context.cpp index 4679a93a..e000cf6a 100644 --- a/src/windows-emulator/process_context.cpp +++ b/src/windows-emulator/process_context.cpp @@ -16,10 +16,8 @@ namespace void setup_gdt(x64_emulator& emu, memory_manager& memory) { - // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) - constexpr uint64_t gdtr[4] = {0, GDT_ADDR, GDT_LIMIT, 0}; - emu.write_register(x64_register::gdtr, &gdtr, sizeof(gdtr)); memory.allocate_memory(GDT_ADDR, GDT_LIMIT, memory_permission::read); + emu.load_gdt(GDT_ADDR, GDT_LIMIT); emu.write_memory(GDT_ADDR + 6 * (sizeof(uint64_t)), 0xEFFE000000FFFF); emu.reg(x64_register::cs, 0x33); @@ -33,7 +31,7 @@ void process_context::setup(x64_emulator& emu, memory_manager& memory, const app const mapped_module& executable, const mapped_module& ntdll, const apiset::container& apiset_container) { - // setup_gdt(emu, memory); + setup_gdt(emu, memory); this->kusd.setup(); From 2a74303cdc0824802540335ad392ec63f397e95c Mon Sep 17 00:00:00 2001 From: momo5502 Date: Sat, 29 Mar 2025 10:43:59 +0100 Subject: [PATCH 12/20] Support syscall hooks --- src/icicle-emulator/icicle_x64_emulator.cpp | 35 ++++++++++++++++++--- src/icicle/src/icicle.rs | 34 ++++++++++++++++++-- src/icicle/src/lib.rs | 18 +++++++++++ 3 files changed, 80 insertions(+), 7 deletions(-) diff --git a/src/icicle-emulator/icicle_x64_emulator.cpp b/src/icicle-emulator/icicle_x64_emulator.cpp index ce50ca00..48625de4 100644 --- a/src/icicle-emulator/icicle_x64_emulator.cpp +++ b/src/icicle-emulator/icicle_x64_emulator.cpp @@ -11,6 +11,8 @@ extern "C" int32_t icicle_unmap_memory(icicle_emulator*, uint64_t address, uint64_t length); int32_t icicle_read_memory(icicle_emulator*, uint64_t address, void* data, size_t length); int32_t icicle_write_memory(icicle_emulator*, uint64_t address, const void* data, size_t length); + uint32_t icicle_add_syscall_hook(icicle_emulator*, void (*callback)(void*), void* data); + void icicle_remove_syscall_hook(icicle_emulator*, uint32_t id); size_t icicle_read_register(icicle_emulator*, int reg, void* data, size_t length); size_t icicle_write_register(icicle_emulator*, int reg, const void* data, size_t length); void icicle_start(icicle_emulator*); @@ -111,7 +113,7 @@ namespace icicle void map_mmio(const uint64_t address, const size_t size, mmio_read_callback read_cb, mmio_write_callback write_cb) override { - return; + this->map_memory(address, size, memory_permission::read_write); // throw std::runtime_error("Not implemented"); } @@ -152,8 +154,23 @@ namespace icicle emulator_hook* hook_instruction(int instruction_type, instruction_hook_callback callback) override { - return nullptr; - // throw std::runtime_error("Not implemented"); + if (static_cast(instruction_type) != x64_hookable_instructions::syscall) + { + return nullptr; + } + + auto callback_store = std::make_unique>([c = std::move(callback)] { + (void)c(); // + }); + + const auto invoker = +[](void* cb) { + (*static_cast*>(cb))(); // + }; + + const auto id = icicle_add_syscall_hook(this->emu_, invoker, callback_store.get()); + this->syscall_hooks_[id] = std::move(callback_store); + + return reinterpret_cast(static_cast(id)); } emulator_hook* hook_basic_block(basic_block_hook_callback callback) override @@ -195,7 +212,15 @@ namespace icicle void delete_hook(emulator_hook* hook) override { - // throw std::runtime_error("Not implemented"); + const auto id = static_cast(reinterpret_cast(hook)); + const auto entry = this->syscall_hooks_.find(id); + if (entry == this->syscall_hooks_.end()) + { + return; + } + + icicle_remove_syscall_hook(this->emu_, id); + this->syscall_hooks_.erase(entry); } void serialize_state(utils::buffer_serializer& buffer, const bool is_snapshot) const override @@ -225,6 +250,8 @@ namespace icicle } private: + using syscall_hook_storage = std::unique_ptr>; + std::unordered_map syscall_hooks_{}; icicle_emulator* emu_{}; }; diff --git a/src/icicle/src/icicle.rs b/src/icicle/src/icicle.rs index 95df2ac9..f47c3b94 100644 --- a/src/icicle/src/icicle.rs +++ b/src/icicle/src/icicle.rs @@ -1,4 +1,5 @@ use icicle_cpu::ValueSource; +use std::collections::HashMap; fn create_x64_vm() -> icicle_vm::Vm { let cpu_config = icicle_vm::cpu::Config::from_target_triple("x86_64-none"); @@ -31,6 +32,9 @@ fn map_permissions(foreign_permissions: u8) -> u8 { pub struct IcicleEmulator { vm: icicle_vm::Vm, reg: X64RegisterNodes, + + syscall_hook_id: u32, + syscall_hooks: HashMap>, } impl IcicleEmulator { @@ -39,6 +43,8 @@ impl IcicleEmulator { Self { reg: X64RegisterNodes::new(&vm_i.cpu.arch), vm: vm_i, + syscall_hook_id: 0, + syscall_hooks: HashMap::new(), } } @@ -47,11 +53,33 @@ impl IcicleEmulator { } pub fn start(&mut self) { - self.vm.run(); + loop { + let reason = self.vm.run(); + + let invoke_syscall = match reason { + icicle_vm::VmExit::UnhandledException((code, _)) => code == icicle_cpu::ExceptionCode::Syscall, + _ => false, + }; + + if !invoke_syscall { + break; + } + + for (_key, func) in &self.syscall_hooks { + func(); + } + } } - pub fn stop(&mut self) { - //self.vm.stop(); + pub fn add_syscall_hook(&mut self, callback: Box) -> u32 { + self.syscall_hook_id += 1; + let id = self.syscall_hook_id; + self.syscall_hooks.insert(id, callback); + return id; + } + + pub fn remove_syscall_hook(&mut self, id: u32) { + self.syscall_hooks.remove(&id); } pub fn map_memory(&mut self, address: u64, length: u64, permissions: u8) -> bool { diff --git a/src/icicle/src/lib.rs b/src/icicle/src/lib.rs index b11b022f..426825b8 100644 --- a/src/icicle/src/lib.rs +++ b/src/icicle/src/lib.rs @@ -77,6 +77,24 @@ pub fn icicle_read_memory(ptr: *mut c_void, address: u64, data: *mut c_void, siz } } +type CFunctionPointer = extern "C" fn(*mut c_void); + +#[unsafe(no_mangle)] +pub fn icicle_add_syscall_hook(ptr: *mut c_void, callback: CFunctionPointer, data: *mut c_void) { + unsafe { + let emulator = &mut *(ptr as *mut IcicleEmulator); + emulator.add_syscall_hook(Box::new(move || callback(data))); + } +} + +#[unsafe(no_mangle)] +pub fn icicle_remove_syscall_hook(ptr: *mut c_void, id: u32) { + unsafe { + let emulator = &mut *(ptr as *mut IcicleEmulator); + emulator.remove_syscall_hook(id); + } +} + #[unsafe(no_mangle)] pub fn icicle_read_register( ptr: *mut c_void, From b21569936046cc52e79b3c2de41b075044ff52d9 Mon Sep 17 00:00:00 2001 From: momo5502 Date: Sat, 29 Mar 2025 11:31:30 +0100 Subject: [PATCH 13/20] Fix syscall execution --- src/icicle/src/icicle.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/icicle/src/icicle.rs b/src/icicle/src/icicle.rs index f47c3b94..c7751c27 100644 --- a/src/icicle/src/icicle.rs +++ b/src/icicle/src/icicle.rs @@ -68,6 +68,8 @@ impl IcicleEmulator { for (_key, func) in &self.syscall_hooks { func(); } + + self.vm.cpu.write_pc(self.vm.cpu.read_pc() + 2); } } From 3e6c8ed84c1eefe6160eea72bf7a958e706605c0 Mon Sep 17 00:00:00 2001 From: momo5502 Date: Sat, 29 Mar 2025 11:39:13 +0100 Subject: [PATCH 14/20] Adjust icicle config --- src/icicle/src/icicle.rs | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/icicle/src/icicle.rs b/src/icicle/src/icicle.rs index c7751c27..28065eff 100644 --- a/src/icicle/src/icicle.rs +++ b/src/icicle/src/icicle.rs @@ -2,9 +2,16 @@ use icicle_cpu::ValueSource; use std::collections::HashMap; fn create_x64_vm() -> icicle_vm::Vm { - let cpu_config = icicle_vm::cpu::Config::from_target_triple("x86_64-none"); - let vm = icicle_vm::build(&cpu_config).unwrap(); - return vm; + let mut cpu_config = icicle_vm::cpu::Config::from_target_triple("x86_64-none"); + cpu_config.enable_jit = true; + cpu_config.enable_jit_mem = true; + cpu_config.enable_shadow_stack = false; + cpu_config.enable_recompilation = true; + cpu_config.track_uninitialized = false; + cpu_config.optimize_instructions = true; + cpu_config.optimize_block = false; + + return icicle_vm::build(&cpu_config).unwrap(); } fn map_permissions(foreign_permissions: u8) -> u8 { From 54b5bdc53134814e31b4c41cf7651ba962bf0574 Mon Sep 17 00:00:00 2001 From: momo5502 Date: Tue, 1 Apr 2025 09:27:07 +0200 Subject: [PATCH 15/20] Small fix --- src/icicle-emulator/icicle_x64_emulator.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/icicle-emulator/icicle_x64_emulator.cpp b/src/icicle-emulator/icicle_x64_emulator.cpp index 48625de4..85a276c5 100644 --- a/src/icicle-emulator/icicle_x64_emulator.cpp +++ b/src/icicle-emulator/icicle_x64_emulator.cpp @@ -175,14 +175,14 @@ namespace icicle emulator_hook* hook_basic_block(basic_block_hook_callback callback) override { - return nullptr; - // throw std::runtime_error("Not implemented"); + (void)callback; + throw std::runtime_error("Not implemented"); } emulator_hook* hook_edge_generation(edge_generation_hook_callback callback) override { - return nullptr; - // throw std::runtime_error("Not implemented"); + (void)callback; + throw std::runtime_error("Not implemented"); } emulator_hook* hook_interrupt(interrupt_hook_callback callback) override From 7222c0fc1dec592829c2696abc830c2ffd2253d3 Mon Sep 17 00:00:00 2001 From: Maurice Heumann Date: Tue, 1 Apr 2025 15:40:53 +0200 Subject: [PATCH 16/20] Add icicle mmio support --- src/common/utils/object.hpp | 15 ++ src/icicle-emulator/icicle_x64_emulator.cpp | 70 +++++- src/icicle/src/icicle.rs | 226 +++++++++++++++--- src/icicle/src/lib.rs | 35 ++- src/unicorn-emulator/function_wrapper.hpp | 4 +- src/unicorn-emulator/object.hpp | 12 - src/unicorn-emulator/unicorn_x64_emulator.cpp | 6 +- 7 files changed, 312 insertions(+), 56 deletions(-) create mode 100644 src/common/utils/object.hpp delete mode 100644 src/unicorn-emulator/object.hpp diff --git a/src/common/utils/object.hpp b/src/common/utils/object.hpp new file mode 100644 index 00000000..e0cc9a84 --- /dev/null +++ b/src/common/utils/object.hpp @@ -0,0 +1,15 @@ +#pragma once + +namespace utils +{ + struct object + { + object() = default; + virtual ~object() = default; + + object(object&&) = default; + object(const object&) = default; + object& operator=(object&&) = default; + object& operator=(const object&) = default; + }; +} diff --git a/src/icicle-emulator/icicle_x64_emulator.cpp b/src/icicle-emulator/icicle_x64_emulator.cpp index 85a276c5..e2a8f923 100644 --- a/src/icicle-emulator/icicle_x64_emulator.cpp +++ b/src/icicle-emulator/icicle_x64_emulator.cpp @@ -1,13 +1,20 @@ #define ICICLE_EMULATOR_IMPL #include "icicle_x64_emulator.hpp" +#include + using icicle_emulator = struct icicle_emulator_; extern "C" { + using icicle_mmio_read_func = void(void* user, uint64_t address, size_t length, void* data); + using icicle_mmio_write_func = void(void* user, uint64_t address, size_t length, const void* data); + icicle_emulator* icicle_create_emulator(); int32_t icicle_protect_memory(icicle_emulator*, uint64_t address, uint64_t length, uint8_t permissions); int32_t icicle_map_memory(icicle_emulator*, uint64_t address, uint64_t length, uint8_t permissions); + int32_t icicle_map_mmio(icicle_emulator*, uint64_t address, uint64_t length, icicle_mmio_read_func* read_callback, + void* read_data, icicle_mmio_write_func* write_callback, void* write_data); int32_t icicle_unmap_memory(icicle_emulator*, uint64_t address, uint64_t length); int32_t icicle_read_memory(icicle_emulator*, uint64_t address, void* data, size_t length); int32_t icicle_write_memory(icicle_emulator*, uint64_t address, const void* data, size_t length); @@ -61,6 +68,9 @@ namespace icicle timeout = {}; } + (void)start; + (void)end; + (void)count; icicle_start(this->emu_); } @@ -113,8 +123,47 @@ namespace icicle void map_mmio(const uint64_t address, const size_t size, mmio_read_callback read_cb, mmio_write_callback write_cb) override { - this->map_memory(address, size, memory_permission::read_write); - // throw std::runtime_error("Not implemented"); + struct mmio_wrapper : utils::object + { + uint64_t base{}; + mmio_read_callback read_cb{}; + mmio_write_callback write_cb{}; + }; + + auto wrapper = std::make_unique(); + wrapper->base = address; + wrapper->read_cb = std::move(read_cb); + wrapper->write_cb = std::move(write_cb); + + auto* ptr = wrapper.get(); + this->storage_.push_back(std::move(wrapper)); + + auto* read_wrapper = +[](void* user, const uint64_t address, const size_t length, void* data) { + constexpr auto limit = sizeof(uint64_t); + const auto* w = static_cast(user); + + for (size_t offset = 0; offset < length; offset += limit) + { + const auto max_read = std::min(limit, length - offset); + const auto value = w->read_cb(address + offset - w->base, max_read); + memcpy(static_cast(data) + offset, &value, max_read); + } + }; + + auto* write_wrapper = +[](void* user, const uint64_t address, const size_t length, const void* data) { + constexpr auto limit = sizeof(uint64_t); + const auto* w = static_cast(user); + + for (size_t offset = 0; offset < length; offset += limit) + { + uint64_t value{}; + const auto max_read = std::min(limit, length - offset); + memcpy(&value, static_cast(data) + offset, max_read); + w->write_cb(address + offset - w->base, max_read, value); + } + }; + + icicle_map_mmio(this->emu_, address, size, read_wrapper, ptr, write_wrapper, ptr); } void map_memory(const uint64_t address, const size_t size, memory_permission permissions) override @@ -187,6 +236,7 @@ namespace icicle emulator_hook* hook_interrupt(interrupt_hook_callback callback) override { + (void)callback; return nullptr; // throw std::runtime_error("Not implemented"); } @@ -194,6 +244,9 @@ namespace icicle emulator_hook* hook_memory_violation(uint64_t address, size_t size, memory_violation_hook_callback callback) override { + (void)address; + (void)size; + (void)callback; return nullptr; // throw std::runtime_error("Not implemented"); } @@ -206,6 +259,9 @@ namespace icicle return nullptr; } + (void)address; + (void)size; + (void)callback; return nullptr; // throw std::runtime_error("Not implemented"); } @@ -225,12 +281,16 @@ namespace icicle void serialize_state(utils::buffer_serializer& buffer, const bool is_snapshot) const override { - // throw std::runtime_error("Not implemented"); + (void)buffer; + (void)is_snapshot; + throw std::runtime_error("Not implemented"); } void deserialize_state(utils::buffer_deserializer& buffer, const bool is_snapshot) override { - // throw std::runtime_error("Not implemented"); + (void)buffer; + (void)is_snapshot; + throw std::runtime_error("Not implemented"); } std::vector save_registers() override @@ -241,6 +301,7 @@ namespace icicle void restore_registers(const std::vector& register_data) override { + (void)register_data; // throw std::runtime_error("Not implemented"); } @@ -250,6 +311,7 @@ namespace icicle } private: + std::list> storage_{}; using syscall_hook_storage = std::unique_ptr>; std::unordered_map syscall_hooks_{}; icicle_emulator* emu_{}; diff --git a/src/icicle/src/icicle.rs b/src/icicle/src/icicle.rs index 28065eff..39f6aa1d 100644 --- a/src/icicle/src/icicle.rs +++ b/src/icicle/src/icicle.rs @@ -10,7 +10,7 @@ fn create_x64_vm() -> icicle_vm::Vm { cpu_config.track_uninitialized = false; cpu_config.optimize_instructions = true; cpu_config.optimize_block = false; - + return icicle_vm::build(&cpu_config).unwrap(); } @@ -36,22 +36,107 @@ fn map_permissions(foreign_permissions: u8) -> u8 { return permissions; } +#[repr(u8)] +#[allow(dead_code)] +#[derive(PartialEq)] +enum HookType { + Syscall = 1, + Read, + Write, + Execute, + Unknown, +} + +fn u8_to_hook_type_unsafe(value: u8) -> HookType { + // This is unsafe because it assumes the value is valid + unsafe { std::mem::transmute(value) } +} + +fn split_hook_id(id: u32) -> (u32, HookType) { + let hook_id = id & 0xFFFFFF; + let hook_type = u8_to_hook_type_unsafe((id >> 24) as u8); + + return (hook_id, hook_type); +} + +fn qualify_hook_id(hook_id: u32, hook_type: HookType) -> u32 { + let hook_type: u32 = (hook_type as u8).into(); + let hook_type_mask: u32 = hook_type << 24; + return (hook_id | hook_type_mask).into(); +} + +pub struct HookContainer { + hook_id: u32, + hooks: HashMap>, +} + +impl HookContainer { + pub fn new() -> Self { + Self { + hook_id: 0, + hooks: HashMap::new(), + } + } + + pub fn add_hook(&mut self, callback: Box) -> u32 { + self.hook_id += 1; + let id = self.hook_id; + self.hooks.insert(id, callback); + + return id; + } + + pub fn get_hooks(&self) -> &HashMap> { + return &self.hooks; + } + + pub fn remove_hook(&mut self, id: u32) { + self.hooks.remove(&id); + } +} + pub struct IcicleEmulator { vm: icicle_vm::Vm, reg: X64RegisterNodes, - - syscall_hook_id: u32, - syscall_hooks: HashMap>, + syscall_hooks: HookContainer, +} + +pub struct MmioHandler { + read_handler: Box, + write_handler: Box, +} + +impl MmioHandler { + pub fn new( + read_function: Box, + write_function: Box, + ) -> Self { + Self { + read_handler: read_function, + write_handler: write_function, + } + } +} + +impl icicle_cpu::mem::IoMemory for MmioHandler { + fn read(&mut self, addr: u64, buf: &mut [u8]) -> icicle_cpu::mem::MemResult<()> { + (self.read_handler)(addr, buf); + return Ok(()); + } + + fn write(&mut self, addr: u64, value: &[u8]) -> icicle_cpu::mem::MemResult<()> { + (self.write_handler)(addr, value); + return Ok(()); + } } impl IcicleEmulator { pub fn new() -> Self { - let vm_i = create_x64_vm(); + let virtual_machine = create_x64_vm(); Self { - reg: X64RegisterNodes::new(&vm_i.cpu.arch), - vm: vm_i, - syscall_hook_id: 0, - syscall_hooks: HashMap::new(), + reg: X64RegisterNodes::new(&virtual_machine.cpu.arch), + vm: virtual_machine, + syscall_hooks: HookContainer::new(), } } @@ -64,7 +149,9 @@ impl IcicleEmulator { let reason = self.vm.run(); let invoke_syscall = match reason { - icicle_vm::VmExit::UnhandledException((code, _)) => code == icicle_cpu::ExceptionCode::Syscall, + icicle_vm::VmExit::UnhandledException((code, _)) => { + code == icicle_cpu::ExceptionCode::Syscall + } _ => false, }; @@ -72,7 +159,7 @@ impl IcicleEmulator { break; } - for (_key, func) in &self.syscall_hooks { + for (_key, func) in self.syscall_hooks.get_hooks() { func(); } @@ -81,14 +168,17 @@ impl IcicleEmulator { } pub fn add_syscall_hook(&mut self, callback: Box) -> u32 { - self.syscall_hook_id += 1; - let id = self.syscall_hook_id; - self.syscall_hooks.insert(id, callback); - return id; + let hook_id = self.syscall_hooks.add_hook(callback); + return qualify_hook_id(hook_id, HookType::Syscall); } - pub fn remove_syscall_hook(&mut self, id: u32) { - self.syscall_hooks.remove(&id); + pub fn remove_hook(&mut self, id: u32) { + let (hook_id, hook_type) = split_hook_id(id); + + match hook_type { + HookType::Syscall => self.syscall_hooks.remove_hook(hook_id), + _ => {} + } } pub fn map_memory(&mut self, address: u64, length: u64, permissions: u8) -> bool { @@ -113,6 +203,28 @@ impl IcicleEmulator { return res.is_ok(); } + pub fn map_mmio( + &mut self, + address: u64, + length: u64, + read_function: Box, + write_function: Box, + ) -> bool { + let mem = self.get_mem(); + + let handler = MmioHandler::new(read_function, write_function); + let handler_id = mem.register_io_handler(handler); + + let layout = icicle_vm::cpu::mem::AllocLayout { + addr: Some(address), + size: length, + align: 0x1000, + }; + + let res = mem.alloc_memory(layout, handler_id); + return res.is_ok(); + } + pub fn unmap_memory(&mut self, address: u64, length: u64) -> bool { return self.get_mem().unmap_memory_len(address, length); } @@ -162,22 +274,70 @@ impl IcicleEmulator { //self.vm.cpu.write_trunc(reg_node, value); match reg_node.size { - 1 => self.vm.cpu.write_var::<[u8; 1]>(reg_node, buffer[..1].try_into().expect("")), - 2 => self.vm.cpu.write_var::<[u8; 2]>(reg_node, buffer[..2].try_into().expect("")), - 3 => self.vm.cpu.write_var::<[u8; 3]>(reg_node, buffer[..3].try_into().expect("")), - 4 => self.vm.cpu.write_var::<[u8; 4]>(reg_node, buffer[..4].try_into().expect("")), - 5 => self.vm.cpu.write_var::<[u8; 5]>(reg_node, buffer[..5].try_into().expect("")), - 6 => self.vm.cpu.write_var::<[u8; 6]>(reg_node, buffer[..6].try_into().expect("")), - 7 => self.vm.cpu.write_var::<[u8; 7]>(reg_node, buffer[..7].try_into().expect("")), - 8 => self.vm.cpu.write_var::<[u8; 8]>(reg_node, buffer[..8].try_into().expect("")), - 9 => self.vm.cpu.write_var::<[u8; 9]>(reg_node, buffer[..9].try_into().expect("")), - 10 => self.vm.cpu.write_var::<[u8; 10]>(reg_node, buffer[..10].try_into().expect("")), - 11 => self.vm.cpu.write_var::<[u8; 11]>(reg_node, buffer[..11].try_into().expect("")), - 12 => self.vm.cpu.write_var::<[u8; 12]>(reg_node, buffer[..12].try_into().expect("")), - 13 => self.vm.cpu.write_var::<[u8; 13]>(reg_node, buffer[..13].try_into().expect("")), - 14 => self.vm.cpu.write_var::<[u8; 14]>(reg_node, buffer[..14].try_into().expect("")), - 15 => self.vm.cpu.write_var::<[u8; 15]>(reg_node, buffer[..15].try_into().expect("")), - 16 => self.vm.cpu.write_var::<[u8; 16]>(reg_node, buffer[..16].try_into().expect("")), + 1 => self + .vm + .cpu + .write_var::<[u8; 1]>(reg_node, buffer[..1].try_into().expect("")), + 2 => self + .vm + .cpu + .write_var::<[u8; 2]>(reg_node, buffer[..2].try_into().expect("")), + 3 => self + .vm + .cpu + .write_var::<[u8; 3]>(reg_node, buffer[..3].try_into().expect("")), + 4 => self + .vm + .cpu + .write_var::<[u8; 4]>(reg_node, buffer[..4].try_into().expect("")), + 5 => self + .vm + .cpu + .write_var::<[u8; 5]>(reg_node, buffer[..5].try_into().expect("")), + 6 => self + .vm + .cpu + .write_var::<[u8; 6]>(reg_node, buffer[..6].try_into().expect("")), + 7 => self + .vm + .cpu + .write_var::<[u8; 7]>(reg_node, buffer[..7].try_into().expect("")), + 8 => self + .vm + .cpu + .write_var::<[u8; 8]>(reg_node, buffer[..8].try_into().expect("")), + 9 => self + .vm + .cpu + .write_var::<[u8; 9]>(reg_node, buffer[..9].try_into().expect("")), + 10 => self + .vm + .cpu + .write_var::<[u8; 10]>(reg_node, buffer[..10].try_into().expect("")), + 11 => self + .vm + .cpu + .write_var::<[u8; 11]>(reg_node, buffer[..11].try_into().expect("")), + 12 => self + .vm + .cpu + .write_var::<[u8; 12]>(reg_node, buffer[..12].try_into().expect("")), + 13 => self + .vm + .cpu + .write_var::<[u8; 13]>(reg_node, buffer[..13].try_into().expect("")), + 14 => self + .vm + .cpu + .write_var::<[u8; 14]>(reg_node, buffer[..14].try_into().expect("")), + 15 => self + .vm + .cpu + .write_var::<[u8; 15]>(reg_node, buffer[..15].try_into().expect("")), + 16 => self + .vm + .cpu + .write_var::<[u8; 16]>(reg_node, buffer[..16].try_into().expect("")), _ => panic!("invalid dynamic value size"), } diff --git a/src/icicle/src/lib.rs b/src/icicle/src/lib.rs index 426825b8..adbeee0c 100644 --- a/src/icicle/src/lib.rs +++ b/src/icicle/src/lib.rs @@ -25,6 +25,37 @@ pub fn icicle_start(ptr: *mut c_void) { } } +type MmioReadFunction = extern "C" fn(*mut c_void, u64, usize, *mut c_void); +type MmioWriteFunction = extern "C" fn(*mut c_void, u64, usize, *const c_void); + +#[unsafe(no_mangle)] +pub fn icicle_map_mmio( + ptr: *mut c_void, + address: u64, + length: u64, + read_cb: MmioReadFunction, + read_data: *mut c_void, + write_cb: MmioWriteFunction, + write_data: *mut c_void, +) -> i32 { + unsafe { + let emulator = &mut *(ptr as *mut IcicleEmulator); + + let read_wrapper = Box::new(move |addr: u64, data: &mut [u8]| { + let raw_pointer: *mut u8 = data.as_mut_ptr(); + read_cb(read_data, addr, data.len(), raw_pointer as *mut c_void); + }); + + let write_wrapper = Box::new(move |addr: u64, data: &[u8]| { + let raw_pointer: *const u8 = data.as_ptr(); + write_cb(write_data, addr, data.len(), raw_pointer as *const c_void); + }); + + let res = emulator.map_mmio(address, length, read_wrapper, write_wrapper); + return to_cbool(res); + } +} + #[unsafe(no_mangle)] pub fn icicle_map_memory(ptr: *mut c_void, address: u64, length: u64, permissions: u8) -> i32 { unsafe { @@ -83,7 +114,7 @@ type CFunctionPointer = extern "C" fn(*mut c_void); pub fn icicle_add_syscall_hook(ptr: *mut c_void, callback: CFunctionPointer, data: *mut c_void) { unsafe { let emulator = &mut *(ptr as *mut IcicleEmulator); - emulator.add_syscall_hook(Box::new(move || callback(data))); + emulator.add_syscall_hook(Box::new(move || callback(data))); } } @@ -91,7 +122,7 @@ pub fn icicle_add_syscall_hook(ptr: *mut c_void, callback: CFunctionPointer, dat pub fn icicle_remove_syscall_hook(ptr: *mut c_void, id: u32) { unsafe { let emulator = &mut *(ptr as *mut IcicleEmulator); - emulator.remove_syscall_hook(id); + emulator.remove_hook(id); } } diff --git a/src/unicorn-emulator/function_wrapper.hpp b/src/unicorn-emulator/function_wrapper.hpp index f908dac5..a1484c9d 100644 --- a/src/unicorn-emulator/function_wrapper.hpp +++ b/src/unicorn-emulator/function_wrapper.hpp @@ -3,10 +3,10 @@ #include #include -#include "object.hpp" +#include template -class function_wrapper : public object +class function_wrapper : public utils::object { public: using user_data_pointer = void*; diff --git a/src/unicorn-emulator/object.hpp b/src/unicorn-emulator/object.hpp deleted file mode 100644 index 8639c6b3..00000000 --- a/src/unicorn-emulator/object.hpp +++ /dev/null @@ -1,12 +0,0 @@ -#pragma once - -struct object -{ - object() = default; - virtual ~object() = default; - - object(object&&) = default; - object(const object&) = default; - object& operator=(object&&) = default; - object& operator=(const object&) = default; -}; diff --git a/src/unicorn-emulator/unicorn_x64_emulator.cpp b/src/unicorn-emulator/unicorn_x64_emulator.cpp index 29e750ee..d286bd2e 100644 --- a/src/unicorn-emulator/unicorn_x64_emulator.cpp +++ b/src/unicorn-emulator/unicorn_x64_emulator.cpp @@ -75,7 +75,7 @@ namespace unicorn } } - struct hook_object : object + struct hook_object : utils::object { emulator_hook* as_opaque_hook() { @@ -87,7 +87,7 @@ namespace unicorn { public: template - requires(std::is_base_of_v && std::is_move_constructible_v) + requires(std::is_base_of_v && std::is_move_constructible_v) void add(T data, unicorn_hook hook) { hook_entry entry{}; @@ -101,7 +101,7 @@ namespace unicorn private: struct hook_entry { - std::unique_ptr data{}; + std::unique_ptr data{}; unicorn_hook hook{}; }; From fd018c46b4e20ed21d4720d1d4df7276f20391c5 Mon Sep 17 00:00:00 2001 From: momo5502 Date: Tue, 1 Apr 2025 18:23:24 +0200 Subject: [PATCH 17/20] Support saving and restoring registers --- src/icicle-emulator/icicle_x64_emulator.cpp | 19 ++++++++++++---- src/icicle/src/icicle.rs | 20 +++++++++++++++++ src/icicle/src/lib.rs | 24 ++++++++++++++++++--- 3 files changed, 56 insertions(+), 7 deletions(-) diff --git a/src/icicle-emulator/icicle_x64_emulator.cpp b/src/icicle-emulator/icicle_x64_emulator.cpp index e2a8f923..53b45139 100644 --- a/src/icicle-emulator/icicle_x64_emulator.cpp +++ b/src/icicle-emulator/icicle_x64_emulator.cpp @@ -10,6 +10,8 @@ extern "C" using icicle_mmio_read_func = void(void* user, uint64_t address, size_t length, void* data); using icicle_mmio_write_func = void(void* user, uint64_t address, size_t length, const void* data); + using data_accessor_func = void(void* user, const void* data, size_t length); + icicle_emulator* icicle_create_emulator(); int32_t icicle_protect_memory(icicle_emulator*, uint64_t address, uint64_t length, uint8_t permissions); int32_t icicle_map_memory(icicle_emulator*, uint64_t address, uint64_t length, uint8_t permissions); @@ -18,6 +20,8 @@ extern "C" int32_t icicle_unmap_memory(icicle_emulator*, uint64_t address, uint64_t length); int32_t icicle_read_memory(icicle_emulator*, uint64_t address, void* data, size_t length); int32_t icicle_write_memory(icicle_emulator*, uint64_t address, const void* data, size_t length); + int32_t icicle_save_registers(icicle_emulator*, data_accessor_func* accessor, void* accessor_data); + int32_t icicle_restore_registers(icicle_emulator*, const void* data, size_t length); uint32_t icicle_add_syscall_hook(icicle_emulator*, void (*callback)(void*), void* data); void icicle_remove_syscall_hook(icicle_emulator*, uint32_t id); size_t icicle_read_register(icicle_emulator*, int reg, void* data, size_t length); @@ -295,14 +299,21 @@ namespace icicle std::vector save_registers() override { - // throw std::runtime_error("Not implemented"); - return {}; + std::vector data{}; + auto* accessor = +[](void* user, const void* data, const size_t length) { + auto& vec = *static_cast*>(user); + vec.resize(length); + memcpy(vec.data(), data, length); + }; + + icicle_save_registers(this->emu_, accessor, &data); + + return data; } void restore_registers(const std::vector& register_data) override { - (void)register_data; - // throw std::runtime_error("Not implemented"); + icicle_restore_registers(this->emu_, register_data.data(), register_data.size()); } bool has_violation() const override diff --git a/src/icicle/src/icicle.rs b/src/icicle/src/icicle.rs index 39f6aa1d..f8ebc1a4 100644 --- a/src/icicle/src/icicle.rs +++ b/src/icicle/src/icicle.rs @@ -251,6 +251,26 @@ impl IcicleEmulator { return res.is_ok(); } + pub fn save_registers(&self) -> Vec { + const REG_SIZE: usize = std::mem::size_of::(); + unsafe { + let data: [u8; REG_SIZE] = self.vm.cpu.regs.read_at(0); + return data.to_vec(); + } + } + + pub fn restore_registers(&mut self, data: &[u8]) { + const REG_SIZE: usize = std::mem::size_of::(); + + let mut buffer: [u8; REG_SIZE] = [0; REG_SIZE]; + let size = std::cmp::min(REG_SIZE, data.len()); + buffer.copy_from_slice(&data[..size]); + + unsafe { + self.vm.cpu.regs.write_at(0, buffer); + }; + } + pub fn read_register(&mut self, reg: X64Register, buffer: &mut [u8]) -> usize { let reg_node = self.reg.get_node(reg); diff --git a/src/icicle/src/lib.rs b/src/icicle/src/lib.rs index adbeee0c..22c40e16 100644 --- a/src/icicle/src/lib.rs +++ b/src/icicle/src/lib.rs @@ -25,6 +25,8 @@ pub fn icicle_start(ptr: *mut c_void) { } } +type RawFunction = extern "C" fn(*mut c_void); +type DataFunction = extern "C" fn(*mut c_void, *const c_void, usize); type MmioReadFunction = extern "C" fn(*mut c_void, u64, usize, *mut c_void); type MmioWriteFunction = extern "C" fn(*mut c_void, u64, usize, *const c_void); @@ -98,6 +100,24 @@ pub fn icicle_write_memory( } } +#[unsafe(no_mangle)] +pub fn icicle_save_registers(ptr: *mut c_void, accessor: DataFunction, accessor_data: *mut c_void) { + unsafe { + let emulator = &mut *(ptr as *mut IcicleEmulator); + let registers = emulator.save_registers(); + accessor(accessor_data, registers.as_ptr() as *const c_void, registers.len()); + } +} + +#[unsafe(no_mangle)] +pub fn icicle_restore_registers(ptr: *mut c_void, data: *const c_void, size: usize) { + unsafe { + let emulator = &mut *(ptr as *mut IcicleEmulator); + let u8_slice = std::slice::from_raw_parts(data as *const u8, size); + emulator.restore_registers(u8_slice); + } +} + #[unsafe(no_mangle)] pub fn icicle_read_memory(ptr: *mut c_void, address: u64, data: *mut c_void, size: usize) -> i32 { unsafe { @@ -108,10 +128,8 @@ pub fn icicle_read_memory(ptr: *mut c_void, address: u64, data: *mut c_void, siz } } -type CFunctionPointer = extern "C" fn(*mut c_void); - #[unsafe(no_mangle)] -pub fn icicle_add_syscall_hook(ptr: *mut c_void, callback: CFunctionPointer, data: *mut c_void) { +pub fn icicle_add_syscall_hook(ptr: *mut c_void, callback: RawFunction, data: *mut c_void) { unsafe { let emulator = &mut *(ptr as *mut IcicleEmulator); emulator.add_syscall_hook(Box::new(move || callback(data))); From afd9344e9743c710b90b9656efee7a1cf8e5f9e1 Mon Sep 17 00:00:00 2001 From: momo5502 Date: Tue, 1 Apr 2025 18:34:29 +0200 Subject: [PATCH 18/20] Extract registers --- src/icicle/src/icicle.rs | 963 +----------------------------------- src/icicle/src/lib.rs | 4 +- src/icicle/src/registers.rs | 949 +++++++++++++++++++++++++++++++++++ 3 files changed, 958 insertions(+), 958 deletions(-) create mode 100644 src/icicle/src/registers.rs diff --git a/src/icicle/src/icicle.rs b/src/icicle/src/icicle.rs index f8ebc1a4..85ec2f64 100644 --- a/src/icicle/src/icicle.rs +++ b/src/icicle/src/icicle.rs @@ -1,6 +1,8 @@ use icicle_cpu::ValueSource; use std::collections::HashMap; +use crate::registers; + fn create_x64_vm() -> icicle_vm::Vm { let mut cpu_config = icicle_vm::cpu::Config::from_target_triple("x86_64-none"); cpu_config.enable_jit = true; @@ -48,7 +50,6 @@ enum HookType { } fn u8_to_hook_type_unsafe(value: u8) -> HookType { - // This is unsafe because it assumes the value is valid unsafe { std::mem::transmute(value) } } @@ -97,7 +98,7 @@ impl HookContainer { pub struct IcicleEmulator { vm: icicle_vm::Vm, - reg: X64RegisterNodes, + reg: registers::X64RegisterNodes, syscall_hooks: HookContainer, } @@ -134,7 +135,7 @@ impl IcicleEmulator { pub fn new() -> Self { let virtual_machine = create_x64_vm(); Self { - reg: X64RegisterNodes::new(&virtual_machine.cpu.arch), + reg: registers::X64RegisterNodes::new(&virtual_machine.cpu.arch), vm: virtual_machine, syscall_hooks: HookContainer::new(), } @@ -271,7 +272,7 @@ impl IcicleEmulator { }; } - pub fn read_register(&mut self, reg: X64Register, buffer: &mut [u8]) -> usize { + pub fn read_register(&mut self, reg: registers::X64Register, buffer: &mut [u8]) -> usize { let reg_node = self.reg.get_node(reg); let res = self.vm.cpu.read_dynamic(pcode::Value::Var(reg_node)); @@ -283,7 +284,7 @@ impl IcicleEmulator { return reg_node.size.into(); } - pub fn write_register(&mut self, reg: X64Register, data: &[u8]) -> usize { + pub fn write_register(&mut self, reg: registers::X64Register, data: &[u8]) -> usize { let reg_node = self.reg.get_node(reg); let mut buffer = [0u8; 32]; @@ -364,955 +365,3 @@ impl IcicleEmulator { return reg_node.size.into(); } } - -// ------------------------------ - -#[repr(i32)] -#[derive(PartialEq)] -pub enum X64Register { - Invalid = 0, - Ah, - Al, - Ax, - Bh, - Bl, - Bp, - Bpl, - Bx, - Ch, - Cl, - Cs, - Cx, - Dh, - Di, - Dil, - Dl, - Ds, - Dx, - Eax, - Ebp, - Ebx, - Ecx, - Edi, - Edx, - Eflags, - Eip, - Es = 26 + 2, - Esi, - Esp, - Fpsw, - Fs, - Gs, - Ip, - Rax, - Rbp, - Rbx, - Rcx, - Rdi, - Rdx, - Rip, - Rsi = 41 + 2, - Rsp, - Si, - Sil, - Sp, - Spl, - Ss, - Cr0, - Cr1, - Cr2, - Cr3, - Cr4, - Cr8 = 54 + 4, - Dr0 = 58 + 8, - Dr1, - Dr2, - Dr3, - Dr4, - Dr5, - Dr6, - Dr7, - Fp0 = 73 + 9, - Fp1, - Fp2, - Fp3, - Fp4, - Fp5, - Fp6, - Fp7, - K0, - K1, - K2, - K3, - K4, - K5, - K6, - K7, - Mm0, - Mm1, - Mm2, - Mm3, - Mm4, - Mm5, - Mm6, - Mm7, - R8, - R9, - R10, - R11, - R12, - R13, - R14, - R15, - St0, - St1, - St2, - St3, - St4, - St5, - St6, - St7, - Xmm0, - Xmm1, - Xmm2, - Xmm3, - Xmm4, - Xmm5, - Xmm6, - Xmm7, - Xmm8, - Xmm9, - Xmm10, - Xmm11, - Xmm12, - Xmm13, - Xmm14, - Xmm15, - Xmm16, - Xmm17, - Xmm18, - Xmm19, - Xmm20, - Xmm21, - Xmm22, - Xmm23, - Xmm24, - Xmm25, - Xmm26, - Xmm27, - Xmm28, - Xmm29, - Xmm30, - Xmm31, - Ymm0, - Ymm1, - Ymm2, - Ymm3, - Ymm4, - Ymm5, - Ymm6, - Ymm7, - Ymm8, - Ymm9, - Ymm10, - Ymm11, - Ymm12, - Ymm13, - Ymm14, - Ymm15, - Ymm16, - Ymm17, - Ymm18, - Ymm19, - Ymm20, - Ymm21, - Ymm22, - Ymm23, - Ymm24, - Ymm25, - Ymm26, - Ymm27, - Ymm28, - Ymm29, - Ymm30, - Ymm31, - Zmm0, - Zmm1, - Zmm2, - Zmm3, - Zmm4, - Zmm5, - Zmm6, - Zmm7, - Zmm8, - Zmm9, - Zmm10, - Zmm11, - Zmm12, - Zmm13, - Zmm14, - Zmm15, - Zmm16, - Zmm17, - Zmm18, - Zmm19, - Zmm20, - Zmm21, - Zmm22, - Zmm23, - Zmm24, - Zmm25, - Zmm26, - Zmm27, - Zmm28, - Zmm29, - Zmm30, - Zmm31, - R8b, - R9b, - R10b, - R11b, - R12b, - R13b, - R14b, - R15b, - R8d, - R9d, - R10d, - R11d, - R12d, - R13d, - R14d, - R15d, - R8w, - R9w, - R10w, - R11w, - R12w, - R13w, - R14w, - R15w, - Idtr, - Gdtr, - Ldtr, - Tr, - Fpcw, - Fptag, - Msr, - Mxcsr, - FsBase, - GsBase, - Flags, - Rflags, - Fip, - Fcs, - Fdp, - Fds, - Fop, - End, // Must be last -} - -#[derive(Clone)] -struct X64RegisterNodes { - rax: pcode::VarNode, - rbx: pcode::VarNode, - rcx: pcode::VarNode, - rdx: pcode::VarNode, - rsi: pcode::VarNode, - rdi: pcode::VarNode, - rbp: pcode::VarNode, - rsp: pcode::VarNode, - r8: pcode::VarNode, - r9: pcode::VarNode, - r10: pcode::VarNode, - r11: pcode::VarNode, - r12: pcode::VarNode, - r13: pcode::VarNode, - r14: pcode::VarNode, - r15: pcode::VarNode, - rip: pcode::VarNode, - eflags: pcode::VarNode, - cs: pcode::VarNode, - ds: pcode::VarNode, - es: pcode::VarNode, - fs: pcode::VarNode, - gs: pcode::VarNode, - ss: pcode::VarNode, - ah: pcode::VarNode, - al: pcode::VarNode, - ax: pcode::VarNode, - bh: pcode::VarNode, - bl: pcode::VarNode, - bpl: pcode::VarNode, - ch: pcode::VarNode, - cl: pcode::VarNode, - cx: pcode::VarNode, - dh: pcode::VarNode, - dil: pcode::VarNode, - dl: pcode::VarNode, - dx: pcode::VarNode, - eax: pcode::VarNode, - ebp: pcode::VarNode, - ebx: pcode::VarNode, - ecx: pcode::VarNode, - edi: pcode::VarNode, - edx: pcode::VarNode, - esi: pcode::VarNode, - esp: pcode::VarNode, - fpsw: pcode::VarNode, - gdtr: pcode::VarNode, - idtr: pcode::VarNode, - ldtr: pcode::VarNode, - tr: pcode::VarNode, - cr0: pcode::VarNode, - cr1: pcode::VarNode, - cr2: pcode::VarNode, - cr3: pcode::VarNode, - cr4: pcode::VarNode, - cr8: pcode::VarNode, - dr0: pcode::VarNode, - dr1: pcode::VarNode, - dr2: pcode::VarNode, - dr3: pcode::VarNode, - dr4: pcode::VarNode, - dr5: pcode::VarNode, - dr6: pcode::VarNode, - dr7: pcode::VarNode, - fp0: pcode::VarNode, - fp1: pcode::VarNode, - fp2: pcode::VarNode, - fp3: pcode::VarNode, - fp4: pcode::VarNode, - fp5: pcode::VarNode, - fp6: pcode::VarNode, - fp7: pcode::VarNode, - /*k0: pcode::VarNode, - k1: pcode::VarNode, - k2: pcode::VarNode, - k3: pcode::VarNode, - k4: pcode::VarNode, - k5: pcode::VarNode, - k6: pcode::VarNode, - k7: pcode::VarNode,*/ - mm0: pcode::VarNode, - mm1: pcode::VarNode, - mm2: pcode::VarNode, - mm3: pcode::VarNode, - mm4: pcode::VarNode, - mm5: pcode::VarNode, - mm6: pcode::VarNode, - mm7: pcode::VarNode, - st0: pcode::VarNode, - st1: pcode::VarNode, - st2: pcode::VarNode, - st3: pcode::VarNode, - st4: pcode::VarNode, - st5: pcode::VarNode, - st6: pcode::VarNode, - st7: pcode::VarNode, - xmm0: pcode::VarNode, - xmm1: pcode::VarNode, - xmm2: pcode::VarNode, - xmm3: pcode::VarNode, - xmm4: pcode::VarNode, - xmm5: pcode::VarNode, - xmm6: pcode::VarNode, - xmm7: pcode::VarNode, - xmm8: pcode::VarNode, - xmm9: pcode::VarNode, - xmm10: pcode::VarNode, - xmm11: pcode::VarNode, - xmm12: pcode::VarNode, - xmm13: pcode::VarNode, - xmm14: pcode::VarNode, - xmm15: pcode::VarNode, - /*xmm16: pcode::VarNode, - xmm17: pcode::VarNode, - xmm18: pcode::VarNode, - xmm19: pcode::VarNode, - xmm20: pcode::VarNode, - xmm21: pcode::VarNode, - xmm22: pcode::VarNode, - xmm23: pcode::VarNode, - xmm24: pcode::VarNode, - xmm25: pcode::VarNode, - xmm26: pcode::VarNode, - xmm27: pcode::VarNode, - xmm28: pcode::VarNode, - xmm29: pcode::VarNode, - xmm30: pcode::VarNode, - xmm31: pcode::VarNode,*/ - ymm0: pcode::VarNode, - ymm1: pcode::VarNode, - ymm2: pcode::VarNode, - ymm3: pcode::VarNode, - ymm4: pcode::VarNode, - ymm5: pcode::VarNode, - ymm6: pcode::VarNode, - ymm7: pcode::VarNode, - ymm8: pcode::VarNode, - ymm9: pcode::VarNode, - ymm10: pcode::VarNode, - ymm11: pcode::VarNode, - ymm12: pcode::VarNode, - ymm13: pcode::VarNode, - ymm14: pcode::VarNode, - ymm15: pcode::VarNode, - /*ymm16: pcode::VarNode, - ymm17: pcode::VarNode, - ymm18: pcode::VarNode, - ymm19: pcode::VarNode, - ymm20: pcode::VarNode, - ymm21: pcode::VarNode, - ymm22: pcode::VarNode, - ymm23: pcode::VarNode, - ymm24: pcode::VarNode, - ymm25: pcode::VarNode, - ymm26: pcode::VarNode, - ymm27: pcode::VarNode, - ymm28: pcode::VarNode, - ymm29: pcode::VarNode, - ymm30: pcode::VarNode, - ymm31: pcode::VarNode,*/ - /*zmm0: pcode::VarNode, - zmm1: pcode::VarNode, - zmm2: pcode::VarNode, - zmm3: pcode::VarNode, - zmm4: pcode::VarNode, - zmm5: pcode::VarNode, - zmm6: pcode::VarNode, - zmm7: pcode::VarNode, - zmm8: pcode::VarNode, - zmm9: pcode::VarNode, - zmm10: pcode::VarNode, - zmm11: pcode::VarNode, - zmm12: pcode::VarNode, - zmm13: pcode::VarNode, - zmm14: pcode::VarNode, - zmm15: pcode::VarNode, - zmm16: pcode::VarNode, - zmm17: pcode::VarNode, - zmm18: pcode::VarNode, - zmm19: pcode::VarNode, - zmm20: pcode::VarNode, - zmm21: pcode::VarNode, - zmm22: pcode::VarNode, - zmm23: pcode::VarNode, - zmm24: pcode::VarNode, - zmm25: pcode::VarNode, - zmm26: pcode::VarNode, - zmm27: pcode::VarNode, - zmm28: pcode::VarNode, - zmm29: pcode::VarNode, - zmm30: pcode::VarNode, - zmm31: pcode::VarNode,*/ - r8b: pcode::VarNode, - r9b: pcode::VarNode, - r10b: pcode::VarNode, - r11b: pcode::VarNode, - r12b: pcode::VarNode, - r13b: pcode::VarNode, - r14b: pcode::VarNode, - r15b: pcode::VarNode, - r8d: pcode::VarNode, - r9d: pcode::VarNode, - r10d: pcode::VarNode, - r11d: pcode::VarNode, - r12d: pcode::VarNode, - r13d: pcode::VarNode, - r14d: pcode::VarNode, - r15d: pcode::VarNode, - r8w: pcode::VarNode, - r9w: pcode::VarNode, - r10w: pcode::VarNode, - r11w: pcode::VarNode, - r12w: pcode::VarNode, - r13w: pcode::VarNode, - r14w: pcode::VarNode, - r15w: pcode::VarNode, - fpcw: pcode::VarNode, - fptag: pcode::VarNode, - //msr: pcode::VarNode, - mxcsr: pcode::VarNode, - fs_base: pcode::VarNode, - gs_base: pcode::VarNode, - flags: pcode::VarNode, - rflags: pcode::VarNode, - fip: pcode::VarNode, - //fcs: pcode::VarNode, - fdp: pcode::VarNode, - //fds: pcode::VarNode, - fop: pcode::VarNode, -} - -impl X64RegisterNodes { - pub fn new(arch: &icicle_cpu::Arch) -> Self { - let r = |name: &str| arch.sleigh.get_reg(name).unwrap().var; - Self { - rax: r("RAX"), - rbx: r("RBX"), - rcx: r("RCX"), - rdx: r("RDX"), - rsi: r("RSI"), - rdi: r("RDI"), - rbp: r("RBP"), - rsp: r("RSP"), - r8: r("R8"), - r9: r("R9"), - r10: r("R10"), - r11: r("R11"), - r12: r("R12"), - r13: r("R13"), - r14: r("R14"), - r15: r("R15"), - rip: r("RIP"), - eflags: r("eflags"), - cs: r("CS"), - ds: r("DS"), - es: r("ES"), - fs: r("FS"), - gs: r("GS"), - ss: r("SS"), - ah: r("AH"), - al: r("AL"), - ax: r("AX"), - bh: r("BH"), - bl: r("BL"), - bpl: r("BPL"), - ch: r("CH"), - cl: r("CL"), - cx: r("CX"), - dh: r("DH"), - dil: r("DIL"), - dl: r("DL"), - dx: r("DX"), - eax: r("EAX"), - ebp: r("EBP"), - ebx: r("EBX"), - ecx: r("ECX"), - edi: r("EDI"), - edx: r("EDX"), - esi: r("ESI"), - esp: r("ESP"), - fpsw: r("FPUStatusWord"), - gdtr: r("GDTR"), - idtr: r("IDTR"), - ldtr: r("LDTR"), - tr: r("TR"), - cr0: r("CR0"), - cr1: r("CR1"), - cr2: r("CR2"), - cr3: r("CR3"), - cr4: r("CR4"), - cr8: r("CR8"), - dr0: r("DR0"), - dr1: r("DR1"), - dr2: r("DR2"), - dr3: r("DR3"), - dr4: r("DR4"), - dr5: r("DR5"), - dr6: r("DR6"), - dr7: r("DR7"), - fp0: r("ST0"), // ?? - fp1: r("ST1"), - fp2: r("ST2"), - fp3: r("ST3"), - fp4: r("ST4"), - fp5: r("ST5"), - fp6: r("ST6"), - fp7: r("ST7"), - /*k0: r("K0"), - k1: r("K1"), - k2: r("K2"), - k3: r("K3"), - k4: r("K4"), - k5: r("K5"), - k6: r("K6"), - k7: r("K7"),*/ - mm0: r("MM0"), - mm1: r("MM1"), - mm2: r("MM2"), - mm3: r("MM3"), - mm4: r("MM4"), - mm5: r("MM5"), - mm6: r("MM6"), - mm7: r("MM7"), - st0: r("ST0"), - st1: r("ST1"), - st2: r("ST2"), - st3: r("ST3"), - st4: r("ST4"), - st5: r("ST5"), - st6: r("ST6"), - st7: r("ST7"), - xmm0: r("XMM0"), - xmm1: r("XMM1"), - xmm2: r("XMM2"), - xmm3: r("XMM3"), - xmm4: r("XMM4"), - xmm5: r("XMM5"), - xmm6: r("XMM6"), - xmm7: r("XMM7"), - xmm8: r("XMM8"), - xmm9: r("XMM9"), - xmm10: r("XMM10"), - xmm11: r("XMM11"), - xmm12: r("XMM12"), - xmm13: r("XMM13"), - xmm14: r("XMM14"), - xmm15: r("XMM15"), - /*xmm16: r("XMM16"), - xmm17: r("XMM17"), - xmm18: r("XMM18"), - xmm19: r("XMM19"), - xmm20: r("XMM20"), - xmm21: r("XMM21"), - xmm22: r("XMM22"), - xmm23: r("XMM23"), - xmm24: r("XMM24"), - xmm25: r("XMM25"), - xmm26: r("XMM26"), - xmm27: r("XMM27"), - xmm28: r("XMM28"), - xmm29: r("XMM29"), - xmm30: r("XMM30"), - xmm31: r("XMM31"),*/ - ymm0: r("YMM0"), - ymm1: r("YMM1"), - ymm2: r("YMM2"), - ymm3: r("YMM3"), - ymm4: r("YMM4"), - ymm5: r("YMM5"), - ymm6: r("YMM6"), - ymm7: r("YMM7"), - ymm8: r("YMM8"), - ymm9: r("YMM9"), - ymm10: r("YMM10"), - ymm11: r("YMM11"), - ymm12: r("YMM12"), - ymm13: r("YMM13"), - ymm14: r("YMM14"), - ymm15: r("YMM15"), - /*ymm16: r("YMM16"), - ymm17: r("YMM17"), - ymm18: r("YMM18"), - ymm19: r("YMM19"), - ymm20: r("YMM20"), - ymm21: r("YMM21"), - ymm22: r("YMM22"), - ymm23: r("YMM23"), - ymm24: r("YMM24"), - ymm25: r("YMM25"), - ymm26: r("YMM26"), - ymm27: r("YMM27"), - ymm28: r("YMM28"), - ymm29: r("YMM29"), - ymm30: r("YMM30"), - ymm31: r("YMM31"),*/ - /*zmm0: r("ZMM0"), - zmm1: r("ZMM1"), - zmm2: r("ZMM2"), - zmm3: r("ZMM3"), - zmm4: r("ZMM4"), - zmm5: r("ZMM5"), - zmm6: r("ZMM6"), - zmm7: r("ZMM7"), - zmm8: r("ZMM8"), - zmm9: r("ZMM9"), - zmm10: r("ZMM10"), - zmm11: r("ZMM11"), - zmm12: r("ZMM12"), - zmm13: r("ZMM13"), - zmm14: r("ZMM14"), - zmm15: r("ZMM15"), - zmm16: r("ZMM16"), - zmm17: r("ZMM17"), - zmm18: r("ZMM18"), - zmm19: r("ZMM19"), - zmm20: r("ZMM20"), - zmm21: r("ZMM21"), - zmm22: r("ZMM22"), - zmm23: r("ZMM23"), - zmm24: r("ZMM24"), - zmm25: r("ZMM25"), - zmm26: r("ZMM26"), - zmm27: r("ZMM27"), - zmm28: r("ZMM28"), - zmm29: r("ZMM29"), - zmm30: r("ZMM30"), - zmm31: r("ZMM31"),*/ - r8b: r("R8B"), - r9b: r("R9B"), - r10b: r("R10B"), - r11b: r("R11B"), - r12b: r("R12B"), - r13b: r("R13B"), - r14b: r("R14B"), - r15b: r("R15B"), - r8d: r("R8D"), - r9d: r("R9D"), - r10d: r("R10D"), - r11d: r("R11D"), - r12d: r("R12D"), - r13d: r("R13D"), - r14d: r("R14D"), - r15d: r("R15D"), - r8w: r("R8W"), - r9w: r("R9W"), - r10w: r("R10W"), - r11w: r("R11W"), - r12w: r("R12W"), - r13w: r("R13W"), - r14w: r("R14W"), - r15w: r("R15W"), - fpcw: r("FPUControlWord"), - fptag: r("FPUTagWord"), - mxcsr: r("MXCSR"), - flags: r("flags"), - rflags: r("rflags"), - fip: r("FPUInstructionPointer"), - fdp: r("FPUDataPointer"), - fop: r("FPULastInstructionOpcode"), - /*fds: r("FDS"), - msr: r("MSR"), - fcs: r("FCS"),*/ - fs_base: r("FS_OFFSET"), - gs_base: r("GS_OFFSET"), - } - } - - pub fn get_node(&self, reg: X64Register) -> pcode::VarNode { - match reg { - X64Register::Rax => self.rax, - X64Register::Rbx => self.rbx, - X64Register::Rcx => self.rcx, - X64Register::Rdx => self.rdx, - X64Register::Rsi => self.rsi, - X64Register::Rdi => self.rdi, - X64Register::Rbp => self.rbp, - X64Register::Rsp => self.rsp, - X64Register::R8 => self.r8, - X64Register::R9 => self.r9, - X64Register::R10 => self.r10, - X64Register::R11 => self.r11, - X64Register::R12 => self.r12, - X64Register::R13 => self.r13, - X64Register::R14 => self.r14, - X64Register::R15 => self.r15, - X64Register::Rip => self.rip, - X64Register::Eflags => self.eflags, - X64Register::Cs => self.cs, - X64Register::Ds => self.ds, - X64Register::Es => self.es, - X64Register::Fs => self.fs, - X64Register::Gs => self.gs, - X64Register::Ss => self.ss, - X64Register::Ah => self.ah, - X64Register::Al => self.al, - X64Register::Ax => self.ax, - X64Register::Bh => self.bh, - X64Register::Bl => self.bl, - X64Register::Bpl => self.bpl, - X64Register::Ch => self.ch, - X64Register::Cl => self.cl, - X64Register::Cx => self.cx, - X64Register::Dh => self.dh, - X64Register::Dil => self.dil, - X64Register::Dl => self.dl, - X64Register::Dx => self.dx, - X64Register::Eax => self.eax, - X64Register::Ebp => self.ebp, - X64Register::Ebx => self.ebx, - X64Register::Ecx => self.ecx, - X64Register::Edi => self.edi, - X64Register::Edx => self.edx, - X64Register::Esi => self.esi, - X64Register::Esp => self.esp, - X64Register::Fpsw => self.fpsw, - X64Register::Gdtr => self.gdtr, - X64Register::Idtr => self.idtr, - X64Register::Ldtr => self.ldtr, - X64Register::Tr => self.tr, - X64Register::Cr0 => self.cr0, - X64Register::Cr1 => self.cr1, - X64Register::Cr2 => self.cr2, - X64Register::Cr3 => self.cr3, - X64Register::Cr4 => self.cr4, - X64Register::Cr8 => self.cr8, - X64Register::Dr0 => self.dr0, - X64Register::Dr1 => self.dr1, - X64Register::Dr2 => self.dr2, - X64Register::Dr3 => self.dr3, - X64Register::Dr4 => self.dr4, - X64Register::Dr5 => self.dr5, - X64Register::Dr6 => self.dr6, - X64Register::Dr7 => self.dr7, - X64Register::Fp0 => self.fp0, - X64Register::Fp1 => self.fp1, - X64Register::Fp2 => self.fp2, - X64Register::Fp3 => self.fp3, - X64Register::Fp4 => self.fp4, - X64Register::Fp5 => self.fp5, - X64Register::Fp6 => self.fp6, - X64Register::Fp7 => self.fp7, - /*X64Register::K0 => self.k0, - X64Register::K1 => self.k1, - X64Register::K2 => self.k2, - X64Register::K3 => self.k3, - X64Register::K4 => self.k4, - X64Register::K5 => self.k5, - X64Register::K6 => self.k6, - X64Register::K7 => self.k7,*/ - X64Register::Mm0 => self.mm0, - X64Register::Mm1 => self.mm1, - X64Register::Mm2 => self.mm2, - X64Register::Mm3 => self.mm3, - X64Register::Mm4 => self.mm4, - X64Register::Mm5 => self.mm5, - X64Register::Mm6 => self.mm6, - X64Register::Mm7 => self.mm7, - X64Register::St0 => self.st0, - X64Register::St1 => self.st1, - X64Register::St2 => self.st2, - X64Register::St3 => self.st3, - X64Register::St4 => self.st4, - X64Register::St5 => self.st5, - X64Register::St6 => self.st6, - X64Register::St7 => self.st7, - X64Register::Xmm0 => self.xmm0, - X64Register::Xmm1 => self.xmm1, - X64Register::Xmm2 => self.xmm2, - X64Register::Xmm3 => self.xmm3, - X64Register::Xmm4 => self.xmm4, - X64Register::Xmm5 => self.xmm5, - X64Register::Xmm6 => self.xmm6, - X64Register::Xmm7 => self.xmm7, - X64Register::Xmm8 => self.xmm8, - X64Register::Xmm9 => self.xmm9, - X64Register::Xmm10 => self.xmm10, - X64Register::Xmm11 => self.xmm11, - X64Register::Xmm12 => self.xmm12, - X64Register::Xmm13 => self.xmm13, - X64Register::Xmm14 => self.xmm14, - X64Register::Xmm15 => self.xmm15, - /*X64Register::Xmm16 => self.xmm16, - X64Register::Xmm17 => self.xmm17, - X64Register::Xmm18 => self.xmm18, - X64Register::Xmm19 => self.xmm19, - X64Register::Xmm20 => self.xmm20, - X64Register::Xmm21 => self.xmm21, - X64Register::Xmm22 => self.xmm22, - X64Register::Xmm23 => self.xmm23, - X64Register::Xmm24 => self.xmm24, - X64Register::Xmm25 => self.xmm25, - X64Register::Xmm26 => self.xmm26, - X64Register::Xmm27 => self.xmm27, - X64Register::Xmm28 => self.xmm28, - X64Register::Xmm29 => self.xmm29, - X64Register::Xmm30 => self.xmm30, - X64Register::Xmm31 => self.xmm31,*/ - X64Register::Ymm0 => self.ymm0, - X64Register::Ymm1 => self.ymm1, - X64Register::Ymm2 => self.ymm2, - X64Register::Ymm3 => self.ymm3, - X64Register::Ymm4 => self.ymm4, - X64Register::Ymm5 => self.ymm5, - X64Register::Ymm6 => self.ymm6, - X64Register::Ymm7 => self.ymm7, - X64Register::Ymm8 => self.ymm8, - X64Register::Ymm9 => self.ymm9, - X64Register::Ymm10 => self.ymm10, - X64Register::Ymm11 => self.ymm11, - X64Register::Ymm12 => self.ymm12, - X64Register::Ymm13 => self.ymm13, - X64Register::Ymm14 => self.ymm14, - X64Register::Ymm15 => self.ymm15, - /*X64Register::Ymm16 => self.ymm16, - X64Register::Ymm17 => self.ymm17, - X64Register::Ymm18 => self.ymm18, - X64Register::Ymm19 => self.ymm19, - X64Register::Ymm20 => self.ymm20, - X64Register::Ymm21 => self.ymm21, - X64Register::Ymm22 => self.ymm22, - X64Register::Ymm23 => self.ymm23, - X64Register::Ymm24 => self.ymm24, - X64Register::Ymm25 => self.ymm25, - X64Register::Ymm26 => self.ymm26, - X64Register::Ymm27 => self.ymm27, - X64Register::Ymm28 => self.ymm28, - X64Register::Ymm29 => self.ymm29, - X64Register::Ymm30 => self.ymm30, - X64Register::Ymm31 => self.ymm31,*/ - /*X64Register::Zmm0 => self.zmm0, - X64Register::Zmm1 => self.zmm1, - X64Register::Zmm2 => self.zmm2, - X64Register::Zmm3 => self.zmm3, - X64Register::Zmm4 => self.zmm4, - X64Register::Zmm5 => self.zmm5, - X64Register::Zmm6 => self.zmm6, - X64Register::Zmm7 => self.zmm7, - X64Register::Zmm8 => self.zmm8, - X64Register::Zmm9 => self.zmm9, - X64Register::Zmm10 => self.zmm10, - X64Register::Zmm11 => self.zmm11, - X64Register::Zmm12 => self.zmm12, - X64Register::Zmm13 => self.zmm13, - X64Register::Zmm14 => self.zmm14, - X64Register::Zmm15 => self.zmm15, - X64Register::Zmm16 => self.zmm16, - X64Register::Zmm17 => self.zmm17, - X64Register::Zmm18 => self.zmm18, - X64Register::Zmm19 => self.zmm19, - X64Register::Zmm20 => self.zmm20, - X64Register::Zmm21 => self.zmm21, - X64Register::Zmm22 => self.zmm22, - X64Register::Zmm23 => self.zmm23, - X64Register::Zmm24 => self.zmm24, - X64Register::Zmm25 => self.zmm25, - X64Register::Zmm26 => self.zmm26, - X64Register::Zmm27 => self.zmm27, - X64Register::Zmm28 => self.zmm28, - X64Register::Zmm29 => self.zmm29, - X64Register::Zmm30 => self.zmm30, - X64Register::Zmm31 => self.zmm31,*/ - X64Register::R8b => self.r8b, - X64Register::R9b => self.r9b, - X64Register::R10b => self.r10b, - X64Register::R11b => self.r11b, - X64Register::R12b => self.r12b, - X64Register::R13b => self.r13b, - X64Register::R14b => self.r14b, - X64Register::R15b => self.r15b, - X64Register::R8d => self.r8d, - X64Register::R9d => self.r9d, - X64Register::R10d => self.r10d, - X64Register::R11d => self.r11d, - X64Register::R12d => self.r12d, - X64Register::R13d => self.r13d, - X64Register::R14d => self.r14d, - X64Register::R15d => self.r15d, - X64Register::R8w => self.r8w, - X64Register::R9w => self.r9w, - X64Register::R10w => self.r10w, - X64Register::R11w => self.r11w, - X64Register::R12w => self.r12w, - X64Register::R13w => self.r13w, - X64Register::R14w => self.r14w, - X64Register::R15w => self.r15w, - X64Register::Fpcw => self.fpcw, - X64Register::Fptag => self.fptag, - //X64Register::Msr => self.msr, - X64Register::Mxcsr => self.mxcsr, - X64Register::FsBase => self.fs_base, - X64Register::GsBase => self.gs_base, - X64Register::Flags => self.flags, - X64Register::Rflags => self.rflags, - X64Register::Fip => self.fip, - //X64Register::Fcs => self.fcs, - X64Register::Fdp => self.fdp, - //X64Register::Fds => self.fds, - X64Register::Fop => self.fop, - _ => panic!("Unsupported register"), - } - } -} diff --git a/src/icicle/src/lib.rs b/src/icicle/src/lib.rs index 22c40e16..d12b64d5 100644 --- a/src/icicle/src/lib.rs +++ b/src/icicle/src/lib.rs @@ -1,6 +1,8 @@ mod icicle; +mod registers; -use icicle::{IcicleEmulator, X64Register}; +use icicle::IcicleEmulator; +use registers::X64Register; use std::os::raw::c_void; fn to_cbool(value: bool) -> i32 { diff --git a/src/icicle/src/registers.rs b/src/icicle/src/registers.rs new file mode 100644 index 00000000..40d00f9c --- /dev/null +++ b/src/icicle/src/registers.rs @@ -0,0 +1,949 @@ +#[repr(i32)] +#[derive(PartialEq)] +pub enum X64Register { + Invalid = 0, + Ah, + Al, + Ax, + Bh, + Bl, + Bp, + Bpl, + Bx, + Ch, + Cl, + Cs, + Cx, + Dh, + Di, + Dil, + Dl, + Ds, + Dx, + Eax, + Ebp, + Ebx, + Ecx, + Edi, + Edx, + Eflags, + Eip, + Es = 26 + 2, + Esi, + Esp, + Fpsw, + Fs, + Gs, + Ip, + Rax, + Rbp, + Rbx, + Rcx, + Rdi, + Rdx, + Rip, + Rsi = 41 + 2, + Rsp, + Si, + Sil, + Sp, + Spl, + Ss, + Cr0, + Cr1, + Cr2, + Cr3, + Cr4, + Cr8 = 54 + 4, + Dr0 = 58 + 8, + Dr1, + Dr2, + Dr3, + Dr4, + Dr5, + Dr6, + Dr7, + Fp0 = 73 + 9, + Fp1, + Fp2, + Fp3, + Fp4, + Fp5, + Fp6, + Fp7, + K0, + K1, + K2, + K3, + K4, + K5, + K6, + K7, + Mm0, + Mm1, + Mm2, + Mm3, + Mm4, + Mm5, + Mm6, + Mm7, + R8, + R9, + R10, + R11, + R12, + R13, + R14, + R15, + St0, + St1, + St2, + St3, + St4, + St5, + St6, + St7, + Xmm0, + Xmm1, + Xmm2, + Xmm3, + Xmm4, + Xmm5, + Xmm6, + Xmm7, + Xmm8, + Xmm9, + Xmm10, + Xmm11, + Xmm12, + Xmm13, + Xmm14, + Xmm15, + Xmm16, + Xmm17, + Xmm18, + Xmm19, + Xmm20, + Xmm21, + Xmm22, + Xmm23, + Xmm24, + Xmm25, + Xmm26, + Xmm27, + Xmm28, + Xmm29, + Xmm30, + Xmm31, + Ymm0, + Ymm1, + Ymm2, + Ymm3, + Ymm4, + Ymm5, + Ymm6, + Ymm7, + Ymm8, + Ymm9, + Ymm10, + Ymm11, + Ymm12, + Ymm13, + Ymm14, + Ymm15, + Ymm16, + Ymm17, + Ymm18, + Ymm19, + Ymm20, + Ymm21, + Ymm22, + Ymm23, + Ymm24, + Ymm25, + Ymm26, + Ymm27, + Ymm28, + Ymm29, + Ymm30, + Ymm31, + Zmm0, + Zmm1, + Zmm2, + Zmm3, + Zmm4, + Zmm5, + Zmm6, + Zmm7, + Zmm8, + Zmm9, + Zmm10, + Zmm11, + Zmm12, + Zmm13, + Zmm14, + Zmm15, + Zmm16, + Zmm17, + Zmm18, + Zmm19, + Zmm20, + Zmm21, + Zmm22, + Zmm23, + Zmm24, + Zmm25, + Zmm26, + Zmm27, + Zmm28, + Zmm29, + Zmm30, + Zmm31, + R8b, + R9b, + R10b, + R11b, + R12b, + R13b, + R14b, + R15b, + R8d, + R9d, + R10d, + R11d, + R12d, + R13d, + R14d, + R15d, + R8w, + R9w, + R10w, + R11w, + R12w, + R13w, + R14w, + R15w, + Idtr, + Gdtr, + Ldtr, + Tr, + Fpcw, + Fptag, + Msr, + Mxcsr, + FsBase, + GsBase, + Flags, + Rflags, + Fip, + Fcs, + Fdp, + Fds, + Fop, + End, // Must be last +} + +#[derive(Clone)] +pub(crate) struct X64RegisterNodes { + rax: pcode::VarNode, + rbx: pcode::VarNode, + rcx: pcode::VarNode, + rdx: pcode::VarNode, + rsi: pcode::VarNode, + rdi: pcode::VarNode, + rbp: pcode::VarNode, + rsp: pcode::VarNode, + r8: pcode::VarNode, + r9: pcode::VarNode, + r10: pcode::VarNode, + r11: pcode::VarNode, + r12: pcode::VarNode, + r13: pcode::VarNode, + r14: pcode::VarNode, + r15: pcode::VarNode, + rip: pcode::VarNode, + eflags: pcode::VarNode, + cs: pcode::VarNode, + ds: pcode::VarNode, + es: pcode::VarNode, + fs: pcode::VarNode, + gs: pcode::VarNode, + ss: pcode::VarNode, + ah: pcode::VarNode, + al: pcode::VarNode, + ax: pcode::VarNode, + bh: pcode::VarNode, + bl: pcode::VarNode, + bpl: pcode::VarNode, + ch: pcode::VarNode, + cl: pcode::VarNode, + cx: pcode::VarNode, + dh: pcode::VarNode, + dil: pcode::VarNode, + dl: pcode::VarNode, + dx: pcode::VarNode, + eax: pcode::VarNode, + ebp: pcode::VarNode, + ebx: pcode::VarNode, + ecx: pcode::VarNode, + edi: pcode::VarNode, + edx: pcode::VarNode, + esi: pcode::VarNode, + esp: pcode::VarNode, + fpsw: pcode::VarNode, + gdtr: pcode::VarNode, + idtr: pcode::VarNode, + ldtr: pcode::VarNode, + tr: pcode::VarNode, + cr0: pcode::VarNode, + cr1: pcode::VarNode, + cr2: pcode::VarNode, + cr3: pcode::VarNode, + cr4: pcode::VarNode, + cr8: pcode::VarNode, + dr0: pcode::VarNode, + dr1: pcode::VarNode, + dr2: pcode::VarNode, + dr3: pcode::VarNode, + dr4: pcode::VarNode, + dr5: pcode::VarNode, + dr6: pcode::VarNode, + dr7: pcode::VarNode, + fp0: pcode::VarNode, + fp1: pcode::VarNode, + fp2: pcode::VarNode, + fp3: pcode::VarNode, + fp4: pcode::VarNode, + fp5: pcode::VarNode, + fp6: pcode::VarNode, + fp7: pcode::VarNode, + /*k0: pcode::VarNode, + k1: pcode::VarNode, + k2: pcode::VarNode, + k3: pcode::VarNode, + k4: pcode::VarNode, + k5: pcode::VarNode, + k6: pcode::VarNode, + k7: pcode::VarNode,*/ + mm0: pcode::VarNode, + mm1: pcode::VarNode, + mm2: pcode::VarNode, + mm3: pcode::VarNode, + mm4: pcode::VarNode, + mm5: pcode::VarNode, + mm6: pcode::VarNode, + mm7: pcode::VarNode, + st0: pcode::VarNode, + st1: pcode::VarNode, + st2: pcode::VarNode, + st3: pcode::VarNode, + st4: pcode::VarNode, + st5: pcode::VarNode, + st6: pcode::VarNode, + st7: pcode::VarNode, + xmm0: pcode::VarNode, + xmm1: pcode::VarNode, + xmm2: pcode::VarNode, + xmm3: pcode::VarNode, + xmm4: pcode::VarNode, + xmm5: pcode::VarNode, + xmm6: pcode::VarNode, + xmm7: pcode::VarNode, + xmm8: pcode::VarNode, + xmm9: pcode::VarNode, + xmm10: pcode::VarNode, + xmm11: pcode::VarNode, + xmm12: pcode::VarNode, + xmm13: pcode::VarNode, + xmm14: pcode::VarNode, + xmm15: pcode::VarNode, + /*xmm16: pcode::VarNode, + xmm17: pcode::VarNode, + xmm18: pcode::VarNode, + xmm19: pcode::VarNode, + xmm20: pcode::VarNode, + xmm21: pcode::VarNode, + xmm22: pcode::VarNode, + xmm23: pcode::VarNode, + xmm24: pcode::VarNode, + xmm25: pcode::VarNode, + xmm26: pcode::VarNode, + xmm27: pcode::VarNode, + xmm28: pcode::VarNode, + xmm29: pcode::VarNode, + xmm30: pcode::VarNode, + xmm31: pcode::VarNode,*/ + ymm0: pcode::VarNode, + ymm1: pcode::VarNode, + ymm2: pcode::VarNode, + ymm3: pcode::VarNode, + ymm4: pcode::VarNode, + ymm5: pcode::VarNode, + ymm6: pcode::VarNode, + ymm7: pcode::VarNode, + ymm8: pcode::VarNode, + ymm9: pcode::VarNode, + ymm10: pcode::VarNode, + ymm11: pcode::VarNode, + ymm12: pcode::VarNode, + ymm13: pcode::VarNode, + ymm14: pcode::VarNode, + ymm15: pcode::VarNode, + /*ymm16: pcode::VarNode, + ymm17: pcode::VarNode, + ymm18: pcode::VarNode, + ymm19: pcode::VarNode, + ymm20: pcode::VarNode, + ymm21: pcode::VarNode, + ymm22: pcode::VarNode, + ymm23: pcode::VarNode, + ymm24: pcode::VarNode, + ymm25: pcode::VarNode, + ymm26: pcode::VarNode, + ymm27: pcode::VarNode, + ymm28: pcode::VarNode, + ymm29: pcode::VarNode, + ymm30: pcode::VarNode, + ymm31: pcode::VarNode,*/ + /*zmm0: pcode::VarNode, + zmm1: pcode::VarNode, + zmm2: pcode::VarNode, + zmm3: pcode::VarNode, + zmm4: pcode::VarNode, + zmm5: pcode::VarNode, + zmm6: pcode::VarNode, + zmm7: pcode::VarNode, + zmm8: pcode::VarNode, + zmm9: pcode::VarNode, + zmm10: pcode::VarNode, + zmm11: pcode::VarNode, + zmm12: pcode::VarNode, + zmm13: pcode::VarNode, + zmm14: pcode::VarNode, + zmm15: pcode::VarNode, + zmm16: pcode::VarNode, + zmm17: pcode::VarNode, + zmm18: pcode::VarNode, + zmm19: pcode::VarNode, + zmm20: pcode::VarNode, + zmm21: pcode::VarNode, + zmm22: pcode::VarNode, + zmm23: pcode::VarNode, + zmm24: pcode::VarNode, + zmm25: pcode::VarNode, + zmm26: pcode::VarNode, + zmm27: pcode::VarNode, + zmm28: pcode::VarNode, + zmm29: pcode::VarNode, + zmm30: pcode::VarNode, + zmm31: pcode::VarNode,*/ + r8b: pcode::VarNode, + r9b: pcode::VarNode, + r10b: pcode::VarNode, + r11b: pcode::VarNode, + r12b: pcode::VarNode, + r13b: pcode::VarNode, + r14b: pcode::VarNode, + r15b: pcode::VarNode, + r8d: pcode::VarNode, + r9d: pcode::VarNode, + r10d: pcode::VarNode, + r11d: pcode::VarNode, + r12d: pcode::VarNode, + r13d: pcode::VarNode, + r14d: pcode::VarNode, + r15d: pcode::VarNode, + r8w: pcode::VarNode, + r9w: pcode::VarNode, + r10w: pcode::VarNode, + r11w: pcode::VarNode, + r12w: pcode::VarNode, + r13w: pcode::VarNode, + r14w: pcode::VarNode, + r15w: pcode::VarNode, + fpcw: pcode::VarNode, + fptag: pcode::VarNode, + //msr: pcode::VarNode, + mxcsr: pcode::VarNode, + fs_base: pcode::VarNode, + gs_base: pcode::VarNode, + flags: pcode::VarNode, + rflags: pcode::VarNode, + fip: pcode::VarNode, + //fcs: pcode::VarNode, + fdp: pcode::VarNode, + //fds: pcode::VarNode, + fop: pcode::VarNode, +} + +impl X64RegisterNodes { + pub fn new(arch: &icicle_cpu::Arch) -> Self { + let r = |name: &str| arch.sleigh.get_reg(name).unwrap().var; + Self { + rax: r("RAX"), + rbx: r("RBX"), + rcx: r("RCX"), + rdx: r("RDX"), + rsi: r("RSI"), + rdi: r("RDI"), + rbp: r("RBP"), + rsp: r("RSP"), + r8: r("R8"), + r9: r("R9"), + r10: r("R10"), + r11: r("R11"), + r12: r("R12"), + r13: r("R13"), + r14: r("R14"), + r15: r("R15"), + rip: r("RIP"), + eflags: r("eflags"), + cs: r("CS"), + ds: r("DS"), + es: r("ES"), + fs: r("FS"), + gs: r("GS"), + ss: r("SS"), + ah: r("AH"), + al: r("AL"), + ax: r("AX"), + bh: r("BH"), + bl: r("BL"), + bpl: r("BPL"), + ch: r("CH"), + cl: r("CL"), + cx: r("CX"), + dh: r("DH"), + dil: r("DIL"), + dl: r("DL"), + dx: r("DX"), + eax: r("EAX"), + ebp: r("EBP"), + ebx: r("EBX"), + ecx: r("ECX"), + edi: r("EDI"), + edx: r("EDX"), + esi: r("ESI"), + esp: r("ESP"), + fpsw: r("FPUStatusWord"), + gdtr: r("GDTR"), + idtr: r("IDTR"), + ldtr: r("LDTR"), + tr: r("TR"), + cr0: r("CR0"), + cr1: r("CR1"), + cr2: r("CR2"), + cr3: r("CR3"), + cr4: r("CR4"), + cr8: r("CR8"), + dr0: r("DR0"), + dr1: r("DR1"), + dr2: r("DR2"), + dr3: r("DR3"), + dr4: r("DR4"), + dr5: r("DR5"), + dr6: r("DR6"), + dr7: r("DR7"), + fp0: r("ST0"), // ?? + fp1: r("ST1"), + fp2: r("ST2"), + fp3: r("ST3"), + fp4: r("ST4"), + fp5: r("ST5"), + fp6: r("ST6"), + fp7: r("ST7"), + /*k0: r("K0"), + k1: r("K1"), + k2: r("K2"), + k3: r("K3"), + k4: r("K4"), + k5: r("K5"), + k6: r("K6"), + k7: r("K7"),*/ + mm0: r("MM0"), + mm1: r("MM1"), + mm2: r("MM2"), + mm3: r("MM3"), + mm4: r("MM4"), + mm5: r("MM5"), + mm6: r("MM6"), + mm7: r("MM7"), + st0: r("ST0"), + st1: r("ST1"), + st2: r("ST2"), + st3: r("ST3"), + st4: r("ST4"), + st5: r("ST5"), + st6: r("ST6"), + st7: r("ST7"), + xmm0: r("XMM0"), + xmm1: r("XMM1"), + xmm2: r("XMM2"), + xmm3: r("XMM3"), + xmm4: r("XMM4"), + xmm5: r("XMM5"), + xmm6: r("XMM6"), + xmm7: r("XMM7"), + xmm8: r("XMM8"), + xmm9: r("XMM9"), + xmm10: r("XMM10"), + xmm11: r("XMM11"), + xmm12: r("XMM12"), + xmm13: r("XMM13"), + xmm14: r("XMM14"), + xmm15: r("XMM15"), + /*xmm16: r("XMM16"), + xmm17: r("XMM17"), + xmm18: r("XMM18"), + xmm19: r("XMM19"), + xmm20: r("XMM20"), + xmm21: r("XMM21"), + xmm22: r("XMM22"), + xmm23: r("XMM23"), + xmm24: r("XMM24"), + xmm25: r("XMM25"), + xmm26: r("XMM26"), + xmm27: r("XMM27"), + xmm28: r("XMM28"), + xmm29: r("XMM29"), + xmm30: r("XMM30"), + xmm31: r("XMM31"),*/ + ymm0: r("YMM0"), + ymm1: r("YMM1"), + ymm2: r("YMM2"), + ymm3: r("YMM3"), + ymm4: r("YMM4"), + ymm5: r("YMM5"), + ymm6: r("YMM6"), + ymm7: r("YMM7"), + ymm8: r("YMM8"), + ymm9: r("YMM9"), + ymm10: r("YMM10"), + ymm11: r("YMM11"), + ymm12: r("YMM12"), + ymm13: r("YMM13"), + ymm14: r("YMM14"), + ymm15: r("YMM15"), + /*ymm16: r("YMM16"), + ymm17: r("YMM17"), + ymm18: r("YMM18"), + ymm19: r("YMM19"), + ymm20: r("YMM20"), + ymm21: r("YMM21"), + ymm22: r("YMM22"), + ymm23: r("YMM23"), + ymm24: r("YMM24"), + ymm25: r("YMM25"), + ymm26: r("YMM26"), + ymm27: r("YMM27"), + ymm28: r("YMM28"), + ymm29: r("YMM29"), + ymm30: r("YMM30"), + ymm31: r("YMM31"),*/ + /*zmm0: r("ZMM0"), + zmm1: r("ZMM1"), + zmm2: r("ZMM2"), + zmm3: r("ZMM3"), + zmm4: r("ZMM4"), + zmm5: r("ZMM5"), + zmm6: r("ZMM6"), + zmm7: r("ZMM7"), + zmm8: r("ZMM8"), + zmm9: r("ZMM9"), + zmm10: r("ZMM10"), + zmm11: r("ZMM11"), + zmm12: r("ZMM12"), + zmm13: r("ZMM13"), + zmm14: r("ZMM14"), + zmm15: r("ZMM15"), + zmm16: r("ZMM16"), + zmm17: r("ZMM17"), + zmm18: r("ZMM18"), + zmm19: r("ZMM19"), + zmm20: r("ZMM20"), + zmm21: r("ZMM21"), + zmm22: r("ZMM22"), + zmm23: r("ZMM23"), + zmm24: r("ZMM24"), + zmm25: r("ZMM25"), + zmm26: r("ZMM26"), + zmm27: r("ZMM27"), + zmm28: r("ZMM28"), + zmm29: r("ZMM29"), + zmm30: r("ZMM30"), + zmm31: r("ZMM31"),*/ + r8b: r("R8B"), + r9b: r("R9B"), + r10b: r("R10B"), + r11b: r("R11B"), + r12b: r("R12B"), + r13b: r("R13B"), + r14b: r("R14B"), + r15b: r("R15B"), + r8d: r("R8D"), + r9d: r("R9D"), + r10d: r("R10D"), + r11d: r("R11D"), + r12d: r("R12D"), + r13d: r("R13D"), + r14d: r("R14D"), + r15d: r("R15D"), + r8w: r("R8W"), + r9w: r("R9W"), + r10w: r("R10W"), + r11w: r("R11W"), + r12w: r("R12W"), + r13w: r("R13W"), + r14w: r("R14W"), + r15w: r("R15W"), + fpcw: r("FPUControlWord"), + fptag: r("FPUTagWord"), + mxcsr: r("MXCSR"), + flags: r("flags"), + rflags: r("rflags"), + fip: r("FPUInstructionPointer"), + fdp: r("FPUDataPointer"), + fop: r("FPULastInstructionOpcode"), + /*fds: r("FDS"), + msr: r("MSR"), + fcs: r("FCS"),*/ + fs_base: r("FS_OFFSET"), + gs_base: r("GS_OFFSET"), + } + } + + pub fn get_node(&self, reg: X64Register) -> pcode::VarNode { + match reg { + X64Register::Rax => self.rax, + X64Register::Rbx => self.rbx, + X64Register::Rcx => self.rcx, + X64Register::Rdx => self.rdx, + X64Register::Rsi => self.rsi, + X64Register::Rdi => self.rdi, + X64Register::Rbp => self.rbp, + X64Register::Rsp => self.rsp, + X64Register::R8 => self.r8, + X64Register::R9 => self.r9, + X64Register::R10 => self.r10, + X64Register::R11 => self.r11, + X64Register::R12 => self.r12, + X64Register::R13 => self.r13, + X64Register::R14 => self.r14, + X64Register::R15 => self.r15, + X64Register::Rip => self.rip, + X64Register::Eflags => self.eflags, + X64Register::Cs => self.cs, + X64Register::Ds => self.ds, + X64Register::Es => self.es, + X64Register::Fs => self.fs, + X64Register::Gs => self.gs, + X64Register::Ss => self.ss, + X64Register::Ah => self.ah, + X64Register::Al => self.al, + X64Register::Ax => self.ax, + X64Register::Bh => self.bh, + X64Register::Bl => self.bl, + X64Register::Bpl => self.bpl, + X64Register::Ch => self.ch, + X64Register::Cl => self.cl, + X64Register::Cx => self.cx, + X64Register::Dh => self.dh, + X64Register::Dil => self.dil, + X64Register::Dl => self.dl, + X64Register::Dx => self.dx, + X64Register::Eax => self.eax, + X64Register::Ebp => self.ebp, + X64Register::Ebx => self.ebx, + X64Register::Ecx => self.ecx, + X64Register::Edi => self.edi, + X64Register::Edx => self.edx, + X64Register::Esi => self.esi, + X64Register::Esp => self.esp, + X64Register::Fpsw => self.fpsw, + X64Register::Gdtr => self.gdtr, + X64Register::Idtr => self.idtr, + X64Register::Ldtr => self.ldtr, + X64Register::Tr => self.tr, + X64Register::Cr0 => self.cr0, + X64Register::Cr1 => self.cr1, + X64Register::Cr2 => self.cr2, + X64Register::Cr3 => self.cr3, + X64Register::Cr4 => self.cr4, + X64Register::Cr8 => self.cr8, + X64Register::Dr0 => self.dr0, + X64Register::Dr1 => self.dr1, + X64Register::Dr2 => self.dr2, + X64Register::Dr3 => self.dr3, + X64Register::Dr4 => self.dr4, + X64Register::Dr5 => self.dr5, + X64Register::Dr6 => self.dr6, + X64Register::Dr7 => self.dr7, + X64Register::Fp0 => self.fp0, + X64Register::Fp1 => self.fp1, + X64Register::Fp2 => self.fp2, + X64Register::Fp3 => self.fp3, + X64Register::Fp4 => self.fp4, + X64Register::Fp5 => self.fp5, + X64Register::Fp6 => self.fp6, + X64Register::Fp7 => self.fp7, + /*X64Register::K0 => self.k0, + X64Register::K1 => self.k1, + X64Register::K2 => self.k2, + X64Register::K3 => self.k3, + X64Register::K4 => self.k4, + X64Register::K5 => self.k5, + X64Register::K6 => self.k6, + X64Register::K7 => self.k7,*/ + X64Register::Mm0 => self.mm0, + X64Register::Mm1 => self.mm1, + X64Register::Mm2 => self.mm2, + X64Register::Mm3 => self.mm3, + X64Register::Mm4 => self.mm4, + X64Register::Mm5 => self.mm5, + X64Register::Mm6 => self.mm6, + X64Register::Mm7 => self.mm7, + X64Register::St0 => self.st0, + X64Register::St1 => self.st1, + X64Register::St2 => self.st2, + X64Register::St3 => self.st3, + X64Register::St4 => self.st4, + X64Register::St5 => self.st5, + X64Register::St6 => self.st6, + X64Register::St7 => self.st7, + X64Register::Xmm0 => self.xmm0, + X64Register::Xmm1 => self.xmm1, + X64Register::Xmm2 => self.xmm2, + X64Register::Xmm3 => self.xmm3, + X64Register::Xmm4 => self.xmm4, + X64Register::Xmm5 => self.xmm5, + X64Register::Xmm6 => self.xmm6, + X64Register::Xmm7 => self.xmm7, + X64Register::Xmm8 => self.xmm8, + X64Register::Xmm9 => self.xmm9, + X64Register::Xmm10 => self.xmm10, + X64Register::Xmm11 => self.xmm11, + X64Register::Xmm12 => self.xmm12, + X64Register::Xmm13 => self.xmm13, + X64Register::Xmm14 => self.xmm14, + X64Register::Xmm15 => self.xmm15, + /*X64Register::Xmm16 => self.xmm16, + X64Register::Xmm17 => self.xmm17, + X64Register::Xmm18 => self.xmm18, + X64Register::Xmm19 => self.xmm19, + X64Register::Xmm20 => self.xmm20, + X64Register::Xmm21 => self.xmm21, + X64Register::Xmm22 => self.xmm22, + X64Register::Xmm23 => self.xmm23, + X64Register::Xmm24 => self.xmm24, + X64Register::Xmm25 => self.xmm25, + X64Register::Xmm26 => self.xmm26, + X64Register::Xmm27 => self.xmm27, + X64Register::Xmm28 => self.xmm28, + X64Register::Xmm29 => self.xmm29, + X64Register::Xmm30 => self.xmm30, + X64Register::Xmm31 => self.xmm31,*/ + X64Register::Ymm0 => self.ymm0, + X64Register::Ymm1 => self.ymm1, + X64Register::Ymm2 => self.ymm2, + X64Register::Ymm3 => self.ymm3, + X64Register::Ymm4 => self.ymm4, + X64Register::Ymm5 => self.ymm5, + X64Register::Ymm6 => self.ymm6, + X64Register::Ymm7 => self.ymm7, + X64Register::Ymm8 => self.ymm8, + X64Register::Ymm9 => self.ymm9, + X64Register::Ymm10 => self.ymm10, + X64Register::Ymm11 => self.ymm11, + X64Register::Ymm12 => self.ymm12, + X64Register::Ymm13 => self.ymm13, + X64Register::Ymm14 => self.ymm14, + X64Register::Ymm15 => self.ymm15, + /*X64Register::Ymm16 => self.ymm16, + X64Register::Ymm17 => self.ymm17, + X64Register::Ymm18 => self.ymm18, + X64Register::Ymm19 => self.ymm19, + X64Register::Ymm20 => self.ymm20, + X64Register::Ymm21 => self.ymm21, + X64Register::Ymm22 => self.ymm22, + X64Register::Ymm23 => self.ymm23, + X64Register::Ymm24 => self.ymm24, + X64Register::Ymm25 => self.ymm25, + X64Register::Ymm26 => self.ymm26, + X64Register::Ymm27 => self.ymm27, + X64Register::Ymm28 => self.ymm28, + X64Register::Ymm29 => self.ymm29, + X64Register::Ymm30 => self.ymm30, + X64Register::Ymm31 => self.ymm31,*/ + /*X64Register::Zmm0 => self.zmm0, + X64Register::Zmm1 => self.zmm1, + X64Register::Zmm2 => self.zmm2, + X64Register::Zmm3 => self.zmm3, + X64Register::Zmm4 => self.zmm4, + X64Register::Zmm5 => self.zmm5, + X64Register::Zmm6 => self.zmm6, + X64Register::Zmm7 => self.zmm7, + X64Register::Zmm8 => self.zmm8, + X64Register::Zmm9 => self.zmm9, + X64Register::Zmm10 => self.zmm10, + X64Register::Zmm11 => self.zmm11, + X64Register::Zmm12 => self.zmm12, + X64Register::Zmm13 => self.zmm13, + X64Register::Zmm14 => self.zmm14, + X64Register::Zmm15 => self.zmm15, + X64Register::Zmm16 => self.zmm16, + X64Register::Zmm17 => self.zmm17, + X64Register::Zmm18 => self.zmm18, + X64Register::Zmm19 => self.zmm19, + X64Register::Zmm20 => self.zmm20, + X64Register::Zmm21 => self.zmm21, + X64Register::Zmm22 => self.zmm22, + X64Register::Zmm23 => self.zmm23, + X64Register::Zmm24 => self.zmm24, + X64Register::Zmm25 => self.zmm25, + X64Register::Zmm26 => self.zmm26, + X64Register::Zmm27 => self.zmm27, + X64Register::Zmm28 => self.zmm28, + X64Register::Zmm29 => self.zmm29, + X64Register::Zmm30 => self.zmm30, + X64Register::Zmm31 => self.zmm31,*/ + X64Register::R8b => self.r8b, + X64Register::R9b => self.r9b, + X64Register::R10b => self.r10b, + X64Register::R11b => self.r11b, + X64Register::R12b => self.r12b, + X64Register::R13b => self.r13b, + X64Register::R14b => self.r14b, + X64Register::R15b => self.r15b, + X64Register::R8d => self.r8d, + X64Register::R9d => self.r9d, + X64Register::R10d => self.r10d, + X64Register::R11d => self.r11d, + X64Register::R12d => self.r12d, + X64Register::R13d => self.r13d, + X64Register::R14d => self.r14d, + X64Register::R15d => self.r15d, + X64Register::R8w => self.r8w, + X64Register::R9w => self.r9w, + X64Register::R10w => self.r10w, + X64Register::R11w => self.r11w, + X64Register::R12w => self.r12w, + X64Register::R13w => self.r13w, + X64Register::R14w => self.r14w, + X64Register::R15w => self.r15w, + X64Register::Fpcw => self.fpcw, + X64Register::Fptag => self.fptag, + //X64Register::Msr => self.msr, + X64Register::Mxcsr => self.mxcsr, + X64Register::FsBase => self.fs_base, + X64Register::GsBase => self.gs_base, + X64Register::Flags => self.flags, + X64Register::Rflags => self.rflags, + X64Register::Fip => self.fip, + //X64Register::Fcs => self.fcs, + X64Register::Fdp => self.fdp, + //X64Register::Fds => self.fds, + X64Register::Fop => self.fop, + _ => panic!("Unsupported register"), + } + } +} From 7d5555e98518215b788c8e7a73444985e4925951 Mon Sep 17 00:00:00 2001 From: momo5502 Date: Tue, 1 Apr 2025 18:37:00 +0200 Subject: [PATCH 19/20] Fix unicorn and switch back to it as default emulator --- src/unicorn-emulator/unicorn_x64_emulator.cpp | 2 +- src/windows-emulator/windows_emulator.cpp | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/unicorn-emulator/unicorn_x64_emulator.cpp b/src/unicorn-emulator/unicorn_x64_emulator.cpp index d286bd2e..029ad15e 100644 --- a/src/unicorn-emulator/unicorn_x64_emulator.cpp +++ b/src/unicorn-emulator/unicorn_x64_emulator.cpp @@ -307,7 +307,7 @@ namespace unicorn void load_gdt(const pointer_type address, const uint32_t limit) override { const std::array gdtr = {0, address, limit, 0}; - this->write_register(x64_register::gdtr, gdtr.data(), gdtr.size()); + this->write_register(x64_register::gdtr, gdtr.data(), gdtr.size() * sizeof(uint64_t)); } void set_segment_base(const x64_register base, const pointer_type value) override diff --git a/src/windows-emulator/windows_emulator.cpp b/src/windows-emulator/windows_emulator.cpp index dfc7f97d..4091053e 100644 --- a/src/windows-emulator/windows_emulator.cpp +++ b/src/windows-emulator/windows_emulator.cpp @@ -8,7 +8,6 @@ #include #include -#include #include #include "exception_dispatch.hpp" @@ -208,7 +207,7 @@ namespace std::unique_ptr create_default_x64_emulator() { - return icicle::create_x64_emulator(); + return unicorn::create_x64_emulator(); } windows_emulator::windows_emulator(application_settings app_settings, const emulator_settings& settings, From 1cdf280fcf0c8fee209f37bc835880471186218b Mon Sep 17 00:00:00 2001 From: momo5502 Date: Tue, 1 Apr 2025 18:49:41 +0200 Subject: [PATCH 20/20] Support disabling rust code --- CMakeLists.txt | 7 +------ README.md | 1 + cmake/compiler-env.cmake | 16 ++++++++++++++++ src/CMakeLists.txt | 7 +++++-- src/windows-emulator/CMakeLists.txt | 5 +++++ src/windows-emulator/windows_emulator.cpp | 3 +++ 6 files changed, 31 insertions(+), 8 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a4149da5..2168ae43 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,18 +4,13 @@ cmake_minimum_required(VERSION 3.26.4) option(MOMO_ENABLE_SANITIZER "Enable sanitizer" OFF) option(MOMO_ENABLE_CLANG_TIDY "Enable clang-tidy checks" OFF) +option(MOMO_ENABLE_RUST_CODE "Enable code parts written in rust" ON) option(MOMO_BUILD_AS_LIBRARY "Configure and Build the emulator as a shared library (without the samples and tests)" OFF) set(MOMO_REFLECTION_LEVEL "0" CACHE STRING "Reflection level for the build") message(STATUS "Reflection level is set to: ${MOMO_REFLECTION_LEVEL}") add_compile_definitions(MOMO_REFLECTION_LEVEL=${MOMO_REFLECTION_LEVEL}) -if(MOMO_BUILD_AS_LIBRARY) - add_compile_definitions(MOMO_BUILD_AS_LIBRARY=1) -else() - add_compile_definitions(MOMO_BUILD_AS_LIBRARY=0) -endif() - ########################################## set(CMAKE_DISABLE_IN_SOURCE_BUILD ON) diff --git a/README.md b/README.md index 8bd6d61f..b423ea97 100644 --- a/README.md +++ b/README.md @@ -51,6 +51,7 @@ Click + +#if MOMO_ENABLE_RUST_CODE #include +#endif #include #include