Exemple #1
0
        public LoadVirtualFunctionPointerAction(MethodAnalysis context, Instruction instruction) : base(context, instruction)
        {
            regReadFrom = Utils.GetRegisterNameNew(instruction.MemoryBase);
            var inReg = context.GetOperandInRegister(regReadFrom);

            if (!(inReg is ConstantDefinition cons) || !(cons.Value is Il2CppClassIdentifier klass))
            {
                return;
            }

            classReadFrom = klass.backingType;

            var readOffset = instruction.MemoryDisplacement;

            methodPointerRead = Utils.GetMethodFromReadKlassOffset((int)readOffset);

            if (methodPointerRead == null)
            {
                return;
            }

            var regPutInto = Utils.GetRegisterNameNew(instruction.Op0Register);

            if (regPutInto == "rsp")
            {
                //todo how do we handle this kind of instruction - does it even exist?
                // var stackOffset = Utils.GetOperandMemoryOffset(instruction.Operands[0]);
                // context.PushToStack(context.MakeConstant(typeof(MethodDefinition), methodPointerRead), stackOffset);
            }
            else
            {
                destinationConstant = context.MakeConstant(typeof(MethodDefinition), methodPointerRead, reg: regPutInto);
            }
        }
Exemple #2
0
        private int GetFieldOffset(Il2Cpp il2Cpp, Metadata metadata, Il2CppExecutor executor, string classname, string membername)
        {
            int typeDefIndex             = 0;
            Il2CppTypeDefinition typeDef = FindClassEntry(metadata, executor, classname, out typeDefIndex);

            if (typeDef == null)
            {
                return(0);
            }

            var fieldEnd = typeDef.fieldStart + typeDef.field_count;

            for (var i = typeDef.fieldStart; i < fieldEnd; ++i)
            {
                var isStatic  = false;
                var fieldDef  = metadata.fieldDefs[i];
                var fieldType = il2Cpp.types[fieldDef.typeIndex];

                if ((fieldType.attrs & FIELD_ATTRIBUTE_STATIC) != 0)
                {
                    isStatic = true;
                }

                string memberName = metadata.GetStringFromIndex(fieldDef.nameIndex);
                if (memberName == membername)
                {
                    return(il2Cpp.GetFieldOffsetFromIndex(typeDefIndex, i - typeDef.fieldStart, i, typeDef.IsValueType, isStatic));
                }
            }

            throw new Exception("Field " + membername + " not found in " + classname);
        }
Exemple #3
0
 internal static Il2CppTypeReflectionData WrapType(Il2CppTypeDefinition what)
 {
     return(new Il2CppTypeReflectionData
     {
         baseType = what,
         genericParams = new Il2CppTypeReflectionData[0],
         isGenericType = false,
         isType = true,
     });
 }
Exemple #4
0
        private static string GetTypeName(Il2CppTypeDefinition typeDef)
        {
            var ret = string.Empty;

            if (typeDef.declaringTypeIndex != -1)
            {
                ret += GetTypeName(il2cpp.types[typeDef.declaringTypeIndex]) + ".";
            }
            ret += metadata.GetStringFromIndex(typeDef.nameIndex);
            return(ret);
        }
