Source code for angr.analyses.disassembly_utils

import capstone as cs
import logging

from archinfo.arch_arm import is_arm_arch

from ..misc.ux import once

l = logging.getLogger(name=__name__)


INS_GROUP_INFO = {
    "X86": {
        cs.x86.X86_GRP_CALL: "call",
        cs.x86.X86_GRP_JUMP: "branch",
        cs.x86.X86_GRP_RET: "return",
    },
    "AMD64": {
        cs.x86.X86_GRP_CALL: "call",
        cs.x86.X86_GRP_JUMP: "branch",
        cs.x86.X86_GRP_RET: "return",
    },
    "ARM": {
        cs.arm.ARM_GRP_CALL: "call",
        cs.arm.ARM_GRP_BRANCH_RELATIVE: "branch",
        cs.arm.ARM_GRP_JUMP: "branch",
    },
}

INS_GROUP_INFO["ARMEL"] = INS_GROUP_INFO["ARM"]
INS_GROUP_INFO["ARMHF"] = INS_GROUP_INFO["ARM"]
INS_GROUP_INFO["ARMCortexM"] = INS_GROUP_INFO["ARM"]


try:
    INS_GROUP_INFO["MIPS32"] = {
        cs.mips.MIPS_GRP_CALL: "call",
        cs.mips.MIPS_GRP_JUMP: "branch",
        cs.mips.MIPS_GRP_RET: "return",
    }
except AttributeError:
    # The installed capstone is too old - it does not support cs.mips.MIPS_GRP_*
    pass


INS_INFO = {
    "MIPS32": {
        cs.mips.MIPS_INS_JAL: "call",
        cs.mips.MIPS_INS_BAL: "branch",
    }
}


[docs]def decode_instruction(arch, instr): # this is clearly architecture specific arch_name = arch.name if arch_name == "MIPS32" and once("mips-instruction-groups"): l.warning("Your version of capstone does not support MIPS instruction groups.") insn_info = None info = INS_GROUP_INFO.get(arch_name, None) if info is not None: for group in instr.insn.insn.groups: insn_info = info.get(group, None) if insn_info is not None: break if insn_info is None: info = INS_INFO.get(arch_name, None) if info is not None: insn_info = info.get(instr.insn.insn.id, None) if insn_info is None: return instr.type = insn_info if instr.type in ("call", "branch"): # determine if this is a direct or indirect call/branch if arch_name in ("X86", "AMD64"): last_operand = instr.insn.operands[-1] if last_operand.type == cs.x86.X86_OP_IMM: instr.branch_type = "direct" else: instr.branch_type = "indirect" instr.branch_target_operand = len(instr.insn.operands) - 1 elif is_arm_arch(arch): last_operand = instr.insn.operands[-1] if last_operand.type == cs.arm.ARM_OP_IMM: instr.branch_type = "direct" else: instr.branch_type = "indirect" instr.branch_target_operand = len(instr.insn.operands) - 1 elif arch_name == "MIPS32": # check the last operand last_operand = instr.insn.operands[-1] if last_operand.type == cs.mips.MIPS_OP_REG: instr.branch_type = "indirect" else: instr.branch_type = "direct" instr.branch_target_operand = len(instr.insn.operands) - 1