diff --git a/Il2CppDumper/Il2CppCSharpDumper.cs b/Il2CppDumper/Il2CppCSharpDumper.cs index bd646d1..f993577 100644 --- a/Il2CppDumper/Il2CppCSharpDumper.cs +++ b/Il2CppDumper/Il2CppCSharpDumper.cs @@ -207,6 +207,9 @@ namespace Il2CppInspector // Don't output field indices for const fields (they don't have any storage) if (!field.IsLiteral && !SuppressMetadata) sb.Append($" // 0x{(uint) field.Offset:X2}"); + // Output metadata file offset for const fields + if (field.IsLiteral && !SuppressMetadata) + sb.Append($" // Metadata: 0x{(uint) field.DefaultValueMetadataAddress:X8}"); sb.Append("\n"); } codeBlocks.Add("Fields", sb.ToString()); diff --git a/Il2CppInspector/Il2CppInspector.cs b/Il2CppInspector/Il2CppInspector.cs index 8ff151f..e5d6b46 100644 --- a/Il2CppInspector/Il2CppInspector.cs +++ b/Il2CppInspector/Il2CppInspector.cs @@ -20,7 +20,7 @@ namespace Il2CppInspector private Metadata Metadata { get; } // All method pointers sorted in ascending order (for finding the end of a method) - private List sortedMethodPointers { get; set; } + private List sortedMethodPointers { get; } // Shortcuts public double Version => Metadata.Version; @@ -41,8 +41,8 @@ namespace Il2CppInspector public int[] InterfaceUsageIndices => Metadata.InterfaceUsageIndices; public int[] NestedTypeIndices => Metadata.NestedTypeIndices; public int[] AttributeTypeIndices => Metadata.AttributeTypeIndices; - public Dictionary FieldDefaultValue { get; } = new Dictionary(); - public Dictionary ParameterDefaultValue { get; } = new Dictionary(); + public Dictionary FieldDefaultValue { get; } = new Dictionary(); + public Dictionary ParameterDefaultValue { get; } = new Dictionary(); public List FieldOffsets { get; } public List TypeUsages => Binary.Types; public Dictionary Modules => Binary.Modules; @@ -51,10 +51,10 @@ namespace Il2CppInspector // TODO: Finish all file access in the constructor and eliminate the need for this public IFileFormatReader BinaryImage => Binary.Image; - private object getDefaultValue(int typeIndex, int dataIndex) { + private (ulong MetadataAddress, object Value)? getDefaultValue(int typeIndex, int dataIndex) { // No default if (dataIndex == -1) - return null; + return (0ul, null); // Get pointer in binary to default value var pValue = Metadata.Header.fieldAndParameterDefaultValueDataOffset + dataIndex; @@ -62,7 +62,7 @@ namespace Il2CppInspector // Default value is null if (pValue == 0) - return null; + return (0ul, null); object value = null; Metadata.Position = pValue; @@ -107,7 +107,7 @@ namespace Il2CppInspector value = Encoding.UTF8.GetString(Metadata.ReadBytes(uiLen)); break; } - return value; + return ((ulong) pValue, value); } public Il2CppInspector(Il2CppBinary binary, Metadata metadata) { @@ -117,11 +117,11 @@ namespace Il2CppInspector // Get all field default values foreach (var fdv in Metadata.FieldDefaultValues) - FieldDefaultValue.Add(fdv.fieldIndex, getDefaultValue(fdv.typeIndex, fdv.dataIndex)); + FieldDefaultValue.Add(fdv.fieldIndex, ((ulong,object)) getDefaultValue(fdv.typeIndex, fdv.dataIndex)); // Get all parameter default values foreach (var pdv in Metadata.ParameterDefaultValues) - ParameterDefaultValue.Add(pdv.parameterIndex, getDefaultValue(pdv.typeIndex, pdv.dataIndex)); + ParameterDefaultValue.Add(pdv.parameterIndex, ((ulong,object)) getDefaultValue(pdv.typeIndex, pdv.dataIndex)); // Get all field offsets if (Binary.FieldOffsets != null) { diff --git a/Il2CppInspector/Reflection/FieldInfo.cs b/Il2CppInspector/Reflection/FieldInfo.cs index 11efb74..31182cc 100644 --- a/Il2CppInspector/Reflection/FieldInfo.cs +++ b/Il2CppInspector/Reflection/FieldInfo.cs @@ -16,6 +16,7 @@ namespace Il2CppInspector.Reflection { public Il2CppFieldDefinition Definition { get; } public int Index { get; } public long Offset { get; } + public ulong DefaultValueMetadataAddress { get; } // Custom attributes for this member public override IEnumerable CustomAttributes => CustomAttributeData.GetCustomAttributes(this); @@ -111,8 +112,10 @@ namespace Il2CppInspector.Reflection { Attributes |= FieldAttributes.HasDefault; // Default initialization value if present - if (pkg.FieldDefaultValue.TryGetValue(fieldIndex, out object variant)) - DefaultValue = variant; + if (pkg.FieldDefaultValue.TryGetValue(fieldIndex, out (ulong address, object variant) value)) { + DefaultValue = value.variant; + DefaultValueMetadataAddress = value.address; + } } public string GetAccessModifierString() => this switch { diff --git a/Il2CppInspector/Reflection/ParameterInfo.cs b/Il2CppInspector/Reflection/ParameterInfo.cs index b5f3ae8..1cda427 100644 --- a/Il2CppInspector/Reflection/ParameterInfo.cs +++ b/Il2CppInspector/Reflection/ParameterInfo.cs @@ -16,6 +16,7 @@ namespace Il2CppInspector.Reflection // IL2CPP-specific data public Il2CppParameterDefinition Definition { get; } public int Index { get; } + public ulong DefaultValueMetadataAddress { get; } // Information/flags about the parameter public ParameterAttributes Attributes { get; } @@ -84,8 +85,10 @@ namespace Il2CppInspector.Reflection Attributes |= ParameterAttributes.Retval; // Default initialization value if present - if (pkg.ParameterDefaultValue.TryGetValue(paramIndex, out object variant)) - DefaultValue = variant; + if (pkg.ParameterDefaultValue.TryGetValue(paramIndex, out (ulong address, object variant) value)) { + DefaultValue = value.variant; + DefaultValueMetadataAddress = value.address; + } } public string GetModifierString() => @@ -100,7 +103,7 @@ namespace Il2CppInspector.Reflection (Position == 0 && Member.GetCustomAttributes("System.Runtime.CompilerServices.ExtensionAttribute").Any()? "this ":"") + $"{CustomAttributes.ToString(inline: true, emitPointer: emitPointer).Replace("[ParamArray]", "params")}" + $"{getCSharpSignatureString()} {Name}" - + (HasDefaultValue ? " = " + DefaultValue.ToCSharpValue() : ""); + + (HasDefaultValue ? " = " + DefaultValue.ToCSharpValue() + (emitPointer && !(DefaultValue is null)? $" /* Metadata: 0x{(uint) DefaultValueMetadataAddress:X8} */" : "") : ""); public string GetReturnParameterString() => !IsRetval? null : getCSharpSignatureString(); }