예제 #1
0
        public EventInfo(Il2CppInspector pkg, int eventIndex, TypeInfo declaringType) :
            base(declaringType)
        {
            Definition = pkg.Metadata.Events[eventIndex];
            Index      = eventIndex;
            Name       = pkg.Strings[Definition.nameIndex];

            eventType = pkg.TypeUsages[Definition.typeIndex];
            if ((eventType.attrs & Il2CppConstants.FIELD_ATTRIBUTE_SPECIAL_NAME) == Il2CppConstants.FIELD_ATTRIBUTE_SPECIAL_NAME)
            {
                Attributes |= EventAttributes.SpecialName;
            }

            // NOTE: This relies on methods being added to TypeInfo.DeclaredMethods in the same order they are defined in the Il2Cpp metadata
            // add, remove and raise are method indices from the first method of the declaring type
            if (Definition.add >= 0)
            {
                AddMethod = declaringType.DeclaredMethods[Definition.add];
            }
            if (Definition.remove >= 0)
            {
                RemoveMethod = declaringType.DeclaredMethods[Definition.remove];
            }
            if (Definition.raise >= 0)
            {
                RaiseMethod = declaringType.DeclaredMethods[Definition.raise];
            }
        }
예제 #2
0
        public FieldInfo(Il2CppInspector pkg, int fieldIndex, TypeInfo declaringType) :
            base(declaringType)
        {
            Definition    = pkg.Fields[fieldIndex];
            MetadataToken = (int)Definition.token;
            Index         = fieldIndex;
            Name          = pkg.Strings[Definition.nameIndex];

            rawOffset = pkg.FieldOffsets[fieldIndex];

            rootDefinition = this;

            fieldTypeReference = TypeRef.FromReferenceIndex(Assembly.Model, Definition.typeIndex);
            var fieldType = pkg.TypeReferences[Definition.typeIndex];

            // Copy attributes
            Attributes = (FieldAttributes)fieldType.attrs;

            // Default initialization value if present
            if (pkg.FieldDefaultValue.TryGetValue(fieldIndex, out (ulong address, object variant)value))
            {
                DefaultValue = value.variant;
                DefaultValueMetadataAddress = value.address;
            }
        }
예제 #3
0
        public EventInfo(Il2CppInspector pkg, int eventIndex, TypeInfo declaringType) :
            base(declaringType)
        {
            Definition     = pkg.Events[eventIndex];
            Index          = eventIndex;
            Name           = pkg.Strings[Definition.nameIndex];
            rootDefinition = this;

            eventTypeReference = TypeRef.FromReferenceIndex(Assembly.Model, Definition.typeIndex);
            var eventType = pkg.TypeReferences[Definition.typeIndex];

            if ((eventType.attrs & Il2CppConstants.FIELD_ATTRIBUTE_SPECIAL_NAME) == Il2CppConstants.FIELD_ATTRIBUTE_SPECIAL_NAME)
            {
                Attributes |= EventAttributes.SpecialName;
            }

            // NOTE: This relies on methods being added to TypeInfo.DeclaredMethods in the same order they are defined in the Il2Cpp metadata
            // add, remove and raise are method indices from the first method of the declaring type
            if (Definition.add >= 0)
            {
                AddMethod = declaringType.DeclaredMethods.First(x => x.Index == declaringType.Definition.methodStart + Definition.add);
            }
            if (Definition.remove >= 0)
            {
                RemoveMethod = declaringType.DeclaredMethods.First(x => x.Index == declaringType.Definition.methodStart + Definition.remove);
            }
            if (Definition.raise >= 0)
            {
                RaiseMethod = declaringType.DeclaredMethods.First(x => x.Index == declaringType.Definition.methodStart + Definition.raise);
            }
        }
예제 #4
0
        public static MetadataUsage FromEncodedIndex(Il2CppInspector package, uint encodedIndex, ulong virtualAddress = 0)
        {
            uint index;
            MetadataUsageType usageType;

            if (package.Version < 19)
            {
                /* These encoded indices appear only in vtables, and are decoded by IsGenericMethodIndex/GetDecodedMethodIndex */
                var isGeneric = encodedIndex & 0x80000000;
                index     = package.Binary.VTableMethodReferences[encodedIndex & 0x7FFFFFFF];
                usageType = (isGeneric != 0) ? MetadataUsageType.MethodRef : MetadataUsageType.MethodDef;
            }
            else
            {
                /* These encoded indices appear in metadata usages, and are decoded by GetEncodedIndexType/GetDecodedMethodIndex */
                var encodedType = encodedIndex & 0xE0000000;
                usageType = (MetadataUsageType)(encodedType >> 29);
                index     = encodedIndex & 0x1FFFFFFF;

                // From v27 the bottom bit is set to indicate the usage token hasn't been replaced with a pointer at runtime yet
                if (package.Version >= 27)
                {
                    index >>= 1;
                }
            }
            return(new MetadataUsage(usageType, (int)index, virtualAddress));
        }
예제 #5
0
        public EventInfo(Il2CppInspector pkg, int eventIndex, TypeInfo declaringType) :
            base(declaringType)
        {
            Definition     = pkg.Events[eventIndex];
            MetadataToken  = (int)Definition.token;
            Index          = eventIndex;
            Name           = pkg.Strings[Definition.nameIndex];
            rootDefinition = this;

            eventTypeReference = TypeRef.FromReferenceIndex(Assembly.Model, Definition.typeIndex);
            var eventType = pkg.TypeReferences[Definition.typeIndex];

            // Copy attributes
            Attributes = (EventAttributes)eventType.attrs;

            // NOTE: This relies on methods being added to TypeInfo.DeclaredMethods in the same order they are defined in the Il2Cpp metadata
            // add, remove and raise are method indices from the first method of the declaring type
            if (Definition.add >= 0)
            {
                AddMethod = declaringType.DeclaredMethods.First(x => x.Index == declaringType.Definition.methodStart + Definition.add);
            }
            if (Definition.remove >= 0)
            {
                RemoveMethod = declaringType.DeclaredMethods.First(x => x.Index == declaringType.Definition.methodStart + Definition.remove);
            }
            if (Definition.raise >= 0)
            {
                RaiseMethod = declaringType.DeclaredMethods.First(x => x.Index == declaringType.Definition.methodStart + Definition.raise);
            }
        }
예제 #6
0
        public Il2CppReflector(Il2CppInspector package)
        {
            Package = package;

            // Create Assembly objects from Il2Cpp package
            for (var image = 0; image < package.Metadata.Images.Length; image++)
            {
                Assemblies.Add(new Assembly(this, image));
            }
        }
예제 #7
0
        public Il2CppModel(Il2CppInspector package)
        {
            Package = package;
            TypesByDefinitionIndex   = new TypeInfo[package.TypeDefinitions.Length];
            TypesByUsageIndex        = new TypeInfo[package.TypeUsages.Count];
            MethodsByDefinitionIndex = new MethodBase[package.Methods.Length];

            // Create Assembly objects from Il2Cpp package
            for (var image = 0; image < package.Images.Length; image++)
            {
                Assemblies.Add(new Assembly(this, image));
            }
        }
