diff options
| author | Rusty Wagner <rusty.wagner@gmail.com> | 2022-12-13 22:46:39 -0500 |
|---|---|---|
| committer | Rusty Wagner <rusty.wagner@gmail.com> | 2023-01-03 10:41:46 -0500 |
| commit | ffafa54703d239414e616d88633736ced71b63a5 (patch) | |
| tree | 8158860a69828cdf529872b60084d1ce55ca8834 | |
| parent | 3681a37debf204cf2416a807a189865a3834f300 (diff) | |
Add instruction attributes to IL instructions
| -rw-r--r-- | binaryninjaapi.h | 3 | ||||
| -rw-r--r-- | binaryninjacore.h | 18 | ||||
| -rw-r--r-- | highlevelil.cpp | 6 | ||||
| -rw-r--r-- | highlevelilinstruction.cpp | 41 | ||||
| -rw-r--r-- | highlevelilinstruction.h | 3 | ||||
| -rw-r--r-- | lowlevelil.cpp | 6 | ||||
| -rw-r--r-- | lowlevelilinstruction.cpp | 41 | ||||
| -rw-r--r-- | lowlevelilinstruction.h | 3 | ||||
| -rw-r--r-- | mediumlevelil.cpp | 6 | ||||
| -rw-r--r-- | mediumlevelilinstruction.cpp | 41 | ||||
| -rw-r--r-- | mediumlevelilinstruction.h | 3 | ||||
| -rw-r--r-- | python/highlevelil.py | 37 | ||||
| -rw-r--r-- | python/lowlevelil.py | 37 | ||||
| -rw-r--r-- | python/mediumlevelil.py | 37 |
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. |
