Top

miasm2.arch.mep.jit module

# Toshiba MeP-c4 - miasm jitter
# Guillaume Valadon <guillaume@valadon.net>
# Note: inspiration from msp430/jit.py

from miasm2.jitter.jitload import Jitter
from miasm2.core.locationdb import LocationDB
from miasm2.core.utils import *
from miasm2.jitter.codegen import CGen
from miasm2.ir.translators.C import TranslatorC
from miasm2.arch.mep.sem import ir_mepl, ir_mepb

import logging

log = logging.getLogger("jit_mep")
hnd = logging.StreamHandler()
hnd.setFormatter(logging.Formatter("[%(levelname)s]: %(message)s"))
log.addHandler(hnd)
log.setLevel(logging.CRITICAL)


class mep_CGen(CGen):
    """
    Translate a bloc containing MeP instructions to C

    Note: it is used to emulate the *REPEAT instructions
    """

    def __init__(self, ir_arch):
        self.ir_arch = ir_arch
        self.PC = self.ir_arch.arch.regs.PC
        self.translator = TranslatorC(self.ir_arch.loc_db)
        self.init_arch_C()

    def gen_pre_code(self, attrib):
        """Generate C code inserted before the current bloc"""

        # Call the base class method
        out = super(mep_CGen, self).gen_pre_code(attrib)

        # Set the PC register value explicitly
        out.append("mycpu->PC = 0x%X;" % attrib.instr.offset)
        out.append("mycpu->last_addr = mycpu->PC;");

        return out

    def gen_post_code(self, attrib):
        """Generate C code inserted after the current bloc"""

        # Call the base class method
        out = super(mep_CGen, self).gen_post_code(attrib)

        # Implement the *REPEAT instructions logics
        tmp = r"""
        /* *REPEAT instructions logic */
        {
            uint32_t is_repeat_end = mycpu->is_repeat_end;
            mycpu->is_repeat_end = !!(mycpu->last_addr == (mycpu->RPE&~0x1));

            if (is_repeat_end && !mycpu->take_jmp &&
                   (mycpu->in_erepeat || mycpu->RPC)) {
                 if (mycpu->RPC)
                       mycpu->RPC --;

                 //printf("Go repeat  %X\n", mycpu->RPB);
                 DST_value = mycpu->RPB;
                 BlockDst->address = mycpu->RPB;
                 return JIT_RET_NO_EXCEPTION;
             }
        }
        """

        out += tmp.split('`\n')
        return out


class jitter_mepl(Jitter):

    C_Gen = mep_CGen

    def __init__(self, *args, **kwargs):
        sp = LocationDB()
        Jitter.__init__(self, ir_mepl(sp), *args, **kwargs)
        self.vm.set_little_endian()
        self.ir_arch.jit_pc = self.ir_arch.arch.regs.PC

    def push_uint16_t(self, v):
        regs = self.cpu.get_gpreg()
        regs["SP"] -= 2
        self.cpu.set_gpreg(regs)
        self.vm.set_mem(regs["SP"], pck16(v))

    def pop_uint16_t(self):
        regs = self.cpu.get_gpreg()
        x = upck16(self.vm.get_mem(regs["SP"], 2))
        regs["SP"] += 2
        self.cpu.set_gpreg(regs)
        return x

    def get_stack_arg(self, n):
        regs = self.cpu.get_gpreg()
        x = upck16(self.vm.get_mem(regs["SP"] + 2 * n, 2))
        return x

    def init_run(self, *args, **kwargs):
        Jitter.init_run(self, *args, **kwargs)
        self.cpu.PC = self.pc


class jitter_mepb(jitter_mepl):

    def __init__(self, *args, **kwargs):
        sp = LocationDB()
        Jitter.__init__(self, ir_mepb(sp), *args, **kwargs)
        self.vm.set_big_endian()
        self.ir_arch.jit_pc = self.ir_arch.arch.regs.PC

Module variables

var hnd

var log

var pck

Classes

class jitter_mepb

class jitter_mepb(jitter_mepl):

    def __init__(self, *args, **kwargs):
        sp = LocationDB()
        Jitter.__init__(self, ir_mepb(sp), *args, **kwargs)
        self.vm.set_big_endian()
        self.ir_arch.jit_pc = self.ir_arch.arch.regs.PC

Ancestors (in MRO)

Class variables

var C_Gen

Inheritance: jitter_mepl.C_Gen

Static methods

def handle_lib(

jitter)

Inheritance: jitter_mepl.handle_lib

Resolve the name of the function which cause the handler call. Then call the corresponding handler from users callback.

@staticmethod
def handle_lib(jitter):
    """Resolve the name of the function which cause the handler call. Then
    call the corresponding handler from users callback.
    """
    fname = jitter.libs.fad2cname[jitter.pc]
    if fname in jitter.user_globals:
        func = jitter.user_globals[fname]
    else:
        log.debug('%r', fname)
        raise ValueError('unknown api', hex(jitter.pc), repr(fname))
    ret = func(jitter)
    jitter.pc = getattr(jitter.cpu, jitter.ir_arch.pc.name)
    # Don't break on a None return
    if ret is None:
        return True
    else:
        return ret

Methods

def __init__(

self, *args, **kwargs)

Inheritance: jitter_mepl.__init__

def __init__(self, *args, **kwargs):
    sp = LocationDB()
    Jitter.__init__(self, ir_mepb(sp), *args, **kwargs)
    self.vm.set_big_endian()
    self.ir_arch.jit_pc = self.ir_arch.arch.regs.PC

def add_breakpoint(

self, addr, callback)

Inheritance: jitter_mepl.add_breakpoint

Add a callback associated with addr. @addr: breakpoint address @callback: function with definition (jitter instance)

def add_breakpoint(self, addr, callback):
    """Add a callback associated with addr.
    @addr: breakpoint address
    @callback: function with definition (jitter instance)
    """
    self.breakpoints_handler.add_callback(addr, callback)
    self.jit.add_disassembly_splits(addr)
    # De-jit previously jitted blocks
    self.jit.updt_automod_code_range(self.vm, [(addr, addr)])

def add_exception_handler(

self, flag, callback)

Inheritance: jitter_mepl.add_exception_handler

Add a callback associated with an exception flag. @flag: bitflag @callback: function with definition (jitter instance)

def add_exception_handler(self, flag, callback):
    """Add a callback associated with an exception flag.
    @flag: bitflag
    @callback: function with definition (jitter instance)
    """
    self.exceptions_handler.add_callback(flag, callback)

def add_lib_handler(

self, libs, user_globals=None)

Inheritance: jitter_mepl.add_lib_handler

Add a function to handle libs call with breakpoints @libs: libimp instance @user_globals: dictionary for defined user function

