diff --git a/Il2CppInspector/Il2CppModel.cs b/Il2CppInspector/Il2CppModel.cs index 162ff65..31c5c2e 100644 --- a/Il2CppInspector/Il2CppModel.cs +++ b/Il2CppInspector/Il2CppModel.cs @@ -5,6 +5,7 @@ */ using System; +using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Reflection; @@ -26,7 +27,7 @@ namespace Il2CppInspector.Reflection public TypeInfo[] TypesByUsageIndex { get; } // List of type usages that are initialized via pointers in the image - public Dictionary TypesByVirtualAddress { get; } = new Dictionary(); + public ConcurrentDictionary TypesByVirtualAddress { get; } = new ConcurrentDictionary(); // Every type public IEnumerable Types => new IEnumerable[] { TypesByDefinitionIndex, TypesByUsageIndex, TypesByVirtualAddress.Values }.SelectMany(t => t); @@ -35,7 +36,7 @@ namespace Il2CppInspector.Reflection public MethodBase[] MethodsByDefinitionIndex { get; } // List of all generated CustomAttributeData objects by their index into AttributeTypeIndices - public Dictionary AttributesByIndices { get; } = new Dictionary(); + public ConcurrentDictionary AttributesByIndices { get; } = new ConcurrentDictionary(); public Il2CppModel(Il2CppInspector package) { Package = package; @@ -114,7 +115,7 @@ namespace Il2CppInspector.Reflection var type = Package.BinaryImage.ReadMappedObject(ptr); var newUsage = getNewTypeUsage(type, MemberTypes.NestedType); - TypesByVirtualAddress.Add(ptr, newUsage); + TypesByVirtualAddress.TryAdd(ptr, newUsage); return newUsage; } diff --git a/Il2CppInspector/Reflection/CustomAttributeData.cs b/Il2CppInspector/Reflection/CustomAttributeData.cs index 95438a5..b7a7d9a 100644 --- a/Il2CppInspector/Reflection/CustomAttributeData.cs +++ b/Il2CppInspector/Reflection/CustomAttributeData.cs @@ -49,14 +49,20 @@ namespace Il2CppInspector.Reflection attribute = new CustomAttributeData { Index = customAttributeIndex, AttributeType = asm.Model.GetTypeFromUsage(typeIndex) }; - asm.Model.AttributesByIndices.Add(i, attribute); + asm.Model.AttributesByIndices.TryAdd(i, attribute); yield return attribute; } } - private static IList getCustomAttributes(Assembly asm, uint token, int customAttributeIndex) - => getCustomAttributes(asm, asm.Model.GetCustomAttributeIndex(asm, token, customAttributeIndex)).ToList(); - + private static readonly object gcaLock = new object(); + private static IList getCustomAttributes(Assembly asm, uint token, int customAttributeIndex) { + // Force the generation of the collection to be thread-safe + // Convert the result into a list for thread-safe enumeration + lock (gcaLock) { + return getCustomAttributes(asm, asm.Model.GetCustomAttributeIndex(asm, token, customAttributeIndex)).ToList(); + } + } + public static IList GetCustomAttributes(Assembly asm) => getCustomAttributes(asm, asm.AssemblyDefinition.token, asm.AssemblyDefinition.customAttributeIndex); public static IList GetCustomAttributes(EventInfo evt) => getCustomAttributes(evt.Assembly, evt.Definition.token, evt.Definition.customAttributeIndex); public static IList GetCustomAttributes(FieldInfo field) => getCustomAttributes(field.Assembly, field.Definition.token, field.Definition.customAttributeIndex);