public SoftEvaluationContext(SoftDebuggerSession session, StackFrame frame, DC.EvaluationOptions options) : base(options) { Frame = frame; Thread = frame.Thread; Domain = frame.Domain; string method = frame.Method.Name; if (frame.Method.DeclaringType != null) method = frame.Method.DeclaringType.FullName + "." + method; var location = new DC.SourceLocation (method, frame.FileName, frame.LineNumber, frame.ColumnNumber, frame.EndLineNumber, frame.EndColumnNumber, frame.Location.SourceFileHash); string language; if (frame.Method != null) { language = frame.IsNativeTransition ? "Transition" : "Managed"; } else { language = "Native"; } Evaluator = session.GetEvaluator (new DC.StackFrame (frame.ILOffset, location, language, session.IsExternalCode (frame), true)); Adapter = session.Adaptor; this.session = session; stackVersion = session.StackVersion; sourceAvailable = !string.IsNullOrEmpty (frame.FileName) && System.IO.File.Exists (frame.FileName); }
public SoftEvaluationContext(SoftDebuggerSession session, StackFrame frame, DC.EvaluationOptions options) : base(options) { Frame = frame; Thread = frame.Thread; Domain = Thread.Domain; string method = frame.Method.Name; if (frame.Method.DeclaringType != null) { method = frame.Method.DeclaringType.FullName + "." + method; } var location = new DC.SourceLocation(method, frame.FileName, frame.LineNumber, frame.ColumnNumber); string language; if (frame.Method != null) { language = frame.IsNativeTransition ? "Transition" : "Managed"; } else { language = "Native"; } Evaluator = session.GetEvaluator(new DC.StackFrame(frame.ILOffset, location, language, session.IsExternalCode(frame), true)); Adapter = session.Adaptor; this.session = session; stackVersion = session.StackVersion; sourceAvailable = !string.IsNullOrEmpty(frame.FileName) && System.IO.File.Exists(frame.FileName); }
public override void CopyFrom(EvaluationContext ctx) { base.CopyFrom(ctx); SoftEvaluationContext other = (SoftEvaluationContext)ctx; frame = other.frame; stackVersion = other.stackVersion; Thread = other.Thread; session = other.session; }
public SoftDebuggerBacktrace (SoftDebuggerSession session, MDB.ThreadMirror thread): base (session.Adaptor) { this.session = session; this.thread = thread; stackVersion = session.StackVersion; if (thread != null) this.frames = thread.GetFrames (); else this.frames = new MDB.StackFrame[0]; }
DC.StackFrame CreateStackFrame(MDB.StackFrame frame) { string method = frame.Method.Name; if (frame.Method.DeclaringType != null) { method = frame.Method.DeclaringType.FullName + "." + method; } var location = new DC.SourceLocation(method, SoftDebuggerSession.NormalizePath(frame.FileName), frame.LineNumber); var lang = frame.Method != null? "Managed" : "Native"; return(new DC.StackFrame(frame.ILOffset, frame.Method.FullName, location, lang, session.IsExternalCode(frame), true)); }
public SoftDebuggerBacktrace(SoftDebuggerSession session, MDB.ThreadMirror thread) : base(session.Adaptor) { this.session = session; this.thread = thread; stackVersion = session.StackVersion; if (thread != null) { this.frames = thread.GetFrames(); } else { this.frames = new MDB.StackFrame[0]; } }
public SoftEvaluationContext (SoftDebuggerSession session, StackFrame frame, DC.EvaluationOptions options): base (options) { Frame = frame; Thread = frame.Thread; string method = frame.Method.Name; if (frame.Method.DeclaringType != null) method = frame.Method.DeclaringType.FullName + "." + method; var location = new DC.SourceLocation (method, frame.FileName, frame.LineNumber); var lang = frame.Method != null? "Managed" : "Native"; Evaluator = session.GetEvaluator (new DC.StackFrame (frame.ILOffset, location, lang, session.IsExternalCode (frame), true)); Adapter = session.Adaptor; this.session = session; this.stackVersion = session.StackVersion; sourceAvailable = !string.IsNullOrEmpty (frame.FileName) && System.IO.File.Exists (frame.FileName); }
public SoftEvaluationContext(SoftDebuggerSession session, StackFrame frame, DC.EvaluationOptions options) : base(options) { Frame = frame; Thread = frame.Thread; string method = frame.Method.Name; if (frame.Method.DeclaringType != null) { method = frame.Method.DeclaringType.FullName + "." + method; } var location = new DC.SourceLocation(method, frame.FileName, frame.LineNumber); var lang = frame.Method != null? "Managed" : "Native"; Evaluator = session.GetResolver(new DC.StackFrame(frame.ILOffset, location, lang, session.IsExternalCode(frame), true)); Adapter = session.Adaptor; this.session = session; this.stackVersion = session.StackVersion; }
public override void CopyFrom (EvaluationContext ctx) { base.CopyFrom (ctx); SoftEvaluationContext other = (SoftEvaluationContext) ctx; frame = other.frame; stackVersion = other.stackVersion; Thread = other.Thread; session = other.session; }
public static void Kill() { lock (_lock) { if (_session == null) return; CommandLine.InferiorExecuting = true; if (!_session.HasExited) _session.Exit(); _session.Dispose(); _session = null; } }
public static void Disconnect() { lock (_lock) { if (_session == null) return; CommandLine.InferiorExecuting = true; _kind = SessionKind.Disconnected; Breakpoints.Clear(); BreakEvents.Clear(); _session.Continue(); _session = null; } }
static void EnsureCreated() { lock (_lock) { if (_session != null) return; _session = new SoftDebuggerSession(); _session.Breakpoints = BreakEvents; _session.ExceptionHandler = ex => { if (Configuration.Current.LogInternalErrors) { Log.Error("Internal debugger error:", ex.GetType()); Log.Error(ex.ToString()); } return true; }; _session.LogWriter = (isStdErr, text) => { if (Configuration.Current.LogRuntimeSpew) Log.NoticeSameLine("[Mono] {0}", text); // The string already has a line feed. }; _session.OutputWriter = (isStdErr, text) => { //lock (Log.Lock) //{ if (Callback != null) { Callback.Invoke(isStdErr ? "ErrorOutput" : "Output", null, null, text); } else { if (isStdErr) Console.Error.Write(text); else Console.Write(text); } //} }; _session.TypeResolverHandler += (identifier, location) => { // I honestly have no idea how correct this is. I suspect you // could probably break it in some corner cases. It does make // something like `p Android.Runtime.JNIEnv.Handle` work, // though, which would otherwise have required `global::` to // be explicitly prepended. if (identifier == "__EXCEPTION_OBJECT__") return null; foreach (var loc in ActiveFrame.GetAllLocals()) if (loc.Name == identifier) return null; return identifier; }; _session.TargetEvent += (sender, e) => { Log.Debug("Event: '{0}'", e.Type); }; _session.TargetStarted += (sender, e) => { _activeFrame = null; /* if (_showResumeMessage) Log.Notice("Inferior process '{0}' ('{1}') resumed", ActiveProcess.Id, StringizeTarget()); */ }; _session.TargetReady += (sender, e) => { _activeProcess = _session.GetProcesses().SingleOrDefault(); // The inferior process has launched, so we can safely // set our `SIGINT` handler without it interfering with // the inferior. CommandLine.SetControlCHandler(); /* Log.Notice("Inferior process '{0}' ('{1}') started", ActiveProcess.Id, StringizeTarget()); */ }; _session.TargetStopped += (sender, e) => { //Log.Notice("Inferior process '{0}' ('{1}') suspended", // ActiveProcess.Id, StringizeTarget()); //Log.Emphasis(Utilities.StringizeFrame(ActiveFrame, true)); if (Callback != null) { Callback.Invoke("TargetStopped", ActiveFrame.SourceLocation, e.Thread, null); } CommandLine.ResumeEvent.Set(); }; _session.TargetInterrupted += (sender, e) => { Log.Notice("Inferior process '{0}' ('{1}') interrupted", ActiveProcess.Id, StringizeTarget()); Log.Emphasis(Utilities.StringizeFrame(ActiveFrame, true)); CommandLine.ResumeEvent.Set(); }; _session.TargetHitBreakpoint += (sender, e) => { // var bp = e.BreakEvent as Breakpoint; // var fbp = e.BreakEvent as FunctionBreakpoint; /* if (fbp != null) Log.Notice("Hit method breakpoint on '{0}'", fbp.FunctionName); else { var cond = bp.ConditionExpression != null ? string.Format(" (condition '{0}' met)", bp.ConditionExpression) : string.Empty; Log.Notice("Hit breakpoint at '{0}:{1}'{2}", bp.FileName, bp.Line, cond); } Log.Emphasis(Utilities.StringizeFrame(ActiveFrame, true)); */ if (Callback != null) { Callback.Invoke("TargetHitBreakpoint", ActiveFrame.SourceLocation, e.Thread, null); } CommandLine.ResumeEvent.Set(); }; _session.TargetExited += (sender, e) => { var p = ActiveProcess; /* // Can happen when a remote connection attempt fails. if (p == null) { if (_kind == SessionKind.Listening) Log.Notice("Listening socket closed"); else if (_kind == SessionKind.Connected) Log.Notice("Connection attempt terminated"); else Log.Notice("Failed to connect to '{0}'", StringizeTarget()); } else Log.Notice("Inferior process '{0}' ('{1}') exited", ActiveProcess.Id, StringizeTarget()); */ // Make sure we clean everything up on a normal exit. Kill(); _debuggeeKilled = true; _kind = SessionKind.Disconnected; if (Callback != null) { Callback.Invoke("TargetExited", null, null, null); } CommandLine.ResumeEvent.Set(); }; _session.TargetExceptionThrown += (sender, e) => { var ex = ActiveException; //Log.Notice("Trapped first-chance exception of type '{0}'", ex.Type); //Log.Emphasis(Utilities.StringizeFrame(ActiveFrame, true)); PrintException(ex); if (Callback != null) { Callback.Invoke("TargetExceptionThrown", ActiveFrame.SourceLocation, e.Thread, null); } CommandLine.ResumeEvent.Set(); }; _session.TargetUnhandledException += (sender, e) => { var ex = ActiveException; //Log.Notice("Trapped unhandled exception of type '{0}'", ex.Type); //Log.Emphasis(Utilities.StringizeFrame(ActiveFrame, true)); PrintException(ex); if (Callback != null) { Callback.Invoke("TargetUnhandledException", ActiveFrame.SourceLocation, e.Thread, null); } CommandLine.ResumeEvent.Set(); }; _session.TargetThreadStarted += (sender, e) => { //Log.Notice("Inferior thread '{0}' ('{1}') started", // e.Thread.Id, e.Thread.Name); if (Callback != null) { Callback.Invoke("TargetThreadStarted", null, e.Thread, null); } }; _session.TargetThreadStopped += (sender, e) => { //Log.Notice("Inferior thread '{0}' ('{1}') exited", // e.Thread.Id, e.Thread.Name); if (Callback != null) { Callback.Invoke("TargetThreadStopped", null, e.Thread, null); } }; } }
DC.StackFrame CreateStackFrame(MDB.StackFrame frame, int frameIndex) { MDB.MethodMirror method = frame.Method; MDB.TypeMirror type = method.DeclaringType; string fileName = frame.FileName; string typeFullName = null; string typeFQN = null; string methodName; if (fileName != null) { fileName = SoftDebuggerSession.NormalizePath(fileName); } if (method.VirtualMachine.Version.AtLeast(2, 12) && method.IsGenericMethod) { StringBuilder name = new StringBuilder(method.Name); name.Append('<'); if (method.VirtualMachine.Version.AtLeast(2, 15)) { bool first = true; foreach (var argumentType in method.GetGenericArguments()) { if (!first) { name.Append(", "); } name.Append(session.Adaptor.GetDisplayTypeName(argumentType.FullName)); first = false; } } name.Append('>'); methodName = name.ToString(); } else { methodName = method.Name; } if (string.IsNullOrEmpty(methodName)) { methodName = "[Function Without Name]"; } // Compiler generated anonymous/lambda methods bool special_method = false; if (methodName [0] == '<' && methodName.Contains(">m__")) { int nidx = methodName.IndexOf(">m__", StringComparison.Ordinal) + 2; methodName = "AnonymousMethod" + methodName.Substring(nidx, method.Name.Length - nidx); special_method = true; } if (type != null) { string typeDisplayName = session.Adaptor.GetDisplayTypeName(type.FullName); if (SoftDebuggerAdaptor.IsGeneratedType(type)) { // The user-friendly method name is embedded in the generated type name var mn = SoftDebuggerAdaptor.GetNameFromGeneratedType(type); // Strip off the generated type name int dot = typeDisplayName.LastIndexOf('.'); var tname = typeDisplayName.Substring(0, dot); // Keep any type arguments int targs = typeDisplayName.LastIndexOf('<'); if (targs > dot + 1) { mn += typeDisplayName.Substring(targs, typeDisplayName.Length - targs); } typeDisplayName = tname; if (special_method) { typeDisplayName += "." + mn; } else { methodName = mn; } } methodName = typeDisplayName + "." + methodName; typeFQN = type.Module.FullyQualifiedName; typeFullName = type.FullName; } bool external = false; bool hidden = false; if (session.VirtualMachine.Version.AtLeast(2, 21)) { var ctx = GetEvaluationContext(frameIndex, session.EvaluationOptions); var hiddenAttr = session.Adaptor.GetType(ctx, "System.Diagnostics.DebuggerHiddenAttribute") as MDB.TypeMirror; hidden = method.GetCustomAttributes(hiddenAttr, true).Any(); } if (hidden) { external = true; } else { external = session.IsExternalCode(frame); if (!external && session.Options.ProjectAssembliesOnly && session.VirtualMachine.Version.AtLeast(2, 21)) { var ctx = GetEvaluationContext(frameIndex, session.EvaluationOptions); var nonUserCodeAttr = session.Adaptor.GetType(ctx, "System.Diagnostics.DebuggerNonUserCodeAttribute") as MDB.TypeMirror; external = method.GetCustomAttributes(nonUserCodeAttr, true).Any(); } } var location = new DC.SourceLocation(methodName, fileName, frame.LineNumber, frame.ColumnNumber, frame.Location.EndLineNumber, frame.Location.EndColumnNumber, frame.Location.SourceFileHash); string addressSpace = string.Empty; bool hasDebugInfo = false; string language; if (frame.Method != null) { if (frame.IsNativeTransition) { language = "Transition"; } else { addressSpace = method.FullName; language = "Managed"; hasDebugInfo = true; } } else { language = "Native"; } return(new SoftDebuggerStackFrame(frame, addressSpace, location, language, external, hasDebugInfo, hidden, typeFQN, typeFullName)); }
public bool CreateSession(ValueReference startInfo, EvaluationOptions ops) { // Get the exe and arguments from the start info and store them this.arguments = (string)startInfo.GetChild("Arguments", ops).GetRawValue(ops); this.exe = (string)startInfo.GetChild("FileName", ops).GetRawValue(ops); // Create the new session and custom start arguments. // The actual arguments don't matter much since we'll use a custom launcher for the process. newSession = new SoftDebuggerSession(); var startArgs = new SoftDebuggerLaunchArgs(null, new Dictionary <string, string> ()); var dsi = new SoftDebuggerStartInfo(startArgs); // A mono process can be launched either by providing "mono" as launcher and then the assembly name as argument, // or by providing the assembly name directly as file to launch. bool explicitMonoLaunch = IsMonoLauncher(exe); if (explicitMonoLaunch) { // Try to get the assembly name from the command line. The debug session uses what's provided // in the Command property as process name. Without this, all mono processes launched in this // way would show up as "mono" in the IDE. var cmd = GetExeName(arguments); if (cmd != null) { dsi.Command = cmd; } // The new session will add additional runtime arguments to the start info. // We'll use the _ARG_START_ marker to know where those arguments end. dsi.RuntimeArguments = ArgStartMarker; } else { dsi.Command = exe; dsi.Arguments = arguments; } startArgs.CustomProcessLauncher = TargetProcessLauncher; // Start the session. This will run asynchronously, and will at some point call the custom launcher specified just above. newSession.Run(dsi, softDebuggerSession.Options); // Wait for the session to ask for the process to be launched launchingEvent.WaitOne(); if (shutdown) { return(false); } // The custom launcher will store the debugger agent configuration args in debuggerStartInfo. // No the original startInfo object is patched to include the debugger agent args if (explicitMonoLaunch) { // Prepend the debugger args to the original arguments int i = debuggerStartInfo.Arguments.IndexOf(ArgStartMarker); var debuggerArgs = debuggerStartInfo.Arguments.Substring(0, i); startInfo.GetChild("Arguments", ops).SetRawValue(debuggerArgs + " " + arguments, ops); } else { startInfo.GetChild("Arguments", ops).SetRawValue(debuggerStartInfo.Arguments, ops); startInfo.GetChild("FileName", ops).SetRawValue(debuggerStartInfo.FileName, ops); } return(true); }
public Subprocess(long threadId, SoftDebuggerSession softDebuggerSession) { ThreadId = threadId; this.softDebuggerSession = softDebuggerSession; }
DC.StackFrame CreateStackFrame(MDB.StackFrame frame) { MDB.MethodMirror method = frame.Method; MDB.TypeMirror type = method.DeclaringType; string fileName = frame.FileName; string typeFullName = null; string typeFQN = null; string methodName; if (fileName != null) { fileName = SoftDebuggerSession.NormalizePath(fileName); } if (method.VirtualMachine.Version.AtLeast(2, 12) && method.IsGenericMethod) { StringBuilder name = new StringBuilder(method.Name); name.Append('<'); if (method.VirtualMachine.Version.AtLeast(2, 15)) { bool first = true; foreach (var argumentType in method.GetGenericArguments()) { if (!first) { name.Append(", "); } name.Append(session.Adaptor.GetDisplayTypeName(argumentType.FullName)); first = false; } } name.Append('>'); methodName = name.ToString(); } else { methodName = method.Name; } // Compiler generated anonymous/lambda methods bool special_method = false; if (methodName [0] == '<' && methodName.Contains(">m__")) { int nidx = methodName.IndexOf(">m__") + 2; methodName = "AnonymousMethod" + methodName.Substring(nidx, method.Name.Length - nidx); special_method = true; } if (type != null) { string typeDisplayName = session.Adaptor.GetDisplayTypeName(type.FullName); if (SoftDebuggerAdaptor.IsGeneratedType(type)) { // The user-friendly method name is embedded in the generated type name var mn = SoftDebuggerAdaptor.GetNameFromGeneratedType(type); // Strip off the generated type name int dot = typeDisplayName.LastIndexOf('.'); var tname = typeDisplayName.Substring(0, dot); // Keep any type arguments int targs = typeDisplayName.LastIndexOf('<'); if (targs > dot + 1) { mn += typeDisplayName.Substring(targs, typeDisplayName.Length - targs); } typeDisplayName = tname; if (special_method) { typeDisplayName += "." + mn; } else { methodName = mn; } } methodName = typeDisplayName + "." + methodName; typeFQN = type.Module.FullyQualifiedName; typeFullName = type.FullName; } var location = new DC.SourceLocation(methodName, fileName, frame.LineNumber); var external = session.IsExternalCode(frame); return(new SoftDebuggerStackFrame(frame, method.FullName, location, "Managed", external, true, typeFQN, typeFullName)); }