summaryrefslogtreecommitdiff
path: root/rust/src/hlil/lift.rs
blob: 06338dea74dcd713c55368ea03b1bdf7da2d4ca1 (plain)
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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
use super::{operation::*, HighLevelILFunction};

use crate::rc::Ref;
use crate::types::{ConstantData, ILIntrinsic, SSAVariable, Variable};

#[derive(Clone)]
pub enum HighLevelILLiftedOperand {
    ConstantData(ConstantData),
    Expr(HighLevelILLiftedInstruction),
    ExprList(Vec<HighLevelILLiftedInstruction>),
    Float(f64),
    Int(u64),
    IntList(Vec<u64>),
    Intrinsic(ILIntrinsic),
    Label(GotoLabel),
    MemberIndex(Option<usize>),
    Var(Variable),
    VarSsa(SSAVariable),
    VarSsaList(Vec<SSAVariable>),
}

#[derive(Clone, Debug, PartialEq)]
pub struct HighLevelILLiftedInstruction {
    pub function: Ref<HighLevelILFunction>,
    pub address: u64,
    pub kind: HighLevelILLiftedInstructionKind,
}

#[derive(Clone, Debug, PartialEq)]
pub enum HighLevelILLiftedInstructionKind {
    Adc(LiftedBinaryOpCarry),
    Sbb(LiftedBinaryOpCarry),
    Rlc(LiftedBinaryOpCarry),
    Rrc(LiftedBinaryOpCarry),
    Add(LiftedBinaryOp),
    Sub(LiftedBinaryOp),
    And(LiftedBinaryOp),
    Or(LiftedBinaryOp),
    Xor(LiftedBinaryOp),
    Lsl(LiftedBinaryOp),
    Lsr(LiftedBinaryOp),
    Asr(LiftedBinaryOp),
    Rol(LiftedBinaryOp),
    Ror(LiftedBinaryOp),
    Mul(LiftedBinaryOp),
    MuluDp(LiftedBinaryOp),
    MulsDp(LiftedBinaryOp),
    Divu(LiftedBinaryOp),
    DivuDp(LiftedBinaryOp),
    Divs(LiftedBinaryOp),
    DivsDp(LiftedBinaryOp),
    Modu(LiftedBinaryOp),
    ModuDp(LiftedBinaryOp),
    Mods(LiftedBinaryOp),
    ModsDp(LiftedBinaryOp),
    CmpE(LiftedBinaryOp),
    CmpNe(LiftedBinaryOp),
    CmpSlt(LiftedBinaryOp),
    CmpUlt(LiftedBinaryOp),
    CmpSle(LiftedBinaryOp),
    CmpUle(LiftedBinaryOp),
    CmpSge(LiftedBinaryOp),
    CmpUge(LiftedBinaryOp),
    CmpSgt(LiftedBinaryOp),
    CmpUgt(LiftedBinaryOp),
    TestBit(LiftedBinaryOp),
    AddOverflow(LiftedBinaryOp),
    Fadd(LiftedBinaryOp),
    Fsub(LiftedBinaryOp),
    Fmul(LiftedBinaryOp),
    Fdiv(LiftedBinaryOp),
    FcmpE(LiftedBinaryOp),
    FcmpNe(LiftedBinaryOp),
    FcmpLt(LiftedBinaryOp),
    FcmpLe(LiftedBinaryOp),
    FcmpGe(LiftedBinaryOp),
    FcmpGt(LiftedBinaryOp),
    FcmpO(LiftedBinaryOp),
    FcmpUo(LiftedBinaryOp),
    ArrayIndex(LiftedArrayIndex),
    ArrayIndexSsa(LiftedArrayIndexSsa),
    Assign(LiftedAssign),
    AssignMemSsa(LiftedAssignMemSsa),
    AssignUnpack(LiftedAssignUnpack),
    AssignUnpackMemSsa(LiftedAssignUnpackMemSsa),
    Block(LiftedBlock),
    Call(LiftedCall),
    Tailcall(LiftedCall),
    CallSsa(LiftedCallSsa),
    Case(LiftedCase),
    Const(Const),
    ConstPtr(Const),
    Import(Const),
    ConstData(LiftedConstantData),
    Deref(LiftedUnaryOp),
    AddressOf(LiftedUnaryOp),
    Neg(LiftedUnaryOp),
    Not(LiftedUnaryOp),
    Sx(LiftedUnaryOp),
    Zx(LiftedUnaryOp),
    LowPart(LiftedUnaryOp),
    BoolToInt(LiftedUnaryOp),
    UnimplMem(LiftedUnaryOp),
    Fsqrt(LiftedUnaryOp),
    Fneg(LiftedUnaryOp),
    Fabs(LiftedUnaryOp),
    FloatToInt(LiftedUnaryOp),
    IntToFloat(LiftedUnaryOp),
    FloatConv(LiftedUnaryOp),
    RoundToInt(LiftedUnaryOp),
    Floor(LiftedUnaryOp),
    Ceil(LiftedUnaryOp),
    Ftrunc(LiftedUnaryOp),
    DerefFieldSsa(LiftedDerefFieldSsa),
    DerefSsa(LiftedDerefSsa),
    ExternPtr(ExternPtr),
    FloatConst(FloatConst),
    For(LiftedForLoop),
    ForSsa(LiftedForLoopSsa),
    Goto(LiftedLabel),
    Label(LiftedLabel),
    If(LiftedIf),
    Intrinsic(LiftedIntrinsic),
    IntrinsicSsa(LiftedIntrinsicSsa),
    Jump(LiftedJump),
    MemPhi(LiftedMemPhi),
    Nop,
    Break,
    Continue,
    Noret,
    Unreachable,
    Bp,
    Undef,
    Unimpl,
    Ret(LiftedRet),
    Split(LiftedSplit),
    StructField(LiftedStructField),
    DerefField(LiftedStructField),
    Switch(LiftedSwitch),
    Syscall(LiftedSyscall),
    SyscallSsa(LiftedSyscallSsa),
    Trap(Trap),
    VarDeclare(Var),
    Var(Var),
    VarInit(LiftedVarInit),
    VarInitSsa(LiftedVarInitSsa),
    VarPhi(LiftedVarPhi),
    VarSsa(VarSsa),
    While(LiftedWhile),
    DoWhile(LiftedWhile),
    WhileSsa(LiftedWhileSsa),
    DoWhileSsa(LiftedWhileSsa),
}