Exemple #5
0
        internal void WriteEnum(StreamWriter writer, Il2CppTypeDefinition typeDef, string pad = "")
        {
            writer.Write("\n");
            writer.Write(pad + $"enum {metadata.GetTypeName(typeDef)} {{\n");
            var fieldEnd = typeDef.fieldStart + typeDef.field_count;

            for (int i = typeDef.fieldStart + 1; i < fieldEnd; ++i)
            {
                var pField       = metadata.Fields[i];
                var defaultValue = this.GetDefaultValue(i);
                writer.Write(pad + $"\t{metadata.GetString(pField.nameIndex)} = {defaultValue};\n");
            }
            writer.Write(pad + "}\n");
        }
        internal void WriteFields(StreamWriter writer, Il2CppTypeDefinition typeDef)
        {
            if (typeDef.field_count <= 0)
            {
                return;
            }

            writer.Write("\t\t// Fields\n");
            var fieldEnd = typeDef.fieldStart + typeDef.field_count;

            for (int i = typeDef.fieldStart; i < fieldEnd; ++i)
            {
                var pField       = metadata.Fields[i];
                var pType        = il2cpp.Code.GetTypeFromTypeIndex(pField.typeIndex);
                var defaultValue = this.GetDefaultValue(i);

                WriteAttribute(writer, pField.customAttributeIndex, "\t\t");

                if ((pType.attrs & DefineConstants.FIELD_ATTRIBUTE_PINVOKE_IMPL) != 0)
                {
                    writer.Write("// pinvoke\n");
                }

                writer.Write("\t\t");
                if ((pType.attrs & DefineConstants.FIELD_ATTRIBUTE_PRIVATE) == DefineConstants.FIELD_ATTRIBUTE_PRIVATE)
                {
                    writer.Write("private ");
                }
                if ((pType.attrs & DefineConstants.FIELD_ATTRIBUTE_PUBLIC) == DefineConstants.FIELD_ATTRIBUTE_PUBLIC)
                {
                    writer.Write("public ");
                }
                if ((pType.attrs & DefineConstants.FIELD_ATTRIBUTE_STATIC) != 0)
                {
                    writer.Write("static ");
                }
                if ((pType.attrs & DefineConstants.FIELD_ATTRIBUTE_INIT_ONLY) != 0)
                {
                    writer.Write("readonly ");
                }

                writer.Write($"{il2cpp.GetFullTypeName(pType)} {metadata.GetString(pField.nameIndex)}");
                if (defaultValue != null)
                {
                    writer.Write($" = {defaultValue}");
                }
                writer.Write(";\n");
            }
        }
        internal void WriteFields(StreamWriter writer, Il2CppTypeDefinition typeDef)
        {
            if (typeDef.field_count <= 0)
            {
                return;
            }

            var fieldEnd = typeDef.fieldStart + typeDef.field_count;

            for (int i = typeDef.fieldStart; i < fieldEnd; ++i)
            {
                var pField = metadata.Fields[i];
                var pType  = il2cpp.Code.GetTypeFromTypeIndex(pField.typeIndex);

                if ((pType.attrs & DefineConstants.FIELD_ATTRIBUTE_STATIC) == 0)
                {
                    var    fieldname = metadata.GetString(pField.nameIndex);
                    string typename  = "";
                    if (pType.type == Il2CppTypeEnum.IL2CPP_TYPE_CLASS || pType.type == Il2CppTypeEnum.IL2CPP_TYPE_VALUETYPE)
                    {
                        var fieldTypeDef = metadata.Types[pType.klassIndex];
                        if (fieldTypeDef.parentIndex == enumIdx)
                        {
                            typename = "int";
                        }
                        else if ((fieldTypeDef.flags & DefineConstants.TYPE_ATTRIBUTE_INTERFACE) != 0)
                        {
                            typename = "void *";
                        }
                        else
                        {
                            typename = this.GetStructType(il2cpp.GetTypeName(pType));
                        }
                    }
                    else
                    {
                        typename = this.GetStructType(il2cpp.GetTypeName(pType));
                    }

                    writer.Write($"\t{typename} {fieldname};\n");

                    if (pType.type == Il2CppTypeEnum.IL2CPP_TYPE_VALUETYPE || pType.type == Il2CppTypeEnum.IL2CPP_TYPE_GENERICINST)
                    {
                        this.AddTypeToDump(pType);
                    }
                }
            }
        }
        public static int GetTypeIndexFromType(Il2CppTypeDefinition typeDefinition)
        {
            if (LibCpp2IlMain.TheMetadata == null)
            {
                return(-1);
            }

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

            return(-1);
        }
Exemple #9
0
        internal void WriteEnum(StreamWriter writer, Il2CppTypeDefinition typeDef)
        {
            writer.Write("\t");
            if ((typeDef.flags & DefineConstants.TYPE_ATTRIBUTE_VISIBILITY_MASK) == DefineConstants.TYPE_ATTRIBUTE_PUBLIC)
            {
                writer.Write("public ");
            }
            writer.Write("enum {\n");
            var fieldEnd = typeDef.fieldStart + typeDef.field_count;

            for (int i = typeDef.fieldStart + 1; i < fieldEnd; ++i)
            {
                var pField       = metadata.Fields[i];
                var defaultValue = this.GetDefaultValue(i);
                writer.Write($"\t\t{metadata.GetString(pField.nameIndex)} = {defaultValue}\n");
            }
            writer.Write("\t}\n\n");
        }
        internal void WriteType(StreamWriter writer, Il2CppTypeDefinition typeDef)
        {
            if ((typeDef.flags & DefineConstants.TYPE_ATTRIBUTE_INTERFACE) != 0)
            {
                return;
            }

            var nameSpace = metadata.GetTypeNamespace(typeDef);

            if (nameSpace.Length > 0)
            {
                nameSpace += ".";
            }

            var typeName = metadata.GetTypeName(typeDef);

            writer.Write($"struct {typeName}");

            if (typeDef.parentIndex >= 0)
            {
                var pType = il2cpp.Code.GetTypeFromTypeIndex(typeDef.parentIndex);
                var name  = il2cpp.GetTypeName(pType);
                if (name == "object")
                {
                    writer.Write($" : public Il2CppObject");
                }
                else if (name != "ValueType")
                {
                    writer.Write($" : public {name}");
                }
            }

            writer.Write("\n{\n");

            this.WriteFields(writer, typeDef);

            writer.Write("}\n\n");
        }