def add_lib_handler(self, libs, user_globals=None):
    """Add a function to handle libs call with breakpoints
    @libs: libimp instance
    @user_globals: dictionary for defined user function
    """
    if user_globals is None:
        user_globals = {}
    self.libs = libs
    self.user_globals = user_globals
    for f_addr in libs.fad2cname:
        self.handle_function(f_addr)

def continue_run(

self, step=False)

Inheritance: jitter_mepl.continue_run

PRE: init_run. Continue the run of the current session until iterator returns or run is set to False. If step is True, run only one time. Return the iterator value

def continue_run(self, step=False):
    """PRE: init_run.
    Continue the run of the current session until iterator returns or run is
    set to False.
    If step is True, run only one time.
    Return the iterator value"""
    while self.run:
        try:
            return self.run_iterator.next()
        except StopIteration:
            pass
        self.run_iterator = self.runiter_once(self.pc)
        if step is True:
            return None
    return None

def eval_expr(

self, expr)

Inheritance: jitter_mepl.eval_expr

Eval expression @expr in the context of the current instance. Side effects are passed on it

def eval_expr(self, expr):
    """Eval expression @expr in the context of the current instance. Side
    effects are passed on it"""
    self.symbexec.update_engine_from_cpu()
    ret = self.symbexec.eval_updt_expr(expr)
    self.symbexec.update_cpu_from_engine()
    return ret

def get_breakpoint(

self, addr)

Inheritance: jitter_mepl.get_breakpoint

Return breakpoints handlers for address @addr @addr: integer

def get_breakpoint(self, addr):
    """
    Return breakpoints handlers for address @addr
    @addr: integer
    """
    return self.breakpoints_handler.get_callbacks(addr)

def get_exception(

self)

Inheritance: jitter_mepl.get_exception

def get_exception(self):
    return self.cpu.get_exception() | self.vm.get_exception()

def get_stack_arg(

self, n)

Inheritance: jitter_mepl.get_stack_arg

def get_stack_arg(self, n):
    regs = self.cpu.get_gpreg()
    x = upck16(self.vm.get_mem(regs["SP"] + 2 * n, 2))
    return x

def get_str_ansi(

self, addr, max_char=None)

Inheritance: jitter_mepl.get_str_ansi

Get ansi str from vm. @addr: address in memory @max_char: maximum len

def get_str_ansi(self, addr, max_char=None):
    """Get ansi str from vm.
    @addr: address in memory
    @max_char: maximum len"""
    l = 0
    tmp = addr
    while ((max_char is None or l < max_char) and
           self.vm.get_mem(tmp, 1) != "\x00"):
        tmp += 1
        l += 1
    return self.vm.get_mem(addr, l)

def get_str_unic(

self, addr, max_char=None)

Inheritance: jitter_mepl.get_str_unic

Get unicode str from vm. @addr: address in memory @max_char: maximum len

def get_str_unic(self, addr, max_char=None):
    """Get unicode str from vm.
    @addr: address in memory
    @max_char: maximum len"""
    l = 0
    tmp = addr
    while ((max_char is None or l < max_char) and
           self.vm.get_mem(tmp, 2) != "\x00\x00"):
        tmp += 2
        l += 2
    s = self.vm.get_mem(addr, l)
    s = s[::2]  # TODO: real unicode decoding
    return s

def handle_function(

self, f_addr)

Inheritance: jitter_mepl.handle_function

Add a breakpoint which will trigger the function handler

def handle_function(self, f_addr):
    """Add a breakpoint which will trigger the function handler"""
    self.add_breakpoint(f_addr, self.handle_lib)

def init_exceptions_handler(

self)

Inheritance: jitter_mepl.init_exceptions_handler

Add common exceptions handlers

def init_exceptions_handler(self):
    "Add common exceptions handlers"
    def exception_automod(jitter):
        "Tell the JiT backend to update blocks modified"
        self.jit.updt_automod_code(jitter.vm)
        self.vm.set_exception(0)
        return True
    def exception_memory_breakpoint(jitter):
        "Stop the execution and return an identifier"
        return ExceptionHandle.memoryBreakpoint()
    self.add_exception_handler(EXCEPT_CODE_AUTOMOD, exception_automod)
    self.add_exception_handler(EXCEPT_BREAKPOINT_MEMORY,
                               exception_memory_breakpoint)

def init_run(

self, *args, **kwargs)

Inheritance: jitter_mepl.init_run

def init_run(self, *args, **kwargs):
    Jitter.init_run(self, *args, **kwargs)
    self.cpu.PC = self.pc

def init_stack(

self)

Inheritance: jitter_mepl.init_stack

def init_stack(self):
    self.vm.add_memory_page(
        self.stack_base, PAGE_READ | PAGE_WRITE, "\x00" * self.stack_size,
        "Stack")
    sp = self.arch.getsp(self.attrib)
    setattr(self.cpu, sp.name, self.stack_base + self.stack_size)

def pop_uint16_t(

self)

Inheritance: jitter_mepl.pop_uint16_t

def pop_uint16_t(self):
    regs = self.cpu.get_gpreg()
    x = upck16(self.vm.get_mem(regs["SP"], 2))
    regs["SP"] += 2
    self.cpu.set_gpreg(regs)
    return x

def push_uint16_t(

self, v)

Inheritance: jitter_mepl.push_uint16_t

def push_uint16_t(self, v):
    regs = self.cpu.get_gpreg()
    regs["SP"] -= 2
    self.cpu.set_gpreg(regs)
    self.vm.set_mem(regs["SP"], pck16(v))

def remove_breakpoints_by_callback(

self, callback)

Inheritance: jitter_mepl.remove_breakpoints_by_callback

Remove callbacks associated with breakpoint. @callback: callback to remove

def remove_breakpoints_by_callback(self, callback):
    """Remove callbacks associated with breakpoint.
    @callback: callback to remove
    """
    empty_keys = self.breakpoints_handler.remove_callback(callback)
    for key in empty_keys:
        self.jit.remove_disassembly_splits(key)

def run_at(

self, pc)

Inheritance: jitter_mepl.run_at

Wrapper on JiT backend. Run the code at PC and return the next PC. @pc: address of code to run

def run_at(self, pc):
    """Wrapper on JiT backend. Run the code at PC and return the next PC.
    @pc: address of code to run"""
    return self.jit.run_at(
        self.cpu, pc,
        set(self.breakpoints_handler.callbacks.keys())
    )

def runiter_once(

self, pc)

Inheritance: jitter_mepl.runiter_once

Iterator on callbacks results on code running from PC. Check exceptions before breakpoints.

