3 using System
.Threading
;
5 using System
.Diagnostics
;
6 using System
.Collections
;
7 using System
.Collections
.Generic
;
9 namespace Mono
.Debugger
.Soft
11 public class VirtualMachine
: Mirror
15 object startup_monitor
;
16 AppDomainMirror root_domain
;
17 Dictionary
<int, EventRequest
> requests
;
18 ITargetProcess process
;
20 internal Connection conn
;
24 internal VirtualMachine (ITargetProcess process
, Connection conn
) : base () {
25 SetVirtualMachine (this);
27 queue_monitor
= new Object ();
28 startup_monitor
= new Object ();
29 requests
= new Dictionary
<int, EventRequest
> ();
31 this.process
= process
;
32 conn
.ErrorHandler
+= ErrorHandler
;
35 // The standard output of the process is available normally through Process
36 public StreamReader StandardOutput { get; set; }
37 public StreamReader StandardError { get; set; }
40 public Process Process
{
42 ProcessWrapper pw
= process
as ProcessWrapper
;
44 throw new InvalidOperationException ("Process instance not available");
49 public ITargetProcess TargetProcess
{
55 public AppDomainMirror RootDomain
{
61 public EndPoint EndPoint
{
63 var tcpConn
= conn
as TcpConnection
;
65 return tcpConn
.EndPoint
;
70 public VersionInfo Version
{
80 * It is impossible to determine when to resume when using this method, since
81 * the debuggee is suspended only once per event-set, not event.
83 [Obsolete ("Use GetNextEventSet () instead")]
84 public Event
GetNextEvent () {
85 lock (queue_monitor
) {
86 if (current_es
== null || current_es_index
== current_es
.Events
.Length
) {
88 Monitor
.Wait (queue_monitor
);
89 current_es
= (EventSet
)queue
.Dequeue ();
92 return current_es
.Events
[current_es_index
++];
96 public Event
GetNextEvent (int timeout
) {
97 throw new NotImplementedException ();
100 public EventSet
GetNextEventSet () {
101 lock (queue_monitor
) {
102 if (queue
.Count
== 0)
103 Monitor
.Wait (queue_monitor
);
106 current_es_index
= 0;
108 return (EventSet
)queue
.Dequeue ();
112 public EventSet
GetNextEventSet (int timeoutInMilliseconds
) {
113 lock (queue_monitor
) {
114 if (queue
.Count
== 0) {
115 if (!Monitor
.Wait (queue_monitor
, timeoutInMilliseconds
)) {
121 current_es_index
= 0;
123 return (EventSet
)queue
.Dequeue ();
127 [Obsolete ("Use GetNextEventSet () instead")]
128 public T GetNextEvent
<T
> () where T
: Event
{
129 return GetNextEvent () as T
;
132 public void Suspend () {
136 public void Resume () {
138 InvalidateThreadAndFrameCaches ();
140 } catch (CommandException ex
) {
141 if (ex
.ErrorCode
== ErrorCode
.NOT_SUSPENDED
)
142 throw new VMNotSuspendedException ();
148 public void Exit (int exitCode
) {
149 conn
.VM_Exit (exitCode
);
152 public void Detach () {
153 // Notify the application that we are detaching
155 // Close the connection. No further messages can be sent
156 // over the connection after this point.
158 notify_vm_event (EventType
.VMDisconnect
, SuspendPolicy
.None
, 0, 0, null, 0);
161 [Obsolete ("This method was poorly named; use the Detach() method instead")]
162 public void Dispose ()
167 public void ForceDisconnect ()
169 conn
.ForceDisconnect ();
172 HashSet
<ThreadMirror
> threadsToInvalidate
= new HashSet
<ThreadMirror
> ();
173 ThreadMirror
[] threadCache
;
175 void InvalidateThreadAndFrameCaches () {
176 lock (threadsToInvalidate
) {
177 foreach (var thread
in threadsToInvalidate
)
178 thread
.InvalidateFrames ();
179 threadsToInvalidate
.Clear ();
184 internal void InvalidateThreadCache () {
188 internal void AddThreadToInvalidateList (ThreadMirror threadMirror
)
190 lock (threadsToInvalidate
) {
191 threadsToInvalidate
.Add (threadMirror
);
195 public IList
<ThreadMirror
> GetThreads () {
196 var threads
= threadCache
;
197 if (threads
== null) {
199 var fetchingEvent
= new ManualResetEvent (false);
200 vm
.conn
.VM_GetThreads ((threadsIds
) => {
202 threads
= new ThreadMirror
[threadsIds
.Length
];
203 fetchingEvent
.Set ();
205 if (WaitHandle
.WaitAny (new []{ vm.conn.DisconnectedEvent, fetchingEvent }
) == 0) {
206 throw new VMDisconnectedException ();
208 for (int i
= 0; i
< ids
.Length
; ++i
)
209 threads
[i
] = GetThread (ids
[i
]);
210 //Uncomment lines below if you want to re-fetch threads if new threads were started/stopped while
211 //featching threads... This is probably more correct but might cause deadlock of this method if runtime
212 //is starting/stopping threads nonstop, need way to prevent this(counting number of recursions?)
213 //possiblity before uncommenting
214 //if (threadCache != threads) {//While fetching threads threadCache was invalidated(thread was created/destoyed)
215 // return GetThreads ();
217 Thread
.MemoryBarrier ();
218 threadCache
= threads
;
225 // Same as the mirrorOf methods in JDI
226 public PrimitiveValue
CreateValue (object value) {
228 return new PrimitiveValue (vm
, null);
230 if (!value.GetType ().IsPrimitive
)
231 throw new ArgumentException ("value must be of a primitive type instead of '" + value.GetType () + "'", "value");
233 return new PrimitiveValue (vm
, value);
236 public EnumMirror
CreateEnumMirror (TypeMirror type
, PrimitiveValue
value) {
237 return new EnumMirror (this, type
, value);
241 // Enable send and receive timeouts on the connection and send a keepalive event
242 // every 'keepalive_interval' milliseconds.
245 public void SetSocketTimeouts (int send_timeout
, int receive_timeout
, int keepalive_interval
)
247 conn
.SetSocketTimeouts (send_timeout
, receive_timeout
, keepalive_interval
);
251 // Methods to create event request objects
253 public BreakpointEventRequest
CreateBreakpointRequest (MethodMirror method
, long il_offset
) {
254 return new BreakpointEventRequest (this, method
, il_offset
);
257 public BreakpointEventRequest
CreateBreakpointRequest (Location loc
) {
259 throw new ArgumentNullException ("loc");
261 return new BreakpointEventRequest (this, loc
.Method
, loc
.ILOffset
);
264 public StepEventRequest
CreateStepRequest (ThreadMirror thread
) {
265 return new StepEventRequest (this, thread
);
268 public MethodEntryEventRequest
CreateMethodEntryRequest () {
269 return new MethodEntryEventRequest (this);
272 public MethodExitEventRequest
CreateMethodExitRequest () {
273 return new MethodExitEventRequest (this);
276 public ExceptionEventRequest
CreateExceptionRequest (TypeMirror exc_type
) {
277 return new ExceptionEventRequest (this, exc_type
, true, true);
280 public ExceptionEventRequest
CreateExceptionRequest (TypeMirror exc_type
, bool caught
, bool uncaught
) {
281 return new ExceptionEventRequest (this, exc_type
, caught
, uncaught
);
284 public ExceptionEventRequest
CreateExceptionRequest (TypeMirror exc_type
, bool caught
, bool uncaught
, bool everything_else
) {
285 if (Version
.AtLeast (2, 54))
286 return new ExceptionEventRequest (this, exc_type
, caught
, uncaught
, true, everything_else
);
288 return new ExceptionEventRequest (this, exc_type
, caught
, uncaught
);
291 public AssemblyLoadEventRequest
CreateAssemblyLoadRequest () {
292 return new AssemblyLoadEventRequest (this);
295 public TypeLoadEventRequest
CreateTypeLoadRequest () {
296 return new TypeLoadEventRequest (this);
299 public void EnableEvents (params EventType
[] events
) {
300 EnableEvents (events
, SuspendPolicy
.All
);
303 public void EnableEvents (EventType
[] events
, SuspendPolicy suspendPolicy
) {
304 foreach (EventType etype
in events
) {
305 if (etype
== EventType
.Breakpoint
)
306 throw new ArgumentException ("Breakpoint events cannot be requested using EnableEvents", "events");
307 conn
.EnableEvent (etype
, suspendPolicy
, null);
311 public BreakpointEventRequest
SetBreakpoint (MethodMirror method
, long il_offset
) {
312 BreakpointEventRequest req
= CreateBreakpointRequest (method
, il_offset
);
319 public void ClearAllBreakpoints () {
320 conn
.ClearAllBreakpoints ();
323 public void Disconnect () {
328 // Return a list of TypeMirror objects for all loaded types which reference the
329 // source file FNAME. Might return false positives.
330 // Since protocol version 2.7.
332 public IList
<TypeMirror
> GetTypesForSourceFile (string fname
, bool ignoreCase
) {
333 long[] ids
= conn
.VM_GetTypesForSourceFile (fname
, ignoreCase
);
334 var res
= new TypeMirror
[ids
.Length
];
335 for (int i
= 0; i
< ids
.Length
; ++i
)
336 res
[i
] = GetType (ids
[i
]);
341 // Return a list of TypeMirror objects for all loaded types named 'NAME'.
342 // NAME should be in the the same for as with Assembly.GetType ().
343 // Since protocol version 2.9.
345 public IList
<TypeMirror
> GetTypes (string name
, bool ignoreCase
) {
346 long[] ids
= conn
.VM_GetTypes (name
, ignoreCase
);
347 var res
= new TypeMirror
[ids
.Length
];
348 for (int i
= 0; i
< ids
.Length
; ++i
)
349 res
[i
] = GetType (ids
[i
]);
353 internal void queue_event_set (EventSet es
) {
354 lock (queue_monitor
) {
356 Monitor
.Pulse (queue_monitor
);
360 internal void ErrorHandler (object sender
, ErrorHandlerEventArgs args
) {
361 switch (args
.ErrorCode
) {
362 case ErrorCode
.INVALID_OBJECT
:
363 throw new ObjectCollectedException ();
364 case ErrorCode
.INVALID_FRAMEID
:
365 throw new InvalidStackFrameException ();
366 case ErrorCode
.NOT_SUSPENDED
:
367 throw new VMNotSuspendedException ();
368 case ErrorCode
.NOT_IMPLEMENTED
:
369 throw new NotSupportedException ("This request is not supported by the protocol version implemented by the debuggee.");
370 case ErrorCode
.ABSENT_INFORMATION
:
371 throw new AbsentInformationException ();
372 case ErrorCode
.NO_SEQ_POINT_AT_IL_OFFSET
:
373 throw new ArgumentException ("Cannot set breakpoint on the specified IL offset.");
375 throw new CommandException (args
.ErrorCode
, args
.ErrorMessage
);
379 /* Wait for the debuggee to start up and connect to it */
380 internal void connect () {
383 // Test the connection
384 version
= conn
.Version
;
385 if (version
.MajorVersion
!= Connection
.MAJOR_VERSION
)
386 throw new NotSupportedException (String
.Format ("The debuggee implements protocol version {0}.{1}, while {2}.{3} is required.", version
.MajorVersion
, version
.MinorVersion
, Connection
.MAJOR_VERSION
, Connection
.MINOR_VERSION
));
388 long root_domain_id
= conn
.RootDomain
;
389 root_domain
= GetDomain (root_domain_id
);
392 internal void notify_vm_event (EventType evtype
, SuspendPolicy spolicy
, int req_id
, long thread_id
, string vm_uri
, int exit_code
) {
393 //Console.WriteLine ("Event: " + evtype + "(" + vm_uri + ")");
396 case EventType
.VMStart
:
397 /* Notify the main thread that the debuggee started up */
398 lock (startup_monitor
) {
399 Monitor
.Pulse (startup_monitor
);
401 queue_event_set (new EventSet (this, spolicy
, new Event
[] { new VMStartEvent (vm, req_id, thread_id) }
));
403 case EventType
.VMDeath
:
404 queue_event_set (new EventSet (this, spolicy
, new Event
[] { new VMDeathEvent (vm, req_id, exit_code) }
));
406 case EventType
.VMDisconnect
:
407 queue_event_set (new EventSet (this, spolicy
, new Event
[] { new VMDisconnectEvent (vm, req_id) }
));
410 throw new Exception ();
415 // Methods to create instances of mirror objects
419 class MirrorCache<T> {
420 static Dictionary <long, T> mirrors;
421 static object mirror_lock = new object ();
423 internal static T GetMirror (VirtualMachine vm, long id) {
426 mirrors = new Dictionary <long, T> ();
428 if (!mirrors.TryGetValue (id, out obj)) {
429 obj = CreateMirror (vm, id);
436 internal static T CreateMirror (VirtualMachine vm, long id) {
441 // FIXME: When to remove items from the cache ?
443 Dictionary
<long, MethodMirror
> methods
;
444 object methods_lock
= new object ();
446 internal MethodMirror
GetMethod (long id
) {
447 lock (methods_lock
) {
449 methods
= new Dictionary
<long, MethodMirror
> ();
453 if (!methods
.TryGetValue (id
, out obj
)) {
454 obj
= new MethodMirror (this, id
);
461 Dictionary
<long, AssemblyMirror
> assemblies
;
462 object assemblies_lock
= new object ();
464 internal AssemblyMirror
GetAssembly (long id
) {
465 lock (assemblies_lock
) {
466 if (assemblies
== null)
467 assemblies
= new Dictionary
<long, AssemblyMirror
> ();
471 if (!assemblies
.TryGetValue (id
, out obj
)) {
472 obj
= new AssemblyMirror (this, id
);
473 assemblies
[id
] = obj
;
479 Dictionary
<long, ModuleMirror
> modules
;
480 object modules_lock
= new object ();
482 internal ModuleMirror
GetModule (long id
) {
483 lock (modules_lock
) {
485 modules
= new Dictionary
<long, ModuleMirror
> ();
489 if (!modules
.TryGetValue (id
, out obj
)) {
490 obj
= new ModuleMirror (this, id
);
497 Dictionary
<long, AppDomainMirror
> domains
;
498 object domains_lock
= new object ();
500 internal AppDomainMirror
GetDomain (long id
) {
501 lock (domains_lock
) {
503 domains
= new Dictionary
<long, AppDomainMirror
> ();
507 if (!domains
.TryGetValue (id
, out obj
)) {
508 obj
= new AppDomainMirror (this, id
);
515 internal void InvalidateAssemblyCaches () {
516 lock (domains_lock
) {
517 foreach (var d
in domains
.Values
)
518 d
.InvalidateAssembliesCache ();
522 Dictionary
<long, TypeMirror
> types
;
523 object types_lock
= new object ();
525 internal TypeMirror
GetType (long id
) {
528 types
= new Dictionary
<long, TypeMirror
> ();
532 if (!types
.TryGetValue (id
, out obj
)) {
533 obj
= new TypeMirror (this, id
);
540 internal TypeMirror
[] GetTypes (long[] ids
) {
541 var res
= new TypeMirror
[ids
.Length
];
542 for (int i
= 0; i
< ids
.Length
; ++i
)
543 res
[i
] = GetType (ids
[i
]);
547 Dictionary
<long, ObjectMirror
> objects
;
548 object objects_lock
= new object ();
550 // Return a mirror if it exists
551 // Does not call into the debuggee
552 internal T TryGetObject
<T
> (long id
) where T
: ObjectMirror
{
553 lock (objects_lock
) {
555 objects
= new Dictionary
<long, ObjectMirror
> ();
557 objects
.TryGetValue (id
, out obj
);
562 internal T GetObject
<T
> (long id
, long domain_id
, long type_id
) where T
: ObjectMirror
{
563 ObjectMirror obj
= null;
564 lock (objects_lock
) {
566 objects
= new Dictionary
<long, ObjectMirror
> ();
567 objects
.TryGetValue (id
, out obj
);
572 * Obtain the domain/type of the object to determine the type of
573 * object we need to create. Do this outside the lock.
575 if (domain_id
== 0 || type_id
== 0) {
576 if (conn
.Version
.AtLeast (2, 5)) {
577 var info
= conn
.Object_GetInfo (id
);
578 domain_id
= info
.domain_id
;
579 type_id
= info
.type_id
;
582 domain_id
= conn
.Object_GetDomain (id
);
584 type_id
= conn
.Object_GetType (id
);
587 AppDomainMirror d
= GetDomain (domain_id
);
588 TypeMirror t
= GetType (type_id
);
590 if (t
.Assembly
== d
.Corlib
&& t
.Namespace
== "System.Threading" && t
.Name
== "Thread")
591 obj
= new ThreadMirror (this, id
, t
, d
);
592 else if (t
.Assembly
== d
.Corlib
&& t
.Namespace
== "System" && t
.Name
== "String")
593 obj
= new StringMirror (this, id
, t
, d
);
594 else if (typeof (T
) == typeof (ArrayMirror
))
595 obj
= new ArrayMirror (this, id
, t
, d
);
597 obj
= new ObjectMirror (this, id
, t
, d
);
600 lock (objects_lock
) {
601 ObjectMirror prev_obj
;
602 if (objects
.TryGetValue (id
, out prev_obj
))
611 internal T GetObject
<T
> (long id
) where T
: ObjectMirror
{
612 return GetObject
<T
> (id
, 0, 0);
615 internal ObjectMirror
GetObject (long objid
) {
616 return GetObject
<ObjectMirror
> (objid
);
619 internal ThreadMirror
GetThread (long id
) {
620 return GetObject
<ThreadMirror
> (id
);
623 internal ThreadMirror
TryGetThread (long id
) {
624 return TryGetObject
<ThreadMirror
> (id
);
627 Dictionary
<long, FieldInfoMirror
> fields
;
628 object fields_lock
= new object ();
630 internal FieldInfoMirror
GetField (long id
) {
633 fields
= new Dictionary
<long, FieldInfoMirror
> ();
637 if (!fields
.TryGetValue (id
, out obj
)) {
638 obj
= new FieldInfoMirror (this, id
);
645 object requests_lock
= new object ();
647 internal void AddRequest (EventRequest req
, int id
) {
648 lock (requests_lock
) {
653 internal void RemoveRequest (EventRequest req
, int id
) {
654 lock (requests_lock
) {
655 requests
.Remove (id
);
659 internal EventRequest
GetRequest (int id
) {
660 lock (requests_lock
) {
662 requests
.TryGetValue (id
, out obj
);
667 internal Value
DecodeValue (ValueImpl v
) {
668 return DecodeValue (v
, null);
671 internal Value
DecodeValue (ValueImpl v
, Dictionary
<int, Value
> parent_vtypes
) {
672 if (v
.Value
!= null) {
673 if (Version
.AtLeast (2, 46) && (v
.Type
== ElementType
.Ptr
|| v
.Type
== ElementType
.FnPtr
))
674 return new PointerValue(this, GetType(v
.Klass
), (long)v
.Value
);
675 return new PrimitiveValue (this, v
.Value
);
679 case ElementType
.Void
:
681 case ElementType
.SzArray
:
682 case ElementType
.Array
:
683 return GetObject
<ArrayMirror
> (v
.Objid
);
684 case ElementType
.String
:
685 return GetObject
<StringMirror
> (v
.Objid
);
686 case ElementType
.Class
:
687 case ElementType
.Object
:
688 return GetObject (v
.Objid
);
689 case ElementType
.ValueType
:
690 if (parent_vtypes
== null)
691 parent_vtypes
= new Dictionary
<int, Value
> ();
694 vtype
= new EnumMirror (this, GetType (v
.Klass
), (Value
[])null);
696 vtype
= new StructMirror (this, GetType (v
.Klass
), (Value
[])null);
697 parent_vtypes
[parent_vtypes
.Count
] = vtype
;
698 vtype
.SetFields (DecodeValues (v
.Fields
, parent_vtypes
));
699 parent_vtypes
.Remove (parent_vtypes
.Count
- 1);
701 case (ElementType
)ValueTypeId
.VALUE_TYPE_ID_NULL
:
702 return new PrimitiveValue (this, null);
703 case (ElementType
)ValueTypeId
.VALUE_TYPE_ID_PARENT_VTYPE
:
704 return parent_vtypes
[v
.Index
];
706 throw new NotImplementedException ("" + v
.Type
);
710 internal Value
[] DecodeValues (ValueImpl
[] values
) {
711 Value
[] res
= new Value
[values
.Length
];
712 for (int i
= 0; i
< values
.Length
; ++i
)
713 res
[i
] = DecodeValue (values
[i
]);
717 internal Value
[] DecodeValues (ValueImpl
[] values
, Dictionary
<int, Value
> parent_vtypes
) {
718 Value
[] res
= new Value
[values
.Length
];
719 for (int i
= 0; i
< values
.Length
; ++i
)
720 res
[i
] = DecodeValue (values
[i
], parent_vtypes
);
724 internal ValueImpl
EncodeValue (Value v
, List
<Value
> duplicates
= null) {
725 if (v
is PrimitiveValue
) {
726 object val
= (v
as PrimitiveValue
).Value
;
728 return new ValueImpl { Type = (ElementType)ValueTypeId.VALUE_TYPE_ID_NULL, Objid = 0 }
;
730 return new ValueImpl { Value = val }
;
731 } else if (v
is ObjectMirror
) {
732 return new ValueImpl { Type = ElementType.Object, Objid = (v as ObjectMirror).Id }
;
733 } else if (v
is StructMirror
) {
734 if (duplicates
== null)
735 duplicates
= new List
<Value
> ();
736 if (duplicates
.Contains (v
))
737 return new ValueImpl { Type = (ElementType)ValueTypeId.VALUE_TYPE_ID_NULL, Objid = 0 }
;
740 return new ValueImpl { Type = ElementType.ValueType, Klass = (v as StructMirror).Type.Id, Fields = EncodeFieldValues ((v as StructMirror).Fields, (v as StructMirror).Type.GetFields (), duplicates, 1) }
;
741 } else if (v
is PointerValue
) {
742 PointerValue val
= (PointerValue
)v
;
743 return new ValueImpl { Type = ElementType.Ptr, Klass = val.Type.Id, Value = val.Address }
;
745 throw new NotSupportedException ("Value of type " + v
.GetType());
749 internal ValueImpl
EncodeValueFixedSize (Value v
, List
<Value
> duplicates
, int len_fixed_size
) {
750 if (v
is PrimitiveValue
) {
751 object val
= (v
as PrimitiveValue
).Value
;
753 return new ValueImpl { Type = (ElementType)ValueTypeId.VALUE_TYPE_ID_NULL, Objid = 0 }
;
755 return new ValueImpl { Value = val , FixedSize = len_fixed_size}
;
756 } else if (v
is ObjectMirror
) {
757 return new ValueImpl { Type = ElementType.Object, Objid = (v as ObjectMirror).Id }
;
758 } else if (v
is StructMirror
) {
759 if (duplicates
== null)
760 duplicates
= new List
<Value
> ();
761 if (duplicates
.Contains (v
))
762 return new ValueImpl { Type = (ElementType)ValueTypeId.VALUE_TYPE_ID_NULL, Objid = 0 }
;
765 return new ValueImpl { Type = ElementType.ValueType, Klass = (v as StructMirror).Type.Id, Fields = EncodeFieldValues ((v as StructMirror).Fields, (v as StructMirror).Type.GetFields (), duplicates, len_fixed_size) }
;
766 } else if (v
is PointerValue
) {
767 PointerValue val
= (PointerValue
)v
;
768 return new ValueImpl { Type = ElementType.Ptr, Klass = val.Type.Id, Value = val.Address }
;
770 throw new NotSupportedException ("Value of type " + v
.GetType());
774 internal ValueImpl
[] EncodeValues (IList
<Value
> values
, List
<Value
> duplicates
= null) {
775 ValueImpl
[] res
= new ValueImpl
[values
.Count
];
776 for (int i
= 0; i
< values
.Count
; ++i
)
777 res
[i
] = EncodeValue (values
[i
], duplicates
);
781 internal ValueImpl
[] EncodeFieldValues (IList
<Value
> values
, FieldInfoMirror
[] field_info
, List
<Value
> duplicates
, int fixedSize
) {
782 ValueImpl
[] res
= new ValueImpl
[values
.Count
];
783 for (int i
= 0; i
< values
.Count
; ++i
) {
784 if (fixedSize
> 1 || field_info
[i
].FixedSize
> 1)
785 res
[i
] = EncodeValueFixedSize (values
[i
], duplicates
, fixedSize
> 1 ? fixedSize
: field_info
[i
].FixedSize
);
787 res
[i
] = EncodeValue (values
[i
], duplicates
);
792 internal void CheckProtocolVersion (int major
, int minor
) {
793 if (!conn
.Version
.AtLeast (major
, minor
))
794 throw new NotSupportedException ("This request is not supported by the protocol version implemented by the debuggee.");
798 class EventHandler
: MarshalByRefObject
, IEventHandler
802 public EventHandler (VirtualMachine vm
) {
806 public void Events (SuspendPolicy suspend_policy
, EventInfo
[] events
) {
807 var l
= new List
<Event
> ();
809 for (int i
= 0; i
< events
.Length
; ++i
) {
810 EventInfo ei
= events
[i
];
811 int req_id
= ei
.ReqId
;
812 long thread_id
= ei
.ThreadId
;
814 long loc
= ei
.Location
;
816 switch (ei
.EventType
) {
817 case EventType
.VMStart
:
818 vm
.notify_vm_event (EventType
.VMStart
, suspend_policy
, req_id
, thread_id
, null, 0);
820 case EventType
.VMDeath
:
821 vm
.notify_vm_event (EventType
.VMDeath
, suspend_policy
, req_id
, thread_id
, null, ei
.ExitCode
);
823 case EventType
.ThreadStart
:
824 vm
.InvalidateThreadCache ();
825 l
.Add (new ThreadStartEvent (vm
, req_id
, id
));
827 case EventType
.ThreadDeath
:
828 // Avoid calling GetThread () since it might call into the debuggee
829 // and we can't do that in the event handler
830 var thread
= vm
.TryGetThread (id
);
832 thread
.InvalidateFrames ();
833 vm
.InvalidateThreadCache ();
834 l
.Add (new ThreadDeathEvent (vm
, req_id
, id
));
836 case EventType
.AssemblyLoad
:
837 vm
.InvalidateAssemblyCaches ();
838 l
.Add (new AssemblyLoadEvent (vm
, req_id
, thread_id
, id
));
840 case EventType
.AssemblyUnload
:
841 vm
.InvalidateAssemblyCaches ();
842 l
.Add (new AssemblyUnloadEvent (vm
, req_id
, thread_id
, id
));
844 case EventType
.TypeLoad
:
845 l
.Add (new TypeLoadEvent (vm
, req_id
, thread_id
, id
));
847 case EventType
.MethodEntry
:
848 l
.Add (new MethodEntryEvent (vm
, req_id
, thread_id
, id
));
850 case EventType
.MethodExit
:
851 l
.Add (new MethodExitEvent (vm
, req_id
, thread_id
, id
));
853 case EventType
.Breakpoint
:
854 l
.Add (new BreakpointEvent (vm
, req_id
, thread_id
, id
, loc
));
857 l
.Add (new StepEvent (vm
, req_id
, thread_id
, id
, loc
));
859 case EventType
.Exception
:
860 l
.Add (new ExceptionEvent (vm
, req_id
, thread_id
, id
, loc
));
862 case EventType
.AppDomainCreate
:
863 l
.Add (new AppDomainCreateEvent (vm
, req_id
, thread_id
, id
));
865 case EventType
.AppDomainUnload
:
866 l
.Add (new AppDomainUnloadEvent (vm
, req_id
, thread_id
, id
));
868 case EventType
.UserBreak
:
869 l
.Add (new UserBreakEvent (vm
, req_id
, thread_id
));
871 case EventType
.UserLog
:
872 l
.Add (new UserLogEvent (vm
, req_id
, thread_id
, ei
.Level
, ei
.Category
, ei
.Message
));
874 case EventType
.Crash
:
875 l
.Add (new CrashEvent (vm
, req_id
, thread_id
, ei
.Dump
, ei
.Hash
));
881 vm
.queue_event_set (new EventSet (vm
, suspend_policy
, l
.ToArray ()));
884 public void VMDisconnect (int req_id
, long thread_id
, string vm_uri
) {
885 vm
.notify_vm_event (EventType
.VMDisconnect
, SuspendPolicy
.None
, req_id
, thread_id
, vm_uri
, 0);
889 public class CommandException
: Exception
{
891 internal CommandException (ErrorCode error_code
, string error_message
) : base ("Debuggee returned error code " + error_code
+ (error_message
== null || error_message
.Length
== 0 ? "." : " - " + error_message
+ ".")) {
892 ErrorCode
= error_code
;
893 ErrorMessage
= error_message
;
896 public ErrorCode ErrorCode
{
900 public string ErrorMessage
{
905 public class VMNotSuspendedException
: InvalidOperationException
907 public VMNotSuspendedException () : base ("The vm is not suspended.")