-
Notifications
You must be signed in to change notification settings - Fork 19
Expand file tree
/
Copy pathAssemblyImage.cs
More file actions
102 lines (83 loc) · 4.07 KB
/
AssemblyImage.cs
File metadata and controls
102 lines (83 loc) · 4.07 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
namespace HackF5.UnitySpy.Detail
{
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using HackF5.UnitySpy.ProcessFacade;
using JetBrains.Annotations;
/// <summary>
/// Represents an unmanaged _MonoImage instance in a Mono process. This object describes a managed assembly.
/// The .NET equivalent is <see cref="System.Reflection.Assembly"/>.
/// See: _MonoImage in https://github.com/Unity-Technologies/mono/blob/unity-master/mono/metadata/metadata-internals.h.
/// </summary>
[PublicAPI]
public class AssemblyImage : MemoryObject, IAssemblyImage
{
private readonly Dictionary<string, TypeDefinition> typeDefinitionsByFullName =
new Dictionary<string, TypeDefinition>();
private readonly ConcurrentDictionary<IntPtr, TypeDefinition> typeDefinitionsByAddress;
public AssemblyImage(UnityProcessFacade process, IntPtr address)
: base(null, address)
{
this.Process = process;
this.typeDefinitionsByAddress = this.CreateTypeDefinitions();
foreach (var definition in this.TypeDefinitions)
{
definition.Init();
}
foreach (var definition in this.TypeDefinitions)
{
if (definition.FullName.Contains("`"))
{
// ignore generic classes as they have name clashes. in order to make them unique these it would be
// necessary to examine the information held in TypeInfo.Data. see
// ProcessFacade.ReadManagedGenericObject for moral support.
continue;
}
if (!this.typeDefinitionsByFullName.ContainsKey(definition.FullName))
{
this.typeDefinitionsByFullName.Add(definition.FullName, definition);
}
}
}
IEnumerable<ITypeDefinition> IAssemblyImage.TypeDefinitions => this.TypeDefinitions;
public IEnumerable<TypeDefinition> TypeDefinitions =>
this.typeDefinitionsByAddress.ToArray().Select(k => k.Value);
public override AssemblyImage Image => this;
public override UnityProcessFacade Process { get; }
public dynamic this[string fullTypeName] => this.GetTypeDefinition(fullTypeName);
ITypeDefinition IAssemblyImage.GetTypeDefinition(string fullTypeName) => this.GetTypeDefinition(fullTypeName);
public TypeDefinition GetTypeDefinition(string fullTypeName) =>
this.typeDefinitionsByFullName.TryGetValue(fullTypeName, out var d) ? d : default;
public TypeDefinition GetTypeDefinition(IntPtr address)
{
if (address == IntPtr.Zero)
{
return default;
}
return this.typeDefinitionsByAddress.GetOrAdd(
address,
key => new TypeDefinition(this, key));
}
private ConcurrentDictionary<IntPtr, TypeDefinition> CreateTypeDefinitions()
{
var definitions = new ConcurrentDictionary<IntPtr, TypeDefinition>();
int classCache = this.Process.MonoLibraryOffsets.ImageClassCache;
var classCacheSize = this.ReadUInt32(/*classCache + this.Process.MonoLibraryOffsets.HashTableSize*/1256);
var classCacheTableArray = this.ReadPtr(1264/*classCache + this.Process.MonoLibraryOffsets.HashTableTable*/);
for (var tableItem = 0;
tableItem < (classCacheSize * this.Process.SizeOfPtr);
tableItem += this.Process.SizeOfPtr)
{
for (var definition = this.Process.ReadPtr(classCacheTableArray + tableItem);
definition != IntPtr.Zero;
definition = this.Process.ReadPtr(definition + /*this.Process.MonoLibraryOffsets.TypeDefinitionNextClassCache*/264))
{
definitions.GetOrAdd(definition, new TypeDefinition(this, definition));
}
}
return definitions;
}
}
}