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