public static void RemapCmd(string args) { ArgParser ap = new ArgParser(args); if(!(Debugger.Processes.Active.StopReason is RemapOpportunityReachedStopReason)) { WriteError("Not stopped at RemapOpportunity breakpoint"); return; } RemapOpportunityReachedStopReason sr = (RemapOpportunityReachedStopReason)Debugger.Processes.Active.StopReason; if(!ap.Exists(0)) { // no arguments -- we just print content of last remap callback // we want to do remap. WriteOutput("Last FunctionRemapOpportunity Callback:"); WriteOutput("-----------------------------------------"); WriteOutput("AppDomain: "+sr.AppDomain.Name); WriteOutput("NewFunction: "+sr.NewFunction.Token); WriteOutput("OldFunction: "+sr.OldFunction.Token); WriteOutput("OldILOffset: "+sr.OldILOffset); WriteOutput("Thread Number: "+Debugger.Processes.Active.Threads.Lookup(sr.Thread).Number); } else { int newILOffset = ap.AsInt(0); sr.Thread.ActiveFrame.RemapFunction(newILOffset); Debugger.Processes.Active.Threads.InvalidateAllStacks(); WriteOutput("Remap successful."); } }
public static void WhereCmd(string arguments) { const int default_depth = 100; // default number of frames to print const string countOpt = "c"; const string verboseOpt = "v"; ArgParser ap = new ArgParser(arguments, countOpt + ":1;" + verboseOpt); int depth = default_depth; if (ap.OptionPassed(countOpt)) { ArgToken countArg = ap.GetOption(countOpt); if (countArg.AsString == "all") { depth = 0; // 0 means print entire stack } else { depth = countArg.AsInt; if (depth <= 0) { throw new MDbgShellException("Depth must be positive number or string \"all\""); } } } if (ap.Count != 0 && ap.Count != 1) { throw new MDbgShellException("Wrong # of arguments."); } if (ap.Count == 0) { // print current thread only InternalWhereCommand(Debugger.Processes.Active.Threads.Active, depth, ap.OptionPassed(verboseOpt)); } else if (ap.AsString(0).Equals("all")) { foreach (MDbgThread t in Debugger.Processes.Active.Threads) InternalWhereCommand(t, depth, ap.OptionPassed(verboseOpt)); } else { MDbgThread t = Debugger.Processes.Active.Threads[ap.AsInt(0)]; if (t == null) { throw new MDbgShellException("Wrong thread number"); } else { InternalWhereCommand(t, depth, ap.OptionPassed(verboseOpt)); } } }
public static void ShowCmd(string arguments) { MDbgSourcePosition pos = Debugger.Processes.Active.Threads.Active.CurrentSourcePosition; if (pos == null) { throw new MDbgShellException("No source location"); } string fileLoc = Shell.FileLocator.GetFileLocation(pos.Path); if (fileLoc == null) { throw new MDbgShellException(string.Format(CultureInfo.InvariantCulture, "Source file '{0}' not available.", pos.Path)); } IMDbgSourceFile file = Shell.SourceFileMgr.GetSourceFile(fileLoc); ArgParser ap = new ArgParser(arguments); if (ap.Count > 1) { throw new MDbgShellException("Wrong # of arguments."); } int around; if (ap.Exists(0)) { around = ap.AsInt(0); } else { around = 3; } int lo, hi; lo = pos.Line - around; if (lo < 1) { lo = 1; } hi = pos.Line + around; if (hi > file.Count) { hi = file.Count; } for (int i = lo; i < hi; i++) { WriteOutput(String.Format(CultureInfo.InvariantCulture, "{0}{1}{2}", i, i == pos.Line ? ":*" : " ", file[i])); } }
public static void QuitCmd(string arguments) { // Look for optional exit code. ArgParser ap = new ArgParser(arguments); int exitCode; if (ap.Exists(0)) { exitCode = ap.AsInt(0); } else { exitCode = 0; } // we cannot modify the collection during enumeration, so // we need to collect all processes to kill in advance. List<MDbgProcess> processesToKill = new List<MDbgProcess>(); foreach (MDbgProcess p in Debugger.Processes) { processesToKill.Add(p); } foreach (MDbgProcess p in processesToKill) { if (p.IsAlive) { Debugger.Processes.Active = p; WriteOutput("Terminating current process..."); try { p.Kill(); // We can't wait for targets that never run (e.g. NoninvasiveStopGoController against a dump) if (p.CanExecute()) p.StopEvent.WaitOne(); } catch { // some processes cannot be killed (e.g. the one that have not loaded runtime) try { Process np = Process.GetProcessById(p.CorProcess.Id); np.Kill(); } catch { } } } } Shell.QuitWithExitCode(exitCode); }
public static void SetIPCmd(string arguments) { const string IlOpt = "il"; ArgParser ap = new ArgParser(arguments, IlOpt); if (ap.OptionPassed(IlOpt)) { Debugger.Processes.Active.Threads.Active.CurrentFrame.CorFrame.SetIP(ap.AsInt(0)); } else { int ilOffset; if (!Debugger.Processes.Active.Threads.Active.CurrentFrame.Function.GetIPFromLine(ap.AsInt(0), out ilOffset)) { throw new MDbgShellException("cannot find correct function mapping"); } int hresult; if (!Debugger.Processes.Active.Threads.Active.CurrentFrame.CorFrame.CanSetIP(ilOffset, out hresult)) { string reason; switch ((HResult)hresult) { case HResult.CORDBG_S_BAD_START_SEQUENCE_POINT: reason = "Attempt to SetIP from non-sequence point."; break; case HResult.CORDBG_S_BAD_END_SEQUENCE_POINT: reason = "Attempt to SetIP from non-sequence point."; break; case HResult.CORDBG_S_INSUFFICIENT_INFO_FOR_SET_IP: reason = "Insufficient information to fix program flow."; break; case HResult.CORDBG_E_CANT_SET_IP_INTO_FINALLY: reason = "Attempt to SetIP into finally block."; break; case HResult.CORDBG_E_CANT_SET_IP_OUT_OF_FINALLY: case HResult.CORDBG_E_CANT_SET_IP_OUT_OF_FINALLY_ON_WIN64: reason = "Attempt to SetIP out of finally block."; break; case HResult.CORDBG_E_CANT_SET_IP_INTO_CATCH: reason = "Attempt to SetIP into catch block."; break; case HResult.CORDBG_E_CANT_SET_IP_OUT_OF_CATCH_ON_WIN64: reason = "Attempt to SetIP out of catch block."; break; case HResult.CORDBG_E_SET_IP_NOT_ALLOWED_ON_NONLEAF_FRAME: reason = "Attempt to SetIP on non-leaf frame."; break; case HResult.CORDBG_E_SET_IP_IMPOSSIBLE: reason = "The operation cannot be completed."; break; case HResult.CORDBG_E_CANT_SETIP_INTO_OR_OUT_OF_FILTER: reason = "Attempt to SetIP into or out of filter."; break; case HResult.CORDBG_E_SET_IP_NOT_ALLOWED_ON_EXCEPTION: reason = "SetIP is not allowed on exception."; break; default: reason = "Reason unknown."; break; } throw new MDbgShellException("Cannot set IP as requested. " + reason); } Debugger.Processes.Active.Threads.Active.CurrentFrame.CorFrame.SetIP(ilOffset); } Debugger.Processes.Active.Threads.InvalidateAllStacks(); Shell.DisplayCurrentLocation(); }
public static void ActiveProcess(string arguments) { ArgParser ap = new ArgParser(arguments); if (ap.Count > 1) { throw new MDbgShellException("Wrong # of arguments."); } if (ap.Exists(0)) { int logicalPID = ap.AsInt(0); bool found = false; foreach (MDbgProcess ps in Debugger.Processes) if (ps.Number == logicalPID) { Debugger.Processes.Active = ps; found = true; break; } if (found) { Shell.DisplayCurrentLocation(); } else { throw new MDbgShellException("Invalid process number"); } } else { MDbgProcess ActiveProcess = Debugger.Processes.HaveActive ? Debugger.Processes.Active : null; WriteOutput("Active Process:"); bool haveProcesses = false; CorPublish corPublish = null; foreach (MDbgProcess p in Debugger.Processes) { haveProcesses = true; string processName = p.Name; string launchMode; if (processName == null) { // in case we're attached (as opposed to launching), // we don't know process name. // Let's find it through CorPublishApi try { if (corPublish == null) { corPublish = new CorPublish(); } processName = corPublish.GetProcess(p.CorProcess.Id).DisplayName; } catch { processName = "N/A"; } launchMode = "attached"; } else { launchMode = "launched"; } WriteOutput((ActiveProcess == p ? "*" : " ") + string.Format(CultureInfo.InvariantCulture, "{0}. [PID: {1}, {2}] {3}", p.Number, p.CorProcess.Id, launchMode, processName)); } if (!haveProcesses) { WriteOutput("No Active Process!"); } } }
public static void WhenCmd(string arguments) { ArgParser ap = new ArgParser(arguments); if (ap.Count == 0) { // we want to list all actions foreach (ExecuteCmdAction a in m_events) { WriteOutput(a.Id + ".\t" + a.ToString()); } } else if (ap.AsString(0) == "delete") { if (ap.AsString(1) == "all") { // delete all actions m_events.Clear(); } else { int idx = 1; while (true) { int actionToRemove = ap.AsInt(idx); foreach (ExecuteCmdAction a in m_events) { if (a.Id == actionToRemove) { m_events.Remove(a); break; // once we remove an item, we cannot iterate further, // this doesn't matter because id's are unique. } } idx++; if (!ap.Exists(idx)) { break; } } } } else { //we want to create an when action ExecuteCmdAction action = null; string cmdString; int argCount; GetDoPart(ap, out cmdString, out argCount); switch (ap.AsString(0)) { case "StepComplete": action = new ExecuteCmdAction(Shell, cmdString, typeof(StepCompleteStopReason)); switch (argCount) { case 0: break; default: throw new ArgumentException(); } break; case "ProcessExited": action = new ExecuteCmdAction(Shell, cmdString, typeof(ProcessExitedStopReason)); switch (argCount) { case 0: break; default: throw new ArgumentException(); } break; case "ThreadCreated": action = new ExecuteCmdAction(Shell, cmdString, typeof(ThreadCreatedStopReason)); switch (argCount) { case 0: break; case 1: action.Number = ap.AsInt(1); break; default: throw new ArgumentException(); } break; case "BreakpointHit": action = new ExecuteCmdAction(Shell, cmdString, typeof(BreakpointHitStopReason)); switch (argCount) { case 0: break; case 1: action.Number = ap.AsInt(1); break; default: throw new ArgumentException(); } break; case "ModuleLoaded": action = new ExecuteCmdAction(Shell, cmdString, typeof(BreakpointHitStopReason)); switch (argCount) { case 0: break; case 1: action.Name = ap.AsString(1); break; default: throw new ArgumentException(); } break; case "ClassLoaded": action = new ExecuteCmdAction(Shell, cmdString, typeof(ClassLoadedStopReason)); switch (argCount) { case 0: break; case 1: action.Name = ap.AsString(1); break; default: throw new ArgumentException(); } break; case "AssemblyLoaded": action = new ExecuteCmdAction(Shell, cmdString, typeof(AssemblyLoadedStopReason)); switch (argCount) { case 0: break; case 1: action.Name = ap.AsString(1); break; default: throw new ArgumentException(); } break; case "AssemblyUnloaded": throw new NotImplementedException(); case "ControlCTrapped": action = new ExecuteCmdAction(Shell, cmdString, typeof(ControlCTrappedStopReason)); switch (argCount) { case 0: break; default: throw new ArgumentException(); } break; case "ExceptionThrown": action = new ExecuteCmdAction(Shell, cmdString, typeof(ExceptionThrownStopReason)); switch (argCount) { case 0: break; case 1: action.Name = ap.AsString(1); break; default: throw new ArgumentException(); } break; case "UnhandledExceptionThrown": action = new ExecuteCmdAction(Shell, cmdString, typeof(UnhandledExceptionThrownStopReason)); switch (argCount) { case 0: break; case 1: action.Name = ap.AsString(1); break; default: throw new ArgumentException(); } break; case "AsyncStop": action = new ExecuteCmdAction(Shell, cmdString, typeof(AsyncStopStopReason)); switch (argCount) { case 0: break; default: throw new ArgumentException(); } break; case "AttachComplete": if (argCount != 0) { throw new ArgumentException(); } action = new ExecuteCmdAction(Shell, cmdString, typeof(AttachCompleteStopReason)); break; case "UserBreak": if (argCount != 0) { throw new ArgumentException(); } action = new ExecuteCmdAction(Shell, cmdString, typeof(UserBreakStopReason)); break; case "EvalComplete": if (argCount != 0) { throw new ArgumentException(); } action = new ExecuteCmdAction(Shell, cmdString, typeof(EvalCompleteStopReason)); break; case "EvalException": if (argCount != 0) { throw new ArgumentException(); } action = new ExecuteCmdAction(Shell, cmdString, typeof(EvalExceptionStopReason)); break; case "RemapOpportunityReached": if (argCount != 0) { throw new ArgumentException(); } action = new ExecuteCmdAction(Shell, cmdString, typeof(RemapOpportunityReachedStopReason)); break; default: throw new ArgumentException("invalid event name"); } m_events.Add(action); } }
public static void DownCmd(string arguments) { string frameNum = "f"; ArgParser ap = new ArgParser(arguments, frameNum); if (ap.OptionPassed(frameNum)) { SwitchToFrame(ap.AsInt(0)); } else { int count = 1; if (ap.Exists(0)) { count = ap.AsInt(0); } while (--count >= 0) { Debugger.Processes.Active.Threads.Active.MoveCurrentFrame(true); } } if (Debugger.Processes.Active.Threads.Active.CurrentFrame.IsManaged) { WriteOutput("Current Frame:" + Debugger.Processes.Active.Threads.Active.CurrentFrame.Function.FullName ); } Shell.DisplayCurrentLocation(); }
public static void AttachCmd(string arguments) { const string versionArg = "ver"; const string continuationEventArg = "attachEvent"; const string pidArg = "pid"; ArgParser ap = new ArgParser(arguments, versionArg + ":1;" + continuationEventArg + ":1;" + pidArg + ":1"); if (ap.Count > 1) { throw new MDbgShellException("Wrong # of arguments."); } if (!ap.Exists(0) && !ap.OptionPassed(pidArg)) { WriteOutput("Please choose some process to attach"); ProcessEnumCmd(""); return; } int pid; if (ap.Exists(0)) { pid = ap.AsInt(0); if (ap.OptionPassed(pidArg)) { WriteOutput("Do not specify pid option when also passing pid as last argument"); return; } } else { Debug.Assert(ap.OptionPassed(pidArg)); // verified above pid = ap.GetOption(pidArg).AsInt; } // // Do some sanity checks to give useful end-user errors. // // Can't attach to ourselves! if (Process.GetCurrentProcess().Id == pid) { throw new MDbgShellException("Cannot attach to myself!"); } // Can't attach to a process that we're already debugging. // ICorDebug may enforce this, but the error may not be very descriptive for an end-user. // For example, ICD may propogate an error from the OS, and the OS may return // something like AccessDenied if another debugger is already attached. // This only checks for cases where this same instance of MDbg is already debugging // the process of interest. foreach (MDbgProcess procOther in Debugger.Processes) { if (pid == procOther.CorProcess.Id) { throw new MDbgShellException("Can't attach to process " + pid + " because it's already being debugged"); } } // Get the OS handle if there was one SafeWin32Handle osEventHandle = null; if (ap.OptionPassed(continuationEventArg)) { osEventHandle = new SafeWin32Handle(new IntPtr(ap.GetOption(continuationEventArg).AsHexOrDecInt)); } // determine the version to attach to string version = null; if (ap.OptionPassed(versionArg)) { version = ap.GetOption(versionArg).AsString; } else { version = MdbgVersionPolicy.GetDefaultAttachVersion(pid); } if (version == null) { throw new MDbgShellException("Can't determine what version of the CLR to attach to in process " + pid + ". Use -ver to specify a version"); } // attach MDbgProcess p; p = Debugger.Attach(pid, osEventHandle, version); p.Go().WaitOne(); if (osEventHandle != null) { osEventHandle.Dispose(); } }
public static void InterceptCmd(string arguments) { ArgParser ap = new ArgParser(arguments); if (ap.Count > 1) { throw new MDbgShellException("Wrong number of arguments."); } if (!ap.Exists(0)) { throw new MDbgShellException("You must supply a frame number."); } int frameID = ap.AsInt(0); MDbgFrame f = Debugger.Processes.Active.Threads.Active.BottomFrame; while (--frameID >= 0) { f = f.NextUp; if (f == null) { break; } } if (f == null) { throw new MDbgShellException("Invalid frame number."); } CorThread t = Debugger.Processes.Active.Threads.Active.CorThread; t.InterceptCurrentException(f.CorFrame); WriteOutput("Interception point is set."); }
public static void DeleteCmd(string arguments) { ArgParser ap = new ArgParser(arguments); if (ap.Count != 1) { WriteOutput("Please choose some breakpoint to delete"); BreakCmd(""); return; } MDbgBreakpoint breakpoint = Debugger.Processes.Active.Breakpoints[ap.AsInt(0)]; if (breakpoint == null) { throw new MDbgShellException("Could not find breakpint #:" + ap.AsInt(0)); } else { breakpoint.Delete(); } }
public static void AttachCmd(string arguments) { ArgParser ap = new ArgParser(arguments); if (ap.Count > 1) { throw new MDbgShellException("Wrong # of arguments."); } if (!ap.Exists(0)) { throw new MDbgShellException("Wrong # of arguments."); } int pid = ap.AsInt(0); if (Process.GetCurrentProcess().Id == pid) { throw new MDbgShellException("Cannot attach to myself!"); } // time to attach, since the user isn't able to specify the DebugModeFlag for attach, use Debug which is the // default if (false == DebugActiveSilverlightProcess(pid, DebugModeFlag.Debug)) { throw new MDbgShellException("Could not find a match for *"); } }