smaller tweaks, hack around loops in cpp type layouting
This commit is contained in:
@@ -228,6 +228,14 @@ namespace Il2CppInspector.Cpp
|
|||||||
ns.ReserveName("_");
|
ns.ReserveName("_");
|
||||||
fieldType = types.Struct(name + "__Fields");
|
fieldType = types.Struct(name + "__Fields");
|
||||||
var baseFieldType = types[TypeNamer.GetName(ti.BaseType) + "__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);
|
fieldType.AddField("_", baseFieldType);
|
||||||
GenerateFieldList(fieldType, ns, ti);
|
GenerateFieldList(fieldType, ns, ti);
|
||||||
}
|
}
|
||||||
@@ -437,17 +445,31 @@ namespace Il2CppInspector.Cpp
|
|||||||
/// <returns>A string containing C type declarations</returns>
|
/// <returns>A string containing C type declarations</returns>
|
||||||
public List<(TypeInfo ilType, CppComplexType valueType, CppComplexType referenceType, CppComplexType fieldsType,
|
public List<(TypeInfo ilType, CppComplexType valueType, CppComplexType referenceType, CppComplexType fieldsType,
|
||||||
CppComplexType vtableType, CppComplexType staticsType)> GenerateRemainingTypeDeclarations() {
|
CppComplexType vtableType, CppComplexType staticsType)> GenerateRemainingTypeDeclarations() {
|
||||||
|
try
|
||||||
|
{
|
||||||
var decl = GenerateVisitedFieldStructs().Select(s =>
|
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);
|
var (cls, statics, vtable) = GenerateTypeStruct(ti);
|
||||||
decl.Add((ti, null, cls, null, vtable, statics));
|
decl.Add((ti, null, cls, null, vtable, statics));
|
||||||
}
|
}
|
||||||
TodoTypeStructs.Clear();
|
|
||||||
|
|
||||||
return decl;
|
return decl;
|
||||||
}
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
TodoTypeStructs.Clear();
|
||||||
|
TodoFieldStructs.Clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Method Generation
|
#region Method Generation
|
||||||
|
|||||||
@@ -4,8 +4,6 @@
|
|||||||
All rights reserved.
|
All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace Il2CppInspector.Cpp
|
namespace Il2CppInspector.Cpp
|
||||||
{
|
{
|
||||||
// A field in a C++ type
|
// A field in a C++ type
|
||||||
|
|||||||
@@ -337,7 +337,15 @@ namespace Il2CppInspector
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Read method invoker pointer indices - one per method
|
// 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];
|
var type = TypeReferences[i];
|
||||||
if (type.Type.IsTypeDefinitionEnum())
|
if (type.Type.IsTypeDefinitionEnum())
|
||||||
{
|
{
|
||||||
|
if (type.Data.Type.PointerValue >= baseDefinitionPtr)
|
||||||
type.Data.Value = (type.Data.Type.PointerValue - baseDefinitionPtr) / definitionSize;
|
type.Data.Value = (type.Data.Type.PointerValue - baseDefinitionPtr) / definitionSize;
|
||||||
|
|
||||||
|
Debug.Assert(Metadata!.Types.Length > type.Data.KlassIndex);
|
||||||
}
|
}
|
||||||
else if (type.Type.IsGenericParameterEnum())
|
else if (type.Type.IsGenericParameterEnum())
|
||||||
{
|
{
|
||||||
|
if (type.Data.Type.PointerValue >= baseGenericPtr)
|
||||||
type.Data.Value = (type.Data.Type.PointerValue - baseGenericPtr) / genericParameterSize;
|
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);
|
builder.Add(type);
|
||||||
}
|
}
|
||||||
TypeReferences = builder.MoveToImmutable();
|
TypeReferences = builder.MoveToImmutable();
|
||||||
|
|||||||
@@ -236,7 +236,17 @@ namespace Il2CppInspector.Model
|
|||||||
break;
|
break;
|
||||||
case MetadataUsageType.MethodDef or MetadataUsageType.MethodRef:
|
case MetadataUsageType.MethodDef or MetadataUsageType.MethodRef:
|
||||||
var method = TypeModel.GetMetadataUsageMethod(usage);
|
var method = TypeModel.GetMetadataUsageMethod(usage);
|
||||||
|
|
||||||
declarationGenerator.IncludeMethod(method);
|
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());
|
AddTypes(declarationGenerator.GenerateRemainingTypeDeclarations());
|
||||||
|
|
||||||
// Any method here SHOULD already be in the Methods list
|
// 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.Add(method, fnPtr, new AppMethod(method, fnPtr) { Group = Group });
|
||||||
}
|
}
|
||||||
Methods[method].MethodInfoPtrAddress = address;
|
Methods[method].MethodInfoPtrAddress = address;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// FieldInfo is used for array initializers.
|
// FieldInfo is used for array initializers.
|
||||||
|
|||||||
@@ -430,7 +430,7 @@ namespace Il2CppInspector.Outputs
|
|||||||
if (method.VirtualAddress.HasValue) {
|
if (method.VirtualAddress.HasValue) {
|
||||||
var args = new List<(string,object)> {
|
var args = new List<(string,object)> {
|
||||||
("RVA", (method.VirtualAddress.Value.Start - model.Package.BinaryImage.ImageBase).ToAddressString()),
|
("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())
|
("VA", method.VirtualAddress.Value.Start.ToAddressString())
|
||||||
};
|
};
|
||||||
if (method.Definition.Slot != ushort.MaxValue)
|
if (method.Definition.Slot != ushort.MaxValue)
|
||||||
@@ -470,7 +470,7 @@ namespace Il2CppInspector.Outputs
|
|||||||
return def.AddAttribute(module, attributeAttribute,
|
return def.AddAttribute(module, attributeAttribute,
|
||||||
("Name", ca.AttributeType.Name),
|
("Name", ca.AttributeType.Name),
|
||||||
("RVA", (ca.VirtualAddress.Start - model.Package.BinaryImage.ImageBase).ToAddressString()),
|
("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}")
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -165,10 +165,9 @@ namespace Il2CppInspector.Reflection
|
|||||||
// Generic type definitions have an invoker index of -1
|
// Generic type definitions have an invoker index of -1
|
||||||
foreach (var method in MethodsByDefinitionIndex) {
|
foreach (var method in MethodsByDefinitionIndex) {
|
||||||
var index = package.GetInvokerIndex(method.DeclaringType.Assembly.ModuleDefinition, method.Definition);
|
var index = package.GetInvokerIndex(method.DeclaringType.Assembly.ModuleDefinition, method.Definition);
|
||||||
if (index != -1) {
|
if (index != -1)
|
||||||
if (MethodInvokers[index] == null)
|
{
|
||||||
MethodInvokers[index] = new MethodInvoker(method, index);
|
MethodInvokers[index] ??= new MethodInvoker(method, index);
|
||||||
|
|
||||||
method.Invoker = MethodInvokers[index];
|
method.Invoker = MethodInvokers[index];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -176,12 +175,13 @@ namespace Il2CppInspector.Reflection
|
|||||||
// Create method invokers sourced from generic method invoker indices
|
// Create method invokers sourced from generic method invoker indices
|
||||||
foreach (var spec in GenericMethods.Keys) {
|
foreach (var spec in GenericMethods.Keys) {
|
||||||
if (package.GenericMethodInvokerIndices.TryGetValue(spec, out var index)) {
|
if (package.GenericMethodInvokerIndices.TryGetValue(spec, out var index)) {
|
||||||
if (MethodInvokers[index] == null)
|
if (index != -1)
|
||||||
MethodInvokers[index] = new MethodInvoker(GenericMethods[spec], index);
|
{
|
||||||
|
MethodInvokers[index] ??= new MethodInvoker(GenericMethods[spec], index);
|
||||||
GenericMethods[spec].Invoker = MethodInvokers[index];
|
GenericMethods[spec].Invoker = MethodInvokers[index];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Post-processing hook
|
// Post-processing hook
|
||||||
PluginHooks.PostProcessTypeModel(this);
|
PluginHooks.PostProcessTypeModel(this);
|
||||||
|
|||||||
Reference in New Issue
Block a user