├── .gitignore
├── Directory.Build.props
├── Mono.Reflection.csproj
├── Mono.Reflection.nuspec
├── Mono.Reflection.sln
├── Mono.Reflection
├── AssemblyInfo.cs
├── BackingFieldResolver.cs
├── ByteBuffer.cs
├── Disassembler.cs
├── ILPattern.cs
├── Image.cs
├── Instruction.cs
└── MethodBodyReader.cs
├── README.md
├── Test
├── .gitignore
├── Mono.Reflection.Tests.csproj
├── Mono.Reflection
│ ├── AssemblyInfo.cs
│ ├── BackingFieldResolverTest.cs
│ ├── BaseReflectionTest.cs
│ ├── DisassemblerTest.cs
│ ├── Formatter.cs
│ └── ImageTest.cs
├── libs
│ └── nunit-2.6.2
│ │ ├── license.txt
│ │ ├── nunit.core.dll
│ │ ├── nunit.core.interfaces.dll
│ │ └── nunit.framework.dll
├── target.dll
└── target.il
└── mono.snk
/.gitignore:
--------------------------------------------------------------------------------
1 | bin
2 | obj
3 | *.suo
4 | *.user
5 | *.nupkg
6 | *ReSharper*
7 |
--------------------------------------------------------------------------------
/Directory.Build.props:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jbevain/mono.reflection/6f2c84705f0bf05baef3d7977a8c4b69843ed402/Directory.Build.props
--------------------------------------------------------------------------------
/Mono.Reflection.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | netstandard2.0;net40
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Mono.Reflection.nuspec:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Mono.Reflection
5 | 2.0.0.0
6 | Mono.Reflection
7 | Jb Evain
8 | Jb Evain
9 | http://opensource.org/licenses/mit-license.php
10 | false
11 | http://github.com/jbevain/mono.reflection/
12 | Complement for System.Reflection, including an IL disassembler.
13 | en-US
14 | assembly assemblies module modules il cil msil bytecode reflection disassembler
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/Mono.Reflection.sln:
--------------------------------------------------------------------------------
1 | Microsoft Visual Studio Solution File, Format Version 11.00
2 | # Visual Studio 2010
3 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mono.Reflection", "Mono.Reflection.csproj", "{97B010AB-0756-46DC-B75A-7A6C4F6FF28D}"
4 | EndProject
5 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mono.Reflection.Tests", "Test\Mono.Reflection.Tests.csproj", "{51FCE249-1187-46EC-96A6-E507889E700D}"
6 | EndProject
7 | Global
8 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
9 | Debug|Any CPU = Debug|Any CPU
10 | Release|Any CPU = Release|Any CPU
11 | EndGlobalSection
12 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
13 | {97B010AB-0756-46DC-B75A-7A6C4F6FF28D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
14 | {97B010AB-0756-46DC-B75A-7A6C4F6FF28D}.Debug|Any CPU.Build.0 = Debug|Any CPU
15 | {97B010AB-0756-46DC-B75A-7A6C4F6FF28D}.Release|Any CPU.ActiveCfg = Release|Any CPU
16 | {97B010AB-0756-46DC-B75A-7A6C4F6FF28D}.Release|Any CPU.Build.0 = Release|Any CPU
17 | {51FCE249-1187-46EC-96A6-E507889E700D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
18 | {51FCE249-1187-46EC-96A6-E507889E700D}.Debug|Any CPU.Build.0 = Debug|Any CPU
19 | {51FCE249-1187-46EC-96A6-E507889E700D}.Release|Any CPU.ActiveCfg = Release|Any CPU
20 | {51FCE249-1187-46EC-96A6-E507889E700D}.Release|Any CPU.Build.0 = Release|Any CPU
21 | EndGlobalSection
22 | GlobalSection(SolutionProperties) = preSolution
23 | HideSolutionNode = FALSE
24 | EndGlobalSection
25 | EndGlobal
26 |
--------------------------------------------------------------------------------
/Mono.Reflection/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | [assembly: AssemblyTitle ("Mono.Reflection")]
6 | [assembly: AssemblyDescription ("")]
7 | [assembly: AssemblyConfiguration ("")]
8 | [assembly: AssemblyCompany ("Novell, Inc.")]
9 | [assembly: AssemblyProduct ("Mono.Reflection")]
10 | [assembly: AssemblyCopyright ("Copyright © Novell, Inc. 2009 - 2010")]
11 | [assembly: AssemblyTrademark ("")]
12 | [assembly: AssemblyCulture ("")]
13 |
14 | [assembly: ComVisible (false)]
15 |
16 | [assembly: Guid ("61b023e8-6ba6-4fa3-8026-3841abdba125")]
17 |
18 | [assembly: AssemblyVersion ("2.0.0.0")]
19 | [assembly: AssemblyFileVersion ("2.0.0.0")]
20 |
--------------------------------------------------------------------------------
/Mono.Reflection/BackingFieldResolver.cs:
--------------------------------------------------------------------------------
1 | //
2 | // BackingFieldResolver.cs
3 | //
4 | // Author:
5 | // Jb Evain (jbevain@novell.com)
6 | //
7 | // (C) 2009 - 2010 Novell, Inc. (http://www.novell.com)
8 | //
9 | // Permission is hereby granted, free of charge, to any person obtaining
10 | // a copy of this software and associated documentation files (the
11 | // "Software"), to deal in the Software without restriction, including
12 | // without limitation the rights to use, copy, modify, merge, publish,
13 | // distribute, sublicense, and/or sell copies of the Software, and to
14 | // permit persons to whom the Software is furnished to do so, subject to
15 | // the following conditions:
16 | //
17 | // The above copyright notice and this permission notice shall be
18 | // included in all copies or substantial portions of the Software.
19 | //
20 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 | //
28 |
29 | using System;
30 | using System.Reflection;
31 | using System.Reflection.Emit;
32 |
33 | namespace Mono.Reflection {
34 |
35 | public static class BackingFieldResolver {
36 |
37 | class FieldPattern : ILPattern {
38 |
39 | public static object FieldKey = new object ();
40 |
41 | ILPattern pattern;
42 |
43 | public FieldPattern (ILPattern pattern)
44 | {
45 | this.pattern = pattern;
46 | }
47 |
48 | public override void Match (MatchContext context)
49 | {
50 | pattern.Match (context);
51 | if (!context.success)
52 | return;
53 |
54 | var match = GetLastMatchingInstruction (context);
55 | var field = (FieldInfo) match.Operand;
56 | context.AddData (FieldKey, field);
57 | }
58 | }
59 |
60 | static ILPattern Field (OpCode opcode)
61 | {
62 | return new FieldPattern (ILPattern.OpCode (opcode));
63 | }
64 |
65 | static ILPattern GetterPattern =
66 | ILPattern.Sequence (
67 | ILPattern.Optional (OpCodes.Nop),
68 | ILPattern.Either (
69 | Field (OpCodes.Ldsfld),
70 | ILPattern.Sequence (
71 | ILPattern.OpCode (OpCodes.Ldarg_0),
72 | Field (OpCodes.Ldfld))),
73 | ILPattern.Optional (
74 | ILPattern.Sequence (
75 | ILPattern.OpCode (OpCodes.Stloc_0),
76 | ILPattern.OpCode (OpCodes.Br_S),
77 | ILPattern.OpCode (OpCodes.Ldloc_0))),
78 | ILPattern.Optional(ILPattern.OpCode(OpCodes.Br_S)),
79 | ILPattern.OpCode (OpCodes.Ret));
80 |
81 | static ILPattern SetterPattern =
82 | ILPattern.Sequence (
83 | ILPattern.Optional (OpCodes.Nop),
84 | ILPattern.OpCode (OpCodes.Ldarg_0),
85 | ILPattern.Either (
86 | Field (OpCodes.Stsfld),
87 | ILPattern.Sequence (
88 | ILPattern.OpCode (OpCodes.Ldarg_1),
89 | Field (OpCodes.Stfld))),
90 | ILPattern.OpCode (OpCodes.Ret));
91 |
92 | static FieldInfo GetBackingField (MethodInfo method, ILPattern pattern)
93 | {
94 | var result = ILPattern.Match (method, pattern);
95 | if (!result.success)
96 | throw new ArgumentException ();
97 |
98 | object value;
99 | if (!result.TryGetData (FieldPattern.FieldKey, out value))
100 | throw new InvalidOperationException ();
101 |
102 | return (FieldInfo) value;
103 | }
104 |
105 | public static FieldInfo GetBackingField (this PropertyInfo self)
106 | {
107 | if (self == null)
108 | throw new ArgumentNullException ("self");
109 |
110 | var getter = self.GetGetMethod (true);
111 | if (getter != null)
112 | return GetBackingField (getter, GetterPattern);
113 |
114 | var setter = self.GetSetMethod (true);
115 | if (setter != null)
116 | return GetBackingField (setter, SetterPattern);
117 |
118 | throw new ArgumentException ();
119 | }
120 | }
121 | }
122 |
--------------------------------------------------------------------------------
/Mono.Reflection/ByteBuffer.cs:
--------------------------------------------------------------------------------
1 | //
2 | // ByteBuffer.cs
3 | //
4 | // Author:
5 | // Jb Evain (jbevain@novell.com)
6 | //
7 | // (C) 2009 - 2010 Novell, Inc. (http://www.novell.com)
8 | //
9 | // Permission is hereby granted, free of charge, to any person obtaining
10 | // a copy of this software and associated documentation files (the
11 | // "Software"), to deal in the Software without restriction, including
12 | // without limitation the rights to use, copy, modify, merge, publish,
13 | // distribute, sublicense, and/or sell copies of the Software, and to
14 | // permit persons to whom the Software is furnished to do so, subject to
15 | // the following conditions:
16 | //
17 | // The above copyright notice and this permission notice shall be
18 | // included in all copies or substantial portions of the Software.
19 | //
20 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 | //
28 |
29 | using System;
30 |
31 | namespace Mono.Reflection {
32 |
33 | class ByteBuffer {
34 |
35 | internal byte [] buffer;
36 | internal int position;
37 |
38 | public ByteBuffer (byte [] buffer)
39 | {
40 | this.buffer = buffer;
41 | }
42 |
43 | public byte ReadByte ()
44 | {
45 | CheckCanRead (1);
46 | return buffer [position++];
47 | }
48 |
49 | public byte [] ReadBytes (int length)
50 | {
51 | CheckCanRead (length);
52 | var value = new byte [length];
53 | Buffer.BlockCopy (buffer, position, value, 0, length);
54 | position += length;
55 | return value;
56 | }
57 |
58 | public short ReadInt16 ()
59 | {
60 | CheckCanRead (2);
61 | short value = (short) (buffer [position]
62 | | (buffer [position + 1] << 8));
63 | position += 2;
64 | return value;
65 | }
66 |
67 | public int ReadInt32 ()
68 | {
69 | CheckCanRead (4);
70 | int value = buffer [position]
71 | | (buffer [position + 1] << 8)
72 | | (buffer [position + 2] << 16)
73 | | (buffer [position + 3] << 24);
74 | position += 4;
75 | return value;
76 | }
77 |
78 | public long ReadInt64 ()
79 | {
80 | CheckCanRead (8);
81 | uint low = (uint) (buffer [position]
82 | | (buffer [position + 1] << 8)
83 | | (buffer [position + 2] << 16)
84 | | (buffer [position + 3] << 24));
85 |
86 | uint high = (uint) (buffer [position + 4]
87 | | (buffer [position + 5] << 8)
88 | | (buffer [position + 6] << 16)
89 | | (buffer [position + 7] << 24));
90 |
91 | long value = (((long) high) << 32) | low;
92 | position += 8;
93 | return value;
94 | }
95 |
96 | public float ReadSingle ()
97 | {
98 | if (!BitConverter.IsLittleEndian) {
99 | var bytes = ReadBytes (4);
100 | Array.Reverse (bytes);
101 | return BitConverter.ToSingle (bytes, 0);
102 | }
103 |
104 | CheckCanRead (4);
105 | float value = BitConverter.ToSingle (buffer, position);
106 | position += 4;
107 | return value;
108 | }
109 |
110 | public double ReadDouble ()
111 | {
112 | if (!BitConverter.IsLittleEndian) {
113 | var bytes = ReadBytes (8);
114 | Array.Reverse (bytes);
115 | return BitConverter.ToDouble (bytes, 0);
116 | }
117 |
118 | CheckCanRead (8);
119 | double value = BitConverter.ToDouble (buffer, position);
120 | position += 8;
121 | return value;
122 | }
123 |
124 | void CheckCanRead (int count)
125 | {
126 | if (position + count > buffer.Length)
127 | throw new ArgumentOutOfRangeException ();
128 | }
129 | }
130 | }
131 |
--------------------------------------------------------------------------------
/Mono.Reflection/Disassembler.cs:
--------------------------------------------------------------------------------
1 | //
2 | // Disassembler.cs
3 | //
4 | // Author:
5 | // Jb Evain (jbevain@novell.com)
6 | //
7 | // (C) 2009 - 2010 Novell, Inc. (http://www.novell.com)
8 | //
9 | // Permission is hereby granted, free of charge, to any person obtaining
10 | // a copy of this software and associated documentation files (the
11 | // "Software"), to deal in the Software without restriction, including
12 | // without limitation the rights to use, copy, modify, merge, publish,
13 | // distribute, sublicense, and/or sell copies of the Software, and to
14 | // permit persons to whom the Software is furnished to do so, subject to
15 | // the following conditions:
16 | //
17 | // The above copyright notice and this permission notice shall be
18 | // included in all copies or substantial portions of the Software.
19 | //
20 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 | //
28 |
29 | using System;
30 | using System.Collections.Generic;
31 | using System.Reflection;
32 |
33 | namespace Mono.Reflection {
34 |
35 | public static class Disassembler {
36 |
37 | public static IList GetInstructions (this MethodBase self)
38 | {
39 | if (self == null)
40 | throw new ArgumentNullException ("self");
41 |
42 | return MethodBodyReader.GetInstructions (self).AsReadOnly ();
43 | }
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/Mono.Reflection/ILPattern.cs:
--------------------------------------------------------------------------------
1 | //
2 | // ILPattern.cs
3 | //
4 | // Author:
5 | // Jb Evain (jbevain@novell.com)
6 | //
7 | // (C) 2009 - 2010 Novell, Inc. (http://www.novell.com)
8 | //
9 | // Permission is hereby granted, free of charge, to any person obtaining
10 | // a copy of this software and associated documentation files (the
11 | // "Software"), to deal in the Software without restriction, including
12 | // without limitation the rights to use, copy, modify, merge, publish,
13 | // distribute, sublicense, and/or sell copies of the Software, and to
14 | // permit persons to whom the Software is furnished to do so, subject to
15 | // the following conditions:
16 | //
17 | // The above copyright notice and this permission notice shall be
18 | // included in all copies or substantial portions of the Software.
19 | //
20 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 | // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 | // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 | //
28 |
29 | using System;
30 | using System.Collections.Generic;
31 | using System.Linq;
32 | using System.Reflection;
33 | using System.Reflection.Emit;
34 |
35 | namespace Mono.Reflection {
36 |
37 | public abstract class ILPattern {
38 |
39 | public static ILPattern Optional (OpCode opcode)
40 | {
41 | return Optional (OpCode (opcode));
42 | }
43 |
44 | public static ILPattern Optional (params OpCode [] opcodes)
45 | {
46 | return Optional (Sequence (opcodes.Select (opcode => OpCode (opcode)).ToArray ()));
47 | }
48 |
49 | public static ILPattern Optional (ILPattern pattern)
50 | {
51 | return new OptionalPattern (pattern);
52 | }
53 |
54 | class OptionalPattern : ILPattern {
55 |
56 | ILPattern pattern;
57 |
58 | public OptionalPattern (ILPattern optional)
59 | {
60 | this.pattern = optional;
61 | }
62 |
63 | public override void Match (MatchContext context)
64 | {
65 | pattern.TryMatch (context);
66 | }
67 | }
68 |
69 | public static ILPattern Sequence (params ILPattern [] patterns)
70 | {
71 | return new SequencePattern (patterns);
72 | }
73 |
74 | class SequencePattern : ILPattern {
75 |
76 | ILPattern [] patterns;
77 |
78 | public SequencePattern (ILPattern [] patterns)
79 | {
80 | this.patterns = patterns;
81 | }
82 |
83 | public override void Match (MatchContext context)
84 | {
85 | foreach (var pattern in patterns) {
86 | pattern.Match (context);
87 |
88 | if (!context.success)
89 | break;
90 | }
91 | }
92 | }
93 |
94 | public static ILPattern OpCode (OpCode opcode)
95 | {
96 | return new OpCodePattern (opcode);
97 | }
98 |
99 | class OpCodePattern : ILPattern {
100 |
101 | OpCode opcode;
102 |
103 | public OpCodePattern (OpCode opcode)
104 | {
105 | this.opcode = opcode;
106 | }
107 |
108 | public override void Match (MatchContext context)
109 | {
110 | if (context.instruction == null) {
111 | context.success = false;
112 | return;
113 | }
114 |
115 | context.success = context.instruction.OpCode == opcode;
116 | context.Advance ();
117 | }
118 | }
119 |
120 | public static ILPattern Either (ILPattern a, ILPattern b)
121 | {
122 | return new EitherPattern (a, b);
123 | }
124 |
125 | class EitherPattern : ILPattern {
126 |
127 | ILPattern a;
128 | ILPattern b;
129 |
130 | public EitherPattern (ILPattern a, ILPattern b)
131 | {
132 | this.a = a;
133 | this.b = b;
134 | }
135 |
136 | public override void Match (MatchContext context)
137 | {
138 | if (!a.TryMatch (context))
139 | b.Match (context);
140 | }
141 | }
142 |
143 | public abstract void Match (MatchContext context);
144 |
145 | protected static Instruction GetLastMatchingInstruction (MatchContext context)
146 | {
147 | if (context.instruction == null)
148 | return null;
149 |
150 | return context.instruction.Previous;
151 | }
152 |
153 | public bool TryMatch (MatchContext context)
154 | {
155 | var instruction = context.instruction;
156 | Match (context);
157 |
158 | if (context.success)
159 | return true;
160 |
161 | context.Reset (instruction);
162 | return false;
163 | }
164 |
165 | public static MatchContext Match (MethodBase method, ILPattern pattern)
166 | {
167 | if (method == null)
168 | throw new ArgumentNullException ("method");
169 | if (pattern == null)
170 | throw new ArgumentNullException ("pattern");
171 |
172 | var instructions = method.GetInstructions ();
173 | if (instructions.Count == 0)
174 | throw new ArgumentException ();
175 |
176 | var context = new MatchContext (instructions [0]);
177 | pattern.Match (context);
178 | return context;
179 | }
180 | }
181 |
182 | public sealed class MatchContext {
183 |
184 | internal Instruction instruction;
185 | internal bool success;
186 |
187 | Dictionary