Beispiel #1
0
        static unsafe MonoObject *CreateArray(MonoObject *typeobj, ulong elements)
        {
            var type = (Type)GetMonoObjectTarget(typeobj);
            var obj  = Array.CreateInstance(type, (int)elements);

            return((MonoObject *)GetMonoObject(obj));
        }
Beispiel #2
0
        static unsafe MonoObject *GetNullableElementType(MonoObject *typeobj)
        {
            var type        = (Type)GetMonoObjectTarget(typeobj);
            var elementType = type.GetGenericArguments() [0];

            return((MonoObject *)GetMonoObject(elementType));
        }
Beispiel #3
0
        static unsafe void SetPendingException(MonoObject *exception_obj)
        {
            var exc = (Exception)GetMonoObjectTarget(exception_obj);

            log_coreclr($"Runtime.SetPendingException ({exc})");
            ObjectiveCMarshal.SetMessageSendPendingException(exc);
        }
Beispiel #4
0
        static unsafe void SetArrayObjectValue(MonoObject *arrayobj, ulong index, MonoObject *mobj)
        {
            var array = (Array)GetMonoObjectTarget(arrayobj);
            var obj   = GetMonoObjectTarget(mobj);

            array.SetValue(obj, (long)index);
        }
Beispiel #5
0
        static unsafe MonoObject *GetArrayObjectValue(MonoObject *arrayobj, ulong index)
        {
            var array = (Array)GetMonoObjectTarget(arrayobj);
            var obj   = array.GetValue((long)index);

            return((MonoObject *)GetMonoObject(obj));
        }
Beispiel #6
0
        static unsafe MonoObject *Box(MonoObject *typeobj, IntPtr value)
        {
            var type = (Type)GetMonoObjectTarget(typeobj);
            var rv   = Box(type, value);

            return((MonoObject *)GetMonoObject(rv));
        }
Beispiel #7
0
        static unsafe void MonoHashTableInsert(MonoObject *tableobj, IntPtr key, MonoObject *valueobj)
        {
            var table = (MonoHashTable)GetMonoObjectTarget(tableobj);
            var value = GetMonoObjectTarget(valueobj);

            table.Insert(key, value);
        }
Beispiel #8
0
        unsafe static IntPtr ClassGetName(MonoObject *typeobj)
        {
            var type = (Type)GetMonoObjectTarget(typeobj);
            var rv   = type.Name;

            return(Marshal.StringToHGlobalAuto(rv));
        }
Beispiel #9
0
        unsafe static bool IsDelegate(MonoObject *typeobj)
        {
            var type = (Type)GetMonoObjectTarget(typeobj);
            var rv   = typeof(MulticastDelegate).IsAssignableFrom(type);

            log_coreclr($"IsDelegate ({type.FullName}) => {rv}");
            return(rv);
        }
Beispiel #10
0
        static unsafe MonoObject *InvokeMethod(MonoObject *methodobj, MonoObject *instanceobj, IntPtr native_parameters)
        {
            var method   = (MethodBase)GetMonoObjectTarget(methodobj);
            var instance = GetMonoObjectTarget(instanceobj);
            var rv       = InvokeMethod(method, instance, native_parameters);

            return((MonoObject *)GetMonoObject(rv));
        }
Beispiel #11
0
        static unsafe void SetArrayStructValue(MonoObject *arrayobj, ulong index, MonoObject *typeobj, IntPtr valueptr)
        {
            var array       = (Array)GetMonoObjectTarget(arrayobj);
            var elementType = (Type)GetMonoObjectTarget(typeobj);
            var obj         = Box(elementType, valueptr);

            array.SetValue(obj, (long)index);
        }
Beispiel #12
0
        // This should work like mono_class_from_mono_type.
        static unsafe MonoObject *TypeToClass(MonoObject *typeobj)
        {
            var type = (Type)GetMonoObjectTarget(typeobj);

            if (type.IsByRef)
            {
                type = type.GetElementType();
            }
            return((MonoObject *)GetMonoObject(type));
        }
Beispiel #13
0
        static object GetMonoObjectTarget(MonoObjectPtr mobj)
        {
            if (mobj == IntPtr.Zero)
            {
                return(null);
            }

            unsafe {
                MonoObject *monoobj = (MonoObject *)mobj;
                return(GetGCHandleTarget(monoobj->GCHandle));
            }
        }