Exemple #11
0
        internal void WriteType(StreamWriter writer, Il2CppTypeDefinition typeDef)
        {
            if ((typeDef.flags & DefineConstants.TYPE_ATTRIBUTE_SERIALIZABLE) != 0)
            {
                writer.Write("\t[Serializable]\n");
            }
            writer.Write("\t");
            if ((typeDef.flags & DefineConstants.TYPE_ATTRIBUTE_VISIBILITY_MASK) == DefineConstants.TYPE_ATTRIBUTE_PUBLIC)
            {
                writer.Write("public ");
            }
            if ((typeDef.flags & DefineConstants.TYPE_ATTRIBUTE_ABSTRACT) != 0)
            {
                writer.Write("abstract ");
            }
            if ((typeDef.flags & DefineConstants.TYPE_ATTRIBUTE_SEALED) != 0)
            {
                writer.Write("sealed ");
            }

            if ((typeDef.flags & DefineConstants.TYPE_ATTRIBUTE_INTERFACE) != 0)
            {
                writer.Write("interface ");
            }
            else
            {
                writer.Write("class ");
            }

            var nameSpace = metadata.GetTypeNamespace(typeDef);

            if (nameSpace.Length > 0)
            {
                nameSpace += ".";
            }

            writer.Write($"{nameSpace}{metadata.GetTypeName(typeDef)}");

            var yes = typeDef.vtable_count == typeDef.method_count;

            yes.ToString();

            // class implements an interface
            //if (typeDef.interfaces_count > 0)
            //{
            //    var maxInterface = typeDef.interfacesStart + typeDef.interfaces_count;
            //    for (var i = typeDef.interfacesStart; i < maxInterface; i++)
            //    {
            //        var pInterface = metadata.Interfaces[i];
            //        //var pType = il2cpp.Code.GetTypeFromTypeIndex(pInterface.);
            //        //var name = il2cpp.GetTypeName(pType);
            //        var name = metadata.GetString(pInterface.nameIndex);
            //        writer.Write($" implements {name}");
            //    }
            //}

            // class extenss another type
            if (typeDef.parentIndex >= 0)
            {
                var pType = il2cpp.Code.GetTypeFromTypeIndex(typeDef.parentIndex);
                var name  = il2cpp.GetTypeName(pType);
                if (name != "object")
                {
                    writer.Write($" extends {name}");
                }
            }

            writer.Write("\n\t{\n");

            this.WriteFields(writer, typeDef);
            this.WriteMethods(writer, typeDef);

            writer.Write("\t}\n\n");
        }
Exemple #12
0
        internal void WriteMethods(StreamWriter writer, Il2CppTypeDefinition typeDef)
        {
            if (typeDef.method_count <= 0)
            {
                return;
            }

            writer.Write("\t\t// Methods\n");
            var methodEnd = typeDef.methodStart + typeDef.method_count;

            for (int i = typeDef.methodStart; i < methodEnd; ++i)
            {
                var methodDef = metadata.Methods[i];

                if (methodDef.methodIndex >= 0)
                {
                    var ptr = il2cpp.Code.MethodPointers[methodDef.methodIndex];
                    writer.Write("\t\t// Offset: 0x{0:x}\n", ptr);
                }
                else
                {
                    writer.Write("\t\t// Offset: ?\n");
                }

                writer.Write("\t\t");
                var pReturnType = il2cpp.Code.GetTypeFromTypeIndex(methodDef.returnType);
                if ((methodDef.flags & DefineConstants.METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) ==
                    DefineConstants.METHOD_ATTRIBUTE_PRIVATE)
                {
                    writer.Write("private ");
                }
                if ((methodDef.flags & DefineConstants.METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) ==
                    DefineConstants.METHOD_ATTRIBUTE_PUBLIC)
                {
                    writer.Write("public ");
                }
                if ((methodDef.flags & DefineConstants.METHOD_ATTRIBUTE_VIRTUAL) != 0)
                {
                    writer.Write("virtual ");
                }
                if ((methodDef.flags & DefineConstants.METHOD_ATTRIBUTE_STATIC) != 0)
                {
                    writer.Write("static ");
                }

                var methodName = metadata.GetString(methodDef.nameIndex);
                writer.Write($"{il2cpp.GetTypeName(pReturnType)} {methodName}(");
                for (int j = 0; j < methodDef.parameterCount; ++j)
                {
                    Il2CppParameterDefinition pParam = metadata.parameterDefs[methodDef.parameterStart + j];
                    string szParamName = metadata.GetString(pParam.nameIndex);
                    var    pType       = il2cpp.Code.GetTypeFromTypeIndex(pParam.typeIndex);
                    string szTypeName  = il2cpp.GetTypeName(pType);
                    if ((pType.attrs & DefineConstants.PARAM_ATTRIBUTE_OPTIONAL) != 0)
                    {
                        writer.Write("optional ");
                    }
                    if ((pType.attrs & DefineConstants.PARAM_ATTRIBUTE_OUT) != 0)
                    {
                        writer.Write("out ");
                    }
                    if (j != methodDef.parameterCount - 1)
                    {
                        writer.Write($"{szTypeName} {szParamName}, ");
                    }
                    else
                    {
                        writer.Write($"{szTypeName} {szParamName}");
                    }
                }
                writer.Write(");\n");
            }
        }