예제 #8
0
        public PropertyInfo(Il2CppInspector pkg, int propIndex, TypeInfo declaringType) :
            base(declaringType)
        {
            Index      = propIndex;
            Definition = pkg.Properties[propIndex];
            Name       = pkg.Strings[Definition.nameIndex];

            // prop.get and prop.set are method indices from the first method of the declaring type
            if (Definition.get >= 0)
            {
                GetMethod = declaringType.DeclaredMethods.First(x => x.Index == declaringType.Definition.methodStart + Definition.get);
            }
            if (Definition.set >= 0)
            {
                SetMethod = declaringType.DeclaredMethods.First(x => x.Index == declaringType.Definition.methodStart + Definition.set);
            }
        }
예제 #9
0
        public PropertyInfo(Il2CppInspector pkg, int propIndex, TypeInfo declaringType) :
            base(declaringType)
        {
            var prop = pkg.Metadata.Properties[propIndex];

            Name = pkg.Strings[prop.nameIndex];

            // NOTE: This relies on methods being added to TypeInfo.DeclaredMethods in the same order they are defined in the Il2Cpp metadata
            // prop.get and prop.set are method indices from the first method of the declaring type
            if (prop.get >= 0)
            {
                GetMethod = declaringType.DeclaredMethods[prop.get];
            }
            if (prop.set >= 0)
            {
                SetMethod = declaringType.DeclaredMethods[prop.set];
            }
        }
예제 #10
0
        public static MetadataUsage FromEncodedIndex(Il2CppInspector package, uint encodedIndex)
        {
            uint index;
            MetadataUsageType usageType;

            if (package.Version < 19)
            {
                /* These encoded indices appear only in vtables, and are decoded by IsGenericMethodIndex/GetDecodedMethodIndex */
                var isGeneric = encodedIndex & 0x80000000;
                index     = package.Binary.VTableMethodReferences[encodedIndex & 0x7FFFFFFF];
                usageType = (isGeneric != 0) ? MetadataUsageType.MethodRef : MetadataUsageType.MethodDef;
            }
            else
            {
                /* These encoded indices appear in metadata usages, and are decoded by GetEncodedIndexType/GetDecodedMethodIndex */
                var encodedType = encodedIndex & 0xE0000000;
                usageType = (MetadataUsageType)(encodedType >> 29);
                index     = encodedIndex & 0x1FFFFFFF;
            }
            return(new MetadataUsage(usageType, (int)index));
        }
예제 #11
0
        public PropertyInfo(Il2CppInspector pkg, int propIndex, TypeInfo declaringType) :
            base(declaringType)
        {
            Index          = propIndex;
            Definition     = pkg.Properties[propIndex];
            MetadataToken  = (int)Definition.token;
            Name           = pkg.Strings[Definition.nameIndex];
            rootDefinition = this;

            // Copy attributes
            Attributes = (PropertyAttributes)Definition.attrs;

            // prop.get and prop.set are method indices from the first method of the declaring type
            if (Definition.get >= 0)
            {
                GetMethod = declaringType.DeclaredMethods.First(x => x.Index == declaringType.Definition.methodStart + Definition.get);
            }
            if (Definition.set >= 0)
            {
                SetMethod = declaringType.DeclaredMethods.First(x => x.Index == declaringType.Definition.methodStart + Definition.set);
            }
        }
예제 #12
0
        // Create a parameter. Specify paramIndex == -1 for a return type parameter
        public ParameterInfo(Il2CppInspector pkg, int paramIndex, MethodBase declaringMethod)
        {
            Index           = paramIndex;
            DeclaringMethod = declaringMethod;

            if (paramIndex == -1)
            {
                Position           = -1;
                paramTypeReference = TypeRef.FromReferenceIndex(declaringMethod.Assembly.Model, declaringMethod.Definition.returnType);
                Attributes        |= ParameterAttributes.Retval;
                return;
            }

            Definition     = pkg.Params[Index];
            MetadataToken  = (int)Definition.token;
            Name           = pkg.Strings[Definition.nameIndex];
            rootDefinition = this;

            // Handle unnamed/obfuscated parameter names
            if (string.IsNullOrEmpty(Name))
            {
                Name = string.Format($"param_{Index:x8}");
            }

            Position           = paramIndex - declaringMethod.Definition.parameterStart;
            paramTypeReference = TypeRef.FromReferenceIndex(declaringMethod.Assembly.Model, Definition.typeIndex);

            var paramType = pkg.TypeReferences[Definition.typeIndex];

            // Copy attributes
            Attributes = (ParameterAttributes)paramType.attrs;

            // Default initialization value if present
            if (pkg.ParameterDefaultValue.TryGetValue(paramIndex, out (ulong address, object variant)value))
            {
                DefaultValue = value.variant;
                DefaultValueMetadataAddress = value.address;
            }
        }
예제 #13
0
        // Create a parameter. Specify paramIndex == -1 for a return type parameter
        public ParameterInfo(Il2CppInspector pkg, int paramIndex, MethodInfo declaringMethod)
        {
            Member = declaringMethod;

            if (paramIndex == -1)
            {
                Position    = -1;
                paramType   = pkg.TypeUsages[declaringMethod.Definition.returnType];
                Attributes |= ParameterAttributes.Retval;
                return;
            }

            var param = pkg.Metadata.Params[paramIndex];

            Name      = pkg.Metadata.Strings[param.nameIndex];
            Position  = paramIndex - declaringMethod.Definition.parameterStart;
            paramType = pkg.TypeUsages[param.typeIndex];

            if ((paramType.attrs & Il2CppConstants.PARAM_ATTRIBUTE_OPTIONAL) != 0)
            {
                Attributes |= ParameterAttributes.Optional;
            }
            if ((paramType.attrs & Il2CppConstants.PARAM_ATTRIBUTE_OUT) != 0)
            {
                Attributes |= ParameterAttributes.Out;
            }

            if (Position == -1)
            {
                Attributes |= ParameterAttributes.Retval;
            }
            else if (!IsOut)
            {
                Attributes |= ParameterAttributes.In;
            }

            // TODO: DefaultValue/HasDefaultValue
        }
