From c382a4610cc0ea7f8b8134b847d29bca7dc25398 Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Sun, 24 Apr 2016 00:33:26 -0400 Subject: Create API for adding known indirect branch targets --- function.cpp | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) (limited to 'function.cpp') diff --git a/function.cpp b/function.cpp index 12f99d1f..8631eb0b 100644 --- a/function.cpp +++ b/function.cpp @@ -313,3 +313,73 @@ bool Function::GetStackVariableAtFrameOffset(int64_t offset, StackVariable& resu BNFreeStackVariable(&var); return true; } + + +void Function::SetAutoIndirectBranches(Architecture* sourceArch, uint64_t source, const std::vector& branches) +{ + BNArchitectureAndAddress* branchList = new BNArchitectureAndAddress[branches.size()]; + for (size_t i = 0; i < branches.size(); i++) + { + branchList[i].arch = branches[i].arch->GetObject(); + branchList[i].address = branches[i].address; + } + BNSetAutoIndirectBranches(m_object, sourceArch->GetObject(), source, branchList, branches.size()); + delete[] branchList; +} + + +void Function::SetUserIndirectBranches(Architecture* sourceArch, uint64_t source, const std::vector& branches) +{ + BNArchitectureAndAddress* branchList = new BNArchitectureAndAddress[branches.size()]; + for (size_t i = 0; i < branches.size(); i++) + { + branchList[i].arch = branches[i].arch->GetObject(); + branchList[i].address = branches[i].address; + } + BNSetUserIndirectBranches(m_object, sourceArch->GetObject(), source, branchList, branches.size()); + delete[] branchList; +} + + +vector Function::GetIndirectBranches() +{ + size_t count; + BNIndirectBranchInfo* branches = BNGetIndirectBranches(m_object, &count); + + vector result; + for (size_t i = 0; i < count; i++) + { + IndirectBranchInfo b; + b.sourceArch = new CoreArchitecture(branches[i].sourceArch); + b.sourceAddr = branches[i].sourceAddr; + b.destArch = new CoreArchitecture(branches[i].destArch); + b.destAddr = branches[i].destAddr; + b.autoDefined = branches[i].autoDefined; + result.push_back(b); + } + + BNFreeIndirectBranchList(branches); + return result; +} + + +vector Function::GetIndirectBranchesAt(Architecture* arch, uint64_t addr) +{ + size_t count; + BNIndirectBranchInfo* branches = BNGetIndirectBranchesAt(m_object, arch->GetObject(), addr, &count); + + vector result; + for (size_t i = 0; i < count; i++) + { + IndirectBranchInfo b; + b.sourceArch = new CoreArchitecture(branches[i].sourceArch); + b.sourceAddr = branches[i].sourceAddr; + b.destArch = new CoreArchitecture(branches[i].destArch); + b.destAddr = branches[i].destAddr; + b.autoDefined = branches[i].autoDefined; + result.push_back(b); + } + + BNFreeIndirectBranchList(branches); + return result; +} -- cgit v1.3.1 From ecaf78b419d323f6b589aac4b9ff5ff24b314bc6 Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Tue, 3 May 2016 21:02:07 -0400 Subject: Add APIs for flag information and data flow --- architecture.cpp | 136 ++++++++++++++++++++++++++++++ binaryninjaapi.h | 25 ++++++ binaryninjacore.h | 48 ++++++++++- function.cpp | 48 +++++++++++ python/__init__.py | 218 ++++++++++++++++++++++++++++++++++++++++++++++++- python/examples/nes.py | 27 ++++-- 6 files changed, 494 insertions(+), 8 deletions(-) (limited to 'function.cpp') 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 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 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 Architecture::GetAllFlagWriteTypes() } +BNFlagRole Architecture::GetFlagRole(uint32_t) +{ + return SpecialFlagRole; +} + + +vector Architecture::GetFlagsRequiredForFlagCondition(BNLowLevelILFlagCondition) +{ + return vector(); +} + + +vector Architecture::GetFlagsWrittenByFlagWriteType(uint32_t) +{ + return vector(); +} + + +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 CoreArchitecture::GetAllFlagWriteTypes() } +BNFlagRole CoreArchitecture::GetFlagRole(uint32_t flag) +{ + return BNGetArchitectureFlagRole(m_object, flag); +} + + +vector CoreArchitecture::GetFlagsRequiredForFlagCondition(BNLowLevelILFlagCondition cond) +{ + size_t count; + uint32_t* flags = BNGetArchitectureFlagsRequiredForFlagCondition(m_object, cond, &count); + + vector result; + for (size_t i = 0; i < count; i++) + result.push_back(flags[i]); + + BNFreeRegisterList(flags); + return result; +} + + +vector CoreArchitecture::GetFlagsWrittenByFlagWriteType(uint32_t writeType) +{ + size_t count; + uint32_t* flags = BNGetArchitectureFlagsWrittenByFlagWriteType(m_object, writeType, &count); + + vector 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 #include #include +#include #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 GetAllRegisters(); virtual std::vector GetAllFlags(); virtual std::vector GetAllFlagWriteTypes(); + virtual BNFlagRole GetFlagRole(uint32_t flag); + virtual std::vector GetFlagsRequiredForFlagCondition(BNLowLevelILFlagCondition cond); + virtual std::vector 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 GetAllRegisters() override; virtual std::vector GetAllFlags() override; virtual std::vector GetAllFlagWriteTypes() override; + virtual BNFlagRole GetFlagRole(uint32_t flag) override; + virtual std::vector GetFlagsRequiredForFlagCondition(BNLowLevelILFlagCondition cond) override; + virtual std::vector 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 GetRegistersWrittenByInstruction(Architecture* arch, uint64_t addr); std::vector GetStackVariablesReferencedByInstruction(Architecture* arch, uint64_t addr); + std::set GetLowLevelILFlagUsesForDefinition(size_t i, uint32_t flag); + std::set GetLowLevelILFlagDefinitionsForUse(size_t i, uint32_t flag); + std::set GetFlagsReadByLowLevelILInstruction(size_t i); + std::set GetFlagsWrittenByLowLevelILInstruction(size_t i); + Ref 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 Function::GetStackVariablesReferencedByInstructio } +set Function::GetLowLevelILFlagUsesForDefinition(size_t i, uint32_t flag) +{ + size_t count; + size_t* instrs = BNGetLowLevelILFlagUsesForDefinition(m_object, i, flag, &count); + + set result; + result.insert(&instrs[0], &instrs[count]); + BNFreeLowLevelILInstructionList(instrs); + return result; +} + + +set Function::GetLowLevelILFlagDefinitionsForUse(size_t i, uint32_t flag) +{ + size_t count; + size_t* instrs = BNGetLowLevelILFlagDefinitionsForUse(m_object, i, flag, &count); + + set result; + result.insert(&instrs[0], &instrs[count]); + BNFreeLowLevelILInstructionList(instrs); + return result; +} + + +set Function::GetFlagsReadByLowLevelILInstruction(size_t i) +{ + size_t count; + uint32_t* flags = BNGetFlagsReadByLowLevelILInstruction(m_object, i, &count); + + set result; + result.insert(&flags[0], &flags[count]); + BNFreeRegisterList(flags); + return result; +} + + +set Function::GetFlagsWrittenByLowLevelILInstruction(size_t i) +{ + size_t count; + uint32_t* flags = BNGetFlagsWrittenByLowLevelILInstruction(m_object, i, &count); + + set result; + result.insert(&flags[0], &flags[count]); + BNFreeRegisterList(flags); + return result; +} + + Ref 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() - -- cgit v1.3.1