DLL: Handle nested generic types and methods

This commit is contained in:
Katy Coe
2021-01-08 07:47:48 +01:00
parent 6322246566
commit 35378f5065

View File

@@ -152,7 +152,9 @@ namespace Il2CppInspector.Outputs
// Generate type recursively with all nested types // Generate type recursively with all nested types
private TypeDefUser CreateType(ModuleDef module, TypeInfo type) { private TypeDefUser CreateType(ModuleDef module, TypeInfo type) {
// Initialize with base class // Initialize with base class
var mType = new TypeDefUser(type.Namespace, type.BaseName, GetTypeRef(module, type.BaseType)) { Attributes = (TypeAttributes) type.Attributes }; var mType = new TypeDefUser(type.Namespace, type.BaseName, GetTypeRef(module, type.BaseType)) {
Attributes = (TypeAttributes) type.Attributes
};
// Generic parameters // Generic parameters
foreach (var gp in type.GenericTypeParameters) { foreach (var gp in type.GenericTypeParameters) {
@@ -174,20 +176,37 @@ namespace Il2CppInspector.Outputs
mType.NestedTypes.Add(CreateType(module, nestedType)); mType.NestedTypes.Add(CreateType(module, nestedType));
// Add methods // Add methods
foreach (var ctor in type.DeclaredConstructors) { foreach (var method in type.DeclaredConstructors.AsEnumerable<MethodBase>().Concat(type.DeclaredMethods)) {
var s = MethodSig.CreateInstance(module.CorLibTypes.Void, // Return type and parameter signature
ctor.DeclaredParameters.Select(p => GetTypeRef(module, p.ParameterType).ToTypeSig()).ToArray()); var s = MethodSig.CreateInstance(
method is MethodInfo mi? GetTypeSig(module, mi.ReturnType) : module.CorLibTypes.Void,
method.DeclaredParameters.Select(p => GetTypeSig(module, p.ParameterType))
.ToArray());
var m = new MethodDefUser(ctor.Name, s, (MethodImplAttributes) ctor.MethodImplementationFlags, (MethodAttributes) ctor.Attributes); // Definition
var mMethod = new MethodDefUser(method.Name, s, (MethodImplAttributes) method.MethodImplementationFlags, (MethodAttributes) method.Attributes);
// Generic type parameters
foreach (var gp in method.GetGenericArguments()) {
var p = new GenericParamUser((ushort) gp.GenericParameterPosition, (GenericParamAttributes) gp.GenericParameterAttributes, gp.Name);
// Generic constraints (types and interfaces)
foreach (var c in gp.GetGenericParameterConstraints())
p.GenericParamConstraints.Add(new GenericParamConstraintUser(GetTypeRef(module, c)));
mMethod.GenericParameters.Add(p);
}
// Parameter names
foreach (var param in method.DeclaredParameters)
mMethod.ParamDefs.Add(new ParamDefUser(param.Name, (ushort) (param.Position + 1)));
// TODO: Generic parameters
// Method body // Method body
if (ctor.VirtualAddress.HasValue) { if (method.VirtualAddress.HasValue) {
} }
mType.Methods.Add(m); mType.Methods.Add(mMethod);
} }
// Add token attribute // Add token attribute
@@ -207,31 +226,42 @@ namespace Il2CppInspector.Outputs
} }
// Convert Il2CppInspector TypeInfo into type reference imported to specified module // Convert Il2CppInspector TypeInfo into type reference imported to specified module
private ITypeDefOrRef GetTypeRef(ModuleDef module, TypeInfo type) { private ITypeDefOrRef GetTypeRef(ModuleDef module, TypeInfo type)
=> module.Import(GetTypeSig(module, type)).ToTypeDefOrRef();
// Convert Il2CppInspector TypeInfo into type signature imported to specified module
private TypeSig GetTypeSig(ModuleDef module, TypeInfo type) {
if (type == null) if (type == null)
return null; return null;
// Generic type parameter // Generic type parameter
if (type.IsGenericParameter) if (type.IsGenericTypeParameter)
return new GenericVar(type.GenericParameterPosition).ToTypeDefOrRef(); return new GenericVar(type.GenericParameterPosition);
// Generic method parameter
if (type.IsGenericMethodParameter)
return new GenericMVar(type.GenericParameterPosition);
// Get module that owns the type // Get module that owns the type
var typeOwnerModule = modules.First(a => a.Name == type.Assembly.ShortName); var typeOwnerModule = modules.First(a => a.Name == type.Assembly.ShortName);
var typeOwnerModuleRef = new ModuleRefUser(typeOwnerModule);
// Get reference to type // Get reference to type; use nested type as resolution scope if applicable
var typeRef = new TypeRefUser(typeOwnerModule, type.Namespace, type.BaseName, typeOwnerModule); var typeSig = new TypeRefUser(typeOwnerModule, type.Namespace, type.BaseName,
type.DeclaringType != null? (IResolutionScope) GetTypeRef(module, type.DeclaringType).ScopeType : typeOwnerModuleRef)
.ToTypeSig();
// Non-generic type // Non-generic type
if (!type.GetGenericArguments().Any()) if (!type.GetGenericArguments().Any())
return module.Import(typeRef); return typeSig;
// Generic type requires generic arguments // Generic type requires generic arguments
var genericInstSig = new GenericInstSig(typeRef.ToTypeSig().ToClassOrValueTypeSig(), type.GenericTypeArguments.Length); var genericInstSig = new GenericInstSig(typeSig.ToClassOrValueTypeSig(), type.GenericTypeArguments.Length);
foreach (var gp in type.GenericTypeArguments) foreach (var gp in type.GetGenericArguments())
genericInstSig.GenericArguments.Add(GetTypeRef(module, gp).ToTypeSig()); genericInstSig.GenericArguments.Add(GetTypeSig(module, gp));
return module.Import(genericInstSig).ToTypeDefOrRef(); return genericInstSig;
} }
// Generate and save all DLLs // Generate and save all DLLs