Exemple #13
0
 private void WriteType(StreamWriter writer, Il2CppTypeDefinition typeDef)
 {
 }
Exemple #14
0
        internal static string GetTypeName(Il2CppMetadata metadata, PE.PE cppAssembly, Il2CppTypeDefinition typeDef)
        {
            var ret = String.Empty;

            if (typeDef.declaringTypeIndex != -1)
            {
                ret += GetTypeName(metadata, cppAssembly, cppAssembly.types[typeDef.declaringTypeIndex]) + ".";
            }

            ret += metadata.GetStringFromIndex(typeDef.nameIndex);
            var names = new List <string>();

            if (typeDef.genericContainerIndex >= 0)
            {
                var genericContainer = metadata.genericContainers[typeDef.genericContainerIndex];
                for (int i = 0; i < genericContainer.type_argc; i++)
                {
                    var genericParameterIndex = genericContainer.genericParameterStart + i;
                    var param = metadata.genericParameters[genericParameterIndex];
                    names.Add(metadata.GetStringFromIndex(param.nameIndex));
                }

                ret  = ret.Replace($"`{genericContainer.type_argc}", "");
                ret += $"<{String.Join(", ", names)}>";
            }

            return(ret);
        }
Exemple #15
0
        private static List <CppMethodData> ProcessTypeContents(Il2CppMetadata metadata, PE.PE cppAssembly, Il2CppTypeDefinition cppTypeDefinition, TypeDefinition ilTypeDefinition)
        {
            var typeMetaText = new StringBuilder();

            typeMetaText.Append($"Type: {ilTypeDefinition.FullName}:")
            .Append($"\n\tBase Class: \n\t\t{ilTypeDefinition.BaseType}\n")
            .Append("\n\tInterfaces:\n");

            foreach (var iface in ilTypeDefinition.Interfaces)
            {
                typeMetaText.Append($"\t\t{iface.InterfaceType.FullName}\n");
            }

            //field
            var fields = new List <FieldInType>();

            var baseFields = new List <FieldDefinition>();

            var current = ilTypeDefinition;

            while (current.BaseType != null)
            {
                var targetName = current.BaseType.FullName;
                if (targetName.Contains("<"))   // types with generic parameters (Type'1<T>) are stored as Type'1, so I just removed the part that causes trouble and called it a day
                {
                    targetName = targetName.Substring(0, targetName.IndexOf("<"));
                }

                current = SharedState.AllTypeDefinitions.Find(t => t.FullName == targetName);

                if (current == null)
                {
                    typeMetaText.Append("WARN: Type " + targetName + " is not defined yet\n");
                    break;
                }

                baseFields.InsertRange(0, current.Fields.Where(f => !f.IsStatic));   // each loop we go one inheritage level deeper, so these "new" fields should be inserted before the previous ones
            }

            //Handle base fields
            var fieldOffset = baseFields.Aggregate((ulong)(ilTypeDefinition.MetadataType == MetadataType.Class ? 0x10 : 0x0), (currentOffset, baseField) => HandleField(baseField.FieldType, currentOffset, baseField.Name, baseField, ref fields, typeMetaText));

            var lastFieldIdx = cppTypeDefinition.firstFieldIdx + cppTypeDefinition.field_count;

            for (var fieldIdx = cppTypeDefinition.firstFieldIdx; fieldIdx < lastFieldIdx; ++fieldIdx)
            {
                var fieldDef     = metadata.fieldDefs[fieldIdx];
                var fieldType    = cppAssembly.types[fieldDef.typeIndex];
                var fieldName    = metadata.GetStringFromIndex(fieldDef.nameIndex);
                var fieldTypeRef = Utils.ImportTypeInto(ilTypeDefinition, fieldType, cppAssembly, metadata);

                var fieldDefinition = new FieldDefinition(fieldName, (FieldAttributes)fieldType.attrs, fieldTypeRef);
                ilTypeDefinition.Fields.Add(fieldDefinition);

                //Field default values
                if (fieldDefinition.HasDefault)
                {
                    var fieldDefault = metadata.GetFieldDefaultValueFromIndex(fieldIdx);
                    if (fieldDefault != null && fieldDefault.dataIndex != -1)
                    {
                        fieldDefinition.Constant = Utils.GetDefaultValue(fieldDefault.dataIndex,
                                                                         fieldDefault.typeIndex, metadata, cppAssembly);
                    }
                }

                if (!fieldDefinition.IsStatic)
                {
                    fieldOffset = HandleField(fieldTypeRef, fieldOffset, fieldName, fieldDefinition, ref fields, typeMetaText);
                }
            }

            fields.Sort(); //By offset
            SharedState.FieldsByType[ilTypeDefinition] = fields;

            //Methods
            var lastMethodId = cppTypeDefinition.firstMethodId + cppTypeDefinition.method_count;
            var typeMethods  = new List <CppMethodData>();
            Il2CppGenericContainer genericContainer;

            for (var methodId = cppTypeDefinition.firstMethodId; methodId < lastMethodId; ++methodId)
            {
                var methodDef        = metadata.methodDefs[methodId];
                var methodReturnType = cppAssembly.types[methodDef.returnType];
                var methodName       = metadata.GetStringFromIndex(methodDef.nameIndex);
                var methodDefinition = new MethodDefinition(methodName, (MethodAttributes)methodDef.flags,
                                                            ilTypeDefinition.Module.ImportReference(typeof(void)));

                //TODO: For Unity 2019 we'll need to fix the imageindex param from 0 to the actual index
                var offsetInRam = cppAssembly.GetMethodPointer(methodDef.methodIndex, methodId, 0, methodDef.token);


                long offsetInFile = offsetInRam == 0 ? 0 : cppAssembly.MapVirtualAddressToRaw(offsetInRam);
                typeMetaText.Append($"\n\tMethod: {methodName}:\n")
                .Append($"\t\tFile Offset 0x{offsetInFile:X8}\n")
                .Append($"\t\tRam Offset 0x{offsetInRam:x8}\n")
                .Append($"\t\tVirtual Method Slot: {methodDef.slot}\n");

                var bytes  = new List <byte>();
                var offset = offsetInFile;
                while (true)
                {
                    var b = cppAssembly.raw[offset];
                    if (b == 0xC3 && cppAssembly.raw[offset + 1] == 0xCC)
                    {
                        break;
                    }
                    if (b == 0xCC && bytes.Count > 0 && (bytes.Last() == 0xcc || bytes.Last() == 0xc3))
                    {
                        break;
                    }
                    bytes.Add(b);
                    offset++;
                }

                typeMetaText.Append($"\t\tMethod Length: {bytes.Count} bytes\n");

                typeMethods.Add(new CppMethodData
                {
                    MethodName      = methodName,
                    MethodId        = methodId,
                    MethodBytes     = bytes.ToArray(),
                    MethodOffsetRam = offsetInRam
                });


                ilTypeDefinition.Methods.Add(methodDefinition);
                methodDefinition.ReturnType = Utils.ImportTypeInto(methodDefinition, methodReturnType, cppAssembly, metadata);
                if (methodDefinition.HasBody && ilTypeDefinition.BaseType?.FullName != "System.MulticastDelegate")
                {
                    var ilprocessor = methodDefinition.Body.GetILProcessor();
                    ilprocessor.Append(ilprocessor.Create(OpCodes.Nop));
                }

                SharedState.MethodsByIndex.Add(methodId, methodDefinition);
                //Method Params
                for (var paramIdx = 0; paramIdx < methodDef.parameterCount; ++paramIdx)
                {
                    var parameterDef        = metadata.parameterDefs[methodDef.parameterStart + paramIdx];
                    var parameterName       = metadata.GetStringFromIndex(parameterDef.nameIndex);
                    var parameterType       = cppAssembly.types[parameterDef.typeIndex];
                    var parameterTypeRef    = Utils.ImportTypeInto(methodDefinition, parameterType, cppAssembly, metadata);
                    var parameterDefinition = new ParameterDefinition(parameterName, (ParameterAttributes)parameterType.attrs, parameterTypeRef);
                    methodDefinition.Parameters.Add(parameterDefinition);
                    //Default values for params
                    if (parameterDefinition.HasDefault)
                    {
                        var parameterDefault = metadata.GetParameterDefaultValueFromIndex(methodDef.parameterStart + paramIdx);
                        if (parameterDefault != null && parameterDefault.dataIndex != -1)
                        {
                            parameterDefinition.Constant = Utils.GetDefaultValue(parameterDefault.dataIndex, parameterDefault.typeIndex, metadata, cppAssembly);
                        }
                    }


                    typeMetaText.Append($"\n\t\tParameter {paramIdx}:\n")
                    .Append($"\t\t\tName: {parameterName}\n")
                    .Append($"\t\t\tType: {(parameterTypeRef.Namespace == "" ? "<None>" : parameterTypeRef.Namespace)}.{parameterTypeRef.Name}\n")
                    .Append($"\t\t\tDefault Value: {parameterDefinition.Constant}");
                }

                if (methodDef.genericContainerIndex >= 0)
                {
                    genericContainer = metadata.genericContainers[methodDef.genericContainerIndex];
                    if (genericContainer.type_argc > methodDefinition.GenericParameters.Count)
                    {
                        for (var j = 0; j < genericContainer.type_argc; j++)
                        {
                            var genericParameterIndex = genericContainer.genericParameterStart + j;
                            var param       = metadata.genericParameters[genericParameterIndex];
                            var genericName = metadata.GetStringFromIndex(param.nameIndex);
                            if (!SharedState.GenericParamsByIndex.TryGetValue(genericParameterIndex,
                                                                              out var genericParameter))
                            {
                                genericParameter = new GenericParameter(genericName, methodDefinition);
                                methodDefinition.GenericParameters.Add(genericParameter);
                                SharedState.GenericParamsByIndex.Add(genericParameterIndex, genericParameter);
                            }
                            else
                            {
                                if (!methodDefinition.GenericParameters.Contains(genericParameter))
                                {
                                    methodDefinition.GenericParameters.Add(genericParameter);
                                }
                            }
                        }
                    }
                }

                if (methodDef.slot < ushort.MaxValue)
                {
                    SharedState.VirtualMethodsBySlot[methodDef.slot] = methodDefinition;
                }

                SharedState.MethodsByAddress[offsetInRam] = methodDefinition;
            }

            //Properties
            var lastPropertyId = cppTypeDefinition.firstPropertyId + cppTypeDefinition.propertyCount;

            for (var propertyId = cppTypeDefinition.firstPropertyId; propertyId < lastPropertyId; ++propertyId)
            {
                var              propertyDef  = metadata.propertyDefs[propertyId];
                var              propertyName = metadata.GetStringFromIndex(propertyDef.nameIndex);
                TypeReference    propertyType = null;
                MethodDefinition getter       = null;
                MethodDefinition setter       = null;
                if (propertyDef.get >= 0)
                {
                    getter       = SharedState.MethodsByIndex[cppTypeDefinition.firstMethodId + propertyDef.get];
                    propertyType = getter.ReturnType;
                }

                if (propertyDef.set >= 0)
                {
                    setter = SharedState.MethodsByIndex[cppTypeDefinition.firstMethodId + propertyDef.set];
                    if (propertyType == null)
                    {
                        propertyType = setter.Parameters[0].ParameterType;
                    }
                }

                var propertyDefinition = new PropertyDefinition(propertyName, (PropertyAttributes)propertyDef.attrs, propertyType)
                {
                    GetMethod = getter,
                    SetMethod = setter
                };
                ilTypeDefinition.Properties.Add(propertyDefinition);
            }

            //Events
            var lastEventId = cppTypeDefinition.firstEventId + cppTypeDefinition.eventCount;

            for (var eventId = cppTypeDefinition.firstEventId; eventId < lastEventId; ++eventId)
            {
                var eventDef        = metadata.eventDefs[eventId];
                var eventName       = metadata.GetStringFromIndex(eventDef.nameIndex);
                var eventType       = cppAssembly.types[eventDef.typeIndex];
                var eventTypeRef    = Utils.ImportTypeInto(ilTypeDefinition, eventType, cppAssembly, metadata);
                var eventDefinition = new EventDefinition(eventName, (EventAttributes)eventType.attrs, eventTypeRef);
                if (eventDef.add >= 0)
                {
                    eventDefinition.AddMethod = SharedState.MethodsByIndex[cppTypeDefinition.firstMethodId + eventDef.add];
                }
                if (eventDef.remove >= 0)
                {
                    eventDefinition.RemoveMethod = SharedState.MethodsByIndex[cppTypeDefinition.firstMethodId + eventDef.remove];
                }
                if (eventDef.raise >= 0)
                {
                    eventDefinition.InvokeMethod = SharedState.MethodsByIndex[cppTypeDefinition.firstMethodId + eventDef.raise];
                }
                ilTypeDefinition.Events.Add(eventDefinition);
            }

            File.WriteAllText(Path.Combine(Path.GetFullPath("cpp2il_out"), "types", ilTypeDefinition.Module.Assembly.Name.Name, ilTypeDefinition.Name.Replace("<", "_").Replace(">", "_") + "_metadata.txt"), typeMetaText.ToString());

            if (cppTypeDefinition.genericContainerIndex < 0)
            {
                return(typeMethods);                                             //Finished processing if not generic
            }
            genericContainer = metadata.genericContainers[cppTypeDefinition.genericContainerIndex];
            if (genericContainer.type_argc <= ilTypeDefinition.GenericParameters.Count)
            {
                return(typeMethods);                                                                        //Finished processing
            }
            for (var i = 0; i < genericContainer.type_argc; i++)
            {
                var genericParameterIndex = genericContainer.genericParameterStart + i;
                var param       = metadata.genericParameters[genericParameterIndex];
                var genericName = metadata.GetStringFromIndex(param.nameIndex);
                if (!SharedState.GenericParamsByIndex.TryGetValue(genericParameterIndex, out var genericParameter))
                {
                    genericParameter = new GenericParameter(genericName, ilTypeDefinition);
                    ilTypeDefinition.GenericParameters.Add(genericParameter);
                    SharedState.GenericParamsByIndex.Add(genericParameterIndex, genericParameter);
                }
                else
                {
                    if (ilTypeDefinition.GenericParameters.Contains(genericParameter))
                    {
                        continue;
                    }
                    ilTypeDefinition.GenericParameters.Add(genericParameter);
                }
            }

            return(typeMethods);
        }
        internal void WriteType(StreamWriter writer, Il2CppTypeDefinition typeDef)
        {
            if ((typeDef.flags & DefineConstants.TYPE_ATTRIBUTE_SERIALIZABLE) != 0)
            {
                writer.Write("\t[Serializable]\n");
            }

            WriteAttribute(writer, typeDef.customAttributeIndex, "\t");

            var    isStruct = false;
            string parent   = null;

            if (typeDef.parentIndex >= 0)
            {
                var pType = il2cpp.Code.GetTypeFromTypeIndex(typeDef.parentIndex);
                var name  = il2cpp.GetTypeName(pType);
                if (name == "ValueType")
                {
                    isStruct = true;
                }
                else if (name != "object")
                {
                    parent = name;
                }
            }

            writer.Write("\t");
            if ((typeDef.flags & DefineConstants.TYPE_ATTRIBUTE_VISIBILITY_MASK) == DefineConstants.TYPE_ATTRIBUTE_PUBLIC)
            {
                writer.Write("public ");
            }
            if ((typeDef.flags & DefineConstants.TYPE_ATTRIBUTE_ABSTRACT) != 0)
            {
                writer.Write("abstract ");
            }
            if (!isStruct && (typeDef.flags & DefineConstants.TYPE_ATTRIBUTE_SEALED) != 0)
            {
                writer.Write("sealed ");
            }

            if ((typeDef.flags & DefineConstants.TYPE_ATTRIBUTE_INTERFACE) != 0)
            {
                writer.Write("interface ");
            }
            else if (isStruct)
            {
                writer.Write("struct ");
            }
            else
            {
                writer.Write("class ");
            }

            var nameSpace = metadata.GetTypeNamespace(typeDef);

            if (nameSpace.Length > 0)
            {
                nameSpace += ".";
            }

            writer.Write($"{nameSpace}{metadata.GetTypeName(typeDef)}");

            var yes = typeDef.vtable_count == typeDef.method_count;

            yes.ToString();


            // class extenss another type
            if (parent != null)
            {
                writer.Write($" : {parent}");
            }

            writer.Write("\n\t{\n");

            this.WriteFields(writer, typeDef);
            this.WriteMethods(writer, typeDef);

            writer.Write("\t}\n\n");
        }
