binaryninja/
low_level_il.rs

1// Copyright 2021-2025 Vector 35 Inc.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use std::borrow::Cow;
16use std::fmt;
17
18// TODO : provide some way to forbid emitting register reads for certain registers
19// also writing for certain registers (e.g. zero register must prohibit il.set_reg and il.reg
20// (replace with nop or const(0) respectively)
21// requirements on load/store memory address sizes?
22// can reg/set_reg be used with sizes that differ from what is in BNRegisterInfo?
23
24use crate::architecture::{Architecture, Flag, RegisterId};
25use crate::architecture::{CoreRegister, Register as ArchReg};
26use crate::function::Location;
27
28pub mod block;
29pub mod expression;
30pub mod function;
31pub mod instruction;
32pub mod lifting;
33pub mod operation;
34
35use self::expression::*;
36use self::function::*;
37use self::instruction::*;
38
39/// Regular low-level IL, if you are not modifying the functions IL or needing SSA, use this.
40pub type LowLevelILRegularFunction = LowLevelILFunction<Finalized, NonSSA>;
41pub type LowLevelILRegularInstruction<'a> = LowLevelILInstruction<'a, Finalized, NonSSA>;
42pub type LowLevelILRegularInstructionKind<'a> = LowLevelILInstructionKind<'a, Finalized, NonSSA>;
43pub type LowLevelILRegularExpression<'a, ReturnType> =
44    LowLevelILExpression<'a, Finalized, NonSSA, ReturnType>;
45pub type LowLevelILRegularExpressionKind<'a> = LowLevelILExpressionKind<'a, Finalized, NonSSA>;
46
47/// Mutable low-level IL, used when lifting in architectures and modifying IL in workflow activities.
48pub type LowLevelILMutableFunction = LowLevelILFunction<Mutable, NonSSA>;
49pub type LowLevelILMutableExpression<'a, ReturnType> =
50    LowLevelILExpression<'a, Mutable, NonSSA, ReturnType>;
51
52/// SSA Variant of low-level IL, this can never be mutated directly.
53pub type LowLevelILSSAFunction = LowLevelILFunction<Finalized, SSA>;
54
55#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
56pub struct LowLevelILTempRegister {
57    /// The temporary id for the register, this will **NOT** be the referenced id in the core.
58    ///
59    /// Do not attempt to pass this to the core. Use [`LowLevelILTempRegister::id`] instead.
60    temp_id: RegisterId,
61}
62
63impl LowLevelILTempRegister {
64    pub fn new(temp_id: u32) -> Self {
65        Self {
66            temp_id: RegisterId(temp_id),
67        }
68    }
69
70    pub fn from_id(id: RegisterId) -> Option<Self> {
71        match id.is_temporary() {
72            true => {
73                let temp_id = RegisterId(id.0 & 0x7fff_ffff);
74                Some(Self { temp_id })
75            }
76            false => None,
77        }
78    }
79
80    /// The temporary registers core id, with the temporary bit set.
81    pub fn id(&self) -> RegisterId {
82        RegisterId(self.temp_id.0 | 0x8000_0000)
83    }
84}
85
86impl fmt::Debug for LowLevelILTempRegister {
87    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
88        write!(f, "temp{}", self.temp_id)
89    }
90}
91
92impl TryFrom<RegisterId> for LowLevelILTempRegister {
93    type Error = ();
94
95    fn try_from(value: RegisterId) -> Result<Self, Self::Error> {
96        Self::from_id(value).ok_or(())
97    }
98}
99
100impl From<u32> for LowLevelILTempRegister {
101    fn from(value: u32) -> Self {
102        Self::new(value)
103    }
104}
105
106#[derive(Copy, Clone, PartialEq, Eq)]
107pub enum LowLevelILRegisterKind<R: ArchReg> {
108    Arch(R),
109    Temp(LowLevelILTempRegister),
110}
111
112impl<R: ArchReg> LowLevelILRegisterKind<R> {
113    pub fn from_raw(arch: &impl Architecture<Register = R>, val: RegisterId) -> Option<Self> {
114        match val.is_temporary() {
115            true => {
116                let temp_reg = LowLevelILTempRegister::from_id(val)?;
117                Some(LowLevelILRegisterKind::Temp(temp_reg))
118            }
119            false => {
120                let arch_reg = arch.register_from_id(val)?;
121                Some(LowLevelILRegisterKind::Arch(arch_reg))
122            }
123        }
124    }
125
126    pub fn from_temp(temp: impl Into<LowLevelILTempRegister>) -> Self {
127        LowLevelILRegisterKind::Temp(temp.into())
128    }
129
130    pub fn id(&self) -> RegisterId {
131        match *self {
132            LowLevelILRegisterKind::Arch(ref r) => r.id(),
133            LowLevelILRegisterKind::Temp(temp) => temp.id(),
134        }
135    }
136
137    pub fn name(&self) -> Cow<'_, str> {
138        match *self {
139            LowLevelILRegisterKind::Arch(ref r) => r.name(),
140            LowLevelILRegisterKind::Temp(temp) => Cow::Owned(format!("temp{}", temp.temp_id)),
141        }
142    }
143}
144
145impl<R: ArchReg> fmt::Debug for LowLevelILRegisterKind<R> {
146    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
147        match *self {
148            LowLevelILRegisterKind::Arch(ref r) => r.fmt(f),
149            LowLevelILRegisterKind::Temp(id) => id.fmt(f),
150        }
151    }
152}
153
154impl From<LowLevelILTempRegister> for LowLevelILRegisterKind<CoreRegister> {
155    fn from(reg: LowLevelILTempRegister) -> Self {
156        LowLevelILRegisterKind::Temp(reg)
157    }
158}
159
160#[derive(Copy, Clone, Debug)]
161pub enum LowLevelILSSARegisterKind<R: ArchReg> {
162    Full {
163        kind: LowLevelILRegisterKind<R>,
164        version: u32,
165    },
166    Partial {
167        full_reg: CoreRegister,
168        partial_reg: CoreRegister,
169        version: u32,
170    },
171}
172
173impl<R: ArchReg> LowLevelILSSARegisterKind<R> {
174    pub fn new_full(kind: LowLevelILRegisterKind<R>, version: u32) -> Self {
175        Self::Full { kind, version }
176    }
177
178    pub fn new_partial(full_reg: CoreRegister, partial_reg: CoreRegister, version: u32) -> Self {
179        Self::Partial {
180            full_reg,
181            partial_reg,
182            version,
183        }
184    }
185
186    pub fn version(&self) -> u32 {
187        match *self {
188            LowLevelILSSARegisterKind::Full { version, .. }
189            | LowLevelILSSARegisterKind::Partial { version, .. } => version,
190        }
191    }
192}
193
194#[derive(Copy, Clone, Debug)]
195pub struct LowLevelILSSAFlag<F: Flag> {
196    pub flag: F,
197    pub version: u32,
198}
199
200impl<F: Flag> LowLevelILSSAFlag<F> {
201    pub fn new(flag: F, version: u32) -> Self {
202        Self { flag, version }
203    }
204}
205
206#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
207pub enum VisitorAction {
208    Descend,
209    Sibling,
210    Halt,
211}