diff options
| author | Fabrice Desclaux <fabrice.desclaux@cea.fr> | 2017-04-14 13:32:59 +0200 |
|---|---|---|
| committer | Fabrice Desclaux <fabrice.desclaux@cea.fr> | 2017-04-20 12:31:33 +0200 |
| commit | 16fc339e53bfc908dbcd73fc912d7d75aed7218c (patch) | |
| tree | f13faa66157ddd4c12dff191d314d81e5f2bf33f | |
| parent | ff981a11ef71960a239ec44295f06bb384124521 (diff) | |
| download | miasm-16fc339e53bfc908dbcd73fc912d7d75aed7218c.tar.gz miasm-16fc339e53bfc908dbcd73fc912d7d75aed7218c.zip | |
Ir: make AssignBlock immutable
| -rw-r--r-- | miasm2/analysis/data_flow.py | 7 | ||||
| -rw-r--r-- | miasm2/analysis/depgraph.py | 6 | ||||
| -rw-r--r-- | miasm2/arch/aarch64/sem.py | 10 | ||||
| -rw-r--r-- | miasm2/arch/mips32/jit.py | 12 | ||||
| -rw-r--r-- | miasm2/arch/x86/sem.py | 12 | ||||
| -rw-r--r-- | miasm2/ir/ir.py | 74 | ||||
| -rw-r--r-- | miasm2/jitter/codegen.py | 255 | ||||
| -rw-r--r-- | miasm2/jitter/llvmconvert.py | 39 | ||||
| -rw-r--r-- | test/analysis/data_flow.py | 5 | ||||
| -rwxr-xr-x | test/ir/symbexec.py | 3 |
10 files changed, 249 insertions, 174 deletions
diff --git a/miasm2/analysis/data_flow.py b/miasm2/analysis/data_flow.py index b9764daa..3c77fc40 100644 --- a/miasm2/analysis/data_flow.py +++ b/miasm2/analysis/data_flow.py @@ -2,6 +2,7 @@ from collections import namedtuple from miasm2.core.graph import DiGraph +from miasm2.ir.ir import AssignBlock class ReachingDefinitions(dict): """ @@ -247,6 +248,8 @@ def dead_simp(ir_a): useful = set(dead_simp_useful_instrs(defuse, reaching_defs)) for block in ir_a.blocks.itervalues(): for idx, assignblk in enumerate(block.irs): - for lval in assignblk.keys(): + new_assignblk = dict(assignblk) + for lval in assignblk: if InstrNode(block.label, idx, lval) not in useful: - del assignblk[lval] + del new_assignblk[lval] + block.irs[idx] = AssignBlock(new_assignblk) diff --git a/miasm2/analysis/depgraph.py b/miasm2/analysis/depgraph.py index bab4d2bc..d1ac13c8 100644 --- a/miasm2/analysis/depgraph.py +++ b/miasm2/analysis/depgraph.py @@ -263,12 +263,12 @@ class DependencyResult(DependencyState): for line_nb, elements in sorted(line2elements.iteritems()): if max_line is not None and line_nb >= max_line: break - assignblk = AssignBlock() + assignmnts = {} for element in elements: if element in irb.irs[line_nb]: # constants, label, ... are not in destination - assignblk[element] = irb.irs[line_nb][element] - assignblks.append(assignblk) + assignmnts[element] = irb.irs[line_nb][element] + assignblks.append(AssignBlock(assignmnts)) return IRBlock(irb.label, assignblks) diff --git a/miasm2/arch/aarch64/sem.py b/miasm2/arch/aarch64/sem.py index e9eaffc8..edc6e3a5 100644 --- a/miasm2/arch/aarch64/sem.py +++ b/miasm2/arch/aarch64/sem.py @@ -777,9 +777,10 @@ class ir_aarch64l(IntermediateRepresentation): return m2_expr.ExprAff(dst, src) def irbloc_fix_regs_for_mode(self, irbloc, mode=64): - for assignblk in irbloc.irs: - for dst, src in assignblk.items(): - del(assignblk[dst]) + for idx, assignblk in enumerate(irbloc.irs): + new_assignblk = dict(assignblk) + for dst, src in assignblk.iteritems(): + del(new_assignblk[dst]) # Special case for 64 bits: # If destination is a 32 bit reg, zero extend the 64 bit reg @@ -791,7 +792,8 @@ class ir_aarch64l(IntermediateRepresentation): dst = self.expr_fix_regs_for_mode(dst) src = self.expr_fix_regs_for_mode(src) - assignblk[dst] = src + new_assignblk[dst] = src + irbloc.irs[idx] = AssignBlock(new_assignblk) if irbloc.dst is not None: irbloc.dst = self.expr_fix_regs_for_mode(irbloc.dst) diff --git a/miasm2/arch/mips32/jit.py b/miasm2/arch/mips32/jit.py index bfa9c5fd..939a0e50 100644 --- a/miasm2/arch/mips32/jit.py +++ b/miasm2/arch/mips32/jit.py @@ -5,6 +5,7 @@ from miasm2.core import asmblock from miasm2.core.utils import pck32, upck32 from miasm2.arch.mips32.sem import ir_mips32l, ir_mips32b from miasm2.jitter.codegen import CGen +from miasm2.ir.ir import AssignBlock import miasm2.expression.expression as m2_expr log = logging.getLogger('jit_mips32') @@ -43,18 +44,21 @@ class mipsCGen(CGen): if not instr.breakflow(): continue for irblock in irblocks: - for assignblock in irblock.irs: + for idx, assignblock in enumerate(irblock.irs): if self.ir_arch.pc not in assignblock: continue + new_assignblock = dict(assignblock) # Add internal branch destination - assignblock[self.delay_slot_dst] = assignblock[ + new_assignblock[self.delay_slot_dst] = assignblock[ self.ir_arch.pc] - assignblock[self.delay_slot_set] = m2_expr.ExprInt(1, 32) + new_assignblock[self.delay_slot_set] = m2_expr.ExprInt(1, 32) # Replace IRDst with next instruction - assignblock[self.ir_arch.IRDst] = m2_expr.ExprId( + new_assignblock[self.ir_arch.IRDst] = m2_expr.ExprId( self.ir_arch.get_next_instr(instr)) irblock.dst = m2_expr.ExprId( self.ir_arch.get_next_instr(instr)) + irblock.irs[idx] = AssignBlock(new_assignblock) + return irblocks_list def gen_finalize(self, block): diff --git a/miasm2/arch/x86/sem.py b/miasm2/arch/x86/sem.py index 98866e65..b0cdc280 100644 --- a/miasm2/arch/x86/sem.py +++ b/miasm2/arch/x86/sem.py @@ -21,7 +21,7 @@ from miasm2.expression.simplifications import expr_simp from miasm2.arch.x86.regs import * from miasm2.arch.x86.arch import mn_x86, repeat_mn, replace_regs from miasm2.expression.expression_helper import expr_cmps, expr_cmpu -from miasm2.ir.ir import IntermediateRepresentation, IRBlock +from miasm2.ir.ir import IntermediateRepresentation, IRBlock, AssignBlock from miasm2.core.sembuilder import SemBuilder import math import struct @@ -4602,9 +4602,10 @@ class ir_x86_16(IntermediateRepresentation): return m2_expr.ExprAff(dst, src) def irbloc_fix_regs_for_mode(self, irbloc, mode=64): - for assignblk in irbloc.irs: - for dst, src in assignblk.items(): - del assignblk[dst] + for idx, assignblk in enumerate(irbloc.irs): + new_assignblk = dict(assignblk) + for dst, src in assignblk.iteritems(): + del new_assignblk[dst] # Special case for 64 bits: # If destination is a 32 bit reg, zero extend the 64 bit reg if mode == 64: @@ -4615,7 +4616,8 @@ class ir_x86_16(IntermediateRepresentation): dst = replace_regs[64][dst].arg dst = self.expr_fix_regs_for_mode(dst, mode) src = self.expr_fix_regs_for_mode(src, mode) - assignblk[dst] = src + new_assignblk[dst] = src + irbloc.irs[idx] = AssignBlock(new_assignblk) if irbloc.dst is not None: irbloc.dst = self.expr_fix_regs_for_mode(irbloc.dst, mode) diff --git a/miasm2/ir/ir.py b/miasm2/ir/ir.py index f8ac6722..bdad4f30 100644 --- a/miasm2/ir/ir.py +++ b/miasm2/ir/ir.py @@ -29,19 +29,24 @@ from miasm2.core.asmblock import AsmSymbolPool, expr_is_label, AsmLabel, \ from miasm2.core.graph import DiGraph -class AssignBlock(dict): +class AssignBlock(object): + __slots__ = ["_assigns"] def __init__(self, irs=None): """@irs seq""" if irs is None: irs = [] - super(AssignBlock, self).__init__() + self._assigns = {} # ExprAff.dst -> ExprAff.src - for expraff in irs: - # Concurrent assignments are handled in __setitem__ - self[expraff.dst] = expraff.src + # Concurrent assignments are handled in _set + if hasattr(irs, "iteritems"): + for dst, src in irs.iteritems(): + self._set(dst, src) + else: + for expraff in irs: + self._set(expraff.dst, expraff.src) - def __setitem__(self, dst, src): + def _set(self, dst, src): """ Special cases: * if dst is an ExprSlice, expand it to affect the full Expression @@ -64,7 +69,7 @@ class AssignBlock(dict): else: new_dst, new_src = dst, src - if new_dst in self and isinstance(new_src, m2_expr.ExprCompose): + if new_dst in self._assigns and isinstance(new_src, m2_expr.ExprCompose): if not isinstance(self[new_dst], m2_expr.ExprCompose): # prev_RAX = 0x1122334455667788 # input_RAX[0:8] = 0x89 @@ -103,7 +108,51 @@ class AssignBlock(dict): args = [expr for (expr, _, _) in args] new_src = m2_expr.ExprCompose(*args) - super(AssignBlock, self).__setitem__(new_dst, new_src) + self._assigns[new_dst] = new_src + + def __setitem__(self, dst, src): + raise RuntimeError('AssignBlock is immutable') + + def __getitem__(self, key): + return self._assigns[key] + + def __contains__(self, key): + return key in self._assigns + + def iteritems(self): + for dst, src in self._assigns.iteritems(): + yield dst, src + + def itervalues(self): + for src in self._assigns.itervalues(): + yield src + + def keys(self): + return self._assigns.keys() + + def values(self): + return self._assigns.values() + + def __iter__(self): + for dst in self._assigns: + yield dst + + def __delitem__(self, _): + raise RuntimeError('AssignBlock is immutable') + + def update(self, _): + raise RuntimeError('AssignBlock is immutable') + + def __eq__(self, other): + if self.keys() != other.keys(): + return False + return all(other[dst] == src for dst, src in self.iteritems()) + + def __len__(self): + return len(self._assigns) + + def get(self, key, default): + return self._assigns.get(key, default) @staticmethod def get_modified_slice(dst, src): @@ -207,15 +256,14 @@ class IRBlock(object): if self._dst_linenb is None: self._get_dst() - assignblk = self.irs[self._dst_linenb] - for dst in assignblk: + new_assignblk = dict(self.irs[self._dst_linenb]) + for dst in new_assignblk: if isinstance(dst, m2_expr.ExprId) and dst.name == "IRDst": - del assignblk[dst] - assignblk[dst] = value + new_assignblk[dst] = value # Sanity check is already done in _get_dst break self._dst = value - + self.irs[self._dst_linenb] = AssignBlock(new_assignblk) dst = property(_get_dst, _set_dst) @property diff --git a/miasm2/jitter/codegen.py b/miasm2/jitter/codegen.py index 09a6fecf..8a03c667 100644 --- a/miasm2/jitter/codegen.py +++ b/miasm2/jitter/codegen.py @@ -1,5 +1,9 @@ +""" +Module to generate C code for a given native @block +""" + import miasm2.expression.expression as m2_expr -from miasm2.ir.ir import IRBlock +from miasm2.ir.ir import IRBlock, AssignBlock from miasm2.ir.translators import Translator from miasm2.core.asmblock import expr_is_label, AsmBlockBad, AsmLabel @@ -131,17 +135,22 @@ class CGen(object): def assignblk_to_irbloc(self, instr, assignblk): """ Ensure IRDst is always set in the head @assignblk of the @instr - @assignblk: Assignblk instance @instr: an instruction instance + @assignblk: Assignblk instance """ + new_assignblk = dict(assignblk) if self.ir_arch.IRDst not in assignblk: - assignblk[self.ir_arch.IRDst] = m2_expr.ExprInt( - instr.offset + instr.l, - self.ir_arch.IRDst.size) - - return IRBlock(self.ir_arch.get_instr_label(instr), [assignblk]) + offset = instr.offset + instr.l + dst = m2_expr.ExprInt(offset, self.ir_arch.IRDst.size) + new_assignblk[self.ir_arch.IRDst] = dst + irs = [AssignBlock(new_assignblk)] + return IRBlock(self.ir_arch.get_instr_label(instr), irs) 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) @@ -155,16 +164,13 @@ class CGen(object): irblocks_list.append(irblocks) return irblocks_list - def gen_mem_prefetch(self, assignblk, mems_to_prefetch): - out = [] - for expr, prefetcher in sorted(mems_to_prefetch.iteritems()): - str_src = self.id_to_c(expr) - str_dst = self.id_to_c(prefetcher) - out.append('%s = %s;' % (str_dst, str_src)) - assignblk.C_prefetch = out - return out - 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 @@ -176,17 +182,51 @@ class CGen(object): dst_var[expr] = dst return dst - def gen_assignments(self, assignblk, prefetchers): - out_var = [] - out_main = [] - out_mem = [] - out_updt = [] + 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, m2_expr.ExprMem): + continue + var_num = mem_index[expr.size] + mem_index[expr.size] += 1 + var = m2_expr.ExprId( + "prefetch_%.2d_%.2d" % (expr.size, var_num), expr.size) + mem_var[expr] = var + + # Generate memory prefetch + return mem_var + + 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} + 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(): - out_var.append("uint%d_t %s;" % (var.size, var)) + c_var.append("uint%d_t %s;" % (var.size, var)) for dst, src in sorted(assignblk.iteritems()): src = src.replace_expr(prefetchers) @@ -196,10 +236,10 @@ class CGen(object): 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 - out_main.append( + c_main.append( '%s = (%s);' % (self.id_to_c(new_dst), self.id_to_c(src))) else: - out_main.append( + c_main.append( '%s = (%s)&0x%X;' % (self.id_to_c(new_dst), self.id_to_c(src), SIZE_TO_MASK[src.size])) @@ -207,48 +247,17 @@ class CGen(object): ptr = dst.arg.replace_expr(prefetchers) new_dst = m2_expr.ExprMem(ptr, dst.size) str_dst = self.id_to_c(new_dst).replace('MEM_LOOKUP', 'MEM_WRITE') - out_mem.append('%s, %s);' % (str_dst[:-1], self.id_to_c(src))) + c_mem.append('%s, %s);' % (str_dst[:-1], self.id_to_c(src))) else: raise ValueError("Unknown dst") for dst, new_dst in dst_var.iteritems(): if dst is self.ir_arch.IRDst: continue - out_updt.append('%s = %s;' % (self.id_to_c(dst), self.id_to_c(new_dst))) - out_var.append("uint%d_t %s;" % (new_dst.size, new_dst)) - - assignblk.C_var = out_var - assignblk.C_main = out_main - assignblk.C_mem = out_mem - assignblk.C_updt = out_updt + c_updt.append('%s = %s;' % (self.id_to_c(dst), self.id_to_c(new_dst))) + c_var.append("uint%d_t %s;" % (new_dst.size, new_dst)) - def gen_c_assignblk(self, assignblk): - mem_read, mem_write = False, False - - mem_index = {8: 0, 16: 0, 32: 0, 64: 0} - mem_var = {} - prefetch_index = {8: 0, 16: 0, 32: 0, 64: 0} - - # Prefetch memory read - for expr in assignblk.get_r(mem_read=True): - if not isinstance(expr, m2_expr.ExprMem): - continue - mem_read = True - var_num = mem_index[expr.size] - mem_index[expr.size] += 1 - var = m2_expr.ExprId( - "prefetch_%.2d_%.2d" % (expr.size, var_num), expr.size) - mem_var[expr] = var - - # Check if assignblk can write mem - mem_write = any(isinstance(expr, m2_expr.ExprMem) - for expr in assignblk.get_w()) - - assignblk.mem_write = mem_write - assignblk.mem_read = mem_read - - # Generate memory prefetch - return mem_var + return c_prefetch, c_var, c_main, c_mem, c_updt def gen_check_memory_exception(self, address): dst = self.dst_to_c(address) @@ -313,12 +322,12 @@ class CGen(object): return out - def gen_pre_code(self, attrib): + def gen_pre_code(self, instr_attrib): out = [] - if attrib.log_mn: - out.append('printf("%.8X %s\\n");' % (attrib.instr.offset, - attrib.instr)) + if instr_attrib.log_mn: + out.append('printf("%.8X %s\\n");' % (instr_attrib.instr.offset, + instr_attrib.instr)) return out def gen_post_code(self, attrib): @@ -357,7 +366,7 @@ class CGen(object): """ Generate code for possible @dst2index. - @attrib: an Attributs instance + @attrib: an Attributes instance @instr_offsets: list of instructions offsets @dst2index: link from destination to index """ @@ -377,54 +386,57 @@ class CGen(object): 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_c_code(self, assignblk, c_dst): + def gen_c_code(self, attrib, c_dst, c_assignmnts): """ - Generate the C code for @assignblk. - @assignblk: an Assignblk instance + 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 += assignblk.C_var + out += c_var out.append("// Prefetch") - out += assignblk.C_prefetch + out += c_prefetch out.append("// Dst") out += c_dst out.append("// Main") - out += assignblk.C_main + out += c_main out.append("// Check op/mem exceptions") # Check memory access if assignblk has memory read - if assignblk.C_prefetch: - out += self.gen_check_memory_exception(assignblk.instr_addr) + if c_prefetch: + out += self.gen_check_memory_exception(attrib.instr.offset) # Check if operator raised exception flags - if assignblk.op_set_exception: - out += self.gen_check_cpu_exception(assignblk.instr_addr) + if attrib.op_set_exception: + out += self.gen_check_cpu_exception(attrib.instr.offset) out.append("// Mem updt") - out += assignblk.C_mem + out += c_mem out.append("// Check exception Mem write") # Check memory write exceptions - if assignblk.mem_write: - out += self.gen_check_memory_exception(assignblk.instr_addr) + if attrib.mem_write: + out += self.gen_check_memory_exception(attrib.instr.offset) out.append("// Updt") - out += assignblk.C_updt + out += c_updt out.append("// Checks exception") # Check post assignblk exception flags - if assignblk.set_exception: - out += self.gen_check_cpu_exception(assignblk.instr_addr) + if attrib.set_exception: + out += self.gen_check_cpu_exception(attrib.instr.offset) out.append("}") @@ -436,29 +448,27 @@ class CGen(object): return any(operator.startswith(except_op) for except_op in self.IMPLICIT_EXCEPTION_OP) - def get_caracteristics(self, irblock): + def get_caracteristics(self, assignblk, attrib): """ - Get the carateristics of each assignblk in the @irblock - @irblock: an irbloc instance + Set the carateristics in @attrib according to the @assignblk + @assignblk: an AssignBlock instance + @attrib: an Attributes instance """ - for assignblk in irblock.irs: - assignblk.mem_read, assignblk.mem_write = False, False - assignblk.op_set_exception = False - # Check explicit exception raising - assignblk.set_exception = self.ir_arch.arch.regs.exception_flags in assignblk - - element_read = assignblk.get_r(mem_read=True) - # Check implicit exception raising - assignblk.op_set_exception = any(self.is_exception_operator(operator) - for elem in assignblk.values() - for operator in m2_expr.get_expr_ops(elem)) - # Check mem read - assignblk.mem_read = any(isinstance(expr, m2_expr.ExprMem) - for expr in element_read) - # Check mem write - assignblk.mem_write = any(isinstance(dst, m2_expr.ExprMem) - for dst in assignblk) + # 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 implicit exception raising + attrib.op_set_exception = any(self.is_exception_operator(operator) + for elem in assignblk.values() + for operator in m2_expr.get_expr_ops(elem)) + # Check mem read + attrib.mem_read = any(isinstance(expr, m2_expr.ExprMem) + for expr in element_read) + # Check mem write + attrib.mem_write = any(isinstance(dst, m2_expr.ExprMem) + for dst in assignblk) def get_attributes(self, instr, irblocks, log_mn=False, log_regs=False): """ @@ -469,17 +479,24 @@ class CGen(object): @log_regs: generate code to log registers states """ - attrib = Attributes(log_mn, log_regs) + instr_attrib = Attributes() + instr_attrib.instr = instr + irblocks_attributes = [] for irblock in irblocks: + attributes = [] + irblocks_attributes.append(attributes) for assignblk in irblock.irs: - self.get_caracteristics(irblock) - attrib.mem_read |= assignblk.mem_read - attrib.mem_write |= assignblk.mem_write - attrib.set_exception |= assignblk.set_exception - attrib.op_set_exception |= assignblk.op_set_exception - attrib.instr = instr - return attrib + 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.op_set_exception |= attrib.op_set_exception + instr_attrib.set_exception |= attrib.set_exception + + return instr_attrib, irblocks_attributes def gen_bad_block(self): """ @@ -503,12 +520,11 @@ class CGen(object): lbl_start = self.ir_arch.symbol_pool.getby_offset_create(instr_offsets[0]) return (self.CODE_INIT % self.label_to_jitlabel(lbl_start)).split("\n"), instr_offsets - def gen_irblock(self, attrib, instr_offsets, instr, irblock): + def gen_irblock(self, instr_attrib, attributes, instr_offsets, irblock): """ Generate the C code for an @irblock - @instr: the current instruction to translate @irblock: an irbloc instance - @attrib: an Attributs instance + @attributes: an Attributes instance list """ out = [] @@ -518,17 +534,14 @@ class CGen(object): c_dst, dst2index = self.gen_assignblk_dst(irblock.dst) else: c_dst = [] - assignblk.instr_addr = instr.offset - prefetchers = self.gen_c_assignblk(assignblk) - self.gen_mem_prefetch(assignblk, prefetchers) - self.gen_assignments(assignblk, prefetchers) - out += self.gen_c_code(assignblk, 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(attrib, instr_offsets, dst2index) + out += self.gen_dst_goto(instr_attrib, instr_offsets, dst2index) return out @@ -556,7 +569,7 @@ class CGen(object): out, instr_offsets = self.gen_init(block) for instr, irblocks in zip(block.lines, irblocks_list): - attrib = self.get_attributes(instr, irblocks, log_mn, log_regs) + instr_attrib, irblocks_attributes = self.get_attributes(instr, irblocks, log_mn, log_regs) for index, irblock in enumerate(irblocks): self.ir_arch.irbloc_fix_regs_for_mode( @@ -569,8 +582,8 @@ class CGen(object): out.append("%-40s // %.16X %s" % (self.label_to_jitlabel(irblock.label) + ":", instr.offset, instr)) if index == 0: - out += self.gen_pre_code(attrib) - out += self.gen_irblock(attrib, instr_offsets, instr, irblock) + out += self.gen_pre_code(instr_attrib) + out += self.gen_irblock(instr_attrib, irblocks_attributes[index], instr_offsets, irblock) out += self.gen_finalize(block) return ['\t' + line for line in out] diff --git a/miasm2/jitter/llvmconvert.py b/miasm2/jitter/llvmconvert.py index b2e1e957..e7a1d6bc 100644 --- a/miasm2/jitter/llvmconvert.py +++ b/miasm2/jitter/llvmconvert.py @@ -1003,10 +1003,10 @@ class LLVMFunction(): # Reactivate object caching self.main_stream = current_main_stream - def gen_pre_code(self, attributes): - if attributes.log_mn: - self.printf("%.8X %s\n" % (attributes.instr.offset, - attributes.instr)) + def gen_pre_code(self, instr_attrib): + if instr_attrib.log_mn: + self.printf("%.8X %s\n" % (instr_attrib.instr.offset, + instr_attrib.instr)) def gen_post_code(self, attributes): if attributes.log_regs: @@ -1110,19 +1110,20 @@ class LLVMFunction(): self.set_ret(dst) - def gen_irblock(self, attrib, instr, instr_offsets, irblock): + def gen_irblock(self, instr_attrib, attributes, instr_offsets, irblock): """ Generate the code for an @irblock - @instr: the current instruction to translate - @irblock: an irbloc instance - @attrib: an Attributs instance + @instr_attrib: an Attributs instance or the instruction to translate + @attributes: list of Attributs corresponding to irblock assignments @instr_offsets: offset of all asmblock's instructions + @irblock: an irblock instance """ case2dst = None case_value = None + instr = instr_attrib.instr - for assignblk in irblock.irs: + for index, assignblk in enumerate(irblock.irs): # Enable cache self.main_stream = True self.expr_cache = {} @@ -1141,12 +1142,12 @@ class LLVMFunction(): values[dst] = self.add_ir(src) # Check memory access exception - if assignblk.mem_read: + if attributes[index].mem_read: self.check_memory_exception(instr.offset, restricted_exception=True) # Check operation exception - if assignblk.op_set_exception: + if attributes[index].op_set_exception: self.check_cpu_exception(instr.offset, restricted_exception=True) # Update the memory @@ -1155,7 +1156,7 @@ class LLVMFunction(): self.affect(src, dst) # Check memory write exception - if assignblk.mem_write: + if attributes[index].mem_write: self.check_memory_exception(instr.offset, restricted_exception=True) @@ -1165,14 +1166,14 @@ class LLVMFunction(): self.affect(src, dst) # Check post assignblk exception flags - if assignblk.set_exception: + if attributes[index].set_exception: self.check_cpu_exception(instr.offset, restricted_exception=True) # Destination assert case2dst is not None if len(case2dst) == 1: # Avoid switch in this common case - self.gen_jump2dst(attrib, instr_offsets, case2dst.values()[0]) + self.gen_jump2dst(instr_attrib, instr_offsets, case2dst.values()[0]) else: current_bbl = self.builder.basic_block @@ -1184,7 +1185,7 @@ class LLVMFunction(): bbl = self.append_basic_block(name) case2bbl[case] = bbl self.builder.position_at_start(bbl) - self.gen_jump2dst(attrib, instr_offsets, dst) + self.gen_jump2dst(instr_attrib, instr_offsets, dst) # Jump on the correct output self.builder.position_at_end(current_bbl) @@ -1311,8 +1312,8 @@ class LLVMFunction(): for instr, irblocks in zip(asmblock.lines, irblocks_list): - attrib = codegen.get_attributes(instr, irblocks, self.log_mn, - self.log_regs) + instr_attrib, irblocks_attributes = codegen.get_attributes(instr, irblocks, self.log_mn, + self.log_regs) # Pre-create basic blocks for irblock in irblocks: @@ -1328,8 +1329,8 @@ class LLVMFunction(): self.builder.position_at_end(self.get_basic_bloc_by_label(name)) if index == 0: - self.gen_pre_code(attrib) - self.gen_irblock(attrib, instr, instr_offsets, irblock) + self.gen_pre_code(instr_attrib) + self.gen_irblock(instr_attrib, irblocks_attributes[index], instr_offsets, irblock) # Gen finalize (see codegen::CGen) is unrecheable, except with delayslot self.gen_finalize(asmblock, codegen) diff --git a/test/analysis/data_flow.py b/test/analysis/data_flow.py index 1784f87f..e9029e8e 100644 --- a/test/analysis/data_flow.py +++ b/test/analysis/data_flow.py @@ -32,6 +32,8 @@ LBL4 = AsmLabel("lbl4") LBL5 = AsmLabel("lbl5") LBL6 = AsmLabel("lbl6") +IRDst = ExprId('IRDst', 32) +dummy = ExprId('dummy', 32) def gen_irblock(label, exprs_list): @@ -43,6 +45,7 @@ def gen_irblock(label, exprs_list): else: irs.append(AssignBlock(exprs)) + irs.append(AssignBlock({IRDst:dummy})) irbl = IRBlock(label, irs, lines) return irbl @@ -67,7 +70,7 @@ class IRATest(ira): def __init__(self, symbol_pool=None): arch = Arch() super(IRATest, self).__init__(arch, 32, symbol_pool) - self.IRDst = pc + self.IRDst = IRDst self.ret_reg = r def get_out_regs(self, _): diff --git a/test/ir/symbexec.py b/test/ir/symbexec.py index bd28c4ee..e2bd411f 100755 --- a/test/ir/symbexec.py +++ b/test/ir/symbexec.py @@ -63,8 +63,7 @@ class TestSymbExec(unittest.TestCase): # apply_change / eval_ir / apply_expr ## x = a (with a = 0x0) - assignblk = AssignBlock() - assignblk[id_x] = id_a + assignblk = AssignBlock({id_x:id_a}) e.eval_ir(assignblk) self.assertEqual(e.apply_expr(id_x), addr0) |