pub trait Architecture:
'static
+ Sized
+ AsRef<CoreArchitecture> {
type Handle: Borrow<Self> + Clone;
type RegisterInfo: RegisterInfo<RegType = Self::Register>;
type Register: Register<InfoType = Self::RegisterInfo>;
type RegisterStackInfo: RegisterStackInfo<RegType = Self::Register, RegInfoType = Self::RegisterInfo, RegStackType = Self::RegisterStack>;
type RegisterStack: RegisterStack<InfoType = Self::RegisterStackInfo, RegType = Self::Register, RegInfoType = Self::RegisterInfo>;
type Flag: Flag<FlagClass = Self::FlagClass>;
type FlagWrite: FlagWrite<FlagType = Self::Flag, FlagClass = Self::FlagClass>;
type FlagClass: FlagClass;
type FlagGroup: FlagGroup<FlagType = Self::Flag, FlagClass = Self::FlagClass>;
type Intrinsic: Intrinsic;
Show 48 methods
// Required methods
fn endianness(&self) -> Endianness;
fn address_size(&self) -> usize;
fn default_integer_size(&self) -> usize;
fn instruction_alignment(&self) -> usize;
fn max_instr_len(&self) -> usize;
fn instruction_info(
&self,
data: &[u8],
addr: u64,
) -> Option<InstructionInfo>;
fn instruction_text(
&self,
data: &[u8],
addr: u64,
) -> Option<(usize, Vec<InstructionTextToken>)>;
fn instruction_llil(
&self,
data: &[u8],
addr: u64,
il: &LowLevelILMutableFunction,
) -> Option<(usize, bool)>;
fn registers_all(&self) -> Vec<Self::Register>;
fn register_from_id(&self, id: RegisterId) -> Option<Self::Register>;
fn registers_full_width(&self) -> Vec<Self::Register>;
fn stack_pointer_reg(&self) -> Option<Self::Register>;
fn handle(&self) -> Self::Handle;
// Provided methods
fn opcode_display_len(&self) -> usize { ... }
fn associated_arch_by_addr(&self, _addr: u64) -> CoreArchitecture { ... }
fn analyze_basic_blocks(
&self,
function: &mut Function,
context: &mut BasicBlockAnalysisContext,
) { ... }
fn lift_function(
&self,
function: LowLevelILMutableFunction,
context: &mut FunctionLifterContext,
) -> bool { ... }
fn flag_write_llil<'a>(
&self,
flag: Self::Flag,
flag_write_type: Self::FlagWrite,
op: LowLevelILFlagWriteOp<Self::Register>,
il: &'a LowLevelILMutableFunction,
) -> Option<LowLevelILMutableExpression<'a, ValueExpr>> { ... }
fn flags_required_for_flag_condition(
&self,
_condition: FlagCondition,
_class: Option<Self::FlagClass>,
) -> Vec<Self::Flag> { ... }
fn flag_cond_llil<'a>(
&self,
cond: FlagCondition,
class: Option<Self::FlagClass>,
il: &'a LowLevelILMutableFunction,
) -> Option<LowLevelILMutableExpression<'a, ValueExpr>> { ... }
fn flag_group_llil<'a>(
&self,
_group: Self::FlagGroup,
_il: &'a LowLevelILMutableFunction,
) -> Option<LowLevelILMutableExpression<'a, ValueExpr>> { ... }
fn registers_global(&self) -> Vec<Self::Register> { ... }
fn registers_system(&self) -> Vec<Self::Register> { ... }
fn link_reg(&self) -> Option<Self::Register> { ... }
fn register_stacks(&self) -> Vec<Self::RegisterStack> { ... }
fn register_stack_from_id(
&self,
_id: RegisterStackId,
) -> Option<Self::RegisterStack> { ... }
fn flags(&self) -> Vec<Self::Flag> { ... }
fn flag_from_id(&self, _id: FlagId) -> Option<Self::Flag> { ... }
fn flag_write_types(&self) -> Vec<Self::FlagWrite> { ... }
fn flag_write_from_id(&self, _id: FlagWriteId) -> Option<Self::FlagWrite> { ... }
fn flag_classes(&self) -> Vec<Self::FlagClass> { ... }
fn flag_class_from_id(&self, _id: FlagClassId) -> Option<Self::FlagClass> { ... }
fn flag_groups(&self) -> Vec<Self::FlagGroup> { ... }
fn flag_group_from_id(&self, _id: FlagGroupId) -> Option<Self::FlagGroup> { ... }
fn intrinsics(&self) -> Vec<Self::Intrinsic> { ... }
fn intrinsic_class(&self, _id: IntrinsicId) -> BNIntrinsicClass { ... }
fn intrinsic_from_id(&self, _id: IntrinsicId) -> Option<Self::Intrinsic> { ... }
fn can_assemble(&self) -> bool { ... }
fn assemble(&self, _code: &str, _addr: u64) -> Result<Vec<u8>, String> { ... }
fn is_never_branch_patch_available(&self, data: &[u8], addr: u64) -> bool { ... }
fn is_always_branch_patch_available(&self, _data: &[u8], _addr: u64) -> bool { ... }
fn is_invert_branch_patch_available(&self, _data: &[u8], _addr: u64) -> bool { ... }
fn is_skip_and_return_zero_patch_available(
&self,
data: &[u8],
addr: u64,
) -> bool { ... }
fn is_skip_and_return_value_patch_available(
&self,
_data: &[u8],
_addr: u64,
) -> bool { ... }
fn convert_to_nop(&self, _data: &mut [u8], _addr: u64) -> bool { ... }
fn always_branch(&self, _data: &mut [u8], _addr: u64) -> bool { ... }
fn invert_branch(&self, _data: &mut [u8], _addr: u64) -> bool { ... }
fn skip_and_return_value(
&self,
_data: &mut [u8],
_addr: u64,
_value: u64,
) -> bool { ... }
}Expand description
The Architecture trait is the backbone of Binary Ninja’s analysis capabilities. It tells the
core how to interpret the machine code into LLIL, a generic intermediate representation for
program analysis.
To add support for a new Instruction Set Architecture (ISA), you must implement this trait and register it. The core analysis loop relies on your implementation for three critical stages:
- Disassembly (
Architecture::instruction_text): Machine code into human-readable text (e.g.,55->push rbp). - Control Flow Analysis (
Architecture::instruction_info): Identifying where execution goes next (e.g., “This is acallinstruction, it targets address0x401000”). - Lifting (
Architecture::instruction_llil): Translating machine code into Low Level Intermediate Language (LLIL), which enables decompilation and automated analysis.
Required Associated Types§
type Handle: Borrow<Self> + Clone
Sourcetype RegisterInfo: RegisterInfo<RegType = Self::Register>
type RegisterInfo: RegisterInfo<RegType = Self::Register>
The RegisterInfo associated with this architecture.
Sourcetype Register: Register<InfoType = Self::RegisterInfo>
type Register: Register<InfoType = Self::RegisterInfo>
The Register associated with this architecture.
Sourcetype RegisterStackInfo: RegisterStackInfo<RegType = Self::Register, RegInfoType = Self::RegisterInfo, RegStackType = Self::RegisterStack>
type RegisterStackInfo: RegisterStackInfo<RegType = Self::Register, RegInfoType = Self::RegisterInfo, RegStackType = Self::RegisterStack>
The RegisterStackInfo associated with this architecture.
You may only set this to UnusedRegisterStack if Self::RegisterStack is as well.
Sourcetype RegisterStack: RegisterStack<InfoType = Self::RegisterStackInfo, RegType = Self::Register, RegInfoType = Self::RegisterInfo>
type RegisterStack: RegisterStack<InfoType = Self::RegisterStackInfo, RegType = Self::Register, RegInfoType = Self::RegisterInfo>
The RegisterStack associated with this architecture.
If you do not override Architecture::register_stack_from_id and Architecture::register_stacks,
you may set this to UnusedRegisterStack.
Sourcetype Flag: Flag<FlagClass = Self::FlagClass>
type Flag: Flag<FlagClass = Self::FlagClass>
The Flag associated with this architecture.
If you do not override Architecture::flag_from_id and Architecture::flags, you may
set this to UnusedFlag.
Sourcetype FlagWrite: FlagWrite<FlagType = Self::Flag, FlagClass = Self::FlagClass>
type FlagWrite: FlagWrite<FlagType = Self::Flag, FlagClass = Self::FlagClass>
The FlagWrite associated with this architecture.
Can only be set to UnusedFlag if Self::Flag is as well. Otherwise, it is expected that
this points to a custom FlagWrite with the following functions defined:
Sourcetype FlagClass: FlagClass
type FlagClass: FlagClass
The FlagClass associated with this architecture.
Can only be set to UnusedFlag if Self::Flag is as well. Otherwise, it is expected that
this points to a custom FlagClass with the following functions defined:
Sourcetype FlagGroup: FlagGroup<FlagType = Self::Flag, FlagClass = Self::FlagClass>
type FlagGroup: FlagGroup<FlagType = Self::Flag, FlagClass = Self::FlagClass>
The FlagGroup associated with this architecture.
Can only be set to UnusedFlag if Self::Flag is as well. Otherwise, it is expected that
this points to a custom FlagGroup with the following functions defined:
type Intrinsic: Intrinsic
Required Methods§
fn endianness(&self) -> Endianness
fn address_size(&self) -> usize
fn default_integer_size(&self) -> usize
fn instruction_alignment(&self) -> usize
Sourcefn max_instr_len(&self) -> usize
fn max_instr_len(&self) -> usize
The maximum length of an instruction in bytes. This is used to determine the size of the buffer
given to callbacks such as Architecture::instruction_info, Architecture::instruction_text
and Architecture::instruction_llil.
NOTE: The maximum CANNOT be greater than 256.
Sourcefn instruction_info(&self, data: &[u8], addr: u64) -> Option<InstructionInfo>
fn instruction_info(&self, data: &[u8], addr: u64) -> Option<InstructionInfo>
Returns the InstructionInfo at the given virtual address with data.
The InstructionInfo object should always fill the proper length and branches if not, the
next instruction will likely be incorrect.
Sourcefn instruction_text(
&self,
data: &[u8],
addr: u64,
) -> Option<(usize, Vec<InstructionTextToken>)>
fn instruction_text( &self, data: &[u8], addr: u64, ) -> Option<(usize, Vec<InstructionTextToken>)>
Disassembles a raw byte sequence into a human-readable list of text tokens.
This function is responsible for the visual representation of assembly instructions.
It does not define semantics (use Architecture::instruction_llil for that);
it simply tells the UI how to print the instruction.
§Returns
An Option containing a tuple:
usize: The size of the decoded instruction in bytes. Is used to advance to the next instruction.Vec<InstructionTextToken>: A list of text tokens representing the instruction.
Returns None if the bytes do not form a valid instruction.
Sourcefn instruction_llil(
&self,
data: &[u8],
addr: u64,
il: &LowLevelILMutableFunction,
) -> Option<(usize, bool)>
fn instruction_llil( &self, data: &[u8], addr: u64, il: &LowLevelILMutableFunction, ) -> Option<(usize, bool)>
Appends arbitrary low-level il instructions to il.
If None is returned, no instructions were appended and the data is invalid. If Some is returned,
the instructions consumed length is returned (necessary for variable length instruction decoding).
fn registers_all(&self) -> Vec<Self::Register>
fn register_from_id(&self, id: RegisterId) -> Option<Self::Register>
fn registers_full_width(&self) -> Vec<Self::Register>
fn stack_pointer_reg(&self) -> Option<Self::Register>
fn handle(&self) -> Self::Handle
Provided Methods§
Sourcefn opcode_display_len(&self) -> usize
fn opcode_display_len(&self) -> usize
How many bytes to display in the opcode space before displaying a ..., typically set to
the Architecture::max_instr_len, however, can be overridden to display a truncated opcode.
Sourcefn associated_arch_by_addr(&self, _addr: u64) -> CoreArchitecture
fn associated_arch_by_addr(&self, _addr: u64) -> CoreArchitecture
In binaries with multiple architectures, you may wish to associate a specific architecture with a given virtual address. This can be seen in armv7 where odd addresses are associated with the thumb architecture.
Sourcefn analyze_basic_blocks(
&self,
function: &mut Function,
context: &mut BasicBlockAnalysisContext,
)
fn analyze_basic_blocks( &self, function: &mut Function, context: &mut BasicBlockAnalysisContext, )
Performs basic block recovery and commits the results to the function analysis.
NOTE: Only implement this method if function-level analysis is required. Otherwise, do not implement to let default basic block analysis take place.
fn lift_function( &self, function: LowLevelILMutableFunction, context: &mut FunctionLifterContext, ) -> bool
Sourcefn flag_write_llil<'a>(
&self,
flag: Self::Flag,
flag_write_type: Self::FlagWrite,
op: LowLevelILFlagWriteOp<Self::Register>,
il: &'a LowLevelILMutableFunction,
) -> Option<LowLevelILMutableExpression<'a, ValueExpr>>
fn flag_write_llil<'a>( &self, flag: Self::Flag, flag_write_type: Self::FlagWrite, op: LowLevelILFlagWriteOp<Self::Register>, il: &'a LowLevelILMutableFunction, ) -> Option<LowLevelILMutableExpression<'a, ValueExpr>>
Fallback flag value calculation path. This method is invoked when the core is unable to recover the flag using semantics and resorts to emitting instructions that explicitly set each observed flag to the value of an expression returned by this function.
This function MUST NOT append instructions that have side effects.
This function MUST NOT observe the values of other flags.
This function MUST return None or an expression representing a boolean value.
Sourcefn flags_required_for_flag_condition(
&self,
_condition: FlagCondition,
_class: Option<Self::FlagClass>,
) -> Vec<Self::Flag>
fn flags_required_for_flag_condition( &self, _condition: FlagCondition, _class: Option<Self::FlagClass>, ) -> Vec<Self::Flag>
Determines what flags need to be examined to attempt automatic recovery of the flag uses semantics.
If automatic recovery is not possible, the Architecture::flag_cond_llil method will be invoked
to give this Architecture implementation arbitrary control over the expression to be evaluated.
Sourcefn flag_cond_llil<'a>(
&self,
cond: FlagCondition,
class: Option<Self::FlagClass>,
il: &'a LowLevelILMutableFunction,
) -> Option<LowLevelILMutableExpression<'a, ValueExpr>>
fn flag_cond_llil<'a>( &self, cond: FlagCondition, class: Option<Self::FlagClass>, il: &'a LowLevelILMutableFunction, ) -> Option<LowLevelILMutableExpression<'a, ValueExpr>>
This function MUST NOT append instructions that have side effects.
This function MUST NOT observe the values of flags not returned by
flags_required_for_flag_condition.
This function MUST return None or an expression representing a boolean value.
Sourcefn flag_group_llil<'a>(
&self,
_group: Self::FlagGroup,
_il: &'a LowLevelILMutableFunction,
) -> Option<LowLevelILMutableExpression<'a, ValueExpr>>
fn flag_group_llil<'a>( &self, _group: Self::FlagGroup, _il: &'a LowLevelILMutableFunction, ) -> Option<LowLevelILMutableExpression<'a, ValueExpr>>
Performs fallback resolution when the core was unable to recover the semantics of a
LLIL_FLAG_GROUP expression. This occurs when multiple instructions may have set the flags
at the flag group query, or when the FlagGroup::flag_conditions() map doesn’t have an entry
for the FlagClass associated with the FlagWrite type of the expression that last set
the flags required by the FlagGroup group.
In this fallback path, the Architecture must generate the boolean expression in terms of
the values of that flags returned by group’s flags_required method.
This function must return an expression representing a boolean (as in, size of 0) value.
It is not allowed to add any instructions that can cause side effects.
This function must not observe the values of any flag not returned by group’s
flags_required method.
fn registers_global(&self) -> Vec<Self::Register>
fn registers_system(&self) -> Vec<Self::Register>
fn link_reg(&self) -> Option<Self::Register>
Sourcefn register_stacks(&self) -> Vec<Self::RegisterStack>
fn register_stacks(&self) -> Vec<Self::RegisterStack>
List of concrete register stacks for this architecture.
You must override the following functions as well:
Sourcefn register_stack_from_id(
&self,
_id: RegisterStackId,
) -> Option<Self::RegisterStack>
fn register_stack_from_id( &self, _id: RegisterStackId, ) -> Option<Self::RegisterStack>
Get the Self::RegisterStack associated with the given RegisterStackId.
You must override the following functions as well:
Sourcefn flags(&self) -> Vec<Self::Flag>
fn flags(&self) -> Vec<Self::Flag>
List of concrete flags for this architecture.
You must override the following functions as well:
Sourcefn flag_from_id(&self, _id: FlagId) -> Option<Self::Flag>
fn flag_from_id(&self, _id: FlagId) -> Option<Self::Flag>
Get the Self::Flag associated with the given FlagId.
You must override the following functions as well:
Sourcefn flag_write_types(&self) -> Vec<Self::FlagWrite>
fn flag_write_types(&self) -> Vec<Self::FlagWrite>
List of concrete flag write types for this architecture.
You must override the following functions as well:
Sourcefn flag_write_from_id(&self, _id: FlagWriteId) -> Option<Self::FlagWrite>
fn flag_write_from_id(&self, _id: FlagWriteId) -> Option<Self::FlagWrite>
Get the Self::FlagWrite associated with the given FlagWriteId.
You must override the following functions as well:
Sourcefn flag_classes(&self) -> Vec<Self::FlagClass>
fn flag_classes(&self) -> Vec<Self::FlagClass>
List of concrete flag classes for this architecture.
You must override the following functions as well:
Sourcefn flag_class_from_id(&self, _id: FlagClassId) -> Option<Self::FlagClass>
fn flag_class_from_id(&self, _id: FlagClassId) -> Option<Self::FlagClass>
Get the Self::FlagClass associated with the given FlagClassId.
You must override the following functions as well:
Sourcefn flag_groups(&self) -> Vec<Self::FlagGroup>
fn flag_groups(&self) -> Vec<Self::FlagGroup>
List of concrete flag groups for this architecture.
You must override the following functions as well:
Sourcefn flag_group_from_id(&self, _id: FlagGroupId) -> Option<Self::FlagGroup>
fn flag_group_from_id(&self, _id: FlagGroupId) -> Option<Self::FlagGroup>
Get the Self::FlagGroup associated with the given FlagGroupId.
You must override the following functions as well:
Sourcefn intrinsics(&self) -> Vec<Self::Intrinsic>
fn intrinsics(&self) -> Vec<Self::Intrinsic>
List of concrete intrinsics for this architecture.
You must override the following functions as well:
fn intrinsic_class(&self, _id: IntrinsicId) -> BNIntrinsicClass
Sourcefn intrinsic_from_id(&self, _id: IntrinsicId) -> Option<Self::Intrinsic>
fn intrinsic_from_id(&self, _id: IntrinsicId) -> Option<Self::Intrinsic>
Get the Self::Intrinsic associated with the given IntrinsicId.
You must override the following functions as well:
Sourcefn can_assemble(&self) -> bool
fn can_assemble(&self) -> bool
Let the UI display this patch option.
If set to true, you must override Architecture::assemble.
Sourcefn assemble(&self, _code: &str, _addr: u64) -> Result<Vec<u8>, String>
fn assemble(&self, _code: &str, _addr: u64) -> Result<Vec<u8>, String>
Assemble the code at the specified address and return the machine code in bytes.
If overridden, you must set Architecture::can_assemble to true.
Sourcefn is_never_branch_patch_available(&self, data: &[u8], addr: u64) -> bool
fn is_never_branch_patch_available(&self, data: &[u8], addr: u64) -> bool
Let the UI display this patch option.
If set to true, you must override Architecture::invert_branch.
Sourcefn is_always_branch_patch_available(&self, _data: &[u8], _addr: u64) -> bool
fn is_always_branch_patch_available(&self, _data: &[u8], _addr: u64) -> bool
Let the UI display this patch option.
If set to true, you must override Architecture::always_branch.
Sourcefn is_invert_branch_patch_available(&self, _data: &[u8], _addr: u64) -> bool
fn is_invert_branch_patch_available(&self, _data: &[u8], _addr: u64) -> bool
Let the UI display this patch option.
If set to true, you must override Architecture::invert_branch.
Sourcefn is_skip_and_return_zero_patch_available(
&self,
data: &[u8],
addr: u64,
) -> bool
fn is_skip_and_return_zero_patch_available( &self, data: &[u8], addr: u64, ) -> bool
Let the UI display this patch option.
If set to true, you must override Architecture::skip_and_return_value.
Sourcefn is_skip_and_return_value_patch_available(
&self,
_data: &[u8],
_addr: u64,
) -> bool
fn is_skip_and_return_value_patch_available( &self, _data: &[u8], _addr: u64, ) -> bool
Let the UI display this patch option.
If set to true, you must override Architecture::skip_and_return_value.
fn convert_to_nop(&self, _data: &mut [u8], _addr: u64) -> bool
Sourcefn always_branch(&self, _data: &mut [u8], _addr: u64) -> bool
fn always_branch(&self, _data: &mut [u8], _addr: u64) -> bool
Patch the instruction to always branch.
If overridden, you must also override Architecture::is_always_branch_patch_available.
Sourcefn invert_branch(&self, _data: &mut [u8], _addr: u64) -> bool
fn invert_branch(&self, _data: &mut [u8], _addr: u64) -> bool
Patch the instruction to invert the branch condition.
If overridden, you must also override Architecture::is_invert_branch_patch_available.
Sourcefn skip_and_return_value(
&self,
_data: &mut [u8],
_addr: u64,
_value: u64,
) -> bool
fn skip_and_return_value( &self, _data: &mut [u8], _addr: u64, _value: u64, ) -> bool
Patch the instruction to skip and return value.
If overridden, you must also override Architecture::is_skip_and_return_value_patch_available.
Dyn Compatibility§
This trait is not dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.