From 73677828aaa0a03d89cbdbd8eb78be611738d64c Mon Sep 17 00:00:00 2001 From: nicolodev Date: Sat, 22 Mar 2025 14:40:42 +0100 Subject: [PATCH] added the option to enable printing the operand as an absolute address --- bindings/rust/examples/cli.rs | 1 + bindings/rust/src/lib.rs | 11 ++++++++++- bindings/rust/src/nyxstone_ffi.cpp | 3 ++- bindings/rust/src/nyxstone_ffi.hpp | 2 +- bindings/rust/tests/validation.rs | 27 +++++++++++++++++++++++++++ include/nyxstone.h | 7 +++++++ src/nyxstone.cpp | 8 ++++++++ 7 files changed, 56 insertions(+), 3 deletions(-) diff --git a/bindings/rust/examples/cli.rs b/bindings/rust/examples/cli.rs index 3f7e5b2..e42fb95 100644 --- a/bindings/rust/examples/cli.rs +++ b/bindings/rust/examples/cli.rs @@ -81,6 +81,7 @@ fn main() -> Result<()> { cpu: &cli.cpu.unwrap_or_default(), features: &cli.features.unwrap_or_default(), immediate_style: IntegerBase::HexPrefix, + print_branch_imm_as_address: false, }, )?; diff --git a/bindings/rust/src/lib.rs b/bindings/rust/src/lib.rs index bcd0796..b10c2f8 100644 --- a/bindings/rust/src/lib.rs +++ b/bindings/rust/src/lib.rs @@ -97,6 +97,7 @@ impl Nyxstone { config.cpu, config.features, config.immediate_style.into(), + config.print_branch_imm_as_address, ); if !result.error.is_empty() { @@ -272,6 +273,8 @@ pub struct NyxstoneConfig<'a, 'b> { pub features: &'b str, /// The printing style of immediates. pub immediate_style: IntegerBase, + /// Option If true, a branch immediate (e.g. bl 4) will be printed as a hexadecimal address (e.g. bl 0x20004) + pub print_branch_imm_as_address: bool, } #[cxx::bridge] @@ -341,7 +344,13 @@ 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, + print_branch_imm_as_address: bool, + ) -> NyxstoneResult; // Translates assembly instructions at a given start address to bytes. // Additional label definitions by absolute address may be supplied. diff --git a/bindings/rust/src/nyxstone_ffi.cpp b/bindings/rust/src/nyxstone_ffi.cpp index c65676f..a4b0763 100644 --- a/bindings/rust/src/nyxstone_ffi.cpp +++ b/bindings/rust/src/nyxstone_ffi.cpp @@ -119,7 +119,7 @@ InstructionResult NyxstoneFFI::disassemble_to_instructions( } NyxstoneResult create_nyxstone_ffi( // cppcheck-suppress unusedFunction - const rust::str triple_name, const rust::str cpu, const rust::str features, const IntegerBase imm_style) + const rust::str triple_name, const rust::str cpu, const rust::str features, const IntegerBase imm_style, const bool print_branch_immediate_as_address) { NyxstoneBuilder::IntegerBase style = static_cast(static_cast(imm_style)); @@ -127,6 +127,7 @@ NyxstoneResult create_nyxstone_ffi( // cppcheck-suppress unusedFunction .with_cpu(std::string { cpu }) .with_features(std::string { features }) .with_immediate_style(style) + .with_print_immediate_as_address(print_branch_immediate_as_address) .build(); // Note: This is disgusting, but this is necesarry for two reasons: diff --git a/bindings/rust/src/nyxstone_ffi.hpp b/bindings/rust/src/nyxstone_ffi.hpp index c5b4516..a8f4a68 100644 --- a/bindings/rust/src/nyxstone_ffi.hpp +++ b/bindings/rust/src/nyxstone_ffi.hpp @@ -54,4 +54,4 @@ class NyxstoneFFI { /// @param cpu The cpu to be used. /// @param features Llvm features string. /// @param imm_style The integer representation for immediates. -NyxstoneResult create_nyxstone_ffi(rust::str triple_name, rust::str cpu, rust::str features, IntegerBase imm_style); +NyxstoneResult create_nyxstone_ffi(rust::str triple_name, rust::str cpu, rust::str features, IntegerBase imm_style, bool print_branch_immediate_as_address); diff --git a/bindings/rust/tests/validation.rs b/bindings/rust/tests/validation.rs index 663100e..7bfaa48 100644 --- a/bindings/rust/tests/validation.rs +++ b/bindings/rust/tests/validation.rs @@ -97,6 +97,33 @@ mod tests { Ok(()) } + #[test] + fn nyxstone_disassemble_with_branch_as_address() -> Result<()> { + let config = NyxstoneConfig { + print_branch_imm_as_address: true, + ..Default::default() + }; + + let labels = HashMap::from([(".label", 0x1010)]); + + let nyxstone_x86_64 = Nyxstone::new("x86_64-linux-gnu", config)?; + + let result = nyxstone_x86_64.assemble_with("jmp .label", 0x1000, &labels)?; + assert_eq!(result, vec![235, 14]); + + let result = nyxstone_x86_64.disassemble_to_instructions(&result, 0x1000, 0)?; + assert_eq!( + result, + vec![Instruction { + address: 0x1000, + assembly: "jmp 0x100e".into(), + bytes: vec![235, 14], + }], + ); + + Ok(()) + } + #[test] fn nyxstone_test() -> Result<()> { let nyxstone_x86_64 = Nyxstone::new("x86_64-linux-gnu", NyxstoneConfig::default())?; diff --git a/include/nyxstone.h b/include/nyxstone.h index 86b05e5..ff7be53 100644 --- a/include/nyxstone.h +++ b/include/nyxstone.h @@ -192,6 +192,11 @@ class NyxstoneBuilder { /// @return Reference to the updated NyxstoneBuilder object. NyxstoneBuilder& with_immediate_style(IntegerBase style) noexcept; + /// @brief Specify if some operands should be printed as an absolute address. + /// + /// @return Reference to the updated NyxstoneBuilder object. + NyxstoneBuilder& with_print_immediate_as_address(bool option) noexcept; + /// @brief Builds a nyxstone instance from the builder. /// /// @return A unique_ptr holding the created nyxstone instance on success, an error string otherwise. @@ -206,6 +211,8 @@ class NyxstoneBuilder { std::string m_features; /// @brief In which style immediates should be represented in disassembly. IntegerBase m_imm_style = IntegerBase::Dec; + /// @brief Option if true a branch immediate will be printed as an absolute address + bool m_print_branch_immediate_as_address = false; }; /// Detects all ARM Thumb architectures. LLVM doesn't seem to have a short way to check this. diff --git a/src/nyxstone.cpp b/src/nyxstone.cpp index 733a5d9..b27a017 100644 --- a/src/nyxstone.cpp +++ b/src/nyxstone.cpp @@ -41,6 +41,12 @@ NyxstoneBuilder& NyxstoneBuilder::with_immediate_style(NyxstoneBuilder::IntegerB return *this; } +NyxstoneBuilder& NyxstoneBuilder::with_print_immediate_as_address(bool option) noexcept +{ + m_print_branch_immediate_as_address = option; + return *this; +} + tl::expected, std::string> NyxstoneBuilder::build() { // # Note @@ -118,6 +124,8 @@ tl::expected, std::string> NyxstoneBuilder::build() break; } + instruction_printer->setPrintBranchImmAsAddress(m_print_branch_immediate_as_address); + return std::make_unique(std::move(triple), // target is a static object, thus it is safe to take its reference here: *target, std::move(target_options), std::move(register_info), std::move(assembler_info),