diff options
58 files changed, 1528 insertions, 435 deletions
diff --git a/example/disasm/callback.py b/example/disasm/callback.py index 63987e85..a9bef20b 100644 --- a/example/disasm/callback.py +++ b/example/disasm/callback.py @@ -52,7 +52,7 @@ print "\n".join(str(block) for block in blocks) # Enable callback cb_x86_funcs.append(cb_x86_callpop) ## Other method: -## mdis.dis_bloc_callback = cb_x86_callpop +## mdis.dis_block_callback = cb_x86_callpop print "=" * 40 print "With callback:\n" diff --git a/example/expression/access_c.py b/example/expression/access_c.py index f285eb55..de158730 100644 --- a/example/expression/access_c.py +++ b/example/expression/access_c.py @@ -60,15 +60,15 @@ def find_call(ira): for irb in ira.blocks.values(): out = set() - if len(irb.irs) < 2: + if len(irb) < 2: continue - assignblk = irb.irs[-2] + assignblk = irb[-2] for src in assignblk.itervalues(): if not isinstance(src, ExprOp): continue if not src.op.startswith('call_func'): continue - out.add((irb, len(irb.irs) - 2)) + out.add((irb, len(irb) - 2)) if len(out) != 1: continue irb, index = out.pop() @@ -98,7 +98,7 @@ def get_funcs_arg0(ctx, ira, lbl_head): element = ira.arch.regs.RSI for irb, index in find_call(ira): - instr = irb.irs[index].instr + instr = irb[index].instr print 'Analysing references from:', hex(instr.offset), instr g_list = g_dep.get(irb.label, set([element]), index, set([lbl_head])) for dep in g_list: diff --git a/example/expression/basic_simplification.py b/example/expression/basic_simplification.py index ef904686..eefdc765 100644 --- a/example/expression/basic_simplification.py +++ b/example/expression/basic_simplification.py @@ -6,8 +6,8 @@ Simple expression simplification demo """ -a = ExprId('eax') -b = ExprId('ebx') +a = ExprId('eax', 32) +b = ExprId('ebx', 32) exprs = [a + b - a, ExprInt(0x12, 32) + ExprInt(0x30, 32) - a, diff --git a/example/expression/expr_grapher.py b/example/expression/expr_grapher.py index 0de2142b..9bf6cd84 100644 --- a/example/expression/expr_grapher.py +++ b/example/expression/expr_grapher.py @@ -2,10 +2,10 @@ from miasm2.expression.expression import * print "Simple Expression grapher demo" -a = ExprId("A") -b = ExprId("B") -c = ExprId("C") -d = ExprId("D") +a = ExprId("A", 32) +b = ExprId("B", 32) +c = ExprId("C", 32) +d = ExprId("D", 32) m = ExprMem(a + b + c + a) e1 = ExprCompose(a + b - (c * a) / m | b, a + m) diff --git a/example/expression/expr_reduce.py b/example/expression/expr_reduce.py index bb94ceb9..7c6e0c4c 100644 --- a/example/expression/expr_reduce.py +++ b/example/expression/expr_reduce.py @@ -75,7 +75,7 @@ class StructLookup(ExprReducer): def test(): struct_lookup = StructLookup() - ptr = ExprId('ECX') + ptr = ExprId('ECX', 32) int4 = ExprInt(4, 32) tests = [ (ptr, StructLookup.FIELD_A_PTR), diff --git a/example/expression/get_read_write.py b/example/expression/get_read_write.py index f4dde4b5..b4a0773b 100644 --- a/example/expression/get_read_write.py +++ b/example/expression/get_read_write.py @@ -16,10 +16,10 @@ l.offset, l.l = 0, 15 ir_arch.add_instr(l) print '*' * 80 -for lbl, b in ir_arch.blocks.items(): - print b - for irs in b.irs: - o_r, o_w = get_rw(irs) +for lbl, irblock in ir_arch.blocks.items(): + print irblock + for assignblk in irblock: + o_r, o_w = get_rw(assignblk) print 'read: ', [str(x) for x in o_r] print 'written:', [str(x) for x in o_w] print diff --git a/example/expression/simplification_add.py b/example/expression/simplification_add.py index 41720f3a..621d1139 100644 --- a/example/expression/simplification_add.py +++ b/example/expression/simplification_add.py @@ -30,7 +30,7 @@ def simp_add_mul(expr_simp, expr): # Do not simplify return expr -a = m2_expr.ExprId('a') +a = m2_expr.ExprId('a', 32) base_expr = a + a + a print "Without adding the simplification:" print "\t%s = %s" % (base_expr, expr_simp(base_expr)) diff --git a/example/expression/simplification_tools.py b/example/expression/simplification_tools.py index 258b5ce4..1fb95a80 100644 --- a/example/expression/simplification_tools.py +++ b/example/expression/simplification_tools.py @@ -7,11 +7,11 @@ Expression simplification demo. """ -a = ExprId('a') -b = ExprId('b') -c = ExprId('c') -d = ExprId('d') -e = ExprId('e') +a = ExprId('a', 32) +b = ExprId('b', 32) +c = ExprId('c', 32) +d = ExprId('d', 32) +e = ExprId('e', 32) m = ExprMem(a) s = a[:8] diff --git a/example/expression/solve_condition_stp.py b/example/expression/solve_condition_stp.py index b3ee6938..24d2dd50 100644 --- a/example/expression/solve_condition_stp.py +++ b/example/expression/solve_condition_stp.py @@ -109,7 +109,7 @@ if __name__ == '__main__': argc = ExprId('argc', 32) argv = ExprId('argv', 32) - ret_addr = ExprId('ret_addr') + ret_addr = ExprId('ret_addr', 32) reg_and_id[argc.name] = argc reg_and_id[argv.name] = argv reg_and_id[ret_addr.name] = ret_addr diff --git a/example/ida/ctype_propagation.py b/example/ida/ctype_propagation.py index 8c64c6d2..54b23516 100644 --- a/example/ida/ctype_propagation.py +++ b/example/ida/ctype_propagation.py @@ -114,7 +114,7 @@ class SymbExecCTypeFix(SymbExecCType): """ offset2cmt = {} - for index, assignblk in enumerate(irb.irs): + for index, assignblk in enumerate(irb): if set(assignblk) == set([self.ir_arch.IRDst, self.ir_arch.pc]): # Don't display on jxx continue diff --git a/example/ida/depgraph.py b/example/ida/depgraph.py index 915f14bc..5342313a 100644 --- a/example/ida/depgraph.py +++ b/example/ida/depgraph.py @@ -34,7 +34,7 @@ class depGraphSettingsForm(ida_kernwin.Form): cur_block = block assert cur_block is not None line_nb = None - for line_nb, assignblk in enumerate(cur_block.irs): + for line_nb, assignblk in enumerate(cur_block): if assignblk.instr.offset == self.address: break assert line_nb is not None @@ -110,13 +110,13 @@ Method to use: elif mode == 1: return value + 1 else: - return len(self.ira.blocks[self.label].irs) + return len(self.ira.blocks[self.label]) @property def elements(self): value = self.cbReg.value if value in self.stk_args: - line = self.ira.blocks[self.label].irs[self.line_nb].instr + line = self.ira.blocks[self.label][self.line_nb].instr arg_num = self.stk_args[value] stk_high = m2_expr.ExprInt(idc.GetSpd(line.offset), ir_arch.sp.size) stk_off = m2_expr.ExprInt(self.ira.sp.size/8 * arg_num, ir_arch.sp.size) @@ -174,7 +174,7 @@ def treat_element(): for node in graph.relevant_nodes: try: - offset = ir_arch.blocks[node.label].irs[node.line_nb].instr.offset + offset = ir_arch.blocks[node.label][node.line_nb].instr.offset except IndexError: print "Unable to highlight %s" % node continue @@ -229,7 +229,7 @@ def launch_depgraph(): for irb in ir_arch.blocks.values(): irs = [] fix_stack = irb.label.offset is not None and settings.unalias_stack - for assignblk in irb.irs: + for assignblk in irb: if fix_stack: stk_high = m2_expr.ExprInt(idc.GetSpd(assignblk.instr.offset), ir_arch.sp.size) fix_dct = {ir_arch.sp: mn.regs.regs_init[ir_arch.sp] + stk_high} diff --git a/example/ida/graph_ir.py b/example/ida/graph_ir.py index 8d9dea4f..7e303aac 100644 --- a/example/ida/graph_ir.py +++ b/example/ida/graph_ir.py @@ -40,7 +40,7 @@ def color_irblock(irblock, ir_arch): out = [] lbl = idaapi.COLSTR(str(irblock.label), idaapi.SCOLOR_INSN) out.append(lbl) - for assignblk in irblock.irs: + for assignblk in irblock: for dst, src in sorted(assignblk.iteritems()): dst_f = expr2colorstr(ir_arch.arch.regs.all_regs_ids, dst) src_f = expr2colorstr(ir_arch.arch.regs.all_regs_ids, src) @@ -148,7 +148,7 @@ def build_graph(verbose=False, simplify=False): for irb in ir_arch.blocks.itervalues(): irs = [] - for assignblk in irb.irs: + for assignblk in irb: new_assignblk = { expr_simp(dst): expr_simp(src) for dst, src in assignblk.iteritems() diff --git a/example/symbol_exec/depgraph.py b/example/symbol_exec/depgraph.py index c1d6174d..b8d838ae 100644 --- a/example/symbol_exec/depgraph.py +++ b/example/symbol_exec/depgraph.py @@ -55,8 +55,8 @@ if args.rename_args: if arch == "x86_32": # StdCall example for i in xrange(4): - e_mem = ExprMem(ExprId("ESP_init") + ExprInt(4 * (i + 1), 32), 32) - init_ctx[e_mem] = ExprId("arg%d" % i) + e_mem = ExprMem(ExprId("ESP_init", 32) + ExprInt(4 * (i + 1), 32), 32) + init_ctx[e_mem] = ExprId("arg%d" % i, 32) # Disassemble the targeted function blocks = mdis.dis_multiblock(int(args.func_addr, 0)) @@ -74,14 +74,14 @@ dg = DependencyGraph(ir_arch, implicit=args.implicit, # Build information target_addr = int(args.target_addr, 0) current_block = list(ir_arch.getby_offset(target_addr))[0] -line_nb = 0 -for line_nb, assignblk in enumerate(current_block.irs): +assignblk_index = 0 +for assignblk_index, assignblk in enumerate(current_block): if assignblk.instr.offset == target_addr: break # Enumerate solutions json_solutions = [] -for sol_nb, sol in enumerate(dg.get(current_block.label, elements, line_nb, set())): +for sol_nb, sol in enumerate(dg.get(current_block.label, elements, assignblk_index, set())): fname = "sol_%d.dot" % sol_nb with open(fname, "w") as fdesc: fdesc.write(sol.graph.dot()) diff --git a/miasm2/analysis/cst_propag.py b/miasm2/analysis/cst_propag.py index 2a439ccc..7946a496 100644 --- a/miasm2/analysis/cst_propag.py +++ b/miasm2/analysis/cst_propag.py @@ -73,7 +73,7 @@ class SymbExecStateFix(SymbolicExecutionEngine): self.cst_propag_link = cst_propag_link def propag_expr_cst(self, expr): - """Propagate consttant expressions in @expr + """Propagate constant expressions in @expr @expr: Expression to update""" elements = expr.get_r(mem_read=True) to_propag = {} @@ -93,7 +93,7 @@ class SymbExecStateFix(SymbolicExecutionEngine): @step: display intermediate steps """ assignblks = [] - for index, assignblk in enumerate(irb.irs): + for index, assignblk in enumerate(irb): new_assignblk = {} links = {} for dst, src in assignblk.iteritems(): diff --git a/miasm2/analysis/data_analysis.py b/miasm2/analysis/data_analysis.py index b3e15ca6..130d45a4 100644 --- a/miasm2/analysis/data_analysis.py +++ b/miasm2/analysis/data_analysis.py @@ -14,7 +14,7 @@ def intra_block_flow_raw(ir_arch, flow_graph, irb, in_nodes, out_nodes): Create data flow for an irbloc using raw IR expressions """ current_nodes = {} - for i, assignblk in enumerate(irb.irs): + for i, assignblk in enumerate(irb): dict_rw = assignblk.get_rw(cst_read=True) if irb.label.offset == 0x13: print irb.label @@ -85,7 +85,7 @@ def intra_block_flow_symbexec(ir_arch, flow_graph, irb, in_nodes, out_nodes): continue read_values = v.get_r(cst_read=True) # print n_w, v, [str(x) for x in read_values] - node_n_w = get_node_name(irb.label, len(irb.irs), n_w) + node_n_w = get_node_name(irb.label, len(irb), n_w) for n_r in read_values: if n_r in current_nodes: @@ -171,7 +171,7 @@ def create_implicit_flow(ir_arch, flow_graph, irb_in_nodes, irb_out_ndes): # print "###", irb_son # print "###", 'IN', [str(x) for x in irb_son.in_nodes] - node_n_w = irb.label, len(irb.irs), n_r + node_n_w = irb.label, len(irb), n_r irb_out_nodes[irb.label][n_r] = node_n_w if not n_r in irb_in_nodes[irb.label]: irb_in_nodes[irb.label][n_r] = irb.label, 0, n_r diff --git a/miasm2/analysis/data_flow.py b/miasm2/analysis/data_flow.py index 67768264..d9f61c56 100644 --- a/miasm2/analysis/data_flow.py +++ b/miasm2/analysis/data_flow.py @@ -6,7 +6,7 @@ from miasm2.ir.ir import AssignBlock, IRBlock class ReachingDefinitions(dict): """ - Computes for each instruction the set of reaching definitions. + Computes for each assignblock the set of reaching definitions. Example: IR block: lbl0: @@ -26,7 +26,7 @@ class ReachingDefinitions(dict): IBM Thomas J. Watson Research Division, Algorithm MK This class is usable as a dictionnary whose struture is - { (block, instr_index): { lvalue: set((block, instr_index)) } } + { (block, index): { lvalue: set((block, index)) } } """ ir_a = None @@ -36,12 +36,12 @@ class ReachingDefinitions(dict): self.ir_a = ir_a self.compute() - def get_definitions(self, block_lbl, instruction): - """Returns the dict { lvalue: set((def_block_lbl, def_instr_index)) } - associated with self.ir_a.@block.irs[@instruction] + def get_definitions(self, block_lbl, assignblk_index): + """Returns the dict { lvalue: set((def_block_lbl, def_index)) } + associated with self.ir_a.@block.assignblks[@assignblk_index] or {} if it is not yet computed """ - return self.get((block_lbl, instruction), {}) + return self.get((block_lbl, assignblk_index), {}) def compute(self): """This is the main fixpoint""" @@ -54,12 +54,12 @@ class ReachingDefinitions(dict): def process_block(self, block): """ Fetch reach definitions from predecessors and propagate it to - the instruction in block @block. + the assignblk in block @block. """ predecessor_state = {} for pred_lbl in self.ir_a.graph.predecessors(block.label): pred = self.ir_a.blocks[pred_lbl] - for lval, definitions in self.get_definitions(pred_lbl, len(pred.irs)).iteritems(): + for lval, definitions in self.get_definitions(pred_lbl, len(pred)).iteritems(): predecessor_state.setdefault(lval, set()).update(definitions) modified = self.get((block.label, 0)) != predecessor_state @@ -67,33 +67,33 @@ class ReachingDefinitions(dict): return False self[(block.label, 0)] = predecessor_state - for instr_index in xrange(len(block.irs)): - modified |= self.process_instruction(block, instr_index) + for index in xrange(len(block)): + modified |= self.process_assignblock(block, index) return modified - def process_instruction(self, block, instr_index): + def process_assignblock(self, block, assignblk_index): """ Updates the reach definitions with values defined at - instruction @instr_index in block @block. - NB: the effect of instruction @instr_index in stored at index - (@block, @instr_index + 1). + assignblock @assignblk_index in block @block. + NB: the effect of assignblock @assignblk_index in stored at index + (@block, @assignblk_index + 1). """ - instr = block.irs[instr_index] - defs = self.get_definitions(block.label, instr_index).copy() - for lval in instr: - defs.update({lval: set([(block.label, instr_index)])}) + assignblk = block[assignblk_index] + defs = self.get_definitions(block.label, assignblk_index).copy() + for lval in assignblk: + defs.update({lval: set([(block.label, assignblk_index)])}) - modified = self.get((block.label, instr_index + 1)) != defs + modified = self.get((block.label, assignblk_index + 1)) != defs if modified: - self[(block.label, instr_index + 1)] = defs + self[(block.label, assignblk_index + 1)] = defs return modified ATTR_DEP = {"color" : "black", "_type" : "data"} -InstrNode = namedtuple('InstructionNode', ['label', 'index', 'var']) +AssignblkNode = namedtuple('AssignblkNode', ['label', 'index', 'var']) class DiGraphDefUse(DiGraph): """Representation of a Use-Definition graph as defined by @@ -148,18 +148,18 @@ class DiGraphDefUse(DiGraph): deref_mem=deref_mem) def _compute_def_use_block(self, block, reaching_defs, deref_mem=False): - for ind, instr in enumerate(block.irs): - instruction_reaching_defs = reaching_defs.get_definitions(block.label, ind) - for lval, expr in instr.iteritems(): - self.add_node(InstrNode(block.label, ind, lval)) + for index, assignblk in enumerate(block): + assignblk_reaching_defs = reaching_defs.get_definitions(block.label, index) + for lval, expr in assignblk.iteritems(): + self.add_node(AssignblkNode(block.label, index, lval)) read_vars = expr.get_r(mem_read=deref_mem) if deref_mem and lval.is_mem(): read_vars.update(lval.arg.get_r(mem_read=deref_mem)) for read_var in read_vars: - for reach in instruction_reaching_defs.get(read_var, set()): - self.add_data_edge(InstrNode(reach[0], reach[1], read_var), - InstrNode(block.label, ind, lval)) + for reach in assignblk_reaching_defs.get(read_var, set()): + self.add_data_edge(AssignblkNode(reach[0], reach[1], read_var), + AssignblkNode(block.label, index, lval)) def del_edge(self, src, dst): super(DiGraphDefUse, self).del_edge(src, dst) @@ -178,25 +178,25 @@ class DiGraphDefUse(DiGraph): self.add_uniq_labeled_edge(src, dst, ATTR_DEP) def node2lines(self, node): - lbl, ind, reg = node - yield self.DotCellDescription(text="%s (%s)" % (lbl, ind), + lbl, index, reg = node + yield self.DotCellDescription(text="%s (%s)" % (lbl, index), attr={'align': 'center', 'colspan': 2, 'bgcolor': 'grey'}) - src = self._blocks[lbl].irs[ind][reg] + src = self._blocks[lbl][index][reg] line = "%s = %s" % (reg, src) yield self.DotCellDescription(text=line, attr={}) yield self.DotCellDescription(text="", attr={}) -def dead_simp_useful_instrs(defuse, reaching_defs): +def dead_simp_useful_assignblks(defuse, reaching_defs): """Mark useful statements using previous reach analysis and defuse Source : Kennedy, K. (1979). A survey of data flow analysis techniques. IBM Thomas J. Watson Research Division, Algorithm MK - Return a set of triplets (block, instruction number, instruction) of - useful instructions + Return a set of triplets (block, assignblk number, lvalue) of + useful definitions PRE: compute_reach(self) """ @@ -215,20 +215,20 @@ def dead_simp_useful_instrs(defuse, reaching_defs): # Block has a nonexistant successor or is a leaf if keep_all_definitions or (len(successors) == 0): valid_definitions = reaching_defs.get_definitions(block_lbl, - len(block.irs)) + len(block)) for lval, definitions in valid_definitions.iteritems(): if (lval in ir_a.get_out_regs(block) or keep_all_definitions): for definition in definitions: - useful.add(InstrNode(definition[0], definition[1], lval)) + useful.add(AssignblkNode(definition[0], definition[1], lval)) # Force keeping of specific cases - for instr_index, instr in enumerate(block.irs): - for lval, rval in instr.iteritems(): + for index, assignblk in enumerate(block): + for lval, rval in assignblk.iteritems(): if (lval.is_mem() or ir_a.IRDst == lval or rval.is_function_call()): - useful.add(InstrNode(block_lbl, instr_index, lval)) + useful.add(AssignblkNode(block_lbl, index, lval)) # Useful nodes dependencies for node in useful: @@ -237,22 +237,27 @@ def dead_simp_useful_instrs(defuse, reaching_defs): def dead_simp(ir_a): """ + Remove useless affectations. + This function is used to analyse relation of a * complete function * This means the blocks under study represent a solid full function graph. Source : Kennedy, K. (1979). A survey of data flow analysis techniques. IBM Thomas J. Watson Research Division, page 43 + + @ir_a: IntermediateRepresentation instance """ + modified = False reaching_defs = ReachingDefinitions(ir_a) defuse = DiGraphDefUse(reaching_defs, deref_mem=True) - useful = set(dead_simp_useful_instrs(defuse, reaching_defs)) + useful = set(dead_simp_useful_assignblks(defuse, reaching_defs)) for block in ir_a.blocks.itervalues(): irs = [] - for idx, assignblk in enumerate(block.irs): + for idx, assignblk in enumerate(block): new_assignblk = dict(assignblk) for lval in assignblk: - if InstrNode(block.label, idx, lval) not in useful: + if AssignblkNode(block.label, idx, lval) not in useful: del new_assignblk[lval] modified = True irs.append(AssignBlock(new_assignblk, assignblk.instr)) diff --git a/miasm2/analysis/depgraph.py b/miasm2/analysis/depgraph.py index d1ac13c8..bd4bfa7e 100644 --- a/miasm2/analysis/depgraph.py +++ b/miasm2/analysis/depgraph.py @@ -265,9 +265,9 @@ class DependencyResult(DependencyState): break assignmnts = {} for element in elements: - if element in irb.irs[line_nb]: + if element in irb[line_nb]: # constants, label, ... are not in destination - assignmnts[element] = irb.irs[line_nb][element] + assignmnts[element] = irb[line_nb][element] assignblks.append(AssignBlock(assignmnts)) return IRBlock(irb.label, assignblks) @@ -294,7 +294,7 @@ class DependencyResult(DependencyState): else: line_nb = None assignblks += self.irblock_slice(self._ira.blocks[label], - line_nb).irs + line_nb).assignblks # Eval the block temp_label = AsmLabel("Temp") @@ -581,9 +581,9 @@ class DependencyGraph(object): @state: instance of DependencyState""" irb = self._ira.blocks[state.label] - line_nb = len(irb.irs) if state.line_nb is None else state.line_nb + line_nb = len(irb) if state.line_nb is None else state.line_nb - for cur_line_nb, assignblk in reversed(list(enumerate(irb.irs[:line_nb]))): + for cur_line_nb, assignblk in reversed(list(enumerate(irb[:line_nb]))): self._track_exprs(state, assignblk, cur_line_nb) def get(self, label, elements, line_nb, heads): diff --git a/miasm2/analysis/disasm_cb.py b/miasm2/analysis/disasm_cb.py index 9a75603f..e759e313 100644 --- a/miasm2/analysis/disasm_cb.py +++ b/miasm2/analysis/disasm_cb.py @@ -39,7 +39,7 @@ def arm_guess_subcall( # print irblock pc_val = None lr_val = None - for exprs in irblock.irs: + for exprs in irblock: for e in exprs: if e.dst == ir_arch.pc: pc_val = e.src @@ -84,7 +84,7 @@ def arm_guess_jump_table( # print irblock pc_val = None # lr_val = None - for exprs in irblock.irs: + for exprs in irblock: for e in exprs: if e.dst == ir_arch.pc: pc_val = e.src diff --git a/miasm2/arch/aarch64/arch.py b/miasm2/arch/aarch64/arch.py index 7af1953a..2712e60a 100644 --- a/miasm2/arch/aarch64/arch.py +++ b/miasm2/arch/aarch64/arch.py @@ -219,7 +219,7 @@ simdregs_h_zero = (simd32_info.parser | def ast_id2expr(t): if not t in mn_aarch64.regs.all_regs_ids_byname: - r = m2_expr.ExprId(AsmLabel(t)) + r = m2_expr.ExprId(AsmLabel(t), 32) else: r = mn_aarch64.regs.all_regs_ids_byname[t] return r diff --git a/miasm2/arch/aarch64/disasm.py b/miasm2/arch/aarch64/disasm.py index a8604fe5..17eec414 100644 --- a/miasm2/arch/aarch64/disasm.py +++ b/miasm2/arch/aarch64/disasm.py @@ -14,7 +14,7 @@ class dis_aarch64b(disasmEngine): def __init__(self, bs=None, **kwargs): super(dis_aarch64b, self).__init__( mn_aarch64, self.attrib, bs, - dis_bloc_callback = cb_aarch64_disasm, + dis_block_callback = cb_aarch64_disasm, **kwargs) @@ -23,5 +23,5 @@ class dis_aarch64l(disasmEngine): def __init__(self, bs=None, **kwargs): super(dis_aarch64l, self).__init__( mn_aarch64, self.attrib, bs, - dis_bloc_callback = cb_aarch64_disasm, + dis_block_callback = cb_aarch64_disasm, **kwargs) diff --git a/miasm2/arch/aarch64/regs.py b/miasm2/arch/aarch64/regs.py index 4589c17a..f2655ea7 100644 --- a/miasm2/arch/aarch64/regs.py +++ b/miasm2/arch/aarch64/regs.py @@ -4,6 +4,7 @@ from miasm2.expression.expression import * from miasm2.core.cpu import gen_reg, gen_regs exception_flags = ExprId('exception_flags', 32) +interrupt_num = ExprId('interrupt_num', 32) gpregs32_str = ["W%d" % i for i in xrange(0x1f)] + ["WSP"] @@ -86,7 +87,7 @@ all_regs_ids = [ X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, LR, SP, - exception_flags, + exception_flags, interrupt_num, PC, WZR, zf, nf, of, cf, diff --git a/miasm2/arch/aarch64/sem.py b/miasm2/arch/aarch64/sem.py index ab45425c..697fa981 100644 --- a/miasm2/arch/aarch64/sem.py +++ b/miasm2/arch/aarch64/sem.py @@ -3,7 +3,7 @@ from miasm2.ir.ir import IntermediateRepresentation, IRBlock, AssignBlock from miasm2.arch.aarch64.arch import mn_aarch64, conds_expr, replace_regs from miasm2.arch.aarch64.regs import * from miasm2.core.sembuilder import SemBuilder -from miasm2.jitter.csts import EXCEPT_DIV_BY_ZERO +from miasm2.jitter.csts import EXCEPT_DIV_BY_ZERO, EXCEPT_INT_XX # CPSR: N Z C V @@ -73,6 +73,13 @@ def update_flag_sub_of(op1, op2, res): "Compote OF in @res = @op1 - @op2" return m2_expr.ExprAff(of, (((op1 ^ res) & (op1 ^ op2))).msb()) + +# clearing cv flags for bics (see C5.6.25) + +def update_flag_bics (): + "Clear CF and OF" + return [ExprAff(cf, ExprInt (0,1)), ExprAff(of, ExprInt (0,1))] + # z = x+y (+cf?) @@ -119,11 +126,14 @@ def extend_arg(dst, arg): op, (reg, shift) = arg.op, arg.args if op == 'SXTW': base = reg.signExtend(dst.size) - else: + op = "<<" + elif op in ['<<', '>>', '<<a', 'a>>', '<<<', '>>>']: base = reg.zeroExtend(dst.size) + else: + raise NotImplementedError('Unknown shifter operator') - out = base << (shift.zeroExtend(dst.size) - & m2_expr.ExprInt(dst.size - 1, dst.size)) + out = ExprOp(op, base, (shift.zeroExtend(dst.size) + & m2_expr.ExprInt(dst.size - 1, dst.size))) return out @@ -138,7 +148,9 @@ ctx = {"PC": PC, "extend_arg": extend_arg, "m2_expr":m2_expr, "exception_flags": exception_flags, + "interrupt_num": interrupt_num, "EXCEPT_DIV_BY_ZERO": EXCEPT_DIV_BY_ZERO, + "EXCEPT_INT_XX": EXCEPT_INT_XX, } sbuild = SemBuilder(ctx) @@ -191,6 +203,14 @@ def bic(arg1, arg2, arg3): arg1 = arg2 & (~extend_arg(arg2, arg3)) +def bics(ir, instr, arg1, arg2, arg3): + e = [] + arg1 = arg2 & (~extend_arg(arg2, arg3)) + e += update_flag_logic (arg1) + e += update_flag_bics () + return e, [] + + @sbuild.parse def mvn(arg1, arg2): arg1 = (~extend_arg(arg1, arg2)) @@ -402,26 +422,47 @@ def ldr(ir, instr, arg1, arg2): return e, [] -def ldrb(ir, instr, arg1, arg2): +def ldr_size(ir, instr, arg1, arg2, size): e = [] addr, updt = get_mem_access(arg2) e.append( - m2_expr.ExprAff(arg1, m2_expr.ExprMem(addr, 8).zeroExtend(arg1.size))) + m2_expr.ExprAff(arg1, m2_expr.ExprMem(addr, size).zeroExtend(arg1.size))) if updt: e.append(updt) return e, [] +def ldrb(ir, instr, arg1, arg2): + return ldr_size(ir, instr, arg1, arg2, 8) + + def ldrh(ir, instr, arg1, arg2): + return ldr_size(ir, instr, arg1, arg2, 16) + + +def ldrs_size(ir, instr, arg1, arg2, size): e = [] addr, updt = get_mem_access(arg2) e.append( - m2_expr.ExprAff(arg1, m2_expr.ExprMem(addr, 16).zeroExtend(arg1.size))) + m2_expr.ExprAff(arg1, m2_expr.ExprMem(addr, size).signExtend(arg1.size))) if updt: e.append(updt) return e, [] +def ldrsb(ir, instr, arg1, arg2): + return ldrs_size(ir, instr, arg1, arg2, 8) + + +def ldrsh(ir, instr, arg1, arg2): + return ldrs_size(ir, instr, arg1, arg2, 16) + + +def ldrsw(ir, instr, arg1, arg2): + return ldrs_size(ir, instr, arg1, arg2, 32) + + + def l_str(ir, instr, arg1, arg2): e = [] addr, updt = get_mem_access(arg2) @@ -471,16 +512,6 @@ def ldp(ir, instr, arg1, arg2, arg3): return e, [] -def ldrsw(ir, instr, arg1, arg2): - e = [] - addr, updt = get_mem_access(arg2) - e.append( - m2_expr.ExprAff(arg1, m2_expr.ExprMem(addr, 32).signExtend(arg1.size))) - if updt: - e.append(updt) - return e, [] - - def sbfm(ir, instr, arg1, arg2, arg3, arg4): e = [] rim, sim = int(arg3.arg), int(arg4) + 1 @@ -691,6 +722,12 @@ def extr(arg1, arg2, arg3, arg4): compose = m2_expr.ExprCompose(arg2, arg3) arg1 = compose[int(arg4.arg):int(arg4)+arg1.size] + +@sbuild.parse +def svc(arg1): + exception_flags = m2_expr.ExprInt(EXCEPT_INT_XX, exception_flags.size) + interrupt_num = m2_expr.ExprInt(int(arg1), interrupt_num.size) + mnemo_func = sbuild.functions mnemo_func.update({ 'and': and_l, @@ -718,6 +755,8 @@ mnemo_func.update({ 'b.ls': b_ls, 'b.lt': b_lt, + 'bics': bics, + 'ret': ret, 'stp': stp, 'ldp': ldp, @@ -728,7 +767,14 @@ mnemo_func.update({ 'ldur': ldr, 'ldurb': ldrb, + 'ldursb': ldrsb, 'ldurh': ldrh, + 'ldursh': ldrsh, + 'ldursw': ldrsw, + + 'ldrsb': ldrsb, + 'ldrsh': ldrsh, + 'ldrsw': ldrsw, 'str': l_str, 'strb': strb, @@ -738,8 +784,6 @@ mnemo_func.update({ 'sturb': strb, 'sturh': strh, - 'ldrsw': ldrsw, - 'bfm': bfm, 'sbfm': sbfm, @@ -781,7 +825,6 @@ class ir_aarch64l(IntermediateRepresentation): instr_ir, extra_ir = get_mnemo_expr(self, instr, *args) self.mod_pc(instr, instr_ir, extra_ir) instr_ir, extra_ir = self.del_dst_zr(instr, instr_ir, extra_ir) - return instr_ir, extra_ir def expr_fix_regs_for_mode(self, e): @@ -794,7 +837,7 @@ class ir_aarch64l(IntermediateRepresentation): def irbloc_fix_regs_for_mode(self, irblock, mode=64): irs = [] - for assignblk in irblock.irs: + for assignblk in irblock: new_assignblk = dict(assignblk) for dst, src in assignblk.iteritems(): del(new_assignblk[dst]) @@ -837,7 +880,7 @@ class ir_aarch64l(IntermediateRepresentation): new_irblocks = [] for irblock in extra_ir: irs = [] - for assignblk in irblock.irs: + for assignblk in irblock: new_dsts = {dst:src for dst, src in assignblk.iteritems() if dst not in regs_to_fix} irs.append(AssignBlock(new_dsts, assignblk.instr)) diff --git a/miasm2/arch/arm/arch.py b/miasm2/arch/arm/arch.py index c74d10a8..5e4b02f9 100644 --- a/miasm2/arch/arm/arch.py +++ b/miasm2/arch/arm/arch.py @@ -18,7 +18,7 @@ log.addHandler(console_handler) log.setLevel(logging.DEBUG) # arm regs ############## -reg_dum = ExprId('DumReg') +reg_dum = ExprId('DumReg', 32) gen_reg('PC', globals()) @@ -66,13 +66,13 @@ spsr_regs = reg_info(spsr_regs_str, spsr_regs_expr) # CP cpregs_str = ['c%d' % r for r in xrange(0x10)] -cpregs_expr = [ExprId(x) for x in cpregs_str] +cpregs_expr = [ExprId(x, 32) for x in cpregs_str] cp_regs = reg_info(cpregs_str, cpregs_expr) # P pregs_str = ['p%d' % r for r in xrange(0x10)] -pregs_expr = [ExprId(x) for x in pregs_str] +pregs_expr = [ExprId(x, 32) for x in pregs_str] p_regs = reg_info(pregs_str, pregs_expr) diff --git a/miasm2/arch/arm/disasm.py b/miasm2/arch/arm/disasm.py index 3f6ea4d5..586fa903 100644 --- a/miasm2/arch/arm/disasm.py +++ b/miasm2/arch/arm/disasm.py @@ -39,13 +39,13 @@ class dis_armb(disasmEngine): attrib = 'b' def __init__(self, bs=None, **kwargs): super(dis_armb, self).__init__(mn_arm, self.attrib, bs, **kwargs) - self.dis_bloc_callback = cb_arm_disasm + self.dis_block_callback = cb_arm_disasm class dis_arml(disasmEngine): attrib = 'l' def __init__(self, bs=None, **kwargs): super(dis_arml, self).__init__(mn_arm, self.attrib, bs, **kwargs) - self.dis_bloc_callback = cb_arm_disasm + self.dis_block_callback = cb_arm_disasm class dis_armtb(disasmEngine): attrib = 'b' diff --git a/miasm2/arch/arm/regs.py b/miasm2/arch/arm/regs.py index 400c6080..8587d7c2 100644 --- a/miasm2/arch/arm/regs.py +++ b/miasm2/arch/arm/regs.py @@ -29,22 +29,22 @@ SP = regs32_expr[13] LR = regs32_expr[14] PC = regs32_expr[15] -R0_init = ExprId("R0_init") -R1_init = ExprId("R1_init") -R2_init = ExprId("R2_init") -R3_init = ExprId("R3_init") -R4_init = ExprId("R4_init") -R5_init = ExprId("R5_init") -R6_init = ExprId("R6_init") -R7_init = ExprId("R7_init") -R8_init = ExprId("R8_init") -R9_init = ExprId("R9_init") -R10_init = ExprId("R10_init") -R11_init = ExprId("R11_init") -R12_init = ExprId("R12_init") -SP_init = ExprId("SP_init") -LR_init = ExprId("LR_init") -PC_init = ExprId("PC_init") +R0_init = ExprId("R0_init", 32) +R1_init = ExprId("R1_init", 32) +R2_init = ExprId("R2_init", 32) +R3_init = ExprId("R3_init", 32) +R4_init = ExprId("R4_init", 32) +R5_init = ExprId("R5_init", 32) +R6_init = ExprId("R6_init", 32) +R7_init = ExprId("R7_init", 32) +R8_init = ExprId("R8_init", 32) +R9_init = ExprId("R9_init", 32) +R10_init = ExprId("R10_init", 32) +R11_init = ExprId("R11_init", 32) +R12_init = ExprId("R12_init", 32) +SP_init = ExprId("SP_init", 32) +LR_init = ExprId("LR_init", 32) +PC_init = ExprId("PC_init", 32) reg_zf = 'zf' diff --git a/miasm2/arch/mips32/ira.py b/miasm2/arch/mips32/ira.py index f1e21a41..7aefad32 100644 --- a/miasm2/arch/mips32/ira.py +++ b/miasm2/arch/mips32/ira.py @@ -21,7 +21,7 @@ class ir_a_mips32l(ir_mips32l, ira): for irb in ir_blocks: pc_val = None lr_val = None - for assignblk in irb.irs: + for assignblk in irb: pc_val = assignblk.get(self.arch.regs.PC, pc_val) lr_val = assignblk.get(self.arch.regs.RA, lr_val) diff --git a/miasm2/arch/mips32/jit.py b/miasm2/arch/mips32/jit.py index 493da595..1d2ec483 100644 --- a/miasm2/arch/mips32/jit.py +++ b/miasm2/arch/mips32/jit.py @@ -35,19 +35,19 @@ class mipsCGen(CGen): def __init__(self, ir_arch): super(mipsCGen, self).__init__(ir_arch) - self.delay_slot_dst = m2_expr.ExprId("branch_dst_irdst") - self.delay_slot_set = m2_expr.ExprId("branch_dst_set") + self.delay_slot_dst = m2_expr.ExprId("branch_dst_irdst", 32) + self.delay_slot_set = m2_expr.ExprId("branch_dst_set", 32) def block2assignblks(self, block): irblocks_list = super(mipsCGen, self).block2assignblks(block) for irblocks in irblocks_list: for blk_idx, irblock in enumerate(irblocks): - has_breakflow = any(assignblock.instr.breakflow() for assignblock in irblock.irs) + has_breakflow = any(assignblock.instr.breakflow() for assignblock in irblock) if not has_breakflow: continue irs = [] - for assignblock in irblock.irs: + for assignblock in irblock: if self.ir_arch.pc not in assignblock: irs.append(AssignBlock(assignments, assignblock.instr)) continue @@ -58,7 +58,7 @@ class mipsCGen(CGen): assignments[self.delay_slot_set] = m2_expr.ExprInt(1, 32) # Replace IRDst with next instruction assignments[self.ir_arch.IRDst] = m2_expr.ExprId( - self.ir_arch.get_next_instr(assignblock.instr)) + self.ir_arch.get_next_instr(assignblock.instr), 32) irs.append(AssignBlock(assignments, assignblock.instr)) irblocks[blk_idx] = IRBlock(irblock.label, irs) @@ -72,8 +72,8 @@ class mipsCGen(CGen): lbl = self.get_block_post_label(block) out = (self.CODE_RETURN_NO_EXCEPTION % (self.label_to_jitlabel(lbl), self.C_PC, - m2_expr.ExprId('branch_dst_irdst'), - m2_expr.ExprId('branch_dst_irdst'), + m2_expr.ExprId('branch_dst_irdst', 32), + m2_expr.ExprId('branch_dst_irdst', 32), self.id_to_c(m2_expr.ExprInt(lbl.offset, 32))) ).split('\n') return out diff --git a/miasm2/arch/mips32/regs.py b/miasm2/arch/mips32/regs.py index fbd55a46..afade869 100644 --- a/miasm2/arch/mips32/regs.py +++ b/miasm2/arch/mips32/regs.py @@ -12,8 +12,8 @@ gen_reg('R_HI', globals()) exception_flags = ExprId('exception_flags', 32) -PC_init = ExprId("PC_init") -PC_FETCH_init = ExprId("PC_FETCH_init") +PC_init = ExprId("PC_init", 32) +PC_FETCH_init = ExprId("PC_FETCH_init", 32) regs32_str = ["ZERO", 'AT', 'V0', 'V1'] +\ ['A%d'%i for i in xrange(4)] +\ diff --git a/miasm2/arch/mips32/sem.py b/miasm2/arch/mips32/sem.py index 645f9a4f..855cb6c8 100644 --- a/miasm2/arch/mips32/sem.py +++ b/miasm2/arch/mips32/sem.py @@ -34,7 +34,7 @@ def jal(arg1): "Jumps to the calculated address @arg1 and stores the return address in $RA" PC = arg1 ir.IRDst = arg1 - RA = ExprId(ir.get_next_break_label(instr)) + RA = ExprId(ir.get_next_break_label(instr), 32) @sbuild.parse def jalr(arg1, arg2): @@ -42,13 +42,13 @@ def jalr(arg1, arg2): address in another register @arg2""" PC = arg1 ir.IRDst = arg1 - arg2 = ExprId(ir.get_next_break_label(instr)) + arg2 = ExprId(ir.get_next_break_label(instr), 32) @sbuild.parse def bal(arg1): PC = arg1 ir.IRDst = arg1 - RA = ExprId(ir.get_next_break_label(instr)) + RA = ExprId(ir.get_next_break_label(instr), 32) @sbuild.parse def l_b(arg1): @@ -75,7 +75,7 @@ def lb(arg1, arg2): @sbuild.parse def beq(arg1, arg2, arg3): "Branches on @arg3 if the quantities of two registers @arg1, @arg2 are eq" - dst = ExprId(ir.get_next_break_label(instr)) if arg1 - arg2 else arg3 + dst = ExprId(ir.get_next_break_label(instr), 32) if arg1 - arg2 else arg3 PC = dst ir.IRDst = dst @@ -83,7 +83,7 @@ def beq(arg1, arg2, arg3): def bgez(arg1, arg2): """Branches on @arg2 if the quantities of register @arg1 is greater than or equal to zero""" - dst = ExprId(ir.get_next_break_label(instr)) if arg1.msb() else arg2 + dst = ExprId(ir.get_next_break_label(instr), 32) if arg1.msb() else arg2 PC = dst ir.IRDst = dst @@ -91,7 +91,7 @@ def bgez(arg1, arg2): def bne(arg1, arg2, arg3): """Branches on @arg3 if the quantities of two registers @arg1, @arg2 are NOT equal""" - dst = arg3 if arg1 - arg2 else ExprId(ir.get_next_break_label(instr)) + dst = arg3 if arg1 - arg2 else ExprId(ir.get_next_break_label(instr), 32) PC = dst ir.IRDst = dst @@ -229,7 +229,7 @@ def seh(arg1, arg2): @sbuild.parse def bltz(arg1, arg2): """Branches on @arg2 if the register @arg1 is less than zero""" - dst_o = arg2 if arg1.msb() else ExprId(ir.get_next_break_label(instr)) + dst_o = arg2 if arg1.msb() else ExprId(ir.get_next_break_label(instr), 32) PC = dst_o ir.IRDst = dst_o @@ -237,7 +237,7 @@ def bltz(arg1, arg2): def blez(arg1, arg2): """Branches on @arg2 if the register @arg1 is less than or equal to zero""" cond = (i1(1) if arg1 else i1(0)) | arg1.msb() - dst_o = arg2 if cond else ExprId(ir.get_next_break_label(instr)) + dst_o = arg2 if cond else ExprId(ir.get_next_break_label(instr), 32) PC = dst_o ir.IRDst = dst_o @@ -245,7 +245,7 @@ def blez(arg1, arg2): def bgtz(arg1, arg2): """Branches on @arg2 if the register @arg1 is greater than zero""" cond = (i1(1) if arg1 else i1(0)) | arg1.msb() - dst_o = ExprId(ir.get_next_break_label(instr)) if cond else arg2 + dst_o = ExprId(ir.get_next_break_label(instr), 32) if cond else arg2 PC = dst_o ir.IRDst = dst_o @@ -345,13 +345,13 @@ def c_le_d(arg1, arg2, arg3): @sbuild.parse def bc1t(arg1, arg2): - dst_o = arg2 if arg1 else ExprId(ir.get_next_break_label(instr)) + dst_o = arg2 if arg1 else ExprId(ir.get_next_break_label(instr), 32) PC = dst_o ir.IRDst = dst_o @sbuild.parse def bc1f(arg1, arg2): - dst_o = ExprId(ir.get_next_break_label(instr)) if arg1 else arg2 + dst_o = ExprId(ir.get_next_break_label(instr), 32) if arg1 else arg2 PC = dst_o ir.IRDst = dst_o diff --git a/miasm2/arch/sh4/arch.py b/miasm2/arch/sh4/arch.py index eeafd5f5..d7ae4f12 100644 --- a/miasm2/arch/sh4/arch.py +++ b/miasm2/arch/sh4/arch.py @@ -7,9 +7,9 @@ from collections import defaultdict import miasm2.arch.sh4.regs as regs_module from miasm2.arch.sh4.regs import * -jra = ExprId('jra') -jrb = ExprId('jrb') -jrc = ExprId('jrc') +jra = ExprId('jra', 32) +jrb = ExprId('jrb', 32) +jrc = ExprId('jrc', 32) # parser helper ########### diff --git a/miasm2/arch/x86/arch.py b/miasm2/arch/x86/arch.py index 13c06ae6..72ed3309 100644 --- a/miasm2/arch/x86/arch.py +++ b/miasm2/arch/x86/arch.py @@ -4306,6 +4306,10 @@ addop("pmaxuw", [bs8(0x0f), bs8(0x38), bs8(0x3e), pref_66] + addop("pmaxud", [bs8(0x0f), bs8(0x38), bs8(0x3f), pref_66] + rmmod(xmm_reg, rm_arg_xmm)) +addop("pmaxsw", [bs8(0x0f), bs8(0xee), no_xmm_pref] + + rmmod(mm_reg, rm_arg_mm_m64)) +addop("pmaxsw", [bs8(0x0f), bs8(0xee), pref_66] + + rmmod(xmm_reg, rm_arg_xmm_m128)) addop("pminub", [bs8(0x0f), bs8(0xda), no_xmm_pref] + rmmod(mm_reg, rm_arg_mm)) @@ -4339,6 +4343,11 @@ addop("pcmpgtb", [bs8(0x0f), bs8(0x64), no_xmm_pref] + addop("pcmpgtb", [bs8(0x0f), bs8(0x64), pref_66] + rmmod(xmm_reg, rm_arg_xmm)) +addop("pcmpgtw", [bs8(0x0f), bs8(0x65), no_xmm_pref] + + rmmod(mm_reg, rm_arg_mm)) +addop("pcmpgtw", [bs8(0x0f), bs8(0x65), pref_66] + + rmmod(xmm_reg, rm_arg_xmm)) + addop("pcmpgtd", [bs8(0x0f), bs8(0x66), no_xmm_pref] + rmmod(mm_reg, rm_arg_mm)) addop("pcmpgtd", [bs8(0x0f), bs8(0x66), pref_66] + @@ -4423,9 +4432,9 @@ addop("pextrq", [bs8(0x0f), bs8(0x3a), bs8(0x16), pref_66] + addop("pextrw", [bs8(0x0f), bs8(0x3a), bs8(0x15), pref_66] + rmmod(xmm_reg, rm_arg_reg_m16) + [u08], [rm_arg_reg_m16, xmm_reg, u08]) addop("pextrw", [bs8(0x0f), bs8(0xc5), no_xmm_pref] + - rmmod(mm_reg, rm_arg_reg_m16) + [u08], [rm_arg_reg_m16, mm_reg, u08]) + rmmod(rmreg, rm_arg_mm) + [u08], [rmreg, rm_arg_mm, u08]) addop("pextrw", [bs8(0x0f), bs8(0xc5), pref_66] + - rmmod(xmm_reg, rm_arg_reg_m16) + [u08], [rm_arg_reg_m16, xmm_reg, u08]) + rmmod(rmreg, rm_arg_xmm) + [u08], [rmreg, rm_arg_xmm, u08]) addop("sqrtpd", [bs8(0x0f), bs8(0x51), pref_66] + @@ -4453,6 +4462,100 @@ addop("aesdec", [bs8(0x0f), bs8(0x38), bs8(0xde), pref_66] + rmmod(xmm_reg, rm_a addop("aesenclast", [bs8(0x0f), bs8(0x38), bs8(0xdd), pref_66] + rmmod(xmm_reg, rm_arg_xmm)) addop("aesdeclast", [bs8(0x0f), bs8(0x38), bs8(0xdf), pref_66] + rmmod(xmm_reg, rm_arg_xmm)) +addop("packsswb", [bs8(0x0f), bs8(0x63), no_xmm_pref] + + rmmod(mm_reg, rm_arg_mm_m64)) +addop("packsswb", [bs8(0x0f), bs8(0x63), pref_66] + + rmmod(xmm_reg, rm_arg_xmm_m128)) +addop("packssdw", [bs8(0x0f), bs8(0x6b), no_xmm_pref] + + rmmod(mm_reg, rm_arg_mm_m64)) +addop("packssdw", [bs8(0x0f), bs8(0x6b), pref_66] + + rmmod(xmm_reg, rm_arg_xmm_m128)) + +addop("packuswb", [bs8(0x0f), bs8(0x67), no_xmm_pref] + + rmmod(mm_reg, rm_arg_mm_m64)) +addop("packuswb", [bs8(0x0f), bs8(0x67), pref_66] + + rmmod(xmm_reg, rm_arg_xmm_m128)) + +addop("pmullw", [bs8(0x0f), bs8(0xd5), no_xmm_pref] + + rmmod(mm_reg, rm_arg_mm_m64)) +addop("pmullw", [bs8(0x0f), bs8(0xd5), pref_66] + + rmmod(xmm_reg, rm_arg_xmm_m128)) +addop("pmulhuw", [bs8(0x0f), bs8(0xe4), no_xmm_pref] + + rmmod(mm_reg, rm_arg_mm_m64)) +addop("pmulhuw", [bs8(0x0f), bs8(0xe4), pref_66] + + rmmod(xmm_reg, rm_arg_xmm_m128)) +addop("pmulhw", [bs8(0x0f), bs8(0xe5), no_xmm_pref] + + rmmod(mm_reg, rm_arg_mm_m64)) +addop("pmulhw", [bs8(0x0f), bs8(0xe5), pref_66] + + rmmod(xmm_reg, rm_arg_xmm_m128)) +addop("pmuludq", [bs8(0x0f), bs8(0xf4), no_xmm_pref] + + rmmod(mm_reg, rm_arg_mm_m64)) +addop("pmuludq", [bs8(0x0f), bs8(0xf4), pref_66] + + rmmod(xmm_reg, rm_arg_xmm_m128)) + + +addop("psubusb", [bs8(0x0f), bs8(0xd8), no_xmm_pref] + + rmmod(mm_reg, rm_arg_mm_m64)) +addop("psubusb", [bs8(0x0f), bs8(0xd8), pref_66] + + rmmod(xmm_reg, rm_arg_xmm_m128)) +addop("psubusw", [bs8(0x0f), bs8(0xd9), no_xmm_pref] + + rmmod(mm_reg, rm_arg_mm_m64)) +addop("psubusw", [bs8(0x0f), bs8(0xd9), pref_66] + + rmmod(xmm_reg, rm_arg_xmm_m128)) +addop("psubsb", [bs8(0x0f), bs8(0xe8), no_xmm_pref] + + rmmod(mm_reg, rm_arg_mm_m64)) +addop("psubsb", [bs8(0x0f), bs8(0xe8), pref_66] + + rmmod(xmm_reg, rm_arg_xmm_m128)) +addop("psubsw", [bs8(0x0f), bs8(0xe9), no_xmm_pref] + + rmmod(mm_reg, rm_arg_mm_m64)) +addop("psubsw", [bs8(0x0f), bs8(0xe9), pref_66] + + rmmod(xmm_reg, rm_arg_xmm_m128)) + + +addop("paddusb", [bs8(0x0f), bs8(0xdc), no_xmm_pref] + + rmmod(mm_reg, rm_arg_mm_m64)) +addop("paddusb", [bs8(0x0f), bs8(0xdc), pref_66] + + rmmod(xmm_reg, rm_arg_xmm_m128)) +addop("paddusw", [bs8(0x0f), bs8(0xdd), no_xmm_pref] + + rmmod(mm_reg, rm_arg_mm_m64)) +addop("paddusw", [bs8(0x0f), bs8(0xdd), pref_66] + + rmmod(xmm_reg, rm_arg_xmm_m128)) +addop("paddsb", [bs8(0x0f), bs8(0xec), no_xmm_pref] + + rmmod(mm_reg, rm_arg_mm_m64)) +addop("paddsb", [bs8(0x0f), bs8(0xec), pref_66] + + rmmod(xmm_reg, rm_arg_xmm_m128)) +addop("paddsw", [bs8(0x0f), bs8(0xed), no_xmm_pref] + + rmmod(mm_reg, rm_arg_mm_m64)) +addop("paddsw", [bs8(0x0f), bs8(0xed), pref_66] + + rmmod(xmm_reg, rm_arg_xmm_m128)) + +addop("pmaddwd", [bs8(0x0f), bs8(0xf5), no_xmm_pref] + + rmmod(mm_reg, rm_arg_mm_m64)) +addop("pmaddwd", [bs8(0x0f), bs8(0xf5), pref_66] + + rmmod(xmm_reg, rm_arg_xmm_m128)) + +addop("psadbw", [bs8(0x0f), bs8(0xf6), no_xmm_pref] + + rmmod(mm_reg, rm_arg_mm_m64)) +addop("psadbw", [bs8(0x0f), bs8(0xf6), pref_66] + + rmmod(xmm_reg, rm_arg_xmm_m128)) + +addop("pavgb", [bs8(0x0f), bs8(0xe0), no_xmm_pref] + + rmmod(mm_reg, rm_arg_mm_m64)) +addop("pavgb", [bs8(0x0f), bs8(0xe0), pref_66] + + rmmod(xmm_reg, rm_arg_xmm_m128)) +addop("pavgw", [bs8(0x0f), bs8(0xe3), no_xmm_pref] + + rmmod(mm_reg, rm_arg_mm_m64)) +addop("pavgw", [bs8(0x0f), bs8(0xe3), pref_66] + + rmmod(xmm_reg, rm_arg_xmm_m128)) + +addop("maskmovq", [bs8(0x0f), bs8(0xf7), no_xmm_pref] + + rmmod(mm_reg, rm_arg_mm_reg)) +addop("maskmovdqu", [bs8(0x0f), bs8(0xf7), pref_66] + + rmmod(xmm_reg, rm_arg_xmm_reg)) + +addop("emms", [bs8(0x0f), bs8(0x77)]) + + mn_x86.bintree = factor_one_bit(mn_x86.bintree) # mn_x86.bintree = factor_fields_all(mn_x86.bintree) """ diff --git a/miasm2/arch/x86/disasm.py b/miasm2/arch/x86/disasm.py index fc981c09..ecb1b8da 100644 --- a/miasm2/arch/x86/disasm.py +++ b/miasm2/arch/x86/disasm.py @@ -15,7 +15,7 @@ class dis_x86(disasmEngine): def __init__(self, bs=None, **kwargs): super(dis_x86, self).__init__(mn_x86, self.attrib, bs, **kwargs) - self.dis_bloc_callback = cb_x86_disasm + self.dis_block_callback = cb_x86_disasm class dis_x86_16(dis_x86): diff --git a/miasm2/arch/x86/regs.py b/miasm2/arch/x86/regs.py index cb7e0d7b..84590c75 100644 --- a/miasm2/arch/x86/regs.py +++ b/miasm2/arch/x86/regs.py @@ -251,23 +251,23 @@ reg_float_address = 'reg_float_address' reg_float_ds = 'reg_float_ds' -dr0 = ExprId(reg_dr0) -dr1 = ExprId(reg_dr1) -dr2 = ExprId(reg_dr2) -dr3 = ExprId(reg_dr3) -dr4 = ExprId(reg_dr4) -dr5 = ExprId(reg_dr5) -dr6 = ExprId(reg_dr6) -dr7 = ExprId(reg_dr7) - -cr0 = ExprId(reg_cr0) -cr1 = ExprId(reg_cr1) -cr2 = ExprId(reg_cr2) -cr3 = ExprId(reg_cr3) -cr4 = ExprId(reg_cr4) -cr5 = ExprId(reg_cr5) -cr6 = ExprId(reg_cr6) -cr7 = ExprId(reg_cr7) +dr0 = ExprId(reg_dr0, 32) +dr1 = ExprId(reg_dr1, 32) +dr2 = ExprId(reg_dr2, 32) +dr3 = ExprId(reg_dr3, 32) +dr4 = ExprId(reg_dr4, 32) +dr5 = ExprId(reg_dr5, 32) +dr6 = ExprId(reg_dr6, 32) +dr7 = ExprId(reg_dr7, 32) + +cr0 = ExprId(reg_cr0, 32) +cr1 = ExprId(reg_cr1, 32) +cr2 = ExprId(reg_cr2, 32) +cr3 = ExprId(reg_cr3, 32) +cr4 = ExprId(reg_cr4, 32) +cr5 = ExprId(reg_cr5, 32) +cr6 = ExprId(reg_cr6, 32) +cr7 = ExprId(reg_cr7, 32) mm0 = ExprId(reg_mm0, 64) mm1 = ExprId(reg_mm1, 64) @@ -330,9 +330,9 @@ float_c2 = ExprId(reg_float_c2, size=1) float_c3 = ExprId(reg_float_c3, size=1) float_stack_ptr = ExprId(reg_float_stack_ptr, size=3) float_control = ExprId(reg_float_control, 16) -float_eip = ExprId(reg_float_eip) +float_eip = ExprId(reg_float_eip, 32) float_cs = ExprId(reg_float_cs, size=16) -float_address = ExprId(reg_float_address) +float_address = ExprId(reg_float_address, 32) float_ds = ExprId(reg_float_ds, size=16) float_st0 = ExprId("float_st0", 64) @@ -352,14 +352,14 @@ float_replace = {fltregs32_expr[i]: float_list[i] for i in xrange(8)} float_replace[r_st_all.expr[0]] = float_st0 -EAX_init = ExprId('EAX_init') -EBX_init = ExprId('EBX_init') -ECX_init = ExprId('ECX_init') -EDX_init = ExprId('EDX_init') -ESI_init = ExprId('ESI_init') -EDI_init = ExprId('EDI_init') -ESP_init = ExprId('ESP_init') -EBP_init = ExprId('EBP_init') +EAX_init = ExprId('EAX_init', 32) +EBX_init = ExprId('EBX_init', 32) +ECX_init = ExprId('ECX_init', 32) +EDX_init = ExprId('EDX_init', 32) +ESI_init = ExprId('ESI_init', 32) +EDI_init = ExprId('EDI_init', 32) +ESP_init = ExprId('ESP_init', 32) +EBP_init = ExprId('EBP_init', 32) RAX_init = ExprId('RAX_init', 64) diff --git a/miasm2/arch/x86/sem.py b/miasm2/arch/x86/sem.py index 56aca1c2..589c2eb9 100644 --- a/miasm2/arch/x86/sem.py +++ b/miasm2/arch/x86/sem.py @@ -1614,22 +1614,25 @@ def imul(_, instr, src1, src2=None, src3=None): def cbw(_, instr): + # Only in 16 bit e = [] - tempAL = mRAX[instr.mode][:8] - tempAX = mRAX[instr.mode][:16] + tempAL = mRAX[instr.v_opmode()][:8] + tempAX = mRAX[instr.v_opmode()][:16] e.append(m2_expr.ExprAff(tempAX, tempAL.signExtend(16))) return e, [] def cwde(_, instr): + # Only in 32/64 bit e = [] - tempAX = mRAX[instr.mode][:16] - tempEAX = mRAX[instr.mode][:32] + tempAX = mRAX[instr.v_opmode()][:16] + tempEAX = mRAX[instr.v_opmode()][:32] e.append(m2_expr.ExprAff(tempEAX, tempAX.signExtend(32))) return e, [] def cdqe(_, instr): + # Only in 64 bit e = [] tempEAX = mRAX[instr.mode][:32] tempRAX = mRAX[instr.mode][:64] @@ -1638,32 +1641,34 @@ def cdqe(_, instr): def cwd(_, instr): + # Only in 16 bit e = [] tempAX = mRAX[instr.mode][:16] tempDX = mRDX[instr.mode][:16] - c = tempAX.signExtend(32) - e.append(m2_expr.ExprAff(tempAX, c[:16])) - e.append(m2_expr.ExprAff(tempDX, c[16:32])) + result = tempAX.signExtend(32) + e.append(m2_expr.ExprAff(tempAX, result[:16])) + e.append(m2_expr.ExprAff(tempDX, result[16:32])) return e, [] def cdq(_, instr): + # Only in 32/64 bit e = [] - tempEAX = mRAX[instr.mode][:32] - tempEDX = mRDX[instr.mode][:32] - c = tempEAX.signExtend(64) - e.append(m2_expr.ExprAff(tempEAX, c[:32])) - e.append(m2_expr.ExprAff(tempEDX, c[32:64])) + tempEAX = mRAX[instr.v_opmode()] + tempEDX = mRDX[instr.v_opmode()] + result = tempEAX.signExtend(64) + e.append(m2_expr.ExprAff(tempEDX, result[32:64])) return e, [] def cqo(_, instr): + # Only in 64 bit e = [] tempRAX = mRAX[instr.mode][:64] tempRDX = mRDX[instr.mode][:64] - c = tempRAX.signExtend(128) - e.append(m2_expr.ExprAff(tempRAX, c[:64])) - e.append(m2_expr.ExprAff(tempRDX, c[64:128])) + result = tempRAX.signExtend(128) + e.append(m2_expr.ExprAff(tempRAX, result[:64])) + e.append(m2_expr.ExprAff(tempRDX, result[64:128])) return e, [] @@ -3314,62 +3319,104 @@ def vec_op_clip(op, size): # Generic vertical operation -def vec_vertical_sem(op, elt_size, reg_size, dst, src): +def vec_vertical_sem(op, elt_size, reg_size, dst, src, apply_on_output): assert reg_size % elt_size == 0 n = reg_size / elt_size if op == '-': ops = [ - (dst[i * elt_size:(i + 1) * elt_size] - - src[i * elt_size:(i + 1) * elt_size]) for i in xrange(0, n)] + apply_on_output((dst[i * elt_size:(i + 1) * elt_size] + - src[i * elt_size:(i + 1) * elt_size])) + for i in xrange(0, n) + ] else: - ops = [m2_expr.ExprOp(op, dst[i * elt_size:(i + 1) * elt_size], - src[i * elt_size:(i + 1) * elt_size]) for i in xrange(0, n)] + ops = [ + apply_on_output(m2_expr.ExprOp(op, dst[i * elt_size:(i + 1) * elt_size], + src[i * elt_size:(i + 1) * elt_size])) + for i in xrange(0, n) + ] return m2_expr.ExprCompose(*ops) -def float_vec_vertical_sem(op, elt_size, reg_size, dst, src): +def float_vec_vertical_sem(op, elt_size, reg_size, dst, src, apply_on_output): assert reg_size % elt_size == 0 n = reg_size / elt_size x_to_int, int_to_x = {32: ('float_to_int_%d', 'int_%d_to_float'), 64: ('double_to_int_%d', 'int_%d_to_double')}[elt_size] if op == '-': - ops = [m2_expr.ExprOp(x_to_int % elt_size, - m2_expr.ExprOp(int_to_x % elt_size, dst[i * elt_size:(i + 1) * elt_size]) - - m2_expr.ExprOp( - int_to_x % elt_size, src[i * elt_size:( - i + 1) * elt_size])) for i in xrange(0, n)] + ops = [ + apply_on_output(m2_expr.ExprOp( + x_to_int % elt_size, + m2_expr.ExprOp(int_to_x % elt_size, dst[i * elt_size:(i + 1) * elt_size]) - + m2_expr.ExprOp( + int_to_x % elt_size, src[i * elt_size:( + i + 1) * elt_size]))) + for i in xrange(0, n) + ] else: - ops = [m2_expr.ExprOp(x_to_int % elt_size, - m2_expr.ExprOp(op, - m2_expr.ExprOp( - int_to_x % elt_size, dst[i * elt_size:( - i + 1) * elt_size]), - m2_expr.ExprOp( - int_to_x % elt_size, src[i * elt_size:( - i + 1) * elt_size]))) for i in xrange(0, n)] + ops = [ + apply_on_output(m2_expr.ExprOp( + x_to_int % elt_size, + m2_expr.ExprOp(op, + m2_expr.ExprOp( + int_to_x % elt_size, dst[i * elt_size:( + i + 1) * elt_size]), + m2_expr.ExprOp( + int_to_x % elt_size, src[i * elt_size:( + i + 1) * elt_size])))) + for i in xrange(0, n)] return m2_expr.ExprCompose(*ops) -def __vec_vertical_instr_gen(op, elt_size, sem): +def __vec_vertical_instr_gen(op, elt_size, sem, apply_on_output): def vec_instr(ir, instr, dst, src): e = [] if isinstance(src, m2_expr.ExprMem): src = ir.ExprMem(src.arg, dst.size) reg_size = dst.size - e.append(m2_expr.ExprAff(dst, sem(op, elt_size, reg_size, dst, src))) + e.append(m2_expr.ExprAff(dst, sem(op, elt_size, reg_size, dst, src, + apply_on_output))) return e, [] return vec_instr -def vec_vertical_instr(op, elt_size): - return __vec_vertical_instr_gen(op, elt_size, vec_vertical_sem) +def vec_vertical_instr(op, elt_size, apply_on_output=lambda x: x): + return __vec_vertical_instr_gen(op, elt_size, vec_vertical_sem, + apply_on_output) -def float_vec_vertical_instr(op, elt_size): - return __vec_vertical_instr_gen(op, elt_size, float_vec_vertical_sem) +def float_vec_vertical_instr(op, elt_size, apply_on_output=lambda x: x): + return __vec_vertical_instr_gen(op, elt_size, float_vec_vertical_sem, + apply_on_output) + + +def _keep_mul_high(expr, signed=False): + assert expr.is_op("*") and len(expr.args) == 2 + + if signed: + arg1 = expr.args[0].signExtend(expr.size * 2) + arg2 = expr.args[1].signExtend(expr.size * 2) + else: + arg1 = expr.args[0].zeroExtend(expr.size * 2) + arg2 = expr.args[1].zeroExtend(expr.size * 2) + return m2_expr.ExprOp("*", arg1, arg2)[expr.size:] + +# Op, signed => associated comparison +_min_max_func = { + ("min", False): m2_expr.expr_is_unsigned_lower, + ("min", True): m2_expr.expr_is_signed_lower, + ("max", False): m2_expr.expr_is_unsigned_greater, + ("max", True): m2_expr.expr_is_signed_greater, +} +def _min_max(expr, signed): + assert (expr.is_op("min") or expr.is_op("max")) and len(expr.args) == 2 + return m2_expr.ExprCond( + _min_max_func[(expr.op, signed)](expr.args[1], expr.args[0]), + expr.args[1], + expr.args[0], + ) # Integer arithmetic @@ -3393,6 +3440,109 @@ psubw = vec_vertical_instr('-', 16) psubd = vec_vertical_instr('-', 32) psubq = vec_vertical_instr('-', 64) +# Multiplications +# + +# SSE +pmullb = vec_vertical_instr('*', 8) +pmullw = vec_vertical_instr('*', 16) +pmulld = vec_vertical_instr('*', 32) +pmullq = vec_vertical_instr('*', 64) +pmulhub = vec_vertical_instr('*', 8, _keep_mul_high) +pmulhuw = vec_vertical_instr('*', 16, _keep_mul_high) +pmulhud = vec_vertical_instr('*', 32, _keep_mul_high) +pmulhuq = vec_vertical_instr('*', 64, _keep_mul_high) +pmulhb = vec_vertical_instr('*', 8, lambda x: _keep_mul_high(x, signed=True)) +pmulhw = vec_vertical_instr('*', 16, lambda x: _keep_mul_high(x, signed=True)) +pmulhd = vec_vertical_instr('*', 32, lambda x: _keep_mul_high(x, signed=True)) +pmulhq = vec_vertical_instr('*', 64, lambda x: _keep_mul_high(x, signed=True)) + +def pmuludq(ir, instr, dst, src): + e = [] + if dst.size == 64: + e.append(m2_expr.ExprAff( + dst, + src[:32].zeroExtend(64) * dst[:32].zeroExtend(64) + )) + elif dst.size == 128: + e.append(m2_expr.ExprAff( + dst[:64], + src[:32].zeroExtend(64) * dst[:32].zeroExtend(64) + )) + e.append(m2_expr.ExprAff( + dst[64:], + src[64:96].zeroExtend(64) * dst[64:96].zeroExtend(64) + )) + else: + raise RuntimeError("Unsupported size %d" % dst.size) + return e, [] + +# Mix +# + +# SSE +def pmaddwd(ir, instr, dst, src): + sizedst = 32 + sizesrc = 16 + out = [] + for start in xrange(0, dst.size, sizedst): + base = start + mul1 = src[base: base + sizesrc].signExtend(sizedst) * dst[base: base + sizesrc].signExtend(sizedst) + base += sizesrc + mul2 = src[base: base + sizesrc].signExtend(sizedst) * dst[base: base + sizesrc].signExtend(sizedst) + out.append(mul1 + mul2) + return [m2_expr.ExprAff(dst, m2_expr.ExprCompose(*out))], [] + + +def _absolute(expr): + """Return abs(@expr)""" + signed = expr.msb() + value_unsigned = (expr ^ expr.mask) + m2_expr.ExprInt(1, expr.size) + return m2_expr.ExprCond(signed, value_unsigned, expr) + + +def psadbw(ir, instr, dst, src): + sizedst = 16 + sizesrc = 8 + out_dst = [] + for start in xrange(0, dst.size, 64): + out = [] + for src_start in xrange(0, 64, sizesrc): + beg = start + src_start + end = beg + sizesrc + # Not clear in the doc equations, but in the text, src and dst are: + # "8 unsigned byte integers" + out.append(_absolute(dst[beg: end].zeroExtend(sizedst) - src[beg: end].zeroExtend(sizedst))) + out_dst.append(m2_expr.ExprOp("+", *out)) + out_dst.append(m2_expr.ExprInt(0, 64 - sizedst)) + + return [m2_expr.ExprAff(dst, m2_expr.ExprCompose(*out_dst))], [] + +def _average(expr): + assert expr.is_op("avg") and len(expr.args) == 2 + + arg1 = expr.args[0].zeroExtend(expr.size * 2) + arg2 = expr.args[1].zeroExtend(expr.size * 2) + one = m2_expr.ExprInt(1, arg1.size) + # avg(unsigned) = (a + b + 1) >> 1, addition beeing at least on one more bit + return ((arg1 + arg2 + one) >> one)[:expr.size] + +pavgb = vec_vertical_instr('avg', 8, _average) +pavgw = vec_vertical_instr('avg', 16, _average) + +# Comparisons +# + +# SSE +pminsw = vec_vertical_instr('min', 16, lambda x: _min_max(x, signed=True)) +pminub = vec_vertical_instr('min', 8, lambda x: _min_max(x, signed=False)) +pminuw = vec_vertical_instr('min', 16, lambda x: _min_max(x, signed=False)) +pminud = vec_vertical_instr('min', 32, lambda x: _min_max(x, signed=False)) +pmaxub = vec_vertical_instr('max', 8, lambda x: _min_max(x, signed=False)) +pmaxuw = vec_vertical_instr('max', 16, lambda x: _min_max(x, signed=False)) +pmaxud = vec_vertical_instr('max', 32, lambda x: _min_max(x, signed=False)) +pmaxsw = vec_vertical_instr('max', 16, lambda x: _min_max(x, signed=True)) + # Floating-point arithmetic # @@ -3443,12 +3593,6 @@ def por(_, instr, dst, src): return e, [] -def pminsw(_, instr, dst, src): - e = [] - e.append(m2_expr.ExprAff(dst, m2_expr.ExprCond((dst - src).msb(), dst, src))) - return e, [] - - def cvtdq2pd(_, instr, dst, src): e = [] e.append( @@ -3814,62 +3958,6 @@ def iret(ir, instr): return exprs, [] -def pmaxu(_, instr, dst, src, size): - e = [] - for i in xrange(0, dst.size, size): - op1 = dst[i:i + size] - op2 = src[i:i + size] - res = op1 - op2 - # Compote CF in @res = @op1 - @op2 - ret = (((op1 ^ op2) ^ res) ^ ((op1 ^ res) & (op1 ^ op2))).msb() - - e.append(m2_expr.ExprAff(dst[i:i + size], - m2_expr.ExprCond(ret, - src[i:i + size], - dst[i:i + size]))) - return e, [] - - -def pmaxub(ir, instr, dst, src): - return pmaxu(ir, instr, dst, src, 8) - - -def pmaxuw(ir, instr, dst, src): - return pmaxu(ir, instr, dst, src, 16) - - -def pmaxud(ir, instr, dst, src): - return pmaxu(ir, instr, dst, src, 32) - - -def pminu(_, instr, dst, src, size): - e = [] - for i in xrange(0, dst.size, size): - op1 = dst[i:i + size] - op2 = src[i:i + size] - res = op1 - op2 - # Compote CF in @res = @op1 - @op2 - ret = (((op1 ^ op2) ^ res) ^ ((op1 ^ res) & (op1 ^ op2))).msb() - - e.append(m2_expr.ExprAff(dst[i:i + size], - m2_expr.ExprCond(ret, - dst[i:i + size], - src[i:i + size]))) - return e, [] - - -def pminub(ir, instr, dst, src): - return pminu(ir, instr, dst, src, 8) - - -def pminuw(ir, instr, dst, src): - return pminu(ir, instr, dst, src, 16) - - -def pminud(ir, instr, dst, src): - return pminu(ir, instr, dst, src, 32) - - def pcmpeq(_, instr, dst, src, size): e = [] for i in xrange(0, dst.size, size): @@ -4168,6 +4256,202 @@ def palignr(ir, instr, dst, src, imm): return [m2_expr.ExprAff(dst, result)], [] +def _signed_saturation(expr, dst_size): + """Saturate the expr @expr for @dst_size bit + Signed saturation return MAX_INT / MIN_INT or value depending on the value + """ + assert expr.size > dst_size + + median = 1 << (dst_size - 1) + min_int = m2_expr.ExprInt(- median, dst_size) + max_int = m2_expr.ExprInt(median - 1, dst_size) + signed = expr.msb() + value_unsigned = (expr ^ expr.mask) + m2_expr.ExprInt(1, expr.size) + # Re-use the sign bit + value = m2_expr.ExprCompose(expr[:dst_size - 1], signed) + + # Bit hack: to avoid a double signed comparison, use mask + # ie., in unsigned, 0xXY > 0x0f iff X is not null + + # if expr >s 0 + # if expr[dst_size - 1:] > 0: # bigger than max_int + # -> max_int + # else + # -> value + # else # negative + # if expr[dst_size:-1] > 0: # smaller than min_int + # -> value + # else + # -> min_int + + return m2_expr.ExprCond( + signed, + m2_expr.ExprCond(value_unsigned[dst_size - 1:], + min_int, + value), + m2_expr.ExprCond(expr[dst_size - 1:], + max_int, + value), + ) + + +def _unsigned_saturation(expr, dst_size): + """Saturate the expr @expr for @dst_size bit + Unsigned saturation return MAX_INT or value depending on the value + """ + assert expr.size > dst_size + + zero = m2_expr.ExprInt(0, dst_size) + max_int = m2_expr.ExprInt(-1, dst_size) + value = expr[:dst_size] + signed = expr.msb() + + + # Bit hack: to avoid a double signed comparison, use mask + # ie., in unsigned, 0xXY > 0x0f iff X is not null + + return m2_expr.ExprCond( + signed, + zero, + m2_expr.ExprCond(expr[dst_size:], + max_int, + value), + ) + + + +def packsswb(ir, instr, dst, src): + out = [] + for source in [dst, src]: + for start in xrange(0, dst.size, 16): + out.append(_signed_saturation(source[start:start + 16], 8)) + return [m2_expr.ExprAff(dst, m2_expr.ExprCompose(*out))], [] + + +def packssdw(ir, instr, dst, src): + out = [] + for source in [dst, src]: + for start in xrange(0, dst.size, 32): + out.append(_signed_saturation(source[start:start + 32], 16)) + return [m2_expr.ExprAff(dst, m2_expr.ExprCompose(*out))], [] + + +def packuswb(ir, instr, dst, src): + out = [] + for source in [dst, src]: + for start in xrange(0, dst.size, 16): + out.append(_unsigned_saturation(source[start:start + 16], 8)) + return [m2_expr.ExprAff(dst, m2_expr.ExprCompose(*out))], [] + + +def _saturation_sub_unsigned(expr): + assert expr.is_op("+") and len(expr.args) == 2 and expr.args[-1].is_op("-") + + # Compute the soustraction on one more bit to be able to distinguish cases: + # 0x48 - 0xd7 in 8 bit, should saturate + arg1 = expr.args[0].zeroExtend(expr.size + 1) + arg2 = expr.args[1].args[0].zeroExtend(expr.size + 1) + return _unsigned_saturation(arg1 - arg2, expr.size) + +def _saturation_sub_signed(expr): + assert expr.is_op("+") and len(expr.args) == 2 and expr.args[-1].is_op("-") + + # Compute the substraction on two more bits, see _saturation_sub_unsigned + arg1 = expr.args[0].signExtend(expr.size + 2) + arg2 = expr.args[1].args[0].signExtend(expr.size + 2) + return _signed_saturation(arg1 - arg2, expr.size) + +def _saturation_add(expr): + assert expr.is_op("+") and len(expr.args) == 2 + + # Compute the addition on one more bit to be able to distinguish cases: + # 0x48 + 0xd7 in 8 bit, should saturate + + arg1 = expr.args[0].zeroExtend(expr.size + 1) + arg2 = expr.args[1].zeroExtend(expr.size + 1) + + # We can also use _unsigned_saturation with two additionnal bits (to + # distinguish minus and overflow case) + # The resulting expression being more complicated with an impossible case + # (signed=True), we rewrite the rule here + + return m2_expr.ExprCond((arg1 + arg2).msb(), m2_expr.ExprInt(-1, expr.size), + expr) + +def _saturation_add_signed(expr): + assert expr.is_op("+") and len(expr.args) == 2 + + # Compute the substraction on two more bits, see _saturation_add_unsigned + + arg1 = expr.args[0].signExtend(expr.size + 2) + arg2 = expr.args[1].signExtend(expr.size + 2) + + return _signed_saturation(arg1 + arg2, expr.size) + + +# Saturate SSE operations + +psubusb = vec_vertical_instr('-', 8, _saturation_sub_unsigned) +psubusw = vec_vertical_instr('-', 16, _saturation_sub_unsigned) +paddusb = vec_vertical_instr('+', 8, _saturation_add) +paddusw = vec_vertical_instr('+', 16, _saturation_add) +psubsb = vec_vertical_instr('-', 8, _saturation_sub_signed) +psubsw = vec_vertical_instr('-', 16, _saturation_sub_signed) +paddsb = vec_vertical_instr('+', 8, _saturation_add_signed) +paddsw = vec_vertical_instr('+', 16, _saturation_add_signed) + + +# Others SSE operations + +def maskmovq(ir, instr, src, mask): + lbl_next = m2_expr.ExprId(ir.get_next_label(instr), ir.IRDst.size) + blks = [] + + # For each possibility, check if a write is necessary + check_labels = [m2_expr.ExprId(ir.gen_label(), ir.IRDst.size) + for _ in xrange(0, mask.size, 8)] + # If the write has to be done, do it (otherwise, nothing happen) + write_labels = [m2_expr.ExprId(ir.gen_label(), ir.IRDst.size) + for _ in xrange(0, mask.size, 8)] + + # Build check blocks + for i, start in enumerate(xrange(0, mask.size, 8)): + bit = mask[start + 7: start + 8] + cur_label = check_labels[i] + next_check_label = check_labels[i + 1] if (i + 1) < len(check_labels) else lbl_next + write_label = write_labels[i] + check = m2_expr.ExprAff(ir.IRDst, + m2_expr.ExprCond(bit, + write_label, + next_check_label)) + blks.append(IRBlock(cur_label.name, [AssignBlock([check], instr)])) + + # Build write blocks + dst_addr = mRDI[instr.mode] + for i, start in enumerate(xrange(0, mask.size, 8)): + bit = mask[start + 7: start + 8] + cur_label = write_labels[i] + next_check_label = check_labels[i + 1] if (i + 1) < len(check_labels) else lbl_next + write_addr = dst_addr + m2_expr.ExprInt(i, dst_addr.size) + + # @8[DI/EDI/RDI + i] = src[byte i] + write_mem = m2_expr.ExprAff(m2_expr.ExprMem(write_addr, 8), + src[start: start + 8]) + jump = m2_expr.ExprAff(ir.IRDst, next_check_label) + blks.append(IRBlock(cur_label.name, [AssignBlock([write_mem, jump], instr)])) + + # If mask is null, bypass all + e = [m2_expr.ExprAff(ir.IRDst, m2_expr.ExprCond(mask, + check_labels[0], + lbl_next))] + return e, blks + + +def emms(ir, instr): + # Implemented as a NOP + return [], [] + + mnemo_func = {'mov': mov, 'xchg': xchg, 'movzx': movzx, @@ -4552,6 +4836,29 @@ mnemo_func = {'mov': mov, "psubd": psubd, "psubq": psubq, + # Multiplications + # SSE + "pmullb": pmullb, + "pmullw": pmullw, + "pmulld": pmulld, + "pmullq": pmullq, + "pmulhub": pmulhub, + "pmulhuw": pmulhuw, + "pmulhud": pmulhud, + "pmulhuq": pmulhuq, + "pmulhb": pmulhb, + "pmulhw": pmulhw, + "pmulhd": pmulhd, + "pmulhq": pmulhq, + "pmuludq": pmuludq, + + # Mix + # SSE + "pmaddwd": pmaddwd, + "psadbw": psadbw, + "pavgb": pavgb, + "pavgw": pavgw, + # Arithmetic (floating-point) # @@ -4609,6 +4916,7 @@ mnemo_func = {'mov': mov, "pmaxub": pmaxub, "pmaxuw": pmaxuw, "pmaxud": pmaxud, + "pmaxsw": pmaxsw, "pminub": pminub, "pminuw": pminuw, @@ -4665,8 +4973,23 @@ mnemo_func = {'mov': mov, "pmovmskb": pmovmskb, - "smsw": smsw, + "packsswb": packsswb, + "packssdw": packssdw, + "packuswb": packuswb, + + "psubusb": psubusb, + "psubusw": psubusw, + "paddusb": paddusb, + "paddusw": paddusw, + "psubsb": psubsb, + "psubsw": psubsw, + "paddsb": paddsb, + "paddsw": paddsw, + "smsw": smsw, + "maskmovq": maskmovq, + "maskmovdqu": maskmovq, + "emms": emms, } @@ -4788,7 +5111,7 @@ class ir_x86_16(IntermediateRepresentation): def irbloc_fix_regs_for_mode(self, irblock, mode=64): irs = [] - for assignblk in irblock.irs: + for assignblk in irblock: new_assignblk = dict(assignblk) for dst, src in assignblk.iteritems(): del new_assignblk[dst] diff --git a/miasm2/core/asmblock.py b/miasm2/core/asmblock.py index 5b95976f..7d18c4f5 100644 --- a/miasm2/core/asmblock.py +++ b/miasm2/core/asmblock.py @@ -1350,7 +1350,7 @@ class disasmEngine(object): + callback(arch, attrib, pool_bin, cur_bloc, offsets_to_dis, symbol_pool) - - dis_bloc_callback: callback after each new disassembled block + - dis_block_callback: callback after each new disassembled block """ def __init__(self, arch, attrib, bin_stream, **kwargs): @@ -1372,7 +1372,7 @@ class disasmEngine(object): self.dontdis_retcall = False self.lines_wd = None self.blocs_wd = None - self.dis_bloc_callback = None + self.dis_block_callback = None self.dont_dis_nulstart_bloc = False self.dont_dis_retcall_funcs = set() @@ -1387,9 +1387,18 @@ class disasmEngine(object): warnings.warn("""DEPRECATION WARNING: "job_done" is not needed anymore, support is dropped.""") return + def get_dis_bloc_callback(self): + warnings.warn("""DEPRECATION WARNING: "dis_bloc_callback" use dis_block_callback.""") + return self.dis_block_callback + + def set_dis_bloc_callback(self, function): + warnings.warn("""DEPRECATION WARNING: "dis_bloc_callback" use dis_block_callback.""") + self.dis_block_callback = function + # Deprecated job_done = property(get_job_done, set_job_done) + dis_bloc_callback = property(get_dis_bloc_callback, set_dis_bloc_callback) def _dis_block(self, offset, job_done=None): """Disassemble the block at offset @offset @@ -1520,11 +1529,11 @@ class disasmEngine(object): # Fix multiple constraints cur_block.fix_constraints() - if self.dis_bloc_callback is not None: - self.dis_bloc_callback(mn=self.arch, attrib=self.attrib, - pool_bin=self.bin_stream, cur_bloc=cur_block, - offsets_to_dis=offsets_to_dis, - symbol_pool=self.symbol_pool) + if self.dis_block_callback is not None: + self.dis_block_callback(mn=self.arch, attrib=self.attrib, + pool_bin=self.bin_stream, cur_bloc=cur_block, + offsets_to_dis=offsets_to_dis, + symbol_pool=self.symbol_pool) return cur_block, offsets_to_dis def dis_block(self, offset): @@ -1573,7 +1582,7 @@ class disasmEngine(object): blocks.add_node(cur_block) blocks.apply_splitting(self.symbol_pool, - dis_block_callback=self.dis_bloc_callback, + dis_block_callback=self.dis_block_callback, mn=self.arch, attrib=self.attrib, pool_bin=self.bin_stream) return blocks diff --git a/miasm2/expression/expression.py b/miasm2/expression/expression.py index 6b189c4d..a72c1ec4 100644 --- a/miasm2/expression/expression.py +++ b/miasm2/expression/expression.py @@ -525,11 +525,14 @@ class ExprId(Expr): __slots__ = Expr.__slots__ + ["_name"] - def __init__(self, name, size=32): + def __init__(self, name, size=None): """Create an identifier @name: str, identifier's name @size: int, identifier's size """ + if size is None: + warnings.warn('DEPRECATION WARNING: size is a mandatory argument: use ExprId(name, SIZE)') + size = 32 super(ExprId, self).__init__(size) self._name = name diff --git a/miasm2/expression/simplifications_cond.py b/miasm2/expression/simplifications_cond.py index 3054d92b..6bdc810f 100644 --- a/miasm2/expression/simplifications_cond.py +++ b/miasm2/expression/simplifications_cond.py @@ -19,9 +19,9 @@ import miasm2.expression.expression as m2_expr # Jokers for expression matching -jok1 = m2_expr.ExprId("jok1") -jok2 = m2_expr.ExprId("jok2") -jok3 = m2_expr.ExprId("jok3") +jok1 = m2_expr.ExprId("jok1", 32) +jok2 = m2_expr.ExprId("jok2", 32) +jok3 = m2_expr.ExprId("jok3", 32) jok_small = m2_expr.ExprId("jok_small", 1) diff --git a/miasm2/ir/ir.py b/miasm2/ir/ir.py index afb6b382..64eb3463 100644 --- a/miasm2/ir/ir.py +++ b/miasm2/ir/ir.py @@ -258,25 +258,43 @@ class IRBlock(object): Stand for an intermediate representation basic block. """ - __slots__ = ["label", "_assignments", "_dst", "_dst_linenb"] + __slots__ = ["label", "_assignblks", "_dst", "_dst_linenb"] - def __init__(self, label, irs): + def __init__(self, label, assignblks): """ @label: AsmLabel of the IR basic block - @irs: list of AssignBlock + @assignblks: list of AssignBlock """ assert isinstance(label, AsmLabel) self.label = label - for assignblk in irs: + for assignblk in assignblks: assert isinstance(assignblk, AssignBlock) - self._assignments = tuple(irs) + self._assignblks = tuple(assignblks) self._dst = None self._dst_linenb = None + + @property + def assignblks(self): + return self._assignblks + @property def irs(self): - return self._assignments + warnings.warn('DEPRECATION WARNING: use "irblock.assignblks" instead of "irblock.irs"') + return self._assignblks + + def __iter__(self): + """Iterate on assignblks""" + return self._assignblks.__iter__() + + def __getitem__(self, index): + """Getitem on assignblks""" + return self._assignblks.__getitem__(index) + + def __len__(self): + """Length of assignblks""" + return self._assignblks.__len__() def is_dst_set(self): return self._dst is not None @@ -284,7 +302,7 @@ class IRBlock(object): def cache_dst(self): final_dst = None final_linenb = None - for linenb, assignblk in enumerate(self.irs): + for linenb, assignblk in enumerate(self): for dst, src in assignblk.iteritems(): if dst.is_id("IRDst"): if final_dst is not None: @@ -306,7 +324,7 @@ class IRBlock(object): """Generate a new IRBlock with a dst (IRBlock) fixed to @value""" irs = [] dst_found = False - for assignblk in self.irs: + for assignblk in self: new_assignblk = {} for dst, src in assignblk.iteritems(): if dst.is_id("IRDst"): @@ -328,7 +346,7 @@ class IRBlock(object): def __str__(self): out = [] out.append('%s' % self.label) - for assignblk in self.irs: + for assignblk in self: for dst, src in assignblk.iteritems(): out.append('\t%s = %s' % (dst, src)) out.append("") @@ -349,7 +367,7 @@ class IRBlock(object): mod_src = lambda expr:expr assignblks = [] - for assignblk in self.irs: + for assignblk in self: new_assignblk = {} for dst, src in assignblk.iteritems(): new_assignblk[mod_dst(dst)] = mod_src(src) @@ -387,7 +405,7 @@ class DiGraphIR(DiGraph): if node not in self._blocks: yield [self.DotCellDescription(text="NOT PRESENT", attr={})] raise StopIteration - for i, assignblk in enumerate(self._blocks[node].irs): + for i, assignblk in enumerate(self._blocks[node]): for dst, src in assignblk.iteritems(): line = "%s = %s" % (dst, src) if self._dot_offset: @@ -456,7 +474,7 @@ class IntermediateRepresentation(object): ir_bloc_cur, extra_irblocks = self.get_ir(instr) for index, irb in enumerate(extra_irblocks): irs = [] - for assignblk in irb.irs: + for assignblk in irb: irs.append(AssignBlock(assignblk, instr)) extra_irblocks[index] = IRBlock(irb.label, irs) assignblk = AssignBlock(ir_bloc_cur, instr) @@ -502,7 +520,7 @@ class IntermediateRepresentation(object): def getby_offset(self, offset): out = set() for irb in self.blocks.values(): - for assignblk in irb.irs: + for assignblk in irb: instr = assignblk.instr if instr.offset <= offset < instr.offset + instr.l: out.add(irb) @@ -607,11 +625,12 @@ class IntermediateRepresentation(object): return irblock 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 irs in block.irs: - for assignblk in irs: - if assignblk.dst in all_pc: - return assignblk + for assignblk in block: + if assignblk.dst in all_pc: + return assignblk return None def set_empty_dst_to_next(self, block, ir_blocks): @@ -625,8 +644,8 @@ class IntermediateRepresentation(object): else: dst = m2_expr.ExprId(next_lbl, self.pc.size) - assignblk = AssignBlock({self.IRDst: dst}, irblock.irs[-1].instr) - ir_blocks[index] = IRBlock(irblock.label, list(irblock.irs) + [assignblk]) + assignblk = AssignBlock({self.IRDst: dst}, irblock[-1].instr) + ir_blocks[index] = IRBlock(irblock.label, list(irblock.assignblks) + [assignblk]) def post_add_block(self, block, ir_blocks): self.set_empty_dst_to_next(block, ir_blocks) @@ -670,13 +689,13 @@ class IntermediateRepresentation(object): """ for label, block in self.blocks.iteritems(): assignblks = [] - for assignblk in block.irs: + for assignblk in block: new_assignblk = assignblk.simplify(simplifier) assignblks.append(new_assignblk) self.blocks[label] = IRBlock(label, assignblks) def replace_expr_in_ir(self, bloc, rep): - for assignblk in bloc.irs: + for assignblk in bloc: for dst, src in assignblk.items(): del assignblk[dst] assignblk[dst.replace_expr(rep)] = src.replace_expr(rep) @@ -720,7 +739,7 @@ class IntermediateRepresentation(object): todo = set([irb.dst]) done = set() - for assignblk in reversed(irb.irs): + for assignblk in reversed(irb): if not todo: break out = self._extract_dst(todo, done) @@ -746,7 +765,7 @@ class IntermediateRepresentation(object): for dst in self.dst_trackback(block): if dst.is_int(): dst_lbl = self.symbol_pool.getby_offset_create(int(dst)) - dst = m2_expr.ExprId(dst_lbl) + dst = m2_expr.ExprId(dst_lbl, self.pc.size) if expr_is_label(dst): self._graph.add_edge(lbl, dst.name) @@ -762,7 +781,7 @@ class IntermediateRepresentation(object): modified = False for label, block in self.blocks.iteritems(): irs = [] - for assignblk in block.irs: + for assignblk in block: if len(assignblk): irs.append(assignblk) else: @@ -779,9 +798,9 @@ class IntermediateRepresentation(object): # Find candidates jmp_blocks = set() for block in self.blocks.itervalues(): - if len(block.irs) != 1: + if len(block) != 1: continue - assignblk = block.irs[0] + assignblk = block[0] if len(assignblk) > 1: continue assert set(assignblk.keys()) == set([self.IRDst]) @@ -860,7 +879,7 @@ class IntermediateRepresentation(object): continue # Block has one son, son has one parent => merge assignblks =[] - for assignblk in self.blocks[block].irs: + for assignblk in self.blocks[block]: if self.IRDst not in assignblk: assignblks.append(assignblk) continue @@ -870,7 +889,7 @@ class IntermediateRepresentation(object): affs[dst] = src assignblks.append(AssignBlock(affs, assignblk.instr)) - assignblks += self.blocks[son].irs + assignblks += self.blocks[son].assignblks new_block = IRBlock(block, assignblks) self.graph.discard_edge(block, son) diff --git a/miasm2/ir/symbexec.py b/miasm2/ir/symbexec.py index 593ab49a..8ecde21c 100644 --- a/miasm2/ir/symbexec.py +++ b/miasm2/ir/symbexec.py @@ -524,7 +524,7 @@ class SymbolicExecutionEngine(object): @irb: irbloc instance @step: display intermediate steps """ - for assignblk in irb.irs: + for assignblk in irb: if step: print 'Instr', assignblk.instr print 'Assignblk:' diff --git a/miasm2/jitter/arch/JitCore_aarch64.c b/miasm2/jitter/arch/JitCore_aarch64.c index 03113d30..e10d847e 100644 --- a/miasm2/jitter/arch/JitCore_aarch64.c +++ b/miasm2/jitter/arch/JitCore_aarch64.c @@ -50,6 +50,10 @@ reg_dict gpreg_dict[] = { {.name = "nf", .offset = offsetof(vm_cpu_t, nf)}, {.name = "of", .offset = offsetof(vm_cpu_t, of)}, {.name = "cf", .offset = offsetof(vm_cpu_t, cf)}, + + {.name = "exception_flags", .offset = offsetof(vm_cpu_t, exception_flags)}, + {.name = "interrupt_num", .offset = offsetof(vm_cpu_t, interrupt_num)}, + }; /************************** JitCpu object **************************/ @@ -375,6 +379,9 @@ getset_reg_u32(of); getset_reg_u32(cf); +getset_reg_u32(exception_flags); +getset_reg_u32(interrupt_num); + PyObject* get_gpreg_offset_all(void) { @@ -485,6 +492,9 @@ static PyGetSetDef JitCpu_getseters[] = { {"of", (getter)JitCpu_get_of, (setter)JitCpu_set_of, "of", NULL}, {"cf", (getter)JitCpu_get_cf, (setter)JitCpu_set_cf, "cf", NULL}, + {"exception_flags", (getter)JitCpu_get_exception_flags, (setter)JitCpu_set_exception_flags, "exception_flags", NULL}, + {"interrupt_num", (getter)JitCpu_get_interrupt_num, (setter)JitCpu_set_interrupt_num, "interrupt_num", NULL}, + {NULL} /* Sentinel */ }; diff --git a/miasm2/jitter/arch/JitCore_aarch64.h b/miasm2/jitter/arch/JitCore_aarch64.h index 4635b395..c7fc3cea 100644 --- a/miasm2/jitter/arch/JitCore_aarch64.h +++ b/miasm2/jitter/arch/JitCore_aarch64.h @@ -1,6 +1,7 @@ typedef struct { uint32_t exception_flags; + uint32_t interrupt_num; /* gpregs */ diff --git a/miasm2/jitter/arch/JitCore_x86.c b/miasm2/jitter/arch/JitCore_x86.c index 3198eff3..407a01c7 100644 --- a/miasm2/jitter/arch/JitCore_x86.c +++ b/miasm2/jitter/arch/JitCore_x86.c @@ -178,6 +178,29 @@ PyObject * cpu_init_regs(JitCpu* self) } +void dump_gpregs_16(vm_cpu_t* vmcpu) +{ + + printf("EAX %.8"PRIX32" EBX %.8"PRIX32" ECX %.8"PRIX32" EDX %.8"PRIX32" ", + (uint32_t)(vmcpu->RAX & 0xFFFFFFFF), + (uint32_t)(vmcpu->RBX & 0xFFFFFFFF), + (uint32_t)(vmcpu->RCX & 0xFFFFFFFF), + (uint32_t)(vmcpu->RDX & 0xFFFFFFFF)); + printf("ESI %.8"PRIX32" EDI %.8"PRIX32" ESP %.8"PRIX32" EBP %.8"PRIX32" ", + (uint32_t)(vmcpu->RSI & 0xFFFFFFFF), + (uint32_t)(vmcpu->RDI & 0xFFFFFFFF), + (uint32_t)(vmcpu->RSP & 0xFFFFFFFF), + (uint32_t)(vmcpu->RBP & 0xFFFFFFFF)); + printf("EIP %.8"PRIX32" ", + (uint32_t)(vmcpu->RIP & 0xFFFFFFFF)); + printf("zf %.1"PRIX32" nf %.1"PRIX32" of %.1"PRIX32" cf %.1"PRIX32"\n", + (uint32_t)(vmcpu->zf & 0x1), + (uint32_t)(vmcpu->nf & 0x1), + (uint32_t)(vmcpu->of & 0x1), + (uint32_t)(vmcpu->cf & 0x1)); + +} + void dump_gpregs_32(vm_cpu_t* vmcpu) { diff --git a/miasm2/jitter/codegen.py b/miasm2/jitter/codegen.py index 61a9a784..9ed55f37 100644 --- a/miasm2/jitter/codegen.py +++ b/miasm2/jitter/codegen.py @@ -489,7 +489,7 @@ class CGen(object): for irblock in irblocks: attributes = [] irblocks_attributes.append(attributes) - for assignblk in irblock.irs: + for assignblk in irblock: attrib = Attributes(log_mn, log_regs) attributes.append(attrib) self.get_caracteristics(assignblk, attrib) @@ -534,7 +534,7 @@ class CGen(object): out = [] dst2index = None - for index, assignblk in enumerate(irblock.irs): + for index, assignblk in enumerate(irblock): if index == irblock.dst_linenb: c_dst, dst2index = self.gen_assignblk_dst(irblock.dst) else: diff --git a/miasm2/jitter/jitcore.py b/miasm2/jitter/jitcore.py index 9c35f829..f2b1375d 100644 --- a/miasm2/jitter/jitcore.py +++ b/miasm2/jitter/jitcore.py @@ -63,7 +63,7 @@ class JitCore(object): follow_call=False, dontdis_retcall=False, split_dis=self.split_dis, - dis_bloc_callback=self.disasm_cb) + dis_block_callback=self.disasm_cb) def set_options(self, **kwargs): @@ -140,7 +140,7 @@ class JitCore(object): # Prepare disassembler self.mdis.lines_wd = self.options["jit_maxline"] - self.mdis.dis_bloc_callback = self.disasm_cb + self.mdis.dis_block_callback = self.disasm_cb # Disassemble it try: diff --git a/miasm2/jitter/jitcore_python.py b/miasm2/jitter/jitcore_python.py index 6d954aae..a74ef7e6 100644 --- a/miasm2/jitter/jitcore_python.py +++ b/miasm2/jitter/jitcore_python.py @@ -72,7 +72,7 @@ class JitCore_Python(jitcore.JitCore): exec_engine.update_engine_from_cpu() # Execute current ir bloc - for assignblk in irb.irs: + for assignblk in irb: instr = assignblk.instr # For each new instruction (in assembly) if instr.offset not in offsets_jitted: diff --git a/miasm2/jitter/jitload.py b/miasm2/jitter/jitload.py index 4760c8dd..ff7ba215 100644 --- a/miasm2/jitter/jitload.py +++ b/miasm2/jitter/jitload.py @@ -448,7 +448,7 @@ class jitter: return ret def handle_function(self, f_addr): - """Add a brakpoint which will trigger the function handler""" + """Add a breakpoint which will trigger the function handler""" self.add_breakpoint(f_addr, self.handle_lib) def add_lib_handler(self, libs, user_globals=None): diff --git a/miasm2/jitter/llvmconvert.py b/miasm2/jitter/llvmconvert.py index 83349781..65c6aa07 100644 --- a/miasm2/jitter/llvmconvert.py +++ b/miasm2/jitter/llvmconvert.py @@ -966,7 +966,7 @@ class LLVMFunction(): if isinstance(offset, (int, long)): offset = self.add_ir(m2_expr.ExprInt(offset, PC.size)) self.affect(offset, PC) - self.affect(self.add_ir(m2_expr.ExprInt(1, 8)), m2_expr.ExprId("status")) + self.affect(self.add_ir(m2_expr.ExprInt(1, 8)), m2_expr.ExprId("status", 32)) self.set_ret(offset) builder.position_at_end(merge_block) @@ -1013,7 +1013,7 @@ class LLVMFunction(): if isinstance(offset, (int, long)): offset = self.add_ir(m2_expr.ExprInt(offset, PC.size)) self.affect(offset, PC) - self.affect(self.add_ir(m2_expr.ExprInt(1, 8)), m2_expr.ExprId("status")) + self.affect(self.add_ir(m2_expr.ExprInt(1, 8)), m2_expr.ExprId("status", 32)) self.set_ret(offset) builder.position_at_end(merge_block) @@ -1121,7 +1121,7 @@ class LLVMFunction(): self.gen_post_code(attrib) self.affect(dst, PC) self.gen_post_instr_checks(attrib, dst) - self.affect(self.add_ir(m2_expr.ExprInt(0, 8)), m2_expr.ExprId("status")) + self.affect(self.add_ir(m2_expr.ExprInt(0, 8)), m2_expr.ExprId("status", 32)) self.set_ret(dst) @@ -1138,7 +1138,7 @@ class LLVMFunction(): case_value = None instr = instr_attrib.instr - for index, assignblk in enumerate(irblock.irs): + for index, assignblk in enumerate(irblock): # Enable cache self.main_stream = True self.expr_cache = {} @@ -1215,7 +1215,7 @@ class LLVMFunction(): m2_exception_flag = self.llvm_context.ir_arch.arch.regs.exception_flags t_size = LLVMType.IntType(m2_exception_flag.size) self.affect(self.add_ir(m2_expr.ExprInt(1, 8)), - m2_expr.ExprId("status")) + m2_expr.ExprId("status", 32)) self.affect(t_size(m2_csts.EXCEPT_UNK_MNEMO), m2_exception_flag) self.set_ret(LLVMType.IntType(64)(asmblock.label.offset)) @@ -1233,7 +1233,7 @@ class LLVMFunction(): # Common code self.affect(self.add_ir(m2_expr.ExprInt(0, 8)), - m2_expr.ExprId("status")) + m2_expr.ExprId("status", 32)) # Check if IRDst has been set zero_casted = LLVMType.IntType(codegen.delay_slot_set.size)(0) @@ -1257,7 +1257,7 @@ class LLVMFunction(): to_ret = self.add_ir(codegen.delay_slot_dst) self.affect(to_ret, PC) self.affect(self.add_ir(m2_expr.ExprInt(0, 8)), - m2_expr.ExprId("status")) + m2_expr.ExprId("status", 32)) self.set_ret(to_ret) # Else Block @@ -1272,16 +1272,16 @@ class LLVMFunction(): Prototype : f(i8* jitcpu, i8* vmcpu, i8* vmmngr, i8* status)""" # Build function signature - self.my_args.append((m2_expr.ExprId("jitcpu"), + self.my_args.append((m2_expr.ExprId("jitcpu", 32), llvm_ir.PointerType(LLVMType.IntType(8)), "jitcpu")) - self.my_args.append((m2_expr.ExprId("vmcpu"), + self.my_args.append((m2_expr.ExprId("vmcpu", 32), llvm_ir.PointerType(LLVMType.IntType(8)), "vmcpu")) - self.my_args.append((m2_expr.ExprId("vmmngr"), + self.my_args.append((m2_expr.ExprId("vmmngr", 32), llvm_ir.PointerType(LLVMType.IntType(8)), "vmmngr")) - self.my_args.append((m2_expr.ExprId("status"), + self.my_args.append((m2_expr.ExprId("status", 32), llvm_ir.PointerType(LLVMType.IntType(8)), "status")) ret_size = 64 diff --git a/test/analysis/data_flow.py b/test/analysis/data_flow.py index 2c24773a..dff88470 100644 --- a/test/analysis/data_flow.py +++ b/test/analysis/data_flow.py @@ -5,20 +5,20 @@ from miasm2.analysis.data_flow import * from miasm2.ir.analysis import ira from miasm2.ir.ir import IRBlock, AssignBlock -a = ExprId("a") -b = ExprId("b") -c = ExprId("c") -d = ExprId("d") -r = ExprId("r") +a = ExprId("a", 32) +b = ExprId("b", 32) +c = ExprId("c", 32) +d = ExprId("d", 32) +r = ExprId("r", 32) -a_init = ExprId("a_init") -b_init = ExprId("b_init") -c_init = ExprId("c_init") -d_init = ExprId("d_init") -r_init = ExprId("r_init") # Return register +a_init = ExprId("a_init", 32) +b_init = ExprId("b_init", 32) +c_init = ExprId("c_init", 32) +d_init = ExprId("d_init", 32) +r_init = ExprId("r_init", 32) # Return register -pc = ExprId("pc") -sp = ExprId("sp") +pc = ExprId("pc", 32) +sp = ExprId("sp", 32) CST1 = ExprInt(0x11, 32) CST2 = ExprInt(0x12, 32) @@ -635,7 +635,7 @@ G17_EXP_IRB0 = gen_irblock(LBL0, [[], ExprAff(b, a), ExprAff(c, b)], - G17_IRB0.irs[14] + G17_IRB0[14] # Trick because a+b+c != ((a+b)+c) ]) @@ -684,4 +684,4 @@ for test_nb, test in enumerate([(G1_IRA, G1_EXP_IRA), # Check that each expr in the blocks are the same for lbl, irb in g_ira.blocks.iteritems(): exp_irb = g_exp_ira.blocks[lbl] - assert exp_irb.irs == irb.irs + assert exp_irb.assignblks == irb.assignblks diff --git a/test/analysis/depgraph.py b/test/analysis/depgraph.py index 63313861..9fb046d0 100644 --- a/test/analysis/depgraph.py +++ b/test/analysis/depgraph.py @@ -16,19 +16,19 @@ except ImportError: EMULATION = False STEP_COUNTER = count() -A = ExprId("a") -B = ExprId("b") -C = ExprId("c") -D = ExprId("d") -R = ExprId("r") +A = ExprId("a", 32) +B = ExprId("b", 32) +C = ExprId("c", 32) +D = ExprId("d", 32) +R = ExprId("r", 32) -A_INIT = ExprId("a_init") -B_INIT = ExprId("b_init") -C_INIT = ExprId("c_init") -D_INIT = ExprId("d_init") +A_INIT = ExprId("a_init", 32) +B_INIT = ExprId("b_init", 32) +C_INIT = ExprId("c_init", 32) +D_INIT = ExprId("d_init", 32) -PC = ExprId("pc") -SP = ExprId("sp") +PC = ExprId("pc", 32) +SP = ExprId("sp", 32) CST0 = ExprInt(0x0, 32) CST1 = ExprInt(0x1, 32) @@ -132,7 +132,7 @@ def bloc2graph(irgraph, label=False, lines=True): label_attr, label_name) block_html_lines = [] if lines and irblock is not None: - for assignblk in irblock.irs: + for assignblk in irblock: for dst, src in assignblk.iteritems(): if False: out_render = "%.8X</td><td %s> " % (0, td_attr) @@ -277,8 +277,8 @@ G4_IRA = IRATest() G4_IRB0 = gen_irblock(LBL0, [[ExprAff(C, CST1)]]) G4_IRB1 = gen_irblock(LBL1, [[ExprAff(C, C + CST2)], [ExprAff(G4_IRA.IRDst, - ExprCond(C, ExprId(LBL2), - ExprId(LBL1)))]]) + ExprCond(C, ExprId(LBL2, 32), + ExprId(LBL1, 32)))]]) G4_IRB2 = gen_irblock(LBL2, [[ExprAff(A, B)]]) @@ -296,8 +296,8 @@ G5_IRA = IRATest() G5_IRB0 = gen_irblock(LBL0, [[ExprAff(B, CST1)]]) G5_IRB1 = gen_irblock(LBL1, [[ExprAff(B, B + CST2)], [ExprAff(G5_IRA.IRDst, - ExprCond(B, ExprId(LBL2), - ExprId(LBL1)))]]) + ExprCond(B, ExprId(LBL2, 32), + ExprId(LBL1, 32)))]]) G5_IRB2 = gen_irblock(LBL2, [[ExprAff(A, B)]]) @@ -400,16 +400,16 @@ G13_IRA = IRATest() G13_IRB0 = gen_irblock(LBL0, [[ExprAff(A, CST1)], #[ExprAff(B, A)], [ExprAff(G13_IRA.IRDst, - ExprId(LBL1))]]) + ExprId(LBL1, 32))]]) G13_IRB1 = gen_irblock(LBL1, [[ExprAff(C, A)], #[ExprAff(A, A + CST1)], [ExprAff(G13_IRA.IRDst, - ExprCond(R, ExprId(LBL2), - ExprId(LBL1)))]]) + ExprCond(R, ExprId(LBL2, 32), + ExprId(LBL1, 32)))]]) G13_IRB2 = gen_irblock(LBL2, [[ExprAff(B, A + CST3)], [ExprAff(A, B + CST3)], [ExprAff(G13_IRA.IRDst, - ExprId(LBL1))]]) + ExprId(LBL1, 32))]]) G13_IRB3 = gen_irblock(LBL3, [[ExprAff(R, C)]]) @@ -427,18 +427,18 @@ G14_IRA = IRATest() G14_IRB0 = gen_irblock(LBL0, [[ExprAff(A, CST1)], [ExprAff(G14_IRA.IRDst, - ExprId(LBL1))] + ExprId(LBL1, 32))] ]) G14_IRB1 = gen_irblock(LBL1, [[ExprAff(B, A)], [ExprAff(G14_IRA.IRDst, - ExprCond(C, ExprId(LBL2), - ExprId(LBL3)))] + ExprCond(C, ExprId(LBL2, 32), + ExprId(LBL3, 32)))] ]) G14_IRB2 = gen_irblock(LBL2, [[ExprAff(D, A)], [ExprAff(A, D + CST1)], [ExprAff(G14_IRA.IRDst, - ExprId(LBL1))] + ExprId(LBL1, 32))] ]) G14_IRB3 = gen_irblock(LBL3, [[ExprAff(R, D + B)]]) @@ -510,72 +510,72 @@ G17_IRA.blocks = dict([(irb.label, irb) for irb in [G17_IRB0, G17_IRB1, # Test graph 1 G1_TEST1_DN1 = DependencyNode( - G1_IRB2.label, A, len(G1_IRB2.irs)) + G1_IRB2.label, A, len(G1_IRB2)) G1_INPUT = (set([G1_TEST1_DN1]), set([G1_IRB0.label])) # Test graph 2 G2_TEST1_DN1 = DependencyNode( - G2_IRB2.label, A, len(G2_IRB2.irs)) + G2_IRB2.label, A, len(G2_IRB2)) G2_INPUT = (set([G2_TEST1_DN1]), set([G2_IRB0.label])) # Test graph 3 G3_TEST1_0_DN1 = DependencyNode( - G3_IRB3.label, A, len(G3_IRB3.irs)) + G3_IRB3.label, A, len(G3_IRB3)) G3_INPUT = (set([G3_TEST1_0_DN1]), set([G3_IRB0.label])) # Test graph 4 G4_TEST1_DN1 = DependencyNode( - G4_IRB2.label, A, len(G2_IRB0.irs)) + G4_IRB2.label, A, len(G2_IRB0)) G4_INPUT = (set([G4_TEST1_DN1]), set([G4_IRB0.label])) # Test graph 5 G5_TEST1_0_DN1 = DependencyNode( - G5_IRB2.label, A, len(G5_IRB2.irs)) + G5_IRB2.label, A, len(G5_IRB2)) G5_INPUT = (set([G5_TEST1_0_DN1]), set([G5_IRB0.label])) # Test graph 6 G6_TEST1_0_DN1 = DependencyNode( - G6_IRB1.label, A, len(G6_IRB1.irs)) + G6_IRB1.label, A, len(G6_IRB1)) G6_INPUT = (set([G6_TEST1_0_DN1]), set([G6_IRB0.label])) # Test graph 7 G7_TEST1_0_DN1 = DependencyNode( - G7_IRB2.label, D, len(G7_IRB2.irs)) + G7_IRB2.label, D, len(G7_IRB2)) G7_INPUT = (set([G7_TEST1_0_DN1]), set([G7_IRB0.label])) # Test graph 8 G8_TEST1_0_DN1 = DependencyNode( - G8_IRB2.label, A, len(G8_IRB2.irs)) + G8_IRB2.label, A, len(G8_IRB2)) G8_INPUT = (set([G8_TEST1_0_DN1]), set([G3_IRB0.label])) # Test 9: Multi elements G9_TEST1_0_DN1 = DependencyNode( - G8_IRB2.label, A, len(G8_IRB2.irs)) + G8_IRB2.label, A, len(G8_IRB2)) G9_TEST1_0_DN5 = DependencyNode( - G8_IRB2.label, C, len(G8_IRB2.irs)) + G8_IRB2.label, C, len(G8_IRB2)) G9_INPUT = (set([G9_TEST1_0_DN1, G9_TEST1_0_DN5]), set([G8_IRB0.label])) # Test 10: loop at beginning G10_TEST1_0_DN1 = DependencyNode( - G10_IRB2.label, A, len(G10_IRB2.irs)) + G10_IRB2.label, A, len(G10_IRB2)) G10_INPUT = (set([G10_TEST1_0_DN1]), set([G10_IRB1.label])) @@ -583,7 +583,7 @@ G10_INPUT = (set([G10_TEST1_0_DN1]), set([G10_IRB1.label])) # Test 11: no dual bloc emulation G11_TEST1_DN1 = DependencyNode( - G11_IRB2.label, A, len(G11_IRB2.irs)) + G11_IRB2.label, A, len(G11_IRB2)) G11_INPUT = (set([G11_TEST1_DN1]), set([G11_IRB0.label])) diff --git a/test/arch/x86/arch.py b/test/arch/x86/arch.py index d3b2964c..2af90c8a 100644 --- a/test/arch/x86/arch.py +++ b/test/arch/x86/arch.py @@ -2902,11 +2902,11 @@ reg_tests = [ (m32, "00000000 PEXTRW WORD PTR [EDX], XMM2, 0x5", "660F3A151205"), + (m32, "00000000 PEXTRW EAX, MM2, 0x5", + "0fc5c205"), + (m32, "00000000 PEXTRW EAX, XMM2, 0x5", + "660fc5c205"), - (m32, "00000000 PEXTRW WORD PTR [EDX], MM2, 0x5", - "0FC51205"), - (m32, "00000000 PEXTRW WORD PTR [EDX], XMM2, 0x5", - "660FC51205"), (m32, "00000000 PEXTRD DWORD PTR [EDX], XMM2, 0x5", "660F3A161205"), @@ -2970,6 +2970,113 @@ reg_tests = [ (m64, "00000000 BNDMOV BND3, XMMWORD PTR [RSP + 0xB0]", "660f1a9c24b0000000"), + (m32, "00000000 PACKSSWB MM7, MM0", + "0f63f8"), + (m32, "00000000 PACKSSWB XMM0, XMM5", + "660f63c5"), + + (m32, "00000000 PACKSSDW MM2, MM0", + "0f6bd0"), + (m32, "00000000 PACKSSDW XMM0, XMM7", + "660f6bc7"), + + (m32, "00000000 PACKUSWB MM1, MM7", + "0f67cf"), + (m32, "00000000 PACKUSWB XMM0, XMM6", + "660f67c6"), + + (m32, "00000000 PMULLW MM4, MM2", + "0fd5e2"), + (m32, "00000000 PMULLW XMM0, XMM3", + "660fd5c3"), + + (m32, "00000000 PSUBUSB MM5, MM3", + "0fd8eb"), + (m32, "00000000 PSUBUSB XMM0, XMM5", + "660fd8c5"), + + (m32, "00000000 PSUBUSW MM5, MM3", + "0fd9eb"), + (m32, "00000000 PSUBUSW XMM0, XMM5", + "660fd9c5"), + + (m32, "00000000 PADDUSB MM5, MM3", + "0fdceb"), + (m32, "00000000 PADDUSB XMM0, XMM6", + "660fdcc6"), + + (m32, "00000000 PADDUSW MM7, MM5", + "0fddfd"), + (m32, "00000000 PADDUSW XMM0, XMM1", + "660fddc1"), + + (m32, "00000000 PMULHUW MM6, MM4", + "0fe4f4"), + (m32, "00000000 PMULHUW XMM0, XMM7", + "660fe4c7"), + + (m32, "00000000 PMULHW MM6, MM4", + "0fe5f4"), + (m32, "00000000 PMULHW XMM0, XMM7", + "660fe5c7"), + + (m32, "00000000 PSUBSB MM2, MM0", + "0fe8d0"), + (m32, "00000000 PSUBSB XMM0, XMM4", + "660fe8c4"), + + (m32, "00000000 PSUBSW MM3, MM1", + "0fe9d9"), + (m32, "00000000 PSUBSW XMM0, XMM6", + "660fe9c6"), + + (m32, "00000000 PADDSB MM2, MM0", + "0fecd0"), + (m32, "00000000 PADDSB XMM0, XMM4", + "660fecc4"), + + (m32, "00000000 PADDSW MM3, MM1", + "0fedd9"), + (m32, "00000000 PADDSW XMM0, XMM6", + "660fedc6"), + + (m32, "00000000 PMAXSW MM3, MM1", + "0feed9"), + (m32, "00000000 PMAXSW XMM0, XMM6", + "660feec6"), + + (m32, "00000000 PMULUDQ MM3, MM1", + "0ff4d9"), + (m32, "00000000 PMULUDQ XMM0, XMM6", + "660ff4c6"), + + (m32, "00000000 PMADDWD MM3, MM1", + "0ff5d9"), + (m32, "00000000 PMADDWD XMM0, XMM6", + "660ff5c6"), + + (m32, "00000000 PSADBW MM3, MM1", + "0ff6d9"), + (m32, "00000000 PSADBW XMM0, XMM6", + "660ff6c6"), + + (m32, "00000000 PAVGB MM3, MM1", + "0fe0d9"), + (m32, "00000000 PAVGB XMM0, XMM6", + "660fe0c6"), + + (m32, "00000000 PAVGW MM3, MM1", + "0fe3d9"), + (m32, "00000000 PAVGW XMM0, XMM6", + "660fe3c6"), + + (m32, "00000000 MASKMOVQ MM2, MM3", + "0ff7d3"), + (m32, "00000000 MASKMOVDQU XMM4, XMM5", + "660ff7e5"), + + (m32, "00000000 EMMS", + "0f77"), ] diff --git a/test/arch/x86/unit/mn_cdq.py b/test/arch/x86/unit/mn_cdq.py new file mode 100644 index 00000000..f4e4d6e7 --- /dev/null +++ b/test/arch/x86/unit/mn_cdq.py @@ -0,0 +1,445 @@ +#! /usr/bin/env python2 + +import sys + +from asm_test import Asm_Test_16, Asm_Test_32, Asm_Test_64 +from miasm2.core.utils import pck16, pck32 + + +class Test_CBW_16(Asm_Test_16): + MYSTRING = "test CBW 16" + + def prepare(self): + self.myjit.ir_arch.symbol_pool.add_label("lbl_ret", self.ret_addr) + + def test_init(self): + self.myjit.cpu.EAX = 0x87654321 + self.myjit.cpu.EDX = 0x11223344 + + TXT = ''' + main: + CBW + JMP lbl_ret + ''' + + def check(self): + assert self.myjit.cpu.EAX == 0x87650021 + assert self.myjit.cpu.EDX == 0x11223344 + + +class Test_CBW_16_signed(Asm_Test_16): + MYSTRING = "test CBW 16 signed" + + def prepare(self): + self.myjit.ir_arch.symbol_pool.add_label("lbl_ret", self.ret_addr) + + def test_init(self): + self.myjit.cpu.EAX = 0x87654381 + self.myjit.cpu.EDX = 0x11223344 + + TXT = ''' + main: + CBW + JMP lbl_ret + ''' + + def check(self): + assert self.myjit.cpu.EAX == 0x8765FF81 + assert self.myjit.cpu.EDX == 0x11223344 + + +class Test_CBW_32(Asm_Test_32): + MYSTRING = "test CBW 32" + + def prepare(self): + self.myjit.ir_arch.symbol_pool.add_label("lbl_ret", self.ret_addr) + + def test_init(self): + self.myjit.cpu.EAX = 0x87654321 + self.myjit.cpu.EDX = 0x11223344 + + TXT = ''' + main: + CBW + JMP lbl_ret + ''' + + def check(self): + assert self.myjit.cpu.EAX == 0x87650021 + assert self.myjit.cpu.EDX == 0x11223344 + + +class Test_CBW_32_signed(Asm_Test_32): + MYSTRING = "test CBW 32 signed" + + def prepare(self): + self.myjit.ir_arch.symbol_pool.add_label("lbl_ret", self.ret_addr) + + def test_init(self): + self.myjit.cpu.EAX = 0x87654381 + self.myjit.cpu.EDX = 0x11223344 + + TXT = ''' + main: + CBW + JMP lbl_ret + ''' + + def check(self): + assert self.myjit.cpu.EAX == 0x8765FF81 + assert self.myjit.cpu.EDX == 0x11223344 + + +class Test_CDQ_32(Asm_Test_32): + MYSTRING = "test cdq 32" + + def prepare(self): + self.myjit.ir_arch.symbol_pool.add_label("lbl_ret", self.ret_addr) + + def test_init(self): + self.myjit.cpu.EAX = 0x77654321 + self.myjit.cpu.EDX = 0x11223344 + + TXT = ''' + main: + CDQ + JMP lbl_ret + ''' + + def check(self): + assert self.myjit.cpu.EAX == 0x77654321 + assert self.myjit.cpu.EDX == 0x0 + + +class Test_CDQ_32_signed(Asm_Test_32): + MYSTRING = "test cdq 32 signed" + + def prepare(self): + self.myjit.ir_arch.symbol_pool.add_label("lbl_ret", self.ret_addr) + + def test_init(self): + self.myjit.cpu.EAX = 0x87654321 + self.myjit.cpu.EDX = 0x11223344 + + TXT = ''' + main: + CDQ + JMP lbl_ret + ''' + + def check(self): + assert self.myjit.cpu.EAX == 0x87654321 + assert self.myjit.cpu.EDX == 0xFFFFFFFF + + +class Test_CDQ_64(Asm_Test_64): + MYSTRING = "test cdq 64" + + def prepare(self): + self.myjit.ir_arch.symbol_pool.add_label("lbl_ret", self.ret_addr) + + def test_init(self): + self.myjit.cpu.RAX = 0x1234567877654321 + self.myjit.cpu.RDX = 0x1122334455667788 + + TXT = ''' + main: + CDQ + JMP lbl_ret + ''' + + def check(self): + assert self.myjit.cpu.RAX == 0x1234567877654321 + assert self.myjit.cpu.RDX == 0x0 + + +class Test_CDQ_64_signed(Asm_Test_64): + MYSTRING = "test cdq 64 signed" + + def prepare(self): + self.myjit.ir_arch.symbol_pool.add_label("lbl_ret", self.ret_addr) + + def test_init(self): + self.myjit.cpu.RAX = 0x1234567887654321 + self.myjit.cpu.RDX = 0x1122334455667788 + + TXT = ''' + main: + CDQ + JMP lbl_ret + ''' + + def check(self): + assert self.myjit.cpu.RAX == 0x1234567887654321 + assert self.myjit.cpu.RDX == 0x00000000FFFFFFFF + + +class Test_CDQE_64(Asm_Test_64): + MYSTRING = "test cdq 64" + + def prepare(self): + self.myjit.ir_arch.symbol_pool.add_label("lbl_ret", self.ret_addr) + + def test_init(self): + self.myjit.cpu.RAX = 0x1234567877654321 + self.myjit.cpu.RDX = 0x1122334455667788 + + TXT = ''' + main: + CDQE + JMP lbl_ret + ''' + + def check(self): + assert self.myjit.cpu.RAX == 0x77654321 + assert self.myjit.cpu.RDX == 0x1122334455667788 + + +class Test_CDQE_64_signed(Asm_Test_64): + MYSTRING = "test cdq 64 signed" + + def prepare(self): + self.myjit.ir_arch.symbol_pool.add_label("lbl_ret", self.ret_addr) + + def test_init(self): + self.myjit.cpu.RAX = 0x1234567887654321 + self.myjit.cpu.RDX = 0x1122334455667788 + + TXT = ''' + main: + CDQE + JMP lbl_ret + ''' + + def check(self): + assert self.myjit.cpu.RAX == 0xFFFFFFFF87654321 + assert self.myjit.cpu.RDX == 0x1122334455667788 + + +class Test_CWD_32(Asm_Test_32): + MYSTRING = "test cdq 32" + + def prepare(self): + self.myjit.ir_arch.symbol_pool.add_label("lbl_ret", self.ret_addr) + + def test_init(self): + self.myjit.cpu.EAX = 0x87654321 + self.myjit.cpu.EDX = 0x12345678 + + TXT = ''' + main: + CWD + JMP lbl_ret + ''' + + def check(self): + assert self.myjit.cpu.RAX == 0x87654321 + assert self.myjit.cpu.RDX == 0x12340000 + + +class Test_CWD_32_signed(Asm_Test_32): + MYSTRING = "test cdq 32" + + def prepare(self): + self.myjit.ir_arch.symbol_pool.add_label("lbl_ret", self.ret_addr) + + def test_init(self): + self.myjit.cpu.EAX = 0x87658321 + self.myjit.cpu.EDX = 0x12345678 + + TXT = ''' + main: + CWD + JMP lbl_ret + ''' + + def check(self): + assert self.myjit.cpu.RAX == 0x87658321 + assert self.myjit.cpu.RDX == 0x1234FFFF + + +class Test_CWD_32(Asm_Test_32): + MYSTRING = "test cdq 32" + + def prepare(self): + self.myjit.ir_arch.symbol_pool.add_label("lbl_ret", self.ret_addr) + + def test_init(self): + self.myjit.cpu.EAX = 0x87654321 + self.myjit.cpu.EDX = 0x12345678 + + TXT = ''' + main: + CWD + JMP lbl_ret + ''' + + def check(self): + assert self.myjit.cpu.RAX == 0x87654321 + assert self.myjit.cpu.RDX == 0x12340000 + + +class Test_CWDE_32(Asm_Test_32): + MYSTRING = "test cwde 32" + + def prepare(self): + self.myjit.ir_arch.symbol_pool.add_label("lbl_ret", self.ret_addr) + + def test_init(self): + self.myjit.cpu.EAX = 0x87654321 + self.myjit.cpu.EDX = 0x11223344 + + TXT = ''' + main: + CWDE + JMP lbl_ret + ''' + + def check(self): + assert self.myjit.cpu.RAX == 0x4321 + assert self.myjit.cpu.RDX == 0x11223344 + + +class Test_CWDE_32_signed(Asm_Test_32): + MYSTRING = "test cwde 32 signed" + + def prepare(self): + self.myjit.ir_arch.symbol_pool.add_label("lbl_ret", self.ret_addr) + + def test_init(self): + self.myjit.cpu.RAX = 0x87658321 + self.myjit.cpu.RDX = 0x11223344 + + TXT = ''' + main: + CWDE + JMP lbl_ret + ''' + + def check(self): + assert self.myjit.cpu.EAX == 0xFFFF8321 + assert self.myjit.cpu.RDX == 0x11223344 + + +class Test_CWDE_64(Asm_Test_64): + MYSTRING = "test cwde 64" + + def prepare(self): + self.myjit.ir_arch.symbol_pool.add_label("lbl_ret", self.ret_addr) + + def test_init(self): + self.myjit.cpu.RAX = 0x1234567887654321 + self.myjit.cpu.RDX = 0x1122334455667788 + + TXT = ''' + main: + CWDE + JMP lbl_ret + ''' + + def check(self): + assert self.myjit.cpu.RAX == 0x4321 + assert self.myjit.cpu.RDX == 0x1122334455667788 + + +class Test_CWDE_64_signed(Asm_Test_64): + MYSTRING = "test cwde 64 signed" + + def prepare(self): + self.myjit.ir_arch.symbol_pool.add_label("lbl_ret", self.ret_addr) + + def test_init(self): + self.myjit.cpu.RAX = 0x1234567887658321 + self.myjit.cpu.RDX = 0x1122334455667788 + + TXT = ''' + main: + CWDE + JMP lbl_ret + ''' + + def check(self): + assert self.myjit.cpu.RAX == 0xFFFF8321 + assert self.myjit.cpu.RDX == 0x1122334455667788 + + +class Test_CQO_64(Asm_Test_64): + MYSTRING = "test cwde 64" + + def prepare(self): + self.myjit.ir_arch.symbol_pool.add_label("lbl_ret", self.ret_addr) + + def test_init(self): + self.myjit.cpu.RAX = 0x1234567887654321 + self.myjit.cpu.RDX = 0x1122334455667788 + + TXT = ''' + main: + CQO + JMP lbl_ret + ''' + + def check(self): + assert self.myjit.cpu.RAX == 0x1234567887654321 + assert self.myjit.cpu.RDX == 0x0 + + +class Test_CQO_64_signed(Asm_Test_64): + MYSTRING = "test cwde 64 signed" + + def prepare(self): + self.myjit.ir_arch.symbol_pool.add_label("lbl_ret", self.ret_addr) + + def test_init(self): + self.myjit.cpu.RAX = 0x8234567887658321 + self.myjit.cpu.RDX = 0x1122334455667788 + + TXT = ''' + main: + CQO + JMP lbl_ret + ''' + + def check(self): + assert self.myjit.cpu.RAX == 0x8234567887658321 + assert self.myjit.cpu.RDX == 0xFFFFFFFFFFFFFFFF + + + + +if __name__ == "__main__": + tests = [ + Test_CBW_16, + Test_CBW_16_signed, + + Test_CBW_32, + Test_CBW_32_signed, + + Test_CWD_32, + Test_CWD_32_signed, + + Test_CWDE_32, + Test_CWDE_32_signed, + + Test_CWDE_64, + Test_CWDE_64_signed, + + Test_CDQ_32, + Test_CDQ_32_signed, + + Test_CDQ_64, + Test_CDQ_64_signed, + + Test_CDQE_64, + Test_CDQE_64_signed, + ] + if sys.argv[1] not in ["gcc", "tcc"]: + # TODO XXX CQO use 128 bit not supported in gcc yet! + tests += [ + Test_CQO_64, + Test_CQO_64_signed, + ] + + [ + test(*sys.argv[1:])() for test in tests + ] diff --git a/test/core/sembuilder.py b/test/core/sembuilder.py index d8fdb6c4..ebf9f385 100644 --- a/test/core/sembuilder.py +++ b/test/core/sembuilder.py @@ -8,7 +8,7 @@ from miasm2.core.asmblock import AsmLabel # Test classes class IR(object): - IRDst = m2_expr.ExprId("IRDst") + IRDst = m2_expr.ExprId("IRDst", 32) def get_next_instr(self, _): return AsmLabel("NEXT") @@ -41,9 +41,9 @@ def test(Arg1, Arg2, Arg3): else: alias = {i16(4), i8(5)} -a = m2_expr.ExprId('A') -b = m2_expr.ExprId('B') -c = m2_expr.ExprId('C') +a = m2_expr.ExprId('A', 32) +b = m2_expr.ExprId('B', 32) +c = m2_expr.ExprId('C', 32) ir = IR() instr = Instr() res = test(ir, instr, a, b, c) @@ -59,7 +59,7 @@ for statement in res[0]: print "[+] Blocks:" for irb in res[1]: print irb.label - for exprs in irb.irs: - for expr in exprs: + for assignblk in irb: + for expr in assignblk: print expr print diff --git a/test/expression/expression.py b/test/expression/expression.py index ac145a04..6bb6d94c 100644 --- a/test/expression/expression.py +++ b/test/expression/expression.py @@ -15,7 +15,7 @@ assert big_cst.size == 0x1000 # Possible values #- Common constants -A = ExprId("A") +A = ExprId("A", 32) cond1 = ExprId("cond1", 1) cond2 = ExprId("cond2", 16) cst1 = ExprInt(1, 32) diff --git a/test/expression/expression_helper.py b/test/expression/expression_helper.py index a4c221e9..35873ca4 100755 --- a/test/expression/expression_helper.py +++ b/test/expression/expression_helper.py @@ -12,8 +12,8 @@ class TestExpressionExpressionHelper(unittest.TestCase): # Build a complex expression cst = m2_expr.ExprInt(0x100, 16) - eax = m2_expr.ExprId("EAX") - ebx = m2_expr.ExprId("EBX") + eax = m2_expr.ExprId("EAX", 32) + ebx = m2_expr.ExprId("EBX", 32) ax = eax[0:16] expr = eax + ebx expr = m2_expr.ExprCompose(ax, expr[16:32]) diff --git a/test/expression/simplifications.py b/test/expression/simplifications.py index 6d17db10..b4f5b783 100644 --- a/test/expression/simplifications.py +++ b/test/expression/simplifications.py @@ -8,11 +8,11 @@ from miasm2.expression.simplifications import expr_simp, ExpressionSimplifier from miasm2.expression.simplifications_cond import ExprOp_inf_signed, ExprOp_inf_unsigned, ExprOp_equal # Define example objects -a = ExprId('a') -b = ExprId('b') -c = ExprId('c') -d = ExprId('d') -e = ExprId('e') +a = ExprId('a', 32) +b = ExprId('b', 32) +c = ExprId('c', 32) +d = ExprId('d', 32) +e = ExprId('e', 32) f = ExprId('f', size=64) m = ExprMem(a) @@ -382,17 +382,17 @@ for e, e_check in to_test[:]: -x = ExprId('x') -y = ExprId('y') -z = ExprId('z') -a = ExprId('a') -b = ExprId('b') -c = ExprId('c') +x = ExprId('x', 32) +y = ExprId('y', 32) +z = ExprId('z', 32) +a = ExprId('a', 32) +b = ExprId('b', 32) +c = ExprId('c', 32) -jra = ExprId('jra') -jrb = ExprId('jrb') -jrint1 = ExprId('jrint1') +jra = ExprId('jra', 32) +jrb = ExprId('jrb', 32) +jrint1 = ExprId('jrint1', 32) e1 = ExprMem((a & ExprInt(0xFFFFFFFC, 32)) + ExprInt(0x10, 32), 32) diff --git a/test/ir/ir.py b/test/ir/ir.py index 05936d75..3774e4e9 100644 --- a/test/ir/ir.py +++ b/test/ir/ir.py @@ -2,8 +2,8 @@ from miasm2.expression.expression import * from miasm2.ir.ir import AssignBlock from miasm2.expression.simplifications import expr_simp -id_a = ExprId("a") -id_b = ExprId("b") +id_a = ExprId("a", 32) +id_b = ExprId("b", 32) int0 = ExprInt(0, id_a.size) # Test AssignBlock diff --git a/test/ir/symbexec.py b/test/ir/symbexec.py index f8d8c7bf..492dcfec 100755 --- a/test/ir/symbexec.py +++ b/test/ir/symbexec.py @@ -30,10 +30,10 @@ class TestSymbExec(unittest.TestCase): mem40w = ExprMem(addr40, 16) mem50v = ExprMem(addr50, 8) mem50w = ExprMem(addr50, 16) - id_x = ExprId('x') + id_x = ExprId('x', 32) id_y = ExprId('y', 8) - id_a = ExprId('a') - id_eax = ExprId('eax_init') + id_a = ExprId('a', 32) + id_eax = ExprId('eax_init', 32) e = SymbolicExecutionEngine(ir_x86_32(), {mem0: id_x, mem1: id_y, mem9: id_x, diff --git a/test/test_all.py b/test/test_all.py index 23937366..04aca62e 100755 --- a/test/test_all.py +++ b/test/test_all.py @@ -79,6 +79,7 @@ for script in ["x86/sem.py", "x86/unit/mn_pextr.py", "x86/unit/mn_pmovmskb.py", "x86/unit/mn_pushpop.py", + "x86/unit/mn_cdq.py", "x86/unit/mn_seh.py", "x86/unit/mn_cpuid.py", "x86/unit/mn_div.py", |