diff --git a/Architecture/CustomArchitectureRegistration.cs b/Architecture/CustomArchitectureRegistration.cs
new file mode 100644
index 0000000..a9609f7
--- /dev/null
+++ b/Architecture/CustomArchitectureRegistration.cs
@@ -0,0 +1,179 @@
+using System;
+using System.Runtime.InteropServices;
+
+namespace BinaryNinja
+{
+ public abstract partial class CustomArchitecture
+ {
+ [UnmanagedFunctionPointer(System.Runtime.InteropServices.CallingConvention.Cdecl)]
+ private delegate void InitCallback(IntPtr context, IntPtr architecture);
+
+ [UnmanagedFunctionPointer(System.Runtime.InteropServices.CallingConvention.Cdecl)]
+ private delegate Endianness GetEndiannessCallback(IntPtr context);
+
+ [UnmanagedFunctionPointer(System.Runtime.InteropServices.CallingConvention.Cdecl)]
+ private delegate ulong GetSizeCallback(IntPtr context);
+
+ [UnmanagedFunctionPointer(System.Runtime.InteropServices.CallingConvention.Cdecl)]
+ private delegate IntPtr GetAssociatedArchitectureCallback(
+ IntPtr context,
+ ref ulong address);
+
+ private readonly object registrationLock = new object();
+ private Architecture? registeredArchitecture;
+
+ ///
+ /// Registers this architecture with the core for the lifetime of the process.
+ ///
+ public Architecture Register(string name)
+ {
+ if (string.IsNullOrWhiteSpace(name))
+ {
+ throw new ArgumentException("An architecture name is required.", nameof(name));
+ }
+
+ lock (this.registrationLock)
+ {
+ if (null != this.registeredArchitecture)
+ {
+ throw new InvalidOperationException("This architecture is already registered.");
+ }
+
+ BNCustomArchitecture callbacks = new BNCustomArchitecture
+ {
+ context = IntPtr.Zero,
+ init = UnsafeUtils.PinCallback(this.InitAdapter),
+ getEndianness = UnsafeUtils.PinCallback(
+ this.GetEndiannessAdapter),
+ getAddressSize = UnsafeUtils.PinCallback(
+ this.GetAddressSizeAdapter),
+ getDefaultIntegerSize = UnsafeUtils.PinCallback(
+ this.GetDefaultIntegerSizeAdapter),
+ getInstructionAlignment = UnsafeUtils.PinCallback(
+ this.GetInstructionAlignmentAdapter),
+ getMaxInstructionLength = UnsafeUtils.PinCallback(
+ this.GetMaxInstructionLengthAdapter),
+ getOpcodeDisplayLength = UnsafeUtils.PinCallback(
+ this.GetOpcodeDisplayLengthAdapter),
+ getAssociatedArchitectureByAddress =
+ UnsafeUtils.PinCallback(
+ this.GetAssociatedArchitectureAdapter)
+ };
+
+ using (ScopedAllocator allocator = new ScopedAllocator())
+ {
+ IntPtr handle = NativeMethods.BNRegisterArchitecture(
+ name,
+ allocator.AllocStruct(callbacks));
+ this.registeredArchitecture = Architecture.MustFromHandle(handle);
+ return Architecture.MustFromHandle(handle);
+ }
+ }
+ }
+
+ private void InitAdapter(IntPtr context, IntPtr architectureHandle)
+ {
+ try
+ {
+ Architecture architecture = Architecture.MustFromHandle(architectureHandle);
+ this.registeredArchitecture = architecture;
+ this.Init(architecture);
+ }
+ catch (Exception exception)
+ {
+ Core.LogError("Unhandled exception in CustomArchitecture.Init: {0}", exception);
+ }
+ }
+
+ private Endianness GetEndiannessAdapter(IntPtr context)
+ {
+ try
+ {
+ return this.GetEndianness();
+ }
+ catch (Exception exception)
+ {
+ Core.LogError(
+ "Unhandled exception in CustomArchitecture.GetEndianness: {0}",
+ exception);
+ return Endianness.LittleEndian;
+ }
+ }
+
+ private ulong GetAddressSizeAdapter(IntPtr context)
+ {
+ return this.InvokeSizeCallback(this.GetAddressSize, "GetAddressSize");
+ }
+
+ private ulong GetDefaultIntegerSizeAdapter(IntPtr context)
+ {
+ return this.InvokeSizeCallback(
+ this.GetDefaultIntegerSize,
+ "GetDefaultIntegerSize");
+ }
+
+ private ulong GetInstructionAlignmentAdapter(IntPtr context)
+ {
+ return this.InvokeSizeCallback(
+ this.GetInstructionAlignment,
+ "GetInstructionAlignment");
+ }
+
+ private ulong GetMaxInstructionLengthAdapter(IntPtr context)
+ {
+ return this.InvokeSizeCallback(
+ this.GetMaxInstructionLength,
+ "GetMaxInstructionLength");
+ }
+
+ private ulong GetOpcodeDisplayLengthAdapter(IntPtr context)
+ {
+ return this.InvokeSizeCallback(
+ this.GetOpcodeDisplayLength,
+ "GetOpcodeDisplayLength");
+ }
+
+ private ulong InvokeSizeCallback(Func callback, string callbackName)
+ {
+ try
+ {
+ return callback();
+ }
+ catch (Exception exception)
+ {
+ Core.LogError(
+ "Unhandled exception in CustomArchitecture.{0}: {1}",
+ callbackName,
+ exception);
+ return 0;
+ }
+ }
+
+ private IntPtr GetAssociatedArchitectureAdapter(
+ IntPtr context,
+ ref ulong address)
+ {
+ try
+ {
+ Architecture? architecture = this.GetAssociatedArchitectureByAddress(ref address);
+ if (null == architecture)
+ {
+ architecture = this.registeredArchitecture;
+ }
+
+ return null == architecture
+ ? IntPtr.Zero
+ : architecture.DangerousGetHandle();
+ }
+ catch (Exception exception)
+ {
+ Core.LogError(
+ "Unhandled exception in CustomArchitecture.GetAssociatedArchitectureByAddress: {0}",
+ exception);
+ return null == this.registeredArchitecture
+ ? IntPtr.Zero
+ : this.registeredArchitecture.DangerousGetHandle();
+ }
+ }
+ }
+}
diff --git a/Struct/BNCustomArchitecture.cs b/Struct/BNCustomArchitecture.cs
index 5695b85..f20076e 100644
--- a/Struct/BNCustomArchitecture.cs
+++ b/Struct/BNCustomArchitecture.cs
@@ -334,7 +334,7 @@ internal unsafe struct BNCustomArchitecture
internal IntPtr skipAndReturnValue;
}
- public abstract class CustomArchitecture
+ public abstract partial class CustomArchitecture
{
internal delegate void InitDelegate(
Architecture arch
@@ -998,4 +998,4 @@ ulong value
#endregion
}
-}
\ No newline at end of file
+}