예제 #14
0
        // Create type model
        public TypeModel(Il2CppInspector package)
        {
            Package = package;
            TypesByDefinitionIndex   = new TypeInfo[package.TypeDefinitions.Length];
            TypesByReferenceIndex    = new TypeInfo[package.TypeReferences.Count];
            GenericParameterTypes    = new TypeInfo[package.GenericParameters.Length];
            MethodsByDefinitionIndex = new MethodBase[package.Methods.Length];
            MethodInvokers           = new MethodInvoker[package.MethodInvokePointers.Length];

            // Recursively create hierarchy of assemblies and types from TypeDefs
            // No code that executes here can access any type through a TypeRef (ie. via TypesByReferenceIndex)
            for (var image = 0; image < package.Images.Length; image++)
            {
                Assemblies.Add(new Assembly(this, image));
            }

            // Create and reference types from TypeRefs
            // Note that you can't resolve any TypeRefs until all the TypeDefs have been processed
            for (int typeRefIndex = 0; typeRefIndex < package.TypeReferences.Count; typeRefIndex++)
            {
                if (TypesByReferenceIndex[typeRefIndex] != null)
                {
                    /* type already generated - probably by forward reference through GetTypeFromVirtualAddress */
                    continue;
                }

                var typeRef        = Package.TypeReferences[typeRefIndex];
                var referencedType = resolveTypeReference(typeRef);

                TypesByReferenceIndex[typeRefIndex] = referencedType;
            }

            // Create types and methods from MethodSpec (which incorporates TypeSpec in IL2CPP)
            foreach (var spec in Package.MethodSpecs)
            {
                var methodDefinition = MethodsByDefinitionIndex[spec.methodDefinitionIndex];
                var declaringType    = methodDefinition.DeclaringType;

                // Concrete instance of a generic class
                // If the class index is not specified, we will later create a generic method in a non-generic class
                if (spec.classIndexIndex != -1)
                {
                    var genericInstance  = Package.GenericInstances[spec.classIndexIndex];
                    var genericArguments = ResolveGenericArguments(genericInstance);
                    declaringType = declaringType.MakeGenericType(genericArguments);
                }

                MethodBase method;
                if (methodDefinition is ConstructorInfo)
                {
                    method = declaringType.GetConstructorByDefinition((ConstructorInfo)methodDefinition);
                }
                else
                {
                    method = declaringType.GetMethodByDefinition((MethodInfo)methodDefinition);
                }

                if (spec.methodIndexIndex != -1)
                {
                    var genericInstance  = Package.GenericInstances[spec.methodIndexIndex];
                    var genericArguments = ResolveGenericArguments(genericInstance);
                    method = method.MakeGenericMethod(genericArguments);
                }
                method.VirtualAddress = Package.GetGenericMethodPointer(spec);
                GenericMethods[spec]  = method;
            }

            // Generate a list of all namespaces used
            Namespaces = Assemblies.SelectMany(x => x.DefinedTypes).GroupBy(t => t.Namespace).Select(n => n.Key).Distinct().ToList();

            // Find all custom attribute generators (populate AttributesByIndices) (use ToList() to force evaluation)
            var allAssemblyAttributes  = Assemblies.Select(a => a.CustomAttributes).ToList();
            var allTypeAttributes      = TypesByDefinitionIndex.Select(t => t.CustomAttributes).ToList();
            var allEventAttributes     = TypesByDefinitionIndex.SelectMany(t => t.DeclaredEvents).Select(e => e.CustomAttributes).ToList();
            var allFieldAttributes     = TypesByDefinitionIndex.SelectMany(t => t.DeclaredFields).Select(f => f.CustomAttributes).ToList();
            var allPropertyAttributes  = TypesByDefinitionIndex.SelectMany(t => t.DeclaredProperties).Select(p => p.CustomAttributes).ToList();
            var allMethodAttributes    = MethodsByDefinitionIndex.Select(m => m.CustomAttributes).ToList();
            var allParameterAttributes = MethodsByDefinitionIndex.SelectMany(m => m.DeclaredParameters).Select(p => p.CustomAttributes).ToList();

            // Create method invokers (one per signature, in invoker index order)
            foreach (var method in MethodsByDefinitionIndex)
            {
                var index = package.GetInvokerIndex(method.DeclaringType.Assembly.ModuleDefinition, method.Definition);
                if (index != -1)
                {
                    if (MethodInvokers[index] == null)
                    {
                        MethodInvokers[index] = new MethodInvoker(method, index);
                    }

                    method.Invoker = MethodInvokers[index];
                }
            }

            // TODO: Some invokers are not initialized or missing, need to find out why
            // Create method invokers sourced from generic method invoker indices
            foreach (var spec in GenericMethods.Keys)
            {
                if (package.GenericMethodInvokerIndices.TryGetValue(spec, out var index))
                {
                    if (MethodInvokers[index] == null)
                    {
                        MethodInvokers[index] = new MethodInvoker(GenericMethods[spec], index);
                    }

                    GenericMethods[spec].Invoker = MethodInvokers[index];
                }
            }
        }
