Skip to content

Commit

Permalink
Core: Fix issues with CA gen analysis on v27, crash if no game path o…
Browse files Browse the repository at this point in the history
…r force options specified.
  • Loading branch information
SamboyCoding committed Jan 28, 2025
1 parent 3f553f5 commit 799006b
Show file tree
Hide file tree
Showing 8 changed files with 57 additions and 7 deletions.
26 changes: 24 additions & 2 deletions Cpp2IL.Core/Model/Contexts/HasCustomAttributes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ public abstract class HasCustomAttributes(uint token, ApplicationAnalysisContext
: HasToken(token, appContext)
{
private bool _hasAnalyzedCustomAttributeData;
private bool _hasInitCustomAttributeData;

/// <summary>
/// On V29, stores the custom attribute blob. Pre-29, stores the bytes for the custom attribute generator function.
Expand Down Expand Up @@ -63,11 +64,16 @@ public abstract class HasCustomAttributes(uint token, ApplicationAnalysisContext
public abstract AssemblyAnalysisContext CustomAttributeAssembly { get; }

public abstract string CustomAttributeOwnerName { get; }

/// <summary>
/// Returns true if this member is injected by Cpp2IL (and thus should not be analyzed for custom attributes).
/// </summary>
protected virtual bool IsInjected { get; } = false;

/// <summary>
/// Pre-v29, stores the index of the custom attribute range for this member. Post-v29, always 0.
/// Pre-v29, stores the index of the custom attribute range for this member. Post-v29, always -1.
/// </summary>
private int Pre29RangeIndex;
private int Pre29RangeIndex = -1;

public bool IsCompilerGeneratedBasedOnCustomAttributes =>
CustomAttributes?.Any(a => a.Constructor.DeclaringType!.FullName.Contains("CompilerGeneratedAttribute"))
Expand All @@ -80,6 +86,10 @@ public abstract class HasCustomAttributes(uint token, ApplicationAnalysisContext

protected void InitCustomAttributeData()
{
if(IsInjected)
return;

_hasInitCustomAttributeData = true;
if (AppContext.MetadataVersion >= 29)
{
var offsets = GetV29BlobOffsets();
Expand Down Expand Up @@ -157,6 +167,12 @@ private void InitPre29AttributeGeneratorAnalysis(int rangeIndex)
}
else
{
if(AttributeTypeRange == null || AttributeTypeRange.count == 0)
{
RawIl2CppCustomAttributeData = Array.Empty<byte>();
return;
}

var baseAddress = CustomAttributeAssembly.CodeGenModule!.customAttributeCacheGenerator;
var relativeIndex = rangeIndex - CustomAttributeAssembly.Definition.Image.customAttributeStart;
var ptrToAddress = baseAddress + (ulong)relativeIndex * AppContext.Binary.PointerSize;
Expand All @@ -181,6 +197,12 @@ public void AnalyzeCustomAttributeData(bool allowAnalysis = true)
{
if (_hasAnalyzedCustomAttributeData)
return;

if(IsInjected)
return;

if(!_hasInitCustomAttributeData)
throw new($"Must call InitCustomAttributeData before AnalyzeCustomAttributeData on {this}");

_hasAnalyzedCustomAttributeData = true;

Expand Down
2 changes: 2 additions & 0 deletions Cpp2IL.Core/Model/Contexts/InjectedFieldAnalysisContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ public class InjectedFieldAnalysisContext : FieldAnalysisContext
public override TypeAnalysisContext FieldTypeContext { get; }
public override FieldAttributes Attributes { get; }

protected override bool IsInjected => true;

public InjectedFieldAnalysisContext(string name, TypeAnalysisContext type, FieldAttributes attributes, TypeAnalysisContext parent) : base(null, parent)
{
OverrideName = name;
Expand Down
2 changes: 2 additions & 0 deletions Cpp2IL.Core/Model/Contexts/InjectedMethodAnalysisContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ public class InjectedMethodAnalysisContext : MethodAnalysisContext
public override bool IsStatic { get; }

public override MethodAttributes Attributes { get; }

protected override bool IsInjected => true;

public InjectedMethodAnalysisContext(TypeAnalysisContext parent, string name, bool isStatic, TypeAnalysisContext returnType, MethodAttributes attributes, TypeAnalysisContext[] injectedParameterTypes, string[]? injectedParameterNames = null) : base(null, parent)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ public class InjectedParameterAnalysisContext : ParameterAnalysisContext
public override bool IsRef => ParameterTypeContext is ReferencedTypeAnalysisContext;

public override ParameterAttributes ParameterAttributes => ParameterAttributes.None;

protected override bool IsInjected => true;

public InjectedParameterAnalysisContext(string? name, Il2CppType type, int paramIndex, MethodAnalysisContext declaringMethod)
: this(name, declaringMethod.DeclaringType!.DeclaringAssembly.ResolveIl2CppType(type) ?? throw new($"Type {type} could not be resolved."), paramIndex, declaringMethod)
Expand Down
2 changes: 2 additions & 0 deletions Cpp2IL.Core/Model/Contexts/InjectedTypeAnalysisContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ public class InjectedTypeAnalysisContext : TypeAnalysisContext
public override string DefaultNs { get; }

public override TypeAttributes TypeAttributes { get; }

protected override bool IsInjected => true;

public InjectedTypeAnalysisContext(AssemblyAnalysisContext containingAssembly, string name, string ns, TypeAnalysisContext? baseType, TypeAttributes typeAttributes = DefaultTypeAttributes) : base(null, containingAssembly)
{
Expand Down
4 changes: 4 additions & 0 deletions Cpp2IL.Core/Utils/MiscUtils.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
//#define NOT_REALLY_PARALLEL_FOR_TESTING

using System;
using System.Collections;
using System.Collections.Generic;
Expand Down Expand Up @@ -247,7 +249,9 @@ bool F2(T t)
}

enumerable
#if !NOT_REALLY_PARALLEL_FOR_TESTING
.AsParallel()
#endif
.Select((Func<T, bool>)F2)
.ToList();
}
Expand Down
2 changes: 1 addition & 1 deletion Cpp2IL/CommandLineArgs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ namespace Cpp2IL;
public class CommandLineArgs
{
[Option("game-path", HelpText = "Specify path to the game folder (containing the exe)")]
public string GamePath { get; set; } = null!; //Suppressed because it's set by CommandLineParser.
public string? GamePath { get; set; } = null!; //Suppressed because it's set by CommandLineParser.

[Option("exe-name", HelpText = "Specify an override for the unity executable name in case the auto-detection doesn't work.")]
public string? ExeName { get; set; }
Expand Down
24 changes: 20 additions & 4 deletions Cpp2IL/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,10 @@
using LibCpp2IL.Wasm;
using AssetRipper.Primitives;
using Cpp2IL.Core.Extensions;

#if NET472
using LibCpp2IL;
#endif

namespace Cpp2IL;

Expand All @@ -28,10 +31,15 @@ internal class Program

public static readonly string Cpp2IlVersionString = typeof(Program).Assembly.GetCustomAttribute<AssemblyInformationalVersionAttribute>()!.InformationalVersion;

private static void ResolvePathsFromCommandLine(string gamePath, string? inputExeName, ref Cpp2IlRuntimeArgs args)
private static void ResolvePathsFromCommandLine(string? gamePath, string? inputExeName, ref Cpp2IlRuntimeArgs args)
{
if (string.IsNullOrEmpty(gamePath))
throw new SoftException("No force options provided, and no game path was provided either. Please provide a game path or use the --force- options.");

//Somehow the above doesn't tell .net that gamePath can't be null on net472, so we do this stupid thing to avoid nullable warnings
#if NET472
gamePath = gamePath!;
#endif

Logger.VerboseNewline("Beginning path resolution...");

Expand Down Expand Up @@ -341,7 +349,7 @@ private static void HandleXapk(string gamePath, ref Cpp2IlRuntimeArgs args)
ZipArchiveEntry? configApk = null;
var configApks = xapkZip.Entries.Where(e => e.FullName.Contains("config.") && e.FullName.EndsWith(".apk")).ToList();

var instructionSetPreference = new string[] { "arm64_v8a", "arm64", "armeabi_v7a", "arm" };
var instructionSetPreference = new[] { "arm64_v8a", "arm64", "armeabi_v7a", "arm" };
foreach (var instructionSet in instructionSetPreference)
{
configApk = configApks.FirstOrDefault(e => e.FullName.Contains(instructionSet));
Expand Down Expand Up @@ -495,7 +503,9 @@ private static Cpp2IlRuntimeArgs GetRuntimeOptionsFromCommandLine(string[] comma

ConsoleLogger.ShowVerbose = options.Verbose;

#pragma warning disable IL2026 // RequiresUnreferencedCode
Cpp2IlApi.Init();
#pragma warning restore IL2026

if (options.ListProcessors)
{
Expand All @@ -522,8 +532,14 @@ private static Cpp2IlRuntimeArgs GetRuntimeOptionsFromCommandLine(string[] comma

if (options.ForcedBinaryPath == null)
{
if (options.GamePath.StartsWith("~"))
options.GamePath = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile) + options.GamePath.Substring(1);
#if !NET472
if (options.GamePath != null && options.GamePath.StartsWith('~'))
options.GamePath = string.Concat(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), options.GamePath.AsSpan(1));
#else
if (options.GamePath != null && options.GamePath.StartsWith("~"))
options.GamePath = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile) + options.GamePath[1..];
#endif

ResolvePathsFromCommandLine(options.GamePath, options.ExeName, ref result);
}
else
Expand Down

0 comments on commit 799006b

Please sign in to comment.