def perform_get_instruction_info(self, data, addr): nfo = binaryninja.InstructionInfo() ins = self._get_instruction(data, addr) if not ins: # Failsafe: Assume 2 bytes if we couldn't decode the instruction. binaryninja.log.log_warn( "Could not get instruction @ 0x{:X}, assuming len=2".format( addr)) nfo.length = 2 return nfo nfo.length = ins.length() if self._is_conditional_branch(ins): v = addr + ins.operands[0].immediate_value if v >= self.chip.ROM_SIZE: v -= self.chip.ROM_SIZE elif v < 0: v += self.chip.ROM_SIZE nfo.add_branch(BranchType.TrueBranch, v) nfo.add_branch(BranchType.FalseBranch, addr + 2) elif ins.__class__ in [ instructions.Instruction_CPSE, instructions.Instruction_SBRC, instructions.Instruction_SBRS, instructions.Instruction_SBIC, instructions.Instruction_SBIS, ]: # TODO: This should skip a whole instruction but we don't know how # big the next instruction is (2 or 4 bytes). # Assume two bytes for now as it is pretty much always followed by a # rjmp nfo.add_branch(BranchType.TrueBranch, addr + 4) nfo.add_branch(BranchType.FalseBranch, addr + 2) elif isinstance(ins, instructions.Instruction_JMP): nfo.add_branch(BranchType.UnconditionalBranch, ins.operands[0].immediate_value) elif isinstance(ins, instructions.Instruction_CALL): nfo.add_branch(BranchType.CallDestination, ins.operands[0].immediate_value) elif (isinstance(ins, instructions.Instruction_RET) or isinstance(ins, instructions.Instruction_RETI)): nfo.add_branch(BranchType.FunctionReturn) elif (isinstance(ins, instructions.Instruction_RCALL)): v = addr + ins.operands[0].immediate_value if v >= self.chip.ROM_SIZE: v -= self.chip.ROM_SIZE elif v < 0: v += self.chip.ROM_SIZE nfo.add_branch(BranchType.CallDestination, v) elif (isinstance(ins, instructions.Instruction_RJMP)): v = addr + ins.operands[0].immediate_value if v >= self.chip.ROM_SIZE: v -= self.chip.ROM_SIZE elif v < 0: v += self.chip.ROM_SIZE nfo.add_branch(BranchType.UnconditionalBranch, v) elif (isinstance(ins, instructions.Instruction_ICALL) or isinstance(ins, instructions.Instruction_EICALL) or isinstance(ins, instructions.Instruction_IJMP) or isinstance(ins, instructions.Instruction_EIJMP)): nfo.add_branch(BranchType.IndirectBranch) else: # TODO: Doublecheck that there are no more controlflow modifying # operations. pass return nfo
def info(self): ii = bn.InstructionInfo() if self.delay: ii.branch_delay = True ii.length = len(self) return ii
def get_instruction_info(self, data, addr): instr = WasmDisasm.disasm(data, addr) ins_info = binaryninja.InstructionInfo() ins_info.length = instr.size return ins_info