diff options
| -rw-r--r-- | architecture.cpp | 20 | ||||
| -rw-r--r-- | binaryninjaapi.h | 10 | ||||
| -rw-r--r-- | binaryninjacore.h | 7 | ||||
| -rw-r--r-- | lowlevelil.cpp | 39 | ||||
| -rw-r--r-- | python/architecture.py | 42 | ||||
| -rw-r--r-- | python/examples/nes.py | 9 |
6 files changed, 105 insertions, 22 deletions
diff --git a/architecture.cpp b/architecture.cpp index d72e7f42..02f2a88f 100644 --- a/architecture.cpp +++ b/architecture.cpp @@ -598,22 +598,30 @@ vector<uint32_t> Architecture::GetFlagsWrittenByFlagWriteType(uint32_t) size_t Architecture::GetFlagWriteLowLevelIL(BNLowLevelILOperation op, size_t size, uint32_t flagWriteType, uint32_t flag, BNRegisterOrConstant* operands, size_t operandCount,LowLevelILFunction& il) { - return BNGetDefaultArchitectureFlagWriteLowLevelIL(m_object, op, size, flagWriteType, flag, operands, + (void)flagWriteType; + BNFlagRole role = GetFlagRole(flag); + return BNGetDefaultArchitectureFlagWriteLowLevelIL(m_object, op, size, role, operands, operandCount, il.GetObject()); } -size_t Architecture::GetDefaultFlagWriteLowLevelIL(BNLowLevelILOperation op, size_t size, uint32_t flagWriteType, - uint32_t flag, BNRegisterOrConstant* operands, size_t operandCount,LowLevelILFunction& il) +size_t Architecture::GetDefaultFlagWriteLowLevelIL(BNLowLevelILOperation op, size_t size, BNFlagRole role, + BNRegisterOrConstant* operands, size_t operandCount,LowLevelILFunction& il) { - return BNGetDefaultArchitectureFlagWriteLowLevelIL(m_object, op, size, flagWriteType, flag, operands, + return BNGetDefaultArchitectureFlagWriteLowLevelIL(m_object, op, size, role, operands, operandCount, il.GetObject()); } -ExprId Architecture::GetFlagConditionLowLevelIL(BNLowLevelILFlagCondition, LowLevelILFunction& il) +ExprId Architecture::GetFlagConditionLowLevelIL(BNLowLevelILFlagCondition cond, LowLevelILFunction& il) +{ + return BNGetDefaultArchitectureFlagConditionLowLevelIL(m_object, cond, il.GetObject()); +} + + +ExprId Architecture::GetDefaultFlagConditionLowLevelIL(BNLowLevelILFlagCondition cond, LowLevelILFunction& il) { - return il.Unimplemented(); + return BNGetDefaultArchitectureFlagConditionLowLevelIL(m_object, cond, il.GetObject()); } diff --git a/binaryninjaapi.h b/binaryninjaapi.h index a179a810..068653b3 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -1440,9 +1440,10 @@ namespace BinaryNinja virtual std::vector<uint32_t> GetFlagsWrittenByFlagWriteType(uint32_t writeType); virtual ExprId GetFlagWriteLowLevelIL(BNLowLevelILOperation op, size_t size, uint32_t flagWriteType, uint32_t flag, BNRegisterOrConstant* operands, size_t operandCount, LowLevelILFunction& il); - ExprId GetDefaultFlagWriteLowLevelIL(BNLowLevelILOperation op, size_t size, uint32_t flagWriteType, - uint32_t flag, BNRegisterOrConstant* operands, size_t operandCount, LowLevelILFunction& il); + ExprId GetDefaultFlagWriteLowLevelIL(BNLowLevelILOperation op, size_t size, BNFlagRole role, + BNRegisterOrConstant* operands, size_t operandCount, LowLevelILFunction& il); virtual ExprId GetFlagConditionLowLevelIL(BNLowLevelILFlagCondition cond, LowLevelILFunction& il); + ExprId GetDefaultFlagConditionLowLevelIL(BNLowLevelILFlagCondition cond, LowLevelILFunction& il); virtual BNRegisterInfo GetRegisterInfo(uint32_t reg); virtual uint32_t GetStackPointerRegister(); virtual uint32_t GetLinkRegister(); @@ -2179,6 +2180,11 @@ namespace BinaryNinja ExprId AddLabelList(const std::vector<BNLowLevelILLabel*>& labels); ExprId AddOperandList(const std::vector<ExprId> operands); + ExprId GetExprForRegisterOrConstant(const BNRegisterOrConstant& operand, size_t size); + ExprId GetNegExprForRegisterOrConstant(const BNRegisterOrConstant& operand, size_t size); + ExprId GetExprForRegisterOrConstantOperation(BNLowLevelILOperation op, size_t size, + BNRegisterOrConstant* operands, size_t operandCount); + ExprId Operand(uint32_t n, ExprId expr); BNLowLevelILInstruction operator[](size_t i) const; diff --git a/binaryninjacore.h b/binaryninjacore.h index abb53a7b..8838ca97 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -334,6 +334,7 @@ extern "C" LLIL_CMP_UGT, LLIL_TEST_BIT, LLIL_BOOL_TO_INT, + LLIL_ADD_OVERFLOW, LLIL_SYSCALL, LLIL_BP, LLIL_TRAP, @@ -775,6 +776,7 @@ extern "C" MLIL_CMP_UGT, MLIL_TEST_BIT, MLIL_BOOL_TO_INT, + MLIL_ADD_OVERFLOW, MLIL_SYSCALL, // Not valid in SSA form (see MLIL_SYSCALL_SSA) MLIL_SYSCALL_UNTYPED, // Not valid in SSA form (see MLIL_SYSCALL_UNTYPED_SSA) MLIL_BP, @@ -1830,10 +1832,11 @@ extern "C" size_t size, uint32_t flagWriteType, uint32_t flag, BNRegisterOrConstant* operands, size_t operandCount, BNLowLevelILFunction* il); BINARYNINJACOREAPI size_t BNGetDefaultArchitectureFlagWriteLowLevelIL(BNArchitecture* arch, BNLowLevelILOperation op, - size_t size, uint32_t flagWriteType, uint32_t flag, BNRegisterOrConstant* operands, size_t operandCount, - BNLowLevelILFunction* il); + size_t size, BNFlagRole role, BNRegisterOrConstant* operands, size_t operandCount, BNLowLevelILFunction* il); BINARYNINJACOREAPI size_t BNGetArchitectureFlagConditionLowLevelIL(BNArchitecture* arch, BNLowLevelILFlagCondition cond, BNLowLevelILFunction* il); + BINARYNINJACOREAPI size_t BNGetDefaultArchitectureFlagConditionLowLevelIL(BNArchitecture* arch, BNLowLevelILFlagCondition cond, + BNLowLevelILFunction* il); BINARYNINJACOREAPI uint32_t* BNGetModifiedArchitectureRegistersOnWrite(BNArchitecture* arch, uint32_t reg, size_t* count); BINARYNINJACOREAPI void BNFreeRegisterList(uint32_t* regs); BINARYNINJACOREAPI BNRegisterInfo BNGetArchitectureRegisterInfo(BNArchitecture* arch, uint32_t reg); diff --git a/lowlevelil.cpp b/lowlevelil.cpp index 0b2837f1..875f0083 100644 --- a/lowlevelil.cpp +++ b/lowlevelil.cpp @@ -534,6 +534,45 @@ ExprId LowLevelILFunction::AddOperandList(const vector<ExprId> operands) } +ExprId LowLevelILFunction::GetExprForRegisterOrConstant(const BNRegisterOrConstant& operand, size_t size) +{ + if (operand.constant) + return AddExpr(LLIL_CONST, size, 0, operand.value); + return AddExpr(LLIL_REG, size, 0, operand.reg); +} + + +ExprId LowLevelILFunction::GetNegExprForRegisterOrConstant(const BNRegisterOrConstant& operand, size_t size) +{ + if (operand.constant) + return AddExpr(LLIL_CONST, size, 0, -(int64_t)operand.value); + return AddExpr(LLIL_NEG, size, 0, AddExpr(LLIL_REG, size, 0, operand.reg)); +} + + +ExprId LowLevelILFunction::GetExprForRegisterOrConstantOperation(BNLowLevelILOperation op, size_t size, + BNRegisterOrConstant* operands, size_t operandCount) +{ + if (operandCount == 0) + return AddExpr(op, size, 0); + if (operandCount == 1) + return AddExpr(op, size, 0, GetExprForRegisterOrConstant(operands[0], size)); + if (operandCount == 2) + { + return AddExpr(op, size, 0, GetExprForRegisterOrConstant(operands[0], size), + GetExprForRegisterOrConstant(operands[1], size)); + } + if (operandCount == 3) + { + return AddExpr(op, size, 0, GetExprForRegisterOrConstant(operands[0], size), + GetExprForRegisterOrConstant(operands[1], size), GetExprForRegisterOrConstant(operands[2], size)); + } + return AddExpr(op, size, 0, GetExprForRegisterOrConstant(operands[0], size), + GetExprForRegisterOrConstant(operands[1], size), GetExprForRegisterOrConstant(operands[2], size), + GetExprForRegisterOrConstant(operands[3], size)); +} + + ExprId LowLevelILFunction::Operand(uint32_t n, ExprId expr) { BNLowLevelILSetExprSourceOperand(m_object, expr, n); diff --git a/python/architecture.py b/python/architecture.py index 60c8a1dd..236ef90b 100644 --- a/python/architecture.py +++ b/python/architecture.py @@ -651,11 +651,11 @@ class Architecture(object): operand_list = [] for i in xrange(operand_count): if operands[i].constant: - operand_list.append(("const", operands[i].value)) + operand_list.append(operands[i].value) elif lowlevelil.LLIL_REG_IS_TEMP(operands[i].reg): - operand_list.append(("reg", operands[i].reg)) + operand_list.append(lowlevelil.ILRegister(self, operands[i].reg)) else: - operand_list.append(("reg", self._regs_by_index[operands[i].reg])) + operand_list.append(lowlevelil.ILRegister(self, operands[i].reg)) return self.perform_get_flag_write_low_level_il(op, size, write_type_name, flag_name, operand_list, lowlevelil.LowLevelILFunction(self, core.BNNewLowLevelILFunctionReference(il))).index except (KeyError, OSError): @@ -915,7 +915,10 @@ class Architecture(object): :param LowLevelILFunction il: :rtype: LowLevelILExpr """ - return il.unimplemented() + flag = self.get_flag_index(flag) + if flag not in self._flag_roles: + return il.unimplemented() + return self.get_default_flag_write_low_level_il(op, size, self._flag_roles[flag], operands, il) @abc.abstractmethod def perform_get_flag_condition_low_level_il(self, cond, il): @@ -927,7 +930,7 @@ class Architecture(object): :param LowLevelILFunction il: :rtype: LowLevelILExpr """ - return il.unimplemented() + return self.get_default_flag_condition_low_level_il(cond, il) @abc.abstractmethod def perform_assemble(self, code, addr): @@ -1276,7 +1279,7 @@ class Architecture(object): """ return self._flag_write_types[write_type] - def get_flag_write_low_level_il(self, op, size, write_type, operands, il): + def get_flag_write_low_level_il(self, op, size, write_type, flag, operands, il): """ :param LowLevelILOperation op: :param int size: @@ -1286,22 +1289,26 @@ class Architecture(object): :param LowLevelILFunction il: :rtype: LowLevelILExpr """ + flag = self.get_flag_index(flag) operand_list = (core.BNRegisterOrConstant * len(operands))() for i in xrange(len(operands)): if isinstance(operands[i], str): operand_list[i].constant = False - operand_list[i].reg = self._flags[operands[i]] + operand_list[i].reg = self.regs[operands[i]] + elif isinstance(operands[i], lowlevelil.ILRegister): + operand_list[i].constant = False + operand_list[i].reg = operands[i].index else: operand_list[i].constant = True operand_list[i].value = operands[i] return lowlevelil.LowLevelILExpr(core.BNGetArchitectureFlagWriteLowLevelIL(self.handle, op, size, - self._flag_write_types[write_type], operand_list, len(operand_list), il.handle)) + self._flag_write_types[write_type], flag, operand_list, len(operand_list), il.handle)) - def get_default_flag_write_low_level_il(self, op, size, write_type, operands, il): + def get_default_flag_write_low_level_il(self, op, size, role, operands, il): """ :param LowLevelILOperation op: :param int size: - :param str write_type: + :param FlagRole role: :param list(str or int) operands: a list of either items that are either string register names or constant \ integer values :param LowLevelILFunction il: @@ -1311,12 +1318,15 @@ class Architecture(object): for i in xrange(len(operands)): if isinstance(operands[i], str): operand_list[i].constant = False - operand_list[i].reg = self._flags[operands[i]] + operand_list[i].reg = self.regs[operands[i]] + elif isinstance(operands[i], lowlevelil.ILRegister): + operand_list[i].constant = False + operand_list[i].reg = operands[i].index else: operand_list[i].constant = True operand_list[i].value = operands[i] return lowlevelil.LowLevelILExpr(core.BNGetDefaultArchitectureFlagWriteLowLevelIL(self.handle, op, size, - self._flag_write_types[write_type], operand_list, len(operand_list), il.handle)) + role, operand_list, len(operand_list), il.handle)) def get_flag_condition_low_level_il(self, cond, il): """ @@ -1326,6 +1336,14 @@ class Architecture(object): """ return lowlevelil.LowLevelILExpr(core.BNGetArchitectureFlagConditionLowLevelIL(self.handle, cond, il.handle)) + def get_default_flag_condition_low_level_il(self, cond, il): + """ + :param LowLevelILFlagCondition cond: + :param LowLevelILFunction il: + :rtype: LowLevelILExpr + """ + return lowlevelil.LowLevelILExpr(core.BNGetDefaultArchitectureFlagConditionLowLevelIL(self.handle, cond, il.handle)) + def get_modified_regs_on_write(self, reg): """ ``get_modified_regs_on_write`` returns a list of register names that are modified when ``reg`` is written. diff --git a/python/examples/nes.py b/python/examples/nes.py index 813b91c9..0018b956 100644 --- a/python/examples/nes.py +++ b/python/examples/nes.py @@ -469,6 +469,15 @@ class M6502(Architecture): return length + def perform_get_flag_write_low_level_il(self, op, size, write_type, flag, operands, il): + if flag == 'c': + if (op == LowLevelILOperation.LLIL_SUB) or (op == LowLevelILOperation.LLIL_SBB): + # Subtraction carry flag is inverted from the commom implementation + return il.not_expr(0, self.get_default_flag_write_low_level_il(op, size, FlagRole.CarryFlagRole, operands, il)) + # Other operations use a normal carry flag + return self.get_default_flag_write_low_level_il(op, size, FlagRole.CarryFlagRole, operands, il) + return Architecture.perform_get_flag_write_low_level_il(self, op, size, write_type, flag, operands, il) + def perform_is_never_branch_patch_available(self, data, addr): if (data[0] == "\x10") or (data[0] == "\x30") or (data[0] == "\x50") or (data[0] == "\x70") or (data[0] == "\x90") or (data[0] == "\xb0") or (data[0] == "\xd0") or (data[0] == "\xf0"): return True |
