Ejemplo n.º 1
0
        private static bool IsMethodEligible(MethodInfo method)
        {
            if (method.IsGenericMethod || method.IsGenericMethodDefinition)
            {
                return(false);
            }
            if (method.Name == "Finalize")
            {
                return(false);
            }
            if (method.IsStatic || method.IsAbstract)
            {
                return(false);
            }
            if (!IsTypeSupported(method.ReturnType))
            {
                LogSupport.Warning($"Method {method} on type {method.DeclaringType} has unsupported return type {method.ReturnType}");
                return(false);
            }

            foreach (var parameter in method.GetParameters())
            {
                var parameterType = parameter.ParameterType;
                if (!IsTypeSupported(parameterType))
                {
                    LogSupport.Warning($"Method {method} on type {method.DeclaringType} has unsupported parameter {parameter} of type {parameterType}");
                    return(false);
                }
            }

            return(true);
        }
Ejemplo n.º 2
0
        private static bool IsMethodEligible(MethodInfo method)
        {
            if (method.IsGenericMethod || method.IsGenericMethodDefinition)
            {
                return(false);
            }
            if (method.Name == "Finalize")
            {
                return(false);
            }
            if (method.IsStatic || method.IsAbstract)
            {
                return(false);
            }
            if (method.CustomAttributes.Any(it => it.AttributeType == typeof(HideFromIl2CppAttribute)))
            {
                return(false);
            }

            if (
                method.DeclaringType != null &&
                method.DeclaringType.GetProperties()
                .Where(property => property.GetAccessors(true).Contains(method))
                .Any(property => property.CustomAttributes.Any(it => it.AttributeType == typeof(HideFromIl2CppAttribute)))
                )
            {
                return(false);
            }

            if (!IsTypeSupported(method.ReturnType))
            {
                LogSupport.Warning($"Method {method} on type {method.DeclaringType} has unsupported return type {method.ReturnType}");
                return(false);
            }

            foreach (var parameter in method.GetParameters())
            {
                var parameterType = parameter.ParameterType;
                if (!IsTypeSupported(parameterType))
                {
                    LogSupport.Warning($"Method {method} on type {method.DeclaringType} has unsupported parameter {parameter} of type {parameterType}");
                    return(false);
                }
            }

            return(true);
        }
        public static void GenerateInvokerMethodBody(MethodDefinition newMethod, FieldDefinition delegateField, TypeDefinition delegateType, TypeRewriteContext enclosingType, AssemblyKnownImports imports)
        {
            var body = newMethod.Body.GetILProcessor();

            body.Emit(OpCodes.Ldsfld, delegateField);
            if (newMethod.HasThis)
            {
                body.Emit(OpCodes.Ldarg_0);
                body.Emit(OpCodes.Call, imports.Il2CppObjectBaseToPointerNotNull);
            }

            var argOffset = newMethod.HasThis ? 1 : 0;

            for (var i = 0; i < newMethod.Parameters.Count; i++)
            {
                var param     = newMethod.Parameters[i];
                var paramType = param.ParameterType;
                if (paramType.IsValueType || paramType.IsByReference && paramType.GetElementType().IsValueType)
                {
                    body.Emit(OpCodes.Ldarg, i + argOffset);
                }
                else
                {
                    body.EmitObjectToPointer(param.ParameterType, param.ParameterType, enclosingType, i + argOffset, false, true, true, out var refVar);
                    if (refVar != null)
                    {
                        LogSupport.Warning($"Method {newMethod} has a reference-typed ref parameter, this will be ignored");
                    }
                }
            }

            body.Emit(OpCodes.Call, delegateType.Methods.Single(it => it.Name == "Invoke"));
            if (!newMethod.ReturnType.IsValueType)
            {
                var pointerVar = new VariableDefinition(imports.IntPtr);
                newMethod.Body.Variables.Add(pointerVar);
                body.Emit(OpCodes.Stloc, pointerVar);
                var loadInstr = body.Create(OpCodes.Ldloc, pointerVar);
                body.EmitPointerToObject(newMethod.ReturnType, newMethod.ReturnType, enclosingType, loadInstr, false, false);
            }
            body.Emit(OpCodes.Ret);
        }
