完善头文件输出

This commit is contained in:
Perfare 2020-02-27 01:01:06 +08:00
parent 1b89455c95
commit cfa4037d23
4 changed files with 137 additions and 41 deletions

View file

@ -9,9 +9,7 @@ namespace Il2CppDumper
public static class HeaderConstants public static class HeaderConstants
{ {
public readonly static string HeaderV242 = public readonly static string HeaderV242 =
@"#define ALIGN_TYPE(val) __attribute__((aligned(val))) @"struct VirtualInvokeData
struct VirtualInvokeData
{ {
uintptr_t methodPtr; uintptr_t methodPtr;
void* method; void* method;
@ -20,11 +18,7 @@ struct VirtualInvokeData
struct Il2CppType struct Il2CppType
{ {
void* data; void* data;
unsigned int attrs : 16; unsigned int bits;
unsigned int type : 8;
unsigned int num_mods : 6;
unsigned int byref : 1;
unsigned int pinned : 1;
}; };
struct Il2CppClass; struct Il2CppClass;
@ -62,7 +56,7 @@ struct Il2CppClass_2
uint32_t initializationExceptionGCHandle; uint32_t initializationExceptionGCHandle;
uint32_t cctor_started; uint32_t cctor_started;
uint32_t cctor_finished; uint32_t cctor_finished;
ALIGN_TYPE(8) size_t cctor_thread; size_t cctor_thread;
int32_t genericContainerIndex; int32_t genericContainerIndex;
uint32_t instance_size; uint32_t instance_size;
uint32_t actualSize; uint32_t actualSize;
@ -89,20 +83,8 @@ struct Il2CppClass_2
uint8_t minimumAlignment; uint8_t minimumAlignment;
uint8_t naturalAligment; uint8_t naturalAligment;
uint8_t packingSize; uint8_t packingSize;
uint8_t initialized_and_no_error : 1; uint8_t bitflags1;
uint8_t valuetype : 1; uint8_t bitflags2;
uint8_t initialized : 1;
uint8_t enumtype : 1;
uint8_t is_generic : 1;
uint8_t has_references : 1;
uint8_t init_pending : 1;
uint8_t size_inited : 1;
uint8_t has_finalize : 1;
uint8_t has_cctor : 1;
uint8_t is_blittable : 1;
uint8_t is_import_or_windows_runtime : 1;
uint8_t is_vtable_initialized : 1;
uint8_t has_initialization_error : 1;
}; };
struct Il2CppClass struct Il2CppClass

View file

@ -99,6 +99,15 @@ namespace Il2CppDumper
json.ScriptMetadata.Add(scriptMetadata); json.ScriptMetadata.Add(scriptMetadata);
scriptMetadata.Address = il2Cpp.GetRVA(il2Cpp.metadataUsages[i.Key]); scriptMetadata.Address = il2Cpp.GetRVA(il2Cpp.metadataUsages[i.Key]);
scriptMetadata.Name = "Class$" + typeName; scriptMetadata.Name = "Class$" + typeName;
var signature = GetIl2CppTypeSignature(type);
if (signature == "Il2CppArray*")
{
scriptMetadata.Signature = signature;
}
else
{
scriptMetadata.Signature = FixName(signature) + "_c*";
}
} }
foreach (var i in metadata.metadataUsageDic[2]) //kIl2CppMetadataUsageIl2CppType foreach (var i in metadata.metadataUsageDic[2]) //kIl2CppMetadataUsageIl2CppType
{ {
@ -108,6 +117,15 @@ namespace Il2CppDumper
json.ScriptMetadata.Add(scriptMetadata); json.ScriptMetadata.Add(scriptMetadata);
scriptMetadata.Address = il2Cpp.GetRVA(il2Cpp.metadataUsages[i.Key]); scriptMetadata.Address = il2Cpp.GetRVA(il2Cpp.metadataUsages[i.Key]);
scriptMetadata.Name = "Class$" + typeName; scriptMetadata.Name = "Class$" + typeName;
var signature = GetIl2CppTypeSignature(type);
if (signature == "Il2CppArray*")
{
scriptMetadata.Signature = signature;
}
else
{
scriptMetadata.Signature = FixName(signature) + "_t*";
}
} }
foreach (var i in metadata.metadataUsageDic[3]) //kIl2CppMetadataUsageMethodDef foreach (var i in metadata.metadataUsageDic[3]) //kIl2CppMetadataUsageMethodDef
{ {
@ -226,32 +244,25 @@ namespace Il2CppDumper
var headerClass = new StringBuilder(); var headerClass = new StringBuilder();
foreach (var info in StructInfo) foreach (var info in StructInfo)
{ {
preHeader.Append($"struct {info.TypeName}_t;\n");
if (info.IsValueType) if (info.IsValueType)
{ {
preHeader.Append($"struct {info.TypeName}_t;\n");
headerStruct.Append(RecursionStructInfo(info)); headerStruct.Append(RecursionStructInfo(info));
} }
else else
{ {
preHeader.Append($"struct {info.TypeName}_t;\n");
headerClass.Append($"struct {info.TypeName}_StaticFields {{\n"); headerClass.Append($"struct {info.TypeName}_StaticFields {{\n");
if (info.StaticFields.Count > 0) foreach (var field in info.StaticFields)
{ {
foreach (var field in info.StaticFields) headerClass.Append($"\t{field.FieldTypeName} {field.FieldName};\n");
{
headerClass.Append($"\t{field.FieldTypeName} {field.FieldName};\n");
}
} }
headerClass.Append("};\n"); headerClass.Append("};\n");
headerClass.Append($"struct {info.TypeName}_VTable {{\n"); headerClass.Append($"struct {info.TypeName}_VTable {{\n");
if (info.VTableMethod.Count > 0) foreach (var method in info.VTableMethod)
{ {
foreach (var method in info.VTableMethod) headerClass.Append($"\tVirtualInvokeData {method.MethodName};\n");
{
headerClass.Append($"\tVirtualInvokeData {method.MethodName};\n");
}
} }
headerClass.Append("};\n"); headerClass.Append("};\n");
@ -395,7 +406,7 @@ namespace Il2CppDumper
return "intptr_t"; return "intptr_t";
case Il2CppTypeEnum.IL2CPP_TYPE_U: case Il2CppTypeEnum.IL2CPP_TYPE_U:
return "uintptr_t"; return "uintptr_t";
case Il2CppTypeEnum.IL2CPP_TYPE_OBJECT: case Il2CppTypeEnum.IL2CPP_TYPE_OBJECT: //TODO
return "Il2CppObject*"; return "Il2CppObject*";
case Il2CppTypeEnum.IL2CPP_TYPE_SZARRAY: //TODO case Il2CppTypeEnum.IL2CPP_TYPE_SZARRAY: //TODO
return "Il2CppArray*"; return "Il2CppArray*";
@ -579,14 +590,14 @@ namespace Il2CppDumper
} }
var sb = new StringBuilder(); var sb = new StringBuilder();
sb.Append($"struct {info.TypeName}_t {{\n");
sb.Append($"struct {info.TypeName}_t {{\n");
foreach (var field in info.Fields) foreach (var field in info.Fields)
{ {
if (!field.FieldTypeName.EndsWith("*")) if (!field.FieldTypeName.EndsWith("*")) //hack
{ {
var fieldTypeName = field.FieldTypeName.Substring(0, field.FieldTypeName.Length - 2); var fieldTypeName = field.FieldTypeName.Substring(0, field.FieldTypeName.Length - 2);
var fieldInfo = StructInfo.Find(x => x.TypeName == fieldTypeName); //hack var fieldInfo = StructInfo.Find(x => x.TypeName == fieldTypeName);
if (fieldInfo != null) if (fieldInfo != null)
{ {
sb.Insert(0, RecursionStructInfo(fieldInfo)); sb.Insert(0, RecursionStructInfo(fieldInfo));
@ -595,7 +606,102 @@ namespace Il2CppDumper
sb.Append($"\t{field.FieldTypeName} {field.FieldName};\n"); sb.Append($"\t{field.FieldTypeName} {field.FieldName};\n");
} }
sb.Append("};\n"); sb.Append("};\n");
sb.Append($"struct {info.TypeName}_StaticFields {{\n");
foreach (var field in info.StaticFields)
{
if (!field.FieldTypeName.EndsWith("*")) //hack
{
var fieldTypeName = field.FieldTypeName.Substring(0, field.FieldTypeName.Length - 2);
var fieldInfo = StructInfo.Find(x => x.TypeName == fieldTypeName);
if (fieldInfo != null)
{
sb.Insert(0, 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 sb.ToString(); return sb.ToString();
} }
private string GetIl2CppTypeSignature(Il2CppType il2CppType)
{
switch (il2CppType.type)
{
case Il2CppTypeEnum.IL2CPP_TYPE_VOID:
case Il2CppTypeEnum.IL2CPP_TYPE_BOOLEAN:
case Il2CppTypeEnum.IL2CPP_TYPE_CHAR:
case Il2CppTypeEnum.IL2CPP_TYPE_I1:
case Il2CppTypeEnum.IL2CPP_TYPE_U1:
case Il2CppTypeEnum.IL2CPP_TYPE_I2:
case Il2CppTypeEnum.IL2CPP_TYPE_U2:
case Il2CppTypeEnum.IL2CPP_TYPE_I4:
case Il2CppTypeEnum.IL2CPP_TYPE_U4:
case Il2CppTypeEnum.IL2CPP_TYPE_I8:
case Il2CppTypeEnum.IL2CPP_TYPE_U8:
case Il2CppTypeEnum.IL2CPP_TYPE_R4:
case Il2CppTypeEnum.IL2CPP_TYPE_R8:
case Il2CppTypeEnum.IL2CPP_TYPE_STRING:
case Il2CppTypeEnum.IL2CPP_TYPE_TYPEDBYREF:
case Il2CppTypeEnum.IL2CPP_TYPE_I:
case Il2CppTypeEnum.IL2CPP_TYPE_U:
case Il2CppTypeEnum.IL2CPP_TYPE_VALUETYPE:
case Il2CppTypeEnum.IL2CPP_TYPE_CLASS:
case Il2CppTypeEnum.IL2CPP_TYPE_OBJECT:
{
var typeDef = metadata.typeDefs[il2CppType.data.klassIndex];
if (typeDef.IsEnum)
{
return GetIl2CppTypeSignature(il2Cpp.types[typeDef.elementTypeIndex]);
}
return StructNameDic[typeDef];
}
case Il2CppTypeEnum.IL2CPP_TYPE_PTR:
{
var oriType = il2Cpp.GetIl2CppType(il2CppType.data.type);
return GetIl2CppTypeSignature(oriType);
}
case Il2CppTypeEnum.IL2CPP_TYPE_ARRAY: //TODO
case Il2CppTypeEnum.IL2CPP_TYPE_SZARRAY: //TODO
return "Il2CppArray*";
case Il2CppTypeEnum.IL2CPP_TYPE_GENERICINST:
{
//TODO Enum ValueType
if (!GenericClassStructNameDic.TryGetValue(il2CppType.data.generic_class, out var typeStructName))
{
var genericClass = il2Cpp.MapVATR<Il2CppGenericClass>(il2CppType.data.generic_class);
var typeDef = metadata.typeDefs[genericClass.typeDefinitionIndex];
var typeOriName = StructNameDic[typeDef];
var typeToReplaceName = FixName(executor.GetTypeDefName(typeDef, true, true));
var typeReplaceName = FixName(executor.GetTypeName(il2CppType, true, false));
typeStructName = typeOriName.Replace(typeToReplaceName, typeReplaceName);
GenericClassStructNameDic.Add(il2CppType.data.generic_class, typeStructName);
if (StructNameHashSet.Add(typeStructName))
{
GenericClass.Add(il2CppType.data.generic_class);
}
}
return typeStructName;
}
default:
throw new NotSupportedException();
}
}
} }
} }

View file

@ -33,6 +33,7 @@ namespace Il2CppDumper
{ {
public ulong Address; public ulong Address;
public string Name; public string Name;
public string Signature;
} }
public class ScriptMetadataMethod public class ScriptMetadataMethod

View file

@ -21,6 +21,8 @@ def make_function(start, end):
ida_funcs.add_func(start, end) ida_funcs.add_func(start, end)
path = idaapi.ask_file(False, '*.json', 'script.json from Il2cppdumper') path = idaapi.ask_file(False, '*.json', 'script.json from Il2cppdumper')
hpath = idaapi.ask_file(False, '*.h', 'il2cpp.h from Il2cppdumper')
parse_decls(open(hpath, 'rb').read(), 0)
data = json.loads(open(path, 'rb').read().decode('utf-8')) data = json.loads(open(path, 'rb').read().decode('utf-8'))
scriptMethods = data["ScriptMethod"] scriptMethods = data["ScriptMethod"]
for scriptMethod in scriptMethods: for scriptMethod in scriptMethods:
@ -28,7 +30,7 @@ for scriptMethod in scriptMethods:
name = scriptMethod["Name"].encode("utf-8") name = scriptMethod["Name"].encode("utf-8")
set_name(addr, name) set_name(addr, name)
signature = scriptMethod["Signature"].encode("utf-8") signature = scriptMethod["Signature"].encode("utf-8")
if not apply_type(addr, parse_decl(signature, 0), 1): if apply_type(addr, parse_decl(signature, 0), 1) == False:
print "apply_type failed:", hex(addr), signature print "apply_type failed:", hex(addr), signature
index = 1 index = 1
scriptStrings = data["ScriptString"] scriptStrings = data["ScriptString"]
@ -45,6 +47,11 @@ for scriptMetadata in scriptMetadatas:
name = scriptMetadata["Name"].encode("utf-8") name = scriptMetadata["Name"].encode("utf-8")
set_name(addr, name) set_name(addr, name)
idc.set_cmt(addr, name, 1) idc.set_cmt(addr, name, 1)
if scriptMetadata["Signature"] is not None:
signature = scriptMetadata["Signature"].encode("utf-8")
if apply_type(addr, parse_decl(signature, 0), 1) == False:
print "apply_type failed:", hex(addr), signature
scriptMetadataMethods = data["ScriptMetadataMethod"] scriptMetadataMethods = data["ScriptMetadataMethod"]
for scriptMetadataMethod in scriptMetadataMethods: for scriptMetadataMethod in scriptMetadataMethods:
addr = get_addr(scriptMetadataMethod["Address"]) addr = get_addr(scriptMetadataMethod["Address"])