def runiter_once(self, pc):
    """Iterator on callbacks results on code running from PC.
    Check exceptions before breakpoints."""
    self.pc = pc
    # Callback called before exec
    if self.exec_cb is not None:
        res = self.exec_cb(self)
        if res is not True:
            yield res
    # Check breakpoints
    old_pc = self.pc
    for res in self.breakpoints_handler.call_callbacks(self.pc, self):
        if res is not True:
            if isinstance(res, collections.Iterator):
                # If the breakpoint is a generator, yield it step by step
                for tmp in res:
                    yield tmp
            else:
                yield res
    # Check exceptions (raised by breakpoints)
    exception_flag = self.get_exception()
    for res in self.exceptions_handler(exception_flag, self):
        if res is not True:
            if isinstance(res, collections.Iterator):
                for tmp in res:
                    yield tmp
            else:
                yield res
    # If a callback changed pc, re call every callback
    if old_pc != self.pc:
        return
    # Exceptions should never be activated before run
    assert(self.get_exception() == 0)
    # Run the bloc at PC
    self.pc = self.run_at(self.pc)
    # Check exceptions (raised by the execution of the block)
    exception_flag = self.get_exception()
    for res in self.exceptions_handler(exception_flag, self):
        if res is not True:
            if isinstance(res, collections.Iterator):
                for tmp in res:
                    yield tmp
            else:
                yield res

def set_breakpoint(

self, addr, *args)

Inheritance: jitter_mepl.set_breakpoint

Set callbacks associated with addr. @addr: breakpoint address @args: functions with definition (jitter instance)

def set_breakpoint(self, addr, *args):
    """Set callbacks associated with addr.
    @addr: breakpoint address
    @args: functions with definition (jitter instance)
    """
    self.breakpoints_handler.set_callback(addr, *args)
    self.jit.add_disassembly_splits(addr)

def set_str_ansi(

self, addr, s)

Inheritance: jitter_mepl.set_str_ansi

Set an ansi string in memory

def set_str_ansi(self, addr, s):
    """Set an ansi string in memory"""
    s = s + "\x00"
    self.vm.set_mem(addr, s)

def set_str_unic(

self, addr, s)

Inheritance: jitter_mepl.set_str_unic

Set an unicode string in memory

def set_str_unic(self, addr, s):
    """Set an unicode string in memory"""
    s = "\x00".join(list(s)) + '\x00' * 3
    self.vm.set_mem(addr, s)

def set_trace_log(

self, trace_instr=True, trace_regs=True, trace_new_blocks=False)

Inheritance: jitter_mepl.set_trace_log

Activate/Deactivate trace log options

@trace_instr: activate instructions tracing log @trace_regs: activate registers tracing log @trace_new_blocks: dump new code blocks log

def set_trace_log(self,
                  trace_instr=True, trace_regs=True,
                  trace_new_blocks=False):
    """
    Activate/Deactivate trace log options
    @trace_instr: activate instructions tracing log
    @trace_regs: activate registers tracing log
    @trace_new_blocks: dump new code blocks log
    """
    # As trace state changes, clear already jitted blocks
    self.jit.clear_jitted_blocks()
    self.jit.log_mn = trace_instr
    self.jit.log_regs = trace_regs
    self.jit.log_newbloc = trace_new_blocks

class jitter_mepl

class jitter_mepl(Jitter):

    C_Gen = mep_CGen

    def __init__(self, *args, **kwargs):
        sp = LocationDB()
        Jitter.__init__(self, ir_mepl(sp), *args, **kwargs)
        self.vm.set_little_endian()
        self.ir_arch.jit_pc = self.ir_arch.arch.regs.PC

    def push_uint16_t(self, v):
        regs = self.cpu.get_gpreg()
        regs["SP"] -= 2
        self.cpu.set_gpreg(regs)
        self.vm.set_mem(regs["SP"], pck16(v))

    def pop_uint16_t(self):
        regs = self.cpu.get_gpreg()
        x = upck16(self.vm.get_mem(regs["SP"], 2))
        regs["SP"] += 2
        self.cpu.set_gpreg(regs)
        return x

    def get_stack_arg(self, n):
        regs = self.cpu.get_gpreg()
        x = upck16(self.vm.get_mem(regs["SP"] + 2 * n, 2))
        return x

    def init_run(self, *args, **kwargs):
        Jitter.init_run(self, *args, **kwargs)
        self.cpu.PC = self.pc

Ancestors (in MRO)

  • jitter_mepl
  • miasm2.jitter.jitload.Jitter
  • __builtin__.object

Class variables

var C_Gen

Static methods

def handle_lib(

jitter)

Resolve the name of the function which cause the handler call. Then call the corresponding handler from users callback.

@staticmethod
def handle_lib(jitter):
    """Resolve the name of the function which cause the handler call. Then
    call the corresponding handler from users callback.
    """
    fname = jitter.libs.fad2cname[jitter.pc]
    if fname in jitter.user_globals:
        func = jitter.user_globals[fname]
    else:
        log.debug('%r', fname)
        raise ValueError('unknown api', hex(jitter.pc), repr(fname))
    ret = func(jitter)
    jitter.pc = getattr(jitter.cpu, jitter.ir_arch.pc.name)
    # Don't break on a None return
    if ret is None:
        return True
    else:
        return ret

Methods

def __init__(

self, *args, **kwargs)

def __init__(self, *args, **kwargs):
    sp = LocationDB()
    Jitter.__init__(self, ir_mepl(sp), *args, **kwargs)
    self.vm.set_little_endian()
    self.ir_arch.jit_pc = self.ir_arch.arch.regs.PC

def add_breakpoint(

self, addr, callback)

Add a callback associated with addr. @addr: breakpoint address @callback: function with definition (jitter instance)

def add_breakpoint(self, addr, callback):
    """Add a callback associated with addr.
    @addr: breakpoint address
    @callback: function with definition (jitter instance)
    """
    self.breakpoints_handler.add_callback(addr, callback)
    self.jit.add_disassembly_splits(addr)
    # De-jit previously jitted blocks
    self.jit.updt_automod_code_range(self.vm, [(addr, addr)])

def add_exception_handler(

self, flag, callback)

Add a callback associated with an exception flag. @flag: bitflag @callback: function with definition (jitter instance)

def add_exception_handler(self, flag, callback):
    """Add a callback associated with an exception flag.
    @flag: bitflag
    @callback: function with definition (jitter instance)
    """
    self.exceptions_handler.add_callback(flag, callback)

def add_lib_handler(

self, libs, user_globals=None)

Add a function to handle libs call with breakpoints @libs: libimp instance @user_globals: dictionary for defined user function

def add_lib_handler(self, libs, user_globals=None):
    """Add a function to handle libs call with breakpoints
    @libs: libimp instance
    @user_globals: dictionary for defined user function
    """
    if user_globals is None:
        user_globals = {}
    self.libs = libs
    self.user_globals = user_globals
    for f_addr in libs.fad2cname:
        self.handle_function(f_addr)

def continue_run(

self, step=False)

PRE: init_run. Continue the run of the current session until iterator returns or run is set to False. If step is True, run only one time. Return the iterator value

