mirror of
https://github.com/Perfare/Il2CppDumper.git
synced 2025-01-25 02:03:02 -03:00
v29支持
This commit is contained in:
parent
22c6374f6f
commit
43ff0f23c1
15 changed files with 725 additions and 239 deletions
101
Il2CppDumper/Extensions/BinaryReaderExtensions.cs
Normal file
101
Il2CppDumper/Extensions/BinaryReaderExtensions.cs
Normal file
|
@ -0,0 +1,101 @@
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Il2CppDumper
|
||||||
|
{
|
||||||
|
public static class BinaryReaderExtensions
|
||||||
|
{
|
||||||
|
public static string ReadString(this BinaryReader reader, int numChars)
|
||||||
|
{
|
||||||
|
var start = reader.BaseStream.Position;
|
||||||
|
// UTF8 takes up to 4 bytes per character
|
||||||
|
var str = Encoding.UTF8.GetString(reader.ReadBytes(numChars * 4)).Substring(0, numChars);
|
||||||
|
// make our position what it would have been if we'd known the exact number of bytes needed.
|
||||||
|
reader.BaseStream.Position = start;
|
||||||
|
reader.ReadBytes(Encoding.UTF8.GetByteCount(str));
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static uint ReadULeb128(this BinaryReader reader)
|
||||||
|
{
|
||||||
|
uint value = reader.ReadByte();
|
||||||
|
if (value >= 0x80)
|
||||||
|
{
|
||||||
|
var bitshift = 0;
|
||||||
|
value &= 0x7f;
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
var b = reader.ReadByte();
|
||||||
|
bitshift += 7;
|
||||||
|
value |= (uint)((b & 0x7f) << bitshift);
|
||||||
|
if (b < 0x80)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static uint ReadCompressedUInt32(this BinaryReader reader)
|
||||||
|
{
|
||||||
|
uint val;
|
||||||
|
var read = reader.ReadByte();
|
||||||
|
|
||||||
|
if ((read & 0x80) == 0)
|
||||||
|
{
|
||||||
|
// 1 byte written
|
||||||
|
val = read;
|
||||||
|
}
|
||||||
|
else if ((read & 0xC0) == 0x80)
|
||||||
|
{
|
||||||
|
// 2 bytes written
|
||||||
|
val = (read & ~0x80u) << 8;
|
||||||
|
val |= reader.ReadByte();
|
||||||
|
}
|
||||||
|
else if ((read & 0xE0) == 0xC0)
|
||||||
|
{
|
||||||
|
// 4 bytes written
|
||||||
|
val = (read & ~0xC0u) << 24;
|
||||||
|
val |= ((uint)reader.ReadByte() << 16);
|
||||||
|
val |= ((uint)reader.ReadByte() << 8);
|
||||||
|
val |= reader.ReadByte();
|
||||||
|
}
|
||||||
|
else if (read == 0xF0)
|
||||||
|
{
|
||||||
|
// 5 bytes written, we had a really large int32!
|
||||||
|
val = reader.ReadUInt32();
|
||||||
|
}
|
||||||
|
else if (read == 0xFE)
|
||||||
|
{
|
||||||
|
// Special encoding for Int32.MaxValue
|
||||||
|
val = uint.MaxValue - 1;
|
||||||
|
}
|
||||||
|
else if (read == 0xFF)
|
||||||
|
{
|
||||||
|
// Yes we treat UInt32.MaxValue (and Int32.MinValue, see ReadCompressedInt32) specially
|
||||||
|
val = uint.MaxValue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new Exception("Invalid compressed integer format");
|
||||||
|
}
|
||||||
|
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int ReadCompressedInt32(this BinaryReader reader)
|
||||||
|
{
|
||||||
|
var encoded = reader.ReadCompressedUInt32();
|
||||||
|
|
||||||
|
// -UINT32_MAX can't be represted safely in an int32_t, so we treat it specially
|
||||||
|
if (encoded == uint.MaxValue)
|
||||||
|
return int.MinValue;
|
||||||
|
|
||||||
|
bool isNegative = (encoded & 1) != 0;
|
||||||
|
encoded >>= 1;
|
||||||
|
if (isNegative)
|
||||||
|
return -(int)(encoded + 1);
|
||||||
|
return (int)encoded;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -52,24 +52,11 @@ namespace Il2CppDumper
|
||||||
|
|
||||||
public double ReadDouble() => reader.ReadDouble();
|
public double ReadDouble() => reader.ReadDouble();
|
||||||
|
|
||||||
public uint ReadULeb128()
|
public uint ReadCompressedUInt32() => reader.ReadCompressedUInt32();
|
||||||
{
|
|
||||||
uint value = reader.ReadByte();
|
public int ReadCompressedInt32() => reader.ReadCompressedInt32();
|
||||||
if (value >= 0x80)
|
|
||||||
{
|
public uint ReadULeb128() => reader.ReadULeb128();
|
||||||
var bitshift = 0;
|
|
||||||
value &= 0x7f;
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
var b = reader.ReadByte();
|
|
||||||
bitshift += 7;
|
|
||||||
value |= (uint)((b & 0x7f) << bitshift);
|
|
||||||
if (b < 0x80)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Write(bool value) => writer.Write(value);
|
public void Write(bool value) => writer.Write(value);
|
||||||
|
|
||||||
|
@ -246,6 +233,10 @@ namespace Il2CppDumper
|
||||||
get => Is32Bit ? 4ul : 8ul;
|
get => Is32Bit ? 4ul : 8ul;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public BinaryReader Reader => reader;
|
||||||
|
|
||||||
|
public BinaryWriter Writer => writer;
|
||||||
|
|
||||||
protected virtual void Dispose(bool disposing)
|
protected virtual void Dispose(bool disposing)
|
||||||
{
|
{
|
||||||
if (disposing)
|
if (disposing)
|
||||||
|
|
|
@ -128,7 +128,8 @@ namespace Il2CppDumper
|
||||||
IL2CPP_TYPE_SENTINEL = 0x41, /* Sentinel for varargs method signature */
|
IL2CPP_TYPE_SENTINEL = 0x41, /* Sentinel for varargs method signature */
|
||||||
IL2CPP_TYPE_PINNED = 0x45, /* Local var that points to pinned object */
|
IL2CPP_TYPE_PINNED = 0x45, /* Local var that points to pinned object */
|
||||||
|
|
||||||
IL2CPP_TYPE_ENUM = 0x55 /* an enumeration */
|
IL2CPP_TYPE_ENUM = 0x55, /* an enumeration */
|
||||||
|
IL2CPP_TYPE_IL2CPP_TYPE_INDEX = 0xff /* an index into IL2CPP type metadata table */
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Il2CppType
|
public class Il2CppType
|
||||||
|
@ -261,7 +262,7 @@ namespace Il2CppDumper
|
||||||
public long rgctxsCount;
|
public long rgctxsCount;
|
||||||
public ulong rgctxs;
|
public ulong rgctxs;
|
||||||
public ulong debuggerMetadata;
|
public ulong debuggerMetadata;
|
||||||
[Version(Min = 27)]
|
[Version(Min = 27, Max = 27.2)]
|
||||||
public ulong customAttributeCacheGenerator;
|
public ulong customAttributeCacheGenerator;
|
||||||
[Version(Min = 27)]
|
[Version(Min = 27)]
|
||||||
public ulong moduleInitializer;
|
public ulong moduleInitializer;
|
||||||
|
|
|
@ -20,6 +20,7 @@ namespace Il2CppDumper
|
||||||
private Dictionary<int, Il2CppParameterDefaultValue> parameterDefaultValuesDic;
|
private Dictionary<int, Il2CppParameterDefaultValue> parameterDefaultValuesDic;
|
||||||
public Il2CppPropertyDefinition[] propertyDefs;
|
public Il2CppPropertyDefinition[] propertyDefs;
|
||||||
public Il2CppCustomAttributeTypeRange[] attributeTypeRanges;
|
public Il2CppCustomAttributeTypeRange[] attributeTypeRanges;
|
||||||
|
public Il2CppCustomAttributeDataRange[] attributeDataRanges;
|
||||||
private Dictionary<Il2CppImageDefinition, Dictionary<uint, int>> attributeTypeRangesDic;
|
private Dictionary<Il2CppImageDefinition, Dictionary<uint, int>> attributeTypeRangesDic;
|
||||||
public Il2CppStringLiteral[] stringLiterals;
|
public Il2CppStringLiteral[] stringLiterals;
|
||||||
private Il2CppMetadataUsageList[] metadataUsageLists;
|
private Il2CppMetadataUsageList[] metadataUsageLists;
|
||||||
|
@ -48,7 +49,7 @@ namespace Il2CppDumper
|
||||||
throw new InvalidDataException("ERROR: Metadata file supplied is not valid metadata file.");
|
throw new InvalidDataException("ERROR: Metadata file supplied is not valid metadata file.");
|
||||||
}
|
}
|
||||||
var version = ReadInt32();
|
var version = ReadInt32();
|
||||||
if (version < 16 || version > 27)
|
if (version < 16 || version > 29)
|
||||||
{
|
{
|
||||||
throw new NotSupportedException($"ERROR: Metadata file supplied is not a supported version[{version}].");
|
throw new NotSupportedException($"ERROR: Metadata file supplied is not a supported version[{version}].");
|
||||||
}
|
}
|
||||||
|
@ -63,39 +64,39 @@ namespace Il2CppDumper
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
imageDefs = ReadMetadataClassArray<Il2CppImageDefinition>(header.imagesOffset, header.imagesCount);
|
imageDefs = ReadMetadataClassArray<Il2CppImageDefinition>(header.imagesOffset, header.imagesSize);
|
||||||
if (imageDefs.Any(x => x.token != 1))
|
if (imageDefs.Any(x => x.token != 1))
|
||||||
{
|
{
|
||||||
Version = 24.1;
|
Version = 24.1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
imageDefs = ReadMetadataClassArray<Il2CppImageDefinition>(header.imagesOffset, header.imagesCount);
|
imageDefs = ReadMetadataClassArray<Il2CppImageDefinition>(header.imagesOffset, header.imagesSize);
|
||||||
if (Version == 24.2 && header.assembliesCount / 68 < imageDefs.Length)
|
if (Version == 24.2 && header.assembliesSize / 68 < imageDefs.Length)
|
||||||
{
|
{
|
||||||
Version = 24.4;
|
Version = 24.4;
|
||||||
}
|
}
|
||||||
assemblyDefs = ReadMetadataClassArray<Il2CppAssemblyDefinition>(header.assembliesOffset, header.assembliesCount);
|
assemblyDefs = ReadMetadataClassArray<Il2CppAssemblyDefinition>(header.assembliesOffset, header.assembliesSize);
|
||||||
typeDefs = ReadMetadataClassArray<Il2CppTypeDefinition>(header.typeDefinitionsOffset, header.typeDefinitionsCount);
|
typeDefs = ReadMetadataClassArray<Il2CppTypeDefinition>(header.typeDefinitionsOffset, header.typeDefinitionsSize);
|
||||||
methodDefs = ReadMetadataClassArray<Il2CppMethodDefinition>(header.methodsOffset, header.methodsCount);
|
methodDefs = ReadMetadataClassArray<Il2CppMethodDefinition>(header.methodsOffset, header.methodsSize);
|
||||||
parameterDefs = ReadMetadataClassArray<Il2CppParameterDefinition>(header.parametersOffset, header.parametersCount);
|
parameterDefs = ReadMetadataClassArray<Il2CppParameterDefinition>(header.parametersOffset, header.parametersSize);
|
||||||
fieldDefs = ReadMetadataClassArray<Il2CppFieldDefinition>(header.fieldsOffset, header.fieldsCount);
|
fieldDefs = ReadMetadataClassArray<Il2CppFieldDefinition>(header.fieldsOffset, header.fieldsSize);
|
||||||
var fieldDefaultValues = ReadMetadataClassArray<Il2CppFieldDefaultValue>(header.fieldDefaultValuesOffset, header.fieldDefaultValuesCount);
|
var fieldDefaultValues = ReadMetadataClassArray<Il2CppFieldDefaultValue>(header.fieldDefaultValuesOffset, header.fieldDefaultValuesSize);
|
||||||
var parameterDefaultValues = ReadMetadataClassArray<Il2CppParameterDefaultValue>(header.parameterDefaultValuesOffset, header.parameterDefaultValuesCount);
|
var parameterDefaultValues = ReadMetadataClassArray<Il2CppParameterDefaultValue>(header.parameterDefaultValuesOffset, header.parameterDefaultValuesSize);
|
||||||
fieldDefaultValuesDic = fieldDefaultValues.ToDictionary(x => x.fieldIndex);
|
fieldDefaultValuesDic = fieldDefaultValues.ToDictionary(x => x.fieldIndex);
|
||||||
parameterDefaultValuesDic = parameterDefaultValues.ToDictionary(x => x.parameterIndex);
|
parameterDefaultValuesDic = parameterDefaultValues.ToDictionary(x => x.parameterIndex);
|
||||||
propertyDefs = ReadMetadataClassArray<Il2CppPropertyDefinition>(header.propertiesOffset, header.propertiesCount);
|
propertyDefs = ReadMetadataClassArray<Il2CppPropertyDefinition>(header.propertiesOffset, header.propertiesSize);
|
||||||
interfaceIndices = ReadClassArray<int>(header.interfacesOffset, header.interfacesCount / 4);
|
interfaceIndices = ReadClassArray<int>(header.interfacesOffset, header.interfacesSize / 4);
|
||||||
nestedTypeIndices = ReadClassArray<int>(header.nestedTypesOffset, header.nestedTypesCount / 4);
|
nestedTypeIndices = ReadClassArray<int>(header.nestedTypesOffset, header.nestedTypesSize / 4);
|
||||||
eventDefs = ReadMetadataClassArray<Il2CppEventDefinition>(header.eventsOffset, header.eventsCount);
|
eventDefs = ReadMetadataClassArray<Il2CppEventDefinition>(header.eventsOffset, header.eventsSize);
|
||||||
genericContainers = ReadMetadataClassArray<Il2CppGenericContainer>(header.genericContainersOffset, header.genericContainersCount);
|
genericContainers = ReadMetadataClassArray<Il2CppGenericContainer>(header.genericContainersOffset, header.genericContainersSize);
|
||||||
genericParameters = ReadMetadataClassArray<Il2CppGenericParameter>(header.genericParametersOffset, header.genericParametersCount);
|
genericParameters = ReadMetadataClassArray<Il2CppGenericParameter>(header.genericParametersOffset, header.genericParametersSize);
|
||||||
constraintIndices = ReadClassArray<int>(header.genericParameterConstraintsOffset, header.genericParameterConstraintsCount / 4);
|
constraintIndices = ReadClassArray<int>(header.genericParameterConstraintsOffset, header.genericParameterConstraintsSize / 4);
|
||||||
vtableMethods = ReadClassArray<uint>(header.vtableMethodsOffset, header.vtableMethodsCount / 4);
|
vtableMethods = ReadClassArray<uint>(header.vtableMethodsOffset, header.vtableMethodsSize / 4);
|
||||||
stringLiterals = ReadMetadataClassArray<Il2CppStringLiteral>(header.stringLiteralOffset, header.stringLiteralCount);
|
stringLiterals = ReadMetadataClassArray<Il2CppStringLiteral>(header.stringLiteralOffset, header.stringLiteralSize);
|
||||||
if (Version > 16)
|
if (Version > 16)
|
||||||
{
|
{
|
||||||
fieldRefs = ReadMetadataClassArray<Il2CppFieldRef>(header.fieldRefsOffset, header.fieldRefsCount);
|
fieldRefs = ReadMetadataClassArray<Il2CppFieldRef>(header.fieldRefsOffset, header.fieldRefsSize);
|
||||||
if (Version < 27)
|
if (Version < 27)
|
||||||
{
|
{
|
||||||
metadataUsageLists = ReadMetadataClassArray<Il2CppMetadataUsageList>(header.metadataUsageListsOffset, header.metadataUsageListsCount);
|
metadataUsageLists = ReadMetadataClassArray<Il2CppMetadataUsageList>(header.metadataUsageListsOffset, header.metadataUsageListsCount);
|
||||||
|
@ -104,11 +105,15 @@ namespace Il2CppDumper
|
||||||
ProcessingMetadataUsage();
|
ProcessingMetadataUsage();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (Version > 20)
|
if (Version > 20 && Version < 29)
|
||||||
{
|
{
|
||||||
attributeTypeRanges = ReadMetadataClassArray<Il2CppCustomAttributeTypeRange>(header.attributesInfoOffset, header.attributesInfoCount);
|
attributeTypeRanges = ReadMetadataClassArray<Il2CppCustomAttributeTypeRange>(header.attributesInfoOffset, header.attributesInfoCount);
|
||||||
attributeTypes = ReadClassArray<int>(header.attributeTypesOffset, header.attributeTypesCount / 4);
|
attributeTypes = ReadClassArray<int>(header.attributeTypesOffset, header.attributeTypesCount / 4);
|
||||||
}
|
}
|
||||||
|
if (Version >= 29)
|
||||||
|
{
|
||||||
|
attributeDataRanges = ReadMetadataClassArray<Il2CppCustomAttributeDataRange>(header.attributeDataRangeOffset, header.attributeDataRangeSize);
|
||||||
|
}
|
||||||
if (Version > 24)
|
if (Version > 24)
|
||||||
{
|
{
|
||||||
attributeTypeRangesDic = new Dictionary<Il2CppImageDefinition, Dictionary<uint, int>>();
|
attributeTypeRangesDic = new Dictionary<Il2CppImageDefinition, Dictionary<uint, int>>();
|
||||||
|
@ -119,7 +124,14 @@ namespace Il2CppDumper
|
||||||
var end = imageDef.customAttributeStart + imageDef.customAttributeCount;
|
var end = imageDef.customAttributeStart + imageDef.customAttributeCount;
|
||||||
for (int i = imageDef.customAttributeStart; i < end; i++)
|
for (int i = imageDef.customAttributeStart; i < end; i++)
|
||||||
{
|
{
|
||||||
dic.Add(attributeTypeRanges[i].token, i);
|
if (Version >= 29)
|
||||||
|
{
|
||||||
|
dic.Add(attributeDataRanges[i].token, i);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dic.Add(attributeTypeRanges[i].token, i);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -268,16 +280,5 @@ namespace Il2CppDumper
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public string ReadString(int numChars)
|
|
||||||
{
|
|
||||||
var start = Position;
|
|
||||||
// UTF8 takes up to 4 bytes per character
|
|
||||||
var str = Encoding.UTF8.GetString(ReadBytes(numChars * 4)).Substring(0, numChars);
|
|
||||||
// make our position what it would have been if we'd known the exact number of bytes needed.
|
|
||||||
Position = start;
|
|
||||||
ReadBytes(Encoding.UTF8.GetByteCount(str));
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,53 +7,53 @@ namespace Il2CppDumper
|
||||||
public uint sanity;
|
public uint sanity;
|
||||||
public int version;
|
public int version;
|
||||||
public uint stringLiteralOffset; // string data for managed code
|
public uint stringLiteralOffset; // string data for managed code
|
||||||
public int stringLiteralCount;
|
public int stringLiteralSize;
|
||||||
public uint stringLiteralDataOffset;
|
public uint stringLiteralDataOffset;
|
||||||
public int stringLiteralDataCount;
|
public int stringLiteralDataSize;
|
||||||
public uint stringOffset; // string data for metadata
|
public uint stringOffset; // string data for metadata
|
||||||
public int stringCount;
|
public int stringSize;
|
||||||
public uint eventsOffset; // Il2CppEventDefinition
|
public uint eventsOffset; // Il2CppEventDefinition
|
||||||
public int eventsCount;
|
public int eventsSize;
|
||||||
public uint propertiesOffset; // Il2CppPropertyDefinition
|
public uint propertiesOffset; // Il2CppPropertyDefinition
|
||||||
public int propertiesCount;
|
public int propertiesSize;
|
||||||
public uint methodsOffset; // Il2CppMethodDefinition
|
public uint methodsOffset; // Il2CppMethodDefinition
|
||||||
public int methodsCount;
|
public int methodsSize;
|
||||||
public uint parameterDefaultValuesOffset; // Il2CppParameterDefaultValue
|
public uint parameterDefaultValuesOffset; // Il2CppParameterDefaultValue
|
||||||
public int parameterDefaultValuesCount;
|
public int parameterDefaultValuesSize;
|
||||||
public uint fieldDefaultValuesOffset; // Il2CppFieldDefaultValue
|
public uint fieldDefaultValuesOffset; // Il2CppFieldDefaultValue
|
||||||
public int fieldDefaultValuesCount;
|
public int fieldDefaultValuesSize;
|
||||||
public uint fieldAndParameterDefaultValueDataOffset; // uint8_t
|
public uint fieldAndParameterDefaultValueDataOffset; // uint8_t
|
||||||
public int fieldAndParameterDefaultValueDataCount;
|
public int fieldAndParameterDefaultValueDataSize;
|
||||||
public int fieldMarshaledSizesOffset; // Il2CppFieldMarshaledSize
|
public int fieldMarshaledSizesOffset; // Il2CppFieldMarshaledSize
|
||||||
public int fieldMarshaledSizesCount;
|
public int fieldMarshaledSizesSize;
|
||||||
public uint parametersOffset; // Il2CppParameterDefinition
|
public uint parametersOffset; // Il2CppParameterDefinition
|
||||||
public int parametersCount;
|
public int parametersSize;
|
||||||
public uint fieldsOffset; // Il2CppFieldDefinition
|
public uint fieldsOffset; // Il2CppFieldDefinition
|
||||||
public int fieldsCount;
|
public int fieldsSize;
|
||||||
public uint genericParametersOffset; // Il2CppGenericParameter
|
public uint genericParametersOffset; // Il2CppGenericParameter
|
||||||
public int genericParametersCount;
|
public int genericParametersSize;
|
||||||
public uint genericParameterConstraintsOffset; // TypeIndex
|
public uint genericParameterConstraintsOffset; // TypeIndex
|
||||||
public int genericParameterConstraintsCount;
|
public int genericParameterConstraintsSize;
|
||||||
public uint genericContainersOffset; // Il2CppGenericContainer
|
public uint genericContainersOffset; // Il2CppGenericContainer
|
||||||
public int genericContainersCount;
|
public int genericContainersSize;
|
||||||
public uint nestedTypesOffset; // TypeDefinitionIndex
|
public uint nestedTypesOffset; // TypeDefinitionIndex
|
||||||
public int nestedTypesCount;
|
public int nestedTypesSize;
|
||||||
public uint interfacesOffset; // TypeIndex
|
public uint interfacesOffset; // TypeIndex
|
||||||
public int interfacesCount;
|
public int interfacesSize;
|
||||||
public uint vtableMethodsOffset; // EncodedMethodIndex
|
public uint vtableMethodsOffset; // EncodedMethodIndex
|
||||||
public int vtableMethodsCount;
|
public int vtableMethodsSize;
|
||||||
public int interfaceOffsetsOffset; // Il2CppInterfaceOffsetPair
|
public int interfaceOffsetsOffset; // Il2CppInterfaceOffsetPair
|
||||||
public int interfaceOffsetsCount;
|
public int interfaceOffsetsSize;
|
||||||
public uint typeDefinitionsOffset; // Il2CppTypeDefinition
|
public uint typeDefinitionsOffset; // Il2CppTypeDefinition
|
||||||
public int typeDefinitionsCount;
|
public int typeDefinitionsSize;
|
||||||
[Version(Max = 24.1)]
|
[Version(Max = 24.1)]
|
||||||
public uint rgctxEntriesOffset; // Il2CppRGCTXDefinition
|
public uint rgctxEntriesOffset; // Il2CppRGCTXDefinition
|
||||||
[Version(Max = 24.1)]
|
[Version(Max = 24.1)]
|
||||||
public int rgctxEntriesCount;
|
public int rgctxEntriesCount;
|
||||||
public uint imagesOffset; // Il2CppImageDefinition
|
public uint imagesOffset; // Il2CppImageDefinition
|
||||||
public int imagesCount;
|
public int imagesSize;
|
||||||
public uint assembliesOffset; // Il2CppAssemblyDefinition
|
public uint assembliesOffset; // Il2CppAssemblyDefinition
|
||||||
public int assembliesCount;
|
public int assembliesSize;
|
||||||
[Version(Min = 19, Max = 24.5)]
|
[Version(Min = 19, Max = 24.5)]
|
||||||
public uint metadataUsageListsOffset; // Il2CppMetadataUsageList
|
public uint metadataUsageListsOffset; // Il2CppMetadataUsageList
|
||||||
[Version(Min = 19, Max = 24.5)]
|
[Version(Min = 19, Max = 24.5)]
|
||||||
|
@ -65,27 +65,35 @@ namespace Il2CppDumper
|
||||||
[Version(Min = 19)]
|
[Version(Min = 19)]
|
||||||
public uint fieldRefsOffset; // Il2CppFieldRef
|
public uint fieldRefsOffset; // Il2CppFieldRef
|
||||||
[Version(Min = 19)]
|
[Version(Min = 19)]
|
||||||
public int fieldRefsCount;
|
public int fieldRefsSize;
|
||||||
[Version(Min = 20)]
|
[Version(Min = 20)]
|
||||||
public int referencedAssembliesOffset; // int32_t
|
public int referencedAssembliesOffset; // int32_t
|
||||||
[Version(Min = 20)]
|
[Version(Min = 20)]
|
||||||
public int referencedAssembliesCount;
|
public int referencedAssembliesSize;
|
||||||
[Version(Min = 21)]
|
[Version(Min = 21, Max = 27.2)]
|
||||||
public uint attributesInfoOffset; // Il2CppCustomAttributeTypeRange
|
public uint attributesInfoOffset; // Il2CppCustomAttributeTypeRange
|
||||||
[Version(Min = 21)]
|
[Version(Min = 21, Max = 27.2)]
|
||||||
public int attributesInfoCount;
|
public int attributesInfoCount;
|
||||||
[Version(Min = 21)]
|
[Version(Min = 21, Max = 27.2)]
|
||||||
public uint attributeTypesOffset; // TypeIndex
|
public uint attributeTypesOffset; // TypeIndex
|
||||||
[Version(Min = 21)]
|
[Version(Min = 21, Max = 27.2)]
|
||||||
public int attributeTypesCount;
|
public int attributeTypesCount;
|
||||||
|
[Version(Min = 29)]
|
||||||
|
public uint attributeDataOffset;
|
||||||
|
[Version(Min = 29)]
|
||||||
|
public int attributeDataSize;
|
||||||
|
[Version(Min = 29)]
|
||||||
|
public uint attributeDataRangeOffset;
|
||||||
|
[Version(Min = 29)]
|
||||||
|
public int attributeDataRangeSize;
|
||||||
[Version(Min = 22)]
|
[Version(Min = 22)]
|
||||||
public int unresolvedVirtualCallParameterTypesOffset; // TypeIndex
|
public int unresolvedVirtualCallParameterTypesOffset; // TypeIndex
|
||||||
[Version(Min = 22)]
|
[Version(Min = 22)]
|
||||||
public int unresolvedVirtualCallParameterTypesCount;
|
public int unresolvedVirtualCallParameterTypesSize;
|
||||||
[Version(Min = 22)]
|
[Version(Min = 22)]
|
||||||
public int unresolvedVirtualCallParameterRangesOffset; // Il2CppRange
|
public int unresolvedVirtualCallParameterRangesOffset; // Il2CppRange
|
||||||
[Version(Min = 22)]
|
[Version(Min = 22)]
|
||||||
public int unresolvedVirtualCallParameterRangesCount;
|
public int unresolvedVirtualCallParameterRangesSize;
|
||||||
[Version(Min = 23)]
|
[Version(Min = 23)]
|
||||||
public int windowsRuntimeTypeNamesOffset; // Il2CppWindowsRuntimeTypeNamePair
|
public int windowsRuntimeTypeNamesOffset; // Il2CppWindowsRuntimeTypeNamePair
|
||||||
[Version(Min = 23)]
|
[Version(Min = 23)]
|
||||||
|
@ -97,7 +105,7 @@ namespace Il2CppDumper
|
||||||
[Version(Min = 24)]
|
[Version(Min = 24)]
|
||||||
public int exportedTypeDefinitionsOffset; // TypeDefinitionIndex
|
public int exportedTypeDefinitionsOffset; // TypeDefinitionIndex
|
||||||
[Version(Min = 24)]
|
[Version(Min = 24)]
|
||||||
public int exportedTypeDefinitionsCount;
|
public int exportedTypeDefinitionsSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Il2CppAssemblyDefinition
|
public class Il2CppAssemblyDefinition
|
||||||
|
@ -368,6 +376,7 @@ namespace Il2CppDumper
|
||||||
IL2CPP_RGCTX_DATA_CLASS,
|
IL2CPP_RGCTX_DATA_CLASS,
|
||||||
IL2CPP_RGCTX_DATA_METHOD,
|
IL2CPP_RGCTX_DATA_METHOD,
|
||||||
IL2CPP_RGCTX_DATA_ARRAY,
|
IL2CPP_RGCTX_DATA_ARRAY,
|
||||||
|
IL2CPP_RGCTX_DATA_CONSTRAINED,
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Il2CppRGCTXDefinitionData
|
public class Il2CppRGCTXDefinitionData
|
||||||
|
@ -379,7 +388,11 @@ namespace Il2CppDumper
|
||||||
|
|
||||||
public class Il2CppRGCTXDefinition
|
public class Il2CppRGCTXDefinition
|
||||||
{
|
{
|
||||||
public Il2CppRGCTXDataType type;
|
public Il2CppRGCTXDataType type => type_post29 == 0 ? (Il2CppRGCTXDataType)type_pre29 : (Il2CppRGCTXDataType)type_post29;
|
||||||
|
[Version(Max = 27.1)]
|
||||||
|
public int type_pre29;
|
||||||
|
[Version(Min = 29)]
|
||||||
|
public ulong type_post29;
|
||||||
[Version(Max = 27.1)]
|
[Version(Max = 27.1)]
|
||||||
public Il2CppRGCTXDefinitionData data;
|
public Il2CppRGCTXDefinitionData data;
|
||||||
[Version(Min = 27.2)]
|
[Version(Min = 27.2)]
|
||||||
|
@ -396,4 +409,10 @@ namespace Il2CppDumper
|
||||||
kIl2CppMetadataUsageStringLiteral,
|
kIl2CppMetadataUsageStringLiteral,
|
||||||
kIl2CppMetadataUsageMethodRef,
|
kIl2CppMetadataUsageMethodRef,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
public class Il2CppCustomAttributeDataRange
|
||||||
|
{
|
||||||
|
public uint token;
|
||||||
|
public uint startOffset;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<TargetFrameworks>net472;netcoreapp3.1</TargetFrameworks>
|
<TargetFrameworks>net472;net5.0;net6.0</TargetFrameworks>
|
||||||
<Version>1.0.0</Version>
|
<Version>1.0.0</Version>
|
||||||
<AssemblyVersion>1.0.0.0</AssemblyVersion>
|
<AssemblyVersion>1.0.0.0</AssemblyVersion>
|
||||||
<FileVersion>1.0.0.0</FileVersion>
|
<FileVersion>1.0.0.0</FileVersion>
|
||||||
|
@ -10,8 +10,8 @@
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Mono.Cecil" Version="0.11.2" />
|
<PackageReference Include="Mono.Cecil" Version="0.11.4" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup Condition="'$(TargetFramework)' == 'net472'">
|
<ItemGroup Condition="'$(TargetFramework)' == 'net472'">
|
||||||
|
|
|
@ -165,7 +165,7 @@ namespace Il2CppDumper
|
||||||
writer.Write($"{executor.GetTypeName(fieldType, false, false)} {metadata.GetStringFromIndex(fieldDef.nameIndex)}");
|
writer.Write($"{executor.GetTypeName(fieldType, false, false)} {metadata.GetStringFromIndex(fieldDef.nameIndex)}");
|
||||||
if (metadata.GetFieldDefaultValueFromIndex(i, out var fieldDefaultValue) && fieldDefaultValue.dataIndex != -1)
|
if (metadata.GetFieldDefaultValueFromIndex(i, out var fieldDefaultValue) && fieldDefaultValue.dataIndex != -1)
|
||||||
{
|
{
|
||||||
if (TryGetDefaultValue(fieldDefaultValue.typeIndex, fieldDefaultValue.dataIndex, out var value))
|
if (executor.TryGetDefaultValue(fieldDefaultValue.typeIndex, fieldDefaultValue.dataIndex, out var value))
|
||||||
{
|
{
|
||||||
writer.Write($" = ");
|
writer.Write($" = ");
|
||||||
if (value is string str)
|
if (value is string str)
|
||||||
|
@ -181,6 +181,10 @@ namespace Il2CppDumper
|
||||||
{
|
{
|
||||||
writer.Write($"{value}");
|
writer.Write($"{value}");
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
writer.Write("null");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -238,13 +242,13 @@ namespace Il2CppDumper
|
||||||
{
|
{
|
||||||
writer.Write("\n");
|
writer.Write("\n");
|
||||||
var methodDef = metadata.methodDefs[i];
|
var methodDef = metadata.methodDefs[i];
|
||||||
|
var isAbstract = (methodDef.flags & METHOD_ATTRIBUTE_ABSTRACT) != 0;
|
||||||
if (config.DumpAttribute)
|
if (config.DumpAttribute)
|
||||||
{
|
{
|
||||||
writer.Write(GetCustomAttribute(imageDef, methodDef.customAttributeIndex, methodDef.token, "\t"));
|
writer.Write(GetCustomAttribute(imageDef, methodDef.customAttributeIndex, methodDef.token, "\t"));
|
||||||
}
|
}
|
||||||
if (config.DumpMethodOffset)
|
if (config.DumpMethodOffset)
|
||||||
{
|
{
|
||||||
var isAbstract = (methodDef.flags & METHOD_ATTRIBUTE_ABSTRACT) != 0;
|
|
||||||
var methodPointer = il2Cpp.GetMethodPointer(imageName, methodDef);
|
var methodPointer = il2Cpp.GetMethodPointer(imageName, methodDef);
|
||||||
if (!isAbstract && methodPointer > 0)
|
if (!isAbstract && methodPointer > 0)
|
||||||
{
|
{
|
||||||
|
@ -312,7 +316,7 @@ namespace Il2CppDumper
|
||||||
parameterStr += $"{parameterTypeName} {parameterName}";
|
parameterStr += $"{parameterTypeName} {parameterName}";
|
||||||
if (metadata.GetParameterDefaultValueFromIndex(methodDef.parameterStart + j, out var parameterDefault) && parameterDefault.dataIndex != -1)
|
if (metadata.GetParameterDefaultValueFromIndex(methodDef.parameterStart + j, out var parameterDefault) && parameterDefault.dataIndex != -1)
|
||||||
{
|
{
|
||||||
if (TryGetDefaultValue(parameterDefault.typeIndex, parameterDefault.dataIndex, out var value))
|
if (executor.TryGetDefaultValue(parameterDefault.typeIndex, parameterDefault.dataIndex, out var value))
|
||||||
{
|
{
|
||||||
parameterStr += " = ";
|
parameterStr += " = ";
|
||||||
if (value is string str)
|
if (value is string str)
|
||||||
|
@ -328,6 +332,10 @@ namespace Il2CppDumper
|
||||||
{
|
{
|
||||||
parameterStr += $"{value}";
|
parameterStr += $"{value}";
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
writer.Write("null");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -337,7 +345,14 @@ namespace Il2CppDumper
|
||||||
parameterStrs.Add(parameterStr);
|
parameterStrs.Add(parameterStr);
|
||||||
}
|
}
|
||||||
writer.Write(string.Join(", ", parameterStrs));
|
writer.Write(string.Join(", ", parameterStrs));
|
||||||
writer.Write(") { }\n");
|
if (isAbstract)
|
||||||
|
{
|
||||||
|
writer.Write(");\n");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
writer.Write(") { }\n");
|
||||||
|
}
|
||||||
|
|
||||||
if (il2Cpp.methodDefinitionMethodSpecs.TryGetValue(i, out var methodSpecs))
|
if (il2Cpp.methodDefinitionMethodSpecs.TryGetValue(i, out var methodSpecs))
|
||||||
{
|
{
|
||||||
|
@ -387,21 +402,44 @@ namespace Il2CppDumper
|
||||||
var attributeIndex = metadata.GetCustomAttributeIndex(imageDef, customAttributeIndex, token);
|
var attributeIndex = metadata.GetCustomAttributeIndex(imageDef, customAttributeIndex, token);
|
||||||
if (attributeIndex >= 0)
|
if (attributeIndex >= 0)
|
||||||
{
|
{
|
||||||
var methodPointer = executor.customAttributeGenerators[attributeIndex];
|
if (il2Cpp.Version < 29)
|
||||||
var fixedMethodPointer = il2Cpp.GetRVA(methodPointer);
|
|
||||||
var attributeTypeRange = metadata.attributeTypeRanges[attributeIndex];
|
|
||||||
var sb = new StringBuilder();
|
|
||||||
for (var i = 0; i < attributeTypeRange.count; i++)
|
|
||||||
{
|
{
|
||||||
var typeIndex = metadata.attributeTypes[attributeTypeRange.start + i];
|
var methodPointer = executor.customAttributeGenerators[attributeIndex];
|
||||||
sb.AppendFormat("{0}[{1}] // RVA: 0x{2:X} Offset: 0x{3:X} VA: 0x{4:X}\n",
|
var fixedMethodPointer = il2Cpp.GetRVA(methodPointer);
|
||||||
padding,
|
var attributeTypeRange = metadata.attributeTypeRanges[attributeIndex];
|
||||||
executor.GetTypeName(il2Cpp.types[typeIndex], false, false),
|
var sb = new StringBuilder();
|
||||||
fixedMethodPointer,
|
for (var i = 0; i < attributeTypeRange.count; i++)
|
||||||
il2Cpp.MapVATR(methodPointer),
|
{
|
||||||
methodPointer);
|
var typeIndex = metadata.attributeTypes[attributeTypeRange.start + i];
|
||||||
|
sb.AppendFormat("{0}[{1}] // RVA: 0x{2:X} Offset: 0x{3:X} VA: 0x{4:X}\n",
|
||||||
|
padding,
|
||||||
|
executor.GetTypeName(il2Cpp.types[typeIndex], false, false),
|
||||||
|
fixedMethodPointer,
|
||||||
|
il2Cpp.MapVATR(methodPointer),
|
||||||
|
methodPointer);
|
||||||
|
}
|
||||||
|
return sb.ToString();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var startRange = metadata.attributeDataRanges[attributeIndex];
|
||||||
|
var endRange = metadata.attributeDataRanges[attributeIndex + 1];
|
||||||
|
metadata.Position = metadata.header.attributeDataOffset + startRange.startOffset;
|
||||||
|
var buff = metadata.ReadBytes((int)(endRange.startOffset - startRange.startOffset));
|
||||||
|
var reader = new CustomAttributeDataReader(executor, buff);
|
||||||
|
if (reader.Count == 0)
|
||||||
|
{
|
||||||
|
return string.Empty;
|
||||||
|
}
|
||||||
|
var sb = new StringBuilder();
|
||||||
|
for (var i = 0; i < reader.Count; i++)
|
||||||
|
{
|
||||||
|
sb.Append(padding);
|
||||||
|
sb.Append(reader.GetStringCustomAttributeData());
|
||||||
|
sb.Append("\n");
|
||||||
|
}
|
||||||
|
return sb.ToString();
|
||||||
}
|
}
|
||||||
return sb.ToString();
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -458,58 +496,5 @@ namespace Il2CppDumper
|
||||||
methodModifiers.Add(methodDef, str);
|
methodModifiers.Add(methodDef, str);
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool TryGetDefaultValue(int typeIndex, int dataIndex, out object value)
|
|
||||||
{
|
|
||||||
var pointer = metadata.GetDefaultValueFromIndex(dataIndex);
|
|
||||||
var defaultValueType = il2Cpp.types[typeIndex];
|
|
||||||
metadata.Position = pointer;
|
|
||||||
switch (defaultValueType.type)
|
|
||||||
{
|
|
||||||
case Il2CppTypeEnum.IL2CPP_TYPE_BOOLEAN:
|
|
||||||
value = metadata.ReadBoolean();
|
|
||||||
return true;
|
|
||||||
case Il2CppTypeEnum.IL2CPP_TYPE_U1:
|
|
||||||
value = metadata.ReadByte();
|
|
||||||
return true;
|
|
||||||
case Il2CppTypeEnum.IL2CPP_TYPE_I1:
|
|
||||||
value = metadata.ReadSByte();
|
|
||||||
return true;
|
|
||||||
case Il2CppTypeEnum.IL2CPP_TYPE_CHAR:
|
|
||||||
value = BitConverter.ToChar(metadata.ReadBytes(2), 0);
|
|
||||||
return true;
|
|
||||||
case Il2CppTypeEnum.IL2CPP_TYPE_U2:
|
|
||||||
value = metadata.ReadUInt16();
|
|
||||||
return true;
|
|
||||||
case Il2CppTypeEnum.IL2CPP_TYPE_I2:
|
|
||||||
value = metadata.ReadInt16();
|
|
||||||
return true;
|
|
||||||
case Il2CppTypeEnum.IL2CPP_TYPE_U4:
|
|
||||||
value = metadata.ReadUInt32();
|
|
||||||
return true;
|
|
||||||
case Il2CppTypeEnum.IL2CPP_TYPE_I4:
|
|
||||||
value = metadata.ReadInt32();
|
|
||||||
return true;
|
|
||||||
case Il2CppTypeEnum.IL2CPP_TYPE_U8:
|
|
||||||
value = metadata.ReadUInt64();
|
|
||||||
return true;
|
|
||||||
case Il2CppTypeEnum.IL2CPP_TYPE_I8:
|
|
||||||
value = metadata.ReadInt64();
|
|
||||||
return true;
|
|
||||||
case Il2CppTypeEnum.IL2CPP_TYPE_R4:
|
|
||||||
value = metadata.ReadSingle();
|
|
||||||
return true;
|
|
||||||
case Il2CppTypeEnum.IL2CPP_TYPE_R8:
|
|
||||||
value = metadata.ReadDouble();
|
|
||||||
return true;
|
|
||||||
case Il2CppTypeEnum.IL2CPP_TYPE_STRING:
|
|
||||||
var len = metadata.ReadInt32();
|
|
||||||
value = metadata.ReadString(len);
|
|
||||||
return true;
|
|
||||||
default:
|
|
||||||
value = pointer;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -243,7 +243,10 @@ namespace Il2CppDumper
|
||||||
}
|
}
|
||||||
orderedPointers.AddRange(il2Cpp.genericMethodPointers);
|
orderedPointers.AddRange(il2Cpp.genericMethodPointers);
|
||||||
orderedPointers.AddRange(il2Cpp.invokerPointers);
|
orderedPointers.AddRange(il2Cpp.invokerPointers);
|
||||||
orderedPointers.AddRange(executor.customAttributeGenerators);
|
if (il2Cpp.Version < 29)
|
||||||
|
{
|
||||||
|
orderedPointers.AddRange(executor.customAttributeGenerators);
|
||||||
|
}
|
||||||
if (il2Cpp.Version >= 22)
|
if (il2Cpp.Version >= 22)
|
||||||
{
|
{
|
||||||
if (il2Cpp.reversePInvokeWrappers != null)
|
if (il2Cpp.reversePInvokeWrappers != null)
|
||||||
|
|
8
Il2CppDumper/Utils/AttributeArgument.cs
Normal file
8
Il2CppDumper/Utils/AttributeArgument.cs
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
namespace Il2CppDumper
|
||||||
|
{
|
||||||
|
public class AttributeArgument
|
||||||
|
{
|
||||||
|
public BlobValue Value;
|
||||||
|
public int Index;
|
||||||
|
}
|
||||||
|
}
|
15
Il2CppDumper/Utils/BlobValue.cs
Normal file
15
Il2CppDumper/Utils/BlobValue.cs
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Il2CppDumper
|
||||||
|
{
|
||||||
|
public class BlobValue
|
||||||
|
{
|
||||||
|
public object Value;
|
||||||
|
public Il2CppTypeEnum il2CppTypeEnum;
|
||||||
|
public Il2CppType EnumType;
|
||||||
|
}
|
||||||
|
}
|
170
Il2CppDumper/Utils/CustomAttributeDataReader.cs
Normal file
170
Il2CppDumper/Utils/CustomAttributeDataReader.cs
Normal file
|
@ -0,0 +1,170 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
namespace Il2CppDumper
|
||||||
|
{
|
||||||
|
public class CustomAttributeDataReader : BinaryReader
|
||||||
|
{
|
||||||
|
private Il2CppExecutor executor;
|
||||||
|
private Metadata metadata;
|
||||||
|
private Il2Cpp il2Cpp;
|
||||||
|
private long ctorBuffer;
|
||||||
|
private long dataBuffer;
|
||||||
|
|
||||||
|
public uint Count { get; set; }
|
||||||
|
|
||||||
|
public CustomAttributeDataReader(Il2CppExecutor executor, byte[] buff) : base(new MemoryStream(buff))
|
||||||
|
{
|
||||||
|
this.executor = executor;
|
||||||
|
metadata = executor.metadata;
|
||||||
|
il2Cpp = executor.il2Cpp;
|
||||||
|
Count = this.ReadCompressedUInt32();
|
||||||
|
ctorBuffer = BaseStream.Position;
|
||||||
|
dataBuffer = BaseStream.Position + Count * 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetStringCustomAttributeData()
|
||||||
|
{
|
||||||
|
BaseStream.Position = ctorBuffer;
|
||||||
|
var ctorIndex = ReadInt32();
|
||||||
|
var methodDef = metadata.methodDefs[ctorIndex];
|
||||||
|
var typeDef = metadata.typeDefs[methodDef.declaringType];
|
||||||
|
ctorBuffer = BaseStream.Position;
|
||||||
|
|
||||||
|
BaseStream.Position = dataBuffer;
|
||||||
|
var argumentCount = this.ReadCompressedUInt32();
|
||||||
|
var fieldCount = this.ReadCompressedUInt32();
|
||||||
|
var propertyCount = this.ReadCompressedUInt32();
|
||||||
|
|
||||||
|
var argList = new List<string>();
|
||||||
|
|
||||||
|
for (var i = 0; i < argumentCount; i++)
|
||||||
|
{
|
||||||
|
argList.Add($"{AttributeDataToString(ReadAttributeDataValue())}");
|
||||||
|
}
|
||||||
|
for (var i = 0; i < fieldCount; i++)
|
||||||
|
{
|
||||||
|
var str = AttributeDataToString(ReadAttributeDataValue());
|
||||||
|
(var declaring, var fieldIndex) = ReadCustomAttributeNamedArgumentClassAndIndex(typeDef);
|
||||||
|
var fieldDef = metadata.fieldDefs[declaring.fieldStart + fieldIndex];
|
||||||
|
argList.Add($"{metadata.GetStringFromIndex(fieldDef.nameIndex)} = {str}");
|
||||||
|
}
|
||||||
|
for (var i = 0; i < propertyCount; i++)
|
||||||
|
{
|
||||||
|
var str = AttributeDataToString(ReadAttributeDataValue());
|
||||||
|
(var declaring, var propertyIndex) = ReadCustomAttributeNamedArgumentClassAndIndex(typeDef);
|
||||||
|
var propertyDef = metadata.propertyDefs[declaring.propertyStart + propertyIndex];
|
||||||
|
argList.Add($"{metadata.GetStringFromIndex(propertyDef.nameIndex)} = {str}");
|
||||||
|
}
|
||||||
|
dataBuffer = BaseStream.Position;
|
||||||
|
|
||||||
|
|
||||||
|
var typeName = metadata.GetStringFromIndex(typeDef.nameIndex).Replace("Attribute", "");
|
||||||
|
if (argList.Count > 0)
|
||||||
|
{
|
||||||
|
return $"[{typeName}({string.Join(", ", argList)})]";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return $"[{typeName}]";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private string AttributeDataToString(BlobValue blobValue)
|
||||||
|
{
|
||||||
|
//TODO enum
|
||||||
|
if (blobValue.Value == null)
|
||||||
|
{
|
||||||
|
return "null";
|
||||||
|
}
|
||||||
|
switch (blobValue.il2CppTypeEnum)
|
||||||
|
{
|
||||||
|
case Il2CppTypeEnum.IL2CPP_TYPE_STRING:
|
||||||
|
return $"\"{blobValue.Value}\"";
|
||||||
|
case Il2CppTypeEnum.IL2CPP_TYPE_SZARRAY:
|
||||||
|
var array = (BlobValue[])blobValue.Value;
|
||||||
|
var list = new List<string>();
|
||||||
|
foreach (var item in array)
|
||||||
|
{
|
||||||
|
list.Add(AttributeDataToString(item));
|
||||||
|
}
|
||||||
|
return $"new[] {{ {string.Join(", ", list)} }}";
|
||||||
|
case Il2CppTypeEnum.IL2CPP_TYPE_IL2CPP_TYPE_INDEX:
|
||||||
|
var il2CppType = (Il2CppType)blobValue.Value;
|
||||||
|
return $"typeof({executor.GetTypeName(il2CppType, false, false)})";
|
||||||
|
default:
|
||||||
|
return blobValue.Value.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public CustomAttributeReaderVisitor VisitCustomAttributeData()
|
||||||
|
{
|
||||||
|
var visitor = new CustomAttributeReaderVisitor();
|
||||||
|
|
||||||
|
BaseStream.Position = ctorBuffer;
|
||||||
|
var ctorIndex = ReadInt32();
|
||||||
|
visitor.CtorIndex = ctorIndex;
|
||||||
|
var methodDef = metadata.methodDefs[ctorIndex];
|
||||||
|
var typeDef = metadata.typeDefs[methodDef.declaringType];
|
||||||
|
ctorBuffer = BaseStream.Position;
|
||||||
|
|
||||||
|
BaseStream.Position = dataBuffer;
|
||||||
|
var argumentCount = this.ReadCompressedUInt32();
|
||||||
|
var fieldCount = this.ReadCompressedUInt32();
|
||||||
|
var propertyCount = this.ReadCompressedUInt32();
|
||||||
|
|
||||||
|
visitor.Arguments = new AttributeArgument[argumentCount];
|
||||||
|
for (var i = 0; i < argumentCount; i++)
|
||||||
|
{
|
||||||
|
var argument = visitor.Arguments[i] = new AttributeArgument();
|
||||||
|
argument.Value = ReadAttributeDataValue();
|
||||||
|
argument.Index = i;
|
||||||
|
}
|
||||||
|
visitor.Fields = new AttributeArgument[fieldCount];
|
||||||
|
for (var i = 0; i < fieldCount; i++)
|
||||||
|
{
|
||||||
|
var field = visitor.Fields[i] = new AttributeArgument();
|
||||||
|
field.Value = ReadAttributeDataValue();
|
||||||
|
(var declaring, var fieldIndex) = ReadCustomAttributeNamedArgumentClassAndIndex(typeDef);
|
||||||
|
field.Index = declaring.fieldStart + fieldIndex;
|
||||||
|
}
|
||||||
|
visitor.Properties = new AttributeArgument[propertyCount];
|
||||||
|
for (var i = 0; i < propertyCount; i++)
|
||||||
|
{
|
||||||
|
var property = visitor.Properties[i] = new AttributeArgument();
|
||||||
|
property.Value = ReadAttributeDataValue();
|
||||||
|
(var declaring, var propertyIndex) = ReadCustomAttributeNamedArgumentClassAndIndex(typeDef);
|
||||||
|
property.Index = declaring.propertyStart + propertyIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
dataBuffer = BaseStream.Position;
|
||||||
|
return visitor;
|
||||||
|
}
|
||||||
|
|
||||||
|
private BlobValue ReadAttributeDataValue()
|
||||||
|
{
|
||||||
|
var type = executor.ReadEncodedTypeEnum(this, out var enumType);
|
||||||
|
executor.GetConstantValueFromBlob(type, this, out var blobValue);
|
||||||
|
if (enumType != null)
|
||||||
|
{
|
||||||
|
blobValue.EnumType = enumType;
|
||||||
|
}
|
||||||
|
return blobValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
private (Il2CppTypeDefinition, int) ReadCustomAttributeNamedArgumentClassAndIndex(Il2CppTypeDefinition typeDef)
|
||||||
|
{
|
||||||
|
var memberIndex = this.ReadCompressedInt32();
|
||||||
|
if (memberIndex >= 0)
|
||||||
|
{
|
||||||
|
return (typeDef, memberIndex);
|
||||||
|
}
|
||||||
|
memberIndex = -(memberIndex + 1);
|
||||||
|
|
||||||
|
var typeIndex = this.ReadCompressedUInt32();
|
||||||
|
var declaringClass = metadata.typeDefs[typeIndex];
|
||||||
|
|
||||||
|
return (declaringClass, memberIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
10
Il2CppDumper/Utils/CustomAttributeReaderVisitor.cs
Normal file
10
Il2CppDumper/Utils/CustomAttributeReaderVisitor.cs
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
namespace Il2CppDumper
|
||||||
|
{
|
||||||
|
public class CustomAttributeReaderVisitor
|
||||||
|
{
|
||||||
|
public int CtorIndex;
|
||||||
|
public AttributeArgument[] Arguments;
|
||||||
|
public AttributeArgument[] Fields;
|
||||||
|
public AttributeArgument[] Properties;
|
||||||
|
}
|
||||||
|
}
|
|
@ -18,7 +18,9 @@ namespace Il2CppDumper
|
||||||
private Dictionary<Il2CppGenericParameter, GenericParameter> genericParameterDic = new Dictionary<Il2CppGenericParameter, GenericParameter>();
|
private Dictionary<Il2CppGenericParameter, GenericParameter> genericParameterDic = new Dictionary<Il2CppGenericParameter, GenericParameter>();
|
||||||
private MethodDefinition attributeAttribute;
|
private MethodDefinition attributeAttribute;
|
||||||
private TypeReference stringType;
|
private TypeReference stringType;
|
||||||
private Dictionary<string, MethodDefinition> knownAttributes = new Dictionary<string, MethodDefinition>();
|
private Dictionary<int, FieldDefinition> fieldDefinitionDic = new Dictionary<int, FieldDefinition>();
|
||||||
|
private Dictionary<int, PropertyDefinition> propertyDefinitionDic = new Dictionary<int, PropertyDefinition>();
|
||||||
|
private Dictionary<int, MethodDefinition> methodDefinitionDic = new Dictionary<int, MethodDefinition>();
|
||||||
|
|
||||||
public DummyAssemblyGenerator(Il2CppExecutor il2CppExecutor, bool addToken)
|
public DummyAssemblyGenerator(Il2CppExecutor il2CppExecutor, bool addToken)
|
||||||
{
|
{
|
||||||
|
@ -44,10 +46,7 @@ namespace Il2CppDumper
|
||||||
};
|
};
|
||||||
resolver.Register(il2CppDummyDll);
|
resolver.Register(il2CppDummyDll);
|
||||||
|
|
||||||
var fieldDefinitionDic = new Dictionary<int, FieldDefinition>();
|
|
||||||
var methodDefinitionDic = new Dictionary<int, MethodDefinition>();
|
|
||||||
var parameterDefinitionDic = new Dictionary<int, ParameterDefinition>();
|
var parameterDefinitionDic = new Dictionary<int, ParameterDefinition>();
|
||||||
var propertyDefinitionDic = new Dictionary<int, PropertyDefinition>();
|
|
||||||
var eventDefinitionDic = new Dictionary<int, EventDefinition>();
|
var eventDefinitionDic = new Dictionary<int, EventDefinition>();
|
||||||
|
|
||||||
//创建程序集,同时创建所有类
|
//创建程序集,同时创建所有类
|
||||||
|
@ -56,7 +55,17 @@ namespace Il2CppDumper
|
||||||
var imageName = metadata.GetStringFromIndex(imageDef.nameIndex);
|
var imageName = metadata.GetStringFromIndex(imageDef.nameIndex);
|
||||||
var aname = metadata.assemblyDefs[imageDef.assemblyIndex].aname;
|
var aname = metadata.assemblyDefs[imageDef.assemblyIndex].aname;
|
||||||
var assemblyName = metadata.GetStringFromIndex(aname.nameIndex);
|
var assemblyName = metadata.GetStringFromIndex(aname.nameIndex);
|
||||||
var assemblyNameDef = new AssemblyNameDefinition(assemblyName, new Version(aname.major, aname.minor, aname.build, aname.revision));
|
Version vers;
|
||||||
|
if (aname.build >= 0)
|
||||||
|
{
|
||||||
|
vers = new Version(aname.major, aname.minor, aname.build, aname.revision);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//__Generated
|
||||||
|
vers = new Version(3, 7, 1, 6);
|
||||||
|
}
|
||||||
|
var assemblyNameDef = new AssemblyNameDefinition(assemblyName, vers);
|
||||||
/*assemblyNameDef.Culture = metadata.GetStringFromIndex(aname.cultureIndex);
|
/*assemblyNameDef.Culture = metadata.GetStringFromIndex(aname.cultureIndex);
|
||||||
assemblyNameDef.PublicKey = Encoding.UTF8.GetBytes(metadata.GetStringFromIndex(aname.publicKeyIndex));
|
assemblyNameDef.PublicKey = Encoding.UTF8.GetBytes(metadata.GetStringFromIndex(aname.publicKeyIndex));
|
||||||
assemblyNameDef.HashAlgorithm = (AssemblyHashAlgorithm)aname.hash_alg;
|
assemblyNameDef.HashAlgorithm = (AssemblyHashAlgorithm)aname.hash_alg;
|
||||||
|
@ -169,7 +178,7 @@ namespace Il2CppDumper
|
||||||
//fieldDefault
|
//fieldDefault
|
||||||
if (metadata.GetFieldDefaultValueFromIndex(i, out var fieldDefault) && fieldDefault.dataIndex != -1)
|
if (metadata.GetFieldDefaultValueFromIndex(i, out var fieldDefault) && fieldDefault.dataIndex != -1)
|
||||||
{
|
{
|
||||||
if (TryGetDefaultValue(fieldDefault.typeIndex, fieldDefault.dataIndex, out var value))
|
if (executor.TryGetDefaultValue(fieldDefault.typeIndex, fieldDefault.dataIndex, out var value))
|
||||||
{
|
{
|
||||||
fieldDefinition.Constant = value;
|
fieldDefinition.Constant = value;
|
||||||
}
|
}
|
||||||
|
@ -262,7 +271,7 @@ namespace Il2CppDumper
|
||||||
//ParameterDefault
|
//ParameterDefault
|
||||||
if (metadata.GetParameterDefaultValueFromIndex(methodDef.parameterStart + j, out var parameterDefault) && parameterDefault.dataIndex != -1)
|
if (metadata.GetParameterDefaultValueFromIndex(methodDef.parameterStart + j, out var parameterDefault) && parameterDefault.dataIndex != -1)
|
||||||
{
|
{
|
||||||
if (TryGetDefaultValue(parameterDefault.typeIndex, parameterDefault.dataIndex, out var value))
|
if (executor.TryGetDefaultValue(parameterDefault.typeIndex, parameterDefault.dataIndex, out var value))
|
||||||
{
|
{
|
||||||
parameterDefinition.Constant = value;
|
parameterDefinition.Constant = value;
|
||||||
}
|
}
|
||||||
|
@ -537,83 +546,71 @@ namespace Il2CppDumper
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool TryGetDefaultValue(int typeIndex, int dataIndex, out object value)
|
|
||||||
{
|
|
||||||
var pointer = metadata.GetDefaultValueFromIndex(dataIndex);
|
|
||||||
var defaultValueType = il2Cpp.types[typeIndex];
|
|
||||||
metadata.Position = pointer;
|
|
||||||
switch (defaultValueType.type)
|
|
||||||
{
|
|
||||||
case Il2CppTypeEnum.IL2CPP_TYPE_BOOLEAN:
|
|
||||||
value = metadata.ReadBoolean();
|
|
||||||
return true;
|
|
||||||
case Il2CppTypeEnum.IL2CPP_TYPE_U1:
|
|
||||||
value = metadata.ReadByte();
|
|
||||||
return true;
|
|
||||||
case Il2CppTypeEnum.IL2CPP_TYPE_I1:
|
|
||||||
value = metadata.ReadSByte();
|
|
||||||
return true;
|
|
||||||
case Il2CppTypeEnum.IL2CPP_TYPE_CHAR:
|
|
||||||
value = BitConverter.ToChar(metadata.ReadBytes(2), 0);
|
|
||||||
return true;
|
|
||||||
case Il2CppTypeEnum.IL2CPP_TYPE_U2:
|
|
||||||
value = metadata.ReadUInt16();
|
|
||||||
return true;
|
|
||||||
case Il2CppTypeEnum.IL2CPP_TYPE_I2:
|
|
||||||
value = metadata.ReadInt16();
|
|
||||||
return true;
|
|
||||||
case Il2CppTypeEnum.IL2CPP_TYPE_U4:
|
|
||||||
value = metadata.ReadUInt32();
|
|
||||||
return true;
|
|
||||||
case Il2CppTypeEnum.IL2CPP_TYPE_I4:
|
|
||||||
value = metadata.ReadInt32();
|
|
||||||
return true;
|
|
||||||
case Il2CppTypeEnum.IL2CPP_TYPE_U8:
|
|
||||||
value = metadata.ReadUInt64();
|
|
||||||
return true;
|
|
||||||
case Il2CppTypeEnum.IL2CPP_TYPE_I8:
|
|
||||||
value = metadata.ReadInt64();
|
|
||||||
return true;
|
|
||||||
case Il2CppTypeEnum.IL2CPP_TYPE_R4:
|
|
||||||
value = metadata.ReadSingle();
|
|
||||||
return true;
|
|
||||||
case Il2CppTypeEnum.IL2CPP_TYPE_R8:
|
|
||||||
value = metadata.ReadDouble();
|
|
||||||
return true;
|
|
||||||
case Il2CppTypeEnum.IL2CPP_TYPE_STRING:
|
|
||||||
var len = metadata.ReadInt32();
|
|
||||||
value = metadata.ReadString(len);
|
|
||||||
return true;
|
|
||||||
default:
|
|
||||||
value = pointer;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void CreateCustomAttribute(Il2CppImageDefinition imageDef, int customAttributeIndex, uint token, ModuleDefinition moduleDefinition, Collection<CustomAttribute> customAttributes)
|
private void CreateCustomAttribute(Il2CppImageDefinition imageDef, int customAttributeIndex, uint token, ModuleDefinition moduleDefinition, Collection<CustomAttribute> customAttributes)
|
||||||
{
|
{
|
||||||
var attributeIndex = metadata.GetCustomAttributeIndex(imageDef, customAttributeIndex, token);
|
var attributeIndex = metadata.GetCustomAttributeIndex(imageDef, customAttributeIndex, token);
|
||||||
if (attributeIndex >= 0)
|
if (attributeIndex >= 0)
|
||||||
{
|
{
|
||||||
var attributeTypeRange = metadata.attributeTypeRanges[attributeIndex];
|
if (il2Cpp.Version < 29)
|
||||||
for (int i = 0; i < attributeTypeRange.count; i++)
|
|
||||||
{
|
{
|
||||||
var attributeTypeIndex = metadata.attributeTypes[attributeTypeRange.start + i];
|
var attributeTypeRange = metadata.attributeTypeRanges[attributeIndex];
|
||||||
var attributeType = il2Cpp.types[attributeTypeIndex];
|
for (int i = 0; i < attributeTypeRange.count; i++)
|
||||||
var typeDef = executor.GetTypeDefinitionFromIl2CppType(attributeType);
|
|
||||||
var typeDefinition = typeDefinitionDic[typeDef];
|
|
||||||
if (!TryRestoreCustomAttribute(typeDefinition, moduleDefinition, customAttributes))
|
|
||||||
{
|
{
|
||||||
var methodPointer = executor.customAttributeGenerators[attributeIndex];
|
var attributeTypeIndex = metadata.attributeTypes[attributeTypeRange.start + i];
|
||||||
var fixedMethodPointer = il2Cpp.GetRVA(methodPointer);
|
var attributeType = il2Cpp.types[attributeTypeIndex];
|
||||||
var customAttribute = new CustomAttribute(moduleDefinition.ImportReference(attributeAttribute));
|
var typeDef = executor.GetTypeDefinitionFromIl2CppType(attributeType);
|
||||||
var name = new CustomAttributeNamedArgument("Name", new CustomAttributeArgument(stringType, typeDefinition.Name));
|
var typeDefinition = typeDefinitionDic[typeDef];
|
||||||
var rva = new CustomAttributeNamedArgument("RVA", new CustomAttributeArgument(stringType, $"0x{fixedMethodPointer:X}"));
|
if (!TryRestoreCustomAttribute(typeDefinition, moduleDefinition, customAttributes))
|
||||||
var offset = new CustomAttributeNamedArgument("Offset", new CustomAttributeArgument(stringType, $"0x{il2Cpp.MapVATR(methodPointer):X}"));
|
{
|
||||||
customAttribute.Fields.Add(name);
|
var methodPointer = executor.customAttributeGenerators[attributeIndex];
|
||||||
customAttribute.Fields.Add(rva);
|
var fixedMethodPointer = il2Cpp.GetRVA(methodPointer);
|
||||||
customAttribute.Fields.Add(offset);
|
var customAttribute = new CustomAttribute(moduleDefinition.ImportReference(attributeAttribute));
|
||||||
customAttributes.Add(customAttribute);
|
var name = new CustomAttributeNamedArgument("Name", new CustomAttributeArgument(stringType, typeDefinition.Name));
|
||||||
|
var rva = new CustomAttributeNamedArgument("RVA", new CustomAttributeArgument(stringType, $"0x{fixedMethodPointer:X}"));
|
||||||
|
var offset = new CustomAttributeNamedArgument("Offset", new CustomAttributeArgument(stringType, $"0x{il2Cpp.MapVATR(methodPointer):X}"));
|
||||||
|
customAttribute.Fields.Add(name);
|
||||||
|
customAttribute.Fields.Add(rva);
|
||||||
|
customAttribute.Fields.Add(offset);
|
||||||
|
customAttributes.Add(customAttribute);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var startRange = metadata.attributeDataRanges[attributeIndex];
|
||||||
|
var endRange = metadata.attributeDataRanges[attributeIndex + 1];
|
||||||
|
metadata.Position = metadata.header.attributeDataOffset + startRange.startOffset;
|
||||||
|
var buff = metadata.ReadBytes((int)(endRange.startOffset - startRange.startOffset));
|
||||||
|
var reader = new CustomAttributeDataReader(executor, buff);
|
||||||
|
if (reader.Count != 0)
|
||||||
|
{
|
||||||
|
for (var i = 0; i < reader.Count; i++)
|
||||||
|
{
|
||||||
|
var visitor = reader.VisitCustomAttributeData();
|
||||||
|
var methodDefinition = methodDefinitionDic[visitor.CtorIndex];
|
||||||
|
var customAttribute = new CustomAttribute(moduleDefinition.ImportReference(methodDefinition));
|
||||||
|
foreach (var argument in visitor.Arguments)
|
||||||
|
{
|
||||||
|
var parameterDefinition = methodDefinition.Parameters[argument.Index];
|
||||||
|
var customAttributeArgument = CreateCustomAttributeArgument(parameterDefinition.ParameterType, argument.Value, methodDefinition);
|
||||||
|
customAttribute.ConstructorArguments.Add(customAttributeArgument);
|
||||||
|
}
|
||||||
|
foreach (var field in visitor.Fields)
|
||||||
|
{
|
||||||
|
var fieldDefinition = fieldDefinitionDic[field.Index];
|
||||||
|
var customAttributeArgument = CreateCustomAttributeArgument(fieldDefinition.FieldType, field.Value, fieldDefinition);
|
||||||
|
var customAttributeNamedArgument = new CustomAttributeNamedArgument(fieldDefinition.Name, customAttributeArgument);
|
||||||
|
customAttribute.Fields.Add(customAttributeNamedArgument);
|
||||||
|
}
|
||||||
|
foreach (var property in visitor.Properties)
|
||||||
|
{
|
||||||
|
var propertyDefinition = propertyDefinitionDic[property.Index];
|
||||||
|
var customAttributeArgument = CreateCustomAttributeArgument(propertyDefinition.PropertyType, property.Value, propertyDefinition);
|
||||||
|
var customAttributeNamedArgument = new CustomAttributeNamedArgument(propertyDefinition.Name, customAttributeArgument);
|
||||||
|
customAttribute.Properties.Add(customAttributeNamedArgument);
|
||||||
|
}
|
||||||
|
customAttributes.Add(customAttribute);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -650,5 +647,41 @@ namespace Il2CppDumper
|
||||||
}
|
}
|
||||||
return genericParameter;
|
return genericParameter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private CustomAttributeArgument CreateCustomAttributeArgument(TypeReference typeReference, BlobValue blobValue, MemberReference memberReference)
|
||||||
|
{
|
||||||
|
var val = blobValue.Value;
|
||||||
|
if (typeReference.FullName == "System.Object")
|
||||||
|
{
|
||||||
|
val = new CustomAttributeArgument(GetBlobValueTypeReference(blobValue, memberReference), val);
|
||||||
|
}
|
||||||
|
else if (typeReference is ArrayType arrayType)
|
||||||
|
{
|
||||||
|
var arrayVal = (BlobValue[])val;
|
||||||
|
var array = new CustomAttributeArgument[arrayVal.Length];
|
||||||
|
var elementType = arrayType.ElementType;
|
||||||
|
for (int i = 0; i < arrayVal.Length; i++)
|
||||||
|
{
|
||||||
|
array[i] = CreateCustomAttributeArgument(elementType, arrayVal[i], memberReference);
|
||||||
|
}
|
||||||
|
val = array;
|
||||||
|
}
|
||||||
|
else if (typeReference.FullName == "System.Type")
|
||||||
|
{
|
||||||
|
val = GetTypeReference(memberReference, (Il2CppType)val);
|
||||||
|
}
|
||||||
|
return new CustomAttributeArgument(typeReference, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
private TypeReference GetBlobValueTypeReference(BlobValue blobValue, MemberReference memberReference)
|
||||||
|
{
|
||||||
|
if (blobValue.EnumType != null)
|
||||||
|
{
|
||||||
|
return GetTypeReference(memberReference, blobValue.EnumType);
|
||||||
|
}
|
||||||
|
var il2CppType = new Il2CppType();
|
||||||
|
il2CppType.type = blobValue.il2CppTypeEnum;
|
||||||
|
return GetTypeReference(memberReference, il2CppType);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
namespace Il2CppDumper
|
namespace Il2CppDumper
|
||||||
{
|
{
|
||||||
|
@ -36,7 +38,7 @@ namespace Il2CppDumper
|
||||||
this.metadata = metadata;
|
this.metadata = metadata;
|
||||||
this.il2Cpp = il2Cpp;
|
this.il2Cpp = il2Cpp;
|
||||||
|
|
||||||
if (il2Cpp.Version >= 27)
|
if (il2Cpp.Version >= 27 && il2Cpp.Version < 29)
|
||||||
{
|
{
|
||||||
customAttributeGenerators = new ulong[metadata.imageDefs.Sum(x => x.customAttributeCount)];
|
customAttributeGenerators = new ulong[metadata.imageDefs.Sum(x => x.customAttributeCount)];
|
||||||
foreach (var imageDef in metadata.imageDefs)
|
foreach (var imageDef in metadata.imageDefs)
|
||||||
|
@ -50,7 +52,7 @@ namespace Il2CppDumper
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else if (il2Cpp.Version < 27)
|
||||||
{
|
{
|
||||||
customAttributeGenerators = il2Cpp.customAttributeGenerators;
|
customAttributeGenerators = il2Cpp.customAttributeGenerators;
|
||||||
}
|
}
|
||||||
|
@ -320,5 +322,148 @@ namespace Il2CppDumper
|
||||||
{
|
{
|
||||||
return il2Cpp.GetSectionHelper(metadata.methodDefs.Count(x => x.methodIndex >= 0), metadata.typeDefs.Length, metadata.imageDefs.Length);
|
return il2Cpp.GetSectionHelper(metadata.methodDefs.Count(x => x.methodIndex >= 0), metadata.typeDefs.Length, metadata.imageDefs.Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool TryGetDefaultValue(int typeIndex, int dataIndex, out object value)
|
||||||
|
{
|
||||||
|
var pointer = metadata.GetDefaultValueFromIndex(dataIndex);
|
||||||
|
var defaultValueType = il2Cpp.types[typeIndex];
|
||||||
|
metadata.Position = pointer;
|
||||||
|
if (GetConstantValueFromBlob(defaultValueType.type, metadata.Reader, out var blobValue))
|
||||||
|
{
|
||||||
|
value = blobValue.Value;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
value = pointer;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool GetConstantValueFromBlob(Il2CppTypeEnum type, BinaryReader reader, out BlobValue value)
|
||||||
|
{
|
||||||
|
value = new BlobValue();
|
||||||
|
value.il2CppTypeEnum = type;
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case Il2CppTypeEnum.IL2CPP_TYPE_BOOLEAN:
|
||||||
|
value.Value = reader.ReadBoolean();
|
||||||
|
return true;
|
||||||
|
case Il2CppTypeEnum.IL2CPP_TYPE_U1:
|
||||||
|
value.Value = reader.ReadByte();
|
||||||
|
return true;
|
||||||
|
case Il2CppTypeEnum.IL2CPP_TYPE_I1:
|
||||||
|
value.Value = reader.ReadSByte();
|
||||||
|
return true;
|
||||||
|
case Il2CppTypeEnum.IL2CPP_TYPE_CHAR:
|
||||||
|
value.Value = BitConverter.ToChar(reader.ReadBytes(2), 0);
|
||||||
|
return true;
|
||||||
|
case Il2CppTypeEnum.IL2CPP_TYPE_U2:
|
||||||
|
value.Value = reader.ReadUInt16();
|
||||||
|
return true;
|
||||||
|
case Il2CppTypeEnum.IL2CPP_TYPE_I2:
|
||||||
|
value.Value = reader.ReadInt16();
|
||||||
|
return true;
|
||||||
|
case Il2CppTypeEnum.IL2CPP_TYPE_U4:
|
||||||
|
if (il2Cpp.Version >= 29)
|
||||||
|
{
|
||||||
|
value.Value = reader.ReadCompressedUInt32();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
value.Value = reader.ReadUInt32();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
case Il2CppTypeEnum.IL2CPP_TYPE_I4:
|
||||||
|
if (il2Cpp.Version >= 29)
|
||||||
|
{
|
||||||
|
value.Value = reader.ReadCompressedInt32();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
value.Value = reader.ReadInt32();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
case Il2CppTypeEnum.IL2CPP_TYPE_U8:
|
||||||
|
value.Value = reader.ReadUInt64();
|
||||||
|
return true;
|
||||||
|
case Il2CppTypeEnum.IL2CPP_TYPE_I8:
|
||||||
|
value.Value = reader.ReadInt64();
|
||||||
|
return true;
|
||||||
|
case Il2CppTypeEnum.IL2CPP_TYPE_R4:
|
||||||
|
value.Value = reader.ReadSingle();
|
||||||
|
return true;
|
||||||
|
case Il2CppTypeEnum.IL2CPP_TYPE_R8:
|
||||||
|
value.Value = reader.ReadDouble();
|
||||||
|
return true;
|
||||||
|
case Il2CppTypeEnum.IL2CPP_TYPE_STRING:
|
||||||
|
int length;
|
||||||
|
if (il2Cpp.Version >= 29)
|
||||||
|
{
|
||||||
|
length = reader.ReadCompressedInt32();
|
||||||
|
if (length == -1)
|
||||||
|
{
|
||||||
|
value.Value = null;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
value.Value = Encoding.UTF8.GetString(reader.ReadBytes(length));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
length = reader.ReadInt32();
|
||||||
|
value.Value = reader.ReadString(length);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
case Il2CppTypeEnum.IL2CPP_TYPE_SZARRAY:
|
||||||
|
var arrayLen = reader.ReadCompressedInt32();
|
||||||
|
if (arrayLen == -1)
|
||||||
|
{
|
||||||
|
value.Value = null;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var array = new BlobValue[arrayLen];
|
||||||
|
var arrayElementType = ReadEncodedTypeEnum(reader, out var enumType);
|
||||||
|
var arrayElementsAreDifferent = reader.ReadByte();
|
||||||
|
for (int i = 0; i < arrayLen; i++)
|
||||||
|
{
|
||||||
|
var elementType = arrayElementType;
|
||||||
|
if (arrayElementsAreDifferent == 1)
|
||||||
|
{
|
||||||
|
elementType = ReadEncodedTypeEnum(reader, out enumType);
|
||||||
|
}
|
||||||
|
GetConstantValueFromBlob(elementType, reader, out var data);
|
||||||
|
data.il2CppTypeEnum = elementType;
|
||||||
|
data.EnumType = enumType;
|
||||||
|
array[i] = data;
|
||||||
|
}
|
||||||
|
value.Value = array;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
case Il2CppTypeEnum.IL2CPP_TYPE_IL2CPP_TYPE_INDEX:
|
||||||
|
var typeIndex = reader.ReadCompressedInt32();
|
||||||
|
value.Value = il2Cpp.types[typeIndex];
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
value = null;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Il2CppTypeEnum ReadEncodedTypeEnum(BinaryReader reader, out Il2CppType enumType)
|
||||||
|
{
|
||||||
|
enumType = null;
|
||||||
|
var type = (Il2CppTypeEnum)reader.ReadByte();
|
||||||
|
if (type == Il2CppTypeEnum.IL2CPP_TYPE_ENUM)
|
||||||
|
{
|
||||||
|
var enumTypeIndex = reader.ReadCompressedInt32();
|
||||||
|
enumType = il2Cpp.types[enumTypeIndex];
|
||||||
|
var typeDef = GetTypeDefinitionFromIl2CppType(enumType);
|
||||||
|
type = il2Cpp.types[typeDef.elementTypeIndex].type;
|
||||||
|
}
|
||||||
|
return type;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -340,6 +340,10 @@ namespace Il2CppDumper
|
||||||
var va2 = FindReference(va - (ulong)i * il2Cpp.PointerSize);
|
var va2 = FindReference(va - (ulong)i * il2Cpp.PointerSize);
|
||||||
if (va2 != 0ul)
|
if (va2 != 0ul)
|
||||||
{
|
{
|
||||||
|
if (il2Cpp.Version >= 29)
|
||||||
|
{
|
||||||
|
return va2 - il2Cpp.PointerSize * 14;
|
||||||
|
}
|
||||||
return va2 - il2Cpp.PointerSize * 13;
|
return va2 - il2Cpp.PointerSize * 13;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue