Files
d810/d810/optimizers/instructions/pattern_matching/rewrite_predicates.py
Boris Batteux 33f8d22f28 Initial commit
2020-10-29 11:09:07 +01:00

404 lines
15 KiB
Python

from ida_hexrays import *
from d810.optimizers.instructions.pattern_matching.handler import PatternMatchingRule
from d810.ast import AstLeaf, AstConstant, AstNode
from d810.hexrays_helpers import equal_bnot_mop, SUB_TABLE, AND_TABLE
# PredSetnzRule1: (x_0 | c_1) != c_2 ==> 1 if c_1 | c_2 != c_2
class PredSetnzRule1(PatternMatchingRule):
PATTERN = AstNode(m_setnz,
AstNode(m_or,
AstLeaf("x_0"),
AstConstant("c_1")),
AstConstant("c_2"))
REPLACEMENT_PATTERN = AstNode(m_mov, AstConstant("val_1"))
def check_candidate(self, candidate):
if (candidate["c_1"].value | candidate["c_2"].value) == candidate["c_2"].value:
return False
candidate.add_constant_leaf("val_1", 1, candidate.size)
return True
# PredSetnzRule2: (x_0 & c_1) != c_2 ==> 1 if c_1 & c_2 != c_2
class PredSetnzRule2(PatternMatchingRule):
PATTERN = AstNode(m_setnz,
AstNode(m_and,
AstLeaf("x_0"),
AstConstant("c_1")),
AstConstant("c_2"))
REPLACEMENT_PATTERN = AstNode(m_mov, AstConstant("val_1"))
def check_candidate(self, candidate):
if (candidate["c_1"].value & candidate["c_2"].value) == candidate["c_2"].value:
return False
candidate.add_constant_leaf("val_1", 1, candidate.size)
return True
# PredSetnzRule3: (x_0 | 2) + (x_0 ^ 2) != 0 ==> 1 (because math)
class PredSetnzRule3(PatternMatchingRule):
PATTERN = AstNode(m_setnz,
AstNode(m_add,
AstNode(m_or,
AstLeaf("x_0"),
AstConstant("2", 2)),
AstNode(m_xor,
AstLeaf("x_0"),
AstConstant("2", 2))),
AstConstant("0", 0))
REPLACEMENT_PATTERN = AstNode(m_mov, AstConstant("val_1"))
def check_candidate(self, candidate):
candidate.add_constant_leaf("val_1", 1, candidate.size)
return True
# PredSetnzRule4: (cst_1 - x_0) ^ x_0 != 0 ==> 1 if cst_1 % 2 == 1 (because math)
class PredSetnzRule4(PatternMatchingRule):
PATTERN = AstNode(m_setnz,
AstNode(m_xor,
AstNode(m_sub,
AstConstant("cst_1"),
AstLeaf("x_0")),
AstLeaf("x_0")),
AstConstant("0", 0))
REPLACEMENT_PATTERN = AstNode(m_mov, AstConstant("val_1"))
def check_candidate(self, candidate):
if (candidate["cst_1"].value % 2) == 0:
return False
candidate.add_constant_leaf("val_1", 1, candidate.size)
return True
# PredSetnzRule5: (-(~x_0 & 1)) != x_0 ==> 1 (because math)
class PredSetnzRule5(PatternMatchingRule):
PATTERN = AstNode(m_setnz,
AstNode(m_neg,
AstNode(m_and,
AstNode(m_bnot,
AstLeaf("x_0")),
AstConstant("1", 1))),
AstLeaf("x_0"))
REPLACEMENT_PATTERN = AstNode(m_mov, AstConstant("val_1"))
def check_candidate(self, candidate):
candidate.add_constant_leaf("val_1", 1, candidate.size)
return True
# PredSetnzRule6: ((x_0 + c_1) + ((x_0 + c_2) & 1)) != 0 ==> 1 (if (c_2 - c_1) & 1 == 1)
class PredSetnzRule6(PatternMatchingRule):
PATTERN = AstNode(m_setnz,
AstNode(m_add,
AstNode(m_add,
AstLeaf("x_0"),
AstConstant("c_1")),
AstNode(m_and,
AstNode(m_add,
AstLeaf("x_0"),
AstConstant("c_2")),
AstConstant("1", 1))),
AstConstant("0", 0))
REPLACEMENT_PATTERN = AstNode(m_mov, AstConstant("val_1"))
def check_candidate(self, candidate):
if (candidate["c_2"].value - candidate["c_1"].value) & 0x1 != 1:
return False
candidate.add_constant_leaf("val_1", 1, candidate.size)
return True
# PredSetnzRule8: bnot((3 - x_0)) ^ bnot(x_0) != 0 ==> 1
class PredSetnzRule8(PatternMatchingRule):
PATTERN = AstNode(m_setnz,
AstNode(m_xor,
AstNode(m_bnot,
AstNode(m_sub,
AstConstant("3", 3),
AstLeaf("x_0"))),
AstNode(m_bnot,
AstLeaf("x_0"))),
AstConstant("0", 0))
REPLACEMENT_PATTERN = AstNode(m_mov, AstConstant("val_1"))
def check_candidate(self, candidate):
candidate.add_constant_leaf("val_1", 1, candidate.size)
return True
# PredSetzRule1: (x_0 | c_1) == c_2 ==> 0 if c_1 | c_2 != c_2
class PredSetzRule1(PatternMatchingRule):
PATTERN = AstNode(m_setz,
AstNode(m_or,
AstLeaf("x_0"),
AstConstant("c_1")),
AstConstant("c_2"))
REPLACEMENT_PATTERN = AstNode(m_mov, AstConstant("val_0"))
def check_candidate(self, candidate):
if (candidate["c_1"].value | candidate["c_2"].value) == candidate["c_2"].value:
return False
candidate.add_constant_leaf("val_0", 0, candidate.size)
return True
# PredSetzRule2: (x_0 & c_1) == c_2 ==> 0 if c_1 & c_2 != c_2
class PredSetzRule2(PatternMatchingRule):
PATTERN = AstNode(m_setz,
AstNode(m_and,
AstLeaf("x_0"),
AstConstant("c_1")),
AstConstant("c_2"))
REPLACEMENT_PATTERN = AstNode(m_mov, AstConstant("val_0"))
def check_candidate(self, candidate):
if (candidate["c_1"].value & candidate["c_2"].value) == candidate["c_2"].value:
return False
candidate.add_constant_leaf("val_0", 0, candidate.size)
return True
# PredSetzRule3: (x_0 | 2) + (x_0 ^ 2) == 0 ==> 0 (because math)
class PredSetzRule3(PatternMatchingRule):
PATTERN = AstNode(m_setz,
AstNode(m_add,
AstNode(m_or,
AstLeaf("x_0"),
AstConstant("2", 2)),
AstNode(m_xor,
AstLeaf("x_0"),
AstConstant("2", 2))),
AstConstant("0", 0))
REPLACEMENT_PATTERN = AstNode(m_mov, AstConstant("val_0"))
def check_candidate(self, candidate):
candidate.add_constant_leaf("val_0", 0, candidate.size)
return True
# PredSetbRule1: (x_0 & c_1) <u c_2 ==> 0 if c_1 <u c_2
class PredSetbRule1(PatternMatchingRule):
PATTERN = AstNode(m_setb,
AstNode(m_and,
AstLeaf("x_0"),
AstConstant("c_1")),
AstConstant("c_2"))
REPLACEMENT_PATTERN = AstNode(m_mov, AstConstant("val_0"))
def check_candidate(self, candidate):
if candidate["c_1"].value >= candidate["c_2"].value:
return False
candidate.add_constant_leaf("val_0", 0, candidate.size)
return True
class PredOdd1(PatternMatchingRule):
PATTERN = AstNode(m_and,
AstNode(m_mul,
AstLeaf('x_0'),
AstNode(m_sub,
AstLeaf('x_0'),
AstConstant('1', 1))),
AstConstant('1', 1))
REPLACEMENT_PATTERN = AstNode(m_mov, AstConstant('val_0'))
def check_candidate(self, candidate):
candidate.add_constant_leaf("val_0", 0, candidate.size)
return True
class PredOdd2(PatternMatchingRule):
PATTERN = AstNode(m_and,
AstNode(m_mul,
AstLeaf('x_0'),
AstNode(m_add,
AstLeaf('x_0'),
AstConstant('1', 1))),
AstConstant('1', 1))
REPLACEMENT_PATTERN = AstNode(m_mov, AstConstant('val_0'))
def check_candidate(self, candidate):
candidate.add_constant_leaf("val_0", 0, candidate.size)
return True
# Pred0Rule1: (x_0 & ~x_0) ==> 0
class Pred0Rule1(PatternMatchingRule):
PATTERN = AstNode(m_and,
AstLeaf("x_0"),
AstNode(m_bnot,
AstLeaf("x_0")))
REPLACEMENT_PATTERN = AstNode(m_mov, AstConstant("val_0"))
def check_candidate(self, candidate):
candidate.add_constant_leaf("val_0", 0, candidate.size)
return True
# Pred0Rule2: (xdu(x_0 & 1) == 2) ==> 0
class Pred0Rule2(PatternMatchingRule):
PATTERN = AstNode(m_setz,
AstNode(m_xdu,
AstNode(m_and,
AstLeaf("x_0"),
AstConstant("c_1", 1))),
AstConstant("c_2", 2))
REPLACEMENT_PATTERN = AstNode(m_mov, AstConstant("val_0"))
def check_candidate(self, candidate):
candidate.add_constant_leaf("val_0", 0, candidate.size)
return True
class Pred0Rule3(PatternMatchingRule):
PATTERN = AstNode(m_and,
AstLeaf("x_0"),
AstNode(m_bnot,
AstNode(m_or,
AstLeaf("x_0"),
AstLeaf("x_1"))))
REPLACEMENT_PATTERN = AstNode(m_mov, AstLeaf("val_0"))
def check_candidate(self, candidate):
candidate.add_constant_leaf("val_0", 0, candidate.size)
return True
class Pred0Rule4(PatternMatchingRule):
PATTERN = AstNode(m_and,
AstNode(m_and,
AstLeaf('x_0'),
AstLeaf('x_1')),
AstNode(m_bnot,
AstNode(m_or,
AstLeaf('x_0'),
AstLeaf('x_1'))))
REPLACEMENT_PATTERN = AstNode(m_mov, AstLeaf("val_0"))
def check_candidate(self, candidate):
candidate.add_constant_leaf("val_0", 0, candidate.size)
return True
class Pred0Rule5(PatternMatchingRule):
PATTERN = AstNode(m_and,
AstNode(m_and,
AstLeaf('x_0'),
AstLeaf('x_1')),
AstNode(m_xor,
AstLeaf('x_0'),
AstLeaf('x_1')))
REPLACEMENT_PATTERN = AstNode(m_mov, AstLeaf("val_0"))
def check_candidate(self, candidate):
candidate.add_constant_leaf("val_0", 0, candidate.size)
return True
class PredFFRule1(PatternMatchingRule):
PATTERN = AstNode(m_or,
AstLeaf("x_0"),
AstNode(m_bnot,
AstLeaf("x_0")))
REPLACEMENT_PATTERN = AstNode(m_mov, AstConstant("val_ff"))
def check_candidate(self, candidate):
candidate.add_constant_leaf("val_ff", AND_TABLE[candidate.size], candidate.size)
return True
# Pred1Rule2: (x_0 ^ x_1) | (~x_0 | x_1) ==> 0xff
class PredFFRule2(PatternMatchingRule):
PATTERN = AstNode(m_or,
AstNode(m_xor,
AstLeaf("x_0"),
AstLeaf("x_1")),
AstNode(m_or,
AstLeaf("bnot_x_0"),
AstLeaf("x_1")))
REPLACEMENT_PATTERN = AstNode(m_mov, AstConstant("val_ff"))
def check_candidate(self, candidate):
if not equal_bnot_mop(candidate["x_0"].mop, candidate["bnot_x_0"].mop):
return False
candidate.add_constant_leaf("val_ff", AND_TABLE[candidate.size], candidate.size)
return True
class PredFFRule3(PatternMatchingRule):
PATTERN = AstNode(m_or,
AstLeaf("x_0"),
AstNode(m_bnot,
AstNode(m_and,
AstLeaf("x_0"),
AstLeaf("x_1"))))
REPLACEMENT_PATTERN = AstNode(m_mov, AstLeaf("val_ff"))
def check_candidate(self, candidate):
candidate.add_constant_leaf("val_ff", AND_TABLE[candidate.size], candidate.size)
return True
class PredFFRule4(PatternMatchingRule):
DESCRIPTION = "(x_0 | x_1) | (~(x_0 & x_1)) ==> 0xff"
PATTERN = AstNode(m_or,
AstNode(m_or,
AstLeaf('x_0'),
AstLeaf('x_1')),
AstNode(m_bnot,
AstNode(m_and,
AstLeaf('x_0'),
AstLeaf('x_1'))))
REPLACEMENT_PATTERN = AstNode(m_mov, AstConstant("val_ff"))
def check_candidate(self, candidate):
candidate.add_constant_leaf("val_ff", AND_TABLE[candidate.size], candidate.size)
return True
class PredOr2_Rule_1(PatternMatchingRule):
PATTERN = AstNode(m_and,
AstNode(m_bnot,
AstNode(m_mul,
AstLeaf('x_0'),
AstLeaf('x_0'))),
AstConstant('3', 3))
REPLACEMENT_PATTERN = AstNode(m_or,
AstNode(m_and,
AstNode(m_bnot, AstLeaf('x_0')),
AstConstant('val_1')),
AstConstant('val_2'))
def check_candidate(self, candidate):
candidate.add_constant_leaf("val_1", 1, candidate["x_0"].mop.size)
candidate.add_constant_leaf("val_2", 2, candidate["x_0"].mop.size)
return True
class PredOr1_Rule_1(PatternMatchingRule):
PATTERN = AstNode(m_xor,
AstLeaf('x_0'),
AstNode(m_add,
AstNode(m_and,
AstLeaf('x_0'),
AstConstant('1', 1)),
AstConstant('1', 1)))
REPLACEMENT_PATTERN = AstNode(m_or,
AstNode(m_xor,
AstLeaf('x_0'),
AstNode(m_mul,
AstConstant('val_2'),
AstNode(m_and,
AstLeaf('x_0'),
AstConstant('val_1')))),
AstConstant('val_1'))
def check_candidate(self, candidate):
candidate.add_constant_leaf("val_1", 1, candidate["x_0"].mop.size)
candidate.add_constant_leaf("val_2", 2, candidate["x_0"].mop.size)
return True