1use binaryninjacore_sys::BNLowLevelILInstruction;
16use binaryninjacore_sys::{
17 BNGetLowLevelILByIndex, BNGetLowLevelILExprValue, BNGetLowLevelILPossibleExprValues,
18};
19
20use super::operation;
21use super::operation::Operation;
22use super::VisitorAction;
23use super::*;
24use crate::architecture::CoreFlagWrite;
25use crate::variable::{PossibleValueSet, RegisterValue};
26use crate::DataFlowQueryOption;
27use std::fmt;
28use std::fmt::{Debug, Display, Formatter};
29use std::marker::PhantomData;
30
31#[derive(Copy, Clone, Debug)]
33pub struct ValueExpr;
34
35#[derive(Copy, Clone, Debug)]
37pub struct VoidExpr;
38
39pub trait ExpressionResultType: 'static + Debug {}
40impl ExpressionResultType for ValueExpr {}
41impl ExpressionResultType for VoidExpr {}
42
43#[repr(transparent)]
44#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
45pub struct LowLevelExpressionIndex(pub usize);
46
47impl Display for LowLevelExpressionIndex {
48 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
49 f.write_fmt(format_args!("{}", self.0))
50 }
51}
52
53pub trait ExpressionHandler<'func, M, F>
55where
56 M: FunctionMutability,
57 F: FunctionForm,
58{
59 fn kind(&self) -> LowLevelILExpressionKind<'func, M, F>;
60
61 fn visit_tree<T>(&self, f: &mut T) -> VisitorAction
62 where
63 T: FnMut(&LowLevelILExpression<'func, M, F, ValueExpr>) -> VisitorAction;
64}
65
66#[derive(Copy)]
67pub struct LowLevelILExpression<'func, M, F, R>
68where
69 M: FunctionMutability,
70 F: FunctionForm,
71 R: ExpressionResultType,
72{
73 pub(crate) function: &'func LowLevelILFunction<M, F>,
74 pub index: LowLevelExpressionIndex,
75
76 pub(crate) _ty: PhantomData<R>,
78}
79
80impl<M, F, R> Clone for LowLevelILExpression<'_, M, F, R>
81where
82 M: FunctionMutability,
83 F: FunctionForm,
84 R: ExpressionResultType,
85{
86 fn clone(&self) -> Self {
87 Self {
88 function: self.function,
89 index: self.index,
90 _ty: PhantomData,
91 }
92 }
93}
94
95impl<'func, M, F, R> LowLevelILExpression<'func, M, F, R>
96where
97 M: FunctionMutability,
98 F: FunctionForm,
99 R: ExpressionResultType,
100{
101 pub fn new(function: &'func LowLevelILFunction<M, F>, index: LowLevelExpressionIndex) -> Self {
102 Self {
104 function,
105 index,
106 _ty: PhantomData,
107 }
108 }
109}
110
111impl<M, F, R> Debug for LowLevelILExpression<'_, M, F, R>
112where
113 M: FunctionMutability,
114 F: FunctionForm,
115 R: ExpressionResultType,
116{
117 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
118 let op = unsafe { BNGetLowLevelILByIndex(self.function.handle, self.index.0) };
119 let kind = LowLevelILExpressionKind::from_raw(self.function, op, self.index);
120 kind.fmt(f)
121 }
122}
123
124impl<M, R> LowLevelILExpression<'_, M, SSA, R>
125where
126 M: FunctionMutability,
127 R: ExpressionResultType,
128{
129 pub fn non_ssa_form<'func>(
130 &self,
131 non_ssa: &'func LowLevelILFunction<M, NonSSA>,
132 ) -> LowLevelILExpression<'func, M, NonSSA, R> {
133 use binaryninjacore_sys::BNGetLowLevelILNonSSAExprIndex;
134 let idx = unsafe { BNGetLowLevelILNonSSAExprIndex(self.function.handle, self.index.0) };
135 LowLevelILExpression::new(non_ssa, LowLevelExpressionIndex(idx))
136 }
137}
138
139impl<M, R> LowLevelILExpression<'_, M, NonSSA, R>
140where
141 M: FunctionMutability,
142 R: ExpressionResultType,
143{
144 pub fn ssa_form<'func>(
145 &self,
146 ssa: &'func LowLevelILFunction<M, SSA>,
147 ) -> LowLevelILExpression<'func, M, SSA, R> {
148 use binaryninjacore_sys::BNGetLowLevelILSSAExprIndex;
149 let idx = unsafe { BNGetLowLevelILSSAExprIndex(self.function.handle, self.index.0) };
150 LowLevelILExpression::new(ssa, LowLevelExpressionIndex(idx))
151 }
152}
153
154impl<'func, M> ExpressionHandler<'func, M, SSA> for LowLevelILExpression<'func, M, SSA, ValueExpr>
155where
156 M: FunctionMutability,
157{
158 fn kind(&self) -> LowLevelILExpressionKind<'func, M, SSA> {
159 #[allow(unused_imports)]
160 use binaryninjacore_sys::BNLowLevelILOperation::*;
161 let op = unsafe { BNGetLowLevelILByIndex(self.function.handle, self.index.0) };
162 #[allow(clippy::match_single_binding)]
163 match op.operation {
164 _ => LowLevelILExpressionKind::from_raw(self.function, op, self.index),
167 }
168 }
169
170 fn visit_tree<T>(&self, f: &mut T) -> VisitorAction
171 where
172 T: FnMut(&LowLevelILExpression<'func, M, SSA, ValueExpr>) -> VisitorAction,
173 {
174 match f(self) {
176 VisitorAction::Descend => {
177 self.kind().visit_sub_expressions(|e| e.visit_tree(f))
179 }
180 action => action,
181 }
182 }
183}
184
185impl<'func, M> ExpressionHandler<'func, M, NonSSA>
186 for LowLevelILExpression<'func, M, NonSSA, ValueExpr>
187where
188 M: FunctionMutability,
189{
190 fn kind(&self) -> LowLevelILExpressionKind<'func, M, NonSSA> {
191 #[allow(unused_imports)]
192 use binaryninjacore_sys::BNLowLevelILOperation::*;
193 let op = unsafe { BNGetLowLevelILByIndex(self.function.handle, self.index.0) };
194 #[allow(clippy::match_single_binding)]
195 match op.operation {
196 _ => LowLevelILExpressionKind::from_raw(self.function, op, self.index),
199 }
200 }
201
202 fn visit_tree<T>(&self, f: &mut T) -> VisitorAction
203 where
204 T: FnMut(&LowLevelILExpression<'func, M, NonSSA, ValueExpr>) -> VisitorAction,
205 {
206 match f(self) {
208 VisitorAction::Descend => {
209 self.kind().visit_sub_expressions(|e| e.visit_tree(f))
211 }
212 action => action,
213 }
214 }
215}
216
217impl<M, F> LowLevelILExpression<'_, M, F, ValueExpr>
218where
219 M: FunctionMutability,
220 F: FunctionForm,
221{
222 pub fn value(&self) -> RegisterValue {
226 let value = unsafe { BNGetLowLevelILExprValue(self.function.handle, self.index.0) };
227 RegisterValue::from(value)
228 }
229
230 pub fn possible_values(&self) -> PossibleValueSet {
232 self.possible_values_with_opts(&[])
233 }
234
235 pub fn possible_values_with_opts(&self, options: &[DataFlowQueryOption]) -> PossibleValueSet {
237 let value = unsafe {
238 BNGetLowLevelILPossibleExprValues(
239 self.function.handle,
240 self.index.0,
241 options.as_ptr() as *mut _,
242 options.len(),
243 )
244 };
245 PossibleValueSet::from_owned_core_raw(value)
246 }
247
248 }
250
251#[derive(Debug)]
252pub enum LowLevelILExpressionKind<'func, M, F>
253where
254 M: FunctionMutability,
255 F: FunctionForm,
256{
257 Load(Operation<'func, M, F, operation::Load>),
258 LoadSsa(Operation<'func, M, F, operation::LoadSsa>),
259 Pop(Operation<'func, M, F, operation::Pop>),
260 Reg(Operation<'func, M, F, operation::Reg>),
261 RegSsa(Operation<'func, M, F, operation::RegSsa>),
262 RegPartialSsa(Operation<'func, M, F, operation::RegPartialSsa>),
263 RegSplit(Operation<'func, M, F, operation::RegSplit>),
264 RegSplitSsa(Operation<'func, M, F, operation::RegSplitSsa>),
265 Const(Operation<'func, M, F, operation::Const>),
266 ConstPtr(Operation<'func, M, F, operation::Const>),
267 Flag(Operation<'func, M, F, operation::Flag>),
268 FlagBit(Operation<'func, M, F, operation::FlagBit>),
269 ExternPtr(Operation<'func, M, F, operation::Extern>),
270
271 RegStackPop(Operation<'func, M, F, operation::RegStackPop>),
272 RegStackFreeReg(Operation<'func, M, F, operation::RegStackPop>),
273
274 CallOutputSsa(Operation<'func, M, F, operation::CallOutputSsa>),
275 CallParamSsa(Operation<'func, M, F, operation::CallParamSsa>),
276 CallStackSsa(Operation<'func, M, F, operation::CallStackSsa>),
277
278 Add(Operation<'func, M, F, operation::BinaryOp>),
279 AddOverflow(Operation<'func, M, F, operation::BinaryOp>),
280 Adc(Operation<'func, M, F, operation::BinaryOpCarry>),
281 Sub(Operation<'func, M, F, operation::BinaryOp>),
282 Sbb(Operation<'func, M, F, operation::BinaryOpCarry>),
283 And(Operation<'func, M, F, operation::BinaryOp>),
284 Or(Operation<'func, M, F, operation::BinaryOp>),
285 Xor(Operation<'func, M, F, operation::BinaryOp>),
286 Lsl(Operation<'func, M, F, operation::BinaryOp>),
287 Lsr(Operation<'func, M, F, operation::BinaryOp>),
288 Asr(Operation<'func, M, F, operation::BinaryOp>),
289 Rol(Operation<'func, M, F, operation::BinaryOp>),
290 Rlc(Operation<'func, M, F, operation::BinaryOpCarry>),
291 Ror(Operation<'func, M, F, operation::BinaryOp>),
292 Rrc(Operation<'func, M, F, operation::BinaryOpCarry>),
293 Mul(Operation<'func, M, F, operation::BinaryOp>),
294
295 MulsDp(Operation<'func, M, F, operation::BinaryOp>),
296 MuluDp(Operation<'func, M, F, operation::BinaryOp>),
297
298 Divu(Operation<'func, M, F, operation::BinaryOp>),
299 Divs(Operation<'func, M, F, operation::BinaryOp>),
300
301 DivuDp(Operation<'func, M, F, operation::BinaryOp>),
302 DivsDp(Operation<'func, M, F, operation::BinaryOp>),
303
304 Modu(Operation<'func, M, F, operation::BinaryOp>),
305 Mods(Operation<'func, M, F, operation::BinaryOp>),
306
307 ModuDp(Operation<'func, M, F, operation::BinaryOp>),
308 ModsDp(Operation<'func, M, F, operation::BinaryOp>),
309
310 Neg(Operation<'func, M, F, operation::UnaryOp>),
311 Not(Operation<'func, M, F, operation::UnaryOp>),
312 Sx(Operation<'func, M, F, operation::UnaryOp>),
313 Zx(Operation<'func, M, F, operation::UnaryOp>),
314 LowPart(Operation<'func, M, F, operation::UnaryOp>),
315
316 FlagCond(Operation<'func, M, F, operation::FlagCond>),
318 FlagGroup(Operation<'func, M, F, operation::FlagGroup>),
320
321 CmpE(Operation<'func, M, F, operation::Condition>),
322 CmpNe(Operation<'func, M, F, operation::Condition>),
323 CmpSlt(Operation<'func, M, F, operation::Condition>),
324 CmpUlt(Operation<'func, M, F, operation::Condition>),
325 CmpSle(Operation<'func, M, F, operation::Condition>),
326 CmpUle(Operation<'func, M, F, operation::Condition>),
327 CmpSge(Operation<'func, M, F, operation::Condition>),
328 CmpUge(Operation<'func, M, F, operation::Condition>),
329 CmpSgt(Operation<'func, M, F, operation::Condition>),
330 CmpUgt(Operation<'func, M, F, operation::Condition>),
331
332 TestBit(Operation<'func, M, F, operation::BinaryOp>),
333 BoolToInt(Operation<'func, M, F, operation::UnaryOp>),
334
335 Fadd(Operation<'func, M, F, operation::BinaryOp>),
336 Fsub(Operation<'func, M, F, operation::BinaryOp>),
337 Fmul(Operation<'func, M, F, operation::BinaryOp>),
338 Fdiv(Operation<'func, M, F, operation::BinaryOp>),
339 Fsqrt(Operation<'func, M, F, operation::UnaryOp>),
340 Fneg(Operation<'func, M, F, operation::UnaryOp>),
341 Fabs(Operation<'func, M, F, operation::UnaryOp>),
342 FloatToInt(Operation<'func, M, F, operation::UnaryOp>),
343 IntToFloat(Operation<'func, M, F, operation::UnaryOp>),
344 FloatConv(Operation<'func, M, F, operation::UnaryOp>),
345 RoundToInt(Operation<'func, M, F, operation::UnaryOp>),
346 Floor(Operation<'func, M, F, operation::UnaryOp>),
347 Ceil(Operation<'func, M, F, operation::UnaryOp>),
348 Ftrunc(Operation<'func, M, F, operation::UnaryOp>),
349
350 FloatConst(Operation<'func, M, F, operation::FloatConst>),
351
352 FcmpE(Operation<'func, M, F, operation::Condition>),
353 FcmpNE(Operation<'func, M, F, operation::Condition>),
354 FcmpLT(Operation<'func, M, F, operation::Condition>),
355 FcmpLE(Operation<'func, M, F, operation::Condition>),
356 FcmpGE(Operation<'func, M, F, operation::Condition>),
357 FcmpGT(Operation<'func, M, F, operation::Condition>),
358 FcmpO(Operation<'func, M, F, operation::Condition>),
359 FcmpUO(Operation<'func, M, F, operation::Condition>),
360
361 SeparateParamListSsa(Operation<'func, M, F, operation::SeparateParamListSsa>),
362
363 Unimpl(Operation<'func, M, F, operation::NoArgs>),
364 UnimplMem(Operation<'func, M, F, operation::UnimplMem>),
365
366 Undef(Operation<'func, M, F, operation::NoArgs>),
367}
368
369impl<'func, M, F> LowLevelILExpressionKind<'func, M, F>
370where
371 M: FunctionMutability,
372 F: FunctionForm,
373{
374 pub(crate) fn from_raw(
375 function: &'func LowLevelILFunction<M, F>,
376 op: BNLowLevelILInstruction,
377 index: LowLevelExpressionIndex,
378 ) -> Self {
379 use binaryninjacore_sys::BNLowLevelILOperation::*;
380
381 match op.operation {
382 LLIL_LOAD => LowLevelILExpressionKind::Load(Operation::new(function, op, index)),
383 LLIL_LOAD_SSA => LowLevelILExpressionKind::LoadSsa(Operation::new(function, op, index)),
384 LLIL_POP => LowLevelILExpressionKind::Pop(Operation::new(function, op, index)),
385 LLIL_REG => LowLevelILExpressionKind::Reg(Operation::new(function, op, index)),
386 LLIL_REG_SSA => LowLevelILExpressionKind::RegSsa(Operation::new(function, op, index)),
387 LLIL_REG_SSA_PARTIAL => {
388 LowLevelILExpressionKind::RegPartialSsa(Operation::new(function, op, index))
389 }
390 LLIL_REG_SPLIT => {
391 LowLevelILExpressionKind::RegSplit(Operation::new(function, op, index))
392 }
393 LLIL_REG_SPLIT_SSA => {
394 LowLevelILExpressionKind::RegSplitSsa(Operation::new(function, op, index))
395 }
396 LLIL_CONST => LowLevelILExpressionKind::Const(Operation::new(function, op, index)),
397 LLIL_CONST_PTR => {
398 LowLevelILExpressionKind::ConstPtr(Operation::new(function, op, index))
399 }
400 LLIL_FLAG | LLIL_FLAG_SSA => {
401 LowLevelILExpressionKind::Flag(Operation::new(function, op, index))
402 }
403 LLIL_FLAG_GROUP => {
404 LowLevelILExpressionKind::FlagGroup(Operation::new(function, op, index))
405 }
406 LLIL_FLAG_COND => {
407 LowLevelILExpressionKind::FlagCond(Operation::new(function, op, index))
408 }
409 LLIL_FLAG_BIT | LLIL_FLAG_BIT_SSA => {
410 LowLevelILExpressionKind::FlagBit(Operation::new(function, op, index))
411 }
412 LLIL_EXTERN_PTR => {
413 LowLevelILExpressionKind::ExternPtr(Operation::new(function, op, index))
414 }
415
416 LLIL_REG_STACK_POP => {
417 LowLevelILExpressionKind::RegStackPop(Operation::new(function, op, index))
418 }
419 LLIL_REG_STACK_FREE_REG => {
420 LowLevelILExpressionKind::RegStackFreeReg(Operation::new(function, op, index))
421 }
422
423 LLIL_CALL_OUTPUT_SSA => {
424 LowLevelILExpressionKind::CallOutputSsa(Operation::new(function, op, index))
425 }
426 LLIL_CALL_PARAM => {
427 LowLevelILExpressionKind::CallParamSsa(Operation::new(function, op, index))
428 }
429 LLIL_CALL_STACK_SSA => {
430 LowLevelILExpressionKind::CallStackSsa(Operation::new(function, op, index))
431 }
432
433 LLIL_ADD => LowLevelILExpressionKind::Add(Operation::new(function, op, index)),
434 LLIL_ADD_OVERFLOW => {
435 LowLevelILExpressionKind::AddOverflow(Operation::new(function, op, index))
436 }
437 LLIL_ADC => LowLevelILExpressionKind::Adc(Operation::new(function, op, index)),
438 LLIL_SUB => LowLevelILExpressionKind::Sub(Operation::new(function, op, index)),
439 LLIL_SBB => LowLevelILExpressionKind::Sbb(Operation::new(function, op, index)),
440 LLIL_AND => LowLevelILExpressionKind::And(Operation::new(function, op, index)),
441 LLIL_OR => LowLevelILExpressionKind::Or(Operation::new(function, op, index)),
442 LLIL_XOR => LowLevelILExpressionKind::Xor(Operation::new(function, op, index)),
443 LLIL_LSL => LowLevelILExpressionKind::Lsl(Operation::new(function, op, index)),
444 LLIL_LSR => LowLevelILExpressionKind::Lsr(Operation::new(function, op, index)),
445 LLIL_ASR => LowLevelILExpressionKind::Asr(Operation::new(function, op, index)),
446 LLIL_ROL => LowLevelILExpressionKind::Rol(Operation::new(function, op, index)),
447 LLIL_RLC => LowLevelILExpressionKind::Rlc(Operation::new(function, op, index)),
448 LLIL_ROR => LowLevelILExpressionKind::Ror(Operation::new(function, op, index)),
449 LLIL_RRC => LowLevelILExpressionKind::Rrc(Operation::new(function, op, index)),
450 LLIL_MUL => LowLevelILExpressionKind::Mul(Operation::new(function, op, index)),
451
452 LLIL_MULU_DP => LowLevelILExpressionKind::MuluDp(Operation::new(function, op, index)),
453 LLIL_MULS_DP => LowLevelILExpressionKind::MulsDp(Operation::new(function, op, index)),
454
455 LLIL_DIVU => LowLevelILExpressionKind::Divu(Operation::new(function, op, index)),
456 LLIL_DIVS => LowLevelILExpressionKind::Divs(Operation::new(function, op, index)),
457
458 LLIL_DIVU_DP => LowLevelILExpressionKind::DivuDp(Operation::new(function, op, index)),
459 LLIL_DIVS_DP => LowLevelILExpressionKind::DivsDp(Operation::new(function, op, index)),
460
461 LLIL_MODU => LowLevelILExpressionKind::Modu(Operation::new(function, op, index)),
462 LLIL_MODS => LowLevelILExpressionKind::Mods(Operation::new(function, op, index)),
463
464 LLIL_MODU_DP => LowLevelILExpressionKind::ModuDp(Operation::new(function, op, index)),
465 LLIL_MODS_DP => LowLevelILExpressionKind::ModsDp(Operation::new(function, op, index)),
466
467 LLIL_NEG => LowLevelILExpressionKind::Neg(Operation::new(function, op, index)),
468 LLIL_NOT => LowLevelILExpressionKind::Not(Operation::new(function, op, index)),
469
470 LLIL_SX => LowLevelILExpressionKind::Sx(Operation::new(function, op, index)),
471 LLIL_ZX => LowLevelILExpressionKind::Zx(Operation::new(function, op, index)),
472 LLIL_LOW_PART => LowLevelILExpressionKind::LowPart(Operation::new(function, op, index)),
473
474 LLIL_CMP_E => LowLevelILExpressionKind::CmpE(Operation::new(function, op, index)),
475 LLIL_CMP_NE => LowLevelILExpressionKind::CmpNe(Operation::new(function, op, index)),
476 LLIL_CMP_SLT => LowLevelILExpressionKind::CmpSlt(Operation::new(function, op, index)),
477 LLIL_CMP_ULT => LowLevelILExpressionKind::CmpUlt(Operation::new(function, op, index)),
478 LLIL_CMP_SLE => LowLevelILExpressionKind::CmpSle(Operation::new(function, op, index)),
479 LLIL_CMP_ULE => LowLevelILExpressionKind::CmpUle(Operation::new(function, op, index)),
480 LLIL_CMP_SGE => LowLevelILExpressionKind::CmpSge(Operation::new(function, op, index)),
481 LLIL_CMP_UGE => LowLevelILExpressionKind::CmpUge(Operation::new(function, op, index)),
482 LLIL_CMP_SGT => LowLevelILExpressionKind::CmpSgt(Operation::new(function, op, index)),
483 LLIL_CMP_UGT => LowLevelILExpressionKind::CmpUgt(Operation::new(function, op, index)),
484
485 LLIL_TEST_BIT => LowLevelILExpressionKind::TestBit(Operation::new(function, op, index)),
486 LLIL_BOOL_TO_INT => {
487 LowLevelILExpressionKind::BoolToInt(Operation::new(function, op, index))
488 }
489
490 LLIL_FADD => LowLevelILExpressionKind::Fadd(Operation::new(function, op, index)),
491 LLIL_FSUB => LowLevelILExpressionKind::Fsub(Operation::new(function, op, index)),
492 LLIL_FMUL => LowLevelILExpressionKind::Fmul(Operation::new(function, op, index)),
493 LLIL_FDIV => LowLevelILExpressionKind::Fdiv(Operation::new(function, op, index)),
494
495 LLIL_FSQRT => LowLevelILExpressionKind::Fsqrt(Operation::new(function, op, index)),
496 LLIL_FNEG => LowLevelILExpressionKind::Fneg(Operation::new(function, op, index)),
497 LLIL_FABS => LowLevelILExpressionKind::Fabs(Operation::new(function, op, index)),
498 LLIL_FLOAT_TO_INT => {
499 LowLevelILExpressionKind::FloatToInt(Operation::new(function, op, index))
500 }
501 LLIL_INT_TO_FLOAT => {
502 LowLevelILExpressionKind::IntToFloat(Operation::new(function, op, index))
503 }
504 LLIL_FLOAT_CONV => {
505 LowLevelILExpressionKind::FloatConv(Operation::new(function, op, index))
506 }
507 LLIL_ROUND_TO_INT => {
508 LowLevelILExpressionKind::RoundToInt(Operation::new(function, op, index))
509 }
510 LLIL_FLOOR => LowLevelILExpressionKind::Floor(Operation::new(function, op, index)),
511 LLIL_CEIL => LowLevelILExpressionKind::Ceil(Operation::new(function, op, index)),
512 LLIL_FTRUNC => LowLevelILExpressionKind::Ftrunc(Operation::new(function, op, index)),
513
514 LLIL_FCMP_E => LowLevelILExpressionKind::FcmpE(Operation::new(function, op, index)),
515 LLIL_FCMP_NE => LowLevelILExpressionKind::FcmpNE(Operation::new(function, op, index)),
516 LLIL_FCMP_LT => LowLevelILExpressionKind::FcmpLT(Operation::new(function, op, index)),
517 LLIL_FCMP_LE => LowLevelILExpressionKind::FcmpLE(Operation::new(function, op, index)),
518 LLIL_FCMP_GT => LowLevelILExpressionKind::FcmpGT(Operation::new(function, op, index)),
519 LLIL_FCMP_GE => LowLevelILExpressionKind::FcmpGE(Operation::new(function, op, index)),
520 LLIL_FCMP_O => LowLevelILExpressionKind::FcmpO(Operation::new(function, op, index)),
521 LLIL_FCMP_UO => LowLevelILExpressionKind::FcmpUO(Operation::new(function, op, index)),
522
523 LLIL_FLOAT_CONST => {
524 LowLevelILExpressionKind::FloatConst(Operation::new(function, op, index))
525 }
526
527 LLIL_SEPARATE_PARAM_LIST_SSA => {
528 LowLevelILExpressionKind::SeparateParamListSsa(Operation::new(function, op, index))
529 }
530
531 LLIL_UNDEF => LowLevelILExpressionKind::Undef(Operation::new(function, op, index)),
532
533 LLIL_UNIMPL => LowLevelILExpressionKind::Unimpl(Operation::new(function, op, index)),
534 LLIL_UNIMPL_MEM => {
535 LowLevelILExpressionKind::UnimplMem(Operation::new(function, op, index))
536 }
537
538 _ => {
539 log::error!(
541 "Got unexpected operation {:?} in value expr at 0x{:x}",
542 op.operation,
543 op.address
544 );
545
546 LowLevelILExpressionKind::Undef(Operation::new(function, op, index))
547 }
548 }
549 }
550
551 pub fn size(&self) -> Option<usize> {
556 use self::LowLevelILExpressionKind::*;
557
558 match *self {
559 Undef(..) | Unimpl(..) => None,
560
561 FlagCond(..) | FlagGroup(..) | CmpE(..) | CmpNe(..) | CmpSlt(..) | CmpUlt(..)
562 | CmpSle(..) | CmpUle(..) | CmpSge(..) | CmpUge(..) | CmpSgt(..) | CmpUgt(..) => {
563 Some(0)
564 }
565
566 _ => Some(self.raw_struct().size),
567 }
568 }
569
570 pub fn address(&self) -> u64 {
571 self.raw_struct().address
572 }
573
574 pub fn is_same_op_as(&self, other: &Self) -> bool {
578 use self::LowLevelILExpressionKind::*;
579
580 match (self, other) {
581 (&Reg(..), &Reg(..)) => true,
582 _ => self.raw_struct().operation == other.raw_struct().operation,
583 }
584 }
585
586 pub fn as_cmp_op(&self) -> Option<&Operation<'func, M, F, operation::Condition>> {
587 use self::LowLevelILExpressionKind::*;
588
589 match *self {
590 CmpE(ref op) | CmpNe(ref op) | CmpSlt(ref op) | CmpUlt(ref op) | CmpSle(ref op)
591 | CmpUle(ref op) | CmpSge(ref op) | CmpUge(ref op) | CmpSgt(ref op)
592 | CmpUgt(ref op) | FcmpE(ref op) | FcmpNE(ref op) | FcmpLT(ref op) | FcmpLE(ref op)
593 | FcmpGE(ref op) | FcmpGT(ref op) | FcmpO(ref op) | FcmpUO(ref op) => Some(op),
594 _ => None,
595 }
596 }
597
598 pub fn as_binary_op(&self) -> Option<&Operation<'func, M, F, operation::BinaryOp>> {
599 use self::LowLevelILExpressionKind::*;
600
601 match *self {
602 Add(ref op) | Sub(ref op) | And(ref op) | Or(ref op) | Xor(ref op) | Lsl(ref op)
603 | Lsr(ref op) | Asr(ref op) | Rol(ref op) | Ror(ref op) | Mul(ref op)
604 | MulsDp(ref op) | MuluDp(ref op) | Divu(ref op) | Divs(ref op) | Modu(ref op)
605 | Mods(ref op) | Fadd(ref op) | Fsub(ref op) | Fmul(ref op) | Fdiv(ref op)
606 | DivuDp(ref op) | DivsDp(ref op) | ModuDp(ref op) | ModsDp(ref op) => Some(op),
607 _ => None,
608 }
609 }
610
611 pub fn as_binary_op_carry(&self) -> Option<&Operation<'func, M, F, operation::BinaryOpCarry>> {
612 use self::LowLevelILExpressionKind::*;
613
614 match *self {
615 Adc(ref op) | Sbb(ref op) | Rlc(ref op) | Rrc(ref op) => Some(op),
616 _ => None,
617 }
618 }
619
620 pub fn as_unary_op(&self) -> Option<&Operation<'func, M, F, operation::UnaryOp>> {
621 use self::LowLevelILExpressionKind::*;
622
623 match *self {
624 Neg(ref op) | Not(ref op) | Sx(ref op) | Zx(ref op) | LowPart(ref op)
625 | BoolToInt(ref op) | Fsqrt(ref op) | Fneg(ref op) | Fabs(ref op)
626 | FloatToInt(ref op) | IntToFloat(ref op) | FloatConv(ref op) | RoundToInt(ref op)
627 | Floor(ref op) | Ceil(ref op) | Ftrunc(ref op) => Some(op),
628 _ => None,
629 }
630 }
631
632 pub fn visit_sub_expressions<T>(&self, mut visitor: T) -> VisitorAction
633 where
634 T: FnMut(LowLevelILExpression<'func, M, F, ValueExpr>) -> VisitorAction,
635 {
636 use LowLevelILExpressionKind::*;
637
638 macro_rules! visit {
639 ($expr:expr) => {
640 if let VisitorAction::Halt = visitor($expr) {
641 return VisitorAction::Halt;
642 }
643 };
644 }
645
646 match self {
647 CmpE(ref op) | CmpNe(ref op) | CmpSlt(ref op) | CmpUlt(ref op) | CmpSle(ref op)
648 | CmpUle(ref op) | CmpSge(ref op) | CmpUge(ref op) | CmpSgt(ref op)
649 | CmpUgt(ref op) | FcmpE(ref op) | FcmpNE(ref op) | FcmpLT(ref op) | FcmpLE(ref op)
650 | FcmpGE(ref op) | FcmpGT(ref op) | FcmpO(ref op) | FcmpUO(ref op) => {
651 visit!(op.left());
652 visit!(op.right());
653 }
654 Adc(ref op) | Sbb(ref op) | Rlc(ref op) | Rrc(ref op) => {
655 visit!(op.left());
656 visit!(op.right());
657 visit!(op.carry());
658 }
659 Add(ref op) | AddOverflow(ref op) | Sub(ref op) | And(ref op) | Or(ref op)
660 | Xor(ref op) | Lsl(ref op) | Lsr(ref op) | Asr(ref op) | Rol(ref op) | Ror(ref op)
661 | Mul(ref op) | MulsDp(ref op) | MuluDp(ref op) | Divu(ref op) | Divs(ref op)
662 | Modu(ref op) | Mods(ref op) | Fadd(ref op) | Fsub(ref op) | Fmul(ref op)
663 | DivuDp(ref op) | DivsDp(ref op) | ModuDp(ref op) | ModsDp(ref op) | Fdiv(ref op)
664 | TestBit(ref op) => {
665 visit!(op.left());
666 visit!(op.right());
667 }
668 Neg(ref op) | Not(ref op) | Sx(ref op) | Zx(ref op) | LowPart(ref op)
669 | BoolToInt(ref op) | Fsqrt(ref op) | Fneg(ref op) | Fabs(ref op)
670 | FloatToInt(ref op) | IntToFloat(ref op) | FloatConv(ref op) | RoundToInt(ref op)
671 | Floor(ref op) | Ceil(ref op) | Ftrunc(ref op) => {
672 visit!(op.operand());
673 }
674 UnimplMem(ref op) => {
675 visit!(op.mem_expr());
676 }
677 Load(ref op) => {
678 visit!(op.source_expr());
679 }
680 LoadSsa(ref op) => {
681 visit!(op.source_expr());
682 }
683 CallParamSsa(ref op) => {
684 for param_expr in op.param_exprs() {
685 visit!(param_expr);
686 }
687 }
688 SeparateParamListSsa(ref op) => {
689 for param_expr in op.param_exprs() {
690 visit!(param_expr);
691 }
692 }
693 Pop(_) | Reg(_) | RegSsa(_) | RegPartialSsa(_) | RegSplit(_) | RegSplitSsa(_)
695 | Const(_) | ConstPtr(_) | Flag(_) | FlagBit(_) | ExternPtr(_) | FlagCond(_)
696 | FlagGroup(_) | Unimpl(_) | Undef(_) | RegStackPop(_) | RegStackFreeReg(_)
697 | CallOutputSsa(_) | CallStackSsa(_) | FloatConst(_) => {}
698 }
699
700 VisitorAction::Sibling
701 }
702
703 pub(crate) fn raw_struct(&self) -> &BNLowLevelILInstruction {
704 use self::LowLevelILExpressionKind::*;
705
706 match *self {
707 Undef(ref op) => &op.op,
708
709 Unimpl(ref op) => &op.op,
710
711 FlagCond(ref op) => &op.op,
712 FlagGroup(ref op) => &op.op,
713
714 CmpE(ref op) | CmpNe(ref op) | CmpSlt(ref op) | CmpUlt(ref op) | CmpSle(ref op)
715 | CmpUle(ref op) | CmpSge(ref op) | CmpUge(ref op) | CmpSgt(ref op)
716 | CmpUgt(ref op) | FcmpE(ref op) | FcmpNE(ref op) | FcmpLT(ref op) | FcmpLE(ref op)
717 | FcmpGE(ref op) | FcmpGT(ref op) | FcmpO(ref op) | FcmpUO(ref op) => &op.op,
718
719 Load(ref op) => &op.op,
720
721 LoadSsa(ref op) => &op.op,
722
723 Pop(ref op) => &op.op,
724
725 Reg(ref op) => &op.op,
726
727 RegSsa(ref op) => &op.op,
728
729 RegPartialSsa(ref op) => &op.op,
730
731 RegSplit(ref op) => &op.op,
732
733 RegSplitSsa(ref op) => &op.op,
734
735 Flag(ref op) => &op.op,
736
737 FlagBit(ref op) => &op.op,
738
739 Const(ref op) | ConstPtr(ref op) => &op.op,
740
741 FloatConst(ref op) => &op.op,
742
743 ExternPtr(ref op) => &op.op,
744
745 RegStackPop(ref op) => &op.op,
746 RegStackFreeReg(ref op) => &op.op,
747
748 CallOutputSsa(ref op) => &op.op,
749 CallParamSsa(ref op) => &op.op,
750 CallStackSsa(ref op) => &op.op,
751
752 Adc(ref op) | Sbb(ref op) | Rlc(ref op) | Rrc(ref op) => &op.op,
753
754 Add(ref op) | AddOverflow(ref op) | Sub(ref op) | And(ref op) | Or(ref op)
755 | Xor(ref op) | Lsl(ref op) | Lsr(ref op) | Asr(ref op) | Rol(ref op) | Ror(ref op)
756 | Mul(ref op) | MulsDp(ref op) | MuluDp(ref op) | Divu(ref op) | Divs(ref op)
757 | Modu(ref op) | Mods(ref op) | Fadd(ref op) | Fsub(ref op) | Fmul(ref op)
758 | Fdiv(ref op) | TestBit(ref op) => &op.op,
759
760 DivuDp(ref op) | DivsDp(ref op) | ModuDp(ref op) | ModsDp(ref op) => &op.op,
761
762 Neg(ref op) | Not(ref op) | Sx(ref op) | Zx(ref op) | LowPart(ref op)
763 | BoolToInt(ref op) | Fsqrt(ref op) | Fneg(ref op) | Fabs(ref op)
764 | FloatToInt(ref op) | IntToFloat(ref op) | FloatConv(ref op) | RoundToInt(ref op)
765 | Floor(ref op) | Ceil(ref op) | Ftrunc(ref op) => &op.op,
766
767 SeparateParamListSsa(ref op) => &op.op,
768
769 UnimplMem(ref op) => &op.op,
770 }
771 }
772}
773
774impl LowLevelILExpressionKind<'_, Mutable, NonSSA> {
775 pub fn flag_write(&self) -> Option<CoreFlagWrite> {
776 use self::LowLevelILExpressionKind::*;
777
778 match *self {
779 Undef(ref _op) => None,
780
781 Unimpl(ref _op) => None,
782
783 FlagCond(ref _op) => None,
784 FlagGroup(ref _op) => None,
785
786 CmpE(ref _op) | CmpNe(ref _op) | CmpSlt(ref _op) | CmpUlt(ref _op)
787 | CmpSle(ref _op) | CmpUle(ref _op) | CmpSge(ref _op) | CmpUge(ref _op)
788 | CmpSgt(ref _op) | CmpUgt(ref _op) | FcmpE(ref _op) | FcmpNE(ref _op)
789 | FcmpLT(ref _op) | FcmpLE(ref _op) | FcmpGE(ref _op) | FcmpGT(ref _op)
790 | FcmpO(ref _op) | FcmpUO(ref _op) => None,
791
792 Load(ref op) => op.flag_write(),
793
794 LoadSsa(ref op) => op.flag_write(),
795
796 Pop(ref op) => op.flag_write(),
797
798 Reg(ref op) => op.flag_write(),
799
800 RegSsa(ref op) => op.flag_write(),
801
802 RegPartialSsa(ref op) => op.flag_write(),
803
804 RegSplit(ref op) => op.flag_write(),
805
806 RegSplitSsa(ref op) => op.flag_write(),
807
808 Flag(ref op) => op.flag_write(),
809
810 FlagBit(ref op) => op.flag_write(),
811
812 Const(ref op) | ConstPtr(ref op) => op.flag_write(),
813
814 FloatConst(ref op) => op.flag_write(),
815
816 ExternPtr(ref op) => op.flag_write(),
817
818 RegStackPop(ref op) => op.flag_write(),
819 RegStackFreeReg(ref op) => op.flag_write(),
820
821 CallOutputSsa(ref op) => op.flag_write(),
822 CallParamSsa(ref op) => op.flag_write(),
823 CallStackSsa(ref op) => op.flag_write(),
824
825 Adc(ref op) | Sbb(ref op) | Rlc(ref op) | Rrc(ref op) => op.flag_write(),
826
827 Add(ref op) | AddOverflow(ref op) | Sub(ref op) | And(ref op) | Or(ref op)
828 | Xor(ref op) | Lsl(ref op) | Lsr(ref op) | Asr(ref op) | Rol(ref op) | Ror(ref op)
829 | Mul(ref op) | MulsDp(ref op) | MuluDp(ref op) | Divu(ref op) | Divs(ref op)
830 | Modu(ref op) | Mods(ref op) | Fadd(ref op) | Fsub(ref op) | Fmul(ref op)
831 | Fdiv(ref op) | TestBit(ref op) => op.flag_write(),
832
833 DivuDp(ref op) | DivsDp(ref op) | ModuDp(ref op) | ModsDp(ref op) => op.flag_write(),
834
835 Neg(ref op) | Not(ref op) | Sx(ref op) | Zx(ref op) | LowPart(ref op)
836 | BoolToInt(ref op) | Fsqrt(ref op) | Fneg(ref op) | Fabs(ref op)
837 | FloatToInt(ref op) | IntToFloat(ref op) | FloatConv(ref op) | RoundToInt(ref op)
838 | Floor(ref op) | Ceil(ref op) | Ftrunc(ref op) => op.flag_write(),
839
840 SeparateParamListSsa(ref op) => op.flag_write(),
841
842 UnimplMem(ref op) => op.flag_write(),
843 }
844 }
845}