From d7d49b0c42f8b8b472c47f136eaa64e3dc34e143 Mon Sep 17 00:00:00 2001 From: Duncan Ogilvie Date: Sun, 13 Oct 2024 16:51:23 +0200 Subject: [PATCH 1/9] Fix deprecated PyO3 functions --- src/lib.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 2e892c2..6a9c8a0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -199,11 +199,11 @@ impl From for ExceptionCodePy { #[allow(non_snake_case)] fn raise_MemoryException(message: String, e: MemError) -> PyErr { Python::with_gil(|py| { - let icicle = py.import("icicle").unwrap(); + let icicle = py.import_bound("icicle").unwrap(); let exception = icicle.getattr("MemoryException").unwrap(); let args = (message, MemoryExceptionCode::from(e)); let inst = exception.call1(args).unwrap(); - PyErr::from_value(inst) + PyErr::from_value_bound(inst) }) } @@ -508,7 +508,7 @@ fn architectures() -> PyResult> { /// the `lib.name` setting in the `Cargo.toml`, else Python will not be able to /// import the module. #[pymodule] -fn icicle(_: Python<'_>, m: &PyModule) -> PyResult<()> { +fn icicle(m: &Bound<'_, PyModule>) -> PyResult<()> { m.add_function(wrap_pyfunction!(architectures, m)?)?; m.add_class::()?; m.add_class::()?; From 4083d9f4d4f0215f8efe718b2d043c383fd9ce2b Mon Sep 17 00:00:00 2001 From: Duncan Ogilvie Date: Sun, 13 Oct 2024 16:51:36 +0200 Subject: [PATCH 2/9] Disable shadow stack per default --- python/icicle/__init__.py | 2 +- src/lib.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/python/icicle/__init__.py b/python/icicle/__init__.py index 3e931e5..9ea7cb0 100644 --- a/python/icicle/__init__.py +++ b/python/icicle/__init__.py @@ -79,7 +79,7 @@ class Icicle: def __init__(self, architecture: str, *, jit = True, jit_mem = True, - shadow_stack = True, + shadow_stack = False, recompilation = True, track_uninitialized = False, optimize_instructions = True, diff --git a/src/lib.rs b/src/lib.rs index 6a9c8a0..a181847 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -274,7 +274,7 @@ impl Icicle { architecture, jit = true, jit_mem = true, - shadow_stack = true, + shadow_stack = false, recompilation = true, track_uninitialized = false, optimize_instructions = true, From a4874322d1a09d33f5fa557f08fa9faa2a6461b2 Mon Sep 17 00:00:00 2001 From: Duncan Ogilvie Date: Sun, 13 Oct 2024 16:52:09 +0200 Subject: [PATCH 3/9] Add Icicle.architecture property --- python/icicle/__init__.py | 3 +++ src/lib.rs | 9 ++++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/python/icicle/__init__.py b/python/icicle/__init__.py index 9ea7cb0..5e751a5 100644 --- a/python/icicle/__init__.py +++ b/python/icicle/__init__.py @@ -87,6 +87,9 @@ class Icicle: tracing = False, ) -> None: ... + @property + def architecture(self) -> str: ... + @property def exception_code(self) -> ExceptionCode: ... diff --git a/src/lib.rs b/src/lib.rs index a181847..b0a69f0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -220,6 +220,7 @@ fn convert_protection(protection: MemoryProtection) -> u8 { #[pyclass(unsendable, module = "icicle")] struct Icicle { + architecture: String, vm: icicle_vm::Vm, regs: HashMap, } @@ -269,6 +270,11 @@ impl Icicle { self.vm.cpu.exception.value } + #[getter] + fn get_architecture(&self) -> String { + self.architecture.to_string() + } + #[new] #[pyo3(signature = ( architecture, @@ -341,6 +347,7 @@ impl Icicle { } Ok(Icicle { + architecture, vm, regs, }) @@ -353,7 +360,7 @@ impl Icicle { } else { "little endian" }; - format!("Icicle VM for {0:?} ({endianness})", arch.triple.architecture) + format!("Icicle VM for {0:?} ({endianness})", self.architecture) } fn mem_map(&mut self, address: u64, size: u64, protection: MemoryProtection) -> PyResult<()> { From f4ef5aa9b27bfd351831714a2388139bc02ceb6a Mon Sep 17 00:00:00 2001 From: Duncan Ogilvie Date: Wed, 30 Oct 2024 00:17:37 +0100 Subject: [PATCH 4/9] Bump icicle-emu to the latest version --- Cargo.lock | 296 ++++++++++++++++++++++++++++++++--------------------- icicle-emu | 2 +- 2 files changed, 178 insertions(+), 120 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 10ef78e..5573dbb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,12 +1,12 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "addr2line" -version = "0.21.0" +version = "0.24.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" dependencies = [ "cpp_demangle", "fallible-iterator", @@ -15,6 +15,7 @@ dependencies = [ "object", "rustc-demangle", "smallvec", + "typed-arena", ] [[package]] @@ -30,17 +31,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" dependencies = [ "cfg-if", + "getrandom", "once_cell", "version_check", "zerocopy", ] -[[package]] -name = "allocator-api2" -version = "0.2.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" - [[package]] name = "anyhow" version = "1.0.86" @@ -59,6 +55,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +[[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" @@ -70,6 +72,9 @@ name = "bitflags" version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" +dependencies = [ + "serde", +] [[package]] name = "bstr" @@ -93,12 +98,6 @@ version = "1.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b236fc92302c97ed75b38da1f4917b5cdda4984745740f153a5d3059e48d725e" -[[package]] -name = "byteorder" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" - [[package]] name = "cfg-if" version = "1.0.0" @@ -116,31 +115,39 @@ dependencies = [ [[package]] name = "cranelift" -version = "0.107.2" +version = "0.113.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c31bcc3beea0c0bd94c3281ad625ed5a320380078014d15cb046c7bdd563dfb4" +checksum = "61fcb428a7799e67267ed1ea29d5903b87bec745f44c3decc5c621e97b9b7105" dependencies = [ "cranelift-codegen", "cranelift-frontend", + "cranelift-module", ] [[package]] name = "cranelift-bforest" -version = "0.107.2" +version = "0.113.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebf72ceaf38f7d41194d0cf6748214d8ef7389167fe09aad80f87646dbfa325b" +checksum = "8ea5e7afe85cadb55c4c1176268a2ac046fdff8dfaeca39e18581b9dc319ca9e" dependencies = [ "cranelift-entity", ] [[package]] -name = "cranelift-codegen" -version = "0.107.2" +name = "cranelift-bitset" +version = "0.113.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ee7fde5cd9173f00ce02c491ee9e306d64740f4b1a697946e0474f389999e13" +checksum = "8ab25ef3be935a80680e393183e1f94ef507e93a24a8369494d2c6818aedb3e3" + +[[package]] +name = "cranelift-codegen" +version = "0.113.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "900a19b84545924f1851cbfe386962edfc4ecbc3366a254825cf1ecbcda8ba08" dependencies = [ "bumpalo", "cranelift-bforest", + "cranelift-bitset", "cranelift-codegen-meta", "cranelift-codegen-shared", "cranelift-control", @@ -150,45 +157,49 @@ dependencies = [ "hashbrown 0.14.5", "log", "regalloc2", + "rustc-hash", "smallvec", "target-lexicon", ] [[package]] name = "cranelift-codegen-meta" -version = "0.107.2" +version = "0.113.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b49bec6a517e78d4067500dc16acb558e772491a2bcb37301127448adfb8413c" +checksum = "08c73b2395ffe9e7b4fdf7e2ebc052e7e27af13f68a964985346be4da477a5fc" dependencies = [ "cranelift-codegen-shared", ] [[package]] name = "cranelift-codegen-shared" -version = "0.107.2" +version = "0.113.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ead4ea497b2dc2ac31fcabd6d5d0d5dc25b3964814122e343724bdf65a53c843" +checksum = "7d9ed0854e96a4ff0879bff39d078de8dea7f002721c9494c1fdb4e1baa86ccc" [[package]] name = "cranelift-control" -version = "0.107.2" +version = "0.113.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f81e8028c8d711ea7592648e70221f2e54acb8665f7ecd49545f021ec14c3341" +checksum = "b4aca921dd422e781409de0129c255768fec5dec1dae83239b497fb9138abb89" dependencies = [ "arbitrary", ] [[package]] name = "cranelift-entity" -version = "0.107.2" +version = "0.113.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32acd0632ba65c2566e75f64af9ef094bb8d90e58a9fbd33d920977a9d85c054" +checksum = "e2d770e6605eccee15b49decdd82cd26f2b6404767802471459ea49c57379a98" +dependencies = [ + "cranelift-bitset", +] [[package]] name = "cranelift-frontend" -version = "0.107.2" +version = "0.113.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a395a704934aa944ba8939cac9001174b9ae5236f48bc091f89e33bb968336f6" +checksum = "29268711cb889cb39215b10faf88b9087d4c9e1d2633581e4f722a2bf4bb4ef9" dependencies = [ "cranelift-codegen", "log", @@ -198,15 +209,15 @@ dependencies = [ [[package]] name = "cranelift-isle" -version = "0.107.2" +version = "0.113.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b325ce81c4ee7082dc894537eb342c37898e14230fe7c02ea945691db3e2dd01" +checksum = "dc65156f010aed1985767ad1bff0eb8d186743b7b03e23d0c17604a253e3f356" [[package]] name = "cranelift-jit" -version = "0.107.2" +version = "0.113.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5840f54fc4b65854222339c834f3e01c329488cd12901c0dda8f69f82df6dcb2" +checksum = "40ba6b46367a4f466cfb1abe32793fa1a0f96d862251491b01a44726b8ed9445" dependencies = [ "anyhow", "cranelift-codegen", @@ -219,14 +230,14 @@ dependencies = [ "region", "target-lexicon", "wasmtime-jit-icache-coherence", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] name = "cranelift-module" -version = "0.107.2" +version = "0.113.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a86ed143dc1ba89a513fa8d9fb443c3e36fa9a2e5f64d7431765ea8f9e6f5c1" +checksum = "007607022a4883ebdffc46c0925e2e10babf2a565ae78518034ade722aa825d2" dependencies = [ "anyhow", "cranelift-codegen", @@ -235,9 +246,9 @@ dependencies = [ [[package]] name = "cranelift-native" -version = "0.107.2" +version = "0.113.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea11f5ac85996fa093075d66397922d4f56085d5d84ec13043d0cd4f159c6818" +checksum = "d8bf9b361eaf5a7627647270fabf1dc910d993edbeaf272a652c107861ebe9c2" dependencies = [ "cranelift-codegen", "libc", @@ -259,17 +270,6 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" -[[package]] -name = "derive_more" -version = "0.99.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "equivalent" version = "1.0.1" @@ -303,10 +303,27 @@ dependencies = [ ] [[package]] -name = "gimli" -version = "0.28.1" +name = "foldhash" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" +checksum = "f81ec6369c545a7d40e4589b5597581fa1c441fe1cce96dd1de43159910a36a2" + +[[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", @@ -325,21 +342,20 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.13.2" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" dependencies = [ "ahash", ] [[package]] name = "hashbrown" -version = "0.14.5" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" +checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" dependencies = [ - "ahash", - "allocator-api2", + "foldhash", ] [[package]] @@ -353,10 +369,12 @@ name = "icicle-cpu" version = "0.1.0" dependencies = [ "addr2line", + "ahash", + "anyhow", "bitflags 2.5.0", "bytemuck", + "gimli", "half", - "hashbrown 0.14.5", "icicle-mem", "object", "pcode", @@ -428,8 +446,10 @@ dependencies = [ "icicle-cpu", "icicle-jit", "icicle-linux", + "ihex", "object", "pcode", + "ron", "serde", "serde-xml-rs", "sleigh-compile", @@ -438,6 +458,12 @@ dependencies = [ "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.2.6" @@ -492,10 +518,10 @@ dependencies = [ ] [[package]] -name = "mach" -version = "0.3.2" +name = "mach2" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b823e83b2affd8f40a9ee8c29dbc56404c1e34cd2710921f2801e2cf29527afa" +checksum = "19b955cdeb2a02b9117f121ce63aa52d08ade45de53e48fe6a38b39c10f6f709" dependencies = [ "libc", ] @@ -508,9 +534,9 @@ checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "memmap2" -version = "0.5.10" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83faa42c0a078c393f6b29d5db232d8be22776a891f8f56e5284faee4a20b327" +checksum = "fd3f7eed9d3848f8b98834af67102b720745c4ec028fcd0aa0239277e7de374f" dependencies = [ "libc", ] @@ -545,13 +571,13 @@ dependencies = [ [[package]] name = "object" -version = "0.32.2" +version = "0.36.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +checksum = "aedf0a2d09c573ed1d8d85b30c119153926a2b36dce0ab28322c09a117a4683e" dependencies = [ "crc32fast", "flate2", - "hashbrown 0.14.5", + "hashbrown 0.15.0", "indexmap", "memchr", "ruzstd", @@ -701,11 +727,11 @@ dependencies = [ [[package]] name = "regalloc2" -version = "0.9.3" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad156d539c879b7a24a363a2016d77961786e71f48f2e2fc8302a92abd2429a6" +checksum = "12908dbeb234370af84d0579b9f68258a0f67e201412dd9a2814e6f45b2fc0f0" dependencies = [ - "hashbrown 0.13.2", + "hashbrown 0.14.5", "log", "rustc-hash", "slice-group-by", @@ -714,14 +740,26 @@ dependencies = [ [[package]] name = "region" -version = "2.2.0" +version = "3.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "877e54ea2adcd70d80e9179344c97f93ef0dffd6b03e1f4529e6e83ab2fa9ae0" +checksum = "e6b6ebd13bc009aef9cd476c1310d49ac354d36e240cf1bd753290f3dc7199a7" dependencies = [ "bitflags 1.3.2", "libc", - "mach", - "winapi", + "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.5.0", + "serde", + "serde_derive", ] [[package]] @@ -732,9 +770,9 @@ checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" [[package]] name = "rustc-hash" -version = "1.1.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" +checksum = "583034fd73374156e66797ed8e5b0d5690409c9226b22d87cb7f19821c05d152" [[package]] name = "rustix" @@ -751,12 +789,10 @@ dependencies = [ [[package]] name = "ruzstd" -version = "0.5.0" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58c4eb8a81997cf040a091d1f7e1938aeab6749d3a0dfa73af43cdc32393483d" +checksum = "99c3938e133aac070997ddc684d4b393777d293ba170f2988c8fd5ea2ad4ce21" dependencies = [ - "byteorder", - "derive_more", "twox-hash", ] @@ -868,9 +904,9 @@ dependencies = [ [[package]] name = "target-lexicon" -version = "0.12.14" +version = "0.12.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1fc403891a21bcfb7c37834ba66a547a8f402146eba7265b5a6d88059c9ff2f" +checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" [[package]] name = "thiserror" @@ -969,6 +1005,12 @@ dependencies = [ "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.9" @@ -994,10 +1036,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] -name = "wasmtime-jit-debug" -version = "19.0.2" +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92de34217bf7f0464262adf391a9950eba440f9dfc7d3b0e3209302875c6f65f" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasmtime-jit-debug" +version = "26.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "077d8382176594ded9e7d837db2f320b45915d40b99f4319b2bd1061bbdf5f4f" dependencies = [ "object", "rustix", @@ -1006,20 +1054,21 @@ dependencies = [ [[package]] name = "wasmtime-jit-icache-coherence" -version = "20.0.2" +version = "26.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ede45379f3b4d395d8947006de8043801806099a240a26db553919b68e96ab15" +checksum = "6e458e6a1a010a53f86ac8d75837c0c6b2ce3e54b7503b2f1dc5629a4a541f5a" dependencies = [ + "anyhow", "cfg-if", "libc", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] name = "wasmtime-versioned-export-macros" -version = "19.0.2" +version = "26.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffaafa5c12355b1a9ee068e9295d50c4ca0a400c721950cdae4f5b54391a2da5" +checksum = "abe01058e422966659e1af00af833147d54658b07c7e74606d73ca9af3f1690a" dependencies = [ "proc-macro2", "quote", @@ -1063,7 +1112,16 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.5", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", ] [[package]] @@ -1083,18 +1141,18 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm 0.52.5", - "windows_aarch64_msvc 0.52.5", - "windows_i686_gnu 0.52.5", + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", "windows_i686_gnullvm", - "windows_i686_msvc 0.52.5", - "windows_x86_64_gnu 0.52.5", - "windows_x86_64_gnullvm 0.52.5", - "windows_x86_64_msvc 0.52.5", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", ] [[package]] @@ -1105,9 +1163,9 @@ checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_msvc" @@ -1117,9 +1175,9 @@ checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" [[package]] name = "windows_aarch64_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_i686_gnu" @@ -1129,15 +1187,15 @@ checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" [[package]] name = "windows_i686_gnu" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" [[package]] name = "windows_i686_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_msvc" @@ -1147,9 +1205,9 @@ checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" [[package]] name = "windows_i686_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_x86_64_gnu" @@ -1159,9 +1217,9 @@ checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" [[package]] name = "windows_x86_64_gnu" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnullvm" @@ -1171,9 +1229,9 @@ checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_msvc" @@ -1183,9 +1241,9 @@ checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" [[package]] name = "windows_x86_64_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "xml-rs" diff --git a/icicle-emu b/icicle-emu index 0acbf76..964dabb 160000 --- a/icicle-emu +++ b/icicle-emu @@ -1 +1 @@ -Subproject commit 0acbf76a49d01c14bb10eef66a8661ae1d9d70d7 +Subproject commit 964dabb7276b959d225556ae11a5634f60266611 From 5e8b3160804484eb0b9cdfa961d19f3882bb409c Mon Sep 17 00:00:00 2001 From: Duncan Ogilvie Date: Fri, 29 Nov 2024 22:03:58 +0100 Subject: [PATCH 5/9] Use Icicle from src/lib in src/main --- src/lib.rs | 69 ++++++----- src/main.rs | 351 +++++++--------------------------------------------- 2 files changed, 80 insertions(+), 340 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index b0a69f0..12955b5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -15,8 +15,8 @@ use sleigh_runtime::NamedRegister; // - https://pyo3.rs/main/class #[pyclass(module = "icicle")] -#[derive(Clone)] -enum MemoryProtection { +#[derive(Clone, Debug, PartialEq)] +pub enum MemoryProtection { NoAccess, ReadOnly, ReadWrite, @@ -26,8 +26,8 @@ enum MemoryProtection { } #[pyclass(module = "icicle")] -#[derive(Clone)] -enum RunStatus { +#[derive(Clone, Debug, PartialEq)] +pub enum RunStatus { /// The VM is still running. Running, @@ -60,7 +60,8 @@ enum RunStatus { } #[pyclass(module = "icicle")] -enum MemoryExceptionCode { +#[derive(Clone, Debug, PartialEq)] +pub enum MemoryExceptionCode { Unallocated, Unmapped, UnmappedRegister, @@ -99,8 +100,8 @@ impl From for MemoryExceptionCode { } #[pyclass(module = "icicle", name = "ExceptionCode")] -#[derive(Clone)] -enum ExceptionCodePy { +#[derive(Clone, Debug, PartialEq)] +pub enum ExceptionCodePy { NoException = 0x0000, InstructionLimit = 0x0001, @@ -219,7 +220,7 @@ fn convert_protection(protection: MemoryProtection) -> u8 { } #[pyclass(unsendable, module = "icicle")] -struct Icicle { +pub struct Icicle { architecture: String, vm: icicle_vm::Vm, regs: HashMap, @@ -241,37 +242,37 @@ fn reg_find<'a>(i: &'a Icicle, name: &str) -> PyResult<&'a NamedRegister> { #[pymethods] impl Icicle { #[getter] - fn get_icount_limit(&mut self) -> u64 { + pub fn get_icount_limit(&mut self) -> u64 { self.vm.icount_limit } #[setter] - fn set_icount_limit(&mut self, value: u64) { + pub fn set_icount_limit(&mut self, value: u64) { self.vm.icount_limit = value; } #[getter] - fn get_icount(&mut self) -> u64 { + pub fn get_icount(&mut self) -> u64 { return self.vm.cpu.icount; } #[setter] - fn set_icount(&mut self, value: u64) { + pub fn set_icount(&mut self, value: u64) { self.vm.cpu.icount = value; } #[getter] - fn get_exception_code(&self) -> ExceptionCodePy { + pub fn get_exception_code(&self) -> ExceptionCodePy { ExceptionCode::from_u32(self.vm.cpu.exception.code).into() } #[getter] - fn get_exception_value(&self) -> u64 { + pub fn get_exception_value(&self) -> u64 { self.vm.cpu.exception.value } #[getter] - fn get_architecture(&self) -> String { + pub fn get_architecture(&self) -> String { self.architecture.to_string() } @@ -287,7 +288,7 @@ impl Icicle { optimize_block = true, tracing = false, ))] - fn new( + pub fn new( architecture: String, jit: bool, jit_mem: bool, @@ -353,7 +354,7 @@ impl Icicle { }) } - fn __str__(&mut self) -> String { + pub fn __str__(&mut self) -> String { let arch = &self.vm.cpu.arch; let endianness = if arch.sleigh.big_endian { "big endian" @@ -363,7 +364,7 @@ impl Icicle { format!("Icicle VM for {0:?} ({endianness})", self.architecture) } - fn mem_map(&mut self, address: u64, size: u64, protection: MemoryProtection) -> PyResult<()> { + pub fn mem_map(&mut self, address: u64, size: u64, protection: MemoryProtection) -> PyResult<()> { let mapping = Mapping { perm: convert_protection(protection), value: 0, @@ -380,7 +381,7 @@ impl Icicle { } } - fn mem_unmap(&mut self, address: u64, size: u64) -> PyResult<()> { + pub fn mem_unmap(&mut self, address: u64, size: u64) -> PyResult<()> { if self.vm.cpu.mem.unmap_memory_len(address, size) { Ok(()) } else { @@ -393,7 +394,7 @@ impl Icicle { } } - fn mem_protect(&mut self, address: u64, size: usize, protection: MemoryProtection) -> PyResult<()> { + pub fn mem_protect(&mut self, address: u64, size: usize, protection: MemoryProtection) -> PyResult<()> { self.vm.cpu.mem.update_perm(address, size as u64, convert_protection(protection)) .map_err(|e| { raise_MemoryException( @@ -404,7 +405,7 @@ impl Icicle { Ok(()) } - fn mem_read(&mut self, address: u64, size: usize) -> PyResult> { + pub fn mem_read(&mut self, address: u64, size: usize) -> PyResult> { // Allocate a buffer let mut buffer = Vec::with_capacity(size); buffer.resize(size, 0); @@ -420,7 +421,7 @@ impl Icicle { return Ok(Cow::Owned(buffer)); } - fn mem_write(&mut self, address: u64, data: Vec) -> PyResult<()> { + pub fn mem_write(&mut self, address: u64, data: Vec) -> PyResult<()> { let size = data.len(); self.vm.cpu.mem.write_bytes(address, &data[..], perm::NONE) .map_err(|e| { @@ -431,7 +432,7 @@ impl Icicle { }) } - fn reg_list(&self) -> PyResult> { + pub fn reg_list(&self) -> PyResult> { let mut result = IndexMap::new(); let sleigh = self.vm.cpu.sleigh(); for reg in &sleigh.named_registers { @@ -441,27 +442,27 @@ impl Icicle { return Ok(result); } - fn reg_offset(&self, name: &str) -> PyResult { + pub fn reg_offset(&self, name: &str) -> PyResult { Ok(reg_find(self, name)?.offset) } - fn reg_size(&self, name: &str) -> PyResult { + pub fn reg_size(&self, name: &str) -> PyResult { Ok(reg_find(self, name)?.var.size) } - fn reg_read(&mut self, name: &str) -> PyResult { + pub fn reg_read(&mut self, name: &str) -> PyResult { Ok(self.vm.cpu.read_reg(reg_find(self, name)?.var)) } - fn reg_write(&mut self, name: &str, value: u64) -> PyResult<()> { + pub fn reg_write(&mut self, name: &str, value: u64) -> PyResult<()> { Ok(self.vm.cpu.write_reg(reg_find(self, name)?.var, value)) } - fn reset(&mut self) { + pub fn reset(&mut self) { self.vm.reset(); } - fn run(&mut self) -> RunStatus { + pub fn run(&mut self) -> RunStatus { match self.vm.run() { VmExit::Running => RunStatus::Running, VmExit::InstructionLimit => RunStatus::InstructionLimit, @@ -476,7 +477,7 @@ impl Icicle { } } - fn run_until(&mut self, address: u64) -> RunStatus { + pub fn run_until(&mut self, address: u64) -> RunStatus { let breakpoint_added = self.vm.add_breakpoint(address); let status = self.run(); if breakpoint_added { @@ -485,7 +486,7 @@ impl Icicle { status } - fn step(&mut self, count: u64) -> RunStatus { + pub fn step(&mut self, count: u64) -> RunStatus { let old_limit = self.vm.icount_limit; self.vm.icount_limit = self.vm.cpu.icount.saturating_add(count); let status = self.run(); @@ -493,17 +494,17 @@ impl Icicle { status } - fn add_breakpoint(&mut self, address: u64) -> bool { + pub fn add_breakpoint(&mut self, address: u64) -> bool { self.vm.add_breakpoint(address) } - fn remove_breakpoint(&mut self, address: u64) -> bool { + pub fn remove_breakpoint(&mut self, address: u64) -> bool { self.vm.remove_breakpoint(address) } } #[pyfunction] -fn architectures() -> PyResult> { +pub fn architectures() -> PyResult> { Ok(vec![ "i686", "x86_64", diff --git a/src/main.rs b/src/main.rs index 47b26c1..d9831d5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,281 +1,11 @@ -use std::borrow::Cow; -use std::collections::HashMap; -use icicle_cpu::mem::{Mapping, perm}; -use icicle_cpu::{VmExit}; -use icicle_vm; -use icicle_vm::linux::LinuxCpu; -use target_lexicon; -use indexmap::IndexMap; -use sleigh_runtime::NamedRegister; +#![allow(special_module_name)] +mod lib; -#[allow(dead_code)] -#[derive(Clone)] -enum MemoryProtection { - NoAccess, - ReadOnly, - ReadWrite, - ExecuteOnly, - ExecuteRead, - ExecuteReadWrite, -} +use lib::*; +use pyo3::PyResult; -struct Icicle { - vm: icicle_vm::Vm, - regs: HashMap, -} - -fn convert_protection(protection: MemoryProtection) -> u8 { - match protection { - MemoryProtection::NoAccess => perm::NONE, - MemoryProtection::ReadOnly => perm::READ, - MemoryProtection::ReadWrite => perm::READ | perm::WRITE, - MemoryProtection::ExecuteOnly => perm::EXEC, - MemoryProtection::ExecuteRead => perm::EXEC | perm::READ, - MemoryProtection::ExecuteReadWrite => perm::EXEC | perm::READ | perm::WRITE, - } -} - -fn reg_find<'a>(i: &'a Icicle, name: &str) -> Result<&'a NamedRegister, String> { - let sleigh = i.vm.cpu.sleigh(); - match sleigh.get_reg(name) { - None => { - i.regs.get(name.to_lowercase().as_str()) - .ok_or( - format!("Register not found: {name}") - ) - } - Some(r) => Ok(r), - } -} - -impl Icicle { - #[allow(dead_code)] - fn get_icount_limit(&mut self) -> u64 { - self.vm.icount_limit - } - - #[allow(dead_code)] - fn set_icount_limit(&mut self, value: u64) { - self.vm.icount_limit = value; - } - - #[allow(dead_code)] - fn get_icount(&mut self) -> u64 { - return self.vm.cpu.icount; - } - - #[allow(dead_code)] - fn set_icount(&mut self, value: u64) { - self.vm.cpu.icount = value; - } - - fn new( - architecture: String, - jit: bool, - jit_mem: bool, - shadow_stack: bool, - recompilation: bool, - track_uninitialized: bool, - optimize_instructions: bool, - optimize_block: bool, - tracing: bool, - ) -> Result { - // Prevent mixing '_' and '-' - if architecture.split("-").count() != 1 { - return Err( - format!("Bad architecture format: {architecture}") - ); - } - - // TODO: support instantiating this multiple times - if tracing { - tracing_subscriber::fmt() - .with_max_level(tracing::Level::DEBUG) - .with_target(false) - .init(); - } - - // Setup the CPU state for the target triple - let mut config = icicle_vm::cpu::Config::from_target_triple( - format!("{architecture}-none").as_str() - ); - if config.triple.architecture == target_lexicon::Architecture::Unknown { - return Err( - format!("Unknown architecture: {architecture}") - ); - } - - // Configuration - config.enable_jit = jit; - config.enable_jit_mem = jit_mem; - config.enable_shadow_stack = shadow_stack; - config.enable_recompilation = recompilation; - config.track_uninitialized = track_uninitialized; - config.optimize_instructions = optimize_instructions; - config.optimize_block = optimize_block; - - let vm = icicle_vm::build(&config) - .map_err(|e| { - format!("VM build error: {e}") - })?; - - // Populate the lowercase register map - let mut regs = HashMap::new(); - let sleigh = vm.cpu.sleigh(); - for reg in &sleigh.named_registers { - let name = sleigh.get_str(reg.name); - regs.insert(name.to_lowercase(), reg.clone()); - } - - Ok(Icicle { - vm, - regs, - }) - } - - fn __str__(&mut self) -> String { - let arch = &self.vm.cpu.arch; - let endianness = if arch.sleigh.big_endian { - "big endian" - } else { - "little endian" - }; - format!("Icicle VM for {0:?} ({endianness})", arch.triple.architecture) - } - - fn mem_map(&mut self, address: u64, size: u64, protection: MemoryProtection) -> Result<(), String> { - let mapping = Mapping { - perm: convert_protection(protection), - value: 0, - }; - if self.vm.cpu.mem.map_memory_len(address, size, mapping) { - Ok(()) - } else { - Err( - format!("Failed to map memory {address:X}[{size:X}]") - ) - } - } - - #[allow(dead_code)] - fn mem_unmap(&mut self, address: u64, size: u64) -> Result<(), String> { - if self.vm.cpu.mem.unmap_memory_len(address, size) { - Ok(()) - } else { - Err( - format!("Failed to unmap memory {address:X}[{size:X}]") - ) - } - } - - fn mem_protect(&mut self, address: u64, size: usize, protection: MemoryProtection) -> Result<(), String> { - self.vm.cpu.mem.update_perm(address, size as u64, convert_protection(protection)) - .map_err(|_| { - format!("Failed to protect memory {address:X}[{size:X}]") - })?; - Ok(()) - } - - #[allow(dead_code)] - fn mem_read(&mut self, address: u64, size: usize) -> Result, String> { - // Allocate a buffer - let mut buffer = Vec::with_capacity(size); - buffer.resize(size, 0); - - // Read the memory - match self.vm.cpu.mem.read_bytes(address, &mut buffer[..], perm::NONE) { - Ok(_) => Ok(Cow::Owned(buffer)), - Err(_) => Err(format!("Failed to read memory {address:X}[{size:X}]")) - } - } - - fn mem_write(&mut self, address: u64, data: Vec) -> Result<(), String> { - let size = data.len(); - match self.vm.cpu.mem.write_bytes(address, &data[..], perm::NONE) { - Ok(_) => Ok(()), - Err(_) => Err(format!("Failed to write memory {address:X}[{size:X}]")) - } - } - - #[allow(dead_code)] - fn reg_list(&self) -> IndexMap { - let mut result = IndexMap::new(); - let sleigh = self.vm.cpu.sleigh(); - for reg in &sleigh.named_registers { - let name = sleigh.get_str(reg.name); - result.insert(name.to_string(), (reg.offset, reg.var.size)); - } - return result; - } - - #[allow(dead_code)] - fn reg_offset(&self, name: &str) -> Result { - Ok(reg_find(self, name)?.offset) - } - - #[allow(dead_code)] - fn reg_size(&self, name: &str) -> Result { - Ok(reg_find(self, name)?.var.size) - } - - fn reg_read(&mut self, name: &str) -> Result { - Ok(self.vm.cpu.read_reg(reg_find(self, name)?.var)) - } - - fn reg_write(&mut self, name: &str, value: u64) -> Result<(), String> { - Ok(self.vm.cpu.write_reg(reg_find(self, name)?.var, value)) - } - - #[allow(dead_code)] - fn reset(&mut self) { - self.vm.reset(); - } - - fn run(&mut self) -> VmExit { - self.vm.run() - } - - #[allow(dead_code)] - fn run_until(&mut self, address: u64) -> VmExit { - let breakpoint_added = self.vm.add_breakpoint(address); - let status = self.run(); - if breakpoint_added { - self.vm.remove_breakpoint(address); - } - status - } - - #[allow(dead_code)] - fn step(&mut self, count: u64) -> VmExit { - let old_limit = self.vm.icount_limit; - self.vm.icount_limit = self.vm.cpu.icount.saturating_add(count); - let status = self.run(); - self.vm.icount_limit = old_limit; - status - } - - #[allow(dead_code)] - fn add_breakpoint(&mut self, address: u64) -> bool { - self.vm.add_breakpoint(address) - } - - #[allow(dead_code)] - fn remove_breakpoint(&mut self, address: u64) -> bool { - self.vm.remove_breakpoint(address) - } -} - -#[allow(dead_code)] -fn architectures() -> Result, String> { - Ok(vec![ - "i686", - "x86_64", - "aarch64", - ]) -} - -fn nx_start() { - let mut vm = Icicle::new( +fn nx_start() -> PyResult<()> { + let mut vm: Icicle = Icicle::new( "x86_64".to_string(), false, true, @@ -285,19 +15,21 @@ fn nx_start() { true, true, false, - ).unwrap(); + )?; let page = 0x10000; - vm.mem_map(page, 0x1000, MemoryProtection::ReadOnly).unwrap(); + vm.mem_map(page, 0x1000, MemoryProtection::ReadOnly)?; // inc eax; ret - vm.mem_write(page, b"\xFF\xC0\xC3".to_vec()).unwrap(); - vm.reg_write("rip", page).unwrap(); + vm.mem_write(page, b"\xFF\xC0\xC3".to_vec())?; + vm.reg_write("rip", page)?; let status = vm.run(); println!("status: {:?}", status); - println!("rip: {:#x}", vm.reg_read("rip").unwrap()); + println!("rip: {:#x}", vm.reg_read("rip")?); + + Ok(()) } -fn nx_middle() { - let mut vm = Icicle::new( +fn nx_middle() -> PyResult<()> { + let mut vm: Icicle = Icicle::new( "x86_64".to_string(), false, true, @@ -307,22 +39,24 @@ fn nx_middle() { true, true, false, - ).unwrap(); + )?; let page = 0x10000; - vm.mem_map(page, 0x2000, MemoryProtection::ExecuteRead).unwrap(); - vm.mem_protect(page + 0x1000, 0x1000, MemoryProtection::ReadOnly).unwrap(); + vm.mem_map(page, 0x2000, MemoryProtection::ExecuteRead)?; + vm.mem_protect(page + 0x1000, 0x1000, MemoryProtection::ReadOnly)?; // inc eax; inc eax; ; ret let rip = page + 0x1000 - 2; - vm.mem_write(rip, b"\xFF\xC0\xFF\xC0\xC3".to_vec()).unwrap(); - vm.reg_write("rip", rip).unwrap(); + vm.mem_write(rip, b"\xFF\xC0\xFF\xC0\xC3".to_vec())?; + vm.reg_write("rip", rip)?; let status = vm.run(); println!("status: {:?}", status); - println!("rip: {:#x}", vm.reg_read("rip").unwrap()); - println!("rax: {:#x}", vm.reg_read("rax").unwrap()); + println!("rip: {:#x}", vm.reg_read("rip")?); + println!("rax: {:#x}", vm.reg_read("rax")?); + + Ok(()) } -fn inv_start() { - let mut vm = Icicle::new( +fn inv_start() -> PyResult<()> { + let mut vm: Icicle = Icicle::new( "x86_64".to_string(), false, true, @@ -332,20 +66,22 @@ fn inv_start() { true, true, false, - ).unwrap(); + )?; let page = 0x10000; - vm.mem_map(page, 0x1000, MemoryProtection::ExecuteRead).unwrap(); + vm.mem_map(page, 0x1000, MemoryProtection::ExecuteRead)?; // ; ret - vm.mem_write(page, b"\xFF\xFF\xC3".to_vec()).unwrap(); - vm.reg_write("rip", page).unwrap(); + vm.mem_write(page, b"\xFF\xFF\xC3".to_vec())?; + vm.reg_write("rip", page)?; let status = vm.run(); println!("status: {:?}", status); - println!("rip: {:#x}", vm.reg_read("rip").unwrap()); - println!("rax: {:#x}", vm.reg_read("rax").unwrap()); + println!("rip: {:#x}", vm.reg_read("rip")?); + println!("rax: {:#x}", vm.reg_read("rax")?); + + Ok(()) } -fn inv_middle() { - let mut vm = Icicle::new( +fn inv_middle() -> PyResult<()> { + let mut vm: Icicle = Icicle::new( "x86_64".to_string(), false, true, @@ -355,19 +91,22 @@ fn inv_middle() { true, true, false, - ).unwrap(); + )?; let page = 0x10000; - vm.mem_map(page, 0x1000, MemoryProtection::ExecuteRead).unwrap(); + vm.mem_map(page, 0x1000, MemoryProtection::ExecuteRead)?; // inc eax; ; ret - vm.mem_write(page, b"\xFF\xC0\xFF\xFF\xC3".to_vec()).unwrap(); - vm.reg_write("rip", page).unwrap(); + vm.mem_write(page, b"\xFF\xC0\xFF\xFF\xC3".to_vec())?; + vm.reg_write("rip", page)?; let status = vm.run(); println!("status: {:?}", status); - println!("rip: {:#x}", vm.reg_read("rip").unwrap()); - println!("rax: {:#x}", vm.reg_read("rax").unwrap()); + println!("rip: {:#x}", vm.reg_read("rip")?); + println!("rax: {:#x}", vm.reg_read("rax")?); + + Ok(()) } fn main() { + #![allow(unused_must_use)] println!("=== NX (block start) ==="); nx_start(); println!("=== NX (block middle) ==="); From f8b119ebf2780f3e63b0b0dc96783b7a626ea399 Mon Sep 17 00:00:00 2001 From: Duncan Ogilvie Date: Fri, 29 Nov 2024 22:23:14 +0100 Subject: [PATCH 6/9] Add reproduction for block optimization bug --- src/main.rs | 55 +++++++++++++++++++++++++++++++++++++++++++++++ tests/blockopt.py | 36 +++++++++++++++++++++++++++++++ 2 files changed, 91 insertions(+) create mode 100644 tests/blockopt.py diff --git a/src/main.rs b/src/main.rs index d9831d5..7494784 100644 --- a/src/main.rs +++ b/src/main.rs @@ -105,6 +105,59 @@ fn inv_middle() -> PyResult<()> { Ok(()) } +fn block_optimization() -> PyResult<()> { + let mut vm: Icicle = Icicle::new( + "x86_64".to_string(), // architecture + true, // jit + true, // jit_mem + true, // shadow_stack + true, // recompilation + false, // track_uninitialized + true, // optimize_instructions + true, // optimize_block + false, // tracing + )?; + + // Memory setup + let addr: u64 = 0x140001A73; + let heap: u64 = 0x71000; + vm.mem_map(heap, 0x1000, MemoryProtection::ReadWrite)?; + vm.mem_write(heap + 4, b"\x37\x13\x00\x00".to_vec())?; + vm.mem_map(addr & !0xFFF, 0x1000, MemoryProtection::ExecuteRead)?; + vm.mem_write(addr, b"\x41\xc1\xea\x07\x41\x83\xe2\x1f\x74\x08\x44\x89\xd0\x48\x89\x54\xc6\x08\x49\x83\xc1\x04\x4c\x89\x0e\x4c\x89\xc9\x44\x8b\x11\x44\x89\xd0\xf7\xd0\x49\x89\xc9\xa8\x03\x0f\x84\x88\xf6\xff\xff\xeb\x4c".to_vec())?; + + // Register setup + vm.reg_write("r9", heap)?; + vm.reg_write("r10", 0x13)?; + vm.reg_write("rip", addr)?; + vm.reg_write("rsi", heap + 0x100)?; + + // Step through instructions + for i in 0..11 { + let rip = vm.reg_read("rip")?; + let rcx = vm.reg_read("rcx")?; + let r9 = vm.reg_read("r9")?; + + println!("[{}] RIP: {:#x}, RCX: {:#x}, R9: {:#x}", i, rip, rcx, r9); + + if rip == 0x140001A8F { + vm.reg_write("r9", 0x13370900)?; + } + + vm.step(1); + + if rip == 0x140001A9A { + if rcx != r9 { + println!("[BUG] expected rcx({:#x}) == r9({:#x})", rcx, r9); + } else { + println!("Everything works!"); + } + } + } + + Ok(()) +} + fn main() { #![allow(unused_must_use)] println!("=== NX (block start) ==="); @@ -115,4 +168,6 @@ fn main() { inv_start(); println!("=== Invalid instruction (block middle) ==="); inv_middle(); + println!("=== Block optimization bug ==="); + block_optimization(); } diff --git a/tests/blockopt.py b/tests/blockopt.py new file mode 100644 index 0000000..bbce235 --- /dev/null +++ b/tests/blockopt.py @@ -0,0 +1,36 @@ +from icicle import * + +def main(): + emu = Icicle("x86_64", jit=True, optimize_block=True, tracing=True) + + instructions = bytes.fromhex("41 C1 EA 07 41 83 E2 1F 74 08 44 89 D0 48 89 54 C6 08 49 83 C1 04 4C 89 0E 4C 89 C9 44 8B 11 44 89 D0 F7 D0 49 89 C9 A8 03 0F 84 88 F6 FF FF EB 4C".replace(" ", "")) + + addr = 0x140001A73 + heap = 0x71000 + emu.mem_map(heap, 0x1000, MemoryProtection.ReadWrite) + emu.mem_write(heap + 4, 0x1337.to_bytes(4, "little")) + emu.mem_map(addr & ~0xFFF, 0x1000, MemoryProtection.ExecuteRead) + emu.mem_write(addr, instructions) + emu.reg_write("r9", heap) + emu.reg_write("r10", 0x13) + emu.reg_write("rip", addr) + emu.reg_write("rsi", heap + 0x100) + + for i in range(11): + rip = emu.reg_read("rip") + rcx = emu.reg_read("rcx") + r9 = emu.reg_read("r9") + print(f"[{i}] RIP: {hex(rip)}, RCX: {hex(rcx)}, R9: {hex(r9)}") + + if rip == 0x140001A8F: + emu.reg_write("r9", 0x13370900) + + emu.step(1) + + if rip == 0x140001A9A: + assert rcx == r9, f"expected rcx({hex(rcx)}) == r9({hex(r9)})" + + print("Everything works!") + +if __name__ == "__main__": + main() \ No newline at end of file From e749fe1571c1164ddf406fd76c34e6ebcce2a50c Mon Sep 17 00:00:00 2001 From: Duncan Ogilvie Date: Fri, 29 Nov 2024 22:45:03 +0100 Subject: [PATCH 7/9] Disable optimize_block per default --- python/icicle/__init__.py | 2 +- src/lib.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/python/icicle/__init__.py b/python/icicle/__init__.py index 5e751a5..754e753 100644 --- a/python/icicle/__init__.py +++ b/python/icicle/__init__.py @@ -83,7 +83,7 @@ class Icicle: recompilation = True, track_uninitialized = False, optimize_instructions = True, - optimize_block = True, + optimize_block = False, tracing = False, ) -> None: ... diff --git a/src/lib.rs b/src/lib.rs index 12955b5..de1c6b5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -285,7 +285,7 @@ impl Icicle { recompilation = true, track_uninitialized = false, optimize_instructions = true, - optimize_block = true, + optimize_block = false, tracing = false, ))] pub fn new( From c4a1c18f0471a58643128cb8715bdc702b39c476 Mon Sep 17 00:00:00 2001 From: Duncan Ogilvie Date: Fri, 29 Nov 2024 23:06:35 +0100 Subject: [PATCH 8/9] Bump pyo3 to 0.23.2 --- Cargo.lock | 164 ++++++++--------------------------------------------- Cargo.toml | 4 +- src/lib.rs | 12 ++-- 3 files changed, 33 insertions(+), 147 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5573dbb..6246153 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -360,9 +360,9 @@ dependencies = [ [[package]] name = "heck" -version = "0.4.1" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "icicle-cpu" @@ -466,12 +466,12 @@ checksum = "365a784774bb381e8c19edb91190a90d7f2625e057b55de2bc0f6b57bc779ff2" [[package]] name = "indexmap" -version = "2.2.6" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" +checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" dependencies = [ "equivalent", - "hashbrown 0.14.5", + "hashbrown 0.15.0", ] [[package]] @@ -498,16 +498,6 @@ version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" -[[package]] -name = "lock_api" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" -dependencies = [ - "autocfg", - "scopeguard", -] - [[package]] name = "log" version = "0.4.17" @@ -595,29 +585,6 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" -[[package]] -name = "parking_lot" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" -dependencies = [ - "lock_api", - "parking_lot_core", -] - -[[package]] -name = "parking_lot_core" -version = "0.9.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521" -dependencies = [ - "cfg-if", - "libc", - "redox_syscall", - "smallvec", - "windows-sys 0.45.0", -] - [[package]] name = "pcode" version = "0.2.0" @@ -645,16 +612,16 @@ dependencies = [ [[package]] name = "pyo3" -version = "0.21.2" +version = "0.23.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5e00b96a521718e08e03b1a622f01c8a8deb50719335de3f60b3b3950f069d8" +checksum = "f54b3d09cbdd1f8c20650b28e7b09e338881482f4aa908a5f61a00c98fba2690" dependencies = [ "cfg-if", "indexmap", "indoc", "libc", "memoffset", - "parking_lot", + "once_cell", "portable-atomic", "pyo3-build-config", "pyo3-ffi", @@ -664,9 +631,9 @@ dependencies = [ [[package]] name = "pyo3-build-config" -version = "0.21.2" +version = "0.23.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7883df5835fafdad87c0d888b266c8ec0f4c9ca48a5bed6bbb592e8dedee1b50" +checksum = "3015cf985888fe66cfb63ce0e321c603706cd541b7aec7ddd35c281390af45d8" dependencies = [ "once_cell", "target-lexicon", @@ -674,9 +641,9 @@ dependencies = [ [[package]] name = "pyo3-ffi" -version = "0.21.2" +version = "0.23.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01be5843dc60b916ab4dad1dca6d20b9b4e6ddc8e15f50c47fe6d85f1fb97403" +checksum = "6fca7cd8fd809b5ac4eefb89c1f98f7a7651d3739dfb341ca6980090f554c270" dependencies = [ "libc", "pyo3-build-config", @@ -684,9 +651,9 @@ dependencies = [ [[package]] name = "pyo3-macros" -version = "0.21.2" +version = "0.23.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77b34069fc0682e11b31dbd10321cbf94808394c56fd996796ce45217dfac53c" +checksum = "34e657fa5379a79151b6ff5328d9216a84f55dc93b17b08e7c3609a969b73aa0" dependencies = [ "proc-macro2", "pyo3-macros-backend", @@ -696,9 +663,9 @@ dependencies = [ [[package]] name = "pyo3-macros-backend" -version = "0.21.2" +version = "0.23.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08260721f32db5e1a5beae69a55553f56b99bd0e1c3e6e0a5e8851a9d0f5a85c" +checksum = "295548d5ffd95fd1981d2d3cf4458831b21d60af046b729b6fd143b0ba7aee2f" dependencies = [ "heck", "proc-macro2", @@ -716,15 +683,6 @@ dependencies = [ "proc-macro2", ] -[[package]] -name = "redox_syscall" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" -dependencies = [ - "bitflags 1.3.2", -] - [[package]] name = "regalloc2" version = "0.10.2" @@ -796,12 +754,6 @@ dependencies = [ "twox-hash", ] -[[package]] -name = "scopeguard" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" - [[package]] name = "serde" version = "1.0.203" @@ -1097,22 +1049,13 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" -[[package]] -name = "windows-sys" -version = "0.45.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" -dependencies = [ - "windows-targets 0.42.2", -] - [[package]] name = "windows-sys" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.6", + "windows-targets", ] [[package]] @@ -1121,22 +1064,7 @@ version = "0.59.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" dependencies = [ - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-targets" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" -dependencies = [ - "windows_aarch64_gnullvm 0.42.2", - "windows_aarch64_msvc 0.42.2", - "windows_i686_gnu 0.42.2", - "windows_i686_msvc 0.42.2", - "windows_x86_64_gnu 0.42.2", - "windows_x86_64_gnullvm 0.42.2", - "windows_x86_64_msvc 0.42.2", + "windows-targets", ] [[package]] @@ -1145,46 +1073,28 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm 0.52.6", - "windows_aarch64_msvc 0.52.6", - "windows_i686_gnu 0.52.6", + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", "windows_i686_gnullvm", - "windows_i686_msvc 0.52.6", - "windows_x86_64_gnu 0.52.6", - "windows_x86_64_gnullvm 0.52.6", - "windows_x86_64_msvc 0.52.6", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", ] -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" - [[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.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" - [[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.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" - [[package]] name = "windows_i686_gnu" version = "0.52.6" @@ -1197,48 +1107,24 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" -[[package]] -name = "windows_i686_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" - [[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.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" - [[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.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" - [[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.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" - [[package]] name = "windows_x86_64_msvc" version = "0.52.6" diff --git a/Cargo.toml b/Cargo.toml index cdea8d6..0e11eb8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,10 +15,10 @@ icicle-vm = { path = "icicle-emu/icicle-vm" } pcode = { path = "icicle-emu/sleigh/pcode" } sleigh-runtime = { path = "icicle-emu/sleigh/sleigh-runtime" } indexmap = "2.2.6" -pyo3 = { version = "0.21.2", features = ["extension-module", "indexmap", "abi3-py37"] } +pyo3 = { version = "0.23.2", features = ["extension-module", "indexmap", "abi3-py37"] } target-lexicon = "0.12.7" tracing = "*" tracing-subscriber = "0.3.17" [build-dependencies] -pyo3-build-config = "0.21.2" +pyo3-build-config = "0.23.2" diff --git a/src/lib.rs b/src/lib.rs index de1c6b5..7b30c3d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -14,7 +14,7 @@ use sleigh_runtime::NamedRegister; // - https://pyo3.rs/main/conversions/tables // - https://pyo3.rs/main/class -#[pyclass(module = "icicle")] +#[pyclass(eq, eq_int, module = "icicle")] #[derive(Clone, Debug, PartialEq)] pub enum MemoryProtection { NoAccess, @@ -25,7 +25,7 @@ pub enum MemoryProtection { ExecuteReadWrite, } -#[pyclass(module = "icicle")] +#[pyclass(eq, eq_int, module = "icicle")] #[derive(Clone, Debug, PartialEq)] pub enum RunStatus { /// The VM is still running. @@ -59,7 +59,7 @@ pub enum RunStatus { UnhandledException, } -#[pyclass(module = "icicle")] +#[pyclass(eq, eq_int, module = "icicle")] #[derive(Clone, Debug, PartialEq)] pub enum MemoryExceptionCode { Unallocated, @@ -99,7 +99,7 @@ impl From for MemoryExceptionCode { } } -#[pyclass(module = "icicle", name = "ExceptionCode")] +#[pyclass(eq, eq_int, module = "icicle", name = "ExceptionCode")] #[derive(Clone, Debug, PartialEq)] pub enum ExceptionCodePy { NoException = 0x0000, @@ -200,11 +200,11 @@ impl From for ExceptionCodePy { #[allow(non_snake_case)] fn raise_MemoryException(message: String, e: MemError) -> PyErr { Python::with_gil(|py| { - let icicle = py.import_bound("icicle").unwrap(); + let icicle = py.import("icicle").unwrap(); let exception = icicle.getattr("MemoryException").unwrap(); let args = (message, MemoryExceptionCode::from(e)); let inst = exception.call1(args).unwrap(); - PyErr::from_value_bound(inst) + PyErr::from_value(inst) }) } From 1465ddddafcd5bb9bd8030a8f7ca8aee65a5ae9b Mon Sep 17 00:00:00 2001 From: Duncan Ogilvie Date: Fri, 29 Nov 2024 23:07:14 +0100 Subject: [PATCH 9/9] Bump to 0.0.5 --- Cargo.lock | 2 +- Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6246153..459b066 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -424,7 +424,7 @@ dependencies = [ [[package]] name = "icicle-python" -version = "0.0.4" +version = "0.0.5" dependencies = [ "icicle-cpu", "icicle-vm", diff --git a/Cargo.toml b/Cargo.toml index 0e11eb8..dbe3a35 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,7 +2,7 @@ [package] name = "icicle-python" -version = "0.0.4" +version = "0.0.5" edition = "2021" [lib]