summaryrefslogtreecommitdiff
path: root/rust/src
diff options
context:
space:
mode:
authorMason Reed <mason@vector35.com>2024-06-28 11:32:21 -0400
committermason <35282038+emesare@users.noreply.github.com>2024-07-01 12:35:51 +0000
commitc7d90297d41af6c178dbed4b8c389567aa4a4d06 (patch)
treebcebdf11d6fa2fac07e558bdece6a823566f2844 /rust/src
parent3765f2dce4addd02364af6fb2973ff8eb47a7cd9 (diff)
Add LLIL_REG_SPLIT to rust api
Diffstat (limited to 'rust/src')
-rw-r--r--rust/src/llil/expression.rs34
-rw-r--r--rust/src/llil/lifting.rs37
-rw-r--r--rust/src/llil/operation.rs57
3 files changed, 128 insertions, 0 deletions
diff --git a/rust/src/llil/expression.rs b/rust/src/llil/expression.rs
index d8a3a643..4339787b 100644
--- a/rust/src/llil/expression.rs
+++ b/rust/src/llil/expression.rs
@@ -136,6 +136,8 @@ where
LLIL_ZX => ExprInfo::Zx(Operation::new(function, op)),
LLIL_LOW_PART => ExprInfo::LowPart(Operation::new(function, op)),
+ LLIL_REG_SPLIT => ExprInfo::RegSplit(Operation::new(function, op)),
+
LLIL_CMP_E => ExprInfo::CmpE(Operation::new(function, op)),
LLIL_CMP_NE => ExprInfo::CmpNe(Operation::new(function, op)),
LLIL_CMP_SLT => ExprInfo::CmpSlt(Operation::new(function, op)),
@@ -273,6 +275,7 @@ where
LLIL_LOAD => ExprInfo::Load(Operation::new(self.function, op)),
LLIL_POP => ExprInfo::Pop(Operation::new(self.function, op)),
LLIL_REG => ExprInfo::Reg(Operation::new(self.function, op)),
+ LLIL_REG_SPLIT => ExprInfo::RegSplit(Operation::new(self.function, op)),
LLIL_FLAG => ExprInfo::Flag(Operation::new(self.function, op)),
LLIL_FLAG_BIT => ExprInfo::FlagBit(Operation::new(self.function, op)),
LLIL_FLAG_COND => ExprInfo::FlagCond(Operation::new(self.function, op)), // TODO lifted only
@@ -327,6 +330,7 @@ where
match op.operation {
LLIL_LOAD_SSA => ExprInfo::Load(Operation::new(self.function, op)),
LLIL_REG_SSA | LLIL_REG_SSA_PARTIAL => ExprInfo::Reg(Operation::new(self.function, op)),
+ LLIL_REG_SPLIT_SSA => ExprInfo::RegSplit(Operation::new(self.function, op)),
LLIL_FLAG_SSA => ExprInfo::Flag(Operation::new(self.function, op)),
LLIL_FLAG_BIT_SSA => ExprInfo::FlagBit(Operation::new(self.function, op)),
_ => common_info(self.function, op),
@@ -383,6 +387,7 @@ where
Load(Operation<'func, A, M, F, operation::Load>),
Pop(Operation<'func, A, M, F, operation::Pop>),
Reg(Operation<'func, A, M, F, operation::Reg>),
+ RegSplit(Operation<'func, A, M, F, operation::RegSplit>),
Const(Operation<'func, A, M, F, operation::Const>),
ConstPtr(Operation<'func, A, M, F, operation::Const>),
Flag(Operation<'func, A, M, F, operation::Flag>),
@@ -595,6 +600,8 @@ where
Reg(ref op) => &op.op,
+ RegSplit(ref op) => &op.op,
+
Flag(ref op) => &op.op,
FlagBit(ref op) => &op.op,
@@ -648,6 +655,8 @@ where
Reg(ref op) => op.flag_write(),
+ RegSplit(ref op) => op.flag_write(),
+
Flag(ref op) => op.flag_write(),
FlagBit(ref op) => op.flag_write(),
@@ -735,6 +744,31 @@ where
}
}
+ RegSplit(ref op) => {
+ let low_reg = op.low_reg();
+ let high_reg = op.high_reg();
+ let size = op.size();
+
+ let low_size = match low_reg {
+ Register::Temp(_) => Some(size),
+ Register::ArchReg(ref r) if r.info().size() != size => Some(size),
+ _ => None,
+ };
+
+ let high_size = match high_reg {
+ Register::Temp(_) => Some(size),
+ Register::ArchReg(ref r) if r.info().size() != size => Some(size),
+ _ => None,
+ };
+
+ match (low_size, high_size) {
+ (Some(ls), Some(hs)) => write!(f, "{:?}.{}:{:?}.{}", high_reg, hs, low_reg, ls),
+ (Some(ls), None) => write!(f, "{:?}:{:?}.{}", high_reg, low_reg, ls),
+ (None, Some(hs)) => write!(f, "{:?}.{}:{:?}", high_reg, hs, low_reg),
+ _ => write!(f, "{:?}:{:?}", high_reg, low_reg),
+ }
+ }
+
Flag(ref _op) => write!(f, "flag"), // TODO
FlagBit(ref _op) => write!(f, "flag_bit"), // TODO
diff --git a/rust/src/llil/lifting.rs b/rust/src/llil/lifting.rs
index daf95ac3..e6226070 100644
--- a/rust/src/llil/lifting.rs
+++ b/rust/src/llil/lifting.rs
@@ -1016,6 +1016,43 @@ where
Expression::new(self, expr_idx)
}
+ pub fn reg_split<H: Into<Register<A::Register>>, L: Into<Register<A::Register>>>(
+ &self,
+ size: usize,
+ hi_reg: H,
+ lo_reg: L,
+ ) -> Expression<A, Mutable, NonSSA<LiftedNonSSA>, ValueExpr> {
+ use binaryninjacore_sys::BNLowLevelILAddExpr;
+ use binaryninjacore_sys::BNLowLevelILOperation::LLIL_REG_SPLIT;
+
+ // TODO verify valid id
+ let hi_reg = match hi_reg.into() {
+ Register::ArchReg(r) => r.id(),
+ Register::Temp(r) => 0x8000_0000 | r,
+ };
+
+ // TODO verify valid id
+ let lo_reg = match lo_reg.into() {
+ Register::ArchReg(r) => r.id(),
+ Register::Temp(r) => 0x8000_0000 | r,
+ };
+
+ let expr_idx = unsafe {
+ BNLowLevelILAddExpr(
+ self.handle,
+ LLIL_REG_SPLIT,
+ size,
+ 0,
+ hi_reg as u64,
+ lo_reg as u64,
+ 0,
+ 0,
+ )
+ };
+
+ Expression::new(self, expr_idx)
+ }
+
pub fn set_reg<'a, R, E>(
&'a self,
size: usize,
diff --git a/rust/src/llil/operation.rs b/rust/src/llil/operation.rs
index dfcfbc17..f42b3693 100644
--- a/rust/src/llil/operation.rs
+++ b/rust/src/llil/operation.rs
@@ -290,6 +290,62 @@ where
}
}
+// LLIL_REG_SPLIT
+pub struct RegSplit;
+
+impl<'func, A, M, V> Operation<'func, A, M, NonSSA<V>, RegSplit>
+ where
+ A: 'func + Architecture,
+ M: FunctionMutability,
+ V: NonSSAVariant,
+{
+ pub fn size(&self) -> usize {
+ self.op.size
+ }
+
+ pub fn low_reg(&self) -> Register<A::Register> {
+ let raw_id = self.op.operands[0] as u32;
+
+ if raw_id >= 0x8000_0000 {
+ Register::Temp(raw_id & 0x7fff_ffff)
+ } else {
+ self.function
+ .arch()
+ .register_from_id(raw_id)
+ .map(Register::ArchReg)
+ .unwrap_or_else(|| {
+ error!(
+ "got garbage register from LLIL_REG @ 0x{:x}",
+ self.op.address
+ );
+
+ Register::Temp(0)
+ })
+ }
+ }
+
+ pub fn high_reg(&self) -> Register<A::Register> {
+ let raw_id = self.op.operands[1] as u32;
+
+ if raw_id >= 0x8000_0000 {
+ Register::Temp(raw_id & 0x7fff_ffff)
+ } else {
+ self.function
+ .arch()
+ .register_from_id(raw_id)
+ .map(Register::ArchReg)
+ .unwrap_or_else(|| {
+ error!(
+ "got garbage register from LLIL_REG @ 0x{:x}",
+ self.op.address
+ );
+
+ Register::Temp(0)
+ })
+ }
+ }
+}
+
// LLIL_FLAG, LLIL_FLAG_SSA
pub struct Flag;
@@ -702,6 +758,7 @@ impl OperationArguments for SetFlag {}
impl OperationArguments for Load {}
impl OperationArguments for Store {}
impl OperationArguments for Reg {}
+impl OperationArguments for RegSplit {}
impl OperationArguments for Flag {}
impl OperationArguments for FlagBit {}
impl OperationArguments for Jump {}