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

SamboyCoding / Cpp2IL / 15141315610

20 May 2025 03:13PM UTC coverage: 34.062% (+0.02%) from 34.047%
15141315610

push

github

SamboyCoding
Lib: Fix double-getting type reflection data in metadata usages

1773 of 6620 branches covered (26.78%)

Branch coverage included in aggregate %.

0 of 2 new or added lines in 1 file covered. (0.0%)

17 existing lines in 1 file now uncovered.

4163 of 10807 relevant lines covered (38.52%)

185902.5 hits per line

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

25.4
/LibCpp2IL/MetadataUsage.cs
1
using System;
2
using LibCpp2IL.BinaryStructures;
3
using LibCpp2IL.Metadata;
4
using LibCpp2IL.Reflection;
5

6
namespace LibCpp2IL;
7

8
public class MetadataUsage(MetadataUsageType type, ulong offset, uint value)
582,501✔
9
{
10
    public readonly MetadataUsageType Type = type;
582,501✔
11
    public readonly ulong Offset = offset;
582,501✔
12

13
    private string? _cachedName;
14

15
    private Il2CppType? _cachedType;
16
    private Il2CppTypeReflectionData? _cachedTypeReflectionData;
17

18
    private Il2CppMethodDefinition? _cachedMethod;
19

20
    private Il2CppFieldDefinition? _cachedField;
21

22
    private string? _cachedLiteral;
23

24
    private Cpp2IlMethodRef? _cachedGenericMethod;
25

26
    public uint RawValue => value;
×
27

28
    public object Value =>
29
        Type switch
×
30
        {
×
31
            MetadataUsageType.Type or MetadataUsageType.TypeInfo => AsType(),
×
32
            MetadataUsageType.MethodDef => AsMethod(),
×
33
            MetadataUsageType.FieldInfo => AsField(),
×
34
            MetadataUsageType.StringLiteral => AsLiteral(),
×
35
            MetadataUsageType.MethodRef => AsGenericMethodRef(),
×
36
            _ => throw new ArgumentOutOfRangeException()
×
37
        };
×
38

39
    public bool IsValid =>
40
        Type switch
×
41
        {
×
42
            MetadataUsageType.Type or MetadataUsageType.TypeInfo => value < LibCpp2IlMain.Binary!.NumTypes,
×
43
            MetadataUsageType.MethodDef => value < LibCpp2IlMain.TheMetadata!.methodDefs.Length,
×
44
            MetadataUsageType.FieldInfo => value < LibCpp2IlMain.TheMetadata!.fieldRefs.Length,
×
45
            MetadataUsageType.StringLiteral => value < LibCpp2IlMain.TheMetadata!.stringLiterals.Length,
×
46
            MetadataUsageType.MethodRef => value < LibCpp2IlMain.Binary!.AllGenericMethodSpecs.Length,
×
47
            _ => false
×
48
        };
×
49

50
    public Il2CppTypeReflectionData AsType()
51
    {
52
        if (_cachedTypeReflectionData == null)
×
53
        {
54
            switch (Type)
×
55
            {
56
                case MetadataUsageType.Type:
57
                case MetadataUsageType.TypeInfo:
58
                    try
59
                    {
60
                        _cachedType = LibCpp2IlMain.Binary!.GetType((int)value);
×
NEW
61
                        _cachedTypeReflectionData = LibCpp2ILUtils.GetTypeReflectionData(_cachedType);
×
NEW
62
                        _cachedName = _cachedTypeReflectionData?.ToString();
×
63
                    }
×
64
                    catch (Exception e)
×
65
                    {
66
                        throw new Exception($"Failed to convert this metadata usage to a type, but it is of type {Type}, with a value of {value} (0x{value:X}). There are {LibCpp2IlMain.Binary!.NumTypes} types", e);
×
67
                    }
68

69
                    break;
70
                default:
71
                    throw new Exception($"Cannot cast metadata usage of kind {Type} to a Type");
×
72
            }
73
        }
74

75
        return _cachedTypeReflectionData!;
×
76
    }
77

78
    public Il2CppMethodDefinition AsMethod()
79
    {
80
        if (_cachedMethod == null)
318,193✔
81
        {
82
            switch (Type)
318,193!
83
            {
84
                case MetadataUsageType.MethodDef:
85
                    _cachedMethod = LibCpp2IlMain.TheMetadata!.methodDefs[value];
318,193✔
86
                    _cachedName = _cachedMethod.GlobalKey;
318,193✔
87
                    break;
318,193✔
88
                default:
89
                    throw new Exception($"Cannot cast metadata usage of kind {Type} to a Method Def");
×
90
            }
91
        }
92

93
        return _cachedMethod!;
318,193✔
94
    }
95

96
    public Il2CppFieldDefinition AsField()
97
    {
98
        if (_cachedField == null)
×
99
        {
100
            switch (Type)
×
101
            {
102
                case MetadataUsageType.FieldInfo:
103
                    var fieldRef = LibCpp2IlMain.TheMetadata!.fieldRefs[value];
×
104
                    _cachedField = fieldRef.FieldDefinition;
×
105
                    _cachedName = fieldRef.DeclaringTypeDefinition!.FullName + "." + _cachedField!.Name;
×
106
                    break;
×
107
                default:
108
                    throw new Exception($"Cannot cast metadata usage of kind {Type} to a Field");
×
109
            }
110
        }
111

112
        return _cachedField;
×
113
    }
114

115
    public string AsLiteral()
116
    {
117
        if (_cachedLiteral == null)
×
118
        {
119
            switch (Type)
×
120
            {
121
                case MetadataUsageType.StringLiteral:
122
                    _cachedName = _cachedLiteral = LibCpp2IlMain.TheMetadata!.GetStringLiteralFromIndex(value);
×
123
                    break;
×
124
                default:
125
                    throw new Exception($"Cannot cast metadata usage of kind {Type} to a String Literal");
×
126
            }
127
        }
128

129
        return _cachedLiteral;
×
130
    }
131

132
    public Cpp2IlMethodRef AsGenericMethodRef()
133
    {
134
        if (_cachedGenericMethod == null)
×
135
        {
136
            switch (Type)
×
137
            {
138
                case MetadataUsageType.MethodRef:
139
                    var methodSpec = LibCpp2IlMain.Binary!.GetMethodSpec((int)value);
×
140

141
                    _cachedGenericMethod = new Cpp2IlMethodRef(methodSpec);
×
142
                    _cachedName = _cachedGenericMethod.ToString();
×
143
                    break;
×
144
                default:
145
                    throw new Exception($"Cannot cast metadata usage of kind {Type} to a Generic Method Ref");
×
146
            }
147
        }
148

149
        return _cachedGenericMethod;
×
150
    }
151

152
    public override string ToString()
153
    {
154
        return $"Metadata Usage {{type={Type}, Value={Value}}}";
×
155
    }
156

157

158
    public static MetadataUsage? DecodeMetadataUsage(ulong encoded, ulong address)
159
    {
160
        var encodedType = encoded & 0xE000_0000;
323,832✔
161
        var type = (MetadataUsageType)(encodedType >> 29);
323,832✔
162
        if (type <= MetadataUsageType.MethodRef && type >= MetadataUsageType.TypeInfo)
323,832✔
163
        {
164
            var index = (uint)(encoded & 0x1FFF_FFFF);
320,967✔
165

166
            if (LibCpp2IlMain.MetadataVersion >= 27)
320,967!
167
                index >>= 1;
×
168

169
            if (type is MetadataUsageType.Type or MetadataUsageType.TypeInfo && index > LibCpp2IlMain.Binary!.NumTypes)
320,967!
170
                return null;
×
171

172
            if (type == MetadataUsageType.MethodDef && index > LibCpp2IlMain.TheMetadata!.methodDefs.Length)
320,967!
173
                return null;
×
174

175

176
            return new MetadataUsage(type, address, index);
320,967✔
177
        }
178

179
        return null;
2,865✔
180
    }
181
}
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

© 2026 Coveralls, Inc