internal unsafe VariableInfo ResolveVariable(int threadHashCode, VariableReference variable, out object res) { ILIntepreter intepreter; res = null; if (AppDomain.Intepreters.TryGetValue(threadHashCode, out intepreter)) { if (variable != null) { switch (variable.Type) { case VariableTypes.Normal: { StackObject *ptr = (StackObject *)variable.Address; object obj = StackObject.ToObject(ptr, AppDomain, intepreter.Stack.ManagedStack); if (obj != null) { //return ResolveMember(obj, name, out res); res = obj; return(null); } else { return(VariableInfo.Null); } } case VariableTypes.FieldReference: case VariableTypes.PropertyReference: { object obj; if (variable.Parent != null) { var info = ResolveVariable(threadHashCode, variable.Parent, out obj); if (obj != null) { return(ResolveMember(obj, variable.Name, out res)); } else { return(VariableInfo.NullReferenceExeption); } } else { var frame = intepreter.Stack.Frames.Peek(); var m = frame.Method; if (m.HasThis) { var addr = Minus(frame.LocalVarPointer, m.ParameterCount + 1); var v = StackObject.ToObject(addr, intepreter.AppDomain, intepreter.Stack.ManagedStack); return(ResolveMember(v, variable.Name, out res)); } else { return(VariableInfo.GetCannotFind(variable.Name)); } } } case VariableTypes.IndexAccess: { return(ResolveIndexAccess(threadHashCode, variable.Parent, variable.Parameters[0], out res)); } case VariableTypes.Integer: { res = variable.Offset; return(VariableInfo.GetInteger(variable.Offset)); } case VariableTypes.String: { res = variable.Name; return(VariableInfo.GetString(variable.Name)); } case VariableTypes.Boolean: { if (variable.Offset == 1) { res = true; return(VariableInfo.True); } else { res = false; return(VariableInfo.False); } } case VariableTypes.Null: { res = null; return(VariableInfo.Null); } default: throw new NotImplementedException(); } } else { return(VariableInfo.NullReferenceExeption); } } else { return(VariableInfo.NullReferenceExeption); } }
internal unsafe VariableInfo ResolveIndexAccess(int threadHashCode, VariableReference body, VariableReference idx, out object res) { ILIntepreter intepreter; res = null; if (AppDomain.Intepreters.TryGetValue(threadHashCode, out intepreter)) { object obj; var info = ResolveVariable(threadHashCode, body, out obj); if (obj != null) { object idxObj; info = ResolveVariable(threadHashCode, idx, out idxObj); if (obj is Array) { res = ((Array)obj).GetValue((int)idxObj); info = VariableInfo.FromObject(res); info.Type = VariableTypes.IndexAccess; info.TypeName = obj.GetType().GetElementType().FullName; info.Expandable = res != null && !obj.GetType().GetElementType().IsPrimitive; return(info); } else { if (obj is ILTypeInstance) { var m = ((ILTypeInstance)obj).Type.GetMethod("get_Item"); if (m != null) { res = intepreter.AppDomain.Invoke(m, obj, idxObj); info = VariableInfo.FromObject(res); info.Type = VariableTypes.IndexAccess; info.TypeName = m.ReturnType.FullName; info.Expandable = res != null && !m.ReturnType.IsPrimitive; return(info); } else { return(VariableInfo.NullReferenceExeption); } } else { if (obj is ILRuntime.Runtime.Enviorment.CrossBindingAdaptorType) { throw new NotImplementedException(); } else { if (obj is IDictionary && idxObj is int) { IDictionary dic = (IDictionary)obj; var keys = GetArray(dic.Keys); if (keys[0].GetType() != typeof(int)) { int index = (int)idxObj; var values = GetArray(dic.Values); var t = typeof(KeyValuePair <,>).MakeGenericType(keys[index].GetType(), values[index].GetType()); var ctor = t.GetConstructor(new Type[] { keys[index].GetType(), values[index].GetType() }); res = ctor.Invoke(new object[] { keys[index], values[index] }); info = VariableInfo.FromObject(res); info.Type = VariableTypes.IndexAccess; info.Offset = index; info.TypeName = t.FullName; info.Expandable = true; return(info); } } var pi = obj.GetType().GetProperty("Item"); if (pi != null) { res = pi.GetValue(obj, new object[] { idxObj }); info = VariableInfo.FromObject(res); info.Type = VariableTypes.IndexAccess; info.TypeName = pi.PropertyType.FullName; info.Expandable = res != null && !pi.PropertyType.IsPrimitive; return(info); } else { return(VariableInfo.NullReferenceExeption); } } } } } else { return(VariableInfo.NullReferenceExeption); } } else { return(VariableInfo.NullReferenceExeption); } }
unsafe StackFrameInfo[] GetStackFrameInfo(ILIntepreter intp) { StackFrame[] frames = intp.Stack.Frames.ToArray(); Mono.Cecil.Cil.Instruction ins = null; ILMethod m; StackFrameInfo[] frameInfos = new StackFrameInfo[frames.Length]; for (int j = 0; j < frames.Length; j++) { StackFrameInfo info = new Debugger.StackFrameInfo(); var f = frames[j]; m = f.Method; info.MethodName = m.ToString(); if (f.Address != null) { ins = m.Definition.Body.Instructions[f.Address.Value]; var seq = FindSequencePoint(ins, m.Definition.DebugInformation.GetSequencePointMapping()); if (seq != null) { info.DocumentName = seq.Document.Url; info.StartLine = seq.StartLine - 1; info.StartColumn = seq.StartColumn - 1; info.EndLine = seq.EndLine - 1; info.EndColumn = seq.EndColumn - 1; } } StackFrame topFrame = f; m = topFrame.Method; int argumentCount = m.ParameterCount; if (m.HasThis) { argumentCount++; } info.LocalVariables = new VariableInfo[argumentCount + m.LocalVariableCount]; for (int i = 0; i < argumentCount; i++) { int argIdx = m.HasThis ? i - 1 : i; var arg = Minus(topFrame.LocalVarPointer, argumentCount); string name = null; object v = null; string typeName = null; var val = Add(arg, i); v = StackObject.ToObject(val, intp.AppDomain, intp.Stack.ManagedStack); if (argIdx >= 0) { var lv = m.Definition.Parameters[argIdx]; name = string.IsNullOrEmpty(lv.Name) ? "arg" + lv.Index : lv.Name; typeName = lv.ParameterType.FullName; } else { name = "this"; typeName = m.DeclearingType.FullName; } VariableInfo vinfo = VariableInfo.FromObject(v); vinfo.Address = (long)val; vinfo.Name = name; vinfo.TypeName = typeName; vinfo.Expandable = GetValueExpandable(val, intp.Stack.ManagedStack); info.LocalVariables[i] = vinfo; } for (int i = argumentCount; i < info.LocalVariables.Length; i++) { var locIdx = i - argumentCount; var lv = m.Definition.Body.Variables[locIdx]; var val = Add(topFrame.LocalVarPointer, locIdx); var v = StackObject.ToObject(val, intp.AppDomain, intp.Stack.ManagedStack); var type = intp.AppDomain.GetType(lv.VariableType, m.DeclearingType, m); string vName = null; m.Definition.DebugInformation.TryGetName(lv, out vName); string name = string.IsNullOrEmpty(vName) ? "v" + lv.Index : vName; VariableInfo vinfo = VariableInfo.FromObject(v); vinfo.Address = (long)val; vinfo.Name = name; vinfo.TypeName = lv.VariableType.FullName; vinfo.Expandable = GetValueExpandable(val, intp.Stack.ManagedStack); info.LocalVariables[i] = vinfo; } frameInfos[j] = info; } return(frameInfos); }
internal unsafe VariableInfo[] EnumChildren(int threadHashCode, VariableReference parent) { ILIntepreter intepreter; if (AppDomain.Intepreters.TryGetValue(threadHashCode, out intepreter)) { object obj; var info = ResolveVariable(threadHashCode, parent, out obj); if (obj != null) { if (obj is Array) { return(EnumArray((Array)obj, intepreter)); } else if (obj is IList) { return(EnumList((IList)obj, intepreter)); } else if (obj is IDictionary) { return(EnumDictionary((IDictionary)obj, intepreter)); } else if (obj is ILTypeInstance) { return(EnumILTypeInstance((ILTypeInstance)obj, intepreter)); } else if (obj is ILRuntime.Runtime.Enviorment.CrossBindingAdaptorType) { return(EnumILTypeInstance(((Enviorment.CrossBindingAdaptorType)obj).ILInstance, intepreter)); } else { return(EnumCLRObject(obj, intepreter)); } } else { return new VariableInfo[] { VariableInfo.NullReferenceExeption } }; } else { return new VariableInfo[] { VariableInfo.NullReferenceExeption } }; } VariableInfo[] EnumArray(Array arr, ILIntepreter intepreter) { VariableInfo[] res = new VariableInfo[arr.Length]; for (int i = 0; i < arr.Length; i++) { try { var obj = arr.GetValue(i); VariableInfo info = VariableInfo.FromObject(obj, true); info.Name = string.Format("[{0}]", i); info.Offset = i; info.Type = VariableTypes.IndexAccess; res[i] = info; } catch (Exception ex) { var info = VariableInfo.GetException(ex); info.Name = string.Format("[{0}]", i); res[i] = info; } } return(res); } VariableInfo[] EnumList(IList lst, ILIntepreter intepreter) { VariableInfo[] res = new VariableInfo[lst.Count]; for (int i = 0; i < lst.Count; i++) { try { var obj = lst[i]; VariableInfo info = VariableInfo.FromObject(obj, true); info.Name = string.Format("[{0}]", i); info.Offset = i; info.Type = VariableTypes.IndexAccess; res[i] = info; } catch (Exception ex) { var info = VariableInfo.GetException(ex); info.Name = string.Format("[{0}]", i); res[i] = info; } } return(res); } VariableInfo[] EnumDictionary(IDictionary lst, ILIntepreter intepreter) { VariableInfo[] res = new VariableInfo[lst.Count]; var keys = GetArray(lst.Keys); var values = GetArray(lst.Values); for (int i = 0; i < lst.Count; i++) { try { var obj = values[i]; VariableInfo info = VariableInfo.FromObject(obj, true); info.Name = string.Format("[{0}]", i); info.Type = VariableTypes.IndexAccess; info.Offset = i; info.Value = string.Format("{0},{1}", SafeToString(keys[i]), SafeToString(values[i])); info.Expandable = true; res[i] = info; } catch (Exception ex) { var info = VariableInfo.GetException(ex); info.Name = string.Format("[{0}]", i); res[i] = info; } } return(res); } string SafeToString(object obj) { if (obj != null) { return(obj.ToString()); } else { return("null"); } } object[] GetArray(ICollection lst) { object[] res = new object[lst.Count]; int idx = 0; foreach (var i in lst) { res[idx++] = i; } return(res); } VariableInfo[] EnumILTypeInstance(ILTypeInstance obj, ILIntepreter intepreter) { return(EnumObject(obj, obj.Type.ReflectionType)); } VariableInfo[] EnumCLRObject(object obj, ILIntepreter intepreter) { return(EnumObject(obj, obj.GetType())); } VariableInfo[] EnumObject(object obj, Type t) { List <VariableInfo> lst = new List <VariableInfo>(); foreach (var i in t.GetFields(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)) { try { if (i.GetCustomAttributes(typeof(System.Runtime.CompilerServices.CompilerGeneratedAttribute), false).Length > 0) { continue; } var val = i.GetValue(obj); VariableInfo info = VariableInfo.FromObject(val); info.Type = VariableTypes.FieldReference; info.TypeName = i.FieldType.FullName; info.Name = i.Name; info.Expandable = !i.FieldType.IsPrimitive && val != null; info.IsPrivate = i.IsPrivate; info.IsProtected = i.IsFamily; lst.Add(info); } catch (Exception ex) { var info = VariableInfo.GetException(ex); info.Name = i.Name; lst.Add(info); } } foreach (var i in t.GetProperties(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)) { try { if (i.GetIndexParameters().Length > 0) { continue; } var val = i.GetValue(obj, null); VariableInfo info = VariableInfo.FromObject(val); info.Type = VariableTypes.PropertyReference; info.TypeName = i.PropertyType.FullName; info.Name = i.Name; info.Expandable = !i.PropertyType.IsPrimitive && val != null; info.IsPrivate = i.GetGetMethod(true).IsPrivate; info.IsProtected = i.GetGetMethod(true).IsFamily; lst.Add(info); } catch (Exception ex) { var info = VariableInfo.GetException(ex); info.Name = i.Name; lst.Add(info); } } return(lst.ToArray()); }
void OnReceive(DebugMessageType type, byte[] buffer) { if (clientSocket == null || clientSocket.Disconnected) { return; } System.IO.MemoryStream ms = new System.IO.MemoryStream(buffer); System.IO.BinaryReader br = new System.IO.BinaryReader(ms); switch (type) { case DebugMessageType.CSAttach: { SendAttachResult(); } break; case DebugMessageType.CSBindBreakpoint: { CSBindBreakpoint msg = new Protocol.CSBindBreakpoint(); msg.BreakpointHashCode = br.ReadInt32(); msg.IsLambda = br.ReadBoolean(); msg.TypeName = br.ReadString(); msg.MethodName = br.ReadString(); msg.StartLine = br.ReadInt32(); msg.EndLine = br.ReadInt32(); TryBindBreakpoint(msg); } break; case DebugMessageType.CSDeleteBreakpoint: { CSDeleteBreakpoint msg = new Protocol.CSDeleteBreakpoint(); msg.BreakpointHashCode = br.ReadInt32(); ds.DeleteBreakpoint(msg.BreakpointHashCode); } break; case DebugMessageType.CSExecute: { CSExecute msg = new Protocol.CSExecute(); msg.ThreadHashCode = br.ReadInt32(); ds.ExecuteThread(msg.ThreadHashCode); } break; case DebugMessageType.CSStep: { CSStep msg = new CSStep(); msg.ThreadHashCode = br.ReadInt32(); msg.StepType = (StepTypes)br.ReadByte(); ds.StepThread(msg.ThreadHashCode, msg.StepType); } break; case DebugMessageType.CSResolveVariable: { CSResolveVariable msg = new CSResolveVariable(); msg.ThreadHashCode = br.ReadInt32(); msg.Variable = ReadVariableReference(br); VariableInfo info; try { object res; info = ds.ResolveVariable(msg.ThreadHashCode, msg.Variable, out res); } catch (Exception ex) { info = VariableInfo.GetException(ex); } if (info.Type != VariableTypes.Pending) { SendSCResolveVariableResult(info); } } break; case DebugMessageType.CSResolveIndexAccess: { CSResolveIndexer msg = new CSResolveIndexer(); msg.ThreadHashCode = br.ReadInt32(); msg.Body = ReadVariableReference(br); msg.Index = ReadVariableReference(br); VariableInfo info; try { object res; info = ds.ResolveIndexAccess(msg.ThreadHashCode, msg.Body, msg.Index, out res); } catch (Exception ex) { info = VariableInfo.GetException(ex); } if (info.Type != VariableTypes.Pending) { SendSCResolveVariableResult(info); } } break; case DebugMessageType.CSEnumChildren: { int thId = br.ReadInt32(); var parent = ReadVariableReference(br); VariableInfo[] info = null; try { info = ds.EnumChildren(thId, parent); } catch (Exception ex) { info = new VariableInfo[] { VariableInfo.GetException(ex) }; } if (info != null) { SendSCEnumChildrenResult(info); } } break; } }