forked from HexRaysSA/goomba
-
Notifications
You must be signed in to change notification settings - Fork 0
/
heuristics.cpp
130 lines (117 loc) · 3.19 KB
/
heuristics.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
/*
* Copyright (c) 2023 by Hex-Rays, [email protected]
* ALL RIGHTS RESERVED.
*
* gooMBA plugin for Hex-Rays Decompiler.
*
*/
#include "z3++_no_warn.h"
#include "heuristics.hpp"
//-------------------------------------------------------------------------
inline uint64 rand64()
{
uint32 r1 = rand();
uint32 r2 = rand();
return uint64(r1) << 32 | uint64(r2);
}
//-------------------------------------------------------------------------
mcode_val_t gen_rand_mcode_val(int size)
{
if ( rand() > SPECIAL_PROBABILITY * RAND_MAX )
{
// select from uniform random distribution
return mcode_val_t(rand64(), size);
}
else
{
// select from special cases
return mcode_val_t(SPECIAL[rand() % NUM_SPECIAL], size);
}
}
//-------------------------------------------------------------------------
// guesses whether or not the instruction is MBA
bool is_mba(const minsn_t &insn)
{
struct mba_opc_counter_t : public minsn_visitor_t
{
int bool_cnt = 0;
int arith_cnt = 0;
int idaapi visit_minsn(void) override
{
switch ( curins->opcode )
{
case m_neg:
case m_add:
case m_sub:
case m_mul:
case m_udiv:
case m_sdiv:
case m_umod:
case m_smod:
case m_shl:
case m_shr:
arith_cnt++;
break;
case m_bnot:
case m_or:
case m_and:
case m_xor:
case m_sar:
bool_cnt++;
break;
default:
return 0;
}
return bool_cnt >= MIN_MBA_BOOL_OPS && arith_cnt >= MIN_MBA_ARITH_OPS;
}
};
if ( is_mcode_xdsu(insn.opcode) )
return false; // exclude xdsu, it is better to optimize its operand
mba_opc_counter_t cntr;
return CONST_CAST(minsn_t*)(&insn)->for_all_insns(cntr) != 0;
}
//-------------------------------------------------------------------------
// runs a battery of random test cases against both expressions to see if they are equivalent
bool probably_equivalent(const minsn_t &insn, const candidate_expr_t &expr)
{
for ( int i = 0; i < NUM_TEST_CASES; i++ )
{
mcode_emu_rand_vals_t emu;
mcode_val_t insn_eval = emu.minsn_value(insn);
mcode_val_t expr_eval = expr.evaluate(emu);
if ( insn_eval != expr_eval )
return false;
}
return true;
}
//-------------------------------------------------------------------------
// runs a battery of random test cases against both expressions to see if they are equivalent
bool probably_equivalent(const minsn_t &a, const minsn_t &b)
{
for ( int i = 0; i < NUM_TEST_CASES; i++ )
{
mcode_emu_rand_vals_t emu;
mcode_val_t insn_eval = emu.minsn_value(a);
mcode_val_t expr_eval = emu.minsn_value(b);
if ( insn_eval != expr_eval )
return false;
}
return true;
}
//-------------------------------------------------------------------------
// estimates the "complexity" of a given instruction
int score_complexity(const minsn_t &insn)
{
struct ida_local complexity_counter_t : public minsn_visitor_t
{
int cnt = 0;
int idaapi visit_minsn() override
{
cnt++;
return 0;
}
};
complexity_counter_t cc;
CONST_CAST(minsn_t&)(insn).for_all_insns(cc);
return cc.cnt;
}