/// <summary>
        /// Resolve a MethodDesc to a callable method address and unboxing stub address.
        /// </summary>
        /// <param name="method">Native metadata method description object</param>
        /// <param name="methodAddress">Resolved method address</param>
        /// <param name="unboxingStubAddress">Resolved unboxing stub address</param>
        /// <returns>true when the resolution succeeded, false when not</returns>
        public static bool TryGetMethodAddressFromMethodDesc(
            MethodDesc method,
            out IntPtr methodAddress,
            out IntPtr unboxingStubAddress,
            out MethodAddressType foundAddressType)
        {
            methodAddress       = IntPtr.Zero;
            unboxingStubAddress = IntPtr.Zero;
            foundAddressType    = MethodAddressType.None;

#if SUPPORTS_R2R_LOADING
            TryGetCodeTableEntry(method, out methodAddress, out unboxingStubAddress, out foundAddressType);
#endif
#if SUPPORT_DYNAMIC_CODE
            if (foundAddressType == MethodAddressType.None)
            {
                MethodEntrypointStubs.TryGetMethodEntrypoint(method, out methodAddress, out unboxingStubAddress, out foundAddressType);
            }
#endif
            if (foundAddressType != MethodAddressType.None)
            {
                return(true);
            }

            // Otherwise try to find it via an invoke map
            return(TryGetMethodAddressFromTypeSystemMethodViaInvokeMap(method, out methodAddress, out unboxingStubAddress, out foundAddressType));
        }
