Skip to content

Commit 4b156be

Browse files
Intrinsics don't suck anymore
1 parent 846549e commit 4b156be

File tree

1 file changed

+71
-0
lines changed

1 file changed

+71
-0
lines changed

rust/src/low_level_il/operation.rs

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,16 +230,87 @@ where
230230
// LLIL_INTRINSIC, LLIL_INTRINSIC_SSA
231231
pub struct Intrinsic;
232232

233+
#[derive(Debug, Clone, Copy)]
234+
pub enum RegOrFlag {
235+
Reg(CoreRegister),
236+
Flag(CoreFlag),
237+
}
238+
239+
impl From<CoreRegister> for RegOrFlag {
240+
fn from(value: CoreRegister) -> Self {
241+
Self::Reg(value)
242+
}
243+
}
244+
245+
impl From<CoreFlag> for RegOrFlag {
246+
fn from(value: CoreFlag) -> Self {
247+
Self::Flag(value)
248+
}
249+
}
250+
233251
impl<M, F> Operation<'_, M, F, Intrinsic>
234252
where
235253
M: FunctionMutability,
236254
F: FunctionForm,
237255
{
256+
// Order of operands for this operation:
257+
// 1. Number of outputs in the reg or flag list
258+
// 2. Reg or flag list
259+
// 3. Intrinsic id
260+
// 4. Operand list
261+
238262
// TODO: Support register and expression lists
239263
pub fn intrinsic(&self) -> Option<CoreIntrinsic> {
240264
let raw_id = self.op.operands[2] as u32;
241265
self.function.arch().intrinsic_from_id(IntrinsicId(raw_id))
242266
}
267+
268+
/// Number of outputs the intrinsic has.
269+
#[inline]
270+
pub fn output_count(&self) -> usize {
271+
self.op.operands[0] as usize
272+
}
273+
274+
/// Get the output list.
275+
pub fn outputs(&self) -> Vec<RegOrFlag> {
276+
let mut outputs = Vec::new();
277+
let mut output_size = self.op.operands[0] as usize;
278+
if output_size == 0 {
279+
return outputs;
280+
}
281+
let out_list = unsafe {
282+
BNLowLevelILGetOperandList(
283+
self.function.handle,
284+
self.expr_idx.0,
285+
0,
286+
&mut output_size as *mut _,
287+
)
288+
};
289+
let out_list = unsafe { std::slice::from_raw_parts_mut(out_list, output_size) };
290+
for val in out_list.iter() {
291+
if *val & (1 << 32) != 0 {
292+
outputs.push(
293+
self.function
294+
.arch()
295+
.flag_from_id(FlagId((*val & 0xffffffff) as u32))
296+
.expect("Invalid core flag ID")
297+
.into(),
298+
);
299+
} else {
300+
outputs.push(
301+
self.function
302+
.arch()
303+
.register_from_id(RegisterId((*val & 0xffffffff) as u32))
304+
.expect("Invalid register ID")
305+
.into(),
306+
);
307+
}
308+
}
309+
// Need to drop the list at the end. This will get leaked if there's a panic anywhere.
310+
// TODO: Make a new type for this that implements drop so it can't be leaked.
311+
unsafe { BNLowLevelILFreeOperandList(out_list.as_mut_ptr()) };
312+
outputs
313+
}
243314
}
244315

245316
impl<M, F> Debug for Operation<'_, M, F, Intrinsic>

0 commit comments

Comments
 (0)