Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cpp2IL.Core/Cpp2IL.Core.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<Description>Reverses Unity's IL2CPP Build Process</Description>
<EmbedUntrackedSources>true</EmbedUntrackedSources>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<LangVersion>13</LangVersion>
<LangVersion>14</LangVersion>
<Nullable>enable</Nullable>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<PackageId>Samboy063.Cpp2IL.Core</PackageId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
4 changes: 3 additions & 1 deletion Cpp2IL.Core/Model/Contexts/FieldAnalysisContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down
6 changes: 5 additions & 1 deletion Cpp2IL.Core/Model/Contexts/InjectedFieldAnalysisContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}
39 changes: 31 additions & 8 deletions Cpp2IL.Core/Model/Contexts/ParameterAnalysisContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,38 @@ public ParameterAttributes Attributes
/// </summary>
public bool IsRef => ParameterType is ByRefTypeAnalysisContext || Attributes.HasFlag(ParameterAttributes.Out);

public virtual object? OriginalDefaultValue
{
get
{
if (DefaultAttributes.HasFlag(ParameterAttributes.HasDefault))
{
var index = Il2CppVariableWidthIndex<Il2CppParameterDefinition>.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;
}
}

/// <summary>
/// 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.
/// </summary>
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");

Expand All @@ -79,11 +107,6 @@ public ParameterAnalysisContext(Il2CppParameterDefinition? definition, int param
if (Definition != null)
{
InitCustomAttributeData();

if (Attributes.HasFlag(ParameterAttributes.HasDefault))
{
DefaultValue = AppContext.Metadata.GetParameterDefaultValueFromIndex(Il2CppVariableWidthIndex<Il2CppParameterDefinition>.MakeTemporaryForFixedWidthUsage(declaringMethod.Definition!.parameterStart.Value + parameterIndex))!;
}
}
}

Expand Down Expand Up @@ -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)
Expand Down
12 changes: 6 additions & 6 deletions Cpp2IL.Core/OutputFormats/DiffableCsOutputFormat.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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(',');
}
}
Expand Down Expand Up @@ -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");
Expand Down Expand Up @@ -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() ?? "";
}
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ public override void Process(ApplicationAnalysisContext appContext, Action<int,
if (!StableNameGenerator.IsObfuscated(field.Name))
continue;

field.OverrideName = $"EnumValue" + field.BackingData!.DefaultValue;
field.OverrideName = $"EnumValue{field.ConstantValue}";
}
}

Expand Down
16 changes: 4 additions & 12 deletions Cpp2IL.Core/Utils/AsmResolver/AsmResolverAssemblyPopulator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -351,8 +351,8 @@ private static void CopyFieldsInType(ReferenceImporter importer, TypeAnalysisCon
var managedField = new FieldDefinition(fieldContext.Name, (FieldAttributes)fieldContext.Attributes, fieldTypeSig);

//Field default values
if (managedField.HasDefault && fieldContext.ConstantValue is { } constVal)
managedField.Constant = AsmResolverConstants.GetOrCreateConstant(constVal);
if (managedField.HasDefault)
managedField.Constant = AsmResolverConstants.GetOrCreateConstant(fieldContext.ConstantValue);

//Field Initial Values (used for allocation of Array Literals)
if (managedField.HasFieldRva)
Expand Down Expand Up @@ -385,16 +385,8 @@ private static void CopyMethodsInType(ReferenceImporter importer, TypeAnalysisCo
var sequence = (ushort)(i + 1); //Add one because sequence 0 is the return type
parameterDefinitions[i] = new(sequence, parameterAnalysisContext.Name, (ParameterAttributes)parameterAnalysisContext.Attributes);

if (parameterAnalysisContext.DefaultValue is not { } defaultValueData || !parameterAnalysisContext.Attributes.HasFlag(System.Reflection.ParameterAttributes.HasDefault))
continue;

if (defaultValueData?.ContainedDefaultValue is { } constVal)
parameterDefinitions[i].Constant = AsmResolverConstants.GetOrCreateConstant(constVal);
else if (defaultValueData is { dataIndex.IsNull: true })
{
//Literal null
parameterDefinitions[i].Constant = AsmResolverConstants.Null;
}
if (parameterAnalysisContext.Attributes.HasFlag(System.Reflection.ParameterAttributes.HasDefault))
parameterDefinitions[i].Constant = AsmResolverConstants.GetOrCreateConstant(parameterAnalysisContext.DefaultValue);
}


Expand Down
16 changes: 7 additions & 9 deletions Cpp2IL.Core/Utils/AsmResolver/AsmResolverConstants.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using System;
using System.Collections.Generic;
using System.Text;
using AsmResolver.DotNet;
using AsmResolver.PE.DotNet.Metadata.Tables;
Expand All @@ -8,10 +7,10 @@ namespace Cpp2IL.Core.Utils.AsmResolver;

public static class AsmResolverConstants
{
public static readonly Constant Null = Constant.FromNull();
private static readonly Constant Null = Constant.FromNull();

private static readonly Dictionary<int, Constant> IntegerCache = new();
private static readonly Dictionary<byte, Constant> 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);

Expand All @@ -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],
Expand All @@ -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,
Expand Down
Loading