private bool CheckParameters(Il2CppMethodDefinition method, MethodAnalysis context, bool isInstance)
        {
            var actualArgs = new List <IAnalysedOperand>();

            if (!isInstance)
            {
                actualArgs.Add(context.GetOperandInRegister("rcx") ?? context.GetOperandInRegister("xmm0"));
            }

            actualArgs.Add(context.GetOperandInRegister("rdx") ?? context.GetOperandInRegister("xmm1"));
            actualArgs.Add(context.GetOperandInRegister("r8") ?? context.GetOperandInRegister("xmm2"));
            actualArgs.Add(context.GetOperandInRegister("r9") ?? context.GetOperandInRegister("xmm3"));

            foreach (var parameterData in method.Parameters !)
            {
                if (actualArgs.Count(a => a != null) == 0)
                {
                    return(false);
                }

                var arg = actualArgs.RemoveAndReturn(0);
                switch (arg)
                {
                case ConstantDefinition cons when cons.Type.FullName != parameterData.Type.ToString():                    //Constant type mismatch
                case LocalDefinition local when !Utils.IsManagedTypeAnInstanceOfCppOne(parameterData.Type, local.Type !): //Local type mismatch
                    return(false);
                }
            }

            if (actualArgs.Any(a => a != null && !context.IsEmptyRegArg(a)))
            {
                return(false); //Left over args - it's probably not this one
            }
            return(true);
        }
        public static int GetMethodIndexFromMethod(Il2CppMethodDefinition methodDefinition)
        {
            if (LibCpp2IlMain.TheMetadata == null)
            {
                return(-1);
            }

            for (var i = 0; i < LibCpp2IlMain.TheMetadata.methodDefs.Length; i++)
            {
                if (LibCpp2IlMain.TheMetadata.methodDefs[i] == methodDefinition)
                {
                    return(i);
                }
            }

            return(-1);
        }
        public CallManagedFunctionAction(MethodAnalysis context, Instruction instruction) : base(context, instruction)
        {
            var jumpTarget = instruction.NearBranchTarget;
            var objectMethodBeingCalledOn = context.GetLocalInReg("rcx");
            var listOfCallableMethods     = LibCpp2IlMain.GetManagedMethodImplementationsAtAddress(jumpTarget);

            if (listOfCallableMethods == null)
            {
                return;
            }

            Il2CppMethodDefinition possibleTarget = null;

            if (objectMethodBeingCalledOn?.Type != null)
            {
                //Direct instance methods take priority
                possibleTarget = listOfCallableMethods.FirstOrDefault(m => !m.IsStatic && Utils.AreManagedAndCppTypesEqual(LibCpp2ILUtils.WrapType(m.DeclaringType !), objectMethodBeingCalledOn.Type) && CheckParameters(m, context, true));

                //todo check args and null out

                if (possibleTarget == null)
                {
                    //Base class instance methods
                    possibleTarget = listOfCallableMethods.FirstOrDefault(m => !m.IsStatic && Utils.IsManagedTypeAnInstanceOfCppOne(LibCpp2ILUtils.WrapType(m.DeclaringType !), objectMethodBeingCalledOn.Type) && CheckParameters(m, context, true));
                }

                //check args again.
            }

            //Check static methods
            if (possibleTarget == null)
            {
                possibleTarget = listOfCallableMethods.FirstOrDefault(m => m.IsStatic && CheckParameters(m, context, false));
            }


            if (possibleTarget != null)
            {
                target = SharedState.UnmanagedToManagedMethods[possibleTarget];
                return;
            }

            // SharedState.MethodsByAddress.TryGetValue(jumpTarget, out target);
        }
Exemple #4
0
        private static string GetModifiers(Il2CppMethodDefinition methodDef)
        {
            if (methodModifiers.TryGetValue(methodDef, out string str))
            {
                return(str);
            }
            var access = methodDef.flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK;

            switch (access)
            {
            case METHOD_ATTRIBUTE_PRIVATE:
                str += "private ";
                break;

            case METHOD_ATTRIBUTE_PUBLIC:
                str += "public ";
                break;

            case METHOD_ATTRIBUTE_FAMILY:
                str += "protected ";
                break;

            case METHOD_ATTRIBUTE_ASSEM:
            case METHOD_ATTRIBUTE_FAM_AND_ASSEM:
                str += "internal ";
                break;

            case METHOD_ATTRIBUTE_FAM_OR_ASSEM:
                str += "protected internal ";
                break;
            }
            if ((methodDef.flags & METHOD_ATTRIBUTE_STATIC) != 0)
            {
                str += "static ";
            }
            if ((methodDef.flags & METHOD_ATTRIBUTE_ABSTRACT) != 0)
            {
                str += "abstract ";
                if ((methodDef.flags & METHOD_ATTRIBUTE_VTABLE_LAYOUT_MASK) == METHOD_ATTRIBUTE_REUSE_SLOT)
                {
                    str += "override ";
                }
            }
            else if ((methodDef.flags & METHOD_ATTRIBUTE_FINAL) != 0)
            {
                if ((methodDef.flags & METHOD_ATTRIBUTE_VTABLE_LAYOUT_MASK) == METHOD_ATTRIBUTE_REUSE_SLOT)
                {
                    str += "sealed override ";
                }
            }
            else if ((methodDef.flags & METHOD_ATTRIBUTE_VIRTUAL) != 0)
            {
                if ((methodDef.flags & METHOD_ATTRIBUTE_VTABLE_LAYOUT_MASK) == METHOD_ATTRIBUTE_NEW_SLOT)
                {
                    str += "virtual ";
                }
                else
                {
                    str += "override ";
                }
            }
            if ((methodDef.flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) != 0)
            {
                str += "extern ";
            }
            methodModifiers.Add(methodDef, str);
            return(str);
        }