From 9a63bf733c545960b92fb9e0bb4dd3c65e6d78da Mon Sep 17 00:00:00 2001
From: Jeremy Pritts <49847914+ds5678@users.noreply.github.com>
Date: Wed, 27 Dec 2023 23:18:13 -0500
Subject: [PATCH] Make VersionAwareSizeOf trimmable
---
Cpp2IL.Core/Cpp2IL.Core.csproj | 1 +
Cpp2IL.Core/Utils/MiscUtils.cs | 3 +-
Cpp2IL/Cpp2IL.csproj | 9 ++-
LibCpp2IL/BinarySearcher.cs | 6 +-
LibCpp2IL/Elf/ElfFile.cs | 4 +-
LibCpp2IL/LibCpp2IL.csproj | 3 +-
LibCpp2IL/LibCpp2IlUtils.cs | 92 ++++++++++++++--------------
LibCpp2IL/Metadata/Il2CppMetadata.cs | 5 +-
8 files changed, 66 insertions(+), 57 deletions(-)
diff --git a/Cpp2IL.Core/Cpp2IL.Core.csproj b/Cpp2IL.Core/Cpp2IL.Core.csproj
index 8c67f80d..a4721ee2 100644
--- a/Cpp2IL.Core/Cpp2IL.Core.csproj
+++ b/Cpp2IL.Core/Cpp2IL.Core.csproj
@@ -22,6 +22,7 @@
true
+ true
diff --git a/Cpp2IL.Core/Utils/MiscUtils.cs b/Cpp2IL.Core/Utils/MiscUtils.cs
index e861ab31..b2beb0a4 100644
--- a/Cpp2IL.Core/Utils/MiscUtils.cs
+++ b/Cpp2IL.Core/Utils/MiscUtils.cs
@@ -1,6 +1,7 @@
using System;
using System.Collections;
using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Text;
using Cpp2IL.Core.Extensions;
@@ -153,7 +154,7 @@ public static int GetPointerSizeBytes()
return LibCpp2IlMain.Binary!.is32Bit ? 4 : 8;
}
- public static IConvertible ReinterpretBytes(IConvertible original, Type desired)
+ public static IConvertible ReinterpretBytes(IConvertible original, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicFields)] Type desired)
{
if (desired is null)
throw new ArgumentNullException(nameof(desired), "Destination type is null");
diff --git a/Cpp2IL/Cpp2IL.csproj b/Cpp2IL/Cpp2IL.csproj
index 9bb21c9d..0dcb1864 100644
--- a/Cpp2IL/Cpp2IL.csproj
+++ b/Cpp2IL/Cpp2IL.csproj
@@ -9,14 +9,17 @@
10
enable
Exe
- true
- true
net7.0;net472
- partial
2022.1.0
true
+
+ partial
+ true
+ true
+
+
bin\x64\Debug\
diff --git a/LibCpp2IL/BinarySearcher.cs b/LibCpp2IL/BinarySearcher.cs
index 27614cb3..7241f3b3 100644
--- a/LibCpp2IL/BinarySearcher.cs
+++ b/LibCpp2IL/BinarySearcher.cs
@@ -213,7 +213,7 @@ internal ulong FindCodeRegistrationPost2019()
//We have pCodegenModules which *should* be x-reffed in the last pointer of Il2CppCodeRegistration.
//So, subtract the size of one pointer from that...
- var bytesToGoBack = (ulong) LibCpp2ILUtils.VersionAwareSizeOf(typeof(Il2CppCodeRegistration)) - ptrSize;
+ var bytesToGoBack = (ulong) LibCpp2ILUtils.VersionAwareSizeOf() - ptrSize;
LibLogger.VerboseNewline($"\t\t\tpCodegenModules is the second-to-last field of the codereg struct. Therefore on this version and architecture, we need to subtract {bytesToGoBack} bytes from its address to get pCodeReg");
@@ -285,7 +285,7 @@ public static bool ValidateCodeRegistration(Il2CppCodeRegistration codeReg, Dict
public ulong FindMetadataRegistrationPre24_5()
{
//We're looking for TypeDefinitionsSizesCount, which is the 4th-to-last field
- var sizeOfMr = (ulong) LibCpp2ILUtils.VersionAwareSizeOf(typeof(Il2CppMetadataRegistration));
+ var sizeOfMr = (ulong) LibCpp2ILUtils.VersionAwareSizeOf();
var ptrSize = _binary.is32Bit ? 4ul : 8ul;
var bytesToSubtract = sizeOfMr - ptrSize * 4;
@@ -315,7 +315,7 @@ public ulong FindMetadataRegistrationPre24_5()
public ulong FindMetadataRegistrationPost24_5()
{
var ptrSize = _binary.is32Bit ? 4ul : 8ul;
- var sizeOfMr = (uint) LibCpp2ILUtils.VersionAwareSizeOf(typeof(Il2CppMetadataRegistration));
+ var sizeOfMr = (uint) LibCpp2ILUtils.VersionAwareSizeOf();
LibLogger.VerboseNewline($"\t\t\tLooking for the number of type definitions, 0x{_typeDefinitionsCount:X}");
var ptrsToNumberOfTypes = FindAllMappedWords((ulong) _typeDefinitionsCount).ToList();
diff --git a/LibCpp2IL/Elf/ElfFile.cs b/LibCpp2IL/Elf/ElfFile.cs
index 905d0001..228303ee 100644
--- a/LibCpp2IL/Elf/ElfFile.cs
+++ b/LibCpp2IL/Elf/ElfFile.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
@@ -269,7 +269,7 @@ private void ProcessRelocations()
}
}
- var sizeOfRelocationStruct = (ulong) (is32Bit ? LibCpp2ILUtils.VersionAwareSizeOf(typeof(ElfDynamicSymbol32), true, false) : LibCpp2ILUtils.VersionAwareSizeOf(typeof(ElfDynamicSymbol64), true, false));
+ var sizeOfRelocationStruct = (ulong) (is32Bit ? LibCpp2ILUtils.VersionAwareSizeOf(true, false) : LibCpp2ILUtils.VersionAwareSizeOf(true, false));
LibLogger.Verbose($"\t-Now Processing {rels.Count} relocations...");
diff --git a/LibCpp2IL/LibCpp2IL.csproj b/LibCpp2IL/LibCpp2IL.csproj
index e442da34..b65a3571 100644
--- a/LibCpp2IL/LibCpp2IL.csproj
+++ b/LibCpp2IL/LibCpp2IL.csproj
@@ -19,16 +19,17 @@
Debug;Release
net7.0;net6.0;netstandard2.0
true
+ true
+
-
diff --git a/LibCpp2IL/LibCpp2IlUtils.cs b/LibCpp2IL/LibCpp2IlUtils.cs
index b86ef56f..178d41b9 100644
--- a/LibCpp2IL/LibCpp2IlUtils.cs
+++ b/LibCpp2IL/LibCpp2IlUtils.cs
@@ -35,22 +35,22 @@ public static class LibCpp2ILUtils
{28, "object"}
};
- private static readonly Dictionary PrimitiveSizes = new()
+ private static readonly Dictionary PrimitiveSizes = new()
{
- {"Byte", 1},
- {"SByte", 1},
- {"Boolean", 1},
- {"Int16", 2},
- {"UInt16", 2},
- {"Char", 2},
- {"Int32", 4},
- {"UInt32", 4},
- {"Single", 4},
- {"Int64", 8},
- {"UInt64", 8},
- {"Double", 8},
- {"IntPtr", 8},
- {"UIntPtr", 8},
+ {typeof(byte), 1},
+ {typeof(sbyte), 1},
+ {typeof(bool), 1},
+ {typeof(short), 2},
+ {typeof(ushort), 2},
+ {typeof(char), 2},
+ {typeof(int), 4},
+ {typeof(uint), 4},
+ {typeof(float), 4},
+ {typeof(long), 8},
+ {typeof(ulong), 8},
+ {typeof(double), 8},
+ {typeof(IntPtr), 8},
+ {typeof(UIntPtr), 8},
};
private static Dictionary _cachedVersionAttributes = new();
@@ -393,18 +393,24 @@ public static Il2CppTypeReflectionData GetTypeReflectionData(Il2CppType forWhat)
throw new ArgumentException($"Unknown type {forWhat.Type}");
}
-#pragma warning disable IL2070 //'this' argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicFields'
+ public static int VersionAwareSizeOf<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicFields)] T>(
+ bool dontCheckVersionAttributes = false,
+ bool downsize = true)
+ {
+ return VersionAwareSizeOf(typeof(T), dontCheckVersionAttributes, downsize);
+ }
+
public static int VersionAwareSizeOf(
- Type type,
+ [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicFields)] Type type,
bool dontCheckVersionAttributes = false,
bool downsize = true
)
{
if (type.IsEnum)
- type = type.GetEnumUnderlyingType();
+ return PrimitiveSizes[type.GetEnumUnderlyingType()];
if (type.IsPrimitive)
- return (int) PrimitiveSizes[type.Name];
+ return PrimitiveSizes[type];
var shouldDownsize = downsize && LibCpp2IlMain.Binary!.is32Bit;
@@ -418,36 +424,32 @@ public static int VersionAwareSizeOf(
continue;
}
- switch (field.FieldType.Name)
- {
- case "Int64":
- case "UInt64":
- size += shouldDownsize ? 4 : 8;
- break;
- case "Int32":
- case "UInt32":
- size += 4;
- break;
- case "Int16":
- case "UInt16":
- size += 2;
- break;
- case "Byte":
- case "SByte":
- size += 1;
- break;
- default:
- if (field.FieldType == type)
- throw new Exception($"Infinite recursion is not allowed. Field {field} of type {type} has the same type as its parent.");
-
- size += VersionAwareSizeOf(field.FieldType, dontCheckVersionAttributes, downsize);
- break;
- }
+ if (field.FieldType == typeof(long) || field.FieldType == typeof(ulong))
+ size += shouldDownsize ? 4 : 8;
+ else if (field.FieldType == typeof(int) || field.FieldType == typeof(uint))
+ size += 4;
+ else if (field.FieldType == typeof(short) || field.FieldType == typeof(ushort))
+ size += 2;
+ else if (field.FieldType == typeof(byte) || field.FieldType == typeof(sbyte))
+ size += 1;
+ else if (field.FieldType.IsEnum)
+ size += PrimitiveSizes[field.FieldType.GetEnumUnderlyingType()];
+ else if (field.FieldType.IsPrimitive)
+ size += PrimitiveSizes[field.FieldType];
+ else if (field.FieldType == type)
+ throw new Exception($"Infinite recursion is not allowed. Field {field} of type {type} has the same type as its parent.");
+ else if (field.FieldType == typeof(Il2CppGenericContext))
+ size += VersionAwareSizeOf(typeof(Il2CppGenericContext), dontCheckVersionAttributes, downsize);
+ else if (field.FieldType == typeof(Il2CppGenericMethodIndices))
+ size += VersionAwareSizeOf(typeof(Il2CppGenericMethodIndices), dontCheckVersionAttributes, downsize);
+ else if (field.FieldType == typeof(Il2CppAssemblyNameDefinition))
+ size += VersionAwareSizeOf(typeof(Il2CppAssemblyNameDefinition), dontCheckVersionAttributes, downsize);
+ else
+ throw new Exception($"Custom field type '{field.FieldType}' has no special case.");
}
return size;
}
-#pragma warning restore IL2070
internal static IEnumerable Range(int start, int count)
{
diff --git a/LibCpp2IL/Metadata/Il2CppMetadata.cs b/LibCpp2IL/Metadata/Il2CppMetadata.cs
index 0cbda72f..592bd4ce 100644
--- a/LibCpp2IL/Metadata/Il2CppMetadata.cs
+++ b/LibCpp2IL/Metadata/Il2CppMetadata.cs
@@ -1,6 +1,7 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
using System.Reflection;
@@ -286,9 +287,9 @@ private Il2CppMetadata(MemoryStream stream) : base(stream)
}
#pragma warning restore 8618
- private T[] ReadMetadataClassArray(int offset, int length) where T : ReadableClass, new()
+ private T[] ReadMetadataClassArray<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicFields)] T>(int offset, int length) where T : ReadableClass, new()
{
- return ReadReadableArrayAtRawAddr(offset, length / LibCpp2ILUtils.VersionAwareSizeOf(typeof(T), downsize: false));
+ return ReadReadableArrayAtRawAddr(offset, length / LibCpp2ILUtils.VersionAwareSizeOf(downsize: false));
}
private void DecipherMetadataUsage()