Exemple #17
0
        internal void WriteType(StreamWriter writer, Il2CppTypeDefinition typeDef, string pad = "")
        {
            if ((typeDef.flags & DefineConstants.TYPE_ATTRIBUTE_ABSTRACT) != 0)
            {
                return;
            }
            var typesToDump = new List <GenericIl2CppType>();

            writer.Write("\n");
            writer.Write(pad + $"message {metadata.GetTypeName(typeDef)} {{\n");

            var methodsReturn = new Dictionary <string, GenericIl2CppType>();
            var methodEnd     = typeDef.methodStart + typeDef.method_count;

            for (int i = typeDef.methodStart; i < methodEnd; ++i)
            {
                var methodDef   = metadata.Methods[i];
                var name        = metadata.GetString(methodDef.nameIndex);
                var pReturnType = il2cpp.Code.GetTypeFromTypeIndex(methodDef.returnType);
                methodsReturn[name] = pReturnType;
            }

            var fieldEnd = typeDef.fieldStart + typeDef.field_count;

            for (int i = typeDef.fieldStart; i < fieldEnd; ++i)
            {
                var pField    = metadata.Fields[i];
                var fieldName = metadata.GetString(pField.nameIndex);
                if (fieldName.EndsWith("FieldNumber"))
                {
                    var realName   = fieldName.Substring(0, fieldName.Length - "FieldNumber".Length);
                    var protoIndex = this.GetDefaultValue(i);

                    var getter = "get_" + realName;
                    var pType  = methodsReturn[getter];

                    realName = this.ToSnakeCase(realName);
                    var realType = this.GetProtoType(il2cpp.GetTypeName(methodsReturn[getter]), realName);

                    writer.Write(pad + $"\t{realType} {realName} = {protoIndex};\n");

                    if (pType.type == Il2CppTypeEnum.IL2CPP_TYPE_VALUETYPE || pType.type == Il2CppTypeEnum.IL2CPP_TYPE_GENERICINST)
                    {
                        typesToDump.Add(pType);
                    }
                }
            }

            foreach (var pType in typesToDump)
            {
                var realType = pType;
                if (realType.type == Il2CppTypeEnum.IL2CPP_TYPE_GENERICINST)
                {
                    realType = il2cpp.GetTypeFromGeneric(realType);
                }
                var subtypeDef = metadata.Types[realType.klassIndex];
                if (realType.type == Il2CppTypeEnum.IL2CPP_TYPE_VALUETYPE || realType.type == Il2CppTypeEnum.IL2CPP_TYPE_CLASS)
                {
                    if (!holoTypes.Any(t => t.nameIndex == subtypeDef.nameIndex))
                    {
                        if (subtypeDef.parentIndex == enumIdx)
                        {
                            this.WriteEnum(writer, subtypeDef, pad + "\t");
                        }
                        else
                        {
                            this.WriteType(writer, subtypeDef, pad + "\t");
                        }
                    }
                }
            }

            writer.Write(pad + "}\n");
        }
