Add BlobReader, fix Il2CppType for 27.2+

This commit is contained in:
LukeFZ
2023-11-30 13:31:37 +01:00
parent a4528e5f55
commit ef1a5d1e83
4 changed files with 723 additions and 632 deletions

View File

@@ -218,10 +218,12 @@ namespace Il2CppInspector
public uint attrs => (uint) bits & 0xffff; /* param attributes or field flags */
public Il2CppTypeEnum type => (Il2CppTypeEnum)((bits >> 16) & 0xff);
// TODO: Unity 2021.1 (v27.2): num_mods becomes 1 bit shorter, shifting byref and pinned right 1 bit, valuetype bit added
public uint num_mods => (uint) (bits >> 24) & 0x3f; /* max 64 modifiers follow at the end */
public bool byref => ((bits >> 30) & 1) == 1;
public bool pinned => (bits >> 31) == 1; /* valid when included in a local var signature */
// Unity 2021.1 (v27.2): num_mods becomes 1 bit shorter, shifting byref and pinned left 1 bit, valuetype bit added
public uint NumMods(double version) => (uint) (bits >> 24) & (version >= 27.2 ? 0x1fu : 0x3fu);
public bool ByRef(double version) => (bits >> (version >= 27.2 ? 29 : 30) & 1) == 1;
public bool Pinned(double version) => (bits >> (version >= 27.2 ? 30 : 31) & 1) == 1;
public bool ValueType(double version) => version >= 27.2 && ((bits >> 31) & 1) == 1; // Was only added in 27.2
/*public class Union
{

File diff suppressed because it is too large Load Diff

View File

@@ -259,7 +259,7 @@ namespace Il2CppInspector.Reflection
}
// Create a reference type if necessary
return typeRef.byref ? underlyingType.MakeByRefType() : underlyingType;
return typeRef.ByRef(Package.Version) ? underlyingType.MakeByRefType() : underlyingType;
}
// Basic primitive types are specified via a flag value

View File

@@ -0,0 +1,137 @@
using NoisyCowStudios.Bin2Object;
using System.Text;
using System;
namespace Il2CppInspector.Utils;
public static class BlobReader
{
public static object GetConstantValueFromBlob(Il2CppInspector inspector, Il2CppTypeEnum type, BinaryObjectStream blob)
{
const byte kArrayTypeWithDifferentElements = 1;
object value = null;
switch (type)
{
case Il2CppTypeEnum.IL2CPP_TYPE_BOOLEAN:
value = blob.ReadBoolean();
break;
case Il2CppTypeEnum.IL2CPP_TYPE_U1:
case Il2CppTypeEnum.IL2CPP_TYPE_I1:
value = blob.ReadByte();
break;
case Il2CppTypeEnum.IL2CPP_TYPE_CHAR:
// UTF-8 character assumed
value = BitConverter.ToChar(blob.ReadBytes(2), 0);
break;
case Il2CppTypeEnum.IL2CPP_TYPE_U2:
value = blob.ReadUInt16();
break;
case Il2CppTypeEnum.IL2CPP_TYPE_I2:
value = blob.ReadInt16();
break;
case Il2CppTypeEnum.IL2CPP_TYPE_U4:
value = blob.Version >= 29
? blob.ReadCompressedUInt32()
: blob.ReadUInt32();
break;
case Il2CppTypeEnum.IL2CPP_TYPE_I4:
value = blob.Version >= 29
? blob.ReadCompressedInt32()
: blob.ReadInt32();
break;
case Il2CppTypeEnum.IL2CPP_TYPE_U8:
value = blob.ReadUInt64();
break;
case Il2CppTypeEnum.IL2CPP_TYPE_I8:
value = blob.ReadInt64();
break;
case Il2CppTypeEnum.IL2CPP_TYPE_R4:
value = blob.ReadSingle();
break;
case Il2CppTypeEnum.IL2CPP_TYPE_R8:
value = blob.ReadDouble();
break;
case Il2CppTypeEnum.IL2CPP_TYPE_STRING:
var uiLen = blob.Version >= 29
? blob.ReadCompressedInt32()
: blob.ReadInt32();
if (uiLen != -1)
value = Encoding.UTF8.GetString(blob.ReadBytes(uiLen));
break;
case Il2CppTypeEnum.IL2CPP_TYPE_SZARRAY:
var length = blob.Version >= 29
? blob.ReadCompressedInt32()
: blob.ReadInt32();
if (length == -1)
break;
var arrayElementType = ReadEncodedTypeEnum(inspector, blob, out var arrayElementDef);
var arrayElementsAreDifferent = blob.ReadByte();
if (arrayElementsAreDifferent == kArrayTypeWithDifferentElements)
{
var array = new ConstantBlobArrayElement[length];
for (int i = 0; i < length; i++)
{
var elementType = ReadEncodedTypeEnum(inspector, blob, out var elementTypeDef);
array[i] = new ConstantBlobArrayElement(elementTypeDef, GetConstantValueFromBlob(inspector, elementType, blob));
}
value = new ConstantBlobArray(arrayElementDef, array);
}
else
{
var array = new object[length];
for (int i = 0; i < length; i++)
{
array[i] = GetConstantValueFromBlob(inspector, arrayElementType, blob);
}
value = new ConstantBlobArray(arrayElementDef, array);
}
break;
case Il2CppTypeEnum.IL2CPP_TYPE_CLASS:
case Il2CppTypeEnum.IL2CPP_TYPE_OBJECT:
case Il2CppTypeEnum.IL2CPP_TYPE_GENERICINST:
break;
case Il2CppTypeEnum.IL2CPP_TYPE_IL2CPP_TYPE_INDEX:
var index = blob.ReadCompressedInt32();
if (index != -1)
value = inspector.TypeReferences[index];
break;
}
return value;
}
public static Il2CppTypeEnum ReadEncodedTypeEnum(Il2CppInspector inspector, BinaryObjectStream blob,
out Il2CppTypeDefinition enumType)
{
enumType = null;
var typeEnum = (Il2CppTypeEnum)blob.ReadByte();
if (typeEnum == Il2CppTypeEnum.IL2CPP_TYPE_ENUM)
{
var typeIndex = blob.ReadCompressedInt32();
enumType = inspector.TypeDefinitions[typeIndex];
typeEnum = inspector.TypeReferences[enumType.byvalTypeIndex].type;
}
// This technically also handles SZARRAY (System.Array) and all others by just returning their system type
return typeEnum;
}
public record ConstantBlobArray(Il2CppTypeDefinition ArrayTypeDef, object[] Elements);
public record ConstantBlobArrayElement(Il2CppTypeDefinition TypeDef, object value);
}