diff options
| author | Glenn Smith <glenn@vector35.com> | 2024-03-07 21:32:43 -0500 |
|---|---|---|
| committer | Glenn Smith <glenn@vector35.com> | 2024-03-07 21:32:43 -0500 |
| commit | 4620519194636807511824023284542848735054 (patch) | |
| tree | 79f124def81e468f1e83a305174725ca1ff34fa0 /python | |
| parent | 72cc84aabd188e4add6e5012df86414b65d95bc8 (diff) | |
Python: More IL expr functions
- XLILFunction.get_expr: Get an expr by index
- XLILFunction.copy_expr: Copy an IL expr to a new expr
- XLILInstruction.raw_operands: the straight integers from the core
- Extra accessors on XLILLabel
Diffstat (limited to 'python')
| -rw-r--r-- | python/highlevelil.py | 42 | ||||
| -rw-r--r-- | python/lowlevelil.py | 58 | ||||
| -rw-r--r-- | python/mediumlevelil.py | 58 |
3 files changed, 154 insertions, 4 deletions
diff --git a/python/highlevelil.py b/python/highlevelil.py index 7efbcbb8..2b4d9153 100644 --- a/python/highlevelil.py +++ b/python/highlevelil.py @@ -767,6 +767,11 @@ class HighLevelILInstruction(BaseILInstruction): return GotoLabel(self.function, self.core_instr.operands[operand_index]) @property + def raw_operands(self) -> OperandsType: + """Raw operand expression indices as specified by the core structure (read-only)""" + return self.instr.operands + + @property def operands(self) -> List[HighLevelILOperandType]: """Operands for the instruction""" return list(map(lambda x: x[1], self.detailed_operands)) @@ -2783,6 +2788,43 @@ class HighLevelILFunction: operation_value = operation.value return ExpressionIndex(core.BNHighLevelILAddExpr(self.handle, operation_value, size, a, b, c, d, e)) + def get_expr_count(self) -> int: + """ + ``get_expr_count`` gives a the total number of expressions in this IL function + + You can use this to enumerate all expressions in conjunction with :py:func:`get_expr` + + .. warning :: Not all IL expressions are valid, even if their index is within the bounds of the function, + they might not be used by the function and might not contain properly structured data. + + :return: The number of expressions in the function + """ + return core.BNGetHighLevelILExprCount(self.handle) + + def get_expr(self, index: ExpressionIndex) -> Optional[HighLevelILInstruction]: + """ + ``get_expr`` retrieves the IL expression at a given expression index in the function. + + .. warning :: Not all IL expressions are valid, even if their index is within the bounds of the function, + they might not be used by the function and might not contain properly structured data. + + :param index: Index of desired expression in function + :return: A HighLevelILInstruction object for the expression, if it exists. Otherwise, None + """ + if index >= self.get_expr_count(): + return None + + return HighLevelILInstruction.create(self, index) + + def copy_expr(self, original: HighLevelILInstruction) -> ExpressionIndex: + """ + ``copy_expr`` adds an expression to the function which is equivalent to the given expression + + :param HighLevelILInstruction original: the original IL Instruction you want to copy + :return: The index of the newly copied expression + """ + return self.expr(original.operation, original.raw_operands[0], original.raw_operands[1], original.raw_operands[2], original.raw_operands[3], original.raw_operands[4], original.size) + def replace_expr(self, original: InstructionOrExpression, new: InstructionOrExpression) -> None: """ ``replace_expr`` allows modification of HLIL expressions diff --git a/python/lowlevelil.py b/python/lowlevelil.py index 16ffbd88..02586113 100644 --- a/python/lowlevelil.py +++ b/python/lowlevelil.py @@ -69,6 +69,26 @@ class LowLevelILLabel: else: self.handle = handle + @property + def ref(self) -> bool: + return self.handle[0].ref + + @ref.setter + def ref(self, value): + self.handle[0].ref = value + + @property + def resolved(self) -> bool: + return self.handle[0].resolved + + @property + def operand(self) -> InstructionIndex: + return InstructionIndex(self.handle[0].operand) + + @operand.setter + def operand(self, value: InstructionIndex): + self.handle[0].operand = int(value) + @dataclass(frozen=True) class ILRegister: @@ -671,6 +691,11 @@ class LowLevelILInstruction(BaseILInstruction): return result @property + def raw_operands(self) -> OperandsType: + """Raw operand expression indices as specified by the core structure (read-only)""" + return self.instr.operands + + @property def operands(self) -> List[LowLevelILOperandType]: """Operands for the instruction""" return list(map(lambda x: x[1], self.detailed_operands)) @@ -3232,7 +3257,7 @@ class LowLevelILFunction: def __hash__(self): return hash(ctypes.addressof(self.handle.contents)) - def __getitem__(self, i:ExpressionIndex) -> LowLevelILInstruction: + def __getitem__(self, i: InstructionIndex) -> LowLevelILInstruction: if isinstance(i, slice) or isinstance(i, tuple): raise IndexError("expected integer instruction index") if i < -len(self) or i >= len(self): @@ -3725,10 +3750,39 @@ class LowLevelILFunction: """ ``get_expr_count`` gives a the total number of expressions in this IL function - You can use this to enumerate all expressions in conjunction with LowLevelILInstruction.create() + You can use this to enumerate all expressions in conjunction with :py:func:`get_expr` + + .. warning :: Not all IL expressions are valid, even if their index is within the returned value from this, + they might not be used by the function and might not contain properly structured data. + + :return: The number of expressions in the function """ return core.BNGetLowLevelILExprCount(self.handle) + def get_expr(self, index: ExpressionIndex) -> Optional[LowLevelILInstruction]: + """ + ``get_expr`` retrieves the IL expression at a given expression index in the function. + + .. warning :: Not all IL expressions are valid, even if their index is within the bounds of the function, + they might not be used by the function and might not contain properly structured data. + + :param index: Index of desired expression in function + :return: A LowLevelILInstruction object for the expression, if it exists. Otherwise, None + """ + if index >= self.get_expr_count(): + return None + + return LowLevelILInstruction.create(self, index) + + def copy_expr(self, original: LowLevelILInstruction) -> ExpressionIndex: + """ + ``copy_expr`` adds an expression to the function which is equivalent to the given expression + + :param LowLevelILInstruction original: the original IL Instruction you want to copy + :return: The index of the newly copied expression + """ + return self.expr(original.operation, original.raw_operands[0], original.raw_operands[1], original.raw_operands[2], original.raw_operands[3], original.size, original.flags) + def replace_expr(self, original: InstructionOrExpression, new: InstructionOrExpression) -> None: """ ``replace_expr`` allows modification of expressions but ONLY during lifting. diff --git a/python/mediumlevelil.py b/python/mediumlevelil.py index 159299c7..e857920f 100644 --- a/python/mediumlevelil.py +++ b/python/mediumlevelil.py @@ -109,6 +109,26 @@ class MediumLevelILLabel: else: self.handle = handle + @property + def ref(self) -> bool: + return self.handle[0].ref + + @ref.setter + def ref(self, value): + self.handle[0].ref = value + + @property + def resolved(self) -> bool: + return self.handle[0].resolved + + @property + def operand(self) -> InstructionIndex: + return InstructionIndex(self.handle[0].operand) + + @operand.setter + def operand(self, value: InstructionIndex): + self.handle[0].operand = int(value) + @dataclass(frozen=True, repr=False) class MediumLevelILOperationAndSize: @@ -423,6 +443,11 @@ class MediumLevelILInstruction(BaseILInstruction): return list(map(lambda x: x[1], self.detailed_operands)) @property + def raw_operands(self) -> OperandsType: + """Raw operand expression indices as specified by the core structure (read-only)""" + return self.instr.operands + + @property def detailed_operands(self) -> List[Tuple[str, MediumLevelILOperandType, str]]: """ Returns a list of tuples containing the name of the operand, the operand, and the type of the operand. @@ -3394,9 +3419,38 @@ class MediumLevelILFunction: """ ``get_expr_count`` gives a the total number of expressions in this IL function - You can use this to enumerate all expressions in conjunction with MediumLevelILInstruction.create() + You can use this to enumerate all expressions in conjunction with :py:func:`get_expr` + + .. warning :: Not all IL expressions are valid, even if their index is within the bounds of the function, + they might not be used by the function and might not contain properly structured data. + + :return: The number of expressions in the function + """ + return core.BNGetMediumLevelILExprCount(self.handle) + + def get_expr(self, index: ExpressionIndex) -> Optional[MediumLevelILInstruction]: + """ + ``get_expr`` retrieves the IL expression at a given expression index in the function. + + .. warning :: Not all IL expressions are valid, even if their index is within the bounds of the function, + they might not be used by the function and might not contain properly structured data. + + :param index: Index of desired expression in function + :return: A MediumLevelILInstruction object for the expression, if it exists. Otherwise, None + """ + if index >= self.get_expr_count(): + return None + + return MediumLevelILInstruction.create(self, index) + + def copy_expr(self, original: MediumLevelILInstruction) -> ExpressionIndex: + """ + ``copy_expr`` adds an expression to the function which is equivalent to the given expression + + :param MediumLevelILInstruction original: the original IL Instruction you want to copy + :return: The index of the newly copied expression """ - return core.BNGeMediumLevelILExprCount(self.handle) + return self.expr(original.operation, original.raw_operands[0], original.raw_operands[1], original.raw_operands[2], original.raw_operands[3], original.raw_operands[4], original.size) def replace_expr(self, original: InstructionOrExpression, new: InstructionOrExpression) -> None: """ |