Exemple #18
0
        internal void WriteType(StreamWriter writer, Il2CppTypeDefinition typeDef)
        {
            if ((typeDef.flags & DefineConstants.TYPE_ATTRIBUTE_SERIALIZABLE) != 0)
            {
                writer.Write("\t[Serializable]\n");
            }

            WriteAttribute(writer, typeDef.customAttributeIndex, "\t");

            var    isStruct = false;
            string parent   = null;

            if (typeDef.parentIndex >= 0)
            {
                var pType = il2cpp.Code.GetTypeFromTypeIndex(typeDef.parentIndex);
                var name  = il2cpp.GetTypeName(pType);
                if (name == "ValueType")
                {
                    isStruct = true;
                }
                else if (name != "object")
                {
                    if (pType.type == Il2CppTypeEnum.IL2CPP_TYPE_CLASS)
                    {
                        var klass           = metadata.Types[pType.klassIndex];
                        var parentNameSpace = metadata.GetTypeNamespace(klass);
                        if (parentNameSpace.Length > 0)
                        {
                            parentNameSpace += ".";
                        }
                        parent = parentNameSpace + name;
                    }
                    else
                    {
                        parent = name;
                    }
                }
            }

            writer.Write("\t");
            if ((typeDef.flags & DefineConstants.TYPE_ATTRIBUTE_VISIBILITY_MASK) == DefineConstants.TYPE_ATTRIBUTE_PUBLIC)
            {
                writer.Write("public ");
            }
            if ((typeDef.flags & DefineConstants.TYPE_ATTRIBUTE_ABSTRACT) != 0)
            {
                writer.Write("abstract ");
            }
            if (!isStruct && (typeDef.flags & DefineConstants.TYPE_ATTRIBUTE_SEALED) != 0)
            {
                writer.Write("sealed ");
            }

            if ((typeDef.flags & DefineConstants.TYPE_ATTRIBUTE_INTERFACE) != 0)
            {
                writer.Write("interface ");
            }
            else if (isStruct)
            {
                writer.Write("struct ");
            }
            else
            {
                writer.Write("class ");
            }

            var nameSpace = metadata.GetTypeNamespace(typeDef);

            if (nameSpace.Length > 0)
            {
                nameSpace += ".";
            }

            writer.Write($"{nameSpace}{metadata.GetTypeName(typeDef)}");

            // class extends another type
            if (parent != null)
            {
                writer.Write($" : {parent}");
            }

            writer.Write("\n\t{\n");

            if (this.IncludeOffsets && typeDef.delegateWrapperFromManagedToNativeIndex >= 0)
            {
                var nativeIdx = typeDef.delegateWrapperFromManagedToNativeIndex;
                var ptr       = il2cpp.Code.ManagedToNative[nativeIdx];
                writer.Write("\t\t// Native method : 0x{0:x}\n", ptr);
            }

            this.WriteFields(writer, typeDef);
            this.WriteMethods(writer, typeDef);

            writer.Write("\t}\n\n");
        }