def continue_run(self, step=False):
    """PRE: init_run.
    Continue the run of the current session until iterator returns or run is
    set to False.
    If step is True, run only one time.
    Return the iterator value"""
    while self.run:
        try:
            return self.run_iterator.next()
        except StopIteration:
            pass
        self.run_iterator = self.runiter_once(self.pc)
        if step is True:
            return None
    return None

def eval_expr(

self, expr)

Eval expression @expr in the context of the current instance. Side effects are passed on it

def eval_expr(self, expr):
    """Eval expression @expr in the context of the current instance. Side
    effects are passed on it"""
    self.symbexec.update_engine_from_cpu()
    ret = self.symbexec.eval_updt_expr(expr)
    self.symbexec.update_cpu_from_engine()
    return ret

def get_breakpoint(

self, addr)

Return breakpoints handlers for address @addr @addr: integer

def get_breakpoint(self, addr):
    """
    Return breakpoints handlers for address @addr
    @addr: integer
    """
    return self.breakpoints_handler.get_callbacks(addr)

def get_exception(

self)

def get_exception(self):
    return self.cpu.get_exception() | self.vm.get_exception()

def get_stack_arg(

self, n)

def get_stack_arg(self, n):
    regs = self.cpu.get_gpreg()
    x = upck16(self.vm.get_mem(regs["SP"] + 2 * n, 2))
    return x

def get_str_ansi(

self, addr, max_char=None)

Get ansi str from vm. @addr: address in memory @max_char: maximum len

def get_str_ansi(self, addr, max_char=None):
    """Get ansi str from vm.
    @addr: address in memory
    @max_char: maximum len"""
    l = 0
    tmp = addr
    while ((max_char is None or l < max_char) and
           self.vm.get_mem(tmp, 1) != "\x00"):
        tmp += 1
        l += 1
    return self.vm.get_mem(addr, l)

def get_str_unic(

self, addr, max_char=None)

Get unicode str from vm. @addr: address in memory @max_char: maximum len

def get_str_unic(self, addr, max_char=None):
    """Get unicode str from vm.
    @addr: address in memory
    @max_char: maximum len"""
    l = 0
    tmp = addr
    while ((max_char is None or l < max_char) and
           self.vm.get_mem(tmp, 2) != "\x00\x00"):
        tmp += 2
        l += 2
    s = self.vm.get_mem(addr, l)
    s = s[::2]  # TODO: real unicode decoding
    return s

def handle_function(

self, f_addr)

Add a breakpoint which will trigger the function handler

def handle_function(self, f_addr):
    """Add a breakpoint which will trigger the function handler"""
    self.add_breakpoint(f_addr, self.handle_lib)

def init_exceptions_handler(

self)

Add common exceptions handlers

def init_exceptions_handler(self):
    "Add common exceptions handlers"
    def exception_automod(jitter):
        "Tell the JiT backend to update blocks modified"
        self.jit.updt_automod_code(jitter.vm)
        self.vm.set_exception(0)
        return True
    def exception_memory_breakpoint(jitter):
        "Stop the execution and return an identifier"
        return ExceptionHandle.memoryBreakpoint()
    self.add_exception_handler(EXCEPT_CODE_AUTOMOD, exception_automod)
    self.add_exception_handler(EXCEPT_BREAKPOINT_MEMORY,
                               exception_memory_breakpoint)

def init_run(

self, *args, **kwargs)

def init_run(self, *args, **kwargs):
    Jitter.init_run(self, *args, **kwargs)
    self.cpu.PC = self.pc

def init_stack(

self)

def init_stack(self):
    self.vm.add_memory_page(
        self.stack_base, PAGE_READ | PAGE_WRITE, "\x00" * self.stack_size,
        "Stack")
    sp = self.arch.getsp(self.attrib)
    setattr(self.cpu, sp.name, self.stack_base + self.stack_size)

def pop_uint16_t(

self)

def pop_uint16_t(self):
    regs = self.cpu.get_gpreg()
    x = upck16(self.vm.get_mem(regs["SP"], 2))
    regs["SP"] += 2
    self.cpu.set_gpreg(regs)
    return x

def push_uint16_t(

self, v)

def push_uint16_t(self, v):
    regs = self.cpu.get_gpreg()
    regs["SP"] -= 2
    self.cpu.set_gpreg(regs)
    self.vm.set_mem(regs["SP"], pck16(v))

def remove_breakpoints_by_callback(

self, callback)

Remove callbacks associated with breakpoint. @callback: callback to remove

def remove_breakpoints_by_callback(self, callback):
    """Remove callbacks associated with breakpoint.
    @callback: callback to remove
    """
    empty_keys = self.breakpoints_handler.remove_callback(callback)
    for key in empty_keys:
        self.jit.remove_disassembly_splits(key)

def run_at(

self, pc)

Wrapper on JiT backend. Run the code at PC and return the next PC. @pc: address of code to run

def run_at(self, pc):
    """Wrapper on JiT backend. Run the code at PC and return the next PC.
    @pc: address of code to run"""
    return self.jit.run_at(
        self.cpu, pc,
        set(self.breakpoints_handler.callbacks.keys())
    )

def runiter_once(

self, pc)

Iterator on callbacks results on code running from PC. Check exceptions before breakpoints.

def runiter_once(self, pc):
    """Iterator on callbacks results on code running from PC.
    Check exceptions before breakpoints."""
    self.pc = pc
    # Callback called before exec
    if self.exec_cb is not None:
        res = self.exec_cb(self)
        if res is not True:
            yield res
    # Check breakpoints
    old_pc = self.pc
    for res in self.breakpoints_handler.call_callbacks(self.pc, self):
        if res is not True:
            if isinstance(res, collections.Iterator):
                # If the breakpoint is a generator, yield it step by step
                for tmp in res:
                    yield tmp
            else:
                yield res
    # Check exceptions (raised by breakpoints)
    exception_flag = self.get_exception()
    for res in self.exceptions_handler(exception_flag, self):
        if res is not True:
            if isinstance(res, collections.Iterator):
                for tmp in res:
                    yield tmp
            else:
                yield res
    # If a callback changed pc, re call every callback
    if old_pc != self.pc:
        return
    # Exceptions should never be activated before run
    assert(self.get_exception() == 0)
    # Run the bloc at PC
    self.pc = self.run_at(self.pc)
    # Check exceptions (raised by the execution of the block)
    exception_flag = self.get_exception()
    for res in self.exceptions_handler(exception_flag, self):
        if res is not True:
            if isinstance(res, collections.Iterator):
                for tmp in res:
                    yield tmp
            else:
                yield res

def set_breakpoint(

self, addr, *args)

Set callbacks associated with addr. @addr: breakpoint address @args: functions with definition (jitter instance)

def set_breakpoint(self, addr, *args):
    """Set callbacks associated with addr.
    @addr: breakpoint address
    @args: functions with definition (jitter instance)
    """
    self.breakpoints_handler.set_callback(addr, *args)
    self.jit.add_disassembly_splits(addr)

