• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

SamboyCoding / Cpp2IL / 12320749043

13 Dec 2024 06:07PM UTC coverage: 27.79% (-0.3%) from 28.128%
12320749043

Pull #393

github

web-flow
Merge b9caa35d0 into ac99859af
Pull Request #393: Add Type field to AttributeAttribute

1268 of 6370 branches covered (19.91%)

Branch coverage included in aggregate %.

3 of 93 new or added lines in 7 files covered. (3.23%)

45 existing lines in 4 files now uncovered.

3386 of 10377 relevant lines covered (32.63%)

123656.67 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

41.86
/LibCpp2IL/LibCpp2IlUtils.cs
1
using System;
2
using System.Collections.Generic;
3
using System.Linq;
4
using System.Text;
5
using LibCpp2IL.BinaryStructures;
6
using LibCpp2IL.Logging;
7
using LibCpp2IL.Metadata;
8
using LibCpp2IL.Reflection;
9

10
namespace LibCpp2IL;
11

12
public static class LibCpp2ILUtils
13
{
14
    private static readonly Dictionary<string, ulong> PrimitiveSizes = new()
×
15
    {
×
16
        { "Byte", 1 },
×
17
        { "SByte", 1 },
×
18
        { "Boolean", 1 },
×
19
        { "Int16", 2 },
×
20
        { "UInt16", 2 },
×
21
        { "Char", 2 },
×
22
        { "Int32", 4 },
×
23
        { "UInt32", 4 },
×
24
        { "Single", 4 },
×
25
        { "Int64", 8 },
×
26
        { "UInt64", 8 },
×
27
        { "Double", 8 },
×
28
        { "IntPtr", 8 },
×
29
        { "UIntPtr", 8 },
×
30
    };
×
31

NEW
32
    public static string GetTypeName(Il2CppTypeEnum type) => (int)type switch
×
NEW
33
    {
×
NEW
34
        1 => "void",
×
NEW
35
        2 => "bool",
×
NEW
36
        3 => "char",
×
NEW
37
        4 => "sbyte",
×
NEW
38
        5 => "byte",
×
NEW
39
        6 => "short",
×
NEW
40
        7 => "ushort",
×
NEW
41
        8 => "int",
×
NEW
42
        9 => "uint",
×
NEW
43
        10 => "long",
×
NEW
44
        11 => "ulong",
×
NEW
45
        12 => "float",
×
NEW
46
        13 => "double",
×
NEW
47
        14 => "string",
×
NEW
48
        22 => "TypedReference",
×
NEW
49
        24 => "IntPtr",
×
NEW
50
        25 => "UIntPtr",
×
NEW
51
        28 => "object",
×
NEW
52
        _ => throw new ArgumentOutOfRangeException(nameof(type), type, null)
×
NEW
53
    };
×
54

55
    internal static string GetTypeName(Il2CppMetadata metadata, Il2CppBinary cppAssembly, Il2CppTypeDefinition typeDef, bool fullName = false)
56
    {
57
        var ret = string.Empty;
×
58
        if (fullName)
×
59
        {
60
            ret = typeDef.Namespace;
×
61
            if (ret != string.Empty)
×
62
            {
63
                ret += ".";
×
64
            }
65
        }
66

67
        if (typeDef.DeclaringTypeIndex != -1)
×
68
        {
69
            ret += GetTypeName(metadata, cppAssembly, cppAssembly.GetType(typeDef.DeclaringTypeIndex)) + ".";
×
70
        }
71

72
        ret += metadata.GetStringFromIndex(typeDef.NameIndex);
×
73
        var names = new List<string>();
×
74
        if (typeDef.GenericContainerIndex < 0) return ret;
×
75

76
        var genericContainer = metadata.genericContainers[typeDef.GenericContainerIndex];
×
77
        for (var i = 0; i < genericContainer.genericParameterCount; i++)
×
78
        {
79
            var genericParameterIndex = genericContainer.genericParameterStart + i;
×
80
            var param = metadata.genericParameters[genericParameterIndex];
×
81
            names.Add(metadata.GetStringFromIndex(param.nameIndex));
×
82
        }
83

84
        ret = ret.Replace($"`{genericContainer.genericParameterCount}", "");
×
85
        ret += $"<{string.Join(", ", names)}>";
×
86

87
        return ret;
×
88
    }
89

90
    internal static Il2CppTypeReflectionData[]? GetGenericTypeParams(Il2CppGenericInst genericInst)
91
    {
92
        if (LibCpp2IlMain.Binary == null || LibCpp2IlMain.TheMetadata == null) return null;
395,282!
93

94
        var types = new Il2CppTypeReflectionData[genericInst.pointerCount];
395,282✔
95
        var pointers = LibCpp2IlMain.Binary.ReadNUintArrayAtVirtualAddress(genericInst.pointerStart, (long)genericInst.pointerCount);
395,282✔
96
        for (uint i = 0; i < genericInst.pointerCount; ++i)
1,820,908✔
97
        {
98
            var oriType = LibCpp2IlMain.Binary.GetIl2CppTypeFromPointer(pointers[i]);
515,172✔
99
            types[i] = GetTypeReflectionData(oriType);
515,172✔
100
        }
101

102
        return types;
395,282✔
103
    }
104

105
    internal static string GetGenericTypeParamNames(Il2CppMetadata metadata, Il2CppBinary cppAssembly, Il2CppGenericInst genericInst)
106
    {
107
        var typeNames = genericInst.Types.Select(t => GetTypeName(metadata, cppAssembly, t)).ToArray();
×
108

109
        return $"<{string.Join(", ", typeNames)}>";
×
110
    }
111

112
    public static string GetTypeName(Il2CppMetadata metadata, Il2CppBinary cppAssembly, Il2CppType type, bool fullName = false)
113
    {
114
        string ret;
115
        switch (type.Type)
×
116
        {
117
            case Il2CppTypeEnum.IL2CPP_TYPE_CLASS:
118
            case Il2CppTypeEnum.IL2CPP_TYPE_VALUETYPE:
119
            {
120
                var typeDef = metadata.typeDefs[type.Data.ClassIndex];
×
121
                ret = string.Empty;
×
122

123
                ret += GetTypeName(metadata, cppAssembly, typeDef, fullName);
×
124
                break;
×
125
            }
126
            case Il2CppTypeEnum.IL2CPP_TYPE_GENERICINST:
127
            {
128
                var genericClass = cppAssembly.ReadReadableAtVirtualAddress<Il2CppGenericClass>(type.Data.GenericClass);
×
129
                var typeDef = genericClass.TypeDefinition;
×
130
                ret = typeDef.Name!;
×
131
                var genericInst = genericClass.Context.ClassInst;
×
132
                ret = ret.Replace($"`{genericInst.pointerCount}", "");
×
133
                ret += GetGenericTypeParamNames(metadata, cppAssembly, genericInst);
×
134
                break;
×
135
            }
136
            case Il2CppTypeEnum.IL2CPP_TYPE_VAR:
137
            case Il2CppTypeEnum.IL2CPP_TYPE_MVAR:
138
            {
139
                var param = metadata.genericParameters[type.Data.GenericParameterIndex];
×
140
                ret = metadata.GetStringFromIndex(param.nameIndex);
×
141
                break;
×
142
            }
143
            case Il2CppTypeEnum.IL2CPP_TYPE_ARRAY:
144
            {
145
                var arrayType = cppAssembly.ReadReadableAtVirtualAddress<Il2CppArrayType>(type.Data.Array);
×
146
                var oriType = cppAssembly.GetIl2CppTypeFromPointer(arrayType.etype);
×
147
                ret = $"{GetTypeName(metadata, cppAssembly, oriType)}[{new string(',', arrayType.rank - 1)}]";
×
148
                break;
×
149
            }
150
            case Il2CppTypeEnum.IL2CPP_TYPE_SZARRAY:
151
            {
152
                var oriType = cppAssembly.GetIl2CppTypeFromPointer(type.Data.Type);
×
153
                ret = $"{GetTypeName(metadata, cppAssembly, oriType)}[]";
×
154
                break;
×
155
            }
156
            case Il2CppTypeEnum.IL2CPP_TYPE_PTR:
157
            {
158
                var oriType = cppAssembly.GetIl2CppTypeFromPointer(type.Data.Type);
×
159
                ret = $"{GetTypeName(metadata, cppAssembly, oriType)}*";
×
160
                break;
×
161
            }
162
            default:
NEW
163
                ret = GetTypeName(type.Type);
×
164
                break;
165
        }
166

167
        return ret;
×
168
    }
169

170
    internal static object? GetDefaultValue(int dataIndex, int typeIndex)
171
    {
172
        var metadata = LibCpp2IlMain.TheMetadata!;
63,742✔
173
        var theDll = LibCpp2IlMain.Binary!;
63,742✔
174

175
        if (dataIndex == -1)
63,742!
176
            return null; //Literally null.
×
177

178
        var pointer = metadata.GetDefaultValueFromIndex(dataIndex);
63,742✔
179
        if (pointer <= 0) return null;
63,742!
180

181
        var defaultValueType = theDll.GetType(typeIndex);
63,742✔
182
        metadata.GetLockOrThrow();
63,742✔
183
        metadata.Position = pointer;
63,742✔
184
        try
185
        {
186
            switch (defaultValueType.Type)
63,742!
187
            {
188
                case Il2CppTypeEnum.IL2CPP_TYPE_BOOLEAN:
189
                    return metadata.ReadBoolean();
×
190
                case Il2CppTypeEnum.IL2CPP_TYPE_U1:
191
                    return metadata.ReadByte();
964✔
192
                case Il2CppTypeEnum.IL2CPP_TYPE_I1:
193
                    return metadata.ReadSByte();
134✔
194
                case Il2CppTypeEnum.IL2CPP_TYPE_CHAR:
195
                    return BitConverter.ToChar(metadata.ReadByteArrayAtRawAddressNoLock(pointer, 2), 0);
32✔
196
                case Il2CppTypeEnum.IL2CPP_TYPE_U2:
197
                    return metadata.ReadUInt16();
740✔
198
                case Il2CppTypeEnum.IL2CPP_TYPE_I2:
199
                    return metadata.ReadInt16();
86✔
200
                case Il2CppTypeEnum.IL2CPP_TYPE_U4:
201
                    if (LibCpp2IlMain.MetadataVersion < 29)
572✔
202
                        return metadata.ReadUInt32();
410✔
203
                    return metadata.ReadUnityCompressedUIntAtRawAddrNoLock(pointer, out _);
162✔
204
                case Il2CppTypeEnum.IL2CPP_TYPE_I4:
205
                    if (LibCpp2IlMain.MetadataVersion < 29)
58,356✔
206
                        return metadata.ReadInt32();
39,750✔
207
                    return metadata.ReadUnityCompressedIntAtRawAddr(pointer, false, out _);
18,606✔
208
                case Il2CppTypeEnum.IL2CPP_TYPE_U8:
209
                    return metadata.ReadUInt64();
1,012✔
210
                case Il2CppTypeEnum.IL2CPP_TYPE_I8:
211
                    return metadata.ReadInt64();
422✔
212
                case Il2CppTypeEnum.IL2CPP_TYPE_R4:
213
                    return metadata.ReadSingle();
290✔
214
                case Il2CppTypeEnum.IL2CPP_TYPE_R8:
215
                    return metadata.ReadDouble();
112✔
216
                case Il2CppTypeEnum.IL2CPP_TYPE_STRING:
217
                    int len;
218
                    var lenLen = 4;
1,022✔
219
                    if (LibCpp2IlMain.MetadataVersion < 29)
1,022✔
220
                        len = metadata.ReadInt32();
650✔
221
                    else
222
                        len = metadata.ReadUnityCompressedIntAtRawAddr(pointer, false, out lenLen);
372✔
223
                    if (len > 1024 * 64)
1,022!
224
                        LibLogger.WarnNewline("[GetDefaultValue] String length is really large: " + len);
×
225
                    return Encoding.UTF8.GetString(metadata.ReadByteArrayAtRawAddressNoLock(pointer + lenLen, len));
1,022✔
226
                default:
227
                    return null;
×
228
            }
229
        }
230
        finally
231
        {
232
            metadata.ReleaseLock();
63,742✔
233
        }
63,742✔
234
    }
63,742✔
235

236
    public static Il2CppTypeReflectionData WrapType(Il2CppTypeDefinition what)
237
    {
238
        return new()
309,136✔
239
        {
309,136✔
240
            baseType = what, genericParams = [], isGenericType = false, isType = true,
309,136✔
241
        };
309,136✔
242
    }
243

244
    public static Il2CppTypeReflectionData GetTypeReflectionData(Il2CppType forWhat)
245
    {
246
        if (LibCpp2IlMain.Binary == null || LibCpp2IlMain.TheMetadata == null)
573,032!
247
            throw new Exception("Can't get type reflection data when not initialized. How did you even get the type?");
×
248

249
        switch (forWhat.Type)
573,032!
250
        {
251
            case Il2CppTypeEnum.IL2CPP_TYPE_OBJECT:
252
                return WrapType(LibCpp2IlReflection.GetType("Object", "System")!);
104,246✔
253
            case Il2CppTypeEnum.IL2CPP_TYPE_VOID:
254
                return WrapType(LibCpp2IlReflection.GetType("Void", "System")!);
×
255
            case Il2CppTypeEnum.IL2CPP_TYPE_BOOLEAN:
256
                return WrapType(LibCpp2IlReflection.GetType("Boolean", "System")!);
12,990✔
257
            case Il2CppTypeEnum.IL2CPP_TYPE_CHAR:
258
                return WrapType(LibCpp2IlReflection.GetType("Char", "System")!);
11,810✔
259
            case Il2CppTypeEnum.IL2CPP_TYPE_I1:
260
                return WrapType(LibCpp2IlReflection.GetType("SByte", "System")!);
7,970✔
261
            case Il2CppTypeEnum.IL2CPP_TYPE_U1:
262
                return WrapType(LibCpp2IlReflection.GetType("Byte", "System")!);
11,790✔
263
            case Il2CppTypeEnum.IL2CPP_TYPE_I2:
264
                return WrapType(LibCpp2IlReflection.GetType("Int16", "System")!);
7,970✔
265
            case Il2CppTypeEnum.IL2CPP_TYPE_U2:
266
                return WrapType(LibCpp2IlReflection.GetType("UInt16", "System")!);
7,900✔
267
            case Il2CppTypeEnum.IL2CPP_TYPE_I4:
268
                return WrapType(LibCpp2IlReflection.GetType("Int32", "System")!);
63,820✔
269
            case Il2CppTypeEnum.IL2CPP_TYPE_U4:
270
                return WrapType(LibCpp2IlReflection.GetType("UInt32", "System")!);
21,330✔
271
            case Il2CppTypeEnum.IL2CPP_TYPE_I:
272
                return WrapType(LibCpp2IlReflection.GetType("IntPtr", "System")!);
4,030✔
273
            case Il2CppTypeEnum.IL2CPP_TYPE_U:
274
                return WrapType(LibCpp2IlReflection.GetType("UIntPtr", "System")!);
3,910✔
275
            case Il2CppTypeEnum.IL2CPP_TYPE_I8:
276
                return WrapType(LibCpp2IlReflection.GetType("Int64", "System")!);
20,760✔
277
            case Il2CppTypeEnum.IL2CPP_TYPE_U8:
278
                return WrapType(LibCpp2IlReflection.GetType("UInt64", "System")!);
15,410✔
279
            case Il2CppTypeEnum.IL2CPP_TYPE_R4:
280
                return WrapType(LibCpp2IlReflection.GetType("Single", "System")!);
6,480✔
281
            case Il2CppTypeEnum.IL2CPP_TYPE_R8:
282
                return WrapType(LibCpp2IlReflection.GetType("Double", "System")!);
3,980✔
283
            case Il2CppTypeEnum.IL2CPP_TYPE_STRING:
284
                return WrapType(LibCpp2IlReflection.GetType("String", "System")!);
4,740✔
285
            case Il2CppTypeEnum.IL2CPP_TYPE_TYPEDBYREF:
286
                return WrapType(LibCpp2IlReflection.GetType("TypedReference", "System")!);
×
287
            case Il2CppTypeEnum.IL2CPP_TYPE_CLASS:
288
            case Il2CppTypeEnum.IL2CPP_TYPE_VALUETYPE:
289
                //"normal" type
290
                return new Il2CppTypeReflectionData
230,996✔
291
                {
230,996✔
292
                    baseType = LibCpp2IlMain.TheMetadata.typeDefs[forWhat.Data.ClassIndex], genericParams = [], isType = true, isGenericType = false,
230,996✔
293
                };
230,996✔
294
            case Il2CppTypeEnum.IL2CPP_TYPE_GENERICINST:
295
            {
296
                //Generic type
297
                var genericClass = LibCpp2IlMain.Binary.ReadReadableAtVirtualAddress<Il2CppGenericClass>(forWhat.Data.GenericClass);
31,640✔
298

299
                //CHANGED IN v27: typeDefinitionIndex is a ptr to the type in the file.
300
                Il2CppTypeDefinition typeDefinition;
301
                if (LibCpp2IlMain.MetadataVersion < 27f)
31,640!
302
                    typeDefinition = LibCpp2IlMain.TheMetadata.typeDefs[genericClass.TypeDefinitionIndex];
31,640✔
303
                else
304
                {
305
                    //This is slightly annoying, because we will have already read this type, but we have to re-read it. TODO FUTURE: Make a mapping of type definition addr => type def?
306
                    var type = LibCpp2IlMain.Binary.ReadReadableAtVirtualAddress<Il2CppType>((ulong)genericClass.TypeDefinitionIndex);
×
307
                    typeDefinition = LibCpp2IlMain.TheMetadata.typeDefs[type.Data.ClassIndex];
×
308
                }
309

310
                var genericInst = genericClass.Context.ClassInst;
31,640✔
311

312
                var genericParams = genericInst.Types
31,640✔
313
                    .Select(GetTypeReflectionData) //Recursive call here
31,640✔
314
                    .ToList();
31,640✔
315

316
                return new()
31,640✔
317
                {
31,640✔
318
                    baseType = typeDefinition, genericParams = genericParams.ToArray(), isType = true, isGenericType = true,
31,640✔
319
                };
31,640✔
320
            }
321
            case Il2CppTypeEnum.IL2CPP_TYPE_VAR:
322
            case Il2CppTypeEnum.IL2CPP_TYPE_MVAR:
323
            {
324
                var param = LibCpp2IlMain.TheMetadata.genericParameters[forWhat.Data.GenericParameterIndex];
×
325
                var genericName = LibCpp2IlMain.TheMetadata.GetStringFromIndex(param.nameIndex);
×
326

327
                return new()
×
328
                {
×
329
                    baseType = null,
×
330
                    genericParams = [],
×
331
                    isType = false,
×
332
                    isGenericType = false,
×
333
                    variableGenericParamName = genericName,
×
334
                    variableGenericParamIndex = forWhat.Data.GenericParameterIndex,
×
335
                };
×
336
            }
337
            case Il2CppTypeEnum.IL2CPP_TYPE_SZARRAY:
338
            {
339
                var oriType = LibCpp2IlMain.Binary.GetIl2CppTypeFromPointer(forWhat.Data.Type);
1,260✔
340
                return new()
1,260✔
341
                {
1,260✔
342
                    baseType = null,
1,260✔
343
                    arrayType = GetTypeReflectionData(oriType),
1,260✔
344
                    arrayRank = 1,
1,260✔
345
                    isArray = true,
1,260✔
346
                    isType = false,
1,260✔
347
                    isGenericType = false,
1,260✔
348
                    genericParams = []
1,260✔
349
                };
1,260✔
350
            }
351
            case Il2CppTypeEnum.IL2CPP_TYPE_ARRAY:
352
            {
353
                var arrayType = LibCpp2IlMain.Binary.ReadReadableAtVirtualAddress<Il2CppArrayType>(forWhat.Data.Array);
×
354
                var oriType = LibCpp2IlMain.Binary.GetIl2CppTypeFromPointer(arrayType.etype);
×
355
                return new()
×
356
                {
×
357
                    baseType = null,
×
358
                    arrayType = GetTypeReflectionData(oriType),
×
359
                    isArray = true,
×
360
                    isType = false,
×
361
                    arrayRank = arrayType.rank,
×
362
                    isGenericType = false,
×
363
                    genericParams = []
×
364
                };
×
365
            }
366
            case Il2CppTypeEnum.IL2CPP_TYPE_PTR:
367
            {
368
                var oriType = LibCpp2IlMain.Binary.GetIl2CppTypeFromPointer(forWhat.Data.Type);
×
369
                var ret = GetTypeReflectionData(oriType);
×
370
                ret.isPointer = true;
×
371
                return ret;
×
372
            }
373
        }
374

375
        throw new ArgumentException($"Unknown type {forWhat.Type}");
×
376
    }
377

378
    internal static IEnumerable<int> Range(int start, int count)
379
    {
380
        for (var i = start; i < start + count; i++)
×
381
        {
382
            yield return i;
×
383
        }
384
    }
×
385

386
    internal static void PopulateDeclaringAssemblyCache()
387
    {
388
        foreach (var assembly in LibCpp2IlMain.TheMetadata!.imageDefinitions)
1,304✔
389
        {
390
            foreach (var il2CppTypeDefinition in assembly.Types!)
89,408✔
391
            {
392
                il2CppTypeDefinition.DeclaringAssembly = assembly;
44,068✔
393
            }
394
        }
395
    }
16✔
396
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc