summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRusty Wagner <rusty@vector35.com>2016-05-03 21:02:07 -0400
committerRusty Wagner <rusty@vector35.com>2016-05-03 21:02:07 -0400
commitecaf78b419d323f6b589aac4b9ff5ff24b314bc6 (patch)
tree2f090b2889a0d341ac8c67a3e07b68cc5c340022
parentc382a4610cc0ea7f8b8134b847d29bca7dc25398 (diff)
Add APIs for flag information and data flow
-rw-r--r--architecture.cpp136
-rw-r--r--binaryninjaapi.h25
-rw-r--r--binaryninjacore.h48
-rw-r--r--function.cpp48
-rw-r--r--python/__init__.py218
-rw-r--r--python/examples/nes.py27
6 files changed, 494 insertions, 8 deletions
diff --git a/architecture.cpp b/architecture.cpp
index 3c0f21a2..b1f6c416 100644
--- a/architecture.cpp
+++ b/architecture.cpp
@@ -228,6 +228,57 @@ uint32_t* Architecture::GetAllFlagWriteTypesCallback(void* ctxt, size_t* count)
}
+BNFlagRole Architecture::GetFlagRoleCallback(void* ctxt, uint32_t flag)
+{
+ Architecture* arch = (Architecture*)ctxt;
+ return arch->GetFlagRole(flag);
+}
+
+
+uint32_t* Architecture::GetFlagsRequiredForFlagConditionCallback(void* ctxt, BNLowLevelILFlagCondition cond, size_t* count)
+{
+ Architecture* arch = (Architecture*)ctxt;
+ vector<uint32_t> flags = arch->GetFlagsRequiredForFlagCondition(cond);
+ *count = flags.size();
+
+ uint32_t* result = new uint32_t[flags.size()];
+ for (size_t i = 0; i < flags.size(); i++)
+ result[i] = flags[i];
+ return result;
+}
+
+
+uint32_t* Architecture::GetFlagsWrittenByFlagWriteTypeCallback(void* ctxt, uint32_t writeType, size_t* count)
+{
+ Architecture* arch = (Architecture*)ctxt;
+ vector<uint32_t> flags = arch->GetFlagsWrittenByFlagWriteType(writeType);
+ *count = flags.size();
+
+ uint32_t* result = new uint32_t[flags.size()];
+ for (size_t i = 0; i < flags.size(); i++)
+ result[i] = flags[i];
+ return result;
+}
+
+
+bool Architecture::GetFlagWriteLowLevelILCallback(void* ctxt, BNLowLevelILOperation op, size_t size, uint32_t flagWriteType,
+ BNRegisterOrConstant* operands, size_t operandCount, BNLowLevelILFunction* il)
+{
+ Architecture* arch = (Architecture*)ctxt;
+ LowLevelILFunction func(BNNewLowLevelILFunctionReference(il));
+ return arch->GetFlagWriteLowLevelIL(op, size, flagWriteType, operands, operandCount, func);
+}
+
+
+size_t Architecture::GetFlagConditionLowLevelILCallback(void* ctxt, BNLowLevelILFlagCondition cond,
+ BNLowLevelILFunction* il)
+{
+ Architecture* arch = (Architecture*)ctxt;
+ LowLevelILFunction func(BNNewLowLevelILFunctionReference(il));
+ return arch->GetFlagConditionLowLevelIL(cond, func);
+}
+
+
void Architecture::FreeRegisterListCallback(void*, uint32_t* regs)
{
delete[] regs;
@@ -350,6 +401,11 @@ void Architecture::Register(Architecture* arch)
callbacks.getAllRegisters = GetAllRegistersCallback;
callbacks.getAllFlags = GetAllFlagsCallback;
callbacks.getAllFlagWriteTypes = GetAllFlagWriteTypesCallback;
+ callbacks.getFlagRole = GetFlagRoleCallback;
+ callbacks.getFlagsRequiredForFlagCondition = GetFlagsRequiredForFlagConditionCallback;
+ callbacks.getFlagsWrittenByFlagWriteType = GetFlagsWrittenByFlagWriteTypeCallback;
+ callbacks.getFlagWriteLowLevelIL = GetFlagWriteLowLevelILCallback;
+ callbacks.getFlagConditionLowLevelIL = GetFlagConditionLowLevelILCallback;
callbacks.freeRegisterList = FreeRegisterListCallback;
callbacks.getRegisterInfo = GetRegisterInfoCallback;
callbacks.getStackPointerRegister = GetStackPointerRegisterCallback;
@@ -465,6 +521,38 @@ vector<uint32_t> Architecture::GetAllFlagWriteTypes()
}
+BNFlagRole Architecture::GetFlagRole(uint32_t)
+{
+ return SpecialFlagRole;
+}
+
+
+vector<uint32_t> Architecture::GetFlagsRequiredForFlagCondition(BNLowLevelILFlagCondition)
+{
+ return vector<uint32_t>();
+}
+
+
+vector<uint32_t> Architecture::GetFlagsWrittenByFlagWriteType(uint32_t)
+{
+ return vector<uint32_t>();
+}
+
+
+bool Architecture::GetFlagWriteLowLevelIL(BNLowLevelILOperation op, size_t size, uint32_t flagWriteType,
+ BNRegisterOrConstant* operands, size_t operandCount,LowLevelILFunction& il)
+{
+ return BNGetDefaultArchitectureFlagWriteLowLevelIL(m_object, op, size, flagWriteType, operands,
+ operandCount, il.GetObject());
+}
+
+
+ExprId Architecture::GetFlagConditionLowLevelIL(BNLowLevelILFlagCondition, LowLevelILFunction& il)
+{
+ return il.Unimplemented();
+}
+
+
BNRegisterInfo Architecture::GetRegisterInfo(uint32_t)
{
BNRegisterInfo result;
@@ -888,6 +976,54 @@ vector<uint32_t> CoreArchitecture::GetAllFlagWriteTypes()
}
+BNFlagRole CoreArchitecture::GetFlagRole(uint32_t flag)
+{
+ return BNGetArchitectureFlagRole(m_object, flag);
+}
+
+
+vector<uint32_t> CoreArchitecture::GetFlagsRequiredForFlagCondition(BNLowLevelILFlagCondition cond)
+{
+ size_t count;
+ uint32_t* flags = BNGetArchitectureFlagsRequiredForFlagCondition(m_object, cond, &count);
+
+ vector<uint32_t> result;
+ for (size_t i = 0; i < count; i++)
+ result.push_back(flags[i]);
+
+ BNFreeRegisterList(flags);
+ return result;
+}
+
+
+vector<uint32_t> CoreArchitecture::GetFlagsWrittenByFlagWriteType(uint32_t writeType)
+{
+ size_t count;
+ uint32_t* flags = BNGetArchitectureFlagsWrittenByFlagWriteType(m_object, writeType, &count);
+
+ vector<uint32_t> result;
+ for (size_t i = 0; i < count; i++)
+ result.push_back(flags[i]);
+
+ BNFreeRegisterList(flags);
+ return result;
+}
+
+
+bool CoreArchitecture::GetFlagWriteLowLevelIL(BNLowLevelILOperation op, size_t size, uint32_t flagWriteType,
+ BNRegisterOrConstant* operands, size_t operandCount, LowLevelILFunction& il)
+{
+ return BNGetArchitectureFlagWriteLowLevelIL(m_object, op, size, flagWriteType, operands,
+ operandCount, il.GetObject());
+}
+
+
+ExprId CoreArchitecture::GetFlagConditionLowLevelIL(BNLowLevelILFlagCondition cond, LowLevelILFunction& il)
+{
+ return (ExprId)BNGetArchitectureFlagConditionLowLevelIL(m_object, cond, il.GetObject());
+}
+
+
BNRegisterInfo CoreArchitecture::GetRegisterInfo(uint32_t reg)
{
return BNGetArchitectureRegisterInfo(m_object, reg);
diff --git a/binaryninjaapi.h b/binaryninjaapi.h
index 4ba49cdd..977727e8 100644
--- a/binaryninjaapi.h
+++ b/binaryninjaapi.h
@@ -29,6 +29,7 @@
#include <map>
#include <exception>
#include <functional>
+#include <set>
#include "binaryninjacore.h"
#include "json/json.h"
@@ -1004,6 +1005,13 @@ namespace BinaryNinja
static uint32_t* GetAllRegistersCallback(void* ctxt, size_t* count);
static uint32_t* GetAllFlagsCallback(void* ctxt, size_t* count);
static uint32_t* GetAllFlagWriteTypesCallback(void* ctxt, size_t* count);
+ static BNFlagRole GetFlagRoleCallback(void* ctxt, uint32_t flag);
+ static uint32_t* GetFlagsRequiredForFlagConditionCallback(void* ctxt, BNLowLevelILFlagCondition cond, size_t* count);
+ static uint32_t* GetFlagsWrittenByFlagWriteTypeCallback(void* ctxt, uint32_t writeType, size_t* count);
+ static bool GetFlagWriteLowLevelILCallback(void* ctxt, BNLowLevelILOperation op, size_t size, uint32_t flagWriteType,
+ BNRegisterOrConstant* operands, size_t operandCount, BNLowLevelILFunction* il);
+ static size_t GetFlagConditionLowLevelILCallback(void* ctxt, BNLowLevelILFlagCondition cond,
+ BNLowLevelILFunction* il);
static void FreeRegisterListCallback(void* ctxt, uint32_t* regs);
static void GetRegisterInfoCallback(void* ctxt, uint32_t reg, BNRegisterInfo* result);
static uint32_t GetStackPointerRegisterCallback(void* ctxt);
@@ -1047,6 +1055,12 @@ namespace BinaryNinja
virtual std::vector<uint32_t> GetAllRegisters();
virtual std::vector<uint32_t> GetAllFlags();
virtual std::vector<uint32_t> GetAllFlagWriteTypes();
+ virtual BNFlagRole GetFlagRole(uint32_t flag);
+ virtual std::vector<uint32_t> GetFlagsRequiredForFlagCondition(BNLowLevelILFlagCondition cond);
+ virtual std::vector<uint32_t> GetFlagsWrittenByFlagWriteType(uint32_t writeType);
+ virtual bool GetFlagWriteLowLevelIL(BNLowLevelILOperation op, size_t size, uint32_t flagWriteType,
+ BNRegisterOrConstant* operands, size_t operandCount, LowLevelILFunction& il);
+ virtual ExprId GetFlagConditionLowLevelIL(BNLowLevelILFlagCondition cond, LowLevelILFunction& il);
virtual BNRegisterInfo GetRegisterInfo(uint32_t reg);
virtual uint32_t GetStackPointerRegister();
virtual uint32_t GetLinkRegister();
@@ -1115,6 +1129,12 @@ namespace BinaryNinja
virtual std::vector<uint32_t> GetAllRegisters() override;
virtual std::vector<uint32_t> GetAllFlags() override;
virtual std::vector<uint32_t> GetAllFlagWriteTypes() override;
+ virtual BNFlagRole GetFlagRole(uint32_t flag) override;
+ virtual std::vector<uint32_t> GetFlagsRequiredForFlagCondition(BNLowLevelILFlagCondition cond) override;
+ virtual std::vector<uint32_t> GetFlagsWrittenByFlagWriteType(uint32_t writeType) override;
+ virtual bool GetFlagWriteLowLevelIL(BNLowLevelILOperation op, size_t size, uint32_t flagWriteType,
+ BNRegisterOrConstant* operands, size_t operandCount, LowLevelILFunction& il) override;
+ virtual ExprId GetFlagConditionLowLevelIL(BNLowLevelILFlagCondition cond, LowLevelILFunction& il) override;
virtual BNRegisterInfo GetRegisterInfo(uint32_t reg) override;
virtual uint32_t GetStackPointerRegister() override;
virtual uint32_t GetLinkRegister() override;
@@ -1324,6 +1344,11 @@ namespace BinaryNinja
std::vector<uint32_t> GetRegistersWrittenByInstruction(Architecture* arch, uint64_t addr);
std::vector<StackVariableReference> GetStackVariablesReferencedByInstruction(Architecture* arch, uint64_t addr);
+ std::set<size_t> GetLowLevelILFlagUsesForDefinition(size_t i, uint32_t flag);
+ std::set<size_t> GetLowLevelILFlagDefinitionsForUse(size_t i, uint32_t flag);
+ std::set<uint32_t> GetFlagsReadByLowLevelILInstruction(size_t i);
+ std::set<uint32_t> GetFlagsWrittenByLowLevelILInstruction(size_t i);
+
Ref<Type> GetType() const;
void ApplyImportedTypes(Symbol* sym);
void ApplyAutoDiscoveredType(Type* type);
diff --git a/binaryninjacore.h b/binaryninjacore.h
index aa8caa92..d062c4d8 100644
--- a/binaryninjacore.h
+++ b/binaryninjacore.h
@@ -271,6 +271,19 @@ extern "C"
LLFC_NO
};
+ enum BNFlagRole
+ {
+ SpecialFlagRole = 0,
+ ZeroFlagRole = 1,
+ PositiveSignFlagRole = 2,
+ NegativeSignFlagRole = 3,
+ CarryFlagRole = 4,
+ OverflowFlagRole = 5,
+ HalfCarryFlagRole = 6,
+ EvenParityFlagRole = 7,
+ OddParityFlagRole = 8
+ };
+
enum BNFunctionGraphType
{
NormalFunctionGraph = 0,
@@ -282,7 +295,8 @@ extern "C"
ShowAddress = 0,
// Debugging options
- ShowBasicBlockRegisterState = 128
+ ShowBasicBlockRegisterState = 128,
+ ShowFlagUsage = 129
};
enum BNTypeClass
@@ -353,6 +367,16 @@ extern "C"
int64_t value; // Offset for OffsetFromEntryValue or StackFrameOffset, value of register for ConstantValue
};
+ struct BNRegisterOrConstant
+ {
+ bool constant;
+ union
+ {
+ uint32_t reg;
+ uint64_t value;
+ };
+ };
+
// Callbacks
struct BNLogListener
{
@@ -480,6 +504,12 @@ extern "C"
uint32_t* (*getAllRegisters)(void* ctxt, size_t* count);
uint32_t* (*getAllFlags)(void* ctxt, size_t* count);
uint32_t* (*getAllFlagWriteTypes)(void* ctxt, size_t* count);
+ BNFlagRole (*getFlagRole)(void* ctxt, uint32_t flag);
+ uint32_t* (*getFlagsRequiredForFlagCondition)(void* ctxt, BNLowLevelILFlagCondition cond, size_t* count);
+ uint32_t* (*getFlagsWrittenByFlagWriteType)(void* ctxt, uint32_t writeType, size_t* count);
+ bool (*getFlagWriteLowLevelIL)(void* ctxt, BNLowLevelILOperation op, size_t size, uint32_t flagWriteType,
+ BNRegisterOrConstant* operands, size_t operandCount, BNLowLevelILFunction* il);
+ size_t (*getFlagConditionLowLevelIL)(void* ctxt, BNLowLevelILFlagCondition cond, BNLowLevelILFunction* il);
void (*freeRegisterList)(void* ctxt, uint32_t* regs);
void (*getRegisterInfo)(void* ctxt, uint32_t reg, BNRegisterInfo* result);
uint32_t (*getStackPointerRegister)(void* ctxt);
@@ -977,6 +1007,17 @@ extern "C"
BINARYNINJACOREAPI uint32_t* BNGetAllArchitectureRegisters(BNArchitecture* arch, size_t* count);
BINARYNINJACOREAPI uint32_t* BNGetAllArchitectureFlags(BNArchitecture* arch, size_t* count);
BINARYNINJACOREAPI uint32_t* BNGetAllArchitectureFlagWriteTypes(BNArchitecture* arch, size_t* count);
+ BINARYNINJACOREAPI BNFlagRole BNGetArchitectureFlagRole(BNArchitecture* arch, uint32_t flag);
+ BINARYNINJACOREAPI uint32_t* BNGetArchitectureFlagsRequiredForFlagCondition(BNArchitecture* arch, BNLowLevelILFlagCondition cond,
+ size_t* count);
+ BINARYNINJACOREAPI uint32_t* BNGetArchitectureFlagsWrittenByFlagWriteType(BNArchitecture* arch, uint32_t writeType,
+ size_t* count);
+ BINARYNINJACOREAPI bool BNGetArchitectureFlagWriteLowLevelIL(BNArchitecture* arch, BNLowLevelILOperation op,
+ size_t size, uint32_t flagWriteType, BNRegisterOrConstant* operands, size_t operandCount, BNLowLevelILFunction* il);
+ BINARYNINJACOREAPI bool BNGetDefaultArchitectureFlagWriteLowLevelIL(BNArchitecture* arch, BNLowLevelILOperation op,
+ size_t size, uint32_t flagWriteType, BNRegisterOrConstant* operands, size_t operandCount, BNLowLevelILFunction* il);
+ BINARYNINJACOREAPI size_t BNGetArchitectureFlagConditionLowLevelIL(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);
@@ -1070,6 +1111,11 @@ extern "C"
uint64_t addr, size_t* count);
BINARYNINJACOREAPI void BNFreeStackVariableReferenceList(BNStackVariableReference* refs, size_t count);
+ BINARYNINJACOREAPI size_t* BNGetLowLevelILFlagUsesForDefinition(BNFunction* func, size_t i, uint32_t flag, size_t* count);
+ BINARYNINJACOREAPI size_t* BNGetLowLevelILFlagDefinitionsForUse(BNFunction* func, size_t i, uint32_t flag, size_t* count);
+ BINARYNINJACOREAPI uint32_t* BNGetFlagsReadByLowLevelILInstruction(BNFunction* func, size_t i, size_t* count);
+ BINARYNINJACOREAPI uint32_t* BNGetFlagsWrittenByLowLevelILInstruction(BNFunction* func, size_t i, size_t* count);
+
BINARYNINJACOREAPI BNType* BNGetFunctionType(BNFunction* func);
BINARYNINJACOREAPI void BNApplyImportedTypes(BNFunction* func, BNSymbol* sym);
BINARYNINJACOREAPI void BNApplyAutoDiscoveredFunctionType(BNFunction* func, BNType* type);
diff --git a/function.cpp b/function.cpp
index 8631eb0b..0fb163e0 100644
--- a/function.cpp
+++ b/function.cpp
@@ -229,6 +229,54 @@ vector<StackVariableReference> Function::GetStackVariablesReferencedByInstructio
}
+set<size_t> Function::GetLowLevelILFlagUsesForDefinition(size_t i, uint32_t flag)
+{
+ size_t count;
+ size_t* instrs = BNGetLowLevelILFlagUsesForDefinition(m_object, i, flag, &count);
+
+ set<size_t> result;
+ result.insert(&instrs[0], &instrs[count]);
+ BNFreeLowLevelILInstructionList(instrs);
+ return result;
+}
+
+
+set<size_t> Function::GetLowLevelILFlagDefinitionsForUse(size_t i, uint32_t flag)
+{
+ size_t count;
+ size_t* instrs = BNGetLowLevelILFlagDefinitionsForUse(m_object, i, flag, &count);
+
+ set<size_t> result;
+ result.insert(&instrs[0], &instrs[count]);
+ BNFreeLowLevelILInstructionList(instrs);
+ return result;
+}
+
+
+set<uint32_t> Function::GetFlagsReadByLowLevelILInstruction(size_t i)
+{
+ size_t count;
+ uint32_t* flags = BNGetFlagsReadByLowLevelILInstruction(m_object, i, &count);
+
+ set<uint32_t> result;
+ result.insert(&flags[0], &flags[count]);
+ BNFreeRegisterList(flags);
+ return result;
+}
+
+
+set<uint32_t> Function::GetFlagsWrittenByLowLevelILInstruction(size_t i)
+{
+ size_t count;
+ uint32_t* flags = BNGetFlagsWrittenByLowLevelILInstruction(m_object, i, &count);
+
+ set<uint32_t> result;
+ result.insert(&flags[0], &flags[count]);
+ BNFreeRegisterList(flags);
+ return result;
+}
+
+
Ref<Type> Function::GetType() const
{
return new Type(BNGetFunctionType(m_object));
diff --git a/python/__init__.py b/python/__init__.py
index 65477366..e0de7099 100644
--- a/python/__init__.py
+++ b/python/__init__.py
@@ -2065,6 +2065,46 @@ class Function:
core.BNFreeStackVariableReferenceList(refs, count.value)
return result
+ def get_low_level_il_flag_uses_for_definition(self, i, flag):
+ if isinstance(flag, str):
+ flag = self.arch._flags[flag]
+ count = ctypes.c_ulonglong()
+ instrs = core.BNGetLowLevelILFlagUsesForDefinition(self.handle, i, flag, count)
+ result = []
+ for i in xrange(0, count.value):
+ result.append(instrs[i])
+ core.BNFreeLowLevelILInstructionList(instrs)
+ return result
+
+ def get_low_level_il_flag_definitions_for_use(self, i, flag):
+ if isinstance(flag, str):
+ flag = self.arch._flags[flag]
+ count = ctypes.c_ulonglong()
+ instrs = core.BNGetLowLevelILFlagDefinitionsForUse(self.handle, i, flag, count)
+ result = []
+ for i in xrange(0, count.value):
+ result.append(instrs[i])
+ core.BNFreeLowLevelILInstructionList(instrs)
+ return result
+
+ def get_flags_read_by_low_level_il_instruction(self, i):
+ count = ctypes.c_ulonglong()
+ flags = core.BNGetFlagsReadByLowLevelILInstruction(self.handle, i, count)
+ result = []
+ for i in xrange(0, count.value):
+ result.append(self.arch._flags_by_index[flags[i]])
+ core.BNFreeRegisterList(flags)
+ return result
+
+ def get_flags_written_by_low_level_il_instruction(self, i):
+ count = ctypes.c_ulonglong()
+ flags = core.BNGetFlagsWrittenByLowLevelILInstruction(self.handle, i, count)
+ result = []
+ for i in xrange(0, count.value):
+ result.append(self.arch._flags_by_index[flags[i]])
+ core.BNFreeRegisterList(flags)
+ return result
+
def create_graph(self):
return FunctionGraph(self._view, core.BNCreateFunctionGraph(self.handle))
@@ -2497,6 +2537,9 @@ class Architecture:
link_reg = None
flags = []
flag_write_types = []
+ flag_roles = {}
+ flags_required_for_flag_condition = {}
+ flags_written_by_flag_write_type = {}
__metaclass__ = _ArchitectureMetaClass
def __init__(self, handle = None):
@@ -2545,6 +2588,42 @@ class Architecture:
self._flag_write_types_by_index[types[i]] = name
self.flag_write_types.append(name)
core.BNFreeRegisterList(types)
+
+ self._flag_roles = {}
+ self.__dict__["flag_roles"] = {}
+ for flag in self.__dict__["flags"]:
+ role = core.BNGetArchitectureFlagRole(self.handle, self._flags[flag])
+ self.__dict__["flag_roles"][flag] = role
+ self._flag_roles[self._flags[flag]] = role
+
+ self._flags_required_for_flag_condition = {}
+ self.__dict__["flags_required_for_flag_condition"] = {}
+ for cond in core.BNLowLevelILFlagCondition_names.keys():
+ count = ctypes.c_ulonglong()
+ flags = core.BNGetArchitectureFlagsRequiredForFlagCondition(self.handle, cond, count)
+ flag_indexes = []
+ flag_names = []
+ for i in xrange(0, count.value):
+ flag_indexes.append(flags[i])
+ flag_names.append(self._flags_by_index[flags[i]])
+ core.BNFreeRegisterList(flags)
+ self._flags_required_for_flag_condition[cond] = flag_indexes
+ self.__dict__["flags_required_for_flag_condition"][cond] = flag_names
+
+ self._flags_written_by_flag_write_type = {}
+ self.__dict__["flags_written_by_flag_write_type"] = {}
+ for write_type in self.flag_write_types:
+ count = ctypes.c_ulonglong()
+ flags = core.BNGetArchitectureFlagsWrittenByFlagWriteType(self.handle,
+ self._flag_write_types[write_type], count)
+ flag_indexes = []
+ flag_names = []
+ for i in xrange(0, count.value):
+ flag_indexes.append(flags[i])
+ flag_names.append(self._flags_by_index[flags[i]])
+ core.BNFreeRegisterList(flags)
+ self._flags_written_by_flag_write_type[self._flag_write_types[write_type]] = flag_indexes
+ self.__dict__["flags_written_by_flag_write_type"][write_type] = flag_names
else:
_init_plugins()
self._cb = core.BNCustomArchitecture()
@@ -2565,6 +2644,15 @@ class Architecture:
self._cb.getAllRegisters = self._cb.getAllRegisters.__class__(self._get_all_registers)
self._cb.getAllFlags = self._cb.getAllRegisters.__class__(self._get_all_flags)
self._cb.getAllFlagWriteTypes = self._cb.getAllRegisters.__class__(self._get_all_flag_write_types)
+ self._cb.getFlagRole = self._cb.getFlagRole.__class__(self._get_flag_role)
+ self._cb.getFlagsRequiredForFlagCondition = self._cb.getFlagsRequiredForFlagCondition.__class__(
+ self._get_flags_required_for_flag_condition)
+ self._cb.getFlagsWrittenByFlagWriteType = self._cb.getFlagsWrittenByFlagWriteType.__class__(
+ self._get_flags_written_by_flag_write_type)
+ self._cb.getFlagWriteLowLevelIL = self._cb.getFlagWriteLowLevelIL.__class__(
+ self._get_flag_write_low_level_il)
+ self._cb.getFlagConditionLowLevelIL = self._cb.getFlagConditionLowLevelIL.__class__(
+ self._get_flag_condition_low_level_il)
self._cb.freeRegisterList = self._cb.freeRegisterList.__class__(self._free_register_list)
self._cb.getRegisterInfo = self._cb.getRegisterInfo.__class__(self._get_register_info)
self._cb.getStackPointerRegister = self._cb.getStackPointerRegister.__class__(
@@ -2626,6 +2714,30 @@ class Architecture:
self._flag_write_types_by_index[write_type_index] = write_type
write_type_index += 1
+ self._flag_roles = {}
+ self.__dict__["flag_roles"] = self.__class__.flag_roles
+ for flag in self.__class__.flag_roles.keys():
+ role = self.__class__.flag_roles[flag]
+ if isinstance(role, str):
+ role = core.BNFlagRole_by_name[role]
+ self._flag_roles[self._flags[flag]] = role
+
+ self._flags_required_for_flag_condition = {}
+ self.__dict__["flags_required_for_flag_condition"] = self.__class__.flags_required_for_flag_condition
+ for cond in self.__class__.flags_required_for_flag_condition.keys():
+ flags = []
+ for flag in self.__class__.flags_required_for_flag_condition[cond]:
+ flags.append(self._flags[flag])
+ self._flags_required_for_flag_condition[cond] = flags
+
+ self._flags_written_by_flag_write_type = {}
+ self.__dict__["flags_written_by_flag_write_type"] = self.__class__.flags_written_by_flag_write_type
+ for write_type in self.__class__.flags_written_by_flag_write_type.keys():
+ flags = []
+ for flag in self.__class__.flags_written_by_flag_write_type[write_type]:
+ flags.append(self._flags[flag])
+ self._flags_written_by_flag_write_type[self._flag_write_types[write_type]] = flags
+
self._pending_reg_lists = {}
self._pending_token_lists = {}
@@ -2852,6 +2964,76 @@ class Architecture:
count[0] = 0
return None
+ def _get_flag_role(self, ctxt, flag):
+ try:
+ if flag in self._flag_roles:
+ return self._flag_roles[flag]
+ return core.SpecialFlagRole
+ except:
+ log_error(traceback.format_exc())
+ return None
+
+ def _get_flags_required_for_flag_condition(self, ctxt, cond, count):
+ try:
+ if cond in self._flags_required_for_flag_condition:
+ flags = self._flags_required_for_flag_condition[cond]
+ else:
+ flags = []
+ count[0] = len(flags)
+ flag_buf = (ctypes.c_uint * len(flags))()
+ for i in xrange(0, len(flags)):
+ flag_buf[i] = flags[i]
+ result = ctypes.cast(flag_buf, ctypes.c_void_p)
+ self._pending_reg_lists[result.value] = (result, flag_buf)
+ return result.value
+ except:
+ log_error(traceback.format_exc())
+ count[0] = 0
+ return None
+
+ def _get_flags_written_by_flag_write_type(self, ctxt, write_type, count):
+ try:
+ if write_type in self._flags_written_by_flag_write_type:
+ flags = self._flags_written_by_flag_write_type[write_type]
+ else:
+ flags = []
+ count[0] = len(flags)
+ flag_buf = (ctypes.c_uint * len(flags))()
+ for i in xrange(0, len(flags)):
+ flag_buf[i] = flags[i]
+ result = ctypes.cast(flag_buf, ctypes.c_void_p)
+ self._pending_reg_lists[result.value] = (result, flag_buf)
+ return result.value
+ except:
+ log_error(traceback.format_exc())
+ count[0] = 0
+ return None
+
+ def _get_flag_write_low_level_il(self, ctxt, op, size, write_type, operands, operand_count, il):
+ try:
+ write_type_name = None
+ if write_type != 0:
+ write_type_name = self._flag_write_types_by_index[write_type]
+ operand_list = []
+ for i in xrange(operand_count):
+ if operands[i].constant:
+ operand_list.append(operands[i].value)
+ else:
+ operand_list.append(self._regs_by_index[operands[i].reg])
+ return self.perform_get_flag_write_low_level_il(op, size, write_type_name, operand_list,
+ LowLevelILFunction(self, core.BNNewLowLevelILFunctionReference(il)))
+ except:
+ log_error(traceback.format_exc())
+ return False
+
+ def _get_flag_condition_low_level_il(self, ctxt, cond, il):
+ try:
+ return self.perform_get_flag_condition_low_level_il(cond,
+ LowLevelILFunction(self, core.BNNewLowLevelILFunctionReference(il)))
+ except:
+ log_error(traceback.format_exc())
+ return 0
+
def _free_register_list(self, ctxt, regs):
try:
buf = ctypes.cast(regs, ctypes.c_void_p)
@@ -3028,6 +3210,12 @@ class Architecture:
def perform_get_instruction_low_level_il(self, data, addr, il):
return None
+ def perform_get_flag_write_low_level_il(self, op, size, write_type, operands, il):
+ return False
+
+ def perform_get_flag_condition_low_level_il(self, cond, il):
+ return il.unimplemented()
+
def perform_assemble(self, code, addr):
return None, "Architecture does not implement an assembler.\n"
@@ -3098,7 +3286,6 @@ class Architecture:
return result, length.value
def get_instruction_low_level_il(self, data, addr, il):
- info = core.BNInstructionInfo()
data = str(data)
length = ctypes.c_ulonglong()
length.value = len(data)
@@ -3122,6 +3309,33 @@ class Architecture:
def get_flag_write_type_by_name(self, write_type):
return self._flag_write_types[write_type]
+ def get_flag_write_low_level_il(self, op, size, write_type, operands, il):
+ 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]]
+ else:
+ operand_list[i].constant = True
+ operand_list[i].value = operands[i]
+ return core.BNGetArchitectureFlagWriteLowLevelIL(self.handle, op, size, self._flag_write_types[write_type],
+ operand_list, len(operand_list), il.handle)
+
+ def get_default_flag_write_low_level_il(self, op, size, write_type, operands, il):
+ 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]]
+ else:
+ operand_list[i].constant = True
+ operand_list[i].value = operands[i]
+ return core.BNGetDefaultArchitectureFlagWriteLowLevelIL(self.handle, op, size, self._flag_write_types[write_type],
+ operand_list, len(operand_list), il.handle)
+
+ def get_flag_condition_low_level_il(self, cond, il):
+ return core.BNGetArchitectureFlagConditionLowLevelIL(self.handle, cond, il.handle)
+
def get_modified_regs_on_write(self, reg):
reg = core.BNGetArchitectureRegisterByName(self.handle, str(reg))
count = ctypes.c_ulonglong()
@@ -4645,7 +4859,7 @@ class Platform:
self.__dict__[name] = value
def __dir__(self):
- return dir(self.__class__) + ["default_calling_convention", "cdecl_calling_convention",
+ return dir(self.__class__) + ["default_calling_convention", "cdecl_calling_convention",
"stdcall_calling_convention", "fastcall_calling_convention", "system_call_convention", "calling_conventions"]
def __repr__(self):
diff --git a/python/examples/nes.py b/python/examples/nes.py
index 8387ad74..8d3d9269 100644
--- a/python/examples/nes.py
+++ b/python/examples/nes.py
@@ -231,8 +231,8 @@ OperandIL = [
def cond_branch(il, cond, dest):
t = None
- if il[dest].operation == "LLIL_CONST":
- t = il.get_label_for_address(Architecture['6502'].standalone_platform, il[dest].value)
+ if il[dest].operation == LLIL_CONST:
+ t = il.get_label_for_address(Architecture['6502'], il[dest].value)
if t is None:
t = LowLevelILLabel()
indirect = True
@@ -248,8 +248,8 @@ def cond_branch(il, cond, dest):
def jump(il, dest):
label = None
- if il[dest].operation == "LLIL_CONST":
- label = il.get_label_for_address(Architecture['6502'].standalone_platform, il[dest].value)
+ if il[dest].operation == LLIL_CONST:
+ label = il.get_label_for_address(Architecture['6502'], il[dest].value)
if label is None:
il.append(il.jump(dest))
else:
@@ -358,6 +358,24 @@ class M6502(Architecture):
stack_pointer = "s"
flags = ["c", "z", "i", "d", "b", "v", "s"]
flag_write_types = ["*", "czs", "zvs", "zs"]
+ flag_roles = {
+ "c": SpecialFlagRole, # Not a normal carry flag, subtract result is inverted
+ "z": ZeroFlagRole,
+ "v": OverflowFlagRole,
+ "s": NegativeSignFlagRole
+ }
+ flags_required_for_flag_condition = {
+ LLFC_UGE: ["c"],
+ LLFC_ULT: ["c"],
+ LLFC_E: ["z"],
+ LLFC_NE: ["z"]
+ }
+ flags_written_by_flag_write_type = {
+ "*": ["c", "z", "v", "s"],
+ "czs": ["c", "z", "s"],
+ "zvs": ["z", "v", "s"],
+ "zs": ["z", "s"]
+ }
def decode_instruction(self, data, addr):
if len(data) < 1:
@@ -678,4 +696,3 @@ for i in xrange(0, 32):
NESViewBank.register()
M6502.register()
-