Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions rust/src/low_level_il/expression.rs
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,8 @@ where
FcmpO(Operation<'func, M, F, operation::Condition>),
FcmpUO(Operation<'func, M, F, operation::Condition>),

SeparateParamListSsa(Operation<'func, M, F, operation::SeparateParamListSsa>),

// TODO ADD_OVERFLOW
Unimpl(Operation<'func, M, F, operation::NoArgs>),
UnimplMem(Operation<'func, M, F, operation::UnimplMem>),
Expand Down Expand Up @@ -428,6 +430,12 @@ where
LLIL_FCMP_O => LowLevelILExpressionKind::FcmpO(Operation::new(function, op, index)),
LLIL_FCMP_UO => LowLevelILExpressionKind::FcmpUO(Operation::new(function, op, index)),

LLIL_SEPARATE_PARAM_LIST_SSA => {
LowLevelILExpressionKind::SeparateParamListSsa(Operation::new(function, op, index))
}

LLIL_UNDEF => LowLevelILExpressionKind::Undef(Operation::new(function, op, index)),

LLIL_UNIMPL => LowLevelILExpressionKind::Unimpl(Operation::new(function, op, index)),
LLIL_UNIMPL_MEM => {
LowLevelILExpressionKind::UnimplMem(Operation::new(function, op, index))
Expand Down Expand Up @@ -598,6 +606,11 @@ where
visit!(param_expr);
}
}
SeparateParamListSsa(ref op) => {
for param_expr in op.param_exprs() {
visit!(param_expr);
}
}
// Do not have any sub expressions.
Pop(_) | Reg(_) | RegSsa(_) | RegPartialSsa(_) | RegSplit(_) | RegSplitSsa(_)
| Const(_) | ConstPtr(_) | Flag(_) | FlagBit(_) | ExternPtr(_) | FlagCond(_)
Expand Down Expand Up @@ -668,6 +681,8 @@ where
| FloatToInt(ref op) | IntToFloat(ref op) | FloatConv(ref op) | RoundToInt(ref op)
| Floor(ref op) | Ceil(ref op) | Ftrunc(ref op) => &op.op,

SeparateParamListSsa(ref op) => &op.op,

UnimplMem(ref op) => &op.op,
//TestBit(Operation<'func, M, F, operation::TestBit>), // TODO
}
Expand Down Expand Up @@ -738,6 +753,8 @@ impl LowLevelILExpressionKind<'_, Mutable, NonSSA> {
| FloatToInt(ref op) | IntToFloat(ref op) | FloatConv(ref op) | RoundToInt(ref op)
| Floor(ref op) | Ceil(ref op) | Ftrunc(ref op) => op.flag_write(),

SeparateParamListSsa(ref op) => op.flag_write(),

UnimplMem(ref op) => op.flag_write(),
//TestBit(Operation<'func, M, F, operation::TestBit>), // TODO
}
Expand Down
17 changes: 16 additions & 1 deletion rust/src/low_level_il/instruction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,10 @@ where
ForceVersion(Operation<'func, M, F, operation::ForceVersion>),
ForceVersionSsa(Operation<'func, M, F, operation::ForceVersionSsa>),

RegPhi(Operation<'func, M, F, operation::RegPhi>),
FlagPhi(Operation<'func, M, F, operation::FlagPhi>),
MemPhi(Operation<'func, M, F, operation::MemPhi>),

/// The instruction is an expression.
Value(LowLevelILExpression<'func, M, F, ValueExpr>),
}
Expand Down Expand Up @@ -317,6 +321,16 @@ where
LLIL_FORCE_VER_SSA => {
LowLevelILInstructionKind::ForceVersionSsa(Operation::new(function, op, expr_index))
}
LLIL_REG_PHI => {
LowLevelILInstructionKind::RegPhi(Operation::new(function, op, expr_index))
}
LLIL_MEM_PHI => {
LowLevelILInstructionKind::MemPhi(Operation::new(function, op, expr_index))
}
LLIL_FLAG_PHI => {
LowLevelILInstructionKind::FlagPhi(Operation::new(function, op, expr_index))
}

_ => LowLevelILInstructionKind::Value(LowLevelILExpression::new(function, expr_index)),
}
}
Expand Down Expand Up @@ -370,7 +384,8 @@ where
Value(e) => visit!(e),
// Do not have any sub expressions.
Nop(_) | NoRet(_) | Goto(_) | Syscall(_) | Bp(_) | Trap(_) | Undef(_) | Assert(_)
| AssertSsa(_) | ForceVersion(_) | ForceVersionSsa(_) => {}
| AssertSsa(_) | ForceVersion(_) | ForceVersionSsa(_) | RegPhi(_) | FlagPhi(_)
| MemPhi(_) => {}
}

VisitorAction::Sibling
Expand Down
121 changes: 118 additions & 3 deletions rust/src/low_level_il/operation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1475,40 +1475,125 @@ where

// LLIL_REG_PHI
pub struct RegPhi;
impl<M, F> Operation<'_, M, F, RegPhi>
where
M: FunctionMutability,
F: FunctionForm,
{
pub fn dest_reg(&self) -> LowLevelILSSARegisterKind<CoreRegister> {
let raw_id = RegisterId(self.op.operands[0] as u32);
let reg_kind = LowLevelILRegisterKind::from_raw(&self.function.arch(), raw_id)
.expect("Bad register ID");
let version = self.op.operands[1] as u32;
LowLevelILSSARegisterKind::new_full(reg_kind, version)
}

pub fn source_regs(&self) -> Vec<LowLevelILSSARegisterKind<CoreRegister>> {
let operand_list = self.get_operand_list(2);
let arch = self.function.arch();
operand_list
.chunks_exact(2)
.map(|chunk| {
let (register, version) = (chunk[0], chunk[1]);
LowLevelILSSARegisterKind::new_full(
LowLevelILRegisterKind::from_raw(&arch, RegisterId(register as u32))
.expect("Bad register ID"),
version as u32,
)
})
.collect()
}
}

impl<M, F> Debug for Operation<'_, M, F, RegPhi>
where
M: FunctionMutability,
F: FunctionForm,
{
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
f.debug_struct("RegPhi").finish()
f.debug_struct("RegPhi")
.field("dest_reg", &self.dest_reg())
.field("source_regs", &self.source_regs())
.finish()
}
}

// LLIL_FLAG_PHI
pub struct FlagPhi;

impl<M, F> Operation<'_, M, F, FlagPhi>
where
M: FunctionMutability,
F: FunctionForm,
{
pub fn dest_flag(&self) -> LowLevelILSSAFlag<CoreFlag> {
let flag = self
.function
.arch()
.flag_from_id(FlagId(self.op.operands[0] as u32))
.expect("Bad flag ID");
let version = self.op.operands[1] as u32;
LowLevelILSSAFlag::new(flag, version)
}

pub fn source_flags(&self) -> Vec<LowLevelILSSAFlag<CoreFlag>> {
let operand_list = self.get_operand_list(2);
operand_list
.chunks_exact(2)
.map(|chunk| {
let (flag, version) = (chunk[0], chunk[1]);
let flag = self
.function
.arch()
.flag_from_id(FlagId(flag as u32))
.expect("Bad flag ID");
LowLevelILSSAFlag::new(flag, version as u32)
})
.collect()
}
}

impl<M, F> Debug for Operation<'_, M, F, FlagPhi>
where
M: FunctionMutability,
F: FunctionForm,
{
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
f.debug_struct("FlagPhi").finish()
f.debug_struct("FlagPhi")
.field("dest_flag", &self.dest_flag())
.field("source_flags", &self.source_flags())
.finish()
}
}

// LLIL_MEM_PHI
pub struct MemPhi;

impl<M, F> Operation<'_, M, F, MemPhi>
where
M: FunctionMutability,
F: FunctionForm,
{
pub fn dest_memory_version(&self) -> usize {
self.op.operands[0] as usize
}

pub fn source_memory_versions(&self) -> Vec<usize> {
let operand_list = self.get_operand_list(1);
operand_list.into_iter().map(|op| op as usize).collect()
}
}

impl<M, F> Debug for Operation<'_, M, F, MemPhi>
where
M: FunctionMutability,
F: FunctionForm,
{
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
f.debug_struct("MemPhi").finish()
f.debug_struct("MemPhi")
.field("dest_memory_version", &self.dest_memory_version())
.field("source_memory_versions", &self.source_memory_versions())
.finish()
}
}

Expand Down Expand Up @@ -2026,6 +2111,35 @@ where
}
}

// LLIL_SEPARATE_PARAM_LIST_SSA
pub struct SeparateParamListSsa;

impl<'func, M, F> Operation<'func, M, F, SeparateParamListSsa>
where
M: FunctionMutability,
F: FunctionForm,
{
pub fn param_exprs(&self) -> Vec<LowLevelILExpression<'func, M, F, ValueExpr>> {
self.get_operand_list(0)
.into_iter()
.map(|val| LowLevelExpressionIndex(val as usize))
.map(|expr_idx| LowLevelILExpression::new(self.function, expr_idx))
.collect()
}
}

impl<M, F> Debug for Operation<'_, M, F, SeparateParamListSsa>
where
M: FunctionMutability,
F: FunctionForm,
{
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
f.debug_struct("SeparateParamListSsa")
.field("param_exprs", &self.param_exprs())
.finish()
}
}

// TODO TEST_BIT

pub trait OperationArguments: 'static {}
Expand Down Expand Up @@ -2083,3 +2197,4 @@ impl OperationArguments for Assert {}
impl OperationArguments for AssertSsa {}
impl OperationArguments for ForceVersion {}
impl OperationArguments for ForceVersionSsa {}
impl OperationArguments for SeparateParamListSsa {}
Loading