4
// Ankit Jain <jankit@novell.com>
5
// Lluis Sanchez Gual <lluis@novell.com>
7
// Copyright (c) 2008 Novell, Inc (http://www.novell.com)
9
// Permission is hereby granted, free of charge, to any person obtaining a copy
10
// of this software and associated documentation files (the "Software"), to deal
11
// in the Software without restriction, including without limitation the rights
12
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13
// copies of the Software, and to permit persons to whom the Software is
14
// furnished to do so, subject to the following conditions:
16
// The above copyright notice and this permission notice shall be included in
17
// all copies or substantial portions of the Software.
19
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
31
using System.Collections.Generic;
32
using Mono.Debugging.Backend;
33
using System.Diagnostics;
35
namespace Mono.Debugging.Client
37
public delegate void TargetEventHandler (object sender, TargetEventArgs args);
38
public delegate void ProcessEventHandler(int process_id);
39
public delegate void ThreadEventHandler(int thread_id);
41
public abstract class DebuggerSession: IDisposable
43
InternalDebuggerSession frontend;
44
Dictionary<BreakEvent,object> breakpoints = new Dictionary<BreakEvent,object> ();
47
BreakpointStore breakpointStore;
48
OutputWriterDelegate outputWriter;
49
OutputWriterDelegate logWriter;
52
object slock = new object ();
53
object olock = new object ();
54
ThreadInfo activeThread;
55
BreakEventHitHandler customBreakpointHitHandler;
57
ProcessInfo[] currentProcesses;
59
public event EventHandler<TargetEventArgs> TargetEvent;
61
public event EventHandler TargetStarted;
62
public event EventHandler<TargetEventArgs> TargetStopped;
63
public event EventHandler<TargetEventArgs> TargetInterrupted;
64
public event EventHandler<TargetEventArgs> TargetHitBreakpoint;
65
public event EventHandler<TargetEventArgs> TargetSignaled;
66
public event EventHandler TargetExited;
67
public event EventHandler<TargetEventArgs> TargetExceptionThrown;
68
public event EventHandler<TargetEventArgs> TargetUnhandledException;
70
public DebuggerSession ()
72
frontend = new InternalDebuggerSession (this);
75
public void Initialize ()
79
public virtual void Dispose ()
89
public BreakpointStore Breakpoints {
92
if (breakpointStore == null)
93
Breakpoints = new BreakpointStore ();
94
return breakpointStore;
99
if (breakpointStore != null) {
101
foreach (BreakEvent bp in breakpointStore)
102
RemoveBreakEvent (bp);
104
breakpointStore.BreakEventAdded -= OnBreakpointAdded;
105
breakpointStore.BreakEventRemoved -= OnBreakpointRemoved;
106
breakpointStore.BreakEventModified -= OnBreakpointModified;
107
breakpointStore.BreakEventEnableStatusChanged -= OnBreakpointStatusChanged;
110
breakpointStore = value;
112
if (breakpointStore != null) {
114
foreach (BreakEvent bp in breakpointStore)
117
breakpointStore.BreakEventAdded += OnBreakpointAdded;
118
breakpointStore.BreakEventRemoved += OnBreakpointRemoved;
119
breakpointStore.BreakEventModified += OnBreakpointModified;
120
breakpointStore.BreakEventEnableStatusChanged += OnBreakpointStatusChanged;
126
public BreakEventHitHandler CustomBreakEventHitHandler {
128
return customBreakpointHitHandler;
131
customBreakpointHitHandler = value;
135
public void Run (DebuggerStartInfo startInfo)
148
public void AttachToProcess (ProcessInfo proc)
153
OnAttachToProcess (proc.Id);
162
public void Detach ()
169
public bool AttachedToProcess {
177
public ThreadInfo ActiveThread {
185
activeThread = value;
186
OnSetActiveThread (activeThread.ProcessId, activeThread.Id);
191
public void NextLine ()
204
public void StepLine ()
217
public void NextInstruction ()
222
OnNextInstruction ();
230
public void StepInstruction ()
235
OnStepInstruction ();
243
public void Finish ()
256
public bool IsBreakEventValid (BreakEvent be)
262
return (breakpoints.TryGetValue (be, out handle) && handle != null);
265
void AddBreakEvent (BreakEvent be)
267
object handle = null;
270
handle = OnInsertBreakEvent (be, be.Enabled);
271
} catch (Exception ex) {
272
Breakpoint bp = be as Breakpoint;
274
logWriter (false, "Could not set breakpoint at location '" + bp.FileName + ":" + bp.Line + "' (" + ex.Message + ")\n");
276
logWriter (false, "Could not set catchpoint for exception '" + ((Catchpoint)be).ExceptionName + "' (" + ex.Message + ")\n");
279
breakpoints.Add (be, handle);
280
Breakpoints.NotifyStatusChanged (be);
283
void RemoveBreakEvent (BreakEvent be)
286
if (GetBreakpointHandle (be, out handle)) {
287
breakpoints.Remove (be);
289
OnRemoveBreakEvent (handle);
293
void UpdateBreakEventStatus (BreakEvent be)
296
if (GetBreakpointHandle (be, out handle) && handle != null)
297
OnEnableBreakEvent (handle, be.Enabled);
300
void UpdateBreakEvent (BreakEvent be)
303
if (GetBreakpointHandle (be, out handle)) {
304
if (handle != null) {
305
object newHandle = OnUpdateBreakEvent (handle, be);
306
if (newHandle != handle && (newHandle == null || !newHandle.Equals (handle))) {
307
// Update the handle if it has changed, and notify the status change
308
breakpoints [be] = newHandle;
310
Breakpoints.NotifyStatusChanged (be);
312
// Try inserting the breakpoint again
314
handle = OnInsertBreakEvent (be, be.Enabled);
315
if (handle != null) {
317
breakpoints [be] = handle;
318
Breakpoints.NotifyStatusChanged (be);
320
} catch (Exception ex) {
321
Breakpoint bp = be as Breakpoint;
323
logWriter (false, "Could not set breakpoint at location '" + bp.FileName + ":" + bp.Line + " (" + ex.Message + ")\n");
325
logWriter (false, "Could not set catchpoint for exception '" + ((Catchpoint)be).ExceptionName + "' (" + ex.Message + ")\n");
331
void OnBreakpointAdded (object s, BreakEventArgs args)
335
AddBreakEvent (args.BreakEvent);
339
void OnBreakpointRemoved (object s, BreakEventArgs args)
343
RemoveBreakEvent (args.BreakEvent);
347
void OnBreakpointModified (object s, BreakEventArgs args)
351
UpdateBreakEvent (args.BreakEvent);
355
void OnBreakpointStatusChanged (object s, BreakEventArgs args)
359
UpdateBreakEventStatus (args.BreakEvent);
363
protected bool GetBreakpointHandle (BreakEvent be, out object handle)
365
return breakpoints.TryGetValue (be, out handle);
368
public void Continue ()
395
public bool IsRunning {
403
public ProcessInfo[] GetPocesses ()
406
if (currentProcesses == null) {
407
currentProcesses = OnGetPocesses ();
408
foreach (ProcessInfo p in currentProcesses)
411
return currentProcesses;
415
public OutputWriterDelegate OutputWriter {
416
get { return outputWriter; }
419
outputWriter = value;
424
public OutputWriterDelegate LogWriter {
425
get { return logWriter; }
433
public AssemblyLine[] DisassembleFile (string file)
436
return OnDisassembleFile (file);
440
internal ThreadInfo[] GetThreads (int processId)
443
ThreadInfo[] threads = OnGetThreads (processId);
444
foreach (ThreadInfo t in threads)
450
internal Backtrace GetBacktrace (int processId, int threadId)
453
Backtrace bt = OnGetThreadBacktrace (processId, threadId);
462
TargetEventArgs args = new TargetEventArgs (TargetEventType.TargetStopped);
463
OnTargetEvent (args);
466
internal protected void OnTargetEvent (TargetEventArgs args)
468
currentProcesses = null;
470
if (args.Process != null)
471
args.Process.Attach (this);
472
if (args.Thread != null) {
473
args.Thread.Attach (this);
474
activeThread = args.Thread;
478
case TargetEventType.ExceptionThrown:
482
if (TargetExceptionThrown != null)
483
TargetExceptionThrown (this, args);
485
case TargetEventType.TargetExited:
489
foreach (BreakEvent bp in Breakpoints)
490
Breakpoints.NotifyStatusChanged (bp);
492
if (TargetExited != null)
493
TargetExited (this, args);
495
case TargetEventType.TargetHitBreakpoint:
499
if (TargetHitBreakpoint != null)
500
TargetHitBreakpoint (this, args);
502
case TargetEventType.TargetInterrupted:
506
if (TargetInterrupted != null)
507
TargetInterrupted (this, args);
509
case TargetEventType.TargetSignaled:
513
if (TargetSignaled != null)
514
TargetSignaled (this, args);
516
case TargetEventType.TargetStopped:
520
if (TargetStopped != null)
521
TargetStopped (this, args);
523
case TargetEventType.UnhandledException:
527
if (TargetUnhandledException != null)
528
TargetUnhandledException (this, args);
531
if (TargetEvent != null)
532
TargetEvent (this, args);
535
internal void OnRunning ()
538
if (TargetStarted != null)
539
TargetStarted (this, EventArgs.Empty);
542
internal protected void OnStarted ()
546
foreach (BreakEvent bp in breakpointStore)
551
internal protected void OnTargetOutput (bool isStderr, string text)
554
if (outputWriter != null)
555
outputWriter (isStderr, text);
559
internal protected void OnDebuggerOutput (bool isStderr, string text)
562
if (logWriter != null)
563
logWriter (isStderr, text);
567
BreakEvent GetBreakEvent (object handle)
569
foreach (KeyValuePair<BreakEvent,object> e in breakpoints) {
570
if (handle == e.Value || handle.Equals (e.Value))
576
internal protected bool OnCustomBreakpointAction (string actionId, object handle)
578
BreakEvent ev = GetBreakEvent (handle);
579
return ev != null && customBreakpointHitHandler (actionId, ev);
582
protected void UpdateHitCount (object breakEventHandle, int count)
584
BreakEvent ev = GetBreakEvent (breakEventHandle);
591
protected void UpdateLastTraceValue (object breakEventHandle, string value)
593
BreakEvent ev = GetBreakEvent (breakEventHandle);
595
ev.LastTraceValue = value;
600
protected abstract void OnRun (DebuggerStartInfo startInfo);
602
protected abstract void OnAttachToProcess (int processId);
604
protected abstract void OnDetach ();
606
protected abstract void OnSetActiveThread (int processId, int threadId);
608
protected abstract void OnStop ();
610
protected abstract void OnExit ();
612
// Step one source line
613
protected abstract void OnStepLine ();
615
// Step one source line, but step over method calls
616
protected abstract void OnNextLine ();
618
// Step one instruction
619
protected abstract void OnStepInstruction ();
621
// Step one instruction, but step over method calls
622
protected abstract void OnNextInstruction ();
624
// Continue until leaving the current method
625
protected abstract void OnFinish ();
630
protected abstract object OnInsertBreakEvent (BreakEvent be, bool activate);
632
protected abstract void OnRemoveBreakEvent (object handle);
634
protected abstract object OnUpdateBreakEvent (object handle, BreakEvent be);
636
protected abstract void OnEnableBreakEvent (object handle, bool enable);
638
protected abstract void OnContinue ();
640
protected abstract ThreadInfo[] OnGetThreads (int processId);
642
protected abstract ProcessInfo[] OnGetPocesses ();
644
protected abstract Backtrace OnGetThreadBacktrace (int processId, int threadId);
646
protected virtual AssemblyLine[] OnDisassembleFile (string file)
651
protected IDebuggerSessionFrontend Frontend {
658
class InternalDebuggerSession: IDebuggerSessionFrontend
660
DebuggerSession session;
662
public InternalDebuggerSession (DebuggerSession session)
664
this.session = session;
667
public void NotifyTargetEvent (TargetEventArgs args)
669
session.OnTargetEvent (args);
672
public void NotifyTargetOutput (bool isStderr, string text)
674
session.OnTargetOutput (isStderr, text);
677
public void NotifyDebuggerOutput (bool isStderr, string text)
679
session.OnDebuggerOutput (isStderr, text);
682
public void NotifyStarted ()
684
session.OnStarted ();
687
public bool NotifyCustomBreakpointAction (string actionId, object handle)
689
return session.OnCustomBreakpointAction (actionId, handle);
693
public delegate void OutputWriterDelegate (bool isStderr, string text);