def set_str_ansi(

self, addr, s)

Set an ansi string in memory

def set_str_ansi(self, addr, s):
    """Set an ansi string in memory"""
    s = s + "\x00"
    self.vm.set_mem(addr, s)

def set_str_unic(

self, addr, s)

Set an unicode string in memory

def set_str_unic(self, addr, s):
    """Set an unicode string in memory"""
    s = "\x00".join(list(s)) + '\x00' * 3
    self.vm.set_mem(addr, s)

def set_trace_log(

self, trace_instr=True, trace_regs=True, trace_new_blocks=False)

Activate/Deactivate trace log options

@trace_instr: activate instructions tracing log @trace_regs: activate registers tracing log @trace_new_blocks: dump new code blocks log

def set_trace_log(self,
                  trace_instr=True, trace_regs=True,
                  trace_new_blocks=False):
    """
    Activate/Deactivate trace log options
    @trace_instr: activate instructions tracing log
    @trace_regs: activate registers tracing log
    @trace_new_blocks: dump new code blocks log
    """
    # As trace state changes, clear already jitted blocks
    self.jit.clear_jitted_blocks()
    self.jit.log_mn = trace_instr
    self.jit.log_regs = trace_regs
    self.jit.log_newbloc = trace_new_blocks

class mep_CGen

Translate a bloc containing MeP instructions to C

Note: it is used to emulate the *REPEAT instructions

class mep_CGen(CGen):
    """
    Translate a bloc containing MeP instructions to C

    Note: it is used to emulate the *REPEAT instructions
    """

    def __init__(self, ir_arch):
        self.ir_arch = ir_arch
        self.PC = self.ir_arch.arch.regs.PC
        self.translator = TranslatorC(self.ir_arch.loc_db)
        self.init_arch_C()

    def gen_pre_code(self, attrib):
        """Generate C code inserted before the current bloc"""

        # Call the base class method
        out = super(mep_CGen, self).gen_pre_code(attrib)

        # Set the PC register value explicitly
        out.append("mycpu->PC = 0x%X;" % attrib.instr.offset)
        out.append("mycpu->last_addr = mycpu->PC;");

        return out

    def gen_post_code(self, attrib):
        """Generate C code inserted after the current bloc"""

        # Call the base class method
        out = super(mep_CGen, self).gen_post_code(attrib)

        # Implement the *REPEAT instructions logics
        tmp = r"""
        /* *REPEAT instructions logic */
        {
            uint32_t is_repeat_end = mycpu->is_repeat_end;
            mycpu->is_repeat_end = !!(mycpu->last_addr == (mycpu->RPE&~0x1));

            if (is_repeat_end && !mycpu->take_jmp &&
                   (mycpu->in_erepeat || mycpu->RPC)) {
                 if (mycpu->RPC)
                       mycpu->RPC --;

                 //printf("Go repeat  %X\n", mycpu->RPB);
                 DST_value = mycpu->RPB;
                 BlockDst->address = mycpu->RPB;
                 return JIT_RET_NO_EXCEPTION;
             }
        }
        """

        out += tmp.split('`\n')
        return out

Ancestors (in MRO)

  • mep_CGen
  • miasm2.jitter.codegen.CGen
  • __builtin__.object

Class variables

var CODE_BAD_BLOCK

var CODE_CPU_EXCEPTION_POST_INSTR

var CODE_EXCEPTION_AT_INSTR

var CODE_EXCEPTION_MEM_AT_INSTR

var CODE_INIT

var CODE_RETURN_EXCEPTION

var CODE_RETURN_NO_EXCEPTION

var CODE_VM_EXCEPTION_POST_INSTR

Instance variables

var PC

var ir_arch

var translator

Methods

def __init__(

self, ir_arch)

def __init__(self, ir_arch):
    self.ir_arch = ir_arch
    self.PC = self.ir_arch.arch.regs.PC
    self.translator = TranslatorC(self.ir_arch.loc_db)
    self.init_arch_C()

def add_label_index(

self, dst2index, loc_key)

Insert @lbl to the dictionnary @dst2index with a uniq value @dst2index: LocKey -> uniq value @loc_key: LocKey istance

def add_label_index(self, dst2index, loc_key):
    """Insert @lbl to the dictionnary @dst2index with a uniq value
    @dst2index: LocKey -> uniq value
    @loc_key: LocKey istance"""
    if loc_key not in dst2index:
        dst2index[loc_key] = len(dst2index)

def add_local_var(

self, dst_var, dst_index, expr)

Add local varaible used to store temporay result @dst_var: dictionnary of Expr -> local_var_expr @dst_index : dictionnary of size -> local var count @expr: Expression source

def add_local_var(self, dst_var, dst_index, expr):
    """
    Add local varaible used to store temporay result
    @dst_var: dictionnary of Expr -> local_var_expr
    @dst_index : dictionnary of size -> local var count
    @expr: Expression source
    """
    size = expr.size
    if size < 8:
        size = 8
    if size not in dst_index:
        raise RuntimeError("Unsupported operand size %s", size)
    var_num = dst_index[size]
    dst = ExprId("var_%.2d_%.2d" % (size, var_num), size)
    dst_index[size] += 1
    dst_var[expr] = dst
    return dst

def assignblk_to_irbloc(

self, instr, assignblk)

Ensure IRDst is always set in the head @assignblk of the @instr @instr: an instruction instance @assignblk: Assignblk instance

def assignblk_to_irbloc(self, instr, assignblk):
    """
    Ensure IRDst is always set in the head @assignblk of the @instr
    @instr: an instruction instance
    @assignblk: Assignblk instance
    """
    new_assignblk = dict(assignblk)
    if self.ir_arch.IRDst not in assignblk:
        offset = instr.offset + instr.l
        loc_key = self.ir_arch.loc_db.get_or_create_offset_location(offset)
        dst = ExprLoc(loc_key, self.ir_arch.IRDst.size)
        new_assignblk[self.ir_arch.IRDst] = dst
    irs = [AssignBlock(new_assignblk, instr)]
    return IRBlock(self.ir_arch.get_loc_key_for_instr(instr), irs)

def block2assignblks(

self, block)

Return the list of irblocks for a native @block @block: AsmBlock

def block2assignblks(self, block):
    """
    Return the list of irblocks for a native @block
    @block: AsmBlock
    """
    irblocks_list = []
    for instr in block.lines:
        assignblk_head, assignblks_extra = self.ir_arch.instr2ir(instr)
        # Keep result in ordered list as first element is the assignblk head
        # The remainings order is not really important
        irblock_head = self.assignblk_to_irbloc(instr, assignblk_head)
        irblocks = [irblock_head] + assignblks_extra
        # Simplify high level operators
        out = []
        for irblock in irblocks:
            new_irblock = irblock.simplify(expr_simp_high_to_explicit)[1]
            out.append(new_irblock)
        irblocks = out
        for irblock in irblocks:
            assert irblock.dst is not None
        irblocks_list.append(irblocks)
    return irblocks_list

