-
-
Save rolfbjarne/1ec2d9610ef9543718c2 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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