impl HighLevelILLiftedInstruction {
    pub fn operands(&self) -> Vec<(&'static str, HighLevelILLiftedOperand)> {
        use HighLevelILLiftedInstructionKind::*;
        use HighLevelILLiftedOperand as Operand;
        match &self.kind {
            Adc(op) | Sbb(op) | Rlc(op) | Rrc(op) => vec![
                ("left", Operand::Expr(*op.left.clone())),
                ("right", Operand::Expr(*op.right.clone())),
                ("carry", Operand::Expr(*op.carry.clone())),
            ],
            Add(op) | Sub(op) | And(op) | Or(op) | Xor(op) | Lsl(op) | Lsr(op) | Asr(op)
            | Rol(op) | Ror(op) | Mul(op) | MuluDp(op) | MulsDp(op) | Divu(op) | DivuDp(op)
            | Divs(op) | DivsDp(op) | Modu(op) | ModuDp(op) | Mods(op) | ModsDp(op) | CmpE(op)
            | CmpNe(op) | CmpSlt(op) | CmpUlt(op) | CmpSle(op) | CmpUle(op) | CmpSge(op)
            | CmpUge(op) | CmpSgt(op) | CmpUgt(op) | TestBit(op) | AddOverflow(op) | Fadd(op)
            | Fsub(op) | Fmul(op) | Fdiv(op) | FcmpE(op) | FcmpNe(op) | FcmpLt(op) | FcmpLe(op)
            | FcmpGe(op) | FcmpGt(op) | FcmpO(op) | FcmpUo(op) => vec![
                ("left", Operand::Expr(*op.left.clone())),
                ("right", Operand::Expr(*op.right.clone())),
            ],
            ArrayIndex(op) => vec![
                ("src", Operand::Expr(*op.src.clone())),
                ("index", Operand::Expr(*op.index.clone())),
            ],
            ArrayIndexSsa(op) => vec![
                ("src", Operand::Expr(*op.src.clone())),
                ("src_memory", Operand::Int(op.src_memory)),
                ("index", Operand::Expr(*op.index.clone())),
            ],
            Assign(op) => vec![
                ("dest", Operand::Expr(*op.dest.clone())),
                ("src", Operand::Expr(*op.src.clone())),
            ],
            AssignMemSsa(op) => vec![
                ("dest", Operand::Expr(*op.dest.clone())),
                ("dest_memory", Operand::Int(op.dest_memory)),
                ("src", Operand::Expr(*op.src.clone())),
                ("src_memory", Operand::Int(op.src_memory)),
            ],
            AssignUnpack(op) => vec![
                ("dest", Operand::ExprList(op.dest.clone())),
                ("src", Operand::Expr(*op.src.clone())),
            ],
            AssignUnpackMemSsa(op) => vec![
                ("dest", Operand::ExprList(op.dest.clone())),
                ("dest_memory", Operand::Int(op.dest_memory)),
                ("src", Operand::Expr(*op.src.clone())),
                ("src_memory", Operand::Int(op.src_memory)),
            ],
            Block(op) => vec![("body", Operand::ExprList(op.body.clone()))],
            Call(op) | Tailcall(op) => vec![
                ("dest", Operand::Expr(*op.dest.clone())),
                ("params", Operand::ExprList(op.params.clone())),
            ],
            CallSsa(op) => vec![
                ("dest", Operand::Expr(*op.dest.clone())),
                ("params", Operand::ExprList(op.params.clone())),
                ("dest_memory", Operand::Int(op.dest_memory)),
                ("src_memory", Operand::Int(op.src_memory)),
            ],
            Case(op) => vec![
                ("values", Operand::ExprList(op.values.clone())),
                ("body", Operand::Expr(*op.body.clone())),
            ],
            Const(op) | ConstPtr(op) | Import(op) => vec![("constant", Operand::Int(op.constant))],
            ConstData(op) => vec![(
                "constant_data",
                Operand::ConstantData(op.constant_data.clone()),
            )],
            Deref(op) | AddressOf(op) | Neg(op) | Not(op) | Sx(op) | Zx(op) | LowPart(op)
            | BoolToInt(op) | UnimplMem(op) | Fsqrt(op) | Fneg(op) | Fabs(op) | FloatToInt(op)
            | IntToFloat(op) | FloatConv(op) | RoundToInt(op) | Floor(op) | Ceil(op)
            | Ftrunc(op) => vec![("src", Operand::Expr(*op.src.clone()))],
            DerefFieldSsa(op) => vec![
                ("src", Operand::Expr(*op.src.clone())),
                ("src_memory", Operand::Int(op.src_memory)),
                ("offset", Operand::Int(op.offset)),
                ("member_index", Operand::MemberIndex(op.member_index)),
            ],
            DerefSsa(op) => vec![
                ("src", Operand::Expr(*op.src.clone())),
                ("src_memory", Operand::Int(op.src_memory)),
            ],
            ExternPtr(op) => vec![
                ("constant", Operand::Int(op.constant)),
                ("offset", Operand::Int(op.offset)),
            ],
            FloatConst(op) => vec![("constant", Operand::Float(op.constant))],
            For(op) => vec![
                ("init", Operand::Expr(*op.init.clone())),
                ("condition", Operand::Expr(*op.condition.clone())),
                ("update", Operand::Expr(*op.update.clone())),
                ("body", Operand::Expr(*op.body.clone())),
            ],
            ForSsa(op) => vec![
                ("init", Operand::Expr(*op.init.clone())),
                ("condition_phi", Operand::Expr(*op.condition_phi.clone())),
                ("condition", Operand::Expr(*op.condition.clone())),
                ("update", Operand::Expr(*op.update.clone())),
                ("body", Operand::Expr(*op.body.clone())),
            ],
            Goto(op) | Label(op) => vec![("target", Operand::Label(op.target.clone()))],
            If(op) => vec![
                ("condition", Operand::Expr(*op.condition.clone())),
                ("cond_true", Operand::Expr(*op.cond_true.clone())),
                ("cond_false", Operand::Expr(*op.cond_false.clone())),
            ],
            Intrinsic(op) => vec![
                ("intrinsic", Operand::Intrinsic(op.intrinsic)),
                ("params", Operand::ExprList(op.params.clone())),
            ],
            IntrinsicSsa(op) => vec![
                ("intrinsic", Operand::Intrinsic(op.intrinsic)),
                ("params", Operand::ExprList(op.params.clone())),
                ("dest_memory", Operand::Int(op.dest_memory)),
                ("src_memory", Operand::Int(op.src_memory)),
            ],
            Jump(op) => vec![("dest", Operand::Expr(*op.dest.clone()))],
            MemPhi(op) => vec![
                ("dest", Operand::Int(op.dest)),
                ("src", Operand::IntList(op.src.clone())),
            ],
            Nop | Break | Continue | Noret | Unreachable | Bp | Undef | Unimpl => vec![],
            Ret(op) => vec![("src", Operand::ExprList(op.src.clone()))],
            Split(op) => vec![
                ("high", Operand::Expr(*op.high.clone())),
                ("low", Operand::Expr(*op.low.clone())),
            ],
            StructField(op) | DerefField(op) => vec![
                ("src", Operand::Expr(*op.src.clone())),
                ("offset", Operand::Int(op.offset)),
                ("member_index", Operand::MemberIndex(op.member_index)),
            ],
            Switch(op) => vec![
                ("condition", Operand::Expr(*op.condition.clone())),
                ("default", Operand::Expr(*op.default.clone())),
                ("cases", Operand::ExprList(op.cases.clone())),
            ],
            Syscall(op) => vec![("params", Operand::ExprList(op.params.clone()))],
            SyscallSsa(op) => vec![
                ("params", Operand::ExprList(op.params.clone())),
                ("dest_memory", Operand::Int(op.dest_memory)),
                ("src_memory", Operand::Int(op.src_memory)),
            ],
            Trap(op) => vec![("vector", Operand::Int(op.vector))],
            VarDeclare(op) | Var(op) => vec![("var", Operand::Var(op.var))],
            VarInit(op) => vec![
                ("dest", Operand::Var(op.dest)),
                ("src", Operand::Expr(*op.src.clone())),
            ],
            VarInitSsa(op) => vec![
                ("dest", Operand::VarSsa(op.dest)),
                ("src", Operand::Expr(*op.src.clone())),
            ],
            VarPhi(op) => vec![
                ("dest", Operand::VarSsa(op.dest)),
                ("src", Operand::VarSsaList(op.src.clone())),
            ],
            VarSsa(op) => vec![("var", Operand::VarSsa(op.var))],
            While(op) | DoWhile(op) => vec![
                ("condition", Operand::Expr(*op.condition.clone())),
                ("body", Operand::Expr(*op.body.clone())),
            ],
            WhileSsa(op) | DoWhileSsa(op) => vec![
                ("condition_phi", Operand::Expr(*op.condition_phi.clone())),
                ("condition", Operand::Expr(*op.condition.clone())),
                ("body", Operand::Expr(*op.body.clone())),
            ],
        }
    }
}