Top

miasm2.ir.analysis module

#-*- coding:utf-8 -*-

import warnings
import logging

from miasm2.ir.ir import IntermediateRepresentation, AssignBlock
from miasm2.expression.expression import ExprOp, ExprAff
from miasm2.analysis.data_flow import dead_simp as new_dead_simp_imp


log = logging.getLogger("analysis")
console_handler = logging.StreamHandler()
console_handler.setFormatter(logging.Formatter("%(levelname)-5s: %(message)s"))
log.addHandler(console_handler)
log.setLevel(logging.WARNING)


class ira(IntermediateRepresentation):
    """IR Analysis
    This class provides higher level manipulations on IR, such as dead
    instruction removals.

    This class can be used as a common parent with
    `miasm2.ir.ir::IntermediateRepresentation` class.

    For instance:
        class ira_x86_16(ir_x86_16, ira)

    """
    ret_reg = None

    def call_effects(self, addr, instr):
        """Default modelisation of a function call to @addr. This may be used to:

        * insert dependencies to arguments (stack base, registers, ...)
        * add some side effects (stack clean, return value, ...)

        Return a couple:
        * list of assignments to add to the current irblock
        * list of additional irblocks

        @addr: (Expr) address of the called function
        @instr: native instruction which is responsible of the call
        """

        call_assignblk = AssignBlock(
            [
                ExprAff(self.ret_reg, ExprOp('call_func_ret', addr, self.sp)),
                ExprAff(self.sp, ExprOp('call_func_stack', addr, self.sp))
            ],
            instr
        )
        return [call_assignblk], []

    def add_instr_to_current_state(self, instr, block, assignments, ir_blocks_all, gen_pc_updt):
        """
        Add the IR effects of an instruction to the current state.
        If the instruction is a function call, replace the original IR by a
        model of the sub function

        Returns a bool:
        * True if the current assignments list must be split
        * False in other cases.

        @instr: native instruction
        @block: native block source
        @assignments: current irbloc
        @ir_blocks_all: list of additional effects
        @gen_pc_updt: insert PC update effects between instructions
        """
        if instr.is_subcall():
            call_assignblks, extra_irblocks = self.call_effects(
                instr.args[0],
                instr
            )
            assignments += call_assignblks
            ir_blocks_all += extra_irblocks
            return True

        if gen_pc_updt is not False:
            self.gen_pc_update(assignments, instr)

        assignblk, ir_blocks_extra = self.instr2ir(instr)
        assignments.append(assignblk)
        ir_blocks_all += ir_blocks_extra
        if ir_blocks_extra:
            return True
        return False

    def sizeof_char(self):
        "Return the size of a char in bits"
        raise NotImplementedError("Abstract method")

    def sizeof_short(self):
        "Return the size of a short in bits"
        raise NotImplementedError("Abstract method")

    def sizeof_int(self):
        "Return the size of an int in bits"
        raise NotImplementedError("Abstract method")

    def sizeof_long(self):
        "Return the size of a long in bits"
        raise NotImplementedError("Abstract method")

    def sizeof_pointer(self):
        "Return the size of a void* in bits"
        raise NotImplementedError("Abstract method")

    def dead_simp(self, ircfg):
        """Deprecated: See miasm2.analysis.data_flow.dead_simp()"""
        warnings.warn('DEPRECATION WARNING: Please use miasm2.analysis.data_flow.dead_simp(ira) instead of ira.dead_simp()')
        new_dead_simp_imp(self, ircfg)

Module variables

var console_handler

var log

Classes

class ira

IR Analysis This class provides higher level manipulations on IR, such as dead instruction removals.

This class can be used as a common parent with miasm2.ir.ir::IntermediateRepresentation class.

For instance: class ira_x86_16(ir_x86_16, ira)

