完善泛型相关输出

This commit is contained in:
Perfare 2020-06-19 12:04:15 +08:00
parent bbe3a7cec3
commit 5ab028807c
4 changed files with 97 additions and 35 deletions

View file

@ -20,9 +20,11 @@ namespace Il2CppDumper
private Dictionary<ulong, Il2CppType> typeDic = new Dictionary<ulong, Il2CppType>(); private Dictionary<ulong, Il2CppType> typeDic = new Dictionary<ulong, Il2CppType>();
public ulong[] metadataUsages; public ulong[] metadataUsages;
private Il2CppGenericMethodFunctionsDefinitions[] genericMethodTable; private Il2CppGenericMethodFunctionsDefinitions[] genericMethodTable;
public ulong[] genericInstPointers;
public Il2CppGenericInst[] genericInsts; public Il2CppGenericInst[] genericInsts;
public Il2CppMethodSpec[] methodSpecs; public Il2CppMethodSpec[] methodSpecs;
public Dictionary<int, List<(Il2CppMethodSpec, ulong)>> genericMethoddDictionary = new Dictionary<int, List<(Il2CppMethodSpec, ulong)>>(); public Dictionary<int, List<Il2CppMethodSpec>> methodDefinitionMethodSpecs = new Dictionary<int, List<Il2CppMethodSpec>>();
public Dictionary<Il2CppMethodSpec, ulong> methodSpecGenericMethodPointers = new Dictionary<Il2CppMethodSpec, ulong>();
private bool fieldOffsetsArePointers; private bool fieldOffsetsArePointers;
protected long maxMetadataUsages; protected long maxMetadataUsages;
private Il2CppCodeGenModule[] codeGenModules; private Il2CppCodeGenModule[] codeGenModules;
@ -94,7 +96,8 @@ namespace Il2CppDumper
if (pCodeRegistration.unresolvedVirtualCallCount != 0) if (pCodeRegistration.unresolvedVirtualCallCount != 0)
unresolvedVirtualCallPointers = MapVATR<ulong>(pCodeRegistration.unresolvedVirtualCallPointers, pCodeRegistration.unresolvedVirtualCallCount); unresolvedVirtualCallPointers = MapVATR<ulong>(pCodeRegistration.unresolvedVirtualCallPointers, pCodeRegistration.unresolvedVirtualCallCount);
} }
genericInsts = Array.ConvertAll(MapVATR<ulong>(pMetadataRegistration.genericInsts, pMetadataRegistration.genericInstsCount), x => MapVATR<Il2CppGenericInst>(x)); genericInstPointers = MapVATR<ulong>(pMetadataRegistration.genericInsts, pMetadataRegistration.genericInstsCount);
genericInsts = Array.ConvertAll(genericInstPointers, MapVATR<Il2CppGenericInst>);
fieldOffsetsArePointers = Version > 21; fieldOffsetsArePointers = Version > 21;
if (Version == 21) if (Version == 21)
{ {
@ -147,12 +150,13 @@ namespace Il2CppDumper
{ {
var methodSpec = methodSpecs[table.genericMethodIndex]; var methodSpec = methodSpecs[table.genericMethodIndex];
var methodDefinitionIndex = methodSpec.methodDefinitionIndex; var methodDefinitionIndex = methodSpec.methodDefinitionIndex;
if (!genericMethoddDictionary.TryGetValue(methodDefinitionIndex, out var tuple)) if (!methodDefinitionMethodSpecs.TryGetValue(methodDefinitionIndex, out var list))
{ {
tuple = new List<(Il2CppMethodSpec, ulong)>(); list = new List<Il2CppMethodSpec>();
genericMethoddDictionary.Add(methodDefinitionIndex, tuple); methodDefinitionMethodSpecs.Add(methodDefinitionIndex, list);
} }
tuple.Add((methodSpec, genericMethodPointers[table.indices.methodIndex])); list.Add(methodSpec);
methodSpecGenericMethodPointers.Add(methodSpec, genericMethodPointers[table.indices.methodIndex]);
} }
} }

