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

SamboyCoding / Cpp2IL / 15172433337

21 May 2025 08:57PM UTC coverage: 34.294% (+0.2%) from 34.062%
15172433337

Pull #462

github

web-flow
Merge 32601968e into 5807d2b6c
Pull Request #462: Support overriding member types

1801 of 6644 branches covered (27.11%)

Branch coverage included in aggregate %.

128 of 232 new or added lines in 35 files covered. (55.17%)

5 existing lines in 5 files now uncovered.

4199 of 10852 relevant lines covered (38.69%)

186271.78 hits per line

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

67.61
/LibCpp2IL/Metadata/Il2CppTypeDefinition.cs
1
using System;
2
using System.Linq;
3
using System.Reflection;
4
using LibCpp2IL.BinaryStructures;
5
using LibCpp2IL.Reflection;
6

7
namespace LibCpp2IL.Metadata;
8

9
public class Il2CppTypeDefinition : ReadableClass
10
{
11
    public int NameIndex;
12
    public int NamespaceIndex;
13
    [Version(Max = 24)] public int CustomAttributeIndex;
14
    public int ByvalTypeIndex;
15

16
    [Version(Max = 24.5f)] //Removed in v27 
17
    public int ByrefTypeIndex;
18

19
    public int DeclaringTypeIndex;
20
    public int ParentIndex;
21
    public int ElementTypeIndex; // we can probably remove this one. Only used for enums
22

23
    [Version(Max = 24.15f)] public int RgctxStartIndex;
24
    [Version(Max = 24.15f)] public int RgctxCount;
25

26
    public int GenericContainerIndex;
27

28
    public uint Flags;
29

30
    public int FirstFieldIdx;
31
    public int FirstMethodIdx;
32
    public int FirstEventId;
33
    public int FirstPropertyId;
34
    public int NestedTypesStart;
35
    public int InterfacesStart;
36
    public int VtableStart;
37
    public int InterfaceOffsetsStart;
38

39
    public ushort MethodCount;
40
    public ushort PropertyCount;
41
    public ushort FieldCount;
42
    public ushort EventCount;
43
    public ushort NestedTypeCount;
44
    public ushort VtableCount;
45
    public ushort InterfacesCount;
46
    public ushort InterfaceOffsetsCount;
47

48
    // bitfield to portably encode boolean values as single bits
49
    // 01 - valuetype;
50
    // 02 - enumtype;
51
    // 03 - has_finalize;
52
    // 04 - has_cctor;
53
    // 05 - is_blittable;
54
    // 06 - is_import_or_windows_runtime;
55
    // 07-10 - One of nine possible PackingSize values (0, 1, 2, 4, 8, 16, 32, 64, or 128)
56
    // 11 - PackingSize is default
57
    // 12 - ClassSize is default
58
    // 13-16 - One of nine possible PackingSize values (0, 1, 2, 4, 8, 16, 32, 64, or 128) - the specified packing size (even for explicit layouts)
59
    public uint Bitfield;
60
    public uint Token;
61

62
    public bool IsValueType => (Bitfield >> 0 & 0x1) == 1;
338,081✔
63
    public bool IsEnumType => (Bitfield >> 1 & 0x1) == 1;
14,423✔
64
    public bool HasFinalizer => (Bitfield >> 2 & 0x1) == 1;
×
65
    public bool HasCctor => (Bitfield >> 3 & 0x1) == 1;
×
66
    public bool IsBlittable => (Bitfield >> 4 & 0x1) == 1;
×
67
    public bool IsImportOrWindowsRuntime => (Bitfield >> 5 & 0x1) == 1;
×
68
    public uint PackingSize => ((Il2CppPackingSizeEnum)(Bitfield >> 6 & 0xF)).NumericalValue();
915✔
69
    public bool PackingSizeIsDefault => (Bitfield >> 10 & 0x1) == 1;
2,555✔
70
    public bool ClassSizeIsDefault => (Bitfield >> 11 & 0x1) == 1;
2,555✔
71
    public uint SpecifiedPackingSize => ((Il2CppPackingSizeEnum)(Bitfield >> 12 & 0xF)).NumericalValue();
×
72
    public bool IsByRefLike => (Bitfield >> 16 & 0x1) == 1;
×
73

74
    public TypeAttributes Attributes => (TypeAttributes)Flags;
17,593✔
75

76
    public Il2CppType RawType => LibCpp2IlMain.Binary!.AllTypes[ByvalTypeIndex];
141,662✔
77

78
    public Il2CppTypeDefinitionSizes RawSizes
79
    {
80
        get
81
        {
82
            var sizePtr = LibCpp2IlMain.Binary!.TypeDefinitionSizePointers[TypeIndex];
2,745✔
83
            return LibCpp2IlMain.Binary.ReadReadableAtVirtualAddress<Il2CppTypeDefinitionSizes>(sizePtr);
2,745✔
84
        }
85
    }
86

87
    public int Size => RawSizes.native_size;
2,745✔
88

89
    public Il2CppInterfaceOffset[] InterfaceOffsets
90
    {
91
        get
92
        {
93
            if (InterfaceOffsetsStart < 0) return [];
3,123!
94

95
            return LibCpp2IlMain.TheMetadata!.interfaceOffsets.SubArray(InterfaceOffsetsStart, InterfaceOffsetsCount);
3,123✔
96
        }
97
    }
98

99
    public MetadataUsage?[] VTable
100
    {
101
        get
102
        {
103
            if (VtableStart < 0) return [];
18,057✔
104

105
            return LibCpp2IlMain.TheMetadata!.VTableMethodIndices.SubArray(VtableStart, VtableCount).Select(v => MetadataUsage.DecodeMetadataUsage(v, 0)).ToArray();
341,869✔
106
        }
107
    }
108

109
    public int TypeIndex => LibCpp2IlReflection.GetTypeIndexFromType(this);
317,486✔
110

111
    public bool IsAbstract => ((TypeAttributes)Flags & TypeAttributes.Abstract) != 0;
×
112

UNCOV
113
    public bool IsInterface => ((TypeAttributes)Flags & TypeAttributes.Interface) != 0;
×
114

115
    private Il2CppImageDefinition? _cachedDeclaringAssembly;
116

117
    public Il2CppImageDefinition? DeclaringAssembly
118
    {
119
        get
120
        {
121
            if (_cachedDeclaringAssembly == null)
2,563,976✔
122
            {
123
                if (LibCpp2IlMain.TheMetadata == null) return null;
27!
124

125
                LibCpp2ILUtils.PopulateDeclaringAssemblyCache();
27✔
126
            }
127

128
            return _cachedDeclaringAssembly;
2,563,976✔
129
        }
130
        internal set => _cachedDeclaringAssembly = value;
76,254✔
131
    }
132

133
    public Il2CppCodeGenModule? CodeGenModule => LibCpp2IlMain.Binary == null ? null : LibCpp2IlMain.Binary.GetCodegenModuleByName(DeclaringAssembly!.Name!);
×
134

135
    public Il2CppRGCTXDefinition[] RgctXs
136
    {
137
        get
138
        {
139
            if (LibCpp2IlMain.MetadataVersion < 24.2f)
×
140
            {
141
                //No codegen modules here.
142
                return LibCpp2IlMain.TheMetadata!.RgctxDefinitions.Skip(RgctxStartIndex).Take(RgctxCount).ToArray();
×
143
            }
144

145
            var cgm = CodeGenModule;
×
146

147
            if (cgm == null)
×
148
                return [];
×
149

150
            var rangePair = cgm.RGCTXRanges.FirstOrDefault(r => r.token == Token);
×
151

152
            if (rangePair == null)
×
153
                return [];
×
154

155
            return LibCpp2IlMain.Binary!.GetRgctxDataForPair(cgm, rangePair);
×
156
        }
157
    }
158

159
    public ulong[] RgctxMethodPointers
160
    {
161
        get
162
        {
163
            var index = LibCpp2IlMain.Binary!.GetCodegenModuleIndexByName(DeclaringAssembly!.Name!);
×
164

165
            if (index < 0)
×
166
                return [];
×
167

168
            var pointers = LibCpp2IlMain.Binary!.GetCodegenModuleMethodPointers(index);
×
169

170
            return RgctXs
×
171
                .Where(r => r.type == Il2CppRGCTXDataType.IL2CPP_RGCTX_DATA_METHOD)
×
172
                .Select(r => pointers[r.MethodIndex])
×
173
                .ToArray();
×
174
        }
175
    }
176

177
    private string? _cachedNamespace;
178

179
    public string? Namespace
180
    {
181
        get
182
        {
183
            if (_cachedNamespace == null)
412,776✔
184
                _cachedNamespace = LibCpp2IlMain.TheMetadata == null ? null : LibCpp2IlMain.TheMetadata.GetStringFromIndex(NamespaceIndex);
62,636!
185

186
            return _cachedNamespace;
412,776✔
187
        }
188
    }
189

190
    private string? _cachedName;
191

192
    public string? Name
193
    {
194
        get
195
        {
196
            if (_cachedName == null)
757,673✔
197
                _cachedName = LibCpp2IlMain.TheMetadata == null ? null : LibCpp2IlMain.TheMetadata.GetStringFromIndex(NameIndex);
76,254!
198

199
            return _cachedName;
757,673✔
200
        }
201
    }
202

203
    public string? FullName
204
    {
205
        get
206
        {
207
            if (LibCpp2IlMain.TheMetadata == null)
171,910!
208
                return null;
×
209

210
            if (DeclaringType != null)
171,910✔
211
                return $"{DeclaringType.FullName}/{Name}";
42,948✔
212

213
            return $"{(string.IsNullOrEmpty(Namespace) ? "" : $"{Namespace}.")}{Name}";
128,962✔
214
        }
215
    }
216

217
    public Il2CppType? RawBaseType => ParentIndex == -1 ? null : LibCpp2IlMain.Binary!.GetType(ParentIndex);
449,149✔
218

219
    public Il2CppTypeReflectionData? BaseType => ParentIndex == -1 || LibCpp2IlMain.Binary == null ? null : LibCpp2ILUtils.GetTypeReflectionData(LibCpp2IlMain.Binary!.GetType(ParentIndex));
×
220

221
    public Il2CppFieldDefinition[]? Fields
222
    {
223
        get
224
        {
225
            if (LibCpp2IlMain.TheMetadata == null)
532,009!
226
                return null;
×
227

228
            if (FirstFieldIdx < 0 || FieldCount == 0)
532,009✔
229
                return [];
92,330✔
230

231
            var ret = new Il2CppFieldDefinition[FieldCount];
439,679✔
232

233
            Array.Copy(LibCpp2IlMain.TheMetadata.fieldDefs, FirstFieldIdx, ret, 0, FieldCount);
439,679✔
234

235
            return ret;
439,679✔
236
        }
237
    }
238

239
    public FieldAttributes[]? FieldAttributes => Fields?
376,575!
240
        .Select(f => f.typeIndex)
14,505,000✔
241
        .Select(idx => LibCpp2IlMain.Binary!.GetType(idx))
14,505,000✔
242
        .Select(t => (FieldAttributes)t.Attrs)
14,505,000✔
243
        .ToArray();
376,575✔
244

245
    public object?[]? FieldDefaults => Fields?
76,254!
246
        .Select((f, idx) => (f.FieldIndex, FieldAttributes![idx]))
300,321✔
247
        .Select(tuple => (tuple.Item2 & System.Reflection.FieldAttributes.HasDefault) != 0 ? LibCpp2IlMain.TheMetadata!.GetFieldDefaultValueFromIndex(tuple.FieldIndex) : null)
300,321✔
248
        .Select(def => def == null ? null : LibCpp2ILUtils.GetDefaultValue(def.dataIndex, def.typeIndex))
300,321✔
249
        .ToArray();
76,254✔
250

251
    public Il2CppFieldReflectionData[]? FieldInfos
252
    {
253
        get
254
        {
255
            var fields = Fields;
76,254✔
256
            var attributes = FieldAttributes;
76,254✔
257
            var defaults = FieldDefaults;
76,254✔
258

259
            if (fields == null || attributes == null || defaults == null)
76,254!
260
                return null;
×
261

262
            var ret = new Il2CppFieldReflectionData[FieldCount];
76,254✔
263
            for (var i = 0; i < FieldCount; i++)
753,150✔
264
            {
265
                ret[i] = new(
300,321✔
266
                    fields[i],
300,321✔
267
                    attributes![i],
300,321✔
268
                    defaults![i],
300,321✔
269
                    i,
300,321✔
270
                    LibCpp2IlMain.Binary!.GetFieldOffsetFromIndex(TypeIndex, i, fields[i].FieldIndex, IsValueType, attributes[i].HasFlag(System.Reflection.FieldAttributes.Static))
300,321✔
271
                );
300,321✔
272
            }
273

274
            return ret;
76,254✔
275
        }
276
    }
277

278
    public Il2CppMethodDefinition[]? Methods
279
    {
280
        get
281
        {
282
            if (LibCpp2IlMain.TheMetadata == null)
76,254!
283
                return null;
×
284

285
            if (FirstMethodIdx < 0 || MethodCount == 0)
76,254✔
286
                return [];
22,302✔
287

288
            var ret = new Il2CppMethodDefinition[MethodCount];
53,952✔
289

290
            Array.Copy(LibCpp2IlMain.TheMetadata.methodDefs, FirstMethodIdx, ret, 0, MethodCount);
53,952✔
291

292
            return ret;
53,952✔
293
        }
294
    }
295

296
    public Il2CppPropertyDefinition[]? Properties
297
    {
298
        get
299
        {
300
            if (LibCpp2IlMain.TheMetadata == null)
76,254!
301
                return null;
×
302

303
            if (FirstPropertyId < 0 || PropertyCount == 0)
76,254✔
304
                return [];
57,030✔
305

306
            var ret = new Il2CppPropertyDefinition[PropertyCount];
19,224✔
307

308
            Array.Copy(LibCpp2IlMain.TheMetadata.propertyDefs, FirstPropertyId, ret, 0, PropertyCount);
19,224✔
309

310
            return ret.Select(p =>
19,224✔
311
            {
19,224✔
312
                p.DeclaringType = this;
75,972✔
313
                return p;
75,972✔
314
            }).ToArray();
19,224✔
315
        }
316
    }
317

318
    public Il2CppEventDefinition[]? Events => LibCpp2IlMain.TheMetadata == null
76,254!
319
        ? null
76,254✔
320
        : LibCpp2IlMain.TheMetadata.eventDefs.Skip(FirstEventId).Take(EventCount).Select(e =>
76,254✔
321
        {
76,254✔
322
            e.DeclaringType = this;
345✔
323
            return e;
345✔
324
        }).ToArray();
76,254✔
325

326
    public Il2CppTypeDefinition[]? NestedTypes => LibCpp2IlMain.TheMetadata == null ? null : LibCpp2IlMain.TheMetadata.nestedTypeIndices.Skip(NestedTypesStart).Take(NestedTypeCount).Select(idx => LibCpp2IlMain.TheMetadata.typeDefs[idx]).ToArray();
23,205!
327

328
    public Il2CppType[] RawInterfaces => LibCpp2IlMain.TheMetadata == null || LibCpp2IlMain.Binary == null
14,420!
329
        ? []
14,420✔
330
        : LibCpp2IlMain.TheMetadata.interfaceIndices
14,420✔
331
            .Skip(InterfacesStart)
14,420✔
332
            .Take(InterfacesCount)
14,420✔
333
            .Select(idx => LibCpp2IlMain.Binary.GetType(idx))
4,695✔
334
            .ToArray();
14,420✔
335

336
    public Il2CppTypeReflectionData[]? Interfaces => LibCpp2IlMain.TheMetadata == null || LibCpp2IlMain.Binary == null
×
337
        ? null
×
338
        : RawInterfaces
×
339
            .Select(LibCpp2ILUtils.GetTypeReflectionData)
×
340
            .ToArray();
×
341

342
    public Il2CppTypeDefinition? DeclaringType => LibCpp2IlMain.TheMetadata == null || LibCpp2IlMain.Binary == null || DeclaringTypeIndex < 0 ? null : LibCpp2IlMain.TheMetadata.typeDefs[LibCpp2IlMain.Binary.GetType(DeclaringTypeIndex).Data.ClassIndex];
214,858✔
343
    
344
    public Il2CppTypeDefinition? ElementType => LibCpp2IlMain.TheMetadata == null || LibCpp2IlMain.Binary == null || ElementTypeIndex < 0 ? null : LibCpp2IlMain.TheMetadata.typeDefs[LibCpp2IlMain.Binary.GetType(ElementTypeIndex).Data.ClassIndex];
×
345

346
    public Il2CppGenericContainer? GenericContainer => GenericContainerIndex < 0 ? null : LibCpp2IlMain.TheMetadata?.genericContainers[GenericContainerIndex];
17,833!
347

348
    public Il2CppType EnumUnderlyingType => IsEnumType ? LibCpp2IlMain.Binary!.GetType(ElementTypeIndex) : throw new InvalidOperationException("Cannot get the underlying type of a non-enum type.");
3!
349

350
    public override string? ToString()
351
    {
352
        if (LibCpp2IlMain.TheMetadata == null)
×
353
            return base.ToString();
×
354

355
        return $"Il2CppTypeDefinition[namespace='{Namespace}', name='{Name}', parentType={BaseType?.ToString() ?? "null"}, assembly={DeclaringAssembly}]";
×
356
    }
357

358
    public override void Read(ClassReadingBinaryReader reader)
359
    {
360
        NameIndex = reader.ReadInt32();
141,662✔
361
        NamespaceIndex = reader.ReadInt32();
141,662✔
362

363
        if (IsAtMost(24f))
141,662!
364
            CustomAttributeIndex = reader.ReadInt32();
×
365

366
        ByvalTypeIndex = reader.ReadInt32();
141,662✔
367

368
        if (IsLessThan(27f))
141,662✔
369
            ByrefTypeIndex = reader.ReadInt32();
102,407✔
370

371
        DeclaringTypeIndex = reader.ReadInt32();
141,662✔
372
        ParentIndex = reader.ReadInt32();
141,662✔
373
        ElementTypeIndex = reader.ReadInt32();
141,662✔
374

375
        if (IsAtMost(24.15f))
141,662✔
376
        {
377
            RgctxStartIndex = reader.ReadInt32();
17,051✔
378
            RgctxCount = reader.ReadInt32();
17,051✔
379
        }
380

381
        GenericContainerIndex = reader.ReadInt32();
141,662✔
382
        Flags = reader.ReadUInt32();
141,662✔
383

384
        FirstFieldIdx = reader.ReadInt32();
141,662✔
385
        FirstMethodIdx = reader.ReadInt32();
141,662✔
386
        FirstEventId = reader.ReadInt32();
141,662✔
387
        FirstPropertyId = reader.ReadInt32();
141,662✔
388
        NestedTypesStart = reader.ReadInt32();
141,662✔
389
        InterfacesStart = reader.ReadInt32();
141,662✔
390
        VtableStart = reader.ReadInt32();
141,662✔
391
        InterfaceOffsetsStart = reader.ReadInt32();
141,662✔
392

393
        MethodCount = reader.ReadUInt16();
141,662✔
394
        PropertyCount = reader.ReadUInt16();
141,662✔
395
        FieldCount = reader.ReadUInt16();
141,662✔
396
        EventCount = reader.ReadUInt16();
141,662✔
397
        NestedTypeCount = reader.ReadUInt16();
141,662✔
398
        VtableCount = reader.ReadUInt16();
141,662✔
399
        InterfacesCount = reader.ReadUInt16();
141,662✔
400
        InterfaceOffsetsCount = reader.ReadUInt16();
141,662✔
401

402
        Bitfield = reader.ReadUInt32();
141,662✔
403
        Token = reader.ReadUInt32();
141,662✔
404
    }
141,662✔
405
}
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