class ira(IntermediateRepresentation):
    """IR Analysis
    This class provides higher level manipulations on IR, such as dead
    instruction removals.

    This class can be used as a common parent with
    `miasm2.ir.ir::IntermediateRepresentation` class.

    For instance:
        class ira_x86_16(ir_x86_16, ira)

    """
    ret_reg = None

    def call_effects(self, addr, instr):
        """Default modelisation of a function call to @addr. This may be used to:

        * insert dependencies to arguments (stack base, registers, ...)
        * add some side effects (stack clean, return value, ...)

        Return a couple:
        * list of assignments to add to the current irblock
        * list of additional irblocks

        @addr: (Expr) address of the called function
        @instr: native instruction which is responsible of the call
        """

        call_assignblk = AssignBlock(
            [
                ExprAff(self.ret_reg, ExprOp('call_func_ret', addr, self.sp)),
                ExprAff(self.sp, ExprOp('call_func_stack', addr, self.sp))
            ],
            instr
        )
        return [call_assignblk], []

    def add_instr_to_current_state(self, instr, block, assignments, ir_blocks_all, gen_pc_updt):
        """
        Add the IR effects of an instruction to the current state.
        If the instruction is a function call, replace the original IR by a
        model of the sub function

        Returns a bool:
        * True if the current assignments list must be split
        * False in other cases.

        @instr: native instruction
        @block: native block source
        @assignments: current irbloc
        @ir_blocks_all: list of additional effects
        @gen_pc_updt: insert PC update effects between instructions
        """
        if instr.is_subcall():
            call_assignblks, extra_irblocks = self.call_effects(
                instr.args[0],
                instr
            )
            assignments += call_assignblks
            ir_blocks_all += extra_irblocks
            return True

        if gen_pc_updt is not False:
            self.gen_pc_update(assignments, instr)

        assignblk, ir_blocks_extra = self.instr2ir(instr)
        assignments.append(assignblk)
        ir_blocks_all += ir_blocks_extra
        if ir_blocks_extra:
            return True
        return False

    def sizeof_char(self):
        "Return the size of a char in bits"
        raise NotImplementedError("Abstract method")

    def sizeof_short(self):
        "Return the size of a short in bits"
        raise NotImplementedError("Abstract method")

    def sizeof_int(self):
        "Return the size of an int in bits"
        raise NotImplementedError("Abstract method")

    def sizeof_long(self):
        "Return the size of a long in bits"
        raise NotImplementedError("Abstract method")

    def sizeof_pointer(self):
        "Return the size of a void* in bits"
        raise NotImplementedError("Abstract method")

    def dead_simp(self, ircfg):
        """Deprecated: See miasm2.analysis.data_flow.dead_simp()"""
        warnings.warn('DEPRECATION WARNING: Please use miasm2.analysis.data_flow.dead_simp(ira) instead of ira.dead_simp()')
        new_dead_simp_imp(self, ircfg)

Ancestors (in MRO)

  • ira
  • miasm2.ir.ir.IntermediateRepresentation
  • __builtin__.object

Class variables

var ret_reg

Methods

def __init__(

self, arch, attrib, loc_db)

def __init__(self, arch, attrib, loc_db):
    self.pc = arch.getpc(attrib)
    self.sp = arch.getsp(attrib)
    self.arch = arch
    self.attrib = attrib
    self.loc_db = loc_db
    self.IRDst = None

def add_asmblock_to_ircfg(

self, block, ircfg, gen_pc_updt=False)

Add a native block to the current IR @block: native assembly block @ircfg: IRCFG instance @gen_pc_updt: insert PC update effects between instructions

def add_asmblock_to_ircfg(self, block, ircfg, gen_pc_updt=False):
    """
    Add a native block to the current IR
    @block: native assembly block
    @ircfg: IRCFG instance
    @gen_pc_updt: insert PC update effects between instructions
    """
    loc_key = block.loc_key
    ir_blocks_all = []
    assignments = []
    for instr in block.lines:
        if loc_key is None:
            assignments = []
            loc_key = self.get_loc_key_for_instr(instr)
        split = self.add_instr_to_current_state(
            instr, block, assignments,
            ir_blocks_all, gen_pc_updt
        )
        if split:
            ir_blocks_all.append(IRBlock(loc_key, assignments))
            loc_key = None
            assignments = []
    if loc_key is not None:
        ir_blocks_all.append(IRBlock(loc_key, assignments))
    new_ir_blocks_all = self.post_add_asmblock_to_ircfg(block, ircfg, ir_blocks_all)
    for irblock in new_ir_blocks_all:
        ircfg.add_irblock(irblock)
    return new_ir_blocks_all

def add_bloc(

self, block, gen_pc_updt=False)

DEPRECATED function Use add_block instead of add_block

def add_bloc(self, block, gen_pc_updt=False):
    """
    DEPRECATED function
    Use add_block instead of add_block
    """
    self.add_block(block, gen_pc_updt)

def add_block(

self, block, gen_pc_updt=False)

DEPRECATED function Use add_block instead of add_block

def add_block(self, block, gen_pc_updt=False):
    """
    DEPRECATED function
    Use add_block instead of add_block
    """
    warnings.warn("""DEPRECATION WARNING
    ircfg is now out of IntermediateRepresentation
    Use:
    ircfg = ir_arch.new_ircfg()
    ir_arch.add_asmblock_to_ircfg(block, ircfg)
    """)
    raise RuntimeError("API Deprecated")

def add_instr_to_current_state(

self, instr, block, assignments, ir_blocks_all, gen_pc_updt)

Add the IR effects of an instruction to the current state. If the instruction is a function call, replace the original IR by a model of the sub function

