Skip to content

Add support for Rust architecture hook plugins - #8659

Open
zznop wants to merge 8 commits into
devfrom
test_rust_arch_hooks
Open

zznop wants to merge 8 commits into
devfrom
test_rust_arch_hooks

Conversation

@zznop

@zznop zznop commented Oct 13, 2026 •

Copy link
Copy Markdown
Member

Adds ArchitectureHook and register_architecture_hook to the Rust API so plugins can override selected behavior of existing architectures. Default methods delegate to the previous implementation, supporting stacked hooks without recursive calls.

  • Fixes shared Rust API limitations needed for transparent forwarding:
  • Preserves address mutation and normalization, including the ARM Thumb bit.
  • Expands flag-write operations to include floating-point and comparison operations, with a shared Raw representation for other operations.
  • Forwards flag-LLIL queries through CoreArchitecture and honors architecture-level intrinsic-class overrides.
  • Preserves decoded instruction length when lifting returns false.
  • Retains native instruction-token metadata and floating-point payload bits, using field storage consistent with C++.
  • Explicitly forwards function-context destruction through stacked hooks.

The attached demonstration plugin annotates ARM instructions that enable or disable interrupts in the attached binary.

ra4m1_hello_world.ino.elf.zip
lib.rs.zip

@zznop zznop added this to the Langara milestone Oct 13, 2026
@zznop
zznop requested a review from emesare October 13, 2026 17:54
@zznop zznop self-assigned this Oct 13, 2026
@zznop zznop added Component: Architecture Issue needs changes to an architecture plugin Component: Rust API Issue needs changes to the Rust API labels Oct 13, 2026
zznop added 8 commits October 19, 2026 09:29
Introduce ArchitectureHook and register_architecture_hook with default
forwarding to the previous implementation. Preserve address normalization
and architecture-specific flag IL and intrinsic classes when delegating.
Forward flag-write operations unsupported by LowLevelILFlagWriteOp to
the previous architecture with their raw arguments intact, preserving
native floating-point flag semantics.

Route intrinsic-class queries through ArchitectureHook::intrinsic_class
while retaining existing custom-architecture behavior.
Change associated_arch_by_addr to accept &mut u64 and preserve updates
through the shared C callback. Update RISC-V and MSP430 implementations.
Dispatch the shared intrinsic-class callback through Architecture::intrinsic_class.
Default to Intrinsic::class() for known IDs and GeneralIntrinsicClass otherwise,
preserving existing intrinsic implementations.
Add floating-point and comparison variants to LowLevelILFlagWriteOp,
updating decoding, operation/size mapping, and operand conversion together.
Add a shared Raw variant to preserve unrepresented operations and complete
operand lists.
Install an explicit freeFunctionArchContext callback that forwards to the
stored previous implementation. This avoids relying on the core fallback
chain, which is lost when another hook copies the callback table.
Forward the native length and success result together through
CoreArchitecture::instruction_llil, preserving length updates when lifting
returns false.
Store native token fields directly and serialize them without reconstructing
metadata from the typed kind. Preserve widths, operands, values, type names,
and floating-point payload bits, matching C++ behavior.

Keep typed constructors and expose kind() as a convenience view. Add raw C
token comparisons before and after stacked empty hooks, covering native x86,
synthetic metadata, and contextual disassembly.
@zznop
zznop force-pushed the test_rust_arch_hooks branch from d06250a to ef08cf3 Compare October 20, 2026 19:35
@zznop

zznop commented Oct 20, 2026

Copy link
Copy Markdown
Member Author

This PR also addresses the 1st and 5th issue in the list here: https://github.com/Vector35/binaryninja/issues/1479

@emesare emesare left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks much better thanks

can we see about adding an example plugin for modifying the cpuid instr to return a particular cpu

il.AddInstruction(il.Register(4, REG_EAX)); // Reference the register so we know it is read

If not I can see about adding it myself shortly after, i just think a plugin example to go along with this would be beneficial.

}

#[test]
fn test_flag_write_op_round_trip() {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably move this to tests

} else {
operands.as_mut_ptr()
};
let root = BNGetArchitectureFlagWriteLowLevelIL(

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we use CoreArchitecture::flag_write_llil instead of writing raw c for these tests, not very maintainable

let arch = BNGetArchitectureByName(name.as_ptr());
let il = BNCreateLowLevelILFunction(arch, std::ptr::null_mut());
assert!(!il.is_null());
let root = BNGetArchitectureFlagWriteLowLevelIL(

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we use CoreArchitecture::flag_write_llil instead of writing raw c for these tests, not very maintainable

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Component: Architecture Issue needs changes to an architecture plugin Component: Rust API Issue needs changes to the Rust API

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants