diff --git a/binaryninjacore.h b/binaryninjacore.h index d36c1767c..0b0c6cddd 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -1738,15 +1738,20 @@ extern "C" void* ctxt, BNDataBuffer* input, BNDataBuffer* output, BNTransformParameter* params, size_t paramCount); } BNCustomTransform; + typedef struct BNBranchInfo + { + BNBranchType branchType; + uint64_t branchTarget; + BNArchitecture* branchArch; // If null, same architecture as instruction + } BNBranchInfo; + typedef struct BNInstructionInfo { size_t length; size_t branchCount; bool archTransitionByTargetAddr; uint8_t delaySlots; - BNBranchType branchType[BN_MAX_INSTRUCTION_BRANCHES]; - uint64_t branchTarget[BN_MAX_INSTRUCTION_BRANCHES]; - BNArchitecture* branchArch[BN_MAX_INSTRUCTION_BRANCHES]; // If null, same architecture as instruction + BNBranchInfo branchInfo[BN_MAX_INSTRUCTION_BRANCHES]; } BNInstructionInfo; typedef enum BNRelocationType diff --git a/python/architecture.py b/python/architecture.py index 29a393a88..c1d8641fc 100644 --- a/python/architecture.py +++ b/python/architecture.py @@ -654,15 +654,15 @@ def _get_instruction_info(self, ctxt, data, addr, max_len, result): result[0].branchCount = len(info.branches) for i in range(0, len(info.branches)): if isinstance(info.branches[i].type, str): - result[0].branchType[i] = BranchType[info.branches[i].type.name] + result[0].branchInfo[i].branchType = BranchType[info.branches[i].type.name] else: - result[0].branchType[i] = info.branches[i].type - result[0].branchTarget[i] = info.branches[i].target + result[0].branchInfo[i].branchType = info.branches[i].type + result[0].branchInfo[i].branchTarget = info.branches[i].target arch = info.branches[i].arch if arch is None: - result[0].branchArch[i] = None + result[0].branchInfo[i].branchArch = None else: - result[0].branchArch[i] = arch.handle + result[0].branchInfo[i].branchArch = arch.handle return True except: log_error(traceback.format_exc()) @@ -2376,13 +2376,12 @@ def get_instruction_info(self, data: bytes, addr: int) -> Optional[InstructionIn result.length = info.length result.arch_transition_by_target_addr = info.archTransitionByTargetAddr result.branch_delay = info.delaySlots - for i in range(0, info.branchCount): - target = info.branchTarget[i] - if info.branchArch[i]: - arch = CoreArchitecture._from_cache(info.branchArch[i]) + for branch_info in info.branchInfo: + if branch_info.branchArch: + arch = CoreArchitecture._from_cache(branch_info.branchArch) else: arch = None - result.add_branch(BranchType(info.branchType[i]), target, arch) + result.add_branch(BranchType(branch_info.branchType), branch_info.branchTarget, arch) return result def get_instruction_text(self, data: bytes, addr: int) -> Optional[Tuple[List['function.InstructionTextToken'], int]]: diff --git a/rust/src/architecture.rs b/rust/src/architecture.rs index 411508402..ead4e3bd6 100644 --- a/rust/src/architecture.rs +++ b/rust/src/architecture.rs @@ -144,19 +144,23 @@ impl BranchInfo { } } -impl From for BNBranchType { +impl From for BNBranchInfo { fn from(value: BranchInfo) -> Self { - match value.kind { - BranchKind::Unresolved => BNBranchType::UnresolvedBranch, - BranchKind::Unconditional(_) => BNBranchType::UnconditionalBranch, - BranchKind::False(_) => BNBranchType::FalseBranch, - BranchKind::True(_) => BNBranchType::TrueBranch, - BranchKind::Call(_) => BNBranchType::CallDestination, - BranchKind::FunctionReturn => BNBranchType::FunctionReturn, - BranchKind::SystemCall => BNBranchType::SystemCall, - BranchKind::Indirect => BNBranchType::IndirectBranch, - BranchKind::Exception => BNBranchType::ExceptionBranch, - BranchKind::UserDefined => BNBranchType::UserDefinedBranch, + Self { + branchType: match value.kind { + BranchKind::Unresolved => BNBranchType::UnresolvedBranch, + BranchKind::Unconditional(_) => BNBranchType::UnconditionalBranch, + BranchKind::False(_) => BNBranchType::FalseBranch, + BranchKind::True(_) => BNBranchType::TrueBranch, + BranchKind::Call(_) => BNBranchType::CallDestination, + BranchKind::FunctionReturn => BNBranchType::FunctionReturn, + BranchKind::SystemCall => BNBranchType::SystemCall, + BranchKind::Indirect => BNBranchType::IndirectBranch, + BranchKind::Exception => BNBranchType::ExceptionBranch, + BranchKind::UserDefined => BNBranchType::UserDefinedBranch, + }, + branchTarget: value.target().unwrap_or_default(), + branchArch: value.arch.map(|a| a.handle).unwrap_or(std::ptr::null_mut()), } } } @@ -207,13 +211,16 @@ impl InstructionInfo { impl From for InstructionInfo { fn from(value: BNInstructionInfo) -> Self { - // TODO: This is quite ugly, but we destructure the branch info so this will have to do. let mut branch_info = [None; NUM_BRANCH_INFO]; - #[allow(clippy::needless_range_loop)] - for i in 0..value.branchCount.min(NUM_BRANCH_INFO) { - let branch_target = value.branchTarget[i]; + for (i, info) in value + .branchInfo + .iter() + .take(value.branchCount.min(NUM_BRANCH_INFO)) + .enumerate() + { + let branch_target = info.branchTarget; branch_info[i] = Some(BranchInfo { - kind: match value.branchType[i] { + kind: match info.branchType { BNBranchType::UnconditionalBranch => BranchKind::Unconditional(branch_target), BNBranchType::FalseBranch => BranchKind::False(branch_target), BNBranchType::TrueBranch => BranchKind::True(branch_target), @@ -225,10 +232,10 @@ impl From for InstructionInfo { BNBranchType::UnresolvedBranch => BranchKind::Unresolved, BNBranchType::UserDefinedBranch => BranchKind::UserDefined, }, - arch: if value.branchArch[i].is_null() { + arch: if info.branchArch.is_null() { None } else { - Some(unsafe { CoreArchitecture::from_raw(value.branchArch[i]) }) + Some(unsafe { CoreArchitecture::from_raw(info.branchArch) }) }, }); } @@ -244,38 +251,15 @@ impl From for InstructionInfo { impl From for BNInstructionInfo { fn from(value: InstructionInfo) -> Self { let branch_count = value.branches.into_iter().filter(Option::is_some).count(); - // TODO: This is quite ugly, but we destructure the branch info so this will have to do. - let branch_info_0 = value.branches[0].unwrap_or_default(); - let branch_info_1 = value.branches[1].unwrap_or_default(); - let branch_info_2 = value.branches[2].unwrap_or_default(); Self { length: value.length, branchCount: branch_count, archTransitionByTargetAddr: value.arch_transition_by_target_addr, delaySlots: value.delay_slots, - branchType: [ - branch_info_0.into(), - branch_info_1.into(), - branch_info_2.into(), - ], - branchTarget: [ - branch_info_0.target().unwrap_or_default(), - branch_info_1.target().unwrap_or_default(), - branch_info_2.target().unwrap_or_default(), - ], - branchArch: [ - branch_info_0 - .arch - .map(|a| a.handle) - .unwrap_or(std::ptr::null_mut()), - branch_info_1 - .arch - .map(|a| a.handle) - .unwrap_or(std::ptr::null_mut()), - branch_info_2 - .arch - .map(|a| a.handle) - .unwrap_or(std::ptr::null_mut()), + branchInfo: [ + value.branches[0].unwrap_or_default().into(), + value.branches[1].unwrap_or_default().into(), + value.branches[2].unwrap_or_default().into(), ], } }