diff --git a/Function/BNCreateCustomLanguageRepresentationFunction.cs b/Function/BNCreateCustomLanguageRepresentationFunction.cs index d431031..d97c871 100644 --- a/Function/BNCreateCustomLanguageRepresentationFunction.cs +++ b/Function/BNCreateCustomLanguageRepresentationFunction.cs @@ -30,7 +30,7 @@ internal static extern IntPtr BNCreateCustomLanguageRepresentationFunction( IntPtr highLevelIL , // BNCustomLanguageRepresentationFunction* callbacks - IntPtr callbacks + in BNCustomLanguageRepresentationFunction callbacks ); } -} \ No newline at end of file +} diff --git a/Function/BNGetLanguageRepresentationFunctionExprText.cs b/Function/BNGetLanguageRepresentationFunctionExprText.cs index 539b0e6..700004e 100644 --- a/Function/BNGetLanguageRepresentationFunctionExprText.cs +++ b/Function/BNGetLanguageRepresentationFunctionExprText.cs @@ -30,16 +30,16 @@ internal static extern IntPtr BNGetLanguageRepresentationFunctionExprText( IntPtr settings , // bool asFullAst - bool asFullAst , + [MarshalAs(UnmanagedType.I1)] bool asFullAst , // BNOperatorPrecedence precedence OperatorPrecedence precedence , // bool statement - bool statement , + [MarshalAs(UnmanagedType.I1)] bool statement , // uint64_t* count out ulong count ); } -} \ No newline at end of file +} diff --git a/Function/BNGetLanguageRepresentationFunctionLinearLines.cs b/Function/BNGetLanguageRepresentationFunctionLinearLines.cs index 7f2ca65..a5c5ec3 100644 --- a/Function/BNGetLanguageRepresentationFunctionLinearLines.cs +++ b/Function/BNGetLanguageRepresentationFunctionLinearLines.cs @@ -30,10 +30,10 @@ internal static extern IntPtr BNGetLanguageRepresentationFunctionLinearLines( IntPtr settings , // bool asFullAst - bool asFullAst , + [MarshalAs(UnmanagedType.I1)] bool asFullAst , // uint64_t* count out ulong count ); } -} \ No newline at end of file +} diff --git a/Function/BNRegisterLanguageRepresentationFunctionType.cs b/Function/BNRegisterLanguageRepresentationFunctionType.cs index 805d74e..0ab2469 100644 --- a/Function/BNRegisterLanguageRepresentationFunctionType.cs +++ b/Function/BNRegisterLanguageRepresentationFunctionType.cs @@ -22,8 +22,8 @@ internal static extern IntPtr BNRegisterLanguageRepresentationFunctionType( [MarshalAs(UnmanagedType.LPUTF8Str)] string name , // BNCustomLanguageRepresentationFunctionType* type - IntPtr type + in BNCustomLanguageRepresentationFunctionType type ); } -} \ No newline at end of file +} diff --git a/Handle/BNFunction.cs b/Handle/BNFunction.cs index bcbd440..b7b106e 100644 --- a/Handle/BNFunction.cs +++ b/Handle/BNFunction.cs @@ -837,7 +837,7 @@ public HighLevelILFunction HighLevelIL return null; } - return new LanguageRepresentationFunction(raw , true); + return LanguageRepresentationFunction.MustTakeHandle(raw); } public FunctionType Type diff --git a/Handle/BNLanguageRepresentationFunction.cs b/Handle/BNLanguageRepresentationFunction.cs index f054037..d635c33 100644 --- a/Handle/BNLanguageRepresentationFunction.cs +++ b/Handle/BNLanguageRepresentationFunction.cs @@ -1,13 +1,13 @@ using System; using System.Collections.Generic; -using System.Runtime.InteropServices; using System.Text; -using Microsoft.Win32.SafeHandles; namespace BinaryNinja { - public sealed class LanguageRepresentationFunction : AbstractSafeHandle + public abstract partial class LanguageRepresentationFunction : AbstractSafeHandle { + private bool custom; + internal LanguageRepresentationFunction(IntPtr handle , bool owner) : base(handle , owner) { @@ -21,7 +21,7 @@ internal LanguageRepresentationFunction(IntPtr handle , bool owner) return null; } - return new LanguageRepresentationFunction( + return new CoreLanguageRepresentationFunction( NativeMethods.BNNewLanguageRepresentationFunctionReference(handle) , true ); @@ -34,7 +34,7 @@ internal static LanguageRepresentationFunction MustNewFromHandle(IntPtr handle) throw new ArgumentNullException(nameof(handle)); } - return new LanguageRepresentationFunction( + return new CoreLanguageRepresentationFunction( NativeMethods.BNNewLanguageRepresentationFunctionReference(handle) , true ); @@ -47,7 +47,7 @@ internal static LanguageRepresentationFunction MustNewFromHandle(IntPtr handle) return null; } - return new LanguageRepresentationFunction(handle, true); + return new CoreLanguageRepresentationFunction(handle, true); } internal static LanguageRepresentationFunction MustTakeHandle(IntPtr handle) @@ -57,7 +57,7 @@ internal static LanguageRepresentationFunction MustTakeHandle(IntPtr handle) throw new ArgumentNullException(nameof(handle)); } - return new LanguageRepresentationFunction(handle, true); + return new CoreLanguageRepresentationFunction(handle, true); } internal static LanguageRepresentationFunction? BorrowHandle(IntPtr handle) @@ -67,7 +67,7 @@ internal static LanguageRepresentationFunction MustTakeHandle(IntPtr handle) return null; } - return new LanguageRepresentationFunction(handle, false); + return new CoreLanguageRepresentationFunction(handle, false); } internal static LanguageRepresentationFunction MustBorrowHandle(IntPtr handle) @@ -77,11 +77,22 @@ internal static LanguageRepresentationFunction MustBorrowHandle(IntPtr handle) throw new ArgumentNullException(nameof(handle)); } - return new LanguageRepresentationFunction(handle, false); + return new CoreLanguageRepresentationFunction(handle, false); } protected override bool ReleaseHandle() { + if (this.custom) + { + if (this.initialReferencePending) + { + this.initialReferencePending = false; + NativeMethods.BNFreeLanguageRepresentationFunction(this.handle); + } + + return true; + } + if ( !this.IsInvalid ) { NativeMethods.BNFreeLanguageRepresentationFunction(this.handle); @@ -335,11 +346,16 @@ public string LinearDisassemblyText /// /// Gets the string that marks the start of an annotation in this language. /// - public string AnnotationStartString + public virtual string AnnotationStartString { get { - return UnsafeUtils.TakeAnsiString( + if (this.custom) + { + return "{"; + } + + return UnsafeUtils.TakeUtf8String( NativeMethods.BNGetLanguageRepresentationFunctionAnnotationStartString(this.handle) ); } @@ -348,11 +364,16 @@ public string AnnotationStartString /// /// Gets the string that marks the end of an annotation in this language. /// - public string AnnotationEndString + public virtual string AnnotationEndString { get { - return UnsafeUtils.TakeAnsiString( + if (this.custom) + { + return "}"; + } + + return UnsafeUtils.TakeUtf8String( NativeMethods.BNGetLanguageRepresentationFunctionAnnotationEndString(this.handle) ); } @@ -361,11 +382,16 @@ public string AnnotationEndString /// /// Gets the string that marks the start of a comment in this language. /// - public string CommentStartString + public virtual string CommentStartString { get { - return UnsafeUtils.TakeAnsiString( + if (this.custom) + { + return "// "; + } + + return UnsafeUtils.TakeUtf8String( NativeMethods.BNGetLanguageRepresentationFunctionCommentStartString(this.handle) ); } @@ -374,109 +400,20 @@ public string CommentStartString /// /// Gets the string that marks the end of a comment in this language. /// - public string CommentEndString + public virtual string CommentEndString { get { - return UnsafeUtils.TakeAnsiString( + if (this.custom) + { + return string.Empty; + } + + return UnsafeUtils.TakeUtf8String( NativeMethods.BNGetLanguageRepresentationFunctionCommentEndString(this.handle) ); } } - // =================================================================== - // Highlight - // =================================================================== - - /// - /// Gets the highlight color for this language representation function at the specified basic block. - /// - /// The basic block to get the highlight for. - /// The highlight color for the block. - public HighlightColor GetHighlight(BasicBlock block) - { - return HighlightColor.FromNative( - NativeMethods.BNGetLanguageRepresentationFunctionHighlight( - this.handle , - block.DangerousGetHandle() - ) - ); - } - - // =================================================================== - // Language type lookup - // =================================================================== - - /// - /// Gets the language representation function type associated with this instance. - /// - /// The LanguageRepresentationFunctionType, or null if not available. - public LanguageRepresentationFunctionType? GetLanguageType() - { - return LanguageRepresentationFunctionType.BorrowHandle( - NativeMethods.BNGetLanguageRepresentationType(this.handle) - ); - } - - /// - /// Gets a registered language representation function type by its name. - /// - /// The name of the language type (e.g., "Pseudo C"). - /// The matching LanguageRepresentationFunctionType, or null if not found. - public static LanguageRepresentationFunctionType? GetLanguageTypeByName(string name) - { - return LanguageRepresentationFunctionType.BorrowHandle( - NativeMethods.BNGetLanguageRepresentationFunctionTypeByName(name) - ); - } - - /// - /// Gets the line formatter settings for this language representation function - /// using the given disassembly settings. Returns a LineFormatterSettings populated - /// with language-specific formatting defaults. - /// - /// The disassembly settings providing base formatting context. - /// A LineFormatterSettings populated with language-appropriate values. - public LineFormatterSettings GetLineFormatterSettings(DisassemblySettings settings) - { - // 1. Call the native API. - IntPtr ptr = NativeMethods.BNGetLanguageRepresentationLineFormatterSettings( - settings.DangerousGetHandle() , - this.handle - ); - - // 2. Handle null return. - if (IntPtr.Zero == ptr) - { - return new LineFormatterSettings(); - } - - // 3. Read the native struct from the pointer. - BNLineFormatterSettings native = Marshal.PtrToStructure(ptr); - - // 4. Convert to managed type. - LineFormatterSettings result = new LineFormatterSettings(); - result.DesiredLineLength = native.desiredLineLength; - result.MinimumContentLength = native.minimumContentLength; - result.TabWidth = native.tabWidth; - result.MaximumAnnotationLength = native.maximumAnnotationLength; - result.StringWrappingWidth = native.stringWrappingWidth; - result.LanguageName = UnsafeUtils.ReadAnsiString(native.languageName); - result.CommentStartString = UnsafeUtils.ReadAnsiString(native.commentStartString); - result.CommentEndString = UnsafeUtils.ReadAnsiString(native.commentEndString); - result.AnnotationStartString = UnsafeUtils.ReadAnsiString(native.annotationStartString); - result.AnnotationEndString = UnsafeUtils.ReadAnsiString(native.annotationEndString); - - // 5. The HLIL function is a borrowed pointer inside the struct; wrap if non-null. - result.HighLevelIL = (native.highLevelIL != IntPtr.Zero) - ? HighLevelILFunction.NewFromHandle(native.highLevelIL) - : null; - - // 6. Free the native struct allocation. - NativeMethods.BNFreeLineFormatterSettings(ptr); - - return result; - } - } -} \ No newline at end of file +} diff --git a/Handle/BNLanguageRepresentationFunctionCustom.cs b/Handle/BNLanguageRepresentationFunctionCustom.cs new file mode 100644 index 0000000..90f6359 --- /dev/null +++ b/Handle/BNLanguageRepresentationFunctionCustom.cs @@ -0,0 +1,496 @@ +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; + +namespace BinaryNinja +{ + public abstract partial class LanguageRepresentationFunction + { + private enum CustomStringKind + { + CommentStart, + CommentEnd, + AnnotationStart, + AnnotationEnd + } + + private static readonly object registrationLock = new object(); + + private static readonly List + registeredFunctions = new List(); + + private bool initialReferencePending; + + private NativeDelegates.BNLanguageRepresentationFunctionEvent? + freeCallback; + + private NativeDelegates.BNLanguageRepresentationTokenEmitter? + initTokenEmitterCallback; + + private NativeDelegates.BNLanguageRepresentationExpression? + getExpressionTextCallback; + + private NativeDelegates.BNLanguageRepresentationLines? + beginLinesCallback; + + private NativeDelegates.BNLanguageRepresentationLines? + endLinesCallback; + + private NativeDelegates.BNLanguageRepresentationString? + getCommentStartStringCallback; + + private NativeDelegates.BNLanguageRepresentationString? + getCommentEndStringCallback; + + private NativeDelegates.BNLanguageRepresentationString? + getAnnotationStartStringCallback; + + private NativeDelegates.BNLanguageRepresentationString? + getAnnotationEndStringCallback; + + /// Creates a custom representation for one high-level IL function. + protected LanguageRepresentationFunction( + LanguageRepresentationFunctionType type, + Architecture architecture, + Function owner, + HighLevelILFunction highLevelIL + ) + : base(false) + { + if (null == type) + { + throw new ArgumentNullException(nameof(type)); + } + + if (null == architecture) + { + throw new ArgumentNullException(nameof(architecture)); + } + + if (null == owner) + { + throw new ArgumentNullException(nameof(owner)); + } + + if (null == highLevelIL) + { + throw new ArgumentNullException(nameof(highLevelIL)); + } + + this.custom = true; + this.InitializeCustomCallbacks(); + BNCustomLanguageRepresentationFunction callbacks = + this.CreateCustomCallbacks(); + IntPtr function = + NativeMethods.BNCreateCustomLanguageRepresentationFunction( + type.RegistrationHandle, + architecture.DangerousGetHandle(), + owner.DangerousGetHandle(), + highLevelIL.DangerousGetHandle(), + in callbacks + ); + if (IntPtr.Zero == function) + { + throw new InvalidOperationException( + "The core rejected the language representation function." + ); + } + + this.SetHandle(function); + this.initialReferencePending = true; + lock (LanguageRepresentationFunction.registrationLock) + { + LanguageRepresentationFunction.registeredFunctions.Add(this); + } + } + + /// Initializes a token emitter before rendering. + protected virtual void InitTokenEmitter(HighLevelILTokenEmitter emitter) + { + } + + /// Emits tokens for one high-level IL expression. + protected abstract void GetExpressionText( + HighLevelILInstruction instruction, + HighLevelILTokenEmitter emitter, + DisassemblySettings? settings, + OperatorPrecedence precedence, + bool statement + ); + + /// Emits tokens before rendering a group of lines. + protected virtual void BeginLines( + HighLevelILInstruction instruction, + HighLevelILTokenEmitter emitter + ) + { + } + + /// Emits tokens after rendering a group of lines. + protected virtual void EndLines( + HighLevelILInstruction instruction, + HighLevelILTokenEmitter emitter + ) + { + } + + internal void ReleaseInitialReferenceForRegistration() + { + if (!this.initialReferencePending) + { + return; + } + + this.initialReferencePending = false; + NativeMethods.BNFreeLanguageRepresentationFunction(this.handle); + } + + private void InitializeCustomCallbacks() + { + this.freeCallback = + new NativeDelegates.BNLanguageRepresentationFunctionEvent( + this.InvokeFree + ); + this.initTokenEmitterCallback = + new NativeDelegates.BNLanguageRepresentationTokenEmitter( + this.InvokeInitTokenEmitter + ); + this.getExpressionTextCallback = + new NativeDelegates.BNLanguageRepresentationExpression( + this.InvokeGetExpressionText + ); + this.beginLinesCallback = + new NativeDelegates.BNLanguageRepresentationLines( + this.InvokeBeginLines + ); + this.endLinesCallback = + new NativeDelegates.BNLanguageRepresentationLines( + this.InvokeEndLines + ); + this.getCommentStartStringCallback = + new NativeDelegates.BNLanguageRepresentationString( + this.InvokeGetCommentStartString + ); + this.getCommentEndStringCallback = + new NativeDelegates.BNLanguageRepresentationString( + this.InvokeGetCommentEndString + ); + this.getAnnotationStartStringCallback = + new NativeDelegates.BNLanguageRepresentationString( + this.InvokeGetAnnotationStartString + ); + this.getAnnotationEndStringCallback = + new NativeDelegates.BNLanguageRepresentationString( + this.InvokeGetAnnotationEndString + ); + } + + private BNCustomLanguageRepresentationFunction CreateCustomCallbacks() + { + BNCustomLanguageRepresentationFunction callbacks = + new BNCustomLanguageRepresentationFunction(); + callbacks.context = IntPtr.Zero; + callbacks.freeObject = this.GetCallbackPointer(this.freeCallback!); + callbacks.externalRefTaken = IntPtr.Zero; + callbacks.externalRefReleased = IntPtr.Zero; + callbacks.initTokenEmitter = this.GetCallbackPointer( + this.initTokenEmitterCallback! + ); + callbacks.getExprText = this.GetCallbackPointer( + this.getExpressionTextCallback! + ); + callbacks.beginLines = this.GetCallbackPointer( + this.beginLinesCallback! + ); + callbacks.endLines = this.GetCallbackPointer( + this.endLinesCallback! + ); + callbacks.getCommentStartString = this.GetCallbackPointer( + this.getCommentStartStringCallback! + ); + callbacks.getCommentEndString = this.GetCallbackPointer( + this.getCommentEndStringCallback! + ); + callbacks.getAnnotationStartString = this.GetCallbackPointer( + this.getAnnotationStartStringCallback! + ); + callbacks.getAnnotationEndString = this.GetCallbackPointer( + this.getAnnotationEndStringCallback! + ); + + return callbacks; + } + + private void InvokeFree(IntPtr context) + { + try + { + lock (LanguageRepresentationFunction.registrationLock) + { + while ( + LanguageRepresentationFunction.registeredFunctions.Remove( + this + ) + ) + { + } + } + + this.SetHandleAsInvalid(); + } + catch (Exception exception) + { + this.LogCallbackException("Free", exception); + } + } + + private void InvokeInitTokenEmitter(IntPtr context, IntPtr emitter) + { + HighLevelILTokenEmitter? managedEmitter = null; + try + { + managedEmitter = HighLevelILTokenEmitter.NewFromHandle(emitter); + this.InitTokenEmitter(managedEmitter!); + } + catch (Exception exception) + { + this.LogCallbackException("InitTokenEmitter", exception); + } + finally + { + if (null != managedEmitter) + { + managedEmitter.Dispose(); + } + } + } + + private void InvokeGetExpressionText( + IntPtr context, + IntPtr highLevelIL, + UIntPtr expressionIndex, + IntPtr emitter, + IntPtr settings, + bool asFullAst, + OperatorPrecedence precedence, + bool statement + ) + { + HighLevelILFunction? managedIL = null; + HighLevelILTokenEmitter? managedEmitter = null; + DisassemblySettings? managedSettings = null; + try + { + managedIL = HighLevelILFunction.NewFromHandle(highLevelIL); + managedEmitter = HighLevelILTokenEmitter.NewFromHandle(emitter); + managedSettings = DisassemblySettings.NewFromHandle(settings); + HighLevelILInstruction instruction = managedIL!.MustGetExpression( + (HighLevelILExpressionIndex)expressionIndex.ToUInt64(), + asFullAst + ); + this.GetExpressionText( + instruction, + managedEmitter!, + managedSettings, + precedence, + statement + ); + } + catch (Exception exception) + { + this.LogCallbackException("GetExpressionText", exception); + } + finally + { + if (null != managedSettings) + { + managedSettings.Dispose(); + } + + if (null != managedEmitter) + { + managedEmitter.Dispose(); + } + + if (null != managedIL) + { + managedIL.Dispose(); + } + } + } + + private void InvokeBeginLines( + IntPtr context, + IntPtr highLevelIL, + UIntPtr expressionIndex, + IntPtr emitter + ) + { + this.InvokeLines( + "BeginLines", + highLevelIL, + expressionIndex, + emitter, + true + ); + } + + private void InvokeEndLines( + IntPtr context, + IntPtr highLevelIL, + UIntPtr expressionIndex, + IntPtr emitter + ) + { + this.InvokeLines( + "EndLines", + highLevelIL, + expressionIndex, + emitter, + false + ); + } + + private void InvokeLines( + string name, + IntPtr highLevelIL, + UIntPtr expressionIndex, + IntPtr emitter, + bool begin + ) + { + HighLevelILFunction? managedIL = null; + HighLevelILTokenEmitter? managedEmitter = null; + try + { + managedIL = HighLevelILFunction.NewFromHandle(highLevelIL); + managedEmitter = HighLevelILTokenEmitter.NewFromHandle(emitter); + HighLevelILInstruction instruction = managedIL!.MustGetExpression( + (HighLevelILExpressionIndex)expressionIndex.ToUInt64() + ); + if (begin) + { + this.BeginLines(instruction, managedEmitter!); + } + else + { + this.EndLines(instruction, managedEmitter!); + } + } + catch (Exception exception) + { + this.LogCallbackException(name, exception); + } + finally + { + if (null != managedEmitter) + { + managedEmitter.Dispose(); + } + + if (null != managedIL) + { + managedIL.Dispose(); + } + } + } + + private IntPtr InvokeGetCommentStartString(IntPtr context) + { + return this.InvokeString( + "CommentStartString", + CustomStringKind.CommentStart + ); + } + + private IntPtr InvokeGetCommentEndString(IntPtr context) + { + return this.InvokeString( + "CommentEndString", + CustomStringKind.CommentEnd + ); + } + + private IntPtr InvokeGetAnnotationStartString(IntPtr context) + { + return this.InvokeString( + "AnnotationStartString", + CustomStringKind.AnnotationStart + ); + } + + private IntPtr InvokeGetAnnotationEndString(IntPtr context) + { + return this.InvokeString( + "AnnotationEndString", + CustomStringKind.AnnotationEnd + ); + } + + private IntPtr InvokeString(string name, CustomStringKind kind) + { + try + { + string value; + if (CustomStringKind.CommentStart == kind) + { + value = this.CommentStartString; + } + else if (CustomStringKind.CommentEnd == kind) + { + value = this.CommentEndString; + } + else if (CustomStringKind.AnnotationStart == kind) + { + value = this.AnnotationStartString; + } + else + { + value = this.AnnotationEndString; + } + + return NativeMethods.BNAllocString(value ?? string.Empty); + } + catch (Exception exception) + { + this.LogCallbackException(name, exception); + + return NativeMethods.BNAllocString(string.Empty); + } + } + + private IntPtr GetCallbackPointer(TDelegate callback) + where TDelegate : Delegate + { + return Marshal.GetFunctionPointerForDelegate(callback); + } + + private void LogCallbackException(string name, Exception exception) + { + Core.LogError( + "Unhandled exception in LanguageRepresentationFunction.{0}: {1}", + name, + exception + ); + } + + private sealed class CoreLanguageRepresentationFunction : + LanguageRepresentationFunction + { + internal CoreLanguageRepresentationFunction(IntPtr handle, bool owner) + : base(handle, owner) + { + } + + protected override void GetExpressionText( + HighLevelILInstruction instruction, + HighLevelILTokenEmitter emitter, + DisassemblySettings? settings, + OperatorPrecedence precedence, + bool statement + ) + { + } + } + } +} diff --git a/Handle/BNLanguageRepresentationFunctionNavigation.cs b/Handle/BNLanguageRepresentationFunctionNavigation.cs new file mode 100644 index 0000000..3c2548e --- /dev/null +++ b/Handle/BNLanguageRepresentationFunctionNavigation.cs @@ -0,0 +1,113 @@ +using System; +using System.Runtime.InteropServices; + +namespace BinaryNinja +{ + public abstract partial class LanguageRepresentationFunction + { + /// Gets the highlight color for a native function basic block. + public HighlightColor GetHighlight(BasicBlock block) + { + if (null == block) + { + throw new ArgumentNullException(nameof(block)); + } + + return HighlightColor.FromNative( + NativeMethods.BNGetLanguageRepresentationFunctionHighlight( + this.handle, + block.DangerousGetHandle() + ) + ); + } + + /// Gets the highlight color for a high-level IL basic block. + public HighlightColor GetHighlight(HighLevelILBasicBlock block) + { + if (null == block) + { + throw new ArgumentNullException(nameof(block)); + } + + return HighlightColor.FromNative( + NativeMethods.BNGetLanguageRepresentationFunctionHighlight( + this.handle, + block.DangerousGetHandle() + ) + ); + } + + /// Gets the language type associated with this function. + public LanguageRepresentationFunctionType? GetLanguageType() + { + return LanguageRepresentationFunctionType.BorrowHandle( + NativeMethods.BNGetLanguageRepresentationType(this.handle) + ); + } + + /// Looks up a registered language type by name. + public static LanguageRepresentationFunctionType? GetLanguageTypeByName( + string name + ) + { + return LanguageRepresentationFunctionType.GetByName(name); + } + + /// Gets language-specific line formatter settings. + public LineFormatterSettings GetLineFormatterSettings( + DisassemblySettings settings + ) + { + if (null == settings) + { + throw new ArgumentNullException(nameof(settings)); + } + + IntPtr pointer = + NativeMethods.BNGetLanguageRepresentationLineFormatterSettings( + settings.DangerousGetHandle(), + this.handle + ); + if (IntPtr.Zero == pointer) + { + return new LineFormatterSettings(); + } + + try + { + BNLineFormatterSettings native = + Marshal.PtrToStructure(pointer); + LineFormatterSettings result = new LineFormatterSettings(); + result.DesiredLineLength = native.desiredLineLength; + result.MinimumContentLength = native.minimumContentLength; + result.TabWidth = native.tabWidth; + result.MaximumAnnotationLength = native.maximumAnnotationLength; + result.StringWrappingWidth = native.stringWrappingWidth; + result.LanguageName = UnsafeUtils.ReadUtf8String( + native.languageName + ); + result.CommentStartString = UnsafeUtils.ReadUtf8String( + native.commentStartString + ); + result.CommentEndString = UnsafeUtils.ReadUtf8String( + native.commentEndString + ); + result.AnnotationStartString = UnsafeUtils.ReadUtf8String( + native.annotationStartString + ); + result.AnnotationEndString = UnsafeUtils.ReadUtf8String( + native.annotationEndString + ); + result.HighLevelIL = HighLevelILFunction.NewFromHandle( + native.highLevelIL + ); + + return result; + } + finally + { + NativeMethods.BNFreeLineFormatterSettings(pointer); + } + } + } +} diff --git a/Handle/BNLanguageRepresentationFunctionOperations.cs b/Handle/BNLanguageRepresentationFunctionOperations.cs new file mode 100644 index 0000000..ddf04bc --- /dev/null +++ b/Handle/BNLanguageRepresentationFunctionOperations.cs @@ -0,0 +1,94 @@ +using System; + +namespace BinaryNinja +{ + public abstract partial class LanguageRepresentationFunction + { + /// Gets rendered lines for one high-level IL expression. + public DisassemblyTextLine[] GetExpressionText( + HighLevelILInstruction instruction, + DisassemblySettings? settings = null, + OperatorPrecedence precedence = OperatorPrecedence.TopLevelOperatorPrecedence, + bool statement = false + ) + { + IntPtr lines = NativeMethods.BNGetLanguageRepresentationFunctionExprText( + this.handle, + instruction.ILFunction.DangerousGetHandle(), + instruction.ExpressionIndex, + null == settings + ? IntPtr.Zero + : settings.DangerousGetHandle(), + instruction.AsFullAst, + precedence, + statement, + out ulong count + ); + + return UnsafeUtils.TakeStructArrayEx< + BNDisassemblyTextLine, + DisassemblyTextLine + >( + lines, + count, + DisassemblyTextLine.FromNative, + NativeMethods.BNFreeDisassemblyTextLines + ); + } + + /// Gets linear-view lines for one high-level IL expression. + public DisassemblyTextLine[] GetLinearLines( + HighLevelILInstruction instruction, + DisassemblySettings? settings = null + ) + { + IntPtr lines = + NativeMethods.BNGetLanguageRepresentationFunctionLinearLines( + this.handle, + instruction.ILFunction.DangerousGetHandle(), + instruction.ExpressionIndex, + null == settings + ? IntPtr.Zero + : settings.DangerousGetHandle(), + instruction.AsFullAst, + out ulong count + ); + + return UnsafeUtils.TakeStructArrayEx< + BNDisassemblyTextLine, + DisassemblyTextLine + >( + lines, + count, + DisassemblyTextLine.FromNative, + NativeMethods.BNFreeDisassemblyTextLines + ); + } + + /// Gets rendered lines for one high-level IL basic block. + public DisassemblyTextLine[] GetBlockLines( + HighLevelILBasicBlock block, + DisassemblySettings? settings = null + ) + { + IntPtr lines = NativeMethods.BNGetLanguageRepresentationFunctionBlockLines( + this.handle, + block.DangerousGetHandle(), + null == settings + ? IntPtr.Zero + : settings.DangerousGetHandle(), + out ulong count + ); + + return UnsafeUtils.TakeStructArrayEx< + BNDisassemblyTextLine, + DisassemblyTextLine + >( + lines, + count, + DisassemblyTextLine.FromNative, + NativeMethods.BNFreeDisassemblyTextLines + ); + } + } +} diff --git a/Handle/BNLanguageRepresentationFunctionType.cs b/Handle/BNLanguageRepresentationFunctionType.cs index 89bf479..692f7e5 100644 --- a/Handle/BNLanguageRepresentationFunctionType.cs +++ b/Handle/BNLanguageRepresentationFunctionType.cs @@ -1,193 +1,287 @@ using System; -using System.Collections.Generic; -using System.Runtime.InteropServices; -using Microsoft.Win32.SafeHandles; namespace BinaryNinja { - /// - /// Represents a registered language representation function type, which defines a - /// decompilation language (e.g., C, C++, LLIL). Handles are always borrowed from - /// the native engine's global registry and must not be freed by this wrapper. - /// - public sealed class LanguageRepresentationFunctionType : AbstractSafeHandle + /// Defines a registered high-level language representation. + public abstract partial class LanguageRepresentationFunctionType : + AbstractSafeHandle { - /// - /// Initializes a new LanguageRepresentationFunctionType wrapper around an existing - /// borrowed handle. The handle is never owned by this instance. - /// - /// The native pointer to the BNLanguageRepresentationFunctionType object. - internal LanguageRepresentationFunctionType(IntPtr handle) - : base(handle, false) + private readonly string? registrationName; + + private bool custom; + + private bool registered; + + internal IntPtr RegistrationHandle { + get + { + return this.handle; + } } - /// - /// Borrows a native handle without taking ownership. Returns null if the handle is zero. - /// - /// The native BNLanguageRepresentationFunctionType pointer. - /// A new LanguageRepresentationFunctionType instance that will not free the handle on dispose. - internal static LanguageRepresentationFunctionType? BorrowHandle(IntPtr handle) + /// Creates an unregistered custom representation type. + protected LanguageRepresentationFunctionType(string name) + : base(false) { - if (handle == IntPtr.Zero) + if (null == name) { - return null; + throw new ArgumentNullException(nameof(name)); } - return new LanguageRepresentationFunctionType(handle); + this.custom = true; + this.registrationName = name; } - /// - /// Borrows a native handle without taking ownership. Throws if the handle is zero. - /// - /// The native BNLanguageRepresentationFunctionType pointer. - /// A new LanguageRepresentationFunctionType instance that will not free the handle on dispose. - internal static LanguageRepresentationFunctionType MustBorrowHandle(IntPtr handle) + private LanguageRepresentationFunctionType(IntPtr handle) + : base(handle, false) { - if (handle == IntPtr.Zero) + } + + internal static LanguageRepresentationFunctionType? BorrowHandle( + IntPtr handle + ) + { + if (IntPtr.Zero == handle) { - throw new ArgumentNullException(nameof(handle)); + return null; } - return new LanguageRepresentationFunctionType(handle); + return new CoreLanguageRepresentationFunctionType(handle); } - /// - /// No-op release: language representation function type handles are always borrowed - /// from the global registry and must not be freed by this wrapper. - /// - /// True (always, since no deallocation is performed). - protected override bool ReleaseHandle() + internal static LanguageRepresentationFunctionType MustBorrowHandle( + IntPtr handle + ) { - // Objects are borrowed from the global registry; the native engine owns their lifetime. - return true; + LanguageRepresentationFunctionType? type = + LanguageRepresentationFunctionType.BorrowHandle(handle); + if (null == type) + { + throw new ArgumentNullException(nameof(handle)); + } + + return type; } - /// - /// Gets the registered name that uniquely identifies this language representation type. - /// + /// Gets the unique registered language name. public string Name { get { - // 1. Retrieve the native ANSI string pointer for the language type name. - IntPtr raw = NativeMethods.BNGetLanguageRepresentationFunctionTypeName(this.handle); + if (this.IsInvalid) + { + return this.registrationName ?? string.Empty; + } - // 2. Copy and free the native string, returning empty on null. - return UnsafeUtils.TakeAnsiString(raw) ?? string.Empty; + return UnsafeUtils.TakeUtf8String( + NativeMethods.BNGetLanguageRepresentationFunctionTypeName( + this.handle + ) + ); } } - /// - /// Gets the line formatter associated with this language representation type. - /// Returns null if no line formatter is registered. - /// - public LineFormatter? Formatter + /// Gets the associated line formatter. + public virtual LineFormatter? Formatter { get { - // Borrow the native line formatter handle; it is owned by the global registry. + if (this.custom) + { + return null; + } + return LineFormatter.BorrowHandle( - NativeMethods.BNGetLanguageRepresentationFunctionTypeLineFormatter(this.handle) + NativeMethods.BNGetLanguageRepresentationFunctionTypeLineFormatter( + this.handle + ) ); } } - /// - /// Gets the type parser associated with this language representation type. - /// Returns null if no parser is registered. - /// - public TypeParser? Parser + /// Gets the associated type parser. + public virtual TypeParser? Parser { get { - // Borrow the native type parser handle; it is owned by the global registry. + if (this.custom) + { + return null; + } + return TypeParser.BorrowHandle( - NativeMethods.BNGetLanguageRepresentationFunctionTypeParser(this.handle) + NativeMethods.BNGetLanguageRepresentationFunctionTypeParser( + this.handle + ) ); } } - /// - /// Gets the type printer associated with this language representation type. - /// Returns null if no printer is registered. - /// - public TypePrinter? Printer + /// Gets the associated type printer. + public virtual TypePrinter? Printer { get { - // Borrow the native type printer handle; it is owned by the global registry. + if (this.custom) + { + return null; + } + return TypePrinter.BorrowHandle( - NativeMethods.BNGetLanguageRepresentationFunctionTypePrinter(this.handle) + NativeMethods.BNGetLanguageRepresentationFunctionTypePrinter( + this.handle + ) ); } } - /// - /// Determines whether this language representation type is valid for the given binary view. - /// - /// The binary view to check validity against. - /// True if this language representation type is applicable to the given view. - public bool IsValidFor(BinaryView view) + /// Registers this custom representation type. + public void Register() { - // Retrieve the raw handle for the view; pass zero if null (although view should not be null). - IntPtr viewHandle = (view != null) ? view.DangerousGetHandle() : IntPtr.Zero; + if (!this.custom) + { + throw new InvalidOperationException( + "Core representation types cannot be registered again." + ); + } - // Delegate to the native validity check. - return NativeMethods.BNIsLanguageRepresentationFunctionTypeValid(this.handle, viewHandle); + if (this.registered || !this.IsInvalid) + { + throw new InvalidOperationException( + "The language representation type is already registered." + ); + } + + this.RegisterCustomType(this.registrationName ?? string.Empty); + this.registered = true; } - /// - /// Retrieves all registered language representation function types from the engine. - /// Each returned instance is a borrowed reference managed by the native engine. - /// - /// An array of all registered LanguageRepresentationFunctionType instances. - /// - /// Gets the function type declaration tokens for the given function using this language - /// representation type. Returns the declaration as an array of disassembly text lines. - /// - /// The function to get type tokens for. - /// Optional disassembly settings. Pass null for defaults. - /// An array of DisassemblyTextLine containing the function type tokens. - public unsafe DisassemblyTextLine[] GetFunctionTypeTokens( - Function func , + /// Creates a language representation for one high-level IL function. + public abstract LanguageRepresentationFunction? Create( + Architecture architecture, + Function owner, + HighLevelILFunction highLevelIL + ); + + /// Determines whether this type applies to a view. + public virtual bool IsValidFor(BinaryView view) + { + if (null == view) + { + throw new ArgumentNullException(nameof(view)); + } + + if (this.custom) + { + return true; + } + + return NativeMethods.BNIsLanguageRepresentationFunctionTypeValid( + this.handle, + view.DangerousGetHandle() + ); + } + + /// Gets function declaration lines for this language. + public virtual unsafe DisassemblyTextLine[] GetFunctionTypeTokens( + Function function, DisassemblySettings? settings = null ) { - // 1. Stack-allocate the count variable. + if (this.custom) + { + return Array.Empty(); + } + ulong count = 0; + IntPtr lines = + NativeMethods.BNGetLanguageRepresentationFunctionTypeFunctionTypeTokens( + this.handle, + function.DangerousGetHandle(), + null == settings + ? IntPtr.Zero + : settings.DangerousGetHandle(), + (IntPtr)(&count) + ); - // 2. Call the native API. - IntPtr arrayPointer = NativeMethods.BNGetLanguageRepresentationFunctionTypeFunctionTypeTokens( - this.handle , - func.DangerousGetHandle() , - (null != settings) ? settings.DangerousGetHandle() : IntPtr.Zero , - (IntPtr)(&count) + return UnsafeUtils.TakeStructArrayEx< + BNDisassemblyTextLine, + DisassemblyTextLine + >( + lines, + count, + DisassemblyTextLine.FromNative, + NativeMethods.BNFreeDisassemblyTextLines ); + } - // 3. Convert the native array to managed objects and free the native memory. - return UnsafeUtils.TakeStructArrayEx( - arrayPointer , - count , - DisassemblyTextLine.FromNative , - NativeMethods.BNFreeDisassemblyTextLines + /// Looks up a registered representation type by name. + public static LanguageRepresentationFunctionType? GetByName(string name) + { + if (null == name) + { + throw new ArgumentNullException(nameof(name)); + } + + return LanguageRepresentationFunctionType.BorrowHandle( + NativeMethods.BNGetLanguageRepresentationFunctionTypeByName(name) ); } + /// Checks a named representation type against a view. + public static bool IsValidByName(string name, BinaryView view) + { + using LanguageRepresentationFunctionType? type = + LanguageRepresentationFunctionType.GetByName(name); + + return null != type && type.IsValidFor(view); + } + + /// Gets every registered representation type. public static LanguageRepresentationFunctionType[] GetList() { - // 1. Call the native API to get the array of language representation function type pointers. - IntPtr arrayPointer = NativeMethods.BNGetLanguageRepresentationFunctionTypeList( - out ulong count - ); + IntPtr types = + NativeMethods.BNGetLanguageRepresentationFunctionTypeList( + out ulong count + ); - // 2. Convert to managed array of borrowed handles and free the native pointer array. return UnsafeUtils.TakeHandleArray( - arrayPointer , - count , - LanguageRepresentationFunctionType.MustBorrowHandle , + types, + count, + LanguageRepresentationFunctionType.MustBorrowHandle, NativeMethods.BNFreeLanguageRepresentationFunctionTypeList ); } + + protected override bool ReleaseHandle() + { + return true; + } + + private sealed class CoreLanguageRepresentationFunctionType : + LanguageRepresentationFunctionType + { + internal CoreLanguageRepresentationFunctionType(IntPtr handle) + : base(handle) + { + } + + public override LanguageRepresentationFunction? Create( + Architecture architecture, + Function owner, + HighLevelILFunction highLevelIL + ) + { + return LanguageRepresentationFunction.TakeHandle( + NativeMethods.BNCreateLanguageRepresentationFunction( + this.handle, + architecture.DangerousGetHandle(), + owner.DangerousGetHandle(), + highLevelIL.DangerousGetHandle() + ) + ); + } + } } } diff --git a/Handle/BNLanguageRepresentationFunctionTypeCustom.cs b/Handle/BNLanguageRepresentationFunctionTypeCustom.cs new file mode 100644 index 0000000..94d3c47 --- /dev/null +++ b/Handle/BNLanguageRepresentationFunctionTypeCustom.cs @@ -0,0 +1,370 @@ +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; + +namespace BinaryNinja +{ + public abstract partial class LanguageRepresentationFunctionType + { + private static readonly object registrationLock = new object(); + + private static readonly List + registeredTypes = new List(); + + private readonly object lineOutputLock = new object(); + + private readonly Dictionary lineOutputs = + new Dictionary(); + + private NativeDelegates.BNLanguageRepresentationCreate? createCallback; + + private NativeDelegates.BNLanguageRepresentationIsValid? isValidCallback; + + private NativeDelegates.BNLanguageRepresentationGetObject? + getPrinterCallback; + + private NativeDelegates.BNLanguageRepresentationGetObject? getParserCallback; + + private NativeDelegates.BNLanguageRepresentationGetObject? + getFormatterCallback; + + private NativeDelegates.BNLanguageRepresentationGetFunctionTypeTokens? + getFunctionTypeTokensCallback; + + private NativeDelegates.BNLanguageRepresentationFreeLines? freeLinesCallback; + + private void RegisterCustomType(string name) + { + this.InitializeCallbacks(); + BNCustomLanguageRepresentationFunctionType callbacks = + new BNCustomLanguageRepresentationFunctionType(); + callbacks.context = IntPtr.Zero; + callbacks.create = this.GetCallbackPointer(this.createCallback!); + callbacks.isValid = this.GetCallbackPointer(this.isValidCallback!); + callbacks.getTypePrinter = this.GetCallbackPointer( + this.getPrinterCallback! + ); + callbacks.getTypeParser = this.GetCallbackPointer( + this.getParserCallback! + ); + callbacks.getLineFormatter = this.GetCallbackPointer( + this.getFormatterCallback! + ); + callbacks.getFunctionTypeTokens = this.GetCallbackPointer( + this.getFunctionTypeTokensCallback! + ); + callbacks.freeLines = this.GetCallbackPointer( + this.freeLinesCallback! + ); + + IntPtr handle = NativeMethods.BNRegisterLanguageRepresentationFunctionType( + name, + in callbacks + ); + if (IntPtr.Zero == handle) + { + throw new InvalidOperationException( + "The core rejected the language representation type." + ); + } + + this.SetHandle(handle); + lock (LanguageRepresentationFunctionType.registrationLock) + { + LanguageRepresentationFunctionType.registeredTypes.Add(this); + } + } + + private void InitializeCallbacks() + { + this.createCallback = new NativeDelegates.BNLanguageRepresentationCreate( + this.InvokeCreate + ); + this.isValidCallback = + new NativeDelegates.BNLanguageRepresentationIsValid( + this.InvokeIsValid + ); + this.getPrinterCallback = + new NativeDelegates.BNLanguageRepresentationGetObject( + this.InvokeGetPrinter + ); + this.getParserCallback = + new NativeDelegates.BNLanguageRepresentationGetObject( + this.InvokeGetParser + ); + this.getFormatterCallback = + new NativeDelegates.BNLanguageRepresentationGetObject( + this.InvokeGetFormatter + ); + this.getFunctionTypeTokensCallback = + new NativeDelegates.BNLanguageRepresentationGetFunctionTypeTokens( + this.InvokeGetFunctionTypeTokens + ); + this.freeLinesCallback = + new NativeDelegates.BNLanguageRepresentationFreeLines( + this.InvokeFreeLines + ); + } + + private IntPtr InvokeCreate( + IntPtr context, + IntPtr architecture, + IntPtr owner, + IntPtr highLevelIL + ) + { + Function? managedOwner = null; + HighLevelILFunction? managedIL = null; + LanguageRepresentationFunction? function = null; + try + { + managedOwner = Function.NewFromHandle(owner); + managedIL = HighLevelILFunction.NewFromHandle(highLevelIL); + Architecture managedArchitecture = Architecture.MustFromHandle( + architecture + ); + function = this.Create( + managedArchitecture, + managedOwner!, + managedIL! + ); + if (null == function) + { + return IntPtr.Zero; + } + + IntPtr result = + NativeMethods.BNNewLanguageRepresentationFunctionReference( + function.DangerousGetHandle() + ); + function.ReleaseInitialReferenceForRegistration(); + + return result; + } + catch (Exception exception) + { + this.LogCallbackException("Create", exception); + + return IntPtr.Zero; + } + finally + { + if (null != function) + { + function.Dispose(); + } + + if (null != managedIL) + { + managedIL.Dispose(); + } + + if (null != managedOwner) + { + managedOwner.Dispose(); + } + } + } + + private bool InvokeIsValid(IntPtr context, IntPtr view) + { + BinaryView? managedView = null; + try + { + managedView = BinaryView.TakeHandle( + NativeMethods.BNNewViewReference(view) + ); + return this.IsValidFor(managedView!); + } + catch (Exception exception) + { + this.LogCallbackException("IsValidFor", exception); + + return false; + } + finally + { + if (null != managedView) + { + managedView.Dispose(); + } + } + } + + private IntPtr InvokeGetPrinter(IntPtr context) + { + try + { + TypePrinter? printer = this.Printer; + + return null == printer + ? IntPtr.Zero + : printer.DangerousGetHandle(); + } + catch (Exception exception) + { + this.LogCallbackException("Printer", exception); + + return IntPtr.Zero; + } + } + + private IntPtr InvokeGetParser(IntPtr context) + { + try + { + TypeParser? parser = this.Parser; + + return null == parser + ? IntPtr.Zero + : parser.DangerousGetHandle(); + } + catch (Exception exception) + { + this.LogCallbackException("Parser", exception); + + return IntPtr.Zero; + } + } + + private IntPtr InvokeGetFormatter(IntPtr context) + { + try + { + LineFormatter? formatter = this.Formatter; + + return null == formatter + ? IntPtr.Zero + : formatter.DangerousGetHandle(); + } + catch (Exception exception) + { + this.LogCallbackException("Formatter", exception); + + return IntPtr.Zero; + } + } + + private IntPtr InvokeGetFunctionTypeTokens( + IntPtr context, + IntPtr function, + IntPtr settings, + IntPtr count + ) + { + Function? managedFunction = null; + DisassemblySettings? managedSettings = null; + try + { + managedFunction = Function.NewFromHandle(function); + managedSettings = DisassemblySettings.NewFromHandle(settings); + DisassemblyTextLine[] lines = this.GetFunctionTypeTokens( + managedFunction!, + managedSettings + ); + + return this.AllocateLines(lines, count); + } + catch (Exception exception) + { + Marshal.WriteIntPtr(count, IntPtr.Zero); + this.LogCallbackException("GetFunctionTypeTokens", exception); + + return IntPtr.Zero; + } + finally + { + if (null != managedSettings) + { + managedSettings.Dispose(); + } + + if (null != managedFunction) + { + managedFunction.Dispose(); + } + } + } + + private IntPtr AllocateLines( + DisassemblyTextLine[]? lines, + IntPtr count + ) + { + DisassemblyTextLine[] safeLines = + lines ?? Array.Empty(); + Marshal.WriteIntPtr(count, new IntPtr(safeLines.Length)); + if (0 == safeLines.Length) + { + return IntPtr.Zero; + } + + ScopedAllocator allocator = new ScopedAllocator(); + try + { + BNDisassemblyTextLine[] nativeLines = + new BNDisassemblyTextLine[safeLines.Length]; + for (int i = 0; i < safeLines.Length; i++) + { + nativeLines[i] = safeLines[i].ToNativeEx(allocator); + } + + IntPtr output = allocator.AllocStructArray(nativeLines); + lock (this.lineOutputLock) + { + this.lineOutputs.Add(output, allocator); + } + + return output; + } + catch + { + allocator.Dispose(); + throw; + } + } + + private void InvokeFreeLines( + IntPtr context, + IntPtr lines, + UIntPtr count + ) + { + try + { + ScopedAllocator? allocator = null; + lock (this.lineOutputLock) + { + if (this.lineOutputs.TryGetValue(lines, out allocator)) + { + this.lineOutputs.Remove(lines); + } + } + + if (null != allocator) + { + allocator.Dispose(); + } + } + catch (Exception exception) + { + this.LogCallbackException("FreeLines", exception); + } + } + + private IntPtr GetCallbackPointer(TDelegate callback) + where TDelegate : Delegate + { + return Marshal.GetFunctionPointerForDelegate(callback); + } + + private void LogCallbackException(string name, Exception exception) + { + Core.LogError( + "Unhandled exception in LanguageRepresentationFunctionType.{0}: {1}", + name, + exception + ); + } + } +} diff --git a/Struct/BNCustomLanguageRepresentationFunction.cs b/Struct/BNCustomLanguageRepresentationFunction.cs index 676e2df..30bf7d2 100644 --- a/Struct/BNCustomLanguageRepresentationFunction.cs +++ b/Struct/BNCustomLanguageRepresentationFunction.cs @@ -1,79 +1,77 @@ using System; -using System.Collections.Generic; using System.Runtime.InteropServices; -using Microsoft.Win32.SafeHandles; namespace BinaryNinja { - [StructLayout(LayoutKind.Sequential)] - internal unsafe struct BNCustomLanguageRepresentationFunction - { - /// - /// void* context - /// - public IntPtr context; - - /// - /// void** freeObject - /// - public IntPtr freeObject; - - /// - /// void** externalRefTaken - /// - public IntPtr externalRefTaken; - - /// - /// void** externalRefReleased - /// - public IntPtr externalRefReleased; - - /// - /// void** initTokenEmitter - /// - public IntPtr initTokenEmitter; - - /// - /// void** getExprText - /// - public IntPtr getExprText; - - /// - /// void** beginLines - /// - public IntPtr beginLines; - - /// - /// void** endLines - /// - public IntPtr endLines; - - /// - /// void** getCommentStartString - /// - public IntPtr getCommentStartString; - - /// - /// void** getCommentEndString - /// - public IntPtr getCommentEndString; - - /// - /// void** getAnnotationStartString - /// - public IntPtr getAnnotationStartString; - - /// - /// void** getAnnotationEndString - /// - public IntPtr getAnnotationEndString; - } - - public class CustomLanguageRepresentationFunction + internal static partial class NativeDelegates + { + [UnmanagedFunctionPointer(System.Runtime.InteropServices.CallingConvention.Cdecl)] + internal delegate void BNLanguageRepresentationFunctionEvent( + IntPtr context + ); + + [UnmanagedFunctionPointer(System.Runtime.InteropServices.CallingConvention.Cdecl)] + internal delegate void BNLanguageRepresentationTokenEmitter( + IntPtr context, + IntPtr emitter + ); + + [UnmanagedFunctionPointer(System.Runtime.InteropServices.CallingConvention.Cdecl)] + internal delegate void BNLanguageRepresentationExpression( + IntPtr context, + IntPtr highLevelIL, + UIntPtr expressionIndex, + IntPtr emitter, + IntPtr settings, + [MarshalAs(UnmanagedType.I1)] bool asFullAst, + OperatorPrecedence precedence, + [MarshalAs(UnmanagedType.I1)] bool statement + ); + + [UnmanagedFunctionPointer(System.Runtime.InteropServices.CallingConvention.Cdecl)] + internal delegate void BNLanguageRepresentationLines( + IntPtr context, + IntPtr highLevelIL, + UIntPtr expressionIndex, + IntPtr emitter + ); + + [UnmanagedFunctionPointer(System.Runtime.InteropServices.CallingConvention.Cdecl)] + internal delegate IntPtr BNLanguageRepresentationString(IntPtr context); + } + + [StructLayout(LayoutKind.Sequential)] + internal struct BNCustomLanguageRepresentationFunction + { + internal IntPtr context; + + internal IntPtr freeObject; + + internal IntPtr externalRefTaken; + + internal IntPtr externalRefReleased; + + internal IntPtr initTokenEmitter; + + internal IntPtr getExprText; + + internal IntPtr beginLines; + + internal IntPtr endLines; + + internal IntPtr getCommentStartString; + + internal IntPtr getCommentEndString; + + internal IntPtr getAnnotationStartString; + + internal IntPtr getAnnotationEndString; + } + + /// + /// Retained for source compatibility. Custom functions use the managed type directly. + /// + public class CustomLanguageRepresentationFunction { - public CustomLanguageRepresentationFunction() - { - - } } -} \ No newline at end of file +} diff --git a/Struct/BNCustomLanguageRepresentationFunctionType.cs b/Struct/BNCustomLanguageRepresentationFunctionType.cs index 011a709..cc7c1d2 100644 --- a/Struct/BNCustomLanguageRepresentationFunctionType.cs +++ b/Struct/BNCustomLanguageRepresentationFunctionType.cs @@ -1,60 +1,68 @@ using System; -using System.Collections.Generic; using System.Runtime.InteropServices; -using Microsoft.Win32.SafeHandles; namespace BinaryNinja { - [StructLayout(LayoutKind.Sequential)] - internal unsafe struct BNCustomLanguageRepresentationFunctionType - { - /// - /// void* context - /// - public IntPtr context; - - /// - /// void** create - /// - public IntPtr create; - - /// - /// void** isValid - /// - public IntPtr isValid; - - /// - /// void** getTypePrinter - /// - public IntPtr getTypePrinter; - - /// - /// void** getTypeParser - /// - public IntPtr getTypeParser; - - /// - /// void** getLineFormatter - /// - public IntPtr getLineFormatter; - - /// - /// void** getFunctionTypeTokens - /// - public IntPtr getFunctionTypeTokens; - - /// - /// void** freeLines - /// - public IntPtr freeLines; - } - - public class CustomLanguageRepresentationFunctionType + internal static partial class NativeDelegates + { + [UnmanagedFunctionPointer(System.Runtime.InteropServices.CallingConvention.Cdecl)] + internal delegate IntPtr BNLanguageRepresentationCreate( + IntPtr context, + IntPtr architecture, + IntPtr owner, + IntPtr highLevelIL + ); + + [UnmanagedFunctionPointer(System.Runtime.InteropServices.CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + internal delegate bool BNLanguageRepresentationIsValid( + IntPtr context, + IntPtr view + ); + + [UnmanagedFunctionPointer(System.Runtime.InteropServices.CallingConvention.Cdecl)] + internal delegate IntPtr BNLanguageRepresentationGetObject(IntPtr context); + + [UnmanagedFunctionPointer(System.Runtime.InteropServices.CallingConvention.Cdecl)] + internal delegate IntPtr BNLanguageRepresentationGetFunctionTypeTokens( + IntPtr context, + IntPtr function, + IntPtr settings, + IntPtr count + ); + + [UnmanagedFunctionPointer(System.Runtime.InteropServices.CallingConvention.Cdecl)] + internal delegate void BNLanguageRepresentationFreeLines( + IntPtr context, + IntPtr lines, + UIntPtr count + ); + } + + [StructLayout(LayoutKind.Sequential)] + internal struct BNCustomLanguageRepresentationFunctionType + { + internal IntPtr context; + + internal IntPtr create; + + internal IntPtr isValid; + + internal IntPtr getTypePrinter; + + internal IntPtr getTypeParser; + + internal IntPtr getLineFormatter; + + internal IntPtr getFunctionTypeTokens; + + internal IntPtr freeLines; + } + + /// + /// Retained for source compatibility. Custom types use the managed type directly. + /// + public class CustomLanguageRepresentationFunctionType { - - public CustomLanguageRepresentationFunctionType() - { - - } } -} \ No newline at end of file +}