diff --git a/Architecture/CustomArchitectureFlagCallbacks.cs b/Architecture/CustomArchitectureFlagCallbacks.cs new file mode 100644 index 0000000..ed9c85b --- /dev/null +++ b/Architecture/CustomArchitectureFlagCallbacks.cs @@ -0,0 +1,316 @@ +using System; +using System.Runtime.InteropServices; + +namespace BinaryNinja +{ + public abstract partial class CustomArchitecture + { + [UnmanagedFunctionPointer(System.Runtime.InteropServices.CallingConvention.Cdecl)] + private delegate FlagRole GetFlagRoleCallback( + IntPtr context, + uint flag, + uint semanticClass); + + [UnmanagedFunctionPointer(System.Runtime.InteropServices.CallingConvention.Cdecl)] + private delegate IntPtr GetFlagsForConditionCallback( + IntPtr context, + LowLevelILFlagCondition condition, + uint semanticClass, + out ulong count); + + [UnmanagedFunctionPointer(System.Runtime.InteropServices.CallingConvention.Cdecl)] + private delegate IntPtr GetIndexedListCallback( + IntPtr context, + uint index, + out ulong count); + + [UnmanagedFunctionPointer(System.Runtime.InteropServices.CallingConvention.Cdecl)] + private delegate void FreeConditionListCallback( + IntPtr context, + IntPtr conditions, + ulong count); + + [UnmanagedFunctionPointer(System.Runtime.InteropServices.CallingConvention.Cdecl)] + private delegate uint GetSemanticClassCallback(IntPtr context, uint writeType); + + private void AddFlagCallbacks(ref BNCustomArchitecture callbacks) + { + callbacks.getFlagName = UnsafeUtils.PinCallback( + this.GetFlagNameAdapter); + callbacks.getFlagWriteTypeName = UnsafeUtils.PinCallback( + this.GetFlagWriteTypeNameAdapter); + callbacks.getSemanticFlagClassName = + UnsafeUtils.PinCallback( + this.GetSemanticFlagClassNameAdapter); + callbacks.getSemanticFlagGroupName = + UnsafeUtils.PinCallback( + this.GetSemanticFlagGroupNameAdapter); + callbacks.getAllFlags = UnsafeUtils.PinCallback( + this.GetAllFlagsAdapter); + callbacks.getAllFlagWriteTypes = UnsafeUtils.PinCallback( + this.GetAllFlagWriteTypesAdapter); + callbacks.getAllSemanticFlagClasses = + UnsafeUtils.PinCallback( + this.GetAllSemanticFlagClassesAdapter); + callbacks.getAllSemanticFlagGroups = + UnsafeUtils.PinCallback( + this.GetAllSemanticFlagGroupsAdapter); + callbacks.getFlagRole = UnsafeUtils.PinCallback( + this.GetFlagRoleAdapter); + callbacks.getFlagsRequiredForFlagCondition = + UnsafeUtils.PinCallback( + this.GetFlagsRequiredForFlagConditionAdapter); + callbacks.getFlagsRequiredForSemanticFlagGroup = + UnsafeUtils.PinCallback( + this.GetFlagsRequiredForSemanticFlagGroupAdapter); + callbacks.getFlagConditionsForSemanticFlagGroup = + UnsafeUtils.PinCallback( + this.GetFlagConditionsForSemanticFlagGroupAdapter); + callbacks.freeFlagConditionsForSemanticFlagGroup = + UnsafeUtils.PinCallback( + this.FreeConditionListAdapter); + callbacks.getFlagsWrittenByFlagWriteType = + UnsafeUtils.PinCallback( + this.GetFlagsWrittenByFlagWriteTypeAdapter); + callbacks.getSemanticClassForFlagWriteType = + UnsafeUtils.PinCallback( + this.GetSemanticClassForFlagWriteTypeAdapter); + } + + private IntPtr GetFlagNameAdapter(IntPtr context, uint flag) + { + try + { + return NativeMethods.BNAllocString(this.getFlagName((FlagIndex)flag)); + } + catch (Exception exception) + { + return this.AllocateEmptyFlagName("getFlagName", exception); + } + } + + private IntPtr GetFlagWriteTypeNameAdapter(IntPtr context, uint writeType) + { + try + { + return NativeMethods.BNAllocString(this.GetFlagWriteTypeName(writeType)); + } + catch (Exception exception) + { + return this.AllocateEmptyFlagName("GetFlagWriteTypeName", exception); + } + } + + private IntPtr GetSemanticFlagClassNameAdapter(IntPtr context, uint semanticClass) + { + try + { + return NativeMethods.BNAllocString( + this.GetSemanticFlagClassName(semanticClass)); + } + catch (Exception exception) + { + return this.AllocateEmptyFlagName("GetSemanticFlagClassName", exception); + } + } + + private IntPtr GetSemanticFlagGroupNameAdapter(IntPtr context, uint semanticGroup) + { + try + { + return NativeMethods.BNAllocString( + this.GetSemanticFlagGroupName(semanticGroup)); + } + catch (Exception exception) + { + return this.AllocateEmptyFlagName("GetSemanticFlagGroupName", exception); + } + } + + private IntPtr AllocateEmptyFlagName(string callbackName, Exception exception) + { + Core.LogError( + "Unhandled exception in CustomArchitecture.{0}: {1}", + callbackName, + exception); + return NativeMethods.BNAllocString(string.Empty); + } + + private IntPtr GetAllFlagsAdapter(IntPtr context, out ulong count) + { + return this.GetRegisterListAdapter(this.GetAllFlags, "GetAllFlags", out count); + } + + private IntPtr GetAllFlagWriteTypesAdapter(IntPtr context, out ulong count) + { + return this.GetRegisterListAdapter( + this.GetAllFlagWriteTypes, + "GetAllFlagWriteTypes", + out count); + } + + private IntPtr GetAllSemanticFlagClassesAdapter(IntPtr context, out ulong count) + { + return this.GetRegisterListAdapter( + this.GetAllSemanticFlagClasses, + "GetAllSemanticFlagClasses", + out count); + } + + private IntPtr GetAllSemanticFlagGroupsAdapter(IntPtr context, out ulong count) + { + return this.GetRegisterListAdapter( + this.GetAllSemanticFlagGroups, + "GetAllSemanticFlagGroups", + out count); + } + + private FlagRole GetFlagRoleAdapter( + IntPtr context, + uint flag, + uint semanticClass) + { + try + { + return this.GetFlagRole(flag, semanticClass); + } + catch (Exception exception) + { + Core.LogError("Unhandled exception in CustomArchitecture.GetFlagRole: {0}", exception); + return FlagRole.SpecialFlagRole; + } + } + + private IntPtr GetFlagsRequiredForFlagConditionAdapter( + IntPtr context, + LowLevelILFlagCondition condition, + uint semanticClass, + out ulong count) + { + try + { + uint[] flags = this.GetFlagsRequiredForFlagCondition(condition, semanticClass); + return this.AllocateFlagList(flags, out count); + } + catch (Exception exception) + { + return this.HandleFlagListException( + "GetFlagsRequiredForFlagCondition", + exception, + out count); + } + } + + private IntPtr GetFlagsRequiredForSemanticFlagGroupAdapter( + IntPtr context, + uint semanticGroup, + out ulong count) + { + try + { + return this.AllocateFlagList( + this.GetFlagsRequiredForSemanticFlagGroup(semanticGroup), + out count); + } + catch (Exception exception) + { + return this.HandleFlagListException( + "GetFlagsRequiredForSemanticFlagGroup", + exception, + out count); + } + } + + private IntPtr GetFlagsWrittenByFlagWriteTypeAdapter( + IntPtr context, + uint writeType, + out ulong count) + { + try + { + return this.AllocateFlagList( + this.GetFlagsWrittenByFlagWriteType(writeType), + out count); + } + catch (Exception exception) + { + return this.HandleFlagListException( + "GetFlagsWrittenByFlagWriteType", + exception, + out count); + } + } + + private IntPtr AllocateFlagList(uint[] flags, out ulong count) + { + return this.AllocateRegisterList(flags ?? Array.Empty(), out count); + } + + private IntPtr HandleFlagListException( + string callbackName, + Exception exception, + out ulong count) + { + Core.LogError( + "Unhandled exception in CustomArchitecture.{0}: {1}", + callbackName, + exception); + count = 0; + return IntPtr.Zero; + } + + private IntPtr GetFlagConditionsForSemanticFlagGroupAdapter( + IntPtr context, + uint semanticGroup, + out ulong count) + { + try + { + FlagConditionForSemanticClass[] conditions = + this.GetFlagConditionsForSemanticFlagGroup(semanticGroup); + BNFlagConditionForSemanticClass[] native = + new BNFlagConditionForSemanticClass[conditions.Length]; + for (int index = 0; index < conditions.Length; index++) + { + native[index] = conditions[index].ToNative(); + } + + count = (ulong)native.Length; + return UnsafeUtils.AllocStructArray(native); + } + catch (Exception exception) + { + return this.HandleFlagListException( + "GetFlagConditionsForSemanticFlagGroup", + exception, + out count); + } + } + + private void FreeConditionListAdapter( + IntPtr context, + IntPtr conditions, + ulong count) + { + if (IntPtr.Zero != conditions) + { + Marshal.FreeHGlobal(conditions); + } + } + + private uint GetSemanticClassForFlagWriteTypeAdapter(IntPtr context, uint writeType) + { + try + { + return this.GetSemanticClassForFlagWriteType(writeType); + } + catch (Exception exception) + { + Core.LogError( + "Unhandled exception in CustomArchitecture.GetSemanticClassForFlagWriteType: {0}", + exception); + return 0; + } + } + } +} diff --git a/Architecture/CustomArchitectureRegisterCallbacks.cs b/Architecture/CustomArchitectureRegisterCallbacks.cs index e9d6e0f..635d905 100644 --- a/Architecture/CustomArchitectureRegisterCallbacks.cs +++ b/Architecture/CustomArchitectureRegisterCallbacks.cs @@ -124,23 +124,7 @@ private IntPtr GetRegisterListAdapter( try { uint[] registers = callback() ?? Array.Empty(); - count = (ulong)registers.Length; - if (0 == registers.Length) - { - return IntPtr.Zero; - } - - IntPtr result = Marshal.AllocHGlobal( - checked(registers.Length * sizeof(uint))); - for (int index = 0; index < registers.Length; index++) - { - Marshal.WriteInt32( - result, - checked(index * sizeof(uint)), - unchecked((int)registers[index])); - } - - return result; + return this.AllocateRegisterList(registers, out count); } catch (Exception exception) { @@ -153,6 +137,27 @@ private IntPtr GetRegisterListAdapter( } } + private IntPtr AllocateRegisterList(uint[] registers, out ulong count) + { + count = (ulong)registers.Length; + if (0 == registers.Length) + { + return IntPtr.Zero; + } + + IntPtr result = Marshal.AllocHGlobal( + checked(registers.Length * sizeof(uint))); + for (int index = 0; index < registers.Length; index++) + { + Marshal.WriteInt32( + result, + checked(index * sizeof(uint)), + unchecked((int)registers[index])); + } + + return result; + } + private void FreeRegisterListAdapter( IntPtr context, IntPtr registers, diff --git a/Architecture/CustomArchitectureRegistration.cs b/Architecture/CustomArchitectureRegistration.cs index 76e5b6d..f417a50 100644 --- a/Architecture/CustomArchitectureRegistration.cs +++ b/Architecture/CustomArchitectureRegistration.cs @@ -60,6 +60,7 @@ public Architecture Register(string name) this.GetAssociatedArchitectureAdapter) }; this.AddRegisterCallbacks(ref callbacks); + this.AddFlagCallbacks(ref callbacks); using (ScopedAllocator allocator = new ScopedAllocator()) { diff --git a/Struct/BNFlagConditionForSemanticClass.cs b/Struct/BNFlagConditionForSemanticClass.cs index af9a3c9..2f1c369 100644 --- a/Struct/BNFlagConditionForSemanticClass.cs +++ b/Struct/BNFlagConditionForSemanticClass.cs @@ -24,6 +24,14 @@ public sealed class FlagConditionForSemanticClass : INativeWrapper