summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRusty Wagner <rusty.wagner@gmail.com>2022-12-13 22:46:39 -0500
committerRusty Wagner <rusty.wagner@gmail.com>2023-01-03 10:41:46 -0500
commitffafa54703d239414e616d88633736ced71b63a5 (patch)
tree8158860a69828cdf529872b60084d1ce55ca8834
parent3681a37debf204cf2416a807a189865a3834f300 (diff)
Add instruction attributes to IL instructions
-rw-r--r--binaryninjaapi.h3
-rw-r--r--binaryninjacore.h18
-rw-r--r--highlevelil.cpp6
-rw-r--r--highlevelilinstruction.cpp41
-rw-r--r--highlevelilinstruction.h3
-rw-r--r--lowlevelil.cpp6
-rw-r--r--lowlevelilinstruction.cpp41
-rw-r--r--lowlevelilinstruction.h3
-rw-r--r--mediumlevelil.cpp6
-rw-r--r--mediumlevelilinstruction.cpp41
-rw-r--r--mediumlevelilinstruction.h3
-rw-r--r--python/highlevelil.py37
-rw-r--r--python/lowlevelil.py37
-rw-r--r--python/mediumlevelil.py37
14 files changed, 273 insertions, 9 deletions
diff --git a/binaryninjaapi.h b/binaryninjaapi.h
index 9f600a42..dfd5ecb5 100644
--- a/binaryninjaapi.h
+++ b/binaryninjaapi.h
@@ -10564,6 +10564,7 @@ namespace BinaryNinja {
void UpdateInstructionOperand(size_t i, size_t operandIndex, ExprId value);
void ReplaceExpr(size_t expr, size_t newExpr);
+ void SetExprAttributes(size_t expr, uint32_t attributes);
void AddLabelForAddress(Architecture* arch, ExprId addr);
BNLowLevelILLabel* GetLabelForAddress(Architecture* arch, ExprId addr);
@@ -10917,6 +10918,7 @@ namespace BinaryNinja {
void MarkInstructionForRemoval(size_t i);
void ReplaceInstruction(size_t i, ExprId expr);
void ReplaceExpr(size_t expr, size_t newExpr);
+ void SetExprAttributes(size_t expr, uint32_t attributes);
void Finalize();
void GenerateSSAForm(bool analyzeConditionals = true, bool handleAliases = true,
@@ -11271,6 +11273,7 @@ namespace BinaryNinja {
void UpdateInstructionOperand(size_t i, size_t operandIndex, ExprId value);
void ReplaceExpr(size_t expr, size_t newExpr);
+ void SetExprAttributes(size_t expr, uint32_t attributes);
void Finalize();
void GenerateSSAForm(const std::set<Variable>& aliases = std::set<Variable>());
diff --git a/binaryninjacore.h b/binaryninjacore.h
index 9c038104..ee4931b3 100644
--- a/binaryninjacore.h
+++ b/binaryninjacore.h
@@ -873,9 +873,22 @@ extern "C"
FlowGraphShowsSecondaryRegisterHighlighting
};
+ enum BNILInstructionAttribute
+ {
+ // If present on a store instruction, allows elimination of variables associated with the store
+ ILAllowDeadStoreElimination = 1,
+
+ // If present on a store instruction, prevents elimination of variables associated with the store
+ ILPreventDeadStoreElimination = 2,
+
+ // Assumes that a variable assignment might be used in some way during MLIL translation
+ MLILAssumePossibleUse = 4
+ };
+
struct BNLowLevelILInstruction
{
BNLowLevelILOperation operation;
+ uint32_t attributes;
size_t size;
uint32_t flags;
uint32_t sourceOperand;
@@ -1184,6 +1197,7 @@ extern "C"
struct BNMediumLevelILInstruction
{
BNMediumLevelILOperation operation;
+ uint32_t attributes;
uint32_t sourceOperand;
size_t size;
uint64_t operands[5];
@@ -1349,6 +1363,7 @@ extern "C"
struct BNHighLevelILInstruction
{
BNHighLevelILOperation operation;
+ uint32_t attributes;
uint32_t sourceOperand;
size_t size;
uint64_t operands[5];
@@ -4797,6 +4812,7 @@ extern "C"
BINARYNINJACOREAPI void BNUpdateLowLevelILOperand(
BNLowLevelILFunction* func, size_t instr, size_t operandIndex, uint64_t value);
BINARYNINJACOREAPI void BNReplaceLowLevelILExpr(BNLowLevelILFunction* func, size_t expr, size_t newExpr);
+ BINARYNINJACOREAPI void BNSetLowLevelILExprAttributes(BNLowLevelILFunction* func, size_t expr, uint32_t attributes);
BINARYNINJACOREAPI void BNAddLowLevelILLabelForAddress(
BNLowLevelILFunction* func, BNArchitecture* arch, uint64_t addr);
@@ -4950,6 +4966,7 @@ extern "C"
BINARYNINJACOREAPI void BNMarkMediumLevelILInstructionForRemoval(BNMediumLevelILFunction* func, size_t instr);
BINARYNINJACOREAPI void BNReplaceMediumLevelILInstruction(BNMediumLevelILFunction* func, size_t instr, size_t expr);
BINARYNINJACOREAPI void BNReplaceMediumLevelILExpr(BNMediumLevelILFunction* func, size_t expr, size_t newExpr);
+ BINARYNINJACOREAPI void BNSetMediumLevelILExprAttributes(BNMediumLevelILFunction* func, size_t expr, uint32_t attributes);
BINARYNINJACOREAPI bool BNGetMediumLevelILExprText(BNMediumLevelILFunction* func, BNArchitecture* arch, size_t i,
BNInstructionTextToken** tokens, size_t* count, BNDisassemblySettings* settings);
@@ -5097,6 +5114,7 @@ extern "C"
BINARYNINJACOREAPI void BNUpdateHighLevelILOperand(
BNHighLevelILFunction* func, size_t instr, size_t operandIndex, uint64_t value);
BINARYNINJACOREAPI void BNReplaceHighLevelILExpr(BNHighLevelILFunction* func, size_t expr, size_t newExpr);
+ BINARYNINJACOREAPI void BNSetHighLevelILExprAttributes(BNHighLevelILFunction* func, size_t expr, uint32_t attributes);
BINARYNINJACOREAPI BNDisassemblyTextLine* BNGetHighLevelILExprText(
BNHighLevelILFunction* func, size_t expr, bool asFullAst, size_t* count, BNDisassemblySettings* settings);
diff --git a/highlevelil.cpp b/highlevelil.cpp
index 7d3789d9..6004ce08 100644
--- a/highlevelil.cpp
+++ b/highlevelil.cpp
@@ -422,6 +422,12 @@ void HighLevelILFunction::ReplaceExpr(size_t expr, size_t newExpr)
}
+void HighLevelILFunction::SetExprAttributes(size_t expr, uint32_t attributes)
+{
+ BNSetHighLevelILExprAttributes(m_object, expr, attributes);
+}
+
+
void HighLevelILFunction::Finalize()
{
BNFinalizeHighLevelILFunction(m_object);
diff --git a/highlevelilinstruction.cpp b/highlevelilinstruction.cpp
index 0b106d8b..e9c2676d 100644
--- a/highlevelilinstruction.cpp
+++ b/highlevelilinstruction.cpp
@@ -639,6 +639,7 @@ HighLevelILOperandList::operator vector<HighLevelILOperand>() const
HighLevelILInstruction::HighLevelILInstruction()
{
operation = HLIL_UNDEF;
+ attributes = 0;
sourceOperand = BN_INVALID_OPERAND;
size = 0;
address = 0;
@@ -652,6 +653,7 @@ HighLevelILInstruction::HighLevelILInstruction(
HighLevelILFunction* func, const BNHighLevelILInstruction& instr, size_t expr, bool asFullAst, size_t instrIdx)
{
operation = instr.operation;
+ attributes = instr.attributes;
sourceOperand = instr.sourceOperand;
size = instr.size;
operands[0] = instr.operands[0];
@@ -671,6 +673,7 @@ HighLevelILInstruction::HighLevelILInstruction(
HighLevelILInstruction::HighLevelILInstruction(const HighLevelILInstructionBase& instr)
{
operation = instr.operation;
+ attributes = instr.attributes;
sourceOperand = instr.sourceOperand;
size = instr.size;
operands[0] = instr.operands[0];
@@ -933,6 +936,44 @@ void HighLevelILInstructionBase::Replace(ExprId expr)
}
+void HighLevelILInstructionBase::SetAttributes(uint32_t attributes)
+{
+ function->SetExprAttributes(exprIndex, attributes);
+}
+
+
+void HighLevelILInstructionBase::SetAttribute(BNILInstructionAttribute attribute, bool state)
+{
+ uint32_t newAttributes = attributes;
+ if (state)
+ {
+ newAttributes |= attribute;
+ switch (attribute)
+ {
+ case ILAllowDeadStoreElimination:
+ newAttributes &= ~ILPreventDeadStoreElimination;
+ break;
+ case ILPreventDeadStoreElimination:
+ newAttributes &= ~ILAllowDeadStoreElimination;
+ break;
+ default:
+ break;
+ }
+ }
+ else
+ {
+ newAttributes &= ~attribute;
+ }
+ SetAttributes(newAttributes);
+}
+
+
+void HighLevelILInstructionBase::ClearAttribute(BNILInstructionAttribute attribute)
+{
+ SetAttribute(attribute, false);
+}
+
+
size_t HighLevelILInstructionBase::GetInstructionIndex() const
{
return function->GetInstructionForExpr(exprIndex);
diff --git a/highlevelilinstruction.h b/highlevelilinstruction.h
index 13d146ac..7ac97d2d 100644
--- a/highlevelilinstruction.h
+++ b/highlevelilinstruction.h
@@ -370,6 +370,9 @@ namespace BinaryNinja
char* Dump() const;
void Replace(ExprId expr);
+ void SetAttributes(uint32_t attributes);
+ void SetAttribute(BNILInstructionAttribute attribute, bool state = true);
+ void ClearAttribute(BNILInstructionAttribute attribute);
size_t GetInstructionIndex() const;
HighLevelILInstruction GetInstruction() const;
diff --git a/lowlevelil.cpp b/lowlevelil.cpp
index 6724e9c2..3fadd92b 100644
--- a/lowlevelil.cpp
+++ b/lowlevelil.cpp
@@ -593,6 +593,12 @@ void LowLevelILFunction::ReplaceExpr(size_t expr, size_t newExpr)
}
+void LowLevelILFunction::SetExprAttributes(size_t expr, uint32_t attributes)
+{
+ BNSetLowLevelILExprAttributes(m_object, expr, attributes);
+}
+
+
void LowLevelILFunction::AddLabelForAddress(Architecture* arch, ExprId addr)
{
BNAddLowLevelILLabelForAddress(m_object, arch->GetObject(), addr);
diff --git a/lowlevelilinstruction.cpp b/lowlevelilinstruction.cpp
index 6325f0a6..842d2925 100644
--- a/lowlevelilinstruction.cpp
+++ b/lowlevelilinstruction.cpp
@@ -1348,6 +1348,7 @@ LowLevelILOperandList::operator vector<LowLevelILOperand>() const
LowLevelILInstruction::LowLevelILInstruction()
{
operation = LLIL_UNDEF;
+ attributes = 0;
sourceOperand = BN_INVALID_OPERAND;
size = 0;
flags = 0;
@@ -1362,6 +1363,7 @@ LowLevelILInstruction::LowLevelILInstruction(
LowLevelILFunction* func, const BNLowLevelILInstruction& instr, size_t expr, size_t instrIdx)
{
operation = instr.operation;
+ attributes = instr.attributes;
sourceOperand = instr.sourceOperand;
size = instr.size;
flags = instr.flags;
@@ -1379,6 +1381,7 @@ LowLevelILInstruction::LowLevelILInstruction(
LowLevelILInstruction::LowLevelILInstruction(const LowLevelILInstructionBase& instr)
{
operation = instr.operation;
+ attributes = instr.attributes;
sourceOperand = instr.sourceOperand;
size = instr.size;
flags = instr.flags;
@@ -1783,6 +1786,44 @@ void LowLevelILInstructionBase::Replace(ExprId expr)
}
+void LowLevelILInstructionBase::SetAttributes(uint32_t attributes)
+{
+ function->SetExprAttributes(exprIndex, attributes);
+}
+
+
+void LowLevelILInstructionBase::SetAttribute(BNILInstructionAttribute attribute, bool state)
+{
+ uint32_t newAttributes = attributes;
+ if (state)
+ {
+ newAttributes |= attribute;
+ switch (attribute)
+ {
+ case ILAllowDeadStoreElimination:
+ newAttributes &= ~ILPreventDeadStoreElimination;
+ break;
+ case ILPreventDeadStoreElimination:
+ newAttributes &= ~ILAllowDeadStoreElimination;
+ break;
+ default:
+ break;
+ }
+ }
+ else
+ {
+ newAttributes &= ~attribute;
+ }
+ SetAttributes(newAttributes);
+}
+
+
+void LowLevelILInstructionBase::ClearAttribute(BNILInstructionAttribute attribute)
+{
+ SetAttribute(attribute, false);
+}
+
+
void LowLevelILInstruction::VisitExprs(const std::function<bool(const LowLevelILInstruction& expr)>& func) const
{
if (!func(*this))
diff --git a/lowlevelilinstruction.h b/lowlevelilinstruction.h
index 387762e1..17c6bc2c 100644
--- a/lowlevelilinstruction.h
+++ b/lowlevelilinstruction.h
@@ -763,6 +763,9 @@ namespace BinaryNinja
char* Dump() const;
void Replace(ExprId expr);
+ void SetAttributes(uint32_t attributes);
+ void SetAttribute(BNILInstructionAttribute attribute, bool state = true);
+ void ClearAttribute(BNILInstructionAttribute attribute);
template <BNLowLevelILOperation N>
LowLevelILInstructionAccessor<N>& As()
diff --git a/mediumlevelil.cpp b/mediumlevelil.cpp
index ba2c94a3..bdb1d60e 100644
--- a/mediumlevelil.cpp
+++ b/mediumlevelil.cpp
@@ -303,6 +303,12 @@ void MediumLevelILFunction::ReplaceExpr(size_t expr, size_t newExpr)
}
+void MediumLevelILFunction::SetExprAttributes(size_t expr, uint32_t attributes)
+{
+ BNSetMediumLevelILExprAttributes(m_object, expr, attributes);
+}
+
+
void MediumLevelILFunction::Finalize()
{
BNFinalizeMediumLevelILFunction(m_object);
diff --git a/mediumlevelilinstruction.cpp b/mediumlevelilinstruction.cpp
index 0cdda81e..ee4ed9e4 100644
--- a/mediumlevelilinstruction.cpp
+++ b/mediumlevelilinstruction.cpp
@@ -887,6 +887,7 @@ MediumLevelILOperandList::operator vector<MediumLevelILOperand>() const
MediumLevelILInstruction::MediumLevelILInstruction()
{
operation = MLIL_UNDEF;
+ attributes = 0;
sourceOperand = BN_INVALID_OPERAND;
size = 0;
address = 0;
@@ -900,6 +901,7 @@ MediumLevelILInstruction::MediumLevelILInstruction(
MediumLevelILFunction* func, const BNMediumLevelILInstruction& instr, size_t expr, size_t instrIdx)
{
operation = instr.operation;
+ attributes = instr.attributes;
sourceOperand = instr.sourceOperand;
size = instr.size;
operands[0] = instr.operands[0];
@@ -917,6 +919,7 @@ MediumLevelILInstruction::MediumLevelILInstruction(
MediumLevelILInstruction::MediumLevelILInstruction(const MediumLevelILInstructionBase& instr)
{
operation = instr.operation;
+ attributes = instr.attributes;
sourceOperand = instr.sourceOperand;
size = instr.size;
operands[0] = instr.operands[0];
@@ -1328,6 +1331,44 @@ void MediumLevelILInstructionBase::Replace(ExprId expr)
}
+void MediumLevelILInstructionBase::SetAttributes(uint32_t attributes)
+{
+ function->SetExprAttributes(exprIndex, attributes);
+}
+
+
+void MediumLevelILInstructionBase::SetAttribute(BNILInstructionAttribute attribute, bool state)
+{
+ uint32_t newAttributes = attributes;
+ if (state)
+ {
+ newAttributes |= attribute;
+ switch (attribute)
+ {
+ case ILAllowDeadStoreElimination:
+ newAttributes &= ~ILPreventDeadStoreElimination;
+ break;
+ case ILPreventDeadStoreElimination:
+ newAttributes &= ~ILAllowDeadStoreElimination;
+ break;
+ default:
+ break;
+ }
+ }
+ else
+ {
+ newAttributes &= ~attribute;
+ }
+ SetAttributes(newAttributes);
+}
+
+
+void MediumLevelILInstructionBase::ClearAttribute(BNILInstructionAttribute attribute)
+{
+ SetAttribute(attribute, false);
+}
+
+
void MediumLevelILInstruction::VisitExprs(const std::function<bool(const MediumLevelILInstruction& expr)>& func) const
{
if (!func(*this))
diff --git a/mediumlevelilinstruction.h b/mediumlevelilinstruction.h
index 6d86386c..373dfa4e 100644
--- a/mediumlevelilinstruction.h
+++ b/mediumlevelilinstruction.h
@@ -509,6 +509,9 @@ namespace BinaryNinja
void MarkInstructionForRemoval();
void Replace(ExprId expr);
+ void SetAttributes(uint32_t attributes);
+ void SetAttribute(BNILInstructionAttribute attribute, bool state = true);
+ void ClearAttribute(BNILInstructionAttribute attribute);
template <BNMediumLevelILOperation N>
MediumLevelILInstructionAccessor<N>& As()
diff --git a/python/highlevelil.py b/python/highlevelil.py
index ca6a8aaf..04ae68ff 100644
--- a/python/highlevelil.py
+++ b/python/highlevelil.py
@@ -20,13 +20,13 @@
import ctypes
import struct
-from typing import Optional, Generator, List, Union, NewType, Tuple, ClassVar, Mapping
+from typing import Optional, Generator, List, Union, NewType, Tuple, ClassVar, Mapping, Set
from dataclasses import dataclass
from enum import Enum
# Binary Ninja components
from . import _binaryninjacore as core
-from .enums import HighLevelILOperation, DataFlowQueryOption, FunctionGraphType
+from .enums import HighLevelILOperation, DataFlowQueryOption, FunctionGraphType, ILInstructionAttribute
from . import decorators
from . import function
from . import binaryview
@@ -61,6 +61,7 @@ HighLevelILOperandType = Union['HighLevelILInstruction', 'lowlevelil.ILIntrinsic
'GotoLabel', databuffer.DataBuffer]
VariablesList = List[Union['mediumlevelil.SSAVariable', 'variable.Variable']]
StringOrType = Union[str, '_types.Type', '_types.TypeBuilder']
+ILInstructionAttributeSet = Union[Set[ILInstructionAttribute], List[ILInstructionAttribute]]
class VariableReferenceType(Enum):
@@ -117,6 +118,7 @@ class GotoLabel:
@dataclass(frozen=True, order=True)
class CoreHighLevelILInstruction:
operation: HighLevelILOperation
+ attributes: int
source_operand: int
size: int
operands: OperandsType
@@ -127,7 +129,7 @@ class CoreHighLevelILInstruction:
def from_BNHighLevelILInstruction(cls, instr: core.BNHighLevelILInstruction) -> 'CoreHighLevelILInstruction':
operands: OperandsType = tuple([ExpressionIndex(instr.operands[i]) for i in range(5)]) # type: ignore
return cls(
- HighLevelILOperation(instr.operation), instr.sourceOperand, instr.size, operands, instr.address,
+ HighLevelILOperation(instr.operation), instr.attributes, instr.sourceOperand, instr.size, operands, instr.address,
instr.parent
)
@@ -644,6 +646,15 @@ class HighLevelILInstruction(BaseILInstruction):
)
return None
+ @property
+ def attributes(self) -> Set[ILInstructionAttribute]:
+ """The set of optional attributes placed on the instruction"""
+ result: Set[ILInstructionAttribute] = set()
+ for flag in ILInstructionAttribute:
+ if self.core_instr.attributes & flag.value != 0:
+ result.add(flag)
+ return result
+
def get_possible_values(self, options: Optional[List[DataFlowQueryOption]] = None) -> 'variable.PossibleValueSet':
mlil = self.mlil
if mlil is None:
@@ -2418,6 +2429,26 @@ class HighLevelILFunction:
core.BNReplaceHighLevelILExpr(self.handle, original, new)
+ def set_expr_attributes(self, expr: InstructionOrExpression, value: ILInstructionAttributeSet):
+ """
+ ``set_expr_attributes`` allows modification of instruction attributes but ONLY during lifting.
+
+ .. warning:: This function should ONLY be called as a part of a lifter. It will otherwise not do anything useful as there's no way to trigger re-analysis of IL levels at this time.
+
+ :param ExpressionIndex expr: the ExpressionIndex to replace (may also be an expression index)
+ :param set(ILInstructionAttribute) value: the set of attributes to place on the instruction
+ :rtype: None
+ """
+ if isinstance(expr, HighLevelILInstruction):
+ expr = expr.expr_index
+ elif isinstance(expr, int):
+ expr = ExpressionIndex(expr)
+
+ result = 0
+ for flag in value:
+ result |= flag.value
+ core.BNSetHighLevelILExprAttributes(self.handle, expr, result)
+
def add_operand_list(self, operands: List[int]) -> ExpressionIndex:
"""
``add_operand_list`` returns an operand list expression for the given list of integer operands.
diff --git a/python/lowlevelil.py b/python/lowlevelil.py
index 4a45514a..f1fb0c5f 100644
--- a/python/lowlevelil.py
+++ b/python/lowlevelil.py
@@ -20,11 +20,11 @@
import ctypes
import struct
-from typing import Generator, List, Optional, Dict, Union, Tuple, NewType, ClassVar
+from typing import Generator, List, Optional, Dict, Union, Tuple, NewType, ClassVar, Set
from dataclasses import dataclass
# Binary Ninja components
-from .enums import LowLevelILOperation, LowLevelILFlagCondition, DataFlowQueryOption, FunctionGraphType
+from .enums import LowLevelILOperation, LowLevelILFlagCondition, DataFlowQueryOption, FunctionGraphType, ILInstructionAttribute
from . import _binaryninjacore as core
from . import basicblock #required for LowLevelILBasicBlock
from . import function
@@ -56,6 +56,7 @@ LowLevelILOperandType = Union['LowLevelILOperationAndSize', 'ILRegister', 'ILFla
'ILSemanticFlagClass', 'ILSemanticFlagGroup', 'LowLevelILFlagCondition', List[int],
List['LowLevelILInstruction'], List[Union['ILFlag', 'ILRegister']], List['SSARegister'],
List['SSARegisterStack'], List['SSAFlag'], List['SSARegisterOrFlag'], None]
+ILInstructionAttributeSet = Union[Set[ILInstructionAttribute], List[ILInstructionAttribute]]
class LowLevelILLabel:
@@ -269,6 +270,7 @@ class LowLevelILOperationAndSize:
@dataclass(frozen=True)
class CoreLowLevelILInstruction:
operation: LowLevelILOperation
+ attributes: int
size: int
flags: int
source_operand: ExpressionIndex
@@ -282,7 +284,7 @@ class CoreLowLevelILInstruction:
ExpressionIndex(instr.operands[3])
)
return cls(
- LowLevelILOperation(instr.operation), instr.size, instr.flags, instr.sourceOperand, operands, instr.address
+ LowLevelILOperation(instr.operation), instr.attributes, instr.size, instr.flags, instr.sourceOperand, operands, instr.address
)
@@ -685,6 +687,15 @@ class LowLevelILInstruction(BaseILInstruction):
result.append(LowLevelILOperationAndSize(self.instr.operation, self.instr.size))
return result
+ @property
+ def attributes(self) -> Set[ILInstructionAttribute]:
+ """The set of optional attributes placed on the instruction"""
+ result: Set[ILInstructionAttribute] = set()
+ for flag in ILInstructionAttribute:
+ if self.instr.attributes & flag.value != 0:
+ result.add(flag)
+ return result
+
@staticmethod
def _make_options_array(options: Optional[List[DataFlowQueryOption]]):
if options is None:
@@ -3166,6 +3177,26 @@ class LowLevelILFunction:
core.BNReplaceLowLevelILExpr(self.handle, original, new)
+ def set_expr_attributes(self, expr: InstructionOrExpression, value: ILInstructionAttributeSet):
+ """
+ ``set_expr_attributes`` allows modification of instruction attributes but ONLY during lifting.
+
+ .. warning:: This function should ONLY be called as a part of a lifter. It will otherwise not do anything useful as there's no way to trigger re-analysis of IL levels at this time.
+
+ :param ExpressionIndex expr: the ExpressionIndex to replace (may also be an expression index)
+ :param set(ILInstructionAttribute) value: the set of attributes to place on the instruction
+ :rtype: None
+ """
+ if isinstance(expr, LowLevelILInstruction):
+ expr = expr.expr_index
+ elif isinstance(expr, int):
+ expr = ExpressionIndex(expr)
+
+ result = 0
+ for flag in value:
+ result |= flag.value
+ core.BNSetLowLevelILExprAttributes(self.handle, expr, result)
+
def append(self, expr: ExpressionIndex) -> int:
"""
``append`` adds the ExpressionIndex ``expr`` to the current LowLevelILFunction.
diff --git a/python/mediumlevelil.py b/python/mediumlevelil.py
index 49c932f3..7280fb5e 100644
--- a/python/mediumlevelil.py
+++ b/python/mediumlevelil.py
@@ -21,12 +21,12 @@
from abc import abstractmethod
import ctypes
import struct
-from typing import Optional, List, Union, Mapping, Generator, NewType, Tuple, ClassVar, Dict
+from typing import Optional, List, Union, Mapping, Generator, NewType, Tuple, ClassVar, Dict, Set
from dataclasses import dataclass
# Binary Ninja components
from . import _binaryninjacore as core
-from .enums import MediumLevelILOperation, ILBranchDependence, DataFlowQueryOption, FunctionGraphType, DeadStoreElimination
+from .enums import MediumLevelILOperation, ILBranchDependence, DataFlowQueryOption, FunctionGraphType, DeadStoreElimination, ILInstructionAttribute
from . import basicblock
from . import function
from . import types
@@ -58,6 +58,7 @@ MediumLevelILOperandType = Union[int, float, 'MediumLevelILOperationAndSize', 'M
List['variable.Variable'], List['SSAVariable'], List['MediumLevelILInstruction'],
Mapping[int, int]]
StringOrType = Union[str, '_types.Type', '_types.TypeBuilder']
+ILInstructionAttributeSet = Union[Set[ILInstructionAttribute], List[ILInstructionAttribute]]
@dataclass(frozen=True, repr=False, order=True)
@@ -108,6 +109,7 @@ class MediumLevelILOperationAndSize:
@dataclass(frozen=True)
class CoreMediumLevelILInstruction:
operation: MediumLevelILOperation
+ attributes: int
source_operand: int
size: int
operands: OperandsType
@@ -116,7 +118,7 @@ class CoreMediumLevelILInstruction:
@classmethod
def from_BNMediumLevelILInstruction(cls, instr: core.BNMediumLevelILInstruction) -> 'CoreMediumLevelILInstruction':
operands: OperandsType = tuple([ExpressionIndex(instr.operands[i]) for i in range(5)]) # type: ignore
- return cls(MediumLevelILOperation(instr.operation), instr.sourceOperand, instr.size, operands, instr.address)
+ return cls(MediumLevelILOperation(instr.operation), instr.attributes, instr.sourceOperand, instr.size, operands, instr.address)
@dataclass(frozen=True)
@@ -578,6 +580,15 @@ class MediumLevelILInstruction(BaseILInstruction):
)
return None
+ @property
+ def attributes(self) -> Set[ILInstructionAttribute]:
+ """The set of optional attributes placed on the instruction"""
+ result: Set[ILInstructionAttribute] = set()
+ for flag in ILInstructionAttribute:
+ if self.instr.attributes & flag.value != 0:
+ result.add(flag)
+ return result
+
@staticmethod
def _make_options_array(options: Optional[List[DataFlowQueryOption]]):
if options is None:
@@ -2901,6 +2912,26 @@ class MediumLevelILFunction:
core.BNReplaceMediumLevelILExpr(self.handle, original, new)
+ def set_expr_attributes(self, expr: InstructionOrExpression, value: ILInstructionAttributeSet):
+ """
+ ``set_expr_attributes`` allows modification of instruction attributes but ONLY during lifting.
+
+ .. warning:: This function should ONLY be called as a part of a lifter. It will otherwise not do anything useful as there's no way to trigger re-analysis of IL levels at this time.
+
+ :param ExpressionIndex expr: the ExpressionIndex to replace (may also be an expression index)
+ :param set(ILInstructionAttribute) value: the set of attributes to place on the instruction
+ :rtype: None
+ """
+ if isinstance(expr, MediumLevelILInstruction):
+ expr = expr.expr_index
+ elif isinstance(expr, int):
+ expr = ExpressionIndex(expr)
+
+ result = 0
+ for flag in value:
+ result |= flag.value
+ core.BNSetMediumLevelILExprAttributes(self.handle, expr, result)
+
def append(self, expr: ExpressionIndex) -> int:
"""
``append`` adds the ExpressionIndex ``expr`` to the current MediumLevelILFunction.