summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--architecture.cpp20
-rw-r--r--binaryninjaapi.h10
-rw-r--r--binaryninjacore.h7
-rw-r--r--lowlevelil.cpp39
-rw-r--r--python/architecture.py42
-rw-r--r--python/examples/nes.py9
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