summaryrefslogtreecommitdiff
path: root/rust/src/mlil/lift.rs
blob: 15caad46e542e688420be9134e92e61650552ea5 (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
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
use std::collections::HashMap;

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

use super::operation::*;
use super::MediumLevelILFunction;

#[derive(Clone)]
pub enum MediumLevelILLiftedOperand {
    ConstantData(ConstantData),
    Intrinsic(ILIntrinsic),
    Expr(MediumLevelILLiftedInstruction),
    ExprList(Vec<MediumLevelILLiftedInstruction>),
    Float(f64),
    Int(u64),
    IntList(Vec<u64>),
    TargetMap(HashMap<u64, u64>),
    Var(Variable),
    VarList(Vec<Variable>),
    VarSsa(SSAVariable),
    VarSsaList(Vec<SSAVariable>),
}

#[derive(Clone, Debug, PartialEq)]
pub struct MediumLevelILLiftedInstruction {
    pub function: Ref<MediumLevelILFunction>,
    pub address: u64,
    pub kind: MediumLevelILLiftedInstructionKind,
}

#[derive(Clone, Debug, PartialEq)]
pub enum MediumLevelILLiftedInstructionKind {
    Nop,
    Noret,
    Bp,
    Undef,
    Unimpl,
    If(LiftedIf),
    FloatConst(FloatConst),
    Const(Constant),
    ConstPtr(Constant),
    Import(Constant),
    ExternPtr(ExternPtr),
    ConstData(LiftedConstantData),
    Jump(LiftedJump),
    RetHint(LiftedJump),
    StoreSsa(LiftedStoreSsa),
    StoreStructSsa(LiftedStoreStructSsa),
    StoreStruct(LiftedStoreStruct),
    Store(LiftedStore),
    JumpTo(LiftedJumpTo),
    Goto(Goto),
    FreeVarSlot(FreeVarSlot),
    SetVarField(LiftedSetVarField),
    SetVar(LiftedSetVar),
    FreeVarSlotSsa(FreeVarSlotSsa),
    SetVarSsaField(LiftedSetVarSsaField),
    SetVarAliasedField(LiftedSetVarSsaField),
    SetVarAliased(LiftedSetVarAliased),
    SetVarSsa(LiftedSetVarSsa),
    VarPhi(LiftedVarPhi),
    MemPhi(LiftedMemPhi),
    VarSplit(VarSplit),
    SetVarSplit(LiftedSetVarSplit),
    VarSplitSsa(VarSplitSsa),
    SetVarSplitSsa(LiftedSetVarSplitSsa),
    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),
    FcmpE(LiftedBinaryOp),
    FcmpNe(LiftedBinaryOp),
    FcmpLt(LiftedBinaryOp),
    FcmpLe(LiftedBinaryOp),
    FcmpGe(LiftedBinaryOp),
    FcmpGt(LiftedBinaryOp),
    FcmpO(LiftedBinaryOp),
    FcmpUo(LiftedBinaryOp),
    Fadd(LiftedBinaryOp),
    Fsub(LiftedBinaryOp),
    Fmul(LiftedBinaryOp),
    Fdiv(LiftedBinaryOp),
    Adc(LiftedBinaryOpCarry),
    Sbb(LiftedBinaryOpCarry),
    Rlc(LiftedBinaryOpCarry),
    Rrc(LiftedBinaryOpCarry),
    Call(LiftedCall),
    Tailcall(LiftedCall),
    Intrinsic(LiftedIntrinsic),
    Syscall(LiftedSyscallCall),
    IntrinsicSsa(LiftedIntrinsicSsa),
    CallSsa(LiftedCallSsa),
    TailcallSsa(LiftedCallSsa),
    CallUntypedSsa(LiftedCallUntypedSsa),
    TailcallUntypedSsa(LiftedCallUntypedSsa),
    SyscallSsa(LiftedSyscallSsa),
    SyscallUntypedSsa(LiftedSyscallUntypedSsa),
    CallUntyped(LiftedCallUntyped),
    TailcallUntyped(LiftedCallUntyped),
    SyscallUntyped(LiftedSyscallUntyped),
    SeparateParamList(LiftedSeparateParamList),
    SharedParamSlot(LiftedSharedParamSlot),
    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),
    Load(LiftedUnaryOp),
    LoadStruct(LiftedLoadStruct),
    LoadStructSsa(LiftedLoadStructSsa),
    LoadSsa(LiftedLoadSsa),
    Ret(LiftedRet),
    Var(Var),
    AddressOf(Var),
    VarField(Field),
    AddressOfField(Field),
    VarSsa(VarSsa),
    VarAliased(VarSsa),
    VarSsaField(VarSsaField),
    VarAliasedField(VarSsaField),
    Trap(Trap),
}

