From cc319cec629b452eb4e600cfb2b8aac3e8c81e3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20=E2=80=9CCLOVIS=E2=80=9D=20Canet?= Date: Wed, 13 Apr 2022 11:27:30 +0200 Subject: [PATCH 01/39] Import the Expr baseclass for Python Depends on https://github.com/serpilliere/miasm-rs/pull/72 --- miasm/expression/expression.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/miasm/expression/expression.py b/miasm/expression/expression.py index 58d0cefdc..c416c39f1 100644 --- a/miasm/expression/expression.py +++ b/miasm/expression/expression.py @@ -42,9 +42,8 @@ from miasm.core.graph import DiGraph from functools import reduce - from miasm_rs import ExprId, ExprInt, ExprLoc, ExprMem, \ - ExprSlice, ExprCond, ExprCompose, ExprOp, ExprAssign + ExprSlice, ExprCond, ExprCompose, ExprOp, ExprAssign, Expr # Define tokens From f2d09ccca152b46e7f677c7b679f4f6d03933e8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20=E2=80=9CCLOVIS=E2=80=9D=20Canet?= Date: Wed, 13 Apr 2022 16:05:20 +0200 Subject: [PATCH 02/39] DataFlow: updated to new syntax --- miasm/analysis/data_flow.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/miasm/analysis/data_flow.py b/miasm/analysis/data_flow.py index da2e1bece..f1f4b4aaf 100644 --- a/miasm/analysis/data_flow.py +++ b/miasm/analysis/data_flow.py @@ -243,7 +243,7 @@ def get_block_useful_destinations(self, block): for index, assignblk in enumerate(block): for lval, rval in viewitems(assignblk): if (lval.is_mem() or - self.ir_arch.IRDst == lval or + self.lifter.IRDst == lval or lval.is_id("exception_flags") or is_function_call(rval)): useful.add(AssignblkNode(block.loc_key, index, lval)) @@ -386,8 +386,8 @@ def do_dead_removal(self, ircfg): irs = [] for idx, assignblk in enumerate(block): new_assignblk = dict(assignblk) - for lval in assignblk: - if (AssignblkNode(block.loc_key, idx, lval) not in useful) or (lval == self.ir_arch.pc): + for (lval, _) in assignblk: + if (AssignblkNode(block.loc_key, idx, lval) not in useful) or (lval == self.lifter.pc): del new_assignblk[lval] modified = True irs.append(AssignBlock(new_assignblk, assignblk.instr)) From 001d351db548a867ccf6cc32fcb70674414f369f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20=E2=80=9CCLOVIS=E2=80=9D=20Canet?= Date: Wed, 13 Apr 2022 16:06:15 +0200 Subject: [PATCH 03/39] IR: updated to new syntax --- miasm/ir/ir.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/miasm/ir/ir.py b/miasm/ir/ir.py index 0b36854d8..9443feae9 100644 --- a/miasm/ir/ir.py +++ b/miasm/ir/ir.py @@ -128,18 +128,18 @@ def from_ExprCond(self, expr): return out def from_ExprOp(self, expr): - op = ESCAPE_CHARS.sub(self._fix_chars, expr._op) - if expr._op == '-': # Unary minus - return '-' + self.str_protected_child(expr._args[0], expr) + op = ESCAPE_CHARS.sub(self._fix_chars, expr.op) + if expr.op == '-': # Unary minus + return '-' + self.str_protected_child(expr.args[0], expr) if expr.is_associative() or expr.is_infix(): return (' ' + op + ' ').join([self.str_protected_child(arg, expr) - for arg in expr._args]) + for arg in expr.args]) op = '%s' % (utils.COLOR_OP_FUNC, op) return (op + '(' + ', '.join( self.from_expr(arg) - for arg in expr._args + for arg in expr.args ) + ')') def from_ExprAssign(self, expr): From c9220fda2016b64d75b93df6fbbe1e231cfc729f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20=E2=80=9CCLOVIS=E2=80=9D=20Canet?= Date: Thu, 14 Apr 2022 08:49:11 +0200 Subject: [PATCH 04/39] DataFlow: refactor to use the is_unkillable_destination function --- miasm/analysis/data_flow.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/miasm/analysis/data_flow.py b/miasm/analysis/data_flow.py index f1f4b4aaf..c5e1a2c53 100644 --- a/miasm/analysis/data_flow.py +++ b/miasm/analysis/data_flow.py @@ -242,10 +242,7 @@ def get_block_useful_destinations(self, block): useful = set() for index, assignblk in enumerate(block): for lval, rval in viewitems(assignblk): - if (lval.is_mem() or - self.lifter.IRDst == lval or - lval.is_id("exception_flags") or - is_function_call(rval)): + if self.is_unkillable_destination(lval, rval): useful.add(AssignblkNode(block.loc_key, index, lval)) return useful From 7e7ada61f9f45b68393417f3e89175023e017a8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20=E2=80=9CCLOVIS=E2=80=9D=20Canet?= Date: Thu, 14 Apr 2022 10:34:37 +0200 Subject: [PATCH 05/39] DataFlow: updated to new syntax --- miasm/analysis/data_flow.py | 37 +++++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/miasm/analysis/data_flow.py b/miasm/analysis/data_flow.py index c5e1a2c53..285b66db0 100644 --- a/miasm/analysis/data_flow.py +++ b/miasm/analysis/data_flow.py @@ -1,15 +1,16 @@ """Data flow analysis based on miasm intermediate representation""" -from builtins import range from collections import namedtuple, Counter -from pprint import pprint as pp +from typing import Any, Dict, Set, Tuple, Type + from future.utils import viewitems, viewvalues from miasm.core.utils import encode_hex from miasm.core.graph import DiGraph -from miasm.ir.ir import AssignBlock, IRBlock +from miasm.ir.ir import AssignBlock, IRBlock, IRCFG from miasm.expression.expression import ExprLoc, ExprMem, ExprId, ExprInt,\ - ExprAssign, ExprOp, ExprWalk, ExprSlice, \ + ExprAssign, ExprOp, ExprWalk, Expr, \ is_function_call, ExprVisitorCallbackBottomToTop from miasm.expression.simplifications import expr_simp, expr_simp_explicit +from miasm.core.locationdb import LocKey from miasm.core.interval import interval from miasm.expression.expression_helper import possible_values @@ -18,6 +19,7 @@ from miasm.ir.symbexec import get_expr_base_offset from collections import deque + class ReachingDefinitions(dict): """ Computes for each assignblock the set of reaching definitions. @@ -46,11 +48,13 @@ class ReachingDefinitions(dict): ircfg = None def __init__(self, ircfg): + # type: (IRCFG) -> None super(ReachingDefinitions, self).__init__() self.ircfg = ircfg self.compute() def get_definitions(self, block_lbl, assignblk_index): + # type: (LocKey, int) -> Dict[ExprAssign, Set[Tuple[LocKey, int]]] """Returns the dict { lvalue: set((def_block_lbl, def_index)) } associated with self.ircfg.@block.assignblks[@assignblk_index] or {} if it is not yet computed @@ -66,6 +70,7 @@ def compute(self): modified |= self.process_block(block) def process_block(self, block): + # type: (IRBlock) -> bool """ Fetch reach definitions from predecessors and propagate it to the assignblk in block @block. @@ -88,6 +93,7 @@ def process_block(self, block): return modified def process_assignblock(self, block, assignblk_index): + # type: (IRBlock, int) -> bool """ Updates the reach definitions with values defined at assignblock @assignblk_index in block @block. @@ -95,9 +101,9 @@ def process_assignblock(self, block, assignblk_index): (@block, @assignblk_index + 1). """ - assignblk = block[assignblk_index] + assignblk = block[assignblk_index] # type: AssignBlock defs = self.get_definitions(block.loc_key, assignblk_index).copy() - for lval in assignblk: + for lval in assignblk.keys(): defs.update({lval: set([(block.loc_key, assignblk_index)])}) modified = self.get((block.loc_key, assignblk_index + 1)) != defs @@ -132,12 +138,10 @@ class DiGraphDefUse(DiGraph): """ - def __init__(self, reaching_defs, deref_mem=False, apply_simp=False, *args, **kwargs): - """Instantiate a DiGraph - @blocks: IR blocks - """ + # type: (ReachingDefinitions, bool, bool, *Any, **Any) -> None + """Instantiate a DiGraph""" self._edge_attr = {} # For dot display @@ -160,6 +164,7 @@ def edge_attr(self, src, dst): def _compute_def_use(self, reaching_defs, deref_mem=False, apply_simp=False): + # type: (ReachingDefinitions, bool, bool) -> None for block in viewvalues(self._blocks): self._compute_def_use_block(block, reaching_defs, @@ -167,6 +172,7 @@ def _compute_def_use(self, reaching_defs, apply_simp=apply_simp) def _compute_def_use_block(self, block, reaching_defs, deref_mem=False, apply_simp=False): + # type: (IRBlock, ReachingDefinitions, bool, bool) -> None for index, assignblk in enumerate(block): assignblk_reaching_defs = reaching_defs.get_definitions(block.loc_key, index) for lval, expr in viewitems(assignblk): @@ -316,6 +322,7 @@ def add_def_for_incomplete_leaf(self, block, ircfg, reaching_defs): return useful def get_useful_assignments(self, ircfg, defuse, reaching_defs): + # type: (IRCFG, DiGraphDefUse, ReachingDefinitions) -> Set[Tuple[int, LocKey, Expr]] """ Mark useful statements using previous reach analysis and defuse @@ -336,7 +343,6 @@ def get_useful_assignments(self, ircfg, defuse, reaching_defs): block_useful = self.get_block_useful_destinations(block) useful.update(block_useful) - successors = ircfg.successors(block_lbl) for successor in successors: if successor not in ircfg.blocks: @@ -362,16 +368,17 @@ def get_useful_assignments(self, ircfg, defuse, reaching_defs): yield parent def do_dead_removal(self, ircfg): + # type: (IRCFG) -> bool """ Remove useless assignments. - This function is used to analyse relation of a * complete function * + 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 - @ircfg: Lifter instance + :param ircfg: Lifter instance """ modified = False @@ -383,7 +390,7 @@ def do_dead_removal(self, ircfg): irs = [] for idx, assignblk in enumerate(block): new_assignblk = dict(assignblk) - for (lval, _) in assignblk: + for lval in assignblk.keys(): if (AssignblkNode(block.loc_key, idx, lval) not in useful) or (lval == self.lifter.pc): del new_assignblk[lval] modified = True @@ -392,6 +399,8 @@ def do_dead_removal(self, ircfg): return modified def __call__(self, ircfg): + # type: (IRCFG) -> bool + """Convenience method to call `do_dead_removal`.""" ret = self.do_dead_removal(ircfg) return ret From f4f41685fb684b86aa45a59fc3ac5606c8d6cc49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20=E2=80=9CCLOVIS=E2=80=9D=20Canet?= Date: Thu, 14 Apr 2022 10:36:18 +0200 Subject: [PATCH 06/39] IR: type hints --- miasm/ir/ir.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/miasm/ir/ir.py b/miasm/ir/ir.py index 9443feae9..6449f37b0 100644 --- a/miasm/ir/ir.py +++ b/miasm/ir/ir.py @@ -17,22 +17,20 @@ # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # -from builtins import zip import warnings +from typing import Dict, Set -from itertools import chain from future.utils import viewvalues, viewitems import miasm.expression.expression as m2_expr -from miasm.expression.expression_helper import get_missing_interval from miasm.core.asmblock import AsmBlock, AsmBlockBad, AsmConstraint from miasm.core.graph import DiGraph from miasm.ir.translators import Translator -from functools import reduce from miasm.core import utils import re from miasm_rs import IRBlock from miasm_rs import AssignBlock +from miasm.core.locationdb import LocKey def _expr_loc_to_symb(expr, loc_db): if not expr.is_loc(): @@ -194,6 +192,7 @@ def IRDst(self): @property def blocks(self): + # type: () -> Dict[LocKey, IRBlock] return self._blocks def add_irblock(self, irblock): @@ -304,6 +303,7 @@ def get_block(self, addr): return self.blocks.get(loc_key, None) def getby_offset(self, offset): + # type: (int) -> Set[IRBlock] """ Return the set of loc_keys of irblocks containing @offset @offset: address From 0086cee6d5242248091c3ccbf0e24a6603418c9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20=E2=80=9CCLOVIS=E2=80=9D=20Canet?= Date: Thu, 14 Apr 2022 10:36:36 +0200 Subject: [PATCH 07/39] LocationDB: do not warn about unused import --- miasm/core/locationdb.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/miasm/core/locationdb.py b/miasm/core/locationdb.py index b9742f178..bdc320a37 100644 --- a/miasm/core/locationdb.py +++ b/miasm/core/locationdb.py @@ -1,2 +1,2 @@ +# noinspection PyUnresolvedReferences from miasm_rs import LocKey, ExprLoc, LocationDB - From ddd6a6cf322f88bcf92655d382c9441cb2c2c19b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20=E2=80=9CCLOVIS=E2=80=9D=20Canet?= Date: Fri, 15 Apr 2022 09:29:07 +0200 Subject: [PATCH 08/39] x86: updated to new syntax --- miasm/arch/x86/arch.py | 11 ++++------- miasm/arch/x86/sem.py | 26 +++++++++++++------------- 2 files changed, 17 insertions(+), 20 deletions(-) diff --git a/miasm/arch/x86/arch.py b/miasm/arch/x86/arch.py index ed0500c91..36fee990b 100644 --- a/miasm/arch/x86/arch.py +++ b/miasm/arch/x86/arch.py @@ -1,12 +1,7 @@ -#-*- coding:utf-8 -*- - from __future__ import print_function -from builtins import range -import re -from future.utils import viewitems +from typing import Tuple -from miasm.core import utils from miasm.expression.expression import * from pyparsing import * from miasm.core.cpu import * @@ -548,7 +543,8 @@ def fixDstOffset(self): if not isinstance(expr, ExprInt): log.warning('dynamic dst %r', expr) return - self.args[0] = ExprInt(int(expr) - self.offset, self.mode) + value = int(expr) - self.offset + self.args[0] = ExprInt(value, self.mode) if value > 0 else -ExprInt(-value, self.mode) def get_info(self, c): self.additional_info.g1.value = c.g1.value @@ -769,6 +765,7 @@ def fromstring(cls, text, loc_db, mode): @classmethod def pre_dis(cls, v, mode, offset): + # type: (BinStream, int, int) -> Tuple[Dict, BinStream, int, int, int] offset_o = offset pre_dis_info = {'opmode': 0, 'admode': 0, diff --git a/miasm/arch/x86/sem.py b/miasm/arch/x86/sem.py index ffa2641c0..6700691cc 100644 --- a/miasm/arch/x86/sem.py +++ b/miasm/arch/x86/sem.py @@ -189,7 +189,7 @@ def check_ops_msb(a, b, c): def arith_flag(a, b, c): a_s, b_s, c_s = a.size, b.size, c.size check_ops_msb(a_s, b_s, c_s) - a_s, b_s, c_s = a.msb(), b.msb(), c.msb() + a_s, b_s, c_s = a.msb, b.msb, c.msb return a_s, b_s, c_s # checked: ok for adc add because b & c before +cf @@ -635,12 +635,12 @@ def _rotate_tpl(ir, instr, dst, src, op, left=False): # CF is computed with 1-less round than `res` new_cf = m2_expr.ExprOp( op, dst, shifter - m2_expr.ExprInt(1, size=shifter.size)) - new_cf = new_cf.msb() if left else new_cf[:1] + new_cf = new_cf.msb if left else new_cf[:1] # OF is defined only for @b == 1 new_of = m2_expr.ExprCond(src - m2_expr.ExprInt(1, size=src.size), m2_expr.ExprInt(0, size=of.size), - res.msb() ^ new_cf if left else (dst ^ res).msb()) + res.msb ^ new_cf if left else (dst ^ res).msb) # Build basic blocks e_do = [m2_expr.ExprAssign(cf, new_cf), @@ -687,9 +687,9 @@ def rotate_with_carry_tpl(ir, instr, op, dst, src): result_trunc = result[:dst.size] if op == '<<<': - of_value = result_trunc.msb() ^ new_cf + of_value = result_trunc.msb ^ new_cf else: - of_value = (dst ^ result_trunc).msb() + of_value = (dst ^ result_trunc).msb # OF is defined only for @b == 1 new_of = m2_expr.ExprCond(src - m2_expr.ExprInt(1, size=src.size), m2_expr.ExprInt(0, size=of.size), @@ -741,7 +741,7 @@ def _shift_tpl(op, ir, instr, a, b, c=None, op_inv=None, left=False, res = m2_expr.ExprOp(op, a, shifter) cf_from_dst = m2_expr.ExprOp(op, a, (shifter - m2_expr.ExprInt(1, a.size))) - cf_from_dst = cf_from_dst.msb() if left else cf_from_dst[:1] + cf_from_dst = cf_from_dst.msb if left else cf_from_dst[:1] new_cf = cf_from_dst i1 = m2_expr.ExprInt(1, size=a.size) @@ -769,12 +769,12 @@ def _shift_tpl(op, ir, instr, a, b, c=None, op_inv=None, left=False, cf_from_src = m2_expr.ExprOp(op, b, (shifter.zeroExtend(b.size) & m2_expr.ExprInt(a.size - 1, b.size)) - i1) - cf_from_src = cf_from_src.msb() if left else cf_from_src[:1] + cf_from_src = cf_from_src.msb if left else cf_from_src[:1] new_cf = m2_expr.ExprCond(cond_overflow, cf_from_src, cf_from_dst) # Overflow flag, only occurred when shifter is equal to 1 if custom_of is None: - value_of = a.msb() ^ a[-2:-1] if left else b[:1] ^ a.msb() + value_of = a.msb ^ a[-2:-1] if left else b[:1] ^ a.msb else: value_of = custom_of @@ -816,7 +816,7 @@ def sar(ir, instr, dst, src): def shr(ir, instr, dst, src): - return _shift_tpl(">>", ir, instr, dst, src, custom_of=dst.msb()) + return _shift_tpl(">>", ir, instr, dst, src, custom_of=dst.msb) def shrd(ir, instr, dst, src1, src2): @@ -2210,7 +2210,7 @@ def fxam(ir, instr): ) ) base = [m2_expr.ExprAssign(ir.IRDst, irdst), - m2_expr.ExprAssign(float_c1, dst.msb()) + m2_expr.ExprAssign(float_c1, dst.msb) ] base += set_float_cs_eip(instr) @@ -3218,7 +3218,7 @@ def _tpl_aaa(_, instr, op): i1 = m2_expr.ExprInt(1, 1) # cond: if (al & 0xf) > 9 OR af == 1 cond = (r_al & m2_expr.ExprInt(0xf, 8)) - m2_expr.ExprInt(9, 8) - cond = ~cond.msb() & m2_expr.ExprCond(cond, i1, i0) + cond = ~cond.msb & m2_expr.ExprCond(cond, i1, i0) cond |= af & i1 to_add = m2_expr.ExprInt(0x106, size=r_ax.size) @@ -3934,7 +3934,7 @@ def pmaddwd(ir, instr, dst, src): def _absolute(expr): """Return abs(@expr)""" - signed = expr.msb() + signed = expr.msb value_unsigned = (expr ^ expr.mask) + m2_expr.ExprInt(1, expr.size) return m2_expr.ExprCond(signed, value_unsigned, expr) @@ -4930,7 +4930,7 @@ def _saturation_add(expr): # 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), + return m2_expr.ExprCond((arg1 + arg2).msb, m2_expr.ExprInt(-1, expr.size), expr) def _saturation_add_signed(expr): From 884e42fd1742254c3b6d6aa563ca0b8e97e3b7cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20=E2=80=9CCLOVIS=E2=80=9D=20Canet?= Date: Tue, 19 Apr 2022 13:57:25 +0200 Subject: [PATCH 09/39] Binary: generate the BinStream via the Rust implementation of Container --- miasm/analysis/binary.py | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/miasm/analysis/binary.py b/miasm/analysis/binary.py index 043bfeb60..3fce83c86 100644 --- a/miasm/analysis/binary.py +++ b/miasm/analysis/binary.py @@ -3,7 +3,7 @@ from miasm.core.bin_stream import bin_stream_str, bin_stream_elf, bin_stream_pe from miasm.jitter.csts import PAGE_READ -from miasm_rs import Memory +from miasm_rs import Memory, Container as ContainerRS log = logging.getLogger("binary") console_handler = logging.StreamHandler() @@ -152,15 +152,12 @@ def parse(self, data, vm=None, **kwargs): self._arch = guess_arch(self._executable) # Build the bin_stream instance and set the entry point - if True:#try: - #self._bin_stream = bin_stream_pe(self._executable) - memory = Memory() - memory.from_buffer(data) - self._bin_stream = memory.get_binstream() + try: + self._bin_stream = ContainerRS.from_buffer(data).memory.get_binstream() ep_detected = self._executable.Opthdr.AddressOfEntryPoint self._entry_point = self._executable.rva2virt(ep_detected) - #except Exception as error: - # raise ContainerParsingException('Cannot read PE: %s' % error) + except Exception as error: + raise ContainerParsingException('Cannot read PE: %s' % error) class ContainerELF(Container): @@ -204,9 +201,7 @@ def parse(self, data, vm=None, addr=0, apply_reloc=False, **kwargs): # Build the bin_stream instance and set the entry point try: - memory = Memory() - memory.from_buffer(data) - self._bin_stream = memory.get_binstream() + self._bin_stream = ContainerRS.from_buffer(data).memory.get_binstream() self._entry_point = self._executable.Ehdr.entry + addr except Exception as error: From a60eb90632ebac2c8fc18cf71eae4ae8def2bc87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20=E2=80=9CCLOVIS=E2=80=9D=20Canet?= Date: Wed, 20 Apr 2022 09:18:11 +0200 Subject: [PATCH 10/39] ASM: Added repr for AsmBlockBad --- miasm/core/asmblock.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/miasm/core/asmblock.py b/miasm/core/asmblock.py index 3145aded4..bdc04cd1a 100644 --- a/miasm/core/asmblock.py +++ b/miasm/core/asmblock.py @@ -286,6 +286,9 @@ def __str__(self): error_txt ) + def __repr__(self): + return "" % (self.loc_key, self.ERROR_TYPES.get(self._errno, self._errno)) + def is_bad(self): """ Return True is block is AsmBlockBad From bc65cf2fced52d9bf7e5895cc1c3b7504832a2f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20=E2=80=9CCLOVIS=E2=80=9D=20Canet?= Date: Wed, 20 Apr 2022 09:18:57 +0200 Subject: [PATCH 11/39] ASM: Type hints --- miasm/core/asmblock.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/miasm/core/asmblock.py b/miasm/core/asmblock.py index bdc04cd1a..fa5ed1590 100644 --- a/miasm/core/asmblock.py +++ b/miasm/core/asmblock.py @@ -345,6 +345,7 @@ def __len__(self): @property def blocks(self): + # type: () -> Iterable[AsmBlock] return viewvalues(self._loc_key_to_block) # Manage graph with associated constraints @@ -1233,6 +1234,7 @@ def __init__(self, arch, attrib, bin_stream, loc_db, **kwargs): self.__dict__.update(kwargs) def _dis_block(self, offset, job_done=None): + # type: (int, Optional[Set]) -> AsmBlock """Disassemble the block at offset @offset @job_done: a set of already disassembled addresses Return the created AsmBlock and future offsets to disassemble @@ -1378,6 +1380,7 @@ def dis_block(self, offset): return current_block def dis_multiblock(self, offset, blocks=None, job_done=None): + # type: (int, Optional[AsmBlock], Optional[Set]) -> AsmCFG """Disassemble every block reachable from @offset regarding specific disasmEngine conditions Return an AsmCFG instance containing disassembled blocks From f12c62f5497525b180bd73b05ed305ee3af7343c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20=E2=80=9CCLOVIS=E2=80=9D=20Canet?= Date: Wed, 20 Apr 2022 09:19:41 +0200 Subject: [PATCH 12/39] CPU: Type hints --- miasm/core/cpu.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/miasm/core/cpu.py b/miasm/core/cpu.py index 124876707..91299eda3 100644 --- a/miasm/core/cpu.py +++ b/miasm/core/cpu.py @@ -1,11 +1,10 @@ -#-*- coding:utf-8 -*- - +from ast import Bytes from builtins import range import re import struct import logging from collections import defaultdict - +from typing import List, Optional as Option, Set, Dict from future.utils import viewitems, viewvalues @@ -1080,8 +1079,7 @@ class cls_mn(with_metaclass(metamn, object)): @classmethod def guess_mnemo(cls, bs, attrib, pre_dis_info, offset): - candidates = [] - + # type: (BinStream, int, Dict, int) -> Set[Bytes] candidates = set() fname_values = pre_dis_info @@ -1111,7 +1109,7 @@ def guess_mnemo(cls, bs, attrib, pre_dis_info, offset): else: todo.append((dict(fname_values), (nb, v), offset, offset_bit)) - return [c for c in candidates] + return candidates def reset_class(self): for f in self.fields_order: @@ -1176,7 +1174,9 @@ def mod_fields(cls, fields): return fields @classmethod - def dis(cls, bs_o, mode_o = None, offset=0): + def dis(cls, bs_o, mode_o=None, offset=0): + # type: (BinStream, Option[int], int) -> List + assert isinstance(bs_o, BinStream) #if not isinstance(bs_o, bin_stream): # bs_o = bin_stream_str(bs_o) From 70ea6ad32357043d7c95a3203fd70fef782825fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20=E2=80=9CCLOVIS=E2=80=9D=20Canet?= Date: Wed, 20 Apr 2022 09:20:57 +0200 Subject: [PATCH 13/39] DSE: Type hints --- miasm/analysis/dse.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/miasm/analysis/dse.py b/miasm/analysis/dse.py index 5e6c4e8d9..1ead9e39d 100644 --- a/miasm/analysis/dse.py +++ b/miasm/analysis/dse.py @@ -47,7 +47,6 @@ the solver for reducing the possible values thanks to its accumulated constraints. """ -from builtins import range from collections import namedtuple import warnings @@ -59,6 +58,7 @@ from future.utils import viewitems from miasm.core.utils import encode_hex, force_bytes +from miasm.core.locationdb import LocationDB from miasm.expression.expression import ExprMem, ExprInt, ExprCompose, \ ExprAssign, ExprId, ExprLoc, LocKey, canonize_to_exprloc from miasm.core.bin_stream import bin_stream_vm @@ -67,6 +67,7 @@ from miasm.ir.translators import Translator from miasm.analysis.expression_range import expr_range from miasm.analysis.modularintervals import ModularIntervals +from miasm.analysis.machine import Machine DriftInfo = namedtuple("DriftInfo", ["symbol", "computed", "expected"]) @@ -163,6 +164,7 @@ class DSEEngine(object): SYMB_ENGINE = ESETrackModif def __init__(self, machine, loc_db): + # type: (Machine, LocationDB) -> None self.machine = machine self.loc_db = loc_db self.handler = {} # addr -> callback(DSEEngine instance) From c45b3c730bf5742ddaae4db3e18b6937af177816 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20=E2=80=9CCLOVIS=E2=80=9D=20Canet?= Date: Wed, 20 Apr 2022 09:22:00 +0200 Subject: [PATCH 14/39] IR: updated to new syntax --- miasm/ir/ir.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/miasm/ir/ir.py b/miasm/ir/ir.py index 6449f37b0..6db57b17c 100644 --- a/miasm/ir/ir.py +++ b/miasm/ir/ir.py @@ -434,7 +434,7 @@ def instr2ir(self, instr): for assignblk in irb: irs.append(AssignBlock(assignblk, instr)) extra_irblocks[index] = IRBlock(self.loc_db, irb.loc_key, irs) - assignblk = AssignBlock(ir_bloc_cur, instr) + assignblk = AssignBlock(ir_bloc_cur, str(instr)) return assignblk, extra_irblocks def add_instr_to_ircfg(self, instr, ircfg, loc_key=None, gen_pc_updt=False): From 1d544418ecc86eaf87205f6da4130e8239970492 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20=E2=80=9CCLOVIS=E2=80=9D=20Canet?= Date: Wed, 20 Apr 2022 09:22:16 +0200 Subject: [PATCH 15/39] Machine: Type hints --- miasm/analysis/machine.py | 1 + 1 file changed, 1 insertion(+) diff --git a/miasm/analysis/machine.py b/miasm/analysis/machine.py index cc86d7533..8154c38f2 100644 --- a/miasm/analysis/machine.py +++ b/miasm/analysis/machine.py @@ -17,6 +17,7 @@ class Machine(object): def __init__(self, machine_name): + # type: (str) -> None dis_engine = None mn = None From 48f70751e9a28f92d6ab0ba903ba3ac397b74882 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20=E2=80=9CCLOVIS=E2=80=9D=20Canet?= Date: Wed, 20 Apr 2022 15:57:52 +0200 Subject: [PATCH 16/39] Expression: updated to new syntax --- miasm/expression/expression.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/miasm/expression/expression.py b/miasm/expression/expression.py index c416c39f1..f91ed0b8b 100644 --- a/miasm/expression/expression.py +++ b/miasm/expression/expression.py @@ -828,7 +828,7 @@ def _expr_compute_cf(op1, op2): @op2: Expression """ res = op1 - op2 - cf = (((op1 ^ op2) ^ res) ^ ((op1 ^ res) & (op1 ^ op2))).msb() + cf = (((op1 ^ op2) ^ res) ^ ((op1 ^ res) & (op1 ^ op2))).msb return cf def _expr_compute_of(op1, op2): @@ -839,7 +839,7 @@ def _expr_compute_of(op1, op2): @op2: Expression """ res = op1 - op2 - of = (((op1 ^ res) & (op1 ^ op2))).msb() + of = (((op1 ^ res) & (op1 ^ op2))).msb return of def _expr_compute_zf(op1, op2): @@ -862,7 +862,7 @@ def _expr_compute_nf(op1, op2): @op2: Expression """ res = op1 - op2 - nf = res.msb() + nf = res.msb return nf From 081bb98e7a50e0b63ceb610b0facdbcd54b51fae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20=E2=80=9CCLOVIS=E2=80=9D=20Canet?= Date: Thu, 21 Apr 2022 09:41:58 +0200 Subject: [PATCH 17/39] Simplifications: updated to new syntax --- miasm/expression/simplifications_common.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/miasm/expression/simplifications_common.py b/miasm/expression/simplifications_common.py index b6d653904..7caafe5d8 100644 --- a/miasm/expression/simplifications_common.py +++ b/miasm/expression/simplifications_common.py @@ -260,8 +260,8 @@ def simp_cst_propagation(e_s, expr): args[0].is_op(op_name)): X = args[0].args[1] Y = args[1] - if (e_s(X.msb()) == ExprInt(0, 1) and - e_s(Y.msb()) == ExprInt(0, 1)): + if (e_s(X.msb) == ExprInt(0, 1) and + e_s(Y.msb) == ExprInt(0, 1)): args = [args[0].args[0], X + Y] # ((var >> int1) << int1) => var & mask @@ -658,7 +658,7 @@ def simp_cond(_, expr): # a|int ? b:c => b with int != 0 elif (expr.cond.is_op('|') and expr.cond.args[1].is_int() and - expr.cond.args[1].arg != 0): + int(expr.cond.args[1]) != 0): return expr.src1 # (C?int1:int2)?(A:B) => From 737d9aa76c87905f3b2a51a778f2a464ee59acde Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20=E2=80=9CCLOVIS=E2=80=9D=20Canet?= Date: Thu, 21 Apr 2022 10:02:57 +0200 Subject: [PATCH 18/39] Z3: Better error message for invalid endianness --- miasm/ir/translators/z3_ir.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/miasm/ir/translators/z3_ir.py b/miasm/ir/translators/z3_ir.py index 4b674c4e3..d7514781b 100644 --- a/miasm/ir/translators/z3_ir.py +++ b/miasm/ir/translators/z3_ir.py @@ -38,7 +38,7 @@ def __init__(self, endianness="<", name="mem"): import z3 if endianness not in ['<', '>']: - raise ValueError("Endianness should be '>' (big) or '<' (little)") + raise ValueError("Endianness should be '>' (big) or '<' (little), found: " + repr(endianness)) self.endianness = endianness self.mems = {} # Address size -> memory z3.Array self.name = name From 9e1ff315825536618cec085f26a1c55d3f051a2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20=E2=80=9CCLOVIS=E2=80=9D=20Canet?= Date: Thu, 21 Apr 2022 14:03:04 +0200 Subject: [PATCH 19/39] =?UTF-8?q?Fixed=20=E2=80=98getbits=E2=80=99=20in=20?= =?UTF-8?q?all=20architectures?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- miasm/arch/aarch64/arch.py | 32 ++++++++++++++++---------------- miasm/arch/arm/arch.py | 30 +++++++++++++++--------------- miasm/arch/mep/arch.py | 11 ++++++----- miasm/arch/mips32/arch.py | 13 +++++++------ miasm/arch/msp430/arch.py | 15 +++++++-------- miasm/arch/ppc/arch.py | 14 +++++++------- miasm/arch/sh4/arch.py | 14 +++++++------- 7 files changed, 65 insertions(+), 64 deletions(-) diff --git a/miasm/arch/aarch64/arch.py b/miasm/arch/aarch64/arch.py index 7df74b7ec..8f447dd9c 100644 --- a/miasm/arch/aarch64/arch.py +++ b/miasm/arch/aarch64/arch.py @@ -524,13 +524,13 @@ def additional_info(self): return info @classmethod - def getbits(cls, bs, attrib, start, n): - if not n: + def getbits(cls, bs, attrib, offset, offset_bit, size): + if not size: return 0 + + start = offset * 8 + offset_bit o = 0 - if n > bs.getlen() * 8: - raise ValueError('not enough bits %r %r' % (n, len(bs.bin) * 8)) - while n: + while size: offset = start // 8 n_offset = cls.endian_offset(attrib, offset) c = cls.getbytes(bs, n_offset, 1) @@ -539,11 +539,11 @@ def getbits(cls, bs, attrib, start, n): c = ord(c) r = 8 - start % 8 c &= (1 << r) - 1 - l = min(r, n) + l = min(r, size) c >>= (r - l) o <<= l o |= c - n -= l + size -= l start += l return o @@ -612,7 +612,7 @@ def decode(self, v): return True def encode(self): - if not test_set_sf(self.parent, self.expr.size): + if not check_set_sf(self.parent, self.expr.size): return False if not self.expr.size in self.gpregs_info: return False @@ -633,7 +633,7 @@ def decode(self, v): return True def encode(self): - if not test_set_sf(self.parent, self.expr.size): + if not check_set_sf(self.parent, self.expr.size): return False if not self.expr.size in self.gpregs_info: return False @@ -754,7 +754,7 @@ def encode(self): return False if not self.expr.size in self.gpregs_info: return False - if not test_set_sf(self.parent, self.expr.size): + if not check_set_sf(self.parent, self.expr.size): return False if not self.expr in self.gpregs_info[self.expr.size].expr: return False @@ -925,7 +925,7 @@ def fromstring(self, text, loc_db, parser_result=None): def encode(self): if not isinstance(self.expr, m2_expr.ExprInt): return False - if not test_set_sf(self.parent, self.expr.size): + if not check_set_sf(self.parent, self.expr.size): return False value = int(self.expr) if value >= 1 << self.l: @@ -944,7 +944,7 @@ class aarch64_imm_sft(aarch64_imm_sf, aarch64_arg): def encode(self): if not isinstance(self.expr, m2_expr.ExprInt): return False - if not test_set_sf(self.parent, self.expr.size): + if not check_set_sf(self.parent, self.expr.size): return False value = int(self.expr) if value < 1 << self.l: @@ -988,7 +988,7 @@ def encode(self): self.value = gpregsz_info[self.expr.size].expr.index(reg) option = extend_lst.index(self.expr.op) if self.expr.size != OPTION2SIZE[option]: - if not test_set_sf(self.parent, self.expr.size): + if not check_set_sf(self.parent, self.expr.size): return False self.parent.option.value = option self.parent.imm.value = int(amount) @@ -1099,7 +1099,7 @@ def get_size(self): return 4 -def test_set_sf(parent, size): +def check_set_sf(parent, size): if not hasattr(parent, 'sf'): return False if parent.sf.value == None: @@ -1115,7 +1115,7 @@ class aarch64_gpreg_sftimm(reg_noarg, aarch64_arg): def encode(self): size = self.expr.size - if not test_set_sf(self.parent, size): + if not check_set_sf(self.parent, size): return False if isinstance(self.expr, m2_expr.ExprId): if not size in gpregs_info: @@ -1376,7 +1376,7 @@ def decode(self, v): def encode(self): if not isinstance(self.expr, m2_expr.ExprInt): return False - if not test_set_sf(self.parent, self.expr.size): + if not check_set_sf(self.parent, self.expr.size): return False value = int(self.expr) if value == 0: diff --git a/miasm/arch/arm/arch.py b/miasm/arch/arm/arch.py index 9e612d96e..dd034a522 100644 --- a/miasm/arch/arm/arch.py +++ b/miasm/arch/arm/arch.py @@ -690,13 +690,13 @@ def additional_info(self): return info @classmethod - def getbits(cls, bs, attrib, start, n): - if not n: + def getbits(cls, bs, attrib, offset, offset_bit, size): + if not size: return 0 + o = 0 - if n > bs.getlen() * 8: - raise ValueError('not enough bits %r %r' % (n, len(bs.bin) * 8)) - while n: + start = offset * 8 + offset_bit + while size: offset = start // 8 n_offset = cls.endian_offset(attrib, offset) c = cls.getbytes(bs, n_offset, 1) @@ -705,11 +705,11 @@ def getbits(cls, bs, attrib, start, n): c = ord(c) r = 8 - start % 8 c &= (1 << r) - 1 - l = min(r, n) + l = min(r, size) c >>= (r - l) o <<= l o |= c - n -= l + size -= l start += l return o @@ -791,26 +791,26 @@ def additional_info(self): @classmethod - def getbits(cls, bs, attrib, start, n): - if not n: + def getbits(cls, bs, attrib, offset, offset_bits, size): + if not size: return 0 + + start = offset * 8 + offset_bits o = 0 - if n > bs.getlen() * 8: - raise ValueError('not enough bits %r %r' % (n, len(bs.bin) * 8)) - while n: + while size: offset = start // 8 n_offset = cls.endian_offset(attrib, offset) c = cls.getbytes(bs, n_offset, 1) if not c: raise IOError c = ord(c) - r = 8 - start % 8 + r = 8 - size % 8 c &= (1 << r) - 1 - l = min(r, n) + l = min(r, size) c >>= (r - l) o <<= l o |= c - n -= l + size -= l start += l return o diff --git a/miasm/arch/mep/arch.py b/miasm/arch/mep/arch.py index e53cbb09e..375be366d 100644 --- a/miasm/arch/mep/arch.py +++ b/miasm/arch/mep/arch.py @@ -449,18 +449,19 @@ def getsp(cls, attrib=None): return SP @classmethod - def getbits(cls, bitstream, attrib, start, n): + def getbits(cls, bitstream, attrib, offset, offset_bit, size): """Return an integer of n bits at the 'start' offset Note: code from miasm/arch/mips32/arch.py """ # Return zero if zero bits are requested - if not n: + if not size: return 0 + start = offset * 8 + offset_bit o = 0 # the returned value - while n: + while size: # Get a byte, the offset is adjusted according to the endianness offset = start // 8 # the offset in bytes n_offset = cls.endian_offset(attrib, offset) # the adjusted offset @@ -472,11 +473,11 @@ def getbits(cls, bitstream, attrib, start, n): c = ord(c) r = 8 - start % 8 c &= (1 << r) - 1 - l = min(r, n) + l = min(r, size) c >>= (r - l) o <<= l o |= c - n -= l + size -= l start += l return o diff --git a/miasm/arch/mips32/arch.py b/miasm/arch/mips32/arch.py index 2bfb432f8..b23d8769b 100644 --- a/miasm/arch/mips32/arch.py +++ b/miasm/arch/mips32/arch.py @@ -211,11 +211,13 @@ def additional_info(self): return info @classmethod - def getbits(cls, bitstream, attrib, start, n): - if not n: + def getbits(cls, bitstream, attrib, offset, offset_bits, size): + if not size: return 0 + + start = offset * 8 + offset_bits o = 0 - while n: + while size: offset = start // 8 n_offset = cls.endian_offset(attrib, offset) c = cls.getbytes(bitstream, n_offset, 1) @@ -224,11 +226,11 @@ def getbits(cls, bitstream, attrib, start, n): c = ord(c) r = 8 - start % 8 c &= (1 << r) - 1 - l = min(r, n) + l = min(r, size) c >>= (r - l) o <<= l o |= c - n -= l + size -= l start += l return o @@ -842,4 +844,3 @@ class bs_cond_mod(cpu.bs_mod_name): mips32op("mtlo", [cpu.bs('000000'), rs, cpu.bs('000000000000000'), cpu.bs('010011')], [rs]) mips32op("mthi", [cpu.bs('000000'), rs, cpu.bs('000000000000000'), cpu.bs('010001')], [rs]) - diff --git a/miasm/arch/msp430/arch.py b/miasm/arch/msp430/arch.py index 780a2ea09..11571c0df 100644 --- a/miasm/arch/msp430/arch.py +++ b/miasm/arch/msp430/arch.py @@ -263,13 +263,13 @@ def check_mnemo(cls, fields): assert l % 16 == 00, "len %r" % l @classmethod - def getbits(cls, bs, attrib, start, n): - if not n: + def getbits(cls, bs, attrib, offset, offset_bits, size): + if not size: return 0 + + start = offset * 8 + offset_bits o = 0 - if n > bs.getlen() * 8: - raise ValueError('not enough bits %r %r' % (n, len(bs.bin) * 8)) - while n: + while size: i = start // 8 c = cls.getbytes(bs, i) if not c: @@ -277,11 +277,11 @@ def getbits(cls, bs, attrib, start, n): c = ord(c) r = 8 - start % 8 c &= (1 << r) - 1 - l = min(r, n) + l = min(r, size) c >>= (r - l) o <<= l o |= c - n -= l + size -= l start += l return o @@ -614,4 +614,3 @@ def encode(self): bs_f2_jcc = bs_name(l=3, name={'jnz': 0, 'jz': 1, 'jnc': 2, 'jc': 3, 'jn': 4, 'jge': 5, 'jl': 6, 'jmp': 7}) addop("f2_3", [bs('001'), bs_f2_jcc, offimm]) - diff --git a/miasm/arch/ppc/arch.py b/miasm/arch/ppc/arch.py index c6f88a664..cacdb34b0 100644 --- a/miasm/arch/ppc/arch.py +++ b/miasm/arch/ppc/arch.py @@ -250,13 +250,13 @@ def additional_info(self): return info @classmethod - def getbits(cls, bs, attrib, start, n): - if not n: + def getbits(cls, bs, attrib, offset, offset_bits, size): + if not size: return 0 + + start = offset * 8 + offset_bits o = 0 - if n > bs.getlen() * 8: - raise ValueError('not enough bits %r %r' % (n, len(bs.bin) * 8)) - while n: + while size: offset = start // 8 n_offset = cls.endian_offset(attrib, offset) c = cls.getbytes(bs, n_offset, 1) @@ -265,11 +265,11 @@ def getbits(cls, bs, attrib, start, n): c = ord(c) r = 8 - start % 8 c &= (1 << r) - 1 - l = min(r, n) + l = min(r, size) c >>= (r - l) o <<= l o |= c - n -= l + size -= l start += l return o diff --git a/miasm/arch/sh4/arch.py b/miasm/arch/sh4/arch.py index e206d90b4..340a06dc5 100644 --- a/miasm/arch/sh4/arch.py +++ b/miasm/arch/sh4/arch.py @@ -514,13 +514,13 @@ def additional_info(self): return info @classmethod - def getbits(cls, bs, attrib, start, n): - if not n: + def getbits(cls, bs, attrib, offset, offset_bits, size): + if not size: return 0 + + start = offset * 8 + offset_bits o = 0 - if n > bs.getlen() * 8: - raise ValueError('not enough bits %r %r' % (n, len(bs.bin) * 8)) - while n: + while size: i = start // 8 c = cls.getbytes(bs, i) if not c: @@ -528,11 +528,11 @@ def getbits(cls, bs, attrib, start, n): c = ord(c) r = 8 - start % 8 c &= (1 << r) - 1 - l = min(r, n) + l = min(r, size) c >>= (r - l) o <<= l o |= c - n -= l + size -= l start += l return o From e147ff69b87e048288240287f4bdec3e44d56825 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20=E2=80=9CCLOVIS=E2=80=9D=20Canet?= Date: Thu, 21 Apr 2022 14:31:47 +0200 Subject: [PATCH 20/39] CPU: Convert text to binary streams --- miasm/core/cpu.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/miasm/core/cpu.py b/miasm/core/cpu.py index 91299eda3..b92b9ec29 100644 --- a/miasm/core/cpu.py +++ b/miasm/core/cpu.py @@ -1177,9 +1177,8 @@ def mod_fields(cls, fields): def dis(cls, bs_o, mode_o=None, offset=0): # type: (BinStream, Option[int], int) -> List - assert isinstance(bs_o, BinStream) - #if not isinstance(bs_o, bin_stream): - # bs_o = bin_stream_str(bs_o) + if not isinstance(bs_o, BinStream): + bs_o = bin_stream_str(bs_o).get_binstream() #bs_o.enter_atomic_mode() From faebb1279718a8d4a5626f3ddd59a82af4bc4b7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20=E2=80=9CCLOVIS=E2=80=9D=20Canet?= Date: Thu, 21 Apr 2022 15:39:43 +0200 Subject: [PATCH 21/39] MeP: updated to new syntax --- miasm/arch/mep/sem.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/miasm/arch/mep/sem.py b/miasm/arch/mep/sem.py index 878830ad2..812b4a9cf 100644 --- a/miasm/arch/mep/sem.py +++ b/miasm/arch/mep/sem.py @@ -17,11 +17,11 @@ def compute_s_inf(arg1, arg2): """Signed comparison operator""" - return ((arg1 - arg2) ^ ((arg1 ^ arg2) & ((arg1 - arg2) ^ arg1))).msb() + return ((arg1 - arg2) ^ ((arg1 ^ arg2) & ((arg1 - arg2) ^ arg1))).msb def compute_u_inf(x, y): """Unsigned comparison operator""" - result = (((x - y) ^ ((x ^ y) & ((x - y) ^ x))) ^ x ^ y).msb() + result = (((x - y) ^ ((x ^ y) & ((x - y) ^ x))) ^ x ^ y).msb return result def i8(value): From 2d8e0267694b4a335217b744051d14541ed9c791 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20=E2=80=9CCLOVIS=E2=80=9D=20Canet?= Date: Wed, 11 May 2022 14:12:56 +0200 Subject: [PATCH 22/39] PPC: updated to new syntax --- miasm/arch/ppc/sem.py | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/miasm/arch/ppc/sem.py b/miasm/arch/ppc/sem.py index 7fbf61e69..cdd2810c7 100644 --- a/miasm/arch/ppc/sem.py +++ b/miasm/arch/ppc/sem.py @@ -58,9 +58,9 @@ def mn_compute_flags(rvalue, overflow_expr=None): ret = [] - ret.append(ExprAssign(CR0_LT, rvalue.msb())) + ret.append(ExprAssign(CR0_LT, rvalue.msb)) ret.append(ExprAssign(CR0_GT, (ExprCond(rvalue, ExprInt(1, 1), - ExprInt(0, 1)) & ~rvalue.msb()))) + ExprInt(0, 1)) & ~rvalue.msb))) ret.append(ExprAssign(CR0_EQ, ExprCond(rvalue, ExprInt(0, 1), ExprInt(1, 1)))) if overflow_expr != None: @@ -101,9 +101,9 @@ def mn_do_add(ir, instr, arg1, arg2, arg3): over_expr = None if has_o: - msb1 = arg2.msb() - msb2 = arg3.msb() - msba = rvalue.msb() + msb1 = arg2.msb + msb2 = arg3.msb + msba = rvalue.msb over_expr = ~(msb1 ^ msb2) & (msb1 ^ msba) flags_update.append(ExprAssign(XER_OV, over_expr)) flags_update.append(ExprAssign(XER_SO, XER_SO | over_expr)) @@ -113,7 +113,7 @@ def mn_do_add(ir, instr, arg1, arg2, arg3): if has_c or has_e: carry_expr = (((arg2 ^ arg3) ^ rvalue) ^ - ((arg2 ^ rvalue) & (~(arg2 ^ arg3)))).msb() + ((arg2 ^ rvalue) & (~(arg2 ^ arg3)))).msb flags_update.append(ExprAssign(XER_CA, carry_expr)) return ([ ExprAssign(arg1, rvalue) ] + flags_update), [] @@ -572,7 +572,7 @@ def mn_do_sraw(ir, instr, ra, rs, rb): mask = ExprCond(rb[5:6], ExprInt(0xFFFFFFFF, 32), (ExprInt(0xFFFFFFFF, 32) >> (ExprInt(32, 32) - (rb & ExprInt(0b11111, 32))))) - ret.append(ExprAssign(XER_CA, rs.msb() & + ret.append(ExprAssign(XER_CA, rs.msb & ExprCond(rs & mask, ExprInt(1, 1), ExprInt(0, 1)))) return ret, [] @@ -586,7 +586,7 @@ def mn_do_srawi(ir, instr, ra, rs, imm): mask = ExprInt(0xFFFFFFFF >> (32 - int(imm)), 32) - ret.append(ExprAssign(XER_CA, rs.msb() & + ret.append(ExprAssign(XER_CA, rs.msb & ExprCond(rs & mask, ExprInt(1, 1), ExprInt(0, 1)))) return ret, [] @@ -714,9 +714,9 @@ def mn_do_sub(ir, instr, arg1, arg2, arg3): over_expr = None if has_o: - msb1 = arg2.msb() - msb2 = arg3.msb() - msba = rvalue.msb() + msb1 = arg2.msb + msb2 = arg3.msb + msba = rvalue.msb over_expr = (msb1 ^ msb2) & (msb1 ^ msba) flags_update.append(ExprAssign(XER_OV, over_expr)) flags_update.append(ExprAssign(XER_SO, XER_SO | over_expr)) @@ -726,7 +726,7 @@ def mn_do_sub(ir, instr, arg1, arg2, arg3): if has_c or has_e: carry_expr = ((((arg3 ^ arg2) ^ rvalue) ^ - ((arg3 ^ rvalue) & (arg3 ^ arg2))).msb()) + ((arg3 ^ rvalue) & (arg3 ^ arg2))).msb) flags_update.append(ExprAssign(XER_CA, ~carry_expr)) return ([ ExprAssign(arg1, rvalue) ] + flags_update), [] From 44a1c24b9b618d44a4dd97bb8163f612d5250b24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20=E2=80=9CCLOVIS=E2=80=9D=20Canet?= Date: Thu, 21 Apr 2022 14:51:41 +0200 Subject: [PATCH 23/39] x86: call get_bytes instead of getbytes --- miasm/arch/x86/arch.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/miasm/arch/x86/arch.py b/miasm/arch/x86/arch.py index 36fee990b..5733741a7 100644 --- a/miasm/arch/x86/arch.py +++ b/miasm/arch/x86/arch.py @@ -815,7 +815,7 @@ def pre_dis(cls, v, mode, offset): # multiple REX prefixes case - use last REX prefix x = ord(c) offset += 1 - c = v.getbytes(offset) + c = v.get_bytes(offset, 1) pre_dis_info['rex_p'] = 1 pre_dis_info['rex_w'] = (x >> 3) & 1 pre_dis_info['rex_r'] = (x >> 2) & 1 From cfae4b43bc34ab0fc16efc4453a333ba6ff63432 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20=E2=80=9CCLOVIS=E2=80=9D=20Canet?= Date: Tue, 26 Apr 2022 10:36:10 +0200 Subject: [PATCH 24/39] Git: ignore generated files --- .gitignore | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 6fc6b959b..b2877c5fe 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,8 @@ # Build directory -/build/* +/build/ +/dist/ +# Virtual environment +/venv/ # Emacs files *~ # Compiled python files @@ -8,4 +11,4 @@ *.egg* **.dot **.so -VERSION \ No newline at end of file +VERSION From 5424eded929246011184c1aa1873b74b18a74334 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20=E2=80=9CCLOVIS=E2=80=9D=20Canet?= Date: Tue, 26 Apr 2022 10:32:56 +0200 Subject: [PATCH 25/39] doc: explain how to use the new test suite --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 07e1d8e61..8922e435e 100644 --- a/README.md +++ b/README.md @@ -582,6 +582,8 @@ Testing Miasm comes with a set of regression tests. To run all of them: ```pycon +pip install -r requirements.txt +pip install -r test_requirements.txt cd miasm_directory/test python test_all.py ``` From 3e5318006a392f5b14d0746542eab7cd51d7162d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20=E2=80=9CCLOVIS=E2=80=9D=20Canet?= Date: Wed, 27 Apr 2022 13:19:07 +0200 Subject: [PATCH 26/39] aarch64.get_bytes: migration to the new syntax --- miasm/arch/sh4/arch.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/miasm/arch/sh4/arch.py b/miasm/arch/sh4/arch.py index 340a06dc5..f1a1e17cb 100644 --- a/miasm/arch/sh4/arch.py +++ b/miasm/arch/sh4/arch.py @@ -541,7 +541,7 @@ def getbytes(cls, bs, offset, l=1): out = b"" for _ in range(l): n_offset = (offset & ~1) + 1 - offset % 2 - out += bs.getbytes(n_offset, 1) + out += bs.get_bytes_exact(n_offset, 1) offset += 1 return out From 1164d1c823f621dc40c4dd61898acf193e32531d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20=E2=80=9CCLOVIS=E2=80=9D=20Canet?= Date: Wed, 27 Apr 2022 13:21:56 +0200 Subject: [PATCH 27/39] msp430.get_bytes: migration to the new syntax --- miasm/arch/msp430/arch.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/miasm/arch/msp430/arch.py b/miasm/arch/msp430/arch.py index 11571c0df..0d6d4560f 100644 --- a/miasm/arch/msp430/arch.py +++ b/miasm/arch/msp430/arch.py @@ -290,7 +290,7 @@ def getbytes(cls, bs, offset, l=1): out = b"" for _ in range(l): n_offset = (offset & ~1) + 1 - offset % 2 - out += bs.getbytes(n_offset, 1) + out += bs.get_bytes_exact(n_offset, 1) offset += 1 return out From f14936d1ae4f350e9645408da6f5a5b1dab6846c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20=E2=80=9CCLOVIS=E2=80=9D=20Canet?= Date: Thu, 5 May 2022 09:05:41 +0200 Subject: [PATCH 28/39] Convert Python instructions into InstructionIR --- miasm/arch/aarch64/sem.py | 2 +- miasm/arch/arm/sem.py | 3 +-- miasm/arch/msp430/lifter_model_call.py | 3 +-- miasm/arch/ppc/lifter_model_call.py | 2 +- miasm/arch/x86/sem.py | 24 ++++++++++++------------ miasm/core/cpu.py | 10 ++++++++++ miasm/ir/analysis.py | 2 +- miasm/ir/ir.py | 2 +- miasm/jitter/codegen.py | 2 +- test/core/sembuilder.py | 3 +-- 10 files changed, 30 insertions(+), 23 deletions(-) diff --git a/miasm/arch/aarch64/sem.py b/miasm/arch/aarch64/sem.py index 8cbab90ba..f4687122d 100644 --- a/miasm/arch/aarch64/sem.py +++ b/miasm/arch/aarch64/sem.py @@ -2281,7 +2281,7 @@ def smull(arg1, arg2, arg3): def get_mnemo_expr(ir, instr, *args): if not instr.name.lower() in mnemo_func: raise NotImplementedError('unknown mnemo %s' % instr) - instr, extra_ir = mnemo_func[instr.name.lower()](ir, instr, *args) + instr, extra_ir = mnemo_func[instr.name.lower()](ir, instr.to_ir(), *args) return instr, extra_ir diff --git a/miasm/arch/arm/sem.py b/miasm/arch/arm/sem.py index e507a0456..98518e1ca 100644 --- a/miasm/arch/arm/sem.py +++ b/miasm/arch/arm/sem.py @@ -1723,7 +1723,7 @@ def add_condition_expr(ir, instr, cond, instr_ir, extra_ir): break if not has_irdst: instr_ir.append(ExprAssign(ir.IRDst, loc_next_expr)) - e_do = IRBlock(ir.loc_db, loc_do, [AssignBlock(instr_ir, instr)]) + e_do = IRBlock(ir.loc_db, loc_do, [AssignBlock(instr_ir, instr.to_ir())]) e = [ExprAssign(ir.IRDst, dst_cond)] return e, [e_do] + extra_ir @@ -2171,4 +2171,3 @@ def __init__(self, loc_db): self.sp = SP self.IRDst = ExprId('IRDst', 32) self.addrsize = 32 - diff --git a/miasm/arch/msp430/lifter_model_call.py b/miasm/arch/msp430/lifter_model_call.py index 05f649e55..5d4301793 100644 --- a/miasm/arch/msp430/lifter_model_call.py +++ b/miasm/arch/msp430/lifter_model_call.py @@ -17,7 +17,7 @@ def call_effects(self, addr, instr): ExprAssign(self.ret_reg, ExprOp('call_func_ret', addr, self.sp, self.arch.regs.R15)), ExprAssign(self.sp, ExprOp('call_func_stack', addr, self.sp)) ], - instr + instr.to_ir() ) return [call_assignblk], [] @@ -28,4 +28,3 @@ def __init__(self, loc_db): def get_out_regs(self, _): return set([self.ret_reg, self.sp]) - diff --git a/miasm/arch/ppc/lifter_model_call.py b/miasm/arch/ppc/lifter_model_call.py index 066911901..0e83d9e56 100644 --- a/miasm/arch/ppc/lifter_model_call.py +++ b/miasm/arch/ppc/lifter_model_call.py @@ -38,7 +38,7 @@ def call_effects(self, ad, instr): ), ExprAssign(self.sp, ExprOp('call_func_stack', ad, self.sp)), ], - instr + instr.to_ir() ) return [call_assignblks], [] diff --git a/miasm/arch/x86/sem.py b/miasm/arch/x86/sem.py index 6700691cc..21bce23ad 100644 --- a/miasm/arch/x86/sem.py +++ b/miasm/arch/x86/sem.py @@ -666,7 +666,7 @@ def _rotate_tpl(ir, instr, dst, src, op, left=False): e_do.append(m2_expr.ExprAssign(ir.IRDst, loc_skip_expr)) e.append(m2_expr.ExprAssign( ir.IRDst, m2_expr.ExprCond(shifter, loc_do_expr, loc_skip_expr))) - return (e, [IRBlock(ir.loc_db, loc_do, [AssignBlock(e_do, instr)])]) + return (e, [IRBlock(ir.loc_db, loc_do, [AssignBlock(e_do, instr.to_ir())])]) def l_rol(ir, instr, dst, src): @@ -714,7 +714,7 @@ def rotate_with_carry_tpl(ir, instr, op, dst, src): e_do.append(m2_expr.ExprAssign(ir.IRDst, loc_skip_expr)) e.append(m2_expr.ExprAssign( ir.IRDst, m2_expr.ExprCond(shifter, loc_do_expr, loc_skip_expr))) - return (e, [IRBlock(ir.loc_db, loc_do, [AssignBlock(e_do, instr)])]) + return (e, [IRBlock(ir.loc_db, loc_do, [AssignBlock(e_do, instr.to_ir())])]) def rcl(ir, instr, dst, src): return rotate_with_carry_tpl(ir, instr, '<<<', dst, src) @@ -806,7 +806,7 @@ def _shift_tpl(op, ir, instr, a, b, c=None, op_inv=None, left=False, e_do.append(m2_expr.ExprAssign(ir.IRDst, loc_skip_expr)) e.append(m2_expr.ExprAssign(ir.IRDst, m2_expr.ExprCond(shifter, loc_do_expr, loc_skip_expr))) - return e, [IRBlock(ir.loc_db, loc_do, [AssignBlock(e_do, instr)])] + return e, [IRBlock(ir.loc_db, loc_do, [AssignBlock(e_do, instr.to_ir())])] def sar(ir, instr, dst, src): @@ -1797,13 +1797,13 @@ def idiv(ir, instr, src1): do_div = [] do_div += e do_div.append(m2_expr.ExprAssign(ir.IRDst, loc_next_expr)) - blk_div = IRBlock(ir.loc_db, loc_div, [AssignBlock(do_div, instr)]) + blk_div = IRBlock(ir.loc_db, loc_div, [AssignBlock(do_div, instr.to_ir())]) do_except = [] do_except.append(m2_expr.ExprAssign(exception_flags, m2_expr.ExprInt( EXCEPT_DIV_BY_ZERO, exception_flags.size))) do_except.append(m2_expr.ExprAssign(ir.IRDst, loc_next_expr)) - blk_except = IRBlock(ir.loc_db, loc_except, [AssignBlock(do_except, instr)]) + blk_except = IRBlock(ir.loc_db, loc_except, [AssignBlock(do_except, instr.to_ir())]) e = [] e.append(m2_expr.ExprAssign(ir.IRDst, @@ -1969,12 +1969,12 @@ def stos(ir, instr, size): e0 = [] e0.append(m2_expr.ExprAssign(addr_o, addr_p)) e0.append(m2_expr.ExprAssign(ir.IRDst, loc_next_expr)) - e0 = IRBlock(ir.loc_db, loc_df_0, [AssignBlock(e0, instr)]) + e0 = IRBlock(ir.loc_db, loc_df_0, [AssignBlock(e0, instr.to_ir())]) e1 = [] e1.append(m2_expr.ExprAssign(addr_o, addr_m)) e1.append(m2_expr.ExprAssign(ir.IRDst, loc_next_expr)) - e1 = IRBlock(ir.loc_db, loc_df_1, [AssignBlock(e1, instr)]) + e1 = IRBlock(ir.loc_db, loc_df_1, [AssignBlock(e1, instr.to_ir())]) e = [] e.append(m2_expr.ExprAssign(ir.ExprMem(addr, size), b)) @@ -3272,8 +3272,8 @@ def bsr_bsf(ir, instr, dst, src, op_func): e_src_not_null.append(m2_expr.ExprAssign(dst, op_func(src))) e_src_not_null.append(aff_dst) - return e, [IRBlock(ir.loc_db, loc_src_null, [AssignBlock(e_src_null, instr)]), - IRBlock(ir.loc_db, loc_src_not_null, [AssignBlock(e_src_not_null, instr)])] + return e, [IRBlock(ir.loc_db, loc_src_null, [AssignBlock(e_src_null, instr.to_ir())]), + IRBlock(ir.loc_db, loc_src_not_null, [AssignBlock(e_src_not_null, instr.to_ir())])] def bsf(ir, instr, dst, src): @@ -4980,7 +4980,7 @@ def maskmovq(ir, instr, src, mask): m2_expr.ExprCond(bit, write_label, next_check_label)) - blks.append(IRBlock(ir.loc_db, cur_label.loc_key, [AssignBlock([check], instr)])) + blks.append(IRBlock(ir.loc_db, cur_label.loc_key, [AssignBlock([check], instr.to_ir())])) # Build write blocks dst_addr = mRDI[instr.mode] @@ -4993,7 +4993,7 @@ def maskmovq(ir, instr, src, mask): write_mem = m2_expr.ExprAssign(m2_expr.ExprMem(write_addr, 8), src[start: start + 8]) jump = m2_expr.ExprAssign(ir.IRDst, next_check_label) - blks.append(IRBlock(ir.loc_db, cur_label.loc_key, [AssignBlock([write_mem, jump], instr)])) + blks.append(IRBlock(ir.loc_db, cur_label.loc_key, [AssignBlock([write_mem, jump], instr.to_ir())])) # If mask is null, bypass all e = [m2_expr.ExprAssign(ir.IRDst, m2_expr.ExprCond(mask, @@ -5806,7 +5806,7 @@ def get_ir(self, instr): "Mnemonic %s not implemented" % instr.name) instr_ir, extra_ir = mnemo_func[ - instr.name.lower()](self, instr, *args) + instr.name.lower()](self, instr.to_ir(), *args) self.mod_pc(instr, instr_ir, extra_ir) instr.additional_info.except_on_instr = False if instr.additional_info.g1.value & 14 == 0 or \ diff --git a/miasm/core/cpu.py b/miasm/core/cpu.py index b92b9ec29..5c44c7b21 100644 --- a/miasm/core/cpu.py +++ b/miasm/core/cpu.py @@ -7,6 +7,8 @@ from typing import List, Optional as Option, Set, Dict from future.utils import viewitems, viewvalues +from future.utils import with_metaclass +from miasm_rs import BinStream, InstructionIR import pyparsing @@ -1070,6 +1072,14 @@ def resolve_args_with_symbols(self, loc_db): def get_info(self, c): return + def to_ir(self): + # type: () -> InstructionIR + """Converts this instruction into an InstructionIR. + + This is a temporary method that will be removed in the future when instructions will be fully migrated to Rust. + """ + return InstructionIR(self.offset if self.offset is not None else 0, self.b if self.b is not None else [], self.name, self.args, str(self)) + class cls_mn(with_metaclass(metamn, object)): args_symb = [] diff --git a/miasm/ir/analysis.py b/miasm/ir/analysis.py index c08ea13b1..bea8d7b73 100644 --- a/miasm/ir/analysis.py +++ b/miasm/ir/analysis.py @@ -47,7 +47,7 @@ def call_effects(self, addr, instr): ExprAssign(self.ret_reg, ExprOp('call_func_ret', addr, self.sp)), ExprAssign(self.sp, ExprOp('call_func_stack', addr, self.sp)) ], - instr + instr.to_ir() ) return [call_assignblk], [] diff --git a/miasm/ir/ir.py b/miasm/ir/ir.py index 6db57b17c..f6ab52142 100644 --- a/miasm/ir/ir.py +++ b/miasm/ir/ir.py @@ -434,7 +434,7 @@ def instr2ir(self, instr): for assignblk in irb: irs.append(AssignBlock(assignblk, instr)) extra_irblocks[index] = IRBlock(self.loc_db, irb.loc_key, irs) - assignblk = AssignBlock(ir_bloc_cur, str(instr)) + assignblk = AssignBlock(ir_bloc_cur, instr.to_ir()) return assignblk, extra_irblocks def add_instr_to_ircfg(self, instr, ircfg, loc_key=None, gen_pc_updt=False): diff --git a/miasm/jitter/codegen.py b/miasm/jitter/codegen.py index 305d6c360..a72632d40 100644 --- a/miasm/jitter/codegen.py +++ b/miasm/jitter/codegen.py @@ -161,7 +161,7 @@ def assignblk_to_irbloc(self, instr, assignblk): loc_key = self.lifter.loc_db.get_or_create_offset_location(offset) dst = ExprLoc(loc_key, self.lifter.IRDst.size) new_assignblk[self.lifter.IRDst] = dst - irs = [AssignBlock(new_assignblk, instr)] + irs = [AssignBlock(new_assignblk, instr.to_ir())] return IRBlock(self.lifter.loc_db, self.lifter.get_loc_key_for_instr(instr), irs) def block2assignblks(self, block): diff --git a/test/core/sembuilder.py b/test/core/sembuilder.py index f7cc1282d..a3f9291cb 100644 --- a/test/core/sembuilder.py +++ b/test/core/sembuilder.py @@ -48,8 +48,7 @@ def test(Arg1, Arg2, Arg3): c = m2_expr.ExprId('C', 32) loc_db = LocationDB() ir = IR(loc_db) -instr = Instr() -res = test(ir, instr, a, b, c) +res = test(ir, "dummy instruction", a, b, c) print("[+] Returned:") print(res) From 0385b4de68dc243008b2d412b3082474e4f3e053 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20=E2=80=9CCLOVIS=E2=80=9D=20Canet?= Date: Thu, 5 May 2022 09:09:13 +0200 Subject: [PATCH 29/39] DepGraph: do not crash by calling `is_function_call` on non-operations --- miasm/analysis/depgraph.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/miasm/analysis/depgraph.py b/miasm/analysis/depgraph.py index 7fadd9bfc..1047ba513 100644 --- a/miasm/analysis/depgraph.py +++ b/miasm/analysis/depgraph.py @@ -482,7 +482,7 @@ def visit_inner(self, expr, *args, **kwargs): else: self.nofollow.add(expr) return None - elif expr.is_function_call(): + elif expr.is_op() and expr.is_function_call(): if self.follow_call: self.follow.add(expr) else: From 0db19fd781179e5d467d1b38df49a2ae3c001770 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20=E2=80=9CCLOVIS=E2=80=9D=20Canet?= Date: Thu, 5 May 2022 10:14:04 +0200 Subject: [PATCH 30/39] MeP: updated to new syntax --- miasm/arch/mep/arch.py | 9 ++++----- miasm/arch/mep/sem.py | 2 +- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/miasm/arch/mep/arch.py b/miasm/arch/mep/arch.py index 375be366d..ec788f21b 100644 --- a/miasm/arch/mep/arch.py +++ b/miasm/arch/mep/arch.py @@ -185,7 +185,6 @@ def __str__(self): o += ", %s" % self.arg2str(self.args[1]) # The third operand is displayed in decimal, not in hex o += ", %s" % ExprInt2SignedString(self.args[2], pos_fmt="0x%X") - o += ", %s" % ExprInt2SignedString(int(self.args[2]), pos_fmt="0x%X") elif self.name == "(RI)": return o @@ -303,7 +302,7 @@ def fixDstOffset(self): return # Adjust the immediate according to the current instruction offset - off = expr.arg - self.offset + off = int(expr) - self.offset if int(off % 2): raise ValueError("Strange offset! %r" % off) self.args[num] = ExprInt(off, 32) @@ -772,7 +771,7 @@ def encode(self): if getattr(self.parent, "imm7_align4", False): # Get the integer and check the upper bound - v = int(self.expr.ptr.args[1].arg) + v = int(self.expr.ptr.args[1]) if v > 0x80: return False @@ -784,7 +783,7 @@ def encode(self): elif getattr(self.parent, "imm7", False): # Get the integer and check the upper bound - v = int(self.expr.ptr.args[1].arg) + v = int(self.expr.ptr.args[1]) if v > 0x80: return False @@ -796,7 +795,7 @@ def encode(self): elif getattr(self.parent, "disp7_align2", False): # Get the integer and check the upper bound - v = int(self.expr.ptr.args[1].arg) + v = int(self.expr.ptr.args[1]) if v > 0x80: return False diff --git a/miasm/arch/mep/sem.py b/miasm/arch/mep/sem.py index 812b4a9cf..bcc5f1502 100644 --- a/miasm/arch/mep/sem.py +++ b/miasm/arch/mep/sem.py @@ -463,7 +463,7 @@ def sra(rn, rm_or_imm5): mask = (i32(0xFFFFFFFF) >> shift_mask) << shift_mask shift_s = shift_u | mask - rn = shift_s if rn.msb() else shift_u + rn = shift_s if rn.msb else shift_u @sbuild.parse From 1a4a4ad905a2e510c9ba904787dba46c176019b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20=E2=80=9CCLOVIS=E2=80=9D=20Canet?= Date: Thu, 5 May 2022 10:33:41 +0200 Subject: [PATCH 31/39] Simplifications: updated to new syntax --- miasm/expression/simplifications_explicit.py | 25 ++++++++++---------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/miasm/expression/simplifications_explicit.py b/miasm/expression/simplifications_explicit.py index 1f9d2dbeb..5c81f7bc5 100644 --- a/miasm/expression/simplifications_explicit.py +++ b/miasm/expression/simplifications_explicit.py @@ -16,7 +16,7 @@ def simp_ext(_, expr): new_expr = ExprCompose( arg, ExprCond( - arg.msb(), + arg.msb, ExprInt(size2mask(add_size), add_size), ExprInt(0, add_size) ) @@ -36,7 +36,7 @@ def simp_flags(_, expr): return ExprCond(op1 & op2, ExprInt(0, 1), ExprInt(1, 1)) elif expr.is_op("FLAG_SIGN_SUB"): - return (args[0] - args[1]).msb() + return (args[0] - args[1]).msb elif expr.is_op("FLAG_EQ_CMP"): return ExprCond( @@ -48,22 +48,22 @@ def simp_flags(_, expr): elif expr.is_op("FLAG_ADD_CF"): op1, op2 = args res = op1 + op2 - return (((op1 ^ op2) ^ res) ^ ((op1 ^ res) & (~(op1 ^ op2)))).msb() + return (((op1 ^ op2) ^ res) ^ ((op1 ^ res) & (~(op1 ^ op2)))).msb elif expr.is_op("FLAG_SUB_CF"): op1, op2 = args res = op1 - op2 - return (((op1 ^ op2) ^ res) ^ ((op1 ^ res) & (op1 ^ op2))).msb() + return (((op1 ^ op2) ^ res) ^ ((op1 ^ res) & (op1 ^ op2))).msb elif expr.is_op("FLAG_ADD_OF"): op1, op2 = args res = op1 + op2 - return (((op1 ^ res) & (~(op1 ^ op2)))).msb() + return (((op1 ^ res) & (~(op1 ^ op2)))).msb elif expr.is_op("FLAG_SUB_OF"): op1, op2 = args res = op1 - op2 - return (((op1 ^ res) & (op1 ^ op2))).msb() + return (((op1 ^ res) & (op1 ^ op2))).msb elif expr.is_op("FLAG_EQ_ADDWC"): op1, op2, op3 = args @@ -76,30 +76,30 @@ def simp_flags(_, expr): elif expr.is_op("FLAG_ADDWC_OF"): op1, op2, op3 = args res = op1 + op2 + op3.zeroExtend(op1.size) - return (((op1 ^ res) & (~(op1 ^ op2)))).msb() + return (((op1 ^ res) & (~(op1 ^ op2)))).msb elif expr.is_op("FLAG_SUBWC_OF"): op1, op2, op3 = args res = op1 - (op2 + op3.zeroExtend(op1.size)) - return (((op1 ^ res) & (op1 ^ op2))).msb() + return (((op1 ^ res) & (op1 ^ op2))).msb elif expr.is_op("FLAG_ADDWC_CF"): op1, op2, op3 = args res = op1 + op2 + op3.zeroExtend(op1.size) - return (((op1 ^ op2) ^ res) ^ ((op1 ^ res) & (~(op1 ^ op2)))).msb() + return (((op1 ^ op2) ^ res) ^ ((op1 ^ res) & (~(op1 ^ op2)))).msb elif expr.is_op("FLAG_SUBWC_CF"): op1, op2, op3 = args res = op1 - (op2 + op3.zeroExtend(op1.size)) - return (((op1 ^ op2) ^ res) ^ ((op1 ^ res) & (op1 ^ op2))).msb() + return (((op1 ^ op2) ^ res) ^ ((op1 ^ res) & (op1 ^ op2))).msb elif expr.is_op("FLAG_SIGN_ADDWC"): op1, op2, op3 = args - return (op1 + op2 + op3.zeroExtend(op1.size)).msb() + return (op1 + op2 + op3.zeroExtend(op1.size)).msb elif expr.is_op("FLAG_SIGN_SUBWC"): op1, op2, op3 = args - return (op1 - (op2 + op3.zeroExtend(op1.size))).msb() + return (op1 - (op2 + op3.zeroExtend(op1.size))).msb elif expr.is_op("FLAG_EQ_SUBWC"): @@ -156,4 +156,3 @@ def simp_flags(_, expr): return ~op_nf return expr - From 2c8ce07734ce4183ef8421adc4e00e88d0ac05c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20=E2=80=9CCLOVIS=E2=80=9D=20Canet?= Date: Thu, 5 May 2022 10:49:27 +0200 Subject: [PATCH 32/39] x86: missing bytes conversion --- miasm/arch/x86/arch.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/miasm/arch/x86/arch.py b/miasm/arch/x86/arch.py index 5733741a7..495aa5442 100644 --- a/miasm/arch/x86/arch.py +++ b/miasm/arch/x86/arch.py @@ -815,7 +815,7 @@ def pre_dis(cls, v, mode, offset): # multiple REX prefixes case - use last REX prefix x = ord(c) offset += 1 - c = v.get_bytes(offset, 1) + c = bytes(v.get_bytes(offset, 1)) pre_dis_info['rex_p'] = 1 pre_dis_info['rex_w'] = (x >> 3) & 1 pre_dis_info['rex_r'] = (x >> 2) & 1 From 9bbe7fa66d091cf1a717be8cd30e7737d9433839 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20=E2=80=9CCLOVIS=E2=80=9D=20Canet?= Date: Thu, 5 May 2022 11:03:14 +0200 Subject: [PATCH 33/39] data_flow: updated to new syntax --- miasm/analysis/data_flow.py | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/miasm/analysis/data_flow.py b/miasm/analysis/data_flow.py index 285b66db0..eebe3907b 100644 --- a/miasm/analysis/data_flow.py +++ b/miasm/analysis/data_flow.py @@ -506,10 +506,7 @@ def _relink_block_node(ircfg, loc_key, son_loc_key, replace_dct): if parent_block is None: continue - new_block = parent_block.modify_exprs( - lambda expr:expr.replace_expr(replace_dct), - lambda expr:expr.replace_expr(replace_dct) - ) + new_block = parent_block.replace(replace_dct) # Link parent to new dst ircfg.add_uniq_edge(parent, son_loc_key) @@ -1584,8 +1581,8 @@ def get_equivalence_class(self, node, ids_to_src): def del_dummy_phi(self, ssa, head): ids_to_src = {} def_to_loc = {} - for block in ssa.graph.iter(): - for index, assignblock in enumerate(block.iter()): + for block in ssa.graph.blocks.values(): + for index, assignblock in enumerate(block): for dst, src in viewitems(assignblock): if not dst.is_id(): continue @@ -1594,7 +1591,7 @@ def del_dummy_phi(self, ssa, head): modified = False - for block in ssa.graph.iter(): + for block in ssa.graph.blocks.values(): if not irblock_has_phi(block): continue assignblk = block[0] @@ -1624,7 +1621,7 @@ def del_dummy_phi(self, ssa, head): continue fixed_phis[old_dst] = old_phi_src - assignblks = list(block.iter()) + assignblks = list(block) assignblks[0] = AssignBlock(fixed_phis, assignblk.instr) assignblks[1:1] = [AssignBlock({dst: true_value}, assignblk.instr)] new_irblock = IRBlock(block.loc_db, block.loc_key, assignblks) From db4a46bfc3da94339dd4a2aaddbaa24a274fb781 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20=E2=80=9CCLOVIS=E2=80=9D=20Canet?= Date: Thu, 5 May 2022 11:25:45 +0200 Subject: [PATCH 34/39] IRBlock: added set_block --- miasm/ir/ir.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/miasm/ir/ir.py b/miasm/ir/ir.py index f6ab52142..7e6a1a804 100644 --- a/miasm/ir/ir.py +++ b/miasm/ir/ir.py @@ -302,6 +302,9 @@ def get_block(self, addr): return None return self.blocks.get(loc_key, None) + def set_block(self, loc_key, irblock): + self.blocks[loc_key] = irblock + def getby_offset(self, offset): # type: (int) -> Set[IRBlock] """ From 45e108c1d155e50d695705fcf02ab393f624208d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20=E2=80=9CCLOVIS=E2=80=9D=20Canet?= Date: Wed, 11 May 2022 09:07:54 +0200 Subject: [PATCH 35/39] ExpressionSimplifier: temporary conversion to the Rust equivalent The goal is to validate the tests without migrating everything yet. --- miasm/arch/arm/jit.py | 2 +- miasm/expression/simplifications.py | 9 +++++++++ miasm/ir/ir.py | 4 +++- miasm/jitter/codegen.py | 2 +- test/ir/ir.py | 2 +- 5 files changed, 15 insertions(+), 4 deletions(-) diff --git a/miasm/arch/arm/jit.py b/miasm/arch/arm/jit.py index 27c26988b..4dfcef79d 100644 --- a/miasm/arch/arm/jit.py +++ b/miasm/arch/arm/jit.py @@ -50,7 +50,7 @@ def block2assignblks(self, block): # Simplify high level operators out = [] for irblock in irblocks: - new_irblock = irblock.simplify(expr_simp_high_to_explicit)[1] + new_irblock = irblock.simplify(expr_simp_high_to_explicit.to_new_visitor()) out.append(new_irblock) irblocks = out diff --git a/miasm/expression/simplifications.py b/miasm/expression/simplifications.py index 88e599836..74dfa48e8 100644 --- a/miasm/expression/simplifications.py +++ b/miasm/expression/simplifications.py @@ -3,8 +3,10 @@ # # import logging +import warnings from future.utils import viewitems +from miasm_rs import ExprVisitor from miasm.expression import simplifications_common from miasm.expression import simplifications_cond @@ -188,6 +190,13 @@ def __call__(self, expression): "Call simplification recursively" return self.visit(expression) + def to_new_visitor(self): + """Temporary function to convert ExpressionSimplifier to ExprVisitor. + Will be removed when ExpressionSimplifier is ported to Rust in the near future.""" + warnings.warn("ExpressionSimplifier.to_new_visitor is a temporary function and is not part of the Miasm API. It may be removed at any moment without further warnings.") + + return ExprVisitor(lambda e: self.expr_simp_inner(e)) + # Public ExprSimplificationPass instance with commons passes expr_simp = ExpressionSimplifier() diff --git a/miasm/ir/ir.py b/miasm/ir/ir.py index 7e6a1a804..d008f66e9 100644 --- a/miasm/ir/ir.py +++ b/miasm/ir/ir.py @@ -25,6 +25,8 @@ import miasm.expression.expression as m2_expr from miasm.core.asmblock import AsmBlock, AsmBlockBad, AsmConstraint from miasm.core.graph import DiGraph +from miasm.expression.simplifications import ExpressionSimplifier +from miasm.expression.expression import ExprAssign from miasm.ir.translators import Translator from miasm.core import utils import re @@ -331,7 +333,7 @@ def simplify(self, simplifier): for loc_key, block in list(viewitems(self.blocks)): assignblks = [] for assignblk in block: - new_assignblk = assignblk.simplify(simplifier) + new_assignblk = assignblk.simplify(simplifier.to_new_visitor() if isinstance(simplifier, ExpressionSimplifier) else simplifier) if assignblk != new_assignblk: modified = True assignblks.append(new_assignblk) diff --git a/miasm/jitter/codegen.py b/miasm/jitter/codegen.py index a72632d40..6a298210c 100644 --- a/miasm/jitter/codegen.py +++ b/miasm/jitter/codegen.py @@ -181,7 +181,7 @@ def block2assignblks(self, block): out = [] for irblock in irblocks: new_irblock = self.lifter.irbloc_fix_regs_for_mode(irblock, self.lifter.attrib) - new_irblock = new_irblock.simplify(expr_simp_high_to_explicit)[1] + new_irblock = new_irblock.simplify(expr_simp_high_to_explicit.to_new_visitor())[1] out.append(new_irblock) irblocks = out diff --git a/test/ir/ir.py b/test/ir/ir.py index a959a7a76..05cb1c60a 100644 --- a/test/ir/ir.py +++ b/test/ir/ir.py @@ -45,6 +45,6 @@ ## Simplify assignblk3 = AssignBlock({id_a: id_b - id_b}) assert assignblk3[id_a] != int0 -assignblk4 = assignblk3.simplify(expr_simp) +assignblk4 = assignblk3.simplify(expr_simp.to_new_visitor()) assert assignblk3[id_a] != int0 assert assignblk4[id_a] == int0 From 7256e355af3a93dd5951a5b5fa22a2d114dc30dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20=E2=80=9CCLOVIS=E2=80=9D=20Canet?= Date: Wed, 11 May 2022 10:08:15 +0200 Subject: [PATCH 36/39] IRBlock.simplify doesn't return a 'changed' boolean anymore --- miasm/jitter/codegen.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/miasm/jitter/codegen.py b/miasm/jitter/codegen.py index 6a298210c..2286abfb4 100644 --- a/miasm/jitter/codegen.py +++ b/miasm/jitter/codegen.py @@ -181,7 +181,7 @@ def block2assignblks(self, block): out = [] for irblock in irblocks: new_irblock = self.lifter.irbloc_fix_regs_for_mode(irblock, self.lifter.attrib) - new_irblock = new_irblock.simplify(expr_simp_high_to_explicit.to_new_visitor())[1] + new_irblock = new_irblock.simplify(expr_simp_high_to_explicit.to_new_visitor()) out.append(new_irblock) irblocks = out From 452c881b507023eddd7ea6e07372b62fb7df6b82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20=E2=80=9CCLOVIS=E2=80=9D=20Canet?= Date: Wed, 11 May 2022 11:19:13 +0200 Subject: [PATCH 37/39] IR: the AssignBlock constructor cannot be directly used for copies anymore --- miasm/ir/ir.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/miasm/ir/ir.py b/miasm/ir/ir.py index d008f66e9..a11132d73 100644 --- a/miasm/ir/ir.py +++ b/miasm/ir/ir.py @@ -437,7 +437,7 @@ def instr2ir(self, instr): for index, irb in enumerate(extra_irblocks): irs = [] for assignblk in irb: - irs.append(AssignBlock(assignblk, instr)) + irs.append(AssignBlock([ExprAssign(dst, src) for dst, src in assignblk.items()], instr)) extra_irblocks[index] = IRBlock(self.loc_db, irb.loc_key, irs) assignblk = AssignBlock(ir_bloc_cur, instr.to_ir()) return assignblk, extra_irblocks From 97b29cbf45f59122a10a69569c6e95f1ea809036 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20=E2=80=9CCLOVIS=E2=80=9D=20Canet?= Date: Mon, 16 May 2022 13:19:36 +0200 Subject: [PATCH 38/39] Jitcore: ExprRules don't need to be converted to Visitor --- miasm/jitter/jitcore_llvm_rs.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/miasm/jitter/jitcore_llvm_rs.py b/miasm/jitter/jitcore_llvm_rs.py index a671c3b7d..066d8a4a2 100644 --- a/miasm/jitter/jitcore_llvm_rs.py +++ b/miasm/jitter/jitcore_llvm_rs.py @@ -54,9 +54,8 @@ def __init__(self, ir_arch, bin_stream): loc_db = self.ir_arch.loc_db lifter_x86 = LifterX86(loc_db, opsize) - expr_rules = ExprRules() - add_explicit_rules(expr_rules) - expr_simp = ExprVisitor.visit_bottom_up(expr_rules) + expr_simp = ExprRules() + add_explicit_rules(expr_simp) From bbd367f64cd29fde2d17e938a2f0c2437bb36dfc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20=E2=80=9CCLOVIS=E2=80=9D=20Canet?= Date: Mon, 16 May 2022 13:59:47 +0200 Subject: [PATCH 39/39] Jitcore LLVM_RS: updated to new syntax --- miasm/jitter/jitcore_llvm_rs.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/miasm/jitter/jitcore_llvm_rs.py b/miasm/jitter/jitcore_llvm_rs.py index 066d8a4a2..19b724e33 100644 --- a/miasm/jitter/jitcore_llvm_rs.py +++ b/miasm/jitter/jitcore_llvm_rs.py @@ -52,7 +52,7 @@ def __init__(self, ir_arch, bin_stream): # Init rust functions loc_db = self.ir_arch.loc_db - lifter_x86 = LifterX86(loc_db, opsize) + lifter_x86 = LifterX86(loc_db, int(opsize)) expr_simp = ExprRules() add_explicit_rules(expr_simp)