完善泛型相关输出

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>();
public ulong[] metadataUsages;
private Il2CppGenericMethodFunctionsDefinitions[] genericMethodTable;
public ulong[] genericInstPointers;
public Il2CppGenericInst[] genericInsts;
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;
protected long maxMetadataUsages;
private Il2CppCodeGenModule[] codeGenModules;
@ -94,7 +96,8 @@ namespace Il2CppDumper
if (pCodeRegistration.unresolvedVirtualCallCount != 0)
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;
if (Version == 21)
{
@ -147,12 +150,13 @@ namespace Il2CppDumper
{
var methodSpec = methodSpecs[table.genericMethodIndex];
var methodDefinitionIndex = methodSpec.methodDefinitionIndex;
if (!genericMethoddDictionary.TryGetValue(methodDefinitionIndex, out var tuple))
if (!methodDefinitionMethodSpecs.TryGetValue(methodDefinitionIndex, out var list))
{
tuple = new List<(Il2CppMethodSpec, ulong)>();
genericMethoddDictionary.Add(methodDefinitionIndex, tuple);
list = new List<Il2CppMethodSpec>();
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(") { }\n");
if (il2Cpp.genericMethoddDictionary.TryGetValue(i, out var genericMethods))
if (il2Cpp.methodDefinitionMethodSpecs.TryGetValue(i, out var methodSpecs))
{
writer.Write("\t/* GenericInstMethod :\n");
foreach ((var methodSpec, var genericMethodPointer) in genericMethods)
foreach (var methodSpec in methodSpecs)
{
writer.Write("\t|\n");
var genericMethodPointer = il2Cpp.methodSpecGenericMethodPointers[methodSpec];
if (genericMethodPointer > 0)
{
var fixedPointer = il2Cpp.GetRVA(genericMethodPointer);
@ -350,7 +351,8 @@ namespace Il2CppDumper
{
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");
}

View file

@ -37,6 +37,7 @@ namespace Il2CppDumper
public void WriteScript(Config config)
{
var json = new ScriptJson();
// 生成唯一名称
for (var imageIndex = 0; imageIndex < metadata.imageDefs.Length; imageIndex++)
{
var imageDef = metadata.imageDefs[imageIndex];
@ -44,9 +45,21 @@ namespace Il2CppDumper
for (int typeIndex = imageDef.typeStart; typeIndex < typeEnd; typeIndex++)
{
var typeDef = metadata.typeDefs[typeIndex];
typeDefImageIndices.Add(typeDef, imageIndex);
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++)
{
var imageDef = metadata.imageDefs[imageIndex];
@ -54,9 +67,7 @@ namespace Il2CppDumper
for (int typeIndex = imageDef.typeStart; typeIndex < typeEnd; typeIndex++)
{
var typeDef = metadata.typeDefs[typeIndex];
AddStruct(typeDef);
var typeName = executor.GetTypeDefName(typeDef, true, true);
typeDefImageIndices.Add(typeDef, imageIndex);
var methodEnd = typeDef.methodStart + typeDef.method_count;
for (var i = typeDef.methodStart; i < methodEnd; ++i)
{
@ -91,9 +102,54 @@ namespace Il2CppDumper
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)
{
foreach (var i in metadata.metadataUsageDic[1]) //kIl2CppMetadataUsageTypeInfo
@ -177,30 +233,15 @@ namespace Il2CppDumper
foreach (var i in metadata.metadataUsageDic[6]) //kIl2CppMetadataUsageMethodRef
{
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();
json.ScriptMetadataMethod.Add(scriptMetadataMethod);
scriptMetadataMethod.Address = il2Cpp.GetRVA(il2Cpp.metadataUsages[i.Key]);
scriptMetadataMethod.Name = "Method$" + methodName;
var imageIndex = typeDefImageIndices[typeDef];
var methodPointer = il2Cpp.GetMethodPointer(methodDef, imageIndex);
if (methodPointer > 0)
(var methodSpecTypeName, var methodSpecMethodName) = executor.GetMethodSpecName(methodSpec, true);
scriptMetadataMethod.Name = "Method$" + methodSpecTypeName + "." + methodSpecMethodName + "()";
var genericMethodPointer = il2Cpp.methodSpecGenericMethodPointers[methodSpec];
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)}>";
}
public string GetMethodSpecMethodName(Il2CppMethodSpec methodSpec)
public (string, string) GetMethodSpecName(Il2CppMethodSpec methodSpec, bool addNamespace = false)
{
var methodDef = metadata.methodDefs[methodSpec.methodDefinitionIndex];
var typeDef = metadata.typeDefs[methodDef.declaringType];
var typeName = GetTypeDefName(typeDef, false, false);
var typeName = GetTypeDefName(typeDef, addNamespace, false);
if (methodSpec.classIndexIndex != -1)
{
var classInst = il2Cpp.genericInsts[methodSpec.classIndexIndex];
typeName += GetGenericInstParams(classInst);
}
var methodName = typeName + "." + metadata.GetStringFromIndex(methodDef.nameIndex);
var methodName = metadata.GetStringFromIndex(methodDef.nameIndex);
if (methodSpec.methodIndexIndex != -1)
{
var methodInst = il2Cpp.genericInsts[methodSpec.methodIndexIndex];
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 };
}
}
}