Returns a bool: True if the current assignments list must be split False in other cases.

@instr: native instruction @block: native block source @assignments: current irbloc @ir_blocks_all: list of additional effects @gen_pc_updt: insert PC update effects between instructions

def add_instr_to_current_state(self, instr, block, assignments, ir_blocks_all, gen_pc_updt):
    """
    Add the IR effects of an instruction to the current state.
    If the instruction is a function call, replace the original IR by a
    model of the sub function
    Returns a bool:
    * True if the current assignments list must be split
    * False in other cases.
    @instr: native instruction
    @block: native block source
    @assignments: current irbloc
    @ir_blocks_all: list of additional effects
    @gen_pc_updt: insert PC update effects between instructions
    """
    if instr.is_subcall():
        call_assignblks, extra_irblocks = self.call_effects(
            instr.args[0],
            instr
        )
        assignments += call_assignblks
        ir_blocks_all += extra_irblocks
        return True
    if gen_pc_updt is not False:
        self.gen_pc_update(assignments, instr)
    assignblk, ir_blocks_extra = self.instr2ir(instr)
    assignments.append(assignblk)
    ir_blocks_all += ir_blocks_extra
    if ir_blocks_extra:
        return True
    return False

def add_instr_to_ircfg(

self, instr, ircfg, loc_key=None, gen_pc_updt=False)

Add the native instruction @instr to the @ircfg @instr: instruction instance @ircfg: IRCFG instance @loc_key: loc_key instance of the instruction destination @gen_pc_updt: insert PC update effects between instructions

def add_instr_to_ircfg(self, instr, ircfg, loc_key=None, gen_pc_updt=False):
    """
    Add the native instruction @instr to the @ircfg
    @instr: instruction instance
    @ircfg: IRCFG instance
    @loc_key: loc_key instance of the instruction destination
    @gen_pc_updt: insert PC update effects between instructions
    """
    if loc_key is None:
        offset = getattr(instr, "offset", None)
        loc_key = self.loc_db.add_location(offset=offset)
    block = AsmBlock(loc_key)
    block.lines = [instr]
    self.add_asmblock_to_ircfg(block, ircfg, gen_pc_updt)
    return loc_key

def call_effects(

self, addr, instr)

Default modelisation of a function call to @addr. This may be used to:

  • insert dependencies to arguments (stack base, registers, ...)
  • add some side effects (stack clean, return value, ...)

Return a couple: list of assignments to add to the current irblock list of additional irblocks

@addr: (Expr) address of the called function @instr: native instruction which is responsible of the call

def call_effects(self, addr, instr):
    """Default modelisation of a function call to @addr. This may be used to:
    * insert dependencies to arguments (stack base, registers, ...)
    * add some side effects (stack clean, return value, ...)
    Return a couple:
    * list of assignments to add to the current irblock
    * list of additional irblocks
    @addr: (Expr) address of the called function
    @instr: native instruction which is responsible of the call
    """
    call_assignblk = AssignBlock(
        [
            ExprAff(self.ret_reg, ExprOp('call_func_ret', addr, self.sp)),
            ExprAff(self.sp, ExprOp('call_func_stack', addr, self.sp))
        ],
        instr
    )
    return [call_assignblk], []

def dead_simp(

self, ircfg)

Deprecated: See miasm2.analysis.data_flow.dead_simp()

def dead_simp(self, ircfg):
    """Deprecated: See miasm2.analysis.data_flow.dead_simp()"""
    warnings.warn('DEPRECATION WARNING: Please use miasm2.analysis.data_flow.dead_simp(ira) instead of ira.dead_simp()')
    new_dead_simp_imp(self, ircfg)

def expr_fix_regs_for_mode(

self, expr, *args, **kwargs)

def expr_fix_regs_for_mode(self, expr, *args, **kwargs):
    return expr

def expraff_fix_regs_for_mode(

self, expr, *args, **kwargs)

def expraff_fix_regs_for_mode(self, expr, *args, **kwargs):
    return expr

def gen_loc_key_and_expr(

self, size)

Return a loc_key and it's corresponding ExprLoc @size: size of expression

def gen_loc_key_and_expr(self, size):
    """
    Return a loc_key and it's corresponding ExprLoc
    @size: size of expression
    """
    loc_key = self.loc_db.add_location()
    return loc_key, m2_expr.ExprLoc(loc_key, size)

def gen_pc_update(

self, assignments, instr)

def gen_pc_update(self, assignments, instr):
    offset = m2_expr.ExprInt(instr.offset, self.pc.size)
    assignments.append(AssignBlock({self.pc:offset}, instr))

def get_ir(

self, instr)

def get_ir(self, instr):
    raise NotImplementedError("Abstract Method")

