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

SamboyCoding / Cpp2IL / 20488062770

24 Dec 2025 02:19PM UTC coverage: 34.361% (-0.01%) from 34.375%
20488062770

push

github

SamboyCoding
Refactor ResolveContextForMethod to match code style

1811 of 6624 branches covered (27.34%)

Branch coverage included in aggregate %.

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

14 existing lines in 1 file now uncovered.

4208 of 10893 relevant lines covered (38.63%)

201355.63 hits per line

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

68.79
/Cpp2IL.Core/Model/Contexts/ApplicationAnalysisContext.cs
1
using System;
2
using System.Collections.Generic;
3
using System.Diagnostics;
4
using System.Diagnostics.CodeAnalysis;
5
using System.Linq;
6
using System.Reflection;
7
using AssetRipper.Primitives;
8
using Cpp2IL.Core.Api;
9
using Cpp2IL.Core.Exceptions;
10
using Cpp2IL.Core.Il2CppApiFunctions;
11
using Cpp2IL.Core.Logging;
12
using Cpp2IL.Core.Utils;
13
using LibCpp2IL;
14
using LibCpp2IL.Metadata;
15

16
namespace Cpp2IL.Core.Model.Contexts;
17

18
/// <summary>
19
/// Top-level class to represent an individual il2cpp application that has been loaded into cpp2il.
20
/// </summary>
21
public class ApplicationAnalysisContext : ContextWithDataStorage
22
{
23
    /// <summary>
24
    /// The IL2CPP binary file this application was loaded from
25
    /// </summary>
26
    public Il2CppBinary Binary;
27

28
    /// <summary>
29
    /// The IL2CPP global-metadata file this application was loaded from.
30
    /// </summary>
31
    public Il2CppMetadata Metadata;
32

33
    /// <summary>
34
    /// The version of the IL2CPP metadata file this application was loaded from.
35
    /// </summary>
36
    public float MetadataVersion => Metadata.MetadataVersion;
1,620,035✔
37
    
38
    /// <summary>
39
    /// The Unity version this application was compiled with.
40
    /// </summary>
UNCOV
41
    public UnityVersion UnityVersion => Metadata.UnityVersion;
×
42

43
    /// <summary>
44
    /// The instruction set helper class associated with the instruction set that this application was compiled with.
45
    /// </summary>
46
    public Cpp2IlInstructionSet InstructionSet;
47

48
    /// <summary>
49
    /// Contains references to some commonly-used System types.
50
    /// </summary>
51
    public SystemTypesContext SystemTypes;
52

53
    /// <summary>
54
    /// All the managed assemblies contained within the metadata file.
55
    /// </summary>
56
    public readonly List<AssemblyAnalysisContext> Assemblies = [];
31✔
57

58
    /// <summary>
59
    /// A dictionary of all the managed assemblies, by their name.
60
    /// </summary>
61
    public readonly Dictionary<string, AssemblyAnalysisContext> AssembliesByName = new();
31✔
62

63
    /// <summary>
64
    /// A dictionary of method pointers to the corresponding method, which may or may not be generic.
65
    /// </summary>
66
    public readonly Dictionary<ulong, List<MethodAnalysisContext>> MethodsByAddress = new();
31✔
67

68
    /// <summary>
69
    /// A dictionary of all the generic method variants to their corresponding analysis contexts.
70
    /// </summary>
71
    public readonly Dictionary<Cpp2IlMethodRef, ConcreteGenericMethodAnalysisContext> ConcreteGenericMethodsByRef = new();
31✔
72

73
    /// <summary>
74
    /// Key Function Addresses for the binary file. Populated on-demand
75
    /// </summary>
76
    private BaseKeyFunctionAddresses? _keyFunctionAddresses;
77

78
    /// <summary>
79
    /// True if this ApplicationAnalysisContext has finished initialization of all of its child contexts, else false.
80
    /// </summary>
81
    public bool HasFinishedInitializing { get; private set; }
31✔
82

83
    private readonly Dictionary<Il2CppImageDefinition, AssemblyAnalysisContext> AssembliesByImageDefinition = new();
31✔
84

85
    public ApplicationAnalysisContext(Il2CppBinary binary, Il2CppMetadata metadata)
31✔
86
    {
87
        Binary = binary;
31✔
88
        Metadata = metadata;
31✔
89

90
        try
91
        {
92
            InstructionSet = InstructionSetRegistry.GetInstructionSet(binary.InstructionSetId);
31✔
93
        }
31✔
UNCOV
94
        catch (Exception)
×
95
        {
UNCOV
96
            throw new InstructionSetHandlerNotRegisteredException(binary.InstructionSetId);
×
97
        }
98

99
        Logger.VerboseNewline("\tUsing instruction set handler: " + InstructionSet.GetType().FullName);
31✔
100

101
        foreach (var assemblyDefinition in Metadata.AssemblyDefinitions)
2,594✔
102
        {
103
            Logger.VerboseNewline($"\tProcessing assembly: {assemblyDefinition.AssemblyName.Name}...");
1,266✔
104
            var aac = new AssemblyAnalysisContext(assemblyDefinition, this);
1,266✔
105
            Assemblies.Add(aac);
1,266✔
106
            AssembliesByName[assemblyDefinition.AssemblyName.Name] = aac;
1,266✔
107
            AssembliesByImageDefinition[assemblyDefinition.Image] = aac;
1,266✔
108
        }
109

110
        SystemTypes = new(this);
31✔
111
        
112
        MiscUtils.InitFunctionStarts(this);
31✔
113

114
        PopulateMethodsByAddressTable();
31✔
115

116
        HasFinishedInitializing = true;
31✔
117
    }
31✔
118

119
    /// <summary>
120
    /// Populates the <see cref="MethodsByAddress"/> dictionary with all the methods in the application, including concrete generic ones.
121
    /// </summary>
122
    private void PopulateMethodsByAddressTable()
123
    {
124
        Assemblies.SelectMany(a => a.Types).SelectMany(t => t.Methods).ToList().ForEach(m =>
89,255✔
125
        {
31✔
126
            m.EnsureRawBytes();
509,604✔
127
            var ptr = InstructionSet.GetPointerForMethod(m);
509,604✔
128

31✔
129
            if (!MethodsByAddress.ContainsKey(ptr))
509,604✔
130
                MethodsByAddress.Add(ptr, []);
405,815✔
131

31✔
132
            MethodsByAddress[ptr].Add(m);
509,604✔
133
        });
509,635✔
134

135
        Logger.VerboseNewline("\tProcessing concrete generic methods...");
31✔
136
        foreach (var methodRef in Binary.ConcreteGenericMethods.Values.SelectMany(v => v))
745,635✔
137
        {
138
#if !DEBUG
139
            try
140
            {
141
#endif
142
            var gm = new ConcreteGenericMethodAnalysisContext(methodRef, this);
353,916✔
143

144
            var ptr = InstructionSet.GetPointerForMethod(gm);
353,916✔
145

146
            if (!MethodsByAddress.ContainsKey(ptr))
353,916✔
147
                MethodsByAddress[ptr] = [];
118,950✔
148

149
            MethodsByAddress[ptr].Add(gm);
353,916✔
150
            ConcreteGenericMethodsByRef[methodRef] = gm;
353,916✔
151
#if !DEBUG
152
            }
353,916✔
UNCOV
153
            catch (Exception e)
×
154
            {
UNCOV
155
                throw new("Failed to process concrete generic method: " + methodRef, e);
×
156
            }
157
#endif
158
        }
159
    }
31✔
160

161
    /// <summary>
162
    /// Finds an assembly by its name and returns the analysis context for it.
163
    /// </summary>
164
    /// <param name="name">The name of the assembly (without any extension)</param>
165
    /// <returns>An assembly analysis context if one can be found which matches the given name, else null.</returns>
166
    public AssemblyAnalysisContext? GetAssemblyByName(string name)
167
    {
168
        if (name.Length >= 4 && name[^4] == '.' && name[^3] == 'd')
37!
169
            //Trim .dll extension
UNCOV
170
            name = name[..^4];
×
171
        else if (name.Length >= 6 && name[^6] == '.' && name[^5] == 'w')
37!
172
            //Trim .winmd extension
UNCOV
173
            name = name[..^6];
×
174

175
        return AssembliesByName[name];
37✔
176
    }
177

178
    public AssemblyAnalysisContext? ResolveContextForAssembly(Il2CppImageDefinition? imageDefinition)
179
    {
180
        return imageDefinition is not null
353,916!
181
            ? AssembliesByImageDefinition[imageDefinition]
353,916✔
182
            : null;
353,916✔
183
    }
184

185
    public AssemblyAnalysisContext? ResolveContextForAssembly(Il2CppAssemblyDefinition? assemblyDefinition)
186
    {
UNCOV
187
        return ResolveContextForAssembly(assemblyDefinition?.Image);
×
188
    }
189

190
    public TypeAnalysisContext? ResolveContextForType(Il2CppTypeDefinition? typeDefinition)
191
    {
192
        return typeDefinition is not null
2,713,272!
193
            ? AssembliesByImageDefinition[typeDefinition.DeclaringAssembly!].GetTypeByDefinition(typeDefinition)
2,713,272✔
194
            : null;
2,713,272✔
195
    }
196

197
    public MethodAnalysisContext? ResolveContextForMethod(Il2CppMethodDefinition? methodDefinition)
198
    {
199
        return ResolveContextForType(methodDefinition?.DeclaringType)?.Methods.FirstOrDefault(m => m.Definition == methodDefinition);
4,118,570!
200
    }
201

202
    [return: NotNullIfNotNull(nameof(methodReference))]
203
    public ConcreteGenericMethodAnalysisContext? ResolveContextForMethod(Cpp2IlMethodRef? methodReference)
204
    {
NEW
205
        if(methodReference == null)
×
NEW
206
            return null;
×
207
            
NEW
208
        return ConcreteGenericMethodsByRef.TryGetValue(methodReference, out var context) ? context : new(methodReference, this);
×
209
    }
210

211
    public FieldAnalysisContext? ResolveContextForField(Il2CppFieldDefinition? field)
212
    {
213
        return ResolveContextForType(field?.DeclaringType)?.Fields.FirstOrDefault(f => f.BackingData?.Field == field);
2!
214
    }
215

216
    public EventAnalysisContext? ResolveContextForEvent(Il2CppEventDefinition? eventDefinition)
217
    {
218
        return ResolveContextForType(eventDefinition?.DeclaringType)?.Events.FirstOrDefault(e => e.Definition == eventDefinition);
2!
219
    }
220

221
    public PropertyAnalysisContext? ResolveContextForProperty(Il2CppPropertyDefinition? propertyDefinition)
222
    {
223
        return ResolveContextForType(propertyDefinition?.DeclaringType)?.Properties.FirstOrDefault(p => p.Definition == propertyDefinition);
2!
224
    }
225

226
    public GenericParameterTypeAnalysisContext? ResolveContextForGenericParameter(Il2CppGenericParameter? genericParameter)
227
    {
228
        if (genericParameter is null)
194,668!
UNCOV
229
            return null;
×
230

231
        if (genericParameter.Owner.TypeOwner is { } typeOwner)
194,668✔
232
        {
233
            return ResolveContextForType(typeOwner)?.GenericParameters[genericParameter.genericParameterIndexInOwner];
137,990!
234
        }
235
        else
236
        {
237
            Debug.Assert(genericParameter.Owner.MethodOwner is not null);
238
            return ResolveContextForMethod(genericParameter.Owner.MethodOwner)?.GenericParameters[genericParameter.genericParameterIndexInOwner];
56,678!
239
        }
240
    }
241

242
    public BaseKeyFunctionAddresses GetOrCreateKeyFunctionAddresses()
243
    {
UNCOV
244
        lock (InstructionSet)
×
245
        {
UNCOV
246
            if (_keyFunctionAddresses == null)
×
UNCOV
247
                (_keyFunctionAddresses = InstructionSet.CreateKeyFunctionAddressesInstance()).Find(this);
×
248

UNCOV
249
            return _keyFunctionAddresses;
×
250
        }
UNCOV
251
    }
×
252

253
    public MultiAssemblyInjectedType InjectTypeIntoAllAssemblies(string ns, string name, TypeAnalysisContext? baseType, TypeAttributes typeAttributes = TypeAttributes.Public | TypeAttributes.Class | TypeAttributes.Sealed)
254
    {
255
        var types = Assemblies.Select(a => (InjectedTypeAnalysisContext)a.InjectType(ns, name, baseType, typeAttributes)).ToArray();
344✔
256

257
        return new(types);
8✔
258
    }
259

260
    public InjectedAssemblyAnalysisContext InjectAssembly(
261
        string name,
262
        Version? version = null,
263
        uint hashAlgorithm = 0,
264
        uint flags = 0,
265
        string? culture = null,
266
        byte[]? publicKeyToken = null,
267
        byte[]? publicKey = null)
268
    {
269
        var assembly = new InjectedAssemblyAnalysisContext(name, this, version, hashAlgorithm, flags, culture, publicKeyToken, publicKey);
1✔
270
        Assemblies.Add(assembly);
1✔
271
        AssembliesByName.Add(name, assembly);
1✔
272
        return assembly;
1✔
273
    }
274

275
    public IEnumerable<TypeAnalysisContext> AllTypes => Assemblies.SelectMany(a => a.Types);
280✔
276
}
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