Beispiel #14
0
        unsafe static void GCReferenceQueueAdd(MonoObject *mqueue, MonoObject *mobj, IntPtr user_data)
        {
            var queue = (ReferenceQueue)GetMonoObjectTarget(mqueue);
            var obj   = GetMonoObjectTarget(mobj);
            var entry = new ReferenceQueueEntry()
            {
                Queue    = queue,
                UserData = user_data,
            };

            queue.Table.Add(obj, entry);
        }
Beispiel #15
0
        static unsafe IntPtr GetMethodSignature(MonoObject *methodobj)
        {
            var method         = (MethodBase)GetMonoObjectTarget(methodobj);
            var parameters     = method.GetParameters();
            var parameterCount = parameters.Length;
            var rv             = Marshal.AllocHGlobal(sizeof(MonoMethodSignature) + sizeof(MonoObjectPtr) * parameterCount);

            MonoMethodSignature *signature = (MonoMethodSignature *)rv;

            signature->Method = methodobj;
            xamarin_mono_object_retain(methodobj);
            signature->ParameterCount = parameterCount;
            signature->ReturnType     = (MonoObject *)GetMonoObject(GetMethodReturnType(method));

            MonoObject **mparams = &signature->Parameters;

            for (var i = 0; i < parameterCount; i++)
            {
                var p = parameters [i];
                mparams [i] = (MonoObject *)GetMonoObject(p.ParameterType);
            }

            return(rv);
        }
Beispiel #16
0
        static unsafe MonoObject *GetEnumBaseType(MonoObject *typeobj)
        {
            var type = (Type)GetMonoObjectTarget(typeobj);

            return((MonoObject *)GetMonoObject(GetEnumBaseType(type)));
        }
Beispiel #17
0
        unsafe static bool IsEnum(MonoObject *typeobj)
        {
            var type = (Type)GetMonoObjectTarget(typeobj);

            return(type.IsEnum);
        }
Beispiel #18
0
 static unsafe bool IsNullable(MonoObject *type)
 {
     return(IsNullable((Type)GetMonoObjectTarget(type)));
 }
Beispiel #19
0
        static unsafe MonoObject *MonoHashTableLookup(MonoObject *tableobj, IntPtr key)
        {
            var dict = (MonoHashTable)GetMonoObjectTarget(tableobj);

            return((MonoObject *)GetMonoObject(dict.Lookup(key)));
        }
Beispiel #20
0
 static unsafe IntPtr GetMethodFullName(MonoObject *mobj)
 {
     return(Marshal.StringToHGlobalAuto(GetMethodFullName((MethodBase)GetMonoObjectTarget(mobj))));
 }
Beispiel #21
0
 unsafe static extern void xamarin_mono_object_retain(MonoObject *mono_object);
Beispiel #22
0
 unsafe static bool IsClassOfType(MonoObject *typeobj, TypeLookup match)
 {
     return(IsClassOfType((Type)GetMonoObjectTarget(typeobj), match));
 }
Beispiel #23
0
        static unsafe ulong GetArrayLength(MonoObject *obj)
        {
            var array = (Array)GetMonoObjectTarget(obj);

            return((ulong)array.Length);
        }
Beispiel #24
0
        static unsafe MonoObject *GetElementClass(MonoObject *classobj)
        {
            var type = (Type)GetMonoObjectTarget(classobj);

            return((MonoObject *)GetMonoObject(type.GetElementType()));
        }
Beispiel #25
0
        static unsafe IntPtr StringToUtf8(MonoObject *obj)
        {
            var str = (string)GetMonoObjectTarget(obj);

            return(Marshal.StringToHGlobalAuto(str));
        }