View file

@ -335,12 +335,13 @@ namespace Il2CppDumper
writer.Write(string.Join(", ", parameterStrs)); writer.Write(string.Join(", ", parameterStrs));
writer.Write(") { }\n"); writer.Write(") { }\n");
if (il2Cpp.genericMethoddDictionary.TryGetValue(i, out var genericMethods)) if (il2Cpp.methodDefinitionMethodSpecs.TryGetValue(i, out var methodSpecs))
{ {
writer.Write("\t/* GenericInstMethod :\n"); writer.Write("\t/* GenericInstMethod :\n");
foreach ((var methodSpec, var genericMethodPointer) in genericMethods) foreach (var methodSpec in methodSpecs)
{ {
writer.Write("\t|\n"); writer.Write("\t|\n");
var genericMethodPointer = il2Cpp.methodSpecGenericMethodPointers[methodSpec];
if (genericMethodPointer > 0) if (genericMethodPointer > 0)
{ {
var fixedPointer = il2Cpp.GetRVA(genericMethodPointer); var fixedPointer = il2Cpp.GetRVA(genericMethodPointer);
@ -350,7 +351,8 @@ namespace Il2CppDumper
{ {
writer.Write("\t|-RVA: -1 Offset: -1\n"); writer.Write("\t|-RVA: -1 Offset: -1\n");
} }
writer.Write($"\t|-{executor.GetMethodSpecMethodName(methodSpec)}\n"); (var methodSpecTypeName, var methodSpecMethodName) = executor.GetMethodSpecName(methodSpec);
writer.Write($"\t|-{methodSpecTypeName}.{methodSpecMethodName}\n");
} }
writer.Write("\t*/\n"); writer.Write("\t*/\n");
} }

View file

@ -37,6 +37,7 @@ namespace Il2CppDumper
public void WriteScript(Config config) public void WriteScript(Config config)
{ {
var json = new ScriptJson(); var json = new ScriptJson();
// 生成唯一名称
for (var imageIndex = 0; imageIndex < metadata.imageDefs.Length; imageIndex++) for (var imageIndex = 0; imageIndex < metadata.imageDefs.Length; imageIndex++)
{ {
var imageDef = metadata.imageDefs[imageIndex]; var imageDef = metadata.imageDefs[imageIndex];
@ -44,9 +45,21 @@ namespace Il2CppDumper
for (int typeIndex = imageDef.typeStart; typeIndex < typeEnd; typeIndex++) for (int typeIndex = imageDef.typeStart; typeIndex < typeEnd; typeIndex++)
{ {
var typeDef = metadata.typeDefs[typeIndex]; var typeDef = metadata.typeDefs[typeIndex];
typeDefImageIndices.Add(typeDef, imageIndex);
CreateStructNameDic(typeDef); CreateStructNameDic(typeDef);
} }
} }
// 处理类定义
foreach (var typeDef in metadata.typeDefs)
{
AddStruct(typeDef);
}
// 处理泛型实例类
foreach (var genericClass in il2Cpp.types.Where(x => x.type == Il2CppTypeEnum.IL2CPP_TYPE_GENERICINST))
{
ParseType(genericClass);
}
// 处理函数
for (var imageIndex = 0; imageIndex < metadata.imageDefs.Length; imageIndex++) for (var imageIndex = 0; imageIndex < metadata.imageDefs.Length; imageIndex++)
{ {
var imageDef = metadata.imageDefs[imageIndex]; var imageDef = metadata.imageDefs[imageIndex];
@ -54,9 +67,7 @@ namespace Il2CppDumper
for (int typeIndex = imageDef.typeStart; typeIndex < typeEnd; typeIndex++) for (int typeIndex = imageDef.typeStart; typeIndex < typeEnd; typeIndex++)
{ {
var typeDef = metadata.typeDefs[typeIndex]; var typeDef = metadata.typeDefs[typeIndex];
AddStruct(typeDef);
var typeName = executor.GetTypeDefName(typeDef, true, true); var typeName = executor.GetTypeDefName(typeDef, true, true);
typeDefImageIndices.Add(typeDef, imageIndex);
var methodEnd = typeDef.methodStart + typeDef.method_count; var methodEnd = typeDef.methodStart + typeDef.method_count;
for (var i = typeDef.methodStart; i < methodEnd; ++i) for (var i = typeDef.methodStart; i < methodEnd; ++i)
{ {
@ -91,9 +102,54 @@ namespace Il2CppDumper
signature += ");"; signature += ");";
scriptMethod.Signature = signature; scriptMethod.Signature = signature;
} }
//泛型实例函数
if (il2Cpp.methodDefinitionMethodSpecs.TryGetValue(i, out var methodSpecs))
{
foreach (var methodSpec in methodSpecs)
{
var genericMethodPointer = il2Cpp.methodSpecGenericMethodPointers[methodSpec];
if (genericMethodPointer > 0)
{
var scriptMethod = new ScriptMethod();
json.ScriptMethod.Add(scriptMethod);
scriptMethod.Address = il2Cpp.GetRVA(genericMethodPointer);
(var methodSpecTypeName, var methodSpecMethodName) = executor.GetMethodSpecName(methodSpec, true);
var methodFullName = methodSpecTypeName + "$$" + methodSpecMethodName;
scriptMethod.Name = methodFullName;
var genericContext = executor.GetMethodSpecGenericContext(methodSpec);
var methodReturnType = il2Cpp.types[methodDef.returnType];
var returnType = ParseType(methodReturnType, genericContext);
var signature = $"{returnType} {FixName(methodFullName)} (";
var parameterStrs = new List<string>();
if (il2Cpp.Version <= 22f || (methodDef.flags & METHOD_ATTRIBUTE_STATIC) == 0)
{
var thisType = ParseType(il2Cpp.types[typeDef.byrefTypeIndex]);
if (methodSpec.classIndexIndex != -1)
{
var typeToReplaceName = FixName(typeName);
var typeReplaceName = FixName(methodSpecTypeName);
thisType = thisType.Replace(typeToReplaceName, typeReplaceName);
}
parameterStrs.Add($"{thisType} __this");
}
for (var j = 0; j < methodDef.parameterCount; j++)
{
var parameterDef = metadata.parameterDefs[methodDef.parameterStart + j];
var parameterName = metadata.GetStringFromIndex(parameterDef.nameIndex);
var parameterType = il2Cpp.types[parameterDef.typeIndex];
parameterStrs.Add($"{ParseType(parameterType, genericContext)} {FixName(parameterName)}");
}
signature += string.Join(", ", parameterStrs);
signature += ");";
scriptMethod.Signature = signature;
}
}
}
} }
} }
} }
// 处理MetadataUsage
if (il2Cpp.Version > 16) if (il2Cpp.Version > 16)
{ {
foreach (var i in metadata.metadataUsageDic[1]) //kIl2CppMetadataUsageTypeInfo foreach (var i in metadata.metadataUsageDic[1]) //kIl2CppMetadataUsageTypeInfo
@ -177,30 +233,15 @@ namespace Il2CppDumper
foreach (var i in metadata.metadataUsageDic[6]) //kIl2CppMetadataUsageMethodRef foreach (var i in metadata.metadataUsageDic[6]) //kIl2CppMetadataUsageMethodRef
{ {
var methodSpec = il2Cpp.methodSpecs[i.Value]; var methodSpec = il2Cpp.methodSpecs[i.Value];
var methodDef = metadata.methodDefs[methodSpec.methodDefinitionIndex];
var typeDef = metadata.typeDefs[methodDef.declaringType];
var typeName = executor.GetTypeDefName(typeDef, true, false);
if (methodSpec.classIndexIndex != -1)
{
var classInst = il2Cpp.genericInsts[methodSpec.classIndexIndex];
typeName += executor.GetGenericInstParams(classInst);
}
var methodName = typeName + "." + metadata.GetStringFromIndex(methodDef.nameIndex);
if (methodSpec.methodIndexIndex != -1)
{
var methodInst = il2Cpp.genericInsts[methodSpec.methodIndexIndex];
methodName += executor.GetGenericInstParams(methodInst);
}
methodName += "()";
var scriptMetadataMethod = new ScriptMetadataMethod(); var scriptMetadataMethod = new ScriptMetadataMethod();
json.ScriptMetadataMethod.Add(scriptMetadataMethod); json.ScriptMetadataMethod.Add(scriptMetadataMethod);
scriptMetadataMethod.Address = il2Cpp.GetRVA(il2Cpp.metadataUsages[i.Key]); scriptMetadataMethod.Address = il2Cpp.GetRVA(il2Cpp.metadataUsages[i.Key]);
scriptMetadataMethod.Name = "Method$" + methodName; (var methodSpecTypeName, var methodSpecMethodName) = executor.GetMethodSpecName(methodSpec, true);
var imageIndex = typeDefImageIndices[typeDef]; scriptMetadataMethod.Name = "Method$" + methodSpecTypeName + "." + methodSpecMethodName + "()";
var methodPointer = il2Cpp.GetMethodPointer(methodDef, imageIndex); var genericMethodPointer = il2Cpp.methodSpecGenericMethodPointers[methodSpec];
if (methodPointer > 0) if (genericMethodPointer > 0)
{ {
scriptMetadataMethod.MethodAddress = il2Cpp.GetRVA(methodPointer); scriptMetadataMethod.MethodAddress = il2Cpp.GetRVA(genericMethodPointer);
} }
} }
} }

View file

@ -178,23 +178,38 @@ namespace Il2CppDumper
return $"<{string.Join(", ", genericParameterNames)}>"; return $"<{string.Join(", ", genericParameterNames)}>";
} }
public string GetMethodSpecMethodName(Il2CppMethodSpec methodSpec) public (string, string) GetMethodSpecName(Il2CppMethodSpec methodSpec, bool addNamespace = false)
{ {
var methodDef = metadata.methodDefs[methodSpec.methodDefinitionIndex]; var methodDef = metadata.methodDefs[methodSpec.methodDefinitionIndex];
var typeDef = metadata.typeDefs[methodDef.declaringType]; var typeDef = metadata.typeDefs[methodDef.declaringType];
var typeName = GetTypeDefName(typeDef, false, false); var typeName = GetTypeDefName(typeDef, addNamespace, false);
if (methodSpec.classIndexIndex != -1) if (methodSpec.classIndexIndex != -1)
{ {
var classInst = il2Cpp.genericInsts[methodSpec.classIndexIndex]; var classInst = il2Cpp.genericInsts[methodSpec.classIndexIndex];
typeName += GetGenericInstParams(classInst); typeName += GetGenericInstParams(classInst);
} }
var methodName = typeName + "." + metadata.GetStringFromIndex(methodDef.nameIndex); var methodName = metadata.GetStringFromIndex(methodDef.nameIndex);
if (methodSpec.methodIndexIndex != -1) if (methodSpec.methodIndexIndex != -1)
{ {
var methodInst = il2Cpp.genericInsts[methodSpec.methodIndexIndex]; var methodInst = il2Cpp.genericInsts[methodSpec.methodIndexIndex];
methodName += GetGenericInstParams(methodInst); methodName += GetGenericInstParams(methodInst);
} }
return methodName; return (typeName, methodName);
}
public Il2CppGenericContext GetMethodSpecGenericContext(Il2CppMethodSpec methodSpec)
{
var classInstPointer = 0ul;
var methodInstPointer = 0ul;
if (methodSpec.classIndexIndex != -1)
{
classInstPointer = il2Cpp.genericInstPointers[methodSpec.classIndexIndex];
}
if (methodSpec.methodIndexIndex != -1)
{
methodInstPointer = il2Cpp.genericInstPointers[methodSpec.methodIndexIndex];
}
return new Il2CppGenericContext { class_inst = classInstPointer, method_inst = methodInstPointer };
} }
} }
} }