Skip to content

feat!: update rust bindings #2138

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 18 commits into from
Apr 12, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 14 additions & 32 deletions .github/workflows/Crate-publishing.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,59 +25,41 @@ jobs:
fail-fast: false
matrix:
config:
- {
os: windows-2022,
arch: x64,
name: 'Windows x86_64'
}
- {
os: windows-2022,
arch: x86,
name: 'Windows x86'
}
- {
os: ubuntu-latest,
arch: x64,
name: 'Ubuntu x86_64'
}
- {
os: macos-latest,
arch: x64,
name: 'macOS x86_64'
}
- { os: windows-2022, arch: x64, name: "Windows x86_64" }
- { os: windows-2022, arch: x86, name: "Windows x86" }
- { os: ubuntu-latest, arch: x64, name: "Ubuntu x86_64" }
- { os: macos-latest, arch: x64, name: "macOS x86_64" }
steps:
- uses: actions/checkout@v4

- name: '🛠️ Set up Rust'
uses: dtolnay/rust-toolchain@stable
- name: Set up Rust
uses: actions-rust-lang/setup-rust-toolchain@v1

- name: '🛠️ Activate Developer Command Prompt'
- name: "🛠️ Activate Developer Command Prompt"
if: contains(matrix.config.os, 'win')
uses: ilammy/msvc-dev-cmd@v1
with:
arch: ${{ matrix.config.arch }}

- name: '🛠️ Win build dependencies'
- name: "🛠️ Win build dependencies"
if: contains(matrix.config.os, 'win')
shell: bash
run: |
choco install ninja

- name: '🛠️ macOS build dependencies'
- name: "🛠️ macOS build dependencies"
if: contains(matrix.config.os, 'macOS')
shell: bash
run: |
brew install ninja

- name: '🚧 Cargo test'
- name: "🚧 Cargo test"
if: "!startsWith(github.ref, 'refs/tags')"
run: |
cargo test

- name: '📦 Cargo Publish'
- name: Publish crates to Crates.io
if: startsWith(github.ref, 'refs/tags') && !startsWith(github.ref, 'refs/tags/v') && contains(matrix.config.os, 'ubuntu')
env:
TOKEN: ${{ secrets.cratesio_token }}
UNICORN_VERSION: dev
run: |
cargo login $TOKEN && cargo test && cargo publish
uses: katyo/publish-crates@v2
with:
registry-token: ${{ secrets.cratesio_token }}
74 changes: 24 additions & 50 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,57 +1,31 @@
[package]
name = "unicorn-engine"
[workspace]
default-members = ["bindings/rust"]
members = ["bindings/rust", "bindings/rust/sys"]
resolver = "2"

[workspace.package]
rust-version = "1.85.0"
version = "2.1.3"
authors = ["Ziqiao Kong", "Lukas Seidel"]
authors = ["Ziqiao Kong", "Lukas Seidel", "Amaan Qureshi <[email protected]>"]
keywords = ["unicorn", "cpu", "emulator", "bindings"]
categories = ["api-bindings", "emulators", "no-std", "virtualization"]
documentation = "https://github.com/unicorn-engine/unicorn/wiki"
edition = "2021"
edition = "2024"
license = "GPL-2.0"
readme = "README.md"
repository = "https://github.com/unicorn-engine/unicorn"
description = "Rust bindings for the Unicorn emulator with utility functions"
build = "bindings/rust/build.rs"
links = "unicorn"
# use `cargo publish --list` to see files to be included
# the resulting list what cargo uses to check for out-of-date files during build
exclude = [
"/docs",
"/bindings/dotnet",
"/bindings/go",
"/bindings/haskell",
"/bindings/java",
"/bindings/pascal",
"/bindings/python",
"/bindings/ruby",
"/bindings/vb6",
"/bindings/zig",
"/samples",
"/tests",
]

[lib]
path = "bindings/rust/src/lib.rs"

[dependencies]
bitflags = "2.3.3"
libc = "0.2"

[build-dependencies]
cc = { version = "1.0" }
cmake = { version = "0.1" }
pkg-config = { version = "0.3" }

[features]
default = ["arch_all"]
dynamic_linkage = []
arch_all = ["arch_x86", "arch_arm", "arch_aarch64", "arch_riscv", "arch_mips", "arch_sparc", "arch_m68k", "arch_ppc", "arch_s390x", "arch_tricore"]
arch_x86 = []
arch_arm = []
# NOTE: unicorn-c only separates on top-level arch name,
# not on the bit-length, so we include both arm and aarch64
arch_aarch64 = ["arch_arm"]
arch_riscv = []
arch_mips = []
arch_sparc = []
arch_m68k = []
arch_ppc = []
arch_s390x = []
arch_tricore = []
[workspace.lints.clippy]
cast_lossless = "allow"
cast_possible_truncation = "allow"
cast_possible_wrap = "allow"
cast_sign_loss = "allow"
missing_errors_doc = "allow"
missing_panics_doc = "allow"
similar_names = "allow"
unreadable_literal = "allow"
use_self = "allow"
pedantic = { level = "warn", priority = -1 }
nursery = { level = "warn", priority = -1 }
cargo = { level = "warn", priority = -1 }
53 changes: 53 additions & 0 deletions bindings/rust/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
[package]
name = "unicorn-engine"
version.workspace = true
authors.workspace = true
keywords.workspace = true
categories.workspace = true
documentation.workspace = true
edition.workspace = true
license.workspace = true
readme = "README.md"
repository.workspace = true
description.workspace = true