Beispiel #26
0
        // Return value: NULL or a MonoObject* that must be released with xamarin_mono_object_safe_release.
        // Any MonoObject* ref parameters must also be retained and must be released with xamarin_mono_object_release.
        static object InvokeMethod(MethodBase method, object instance, IntPtr native_parameters)
        {
            var methodParameters = method.GetParameters();
            var parameters       = new object [methodParameters.Length];
            var inputParameters  = new object [methodParameters.Length];
            var nativeParameters = new IntPtr [methodParameters.Length];

            // Copy native array of void* to managed array of IntPtr to make the subsequent code simpler.
            unsafe {
                IntPtr *nativeParams = (IntPtr *)native_parameters;
                for (var i = 0; i < methodParameters.Length; i++)
                {
                    nativeParameters [i] = nativeParams [i];
                }
            }

            // Log our input
            log_coreclr($"InvokeMethod ({method.DeclaringType.FullName}::{method}, {instance}, 0x{native_parameters.ToString ("x")})");
            for (var i = 0; i < methodParameters.Length; i++)
            {
                var nativeParam = nativeParameters [i];
                var p           = methodParameters [i];
                var paramType   = p.ParameterType;
                if (paramType.IsByRef)
                {
                    paramType = paramType.GetElementType();
                }
                log_coreclr($"    Argument #{i + 1}: Type = {p.ParameterType.FullName} IsByRef: {p.ParameterType.IsByRef} IsOut: {p.IsOut} IsClass: {paramType.IsClass} IsInterface: {paramType.IsInterface} NativeParameter: 0x{nativeParam.ToString ("x")}");
            }

            // Process the arguments, and convert to what MethodBase.Invoke expects
            for (var i = 0; i < methodParameters.Length; i++)
            {
                var nativeParam = nativeParameters [i];
                var p           = methodParameters [i];
                var paramType   = p.ParameterType;
                var isByRef     = paramType.IsByRef;
                if (isByRef)
                {
                    paramType = paramType.GetElementType();
                }
                log_coreclr($"    Marshalling #{i + 1}: IntPtr => 0x{nativeParam.ToString ("x")} => {p.ParameterType.FullName} [...]");

                if (paramType == typeof(IntPtr))
                {
                    log_coreclr($"        IntPtr");
                    if (isByRef)
                    {
                        if (p.IsOut)
                        {
                            parameters [i] = Marshal.AllocHGlobal(IntPtr.Size);
                        }
                        else
                        {
                            parameters [i] = nativeParam == IntPtr.Zero ? IntPtr.Zero : Marshal.ReadIntPtr(nativeParam);
                        }
                    }
                    else
                    {
                        parameters [i] = nativeParam == IntPtr.Zero ? IntPtr.Zero : Marshal.ReadIntPtr(nativeParam);
                    }
                    log_coreclr($"            => 0x{((IntPtr) parameters [i]).ToString ("x")}");
                }
                else if (paramType.IsClass || paramType.IsInterface || (paramType.IsValueType && IsNullable(paramType)))
                {
                    log_coreclr($"        IsClass/IsInterface/IsNullable IsByRef: {isByRef} IsOut: {p.IsOut} ParameterType: {paramType}");
                    if (nativeParam != IntPtr.Zero)
                    {
                        unsafe {
                            MonoObject *mono_obj = (MonoObject *)nativeParam;
                            // dereference if it's a byref type
                            if (isByRef)
                            {
                                mono_obj = *(MonoObject **)mono_obj;
                            }
                            // get the object
                            parameters [i] = GetMonoObjectTarget(mono_obj);
                        }
                    }
                    log_coreclr($"            => {(parameters [i] == null ? "<null>" : parameters [i].GetType ().FullName)}");
                }
                else if (paramType.IsValueType)
                {
                    log_coreclr($"        IsValueType IsByRef: {isByRef} IsOut: {p.IsOut} nativeParam: 0x{nativeParam.ToString ("x")} ParameterType: {paramType}");
                    if (nativeParam != IntPtr.Zero)
                    {
                        // We need to unwrap nullable types and enum types to their underlying struct type.
                        var  structType = paramType;
                        Type enumType   = null;
                        if (IsNullable(structType))
                        {
                            structType = Nullable.GetUnderlyingType(structType);
                        }
                        if (structType.IsEnum)
                        {
                            enumType   = structType;
                            structType = Enum.GetUnderlyingType(structType);
                        }
                        // convert the pointer to the corresponding structure
                        var vt = PtrToStructure(nativeParam, structType);
                        // convert the structure to the enum type if that's what we need
                        if (enumType != null)
                        {
                            vt = Enum.ToObject(enumType, vt);
                        }
                        parameters [i] = vt;
                    }
                    log_coreclr($"            => {(parameters [i] == null ? "<null>" : parameters [i].ToString ())}");
                }
                else
                {
                    throw ErrorHelper.CreateError(8037, Errors.MX8037 /* Don't know how to marshal the parameter of type {p.ParameterType.FullName} for parameter {p.Name} in call to {method} */, p.ParameterType.FullName, p.Name, method);
                }
            }

            // Make a copy of the array of parameters, so that we can figure out if there were any ref parameters that the method modified.
            parameters.CopyTo(inputParameters, 0);

            // Call the actual method
            log_coreclr($"    Invoking...");

            object rv = null;

            try {
                rv = method.Invoke(instance, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance, null, parameters, null);
            } catch (TargetInvocationException tie) {
                var ex = tie.InnerException ?? tie;
                // This will re-throw the original exception and preserve the stacktrace.
                ExceptionDispatchInfo.Capture(ex).Throw();
            }

            // Copy any byref parameters back out again
            var byrefParameterCount = 0;

            for (var i = 0; i < methodParameters.Length; i++)
            {
                var p = methodParameters [i];
                if (!p.IsOut && !p.ParameterType.IsByRef)
                {
                    continue;
                }

                byrefParameterCount++;

                log_coreclr($"    Marshalling #{i + 1} back (Type: {p.ParameterType.FullName}) value: {(parameters [i] == null ? "<null>" : parameters [i].GetType ().FullName)}");

                var parameterType = p.ParameterType.GetElementType();
                var isMonoObject  = parameterType.IsClass || parameterType.IsInterface || (parameterType.IsValueType && IsNullable(parameterType));

                var nativeParam = nativeParameters [i];

                if (nativeParam == IntPtr.Zero)
                {
                    log_coreclr($"    No output pointer was provided.");
                    continue;
                }

                if (parameters [i] == inputParameters [i])
                {
                    log_coreclr($"        The argument didn't change, no marshalling required");
                    if (parameters [i] != null && parameterType != typeof(IntPtr) && isMonoObject)
                    {
                        // byref parameters must be retained
                        xamarin_mono_object_retain(Marshal.ReadIntPtr(nativeParam));
                    }
                    continue;
                }

                if (parameterType == typeof(IntPtr))
                {
                    Marshal.WriteIntPtr(nativeParam, (IntPtr)parameters [i]);
                    log_coreclr($"        IntPtr: 0x{((IntPtr) parameters [i]).ToString ("x")} => Type: {parameters [i]?.GetType ()} nativeParam: 0x{nativeParam.ToString ("x")}");
                }
                else if (isMonoObject)
                {
                    var ptr = GetMonoObject(parameters [i]);
                    Marshal.WriteIntPtr(nativeParam, ptr);
                    log_coreclr($"        IsClass/IsInterface/IsNullable: {(parameters [i] == null ? "<null>" : parameters [i].GetType ().FullName)}  nativeParam: 0x{nativeParam.ToString ("x")} -> MonoObject: 0x{ptr.ToString ("x")}");
                }
                else if (parameterType.IsValueType)
                {
                    StructureToPtr(parameters [i], nativeParam);
                    log_coreclr($"        IsValueType: {(parameters [i] == null ? "<null>" : parameters [i].ToString ())} nativeParam: 0x{nativeParam.ToString ("x")}");
                }
                else
                {
                    throw ErrorHelper.CreateError(8038, Errors.MX8038 /* Don't know how to marshal back the parameter of type {p.ParameterType.FullName} for parameter {p.Name} in call to {method} */, p.ParameterType.FullName, p.Name, method);
                }
            }

            // we're done!
            log_coreclr($"    Invoke complete with {byrefParameterCount} ref parameters and return value of type {rv?.GetType ()}");

            return(rv);
        }
Beispiel #27
0
 static unsafe object GetMonoObjectTarget(MonoObject *mobj)
 {
     return(GetMonoObjectTarget((IntPtr)mobj));
 }
Beispiel #28
0
        static unsafe int SizeOf(MonoObject *typeobj)
        {
            var type = (Type)GetMonoObjectTarget(typeobj);

            return(SizeOf(type));
        }
Beispiel #29
0
        static unsafe MonoObject *GetMethodDeclaringType(MonoObject *mobj)
        {
            var method = (MethodBase)GetMonoObjectTarget(mobj);

            return((MonoObject *)GetMonoObject(method.DeclaringType));
        }