def get_loc_key_for_instr(

self, instr)

Returns the loc_key associated to an instruction @instr: current instruction

def get_loc_key_for_instr(self, instr):
    """Returns the loc_key associated to an instruction
    @instr: current instruction"""
    return self.loc_db.get_or_create_offset_location(instr.offset)

def get_next_loc_key(

self, instr)

def get_next_loc_key(self, instr):
    loc_key = self.loc_db.get_or_create_offset_location(instr.offset + instr.l)
    return loc_key

def instr2ir(

self, instr)

def instr2ir(self, instr):
    ir_bloc_cur, extra_irblocks = self.get_ir(instr)
    for index, irb in enumerate(extra_irblocks):
        irs = []
        for assignblk in irb:
            irs.append(AssignBlock(assignblk, instr))
        extra_irblocks[index] = IRBlock(irb.loc_key, irs)
    assignblk = AssignBlock(ir_bloc_cur, instr)
    return assignblk, extra_irblocks

def irbloc_fix_regs_for_mode(

self, irblock, *args, **kwargs)

def irbloc_fix_regs_for_mode(self, irblock, *args, **kwargs):
    return irblock

def is_pc_written(

self, block)

Return the first Assignblk of the @blockin which PC is written @block: IRBlock instance

def is_pc_written(self, block):
    """Return the first Assignblk of the @blockin which PC is written
    @block: IRBlock instance"""
    all_pc = self.arch.pc.values()
    for assignblk in block:
        if assignblk.dst in all_pc:
            return assignblk
    return None

def new_ircfg(

self, *args, **kwargs)

Return a new instance of IRCFG

def new_ircfg(self, *args, **kwargs):
    """
    Return a new instance of IRCFG
    """
    return IRCFG(self.IRDst, self.loc_db, *args, **kwargs)

def new_ircfg_from_asmcfg(

self, asmcfg, *args, **kwargs)

Return a new instance of IRCFG from an @asmcfg @asmcfg: AsmCFG instance

def new_ircfg_from_asmcfg(self, asmcfg, *args, **kwargs):
    """
    Return a new instance of IRCFG from an @asmcfg
    @asmcfg: AsmCFG instance
    """
    ircfg = IRCFG(self.IRDst, self.loc_db, *args, **kwargs)
    for block in asmcfg.blocks:
        self.add_asmblock_to_ircfg(block, ircfg)
    return ircfg

def post_add_asmblock_to_ircfg(

self, block, ircfg, ir_blocks)

def post_add_asmblock_to_ircfg(self, block, ircfg, ir_blocks):
    self.set_empty_dst_to_next(block, ir_blocks)
    new_irblocks = []
    for irblock in ir_blocks:
        new_irblock = self.irbloc_fix_regs_for_mode(irblock, self.attrib)
        ircfg.add_irblock(new_irblock)
        new_irblocks.append(new_irblock)
    return new_irblocks

def set_empty_dst_to_next(

self, block, ir_blocks)

def set_empty_dst_to_next(self, block, ir_blocks):
    for index, irblock in enumerate(ir_blocks):
        if irblock.dst is not None:
            continue
        next_loc_key = block.get_next()
        if next_loc_key is None:
            loc_key = None
            if block.lines:
                line = block.lines[-1]
                if line.offset is not None:
                    loc_key = self.loc_db.get_or_create_offset_location(line.offset + line.l)
            if loc_key is None:
                loc_key = self.loc_db.add_location()
            block.add_cst(loc_key, AsmConstraint.c_next)
        else:
            loc_key = next_loc_key
        dst = m2_expr.ExprLoc(loc_key, self.pc.size)
        if irblock.assignblks:
            instr = irblock.assignblks[-1].instr
        else:
            instr = None
        assignblk = AssignBlock({self.IRDst: dst}, instr)
        ir_blocks[index] = IRBlock(irblock.loc_key, list(irblock.assignblks) + [assignblk])

def sizeof_char(

self)

Return the size of a char in bits

def sizeof_char(self):
    "Return the size of a char in bits"
    raise NotImplementedError("Abstract method")

def sizeof_int(

self)

Return the size of an int in bits

def sizeof_int(self):
    "Return the size of an int in bits"
    raise NotImplementedError("Abstract method")

def sizeof_long(

self)

Return the size of a long in bits

def sizeof_long(self):
    "Return the size of a long in bits"
    raise NotImplementedError("Abstract method")

def sizeof_pointer(

self)

Return the size of a void* in bits

def sizeof_pointer(self):
    "Return the size of a void* in bits"
    raise NotImplementedError("Abstract method")

def sizeof_short(

self)

Return the size of a short in bits

def sizeof_short(self):
    "Return the size of a short in bits"
    raise NotImplementedError("Abstract method")