impl MediumLevelILLiftedInstruction {
    pub fn operands(&self) -> Vec<(&'static str, MediumLevelILLiftedOperand)> {
        use MediumLevelILLiftedInstructionKind::*;
        use MediumLevelILLiftedOperand as Operand;
        match &self.kind {
            Nop | Noret | Bp | Undef | Unimpl => vec![],
            If(op) => vec![
                ("condition", Operand::Expr(*op.condition.clone())),
                ("dest_true", Operand::Int(op.dest_true)),
                ("dest_false", Operand::Int(op.dest_false)),
            ],
            FloatConst(op) => vec![("constant", Operand::Float(op.constant))],
            Const(op) | ConstPtr(op) | Import(op) => vec![("constant", Operand::Int(op.constant))],
            ExternPtr(op) => vec![
                ("constant", Operand::Int(op.constant)),
                ("offset", Operand::Int(op.offset)),
            ],
            ConstData(op) => vec![(
                "constant_data",
                Operand::ConstantData(op.constant_data.clone()),
            )],
            Jump(op) | RetHint(op) => vec![("dest", Operand::Expr(*op.dest.clone()))],
            StoreSsa(op) => vec![
                ("dest", Operand::Expr(*op.dest.clone())),
                ("dest_memory", Operand::Int(op.dest_memory)),
                ("src_memory", Operand::Int(op.src_memory)),
                ("src", Operand::Expr(*op.src.clone())),
            ],
            StoreStructSsa(op) => vec![
                ("dest", Operand::Expr(*op.dest.clone())),
                ("offset", Operand::Int(op.offset)),
                ("dest_memory", Operand::Int(op.dest_memory)),
                ("src_memory", Operand::Int(op.src_memory)),
                ("src", Operand::Expr(*op.src.clone())),
            ],
            StoreStruct(op) => vec![
                ("dest", Operand::Expr(*op.dest.clone())),
                ("offset", Operand::Int(op.offset)),
                ("src", Operand::Expr(*op.src.clone())),
            ],
            Store(op) => vec![
                ("dest", Operand::Expr(*op.dest.clone())),
                ("src", Operand::Expr(*op.src.clone())),
            ],
            JumpTo(op) => vec![
                ("dest", Operand::Expr(*op.dest.clone())),
                ("targets", Operand::TargetMap(op.targets.clone())),
            ],
            Goto(op) => vec![("dest", Operand::Int(op.dest))],
            FreeVarSlot(op) => vec![("dest", Operand::Var(op.dest))],
            SetVarField(op) => vec![
                ("dest", Operand::Var(op.dest)),
                ("offset", Operand::Int(op.offset)),
                ("src", Operand::Expr(*op.src.clone())),
            ],
            SetVar(op) => vec![
                ("dest", Operand::Var(op.dest)),
                ("src", Operand::Expr(*op.src.clone())),
            ],
            FreeVarSlotSsa(op) => vec![
                ("dest", Operand::VarSsa(op.dest)),
                ("prev", Operand::VarSsa(op.prev)),
            ],
            SetVarSsaField(op) | SetVarAliasedField(op) => vec![
                ("dest", Operand::VarSsa(op.dest)),
                ("prev", Operand::VarSsa(op.prev)),
                ("offset", Operand::Int(op.offset)),
                ("src", Operand::Expr(*op.src.clone())),
            ],
            SetVarAliased(op) => vec![
                ("dest", Operand::VarSsa(op.dest)),
                ("prev", Operand::VarSsa(op.prev)),
                ("src", Operand::Expr(*op.src.clone())),
            ],
            SetVarSsa(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())),
            ],
            MemPhi(op) => vec![
                ("dest_memory", Operand::Int(op.dest_memory)),
                ("src_memory", Operand::IntList(op.src_memory.clone())),
            ],
            VarSplit(op) => vec![
                ("high", Operand::Var(op.high)),
                ("low", Operand::Var(op.low)),
            ],
            SetVarSplit(op) => vec![
                ("high", Operand::Var(op.high)),
                ("low", Operand::Var(op.low)),
                ("src", Operand::Expr(*op.src.clone())),
            ],
            VarSplitSsa(op) => vec![
                ("high", Operand::VarSsa(op.high)),
                ("low", Operand::VarSsa(op.low)),
            ],
            SetVarSplitSsa(op) => vec![
                ("high", Operand::VarSsa(op.high)),
                ("low", Operand::VarSsa(op.low)),
                ("src", Operand::Expr(*op.src.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) | FcmpE(op)
            | FcmpNe(op) | FcmpLt(op) | FcmpLe(op) | FcmpGe(op) | FcmpGt(op) | FcmpO(op)
            | FcmpUo(op) | Fadd(op) | Fsub(op) | Fmul(op) | Fdiv(op) => vec![
                ("left", Operand::Expr(*op.left.clone())),
                ("right", Operand::Expr(*op.right.clone())),
            ],
            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())),
            ],
            Call(op) | Tailcall(op) => vec![
                ("output", Operand::VarList(op.output.clone())),
                ("dest", Operand::Expr(*op.dest.clone())),
                ("params", Operand::ExprList(op.params.clone())),
            ],
            Syscall(op) => vec![
                ("output", Operand::VarList(op.output.clone())),
                ("params", Operand::ExprList(op.params.clone())),
            ],
            Intrinsic(op) => vec![
                ("output", Operand::VarList(op.output.clone())),
                ("intrinsic", Operand::Intrinsic(op.intrinsic)),
                ("params", Operand::ExprList(op.params.clone())),
            ],
            IntrinsicSsa(op) => vec![
                ("output", Operand::VarSsaList(op.output.clone())),
                ("intrinsic", Operand::Intrinsic(op.intrinsic)),
                ("params", Operand::ExprList(op.params.clone())),
            ],
            CallSsa(op) | TailcallSsa(op) => vec![
                ("output", Operand::VarSsaList(op.output.clone())),
                ("dest", Operand::Expr(*op.dest.clone())),
                ("params", Operand::ExprList(op.params.clone())),
                ("src_memory", Operand::Int(op.src_memory)),
            ],
            CallUntypedSsa(op) | TailcallUntypedSsa(op) => vec![
                ("output", Operand::VarSsaList(op.output.clone())),
                ("dest", Operand::Expr(*op.dest.clone())),
                ("params", Operand::ExprList(op.params.clone())),
                ("stack", Operand::Expr(*op.stack.clone())),
            ],
            SyscallSsa(op) => vec![
                ("output", Operand::VarSsaList(op.output.clone())),
                ("params", Operand::ExprList(op.params.clone())),
                ("src_memory", Operand::Int(op.src_memory)),
            ],
            SyscallUntypedSsa(op) => vec![
                ("output", Operand::VarSsaList(op.output.clone())),
                ("params", Operand::ExprList(op.params.clone())),
                ("stack", Operand::Expr(*op.stack.clone())),
            ],
            CallUntyped(op) | TailcallUntyped(op) => vec![
                ("output", Operand::VarList(op.output.clone())),
                ("dest", Operand::Expr(*op.dest.clone())),
                ("params", Operand::ExprList(op.params.clone())),
                ("stack", Operand::Expr(*op.stack.clone())),
            ],
            SyscallUntyped(op) => vec![
                ("output", Operand::VarList(op.output.clone())),
                ("params", Operand::ExprList(op.params.clone())),
                ("stack", Operand::Expr(*op.stack.clone())),
            ],
            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) | Load(op) => {
                vec![("src", Operand::Expr(*op.src.clone()))]
            }
            LoadStruct(op) => vec![
                ("src", Operand::Expr(*op.src.clone())),
                ("offset", Operand::Int(op.offset)),
            ],
            LoadStructSsa(op) => vec![
                ("src", Operand::Expr(*op.src.clone())),
                ("offset", Operand::Int(op.offset)),
                ("src_memory", Operand::Int(op.src_memory)),
            ],
            LoadSsa(op) => vec![
                ("src", Operand::Expr(*op.src.clone())),
                ("src_memory", Operand::Int(op.src_memory)),
            ],
            Ret(op) => vec![("src", Operand::ExprList(op.src.clone()))],
            SeparateParamList(op) => vec![("params", Operand::ExprList(op.params.clone()))],
            SharedParamSlot(op) => vec![("params", Operand::ExprList(op.params.clone()))],
            Var(op) | AddressOf(op) => vec![("src", Operand::Var(op.src))],
            VarField(op) | AddressOfField(op) => vec![
                ("src", Operand::Var(op.src)),
                ("offset", Operand::Int(op.offset)),
            ],
            VarSsa(op) | VarAliased(op) => vec![("src", Operand::VarSsa(op.src))],
            VarSsaField(op) | VarAliasedField(op) => vec![
                ("src", Operand::VarSsa(op.src)),
                ("offset", Operand::Int(op.offset)),
            ],
            Trap(op) => vec![("vector", Operand::Int(op.vector))],
        }
    }
}