Skip to content

Commit c7d9029

Browse files
committed
Add LLIL_REG_SPLIT to rust api
1 parent 3765f2d commit c7d9029

File tree

3 files changed

+128
-0
lines changed

3 files changed

+128
-0
lines changed

rust/src/llil/expression.rs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,8 @@ where
136136
LLIL_ZX => ExprInfo::Zx(Operation::new(function, op)),
137137
LLIL_LOW_PART => ExprInfo::LowPart(Operation::new(function, op)),
138138

139+
LLIL_REG_SPLIT => ExprInfo::RegSplit(Operation::new(function, op)),
140+
139141
LLIL_CMP_E => ExprInfo::CmpE(Operation::new(function, op)),
140142
LLIL_CMP_NE => ExprInfo::CmpNe(Operation::new(function, op)),
141143
LLIL_CMP_SLT => ExprInfo::CmpSlt(Operation::new(function, op)),
@@ -273,6 +275,7 @@ where
273275
LLIL_LOAD => ExprInfo::Load(Operation::new(self.function, op)),
274276
LLIL_POP => ExprInfo::Pop(Operation::new(self.function, op)),
275277
LLIL_REG => ExprInfo::Reg(Operation::new(self.function, op)),
278+
LLIL_REG_SPLIT => ExprInfo::RegSplit(Operation::new(self.function, op)),
276279
LLIL_FLAG => ExprInfo::Flag(Operation::new(self.function, op)),
277280
LLIL_FLAG_BIT => ExprInfo::FlagBit(Operation::new(self.function, op)),
278281
LLIL_FLAG_COND => ExprInfo::FlagCond(Operation::new(self.function, op)), // TODO lifted only
@@ -327,6 +330,7 @@ where
327330
match op.operation {
328331
LLIL_LOAD_SSA => ExprInfo::Load(Operation::new(self.function, op)),
329332
LLIL_REG_SSA | LLIL_REG_SSA_PARTIAL => ExprInfo::Reg(Operation::new(self.function, op)),
333+
LLIL_REG_SPLIT_SSA => ExprInfo::RegSplit(Operation::new(self.function, op)),
330334
LLIL_FLAG_SSA => ExprInfo::Flag(Operation::new(self.function, op)),
331335
LLIL_FLAG_BIT_SSA => ExprInfo::FlagBit(Operation::new(self.function, op)),
332336
_ => common_info(self.function, op),
@@ -383,6 +387,7 @@ where
383387
Load(Operation<'func, A, M, F, operation::Load>),
384388
Pop(Operation<'func, A, M, F, operation::Pop>),
385389
Reg(Operation<'func, A, M, F, operation::Reg>),
390+
RegSplit(Operation<'func, A, M, F, operation::RegSplit>),
386391
Const(Operation<'func, A, M, F, operation::Const>),
387392
ConstPtr(Operation<'func, A, M, F, operation::Const>),
388393
Flag(Operation<'func, A, M, F, operation::Flag>),
@@ -595,6 +600,8 @@ where
595600

596601
Reg(ref op) => &op.op,
597602

603+
RegSplit(ref op) => &op.op,
604+
598605
Flag(ref op) => &op.op,
599606

600607
FlagBit(ref op) => &op.op,
@@ -648,6 +655,8 @@ where
648655

649656
Reg(ref op) => op.flag_write(),
650657

658+
RegSplit(ref op) => op.flag_write(),
659+
651660
Flag(ref op) => op.flag_write(),
652661

653662
FlagBit(ref op) => op.flag_write(),
@@ -735,6 +744,31 @@ where
735744
}
736745
}
737746

747+
RegSplit(ref op) => {
748+
let low_reg = op.low_reg();
749+
let high_reg = op.high_reg();
750+
let size = op.size();
751+
752+
let low_size = match low_reg {
753+
Register::Temp(_) => Some(size),
754+
Register::ArchReg(ref r) if r.info().size() != size => Some(size),
755+
_ => None,
756+
};
757+
758+
let high_size = match high_reg {
759+
Register::Temp(_) => Some(size),
760+
Register::ArchReg(ref r) if r.info().size() != size => Some(size),
761+
_ => None,
762+
};
763+
764+
match (low_size, high_size) {
765+
(Some(ls), Some(hs)) => write!(f, "{:?}.{}:{:?}.{}", high_reg, hs, low_reg, ls),
766+
(Some(ls), None) => write!(f, "{:?}:{:?}.{}", high_reg, low_reg, ls),
767+
(None, Some(hs)) => write!(f, "{:?}.{}:{:?}", high_reg, hs, low_reg),
768+
_ => write!(f, "{:?}:{:?}", high_reg, low_reg),
769+
}
770+
}
771+
738772
Flag(ref _op) => write!(f, "flag"), // TODO
739773

740774
FlagBit(ref _op) => write!(f, "flag_bit"), // TODO

rust/src/llil/lifting.rs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1016,6 +1016,43 @@ where
10161016
Expression::new(self, expr_idx)
10171017
}
10181018

1019+
pub fn reg_split<H: Into<Register<A::Register>>, L: Into<Register<A::Register>>>(
1020+
&self,
1021+
size: usize,
1022+
hi_reg: H,
1023+
lo_reg: L,
1024+
) -> Expression<A, Mutable, NonSSA<LiftedNonSSA>, ValueExpr> {
1025+
use binaryninjacore_sys::BNLowLevelILAddExpr;
1026+
use binaryninjacore_sys::BNLowLevelILOperation::LLIL_REG_SPLIT;
1027+
1028+
// TODO verify valid id
1029+
let hi_reg = match hi_reg.into() {
1030+
Register::ArchReg(r) => r.id(),
1031+
Register::Temp(r) => 0x8000_0000 | r,
1032+
};
1033+
1034+
// TODO verify valid id
1035+
let lo_reg = match lo_reg.into() {
1036+
Register::ArchReg(r) => r.id(),
1037+
Register::Temp(r) => 0x8000_0000 | r,
1038+
};
1039+
1040+
let expr_idx = unsafe {
1041+
BNLowLevelILAddExpr(
1042+
self.handle,
1043+
LLIL_REG_SPLIT,
1044+
size,
1045+
0,
1046+
hi_reg as u64,
1047+
lo_reg as u64,
1048+
0,
1049+
0,
1050+
)
1051+
};
1052+
1053+
Expression::new(self, expr_idx)
1054+
}
1055+
10191056
pub fn set_reg<'a, R, E>(
10201057
&'a self,
10211058
size: usize,

rust/src/llil/operation.rs

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,62 @@ where
290290
}
291291
}
292292

293+
// LLIL_REG_SPLIT
294+
pub struct RegSplit;
295+
296+
impl<'func, A, M, V> Operation<'func, A, M, NonSSA<V>, RegSplit>
297+
where
298+
A: 'func + Architecture,
299+
M: FunctionMutability,
300+
V: NonSSAVariant,
301+
{
302+
pub fn size(&self) -> usize {
303+
self.op.size
304+
}
305+
306+
pub fn low_reg(&self) -> Register<A::Register> {
307+
let raw_id = self.op.operands[0] as u32;
308+
309+
if raw_id >= 0x8000_0000 {
310+
Register::Temp(raw_id & 0x7fff_ffff)
311+
} else {
312+
self.function
313+
.arch()
314+
.register_from_id(raw_id)
315+
.map(Register::ArchReg)
316+
.unwrap_or_else(|| {
317+
error!(
318+
"got garbage register from LLIL_REG @ 0x{:x}",
319+
self.op.address
320+
);
321+
322+
Register::Temp(0)
323+
})
324+
}
325+
}
326+
327+
pub fn high_reg(&self) -> Register<A::Register> {
328+
let raw_id = self.op.operands[1] as u32;
329+
330+
if raw_id >= 0x8000_0000 {
331+
Register::Temp(raw_id & 0x7fff_ffff)
332+
} else {
333+
self.function
334+
.arch()
335+
.register_from_id(raw_id)
336+
.map(Register::ArchReg)
337+
.unwrap_or_else(|| {
338+
error!(
339+
"got garbage register from LLIL_REG @ 0x{:x}",
340+
self.op.address
341+
);
342+
343+
Register::Temp(0)
344+
})
345+
}
346+
}
347+
}
348+
293349
// LLIL_FLAG, LLIL_FLAG_SSA
294350
pub struct Flag;
295351

@@ -702,6 +758,7 @@ impl OperationArguments for SetFlag {}
702758
impl OperationArguments for Load {}
703759
impl OperationArguments for Store {}
704760
impl OperationArguments for Reg {}
761+
impl OperationArguments for RegSplit {}
705762
impl OperationArguments for Flag {}
706763
impl OperationArguments for FlagBit {}
707764
impl OperationArguments for Jump {}

0 commit comments

Comments
 (0)