예제 #15
0
        public FieldInfo(Il2CppInspector pkg, int fieldIndex, TypeInfo declaringType) :
            base(declaringType)
        {
            Definition = pkg.Fields[fieldIndex];
            Index      = fieldIndex;
            Name       = pkg.Strings[Definition.nameIndex];

            rawOffset = pkg.FieldOffsets[fieldIndex];

            rootDefinition = this;

            fieldTypeReference = TypeRef.FromReferenceIndex(Assembly.Model, Definition.typeIndex);
            var fieldType = pkg.TypeReferences[Definition.typeIndex];

            if ((fieldType.attrs & Il2CppConstants.FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == Il2CppConstants.FIELD_ATTRIBUTE_PRIVATE)
            {
                Attributes |= FieldAttributes.Private;
            }
            if ((fieldType.attrs & Il2CppConstants.FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == Il2CppConstants.FIELD_ATTRIBUTE_PUBLIC)
            {
                Attributes |= FieldAttributes.Public;
            }
            if ((fieldType.attrs & Il2CppConstants.FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == Il2CppConstants.FIELD_ATTRIBUTE_FAM_AND_ASSEM)
            {
                Attributes |= FieldAttributes.FamANDAssem;
            }
            if ((fieldType.attrs & Il2CppConstants.FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == Il2CppConstants.FIELD_ATTRIBUTE_ASSEMBLY)
            {
                Attributes |= FieldAttributes.Assembly;
            }
            if ((fieldType.attrs & Il2CppConstants.FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == Il2CppConstants.FIELD_ATTRIBUTE_FAMILY)
            {
                Attributes |= FieldAttributes.Family;
            }
            if ((fieldType.attrs & Il2CppConstants.FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == Il2CppConstants.FIELD_ATTRIBUTE_FAM_OR_ASSEM)
            {
                Attributes |= FieldAttributes.FamORAssem;
            }
            if ((fieldType.attrs & Il2CppConstants.FIELD_ATTRIBUTE_STATIC) == Il2CppConstants.FIELD_ATTRIBUTE_STATIC)
            {
                Attributes |= FieldAttributes.Static;
            }
            if ((fieldType.attrs & Il2CppConstants.FIELD_ATTRIBUTE_INIT_ONLY) == Il2CppConstants.FIELD_ATTRIBUTE_INIT_ONLY)
            {
                Attributes |= FieldAttributes.InitOnly;
            }
            if ((fieldType.attrs & Il2CppConstants.FIELD_ATTRIBUTE_LITERAL) == Il2CppConstants.FIELD_ATTRIBUTE_LITERAL)
            {
                Attributes |= FieldAttributes.Literal;
            }
            if ((fieldType.attrs & Il2CppConstants.FIELD_ATTRIBUTE_NOT_SERIALIZED) == Il2CppConstants.FIELD_ATTRIBUTE_NOT_SERIALIZED)
            {
                Attributes |= FieldAttributes.NotSerialized;
            }
            if ((fieldType.attrs & Il2CppConstants.FIELD_ATTRIBUTE_SPECIAL_NAME) == Il2CppConstants.FIELD_ATTRIBUTE_SPECIAL_NAME)
            {
                Attributes |= FieldAttributes.SpecialName;
            }
            if ((fieldType.attrs & Il2CppConstants.FIELD_ATTRIBUTE_PINVOKE_IMPL) == Il2CppConstants.FIELD_ATTRIBUTE_PINVOKE_IMPL)
            {
                Attributes |= FieldAttributes.PinvokeImpl;
            }
            if ((fieldType.attrs & Il2CppConstants.FIELD_ATTRIBUTE_HAS_DEFAULT) != 0)
            {
                Attributes |= FieldAttributes.HasDefault;
            }

            // Default initialization value if present
            if (pkg.FieldDefaultValue.TryGetValue(fieldIndex, out (ulong address, object variant)value))
            {
                DefaultValue = value.variant;
                DefaultValueMetadataAddress = value.address;
            }
        }
예제 #16
0
        // TODO: ReturnTypeCustomAttributes

        public MethodInfo(Il2CppInspector pkg, int methodIndex, TypeInfo declaringType) :
            base(declaringType)
        {
            Definition = pkg.Metadata.Methods[methodIndex];
            Index      = methodIndex;
            if (Definition.methodIndex >= 0)
            {
                VirtualAddress = pkg.Binary.MethodPointers[Definition.methodIndex];
                HasBody        = true;
            }
            Name = pkg.Strings[Definition.nameIndex];

            if ((Definition.flags & Il2CppConstants.METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == Il2CppConstants.METHOD_ATTRIBUTE_PRIVATE)
            {
                Attributes |= MethodAttributes.Private;
            }
            if ((Definition.flags & Il2CppConstants.METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == Il2CppConstants.METHOD_ATTRIBUTE_PUBLIC)
            {
                Attributes |= MethodAttributes.Public;
            }
            if ((Definition.flags & Il2CppConstants.METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == Il2CppConstants.METHOD_ATTRIBUTE_FAM_AND_ASSEM)
            {
                Attributes |= MethodAttributes.FamANDAssem;
            }
            if ((Definition.flags & Il2CppConstants.METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == Il2CppConstants.METHOD_ATTRIBUTE_ASSEM)
            {
                Attributes |= MethodAttributes.Assembly;
            }
            if ((Definition.flags & Il2CppConstants.METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == Il2CppConstants.METHOD_ATTRIBUTE_FAMILY)
            {
                Attributes |= MethodAttributes.Family;
            }
            if ((Definition.flags & Il2CppConstants.METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == Il2CppConstants.METHOD_ATTRIBUTE_FAM_OR_ASSEM)
            {
                Attributes |= MethodAttributes.FamORAssem;
            }
            if ((Definition.flags & Il2CppConstants.METHOD_ATTRIBUTE_VIRTUAL) != 0)
            {
                Attributes |= MethodAttributes.Virtual;
            }
            if ((Definition.flags & Il2CppConstants.METHOD_ATTRIBUTE_ABSTRACT) != 0)
            {
                Attributes |= MethodAttributes.Abstract;
            }
            if ((Definition.flags & Il2CppConstants.METHOD_ATTRIBUTE_STATIC) != 0)
            {
                Attributes |= MethodAttributes.Static;
            }
            if ((Definition.flags & Il2CppConstants.METHOD_ATTRIBUTE_FINAL) != 0)
            {
                Attributes |= MethodAttributes.Final;
            }
            if ((Definition.flags & Il2CppConstants.METHOD_ATTRIBUTE_HIDE_BY_SIG) != 0)
            {
                Attributes |= MethodAttributes.HideBySig;
            }
            if ((Definition.flags & Il2CppConstants.METHOD_ATTRIBUTE_VTABLE_LAYOUT_MASK) == Il2CppConstants.METHOD_ATTRIBUTE_NEW_SLOT)
            {
                Attributes |= MethodAttributes.NewSlot;
            }
            if ((Definition.flags & Il2CppConstants.METHOD_ATTRIBUTE_PINVOKE_IMPL) != 0)
            {
                Attributes |= MethodAttributes.PinvokeImpl;
            }
            if ((Definition.flags & Il2CppConstants.METHOD_ATTRIBUTE_SPECIAL_NAME) != 0)
            {
                Attributes |= MethodAttributes.SpecialName;
            }
            if ((Definition.flags & Il2CppConstants.METHOD_ATTRIBUTE_UNMANAGED_EXPORT) != 0)
            {
                Attributes |= MethodAttributes.UnmanagedExport;
            }

            // Add return parameter
            returnType      = pkg.TypeUsages[Definition.returnType];
            ReturnParameter = new ParameterInfo(pkg, -1, this);

            // Add arguments
            for (var p = Definition.parameterStart; p < Definition.parameterStart + Definition.parameterCount; p++)
            {
                DeclaredParameters.Add(new ParameterInfo(pkg, p, this));
            }
        }
예제 #17
0
        public FieldInfo(Il2CppInspector pkg, int fieldIndex, TypeInfo declaringType) :
            base(declaringType)
        {
            Definition = pkg.Metadata.Fields[fieldIndex];
            Index      = fieldIndex;
            Offset     = pkg.FieldOffsets[fieldIndex];
            Name       = pkg.Strings[Definition.nameIndex];

            fieldType = pkg.TypeUsages[Definition.typeIndex];
            if ((fieldType.attrs & Il2CppConstants.FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == Il2CppConstants.FIELD_ATTRIBUTE_PRIVATE)
            {
                Attributes |= FieldAttributes.Private;
            }
            if ((fieldType.attrs & Il2CppConstants.FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == Il2CppConstants.FIELD_ATTRIBUTE_PUBLIC)
            {
                Attributes |= FieldAttributes.Public;
            }
            if ((fieldType.attrs & Il2CppConstants.FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == Il2CppConstants.FIELD_ATTRIBUTE_FAM_AND_ASSEM)
            {
                Attributes |= FieldAttributes.FamANDAssem;
            }
            if ((fieldType.attrs & Il2CppConstants.FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == Il2CppConstants.FIELD_ATTRIBUTE_ASSEMBLY)
            {
                Attributes |= FieldAttributes.Assembly;
            }
            if ((fieldType.attrs & Il2CppConstants.FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == Il2CppConstants.FIELD_ATTRIBUTE_FAMILY)
            {
                Attributes |= FieldAttributes.Family;
            }
            if ((fieldType.attrs & Il2CppConstants.FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == Il2CppConstants.FIELD_ATTRIBUTE_FAM_OR_ASSEM)
            {
                Attributes |= FieldAttributes.FamORAssem;
            }
            if ((fieldType.attrs & Il2CppConstants.FIELD_ATTRIBUTE_STATIC) == Il2CppConstants.FIELD_ATTRIBUTE_STATIC)
            {
                Attributes |= FieldAttributes.Static;
            }
            if ((fieldType.attrs & Il2CppConstants.FIELD_ATTRIBUTE_INIT_ONLY) == Il2CppConstants.FIELD_ATTRIBUTE_INIT_ONLY)
            {
                Attributes |= FieldAttributes.InitOnly;
            }
            if ((fieldType.attrs & Il2CppConstants.FIELD_ATTRIBUTE_LITERAL) == Il2CppConstants.FIELD_ATTRIBUTE_LITERAL)
            {
                Attributes |= FieldAttributes.Literal;
            }
            if ((fieldType.attrs & Il2CppConstants.FIELD_ATTRIBUTE_NOT_SERIALIZED) == Il2CppConstants.FIELD_ATTRIBUTE_NOT_SERIALIZED)
            {
                Attributes |= FieldAttributes.NotSerialized;
            }
            if ((fieldType.attrs & Il2CppConstants.FIELD_ATTRIBUTE_SPECIAL_NAME) == Il2CppConstants.FIELD_ATTRIBUTE_SPECIAL_NAME)
            {
                Attributes |= FieldAttributes.SpecialName;
            }
            if ((fieldType.attrs & Il2CppConstants.FIELD_ATTRIBUTE_PINVOKE_IMPL) == Il2CppConstants.FIELD_ATTRIBUTE_PINVOKE_IMPL)
            {
                Attributes |= FieldAttributes.PinvokeImpl;
            }

            // Default initialization value if present
            if (pkg.FieldDefaultValue.TryGetValue(fieldIndex, out object variant))
            {
                HasDefaultValue = true;
                DefaultValue    = variant;
            }
        }
예제 #18
0
        private static int Run(Options options)
        {
            // Banner
            var asmInfo = FileVersionInfo.GetVersionInfo(System.Reflection.Assembly.GetEntryAssembly().Location);

            Console.WriteLine(asmInfo.ProductName);
            Console.WriteLine("Version " + asmInfo.ProductVersion);
            Console.WriteLine(asmInfo.LegalCopyright);
            Console.WriteLine("");

            // Check excluded namespaces
            if (options.ExcludedNamespaces.Count() == 1 && options.ExcludedNamespaces.First().ToLower() == "none")
            {
                options.ExcludedNamespaces = new List <string>();
            }

            // Check files
            if (!File.Exists(options.BinaryFile))
            {
                Console.Error.WriteLine($"File {options.BinaryFile} does not exist");
                return(1);
            }
            if (!File.Exists(options.MetadataFile))
            {
                Console.Error.WriteLine($"File {options.MetadataFile} does not exist");
                return(1);
            }

            // Creating a Visual Studio solution requires Unity assembly references
            var unityPath           = string.Empty;
            var unityAssembliesPath = string.Empty;

            if (options.CreateSolution)
            {
                unityPath           = Utils.FindPath(options.UnityPath);
                unityAssembliesPath = Utils.FindPath(options.UnityAssembliesPath);

                if (!Directory.Exists(unityPath))
                {
                    Console.Error.WriteLine($"Unity path {unityPath} does not exist");
                    return(1);
                }
                if (!File.Exists(unityPath + @"\Editor\Data\Managed\UnityEditor.dll"))
                {
                    Console.Error.WriteLine($"No Unity installation found at {unityPath}");
                    return(1);
                }
                if (!Directory.Exists(unityAssembliesPath))
                {
                    Console.Error.WriteLine($"Unity assemblies path {unityAssembliesPath} does not exist");
                    return(1);
                }
                if (!File.Exists(unityAssembliesPath + @"\UnityEngine.UI.dll"))
                {
                    Console.Error.WriteLine($"No Unity assemblies found at {unityAssembliesPath}");
                    return(1);
                }

                Console.WriteLine("Using Unity editor at " + unityPath);
                Console.WriteLine("Using Unity assemblies at " + unityAssembliesPath);
            }

            // Analyze data
            List <Il2CppInspector> il2cppInspectors;

            using (var il2cppTimer = new Benchmark("Analyze IL2CPP data"))
                il2cppInspectors = Il2CppInspector.LoadFromFile(options.BinaryFile, options.MetadataFile);

            if (il2cppInspectors == null)
            {
                Environment.Exit(1);
            }

            // Write output file
            int i = 0;

            foreach (var il2cpp in il2cppInspectors)
            {
                // Create model
                Il2CppModel model;
                using (var modelTimer = new Benchmark("Create type model"))
                    model = new Il2CppModel(il2cpp);

                // C# signatures output
                using (var signaturesDumperTimer = new Benchmark("Generate C# code")) {
                    var writer = new CSharpCodeStubs(model)
                    {
                        ExcludedNamespaces = options.ExcludedNamespaces.ToList(),
                        SuppressMetadata   = options.SuppressMetadata,
                        MustCompile        = options.MustCompile
                    };

                    var imageSuffix = i++ > 0 ? "-" + (i - 1) : "";

                    var csOut = options.CSharpOutPath;
                    if (csOut.ToLower().EndsWith(".cs"))
                    {
                        csOut = csOut.Insert(csOut.Length - 3, imageSuffix);
                    }
                    else
                    {
                        csOut += imageSuffix;
                    }

                    if (options.CreateSolution)
                    {
                        writer.WriteSolution(csOut, unityPath, unityAssembliesPath);
                    }

                    else
                    {
                        switch (options.LayoutSchema.ToLower(), options.SortOrder.ToLower())
                        {
예제 #19
0
        private static int Run(Options options)
        {
            // Banner
            var asmInfo = FileVersionInfo.GetVersionInfo(System.Reflection.Assembly.GetEntryAssembly().Location);

            Console.WriteLine(asmInfo.ProductName);
            Console.WriteLine("Version " + asmInfo.ProductVersion);
            Console.WriteLine(asmInfo.LegalCopyright);
            Console.WriteLine("");

            // Check excluded namespaces
            if (options.ExcludedNamespaces.Count() == 1 && options.ExcludedNamespaces.First().ToLower() == "none")
            {
                options.ExcludedNamespaces = new List <string>();
            }

            // Creating a Visual Studio solution requires Unity assembly references
            var unityPath           = string.Empty;
            var unityAssembliesPath = string.Empty;

            if (options.CreateSolution)
            {
                unityPath           = Utils.FindPath(options.UnityPath);
                unityAssembliesPath = Utils.FindPath(options.UnityAssembliesPath);

                if (!Directory.Exists(unityPath))
                {
                    Console.Error.WriteLine($"Unity path {unityPath} does not exist");
                    return(1);
                }

                string editorPathSuffix = RuntimeInformation.IsOSPlatform(OSPlatform.OSX)
                    ? @"/Contents/Managed/UnityEditor.dll"
                    : @"\Editor\Data\Managed\UnityEditor.dll";

                if (!File.Exists(unityPath + editorPathSuffix))
                {
                    Console.Error.WriteLine($"No Unity installation found at {unityPath}");
                    return(1);
                }

                if (!Directory.Exists(unityAssembliesPath))
                {
                    Console.Error.WriteLine($"Unity assemblies path {unityAssembliesPath} does not exist");
                    return(1);
                }

                string uiDllPath = Path.Combine(unityAssembliesPath, "UnityEngine.UI.dll");
                if (!File.Exists(uiDllPath))
                {
                    Console.Error.WriteLine($"No UnityEngine.UI.dll assemblies found at {uiDllPath}");
                    return(1);
                }

                Console.WriteLine("Using Unity editor at " + unityPath);
                Console.WriteLine("Using Unity assemblies at " + unityAssembliesPath);
            }

            // Check files exist and determine whether they're archives or not
            List <Il2CppInspector> il2cppInspectors;

            using (new Benchmark("Analyze IL2CPP data")) {
                if (!File.Exists(options.BinaryFile))
                {
                    Console.Error.WriteLine($"File {options.BinaryFile} does not exist");
                    return(1);
                }

                try {
                    il2cppInspectors = Il2CppInspector.LoadFromPackage(options.BinaryFile);
                }
                catch (Exception ex) {
                    Console.Error.WriteLine(ex.Message);
                    return(1);
                }

                if (il2cppInspectors == null)
                {
                    if (!File.Exists(options.MetadataFile))
                    {
                        Console.Error.WriteLine($"File {options.MetadataFile} does not exist");
                        return(1);
                    }

                    il2cppInspectors = Il2CppInspector.LoadFromFile(options.BinaryFile, options.MetadataFile);
                }
            }

            if (il2cppInspectors == null)
            {
                Environment.Exit(1);
            }

            // Write output file
            int i = 0;

            foreach (var il2cpp in il2cppInspectors)
            {
                // Create model
                TypeModel model;
                using (new Benchmark("Create .NET type model"))
                    model = new TypeModel(il2cpp);

                AppModel appModel;
                using (new Benchmark("Create C++ application model")) {
                    appModel = new AppModel(model).Build(options.UnityVersion, options.CppCompiler);
                }

                // C# signatures output
                using (new Benchmark("Generate C# code")) {
                    var writer = new CSharpCodeStubs(model)
                    {
                        ExcludedNamespaces = options.ExcludedNamespaces.ToList(),
                        SuppressMetadata   = options.SuppressMetadata,
                        MustCompile        = options.MustCompile
                    };

                    var imageSuffix = i++ > 0 ? "-" + (i - 1) : "";

                    var csOut = options.CSharpOutPath;
                    if (csOut.ToLower().EndsWith(".cs"))
                    {
                        csOut = csOut.Insert(csOut.Length - 3, imageSuffix);
                    }
                    else
                    {
                        csOut += imageSuffix;
                    }

                    if (options.CreateSolution)
                    {
                        writer.WriteSolution(csOut, unityPath, unityAssembliesPath);
                    }

                    else
                    {
                        switch (options.LayoutSchema.ToLower(), options.SortOrder.ToLower())
                        {
예제 #20
0
        // IL2CPP doesn't seem to retain return type custom attributes

        public MethodInfo(Il2CppInspector pkg, int methodIndex, TypeInfo declaringType) : base(pkg, methodIndex, declaringType)
        {
            // Add return parameter
            returnTypeUsage = Definition.returnType;
            ReturnParameter = new ParameterInfo(pkg, -1, this);
        }
예제 #21
0
        private static int Run(Options options)
        {
            // Banner
            var asmInfo = FileVersionInfo.GetVersionInfo(System.Reflection.Assembly.GetEntryAssembly().Location);

            Console.WriteLine(asmInfo.ProductName);
            Console.WriteLine("Version " + asmInfo.ProductVersion);
            Console.WriteLine(asmInfo.LegalCopyright);
            Console.WriteLine("");

            // Check script target is valid
            if (!PythonScript.GetAvailableTargets().Contains(options.ScriptTarget))
            {
                Console.Error.WriteLine($"Script target {options.ScriptTarget} is invalid.");
                Console.Error.WriteLine("Valid targets are: " + string.Join(", ", PythonScript.GetAvailableTargets()));
                return(1);
            }

            // Check excluded namespaces
            if (options.ExcludedNamespaces.Count() == 1 && options.ExcludedNamespaces.First().ToLower() == "none")
            {
                options.ExcludedNamespaces = new List <string>();
            }

            // Creating a Visual Studio solution requires Unity assembly references
            var unityPath           = string.Empty;
            var unityAssembliesPath = string.Empty;

            if (options.CreateSolution)
            {
                unityPath           = Utils.FindPath(options.UnityPath);
                unityAssembliesPath = Utils.FindPath(options.UnityAssembliesPath);

                if (!Directory.Exists(unityPath))
                {
                    Console.Error.WriteLine($"Unity path {unityPath} does not exist");
                    return(1);
                }

                string editorPathSuffix = RuntimeInformation.IsOSPlatform(OSPlatform.OSX)
                    ? @"/Contents/Managed/UnityEditor.dll"
                    : @"\Editor\Data\Managed\UnityEditor.dll";

                if (!File.Exists(unityPath + editorPathSuffix))
                {
                    Console.Error.WriteLine($"No Unity installation found at {unityPath}");
                    return(1);
                }

                if (!Directory.Exists(unityAssembliesPath))
                {
                    Console.Error.WriteLine($"Unity assemblies path {unityAssembliesPath} does not exist");
                    return(1);
                }

                string uiDllPath = Path.Combine(unityAssembliesPath, "UnityEngine.UI.dll");
                if (!File.Exists(uiDllPath))
                {
                    Console.Error.WriteLine($"No UnityEngine.UI.dll assemblies found at {uiDllPath}");
                    return(1);
                }

                Console.WriteLine("Using Unity editor at " + unityPath);
                Console.WriteLine("Using Unity assemblies at " + unityAssembliesPath);
            }

            // Check that specified binary files exist
            foreach (var file in options.BinaryFiles)
            {
                if (!File.Exists(file))
                {
                    Console.Error.WriteLine($"File {file} does not exist");
                    return(1);
                }
            }

            // Check files exist and determine whether they're archives or not
            List <Il2CppInspector> il2cppInspectors;

            using (new Benchmark("Analyze IL2CPP data")) {
                try {
                    il2cppInspectors = Il2CppInspector.LoadFromPackage(options.BinaryFiles);
                }
                catch (Exception ex) {
                    Console.Error.WriteLine(ex.Message);
                    return(1);
                }

                if (il2cppInspectors == null)
                {
                    if (!File.Exists(options.MetadataFile))
                    {
                        Console.Error.WriteLine($"File {options.MetadataFile} does not exist");
                        return(1);
                    }

                    try {
                        il2cppInspectors = Il2CppInspector.LoadFromFile(options.BinaryFiles.First(), options.MetadataFile);
                    }
                    catch (Exception ex) {
                        Console.Error.WriteLine(ex.Message);
                        return(1);
                    }
                }
            }

            if (il2cppInspectors == null)
            {
                Environment.Exit(1);
            }

            // Write output files for each binary
            int imageIndex = 0;

            foreach (var il2cpp in il2cppInspectors)
            {
                Console.WriteLine($"Processing image {imageIndex} - {il2cpp.BinaryImage.Arch} / {il2cpp.BinaryImage.Bits}-bit");

                // Create model
                TypeModel model;
                using (new Benchmark("Create .NET type model"))
                    model = new TypeModel(il2cpp);

                AppModel appModel;
                using (new Benchmark("Create C++ application model")) {
                    appModel = new AppModel(model, makeDefaultBuild: false).Build(options.UnityVersion, options.CppCompiler);
                }

                // C# signatures output
                using (new Benchmark("Generate C# code")) {
                    var writer = new CSharpCodeStubs(model)
                    {
                        ExcludedNamespaces = options.ExcludedNamespaces.ToList(),
                        SuppressMetadata   = options.SuppressMetadata,
                        MustCompile        = options.MustCompile
                    };

                    var csOut = getOutputPath(options.CSharpOutPath, "cs", imageIndex);

                    if (options.CreateSolution)
                    {
                        writer.WriteSolution(csOut, unityPath, unityAssembliesPath);
                    }

                    else
                    {
                        switch (options.LayoutSchema.ToLower(), options.SortOrder.ToLower())
                        {
예제 #22
0
        private static int Run(Options options)
        {
            // Banner
            var asmInfo = FileVersionInfo.GetVersionInfo(System.Reflection.Assembly.GetEntryAssembly().Location);

            Console.WriteLine(asmInfo.ProductName);
            Console.WriteLine("Version " + asmInfo.ProductVersion);
            Console.WriteLine(asmInfo.LegalCopyright);
            Console.WriteLine("");

            // Safe plugin manager load
            try {
                PluginManager.EnsureInit();
            }
            catch (Exception ex) when(ex is InvalidOperationException || ex is DirectoryNotFoundException)
            {
                Console.Error.WriteLine(ex.Message);
                Environment.Exit(1);
            }

            // Check plugin options are valid
            if (!PluginOptions.ParsePluginOptions(options.PluginOptions, PluginOptions.GetPluginOptionTypes()))
            {
                return(1);
            }

            // Check script target is valid
            if (!PythonScript.GetAvailableTargets().Contains(options.ScriptTarget))
            {
                Console.Error.WriteLine($"Script target {options.ScriptTarget} is invalid.");
                Console.Error.WriteLine("Valid targets are: " + string.Join(", ", PythonScript.GetAvailableTargets()));
                return(1);
            }

            // Set load options
            var loadOptions = new LoadOptions {
                BinaryFilePath = options.BinaryFiles.First()
            };

            // Check image base
            if (!string.IsNullOrEmpty(options.ElfImageBaseString))
            {
                try {
                    loadOptions.ImageBase = Convert.ToUInt64(options.ElfImageBaseString, 16);
                } catch (Exception ex) when(ex is ArgumentException || ex is FormatException || ex is OverflowException)
                {
                    Console.Error.WriteLine("Image base must be a 32 or 64-bit hex value (optionally starting with '0x')");
                    return(1);
                }
            }

            // Check Unity asset
            if (options.UnityVersionAsset != null)
            {
                try {
                    options.UnityVersion = UnityVersion.FromAssetFile(options.UnityVersionAsset);

                    Console.WriteLine("Unity asset file has version " + options.UnityVersion);
                }
                catch (FileNotFoundException) {
                    Console.Error.WriteLine($"Unity asset file {options.UnityVersionAsset} does not exist");
                    return(1);
                } catch (ArgumentException) {
                    Console.Error.WriteLine("Could not determine Unity version from asset file - ignoring");
                }
            }

            // Check excluded namespaces
            if (options.ExcludedNamespaces.Count() == 1 && options.ExcludedNamespaces.First().ToLower() == "none")
            {
                options.ExcludedNamespaces = new List <string>();
            }

            // Creating a Visual Studio solution requires Unity assembly references
            var unityPath           = string.Empty;
            var unityAssembliesPath = string.Empty;

            if (options.CreateSolution)
            {
                unityPath           = Utils.FindPath(options.UnityPath);
                unityAssembliesPath = Utils.FindPath(options.UnityAssembliesPath);

                if (!Directory.Exists(unityPath))
                {
                    Console.Error.WriteLine($"Unity path {unityPath} does not exist");
                    return(1);
                }

                string editorPathSuffix = RuntimeInformation.IsOSPlatform(OSPlatform.OSX)
                    ? @"/Contents/Managed/UnityEditor.dll"
                    : @"\Editor\Data\Managed\UnityEditor.dll";

                if (!File.Exists(unityPath + editorPathSuffix))
                {
                    Console.Error.WriteLine($"No Unity installation found at {unityPath}");
                    return(1);
                }

                if (!Directory.Exists(unityAssembliesPath))
                {
                    Console.Error.WriteLine($"Unity assemblies path {unityAssembliesPath} does not exist");
                    return(1);
                }

                string uiDllPath = Path.Combine(unityAssembliesPath, "UnityEngine.UI.dll");
                if (!File.Exists(uiDllPath))
                {
                    Console.Error.WriteLine($"No UnityEngine.UI.dll assemblies found at {uiDllPath}");
                    return(1);
                }

                Console.WriteLine("Using Unity editor at " + unityPath);
                Console.WriteLine("Using Unity assemblies at " + unityAssembliesPath);
            }

            // Set plugin handlers
            PluginManager.ErrorHandler += (s, e) => {
                Console.Error.WriteLine($"The plugin {e.Error.Plugin.Name} encountered an error while executing {e.Error.Operation}: {e.Error.Exception.Message}."
                                        + " Plugin has been disabled.");
            };

            PluginManager.StatusHandler += (s, e) => {
                Console.WriteLine("Plugin " + e.Plugin.Name + ": " + e.Text);
            };

            // Check that specified binary files exist
            foreach (var file in options.BinaryFiles)
            {
                if (!File.Exists(file))
                {
                    Console.Error.WriteLine($"File {file} does not exist");
                    return(1);
                }
            }

            // Check files exist and determine whether they're archives or not
            bool isExtractedFromPackage = false;
            List <Il2CppInspector> il2cppInspectors;

            using (new Benchmark("Analyze IL2CPP data")) {
                try {
                    il2cppInspectors       = Il2CppInspector.LoadFromPackage(options.BinaryFiles, loadOptions);
                    isExtractedFromPackage = true;
                }
                catch (Exception ex) {
                    Console.Error.WriteLine(ex.Message);
                    return(1);
                }

                if (il2cppInspectors == null)
                {
                    isExtractedFromPackage = false;

                    if (!File.Exists(options.MetadataFile))
                    {
                        Console.Error.WriteLine($"File {options.MetadataFile} does not exist");
                        return(1);
                    }

                    try {
                        il2cppInspectors = Il2CppInspector.LoadFromFile(options.BinaryFiles.First(), options.MetadataFile, loadOptions);
                    }
                    catch (Exception ex) {
                        Console.Error.WriteLine(ex.Message);
                        return(1);
                    }
                }
            }

            if (il2cppInspectors == null)
            {
                Environment.Exit(1);
            }

            // Save metadata and binary if extracted or modified and save requested
            if (!string.IsNullOrEmpty(options.MetadataFileOut))
            {
                if (isExtractedFromPackage || il2cppInspectors[0].Metadata.IsModified)
                {
                    Console.WriteLine($"Saving metadata file to {options.MetadataFileOut}");

                    il2cppInspectors[0].SaveMetadataToFile(options.MetadataFileOut);
                }
                else
                {
                    Console.WriteLine("Metadata file was not modified - skipping save");
                }
            }

            if (!string.IsNullOrEmpty(options.BinaryFileOut))
            {
                var outputIndex = 0;
                foreach (var il2cpp in il2cppInspectors)
                {
                    // If there's an extension, strip the leading period
                    var ext = Path.GetExtension(options.BinaryFileOut);
                    if (ext.Length > 0)
                    {
                        ext = ext.Substring(1);
                    }
                    var outPath = getOutputPath(options.BinaryFileOut, ext, outputIndex);

                    if (isExtractedFromPackage || il2cpp.Binary.IsModified)
                    {
                        Console.WriteLine($"Saving binary file to {outPath}");

                        il2cpp.SaveBinaryToFile(outPath);
                    }
                    else
                    {
                        Console.WriteLine("Binary file was not modified - skipping save");
                    }

                    outputIndex++;
                }
            }

            // Write output files for each binary
            int imageIndex = 0;

            foreach (var il2cpp in il2cppInspectors)
            {
                Console.WriteLine($"Processing image {imageIndex} - {il2cpp.BinaryImage.Arch} / {il2cpp.BinaryImage.Bits}-bit");

                // Create model
                TypeModel model;
                using (new Benchmark("Create .NET type model"))
                    model = new TypeModel(il2cpp);

                AppModel appModel;
                using (new Benchmark("Create C++ application model")) {
                    appModel = new AppModel(model, makeDefaultBuild: false).Build(options.UnityVersion, options.CppCompiler);
                }

                // C# signatures output
                using (new Benchmark("Generate C# code")) {
                    var writer = new CSharpCodeStubs(model)
                    {
                        ExcludedNamespaces = options.ExcludedNamespaces.ToList(),
                        SuppressMetadata   = options.SuppressMetadata,
                        MustCompile        = options.MustCompile
                    };

                    var csOut = getOutputPath(options.CSharpOutPath, "cs", imageIndex);

                    if (options.CreateSolution)
                    {
                        writer.WriteSolution(csOut, unityPath, unityAssembliesPath);
                    }

                    else
                    {
                        switch (options.LayoutSchema.ToLower(), options.SortOrder.ToLower())
                        {
예제 #23
0
 public ConstructorInfo(Il2CppInspector pkg, int methodIndex, TypeInfo declaringType) : base(pkg, methodIndex, declaringType)
 {
 }
예제 #24
0
        // Create type model
        public Il2CppModel(Il2CppInspector package)
        {
            Package = package;
            TypesByDefinitionIndex   = new TypeInfo[package.TypeDefinitions.Length];
            TypesByReferenceIndex    = new TypeInfo[package.TypeReferences.Count];
            MethodsByDefinitionIndex = new MethodBase[package.Methods.Length];
            MethodInvokers           = new MethodInvoker[package.MethodInvokePointers.Length];

            // Recursively create hierarchy of assemblies and types from TypeDefs
            // No code that executes here can access any type through a TypeRef (ie. via TypesByReferenceIndex)
            for (var image = 0; image < package.Images.Length; image++)
            {
                Assemblies.Add(new Assembly(this, image));
            }

            // Create and reference types from TypeRefs
            // Note that you can't resolve any TypeRefs until all the TypeDefs have been processed
            for (int typeRefIndex = 0; typeRefIndex < package.TypeReferences.Count; typeRefIndex++)
            {
                var typeRef        = Package.TypeReferences[typeRefIndex];
                var referencedType = resolveTypeReference(typeRef);

                TypesByReferenceIndex[typeRefIndex] = referencedType;
            }

            // Create types and methods from MethodSpec (which incorporates TypeSpec in IL2CPP)
            foreach (var spec in Package.MethodSpecs)
            {
                TypeInfo declaringType;

                // Concrete instance of a generic class
                // If the class index is not specified, we will later create a generic method in a non-generic class
                if (spec.classIndexIndex != -1)
                {
                    if (!TypesByMethodSpecClassIndex.ContainsKey(spec.classIndexIndex))
                    {
                        TypesByMethodSpecClassIndex.Add(spec.classIndexIndex, new TypeInfo(this, spec));
                    }

                    declaringType = TypesByMethodSpecClassIndex[spec.classIndexIndex];
                }
                else
                {
                    declaringType = MethodsByDefinitionIndex[spec.methodDefinitionIndex].DeclaringType;
                }

                // Concrete instance of a generic method
                if (spec.methodIndexIndex != -1)
                {
                    // Method or constructor
                    var concreteMethod = new MethodInfo(this, spec, declaringType);
                    if (concreteMethod.Name == ConstructorInfo.ConstructorName || concreteMethod.Name == ConstructorInfo.TypeConstructorName)
                    {
                        GenericMethods.Add(spec, new ConstructorInfo(this, spec, declaringType));
                    }
                    else
                    {
                        GenericMethods.Add(spec, concreteMethod);
                    }
                }
            }

            // Create method invokers (one per signature, in invoker index order)
            foreach (var method in MethodsByDefinitionIndex)
            {
                var index = package.GetInvokerIndex(method.DeclaringType.Assembly.ModuleDefinition, method.Definition);
                if (index != -1)
                {
                    if (MethodInvokers[index] == null)
                    {
                        MethodInvokers[index] = new MethodInvoker(method, index);
                    }

                    method.Invoker = MethodInvokers[index];
                }
            }

            // TODO: Some invokers are not initialized or missing, need to find out why
            // Create method invokers sourced from generic method invoker indices
            foreach (var spec in GenericMethods.Keys)
            {
                if (package.GenericMethodInvokerIndices.TryGetValue(spec, out var index))
                {
                    if (MethodInvokers[index] == null)
                    {
                        MethodInvokers[index] = new MethodInvoker(GenericMethods[spec], index);
                    }

                    GenericMethods[spec].Invoker = MethodInvokers[index];
                }
            }
        }
예제 #25
0
        // Create a parameter. Specify paramIndex == -1 for a return type parameter
        public ParameterInfo(Il2CppInspector pkg, int paramIndex, MethodBase declaringMethod)
        {
            Index           = paramIndex;
            DeclaringMethod = declaringMethod;

            if (paramIndex == -1)
            {
                Position           = -1;
                paramTypeReference = declaringMethod.Definition.returnType;
                Attributes        |= ParameterAttributes.Retval;
                return;
            }

            Definition = pkg.Params[Index];
            Name       = pkg.Strings[Definition.nameIndex];

            // Handle unnamed/obfuscated parameter names
            if (string.IsNullOrEmpty(Name))
            {
                Name = string.Format($"param_{Index:x8}");
            }

            Position           = paramIndex - declaringMethod.Definition.parameterStart;
            paramTypeReference = Definition.typeIndex;
            var paramType = pkg.TypeReferences[paramTypeReference];

            if ((paramType.attrs & Il2CppConstants.PARAM_ATTRIBUTE_HAS_DEFAULT) != 0)
            {
                Attributes |= ParameterAttributes.HasDefault;
            }
            if ((paramType.attrs & Il2CppConstants.PARAM_ATTRIBUTE_OPTIONAL) != 0)
            {
                Attributes |= ParameterAttributes.Optional;
            }
            if ((paramType.attrs & Il2CppConstants.PARAM_ATTRIBUTE_IN) != 0)
            {
                Attributes |= ParameterAttributes.In;
            }
            if ((paramType.attrs & Il2CppConstants.PARAM_ATTRIBUTE_OUT) != 0)
            {
                Attributes |= ParameterAttributes.Out;
            }
            if ((paramType.attrs & Il2CppConstants.PARAM_ATTRIBUTE_RESERVED_MASK) != 0)
            {
                Attributes |= ParameterAttributes.ReservedMask;
            }
            if ((paramType.attrs & Il2CppConstants.PARAM_ATTRIBUTE_HAS_FIELD_MARSHAL) != 0)
            {
                Attributes |= ParameterAttributes.HasFieldMarshal;
            }

            if (Position == -1)
            {
                Attributes |= ParameterAttributes.Retval;
            }

            // Default initialization value if present
            if (pkg.ParameterDefaultValue.TryGetValue(paramIndex, out (ulong address, object variant)value))
            {
                DefaultValue = value.variant;
                DefaultValueMetadataAddress = value.address;
            }
        }