Skip to content

Commit d9fd7a6

Browse files
committed
Add SSA instruction for partial variable writes in HLIL
1 parent e1ebfcd commit d9fd7a6

8 files changed

Lines changed: 108 additions & 0 deletions

File tree

binaryninjaapi.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16347,6 +16347,8 @@ namespace BinaryNinja {
1634716347

1634816348
ExprId Var(size_t size, const Variable& src, const ILSourceLocation& loc = ILSourceLocation());
1634916349
ExprId VarSSA(size_t size, const SSAVariable& src, const ILSourceLocation& loc = ILSourceLocation());
16350+
ExprId VarSSAPartial(size_t size, const Variable& dest, size_t newVersion, size_t prevVersion,
16351+
const ILSourceLocation& loc = ILSourceLocation());
1635016352
ExprId VarPhi(const SSAVariable& dest, const std::vector<SSAVariable>& sources,
1635116353
const ILSourceLocation& loc = ILSourceLocation());
1635216354
ExprId MemPhi(

binaryninjacore.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1737,6 +1737,7 @@ extern "C"
17371737
HLIL_FORCE_VER_SSA,
17381738
HLIL_ASSERT_SSA,
17391739
HLIL_VAR_SSA,
1740+
HLIL_VAR_SSA_PARTIAL,
17401741
HLIL_ARRAY_INDEX_SSA,
17411742
HLIL_DEREF_SSA,
17421743
HLIL_DEREF_FIELD_SSA,

highlevelilinstruction.cpp

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ static constexpr std::array s_operandTypeForUsage = {
6060
OperandUsageType{DestVariableHighLevelOperandUsage, VariableHighLevelOperand},
6161
OperandUsageType{SSAVariableHighLevelOperandUsage, SSAVariableHighLevelOperand},
6262
OperandUsageType{DestSSAVariableHighLevelOperandUsage, SSAVariableHighLevelOperand},
63+
OperandUsageType{PartialSSAVariableSourceHighLevelOperandUsage, SSAVariableHighLevelOperand},
6364
OperandUsageType{DestExprHighLevelOperandUsage, ExprHighLevelOperand},
6465
OperandUsageType{LeftExprHighLevelOperandUsage, ExprHighLevelOperand},
6566
OperandUsageType{RightExprHighLevelOperandUsage, ExprHighLevelOperand},
@@ -113,6 +114,12 @@ struct HighLevelILOperationTraits
113114

114115
static constexpr uint8_t GetOperandIndexAdvance(OperandUsage usage, size_t /* operandIndex */)
115116
{
117+
if (usage == PartialSSAVariableSourceHighLevelOperandUsage)
118+
{
119+
// SSA variables are usually two slots, but this one has previously defined
120+
// variables and thus only takes one slot
121+
return 1;
122+
}
116123
switch (OperandTypeForUsage(usage))
117124
{
118125
case SSAVariableHighLevelOperand:
@@ -252,6 +259,7 @@ static constexpr std::array s_instructionOperandUsage = {
252259
OperandUsage{HLIL_FORCE_VER_SSA, {DestSSAVariableHighLevelOperandUsage, SSAVariableHighLevelOperandUsage}},
253260
OperandUsage{HLIL_ASSERT_SSA, {SSAVariableHighLevelOperandUsage, ConstantHighLevelOperandUsage}},
254261
OperandUsage{HLIL_VAR_SSA, {SSAVariableHighLevelOperandUsage}},
262+
OperandUsage{HLIL_VAR_SSA_PARTIAL, {SSAVariableHighLevelOperandUsage, PartialSSAVariableSourceHighLevelOperandUsage}},
255263
OperandUsage{HLIL_ARRAY_INDEX_SSA, {SourceExprHighLevelOperandUsage, SourceMemoryVersionHighLevelOperandUsage, IndexExprHighLevelOperandUsage}},
256264
OperandUsage{HLIL_DEREF_SSA, {SourceExprHighLevelOperandUsage, SourceMemoryVersionHighLevelOperandUsage}},
257265
OperandUsage{HLIL_DEREF_FIELD_SSA, {SourceExprHighLevelOperandUsage, SourceMemoryVersionHighLevelOperandUsage, OffsetHighLevelOperandUsage, MemberIndexHighLevelOperandUsage}},
@@ -816,6 +824,12 @@ SSAVariable HighLevelILInstructionBase::GetRawOperandAsSSAVariable(size_t operan
816824
}
817825

818826

827+
SSAVariable HighLevelILInstructionBase::GetRawOperandAsPartialSSAVariableSource(size_t operand) const
828+
{
829+
return SSAVariable(Variable::FromIdentifier(operands[operand]), (size_t)operands[operand + 2]);
830+
}
831+
832+
819833
HighLevelILInstructionList HighLevelILInstructionBase::GetRawOperandAsExprList(size_t operand) const
820834
{
821835
return HighLevelILInstructionList(
@@ -1528,6 +1542,10 @@ ExprId HighLevelILInstruction::CopyTo(
15281542
return dest->Var(size, GetVariable<HLIL_VAR>(), loc);
15291543
case HLIL_VAR_SSA:
15301544
return dest->VarSSA(size, GetSSAVariable<HLIL_VAR_SSA>(), loc);
1545+
case HLIL_VAR_SSA_PARTIAL:
1546+
return dest->VarSSAPartial(size, GetDestSSAVariable<HLIL_VAR_SSA_PARTIAL>().var,
1547+
GetDestSSAVariable<HLIL_VAR_SSA_PARTIAL>().version,
1548+
GetSourceSSAVariable<HLIL_VAR_SSA_PARTIAL>().version, loc);
15311549
case HLIL_VAR_PHI:
15321550
return dest->VarPhi(GetDestSSAVariable<HLIL_VAR_PHI>(), GetSourceSSAVariables<HLIL_VAR_PHI>(), loc);
15331551
case HLIL_MEM_PHI:
@@ -1925,6 +1943,16 @@ bool HighLevelILInstruction::operator<(const HighLevelILInstruction& other) cons
19251943
if (size > other.size)
19261944
return false;
19271945
return GetSSAVariable<HLIL_VAR_SSA>() < other.GetSSAVariable<HLIL_VAR_SSA>();
1946+
case HLIL_VAR_SSA_PARTIAL:
1947+
if (size < other.size)
1948+
return true;
1949+
if (size > other.size)
1950+
return false;
1951+
if (GetDestSSAVariable<HLIL_VAR_SSA_PARTIAL>() < other.GetDestSSAVariable<HLIL_VAR_SSA_PARTIAL>())
1952+
return true;
1953+
if (other.GetDestSSAVariable<HLIL_VAR_SSA_PARTIAL>() < GetDestSSAVariable<HLIL_VAR_SSA_PARTIAL>())
1954+
return false;
1955+
return GetSourceSSAVariable<HLIL_VAR_SSA_PARTIAL>() < other.GetSourceSSAVariable<HLIL_VAR_SSA_PARTIAL>();
19281956
case HLIL_STRUCT_FIELD:
19291957
if (size < other.size)
19301958
return true;
@@ -2324,6 +2352,15 @@ SSAVariable HighLevelILInstruction::GetDestSSAVariable() const
23242352
}
23252353

23262354

2355+
SSAVariable HighLevelILInstruction::GetSourceSSAVariable() const
2356+
{
2357+
size_t operandIndex;
2358+
if (GetOperandIndexForUsage(PartialSSAVariableSourceHighLevelOperandUsage, operandIndex))
2359+
return GetRawOperandAsPartialSSAVariableSource(operandIndex - 2);
2360+
throw MediumLevelILInstructionAccessException();
2361+
}
2362+
2363+
23272364
HighLevelILInstruction HighLevelILInstruction::GetDestExpr() const
23282365
{
23292366
size_t operandIndex;
@@ -2831,6 +2868,13 @@ ExprId HighLevelILFunction::VarSSA(size_t size, const SSAVariable& src, const IL
28312868
}
28322869

28332870

2871+
ExprId HighLevelILFunction::VarSSAPartial(size_t size, const Variable& dest, size_t newVersion, size_t prevVersion,
2872+
const ILSourceLocation& loc)
2873+
{
2874+
return AddExprWithLocation(HLIL_VAR_SSA_PARTIAL, loc, size, dest.ToIdentifier(), newVersion, prevVersion);
2875+
}
2876+
2877+
28342878
ExprId HighLevelILFunction::VarPhi(
28352879
const SSAVariable& dest, const vector<SSAVariable>& sources, const ILSourceLocation& loc)
28362880
{

highlevelilinstruction.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ namespace BinaryNinja
8989
DestVariableHighLevelOperandUsage,
9090
SSAVariableHighLevelOperandUsage,
9191
DestSSAVariableHighLevelOperandUsage,
92+
PartialSSAVariableSourceHighLevelOperandUsage,
9293
DestExprHighLevelOperandUsage,
9394
LeftExprHighLevelOperandUsage,
9495
RightExprHighLevelOperandUsage,
@@ -371,6 +372,7 @@ namespace BinaryNinja
371372
HighLevelILInstruction GetRawOperandAsExpr(size_t operand) const;
372373
Variable GetRawOperandAsVariable(size_t operand) const;
373374
SSAVariable GetRawOperandAsSSAVariable(size_t operand) const;
375+
SSAVariable GetRawOperandAsPartialSSAVariableSource(size_t operand) const;
374376
HighLevelILInstructionList GetRawOperandAsExprList(size_t operand) const;
375377
HighLevelILSSAVariableList GetRawOperandAsSSAVariableList(size_t operand) const;
376378
HighLevelILIndexList GetRawOperandAsIndexList(size_t operand) const;
@@ -524,6 +526,11 @@ namespace BinaryNinja
524526
return As<N>().GetDestSSAVariable();
525527
}
526528
template <BNHighLevelILOperation N>
529+
SSAVariable GetSourceSSAVariable() const
530+
{
531+
return As<N>().GetSourceSSAVariable();
532+
}
533+
template <BNHighLevelILOperation N>
527534
HighLevelILInstruction GetDestExpr() const
528535
{
529536
return As<N>().GetDestExpr();
@@ -700,6 +707,11 @@ namespace BinaryNinja
700707
As<N>().SetDestSSAVersion(version);
701708
}
702709
template <BNHighLevelILOperation N>
710+
void SetSourceSSAVersion(size_t version)
711+
{
712+
As<N>().SetSourceSSAVersion(version);
713+
}
714+
template <BNHighLevelILOperation N>
703715
void SetParameterExprs(const _STD_VECTOR<MediumLevelILInstruction>& params)
704716
{
705717
As<N>().SetParameterExprs(params);
@@ -779,6 +791,7 @@ namespace BinaryNinja
779791
Variable GetDestVariable() const;
780792
SSAVariable GetSSAVariable() const;
781793
SSAVariable GetDestSSAVariable() const;
794+
SSAVariable GetSourceSSAVariable() const;
782795
HighLevelILInstruction GetDestExpr() const;
783796
HighLevelILInstruction GetLeftExpr() const;
784797
HighLevelILInstruction GetRightExpr() const;
@@ -1164,6 +1177,14 @@ namespace BinaryNinja
11641177
void SetSSAVersion(size_t version) { UpdateRawOperand(1, version); }
11651178
};
11661179
template <>
1180+
struct HighLevelILInstructionAccessor<HLIL_VAR_SSA_PARTIAL> : public HighLevelILInstructionBase
1181+
{
1182+
SSAVariable GetDestSSAVariable() const { return GetRawOperandAsSSAVariable(0); }
1183+
SSAVariable GetSourceSSAVariable() const { return GetRawOperandAsPartialSSAVariableSource(0); }
1184+
void SetDestSSAVersion(size_t version) { UpdateRawOperand(1, version); }
1185+
void SetSourceSSAVersion(size_t version) { UpdateRawOperand(2, version); }
1186+
};
1187+
template <>
11671188
struct HighLevelILInstructionAccessor<HLIL_VAR_PHI> : public HighLevelILInstructionBase
11681189
{
11691190
SSAVariable GetDestSSAVariable() const { return GetRawOperandAsSSAVariable(0); }

python/highlevelil.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,8 @@ class HighLevelILInstruction(BaseILInstruction):
191191
("dest", "expr_list"), ("dest_memory", "int"), ("src", "expr"), ("src_memory", "int")
192192
], HighLevelILOperation.HLIL_VAR: [("var", "var")], HighLevelILOperation.HLIL_VAR_SSA: [
193193
("var", "var_ssa")
194+
], HighLevelILOperation.HLIL_VAR_SSA_PARTIAL: [
195+
("var", "var_ssa_dest_and_src"), ("prev", "var_ssa_dest_and_src")
194196
], HighLevelILOperation.HLIL_VAR_PHI: [("dest", "var_ssa"),
195197
("src", "var_ssa_list")], HighLevelILOperation.HLIL_MEM_PHI: [
196198
("dest", "int"), ("src", "int_list")
@@ -1552,6 +1554,24 @@ def detailed_operands(self) -> List[Tuple[str, HighLevelILOperandType, str]]:
15521554
]
15531555

15541556

1557+
@dataclass(frozen=True, repr=False, eq=False)
1558+
class HighLevelILVarSsaPartial(HighLevelILInstruction, SSAVariableInstruction):
1559+
@property
1560+
def dest(self) -> 'mediumlevelil.SSAVariable':
1561+
return self._get_var_ssa(0, 1)
1562+
1563+
@property
1564+
def prev(self) -> 'mediumlevelil.SSAVariable':
1565+
return self._get_var_ssa(0, 2)
1566+
1567+
@property
1568+
def detailed_operands(self) -> List[Tuple[str, HighLevelILOperandType, str]]:
1569+
return [
1570+
("dest", self.dest, "SSAVariable"),
1571+
("prev", self.prev, "SSAVariable"),
1572+
]
1573+
1574+
15551575
@dataclass(frozen=True, repr=False, eq=False)
15561576
class HighLevelILVarPhi(HighLevelILInstruction, Phi, SetVar):
15571577
@property
@@ -2495,6 +2515,7 @@ def src(self) -> 'mediumlevelil.SSAVariable':
24952515
HighLevelILAssignUnpackMemSsa, # ("dest", "expr_list"), ("dest_memory", "int"), ("src", "expr"), ("src_memory", "int"),
24962516
HighLevelILOperation.HLIL_VAR: HighLevelILVar, # ("var", "var"),
24972517
HighLevelILOperation.HLIL_VAR_SSA: HighLevelILVarSsa, # ("var", "var_ssa"),
2518+
HighLevelILOperation.HLIL_VAR_SSA_PARTIAL: HighLevelILVarSsaPartial, # ("dest", "var_ssa_dest_and_src"), ("prev", "var_ssa_dest_and_src"),
24982519
HighLevelILOperation.HLIL_VAR_PHI: HighLevelILVarPhi, # ("dest", "var_ssa"), ("src", "var_ssa_list"),
24992520
HighLevelILOperation.HLIL_MEM_PHI: HighLevelILMemPhi, # ("dest", "int"), ("src", "int_list"),
25002521
HighLevelILOperation.HLIL_ARRAY_INDEX: HighLevelILArrayIndex, # ("src", "expr"), ("index", "expr"),

rust/src/high_level_il/instruction.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -614,6 +614,10 @@ impl HighLevelILInstruction {
614614
HLIL_VAR_SSA => Op::VarSsa(VarSsa {
615615
var: get_var_ssa((op.operands[0], op.operands[1] as usize)),
616616
}),
617+
HLIL_VAR_SSA_PARTIAL => Op::VarSsaPartial(VarSsaPartial {
618+
dest: get_var_ssa((op.operands[0], op.operands[1] as usize)),
619+
prev: get_var_ssa((op.operands[0], op.operands[2] as usize)),
620+
}),
617621
HLIL_WHILE => Op::While(While {
618622
condition: HighLevelExpressionIndex::from(op.operands[0]),
619623
body: HighLevelExpressionIndex::from(op.operands[1]),
@@ -977,6 +981,7 @@ impl HighLevelILInstruction {
977981
src: self.get_ssa_var_list(2),
978982
}),
979983
VarSsa(op) => Lifted::VarSsa(op),
984+
VarSsaPartial(op) => Lifted::VarSsaPartial(op),
980985

981986
While(op) => Lifted::While(self.lift_while(op)),
982987
DoWhile(op) => Lifted::DoWhile(self.lift_while(op)),
@@ -1274,6 +1279,7 @@ pub enum HighLevelILInstructionKind {
12741279
VarInitSsa(VarInitSsa),
12751280
VarPhi(VarPhi),
12761281
VarSsa(VarSsa),
1282+
VarSsaPartial(VarSsaPartial),
12771283
While(While),
12781284
DoWhile(While),
12791285
WhileSsa(WhileSsa),

rust/src/high_level_il/lift.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,7 @@ pub enum HighLevelILLiftedInstructionKind {
169169
VarInitSsa(LiftedVarInitSsa),
170170
VarPhi(LiftedVarPhi),
171171
VarSsa(VarSsa),
172+
VarSsaPartial(VarSsaPartial),
172173
While(LiftedWhile),
173174
DoWhile(LiftedWhile),
174175
WhileSsa(LiftedWhileSsa),
@@ -310,6 +311,7 @@ impl HighLevelILLiftedInstruction {
310311
VarInitSsa(_) => "VarInitSsa",
311312
VarPhi(_) => "VarPhi",
312313
VarSsa(_) => "VarSsa",
314+
VarSsaPartial(_) => "VarSsaPartial",
313315
While(_) => "While",
314316
DoWhile(_) => "DoWhile",
315317
WhileSsa(_) => "WhileSsa",
@@ -479,6 +481,10 @@ impl HighLevelILLiftedInstruction {
479481
("src", Operand::VarSsaList(op.src.clone())),
480482
],
481483
VarSsa(op) => vec![("var", Operand::VarSsa(op.var))],
484+
VarSsaPartial(op) => vec![
485+
("dest", Operand::VarSsa(op.dest)),
486+
("prev", Operand::VarSsa(op.prev)),
487+
],
482488
While(op) | DoWhile(op) => vec![
483489
("condition", Operand::Expr(*op.condition.clone())),
484490
("body", Operand::Expr(*op.body.clone())),

rust/src/high_level_il/operation.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -532,6 +532,13 @@ pub struct VarSsa {
532532
pub var: SSAVariable,
533533
}
534534

535+
// VAR_SSA_PARTIAL
536+
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
537+
pub struct VarSsaPartial {
538+
pub dest: SSAVariable,
539+
pub prev: SSAVariable,
540+
}
541+
535542
// WHILE, DO_WHILE
536543
#[derive(Debug, Copy, Clone)]
537544
pub struct While {

0 commit comments

Comments
 (0)