4 releases

0.1.4 Nov 21, 2024
0.1.3 Jun 21, 2024
0.1.2 Jun 21, 2024
0.1.1 Jun 20, 2024
0.1.0 Jun 20, 2024

#210 in Programming languages

Download history 62/week @ 2024-08-16 187/week @ 2024-08-23 128/week @ 2024-08-30 163/week @ 2024-09-06 203/week @ 2024-09-13 233/week @ 2024-09-20 309/week @ 2024-09-27 220/week @ 2024-10-04 244/week @ 2024-10-11 356/week @ 2024-10-18 506/week @ 2024-10-25 88/week @ 2024-11-01 126/week @ 2024-11-08 208/week @ 2024-11-15 401/week @ 2024-11-22 320/week @ 2024-11-29

1,079 downloads per month

MIT license

82KB
1.5K SLoC

C++ 798 SLoC // 0.1% comments Rust 489 SLoC // 0.2% comments

nyxstone-rs

crates.io Github Rust CI Badge

Official bindings for the Nyxstone assembler/disassembler engine.

Building

The project can be build via cargo build, as long as LLVM with a major version in the range 15-18 is installed in the $PATH or the environment variable $NYXSTONE_LLVM_PREFIX points to the installation location of a LLVM library.

LLVM might be linked against FFI, but not correctly report this fact via llvm-config. If your LLVM does link FFI and Nyxstone fails to run, set the NYXSTONE_LINK_FFI environment variable to 1, which will ensure that Nyxstone links against libffi.

Installation

Add nyxstone as a dependency in your Cargo.toml:

[dependencies]
nyxstone = "0.1"

Building nyxstone requires a C/C++ compiler to be installed on your system. Additionally, Nyxstone requires LLVM with a major version in the range 15-18.

Sample

In the following is a short sample of what using Nyxstone can look like:

extern crate anyhow;
extern crate nyxstone;

use std::collections::HashMap;

use anyhow::Result;
use nyxstone::{IntegerBase, Nyxstone, NyxstoneConfig};

fn main() -> Result<()> {
    // Creating a nyxstone instance can fail, for example if the triple is invalid.
    let nyxstone = Nyxstone::new("x86_64", NyxstoneConfig::default())?;

    // Assemble a single instruction
    let instructions = nyxstone.assemble_to_instructions("xor rax, rax", 0x100)?;

    println!("Assembled: ");
    for instr in instructions {
        println!("0x{:04x}: {:15} - {:02x?}", instr.address, instr.assembly, instr.bytes);
    }

    // Assemble with a label definition
    let instructions = nyxstone.assemble_to_instructions_with(
        "mov rax, rbx; cmp rax, rdx; jne .label",
        0x100,
        &HashMap::from([(".label", 0x1200)]),
    )?;

    println!("Assembled: ");
    for instr in instructions {
        println!("0x{:04x}: {:15} - {:02x?}", instr.address, instr.assembly, instr.bytes);
    }

    let disassembly = nyxstone.disassemble(
        &[0x31, 0xd8],
        /* address= */ 0x0,
        /* #instructions= (0 = all)*/ 0,
    )?;

    assert_eq!(disassembly, "xor eax, ebx\n".to_owned());

    let config = NyxstoneConfig {
        immediate_style: IntegerBase::HexPrefix,
        ..Default::default()
    };
    let nyxstone = Nyxstone::new("x86_64", config)?;

    assert_eq!(
        nyxstone.disassemble(&[0x83, 0xc0, 0x01], 0, 0)?,
        "add eax, 0x1\n".to_owned()
    );

    Ok(())
}

Technical overview

The nyxstone-rs bindings are generated via the cxx crate. Since nyxstone is specifically a c++ library, we currently do not plan to support C bindings via bindgen.

Acknowledgements

The build script of the rust bindings borrow heavily from the llvm-sys build script.

Dependencies

~0.6–2.3MB
~36K SLoC