Пример #2
0
        /// <summary>
        /// Resolve a MethodDesc to a callable method address and unboxing stub address by searching
        /// by searching in the InvokeMaps. This function is a wrapper around TryGetMethodInvokeDataFromInvokeMap
        /// that produces output in the format which matches the code table system.
        /// </summary>
        /// <param name="method">Native metadata method description object</param>
        /// <param name="methodAddress">Resolved method address</param>
        /// <param name="unboxingStubAddress">Resolved unboxing stub address</param>
        /// <param name="foundAddressType">Output - The type of method address match found. A canonical address may require extra parameters to call.</param>
        /// <returns>true when the resolution succeeded, false when not</returns>
        private static bool TryGetMethodAddressFromTypeSystemMethodViaInvokeMap(
            MethodDesc method,
            out IntPtr methodAddress,
            out IntPtr unboxingStubAddress,
            out MethodAddressType foundAddressType)
        {
            methodAddress       = IntPtr.Zero;
            unboxingStubAddress = IntPtr.Zero;
            foundAddressType    = MethodAddressType.None;
#if SUPPORTS_NATIVE_METADATA_TYPE_LOADING
            NativeFormatMethod nativeFormatMethod = method.GetTypicalMethodDefinition() as NativeFormatMethod;
            if (nativeFormatMethod == null)
            {
                return(false);
            }

            MethodSignatureComparer methodSignatureComparer = new MethodSignatureComparer(
                nativeFormatMethod.MetadataReader, nativeFormatMethod.Handle);

            // Try to find a specific canonical match, or if that fails, a universal match
            if (TryGetMethodInvokeDataFromInvokeMap(
                    nativeFormatMethod,
                    method,
                    ref methodSignatureComparer,
                    CanonicalFormKind.Specific,
                    out methodAddress,
                    out foundAddressType) ||

                TryGetMethodInvokeDataFromInvokeMap(
                    nativeFormatMethod,
                    method,
                    ref methodSignatureComparer,
                    CanonicalFormKind.Universal,
                    out methodAddress,
                    out foundAddressType))
            {
                if (method.OwningType.IsValueType && !method.Signature.IsStatic)
                {
                    // In this case the invoke map found an unboxing stub, and we should pull the method address out as well
                    unboxingStubAddress = methodAddress;
                    methodAddress       = RuntimeAugments.GetCodeTarget(unboxingStubAddress);

                    if (!method.HasInstantiation && ((foundAddressType != MethodAddressType.Exact) || method.OwningType.IsCanonicalSubtype(CanonicalFormKind.Any)))
                    {
                        IntPtr underlyingTarget; // unboxing and instantiating stub handling
                        if (!TypeLoaderEnvironment.TryGetTargetOfUnboxingAndInstantiatingStub(methodAddress, out underlyingTarget))
                        {
                            Environment.FailFast("Expected this to be an unboxing and instantiating stub.");
                        }
                        methodAddress = underlyingTarget;
                    }
                }

                return(true);
            }
#endif
            return(false);
        }
        /// <summary>
        /// Resolve a MethodDesc to a callable method address and unboxing stub address by searching
        /// by searching in the InvokeMaps. This function is a wrapper around TryGetMethodInvokeDataFromInvokeMap
        /// that produces output in the format which matches the code table system.
        /// </summary>
        /// <param name="method">Native metadata method description object</param>
        /// <param name="methodAddress">Resolved method address</param>
        /// <param name="unboxingStubAddress">Resolved unboxing stub address</param>
        /// <returns>true when the resolution succeeded, false when not</returns>
        private static bool TryGetMethodAddressFromTypeSystemMethodViaInvokeMap(
            MethodDesc method,
            out IntPtr methodAddress,
            out IntPtr unboxingStubAddress,
            out MethodAddressType foundAddressType)
        {
            methodAddress = IntPtr.Zero;
            unboxingStubAddress = IntPtr.Zero;
            foundAddressType = MethodAddressType.None;
#if SUPPORTS_NATIVE_METADATA_TYPE_LOADING
            NativeFormatMethod nativeFormatMethod = method.GetTypicalMethodDefinition() as NativeFormatMethod;
            if (nativeFormatMethod == null)
                return false;

            MethodSignatureComparer methodSignatureComparer = new MethodSignatureComparer(
                nativeFormatMethod.MetadataReader, nativeFormatMethod.Handle);

            // Try to find a specific canonical match, or if that fails, a universal match
            if (TryGetMethodInvokeDataFromInvokeMap(
                nativeFormatMethod,
                method,
                ref methodSignatureComparer,
                CanonicalFormKind.Specific,
                out methodAddress,
                out foundAddressType) ||

                TryGetMethodInvokeDataFromInvokeMap(
                nativeFormatMethod,
                method,
                ref methodSignatureComparer,
                CanonicalFormKind.Universal,
                out methodAddress,
                out foundAddressType))
            {
                if (method.OwningType.IsValueType && !method.Signature.IsStatic)
                {
                    // In this case the invoke map found an unboxing stub, and we should pull the method address out as well
                    unboxingStubAddress = methodAddress;
                    methodAddress = RuntimeAugments.GetCodeTarget(unboxingStubAddress);

                    if (!method.HasInstantiation && ((foundAddressType != MethodAddressType.Exact) || method.OwningType.IsCanonicalSubtype(CanonicalFormKind.Any)))
                    {
                        IntPtr underlyingTarget; // unboxing and instantiating stub handling
                        if (!TypeLoaderEnvironment.TryGetTargetOfUnboxingAndInstantiatingStub(methodAddress, out underlyingTarget))
                        {
                            Environment.FailFast("Expected this to be an unboxing and instantiating stub.");
                        }
                        methodAddress = underlyingTarget;
                    }
                }

                return true;
            }

#endif
            return false;
        }
        /// <summary>
        /// Resolve a MethodDesc to a callable method address and unboxing stub address.
        /// </summary>
        /// <param name="method">Native metadata method description object</param>
        /// <param name="methodAddress">Resolved method address</param>
        /// <param name="unboxingStubAddress">Resolved unboxing stub address</param>
        /// <returns>true when the resolution succeeded, false when not</returns>
        internal static bool TryGetMethodAddressFromMethodDesc(
            MethodDesc method,
            out IntPtr methodAddress,
            out IntPtr unboxingStubAddress,
            out MethodAddressType foundAddressType)
        {
#if SUPPORTS_R2R_LOADING
            // Try to find the method via a code table
            if (TryGetCodeTableEntry(
                    method,
                    out methodAddress,
                    out unboxingStubAddress,
                    out foundAddressType))
            {
                return(true);
            }
#endif

            // Otherwise try to find it via an invoke map
            return(TryGetMethodAddressFromTypeSystemMethodViaInvokeMap(method, out methodAddress, out unboxingStubAddress, out foundAddressType));
        }
        /// <summary>
        /// Resolve a MethodDesc to a callable method address and unboxing stub address.
        /// </summary>
        /// <param name="method">Native metadata method description object</param>
        /// <param name="methodAddress">Resolved method address</param>
        /// <param name="unboxingStubAddress">Resolved unboxing stub address</param>
        /// <returns>true when the resolution succeeded, false when not</returns>
        internal static bool TryGetMethodAddressFromMethodDesc(
            MethodDesc method,
            out IntPtr methodAddress,
            out IntPtr unboxingStubAddress,
            out MethodAddressType foundAddressType)
        {
#if SUPPORTS_R2R_LOADING
            // Try to find the method via a code table
            if (TryGetCodeTableEntry(
                method,
                out methodAddress,
                out unboxingStubAddress, 
                out foundAddressType))
            {
                return true;
            }
#endif

            // Otherwise try to find it via an invoke map
            return TryGetMethodAddressFromTypeSystemMethodViaInvokeMap(method, out methodAddress, out unboxingStubAddress, out foundAddressType);
        }