[lints]
workspace = true

[dependencies]
unicorn-engine-sys = { version = "2.1.3", path = "sys", features = [], default-features = false }

[build-dependencies]
bindgen = "0.71.1"
cc = { version = "1.2.17" }
cmake = { version = "0.1.54" }
pkg-config = { version = "0.3.32" }

[dev-dependencies]
page_size = "0.6.0"

[features]
default = ["arch_all"]
dynamic_linkage = ["unicorn-engine-sys/dynamic_linkage"]
arch_all = [
"arch_x86",
"arch_arm",
"arch_aarch64",
"arch_riscv",
"arch_mips",
"arch_sparc",
"arch_m68k",
"arch_ppc",
"arch_s390x",
"arch_tricore",
]
arch_x86 = ["unicorn-engine-sys/arch_x86"]
arch_arm = ["unicorn-engine-sys/arch_arm"]
arch_aarch64 = ["arch_arm", "unicorn-engine-sys/arch_aarch64"]
arch_riscv = ["unicorn-engine-sys/arch_riscv"]
arch_mips = ["unicorn-engine-sys/arch_mips"]
arch_sparc = ["unicorn-engine-sys/arch_sparc"]
arch_m68k = ["unicorn-engine-sys/arch_m68k"]
arch_ppc = ["unicorn-engine-sys/arch_ppc"]
arch_s390x = ["unicorn-engine-sys/arch_s390x"]
arch_tricore = ["unicorn-engine-sys/arch_tricore"]
20 changes: 9 additions & 11 deletions bindings/rust/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,26 +5,25 @@ Rust bindings for the [Unicorn](http://www.unicorn-engine.org/) emulator with ut
Checkout Unicorn2 source code at [dev branch](https://github.com/unicorn-engine/unicorn/tree/dev).

```rust
use unicorn_engine::{Unicorn, RegisterARM};
use unicorn_engine::unicorn_const::{Arch, Mode, Permission, SECOND_SCALE};
use unicorn_engine::{Arch, Mode, Prot, SECOND_SCALE, Unicorn, RegisterARM};

fn main() {
let arm_code32: Vec<u8> = vec![0x17, 0x00, 0x40, 0xe2]; // sub r0, #23

let mut unicorn = Unicorn::new(Arch::ARM, Mode::LITTLE_ENDIAN).expect("failed to initialize Unicorn instance");
let emu = &mut unicorn;
emu.mem_map(0x1000, 0x4000, Permission::ALL).expect("failed to map code page");
let mut emu = Unicorn::new(Arch::ARM, Mode::LITTLE_ENDIAN).expect("failed to initialize Unicorn instance");
emu.mem_map(0x1000, 0x4000, Prot::ALL).expect("failed to map code page");
emu.mem_write(0x1000, &arm_code32).expect("failed to write instructions");

emu.reg_write(RegisterARM::R0, 123).expect("failed write R0");
emu.reg_write(RegisterARM::R5, 1337).expect("failed write R5");

let _ = emu.emu_start(0x1000, (0x1000 + arm_code32.len()) as u64, 10 * SECOND_SCALE, 1000);
assert_eq!(emu.reg_read(RegisterARM::R0), Ok(100));
assert_eq!(emu.reg_read(RegisterARM::R5), Ok(1337));
emu.emu_start(0x1000, (0x1000 + arm_code32.len()) as u64, 10 * SECOND_SCALE, 1000).expect("failed to start emulation");
assert_eq!(emu.reg_read(RegisterARM::R0).unwrap(), 100);
assert_eq!(emu.reg_read(RegisterARM::R5).unwrap(), 1337);
}
```
Further sample code can be found in [tests](../../tests/rust-tests/main.rs).

Further sample code can be found in [tests](./src/tests).

## Usage

Expand All @@ -37,7 +36,6 @@ unicorn-engine = "2.1.1"

## Acknowledgements

These bindings are based on Sébastien Duquette's (@ekse) [unicorn-rs](https://github.com/unicorn-rs/unicorn-rs).
These bindings were once based on Sébastien Duquette's (@ekse) [unicorn-rs](https://github.com/unicorn-rs/unicorn-rs).
We picked up the project, as it is no longer maintained.
Thanks to all contributors.

Loading
Loading