def dst_to_c(

self, src)

Translate Expr @src into C code

def dst_to_c(self, src):
    """Translate Expr @src into C code"""
    if not isinstance(src, Expr):
        src = ExprInt(src, self.PC.size)
    return self.id_to_c(src)

def gen_assignblk_dst(

self, dst)

Generate C code to handle instruction destination @dst: instruction destination Expr

def gen_assignblk_dst(self, dst):
    """Generate C code to handle instruction destination
    @dst: instruction destination Expr"""
    dst2index = {}
    (ret, retb) = self.traverse_expr_dst(dst, dst2index)
    ret = "DST_case = %s;" % ret
    retb = 'DST_value = %s;' % retb
    return ['// %s' % dst2index,
            '%s' % ret,
            '%s' % retb], dst2index

def gen_bad_block(

self)

Generate the C code for a bad_block instance

def gen_bad_block(self):
    """
    Generate the C code for a bad_block instance
    """
    return self.CODE_BAD_BLOCK.split("\n")

def gen_c(

self, block, log_mn=False, log_regs=False)

Generate the C code for the @block and return it as a list of lines @log_mn: log mnemonics @log_regs: log registers

def gen_c(self, block, log_mn=False, log_regs=False):
    """
    Generate the C code for the @block and return it as a list of lines
    @log_mn: log mnemonics
    @log_regs: log registers
    """
    if isinstance(block, AsmBlockBad):
        return self.gen_bad_block()
    irblocks_list = self.block2assignblks(block)
    out, instr_offsets = self.gen_init(block)
    assert len(block.lines) == len(irblocks_list)
    for instr, irblocks in zip(block.lines, irblocks_list):
        instr_attrib, irblocks_attributes = self.get_attributes(instr, irblocks, log_mn, log_regs)
        for index, irblock in enumerate(irblocks):
            new_irblock = self.ir_arch.irbloc_fix_regs_for_mode(irblock, self.ir_arch.attrib)
            label = str(new_irblock.loc_key)
            out.append("%-40s // %.16X %s" %
                       (label + ":", instr.offset, instr))
            if index == 0:
                out += self.gen_pre_code(instr_attrib)
            out += self.gen_irblock(instr_attrib, irblocks_attributes[index], instr_offsets, new_irblock)
    out += self.gen_finalize(block)
    return ['\t' + line for line in out]

def gen_c_assignments(

self, assignblk)

Return C informations used to generate the C code of the @assignblk @assignblk: an AssignBlock instance

def gen_c_assignments(self, assignblk):
    """
    Return C informations used to generate the C code of the @assignblk
    @assignblk: an AssignBlock instance
    """
    c_var = []
    c_main = []
    c_mem = []
    c_updt = []
    c_prefetch = []
    dst_index = {8: 0, 16: 0, 32: 0, 64: 0, 128:0}
    dst_var = {}
    prefetchers = self.get_mem_prefetch(assignblk)
    for expr, prefetcher in sorted(prefetchers.iteritems()):
        str_src = self.id_to_c(expr)
        str_dst = self.id_to_c(prefetcher)
        c_prefetch.append('%s = %s;' % (str_dst, str_src))
    for var in prefetchers.itervalues():
        if var.size <= self.translator.NATIVE_INT_MAX_SIZE:
            c_var.append("uint%d_t %s;" % (var.size, var))
        else:
            c_var.append("bn_t %s; // %d" % (var, var.size))
    for dst, src in sorted(assignblk.iteritems()):
        src = src.replace_expr(prefetchers)
        if dst == self.ir_arch.IRDst:
            pass
        elif isinstance(dst, ExprId):
            new_dst = self.add_local_var(dst_var, dst_index, dst)
            if dst in self.ir_arch.arch.regs.regs_flt_expr:
                # Dont mask float affectation
                c_main.append(
                    '%s = (%s);' % (self.id_to_c(new_dst), self.id_to_c(src)))
            elif new_dst.size <= self.translator.NATIVE_INT_MAX_SIZE:
                c_main.append(
                    '%s = (%s)&%s;' % (self.id_to_c(new_dst),
                                       self.id_to_c(src),
                                       SIZE_TO_MASK[src.size]))
            else:
                c_main.append(
                    '%s = bignum_mask(%s, %d);' % (
                        self.id_to_c(new_dst),
                        self.id_to_c(src),
                        src.size
                    )
                )
        elif isinstance(dst, ExprMem):
            ptr = dst.arg.replace_expr(prefetchers)
            if ptr.size <= self.translator.NATIVE_INT_MAX_SIZE:
                new_dst = ExprMem(ptr, dst.size)
                str_dst = self.id_to_c(new_dst).replace('MEM_LOOKUP', 'MEM_WRITE')
                c_mem.append('%s, %s);' % (str_dst[:-1], self.id_to_c(src)))
            else:
                ptr_str = self.id_to_c(ptr)
                if ptr.size <= self.translator.NATIVE_INT_MAX_SIZE:
                    c_mem.append('%s, %s);' % (str_dst[:-1], self.id_to_c(src)))
                else:
                    if src.size <= self.translator.NATIVE_INT_MAX_SIZE:
                        c_mem.append('MEM_WRITE_BN_INT(jitcpu, %d, %s, %s);' % (
                            src.size, ptr_str, self.id_to_c(src))
                        )
                    else:
                        c_mem.append('MEM_WRITE_BN_BN(jitcpu, %d, %s, %s);' % (
                            src.size, ptr_str, self.id_to_c(src))
                        )
        else:
            raise ValueError("Unknown dst")
    for dst, new_dst in dst_var.iteritems():
        if dst == self.ir_arch.IRDst:
            continue
        c_updt.append('%s = %s;' % (self.id_to_c(dst), self.id_to_c(new_dst)))
        if dst.size <= self.translator.NATIVE_INT_MAX_SIZE:
            c_var.append("uint%d_t %s;" % (new_dst.size, new_dst))
        else:
            c_var.append("bn_t %s; // %d" % (new_dst, new_dst.size))
    return c_prefetch, c_var, c_main, c_mem, c_updt

def gen_c_code(

self, attrib, c_dst, c_assignmnts)

Generate the C code for assignblk. @attrib: Attributes instance @c_dst: irdst C code

