diff --git a/bindings/rust/Cargo.lock b/bindings/rust/Cargo.lock deleted file mode 100644 index ade8aaf..0000000 --- a/bindings/rust/Cargo.lock +++ /dev/null @@ -1,285 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "anyhow" -version = "1.0.75" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" - -[[package]] -name = "cc" -version = "1.0.83" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" -dependencies = [ - "libc", -] - -[[package]] -name = "codespan-reporting" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" -dependencies = [ - "termcolor", - "unicode-width", -] - -[[package]] -name = "cxx" -version = "1.0.107" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbe98ba1789d56fb3db3bee5e032774d4f421b685de7ba703643584ba24effbe" -dependencies = [ - "cc", - "cxxbridge-flags", - "cxxbridge-macro", - "link-cplusplus", -] - -[[package]] -name = "cxx-build" -version = "1.0.107" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4ce20f6b8433da4841b1dadfb9468709868022d829d5ca1f2ffbda928455ea3" -dependencies = [ - "cc", - "codespan-reporting", - "once_cell", - "proc-macro2", - "quote", - "scratch", - "syn 2.0.37", -] - -[[package]] -name = "cxxbridge-flags" -version = "1.0.107" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20888d9e1d2298e2ff473cee30efe7d5036e437857ab68bbfea84c74dba91da2" - -[[package]] -name = "cxxbridge-macro" -version = "1.0.107" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fa16a70dd58129e4dfffdff535fb1bce66673f7bbeec4a5a1765a504e1ccd84" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.37", -] - -[[package]] -name = "darling" -version = "0.14.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b750cb3417fd1b327431a470f388520309479ab0bf5e323505daf0290cd3850" -dependencies = [ - "darling_core", - "darling_macro", -] - -[[package]] -name = "darling_core" -version = "0.14.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "109c1ca6e6b7f82cc233a97004ea8ed7ca123a9af07a8230878fcfda9b158bf0" -dependencies = [ - "fnv", - "ident_case", - "proc-macro2", - "quote", - "strsim", - "syn 1.0.109", -] - -[[package]] -name = "darling_macro" -version = "0.14.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4aab4dbc9f7611d8b55048a3a16d2d010c2c8334e46304b40ac1cc14bf3b48e" -dependencies = [ - "darling_core", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "derive_builder" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d67778784b508018359cbc8696edb3db78160bab2c2a28ba7f56ef6932997f8" -dependencies = [ - "derive_builder_macro", -] - -[[package]] -name = "derive_builder_core" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c11bdc11a0c47bc7d37d582b5285da6849c96681023680b906673c5707af7b0f" -dependencies = [ - "darling", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "derive_builder_macro" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebcda35c7a396850a55ffeac740804b40ffec779b98fffbb1738f4033f0ee79e" -dependencies = [ - "derive_builder_core", - "syn 1.0.109", -] - -[[package]] -name = "fnv" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" - -[[package]] -name = "ident_case" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" - -[[package]] -name = "libc" -version = "0.2.148" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cdc71e17332e86d2e1d38c1f99edcb6288ee11b815fb1a4b049eaa2114d369b" - -[[package]] -name = "link-cplusplus" -version = "1.0.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d240c6f7e1ba3a28b0249f774e6a9dd0175054b52dfbb61b16eb8505c3785c9" -dependencies = [ - "cc", -] - -[[package]] -name = "nyxstone" -version = "0.1.0" -dependencies = [ - "anyhow", - "cxx", - "cxx-build", - "derive_builder", -] - -[[package]] -name = "once_cell" -version = "1.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" - -[[package]] -name = "proc-macro2" -version = "1.0.67" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d433d9f1a3e8c1263d9456598b16fec66f4acc9a74dacffd35c7bb09b3a1328" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "quote" -version = "1.0.33" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "scratch" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3cf7c11c38cb994f3d40e8a8cde3bbd1f72a435e4c49e85d6553d8312306152" - -[[package]] -name = "strsim" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" - -[[package]] -name = "syn" -version = "1.0.109" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "syn" -version = "2.0.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7303ef2c05cd654186cb250d29049a24840ca25d2747c25c0381c8d9e2f582e8" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "termcolor" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6093bad37da69aab9d123a8091e4be0aa4a03e4d601ec641c327398315f62b64" -dependencies = [ - "winapi-util", -] - -[[package]] -name = "unicode-ident" -version = "1.0.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" - -[[package]] -name = "unicode-width" -version = "0.1.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" - -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - -[[package]] -name = "winapi-util" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" -dependencies = [ - "winapi", -] - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/bindings/rust/Cargo.toml b/bindings/rust/Cargo.toml index e679394..0f038bd 100644 --- a/bindings/rust/Cargo.toml +++ b/bindings/rust/Cargo.toml @@ -16,7 +16,6 @@ categories = ["api-bindings", "compilers"] [dependencies] anyhow = { version = "1.0.68", default-features = true } -derive_builder = { version = "0.12.0" } cxx = "1.0.94" [build-dependencies] diff --git a/bindings/rust/README.md b/bindings/rust/README.md index 4198d5b..c19a905 100644 --- a/bindings/rust/README.md +++ b/bindings/rust/README.md @@ -27,11 +27,11 @@ extern crate anyhow; extern crate nyxstone; use anyhow::Result; -use nyxstone::{IntegerBase, LabelDefinition, NyxstoneBuilder}; +use nyxstone::{IntegerBase, LabelDefinition, Nyxstone, NyxstoneConfig}; fn main() -> Result<()> { // Creating a nyxstone instance can fail, for example if the triple is invalid. - let nyxstone = NyxstoneBuilder::default().with_triple("x86_64").build()?; + let nyxstone = Nyxstone::new("x86_64", NyxstoneConfig::default())?; let instructions = nyxstone.assemble_to_instructions( "mov rax, rbx; cmp rax, rdx; jne .label", @@ -55,10 +55,11 @@ fn main() -> Result<()> { assert_eq!(disassembly, "xor eax, ebx\n".to_owned()); - let nyxstone = NyxstoneBuilder::default() - .with_triple("x86_64") - .with_immediate_style(IntegerBase::HexPrefix) - .build()?; + let config = NyxstoneConfig { + immediate_style: IntegerBase::HexPrefix, + ..Default::default() + }; + let nyxstone = Nyxstone::new("x86_64", config)?; assert_eq!( nyxstone.disassemble_to_text(&[0x83, 0xc0, 0x01], 0, 0)?, @@ -79,4 +80,4 @@ The binding class `NyxstoneFFI` currently copies a lot of data between the rust ## Acknowledgements -The build script of the rust bindings borrow heavily from the [llvm-sys](https://gitlab.com/taricorp/llvm-sys.rs) build script. \ No newline at end of file +The build script of the rust bindings borrow heavily from the [llvm-sys](https://gitlab.com/taricorp/llvm-sys.rs) build script. diff --git a/bindings/rust/examples/usage.rs b/bindings/rust/examples/usage.rs new file mode 100644 index 0000000..663117f --- /dev/null +++ b/bindings/rust/examples/usage.rs @@ -0,0 +1,45 @@ +extern crate anyhow; +extern crate nyxstone; + +use anyhow::Result; +use nyxstone::{IntegerBase, LabelDefinition, 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())?; + + let instructions = nyxstone.assemble_to_instructions( + "mov rax, rbx; cmp rax, rdx; jne .label", + 0x100, + &[LabelDefinition { + name: ".label", + address: 0x1200, + }], + )?; + + println!("Assembled: "); + for instr in instructions { + println!("0x{:04x}: {:15} - {:02x?}", instr.address, instr.assembly, instr.bytes); + } + + let disassembly = nyxstone.disassemble_to_text( + &[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_to_text(&[0x83, 0xc0, 0x01], 0, 0)?, + "add eax, 0x1\n".to_owned() + ); + + Ok(()) +} diff --git a/bindings/rust/src/lib.rs b/bindings/rust/src/lib.rs index 65b12d9..2675ce0 100644 --- a/bindings/rust/src/lib.rs +++ b/bindings/rust/src/lib.rs @@ -1,16 +1,13 @@ use anyhow::anyhow; -use derive_builder::Builder; use ffi::create_nyxstone_ffi; /// Public interface for calling nyxstone from rust. /// # Examples /// /// ```rust -/// # use nyxstone::{Nyxstone, NyxstoneBuilder, Instruction}; +/// # use nyxstone::{Nyxstone, NyxstoneConfig, Instruction}; /// # fn main() -> anyhow::Result<()> { -/// let nyxstone = NyxstoneBuilder::default() -/// .with_triple("x86_64") -/// .build()?; +/// let nyxstone = Nyxstone::new("x86_64", NyxstoneConfig::default())?; /// /// let instructions = nyxstone.assemble_to_instructions("mov rax, rbx", 0x1000, &[])?; /// @@ -25,46 +22,8 @@ use ffi::create_nyxstone_ffi; /// # Ok(()) /// # } /// ``` -#[derive(Builder)] -#[builder(setter(into), pattern = "owned", build_fn(error = "anyhow::Error", skip))] pub struct Nyxstone { - /// Specifies the LLVM target triple Nyxstone uses. MUST be set! - /// - /// # Parameters - /// - `value`: The LLVM target triple, for example `x86_64`. - /// - /// # Returns - /// The updated NyxstoneBuilder instance. - #[builder(field(type = "String"), setter(name = "with_triple"))] - _triple: (), // Empty variable which holds the triple in the auto-generated `NyxstoneBuilder`. - - /// Specifies the CPU for which LLVM assembles/disassembles internally, which might enable/disable certain features. - /// - /// # Parameters - /// - `value`: The CPU name, for example `corei7` - /// - /// # Returns - /// The updated NyxstoneBuilder instance. - #[builder(field(type = "String"), setter(name = "with_cpu"))] - _cpu: (), - #[builder(field(type = "Vec"), setter(custom))] - _enabled_features: (), // Empty variable which holds the enabled features in the auto-generated `NyxstoneBuilder`. - #[builder(field(type = "Vec"), setter(custom))] - _disabled_features: (), // Empty variable which holds the disabled features in the auto-generated `NyxstoneBuilder`. - - /// Specifies in what format immediates should be represented in the output. - /// - /// # Parameters - /// - `value`: One of the [`IntegerBase`] variants. - /// - /// # Returns - /// The updated NyxstoneBuilder instance. - #[builder(field(type = "IntegerBase"), setter(name = "with_immediate_style"))] - _imm_style: (), // Empty variable which holds the hex style for instruction printing in the auto-generated `NyxstoneBuilder`. - /// The c++ `unique_ptr` holding the actual `NyxstoneFFI` instance. - /// Is an empty type in the `NyxstoneBuilder`. - #[builder(setter(skip), field(type = "()"))] inner: cxx::UniquePtr, } @@ -73,7 +32,7 @@ pub use crate::ffi::Instruction; pub use crate::ffi::LabelDefinition; /// Configuration options for the integer style of immediates in disassembly output. -#[derive(Debug, PartialEq, Eq, Default)] +#[derive(Debug, PartialEq, Eq, Default, Clone, Copy)] pub enum IntegerBase { /// Immediates are represented in decimal format. #[default] @@ -95,6 +54,28 @@ impl From for ffi::IntegerBase { } impl Nyxstone { + /// Builds a Nyxstone instance with specific configuration. + /// + /// # Returns + /// Ok() and the Nyxstone instance on success, Err() otherwise. + /// + /// # Errors + /// Errors occur when the LLVM triple was not supplied to the builder or LLVM fails. + pub fn new(target_triple: &str, config: NyxstoneConfig) -> anyhow::Result { + let result = create_nyxstone_ffi( + target_triple, + config.cpu, + config.features, + config.immediate_style.into(), + ); + + if !result.error.is_empty() { + return Err(anyhow!("{}", result.error)); + } + + Ok(Nyxstone { inner: result.ok }) + } + /// Translates assembly instructions at a given start address to bytes. /// /// # Note: @@ -143,7 +124,9 @@ impl Nyxstone { address: u64, labels: &[LabelDefinition], ) -> anyhow::Result> { - let instr_result = self.inner.assemble_to_instructions(assembly, address, labels); + let instr_result = self + .inner + .assemble_to_instructions(assembly, address, labels); if !instr_result.error.is_empty() { return Err(anyhow!("Error during disassembly: {}.", instr_result.error)); @@ -161,7 +144,12 @@ impl Nyxstone { /// /// # Returns: /// Ok() and disassembly text on success, Err() otherwise. - pub fn disassemble_to_text(&self, bytes: &[u8], address: u64, count: usize) -> anyhow::Result { + pub fn disassemble_to_text( + &self, + bytes: &[u8], + address: u64, + count: usize, + ) -> anyhow::Result { let text_result = self.inner.disassemble_to_text(bytes, address, count); if !text_result.error.is_empty() { @@ -186,7 +174,9 @@ impl Nyxstone { address: u64, count: usize, ) -> anyhow::Result> { - let instr_result = self.inner.disassemble_to_instructions(bytes, address, count); + let instr_result = self + .inner + .disassemble_to_instructions(bytes, address, count); if !instr_result.error.is_empty() { return Err(anyhow!("Error during disassembly: {}.", instr_result.error)); @@ -198,99 +188,15 @@ impl Nyxstone { unsafe impl Send for Nyxstone {} -impl NyxstoneBuilder { - /// Enables a given llvm feature. - /// - /// # Parameters - /// - `feature`: The feature to be enabled, should not contain a prepended '+'. - /// - /// # Returns - /// The updated NyxstoneBuilder instance. - pub fn with_feature(mut self, feature: &str) -> Self { - // If the feature is already enabled, we do not need to do anything - if self._enabled_features.iter().any(|f| f == feature) { - return self; - } - - // If the feature is disabled, we need to remove it from the disabled features. - if let Some(pos) = self._disabled_features.iter().position(|f| f == feature) { - self._disabled_features.swap_remove(pos); // We do not need the features to be in-order - } - - self._enabled_features.push(feature.into()); - - self - } - - /// Disables a given llvm feature. - /// - /// # Parameters - /// - `feature`: The feature to be disabled, should not contain a prepended '-'. - /// - /// # Returns - /// The updated NyxstoneBuilder instance. - pub fn without_feature(mut self, feature: &str) -> Self { - // If the feature is already disabled, we do not need to do anything - if self._disabled_features.iter().any(|f| f == feature) { - return self; - } - - // If the feature is enabled, we need to remove it from the enabled features. - if let Some(pos) = self._enabled_features.iter().position(|f| f == feature) { - self._enabled_features.swap_remove(pos); // We do not need the features to be in-order - } - - self._disabled_features.push(feature.into()); - - self - } - - /// Builds a Nyxstone instance from the NyxstoneBuilder. - /// - /// # Returns - /// Ok() and the Nyxstone instance on success, Err() otherwise. - /// - /// # Errors - /// Errors occur when the LLVM triple was not supplied to the builder or LLVM fails. - pub fn build(self) -> anyhow::Result { - if self._triple.is_empty() { - return Err(anyhow::anyhow!("No 'triple' supplied to builder.")); - } - - // Build the features string for LLVM - // LLVM features are comma-seperated strings representing the feature - // preprended with a '+' for an enabled feature and a '-' for a disabled feature. - let features: Vec<_> = self - ._enabled_features - .into_iter() - .map(|mut feature| { - feature.insert(0, '+'); - feature - }) - .chain(self._disabled_features.into_iter().map(|mut feature| { - feature.insert(0, '-'); - feature - })) - .collect(); - - let features: String = features.join(","); - - let nyxstone_result = create_nyxstone_ffi(&self._triple, &self._cpu, &features, self._imm_style.into()); - - if !nyxstone_result.error.is_empty() { - return Err(anyhow!(nyxstone_result.error)); - } - - Ok(Nyxstone { - _triple: (), - _cpu: (), - _enabled_features: (), - _disabled_features: (), - _imm_style: (), - - inner: nyxstone_result.ok, - }) - } +/// Initialization configuration for Nyxstone +#[derive(Debug, Default)] +pub struct NyxstoneConfig<'a, 'b> { + /// The LLVM cpu identifier, empty for no specific cpu target. + pub cpu: &'a str, + /// An LLVM feature string, features are comma seperated strings, which are prepended with '+' when enabled and '-' if disabled. + pub features: &'b str, + /// The printing style of immediates. + pub immediate_style: IntegerBase, } #[cxx::bridge] @@ -360,7 +266,12 @@ mod ffi { /// - features: llvm features string (features delimited by `,` with `+` for enable and `-` for disable), can be empty /// # Returns /// Ok() and UniquePtr holding a NyxstoneFFI on success, Err() otherwise. - fn create_nyxstone_ffi(triple_name: &str, cpu: &str, features: &str, style: IntegerBase) -> NyxstoneResult; + fn create_nyxstone_ffi( + triple_name: &str, + cpu: &str, + features: &str, + style: IntegerBase, + ) -> NyxstoneResult; // Translates assembly instructions at a given start address to bytes. // Additional label definitions by absolute address may be supplied. @@ -383,7 +294,12 @@ mod ffi { ) -> InstructionResult; // Translates bytes to disassembly text at given start address. - fn disassemble_to_text(self: &NyxstoneFFI, bytes: &[u8], address: u64, count: usize) -> StringResult; + fn disassemble_to_text( + self: &NyxstoneFFI, + bytes: &[u8], + address: u64, + count: usize, + ) -> StringResult; // Translates bytes to instruction details containing disassembly text at a given start address. fn disassemble_to_instructions( diff --git a/bindings/rust/tests/validation.rs b/bindings/rust/tests/validation.rs index b3ebfe3..f97e596 100644 --- a/bindings/rust/tests/validation.rs +++ b/bindings/rust/tests/validation.rs @@ -1,12 +1,12 @@ #[cfg(test)] mod tests { use anyhow::Result; - use nyxstone::{Instruction, IntegerBase, LabelDefinition, Nyxstone, NyxstoneBuilder}; + use nyxstone::{Instruction, IntegerBase, LabelDefinition, Nyxstone, NyxstoneConfig}; use std::assert_eq; #[test] fn assembler_test() -> Result<()> { - let nyxstone = NyxstoneBuilder::default().with_triple("x86_64-linux-gnu").build()?; + let nyxstone = Nyxstone::new("x86_64-linux-gnu", NyxstoneConfig::default())?; let result = nyxstone.assemble_to_bytes("mov rax, rax", 0x1000, &[])?; assert_eq!(result, vec![0x48, 0x89, 0xc0]); @@ -16,7 +16,7 @@ mod tests { #[test] fn disassembler_test() -> Result<()> { - let nyxstone = NyxstoneBuilder::default().with_triple("x86_64-linux-gnu").build()?; + let nyxstone = Nyxstone::new("x86_64-linux-gnu", NyxstoneConfig::default())?; let result = nyxstone.disassemble_to_text(&[0x48, 0x89, 0xc0], 0x1000, 0)?; assert_eq!(result, "mov rax, rax\n".to_owned()); @@ -26,7 +26,7 @@ mod tests { #[test] fn ldr_aligned_misaligned_armv6m_test() -> Result<()> { - let nyxstone = NyxstoneBuilder::default().with_triple("armv6m-none-eabi").build()?; + let nyxstone = Nyxstone::new("armv6m-none-eabi", NyxstoneConfig::default())?; // 4 byte aligned instruction addresses let bytes = nyxstone.assemble_to_bytes( @@ -116,9 +116,7 @@ mod tests { #[test] fn ldr_segfault_regression_test() -> Result<()> { - let nyxstone_armv8m = NyxstoneBuilder::default() - .with_triple("armv8m.main-none-eabi") - .build()?; + let nyxstone_armv8m = Nyxstone::new("armv8m.main-none-eabi", NyxstoneConfig::default())?; // #8 assembly="ldr r3, .lbl_0x00c0f4\n.lbl_0x00c0f4:\n", address=49352, let result = nyxstone_armv8m.assemble_to_bytes( @@ -148,10 +146,8 @@ mod tests { #[test] fn nyxstone_test() -> Result<()> { - let nyxstone_x86_64 = NyxstoneBuilder::default().with_triple("x86_64-linux-gnu").build()?; - let nyxstone_armv8m = NyxstoneBuilder::default() - .with_triple("armv8m.main-none-eabi") - .build()?; + let nyxstone_x86_64 = Nyxstone::new("x86_64-linux-gnu", NyxstoneConfig::default())?; + let nyxstone_armv8m = Nyxstone::new("armv8m.main-none-eabi", NyxstoneConfig::default())?; let labels = [LabelDefinition { name: ".label", @@ -212,9 +208,7 @@ mod tests { #[test] fn nyxstone_armv8a_ldr_regression_test() -> Result<()> { - let nyxstone_armv8a = NyxstoneBuilder::default() - .with_triple("aarch64-linux-gnueabihf") - .build()?; + let nyxstone_armv8a = Nyxstone::new("aarch64-linux-gnueabihf", NyxstoneConfig::default())?; let result = nyxstone_armv8a.assemble_to_bytes( "ldr x10, .label", @@ -240,9 +234,7 @@ mod tests { #[test] fn nyxstone_armv8m_ldr_regression_test() -> Result<()> { - let nyxstone_armv8m = NyxstoneBuilder::default() - .with_triple("armv8m.main-none-eabi") - .build()?; + let nyxstone_armv8m = Nyxstone::new("armv8m.main-none-eabi", NyxstoneConfig::default())?; let result = nyxstone_armv8m.assemble_to_bytes( "ldr r3, .label", @@ -259,9 +251,7 @@ mod tests { #[test] fn nyxstone_armv8a_regression_test_call_fixup() -> Result<()> { - let nyxstone_armv8a = NyxstoneBuilder::default() - .with_triple("aarch64-linux-gnueabihf") - .build()?; + let nyxstone_armv8a = Nyxstone::new("aarch64-linux-gnueabihf", NyxstoneConfig::default())?; let labels = [LabelDefinition { name: ".label", @@ -342,10 +332,8 @@ mod tests { #[test] fn nyxstone_regression_test_call_fixup() -> Result<()> { - let nyxstone_x86_64 = NyxstoneBuilder::default().with_triple("x86_64-linux-gnu").build()?; - let nyxstone_armv8m = NyxstoneBuilder::default() - .with_triple("armv8m.main-none-eabi") - .build()?; + let nyxstone_x86_64 = Nyxstone::new("x86_64-linux-gnu", NyxstoneConfig::default())?; + let nyxstone_armv8m = Nyxstone::new("armv8m.main-none-eabi", NyxstoneConfig::default())?; let labels = [LabelDefinition { name: ".label", @@ -379,9 +367,7 @@ mod tests { #[test] fn nyxstone_armv8m_regression_test_call_fixup() -> Result<()> { - let nyxstone_armv8m = NyxstoneBuilder::default() - .with_triple("armv8m.main-none-eabi") - .build()?; + let nyxstone_armv8m = Nyxstone::new("armv8m.main-none-eabi", NyxstoneConfig::default())?; let labels = [LabelDefinition { name: ".label", @@ -411,11 +397,12 @@ mod tests { #[test] fn nyxstone_isa() -> Result<()> { - let nyxstone_armv8m = NyxstoneBuilder::default() - .with_triple("armv8m.main-none-eabi") - .with_feature("fp16") - .with_feature("mve.fp") - .build()?; + let config = NyxstoneConfig { + features: "+fp16,+mve.fp", + ..Default::default() + }; + let nyxstone_armv8m = Nyxstone::new("armv8m.main-none-eabi", config)?; + // test floating point instructions let bytes = nyxstone_armv8m.assemble_to_bytes("vadd.f16 s0, s1, s2", 0x1000, &[])?; assert_eq!(bytes, vec![0x30, 0xee, 0x81, 0x09]); @@ -439,23 +426,20 @@ mod tests { // as well as validating that disabling the enabled features actually disables them... // #[test] // fn nyxstone_isa_cpu() -> Result<()> { - // let nyxstone = NyxstoneBuilder::default() - // .with_triple("some-triple") - // .with_cpu("some-cpu-with-feature-x") - // .without_feature("x") - // .build()?; - // // test feature x + // let config = NyxstoneInit {cpu: "some-cpu-with-feature-x", features: "-feature_x", ..Default::default()}; + // .init("some-triple")?; + // // test that feature x does not work // Ok(()) // } #[test] fn nyxstone_isa_fails() -> Result<()> { - let nyxstone_armv8m = NyxstoneBuilder::default() - .with_triple("armv8m.main-none-eabi") - .with_feature("fp16") - .without_feature("mve.fp") - .build()?; + let config = NyxstoneConfig { + features: "+fp16,-mve.fp", + ..Default::default() + }; + let nyxstone_armv8m = Nyxstone::new("armv8m.main-none-eabi", config)?; // Test that floating point instructions fail if the feature is not enabled. let result = nyxstone_armv8m.assemble_to_bytes("vadd.f16 s0, s1, s2", 0x1000, &[]); @@ -476,27 +460,27 @@ mod tests { let bytes = [0x00, 0xf1, 0x0a, 0x00]; // add.w r0, r0, #10 // Ensure that the default prints immediates as decimals. - let nyxstone = NyxstoneBuilder::default() - .with_triple("armv8m.main-none-eabi") - .build()?; + let nyxstone = Nyxstone::new("armv8m.main-none-eabi", NyxstoneConfig::default())?; let asm = nyxstone.disassemble_to_text(&bytes, 0x0, 0)?; assert_eq!(asm, "add.w r0, r0, #10\n"); // Ensure that HexPrefix works. - let nyxstone = NyxstoneBuilder::default() - .with_triple("armv8m.main-none-eabi") - .with_immediate_style(IntegerBase::HexPrefix) - .build()?; + let config = NyxstoneConfig { + immediate_style: IntegerBase::HexPrefix, + ..Default::default() + }; + let nyxstone = Nyxstone::new("armv8m.main-none-eabi", config)?; let asm = nyxstone.disassemble_to_text(&bytes, 0x0, 0)?; assert_eq!(asm, "add.w r0, r0, #0xa\n"); // Ensure that HexSuffix works. - let nyxstone = NyxstoneBuilder::default() - .with_triple("armv8m.main-none-eabi") - .with_immediate_style(IntegerBase::HexSuffix) - .build()?; + let config = NyxstoneConfig { + immediate_style: IntegerBase::HexSuffix, + ..Default::default() + }; + let nyxstone = Nyxstone::new("armv8m.main-none-eabi", config)?; let asm = nyxstone.disassemble_to_text(&bytes, 0x0, 0)?; assert_eq!(asm, "add.w r0, r0, #0ah\n"); @@ -506,9 +490,7 @@ mod tests { #[test] fn armv8a_adr_out_of_range_regression() -> Result<()> { - let nyxstone_armv8a = NyxstoneBuilder::default() - .with_triple("aarch64-linux-gnueabihf") - .build()?; + let nyxstone_armv8a = Nyxstone::new("aarch64-linux-gnueabihf", NyxstoneConfig::default())?; let result = nyxstone_armv8a.assemble_to_bytes( "adr x21, .label", @@ -526,9 +508,7 @@ mod tests { #[test] fn armv8m_adr_out_of_range_regression() -> Result<()> { - let nyxstone_armv8m = NyxstoneBuilder::default() - .with_triple("armv8m.main-none-eabi") - .build()?; + let nyxstone_armv8m = Nyxstone::new("armv8m.main-none-eabi", NyxstoneConfig::default())?; let result = nyxstone_armv8m.assemble_to_bytes( "adr r0, .label", @@ -694,7 +674,7 @@ mod tests { ), ]; - let nyxstone_armv6m = NyxstoneBuilder::default().with_triple("armv6m-none-eabi").build()?; + let nyxstone_armv6m = Nyxstone::new("armv6m-none-eabi", NyxstoneConfig::default())?; check_instruction_ranges(&nyxstone_armv6m, instructions)?; @@ -770,11 +750,11 @@ mod tests { ), ]; - let nyxstone_armv7m = NyxstoneBuilder::default() - .with_triple("armv7m-none-eabi") - .with_feature("fp16") - .with_feature("mve.fp") - .build()?; + let config = NyxstoneConfig { + features: "+fp16,+mve.fp", + ..Default::default() + }; + let nyxstone_armv7m = Nyxstone::new("armv7m-none-eabi", config)?; check_instruction_ranges(&nyxstone_armv7m, instructions)?; @@ -850,11 +830,11 @@ mod tests { ), ]; - let nyxstone_armv8m = NyxstoneBuilder::default() - .with_triple("armv8m.main-none-eabi") - .with_feature("fp16") - .with_feature("mve.fp") - .build()?; + let config = NyxstoneConfig { + features: "+fp16,+mve.fp", + ..Default::default() + }; + let nyxstone_armv8m = Nyxstone::new("armv8m.main-none-eabi", config)?; check_instruction_ranges(&nyxstone_armv8m, instructions)?; Ok(())