├── .gitignore ├── ILDebugging.Decoder ├── DynamicMethodILProvider.cs ├── DynamicScopeTokenResolver.cs ├── FormatProvider.cs ├── ILDebugging.Decoder.csproj ├── ILInstruction.cs ├── ILProvider.cs ├── ILReader.cs ├── ILReaderFactory.cs ├── Properties │ └── AssemblyInfo.cs ├── README.txt ├── ReadableILStringVisitor.cs └── TokenResolver.cs ├── ILDebugging.Monitor ├── ILDebugging.Monitor.csproj ├── ILMonitorForm.Designer.cs ├── ILMonitorForm.cs ├── ILMonitorForm.resx ├── IncrementalData.cs ├── MiniBrowser.Designer.cs ├── MiniBrowser.cs ├── MiniBrowser.resx ├── MonitorHelper.cs ├── Program.cs ├── Properties │ ├── AssemblyInfo.cs │ ├── Resources.Designer.cs │ ├── Resources.resx │ ├── Settings.Designer.cs │ └── Settings.settings ├── Resources │ └── XSLT.txt └── app.config ├── ILDebugging.Sample ├── ILDebugging.Sample.csproj ├── Program.cs ├── Properties │ └── AssemblyInfo.cs └── app.config ├── ILDebugging.Visualizer ├── ILDebugging.Visualizer.csproj ├── MethodBodyInfo.cs ├── MethodBodyNoVisualizer.cs ├── MethodBodyObjectSource.cs ├── MethodBodyViewer.Designer.cs ├── MethodBodyViewer.cs ├── MethodBodyViewer.resx ├── MethodBodyVisualizer.cs ├── Properties │ ├── AssemblyInfo.cs │ ├── Resource.Designer.cs │ ├── Resource.resx │ ├── Settings.Designer.cs │ └── Settings.settings └── Resources │ └── app.ico ├── ILDebugging.sln ├── Images ├── il-monitor.png ├── il-visualizer.png └── launching-visualizer.png └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | Debug/ 2 | Release/ 3 | bin/ 4 | obj/ 5 | _ReSharper*/ 6 | *.suo 7 | *.user 8 | *.ReSharper 9 | *.DotSettings.user 10 | *.nupkg 11 | packages/ 12 | artifacts/ 13 | node_modules/ 14 | .vs/ 15 | .bowerrc 16 | project.lock.json 17 | /.idea/ 18 | -------------------------------------------------------------------------------- /ILDebugging.Decoder/DynamicMethodILProvider.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | using System.Reflection.Emit; 4 | 5 | namespace ILDebugging.Decoder 6 | { 7 | public class DynamicMethodILProvider : IILProvider 8 | { 9 | private static readonly FieldInfo s_fiLen = typeof(ILGenerator).GetField("m_length", BindingFlags.NonPublic | BindingFlags.Instance); 10 | private static readonly FieldInfo s_fiStream = typeof(ILGenerator).GetField("m_ILStream", BindingFlags.NonPublic | BindingFlags.Instance); 11 | private static readonly MethodInfo s_miBakeByteArray = typeof(ILGenerator).GetMethod("BakeByteArray", BindingFlags.NonPublic | BindingFlags.Instance); 12 | 13 | private readonly DynamicMethod m_method; 14 | private byte[] m_byteArray; 15 | 16 | public DynamicMethodILProvider(DynamicMethod method) 17 | { 18 | m_method = method; 19 | } 20 | 21 | public byte[] GetByteArray() 22 | { 23 | if (m_byteArray == null) 24 | { 25 | var ilgen = m_method.GetILGenerator(); 26 | try 27 | { 28 | m_byteArray = (byte[])s_miBakeByteArray.Invoke(ilgen, null) ?? new byte[0]; 29 | } 30 | catch (TargetInvocationException) 31 | { 32 | var length = (int)s_fiLen.GetValue(ilgen); 33 | m_byteArray = new byte[length]; 34 | Array.Copy((byte[])s_fiStream.GetValue(ilgen), m_byteArray, length); 35 | } 36 | } 37 | return m_byteArray; 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /ILDebugging.Decoder/DynamicScopeTokenResolver.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | using System.Reflection; 4 | using System.Reflection.Emit; 5 | 6 | namespace ILDebugging.Decoder 7 | { 8 | internal class DynamicScopeTokenResolver : ITokenResolver 9 | { 10 | #region Static stuff 11 | 12 | private static readonly PropertyInfo s_indexer; 13 | private static readonly FieldInfo s_scopeFi; 14 | 15 | private static readonly Type s_genMethodInfoType; 16 | private static readonly FieldInfo s_genmethFi1; 17 | private static readonly FieldInfo s_genmethFi2; 18 | 19 | private static readonly Type s_varArgMethodType; 20 | private static readonly FieldInfo s_varargFi1; 21 | 22 | private static readonly Type s_genFieldInfoType; 23 | private static readonly FieldInfo s_genfieldFi1; 24 | private static readonly FieldInfo s_genfieldFi2; 25 | 26 | static DynamicScopeTokenResolver() 27 | { 28 | const BindingFlags flags = BindingFlags.NonPublic | BindingFlags.Instance; 29 | 30 | s_indexer = Type.GetType("System.Reflection.Emit.DynamicScope").GetProperty("Item", flags); 31 | s_scopeFi = Type.GetType("System.Reflection.Emit.DynamicILGenerator").GetField("m_scope", flags); 32 | 33 | s_varArgMethodType = Type.GetType("System.Reflection.Emit.VarArgMethod"); 34 | s_varargFi1 = s_varArgMethodType.GetField("m_method", flags); 35 | 36 | s_genMethodInfoType = Type.GetType("System.Reflection.Emit.GenericMethodInfo"); 37 | s_genmethFi1 = s_genMethodInfoType.GetField("m_methodHandle", flags); 38 | s_genmethFi2 = s_genMethodInfoType.GetField("m_context", flags); 39 | 40 | s_genFieldInfoType = Type.GetType("System.Reflection.Emit.GenericFieldInfo", throwOnError: false); 41 | 42 | s_genfieldFi1 = s_genFieldInfoType?.GetField("m_fieldHandle", flags); 43 | s_genfieldFi2 = s_genFieldInfoType?.GetField("m_context", flags); 44 | } 45 | 46 | #endregion 47 | 48 | private readonly object m_scope; 49 | 50 | private object this[int token] => s_indexer.GetValue(m_scope, new object[] {token}); 51 | 52 | public DynamicScopeTokenResolver(DynamicMethod dm) 53 | { 54 | m_scope = s_scopeFi.GetValue(dm.GetILGenerator()); 55 | } 56 | 57 | public string AsString(int token) 58 | { 59 | return this[token] as string; 60 | } 61 | 62 | public FieldInfo AsField(int token) 63 | { 64 | if (this[token] is RuntimeFieldHandle) 65 | return FieldInfo.GetFieldFromHandle((RuntimeFieldHandle)this[token]); 66 | 67 | if (this[token].GetType() == s_genFieldInfoType) 68 | { 69 | return FieldInfo.GetFieldFromHandle( 70 | (RuntimeFieldHandle)s_genfieldFi1.GetValue(this[token]), 71 | (RuntimeTypeHandle)s_genfieldFi2.GetValue(this[token])); 72 | } 73 | 74 | Debug.Assert(false, $"unexpected type: {this[token].GetType()}"); 75 | return null; 76 | } 77 | 78 | public Type AsType(int token) 79 | { 80 | return Type.GetTypeFromHandle((RuntimeTypeHandle)this[token]); 81 | } 82 | 83 | public MethodBase AsMethod(int token) 84 | { 85 | var dynamicMethod = this[token] as DynamicMethod; 86 | if (dynamicMethod != null) 87 | return dynamicMethod; 88 | 89 | if (this[token] is RuntimeMethodHandle) 90 | return MethodBase.GetMethodFromHandle((RuntimeMethodHandle)this[token]); 91 | 92 | if (this[token].GetType() == s_genMethodInfoType) 93 | return MethodBase.GetMethodFromHandle( 94 | (RuntimeMethodHandle)s_genmethFi1.GetValue(this[token]), 95 | (RuntimeTypeHandle)s_genmethFi2.GetValue(this[token])); 96 | 97 | if (this[token].GetType() == s_varArgMethodType) 98 | return (MethodInfo)s_varargFi1.GetValue(this[token]); 99 | 100 | Debug.Assert(false, $"unexpected type: {this[token].GetType()}"); 101 | return null; 102 | } 103 | 104 | public MemberInfo AsMember(int token) 105 | { 106 | if ((token & 0x02000000) == 0x02000000) 107 | return AsType(token); 108 | if ((token & 0x06000000) == 0x06000000) 109 | return AsMethod(token); 110 | if ((token & 0x04000000) == 0x04000000) 111 | return AsField(token); 112 | 113 | Debug.Assert(false, $"unexpected token type: {token:x8}"); 114 | return null; 115 | } 116 | 117 | public byte[] AsSignature(int token) 118 | { 119 | return this[token] as byte[]; 120 | } 121 | } 122 | } -------------------------------------------------------------------------------- /ILDebugging.Decoder/FormatProvider.cs: -------------------------------------------------------------------------------- 1 | using System.Text; 2 | 3 | namespace ILDebugging.Decoder 4 | { 5 | public interface IFormatProvider 6 | { 7 | string Int32ToHex(int int32); 8 | string Int16ToHex(int int16); 9 | string Int8ToHex(int int8); 10 | string Argument(int ordinal); 11 | string EscapedString(string str); 12 | string Label(int offset); 13 | string MultipleLabels(int[] offsets); 14 | string SigByteArrayToString(byte[] sig); 15 | } 16 | 17 | public sealed class DefaultFormatProvider : IFormatProvider 18 | { 19 | private DefaultFormatProvider() 20 | { 21 | } 22 | 23 | public static DefaultFormatProvider Instance { get; } = new DefaultFormatProvider(); 24 | 25 | public string Int32ToHex(int int32) => int32.ToString("X8"); 26 | public string Int16ToHex(int int16) => int16.ToString("X4"); 27 | public string Int8ToHex(int int8) => int8.ToString("X2"); 28 | public string Argument(int ordinal) => $"V_{ordinal}"; 29 | public string Label(int offset) => $"IL_{offset:x4}"; 30 | 31 | public string MultipleLabels(int[] offsets) 32 | { 33 | var sb = new StringBuilder(); 34 | var length = offsets.Length; 35 | for (var i = 0; i < length; i++) 36 | { 37 | sb.AppendFormat(i == 0 ? "(" : ", "); 38 | sb.Append(Label(offsets[i])); 39 | } 40 | sb.AppendFormat(")"); 41 | return sb.ToString(); 42 | } 43 | 44 | public string EscapedString(string str) 45 | { 46 | var length = str.Length; 47 | var sb = new StringBuilder(length*2); 48 | 49 | sb.Append('"'); 50 | for (var i = 0; i < length; i++) 51 | { 52 | var ch = str[i]; 53 | switch (ch) 54 | { 55 | case '\t': 56 | sb.Append("\\t"); 57 | break; 58 | case '\n': 59 | sb.Append("\\n"); 60 | break; 61 | case '\r': 62 | sb.Append("\\r"); 63 | break; 64 | case '\"': 65 | sb.Append("\\\""); 66 | break; 67 | case '\\': 68 | sb.Append("\\"); 69 | break; 70 | default: 71 | if (ch < 0x20 || ch >= 0x7f) 72 | sb.AppendFormat("\\u{0:x4}", (int)ch); 73 | else 74 | sb.Append(ch); 75 | break; 76 | } 77 | } 78 | sb.Append('"'); 79 | 80 | return sb.ToString(); 81 | } 82 | 83 | public string SigByteArrayToString(byte[] sig) 84 | { 85 | var sb = new StringBuilder(); 86 | var length = sig.Length; 87 | for (var i = 0; i < length; i++) 88 | { 89 | sb.AppendFormat(i == 0 ? "SIG [" : " "); 90 | sb.Append(Int8ToHex(sig[i])); 91 | } 92 | sb.AppendFormat("]"); 93 | return sb.ToString(); 94 | } 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /ILDebugging.Decoder/ILDebugging.Decoder.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Debug 5 | AnyCPU 6 | 8.0.50727 7 | 2.0 8 | {3B40E8C3-C4E8-4085-9F82-F64308F3791C} 9 | Library 10 | Properties 11 | ILDebugging.Decoder 12 | ILDebugging.Decoder 13 | 14 | 15 | 16 | 17 | 3.5 18 | v4.0 19 | 20 | 21 | 22 | true 23 | full 24 | false 25 | bin\Debug\ 26 | DEBUG;TRACE 27 | prompt 28 | 4 29 | 30 | 31 | pdbonly 32 | true 33 | bin\Release\ 34 | TRACE 35 | prompt 36 | 4 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 64 | -------------------------------------------------------------------------------- /ILDebugging.Decoder/ILInstruction.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | using System.Reflection.Emit; 4 | 5 | namespace ILDebugging.Decoder 6 | { 7 | public abstract class ILInstruction 8 | { 9 | internal ILInstruction(int offset, OpCode opCode) 10 | { 11 | Offset = offset; 12 | OpCode = opCode; 13 | } 14 | 15 | public int Offset { get; } 16 | public OpCode OpCode { get; } 17 | 18 | public abstract void Accept(ILInstructionVisitor visitor); 19 | } 20 | 21 | public class InlineNoneInstruction : ILInstruction 22 | { 23 | internal InlineNoneInstruction(int offset, OpCode opCode) 24 | : base(offset, opCode) 25 | { 26 | } 27 | 28 | public override void Accept(ILInstructionVisitor visitor) 29 | { 30 | visitor.VisitInlineNoneInstruction(this); 31 | } 32 | } 33 | 34 | public class InlineBrTargetInstruction : ILInstruction 35 | { 36 | internal InlineBrTargetInstruction(int offset, OpCode opCode, int delta) 37 | : base(offset, opCode) 38 | { 39 | Delta = delta; 40 | } 41 | 42 | public int Delta { get; } 43 | 44 | public int TargetOffset => Offset + Delta + 1 + 4; 45 | 46 | public override void Accept(ILInstructionVisitor visitor) 47 | { 48 | visitor.VisitInlineBrTargetInstruction(this); 49 | } 50 | } 51 | 52 | public class ShortInlineBrTargetInstruction : ILInstruction 53 | { 54 | internal ShortInlineBrTargetInstruction(int offset, OpCode opCode, sbyte delta) 55 | : base(offset, opCode) 56 | { 57 | Delta = delta; 58 | } 59 | 60 | public sbyte Delta { get; } 61 | 62 | public int TargetOffset => Offset + Delta + 1 + 1; 63 | 64 | public override void Accept(ILInstructionVisitor visitor) 65 | { 66 | visitor.VisitShortInlineBrTargetInstruction(this); 67 | } 68 | } 69 | 70 | public class InlineSwitchInstruction : ILInstruction 71 | { 72 | private readonly int[] m_deltas; 73 | private int[] m_targetOffsets; 74 | 75 | internal InlineSwitchInstruction(int offset, OpCode opCode, int[] deltas) 76 | : base(offset, opCode) 77 | { 78 | m_deltas = deltas; 79 | } 80 | 81 | public int[] Deltas => (int[])m_deltas.Clone(); 82 | 83 | public int[] TargetOffsets 84 | { 85 | get 86 | { 87 | if (m_targetOffsets == null) 88 | { 89 | var cases = m_deltas.Length; 90 | var itself = 1 + 4 + 4*cases; 91 | m_targetOffsets = new int[cases]; 92 | for (var i = 0; i < cases; i++) 93 | m_targetOffsets[i] = Offset + m_deltas[i] + itself; 94 | } 95 | return m_targetOffsets; 96 | } 97 | } 98 | 99 | public override void Accept(ILInstructionVisitor visitor) 100 | { 101 | visitor.VisitInlineSwitchInstruction(this); 102 | } 103 | } 104 | 105 | public class InlineIInstruction : ILInstruction 106 | { 107 | internal InlineIInstruction(int offset, OpCode opCode, int value) 108 | : base(offset, opCode) 109 | { 110 | Int32 = value; 111 | } 112 | 113 | public int Int32 { get; } 114 | 115 | public override void Accept(ILInstructionVisitor visitor) 116 | { 117 | visitor.VisitInlineIInstruction(this); 118 | } 119 | } 120 | 121 | public class InlineI8Instruction : ILInstruction 122 | { 123 | internal InlineI8Instruction(int offset, OpCode opCode, long value) 124 | : base(offset, opCode) 125 | { 126 | Int64 = value; 127 | } 128 | 129 | public long Int64 { get; } 130 | 131 | public override void Accept(ILInstructionVisitor visitor) 132 | { 133 | visitor.VisitInlineI8Instruction(this); 134 | } 135 | } 136 | 137 | public class ShortInlineIInstruction : ILInstruction 138 | { 139 | internal ShortInlineIInstruction(int offset, OpCode opCode, byte value) 140 | : base(offset, opCode) 141 | { 142 | Byte = value; 143 | } 144 | 145 | public byte Byte { get; } 146 | 147 | public override void Accept(ILInstructionVisitor visitor) 148 | { 149 | visitor.VisitShortInlineIInstruction(this); 150 | } 151 | } 152 | 153 | public class InlineRInstruction : ILInstruction 154 | { 155 | internal InlineRInstruction(int offset, OpCode opCode, double value) 156 | : base(offset, opCode) 157 | { 158 | Double = value; 159 | } 160 | 161 | public double Double { get; } 162 | 163 | public override void Accept(ILInstructionVisitor visitor) 164 | { 165 | visitor.VisitInlineRInstruction(this); 166 | } 167 | } 168 | 169 | public class ShortInlineRInstruction : ILInstruction 170 | { 171 | internal ShortInlineRInstruction(int offset, OpCode opCode, float value) 172 | : base(offset, opCode) 173 | { 174 | Single = value; 175 | } 176 | 177 | public float Single { get; } 178 | 179 | public override void Accept(ILInstructionVisitor visitor) 180 | { 181 | visitor.VisitShortInlineRInstruction(this); 182 | } 183 | } 184 | 185 | public class InlineFieldInstruction : ILInstruction 186 | { 187 | private readonly ITokenResolver m_resolver; 188 | private FieldInfo m_field; 189 | 190 | internal InlineFieldInstruction(ITokenResolver resolver, int offset, OpCode opCode, int token) 191 | : base(offset, opCode) 192 | { 193 | m_resolver = resolver; 194 | Token = token; 195 | } 196 | 197 | public FieldInfo Field => m_field ?? (m_field = m_resolver.AsField(Token)); 198 | 199 | public int Token { get; } 200 | 201 | public override void Accept(ILInstructionVisitor visitor) 202 | { 203 | visitor.VisitInlineFieldInstruction(this); 204 | } 205 | } 206 | 207 | public class InlineMethodInstruction : ILInstruction 208 | { 209 | private readonly ITokenResolver m_resolver; 210 | private MethodBase m_method; 211 | 212 | internal InlineMethodInstruction(int offset, OpCode opCode, int token, ITokenResolver resolver) 213 | : base(offset, opCode) 214 | { 215 | m_resolver = resolver; 216 | Token = token; 217 | } 218 | 219 | public MethodBase Method => m_method ?? (m_method = m_resolver.AsMethod(Token)); 220 | 221 | public int Token { get; } 222 | 223 | public override void Accept(ILInstructionVisitor visitor) 224 | { 225 | visitor.VisitInlineMethodInstruction(this); 226 | } 227 | } 228 | 229 | public class InlineTypeInstruction : ILInstruction 230 | { 231 | private readonly ITokenResolver m_resolver; 232 | private Type m_type; 233 | 234 | internal InlineTypeInstruction(int offset, OpCode opCode, int token, ITokenResolver resolver) 235 | : base(offset, opCode) 236 | { 237 | m_resolver = resolver; 238 | Token = token; 239 | } 240 | 241 | public Type Type => m_type ?? (m_type = m_resolver.AsType(Token)); 242 | 243 | public int Token { get; } 244 | 245 | public override void Accept(ILInstructionVisitor visitor) 246 | { 247 | visitor.VisitInlineTypeInstruction(this); 248 | } 249 | } 250 | 251 | public class InlineSigInstruction : ILInstruction 252 | { 253 | private readonly ITokenResolver m_resolver; 254 | private byte[] m_signature; 255 | 256 | internal InlineSigInstruction(int offset, OpCode opCode, int token, ITokenResolver resolver) 257 | : base(offset, opCode) 258 | { 259 | m_resolver = resolver; 260 | Token = token; 261 | } 262 | 263 | public byte[] Signature => m_signature ?? (m_signature = m_resolver.AsSignature(Token)); 264 | 265 | public int Token { get; } 266 | 267 | public override void Accept(ILInstructionVisitor visitor) 268 | { 269 | visitor.VisitInlineSigInstruction(this); 270 | } 271 | } 272 | 273 | public class InlineTokInstruction : ILInstruction 274 | { 275 | private readonly ITokenResolver m_resolver; 276 | private MemberInfo m_member; 277 | 278 | internal InlineTokInstruction(int offset, OpCode opCode, int token, ITokenResolver resolver) 279 | : base(offset, opCode) 280 | { 281 | m_resolver = resolver; 282 | Token = token; 283 | } 284 | 285 | public MemberInfo Member => m_member ?? (m_member = m_resolver.AsMember(Token)); 286 | 287 | public int Token { get; } 288 | 289 | public override void Accept(ILInstructionVisitor visitor) 290 | { 291 | visitor.VisitInlineTokInstruction(this); 292 | } 293 | } 294 | 295 | public class InlineStringInstruction : ILInstruction 296 | { 297 | private readonly ITokenResolver m_resolver; 298 | private string m_string; 299 | 300 | internal InlineStringInstruction(int offset, OpCode opCode, int token, ITokenResolver resolver) 301 | : base(offset, opCode) 302 | { 303 | m_resolver = resolver; 304 | Token = token; 305 | } 306 | 307 | public string String => m_string ?? (m_string = m_resolver.AsString(Token)); 308 | 309 | public int Token { get; } 310 | 311 | public override void Accept(ILInstructionVisitor visitor) 312 | { 313 | visitor.VisitInlineStringInstruction(this); 314 | } 315 | } 316 | 317 | public class InlineVarInstruction : ILInstruction 318 | { 319 | internal InlineVarInstruction(int offset, OpCode opCode, ushort ordinal) 320 | : base(offset, opCode) 321 | { 322 | Ordinal = ordinal; 323 | } 324 | 325 | public ushort Ordinal { get; } 326 | 327 | public override void Accept(ILInstructionVisitor visitor) 328 | { 329 | visitor.VisitInlineVarInstruction(this); 330 | } 331 | } 332 | 333 | public class ShortInlineVarInstruction : ILInstruction 334 | { 335 | internal ShortInlineVarInstruction(int offset, OpCode opCode, byte ordinal) 336 | : base(offset, opCode) 337 | { 338 | Ordinal = ordinal; 339 | } 340 | 341 | public byte Ordinal { get; } 342 | 343 | public override void Accept(ILInstructionVisitor visitor) 344 | { 345 | visitor.VisitShortInlineVarInstruction(this); 346 | } 347 | } 348 | } -------------------------------------------------------------------------------- /ILDebugging.Decoder/ILProvider.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | 4 | namespace ILDebugging.Decoder 5 | { 6 | public interface IILProvider 7 | { 8 | byte[] GetByteArray(); 9 | } 10 | 11 | public class MethodBaseILProvider : IILProvider 12 | { 13 | private static readonly Type s_runtimeMethodInfoType = Type.GetType("System.Reflection.RuntimeMethodInfo"); 14 | private static readonly Type s_runtimeConstructorInfoType = Type.GetType("System.Reflection.RuntimeConstructorInfo"); 15 | 16 | private readonly MethodBase m_method; 17 | private byte[] m_byteArray; 18 | 19 | public MethodBaseILProvider(MethodBase method) 20 | { 21 | if (method == null) 22 | throw new ArgumentNullException(nameof(method)); 23 | 24 | var methodType = method.GetType(); 25 | 26 | if (methodType != s_runtimeMethodInfoType && methodType != s_runtimeConstructorInfoType) 27 | throw new ArgumentException("Must have type RuntimeMethodInfo or RuntimeConstructorInfo.", nameof(method)); 28 | 29 | m_method = method; 30 | } 31 | 32 | public byte[] GetByteArray() 33 | { 34 | return m_byteArray ?? (m_byteArray = m_method.GetMethodBody()?.GetILAsByteArray() ?? new byte[0]); 35 | } 36 | } 37 | } -------------------------------------------------------------------------------- /ILDebugging.Decoder/ILReader.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | using System.Reflection; 5 | using System.Reflection.Emit; 6 | 7 | namespace ILDebugging.Decoder 8 | { 9 | public sealed class ILReader : IEnumerable 10 | { 11 | #region Static members 12 | 13 | private static readonly OpCode[] s_OneByteOpCodes = new OpCode[0x100]; 14 | private static readonly OpCode[] s_TwoByteOpCodes = new OpCode[0x100]; 15 | 16 | static ILReader() 17 | { 18 | foreach (var fi in typeof(OpCodes).GetFields(BindingFlags.Public | BindingFlags.Static)) 19 | { 20 | var opCode = (OpCode)fi.GetValue(null); 21 | var value = (ushort)opCode.Value; 22 | 23 | if (value < 0x100) 24 | s_OneByteOpCodes[value] = opCode; 25 | else if ((value & 0xff00) == 0xfe00) 26 | s_TwoByteOpCodes[value & 0xff] = opCode; 27 | } 28 | } 29 | 30 | #endregion 31 | 32 | private readonly ITokenResolver m_resolver; 33 | private readonly byte[] m_byteArray; 34 | 35 | public ILReader(MethodBase method) 36 | : this(new MethodBaseILProvider(method), new ModuleScopeTokenResolver(method)) 37 | { 38 | } 39 | 40 | public ILReader(IILProvider ilProvider, ITokenResolver tokenResolver) 41 | { 42 | if (ilProvider == null) 43 | throw new ArgumentNullException(nameof(ilProvider)); 44 | 45 | m_resolver = tokenResolver; 46 | m_byteArray = ilProvider.GetByteArray(); 47 | } 48 | 49 | public IEnumerator GetEnumerator() 50 | { 51 | var position = 0; 52 | 53 | while (position < m_byteArray.Length) 54 | yield return Next(ref position); 55 | } 56 | 57 | IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); 58 | 59 | private ILInstruction Next(ref int position) 60 | { 61 | var offset = position; 62 | OpCode opCode; 63 | 64 | // read first 1 or 2 bytes as opCode 65 | var code = ReadByte(ref position); 66 | if (code != 0xFE) 67 | { 68 | opCode = s_OneByteOpCodes[code]; 69 | } 70 | else 71 | { 72 | code = ReadByte(ref position); 73 | opCode = s_TwoByteOpCodes[code]; 74 | } 75 | 76 | switch (opCode.OperandType) 77 | { 78 | case OperandType.InlineNone: 79 | { 80 | return new InlineNoneInstruction(offset, opCode); 81 | } 82 | case OperandType.ShortInlineBrTarget: 83 | { 84 | // 8-bit integer branch target 85 | var shortDelta = ReadSByte(ref position); 86 | return new ShortInlineBrTargetInstruction(offset, opCode, shortDelta); 87 | } 88 | case OperandType.InlineBrTarget: 89 | { 90 | // 32-bit integer branch target 91 | var delta = ReadInt32(ref position); 92 | return new InlineBrTargetInstruction(offset, opCode, delta); 93 | } 94 | case OperandType.ShortInlineI: 95 | { 96 | // 8-bit integer: 001F ldc.i4.s, FE12 unaligned. 97 | var int8 = ReadByte(ref position); 98 | return new ShortInlineIInstruction(offset, opCode, int8); 99 | } 100 | case OperandType.InlineI: 101 | { 102 | // 32-bit integer 103 | var int32 = ReadInt32(ref position); 104 | return new InlineIInstruction(offset, opCode, int32); 105 | } 106 | case OperandType.InlineI8: 107 | { 108 | // 64-bit integer 109 | var int64 = ReadInt64(ref position); 110 | return new InlineI8Instruction(offset, opCode, int64); 111 | } 112 | case OperandType.ShortInlineR: 113 | { 114 | // 32-bit IEEE floating point number 115 | var float32 = ReadSingle(ref position); 116 | return new ShortInlineRInstruction(offset, opCode, float32); 117 | } 118 | case OperandType.InlineR: 119 | { 120 | // 64-bit IEEE floating point number 121 | var float64 = ReadDouble(ref position); 122 | return new InlineRInstruction(offset, opCode, float64); 123 | } 124 | case OperandType.ShortInlineVar: 125 | { 126 | // 8-bit integer containing the ordinal of a local variable or an argument 127 | var index8 = ReadByte(ref position); 128 | return new ShortInlineVarInstruction(offset, opCode, index8); 129 | } 130 | case OperandType.InlineVar: 131 | { 132 | // 16-bit integer containing the ordinal of a local variable or an argument 133 | var index16 = ReadUInt16(ref position); 134 | return new InlineVarInstruction(offset, opCode, index16); 135 | } 136 | case OperandType.InlineString: 137 | { 138 | // 32-bit metadata string token 139 | var token = ReadInt32(ref position); 140 | return new InlineStringInstruction(offset, opCode, token, m_resolver); 141 | } 142 | case OperandType.InlineSig: 143 | { 144 | // 32-bit metadata signature token 145 | var token = ReadInt32(ref position); 146 | return new InlineSigInstruction(offset, opCode, token, m_resolver); 147 | } 148 | case OperandType.InlineMethod: 149 | { 150 | // 32-bit metadata token 151 | var token = ReadInt32(ref position); 152 | return new InlineMethodInstruction(offset, opCode, token, m_resolver); 153 | } 154 | case OperandType.InlineField: 155 | { 156 | // 32-bit metadata token 157 | var token = ReadInt32(ref position); 158 | return new InlineFieldInstruction(m_resolver, offset, opCode, token); 159 | } 160 | case OperandType.InlineType: 161 | { 162 | // 32-bit metadata token 163 | var token = ReadInt32(ref position); 164 | return new InlineTypeInstruction(offset, opCode, token, m_resolver); 165 | } 166 | case OperandType.InlineTok: 167 | { 168 | // FieldRef, MethodRef, or TypeRef token 169 | var token = ReadInt32(ref position); 170 | return new InlineTokInstruction(offset, opCode, token, m_resolver); 171 | } 172 | case OperandType.InlineSwitch: 173 | { 174 | // 32-bit integer argument to a switch instruction 175 | var cases = ReadInt32(ref position); 176 | var deltas = new int[cases]; 177 | for (var i = 0; i < cases; i++) 178 | deltas[i] = ReadInt32(ref position); 179 | return new InlineSwitchInstruction(offset, opCode, deltas); 180 | } 181 | 182 | default: 183 | throw new NotSupportedException($"Unsupported operand type: {opCode.OperandType}"); 184 | } 185 | } 186 | 187 | public void Accept(ILInstructionVisitor visitor) 188 | { 189 | if (visitor == null) 190 | throw new ArgumentNullException(nameof(visitor)); 191 | 192 | foreach (var instruction in this) 193 | instruction.Accept(visitor); 194 | } 195 | 196 | #region read in operands 197 | 198 | private byte ReadByte(ref int position) => m_byteArray[position++]; 199 | 200 | private sbyte ReadSByte(ref int position) => (sbyte)ReadByte(ref position); 201 | 202 | private ushort ReadUInt16(ref int position) 203 | { 204 | var value = BitConverter.ToUInt16(m_byteArray, position); 205 | position += 2; 206 | return value; 207 | } 208 | 209 | private uint ReadUInt32(ref int position) 210 | { 211 | var value = BitConverter.ToUInt32(m_byteArray, position); 212 | position += 4; 213 | return value; 214 | } 215 | 216 | private ulong ReadUInt64(ref int position) 217 | { 218 | var value = BitConverter.ToUInt64(m_byteArray, position); 219 | position += 8; 220 | return value; 221 | } 222 | 223 | private int ReadInt32(ref int position) 224 | { 225 | var value = BitConverter.ToInt32(m_byteArray, position); 226 | position += 4; 227 | return value; 228 | } 229 | 230 | private long ReadInt64(ref int position) 231 | { 232 | var value = BitConverter.ToInt64(m_byteArray, position); 233 | position += 8; 234 | return value; 235 | } 236 | 237 | private float ReadSingle(ref int position) 238 | { 239 | var value = BitConverter.ToSingle(m_byteArray, position); 240 | position += 4; 241 | return value; 242 | } 243 | 244 | private double ReadDouble(ref int position) 245 | { 246 | var value = BitConverter.ToDouble(m_byteArray, position); 247 | position += 8; 248 | return value; 249 | } 250 | 251 | #endregion 252 | } 253 | } -------------------------------------------------------------------------------- /ILDebugging.Decoder/ILReaderFactory.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | using System.Reflection.Emit; 4 | 5 | namespace ILDebugging.Decoder 6 | { 7 | public static class ILReaderFactory 8 | { 9 | public static ILReader Create(object obj) 10 | { 11 | var type = obj.GetType(); 12 | 13 | if (type == s_dynamicMethodType || type == s_rtDynamicMethodType) 14 | { 15 | DynamicMethod dm; 16 | if (type == s_rtDynamicMethodType) 17 | { 18 | // 19 | // if the target is RTDynamicMethod, get the value of 20 | // RTDynamicMethod.m_owner instead 21 | // 22 | dm = (DynamicMethod)s_fiOwner.GetValue(obj); 23 | } 24 | else 25 | { 26 | dm = obj as DynamicMethod; 27 | } 28 | 29 | return new ILReader(new DynamicMethodILProvider(dm), new DynamicScopeTokenResolver(dm)); 30 | } 31 | 32 | if (type == s_runtimeMethodInfoType || type == s_runtimeConstructorInfoType) 33 | { 34 | var method = obj as MethodBase; 35 | return new ILReader(method); 36 | } 37 | 38 | throw new NotSupportedException($"Reading IL from type {type} is currently not supported"); 39 | } 40 | 41 | private static readonly Type s_dynamicMethodType = Type.GetType("System.Reflection.Emit.DynamicMethod"); 42 | private static readonly Type s_runtimeMethodInfoType = Type.GetType("System.Reflection.RuntimeMethodInfo"); 43 | private static readonly Type s_runtimeConstructorInfoType = Type.GetType("System.Reflection.RuntimeConstructorInfo"); 44 | 45 | private static readonly Type s_rtDynamicMethodType = Type.GetType("System.Reflection.Emit.DynamicMethod+RTDynamicMethod"); 46 | private static readonly FieldInfo s_fiOwner = s_rtDynamicMethodType.GetField("m_owner", BindingFlags.Instance | BindingFlags.NonPublic); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /ILDebugging.Decoder/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | using System.Security; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | 9 | [assembly: AssemblyTitle("ILDebugging.Decoder")] 10 | [assembly: AssemblyDescription("Reads IL bytes as a sequence of opcodes and operands.")] 11 | [assembly: AssemblyConfiguration("")] 12 | [assembly: AssemblyCompany("Microsoft")] 13 | [assembly: AssemblyProduct("")] 14 | [assembly: AssemblyCopyright("Copyright © 2006")] 15 | [assembly: AssemblyTrademark("")] 16 | [assembly: AssemblyCulture("")] 17 | 18 | // Setting ComVisible to false makes the types in this assembly not visible 19 | // to COM components. If you need to access a type in this assembly from 20 | // COM, set the ComVisible attribute to true on that type. 21 | 22 | [assembly: ComVisible(false)] 23 | 24 | // The following GUID is for the ID of the typelib if this project is exposed to COM 25 | 26 | [assembly: Guid("1032b116-0bc4-4877-9d09-86ce346c17ab")] 27 | 28 | // Version information for an assembly consists of the following four values: 29 | // 30 | // Major Version 31 | // Minor Version 32 | // Build Number 33 | // Revision 34 | // 35 | // You can specify all the values or you can default the Revision and Build Numbers 36 | // by using the '*' as shown below: 37 | 38 | [assembly: AssemblyVersion("1.0.0.0")] 39 | [assembly: AssemblyFileVersion("1.0.0.0")] 40 | [assembly: SecurityTransparent] -------------------------------------------------------------------------------- /ILDebugging.Decoder/README.txt: -------------------------------------------------------------------------------- 1 | 2 | THE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES INTENDED OR IMPLIED. USE AT YOUR OWN RISK -------------------------------------------------------------------------------- /ILDebugging.Decoder/ReadableILStringVisitor.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | 4 | namespace ILDebugging.Decoder 5 | { 6 | public interface IILStringCollector 7 | { 8 | void Process(ILInstruction ilInstruction, string operandString); 9 | } 10 | 11 | public class ReadableILStringToTextWriter : IILStringCollector 12 | { 13 | protected readonly TextWriter writer; 14 | 15 | public ReadableILStringToTextWriter(TextWriter writer) 16 | { 17 | this.writer = writer; 18 | } 19 | 20 | public virtual void Process(ILInstruction ilInstruction, string operandString) 21 | { 22 | writer.WriteLine("IL_{0:x4}: {1,-10} {2}", 23 | ilInstruction.Offset, 24 | ilInstruction.OpCode.Name, 25 | operandString); 26 | } 27 | } 28 | 29 | public class RawILStringToTextWriter : ReadableILStringToTextWriter 30 | { 31 | public RawILStringToTextWriter(TextWriter writer) 32 | : base(writer) 33 | { 34 | } 35 | 36 | public override void Process(ILInstruction ilInstruction, string operandString) 37 | { 38 | writer.WriteLine("IL_{0:x4}: {1,-4:x2}| {2, -8}", 39 | ilInstruction.Offset, 40 | ilInstruction.OpCode.Value, 41 | operandString); 42 | } 43 | } 44 | 45 | public abstract class ILInstructionVisitor 46 | { 47 | public virtual void VisitInlineBrTargetInstruction(InlineBrTargetInstruction inlineBrTargetInstruction) 48 | { 49 | } 50 | 51 | public virtual void VisitInlineFieldInstruction(InlineFieldInstruction inlineFieldInstruction) 52 | { 53 | } 54 | 55 | public virtual void VisitInlineIInstruction(InlineIInstruction inlineIInstruction) 56 | { 57 | } 58 | 59 | public virtual void VisitInlineI8Instruction(InlineI8Instruction inlineI8Instruction) 60 | { 61 | } 62 | 63 | public virtual void VisitInlineMethodInstruction(InlineMethodInstruction inlineMethodInstruction) 64 | { 65 | } 66 | 67 | public virtual void VisitInlineNoneInstruction(InlineNoneInstruction inlineNoneInstruction) 68 | { 69 | } 70 | 71 | public virtual void VisitInlineRInstruction(InlineRInstruction inlineRInstruction) 72 | { 73 | } 74 | 75 | public virtual void VisitInlineSigInstruction(InlineSigInstruction inlineSigInstruction) 76 | { 77 | } 78 | 79 | public virtual void VisitInlineStringInstruction(InlineStringInstruction inlineStringInstruction) 80 | { 81 | } 82 | 83 | public virtual void VisitInlineSwitchInstruction(InlineSwitchInstruction inlineSwitchInstruction) 84 | { 85 | } 86 | 87 | public virtual void VisitInlineTokInstruction(InlineTokInstruction inlineTokInstruction) 88 | { 89 | } 90 | 91 | public virtual void VisitInlineTypeInstruction(InlineTypeInstruction inlineTypeInstruction) 92 | { 93 | } 94 | 95 | public virtual void VisitInlineVarInstruction(InlineVarInstruction inlineVarInstruction) 96 | { 97 | } 98 | 99 | public virtual void VisitShortInlineBrTargetInstruction(ShortInlineBrTargetInstruction shortInlineBrTargetInstruction) 100 | { 101 | } 102 | 103 | public virtual void VisitShortInlineIInstruction(ShortInlineIInstruction shortInlineIInstruction) 104 | { 105 | } 106 | 107 | public virtual void VisitShortInlineRInstruction(ShortInlineRInstruction shortInlineRInstruction) 108 | { 109 | } 110 | 111 | public virtual void VisitShortInlineVarInstruction(ShortInlineVarInstruction shortInlineVarInstruction) 112 | { 113 | } 114 | } 115 | 116 | public class ReadableILStringVisitor : ILInstructionVisitor 117 | { 118 | protected readonly IFormatProvider formatProvider; 119 | protected readonly IILStringCollector collector; 120 | 121 | public ReadableILStringVisitor(IILStringCollector collector) 122 | : this(collector, DefaultFormatProvider.Instance) 123 | { 124 | } 125 | 126 | public ReadableILStringVisitor(IILStringCollector collector, IFormatProvider formatProvider) 127 | { 128 | this.formatProvider = formatProvider; 129 | this.collector = collector; 130 | } 131 | 132 | public override void VisitInlineBrTargetInstruction(InlineBrTargetInstruction inlineBrTargetInstruction) 133 | { 134 | collector.Process(inlineBrTargetInstruction, formatProvider.Label(inlineBrTargetInstruction.TargetOffset)); 135 | } 136 | 137 | public override void VisitInlineFieldInstruction(InlineFieldInstruction inlineFieldInstruction) 138 | { 139 | string field; 140 | try 141 | { 142 | field = inlineFieldInstruction.Field + "/" + inlineFieldInstruction.Field.DeclaringType; 143 | } 144 | catch (Exception ex) 145 | { 146 | field = "!" + ex.Message + "!"; 147 | } 148 | collector.Process(inlineFieldInstruction, field); 149 | } 150 | 151 | public override void VisitInlineIInstruction(InlineIInstruction inlineIInstruction) 152 | { 153 | collector.Process(inlineIInstruction, inlineIInstruction.Int32.ToString()); 154 | } 155 | 156 | public override void VisitInlineI8Instruction(InlineI8Instruction inlineI8Instruction) 157 | { 158 | collector.Process(inlineI8Instruction, inlineI8Instruction.Int64.ToString()); 159 | } 160 | 161 | public override void VisitInlineMethodInstruction(InlineMethodInstruction inlineMethodInstruction) 162 | { 163 | string method; 164 | try 165 | { 166 | method = inlineMethodInstruction.Method + "/" + inlineMethodInstruction.Method.DeclaringType; 167 | } 168 | catch (Exception ex) 169 | { 170 | method = "!" + ex.Message + "!"; 171 | } 172 | collector.Process(inlineMethodInstruction, method); 173 | } 174 | 175 | public override void VisitInlineNoneInstruction(InlineNoneInstruction inlineNoneInstruction) 176 | { 177 | collector.Process(inlineNoneInstruction, string.Empty); 178 | } 179 | 180 | public override void VisitInlineRInstruction(InlineRInstruction inlineRInstruction) 181 | { 182 | collector.Process(inlineRInstruction, inlineRInstruction.Double.ToString()); 183 | } 184 | 185 | public override void VisitInlineSigInstruction(InlineSigInstruction inlineSigInstruction) 186 | { 187 | collector.Process(inlineSigInstruction, formatProvider.SigByteArrayToString(inlineSigInstruction.Signature)); 188 | } 189 | 190 | public override void VisitInlineStringInstruction(InlineStringInstruction inlineStringInstruction) 191 | { 192 | collector.Process(inlineStringInstruction, formatProvider.EscapedString(inlineStringInstruction.String)); 193 | } 194 | 195 | public override void VisitInlineSwitchInstruction(InlineSwitchInstruction inlineSwitchInstruction) 196 | { 197 | collector.Process(inlineSwitchInstruction, formatProvider.MultipleLabels(inlineSwitchInstruction.TargetOffsets)); 198 | } 199 | 200 | public override void VisitInlineTokInstruction(InlineTokInstruction inlineTokInstruction) 201 | { 202 | string member; 203 | try 204 | { 205 | member = inlineTokInstruction.Member + "/" + inlineTokInstruction.Member.DeclaringType; 206 | } 207 | catch (Exception ex) 208 | { 209 | member = "!" + ex.Message + "!"; 210 | } 211 | collector.Process(inlineTokInstruction, member); 212 | } 213 | 214 | public override void VisitInlineTypeInstruction(InlineTypeInstruction inlineTypeInstruction) 215 | { 216 | string type; 217 | try 218 | { 219 | type = inlineTypeInstruction.Type.ToString(); 220 | } 221 | catch (Exception ex) 222 | { 223 | type = "!" + ex.Message + "!"; 224 | } 225 | collector.Process(inlineTypeInstruction, type); 226 | } 227 | 228 | public override void VisitInlineVarInstruction(InlineVarInstruction inlineVarInstruction) 229 | { 230 | collector.Process(inlineVarInstruction, formatProvider.Argument(inlineVarInstruction.Ordinal)); 231 | } 232 | 233 | public override void VisitShortInlineBrTargetInstruction(ShortInlineBrTargetInstruction shortInlineBrTargetInstruction) 234 | { 235 | collector.Process(shortInlineBrTargetInstruction, formatProvider.Label(shortInlineBrTargetInstruction.TargetOffset)); 236 | } 237 | 238 | public override void VisitShortInlineIInstruction(ShortInlineIInstruction shortInlineIInstruction) 239 | { 240 | collector.Process(shortInlineIInstruction, shortInlineIInstruction.Byte.ToString()); 241 | } 242 | 243 | public override void VisitShortInlineRInstruction(ShortInlineRInstruction shortInlineRInstruction) 244 | { 245 | collector.Process(shortInlineRInstruction, shortInlineRInstruction.Single.ToString()); 246 | } 247 | 248 | public override void VisitShortInlineVarInstruction(ShortInlineVarInstruction shortInlineVarInstruction) 249 | { 250 | collector.Process(shortInlineVarInstruction, formatProvider.Argument(shortInlineVarInstruction.Ordinal)); 251 | } 252 | } 253 | 254 | public class RawILStringVisitor : ReadableILStringVisitor 255 | { 256 | public RawILStringVisitor(IILStringCollector collector) 257 | : this(collector, DefaultFormatProvider.Instance) 258 | { 259 | } 260 | 261 | public RawILStringVisitor(IILStringCollector collector, IFormatProvider formatProvider) 262 | : base(collector, formatProvider) 263 | { 264 | } 265 | 266 | public override void VisitInlineBrTargetInstruction(InlineBrTargetInstruction inlineBrTargetInstruction) 267 | { 268 | collector.Process(inlineBrTargetInstruction, formatProvider.Int32ToHex(inlineBrTargetInstruction.Delta)); 269 | } 270 | 271 | public override void VisitInlineFieldInstruction(InlineFieldInstruction inlineFieldInstruction) 272 | { 273 | collector.Process(inlineFieldInstruction, formatProvider.Int32ToHex(inlineFieldInstruction.Token)); 274 | } 275 | 276 | public override void VisitInlineMethodInstruction(InlineMethodInstruction inlineMethodInstruction) 277 | { 278 | collector.Process(inlineMethodInstruction, formatProvider.Int32ToHex(inlineMethodInstruction.Token)); 279 | } 280 | 281 | public override void VisitInlineSigInstruction(InlineSigInstruction inlineSigInstruction) 282 | { 283 | collector.Process(inlineSigInstruction, formatProvider.Int32ToHex(inlineSigInstruction.Token)); 284 | } 285 | 286 | public override void VisitInlineStringInstruction(InlineStringInstruction inlineStringInstruction) 287 | { 288 | collector.Process(inlineStringInstruction, formatProvider.Int32ToHex(inlineStringInstruction.Token)); 289 | } 290 | 291 | public override void VisitInlineSwitchInstruction(InlineSwitchInstruction inlineSwitchInstruction) 292 | { 293 | collector.Process(inlineSwitchInstruction, "..."); 294 | } 295 | 296 | public override void VisitInlineTokInstruction(InlineTokInstruction inlineTokInstruction) 297 | { 298 | collector.Process(inlineTokInstruction, formatProvider.Int32ToHex(inlineTokInstruction.Token)); 299 | } 300 | 301 | public override void VisitInlineTypeInstruction(InlineTypeInstruction inlineTypeInstruction) 302 | { 303 | collector.Process(inlineTypeInstruction, formatProvider.Int32ToHex(inlineTypeInstruction.Token)); 304 | } 305 | 306 | public override void VisitInlineVarInstruction(InlineVarInstruction inlineVarInstruction) 307 | { 308 | collector.Process(inlineVarInstruction, formatProvider.Int16ToHex(inlineVarInstruction.Ordinal)); 309 | } 310 | 311 | public override void VisitShortInlineBrTargetInstruction(ShortInlineBrTargetInstruction shortInlineBrTargetInstruction) 312 | { 313 | collector.Process(shortInlineBrTargetInstruction, formatProvider.Int8ToHex(shortInlineBrTargetInstruction.Delta)); 314 | } 315 | 316 | public override void VisitShortInlineVarInstruction(ShortInlineVarInstruction shortInlineVarInstruction) 317 | { 318 | collector.Process(shortInlineVarInstruction, formatProvider.Int8ToHex(shortInlineVarInstruction.Ordinal)); 319 | } 320 | } 321 | } 322 | -------------------------------------------------------------------------------- /ILDebugging.Decoder/TokenResolver.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | 4 | namespace ILDebugging.Decoder 5 | { 6 | public interface ITokenResolver 7 | { 8 | MethodBase AsMethod(int token); 9 | FieldInfo AsField(int token); 10 | Type AsType(int token); 11 | string AsString(int token); 12 | MemberInfo AsMember(int token); 13 | byte[] AsSignature(int token); 14 | } 15 | 16 | public class ModuleScopeTokenResolver : ITokenResolver 17 | { 18 | private readonly Module m_module; 19 | private readonly Type[] m_methodContext; 20 | private readonly Type[] m_typeContext; 21 | 22 | public ModuleScopeTokenResolver(MethodBase method) 23 | { 24 | m_module = method.Module; 25 | m_methodContext = method is ConstructorInfo ? null : method.GetGenericArguments(); 26 | m_typeContext = method.DeclaringType == null ? null : method.DeclaringType.GetGenericArguments(); 27 | } 28 | 29 | public MethodBase AsMethod(int token) => m_module.ResolveMethod(token, m_typeContext, m_methodContext); 30 | public FieldInfo AsField(int token) => m_module.ResolveField(token, m_typeContext, m_methodContext); 31 | public Type AsType(int token) => m_module.ResolveType(token, m_typeContext, m_methodContext); 32 | public MemberInfo AsMember(int token) => m_module.ResolveMember(token, m_typeContext, m_methodContext); 33 | public string AsString(int token) => m_module.ResolveString(token); 34 | public byte[] AsSignature(int token) => m_module.ResolveSignature(token); 35 | } 36 | } -------------------------------------------------------------------------------- /ILDebugging.Monitor/ILDebugging.Monitor.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Debug 5 | AnyCPU 6 | 8.0.50727 7 | 2.0 8 | {77F852DD-35CD-4B2D-AA0E-0516F1E7597F} 9 | WinExe 10 | Properties 11 | ILDebugging.Monitor 12 | ILDebugging.Monitor 13 | 14 | 15 | 16 | 17 | 3.5 18 | v4.6 19 | 20 | 21 | 22 | true 23 | full 24 | false 25 | bin\Debug\ 26 | DEBUG;TRACE 27 | prompt 28 | 4 29 | false 30 | 31 | 32 | pdbonly 33 | true 34 | bin\Release\ 35 | TRACE 36 | prompt 37 | 4 38 | false 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | Form 49 | 50 | 51 | ILMonitorForm.cs 52 | 53 | 54 | 55 | Form 56 | 57 | 58 | MiniBrowser.cs 59 | 60 | 61 | 62 | 63 | 64 | Designer 65 | ILMonitorForm.cs 66 | 67 | 68 | Designer 69 | MiniBrowser.cs 70 | 71 | 72 | ResXFileCodeGenerator 73 | Resources.Designer.cs 74 | Designer 75 | 76 | 77 | True 78 | Resources.resx 79 | True 80 | 81 | 82 | 83 | SettingsSingleFileGenerator 84 | Settings.Designer.cs 85 | 86 | 87 | True 88 | True 89 | Settings.settings 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | {6F6E9FC5-40A9-4ABD-89F3-EF7B6406F07B} 98 | ILDebugging.Visualizer 99 | 100 | 101 | 102 | 109 | -------------------------------------------------------------------------------- /ILDebugging.Monitor/ILMonitorForm.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace ILDebugging.Monitor { 2 | partial class ILMonitorForm { 3 | /// 4 | /// Required designer variable. 5 | /// 6 | private System.ComponentModel.IContainer components = null; 7 | 8 | /// 9 | /// Clean up any resources being used. 10 | /// 11 | /// true if managed resources should be disposed; otherwise, false. 12 | protected override void Dispose(bool disposing) { 13 | if (disposing && (components != null)) { 14 | components.Dispose(); 15 | } 16 | base.Dispose(disposing); 17 | } 18 | 19 | #region Windows Form Designer generated code 20 | 21 | /// 22 | /// Required method for Designer support - do not modify 23 | /// the contents of this method with the code editor. 24 | /// 25 | private void InitializeComponent() { 26 | this.components = new System.ComponentModel.Container(); 27 | System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(ILMonitorForm)); 28 | this.menuStrip = new System.Windows.Forms.MenuStrip(); 29 | this.fileMenu = new System.Windows.Forms.ToolStripMenuItem(); 30 | this.startToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); 31 | this.stopToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); 32 | this.toolStripSeparator5 = new System.Windows.Forms.ToolStripSeparator(); 33 | this.exitToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); 34 | this.optionsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); 35 | this.autoStartToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); 36 | this.showStatusBarToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); 37 | this.windowsMenu = new System.Windows.Forms.ToolStripMenuItem(); 38 | this.cascadeToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); 39 | this.tileVerticalToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); 40 | this.tileHorizontalToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); 41 | this.closeAllToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); 42 | this.arrangeIconsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); 43 | this.statusStrip = new System.Windows.Forms.StatusStrip(); 44 | this.toolStripStatusLabel = new System.Windows.Forms.ToolStripStatusLabel(); 45 | this.ToolTip = new System.Windows.Forms.ToolTip(this.components); 46 | this.menuStrip.SuspendLayout(); 47 | this.statusStrip.SuspendLayout(); 48 | this.SuspendLayout(); 49 | // 50 | // menuStrip 51 | // 52 | this.menuStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { 53 | this.fileMenu, 54 | this.optionsToolStripMenuItem, 55 | this.windowsMenu}); 56 | this.menuStrip.Location = new System.Drawing.Point(0, 0); 57 | this.menuStrip.MdiWindowListItem = this.windowsMenu; 58 | this.menuStrip.Name = "menuStrip"; 59 | this.menuStrip.Size = new System.Drawing.Size(632, 24); 60 | this.menuStrip.TabIndex = 0; 61 | this.menuStrip.Text = "MenuStrip"; 62 | // 63 | // fileMenu 64 | // 65 | this.fileMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { 66 | this.startToolStripMenuItem, 67 | this.stopToolStripMenuItem, 68 | this.toolStripSeparator5, 69 | this.exitToolStripMenuItem}); 70 | this.fileMenu.ImageTransparentColor = System.Drawing.SystemColors.ActiveBorder; 71 | this.fileMenu.Name = "fileMenu"; 72 | this.fileMenu.Size = new System.Drawing.Size(37, 20); 73 | this.fileMenu.Text = "&File"; 74 | // 75 | // startToolStripMenuItem 76 | // 77 | this.startToolStripMenuItem.Name = "startToolStripMenuItem"; 78 | this.startToolStripMenuItem.Size = new System.Drawing.Size(98, 22); 79 | this.startToolStripMenuItem.Text = "Start"; 80 | this.startToolStripMenuItem.Click += new System.EventHandler(this.startToolStripMenuItem_Click); 81 | // 82 | // stopToolStripMenuItem 83 | // 84 | this.stopToolStripMenuItem.Enabled = false; 85 | this.stopToolStripMenuItem.Name = "stopToolStripMenuItem"; 86 | this.stopToolStripMenuItem.Size = new System.Drawing.Size(98, 22); 87 | this.stopToolStripMenuItem.Text = "Stop"; 88 | this.stopToolStripMenuItem.Click += new System.EventHandler(this.stopToolStripMenuItem_Click); 89 | // 90 | // toolStripSeparator5 91 | // 92 | this.toolStripSeparator5.Name = "toolStripSeparator5"; 93 | this.toolStripSeparator5.Size = new System.Drawing.Size(95, 6); 94 | // 95 | // exitToolStripMenuItem 96 | // 97 | this.exitToolStripMenuItem.Name = "exitToolStripMenuItem"; 98 | this.exitToolStripMenuItem.Size = new System.Drawing.Size(98, 22); 99 | this.exitToolStripMenuItem.Text = "E&xit"; 100 | this.exitToolStripMenuItem.Click += new System.EventHandler(this.ExitToolsStripMenuItem_Click); 101 | // 102 | // optionsToolStripMenuItem 103 | // 104 | this.optionsToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { 105 | this.autoStartToolStripMenuItem, 106 | this.showStatusBarToolStripMenuItem}); 107 | this.optionsToolStripMenuItem.Name = "optionsToolStripMenuItem"; 108 | this.optionsToolStripMenuItem.Size = new System.Drawing.Size(61, 20); 109 | this.optionsToolStripMenuItem.Text = "&Options"; 110 | // 111 | // autoStartToolStripMenuItem 112 | // 113 | this.autoStartToolStripMenuItem.Name = "autoStartToolStripMenuItem"; 114 | this.autoStartToolStripMenuItem.Size = new System.Drawing.Size(238, 22); 115 | this.autoStartToolStripMenuItem.Text = "Start Monitoring Automatically"; 116 | this.autoStartToolStripMenuItem.Click += new System.EventHandler(this.autoStartToolStripMenuItem_Click); 117 | // 118 | // showStatusBarToolStripMenuItem 119 | // 120 | this.showStatusBarToolStripMenuItem.Checked = true; 121 | this.showStatusBarToolStripMenuItem.CheckOnClick = true; 122 | this.showStatusBarToolStripMenuItem.CheckState = System.Windows.Forms.CheckState.Checked; 123 | this.showStatusBarToolStripMenuItem.Name = "showStatusBarToolStripMenuItem"; 124 | this.showStatusBarToolStripMenuItem.Size = new System.Drawing.Size(238, 22); 125 | this.showStatusBarToolStripMenuItem.Text = "Show Status Bar"; 126 | this.showStatusBarToolStripMenuItem.Click += new System.EventHandler(this.showStatusBarToolStripMenuItem_Click); 127 | // 128 | // windowsMenu 129 | // 130 | this.windowsMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { 131 | this.cascadeToolStripMenuItem, 132 | this.tileVerticalToolStripMenuItem, 133 | this.tileHorizontalToolStripMenuItem, 134 | this.closeAllToolStripMenuItem, 135 | this.arrangeIconsToolStripMenuItem}); 136 | this.windowsMenu.Name = "windowsMenu"; 137 | this.windowsMenu.Size = new System.Drawing.Size(68, 20); 138 | this.windowsMenu.Text = "&Windows"; 139 | // 140 | // cascadeToolStripMenuItem 141 | // 142 | this.cascadeToolStripMenuItem.Name = "cascadeToolStripMenuItem"; 143 | this.cascadeToolStripMenuItem.Size = new System.Drawing.Size(151, 22); 144 | this.cascadeToolStripMenuItem.Text = "&Cascade"; 145 | this.cascadeToolStripMenuItem.Click += new System.EventHandler(this.CascadeToolStripMenuItem_Click); 146 | // 147 | // tileVerticalToolStripMenuItem 148 | // 149 | this.tileVerticalToolStripMenuItem.Name = "tileVerticalToolStripMenuItem"; 150 | this.tileVerticalToolStripMenuItem.Size = new System.Drawing.Size(151, 22); 151 | this.tileVerticalToolStripMenuItem.Text = "Tile &Vertical"; 152 | this.tileVerticalToolStripMenuItem.Click += new System.EventHandler(this.TileVerticalToolStripMenuItem_Click); 153 | // 154 | // tileHorizontalToolStripMenuItem 155 | // 156 | this.tileHorizontalToolStripMenuItem.Name = "tileHorizontalToolStripMenuItem"; 157 | this.tileHorizontalToolStripMenuItem.Size = new System.Drawing.Size(151, 22); 158 | this.tileHorizontalToolStripMenuItem.Text = "Tile &Horizontal"; 159 | this.tileHorizontalToolStripMenuItem.Click += new System.EventHandler(this.TileHorizontalToolStripMenuItem_Click); 160 | // 161 | // closeAllToolStripMenuItem 162 | // 163 | this.closeAllToolStripMenuItem.Name = "closeAllToolStripMenuItem"; 164 | this.closeAllToolStripMenuItem.Size = new System.Drawing.Size(151, 22); 165 | this.closeAllToolStripMenuItem.Text = "C&lose All"; 166 | this.closeAllToolStripMenuItem.Click += new System.EventHandler(this.CloseAllToolStripMenuItem_Click); 167 | // 168 | // arrangeIconsToolStripMenuItem 169 | // 170 | this.arrangeIconsToolStripMenuItem.Name = "arrangeIconsToolStripMenuItem"; 171 | this.arrangeIconsToolStripMenuItem.Size = new System.Drawing.Size(151, 22); 172 | this.arrangeIconsToolStripMenuItem.Text = "&Arrange Icons"; 173 | this.arrangeIconsToolStripMenuItem.Click += new System.EventHandler(this.ArrangeIconsToolStripMenuItem_Click); 174 | // 175 | // statusStrip 176 | // 177 | this.statusStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { 178 | this.toolStripStatusLabel}); 179 | this.statusStrip.Location = new System.Drawing.Point(0, 431); 180 | this.statusStrip.Name = "statusStrip"; 181 | this.statusStrip.Size = new System.Drawing.Size(632, 22); 182 | this.statusStrip.TabIndex = 2; 183 | this.statusStrip.Text = "StatusStrip"; 184 | // 185 | // toolStripStatusLabel 186 | // 187 | this.toolStripStatusLabel.ForeColor = System.Drawing.Color.Red; 188 | this.toolStripStatusLabel.Name = "toolStripStatusLabel"; 189 | this.toolStripStatusLabel.Size = new System.Drawing.Size(90, 17); 190 | this.toolStripStatusLabel.Text = "Not monitoring"; 191 | // 192 | // ILMonitorForm 193 | // 194 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 195 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 196 | this.ClientSize = new System.Drawing.Size(632, 453); 197 | this.Controls.Add(this.statusStrip); 198 | this.Controls.Add(this.menuStrip); 199 | this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); 200 | this.IsMdiContainer = true; 201 | this.MainMenuStrip = this.menuStrip; 202 | this.Name = "ILMonitorForm"; 203 | this.Text = "IL Monitor"; 204 | this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.ILMonitorForm_FormClosing); 205 | this.Load += new System.EventHandler(this.ILMonitorForm_Load); 206 | this.menuStrip.ResumeLayout(false); 207 | this.menuStrip.PerformLayout(); 208 | this.statusStrip.ResumeLayout(false); 209 | this.statusStrip.PerformLayout(); 210 | this.ResumeLayout(false); 211 | this.PerformLayout(); 212 | 213 | } 214 | #endregion 215 | 216 | 217 | private System.Windows.Forms.MenuStrip menuStrip; 218 | private System.Windows.Forms.StatusStrip statusStrip; 219 | private System.Windows.Forms.ToolStripSeparator toolStripSeparator5; 220 | private System.Windows.Forms.ToolStripStatusLabel toolStripStatusLabel; 221 | private System.Windows.Forms.ToolStripMenuItem tileHorizontalToolStripMenuItem; 222 | private System.Windows.Forms.ToolStripMenuItem fileMenu; 223 | private System.Windows.Forms.ToolStripMenuItem exitToolStripMenuItem; 224 | private System.Windows.Forms.ToolStripMenuItem windowsMenu; 225 | private System.Windows.Forms.ToolStripMenuItem cascadeToolStripMenuItem; 226 | private System.Windows.Forms.ToolStripMenuItem tileVerticalToolStripMenuItem; 227 | private System.Windows.Forms.ToolStripMenuItem closeAllToolStripMenuItem; 228 | private System.Windows.Forms.ToolStripMenuItem arrangeIconsToolStripMenuItem; 229 | private System.Windows.Forms.ToolTip ToolTip; 230 | private System.Windows.Forms.ToolStripMenuItem stopToolStripMenuItem; 231 | private System.Windows.Forms.ToolStripMenuItem startToolStripMenuItem; 232 | private System.Windows.Forms.ToolStripMenuItem optionsToolStripMenuItem; 233 | private System.Windows.Forms.ToolStripMenuItem autoStartToolStripMenuItem; 234 | private System.Windows.Forms.ToolStripMenuItem showStatusBarToolStripMenuItem; 235 | } 236 | } 237 | 238 | 239 | 240 | -------------------------------------------------------------------------------- /ILDebugging.Monitor/ILMonitorForm.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Drawing; 3 | using System.Windows.Forms; 4 | using ILDebugging.Monitor.Properties; 5 | using ILDebugging.Visualizer; 6 | 7 | namespace ILDebugging.Monitor 8 | { 9 | public partial class ILMonitorForm : Form 10 | { 11 | private AbstractXmlDataMonitor m_monitor; 12 | 13 | public ILMonitorForm() 14 | { 15 | InitializeComponent(); 16 | } 17 | 18 | private void ExitToolsStripMenuItem_Click(object sender, EventArgs e) => Application.Exit(); 19 | 20 | private void CascadeToolStripMenuItem_Click(object sender, EventArgs e) => LayoutMdi(MdiLayout.Cascade); 21 | private void TileVerticalToolStripMenuItem_Click(object sender, EventArgs e) => LayoutMdi(MdiLayout.TileVertical); 22 | private void TileHorizontalToolStripMenuItem_Click(object sender, EventArgs e) => LayoutMdi(MdiLayout.TileHorizontal); 23 | private void ArrangeIconsToolStripMenuItem_Click(object sender, EventArgs e) => LayoutMdi(MdiLayout.ArrangeIcons); 24 | 25 | private void CloseAllToolStripMenuItem_Click(object sender, EventArgs e) 26 | { 27 | foreach (var childForm in MdiChildren) 28 | childForm.Close(); 29 | } 30 | 31 | private void ILMonitorForm_Load(object sender, EventArgs e) 32 | { 33 | m_monitor = new TcpDataMonitor(port: 22017); 34 | 35 | m_monitor.MonitorStatusChange += OnMonitorStatusChange; 36 | m_monitor.VisualizerDataReady += OnVisualizerDataReady; 37 | 38 | if (Settings.Default.AutomaticallyStart) 39 | { 40 | autoStartToolStripMenuItem.Checked = true; 41 | m_monitor.Start(); 42 | } 43 | } 44 | 45 | private void OnMonitorStatusChange(object sender, MonitorStatusChangeEventArgs e) 46 | { 47 | if (e.Status == MonitorStatus.Monitoring) 48 | { 49 | toolStripStatusLabel.Text = "Monitoring"; 50 | toolStripStatusLabel.ForeColor = Color.Blue; 51 | startToolStripMenuItem.Enabled = false; 52 | stopToolStripMenuItem.Enabled = true; 53 | } 54 | else 55 | { 56 | toolStripStatusLabel.Text = "Not Monitoring"; 57 | toolStripStatusLabel.ForeColor = Color.Red; 58 | startToolStripMenuItem.Enabled = true; 59 | stopToolStripMenuItem.Enabled = false; 60 | } 61 | } 62 | 63 | private void OnVisualizerDataReady(object sender, VisualizerDataEventArgs e) 64 | { 65 | var mbi = e.VisualizerData; 66 | var childForm = FindOrCreateChildForm(mbi); 67 | 68 | var imbi = childForm.CurrentData != null 69 | ? IncrementalMethodBodyInfo.Create(mbi, childForm.CurrentData.LengthHistory) 70 | : IncrementalMethodBodyInfo.Create(mbi); 71 | 72 | childForm.UpdateWith(imbi); 73 | } 74 | 75 | private MiniBrowser FindOrCreateChildForm(MethodBodyInfo mbi) 76 | { 77 | foreach (var form in MdiChildren) 78 | { 79 | var miniBrowser = form as MiniBrowser; 80 | 81 | if (mbi.Identity == miniBrowser?.CurrentData?.Identity) 82 | { 83 | miniBrowser.Focus(); 84 | return miniBrowser; 85 | } 86 | } 87 | 88 | var newChild = new MiniBrowser 89 | { 90 | Text = mbi.MethodToString, 91 | MdiParent = this 92 | }; 93 | newChild.Show(); 94 | return newChild; 95 | } 96 | 97 | private void stopToolStripMenuItem_Click(object sender, EventArgs e) => m_monitor.Stop(); 98 | private void startToolStripMenuItem_Click(object sender, EventArgs e) => m_monitor.Start(); 99 | 100 | private void ILMonitorForm_FormClosing(object sender, FormClosingEventArgs e) 101 | { 102 | var s = Settings.Default; 103 | s.AutomaticallyStart = autoStartToolStripMenuItem.Checked; 104 | s.Save(); 105 | 106 | if (stopToolStripMenuItem.Enabled) 107 | { 108 | m_monitor.Stop(); 109 | } 110 | } 111 | 112 | private void autoStartToolStripMenuItem_Click(object sender, EventArgs e) 113 | { 114 | autoStartToolStripMenuItem.Checked = !autoStartToolStripMenuItem.Checked; 115 | } 116 | 117 | private void showStatusBarToolStripMenuItem_Click(object sender, EventArgs e) 118 | { 119 | statusStrip.Visible = showStatusBarToolStripMenuItem.Checked; 120 | } 121 | } 122 | } -------------------------------------------------------------------------------- /ILDebugging.Monitor/ILMonitorForm.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 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 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | 218, 17 122 | 123 | 124 | 17, 17 125 | 126 | 127 | 126, 17 128 | 129 | 130 | 51 131 | 132 | 133 | 134 | 135 | AAABAAMAEBAQAAAABAAoAQAANgAAACAgEAAAAAQA6AIAAF4BAAAQEAAAAAAIAGgFAABGBAAAKAAAABAA 136 | AAAgAAAAAQAEAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAIAAAACAgACAAAAAgACAAICA 137 | AACAgIAAwMDAAAAA/wAA/wAAAP//AP8AAAD/AP8A//8AAP///wAAAAAAAAAAAAB//4/4/48AAH//j/j/ 138 | jwAAeIiIiIiIAAB/d4d4d48AAH93h3h3jwAAeIiIiIiIAAB/d4d4d48AAH93h3h3jwAAeIiIiIiIAAB/ 139 | d4d4d48AAH93h3h3jwAAeIiIiIAAAAB//4/49/cAAH//j/j3cAAAd3d3d3cAAMABAADAAQAAwAEAAMAB 140 | AADAAQAAwAEAAMABAADAAQAAwAEAAMABAADAAQAAwAEAAMABAADAAwAAwAcAAMAPAAAoAAAAIAAAAEAA 141 | AAABAAQAAAAAAIACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAgAAAAICAAIAAAACAAIAAgIAAAICA 142 | gADAwMAAAAD/AAD/AAAA//8A/wAAAP8A/wD//wAA////AAAAAAAAAAAAAAAAAAAAAAAAB4iIiIiIiIiI 143 | iIiIiAAAAAf////4///4///4//gAAAAH////+P//+P//+P/4AAAAB/////j///j///j/+AAAAAf////4 144 | ///4///4//gAAAAH////+P//+P//+P/4AAAAB4iIiIiIiIiIiIiIiAAAAAf/eHh4eHh4eHh4//gAAAAH 145 | /4eHiIeHiIeHiP/4AAAAB/94eHh4eHh4eHj/+AAAAAf/h4eIh4eIh4eI//gAAAAH/3h4eHh4eHh4eP/4 146 | AAAAB4iIiIiIiIiIiIiIiAAAAAf/eHh4eHh4eHh4//gAAAAH/4eHiIeHiIeHiP/4AAAAB/94eHh4eHh4 147 | eHj/+AAAAAf/h4eIh4eIh4eI//gAAAAH/3h4eHh4eHh4eP/4AAAAB4iIiIiIiIiIiIiIiAAAAAf/eHh4 148 | eHh4eHh4//gAAAAH/4eHiIeHiIeHiP/4AAAAB/94eHh4eHh4eHj/+AAAAAf/h4eIh4eIh4eI//gAAAAH 149 | /3h4eHh4eHh4eP/4AAAAB4iIiIiIiIiIiHAAAAAAAAf////4///4//9/+HAAAAAH////+P//+P//f4cA 150 | AAAAB/////j///j//3hwAAAAAAf////4///4//93AAAAAAAH////+P//+P//cAAAAAAAB3d3d3d3d3d3 151 | d3AAAAAA4AAAB+AAAAfgAAAH4AAAB+AAAAfgAAAH4AAAB+AAAAfgAAAH4AAAB+AAAAfgAAAH4AAAB+AA 152 | AAfgAAAH4AAAB+AAAAfgAAAH4AAAB+AAAAfgAAAH4AAAB+AAAAfgAAAH4AAAB+AAAAfgAAAP4AAAH+AA 153 | AD/gAAB/4AAA/+AAAf8oAAAAEAAAACAAAAABAAgAAAAAAAABAAAAAAAAAAAAAAABAAAAAQAAAAAAAAAA 154 | gAAAgAAAAICAAIAAAACAAIAAgIAAAMDAwADA3MAA8MqmAAQEBAAICAgADAwMABEREQAWFhYAHBwcACIi 155 | IgApKSkAVVVVAE1NTQBCQkIAOTk5AIB8/wBQUP8AkwDWAP/szADG1u8A1ufnAJCprQAAADMAAABmAAAA 156 | mQAAAMwAADMAAAAzMwAAM2YAADOZAAAzzAAAM/8AAGYAAABmMwAAZmYAAGaZAABmzAAAZv8AAJkAAACZ 157 | MwAAmWYAAJmZAACZzAAAmf8AAMwAAADMMwAAzGYAAMyZAADMzAAAzP8AAP9mAAD/mQAA/8wAMwAAADMA 158 | MwAzAGYAMwCZADMAzAAzAP8AMzMAADMzMwAzM2YAMzOZADMzzAAzM/8AM2YAADNmMwAzZmYAM2aZADNm 159 | zAAzZv8AM5kAADOZMwAzmWYAM5mZADOZzAAzmf8AM8wAADPMMwAzzGYAM8yZADPMzAAzzP8AM/8zADP/ 160 | ZgAz/5kAM//MADP//wBmAAAAZgAzAGYAZgBmAJkAZgDMAGYA/wBmMwAAZjMzAGYzZgBmM5kAZjPMAGYz 161 | /wBmZgAAZmYzAGZmZgBmZpkAZmbMAGaZAABmmTMAZplmAGaZmQBmmcwAZpn/AGbMAABmzDMAZsyZAGbM 162 | zABmzP8AZv8AAGb/MwBm/5kAZv/MAMwA/wD/AMwAmZkAAJkzmQCZAJkAmQDMAJkAAACZMzMAmQBmAJkz 163 | zACZAP8AmWYAAJlmMwCZM2YAmWaZAJlmzACZM/8AmZkzAJmZZgCZmZkAmZnMAJmZ/wCZzAAAmcwzAGbM 164 | ZgCZzJkAmczMAJnM/wCZ/wAAmf8zAJnMZgCZ/5kAmf/MAJn//wDMAAAAmQAzAMwAZgDMAJkAzADMAJkz 165 | AADMMzMAzDNmAMwzmQDMM8wAzDP/AMxmAADMZjMAmWZmAMxmmQDMZswAmWb/AMyZAADMmTMAzJlmAMyZ 166 | mQDMmcwAzJn/AMzMAADMzDMAzMxmAMzMmQDMzMwAzMz/AMz/AADM/zMAmf9mAMz/mQDM/8wAzP//AMwA 167 | MwD/AGYA/wCZAMwzAAD/MzMA/zNmAP8zmQD/M8wA/zP/AP9mAAD/ZjMAzGZmAP9mmQD/ZswAzGb/AP+Z 168 | AAD/mTMA/5lmAP+ZmQD/mcwA/5n/AP/MAAD/zDMA/8xmAP/MmQD/zMwA/8z/AP//MwDM/2YA//+ZAP// 169 | zABmZv8AZv9mAGb//wD/ZmYA/2b/AP//ZgAhAKUAX19fAHd3dwCGhoYAlpaWAMvLywCysrIA19fXAN3d 170 | 3QDj4+MA6urqAPHx8QD4+PgA8Pv/AKSgoACAgIAAAAD/AAD/AAAA//8A/wAAAP8A/wD//wAA////AAoK 171 | CgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgUFBQUFBQUFBQUKCgoKCgUFBQUFBQUFBQUF 172 | CgoKCqurq6urq6urq6sFBQoKCgqrq6v//////6urBQUKCgoKq6v//6ur//+rqwUFCgoKCqur//+rq/// 173 | q6sFBQoKCgqrq///q6v//6urBQUKCgoKq6v//6ur//+rqwUFCgoKCqurq///////q6sFBQoKCgqrq6ur 174 | q6v//6urBQoKCgoKq6urq6ur//+rqwUKCgoKCqurq6urq///q6sKCgoKCgoKCgoKCgoKCgoKCgoKCgoK 175 | CgoKCgoKCgoKCgoKCgr//wAA//8AAPADAADgAwAAwAMAAMADAADAAwAAwAMAAMADAADAAwAAwAMAAMAH 176 | AADABwAAwA8AAP//AAD//wAA 177 | 178 | 179 | -------------------------------------------------------------------------------- /ILDebugging.Monitor/IncrementalData.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using ILDebugging.Visualizer; 5 | 6 | namespace ILDebugging.Monitor 7 | { 8 | [Serializable] 9 | public class IncrementalMethodBodyInfo 10 | { 11 | [Serializable] 12 | public class AgingInstruction 13 | { 14 | public int Age; 15 | public string ILString; 16 | } 17 | 18 | public int Identity; 19 | public string TypeName; 20 | public AgingInstruction[] Instructions; 21 | public string MethodToString; 22 | 23 | // hidden field 24 | public List LengthHistory; 25 | 26 | public static IncrementalMethodBodyInfo Create(MethodBodyInfo mbi, IEnumerable history = null) 27 | { 28 | var imbi = new IncrementalMethodBodyInfo 29 | { 30 | Identity = mbi.Identity, 31 | TypeName = mbi.TypeName, 32 | MethodToString = mbi.MethodToString, 33 | Instructions = mbi.Instructions.Select(i => new AgingInstruction {ILString = i}).ToArray(), 34 | LengthHistory = new List(history ?? Enumerable.Empty()) {mbi.Instructions.Count} 35 | }; 36 | 37 | for (var i = 0; i < imbi.LengthHistory.Count - 1; i++) 38 | { 39 | for (var a = imbi.LengthHistory[i]; a < imbi.LengthHistory[i + 1]; a++) 40 | { 41 | imbi.Instructions[a].Age = i + 1; 42 | } 43 | } 44 | 45 | return imbi; 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /ILDebugging.Monitor/MiniBrowser.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace ILDebugging.Monitor { 2 | partial class MiniBrowser { 3 | /// 4 | /// Required designer variable. 5 | /// 6 | private System.ComponentModel.IContainer components = null; 7 | 8 | /// 9 | /// Clean up any resources being used. 10 | /// 11 | /// true if managed resources should be disposed; otherwise, false. 12 | protected override void Dispose(bool disposing) { 13 | if (disposing && (components != null)) { 14 | components.Dispose(); 15 | } 16 | base.Dispose(disposing); 17 | } 18 | 19 | #region Windows Form Designer generated code 20 | 21 | /// 22 | /// Required method for Designer support - do not modify 23 | /// the contents of this method with the code editor. 24 | /// 25 | private void InitializeComponent() { 26 | System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MiniBrowser)); 27 | this.webBrowser = new System.Windows.Forms.WebBrowser(); 28 | this.SuspendLayout(); 29 | // 30 | // webBrowser 31 | // 32 | this.webBrowser.Dock = System.Windows.Forms.DockStyle.Fill; 33 | this.webBrowser.Location = new System.Drawing.Point(0, 0); 34 | this.webBrowser.MinimumSize = new System.Drawing.Size(20, 20); 35 | this.webBrowser.Name = "webBrowser"; 36 | this.webBrowser.Size = new System.Drawing.Size(284, 264); 37 | this.webBrowser.TabIndex = 0; 38 | // 39 | // MiniBrowser 40 | // 41 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 42 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 43 | this.ClientSize = new System.Drawing.Size(284, 264); 44 | this.Controls.Add(this.webBrowser); 45 | this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); 46 | this.Name = "MiniBrowser"; 47 | this.Text = "ILStream"; 48 | this.ResumeLayout(false); 49 | 50 | } 51 | 52 | #endregion 53 | 54 | private System.Windows.Forms.WebBrowser webBrowser; 55 | } 56 | } 57 | 58 | -------------------------------------------------------------------------------- /ILDebugging.Monitor/MiniBrowser.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | using System.Windows.Forms; 3 | using System.Xml; 4 | using System.Xml.Serialization; 5 | using System.Xml.Xsl; 6 | using ILDebugging.Monitor.Properties; 7 | 8 | namespace ILDebugging.Monitor 9 | { 10 | public partial class MiniBrowser : Form 11 | { 12 | public MiniBrowser() 13 | { 14 | InitializeComponent(); 15 | } 16 | 17 | public IncrementalMethodBodyInfo CurrentData { get; private set; } 18 | 19 | public void UpdateWith(IncrementalMethodBodyInfo imbi) 20 | { 21 | CurrentData = imbi; 22 | 23 | var xslt = new XslCompiledTransform(); 24 | using (var sr = new StringReader(Resources.XSLT)) 25 | { 26 | using (var xtr = new XmlTextReader(sr)) 27 | { 28 | xslt.Load(xtr); 29 | } 30 | } 31 | 32 | var serializer = new XmlSerializer(typeof(IncrementalMethodBodyInfo)); 33 | using (var beforeTransform = new MemoryStream()) 34 | { 35 | var afterTransform = new MemoryStream(); 36 | serializer.Serialize(beforeTransform, CurrentData); 37 | 38 | beforeTransform.Position = 0; 39 | using (var reader = new XmlTextReader(beforeTransform)) 40 | { 41 | xslt.Transform(reader, null, afterTransform); 42 | } 43 | 44 | afterTransform.Position = 0; 45 | webBrowser.DocumentStream = afterTransform; 46 | } 47 | } 48 | } 49 | } -------------------------------------------------------------------------------- /ILDebugging.Monitor/MiniBrowser.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 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 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | 122 | 123 | AAABAAMAEBAQAAAABAAoAQAANgAAACAgEAAAAAQA6AIAAF4BAAAQEAAAAAAIAGgFAABGBAAAKAAAABAA 124 | AAAgAAAAAQAEAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAIAAAACAgACAAAAAgACAAICA 125 | AACAgIAAwMDAAAAA/wAA/wAAAP//AP8AAAD/AP8A//8AAP///wAAAAAAAAAAAAB//4/4/48AAH//j/j/ 126 | jwAAeIiIiIiIAAB/d4d4d48AAH93h3h3jwAAeIiIiIiIAAB/d4d4d48AAH93h3h3jwAAeIiIiIiIAAB/ 127 | d4d4d48AAH93h3h3jwAAeIiIiIAAAAB//4/49/cAAH//j/j3cAAAd3d3d3cAAMABAADAAQAAwAEAAMAB 128 | AADAAQAAwAEAAMABAADAAQAAwAEAAMABAADAAQAAwAEAAMABAADAAwAAwAcAAMAPAAAoAAAAIAAAAEAA 129 | AAABAAQAAAAAAIACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAgAAAAICAAIAAAACAAIAAgIAAAICA 130 | gADAwMAAAAD/AAD/AAAA//8A/wAAAP8A/wD//wAA////AAAAAAAAAAAAAAAAAAAAAAAAB4iIiIiIiIiI 131 | iIiIiAAAAAf////4///4///4//gAAAAH////+P//+P//+P/4AAAAB/////j///j///j/+AAAAAf////4 132 | ///4///4//gAAAAH////+P//+P//+P/4AAAAB4iIiIiIiIiIiIiIiAAAAAf/eHh4eHh4eHh4//gAAAAH 133 | /4eHiIeHiIeHiP/4AAAAB/94eHh4eHh4eHj/+AAAAAf/h4eIh4eIh4eI//gAAAAH/3h4eHh4eHh4eP/4 134 | AAAAB4iIiIiIiIiIiIiIiAAAAAf/eHh4eHh4eHh4//gAAAAH/4eHiIeHiIeHiP/4AAAAB/94eHh4eHh4 135 | eHj/+AAAAAf/h4eIh4eIh4eI//gAAAAH/3h4eHh4eHh4eP/4AAAAB4iIiIiIiIiIiIiIiAAAAAf/eHh4 136 | eHh4eHh4//gAAAAH/4eHiIeHiIeHiP/4AAAAB/94eHh4eHh4eHj/+AAAAAf/h4eIh4eIh4eI//gAAAAH 137 | /3h4eHh4eHh4eP/4AAAAB4iIiIiIiIiIiHAAAAAAAAf////4///4//9/+HAAAAAH////+P//+P//f4cA 138 | AAAAB/////j///j//3hwAAAAAAf////4///4//93AAAAAAAH////+P//+P//cAAAAAAAB3d3d3d3d3d3 139 | d3AAAAAA4AAAB+AAAAfgAAAH4AAAB+AAAAfgAAAH4AAAB+AAAAfgAAAH4AAAB+AAAAfgAAAH4AAAB+AA 140 | AAfgAAAH4AAAB+AAAAfgAAAH4AAAB+AAAAfgAAAH4AAAB+AAAAfgAAAH4AAAB+AAAAfgAAAP4AAAH+AA 141 | AD/gAAB/4AAA/+AAAf8oAAAAEAAAACAAAAABAAgAAAAAAAABAAAAAAAAAAAAAAABAAAAAQAAAAAAAAAA 142 | gAAAgAAAAICAAIAAAACAAIAAgIAAAMDAwADA3MAA8MqmAAQEBAAICAgADAwMABEREQAWFhYAHBwcACIi 143 | IgApKSkAVVVVAE1NTQBCQkIAOTk5AIB8/wBQUP8AkwDWAP/szADG1u8A1ufnAJCprQAAADMAAABmAAAA 144 | mQAAAMwAADMAAAAzMwAAM2YAADOZAAAzzAAAM/8AAGYAAABmMwAAZmYAAGaZAABmzAAAZv8AAJkAAACZ 145 | MwAAmWYAAJmZAACZzAAAmf8AAMwAAADMMwAAzGYAAMyZAADMzAAAzP8AAP9mAAD/mQAA/8wAMwAAADMA 146 | MwAzAGYAMwCZADMAzAAzAP8AMzMAADMzMwAzM2YAMzOZADMzzAAzM/8AM2YAADNmMwAzZmYAM2aZADNm 147 | zAAzZv8AM5kAADOZMwAzmWYAM5mZADOZzAAzmf8AM8wAADPMMwAzzGYAM8yZADPMzAAzzP8AM/8zADP/ 148 | ZgAz/5kAM//MADP//wBmAAAAZgAzAGYAZgBmAJkAZgDMAGYA/wBmMwAAZjMzAGYzZgBmM5kAZjPMAGYz 149 | /wBmZgAAZmYzAGZmZgBmZpkAZmbMAGaZAABmmTMAZplmAGaZmQBmmcwAZpn/AGbMAABmzDMAZsyZAGbM 150 | zABmzP8AZv8AAGb/MwBm/5kAZv/MAMwA/wD/AMwAmZkAAJkzmQCZAJkAmQDMAJkAAACZMzMAmQBmAJkz 151 | zACZAP8AmWYAAJlmMwCZM2YAmWaZAJlmzACZM/8AmZkzAJmZZgCZmZkAmZnMAJmZ/wCZzAAAmcwzAGbM 152 | ZgCZzJkAmczMAJnM/wCZ/wAAmf8zAJnMZgCZ/5kAmf/MAJn//wDMAAAAmQAzAMwAZgDMAJkAzADMAJkz 153 | AADMMzMAzDNmAMwzmQDMM8wAzDP/AMxmAADMZjMAmWZmAMxmmQDMZswAmWb/AMyZAADMmTMAzJlmAMyZ 154 | mQDMmcwAzJn/AMzMAADMzDMAzMxmAMzMmQDMzMwAzMz/AMz/AADM/zMAmf9mAMz/mQDM/8wAzP//AMwA 155 | MwD/AGYA/wCZAMwzAAD/MzMA/zNmAP8zmQD/M8wA/zP/AP9mAAD/ZjMAzGZmAP9mmQD/ZswAzGb/AP+Z 156 | AAD/mTMA/5lmAP+ZmQD/mcwA/5n/AP/MAAD/zDMA/8xmAP/MmQD/zMwA/8z/AP//MwDM/2YA//+ZAP// 157 | zABmZv8AZv9mAGb//wD/ZmYA/2b/AP//ZgAhAKUAX19fAHd3dwCGhoYAlpaWAMvLywCysrIA19fXAN3d 158 | 3QDj4+MA6urqAPHx8QD4+PgA8Pv/AKSgoACAgIAAAAD/AAD/AAAA//8A/wAAAP8A/wD//wAA////AAoK 159 | CgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgUFBQUFBQUFBQUKCgoKCgUFBQUFBQUFBQUF 160 | CgoKCqurq6urq6urq6sFBQoKCgqrq6v//////6urBQUKCgoKq6v//6ur//+rqwUFCgoKCqur//+rq/// 161 | q6sFBQoKCgqrq///q6v//6urBQUKCgoKq6v//6ur//+rqwUFCgoKCqurq///////q6sFBQoKCgqrq6ur 162 | q6v//6urBQoKCgoKq6urq6ur//+rqwUKCgoKCqurq6urq///q6sKCgoKCgoKCgoKCgoKCgoKCgoKCgoK 163 | CgoKCgoKCgoKCgoKCgr//wAA//8AAPADAADgAwAAwAMAAMADAADAAwAAwAMAAMADAADAAwAAwAMAAMAH 164 | AADABwAAwA8AAP//AAD//wAA 165 | 166 | 167 | -------------------------------------------------------------------------------- /ILDebugging.Monitor/MonitorHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | using System.IO; 4 | using System.Net; 5 | using System.Net.Sockets; 6 | using System.Threading; 7 | using System.Windows.Forms; 8 | using System.Xml.Serialization; 9 | 10 | namespace ILDebugging.Monitor 11 | { 12 | public class VisualizerDataEventArgs : EventArgs 13 | { 14 | public readonly T VisualizerData; 15 | 16 | public VisualizerDataEventArgs(T data) 17 | { 18 | VisualizerData = data; 19 | } 20 | } 21 | 22 | public class MonitorStatusChangeEventArgs : EventArgs 23 | { 24 | public readonly MonitorStatus Status; 25 | 26 | public MonitorStatusChangeEventArgs(MonitorStatus status) 27 | { 28 | Status = status; 29 | } 30 | } 31 | 32 | public enum MonitorStatus 33 | { 34 | NotMonitoring, 35 | Monitoring 36 | } 37 | 38 | public abstract class AbstractXmlDataMonitor 39 | { 40 | public abstract void Start(); 41 | public abstract void Stop(); 42 | 43 | public delegate void VisualizerDataReadyEventHandler(object sender, VisualizerDataEventArgs e); 44 | 45 | public delegate void MonitorStatusChangeEventHandler(object sender, MonitorStatusChangeEventArgs e); 46 | 47 | public event VisualizerDataReadyEventHandler VisualizerDataReady; 48 | public event MonitorStatusChangeEventHandler MonitorStatusChange; 49 | 50 | protected void FireStatusChangeEvent(MonitorStatus status) 51 | { 52 | if (MonitorStatusChange != null) 53 | { 54 | var args = new MonitorStatusChangeEventArgs(status); 55 | 56 | if (MonitorStatusChange.Target is Control targetCtrl) 57 | { 58 | targetCtrl.Invoke(MonitorStatusChange, this, args); 59 | } 60 | else 61 | { 62 | MonitorStatusChange(this, args); 63 | } 64 | } 65 | } 66 | 67 | protected void FireDataReadyEvent(T data) 68 | { 69 | if (VisualizerDataReady != null) 70 | { 71 | var args = new VisualizerDataEventArgs(data); 72 | 73 | if (VisualizerDataReady.Target is Control targetCtrl) 74 | { 75 | targetCtrl.Invoke(VisualizerDataReady, this, args); 76 | } 77 | else 78 | { 79 | VisualizerDataReady(this, args); 80 | } 81 | } 82 | } 83 | } 84 | 85 | public class TcpDataMonitor : AbstractXmlDataMonitor 86 | { 87 | private TcpListener m_listener; 88 | private Thread m_listenerThread; 89 | private readonly int m_port; 90 | 91 | public TcpDataMonitor(int port) 92 | { 93 | m_port = port; 94 | } 95 | 96 | private void ListenerThread() 97 | { 98 | m_listener = new TcpListener(IPAddress.Parse("127.0.0.1"), m_port); 99 | m_listener.Start(); 100 | 101 | try 102 | { 103 | while (true) 104 | { 105 | while (!m_listener.Pending()) 106 | { 107 | Thread.Sleep(1000); 108 | } 109 | var client = m_listener.AcceptTcpClient(); 110 | ThreadPool.QueueUserWorkItem(delegate { HandleConnection(client); }); 111 | } 112 | } 113 | catch (Exception ex) 114 | { 115 | Debug.WriteLine(ex); 116 | } 117 | finally 118 | { 119 | m_listener.Stop(); 120 | } 121 | } 122 | 123 | private void HandleConnection(TcpClient client) 124 | { 125 | using (client) 126 | using (var network = client.GetStream()) 127 | { 128 | var memory = new MemoryStream(); 129 | var buffer = new byte[1024]; 130 | 131 | while (true) 132 | { 133 | var received = network.Read(buffer, 0, 1024); 134 | if (received == 0) 135 | break; 136 | memory.Write(buffer, 0, received); 137 | } 138 | 139 | memory.Position = 0; 140 | 141 | var data = (T)new XmlSerializer(typeof(T)).Deserialize(memory); 142 | 143 | FireDataReadyEvent(data); 144 | } 145 | } 146 | 147 | public override void Start() 148 | { 149 | m_listenerThread = new Thread(ListenerThread); 150 | m_listenerThread.Start(); 151 | FireStatusChangeEvent(MonitorStatus.Monitoring); 152 | } 153 | 154 | public override void Stop() 155 | { 156 | m_listenerThread.Abort(); 157 | FireStatusChangeEvent(MonitorStatus.NotMonitoring); 158 | } 159 | } 160 | } 161 | -------------------------------------------------------------------------------- /ILDebugging.Monitor/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Windows.Forms; 3 | 4 | namespace ILDebugging.Monitor 5 | { 6 | internal static class Program 7 | { 8 | [STAThread] 9 | private static void Main() 10 | { 11 | Application.EnableVisualStyles(); 12 | Application.SetCompatibleTextRenderingDefault(false); 13 | Application.Run(new ILMonitorForm()); 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /ILDebugging.Monitor/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | // General Information about an assembly is controlled through the following 5 | // set of attributes. Change these attribute values to modify the information 6 | // associated with an assembly. 7 | 8 | [assembly: AssemblyTitle("ILDebugging.Monitor")] 9 | [assembly: AssemblyDescription("Receives and displays IL data from debuggees.")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("Microsoft")] 12 | [assembly: AssemblyProduct("ILDebugging.Monitor")] 13 | [assembly: AssemblyCopyright("Copyright © 2006")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | 21 | [assembly: ComVisible(false)] 22 | 23 | // The following GUID is for the ID of the typelib if this project is exposed to COM 24 | 25 | [assembly: Guid("b617795a-39df-4022-a9eb-c0caa098bdaf")] 26 | 27 | // Version information for an assembly consists of the following four values: 28 | // 29 | // Major Version 30 | // Minor Version 31 | // Build Number 32 | // Revision 33 | // 34 | 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] -------------------------------------------------------------------------------- /ILDebugging.Monitor/Properties/Resources.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace ILDebugging.Monitor.Properties { 12 | using System; 13 | 14 | 15 | /// 16 | /// A strongly-typed resource class, for looking up localized strings, etc. 17 | /// 18 | // This class was auto-generated by the StronglyTypedResourceBuilder 19 | // class via a tool like ResGen or Visual Studio. 20 | // To add or remove a member, edit your .ResX file then rerun ResGen 21 | // with the /str option, or rebuild your VS project. 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | internal class Resources { 26 | 27 | private static global::System.Resources.ResourceManager resourceMan; 28 | 29 | private static global::System.Globalization.CultureInfo resourceCulture; 30 | 31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 32 | internal Resources() { 33 | } 34 | 35 | /// 36 | /// Returns the cached ResourceManager instance used by this class. 37 | /// 38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 39 | internal static global::System.Resources.ResourceManager ResourceManager { 40 | get { 41 | if (object.ReferenceEquals(resourceMan, null)) { 42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("ILDebugging.Monitor.Properties.Resources", typeof(Resources).Assembly); 43 | resourceMan = temp; 44 | } 45 | return resourceMan; 46 | } 47 | } 48 | 49 | /// 50 | /// Overrides the current thread's CurrentUICulture property for all 51 | /// resource lookups using this strongly typed resource class. 52 | /// 53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 54 | internal static global::System.Globalization.CultureInfo Culture { 55 | get { 56 | return resourceCulture; 57 | } 58 | set { 59 | resourceCulture = value; 60 | } 61 | } 62 | 63 | /// 64 | /// Looks up a localized string similar to <?xml version="1.0" encoding="UTF-8" ?> 65 | ///<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 66 | /// <xsl:output method="html"/> 67 | /// 68 | /// <xsl:attribute-set name="alternate"> 69 | /// <xsl:attribute name="class"> 70 | /// <xsl:apply-templates select="." mode="alternate"/> 71 | /// </xsl:attribute> 72 | /// </xsl:attribute-set> 73 | /// 74 | /// <xsl:template match="AgingInstruction" mode="alternate"> 75 | /// <xsl:choose> 76 | /// <xsl:when test="Age mod 3 = 0">first</xsl:when> 77 | /// <xsl:when test="Age mod 3 = 1">second< [rest of string was truncated]";. 78 | /// 79 | internal static string XSLT { 80 | get { 81 | return ResourceManager.GetString("XSLT", resourceCulture); 82 | } 83 | } 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /ILDebugging.Monitor/Properties/Resources.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 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 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | 122 | ..\Resources\XSLT.txt;System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252 123 | 124 | -------------------------------------------------------------------------------- /ILDebugging.Monitor/Properties/Settings.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace ILDebugging.Monitor.Properties { 12 | 13 | 14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.5.0.0")] 16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { 17 | 18 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); 19 | 20 | public static Settings Default { 21 | get { 22 | return defaultInstance; 23 | } 24 | } 25 | 26 | [global::System.Configuration.UserScopedSettingAttribute()] 27 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 28 | [global::System.Configuration.DefaultSettingValueAttribute("True")] 29 | public bool AutomaticallyStart { 30 | get { 31 | return ((bool)(this["AutomaticallyStart"])); 32 | } 33 | set { 34 | this["AutomaticallyStart"] = value; 35 | } 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /ILDebugging.Monitor/Properties/Settings.settings: -------------------------------------------------------------------------------- 1 |  2 | 3 | 5 | 6 | 7 | 8 | True 9 | 10 | 11 | -------------------------------------------------------------------------------- /ILDebugging.Monitor/Resources/XSLT.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | first 14 | second 15 | third 16 | 17 | 18 | 19 | 20 | 21 | 22 | 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 |
-------------------------------------------------------------------------------- /ILDebugging.Monitor/app.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /ILDebugging.Sample/ILDebugging.Sample.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Debug 5 | AnyCPU 6 | 8.0.50727 7 | 2.0 8 | {5BF03C0A-2F42-4538-B373-8B2BE569350A} 9 | Exe 10 | Properties 11 | ILDebugging.Sample 12 | ILDebugging.Sample 13 | v4.6 14 | 15 | 16 | 17 | 18 | 2.0 19 | publish\ 20 | true 21 | Disk 22 | false 23 | Foreground 24 | 7 25 | Days 26 | false 27 | false 28 | true 29 | 0 30 | 1.0.0.%2a 31 | false 32 | false 33 | true 34 | 35 | 36 | 37 | true 38 | full 39 | false 40 | bin\Debug\ 41 | DEBUG;TRACE 42 | prompt 43 | 4 44 | false 45 | 46 | 47 | pdbonly 48 | true 49 | bin\Release\ 50 | TRACE 51 | prompt 52 | 4 53 | false 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | {6F6E9FC5-40A9-4ABD-89F3-EF7B6406F07B} 66 | ILDebugging.Visualizer 67 | 68 | 69 | 70 | 71 | False 72 | .NET Framework 3.5 SP1 Client Profile 73 | false 74 | 75 | 76 | False 77 | .NET Framework 3.5 SP1 78 | true 79 | 80 | 81 | False 82 | Windows Installer 3.1 83 | true 84 | 85 | 86 | 87 | 88 | 89 | 90 | 97 | -------------------------------------------------------------------------------- /ILDebugging.Sample/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection.Emit; 3 | using System.Runtime.CompilerServices; 4 | using ILDebugging.Visualizer; 5 | using Microsoft.VisualStudio.DebuggerVisualizers; 6 | 7 | namespace ILDebugging.Sample 8 | { 9 | internal class Foo 10 | { 11 | [MethodImpl(MethodImplOptions.NoInlining)] 12 | public string MyMethod(string x) 13 | { 14 | Console.WriteLine(x); 15 | return x; 16 | } 17 | } 18 | 19 | internal class Program 20 | { 21 | private static void Main() 22 | { 23 | var dm = new DynamicMethod("MyMethodWrapper", typeof(object), new[] {typeof(object[])}, typeof(Program), skipVisibility: true); 24 | var il = dm.GetILGenerator(); 25 | var l1 = il.DefineLabel(); 26 | var returnLocal = il.DeclareLocal(typeof(object)); 27 | 28 | // grab the method parameters of the method we wish to wrap 29 | var method = typeof(Foo).GetMethod(nameof(Foo.MyMethod)); 30 | var methodParameters = method.GetParameters(); 31 | var parameterLength = methodParameters.Length; 32 | 33 | // check to see if the call to MyMethodWrapper has the required amount of arguments in the object[] array. 34 | il.Emit(OpCodes.Ldarg_0); 35 | il.Emit(OpCodes.Ldlen); 36 | il.Emit(OpCodes.Conv_I4); 37 | il.Emit(OpCodes.Ldc_I4, parameterLength + 1); 38 | il.Emit(OpCodes.Beq_S, l1); 39 | il.Emit(OpCodes.Ldstr, "insufficient arguments"); 40 | il.Emit(OpCodes.Newobj, typeof(ArgumentException).GetConstructor(new[] {typeof(string)})); 41 | il.Emit(OpCodes.Throw); 42 | il.MarkLabel(l1); 43 | 44 | // pull out the Foo instance from the first element in the object[] args array 45 | il.Emit(OpCodes.Ldarg_0); 46 | il.Emit(OpCodes.Ldc_I4_0); 47 | il.Emit(OpCodes.Ldelem_Ref); 48 | // cast the instance to Foo 49 | il.Emit(OpCodes.Castclass, typeof(Foo)); 50 | 51 | // pull out the parameters to the instance method call and push them on to the IL stack 52 | for (var i = 0; i < parameterLength; i++) 53 | { 54 | il.Emit(OpCodes.Ldarg_0); 55 | il.Emit(OpCodes.Ldc_I4, i + 1); 56 | il.Emit(OpCodes.Ldelem_Ref); 57 | 58 | // we've special cased it, for this code example 59 | if (methodParameters[i].ParameterType == typeof(string)) 60 | { 61 | il.Emit(OpCodes.Castclass, typeof(string)); 62 | } 63 | 64 | // test or switch on parameter types, you'll need to cast to the respective type 65 | // ... 66 | } 67 | 68 | // call the wrapped method 69 | il.Emit(OpCodes.Call, method); 70 | // return what the method invocation returned 71 | il.Emit(OpCodes.Stloc, returnLocal); 72 | il.Emit(OpCodes.Ldloc, returnLocal); 73 | il.Emit(OpCodes.Ret); 74 | 75 | // Show the visualizer (via code) 76 | var developmentHost = new VisualizerDevelopmentHost( 77 | dm, 78 | typeof(MethodBodyVisualizer), 79 | typeof(MethodBodyObjectSource) 80 | ); 81 | 82 | developmentHost.ShowVisualizer(); 83 | } 84 | } 85 | } -------------------------------------------------------------------------------- /ILDebugging.Sample/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | // General Information about an assembly is controlled through the following 5 | // set of attributes. Change these attribute values to modify the information 6 | // associated with an assembly. 7 | 8 | [assembly: AssemblyTitle("ILDebugging.Sample")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("Microsoft")] 12 | [assembly: AssemblyProduct("")] 13 | [assembly: AssemblyCopyright("Copyright © 2006")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | 21 | [assembly: ComVisible(false)] 22 | 23 | // The following GUID is for the ID of the typelib if this project is exposed to COM 24 | 25 | [assembly: Guid("9d0aaae6-e8ce-48b2-a7ad-adb788ac2ee4")] 26 | 27 | // Version information for an assembly consists of the following four values: 28 | // 29 | // Major Version 30 | // Minor Version 31 | // Build Number 32 | // Revision 33 | // 34 | 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] -------------------------------------------------------------------------------- /ILDebugging.Sample/app.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /ILDebugging.Visualizer/ILDebugging.Visualizer.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Debug 5 | AnyCPU 6 | 8.0.50727 7 | 2.0 8 | {6F6E9FC5-40A9-4ABD-89F3-EF7B6406F07B} 9 | Library 10 | Properties 11 | ILDebugging.Visualizer 12 | ILDebugging.Visualizer 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 3.5 26 | v4.6 27 | publish\ 28 | true 29 | Disk 30 | false 31 | Foreground 32 | 7 33 | Days 34 | false 35 | false 36 | true 37 | 0 38 | 1.0.0.%2a 39 | false 40 | false 41 | true 42 | 43 | 44 | 45 | true 46 | full 47 | false 48 | bin\debug\ 49 | DEBUG;TRACE 50 | prompt 51 | 4 52 | false 53 | 54 | 55 | pdbonly 56 | true 57 | bin\Release\ 58 | TRACE 59 | prompt 60 | 4 61 | false 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | Form 77 | 78 | 79 | MethodBodyViewer.cs 80 | 81 | 82 | 83 | True 84 | True 85 | Settings.settings 86 | 87 | 88 | True 89 | True 90 | Resource.resx 91 | 92 | 93 | 94 | 95 | Designer 96 | MethodBodyViewer.cs 97 | 98 | 99 | Designer 100 | ResXFileCodeGenerator 101 | Resource.Designer.cs 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | SettingsSingleFileGenerator 110 | Settings.Designer.cs 111 | 112 | 113 | 114 | 115 | {3B40E8C3-C4E8-4085-9F82-F64308F3791C} 116 | ILDebugging.Decoder 117 | 118 | 119 | 120 | 121 | False 122 | .NET Framework 3.5 SP1 Client Profile 123 | false 124 | 125 | 126 | False 127 | .NET Framework 3.5 SP1 128 | true 129 | 130 | 131 | False 132 | Windows Installer 3.1 133 | true 134 | 135 | 136 | 137 | 144 | 145 | 146 | 147 | 148 | -------------------------------------------------------------------------------- /ILDebugging.Visualizer/MethodBodyInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Reflection; 4 | using ILDebugging.Decoder; 5 | 6 | namespace ILDebugging.Visualizer 7 | { 8 | [Serializable] 9 | public class MethodBodyInfo 10 | { 11 | public int Identity { get; set; } 12 | public string TypeName { get; set; } 13 | public string MethodToString { get; set; } 14 | public List Instructions { get; } = new List(); 15 | 16 | private void AddInstruction(string inst) 17 | { 18 | Instructions.Add(inst); 19 | } 20 | 21 | public static MethodBodyInfo Create(MethodBase method) 22 | { 23 | var mbi = new MethodBodyInfo 24 | { 25 | Identity = method.GetHashCode(), 26 | TypeName = method.GetType().Name, 27 | MethodToString = method.ToString() 28 | }; 29 | 30 | var visitor = new ReadableILStringVisitor( 31 | new MethodBodyInfoBuilder(mbi), 32 | DefaultFormatProvider.Instance); 33 | 34 | var reader = ILReaderFactory.Create(method); 35 | reader.Accept(visitor); 36 | 37 | return mbi; 38 | } 39 | 40 | private class MethodBodyInfoBuilder : IILStringCollector 41 | { 42 | private readonly MethodBodyInfo m_mbi; 43 | 44 | public MethodBodyInfoBuilder(MethodBodyInfo mbi) 45 | { 46 | m_mbi = mbi; 47 | } 48 | 49 | public void Process(ILInstruction instruction, string operandString) 50 | { 51 | m_mbi.AddInstruction($"IL_{instruction.Offset:x4}: {instruction.OpCode.Name,-10} {operandString}"); 52 | } 53 | } 54 | } 55 | } -------------------------------------------------------------------------------- /ILDebugging.Visualizer/MethodBodyNoVisualizer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | using System.IO; 4 | using System.Net; 5 | using System.Net.Sockets; 6 | using System.Reflection; 7 | using System.Runtime.Serialization.Formatters.Binary; 8 | using System.Windows.Forms; 9 | using System.Xml.Serialization; 10 | using ILDebugging.Visualizer; 11 | using Microsoft.VisualStudio.DebuggerVisualizers; 12 | 13 | [assembly: DebuggerVisualizer( 14 | typeof(MethodBodyNoVisualizer), 15 | typeof(MethodBodyObjectSource), 16 | Target = typeof(MethodBase), 17 | Description = "Send to IL Monitor") 18 | ] 19 | 20 | namespace ILDebugging.Visualizer 21 | { 22 | internal interface IXmlDataProvider 23 | { 24 | void Dump(T obj); 25 | } 26 | 27 | internal class TcpClientDataProvider : IXmlDataProvider 28 | { 29 | private readonly int m_portNumber; 30 | 31 | public TcpClientDataProvider(int port) 32 | { 33 | m_portNumber = port; 34 | } 35 | 36 | public void Dump(MethodBodyInfo mbi) 37 | { 38 | using (var tcpClient = new TcpClient()) 39 | { 40 | tcpClient.Connect(IPAddress.Parse("127.0.0.1"), m_portNumber); 41 | 42 | var memoryStream = new MemoryStream(); 43 | new XmlSerializer(typeof(MethodBodyInfo)).Serialize(memoryStream, mbi); 44 | 45 | memoryStream.Position = 0; 46 | 47 | using (var networkStream = tcpClient.GetStream()) 48 | memoryStream.CopyTo(networkStream); 49 | } 50 | } 51 | } 52 | 53 | public class MethodBodyNoVisualizer : DialogDebuggerVisualizer 54 | { 55 | protected override void Show(IDialogVisualizerService windowService, IVisualizerObjectProvider objectProvider) 56 | { 57 | try 58 | { 59 | MethodBodyInfo mbi; 60 | using (var output = objectProvider.GetData()) 61 | mbi = (MethodBodyInfo)new BinaryFormatter().Deserialize(output, null); 62 | 63 | IXmlDataProvider provider = new TcpClientDataProvider(port: 22017); 64 | provider.Dump(mbi); 65 | } 66 | catch (Exception ex) 67 | { 68 | MessageBox.Show(ex.Message, 69 | "Send to IL Monitor", 70 | MessageBoxButtons.OK, 71 | MessageBoxIcon.Error); 72 | } 73 | } 74 | } 75 | } -------------------------------------------------------------------------------- /ILDebugging.Visualizer/MethodBodyObjectSource.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Reflection; 4 | using System.Runtime.Serialization.Formatters.Binary; 5 | using Microsoft.VisualStudio.DebuggerVisualizers; 6 | 7 | namespace ILDebugging.Visualizer 8 | { 9 | public class MethodBodyObjectSource : VisualizerObjectSource 10 | { 11 | public override void GetData(object target, Stream outgoingData) 12 | { 13 | if (target is MethodBase method) 14 | { 15 | try 16 | { 17 | var mbi = MethodBodyInfo.Create(method); 18 | 19 | var formatter = new BinaryFormatter(); 20 | formatter.Serialize(outgoingData, mbi); 21 | } 22 | catch (Exception) 23 | { 24 | } 25 | } 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /ILDebugging.Visualizer/MethodBodyViewer.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace ILDebugging.Visualizer { 2 | partial class MethodBodyViewer { 3 | /// 4 | /// Required designer variable. 5 | /// 6 | private System.ComponentModel.IContainer components = null; 7 | 8 | /// 9 | /// Clean up any resources being used. 10 | /// 11 | /// true if managed resources should be disposed; otherwise, false. 12 | protected override void Dispose(bool disposing) { 13 | if (disposing && (components != null)) { 14 | components.Dispose(); 15 | } 16 | base.Dispose(disposing); 17 | } 18 | 19 | #region Windows Form Designer generated code 20 | 21 | /// 22 | /// Required method for Designer support - do not modify 23 | /// the contents of this method with the code editor. 24 | /// 25 | private void InitializeComponent() { 26 | this.components = new System.ComponentModel.Container(); 27 | System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MethodBodyViewer)); 28 | this.panel3 = new System.Windows.Forms.Panel(); 29 | this.lblMethodToString = new System.Windows.Forms.Label(); 30 | this.lblMethodGetType = new System.Windows.Forms.Label(); 31 | this.panel2 = new System.Windows.Forms.Panel(); 32 | this.richTextBox = new System.Windows.Forms.RichTextBox(); 33 | this.contextMenuStrip = new System.Windows.Forms.ContextMenuStrip(this.components); 34 | this.fontNameToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); 35 | this.fontSizeToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); 36 | this.panel3.SuspendLayout(); 37 | this.panel2.SuspendLayout(); 38 | this.contextMenuStrip.SuspendLayout(); 39 | this.SuspendLayout(); 40 | // 41 | // panel3 42 | // 43 | this.panel3.Controls.Add(this.lblMethodToString); 44 | this.panel3.Controls.Add(this.lblMethodGetType); 45 | this.panel3.Dock = System.Windows.Forms.DockStyle.Top; 46 | this.panel3.Location = new System.Drawing.Point(0, 0); 47 | this.panel3.Name = "panel3"; 48 | this.panel3.Size = new System.Drawing.Size(492, 25); 49 | this.panel3.TabIndex = 7; 50 | // 51 | // lblMethodToString 52 | // 53 | this.lblMethodToString.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 54 | | System.Windows.Forms.AnchorStyles.Right))); 55 | this.lblMethodToString.AutoSize = true; 56 | this.lblMethodToString.BackColor = System.Drawing.SystemColors.Control; 57 | this.lblMethodToString.Location = new System.Drawing.Point(110, 6); 58 | this.lblMethodToString.Name = "lblMethodToString"; 59 | this.lblMethodToString.Size = new System.Drawing.Size(93, 13); 60 | this.lblMethodToString.TabIndex = 1; 61 | this.lblMethodToString.Text = "lblMethodToString"; 62 | // 63 | // lblMethodGetType 64 | // 65 | this.lblMethodGetType.AutoSize = true; 66 | this.lblMethodGetType.Location = new System.Drawing.Point(3, 6); 67 | this.lblMethodGetType.Name = "lblMethodGetType"; 68 | this.lblMethodGetType.Size = new System.Drawing.Size(94, 13); 69 | this.lblMethodGetType.TabIndex = 1; 70 | this.lblMethodGetType.Text = "lblMethodGetType"; 71 | // 72 | // panel2 73 | // 74 | this.panel2.Controls.Add(this.richTextBox); 75 | this.panel2.Dock = System.Windows.Forms.DockStyle.Fill; 76 | this.panel2.Location = new System.Drawing.Point(0, 25); 77 | this.panel2.Name = "panel2"; 78 | this.panel2.Size = new System.Drawing.Size(492, 380); 79 | this.panel2.TabIndex = 8; 80 | // 81 | // richTextBox 82 | // 83 | this.richTextBox.BackColor = System.Drawing.SystemColors.Window; 84 | this.richTextBox.BorderStyle = System.Windows.Forms.BorderStyle.None; 85 | this.richTextBox.ContextMenuStrip = this.contextMenuStrip; 86 | this.richTextBox.Dock = System.Windows.Forms.DockStyle.Fill; 87 | this.richTextBox.Font = new System.Drawing.Font("Lucida Console", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 88 | this.richTextBox.ForeColor = System.Drawing.Color.Black; 89 | this.richTextBox.Location = new System.Drawing.Point(0, 0); 90 | this.richTextBox.Name = "richTextBox"; 91 | this.richTextBox.Size = new System.Drawing.Size(492, 380); 92 | this.richTextBox.TabIndex = 0; 93 | this.richTextBox.Text = ""; 94 | this.richTextBox.WordWrap = false; 95 | // 96 | // contextMenuStrip 97 | // 98 | this.contextMenuStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { 99 | this.fontNameToolStripMenuItem, 100 | this.fontSizeToolStripMenuItem}); 101 | this.contextMenuStrip.Name = "contextMenuStrip"; 102 | this.contextMenuStrip.Size = new System.Drawing.Size(134, 48); 103 | // 104 | // fontNameToolStripMenuItem 105 | // 106 | this.fontNameToolStripMenuItem.Name = "fontNameToolStripMenuItem"; 107 | this.fontNameToolStripMenuItem.Size = new System.Drawing.Size(133, 22); 108 | this.fontNameToolStripMenuItem.Text = "Font Name"; 109 | // 110 | // fontSizeToolStripMenuItem 111 | // 112 | this.fontSizeToolStripMenuItem.Name = "fontSizeToolStripMenuItem"; 113 | this.fontSizeToolStripMenuItem.Size = new System.Drawing.Size(133, 22); 114 | this.fontSizeToolStripMenuItem.Text = "Font Size"; 115 | // 116 | // MethodBodyViewer 117 | // 118 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 119 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 120 | this.ClientSize = new System.Drawing.Size(492, 405); 121 | this.Controls.Add(this.panel2); 122 | this.Controls.Add(this.panel3); 123 | this.Font = new System.Drawing.Font("Tahoma", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 124 | this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); 125 | this.KeyPreview = true; 126 | this.MinimumSize = new System.Drawing.Size(450, 300); 127 | this.Name = "MethodBodyViewer"; 128 | this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; 129 | this.Text = "IL Visualizer"; 130 | this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.MethodBodyViewer_FormClosing); 131 | this.Load += new System.EventHandler(this.MethodBodyViewer_Load); 132 | this.KeyUp += new System.Windows.Forms.KeyEventHandler(this.MethodForm_KeyUp); 133 | this.panel3.ResumeLayout(false); 134 | this.panel3.PerformLayout(); 135 | this.panel2.ResumeLayout(false); 136 | this.contextMenuStrip.ResumeLayout(false); 137 | this.ResumeLayout(false); 138 | 139 | } 140 | 141 | #endregion 142 | 143 | private System.Windows.Forms.Panel panel3; 144 | private System.Windows.Forms.Label lblMethodToString; 145 | private System.Windows.Forms.Label lblMethodGetType; 146 | private System.Windows.Forms.Panel panel2; 147 | private System.Windows.Forms.RichTextBox richTextBox; 148 | private System.Windows.Forms.ContextMenuStrip contextMenuStrip; 149 | private System.Windows.Forms.ToolStripMenuItem fontNameToolStripMenuItem; 150 | private System.Windows.Forms.ToolStripMenuItem fontSizeToolStripMenuItem; 151 | } 152 | } -------------------------------------------------------------------------------- /ILDebugging.Visualizer/MethodBodyViewer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Drawing; 4 | using System.Runtime.Serialization.Formatters.Binary; 5 | using System.Windows.Forms; 6 | using ILDebugging.Visualizer.Properties; 7 | using Microsoft.VisualStudio.DebuggerVisualizers; 8 | 9 | namespace ILDebugging.Visualizer 10 | { 11 | public partial class MethodBodyViewer : Form 12 | { 13 | public MethodBodyViewer() 14 | { 15 | InitializeComponent(); 16 | } 17 | 18 | public void SetObjectProvider(IVisualizerObjectProvider objectProvider) 19 | { 20 | MethodBodyInfo mbi; 21 | using (var output = objectProvider.GetData()) 22 | mbi = (MethodBodyInfo)new BinaryFormatter().Deserialize(output, null); 23 | 24 | lblMethodGetType.Text = mbi.TypeName; 25 | lblMethodToString.Text = mbi.MethodToString; 26 | richTextBox.Lines = mbi.Instructions.ToArray(); 27 | 28 | ActiveControl = richTextBox; 29 | } 30 | 31 | // allow ESC to close 32 | private void MethodForm_KeyUp(object sender, KeyEventArgs e) 33 | { 34 | if (e.KeyCode == Keys.Escape) 35 | Close(); 36 | } 37 | 38 | private void MethodBodyViewer_Load(object sender, EventArgs e) 39 | { 40 | LoadSettings(); 41 | BuildContextMenu(); 42 | } 43 | 44 | private void MethodBodyViewer_FormClosing(object sender, FormClosingEventArgs e) 45 | { 46 | SaveSettings(); 47 | } 48 | 49 | private string selectedFontName; 50 | private ToolStripMenuItem selectedFontNameMenuItem; 51 | private int selectedFontSize; 52 | private ToolStripMenuItem selectedFontSizeMenuItem; 53 | 54 | private void BuildContextMenu() 55 | { 56 | var fontCandidates = new[] {"Arial", "Consolas", "Courier New", "Lucida Console", "Tahoma"}; 57 | 58 | var fontChoices = new List(); 59 | if (Array.IndexOf(fontCandidates, selectedFontName) == -1) 60 | fontChoices.Add(selectedFontName); 61 | 62 | // only choose those available in current machine 63 | foreach (var ff in FontFamily.Families) 64 | { 65 | if (Array.IndexOf(fontCandidates, ff.Name) != -1) 66 | fontChoices.Add(ff.Name); 67 | } 68 | 69 | var nameCount = fontChoices.Count; 70 | var nameItems = new ToolStripMenuItem[nameCount]; 71 | for (var i = 0; i < nameCount; i++) 72 | { 73 | nameItems[i] = new ToolStripMenuItem(fontChoices[i], null, fontNameToolStripMenuItem_Click); 74 | if (fontChoices[i] == selectedFontName) 75 | { 76 | nameItems[i].Checked = true; 77 | selectedFontNameMenuItem = nameItems[i]; 78 | } 79 | } 80 | fontNameToolStripMenuItem.DropDownItems.AddRange(nameItems); 81 | 82 | var sizeChoices = new[] {9, 10, 11, 12, 14, 20}; 83 | var sizeCount = sizeChoices.Length; 84 | 85 | var sizeItems = new ToolStripMenuItem[sizeCount]; 86 | for (var i = 0; i < sizeCount; i++) 87 | { 88 | sizeItems[i] = new ToolStripMenuItem(sizeChoices[i].ToString(), null, fontSizeToolStripMenuItem_Click); 89 | if (sizeChoices[i] == selectedFontSize) 90 | { 91 | sizeItems[i].Checked = true; 92 | selectedFontSizeMenuItem = sizeItems[i]; 93 | } 94 | } 95 | fontSizeToolStripMenuItem.DropDownItems.AddRange(sizeItems); 96 | 97 | richTextBox.Font = new Font(selectedFontName, selectedFontSize); 98 | } 99 | 100 | private void LoadSettings() 101 | { 102 | var s = Settings.Default; 103 | 104 | Width = s.WindowWidth; 105 | Height = s.WindowHeight; 106 | Left = s.WindowLeft; 107 | Top = s.WindowTop; 108 | 109 | selectedFontName = s.FontName; 110 | selectedFontSize = s.FontSize; 111 | } 112 | 113 | private void SaveSettings() 114 | { 115 | var s = Settings.Default; 116 | 117 | s.WindowWidth = Width; 118 | s.WindowHeight = Height; 119 | s.WindowLeft = Left; 120 | s.WindowTop = Top; 121 | 122 | s.FontName = selectedFontName; 123 | s.FontSize = selectedFontSize; 124 | 125 | s.Save(); 126 | } 127 | 128 | private void fontNameToolStripMenuItem_Click(object sender, EventArgs e) 129 | { 130 | selectedFontNameMenuItem.Checked = false; 131 | selectedFontNameMenuItem = (ToolStripMenuItem)sender; 132 | selectedFontNameMenuItem.Checked = true; 133 | 134 | selectedFontName = selectedFontNameMenuItem.Text; 135 | richTextBox.Font = new Font(selectedFontName, richTextBox.Font.Size); 136 | Update(); 137 | } 138 | 139 | private void fontSizeToolStripMenuItem_Click(object sender, EventArgs e) 140 | { 141 | selectedFontSizeMenuItem.Checked = false; 142 | selectedFontSizeMenuItem = (ToolStripMenuItem)sender; 143 | selectedFontSizeMenuItem.Checked = true; 144 | 145 | selectedFontSize = int.Parse(selectedFontSizeMenuItem.Text); 146 | richTextBox.Font = new Font(richTextBox.Font.Name, selectedFontSize); 147 | Update(); 148 | } 149 | } 150 | } -------------------------------------------------------------------------------- /ILDebugging.Visualizer/MethodBodyViewer.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 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 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | 17, 17 122 | 123 | 124 | 125 | 126 | AAABAAMAEBAQAAAABAAoAQAANgAAACAgEAAAAAQA6AIAAF4BAAAQEAAAAAAIAGgFAABGBAAAKAAAABAA 127 | AAAgAAAAAQAEAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAIAAAACAgACAAAAAgACAAICA 128 | AACAgIAAwMDAAAAA/wAA/wAAAP//AP8AAAD/AP8A//8AAP///wAAAAAAAAAAAAB//4/4/48AAH//j/j/ 129 | jwAAeIiIiIiIAAB/d4d4d48AAH93h3h3jwAAeIiIiIiIAAB/d4d4d48AAH93h3h3jwAAeIiIiIiIAAB/ 130 | d4d4d48AAH93h3h3jwAAeIiIiIAAAAB//4/49/cAAH//j/j3cAAAd3d3d3cAAMABAADAAQAAwAEAAMAB 131 | AADAAQAAwAEAAMABAADAAQAAwAEAAMABAADAAQAAwAEAAMABAADAAwAAwAcAAMAPAAAoAAAAIAAAAEAA 132 | AAABAAQAAAAAAIACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAgAAAAICAAIAAAACAAIAAgIAAAICA 133 | gADAwMAAAAD/AAD/AAAA//8A/wAAAP8A/wD//wAA////AAAAAAAAAAAAAAAAAAAAAAAAB4iIiIiIiIiI 134 | iIiIiAAAAAf////4///4///4//gAAAAH////+P//+P//+P/4AAAAB/////j///j///j/+AAAAAf////4 135 | ///4///4//gAAAAH////+P//+P//+P/4AAAAB4iIiIiIiIiIiIiIiAAAAAf/eHh4eHh4eHh4//gAAAAH 136 | /4eHiIeHiIeHiP/4AAAAB/94eHh4eHh4eHj/+AAAAAf/h4eIh4eIh4eI//gAAAAH/3h4eHh4eHh4eP/4 137 | AAAAB4iIiIiIiIiIiIiIiAAAAAf/eHh4eHh4eHh4//gAAAAH/4eHiIeHiIeHiP/4AAAAB/94eHh4eHh4 138 | eHj/+AAAAAf/h4eIh4eIh4eI//gAAAAH/3h4eHh4eHh4eP/4AAAAB4iIiIiIiIiIiIiIiAAAAAf/eHh4 139 | eHh4eHh4//gAAAAH/4eHiIeHiIeHiP/4AAAAB/94eHh4eHh4eHj/+AAAAAf/h4eIh4eIh4eI//gAAAAH 140 | /3h4eHh4eHh4eP/4AAAAB4iIiIiIiIiIiHAAAAAAAAf////4///4//9/+HAAAAAH////+P//+P//f4cA 141 | AAAAB/////j///j//3hwAAAAAAf////4///4//93AAAAAAAH////+P//+P//cAAAAAAAB3d3d3d3d3d3 142 | d3AAAAAA4AAAB+AAAAfgAAAH4AAAB+AAAAfgAAAH4AAAB+AAAAfgAAAH4AAAB+AAAAfgAAAH4AAAB+AA 143 | AAfgAAAH4AAAB+AAAAfgAAAH4AAAB+AAAAfgAAAH4AAAB+AAAAfgAAAH4AAAB+AAAAfgAAAP4AAAH+AA 144 | AD/gAAB/4AAA/+AAAf8oAAAAEAAAACAAAAABAAgAAAAAAAABAAAAAAAAAAAAAAABAAAAAQAAAAAAAAAA 145 | gAAAgAAAAICAAIAAAACAAIAAgIAAAMDAwADA3MAA8MqmAAQEBAAICAgADAwMABEREQAWFhYAHBwcACIi 146 | IgApKSkAVVVVAE1NTQBCQkIAOTk5AIB8/wBQUP8AkwDWAP/szADG1u8A1ufnAJCprQAAADMAAABmAAAA 147 | mQAAAMwAADMAAAAzMwAAM2YAADOZAAAzzAAAM/8AAGYAAABmMwAAZmYAAGaZAABmzAAAZv8AAJkAAACZ 148 | MwAAmWYAAJmZAACZzAAAmf8AAMwAAADMMwAAzGYAAMyZAADMzAAAzP8AAP9mAAD/mQAA/8wAMwAAADMA 149 | MwAzAGYAMwCZADMAzAAzAP8AMzMAADMzMwAzM2YAMzOZADMzzAAzM/8AM2YAADNmMwAzZmYAM2aZADNm 150 | zAAzZv8AM5kAADOZMwAzmWYAM5mZADOZzAAzmf8AM8wAADPMMwAzzGYAM8yZADPMzAAzzP8AM/8zADP/ 151 | ZgAz/5kAM//MADP//wBmAAAAZgAzAGYAZgBmAJkAZgDMAGYA/wBmMwAAZjMzAGYzZgBmM5kAZjPMAGYz 152 | /wBmZgAAZmYzAGZmZgBmZpkAZmbMAGaZAABmmTMAZplmAGaZmQBmmcwAZpn/AGbMAABmzDMAZsyZAGbM 153 | zABmzP8AZv8AAGb/MwBm/5kAZv/MAMwA/wD/AMwAmZkAAJkzmQCZAJkAmQDMAJkAAACZMzMAmQBmAJkz 154 | zACZAP8AmWYAAJlmMwCZM2YAmWaZAJlmzACZM/8AmZkzAJmZZgCZmZkAmZnMAJmZ/wCZzAAAmcwzAGbM 155 | ZgCZzJkAmczMAJnM/wCZ/wAAmf8zAJnMZgCZ/5kAmf/MAJn//wDMAAAAmQAzAMwAZgDMAJkAzADMAJkz 156 | AADMMzMAzDNmAMwzmQDMM8wAzDP/AMxmAADMZjMAmWZmAMxmmQDMZswAmWb/AMyZAADMmTMAzJlmAMyZ 157 | mQDMmcwAzJn/AMzMAADMzDMAzMxmAMzMmQDMzMwAzMz/AMz/AADM/zMAmf9mAMz/mQDM/8wAzP//AMwA 158 | MwD/AGYA/wCZAMwzAAD/MzMA/zNmAP8zmQD/M8wA/zP/AP9mAAD/ZjMAzGZmAP9mmQD/ZswAzGb/AP+Z 159 | AAD/mTMA/5lmAP+ZmQD/mcwA/5n/AP/MAAD/zDMA/8xmAP/MmQD/zMwA/8z/AP//MwDM/2YA//+ZAP// 160 | zABmZv8AZv9mAGb//wD/ZmYA/2b/AP//ZgAhAKUAX19fAHd3dwCGhoYAlpaWAMvLywCysrIA19fXAN3d 161 | 3QDj4+MA6urqAPHx8QD4+PgA8Pv/AKSgoACAgIAAAAD/AAD/AAAA//8A/wAAAP8A/wD//wAA////AAoK 162 | CgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgUFBQUFBQUFBQUKCgoKCgUFBQUFBQUFBQUF 163 | CgoKCqurq6urq6urq6sFBQoKCgqrq6v//////6urBQUKCgoKq6v//6ur//+rqwUFCgoKCqur//+rq/// 164 | q6sFBQoKCgqrq///q6v//6urBQUKCgoKq6v//6ur//+rqwUFCgoKCqurq///////q6sFBQoKCgqrq6ur 165 | q6v//6urBQoKCgoKq6urq6ur//+rqwUKCgoKCqurq6urq///q6sKCgoKCgoKCgoKCgoKCgoKCgoKCgoK 166 | CgoKCgoKCgoKCgoKCgr//wAA//8AAPADAADgAwAAwAMAAMADAADAAwAAwAMAAMADAADAAwAAwAMAAMAH 167 | AADABwAAwA8AAP//AAD//wAA 168 | 169 | 170 | -------------------------------------------------------------------------------- /ILDebugging.Visualizer/MethodBodyVisualizer.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics; 2 | using System.Reflection; 3 | using ILDebugging.Visualizer; 4 | using Microsoft.VisualStudio.DebuggerVisualizers; 5 | 6 | [assembly: DebuggerVisualizer( 7 | typeof(MethodBodyVisualizer), 8 | typeof(MethodBodyObjectSource), 9 | Target = typeof(MethodBase), 10 | Description = "IL Visualizer") 11 | ] 12 | 13 | namespace ILDebugging.Visualizer 14 | { 15 | public class MethodBodyVisualizer : DialogDebuggerVisualizer 16 | { 17 | protected override void Show(IDialogVisualizerService windowService, IVisualizerObjectProvider objectProvider) 18 | { 19 | using (var viewer = new MethodBodyViewer()) 20 | { 21 | viewer.SetObjectProvider(objectProvider); 22 | viewer.ShowDialog(); 23 | } 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /ILDebugging.Visualizer/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | // General Information about an assembly is controlled through the following 5 | // set of attributes. Change these attribute values to modify the information 6 | // associated with an assembly. 7 | 8 | [assembly: AssemblyTitle("ILDebugging.Visualizer")] 9 | [assembly: AssemblyDescription("Visual Studio debugging visualiser for types that can be represented as IL documents.")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("Microsoft")] 12 | [assembly: AssemblyProduct("")] 13 | [assembly: AssemblyCopyright("Copyright © 2016")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | 21 | [assembly: ComVisible(false)] 22 | 23 | // The following GUID is for the ID of the typelib if this project is exposed to COM 24 | 25 | [assembly: Guid("632585a0-d9e5-4ba1-8b1e-b847b5834a77")] 26 | 27 | // Version information for an assembly consists of the following four values: 28 | // 29 | // Major Version 30 | // Minor Version 31 | // Build Number 32 | // Revision 33 | // 34 | // You can specify all the values or you can default the Revision and Build Numbers 35 | // by using the '*' as shown below: 36 | 37 | [assembly: AssemblyVersion("1.0.0.0")] 38 | [assembly: AssemblyFileVersion("1.0.0.0")] -------------------------------------------------------------------------------- /ILDebugging.Visualizer/Properties/Resource.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace ILDebugging.Visualizer.Properties { 12 | using System; 13 | 14 | 15 | /// 16 | /// A strongly-typed resource class, for looking up localized strings, etc. 17 | /// 18 | // This class was auto-generated by the StronglyTypedResourceBuilder 19 | // class via a tool like ResGen or Visual Studio. 20 | // To add or remove a member, edit your .ResX file then rerun ResGen 21 | // with the /str option, or rebuild your VS project. 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | internal class Resource { 26 | 27 | private static global::System.Resources.ResourceManager resourceMan; 28 | 29 | private static global::System.Globalization.CultureInfo resourceCulture; 30 | 31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 32 | internal Resource() { 33 | } 34 | 35 | /// 36 | /// Returns the cached ResourceManager instance used by this class. 37 | /// 38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 39 | internal static global::System.Resources.ResourceManager ResourceManager { 40 | get { 41 | if (object.ReferenceEquals(resourceMan, null)) { 42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("ILDebugging.Visualizer.Properties.Resource", typeof(Resource).Assembly); 43 | resourceMan = temp; 44 | } 45 | return resourceMan; 46 | } 47 | } 48 | 49 | /// 50 | /// Overrides the current thread's CurrentUICulture property for all 51 | /// resource lookups using this strongly typed resource class. 52 | /// 53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 54 | internal static global::System.Globalization.CultureInfo Culture { 55 | get { 56 | return resourceCulture; 57 | } 58 | set { 59 | resourceCulture = value; 60 | } 61 | } 62 | 63 | /// 64 | /// Looks up a localized resource of type System.Drawing.Icon similar to (Icon). 65 | /// 66 | internal static System.Drawing.Icon app { 67 | get { 68 | object obj = ResourceManager.GetObject("app", resourceCulture); 69 | return ((System.Drawing.Icon)(obj)); 70 | } 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /ILDebugging.Visualizer/Properties/Resource.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 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 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | 122 | ..\Resources\app.ico;System.Drawing.Icon, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 123 | 124 | -------------------------------------------------------------------------------- /ILDebugging.Visualizer/Properties/Settings.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace ILDebugging.Visualizer.Properties { 12 | 13 | 14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.5.0.0")] 16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { 17 | 18 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); 19 | 20 | public static Settings Default { 21 | get { 22 | return defaultInstance; 23 | } 24 | } 25 | 26 | [global::System.Configuration.UserScopedSettingAttribute()] 27 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 28 | [global::System.Configuration.DefaultSettingValueAttribute("400")] 29 | public int WindowWidth { 30 | get { 31 | return ((int)(this["WindowWidth"])); 32 | } 33 | set { 34 | this["WindowWidth"] = value; 35 | } 36 | } 37 | 38 | [global::System.Configuration.UserScopedSettingAttribute()] 39 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 40 | [global::System.Configuration.DefaultSettingValueAttribute("300")] 41 | public int WindowHeight { 42 | get { 43 | return ((int)(this["WindowHeight"])); 44 | } 45 | set { 46 | this["WindowHeight"] = value; 47 | } 48 | } 49 | 50 | [global::System.Configuration.UserScopedSettingAttribute()] 51 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 52 | [global::System.Configuration.DefaultSettingValueAttribute("100")] 53 | public int WindowLeft { 54 | get { 55 | return ((int)(this["WindowLeft"])); 56 | } 57 | set { 58 | this["WindowLeft"] = value; 59 | } 60 | } 61 | 62 | [global::System.Configuration.UserScopedSettingAttribute()] 63 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 64 | [global::System.Configuration.DefaultSettingValueAttribute("100")] 65 | public int WindowTop { 66 | get { 67 | return ((int)(this["WindowTop"])); 68 | } 69 | set { 70 | this["WindowTop"] = value; 71 | } 72 | } 73 | 74 | [global::System.Configuration.UserScopedSettingAttribute()] 75 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 76 | [global::System.Configuration.DefaultSettingValueAttribute("Courier New")] 77 | public string FontName { 78 | get { 79 | return ((string)(this["FontName"])); 80 | } 81 | set { 82 | this["FontName"] = value; 83 | } 84 | } 85 | 86 | [global::System.Configuration.UserScopedSettingAttribute()] 87 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 88 | [global::System.Configuration.DefaultSettingValueAttribute("10")] 89 | public int FontSize { 90 | get { 91 | return ((int)(this["FontSize"])); 92 | } 93 | set { 94 | this["FontSize"] = value; 95 | } 96 | } 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /ILDebugging.Visualizer/Properties/Settings.settings: -------------------------------------------------------------------------------- 1 |  2 | 3 | 5 | 6 | 7 | 8 | 400 9 | 10 | 11 | 300 12 | 13 | 14 | 100 15 | 16 | 17 | 100 18 | 19 | 20 | Courier New 21 | 22 | 23 | 10 24 | 25 | 26 | -------------------------------------------------------------------------------- /ILDebugging.Visualizer/Resources/app.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drewnoakes/il-visualizer/33cdca7f9d3ff2feb9cb6ad123ecf0c62e45a562/ILDebugging.Visualizer/Resources/app.ico -------------------------------------------------------------------------------- /ILDebugging.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 14 4 | VisualStudioVersion = 14.0.25420.1 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ILDebugging.Decoder", "ILDebugging.Decoder\ILDebugging.Decoder.csproj", "{3B40E8C3-C4E8-4085-9F82-F64308F3791C}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ILDebugging.Monitor", "ILDebugging.Monitor\ILDebugging.Monitor.csproj", "{77F852DD-35CD-4B2D-AA0E-0516F1E7597F}" 9 | EndProject 10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ILDebugging.Visualizer", "ILDebugging.Visualizer\ILDebugging.Visualizer.csproj", "{6F6E9FC5-40A9-4ABD-89F3-EF7B6406F07B}" 11 | EndProject 12 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ILDebugging.Sample", "ILDebugging.Sample\ILDebugging.Sample.csproj", "{5BF03C0A-2F42-4538-B373-8B2BE569350A}" 13 | EndProject 14 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{A55BBE27-FF6F-4EB6-9261-E58D05AAE3A9}" 15 | ProjectSection(SolutionItems) = preProject 16 | .gitignore = .gitignore 17 | README.md = README.md 18 | EndProjectSection 19 | EndProject 20 | Global 21 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 22 | Debug|Any CPU = Debug|Any CPU 23 | Release|Any CPU = Release|Any CPU 24 | EndGlobalSection 25 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 26 | {3B40E8C3-C4E8-4085-9F82-F64308F3791C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 27 | {3B40E8C3-C4E8-4085-9F82-F64308F3791C}.Debug|Any CPU.Build.0 = Debug|Any CPU 28 | {3B40E8C3-C4E8-4085-9F82-F64308F3791C}.Release|Any CPU.ActiveCfg = Release|Any CPU 29 | {3B40E8C3-C4E8-4085-9F82-F64308F3791C}.Release|Any CPU.Build.0 = Release|Any CPU 30 | {77F852DD-35CD-4B2D-AA0E-0516F1E7597F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 31 | {77F852DD-35CD-4B2D-AA0E-0516F1E7597F}.Debug|Any CPU.Build.0 = Debug|Any CPU 32 | {77F852DD-35CD-4B2D-AA0E-0516F1E7597F}.Release|Any CPU.ActiveCfg = Release|Any CPU 33 | {77F852DD-35CD-4B2D-AA0E-0516F1E7597F}.Release|Any CPU.Build.0 = Release|Any CPU 34 | {6F6E9FC5-40A9-4ABD-89F3-EF7B6406F07B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 35 | {6F6E9FC5-40A9-4ABD-89F3-EF7B6406F07B}.Debug|Any CPU.Build.0 = Debug|Any CPU 36 | {6F6E9FC5-40A9-4ABD-89F3-EF7B6406F07B}.Release|Any CPU.ActiveCfg = Release|Any CPU 37 | {6F6E9FC5-40A9-4ABD-89F3-EF7B6406F07B}.Release|Any CPU.Build.0 = Release|Any CPU 38 | {5BF03C0A-2F42-4538-B373-8B2BE569350A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 39 | {5BF03C0A-2F42-4538-B373-8B2BE569350A}.Debug|Any CPU.Build.0 = Debug|Any CPU 40 | {5BF03C0A-2F42-4538-B373-8B2BE569350A}.Release|Any CPU.ActiveCfg = Release|Any CPU 41 | {5BF03C0A-2F42-4538-B373-8B2BE569350A}.Release|Any CPU.Build.0 = Release|Any CPU 42 | EndGlobalSection 43 | GlobalSection(SolutionProperties) = preSolution 44 | HideSolutionNode = FALSE 45 | EndGlobalSection 46 | EndGlobal 47 | -------------------------------------------------------------------------------- /Images/il-monitor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drewnoakes/il-visualizer/33cdca7f9d3ff2feb9cb6ad123ecf0c62e45a562/Images/il-monitor.png -------------------------------------------------------------------------------- /Images/il-visualizer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drewnoakes/il-visualizer/33cdca7f9d3ff2feb9cb6ad123ecf0c62e45a562/Images/il-visualizer.png -------------------------------------------------------------------------------- /Images/launching-visualizer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drewnoakes/il-visualizer/33cdca7f9d3ff2feb9cb6ad123ecf0c62e45a562/Images/launching-visualizer.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # IL Visualiser 2 | 3 | Originally developed by Haibo Luo in 2005 and posted in a series of blog posts 4 | ([part one](https://blogs.msdn.microsoft.com/haibo_luo/2005/10/25/debuggervisualizer-for-dynamicmethod-show-me-the-il/), 5 | [part two](https://blogs.msdn.microsoft.com/haibo_luo/2006/11/16/take-two-il-visualizer/)). 6 | 7 | Converted to a Git repository and upgraded to VS2015 by Drew Noakes. Conversion to VS2017 by @dadhi. 8 | 9 | ## Usage 10 | 11 | When paused in the debugger, select an instance of a subclass of `MethodBase` (such as `DynamicMethod`, 12 | `MethodBuilder`, `ConstructorBuilder`, ...) and launch a visualiser: 13 | 14 | ![](Images/launching-visualizer.png) 15 | 16 | There are two ways to use this visualiser. 17 | 18 | ### IL Visualizer (Modal) 19 | 20 | Selecting _"IL Visualizer"_ pops up a window showing the IL code. 21 | 22 | ![](Images/il-visualizer.png) 23 | 24 | This window is modal and debugging may only continue once the window is closed. 25 | 26 | ### Out of Process (Non-modal) 27 | 28 | Sometimes you don't want to close the window before continuing your debugging session. For such cases, you 29 | can run _IL Monitor_ as a separate process, then select _"Send to IL Monitor"_: 30 | 31 | ![](Images/il-monitor.png) 32 | 33 | IL Monitor is a standalone MDI application that allows displaying mutliple IL views. 34 | 35 | ## Installation 36 | 37 | (Notes apply to VS 2015 and 2017, but are similar for earlier versions) 38 | 39 | 1. [Download the latest release for your version of Visual Studio](https://github.com/drewnoakes/il-visualizer/releases), or build from source 40 | 41 | 2. Copy `ILDebugging.Decoder.dll` and `ILDebugging.Visualizer.dll` to one of: 42 | 43 | - `%USERPROFILE%\Documents\Visual Studio 2015\Visualizers` 44 | - `%USERPROFILE%\Documents\Visual Studio 2017\Visualizers` 45 | - `VisualStudioInstallPath_\Common7\Packages\Debugger\Visualizers` 46 | 47 | 3. Restart the debugging session (you don't have to restart Visual Studio) 48 | 49 | **Note**: If you get error _"Operation not supported"_ when invoking the visualizer, restart Visual Studio and try again. 50 | 51 | If you wish to use _Send to IL Monitor_, you run `ILDebugging.Monitor.exe` before attempting to use it from the debugger. 52 | 53 | ## Earlier Visual Studio Versions 54 | 55 | You can target earlier versions of Visual Studio by updating the assembly references for 56 | `Microsoft.VisualStudio.DebuggerVisualizers.dll` to the relevant version. 57 | 58 | ## License 59 | 60 | THE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES INTENDED OR IMPLIED. USE AT YOUR OWN RISK! 61 | --------------------------------------------------------------------------------