Renaming for clarity.

Renamed the class CppDeclarations => CppDeclarationGenerator to better reflect
its function and emphasize its statefulness.

Renamed Visit{Type,Method} => Include{Type,Method} to clarify that these methods
include the type or method into the generator state.

Renamed GenerateVisitedTypes => GenerateRemainingTypeDeclarations to clarify
that it outputs *remaining* declarations, i.e. declarations that haven't been
generated yet.
This commit is contained in:
Robert Xiao
2020-06-29 12:35:26 -06:00
committed by Katy
parent 393d26b2a3
commit 9e455fdabe
2 changed files with 36 additions and 34 deletions

View File

@@ -16,7 +16,7 @@ using System.Text.RegularExpressions;
namespace Il2CppInspector.CppUtils namespace Il2CppInspector.CppUtils
{ {
// Class for generating C header declarations from Reflection objects (TypeInfo, etc.) // Class for generating C header declarations from Reflection objects (TypeInfo, etc.)
public class CppDeclarations public class CppDeclarationGenerator
{ {
private readonly Il2CppModel model; private readonly Il2CppModel model;
@@ -36,7 +36,7 @@ namespace Il2CppInspector.CppUtils
} }
public InheritanceStyleEnum InheritanceStyle; public InheritanceStyleEnum InheritanceStyle;
public CppDeclarations(Il2CppModel model, UnityVersion version) { public CppDeclarationGenerator(Il2CppModel model, UnityVersion version) {
this.model = model; this.model = model;
if (version == null) { if (version == null) {
UnityHeader = UnityHeader.GuessHeadersForModel(model)[0]; UnityHeader = UnityHeader.GuessHeadersForModel(model)[0];
@@ -328,10 +328,11 @@ namespace Il2CppInspector.CppUtils
private readonly List<TypeInfo> TodoTypeStructs = new List<TypeInfo>(); private readonly List<TypeInfo> TodoTypeStructs = new List<TypeInfo>();
/// <summary> /// <summary>
/// Visit a type and all types it depends on. Must call this before generating type structs. /// Include the given type into this generator. This will add the given type and all types it depends on.
/// Call GenerateRemainingTypeDeclarations to produce the actual type declarations afterwards.
/// </summary> /// </summary>
/// <param name="ti"></param> /// <param name="ti"></param>
public void VisitType(TypeInfo ti) { public void IncludeType(TypeInfo ti) {
if (VisitedTypes.Contains(ti)) if (VisitedTypes.Contains(ti))
return; return;
if (ti.ContainsGenericParameters) if (ti.ContainsGenericParameters)
@@ -340,15 +341,15 @@ namespace Il2CppInspector.CppUtils
if (ti.IsArray) { if (ti.IsArray) {
VisitFieldStructs(ti); VisitFieldStructs(ti);
VisitType(ti.ElementType); IncludeType(ti.ElementType);
VisitType(ti.BaseType); IncludeType(ti.BaseType);
return; return;
} else if (ti.HasElementType) { } else if (ti.HasElementType) {
VisitType(ti.ElementType); IncludeType(ti.ElementType);
return; return;
} else if (ti.IsEnum) { } else if (ti.IsEnum) {
VisitFieldStructs(ti); VisitFieldStructs(ti);
VisitType(ti.GetEnumUnderlyingType()); IncludeType(ti.GetEnumUnderlyingType());
return; return;
} }
@@ -357,16 +358,16 @@ namespace Il2CppInspector.CppUtils
VisitFieldStructs(ti); VisitFieldStructs(ti);
if (ti.BaseType != null) if (ti.BaseType != null)
VisitType(ti.BaseType); IncludeType(ti.BaseType);
TypeNamer.GetName(ti); TypeNamer.GetName(ti);
foreach (var fi in ti.DeclaredFields) foreach (var fi in ti.DeclaredFields)
VisitType(fi.FieldType); IncludeType(fi.FieldType);
foreach (var mi in GetFilledVTable(ti)) foreach (var mi in GetFilledVTable(ti))
if (mi != null && !mi.ContainsGenericParameters) if (mi != null && !mi.ContainsGenericParameters)
VisitMethod(mi); IncludeMethod(mi);
TodoTypeStructs.Add(ti); TodoTypeStructs.Add(ti);
} }
@@ -444,11 +445,11 @@ namespace Il2CppInspector.CppUtils
} }
/// <summary> /// <summary>
/// Generate every type that has been visited so far. Types that have previously been generated /// Output type declarations for every type that was included since the last call to GenerateRemainingTypeDeclarations
/// by this instance will not be generated again. /// Type declarations that have previously been generated by this instance of CppDeclarationGenerator will not be generated again.
/// </summary> /// </summary>
/// <returns>A string containing C type declarations</returns> /// <returns>A string containing C type declarations</returns>
public string GenerateVisitedTypes() { public string GenerateRemainingTypeDeclarations() {
var csrc = new StringBuilder(); var csrc = new StringBuilder();
GenerateVisitedFieldStructs(csrc); GenerateVisitedFieldStructs(csrc);
@@ -463,18 +464,19 @@ namespace Il2CppInspector.CppUtils
#region Method Generation #region Method Generation
/// <summary> /// <summary>
/// Visit a method and all types it takes/returns. Must call this before generating method declarations. /// Analyze a method and include all types that it takes and returns.
/// Must call this before generating the method's declaration with GenerateMethodDeclaration or GenerateFunctionPointer.
/// </summary> /// </summary>
/// <param name="mi"></param> /// <param name="mi"></param>
public void VisitMethod(MethodBase method, TypeInfo declaringType = null) { public void IncludeMethod(MethodBase method, TypeInfo declaringType = null) {
if (!method.IsStatic) if (!method.IsStatic)
VisitType(declaringType ?? method.DeclaringType); IncludeType(declaringType ?? method.DeclaringType);
if (method is MethodInfo mi) if (method is MethodInfo mi)
VisitType(mi.ReturnType); IncludeType(mi.ReturnType);
foreach (var pi in method.DeclaredParameters) { foreach (var pi in method.DeclaredParameters) {
VisitType(pi.ParameterType); IncludeType(pi.ParameterType);
} }
} }

30
Il2CppInspector.Common/Outputs/IDAPythonScript.cs Normal file → Executable file
View File

@@ -19,19 +19,19 @@ namespace Il2CppInspector.Outputs
private readonly Il2CppModel model; private readonly Il2CppModel model;
private StreamWriter writer; private StreamWriter writer;
public UnityVersion UnityVersion; public UnityVersion UnityVersion;
private CppDeclarations typeGenerator; private CppDeclarationGenerator declGenerator;
public IDAPythonScript(Il2CppModel model) => this.model = model; public IDAPythonScript(Il2CppModel model) => this.model = model;
public void WriteScriptToFile(string outputFile) { public void WriteScriptToFile(string outputFile) {
typeGenerator = new CppDeclarations(model, UnityVersion); declGenerator = new CppDeclarationGenerator(model, UnityVersion);
UnityVersion = typeGenerator.UnityVersion; UnityVersion = declGenerator.UnityVersion;
using var fs = new FileStream(outputFile, FileMode.Create); using var fs = new FileStream(outputFile, FileMode.Create);
writer = new StreamWriter(fs, Encoding.UTF8); writer = new StreamWriter(fs, Encoding.UTF8);
writeLine("# Generated script file by Il2CppInspector - http://www.djkaty.com - https://github.com/djkaty"); writeLine("# Generated script file by Il2CppInspector - http://www.djkaty.com - https://github.com/djkaty");
writeLine("# Target Unity version: " + typeGenerator.UnityHeader.ToString()); writeLine("# Target Unity version: " + declGenerator.UnityHeader.ToString());
writeLine("print('Generated script file by Il2CppInspector - http://www.djkaty.com - https://github.com/djkaty')"); writeLine("print('Generated script file by Il2CppInspector - http://www.djkaty.com - https://github.com/djkaty')");
writeSectionHeader("Preamble"); writeSectionHeader("Preamble");
writePreamble(); writePreamble();
@@ -83,7 +83,7 @@ typedef __int64 int64_t;
"); ");
var prefix = (model.Package.BinaryImage.Bits == 32) ? "#define IS_32BIT\n" : ""; var prefix = (model.Package.BinaryImage.Bits == 32) ? "#define IS_32BIT\n" : "";
writeDecls(prefix + typeGenerator.UnityHeader.GetHeaderText()); writeDecls(prefix + declGenerator.UnityHeader.GetHeaderText());
} }
private void writeMethods() { private void writeMethods() {
@@ -110,10 +110,10 @@ typedef __int64 int64_t;
private void writeMethods(IEnumerable<MethodBase> methods) { private void writeMethods(IEnumerable<MethodBase> methods) {
foreach (var method in methods.Where(m => m.VirtualAddress.HasValue)) { foreach (var method in methods.Where(m => m.VirtualAddress.HasValue)) {
typeGenerator.VisitMethod(method); declGenerator.IncludeMethod(method);
writeDecls(typeGenerator.GenerateVisitedTypes()); writeDecls(declGenerator.GenerateRemainingTypeDeclarations());
var address = method.VirtualAddress.Value.Start; var address = method.VirtualAddress.Value.Start;
writeTypedName(address, typeGenerator.GenerateMethodDeclaration(method), typeGenerator.MethodNamer.GetName(method)); writeTypedName(address, declGenerator.GenerateMethodDeclaration(method), declGenerator.MethodNamer.GetName(method));
writeComment(address, method); writeComment(address, method);
} }
} }
@@ -141,7 +141,7 @@ typedef __int64 int64_t;
return; return;
} }
var stringType = typeGenerator.AsCType(model.TypesByFullName["System.String"]); var stringType = declGenerator.AsCType(model.TypesByFullName["System.String"]);
foreach (var usage in model.Package.MetadataUsages) { foreach (var usage in model.Package.MetadataUsages) {
var address = usage.VirtualAddress; var address = usage.VirtualAddress;
string name; string name;
@@ -155,10 +155,10 @@ typedef __int64 int64_t;
case MetadataUsageType.Type: case MetadataUsageType.Type:
case MetadataUsageType.TypeInfo: case MetadataUsageType.TypeInfo:
var type = model.GetMetadataUsageType(usage); var type = model.GetMetadataUsageType(usage);
typeGenerator.VisitType(type); declGenerator.IncludeType(type);
writeDecls(typeGenerator.GenerateVisitedTypes()); writeDecls(declGenerator.GenerateRemainingTypeDeclarations());
name = typeGenerator.TypeNamer.GetName(type); name = declGenerator.TypeNamer.GetName(type);
if (usage.Type == MetadataUsageType.TypeInfo) if (usage.Type == MetadataUsageType.TypeInfo)
writeTypedName(address, $"struct {name}__Class *", $"{name}__TypeInfo"); writeTypedName(address, $"struct {name}__Class *", $"{name}__TypeInfo");
else else
@@ -168,10 +168,10 @@ typedef __int64 int64_t;
case MetadataUsageType.MethodDef: case MetadataUsageType.MethodDef:
case MetadataUsageType.MethodRef: case MetadataUsageType.MethodRef:
var method = model.GetMetadataUsageMethod(usage); var method = model.GetMetadataUsageMethod(usage);
typeGenerator.VisitMethod(method); declGenerator.IncludeMethod(method);
writeDecls(typeGenerator.GenerateVisitedTypes()); writeDecls(declGenerator.GenerateRemainingTypeDeclarations());
name = typeGenerator.MethodNamer.GetName(method); name = declGenerator.MethodNamer.GetName(method);
writeTypedName(address, "struct MethodInfo *", $"{name}__MethodInfo"); writeTypedName(address, "struct MethodInfo *", $"{name}__MethodInfo");
writeComment(address, method); writeComment(address, method);
break; break;