smaller tweaks, hack around loops in cpp type layouting

This commit is contained in:
LukeFZ
2025-02-08 17:40:15 +01:00
parent e6bd289aa4
commit ffb1996252
6 changed files with 71 additions and 23 deletions

View File

@@ -228,6 +228,14 @@ namespace Il2CppInspector.Cpp
ns.ReserveName("_");
fieldType = types.Struct(name + "__Fields");
var baseFieldType = types[TypeNamer.GetName(ti.BaseType) + "__Fields"];
if (baseFieldType == null)
{
// if we end up here, there is a loop in the type generation.
// this is not currently supported, so we throw an exception.
throw new InvalidOperationException($"Failed to generate type for {ti}");
}
fieldType.AddField("_", baseFieldType);
GenerateFieldList(fieldType, ns, ti);
}
@@ -437,17 +445,31 @@ namespace Il2CppInspector.Cpp
/// <returns>A string containing C type declarations</returns>
public List<(TypeInfo ilType, CppComplexType valueType, CppComplexType referenceType, CppComplexType fieldsType,
CppComplexType vtableType, CppComplexType staticsType)> GenerateRemainingTypeDeclarations() {
try
{
var decl = GenerateVisitedFieldStructs().Select(s =>
(s.ilType, s.valueType, s.referenceType, s.fieldsType, (CppComplexType) null, (CppComplexType) null)).ToList();
(s.ilType, s.valueType, s.referenceType, s.fieldsType, (CppComplexType)null,
(CppComplexType)null))
.ToList();
foreach (var ti in TodoTypeStructs) {
foreach (var ti in TodoTypeStructs)
{
var (cls, statics, vtable) = GenerateTypeStruct(ti);
decl.Add((ti, null, cls, null, vtable, statics));
}
TodoTypeStructs.Clear();
return decl;
}
catch (Exception)
{
return null;
}
finally
{
TodoTypeStructs.Clear();
TodoFieldStructs.Clear();
}
}
#endregion
#region Method Generation

View File

@@ -4,8 +4,6 @@
All rights reserved.
*/
using System;
namespace Il2CppInspector.Cpp
{
// A field in a C++ type

View File

@@ -337,7 +337,15 @@ namespace Il2CppInspector
}
// Read method invoker pointer indices - one per method
MethodInvokerIndices.Add(module, Image.ReadMappedPrimitiveArray<int>(module.InvokerIndices, (int) module.MethodPointerCount));
try
{
MethodInvokerIndices.Add(module,
Image.ReadMappedPrimitiveArray<int>(module.InvokerIndices, (int)module.MethodPointerCount));
}
catch (InvalidOperationException)
{
MethodInvokerIndices.Add(module, [..new int[(int)module.MethodPointerCount]]);
}
}
}
@@ -398,12 +406,21 @@ namespace Il2CppInspector
var type = TypeReferences[i];
if (type.Type.IsTypeDefinitionEnum())
{
if (type.Data.Type.PointerValue >= baseDefinitionPtr)
type.Data.Value = (type.Data.Type.PointerValue - baseDefinitionPtr) / definitionSize;
Debug.Assert(Metadata!.Types.Length > type.Data.KlassIndex);
}
else if (type.Type.IsGenericParameterEnum())
{
if (type.Data.Type.PointerValue >= baseGenericPtr)
type.Data.Value = (type.Data.Type.PointerValue - baseGenericPtr) / genericParameterSize;
Debug.Assert(Metadata!.GenericParameters.Length > type.Data.KlassIndex);
}
Debug.Assert((long)type.Data.Value >= 0);
builder.Add(type);
}
TypeReferences = builder.MoveToImmutable();

View File

@@ -236,7 +236,17 @@ namespace Il2CppInspector.Model
break;
case MetadataUsageType.MethodDef or MetadataUsageType.MethodRef:
var method = TypeModel.GetMetadataUsageMethod(usage);
declarationGenerator.IncludeMethod(method);
var definitions = declarationGenerator.GenerateRemainingTypeDeclarations();
if (definitions == null)
{
// if we end up here, type generation has failed
// todo: this try/catch is a massive hack to sidestep the original issue of generation failing,
// todo: this needs to be improved.
break;
}
AddTypes(declarationGenerator.GenerateRemainingTypeDeclarations());
// Any method here SHOULD already be in the Methods list
@@ -247,6 +257,7 @@ namespace Il2CppInspector.Model
Methods.Add(method, fnPtr, new AppMethod(method, fnPtr) { Group = Group });
}
Methods[method].MethodInfoPtrAddress = address;
break;
// FieldInfo is used for array initializers.

View File

@@ -430,7 +430,7 @@ namespace Il2CppInspector.Outputs
if (method.VirtualAddress.HasValue) {
var args = new List<(string,object)> {
("RVA", (method.VirtualAddress.Value.Start - model.Package.BinaryImage.ImageBase).ToAddressString()),
("Offset", string.Format("0x{0:X}", model.Package.BinaryImage.MapVATR(method.VirtualAddress.Value.Start))),
("Offset", $"0x{model.Package.BinaryImage.MapVATR(method.VirtualAddress.Value.Start):X}"),
("VA", method.VirtualAddress.Value.Start.ToAddressString())
};
if (method.Definition.Slot != ushort.MaxValue)
@@ -470,7 +470,7 @@ namespace Il2CppInspector.Outputs
return def.AddAttribute(module, attributeAttribute,
("Name", ca.AttributeType.Name),
("RVA", (ca.VirtualAddress.Start - model.Package.BinaryImage.ImageBase).ToAddressString()),
("Offset", string.Format("0x{0:X}", model.Package.BinaryImage.MapVATR(ca.VirtualAddress.Start)))
("Offset", $"0x{model.Package.BinaryImage.MapVATR(ca.VirtualAddress.Start):X}")
);
}

View File

@@ -165,10 +165,9 @@ namespace Il2CppInspector.Reflection
// Generic type definitions have an invoker index of -1
foreach (var method in MethodsByDefinitionIndex) {
var index = package.GetInvokerIndex(method.DeclaringType.Assembly.ModuleDefinition, method.Definition);
if (index != -1) {
if (MethodInvokers[index] == null)
MethodInvokers[index] = new MethodInvoker(method, index);
if (index != -1)
{
MethodInvokers[index] ??= new MethodInvoker(method, index);
method.Invoker = MethodInvokers[index];
}
}
@@ -176,12 +175,13 @@ namespace Il2CppInspector.Reflection
// Create method invokers sourced from generic method invoker indices
foreach (var spec in GenericMethods.Keys) {
if (package.GenericMethodInvokerIndices.TryGetValue(spec, out var index)) {
if (MethodInvokers[index] == null)
MethodInvokers[index] = new MethodInvoker(GenericMethods[spec], index);
if (index != -1)
{
MethodInvokers[index] ??= new MethodInvoker(GenericMethods[spec], index);
GenericMethods[spec].Invoker = MethodInvokers[index];
}
}
}
// Post-processing hook
PluginHooks.PostProcessTypeModel(this);