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 Bswap(Operation<'func, M, F, operation::UnaryOp>),
313 Popcnt(Operation<'func, M, F, operation::UnaryOp>),
314 Clz(Operation<'func, M, F, operation::UnaryOp>),
315 Ctz(Operation<'func, M, F, operation::UnaryOp>),
316 Rbit(Operation<'func, M, F, operation::UnaryOp>),
317 Cls(Operation<'func, M, F, operation::UnaryOp>),
318
319 MinSigned(Operation<'func, M, F, operation::BinaryOp>),
320 MaxSigned(Operation<'func, M, F, operation::BinaryOp>),
321 MinUnsigned(Operation<'func, M, F, operation::BinaryOp>),
322 MaxUnsigned(Operation<'func, M, F, operation::BinaryOp>),
323 Abs(Operation<'func, M, F, operation::UnaryOp>),
324
325 Sx(Operation<'func, M, F, operation::UnaryOp>),
326 Zx(Operation<'func, M, F, operation::UnaryOp>),
327 LowPart(Operation<'func, M, F, operation::UnaryOp>),
328
329 FlagCond(Operation<'func, M, F, operation::FlagCond>),
331 FlagGroup(Operation<'func, M, F, operation::FlagGroup>),
333
334 CmpE(Operation<'func, M, F, operation::Condition>),
335 CmpNe(Operation<'func, M, F, operation::Condition>),
336 CmpSlt(Operation<'func, M, F, operation::Condition>),
337 CmpUlt(Operation<'func, M, F, operation::Condition>),
338 CmpSle(Operation<'func, M, F, operation::Condition>),
339 CmpUle(Operation<'func, M, F, operation::Condition>),
340 CmpSge(Operation<'func, M, F, operation::Condition>),
341 CmpUge(Operation<'func, M, F, operation::Condition>),
342 CmpSgt(Operation<'func, M, F, operation::Condition>),
343 CmpUgt(Operation<'func, M, F, operation::Condition>),
344
345 TestBit(Operation<'func, M, F, operation::BinaryOp>),
346 BoolToInt(Operation<'func, M, F, operation::UnaryOp>),
347
348 Fadd(Operation<'func, M, F, operation::BinaryOp>),
349 Fsub(Operation<'func, M, F, operation::BinaryOp>),
350 Fmul(Operation<'func, M, F, operation::BinaryOp>),
351 Fdiv(Operation<'func, M, F, operation::BinaryOp>),
352 Fsqrt(Operation<'func, M, F, operation::UnaryOp>),
353 Fneg(Operation<'func, M, F, operation::UnaryOp>),
354 Fabs(Operation<'func, M, F, operation::UnaryOp>),
355 FloatToInt(Operation<'func, M, F, operation::UnaryOp>),
356 IntToFloat(Operation<'func, M, F, operation::UnaryOp>),
357 FloatConv(Operation<'func, M, F, operation::UnaryOp>),
358 RoundToInt(Operation<'func, M, F, operation::UnaryOp>),
359 Floor(Operation<'func, M, F, operation::UnaryOp>),
360 Ceil(Operation<'func, M, F, operation::UnaryOp>),
361 Ftrunc(Operation<'func, M, F, operation::UnaryOp>),
362
363 FloatConst(Operation<'func, M, F, operation::FloatConst>),
364
365 FcmpE(Operation<'func, M, F, operation::Condition>),
366 FcmpNE(Operation<'func, M, F, operation::Condition>),
367 FcmpLT(Operation<'func, M, F, operation::Condition>),
368 FcmpLE(Operation<'func, M, F, operation::Condition>),
369 FcmpGE(Operation<'func, M, F, operation::Condition>),
370 FcmpGT(Operation<'func, M, F, operation::Condition>),
371 FcmpO(Operation<'func, M, F, operation::Condition>),
372 FcmpUO(Operation<'func, M, F, operation::Condition>),
373
374 SeparateParamListSsa(Operation<'func, M, F, operation::SeparateParamListSsa>),
375
376 Unimpl(Operation<'func, M, F, operation::NoArgs>),
377 UnimplMem(Operation<'func, M, F, operation::UnimplMem>),
378
379 Undef(Operation<'func, M, F, operation::NoArgs>),
380}
381
382impl<'func, M, F> LowLevelILExpressionKind<'func, M, F>
383where
384 M: FunctionMutability,
385 F: FunctionForm,
386{
387 pub(crate) fn from_raw(
388 function: &'func LowLevelILFunction<M, F>,
389 op: BNLowLevelILInstruction,
390 index: LowLevelExpressionIndex,
391 ) -> Self {
392 use binaryninjacore_sys::BNLowLevelILOperation::*;
393
394 match op.operation {
395 LLIL_LOAD => LowLevelILExpressionKind::Load(Operation::new(function, op, index)),
396 LLIL_LOAD_SSA => LowLevelILExpressionKind::LoadSsa(Operation::new(function, op, index)),
397 LLIL_POP => LowLevelILExpressionKind::Pop(Operation::new(function, op, index)),
398 LLIL_REG => LowLevelILExpressionKind::Reg(Operation::new(function, op, index)),
399 LLIL_REG_SSA => LowLevelILExpressionKind::RegSsa(Operation::new(function, op, index)),
400 LLIL_REG_SSA_PARTIAL => {
401 LowLevelILExpressionKind::RegPartialSsa(Operation::new(function, op, index))
402 }
403 LLIL_REG_SPLIT => {
404 LowLevelILExpressionKind::RegSplit(Operation::new(function, op, index))
405 }
406 LLIL_REG_SPLIT_SSA => {
407 LowLevelILExpressionKind::RegSplitSsa(Operation::new(function, op, index))
408 }
409 LLIL_CONST => LowLevelILExpressionKind::Const(Operation::new(function, op, index)),
410 LLIL_CONST_PTR => {
411 LowLevelILExpressionKind::ConstPtr(Operation::new(function, op, index))
412 }
413 LLIL_FLAG | LLIL_FLAG_SSA => {
414 LowLevelILExpressionKind::Flag(Operation::new(function, op, index))
415 }
416 LLIL_FLAG_GROUP => {
417 LowLevelILExpressionKind::FlagGroup(Operation::new(function, op, index))
418 }
419 LLIL_FLAG_COND => {
420 LowLevelILExpressionKind::FlagCond(Operation::new(function, op, index))
421 }
422 LLIL_FLAG_BIT | LLIL_FLAG_BIT_SSA => {
423 LowLevelILExpressionKind::FlagBit(Operation::new(function, op, index))
424 }
425 LLIL_EXTERN_PTR => {
426 LowLevelILExpressionKind::ExternPtr(Operation::new(function, op, index))
427 }
428
429 LLIL_REG_STACK_POP => {
430 LowLevelILExpressionKind::RegStackPop(Operation::new(function, op, index))
431 }
432 LLIL_REG_STACK_FREE_REG => {
433 LowLevelILExpressionKind::RegStackFreeReg(Operation::new(function, op, index))
434 }
435
436 LLIL_CALL_OUTPUT_SSA => {
437 LowLevelILExpressionKind::CallOutputSsa(Operation::new(function, op, index))
438 }
439 LLIL_CALL_PARAM => {
440 LowLevelILExpressionKind::CallParamSsa(Operation::new(function, op, index))
441 }
442 LLIL_CALL_STACK_SSA => {
443 LowLevelILExpressionKind::CallStackSsa(Operation::new(function, op, index))
444 }
445
446 LLIL_ADD => LowLevelILExpressionKind::Add(Operation::new(function, op, index)),
447 LLIL_ADD_OVERFLOW => {
448 LowLevelILExpressionKind::AddOverflow(Operation::new(function, op, index))
449 }
450 LLIL_ADC => LowLevelILExpressionKind::Adc(Operation::new(function, op, index)),
451 LLIL_SUB => LowLevelILExpressionKind::Sub(Operation::new(function, op, index)),
452 LLIL_SBB => LowLevelILExpressionKind::Sbb(Operation::new(function, op, index)),
453 LLIL_AND => LowLevelILExpressionKind::And(Operation::new(function, op, index)),
454 LLIL_OR => LowLevelILExpressionKind::Or(Operation::new(function, op, index)),
455 LLIL_XOR => LowLevelILExpressionKind::Xor(Operation::new(function, op, index)),
456 LLIL_LSL => LowLevelILExpressionKind::Lsl(Operation::new(function, op, index)),
457 LLIL_LSR => LowLevelILExpressionKind::Lsr(Operation::new(function, op, index)),
458 LLIL_ASR => LowLevelILExpressionKind::Asr(Operation::new(function, op, index)),
459 LLIL_ROL => LowLevelILExpressionKind::Rol(Operation::new(function, op, index)),
460 LLIL_RLC => LowLevelILExpressionKind::Rlc(Operation::new(function, op, index)),
461 LLIL_ROR => LowLevelILExpressionKind::Ror(Operation::new(function, op, index)),
462 LLIL_RRC => LowLevelILExpressionKind::Rrc(Operation::new(function, op, index)),
463 LLIL_MUL => LowLevelILExpressionKind::Mul(Operation::new(function, op, index)),
464
465 LLIL_MULU_DP => LowLevelILExpressionKind::MuluDp(Operation::new(function, op, index)),
466 LLIL_MULS_DP => LowLevelILExpressionKind::MulsDp(Operation::new(function, op, index)),
467
468 LLIL_DIVU => LowLevelILExpressionKind::Divu(Operation::new(function, op, index)),
469 LLIL_DIVS => LowLevelILExpressionKind::Divs(Operation::new(function, op, index)),
470
471 LLIL_DIVU_DP => LowLevelILExpressionKind::DivuDp(Operation::new(function, op, index)),
472 LLIL_DIVS_DP => LowLevelILExpressionKind::DivsDp(Operation::new(function, op, index)),
473
474 LLIL_MODU => LowLevelILExpressionKind::Modu(Operation::new(function, op, index)),
475 LLIL_MODS => LowLevelILExpressionKind::Mods(Operation::new(function, op, index)),
476
477 LLIL_MODU_DP => LowLevelILExpressionKind::ModuDp(Operation::new(function, op, index)),
478 LLIL_MODS_DP => LowLevelILExpressionKind::ModsDp(Operation::new(function, op, index)),
479
480 LLIL_NEG => LowLevelILExpressionKind::Neg(Operation::new(function, op, index)),
481 LLIL_NOT => LowLevelILExpressionKind::Not(Operation::new(function, op, index)),
482 LLIL_BSWAP => LowLevelILExpressionKind::Bswap(Operation::new(function, op, index)),
483 LLIL_POPCNT => LowLevelILExpressionKind::Popcnt(Operation::new(function, op, index)),
484 LLIL_CLZ => LowLevelILExpressionKind::Clz(Operation::new(function, op, index)),
485 LLIL_CTZ => LowLevelILExpressionKind::Ctz(Operation::new(function, op, index)),
486 LLIL_RBIT => LowLevelILExpressionKind::Rbit(Operation::new(function, op, index)),
487 LLIL_CLS => LowLevelILExpressionKind::Cls(Operation::new(function, op, index)),
488
489 LLIL_MINS => LowLevelILExpressionKind::MinSigned(Operation::new(function, op, index)),
490 LLIL_MAXS => LowLevelILExpressionKind::MaxSigned(Operation::new(function, op, index)),
491 LLIL_MINU => LowLevelILExpressionKind::MinUnsigned(Operation::new(function, op, index)),
492 LLIL_MAXU => LowLevelILExpressionKind::MaxUnsigned(Operation::new(function, op, index)),
493 LLIL_ABS => LowLevelILExpressionKind::Abs(Operation::new(function, op, index)),
494
495 LLIL_SX => LowLevelILExpressionKind::Sx(Operation::new(function, op, index)),
496 LLIL_ZX => LowLevelILExpressionKind::Zx(Operation::new(function, op, index)),
497 LLIL_LOW_PART => LowLevelILExpressionKind::LowPart(Operation::new(function, op, index)),
498
499 LLIL_CMP_E => LowLevelILExpressionKind::CmpE(Operation::new(function, op, index)),
500 LLIL_CMP_NE => LowLevelILExpressionKind::CmpNe(Operation::new(function, op, index)),
501 LLIL_CMP_SLT => LowLevelILExpressionKind::CmpSlt(Operation::new(function, op, index)),
502 LLIL_CMP_ULT => LowLevelILExpressionKind::CmpUlt(Operation::new(function, op, index)),
503 LLIL_CMP_SLE => LowLevelILExpressionKind::CmpSle(Operation::new(function, op, index)),
504 LLIL_CMP_ULE => LowLevelILExpressionKind::CmpUle(Operation::new(function, op, index)),
505 LLIL_CMP_SGE => LowLevelILExpressionKind::CmpSge(Operation::new(function, op, index)),
506 LLIL_CMP_UGE => LowLevelILExpressionKind::CmpUge(Operation::new(function, op, index)),
507 LLIL_CMP_SGT => LowLevelILExpressionKind::CmpSgt(Operation::new(function, op, index)),
508 LLIL_CMP_UGT => LowLevelILExpressionKind::CmpUgt(Operation::new(function, op, index)),
509
510 LLIL_TEST_BIT => LowLevelILExpressionKind::TestBit(Operation::new(function, op, index)),
511 LLIL_BOOL_TO_INT => {
512 LowLevelILExpressionKind::BoolToInt(Operation::new(function, op, index))
513 }
514
515 LLIL_FADD => LowLevelILExpressionKind::Fadd(Operation::new(function, op, index)),
516 LLIL_FSUB => LowLevelILExpressionKind::Fsub(Operation::new(function, op, index)),
517 LLIL_FMUL => LowLevelILExpressionKind::Fmul(Operation::new(function, op, index)),
518 LLIL_FDIV => LowLevelILExpressionKind::Fdiv(Operation::new(function, op, index)),
519
520 LLIL_FSQRT => LowLevelILExpressionKind::Fsqrt(Operation::new(function, op, index)),
521 LLIL_FNEG => LowLevelILExpressionKind::Fneg(Operation::new(function, op, index)),
522 LLIL_FABS => LowLevelILExpressionKind::Fabs(Operation::new(function, op, index)),
523 LLIL_FLOAT_TO_INT => {
524 LowLevelILExpressionKind::FloatToInt(Operation::new(function, op, index))
525 }
526 LLIL_INT_TO_FLOAT => {
527 LowLevelILExpressionKind::IntToFloat(Operation::new(function, op, index))
528 }
529 LLIL_FLOAT_CONV => {
530 LowLevelILExpressionKind::FloatConv(Operation::new(function, op, index))
531 }
532 LLIL_ROUND_TO_INT => {
533 LowLevelILExpressionKind::RoundToInt(Operation::new(function, op, index))
534 }
535 LLIL_FLOOR => LowLevelILExpressionKind::Floor(Operation::new(function, op, index)),
536 LLIL_CEIL => LowLevelILExpressionKind::Ceil(Operation::new(function, op, index)),
537 LLIL_FTRUNC => LowLevelILExpressionKind::Ftrunc(Operation::new(function, op, index)),
538
539 LLIL_FCMP_E => LowLevelILExpressionKind::FcmpE(Operation::new(function, op, index)),
540 LLIL_FCMP_NE => LowLevelILExpressionKind::FcmpNE(Operation::new(function, op, index)),
541 LLIL_FCMP_LT => LowLevelILExpressionKind::FcmpLT(Operation::new(function, op, index)),
542 LLIL_FCMP_LE => LowLevelILExpressionKind::FcmpLE(Operation::new(function, op, index)),
543 LLIL_FCMP_GT => LowLevelILExpressionKind::FcmpGT(Operation::new(function, op, index)),
544 LLIL_FCMP_GE => LowLevelILExpressionKind::FcmpGE(Operation::new(function, op, index)),
545 LLIL_FCMP_O => LowLevelILExpressionKind::FcmpO(Operation::new(function, op, index)),
546 LLIL_FCMP_UO => LowLevelILExpressionKind::FcmpUO(Operation::new(function, op, index)),
547
548 LLIL_FLOAT_CONST => {
549 LowLevelILExpressionKind::FloatConst(Operation::new(function, op, index))
550 }
551
552 LLIL_SEPARATE_PARAM_LIST_SSA => {
553 LowLevelILExpressionKind::SeparateParamListSsa(Operation::new(function, op, index))
554 }
555
556 LLIL_UNDEF => LowLevelILExpressionKind::Undef(Operation::new(function, op, index)),
557
558 LLIL_UNIMPL => LowLevelILExpressionKind::Unimpl(Operation::new(function, op, index)),
559 LLIL_UNIMPL_MEM => {
560 LowLevelILExpressionKind::UnimplMem(Operation::new(function, op, index))
561 }
562
563 _ => {
564 tracing::error!(
565 "Got unexpected operation {:?} in value expr at 0x{:x}",
566 op.operation,
567 op.address
568 );
569
570 LowLevelILExpressionKind::Undef(Operation::new(function, op, index))
571 }
572 }
573 }
574
575 pub fn size(&self) -> Option<usize> {
580 use self::LowLevelILExpressionKind::*;
581
582 match *self {
583 Undef(..) | Unimpl(..) => None,
584
585 FlagCond(..) | FlagGroup(..) | CmpE(..) | CmpNe(..) | CmpSlt(..) | CmpUlt(..)
586 | CmpSle(..) | CmpUle(..) | CmpSge(..) | CmpUge(..) | CmpSgt(..) | CmpUgt(..) => {
587 Some(0)
588 }
589
590 _ => Some(self.raw_struct().size),
591 }
592 }
593
594 pub fn address(&self) -> u64 {
595 self.raw_struct().address
596 }
597
598 pub fn is_same_op_as(&self, other: &Self) -> bool {
602 use self::LowLevelILExpressionKind::*;
603
604 match (self, other) {
605 (&Reg(..), &Reg(..)) => true,
606 _ => self.raw_struct().operation == other.raw_struct().operation,
607 }
608 }
609
610 pub fn as_cmp_op(&self) -> Option<&Operation<'func, M, F, operation::Condition>> {
611 use self::LowLevelILExpressionKind::*;
612
613 match *self {
614 CmpE(ref op) | CmpNe(ref op) | CmpSlt(ref op) | CmpUlt(ref op) | CmpSle(ref op)
615 | CmpUle(ref op) | CmpSge(ref op) | CmpUge(ref op) | CmpSgt(ref op)
616 | CmpUgt(ref op) | FcmpE(ref op) | FcmpNE(ref op) | FcmpLT(ref op) | FcmpLE(ref op)
617 | FcmpGE(ref op) | FcmpGT(ref op) | FcmpO(ref op) | FcmpUO(ref op) => Some(op),
618 _ => None,
619 }
620 }
621
622 pub fn as_binary_op(&self) -> Option<&Operation<'func, M, F, operation::BinaryOp>> {
623 use self::LowLevelILExpressionKind::*;
624
625 match *self {
626 Add(ref op) | Sub(ref op) | And(ref op) | Or(ref op) | Xor(ref op) | Lsl(ref op)
627 | Lsr(ref op) | Asr(ref op) | Rol(ref op) | Ror(ref op) | Mul(ref op)
628 | MulsDp(ref op) | MuluDp(ref op) | Divu(ref op) | Divs(ref op) | Modu(ref op)
629 | Mods(ref op) | Fadd(ref op) | Fsub(ref op) | Fmul(ref op) | Fdiv(ref op)
630 | DivuDp(ref op) | DivsDp(ref op) | ModuDp(ref op) | ModsDp(ref op)
631 | MinSigned(ref op) | MaxSigned(ref op) | MinUnsigned(ref op) | MaxUnsigned(ref op) => {
632 Some(op)
633 }
634 _ => None,
635 }
636 }
637
638 pub fn as_binary_op_carry(&self) -> Option<&Operation<'func, M, F, operation::BinaryOpCarry>> {
639 use self::LowLevelILExpressionKind::*;
640
641 match *self {
642 Adc(ref op) | Sbb(ref op) | Rlc(ref op) | Rrc(ref op) => Some(op),
643 _ => None,
644 }
645 }
646
647 pub fn as_unary_op(&self) -> Option<&Operation<'func, M, F, operation::UnaryOp>> {
648 use self::LowLevelILExpressionKind::*;
649
650 match *self {
651 Neg(ref op) | Not(ref op) | Bswap(ref op) | Popcnt(ref op) | Clz(ref op)
652 | Ctz(ref op) | Rbit(ref op) | Cls(ref op) | Abs(ref op) | Sx(ref op) | Zx(ref op)
653 | LowPart(ref op) | BoolToInt(ref op) | Fsqrt(ref op) | Fneg(ref op) | Fabs(ref op)
654 | FloatToInt(ref op) | IntToFloat(ref op) | FloatConv(ref op) | RoundToInt(ref op)
655 | Floor(ref op) | Ceil(ref op) | Ftrunc(ref op) => Some(op),
656 _ => None,
657 }
658 }
659
660 pub fn visit_sub_expressions<T>(&self, mut visitor: T) -> VisitorAction
661 where
662 T: FnMut(LowLevelILExpression<'func, M, F, ValueExpr>) -> VisitorAction,
663 {
664 use LowLevelILExpressionKind::*;
665
666 macro_rules! visit {
667 ($expr:expr) => {
668 if let VisitorAction::Halt = visitor($expr) {
669 return VisitorAction::Halt;
670 }
671 };
672 }
673
674 match self {
675 CmpE(ref op) | CmpNe(ref op) | CmpSlt(ref op) | CmpUlt(ref op) | CmpSle(ref op)
676 | CmpUle(ref op) | CmpSge(ref op) | CmpUge(ref op) | CmpSgt(ref op)
677 | CmpUgt(ref op) | FcmpE(ref op) | FcmpNE(ref op) | FcmpLT(ref op) | FcmpLE(ref op)
678 | FcmpGE(ref op) | FcmpGT(ref op) | FcmpO(ref op) | FcmpUO(ref op) => {
679 visit!(op.left());
680 visit!(op.right());
681 }
682 Adc(ref op) | Sbb(ref op) | Rlc(ref op) | Rrc(ref op) => {
683 visit!(op.left());
684 visit!(op.right());
685 visit!(op.carry());
686 }
687 Add(ref op) | AddOverflow(ref op) | Sub(ref op) | And(ref op) | Or(ref op)
688 | Xor(ref op) | Lsl(ref op) | Lsr(ref op) | Asr(ref op) | Rol(ref op) | Ror(ref op)
689 | Mul(ref op) | MulsDp(ref op) | MuluDp(ref op) | Divu(ref op) | Divs(ref op)
690 | Modu(ref op) | Mods(ref op) | Fadd(ref op) | Fsub(ref op) | Fmul(ref op)
691 | DivuDp(ref op) | DivsDp(ref op) | ModuDp(ref op) | ModsDp(ref op) | Fdiv(ref op)
692 | MinSigned(ref op) | MaxSigned(ref op) | MinUnsigned(ref op) | MaxUnsigned(ref op)
693 | TestBit(ref op) => {
694 visit!(op.left());
695 visit!(op.right());
696 }
697 Neg(ref op) | Not(ref op) | Bswap(ref op) | Popcnt(ref op) | Clz(ref op)
698 | Ctz(ref op) | Rbit(ref op) | Cls(ref op) | Abs(ref op) | Sx(ref op) | Zx(ref op)
699 | LowPart(ref op) | BoolToInt(ref op) | Fsqrt(ref op) | Fneg(ref op) | Fabs(ref op)
700 | FloatToInt(ref op) | IntToFloat(ref op) | FloatConv(ref op) | RoundToInt(ref op)
701 | Floor(ref op) | Ceil(ref op) | Ftrunc(ref op) => {
702 visit!(op.operand());
703 }
704 UnimplMem(ref op) => {
705 visit!(op.mem_expr());
706 }
707 Load(ref op) => {
708 visit!(op.source_expr());
709 }
710 LoadSsa(ref op) => {
711 visit!(op.source_expr());
712 }
713 CallParamSsa(ref op) => {
714 for param_expr in op.param_exprs() {
715 visit!(param_expr);
716 }
717 }
718 SeparateParamListSsa(ref op) => {
719 for param_expr in op.param_exprs() {
720 visit!(param_expr);
721 }
722 }
723 Pop(_) | Reg(_) | RegSsa(_) | RegPartialSsa(_) | RegSplit(_) | RegSplitSsa(_)
725 | Const(_) | ConstPtr(_) | Flag(_) | FlagBit(_) | ExternPtr(_) | FlagCond(_)
726 | FlagGroup(_) | Unimpl(_) | Undef(_) | RegStackPop(_) | RegStackFreeReg(_)
727 | CallOutputSsa(_) | CallStackSsa(_) | FloatConst(_) => {}
728 }
729
730 VisitorAction::Sibling
731 }
732
733 pub(crate) fn raw_struct(&self) -> &BNLowLevelILInstruction {
734 use self::LowLevelILExpressionKind::*;
735
736 match *self {
737 Undef(ref op) => &op.op,
738
739 Unimpl(ref op) => &op.op,
740
741 FlagCond(ref op) => &op.op,
742 FlagGroup(ref op) => &op.op,
743
744 CmpE(ref op) | CmpNe(ref op) | CmpSlt(ref op) | CmpUlt(ref op) | CmpSle(ref op)
745 | CmpUle(ref op) | CmpSge(ref op) | CmpUge(ref op) | CmpSgt(ref op)
746 | CmpUgt(ref op) | FcmpE(ref op) | FcmpNE(ref op) | FcmpLT(ref op) | FcmpLE(ref op)
747 | FcmpGE(ref op) | FcmpGT(ref op) | FcmpO(ref op) | FcmpUO(ref op) => &op.op,
748
749 Load(ref op) => &op.op,
750
751 LoadSsa(ref op) => &op.op,
752
753 Pop(ref op) => &op.op,
754
755 Reg(ref op) => &op.op,
756
757 RegSsa(ref op) => &op.op,
758
759 RegPartialSsa(ref op) => &op.op,
760
761 RegSplit(ref op) => &op.op,
762
763 RegSplitSsa(ref op) => &op.op,
764
765 Flag(ref op) => &op.op,
766
767 FlagBit(ref op) => &op.op,
768
769 Const(ref op) | ConstPtr(ref op) => &op.op,
770
771 FloatConst(ref op) => &op.op,
772
773 ExternPtr(ref op) => &op.op,
774
775 RegStackPop(ref op) => &op.op,
776 RegStackFreeReg(ref op) => &op.op,
777
778 CallOutputSsa(ref op) => &op.op,
779 CallParamSsa(ref op) => &op.op,
780 CallStackSsa(ref op) => &op.op,
781
782 Adc(ref op) | Sbb(ref op) | Rlc(ref op) | Rrc(ref op) => &op.op,
783
784 Add(ref op) | AddOverflow(ref op) | Sub(ref op) | And(ref op) | Or(ref op)
785 | Xor(ref op) | Lsl(ref op) | Lsr(ref op) | Asr(ref op) | Rol(ref op) | Ror(ref op)
786 | Mul(ref op) | MulsDp(ref op) | MuluDp(ref op) | Divu(ref op) | Divs(ref op)
787 | Modu(ref op) | Mods(ref op) | Fadd(ref op) | Fsub(ref op) | Fmul(ref op)
788 | MinSigned(ref op) | MaxSigned(ref op) | MinUnsigned(ref op) | MaxUnsigned(ref op)
789 | Fdiv(ref op) | TestBit(ref op) => &op.op,
790
791 DivuDp(ref op) | DivsDp(ref op) | ModuDp(ref op) | ModsDp(ref op) => &op.op,
792
793 Neg(ref op) | Not(ref op) | Bswap(ref op) | Popcnt(ref op) | Clz(ref op)
794 | Ctz(ref op) | Rbit(ref op) | Cls(ref op) | Abs(ref op) | Sx(ref op) | Zx(ref op)
795 | LowPart(ref op) | BoolToInt(ref op) | Fsqrt(ref op) | Fneg(ref op) | Fabs(ref op)
796 | FloatToInt(ref op) | IntToFloat(ref op) | FloatConv(ref op) | RoundToInt(ref op)
797 | Floor(ref op) | Ceil(ref op) | Ftrunc(ref op) => &op.op,
798
799 SeparateParamListSsa(ref op) => &op.op,
800
801 UnimplMem(ref op) => &op.op,
802 }
803 }
804}
805
806impl LowLevelILExpressionKind<'_, Mutable, NonSSA> {
807 pub fn flag_write(&self) -> Option<CoreFlagWrite> {
808 use self::LowLevelILExpressionKind::*;
809
810 match *self {
811 Undef(ref _op) => None,
812
813 Unimpl(ref _op) => None,
814
815 FlagCond(ref _op) => None,
816 FlagGroup(ref _op) => None,
817
818 CmpE(ref _op) | CmpNe(ref _op) | CmpSlt(ref _op) | CmpUlt(ref _op)
819 | CmpSle(ref _op) | CmpUle(ref _op) | CmpSge(ref _op) | CmpUge(ref _op)
820 | CmpSgt(ref _op) | CmpUgt(ref _op) | FcmpE(ref _op) | FcmpNE(ref _op)
821 | FcmpLT(ref _op) | FcmpLE(ref _op) | FcmpGE(ref _op) | FcmpGT(ref _op)
822 | FcmpO(ref _op) | FcmpUO(ref _op) => None,
823
824 Load(ref op) => op.flag_write(),
825
826 LoadSsa(ref op) => op.flag_write(),
827
828 Pop(ref op) => op.flag_write(),
829
830 Reg(ref op) => op.flag_write(),
831
832 RegSsa(ref op) => op.flag_write(),
833
834 RegPartialSsa(ref op) => op.flag_write(),
835
836 RegSplit(ref op) => op.flag_write(),
837
838 RegSplitSsa(ref op) => op.flag_write(),
839
840 Flag(ref op) => op.flag_write(),
841
842 FlagBit(ref op) => op.flag_write(),
843
844 Const(ref op) | ConstPtr(ref op) => op.flag_write(),
845
846 FloatConst(ref op) => op.flag_write(),
847
848 ExternPtr(ref op) => op.flag_write(),
849
850 RegStackPop(ref op) => op.flag_write(),
851 RegStackFreeReg(ref op) => op.flag_write(),
852
853 CallOutputSsa(ref op) => op.flag_write(),
854 CallParamSsa(ref op) => op.flag_write(),
855 CallStackSsa(ref op) => op.flag_write(),
856
857 Adc(ref op) | Sbb(ref op) | Rlc(ref op) | Rrc(ref op) => op.flag_write(),
858
859 Add(ref op) | AddOverflow(ref op) | Sub(ref op) | And(ref op) | Or(ref op)
860 | Xor(ref op) | Lsl(ref op) | Lsr(ref op) | Asr(ref op) | Rol(ref op) | Ror(ref op)
861 | Mul(ref op) | MulsDp(ref op) | MuluDp(ref op) | Divu(ref op) | Divs(ref op)
862 | Modu(ref op) | Mods(ref op) | Fadd(ref op) | Fsub(ref op) | Fmul(ref op)
863 | MinSigned(ref op) | MaxSigned(ref op) | MinUnsigned(ref op) | MaxUnsigned(ref op)
864 | Fdiv(ref op) | TestBit(ref op) => op.flag_write(),
865
866 DivuDp(ref op) | DivsDp(ref op) | ModuDp(ref op) | ModsDp(ref op) => op.flag_write(),
867
868 Neg(ref op) | Not(ref op) | Bswap(ref op) | Popcnt(ref op) | Clz(ref op)
869 | Ctz(ref op) | Rbit(ref op) | Cls(ref op) | Abs(ref op) | Sx(ref op) | Zx(ref op)
870 | LowPart(ref op) | BoolToInt(ref op) | Fsqrt(ref op) | Fneg(ref op) | Fabs(ref op)
871 | FloatToInt(ref op) | IntToFloat(ref op) | FloatConv(ref op) | RoundToInt(ref op)
872 | Floor(ref op) | Ceil(ref op) | Ftrunc(ref op) => op.flag_write(),
873
874 SeparateParamListSsa(ref op) => op.flag_write(),
875
876 UnimplMem(ref op) => op.flag_write(),
877 }
878 }
879}