diff --git a/Cpp2IL.Core/Cpp2IL.Core.csproj b/Cpp2IL.Core/Cpp2IL.Core.csproj index 88214b1c..2711e0de 100644 --- a/Cpp2IL.Core/Cpp2IL.Core.csproj +++ b/Cpp2IL.Core/Cpp2IL.Core.csproj @@ -7,7 +7,7 @@ Reverses Unity's IL2CPP Build Process true true - 13 + 14 enable true Samboy063.Cpp2IL.Core diff --git a/Cpp2IL.Core/Model/Contexts/ConcreteGenericFieldAnalysisContext.cs b/Cpp2IL.Core/Model/Contexts/ConcreteGenericFieldAnalysisContext.cs index 636b5441..2ae1abf6 100644 --- a/Cpp2IL.Core/Model/Contexts/ConcreteGenericFieldAnalysisContext.cs +++ b/Cpp2IL.Core/Model/Contexts/ConcreteGenericFieldAnalysisContext.cs @@ -10,6 +10,7 @@ public class ConcreteGenericFieldAnalysisContext : FieldAnalysisContext public override FieldAttributes DefaultAttributes => BaseFieldContext.DefaultAttributes; public override FieldAttributes? OverrideAttributes { get => BaseFieldContext.OverrideAttributes; set => BaseFieldContext.OverrideAttributes = value; } public override object? DefaultConstantValue => BaseFieldContext.DefaultConstantValue; + public override bool UseOverrideConstantValue { get => BaseFieldContext.UseOverrideConstantValue; set => BaseFieldContext.UseOverrideConstantValue = value; } public override object? OverrideConstantValue { get => BaseFieldContext.OverrideConstantValue; set => BaseFieldContext.OverrideConstantValue = value; } public override int DefaultOffset => BaseFieldContext.DefaultOffset; public override int? OverrideOffset { get => BaseFieldContext.OverrideOffset; set => BaseFieldContext.OverrideOffset = value; } diff --git a/Cpp2IL.Core/Model/Contexts/ConcreteGenericParameterAnalysisContext.cs b/Cpp2IL.Core/Model/Contexts/ConcreteGenericParameterAnalysisContext.cs index edf576e7..0019339a 100644 --- a/Cpp2IL.Core/Model/Contexts/ConcreteGenericParameterAnalysisContext.cs +++ b/Cpp2IL.Core/Model/Contexts/ConcreteGenericParameterAnalysisContext.cs @@ -10,6 +10,9 @@ public class ConcreteGenericParameterAnalysisContext : ParameterAnalysisContext public override ParameterAttributes? OverrideAttributes { get => BaseParameterContext.OverrideAttributes; set => BaseParameterContext.OverrideAttributes = value; } public override string DefaultName => BaseParameterContext.DefaultName; public override string? OverrideName { get => BaseParameterContext.OverrideName; set => BaseParameterContext.OverrideName = value; } + public override object? OriginalDefaultValue => BaseParameterContext.OriginalDefaultValue; + public override bool UseOverrideDefaultValue { get => BaseParameterContext.UseOverrideDefaultValue; set => BaseParameterContext.UseOverrideDefaultValue = value; } + public override object? OverrideDefaultValue { get => BaseParameterContext.OverrideDefaultValue; set => BaseParameterContext.OverrideDefaultValue = value; } protected override int CustomAttributeIndex => -1; public ConcreteGenericParameterAnalysisContext(ParameterAnalysisContext baseParameter, TypeAnalysisContext parameterType, ConcreteGenericMethodAnalysisContext declaringMethod) : base(null, baseParameter.ParameterIndex, declaringMethod) diff --git a/Cpp2IL.Core/Model/Contexts/FieldAnalysisContext.cs b/Cpp2IL.Core/Model/Contexts/FieldAnalysisContext.cs index ab945771..939ba125 100644 --- a/Cpp2IL.Core/Model/Contexts/FieldAnalysisContext.cs +++ b/Cpp2IL.Core/Model/Contexts/FieldAnalysisContext.cs @@ -45,11 +45,13 @@ public FieldAttributes Attributes public virtual object? DefaultConstantValue => BackingData?.Field.DefaultValue?.Value; + public virtual bool UseOverrideConstantValue { get; set; } = false; + public virtual object? OverrideConstantValue { get; set; } public object? ConstantValue { - get => OverrideConstantValue ?? DefaultConstantValue; + get => UseOverrideConstantValue ? OverrideConstantValue : DefaultConstantValue; set => OverrideConstantValue = value; } diff --git a/Cpp2IL.Core/Model/Contexts/InjectedFieldAnalysisContext.cs b/Cpp2IL.Core/Model/Contexts/InjectedFieldAnalysisContext.cs index eb5be740..fd45e658 100644 --- a/Cpp2IL.Core/Model/Contexts/InjectedFieldAnalysisContext.cs +++ b/Cpp2IL.Core/Model/Contexts/InjectedFieldAnalysisContext.cs @@ -7,13 +7,17 @@ public class InjectedFieldAnalysisContext : FieldAnalysisContext public override TypeAnalysisContext DefaultFieldType { get; } public override string DefaultName { get; } public override FieldAttributes DefaultAttributes { get; } + public override int DefaultOffset { get; } + public override object? DefaultConstantValue { get; } protected override bool IsInjected => true; - public InjectedFieldAnalysisContext(string name, TypeAnalysisContext type, FieldAttributes attributes, TypeAnalysisContext parent) : base(null, parent) + public InjectedFieldAnalysisContext(string name, TypeAnalysisContext type, FieldAttributes attributes, TypeAnalysisContext parent, int offset = -1, object? constantValue = null) : base(null, parent) { DefaultName = name; DefaultAttributes = attributes; DefaultFieldType = type; + DefaultOffset = offset; + DefaultConstantValue = constantValue; } } diff --git a/Cpp2IL.Core/Model/Contexts/InjectedParameterAnalysisContext.cs b/Cpp2IL.Core/Model/Contexts/InjectedParameterAnalysisContext.cs index f2e3eb32..146edce1 100644 --- a/Cpp2IL.Core/Model/Contexts/InjectedParameterAnalysisContext.cs +++ b/Cpp2IL.Core/Model/Contexts/InjectedParameterAnalysisContext.cs @@ -9,13 +9,16 @@ public class InjectedParameterAnalysisContext : ParameterAnalysisContext public override TypeAnalysisContext DefaultParameterType { get; } public override ParameterAttributes DefaultAttributes { get; } - + + public override object? OriginalDefaultValue { get; } + protected override bool IsInjected => true; - public InjectedParameterAnalysisContext(string? name, TypeAnalysisContext typeContext, ParameterAttributes attributes, int parameterIndex, MethodAnalysisContext declaringMethod) : base(null, parameterIndex, declaringMethod) + public InjectedParameterAnalysisContext(string? name, TypeAnalysisContext typeContext, ParameterAttributes attributes, int parameterIndex, MethodAnalysisContext declaringMethod, object? defaultValue = null) : base(null, parameterIndex, declaringMethod) { DefaultName = name ?? $"param_{parameterIndex}"; DefaultParameterType = typeContext; DefaultAttributes = attributes; + OriginalDefaultValue = defaultValue; } } diff --git a/Cpp2IL.Core/Model/Contexts/ParameterAnalysisContext.cs b/Cpp2IL.Core/Model/Contexts/ParameterAnalysisContext.cs index c501c833..2f99d494 100644 --- a/Cpp2IL.Core/Model/Contexts/ParameterAnalysisContext.cs +++ b/Cpp2IL.Core/Model/Contexts/ParameterAnalysisContext.cs @@ -55,10 +55,38 @@ public ParameterAttributes Attributes /// public bool IsRef => ParameterType is ByRefTypeAnalysisContext || Attributes.HasFlag(ParameterAttributes.Out); + public virtual object? OriginalDefaultValue + { + get + { + if (DefaultAttributes.HasFlag(ParameterAttributes.HasDefault)) + { + var index = Il2CppVariableWidthIndex.MakeTemporaryForFixedWidthUsage(DeclaringMethod.Definition!.parameterStart.Value + ParameterIndex); + return AppContext.Metadata.GetParameterDefaultValueFromIndex(index)?.ContainedDefaultValue; + } + return null; + } + } + + public virtual bool UseOverrideDefaultValue { get; set; } = false; + public virtual object? OverrideDefaultValue + { + get; + set + { + UseOverrideDefaultValue = true; + field = value; + } + } + /// - /// The default value data for this parameter. Null if, and only if, the parameter has no default value. If it has a default value of literally null, this will be non-null and have a data index of -1. + /// The default value data for this parameter. /// - public Il2CppParameterDefaultValue? DefaultValue { get; } + public object? DefaultValue + { + get => UseOverrideDefaultValue ? OverrideDefaultValue : OriginalDefaultValue; + set => OverrideDefaultValue = value; + } public virtual TypeAnalysisContext DefaultParameterType => AppContext.ResolveIl2CppType(Definition?.RawType) ?? throw new("Subclasses of ParameterAnalysisContext must provide a parameter type"); @@ -79,11 +107,6 @@ public ParameterAnalysisContext(Il2CppParameterDefinition? definition, int param if (Definition != null) { InitCustomAttributeData(); - - if (Attributes.HasFlag(ParameterAttributes.HasDefault)) - { - DefaultValue = AppContext.Metadata.GetParameterDefaultValueFromIndex(Il2CppVariableWidthIndex.MakeTemporaryForFixedWidthUsage(declaringMethod.Definition!.parameterStart.Value + parameterIndex))!; - } } } @@ -111,7 +134,7 @@ public override string ToString() if (Attributes.HasFlag(ParameterAttributes.HasDefault)) { - var defaultValue = DefaultValue!.ContainedDefaultValue; + var defaultValue = DefaultValue; if (defaultValue is string stringDefaultValue) defaultValue = $"\"{stringDefaultValue}\""; else if (defaultValue is bool boolDefaultValue) diff --git a/Cpp2IL.Core/OutputFormats/DiffableCsOutputFormat.cs b/Cpp2IL.Core/OutputFormats/DiffableCsOutputFormat.cs index 81b7af88..0c8ea99e 100644 --- a/Cpp2IL.Core/OutputFormats/DiffableCsOutputFormat.cs +++ b/Cpp2IL.Core/OutputFormats/DiffableCsOutputFormat.cs @@ -120,7 +120,7 @@ private static void WriteType(IndentedTextWriter writer, TypeAnalysisContext typ { writer.Write(enumValue.Name); writer.Write(" = "); - writer.Write(InvariantValue(enumValue.BackingData!.DefaultValue)); + writer.Write(InvariantValue(enumValue.ConstantValue)); writer.WriteLine(','); } } @@ -190,24 +190,24 @@ private static void WriteField(IndentedTextWriter writer, FieldAnalysisContext f } } - if (field.BackingData?.DefaultValue is { } defaultValue) + if (field.Attributes.HasFlag(FieldAttributes.HasDefault)) { writer.Write(" = "); - if (defaultValue is string stringDefaultValue) + if (field.ConstantValue is string stringDefaultValue) { writer.Write('"'); writer.Write(stringDefaultValue); writer.Write('"'); } - else if (defaultValue is char charDefaultValue) + else if (field.ConstantValue is char charDefaultValue) { writer.Write("'\\u"); writer.Write(((int)charDefaultValue).ToString("X")); writer.Write("'"); } else - writer.Write(InvariantValue(defaultValue)); + writer.Write(InvariantValue(field.ConstantValue)); } writer.Write("; //Field offset: 0x"); @@ -407,5 +407,5 @@ private static void WriteCustomAttributes(IndentedTextWriter writer, HasCustomAt => CsFileUtils.WriteCustomAttributeStrings(owner, writer, true, true); private static string InvariantValue(object? value) - => value is null ? "" : value is IFormattable f ? f.ToString(null, CultureInfo.InvariantCulture) : value.ToString() ?? ""; + => value is null ? "null" : value is IFormattable f ? f.ToString(null, CultureInfo.InvariantCulture) : value.ToString() ?? ""; } diff --git a/Cpp2IL.Core/ProcessingLayers/StableRenamingProcessingLayer.cs b/Cpp2IL.Core/ProcessingLayers/StableRenamingProcessingLayer.cs index 3de4da21..518e2302 100644 --- a/Cpp2IL.Core/ProcessingLayers/StableRenamingProcessingLayer.cs +++ b/Cpp2IL.Core/ProcessingLayers/StableRenamingProcessingLayer.cs @@ -131,7 +131,7 @@ public override void Process(ApplicationAnalysisContext appContext, Action IntegerCache = new(); - private static readonly Dictionary ByteCache = new(); + private static readonly Constant[] IntegerCache = new Constant[16]; + private static readonly Constant[] ByteCache = new Constant[16]; private static readonly Constant SingleZero = Constant.FromValue(0.0F); @@ -27,10 +26,11 @@ static AsmResolverConstants() } } - public static Constant GetOrCreateConstant(object from) + public static Constant GetOrCreateConstant(object? from) { return from switch { + null => Null, string s => new(ElementType.String, new(Encoding.Unicode.GetBytes(s))), bool b => b ? BoolTrue : BoolFalse, byte and >= 0 and < 16 => ByteCache[(byte)@from], @@ -45,10 +45,8 @@ private static Constant CreateNewConstant(IConvertible from) return new(GetElementTypeFromConstant(from), new(MiscUtils.RawBytes(from))); } - private static ElementType GetElementTypeFromConstant(object? primitive) - => primitive is null - ? ElementType.Object - : primitive switch + private static ElementType GetElementTypeFromConstant(IConvertible primitive) + => primitive switch { sbyte => ElementType.I1, byte => ElementType.U1,