def gen_c_code(self, attrib, c_dst, c_assignmnts):
    """
    Generate the C code for assignblk.
    @attrib: Attributes instance
    @c_dst: irdst C code
    """
    c_prefetch, c_var, c_main, c_mem, c_updt = c_assignmnts
    out = []
    out.append("{")
    out.append("// var")
    out += c_var
    out.append("// Prefetch")
    out += c_prefetch
    out.append("// Dst")
    out += c_dst
    out.append("// Main")
    out += c_main
    out.append("// Check op/mem exceptions")
    # Check memory access if assignblk has memory read
    if c_prefetch:
        out += self.gen_check_memory_exception(attrib.instr.offset)
    out.append("// Mem updt")
    out += c_mem
    out.append("// Check exception Mem write")
    # Check memory write exceptions
    if attrib.mem_write:
        out += self.gen_check_memory_exception(attrib.instr.offset)
    out.append("// Updt")
    out += c_updt
    out.append("// Checks exception")
    # Check post assignblk exception flags
    if attrib.set_exception:
        out += self.gen_check_cpu_exception(attrib.instr.offset)
    out.append("}")
    return out

def gen_check_cpu_exception(

self, address)

Generate C code to check cpu exceptions @address: address of the faulty instruction

def gen_check_cpu_exception(self, address):
    """Generate C code to check cpu exceptions
    @address: address of the faulty instruction"""
    dst = self.dst_to_c(address)
    return (self.CODE_EXCEPTION_AT_INSTR % (self.C_PC, dst, dst)).split('\n')

def gen_check_memory_exception(

self, address)

Generate C code to check memory exceptions @address: address of the faulty instruction

def gen_check_memory_exception(self, address):
    """Generate C code to check memory exceptions
    @address: address of the faulty instruction"""
    dst = self.dst_to_c(address)
    return (self.CODE_EXCEPTION_MEM_AT_INSTR % (self.C_PC, dst, dst)).split('\n')

def gen_dst_goto(

self, attrib, instr_offsets, dst2index)

Generate code for possible @dst2index.

@attrib: an Attributes instance @instr_offsets: list of instructions offsets @dst2index: link from destination to index

def gen_dst_goto(self, attrib, instr_offsets, dst2index):
    """
    Generate code for possible @dst2index.
    @attrib: an Attributes instance
    @instr_offsets: list of instructions offsets
    @dst2index: link from destination to index
    """
    if not dst2index:
        return []
    out = []
    out.append('switch(DST_case) {')
    stopcase = False
    for dst, index in sorted(dst2index.iteritems(), key=lambda lblindex: lblindex[1]):
        if index == -1:
            # Handle '-1' case only once
            if not stopcase:
                stopcase = True
            else:
                continue
        out.append('\tcase %d:' % index)
        out += self.gen_goto_code(attrib, instr_offsets, dst)
        out.append('\t\tbreak;')
    out.append('};')
    return out

def gen_finalize(

self, block)

Generate the C code for the final block instruction

def gen_finalize(self, block):
    """
    Generate the C code for the final block instruction
    """
    loc_key = self.get_block_post_label(block)
    offset = self.ir_arch.loc_db.get_location_offset(loc_key)
    dst = self.dst_to_c(offset)
    code = self.CODE_RETURN_NO_EXCEPTION % (loc_key, self.C_PC, dst, dst)
    return code.split('\n')

def gen_goto_code(

self, attrib, instr_offsets, dst)

Generate C code for a potential destination @dst @attrib: instruction Attributes @instr_offsets: instructions offsets list @dst: potential instruction destination

def gen_goto_code(self, attrib, instr_offsets, dst):
    """Generate C code for a potential destination @dst
    @attrib: instruction Attributes
    @instr_offsets: instructions offsets list
    @dst: potential instruction destination"""
    out = []
    if isinstance(dst, Expr):
        out += self.gen_post_code(attrib)
        out.append('BlockDst->address = DST_value;')
        out += self.gen_post_instr_checks(attrib)
        out.append('\t\treturn JIT_RET_NO_EXCEPTION;')
        return out
    assert isinstance(dst, LocKey)
    offset = self.ir_arch.loc_db.get_location_offset(dst)
    if offset is None:
        # Generate goto for local labels
        return ['goto %s;' % dst]
    if (offset > attrib.instr.offset and
        offset in instr_offsets):
        # Only generate goto for next instructions.
        # (consecutive instructions)
        out += self.gen_post_code(attrib)
        out += self.gen_post_instr_checks(attrib)
        out.append('goto %s;' % dst)
    else:
        out += self.gen_post_code(attrib)
        out.append('BlockDst->address = DST_value;')
        out += self.gen_post_instr_checks(attrib)
        out.append('\t\treturn JIT_RET_NO_EXCEPTION;')
    return out

def gen_init(

self, block)

Generate the init C code for a @block @block: an asm_bloc instance

def gen_init(self, block):
    """
    Generate the init C code for a @block
    @block: an asm_bloc instance
    """
    instr_offsets = [line.offset for line in block.lines]
    post_label = self.get_block_post_label(block)
    post_offset = self.ir_arch.loc_db.get_location_offset(post_label)
    instr_offsets.append(post_offset)
    lbl_start = block.loc_key
    return (self.CODE_INIT % lbl_start).split("\n"), instr_offsets

def gen_irblock(

self, instr_attrib, attributes, instr_offsets, irblock)

Generate the C code for an @irblock @irblock: an irbloc instance @attributes: an Attributes instance list

def gen_irblock(self, instr_attrib, attributes, instr_offsets, irblock):
    """
    Generate the C code for an @irblock
    @irblock: an irbloc instance
    @attributes: an Attributes instance list
    """
    out = []
    dst2index = None
    for index, assignblk in enumerate(irblock):
        if index == irblock.dst_linenb:
            c_dst, dst2index = self.gen_assignblk_dst(irblock.dst)
        else:
            c_dst = []
        c_assignmnts = self.gen_c_assignments(assignblk)
        out += self.gen_c_code(attributes[index], c_dst, c_assignmnts)
    if dst2index:
        out.append("// Set irdst")
        # Gen goto on irdst set
        out += self.gen_dst_goto(instr_attrib, instr_offsets, dst2index)
    return out

def gen_post_code(

self, attrib)

Generate C code inserted after the current bloc

def gen_post_code(self, attrib):
    """Generate C code inserted after the current bloc"""
    # Call the base class method
    out = super(mep_CGen, self).gen_post_code(attrib)
    # Implement the *REPEAT instructions logics
    tmp = r"""
    /* *REPEAT instructions logic */
    {
        uint32_t is_repeat_end = mycpu->is_repeat_end;
        mycpu->is_repeat_end = !!(mycpu->last_addr == (mycpu->RPE&~0x1));
        if (is_repeat_end && !mycpu->take_jmp &&
               (mycpu->in_erepeat || mycpu->RPC)) {
             if (mycpu->RPC)
                   mycpu->RPC --;
             //printf("Go repeat  %X\n", mycpu->RPB);
             DST_value = mycpu->RPB;
             BlockDst->address = mycpu->RPB;
             return JIT_RET_NO_EXCEPTION;
         }
    }
    """
    out += tmp.split('`\n')
    return out

def gen_post_instr_checks(

self, attrib)

Generate C code for handling potential exceptions @attrib: Attributes instance