Ejemplo n.º 4
0
        public static void Main(UnhollowerOptions options)
        {
            if (string.IsNullOrEmpty(options.SourceDir))
            {
                Console.WriteLine("No input dir specified; use -h for help");
                return;
            }

            if (string.IsNullOrEmpty(options.OutputDir))
            {
                Console.WriteLine("No target dir specified; use -h for help");
                return;
            }
            if (string.IsNullOrEmpty(options.MscorlibPath))
            {
                Console.WriteLine("No mscorlib specified; use -h for help");
                return;
            }

            if (!Directory.Exists(options.OutputDir))
            {
                Directory.CreateDirectory(options.OutputDir);
            }

            RewriteGlobalContext rewriteContext;

            using (new TimingCookie("Reading assemblies"))
                rewriteContext = new RewriteGlobalContext(options, Directory.EnumerateFiles(options.SourceDir, "*.dll"));

            using (new TimingCookie("Computing renames"))
                Pass05CreateRenameGroups.DoPass(rewriteContext);
            using (new TimingCookie("Creating typedefs"))
                Pass10CreateTypedefs.DoPass(rewriteContext);
            using (new TimingCookie("Computing struct blittability"))
                Pass11ComputeTypeSpecifics.DoPass(rewriteContext);
            using (new TimingCookie("Filling typedefs"))
                Pass12FillTypedefs.DoPass(rewriteContext);
            using (new TimingCookie("Filling generic constraints"))
                Pass13FillGenericConstraints.DoPass(rewriteContext);
            using (new TimingCookie("Creating members"))
                Pass15GenerateMemberContexts.DoPass(rewriteContext);
            using (new TimingCookie("Scanning method cross-references"))
                Pass16ScanMethodRefs.DoPass(rewriteContext, options);
            using (new TimingCookie("Finalizing method declarations"))
                Pass18FinalizeMethodContexts.DoPass(rewriteContext);
            LogSupport.Info($"{Pass18FinalizeMethodContexts.TotalPotentiallyDeadMethods} total potentially dead methods");
            using (new TimingCookie("Filling method parameters"))
                Pass19CopyMethodParameters.DoPass(rewriteContext);

            using (new TimingCookie("Creating static constructors"))
                Pass20GenerateStaticConstructors.DoPass(rewriteContext);
            using (new TimingCookie("Creating value type fields"))
                Pass21GenerateValueTypeFields.DoPass(rewriteContext);
            using (new TimingCookie("Creating enums"))
                Pass22GenerateEnums.DoPass(rewriteContext);
            using (new TimingCookie("Creating IntPtr constructors"))
                Pass23GeneratePointerConstructors.DoPass(rewriteContext);
            using (new TimingCookie("Creating type getters"))
                Pass24GenerateTypeStaticGetters.DoPass(rewriteContext);
            using (new TimingCookie("Creating non-blittable struct constructors"))
                Pass25GenerateNonBlittableValueTypeDefaultCtors.DoPass(rewriteContext);

            using (new TimingCookie("Creating generic method static constructors"))
                Pass30GenerateGenericMethodStoreConstructors.DoPass(rewriteContext);
            using (new TimingCookie("Creating field accessors"))
                Pass40GenerateFieldAccessors.DoPass(rewriteContext);
            using (new TimingCookie("Filling methods"))
                Pass50GenerateMethods.DoPass(rewriteContext);
            using (new TimingCookie("Generating implicit conversions"))
                Pass60AddImplicitConversions.DoPass(rewriteContext);
            using (new TimingCookie("Creating properties"))
                Pass70GenerateProperties.DoPass(rewriteContext);

            if (options.UnityBaseLibsDir != null)
            {
                using (new TimingCookie("Unstripping types"))
                    Pass79UnstripTypes.DoPass(rewriteContext);
                using (new TimingCookie("Unstripping fields"))
                    Pass80UnstripFields.DoPass(rewriteContext);
                using (new TimingCookie("Unstripping methods"))
                    Pass80UnstripMethods.DoPass(rewriteContext);
                using (new TimingCookie("Unstripping method bodies"))
                    Pass81FillUnstrippedMethodBodies.DoPass(rewriteContext);
            }
            else
            {
                LogSupport.Warning("Not performing unstripping as unity libs are not specified");
            }

            using (new TimingCookie("Generating forwarded types"))
                Pass89GenerateForwarders.DoPass(rewriteContext);

            using (new TimingCookie("Writing xref cache"))
                Pass89GenerateMethodXrefCache.DoPass(rewriteContext, options);

            using (new TimingCookie("Writing assemblies"))
                Pass90WriteToDisk.DoPass(rewriteContext, options);

            using (new TimingCookie("Writing method pointer map"))
                Pass91GenerateMethodPointerMap.DoPass(rewriteContext, options);

            if (!options.NoCopyUnhollowerLibs)
            {
                File.Copy(typeof(IL2CPP).Assembly.Location, Path.Combine(options.OutputDir, typeof(IL2CPP).Assembly.GetName().Name + ".dll"), true);
                File.Copy(typeof(RuntimeLibMarker).Assembly.Location, Path.Combine(options.OutputDir, typeof(RuntimeLibMarker).Assembly.GetName().Name + ".dll"), true);
                File.Copy(typeof(Decoder).Assembly.Location, Path.Combine(options.OutputDir, typeof(Decoder).Assembly.GetName().Name + ".dll"), true);
            }

            LogSupport.Info("Done!");

            rewriteContext.Dispose();
        }