1use std::convert::Into;
33
34use binaryninja::low_level_il::{
35 expression::{ExpressionHandler as _, LowLevelILExpression, LowLevelILExpressionKind},
36 instruction::{InstructionHandler as _, LowLevelILInstruction, LowLevelILInstructionKind},
37 LowLevelILRegisterKind, LowLevelILSSARegisterKind,
38};
39
40mod bn {
41 pub use binaryninja::{
42 architecture::CoreRegister,
43 architecture::Register,
44 low_level_il::{
45 expression::{ExpressionHandler, ValueExpr},
46 function::{FunctionForm, FunctionMutability},
47 instruction::{InstructionHandler, LowLevelILInstructionKind},
48 operation::{BinaryOp, Operation},
49 },
50 };
51}
52
53#[derive(Debug)]
54pub struct Instruction<'func, M, F>
55where
56 M: bn::FunctionMutability,
57 F: bn::FunctionForm,
58{
59 pub kind: InstructionKind<'func, M, F>,
60 pub inner: LowLevelILInstruction<'func, M, F>,
61}
62
63#[derive(Debug)]
64pub enum InstructionKind<'func, M, F>
65where
66 M: bn::FunctionMutability,
67 F: bn::FunctionForm,
68{
69 If(
70 Expression<'func, M, F>,
71 LowLevelILInstruction<'func, M, F>,
72 LowLevelILInstruction<'func, M, F>,
73 ),
74 SetReg(
75 LowLevelILRegisterKind<bn::CoreRegister>,
76 Expression<'func, M, F>,
77 ),
78 SetRegSsa(
79 LowLevelILSSARegisterKind<bn::CoreRegister>,
80 Expression<'func, M, F>,
81 ),
82 RegPhi(
83 LowLevelILSSARegisterKind<bn::CoreRegister>,
84 Vec<LowLevelILSSARegisterKind<bn::CoreRegister>>,
85 ),
86 Call(Expression<'func, M, F>),
87 TailCall(Expression<'func, M, F>),
88 CallSsa(Expression<'func, M, F>, Vec<Expression<'func, M, F>>),
89 TailCallSsa(Expression<'func, M, F>, Vec<Expression<'func, M, F>>),
90 Goto(LowLevelILInstruction<'func, M, F>),
91 Jump(Expression<'func, M, F>),
92 Unknown(LowLevelILInstruction<'func, M, F>),
93}
94
95#[derive(Debug)]
96pub struct BinaryExpression<'func, M, F>(pub Expression<'func, M, F>, pub Expression<'func, M, F>)
97where
98 M: bn::FunctionMutability,
99 F: bn::FunctionForm;
100
101impl<'func, M, F> BinaryExpression<'func, M, F>
102where
103 M: bn::FunctionMutability,
104 F: bn::FunctionForm,
105 LowLevelILExpression<'func, M, F, bn::ValueExpr>: bn::ExpressionHandler<'func, M, F>,
106{
107 #[must_use]
108 pub fn kinds(&self) -> (ExpressionKind<'func, M, F>, ExpressionKind<'func, M, F>) {
109 (self.0.kind.clone(), self.1.kind.clone())
110 }
111
112 #[must_use]
113 pub fn inners(
114 &self,
115 ) -> (
116 LowLevelILExpression<'func, M, F, bn::ValueExpr>,
117 LowLevelILExpression<'func, M, F, bn::ValueExpr>,
118 ) {
119 (self.0.inner, self.1.inner)
120 }
121}
122
123impl<'func, M, F> Clone for BinaryExpression<'func, M, F>
124where
125 M: bn::FunctionMutability,
126 F: bn::FunctionForm,
127 LowLevelILExpression<'func, M, F, bn::ValueExpr>: bn::ExpressionHandler<'func, M, F>,
128{
129 fn clone(&self) -> Self {
130 Self(self.0.clone(), self.1.clone())
131 }
132}
133
134#[derive(Debug)]
135pub struct Expression<'func, M, F>
136where
137 M: bn::FunctionMutability,
138 F: bn::FunctionForm,
139{
140 pub inner: LowLevelILExpression<'func, M, F, bn::ValueExpr>,
141 pub kind: ExpressionKind<'func, M, F>,
142}
143
144impl<'func, M, F> Clone for Expression<'func, M, F>
145where
146 M: bn::FunctionMutability,
147 F: bn::FunctionForm,
148 LowLevelILExpression<'func, M, F, bn::ValueExpr>: bn::ExpressionHandler<'func, M, F>,
149{
150 fn clone(&self) -> Self {
151 Self {
152 inner: self.inner,
153 kind: self.kind.clone(),
154 }
155 }
156}
157
158#[derive(Debug)]
159pub enum ExpressionKind<'func, M, F>
160where
161 M: bn::FunctionMutability,
162 F: bn::FunctionForm,
163{
164 Add(Box<BinaryExpression<'func, M, F>>),
165 Sub(Box<BinaryExpression<'func, M, F>>),
166 And(Box<BinaryExpression<'func, M, F>>),
167 Xor(Box<BinaryExpression<'func, M, F>>),
168 Lsl(Box<BinaryExpression<'func, M, F>>),
169 Lsr(Box<BinaryExpression<'func, M, F>>),
170 CmpE(Box<BinaryExpression<'func, M, F>>),
171 Reg(LowLevelILRegisterKind<bn::CoreRegister>),
172 RegSsa(LowLevelILSSARegisterKind<bn::CoreRegister>),
173 Const(u64),
174 ConstPtr(u64),
175 Unknown(LowLevelILExpression<'func, M, F, bn::ValueExpr>),
176}
177
178impl<'func, M, F> Clone for ExpressionKind<'func, M, F>
179where
180 M: bn::FunctionMutability,
181 F: bn::FunctionForm,
182 LowLevelILExpression<'func, M, F, bn::ValueExpr>: bn::ExpressionHandler<'func, M, F>,
183{
184 fn clone(&self) -> Self {
185 match self {
186 ExpressionKind::Add(inner) => ExpressionKind::Add(inner.clone()),
187 ExpressionKind::Sub(inner) => ExpressionKind::Sub(inner.clone()),
188 ExpressionKind::And(inner) => ExpressionKind::And(inner.clone()),
189 ExpressionKind::Xor(inner) => ExpressionKind::Xor(inner.clone()),
190 ExpressionKind::Lsl(inner) => ExpressionKind::Lsl(inner.clone()),
191 ExpressionKind::Lsr(inner) => ExpressionKind::Lsr(inner.clone()),
192 ExpressionKind::CmpE(inner) => ExpressionKind::CmpE(inner.clone()),
193 ExpressionKind::Reg(reg) => ExpressionKind::Reg(*reg),
194 ExpressionKind::RegSsa(reg) => ExpressionKind::RegSsa(*reg),
195 ExpressionKind::Const(value) => ExpressionKind::Const(*value),
196 ExpressionKind::ConstPtr(value) => ExpressionKind::ConstPtr(*value),
197 ExpressionKind::Unknown(expr) => ExpressionKind::Unknown(*expr),
198 }
199 }
200}
201
202impl<'func, M, F> From<LowLevelILInstruction<'func, M, F>> for Instruction<'func, M, F>
203where
204 M: bn::FunctionMutability,
205 F: bn::FunctionForm,
206 LowLevelILInstruction<'func, M, F>: bn::InstructionHandler<'func, M, F>,
207 LowLevelILExpression<'func, M, F, bn::ValueExpr>: bn::ExpressionHandler<'func, M, F>,
208{
209 fn from(instr: LowLevelILInstruction<'func, M, F>) -> Self {
210 Self {
211 kind: InstructionKind::from(instr),
212 inner: instr,
213 }
214 }
215}
216
217impl<'a, 'func, M, F> From<&'a LowLevelILInstruction<'func, M, F>> for Instruction<'func, M, F>
218where
219 M: bn::FunctionMutability,
220 F: bn::FunctionForm,
221 LowLevelILInstruction<'func, M, F>: bn::InstructionHandler<'func, M, F>,
222 LowLevelILExpression<'func, M, F, bn::ValueExpr>: bn::ExpressionHandler<'func, M, F>,
223{
224 fn from(instr: &'a LowLevelILInstruction<'func, M, F>) -> Self {
225 (*instr).into()
226 }
227}
228
229impl<'func, M, F> From<LowLevelILInstruction<'func, M, F>> for InstructionKind<'func, M, F>
230where
231 M: bn::FunctionMutability,
232 F: bn::FunctionForm,
233 LowLevelILInstruction<'func, M, F>: bn::InstructionHandler<'func, M, F>,
234 LowLevelILExpression<'func, M, F, bn::ValueExpr>: bn::ExpressionHandler<'func, M, F>,
235{
236 fn from(instr: LowLevelILInstruction<'func, M, F>) -> Self {
237 use LowLevelILExpressionKind as ExpressionKind;
238 use LowLevelILInstructionKind as Kind;
239 match instr.kind() {
240 Kind::If(operation) => Self::If(
241 operation.condition().into(),
242 operation.true_target(),
243 operation.false_target(),
244 ),
245 Kind::SetReg(operation) => {
246 InstructionKind::SetReg(operation.dest_reg(), operation.source_expr().into())
247 }
248 Kind::SetRegSsa(operation) => {
249 InstructionKind::SetRegSsa(operation.dest_reg(), operation.source_expr().into())
250 }
251 Kind::Call(operation) => InstructionKind::Call(operation.target().into()),
252 Kind::TailCall(operation) => InstructionKind::TailCall(operation.target().into()),
253 Kind::CallSsa(operation) => {
254 let ExpressionKind::CallParamSsa(params) = operation.param_expr().kind() else {
255 panic!(
256 "Unexpected call parameter expression kind: {:?}",
257 operation.param_expr().kind()
258 );
259 };
260 InstructionKind::CallSsa(
261 operation.target().into(),
262 params.param_exprs().into_iter().map(Into::into).collect(),
263 )
264 }
265 Kind::TailCallSsa(operation) => {
266 let ExpressionKind::CallParamSsa(params) = operation.param_expr().kind() else {
267 panic!(
268 "Unexpected call parameter expression kind: {:?}",
269 operation.param_expr().kind()
270 );
271 };
272 InstructionKind::TailCallSsa(
273 operation.target().into(),
274 params.param_exprs().into_iter().map(Into::into).collect(),
275 )
276 }
277 Kind::RegPhi(operation) => {
278 let source_regs = operation.source_regs();
279 InstructionKind::RegPhi(operation.dest_reg(), source_regs)
280 }
281 Kind::Goto(operation) => InstructionKind::Goto(operation.target()),
282 Kind::Jump(operation) => InstructionKind::Jump(operation.target().into()),
283 _ => InstructionKind::Unknown(instr),
284 }
285 }
286}
287
288impl<'a, 'func, M, F> From<&'a LowLevelILInstruction<'func, M, F>> for InstructionKind<'func, M, F>
289where
290 M: bn::FunctionMutability,
291 F: bn::FunctionForm,
292 LowLevelILInstruction<'func, M, F>: bn::InstructionHandler<'func, M, F>,
293 LowLevelILExpression<'func, M, F, bn::ValueExpr>: bn::ExpressionHandler<'func, M, F>,
294{
295 fn from(instr: &'a LowLevelILInstruction<'func, M, F>) -> Self {
296 (*instr).into()
297 }
298}
299
300impl<'func, M, F> From<LowLevelILExpression<'func, M, F, bn::ValueExpr>> for Expression<'func, M, F>
301where
302 M: bn::FunctionMutability,
303 F: bn::FunctionForm,
304 LowLevelILExpression<'func, M, F, bn::ValueExpr>: bn::ExpressionHandler<'func, M, F>,
305{
306 fn from(expr: LowLevelILExpression<'func, M, F, bn::ValueExpr>) -> Self {
307 Self {
308 inner: expr,
309 kind: ExpressionKind::from(expr),
310 }
311 }
312}
313
314impl<'func, M, F> From<LowLevelILExpression<'func, M, F, bn::ValueExpr>>
315 for ExpressionKind<'func, M, F>
316where
317 M: bn::FunctionMutability,
318 F: bn::FunctionForm,
319 LowLevelILExpression<'func, M, F, bn::ValueExpr>: bn::ExpressionHandler<'func, M, F>,
320{
321 fn from(expr: LowLevelILExpression<'func, M, F, bn::ValueExpr>) -> Self {
322 use LowLevelILExpressionKind as Kind;
323 match expr.kind() {
324 Kind::Add(operation) => ExpressionKind::Add(Box::new(operation.into())),
325 Kind::Sub(operation) => ExpressionKind::Sub(Box::new(operation.into())),
326 Kind::And(operation) => ExpressionKind::And(Box::new(operation.into())),
327 Kind::Xor(operation) => ExpressionKind::Xor(Box::new(operation.into())),
328 Kind::Lsl(operation) => ExpressionKind::Lsl(Box::new(operation.into())),
329 Kind::Lsr(operation) => ExpressionKind::Lsr(Box::new(operation.into())),
330 Kind::CmpE(operation) => ExpressionKind::CmpE(Box::new(BinaryExpression(
331 operation.left().into(),
332 operation.right().into(),
333 ))),
334 Kind::Const(operation) => ExpressionKind::Const(operation.value()),
335 Kind::ConstPtr(operation) => ExpressionKind::ConstPtr(operation.value()),
336 Kind::Reg(operation) => ExpressionKind::Reg(operation.source_reg()),
337 Kind::RegSsa(operation) => ExpressionKind::RegSsa(operation.source_reg()),
338 _ => ExpressionKind::Unknown(expr),
339 }
340 }
341}
342
343impl<'func, M, F> From<bn::Operation<'func, M, F, bn::BinaryOp>> for BinaryExpression<'func, M, F>
344where
345 M: bn::FunctionMutability,
346 F: bn::FunctionForm,
347 LowLevelILExpression<'func, M, F, bn::ValueExpr>: bn::ExpressionHandler<'func, M, F>,
348{
349 fn from(operation: bn::Operation<'func, M, F, bn::BinaryOp>) -> Self {
350 Self(operation.left().into(), operation.right().into())
351 }
352}
353
354impl<'func, M, F> Instruction<'func, M, F>
355where
356 M: bn::FunctionMutability,
357 F: bn::FunctionForm,
358 LowLevelILInstruction<'func, M, F>: bn::InstructionHandler<'func, M, F>,
359{
360 #[must_use]
361 pub fn size(&self) -> Option<usize> {
362 use bn::LowLevelILInstructionKind as Kind;
363 match self.inner.kind() {
364 Kind::SetReg(ref op) => Some(op.size()),
365 Kind::SetRegSsa(ref op) => Some(op.size()),
366 Kind::Store(ref op) => Some(op.size()),
367 Kind::StoreSsa(ref op) => Some(op.size()),
368 Kind::Push(ref op) => Some(op.size()),
369 _ => None,
370 }
371 }
372}
373
374pub fn is_same_register<R: bn::Register>(
376 this: &LowLevelILSSARegisterKind<R>,
377 other: &LowLevelILSSARegisterKind<R>,
378) -> bool {
379 match (this, other) {
380 (
381 LowLevelILSSARegisterKind::Full { kind: k1, .. },
382 LowLevelILSSARegisterKind::Full { kind: k2, .. },
383 ) => k1 == k2,
384 (
385 LowLevelILSSARegisterKind::Partial {
386 full_reg: fr1,
387 partial_reg: pr1,
388 ..
389 },
390 LowLevelILSSARegisterKind::Partial {
391 full_reg: fr2,
392 partial_reg: pr2,
393 ..
394 },
395 ) => fr1 == fr2 && pr1 == pr2,
396 _ => false,
397 }
398}
399
400pub fn is_full_register<R: bn::Register>(reg: &LowLevelILSSARegisterKind<R>) -> bool {
402 matches!(reg, LowLevelILSSARegisterKind::Full { .. })
403}
404
405pub fn require_full_register<R: bn::Register, T: std::fmt::Debug>(
408 reg: LowLevelILSSARegisterKind<R>,
409 ctxt: &T,
410) -> Option<LowLevelILRegisterKind<R>> {
411 if let LowLevelILSSARegisterKind::Full { kind, .. } = reg {
412 Some(kind)
413 } else {
414 log::warn!("Expected register used in {ctxt:?} to be a full SSA register, got {reg:?}");
415 None
416 }
417}
418
419#[doc(hidden)]
425pub trait ExtractBoundValue {
426 type BoundType;
427 fn extract_bound_value(self) -> Self::BoundType;
428}
429
430impl<'func, M, F> ExtractBoundValue for Expression<'func, M, F>
431where
432 M: bn::FunctionMutability,
433 F: bn::FunctionForm,
434{
435 type BoundType = LowLevelILExpression<'func, M, F, bn::ValueExpr>;
436
437 fn extract_bound_value(self) -> Self::BoundType {
438 self.inner
439 }
440}
441
442impl<R: bn::Register> ExtractBoundValue for LowLevelILRegisterKind<R> {
444 type BoundType = Self;
445 fn extract_bound_value(self) -> Self::BoundType {
446 self
447 }
448}
449
450impl<R: bn::Register> ExtractBoundValue for LowLevelILSSARegisterKind<R> {
451 type BoundType = Self;
452 fn extract_bound_value(self) -> Self::BoundType {
453 self
454 }
455}
456
457impl ExtractBoundValue for u64 {
458 type BoundType = Self;
459 fn extract_bound_value(self) -> Self::BoundType {
460 self
461 }
462}
463
464impl<M, F> ExtractBoundValue for LowLevelILExpression<'_, M, F, bn::ValueExpr>
465where
466 M: bn::FunctionMutability,
467 F: bn::FunctionForm,
468{
469 type BoundType = Self;
470 fn extract_bound_value(self) -> Self::BoundType {
471 self
472 }
473}
474
475impl<M, F> ExtractBoundValue for Box<BinaryExpression<'_, M, F>>
476where
477 M: bn::FunctionMutability,
478 F: bn::FunctionForm,
479{
480 type BoundType = Self;
481 fn extract_bound_value(self) -> Self::BoundType {
482 self
483 }
484}
485
486impl<M, F> ExtractBoundValue for LowLevelILInstruction<'_, M, F>
487where
488 M: bn::FunctionMutability,
489 F: bn::FunctionForm,
490{
491 type BoundType = Self;
492 fn extract_bound_value(self) -> Self::BoundType {
493 self
494 }
495}
496
497impl<T> ExtractBoundValue for Vec<T>
498where
499 T: ExtractBoundValue,
500{
501 type BoundType = Self;
502 fn extract_bound_value(self) -> Self::BoundType {
503 self
504 }
505}
506
507#[doc(inline)]
539pub use bn_bdash_extras_macros::match_instr;
540
541#[doc(inline)]
571pub use bn_bdash_extras_macros::try_let_instr;
572
573#[doc(inline)]
648pub use bn_bdash_extras_macros::InstrMatch;