Skip to content

Commit 33b6579

Browse files
committed
Add "pass by reference" instruction to mark parameters that are passed by reference according to calling convention
1 parent efe029d commit 33b6579

14 files changed

Lines changed: 119 additions & 6 deletions

binaryninjaapi.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15752,6 +15752,7 @@ namespace BinaryNinja {
1575215752
const ILSourceLocation& loc = ILSourceLocation());
1575315753
ExprId AddressOf(const Variable& var, const ILSourceLocation& loc = ILSourceLocation());
1575415754
ExprId AddressOfField(const Variable& var, uint64_t offset, const ILSourceLocation& loc = ILSourceLocation());
15755+
ExprId PassByRef(size_t size, ExprId src, const ILSourceLocation& loc = ILSourceLocation());
1575515756
ExprId Const(size_t size, uint64_t val, const ILSourceLocation& loc = ILSourceLocation());
1575615757
ExprId ConstPointer(size_t size, uint64_t val, const ILSourceLocation& loc = ILSourceLocation());
1575715758
ExprId ExternPointer(
@@ -16147,6 +16148,7 @@ namespace BinaryNinja {
1614716148
ExprId DerefFieldSSA(size_t size, ExprId src, size_t srcMemVersion, uint64_t offset, size_t memberIndex,
1614816149
const ILSourceLocation& loc = ILSourceLocation());
1614916150
ExprId AddressOf(ExprId src, const ILSourceLocation& loc = ILSourceLocation());
16151+
ExprId PassByRef(size_t size, ExprId src, const ILSourceLocation& loc = ILSourceLocation());
1615016152
ExprId Const(size_t size, uint64_t val, const ILSourceLocation& loc = ILSourceLocation());
1615116153
ExprId ConstPointer(size_t size, uint64_t val, const ILSourceLocation& loc = ILSourceLocation());
1615216154
ExprId ExternPointer(

binaryninjacore.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1362,6 +1362,7 @@ extern "C"
13621362
MLIL_VAR_SPLIT, // Not valid in SSA form (see MLIL_VAR_SPLIT_SSA)
13631363
MLIL_ADDRESS_OF,
13641364
MLIL_ADDRESS_OF_FIELD,
1365+
MLIL_PASS_BY_REF,
13651366
MLIL_CONST,
13661367
MLIL_CONST_DATA,
13671368
MLIL_CONST_PTR,
@@ -1564,6 +1565,7 @@ extern "C"
15641565
HLIL_DEREF,
15651566
HLIL_DEREF_FIELD,
15661567
HLIL_ADDRESS_OF,
1568+
HLIL_PASS_BY_REF,
15671569
HLIL_CONST,
15681570
HLIL_CONST_DATA,
15691571
HLIL_CONST_PTR,

highlevelilinstruction.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,7 @@ static constexpr std::array s_instructionOperandUsage = {
159159
OperandUsage{HLIL_DEREF, {SourceExprHighLevelOperandUsage}},
160160
OperandUsage{HLIL_DEREF_FIELD, {SourceExprHighLevelOperandUsage, OffsetHighLevelOperandUsage, MemberIndexHighLevelOperandUsage}},
161161
OperandUsage{HLIL_ADDRESS_OF, {SourceExprHighLevelOperandUsage}},
162+
OperandUsage{HLIL_PASS_BY_REF, {SourceExprHighLevelOperandUsage}},
162163
OperandUsage{HLIL_CONST, {ConstantHighLevelOperandUsage}},
163164
OperandUsage{HLIL_CONST_DATA, {ConstantDataHighLevelOperandUsage}},
164165
OperandUsage{HLIL_CONST_PTR, {ConstantHighLevelOperandUsage}},
@@ -1265,6 +1266,7 @@ void HighLevelILInstruction::CollectSubExprs(stack<size_t>& toProcess) const
12651266
case HLIL_FLOOR:
12661267
case HLIL_CEIL:
12671268
case HLIL_FTRUNC:
1269+
case HLIL_PASS_BY_REF:
12681270
toProcess.push(AsOneOperand().GetSourceExpr().exprIndex);
12691271
break;
12701272
case HLIL_ADD:
@@ -1571,6 +1573,7 @@ ExprId HighLevelILInstruction::CopyTo(
15711573
case HLIL_FLOOR:
15721574
case HLIL_CEIL:
15731575
case HLIL_FTRUNC:
1576+
case HLIL_PASS_BY_REF:
15741577
return dest->AddExprWithLocation(operation, loc, size, subExprHandler(AsOneOperand().GetSourceExpr()));
15751578
case HLIL_ADD:
15761579
case HLIL_SUB:
@@ -2129,6 +2132,7 @@ bool HighLevelILInstruction::operator<(const HighLevelILInstruction& other) cons
21292132
case HLIL_FLOOR:
21302133
case HLIL_CEIL:
21312134
case HLIL_FTRUNC:
2135+
case HLIL_PASS_BY_REF:
21322136
if (size < other.size)
21332137
return true;
21342138
if (size > other.size)
@@ -2841,6 +2845,12 @@ ExprId HighLevelILFunction::AddressOf(ExprId src, const ILSourceLocation& loc)
28412845
}
28422846

28432847

2848+
ExprId HighLevelILFunction::PassByRef(size_t size, ExprId src, const ILSourceLocation& loc)
2849+
{
2850+
return AddExprWithLocation(HLIL_PASS_BY_REF, loc, size, src);
2851+
}
2852+
2853+
28442854
ExprId HighLevelILFunction::Const(size_t size, uint64_t val, const ILSourceLocation& loc)
28452855
{
28462856
return AddExprWithLocation(HLIL_CONST, loc, size, val);

highlevelilinstruction.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1497,6 +1497,9 @@ namespace BinaryNinja
14971497
template <>
14981498
struct HighLevelILInstructionAccessor<HLIL_FTRUNC> : public HighLevelILOneOperandInstruction
14991499
{};
1500+
template <>
1501+
struct HighLevelILInstructionAccessor<HLIL_PASS_BY_REF> : public HighLevelILOneOperandInstruction
1502+
{};
15001503

15011504
#undef _STD_VECTOR
15021505
#undef _STD_SET

lang/c/pseudoc.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1816,6 +1816,23 @@ void PseudoCFunction::GetExprTextInternal(const HighLevelILInstruction& instr, H
18161816
}();
18171817
break;
18181818

1819+
case HLIL_PASS_BY_REF:
1820+
[&]() {
1821+
const auto srcExpr = instr.GetSourceExpr<HLIL_PASS_BY_REF>();
1822+
if (srcExpr.operation == HLIL_ADDRESS_OF)
1823+
{
1824+
GetExprTextInternal(srcExpr.GetSourceExpr<HLIL_ADDRESS_OF>(), tokens, settings, precedence);
1825+
}
1826+
else
1827+
{
1828+
tokens.Append(OperationToken, "*");
1829+
GetExprTextInternal(srcExpr, tokens, settings, UnaryOperatorPrecedence);
1830+
}
1831+
if (statement)
1832+
tokens.AppendSemicolon();
1833+
}();
1834+
break;
1835+
18191836
case HLIL_FCMP_E:
18201837
[&]() {
18211838
bool parens = precedence > EqualityOperatorPrecedence;

lang/rust/pseudorust.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1900,6 +1900,15 @@ void PseudoRustFunction::GetExprText(const HighLevelILInstruction& instr, HighLe
19001900
}();
19011901
break;
19021902

1903+
case HLIL_PASS_BY_REF:
1904+
[&]() {
1905+
const auto srcExpr = instr.GetSourceExpr<HLIL_PASS_BY_REF>();
1906+
GetExprText(srcExpr, tokens, settings, UnaryOperatorPrecedence);
1907+
if (exprType != InnerExpression)
1908+
tokens.AppendSemicolon();
1909+
}();
1910+
break;
1911+
19031912
case HLIL_FCMP_E:
19041913
case HLIL_CMP_E:
19051914
[&]() {

mediumlevelilinstruction.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,7 @@ static constexpr std::array s_instructionOperandUsage = {
167167
OperandUsage{MLIL_VAR_SPLIT, {HighVariableMediumLevelOperandUsage, LowVariableMediumLevelOperandUsage}},
168168
OperandUsage{MLIL_ADDRESS_OF, {SourceVariableMediumLevelOperandUsage}},
169169
OperandUsage{MLIL_ADDRESS_OF_FIELD, {SourceVariableMediumLevelOperandUsage, OffsetMediumLevelOperandUsage}},
170+
OperandUsage{MLIL_PASS_BY_REF, {SourceExprMediumLevelOperandUsage}},
170171
OperandUsage{MLIL_CONST, {ConstantMediumLevelOperandUsage}},
171172
OperandUsage{MLIL_CONST_DATA, {ConstantDataMediumLevelOperandUsage}},
172173
OperandUsage{MLIL_CONST_PTR, {ConstantMediumLevelOperandUsage}},
@@ -1487,6 +1488,7 @@ void MediumLevelILInstruction::VisitExprs(bn::base::function_ref<bool(const Medi
14871488
case MLIL_FLOOR:
14881489
case MLIL_CEIL:
14891490
case MLIL_FTRUNC:
1491+
case MLIL_PASS_BY_REF:
14901492
AsOneOperand().GetSourceExpr().VisitExprs(func);
14911493
break;
14921494
case MLIL_ADD:
@@ -1774,6 +1776,7 @@ ExprId MediumLevelILInstruction::CopyTo(MediumLevelILFunction* dest,
17741776
case MLIL_FLOOR:
17751777
case MLIL_CEIL:
17761778
case MLIL_FTRUNC:
1779+
case MLIL_PASS_BY_REF:
17771780
return dest->AddExprWithLocation(operation, loc, size, subExprHandler(AsOneOperand().GetSourceExpr()));
17781781
case MLIL_ADD:
17791782
case MLIL_SUB:
@@ -2433,6 +2436,12 @@ ExprId MediumLevelILFunction::AddressOfField(const Variable& var, uint64_t offse
24332436
}
24342437

24352438

2439+
ExprId MediumLevelILFunction::PassByRef(size_t size, ExprId src, const ILSourceLocation& loc)
2440+
{
2441+
return AddExprWithLocation(MLIL_PASS_BY_REF, loc, size, src);
2442+
}
2443+
2444+
24362445
ExprId MediumLevelILFunction::Const(size_t size, uint64_t val, const ILSourceLocation& loc)
24372446
{
24382447
return AddExprWithLocation(MLIL_CONST, loc, size, val);

mediumlevelilinstruction.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1804,6 +1804,9 @@ namespace BinaryNinja
18041804
template <>
18051805
struct MediumLevelILInstructionAccessor<MLIL_FTRUNC> : public MediumLevelILOneOperandInstruction
18061806
{};
1807+
template <>
1808+
struct MediumLevelILInstructionAccessor<MLIL_PASS_BY_REF> : public MediumLevelILOneOperandInstruction
1809+
{};
18071810

18081811
#undef _STD_VECTOR
18091812
#undef _STD_SET

python/highlevelil.py

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,9 @@ class HighLevelILInstruction(BaseILInstruction):
210210
], HighLevelILOperation.HLIL_DEREF_FIELD_SSA: [
211211
("src", "expr"), ("src_memory", "int"), ("offset", "int"),
212212
("member_index", "member_index")
213-
], HighLevelILOperation.HLIL_ADDRESS_OF: [("src", "expr")], HighLevelILOperation.HLIL_CONST: [
213+
], HighLevelILOperation.HLIL_ADDRESS_OF: [("src", "expr")], HighLevelILOperation.HLIL_PASS_BY_REF: [
214+
("src", "expr")
215+
], HighLevelILOperation.HLIL_CONST: [
214216
("constant", "int")
215217
], HighLevelILOperation.HLIL_CONST_PTR: [("constant", "int")], HighLevelILOperation.HLIL_EXTERN_PTR: [
216218
("constant", "int"), ("offset", "int")
@@ -1743,6 +1745,11 @@ def vars_address_taken(self) -> VariablesList:
17431745
return [*self.src.vars_address_taken]
17441746

17451747

1748+
@dataclass(frozen=True, repr=False, eq=False)
1749+
class HighLevelILPassByRef(HighLevelILUnaryBase):
1750+
pass
1751+
1752+
17461753
@dataclass(frozen=True, repr=False, eq=False)
17471754
class HighLevelILConst(HighLevelILInstruction, Constant):
17481755
@property
@@ -2429,6 +2436,7 @@ def src(self) -> 'mediumlevelil.SSAVariable':
24292436
HighLevelILOperation.HLIL_DEREF_FIELD_SSA:
24302437
HighLevelILDerefFieldSsa, # ("src", "expr"), ("src_memory", "int"), ("offset", "int"), ("member_index", "member_index"),
24312438
HighLevelILOperation.HLIL_ADDRESS_OF: HighLevelILAddressOf, # ("src", "expr"),
2439+
HighLevelILOperation.HLIL_PASS_BY_REF: HighLevelILPassByRef, # ("src", "expr"),
24322440
HighLevelILOperation.HLIL_CONST: HighLevelILConst, # ("constant", "int"),
24332441
HighLevelILOperation.HLIL_CONST_PTR: HighLevelILConstPtr, # ("constant", "int"),
24342442
HighLevelILOperation.HLIL_EXTERN_PTR: HighLevelILExternPtr, # ("constant", "int"), ("offset", "int"),
@@ -3380,6 +3388,18 @@ def address_of(self, src: ExpressionIndex, loc: Optional['ILSourceLocation'] = N
33803388
"""
33813389
return self.expr(HighLevelILOperation.HLIL_ADDRESS_OF, src, size=0, source_location=loc)
33823390

3391+
def pass_by_ref(self, size: int, src: ExpressionIndex, loc: Optional['ILSourceLocation'] = None) -> ExpressionIndex:
3392+
"""
3393+
``pass_by_ref`` indicates that ``value`` is being passed by reference to a call with a pointer size of ``size``
3394+
3395+
:param int size: the size of the pointer in bytes
3396+
:param ExpressionIndex src: the expression containing the reference being passed
3397+
:param ILSourceLocation loc: location of returned expression
3398+
:return: The expression ``ref *src``
3399+
:rtype: ExpressionIndex
3400+
"""
3401+
return self.expr(HighLevelILOperation.HLIL_PASS_BY_REF, src, size, source_location=loc)
3402+
33833403
def const(self, size: int, value: int, loc: Optional['ILSourceLocation'] = None) -> ExpressionIndex:
33843404
"""
33853405
``const`` returns an expression for the constant integer ``value`` of size ``size``

python/mediumlevelil.py

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,9 @@ class MediumLevelILInstruction(BaseILInstruction):
218218
MediumLevelILOperation.MLIL_VAR: [("src", "var")], MediumLevelILOperation.MLIL_VAR_FIELD: [
219219
("src", "var"), ("offset", "int")
220220
], MediumLevelILOperation.MLIL_VAR_SPLIT: [("high", "var"), ("low", "var")],
221-
MediumLevelILOperation.MLIL_ADDRESS_OF: [("src", "var")], MediumLevelILOperation.MLIL_ADDRESS_OF_FIELD: [
221+
MediumLevelILOperation.MLIL_ADDRESS_OF: [("src", "var")], MediumLevelILOperation.MLIL_PASS_BY_REF: [
222+
("src", "expr")
223+
], MediumLevelILOperation.MLIL_ADDRESS_OF_FIELD: [
222224
("src", "var"), ("offset", "int")
223225
], MediumLevelILOperation.MLIL_CONST: [("constant", "int")], MediumLevelILOperation.MLIL_CONST_PTR: [
224226
("constant", "int")
@@ -1310,6 +1312,11 @@ def vars_address_taken(self) -> List[variable.Variable]:
13101312
return [self.src]
13111313

13121314

1315+
@dataclass(frozen=True, repr=False, eq=False)
1316+
class MediumLevelILPassByRef(MediumLevelILUnaryBase):
1317+
pass
1318+
1319+
13131320
@dataclass(frozen=True, repr=False, eq=False)
13141321
class MediumLevelILConst(MediumLevelILConstBase):
13151322
@property
@@ -3118,6 +3125,7 @@ def detailed_operands(self) -> List[Tuple[str, MediumLevelILOperandType, str]]:
31183125
MediumLevelILOperation.MLIL_LOAD: MediumLevelILLoad, # [("src", "expr")],
31193126
MediumLevelILOperation.MLIL_VAR: MediumLevelILVar, # [("src", "var")],
31203127
MediumLevelILOperation.MLIL_ADDRESS_OF: MediumLevelILAddressOf, # [("src", "var")],
3128+
MediumLevelILOperation.MLIL_PASS_BY_REF: MediumLevelILPassByRef, # [("src", "expr")],
31213129
MediumLevelILOperation.MLIL_CONST: MediumLevelILConst, # [("constant", "int")],
31223130
MediumLevelILOperation.MLIL_CONST_PTR: MediumLevelILConstPtr, # [("constant", "int")],
31233131
MediumLevelILOperation.MLIL_FLOAT_CONST: MediumLevelILFloatConst, # [("constant", "float")],
@@ -3740,6 +3748,9 @@ def do_copy(
37403748
if expr.operation == MediumLevelILOperation.MLIL_ADDRESS_OF:
37413749
expr: MediumLevelILAddressOf
37423750
return dest.address_of(expr.src, loc)
3751+
if expr.operation == MediumLevelILOperation.MLIL_PASS_BY_REF:
3752+
expr: MediumLevelILPassByRef
3753+
return dest.pass_by_ref(expr.size, expr.src, loc)
37433754
if expr.operation == MediumLevelILOperation.MLIL_ADDRESS_OF_FIELD:
37443755
expr: MediumLevelILAddressOfField
37453756
return dest.address_of_field(expr.src, expr.offset, loc)
@@ -4367,6 +4378,18 @@ def address_of(self, var: 'variable.Variable', loc: Optional['ILSourceLocation']
43674378
"""
43684379
return self.expr(MediumLevelILOperation.MLIL_ADDRESS_OF, var.identifier, size=0, source_location=loc)
43694380

4381+
def pass_by_ref(self, size: int, value: ExpressionIndex, loc: Optional['ILSourceLocation'] = None) -> ExpressionIndex:
4382+
"""
4383+
``pass_by_ref`` indicates that ``value`` is being passed by reference to a call with a pointer size of ``size``
4384+
4385+
:param int size: the size of the pointer in bytes
4386+
:param ExpressionIndex value: the expression containing the reference being passed
4387+
:param ILSourceLocation loc: location of returned expression
4388+
:return: The expression ``ref *value``
4389+
:rtype: ExpressionIndex
4390+
"""
4391+
return self.expr(MediumLevelILOperation.MLIL_PASS_BY_REF, value, size=size, source_location=loc)
4392+
43704393
def address_of_field(self, var: 'variable.Variable', offset: int, loc: Optional['ILSourceLocation'] = None) -> ExpressionIndex:
43714394
"""
43724395
``address_of_field`` takes the address of ``var`` at the offset ``offset``

0 commit comments

Comments
 (0)