Skip to content

Instantly share code, notes, and snippets.

@rolfbjarne
Created February 11, 2012 01:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rolfbjarne/1ec2d9610ef9543718c2 to your computer and use it in GitHub Desktop.
Save rolfbjarne/1ec2d9610ef9543718c2 to your computer and use it in GitHub Desktop.
diff --git a/src/ObjCRuntime/Class.cs b/src/ObjCRuntime/Class.cs
index ace21db..25c3d30 100644
--- a/src/ObjCRuntime/Class.cs
+++ b/src/ObjCRuntime/Class.cs
@@ -223,16 +223,83 @@ namespace MonoMac.ObjCRuntime {
RegisterMethod (minfo, ea, type, handle);
}
-
+
+ delegate int getFrameLength (IntPtr @this, IntPtr sel);
+
+ static getFrameLength getFrameLengthDelegate = Selector.GetFrameLength;
+ static IntPtr getFrameLengthPtr = Marshal.GetFunctionPointerForDelegate (getFrameLengthDelegate);
+
internal unsafe static void RegisterMethod (MethodInfo minfo, ExportAttribute ea, Type type, IntPtr handle) {
NativeMethodBuilder builder = new NativeMethodBuilder (minfo, type, ea);
- class_addMethod (minfo.IsStatic ? ((objc_class *) handle)->isa : handle, builder.Selector, builder.Delegate, builder.Signature);
+ IntPtr fptr = Marshal.GetFunctionPointerForDelegate (builder.Delegate);
+ if (minfo.ReturnType.Name == "RectangleF") {
+ var thunk_ptr = Marshal.AllocHGlobal (4096);//thunk.Length * 2);
+ var rel_fptr = new IntPtr (fptr.ToInt32 () - thunk_ptr.ToInt32 () - 0x59);
+ var rel_aptr = new IntPtr (getFrameLengthPtr.ToInt32 () - thunk_ptr.ToInt32 () - 0x29);
+ var fptr_b = BitConverter.GetBytes (rel_fptr.ToInt32 ());
+ var fptr_a = BitConverter.GetBytes (rel_aptr.ToInt32 ());
+ var thunk = new byte []
+ {
+ /*_monotouch_x86_double_abi_stret_trampoline: */
+ /*00000000 movl $0,%edx */ 0xba, 0x00, 0x00, 0x00, 0x00,
+ /*00000005 jmp 0x0000000c */ 0xeb, 0x05,
+ /*_monotouch_static_x86_double_abi_stret_trampoline:*/
+ /*00000007 movl $0x00000001,%edx */ 0xba, 0x01, 0x00, 0x00, 0x00,
+ /*0000000c pushl %ebp */ 0x55,
+ /*0000000d movl %esp,%ebp */ 0x89, 0xe5,
+ /*0000000f pushl %esi */ 0x56,
+ /*00000010 pushl %edi */ 0x57,
+ /*00000011 pushl %ebx */ 0x53,
+ /*00000012 subl $0x3c,%esp */ 0x83, 0xec, 0x3c,
+ /*00000015 movl %edx,%ebx */ 0x89, 0xd3,
+ /*00000017 movl 0x10(%ebp),%eax */ 0x8b, 0x45, 0x10,
+ /*0000001a movl %eax,0x04(%esp) */ 0x89, 0x44, 0x24, 0x04,
+ /*0000001e movl 0x0c(%ebp),%eax */ 0x8b, 0x45, 0x0c,
+ /*00000021 movl %eax,(%esp) */ 0x89, 0x04, 0x24,
+ /*00000024 calll _get_frame_length */ 0xe8, fptr_a [0], fptr_a [1], fptr_a [2], fptr_a [3],
+ /*00000029 movl %eax,0xf0(%ebp) */ 0x89, 0x45, 0xf0,
+ /*0000002c addl $0x0f,%eax */ 0x83, 0xc0, 0x0f,
+ /*0000002f shrl $0x04,%eax */ 0xc1, 0xe8, 0x04,
+ /*00000032 shll $0x04,%eax */ 0xc1, 0xe0, 0x04,
+ /*00000035 subl %eax,%esp */ 0x29, 0xc4,
+ /*00000037 movl 0xf0(%ebp),%ecx */ 0x8b, 0x4d, 0xf0,
+ /*0000003a leal 0x08(%ebp),%esi */ 0x8d, 0x75, 0x08,
+ /*0000003d movl %esp,%edi */ 0x89, 0xe7,
+ /*0000003f cmpl $0,%ecx */ 0x83, 0xf9, 0x00,
+ /*00000042 je 0x0000004f */ 0x74, 0x0b,
+ /*00000044 subl $0x04,%ecx */ 0x83, 0xe9, 0x04,
+ /*00000047 movl (%esi,%ecx),%eax */ 0x8b, 0x04, 0x0e,
+ /*0000004a movl %eax,(%edi,%ecx) */ 0x89, 0x04, 0x0f,
+ /*0000004d jmp 0x0000003f */ 0xeb, 0xf0,
+ /*0000004f cmpl $0,%ebx */ 0x83, 0xfb, 0x00,
+ /*00000052 jne 0x0000005b */ 0x75, 0x07,
+ /*00000054 calll _monotouch_stret_trampoline */ 0xe8, fptr_b [0], fptr_b [1], fptr_b [2], fptr_b [3],
+ /*00000059 jmp 0x00000060 */ 0xeb, 0x05,
+ /*0000005b calll _monotouch_static_stret_trampoline*/ 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, // NOT USED, NEED TO REMOVE
+ /*00000060 movl 0xf4(%ebp),%ebx */ 0x8b, 0x5d, 0xf4,
+ /*00000063 movl 0xf8(%ebp),%edi */ 0x8b, 0x7d, 0xf8,
+ /*00000066 movl 0xfc(%ebp),%esi */ 0x8b, 0x75, 0xfc,
+ /*00000069 leave */ 0xc9,
+ /*0000006a retl $0x0004 */ 0xc2, 0x04, 0x00,
+ };
+
+ int rv = mprotect (thunk_ptr, 4096, 7 /* EXEC|READ|WRITE */);
+
+ Marshal.Copy (thunk, 0, thunk_ptr, thunk.Length);
+ Console.WriteLine ("patching!!! {0} {1} ({2}) new fptr: 0x{3} old fptr: 0x{4} rv: {5}", minfo.DeclaringType.FullName, minfo.Name, minfo.GetParameters ().Length, thunk_ptr.ToString ("X"), fptr.ToString ("X"), rv);
+ fptr = thunk_ptr;
+ }
+
+ class_addMethod (minfo.IsStatic ? ((objc_class *) handle)->isa : handle, builder.Selector, fptr, builder.Signature);
method_wrappers.Add (builder.Delegate);
#if DEBUG
Console.WriteLine ("[METHOD] Registering {0}[0x{1:x}|{2}] on {3} -> ({4})", ea.Selector, (int) builder.Selector, builder.Signature, type, minfo);
#endif
}
+
+ [DllImportAttribute("libc")]
+ extern static int mprotect (IntPtr addr, int len, int prot);
[DllImport ("/usr/lib/libobjc.dylib")]
extern static IntPtr objc_allocateClassPair (IntPtr superclass, string name, IntPtr extraBytes);
@@ -247,6 +314,8 @@ namespace MonoMac.ObjCRuntime {
[DllImport ("/usr/lib/libobjc.dylib")]
extern static bool class_addMethod (IntPtr cls, IntPtr name, Delegate imp, string types);
[DllImport ("/usr/lib/libobjc.dylib")]
+ extern static bool class_addMethod (IntPtr cls, IntPtr name, IntPtr imp, string types);
+ [DllImport ("/usr/lib/libobjc.dylib")]
extern static IntPtr class_getName (IntPtr cls);
[DllImport ("/usr/lib/libobjc.dylib")]
extern static IntPtr class_getSuperclass (IntPtr cls);
diff --git a/src/ObjCRuntime/Messaging.cs b/src/ObjCRuntime/Messaging.cs
index ac5c5ce..e73cb20 100644
--- a/src/ObjCRuntime/Messaging.cs
+++ b/src/ObjCRuntime/Messaging.cs
@@ -33,6 +33,9 @@ namespace MonoMac.ObjCRuntime {
[DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")]
public extern static uint uint_objc_msgSend (IntPtr receiver, IntPtr selector);
+
+ [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")]
+ public extern static int int_objc_msgSend (IntPtr receiver, IntPtr selector);
/* void returns */
[DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")]
@@ -97,6 +100,8 @@ namespace MonoMac.ObjCRuntime {
/* intptr returns */
[DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")]
+ public extern static IntPtr IntPtr_objc_msgSend_IntPtr (IntPtr receiver, IntPtr selector, IntPtr arg1);
+ [DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")]
public extern static IntPtr intptr_objc_msgSend (IntPtr receiver, IntPtr selector);
[DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")]
public extern static IntPtr intptr_objc_msgSend_intptr (IntPtr receiver, IntPtr selector, IntPtr arg1);
diff --git a/src/ObjCRuntime/Selector.cs b/src/ObjCRuntime/Selector.cs
index c3fe06b..f471bea 100644
--- a/src/ObjCRuntime/Selector.cs
+++ b/src/ObjCRuntime/Selector.cs
@@ -28,6 +28,8 @@ namespace MonoMac.ObjCRuntime {
public class Selector {
public static IntPtr Init = Selector.GetHandle ("init");
public static IntPtr InitWithCoder = Selector.GetHandle ("initWithCoder:");
+ public static IntPtr MethodSignatureForSelector = Selector.GetHandle ("methodSignatureForSelector:");
+ public static IntPtr FrameLength = Selector.GetHandle ("frameLength");
internal static IntPtr Alloc = Selector.GetHandle ("alloc");
internal IntPtr handle;
@@ -53,6 +55,19 @@ namespace MonoMac.ObjCRuntime {
public Selector (string name) : this (name, false) {}
+ public static int GetFrameLength (IntPtr @this, IntPtr sel)
+ {
+ // NSMethodSignature *sig = [this methodSignatureForSelector: sel];
+ Console.WriteLine ("GetFrameLength ({0}, {1})", @this, sel);
+ IntPtr sig = Messaging.IntPtr_objc_msgSend_IntPtr (@this, MethodSignatureForSelector, sel);
+ Console.WriteLine ("GetFrameLength ({0}, {1}) sig: {2}", @this, sel, sig);
+ // return [sig frameLength];
+ int rv = Messaging.int_objc_msgSend (sig, FrameLength);
+ Console.WriteLine ("GetFrameLength ({0}, {1}) rv: {2}", @this, sel, rv);
+ return rv;
+
+ }
+
public IntPtr Handle {
get { return handle; }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment