private void AddVTableMethod(StructInfo structInfo, Il2CppTypeDefinition typeDef) { var dic = new SortedDictionary <int, Il2CppMethodDefinition>(); for (int i = 0; i < typeDef.vtable_count; i++) { var vTableIndex = typeDef.vtableStart + i; var encodedMethodIndex = metadata.vtableMethods[vTableIndex]; var usage = metadata.GetEncodedIndexType(encodedMethodIndex); var index = metadata.GetDecodedMethodIndex(encodedMethodIndex); Il2CppMethodDefinition methodDef; if (usage == 6) //kIl2CppMetadataUsageMethodRef { var methodSpec = il2Cpp.methodSpecs[index]; methodDef = metadata.methodDefs[methodSpec.methodDefinitionIndex]; } else { methodDef = metadata.methodDefs[index]; } dic[methodDef.slot] = methodDef; } foreach (var i in dic) { var methodInfo = new StructVTableMethodInfo(); structInfo.VTableMethod.Add(methodInfo); var methodDef = i.Value; methodInfo.MethodName = $"_{methodDef.slot}_{FixName(metadata.GetStringFromIndex(methodDef.nameIndex))}"; } }
private void AddFields(Il2CppTypeDefinition typeDef, StructInfo structInfo, Il2CppGenericContext context) { if (typeDef.field_count > 0) { var fieldEnd = typeDef.fieldStart + typeDef.field_count; for (var i = typeDef.fieldStart; i < fieldEnd; ++i) { var fieldDef = metadata.fieldDefs[i]; var fieldType = il2Cpp.types[fieldDef.typeIndex]; if ((fieldType.attrs & FIELD_ATTRIBUTE_LITERAL) != 0) { continue; } var structFieldInfo = new StructFieldInfo(); structFieldInfo.FieldTypeName = ParseType(fieldType, context); var fieldName = FixName(metadata.GetStringFromIndex(fieldDef.nameIndex)); structFieldInfo.FieldName = fieldName; structFieldInfo.IsValueType = IsValueType(fieldType, context); if ((fieldType.attrs & FIELD_ATTRIBUTE_STATIC) != 0) { structInfo.StaticFields.Add(structFieldInfo); } else { structInfo.Fields.Add(structFieldInfo); } } } }
private void AddParents(Il2CppTypeDefinition typeDef, StructInfo structInfo) { if (!typeDef.IsValueType && !typeDef.IsEnum) { if (typeDef.parentIndex >= 0) { var parent = il2Cpp.types[typeDef.parentIndex]; var parentDef = GetTypeDefinition(parent); if (parentDef != null) { AddParents(parentDef, structInfo); if (parentDef.field_count > 0) { var fieldEnd = parentDef.fieldStart + parentDef.field_count; for (var i = parentDef.fieldStart; i < fieldEnd; ++i) { var fieldDef = metadata.fieldDefs[i]; var fieldType = il2Cpp.types[fieldDef.typeIndex]; if ((fieldType.attrs & FIELD_ATTRIBUTE_LITERAL) == 0 && (fieldType.attrs & FIELD_ATTRIBUTE_STATIC) == 0) { structInfo.Parents.Add(GetIl2CppStructName(parent)); break; } } } } } } }
private void AddStruct(Il2CppTypeDefinition typeDef) { var structInfo = new StructInfo(); structInfoList.Add(structInfo); structInfo.TypeName = structNameDic[typeDef]; structInfo.IsValueType = typeDef.IsValueType; AddFields(typeDef, structInfo.Fields, structInfo.StaticFields, null, false); AddVTableMethod(structInfo, typeDef); }
private void AddGenericClassStruct(ulong pointer) { var genericClass = il2Cpp.MapVATR <Il2CppGenericClass>(pointer); var typeDef = metadata.typeDefs[genericClass.typeDefinitionIndex]; var structInfo = new StructInfo(); structInfoList.Add(structInfo); structInfo.TypeName = genericClassStructNameDic[pointer]; structInfo.IsValueType = typeDef.IsValueType; AddFields(typeDef, structInfo.Fields, structInfo.StaticFields, genericClass.context, false); AddVTableMethod(structInfo, typeDef); }
private void AddStruct(Il2CppTypeDefinition typeDef) { var structInfo = new StructInfo(); structInfoList.Add(structInfo); structInfo.TypeName = structNameDic[typeDef]; structInfo.IsValueType = typeDef.IsValueType; AddParents(typeDef, structInfo); AddFields(typeDef, structInfo, null); AddVTableMethod(structInfo, typeDef); AddRGCTX(structInfo, typeDef); }
private string RecursionStructInfo(StructInfo info) { if (!structCache.Add(info)) { return(string.Empty); } var sb = new StringBuilder(); var pre = new StringBuilder(); sb.Append($"struct {info.TypeName}_o {{\n"); foreach (var field in info.Fields) { if (field.IsValueType) { var fieldInfo = structInfoWithStructName[field.FieldTypeName]; pre.Append(RecursionStructInfo(fieldInfo)); } sb.Append($"\t{field.FieldTypeName} {field.FieldName};\n"); } sb.Append("};\n"); sb.Append($"struct {info.TypeName}_StaticFields {{\n"); foreach (var field in info.StaticFields) { if (field.IsValueType) { var fieldInfo = structInfoWithStructName[field.FieldTypeName]; pre.Append(RecursionStructInfo(fieldInfo)); } sb.Append($"\t{field.FieldTypeName} {field.FieldName};\n"); } sb.Append("};\n"); sb.Append($"struct {info.TypeName}_VTable {{\n"); foreach (var method in info.VTableMethod) { sb.Append($"\tVirtualInvokeData {method.MethodName};\n"); } sb.Append("};\n"); sb.Append($"struct {info.TypeName}_c {{\n" + $"\tIl2CppClass_1 _1;\n" + $"\t{info.TypeName}_StaticFields* static_fields;\n" + $"\tIl2CppClass_2 _2;\n" + $"\t{info.TypeName}_VTable vtable;\n" + $"}};\n"); return(pre.Append(sb).ToString()); }
private void AddRGCTX(StructInfo structInfo, Il2CppTypeDefinition typeDef) { var imageIndex = typeDefImageIndices[typeDef]; var collection = executor.GetTypeRGCTXDefinition(typeDef, imageIndex); if (collection != null) { foreach (var definitionData in collection) { var structRGCTXInfo = new StructRGCTXInfo(); structInfo.RGCTXs.Add(structRGCTXInfo); structRGCTXInfo.Type = definitionData.type; switch (definitionData.type) { case Il2CppRGCTXDataType.IL2CPP_RGCTX_DATA_TYPE: { var il2CppType = il2Cpp.types[definitionData.data.typeIndex]; structRGCTXInfo.TypeName = FixName(executor.GetTypeName(il2CppType, true, false)); break; } case Il2CppRGCTXDataType.IL2CPP_RGCTX_DATA_CLASS: { var il2CppType = il2Cpp.types[definitionData.data.typeIndex]; structRGCTXInfo.ClassName = FixName(executor.GetTypeName(il2CppType, true, false)); break; } case Il2CppRGCTXDataType.IL2CPP_RGCTX_DATA_METHOD: { var methodSpec = il2Cpp.methodSpecs[definitionData.data.methodIndex]; (var methodSpecTypeName, var methodSpecMethodName) = executor.GetMethodSpecName(methodSpec, true); structRGCTXInfo.MethodName = FixName(methodSpecTypeName + "." + methodSpecMethodName); break; } } } } }
private string RecursionStructInfo(StructInfo info) { if (!structCache.Add(info)) { return(string.Empty); } var sb = new StringBuilder(); var pre = new StringBuilder(); sb.Append($"struct {info.TypeName}_Fields {{\n"); foreach (var field in info.Fields) { if (field.IsValueType) { var fieldInfo = structInfoWithStructName[field.FieldTypeName]; pre.Append(RecursionStructInfo(fieldInfo)); } sb.Append($"\t{field.FieldTypeName} {field.FieldName};\n"); } sb.Append("};\n"); sb.Append($"struct {info.TypeName}_RGCTXs {{\n"); for (int i = 0; i < info.RGCTXs.Count; i++) { var rgctx = info.RGCTXs[i]; switch (rgctx.Type) { case Il2CppRGCTXDataType.IL2CPP_RGCTX_DATA_TYPE: sb.Append($"\tIl2CppType* _{i}_{rgctx.TypeName};\n"); break; case Il2CppRGCTXDataType.IL2CPP_RGCTX_DATA_CLASS: sb.Append($"\tIl2CppClass* _{i}_{rgctx.ClassName};\n"); break; case Il2CppRGCTXDataType.IL2CPP_RGCTX_DATA_METHOD: sb.Append($"\tMethodInfo* _{i}_{rgctx.MethodName};\n"); break; } } sb.Append("};\n"); sb.Append($"struct {info.TypeName}_VTable {{\n"); foreach (var method in info.VTableMethod) { sb.Append($"\tVirtualInvokeData {method.MethodName};\n"); } sb.Append("};\n"); sb.Append($"struct {info.TypeName}_c {{\n" + $"\tIl2CppClass_1 _1;\n" + $"\tstruct {info.TypeName}_StaticFields* static_fields;\n" + $"\t{info.TypeName}_RGCTXs* rgctx_data;\n" + $"\tIl2CppClass_2 _2;\n" + $"\t{info.TypeName}_VTable vtable;\n" + $"}};\n"); sb.Append($"struct {info.TypeName}_o {{\n"); if (!info.IsValueType) { sb.Append($"\t{info.TypeName}_c *klass;\n"); sb.Append($"\tvoid *monitor;\n"); } for (int i = 0; i < info.Parents.Count; i++) { var parent = info.Parents[i]; var parentStructName = parent + "_o"; pre.Append(RecursionStructInfo(structInfoWithStructName[parentStructName])); sb.Append($"\t{parent}_Fields parent_fields_{i};\n"); } sb.Append($"\t{info.TypeName}_Fields fields;\n"); sb.Append("};\n"); sb.Append($"struct {info.TypeName}_StaticFields {{\n"); foreach (var field in info.StaticFields) { if (field.IsValueType) { var fieldInfo = structInfoWithStructName[field.FieldTypeName]; pre.Append(RecursionStructInfo(fieldInfo)); } sb.Append($"\t{field.FieldTypeName} {field.FieldName};\n"); } sb.Append("};\n"); return(pre.Append(sb).ToString()); }