def gen_post_instr_checks(self, attrib):
    """Generate C code for handling potential exceptions
    @attrib: Attributes instance"""
    out = []
    if attrib.mem_read | attrib.mem_write:
        out += (self.CODE_VM_EXCEPTION_POST_INSTR % (self.C_PC)).split('\n')
    if attrib.set_exception:
        out += (self.CODE_CPU_EXCEPTION_POST_INSTR % (self.C_PC)).split('\n')
    if attrib.mem_read | attrib.mem_write:
        out.append("reset_memory_access(&(jitcpu->pyvm->vm_mngr));")
    return out

def gen_pre_code(

self, attrib)

Generate C code inserted before the current bloc

def gen_pre_code(self, attrib):
    """Generate C code inserted before the current bloc"""
    # Call the base class method
    out = super(mep_CGen, self).gen_pre_code(attrib)
    # Set the PC register value explicitly
    out.append("mycpu->PC = 0x%X;" % attrib.instr.offset)
    out.append("mycpu->last_addr = mycpu->PC;");
    return out

def get_attributes(

self, instr, irblocks, log_mn=False, log_regs=False)

Get the carateristics of each @irblocks. Returns the corresponding attributes object. @irblock: a list of irbloc instance @log_mn: generate code to log instructions @log_regs: generate code to log registers states

def get_attributes(self, instr, irblocks, log_mn=False, log_regs=False):
    """
    Get the carateristics of each @irblocks. Returns the corresponding
    attributes object.
    @irblock: a list of irbloc instance
    @log_mn: generate code to log instructions
    @log_regs: generate code to log registers states
    """
    instr_attrib = Attributes(log_mn, log_regs)
    instr_attrib.instr = instr
    irblocks_attributes = []
    for irblock in irblocks:
        attributes = []
        irblocks_attributes.append(attributes)
        for assignblk in irblock:
            attrib = Attributes(log_mn, log_regs)
            attributes.append(attrib)
            self.get_caracteristics(assignblk, attrib)
            attrib.instr = instr
            instr_attrib.mem_read |= attrib.mem_read
            instr_attrib.mem_write |= attrib.mem_write
            instr_attrib.set_exception |= attrib.set_exception
    return instr_attrib, irblocks_attributes

def get_block_post_label(

self, block)

Get label next to the @block @block: AsmBlock instance

def get_block_post_label(self, block):
    """Get label next to the @block
    @block: AsmBlock instance"""
    last_instr = block.lines[-1]
    offset = last_instr.offset + last_instr.l
    return self.ir_arch.loc_db.get_or_create_offset_location(offset)

def get_caracteristics(

self, assignblk, attrib)

Set the carateristics in @attrib according to the @assignblk @assignblk: an AssignBlock instance @attrib: an Attributes instance

def get_caracteristics(self, assignblk, attrib):
    """
    Set the carateristics in @attrib according to the @assignblk
    @assignblk: an AssignBlock instance
    @attrib: an Attributes instance
    """
    # Check explicit exception raising
    attrib.set_exception = self.ir_arch.arch.regs.exception_flags in assignblk
    element_read = assignblk.get_r(mem_read=True)
    # Check mem read
    attrib.mem_read = any(isinstance(expr, ExprMem)
                          for expr in element_read)
    # Check mem write
    attrib.mem_write = any(isinstance(dst, ExprMem)
                           for dst in assignblk)

def get_mem_prefetch(

self, assignblk)

Generate temporary variables used to fetch memory used in the @assignblk Return a dictionnary: ExprMem -> temporary variable @assignblk: AssignBlock instance

def get_mem_prefetch(self, assignblk):
    """
    Generate temporary variables used to fetch memory used in the @assignblk
    Return a dictionnary: ExprMem -> temporary variable
    @assignblk: AssignBlock instance
    """
    mem_index = {8: 0, 16: 0, 32: 0, 64: 0, 128:0}
    mem_var = {}
    # Prefetch memory read
    for expr in assignblk.get_r(mem_read=True):
        if not isinstance(expr, ExprMem):
            continue
        var_num = mem_index[expr.size]
        mem_index[expr.size] += 1
        var = ExprId(
            "prefetch_%.2d_%.2d" % (expr.size, var_num), expr.size
        )
        mem_var[expr] = var
    # Generate memory prefetch
    return mem_var

def id_to_c(

self, expr)

Translate Expr @expr into corresponding C code

def id_to_c(self, expr):
    """Translate Expr @expr into corresponding C code"""
    return self.translator.from_expr(self.patch_c_id(expr))

def init_arch_C(

self)

Iinitialize jitter internals

def init_arch_C(self):
    """Iinitialize jitter internals"""
    self.id_to_c_id = {}
    for reg in self.ir_arch.arch.regs.all_regs_ids:
        self.id_to_c_id[reg] = ExprId('mycpu->%s' % reg, reg.size)
    self.C_PC = self.id_to_c(self.PC)

def patch_c_id(

self, expr)

Replace ExprId in @expr with corresponding C variables

def patch_c_id(self, expr):
    """Replace ExprId in @expr with corresponding C variables"""
    return expr.replace_expr(self.id_to_c_id)

def traverse_expr_dst(

self, expr, dst2index)

Generate the index of the destination label for the @expr @dst2index: dictionnary to link label to its index

def traverse_expr_dst(self, expr, dst2index):
    """
    Generate the index of the destination label for the @expr
    @dst2index: dictionnary to link label to its index
    """
    if isinstance(expr, ExprCond):
        src1, src1b = self.traverse_expr_dst(expr.src1, dst2index)
        src2, src2b = self.traverse_expr_dst(expr.src2, dst2index)
        cond = self.id_to_c(expr.cond)
        if not expr.cond.size <= self.translator.NATIVE_INT_MAX_SIZE:
            cond = "(!bignum_is_zero(%s))" % cond
        return ("((%s)?(%s):(%s))" % (cond, src1, src2),
                "((%s)?(%s):(%s))" % (cond, src1b, src2b))
    if isinstance(expr, ExprInt):
        offset = int(expr)
        loc_key = self.ir_arch.loc_db.get_or_create_offset_location(offset)
        self.add_label_index(dst2index, loc_key)
        value, int_size = int_size_to_bn(offset, 64)
        out = hex(offset)
        return ("%s" % dst2index[loc_key], out)
    if expr.is_loc():
        loc_key = expr.loc_key
        offset = self.ir_arch.loc_db.get_location_offset(expr.loc_key)
        if offset is not None:
            self.add_label_index(dst2index, loc_key)
            value, int_size = int_size_to_bn(offset, 64)
            out = hex(offset)
            return ("%s" % dst2index[loc_key], out)
        self.add_label_index(dst2index, loc_key)
        value, int_size = int_size_to_bn(0, 64)
        out = hex(0)
        return ("%s" % dst2index[loc_key], out)
    dst2index[expr] = -1
    return ("-1", self.id_to_c(expr))