Merge pull request #1407 from chrisvire/bug-24587
[mono.git] / mono / mini / debugger-agent.c
1 /*
2  * debugger-agent.c: Soft Debugger back-end module
3  *
4  * Author:
5  *   Zoltan Varga (vargaz@gmail.com)
6  *
7  * Copyright 2009-2010 Novell, Inc.
8  * Copyright 2011 Xamarin Inc.
9  */
10
11 #include <config.h>
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #ifdef HAVE_SYS_TYPES_H
16 #include <sys/types.h>
17 #endif
18 #ifdef HAVE_SYS_SELECT_H
19 #include <sys/select.h>
20 #endif
21 #ifdef HAVE_SYS_SOCKET_H
22 #include <sys/socket.h>
23 #endif
24 #ifdef HAVE_NETINET_TCP_H
25 #include <netinet/tcp.h>
26 #endif
27 #ifdef HAVE_NETINET_IN_H
28 #include <netinet/in.h>
29 #endif
30 #ifdef HAVE_NETDB_H
31 #include <netdb.h>
32 #endif
33 #ifdef HAVE_UNISTD_H
34 #include <unistd.h>
35 #endif
36 #include <errno.h>
37 #include <glib.h>
38
39 #ifdef HAVE_PTHREAD_H
40 #include <pthread.h>
41 #endif
42
43 #ifdef HAVE_UCONTEXT_H
44 #include <ucontext.h>
45 #endif
46
47 #ifdef HOST_WIN32
48 #ifdef _MSC_VER
49 #include <winsock2.h>
50 #include <process.h>
51 #endif
52 #include <ws2tcpip.h>
53 #ifdef __GNUC__
54 /* cygwin's headers do not seem to define these */
55 void WSAAPI freeaddrinfo (struct addrinfo*);
56 int WSAAPI getaddrinfo (const char*,const char*,const struct addrinfo*,
57                         struct addrinfo**);
58 int WSAAPI getnameinfo(const struct sockaddr*,socklen_t,char*,DWORD,
59                        char*,DWORD,int);
60 #endif
61 #endif
62
63 #ifdef PLATFORM_ANDROID
64 #include <linux/in.h>
65 #include <linux/tcp.h>
66 #include <sys/endian.h>
67 #endif
68
69 #include <mono/metadata/mono-debug.h>
70 #include <mono/metadata/mono-debug-debugger.h>
71 #include <mono/metadata/debug-mono-symfile.h>
72 #include <mono/metadata/gc-internal.h>
73 #include <mono/metadata/environment.h>
74 #include <mono/metadata/threads-types.h>
75 #include <mono/metadata/socket-io.h>
76 #include <mono/metadata/assembly.h>
77 #include <mono/metadata/runtime.h>
78 #include <mono/metadata/threadpool.h>
79 #include <mono/metadata/verify-internals.h>
80 #include <mono/utils/mono-semaphore.h>
81 #include <mono/utils/mono-error-internals.h>
82 #include <mono/utils/mono-stack-unwinding.h>
83 #include <mono/utils/mono-time.h>
84 #include <mono/utils/mono-threads.h>
85 #include "debugger-agent.h"
86 #include "mini.h"
87
88 /*
89 On iOS we can't use System.Environment.Exit () as it will do the wrong
90 shutdown sequence.
91 */
92 #if !defined (TARGET_IOS)
93 #define TRY_MANAGED_SYSTEM_ENVIRONMENT_EXIT
94 #endif
95
96
97 #ifndef MONO_ARCH_SOFT_DEBUG_SUPPORTED
98 #define DISABLE_DEBUGGER_AGENT 1
99 #endif
100
101 #ifdef DISABLE_SOFT_DEBUG
102 #define DISABLE_DEBUGGER_AGENT 1
103 #endif
104
105 #ifndef DISABLE_DEBUGGER_AGENT
106
107 #include <mono/utils/mono-mutex.h>
108
109 /* Definitions to make backporting to 2.6 easier */
110 //#define MonoInternalThread MonoThread
111 //#define mono_thread_internal_current mono_thread_current
112 #define THREAD_TO_INTERNAL(thread) (thread)->internal_thread
113
114 typedef struct {
115         gboolean enabled;
116         char *transport;
117         char *address;
118         int log_level;
119         char *log_file;
120         gboolean suspend;
121         gboolean server;
122         gboolean onuncaught;
123         GSList *onthrow;
124         int timeout;
125         char *launch;
126         gboolean embedding;
127         gboolean defer;
128         int keepalive;
129         gboolean setpgid;
130 } AgentConfig;
131
132 typedef struct
133 {
134         int id;
135         guint32 il_offset, native_offset;
136         MonoDomain *domain;
137         MonoMethod *method;
138         /*
139          * If method is gshared, this is the actual instance, otherwise this is equal to
140          * method.
141          */
142         MonoMethod *actual_method;
143         /*
144          * This is the method which is visible to debugger clients. Same as method,
145          * except for native-to-managed wrappers.
146          */
147         MonoMethod *api_method;
148         MonoContext ctx;
149         MonoDebugMethodJitInfo *jit;
150         MonoJitInfo *ji;
151         int flags;
152         mgreg_t *reg_locations [MONO_MAX_IREGS];
153         /*
154          * Whenever ctx is set. This is FALSE for the last frame of running threads, since
155          * the frame can become invalid.
156          */
157         gboolean has_ctx;
158 } StackFrame;
159
160 typedef struct _InvokeData InvokeData;
161
162 struct _InvokeData
163 {
164         int id;
165         int flags;
166         guint8 *p;
167         guint8 *endp;
168         /* This is the context which needs to be restored after the invoke */
169         MonoContext ctx;
170         gboolean has_ctx;
171         /*
172          * If this is set, invoke this method with the arguments given by ARGS.
173          */
174         MonoMethod *method;
175         gpointer *args;
176         guint32 suspend_count;
177         int nmethods;
178
179         InvokeData *last_invoke;
180 };
181
182 typedef struct {
183         MonoThreadUnwindState context;
184
185         /* This is computed on demand when it is requested using the wire protocol */
186         /* It is freed up when the thread is resumed */
187         int frame_count;
188         StackFrame **frames;
189         /* 
190          * Whenever the frame info is up-to-date. If not, compute_frame_info () will need to
191          * re-compute it.
192          */
193         gboolean frames_up_to_date;
194         /* 
195          * Points to data about a pending invoke which needs to be executed after the thread
196          * resumes.
197          */
198         InvokeData *pending_invoke;
199         /*
200          * Set to TRUE if this thread is suspended in suspend_current () or it is executing
201          * native code.
202          */
203         gboolean suspended;
204         /*
205          * Signals whenever the thread is in the process of suspending, i.e. it will suspend
206          * within a finite amount of time.
207          */
208         gboolean suspending;
209         /*
210          * Set to TRUE if this thread is suspended in suspend_current ().
211          */
212         gboolean really_suspended;
213         /* Used to pass the context to the breakpoint/single step handler */
214         MonoContext handler_ctx;
215         /* Whenever thread_stop () was called for this thread */
216         gboolean terminated;
217
218         /* Number of thread interruptions not yet processed */
219         gint32 interrupt_count;
220
221         /* Whenever to disable breakpoints (used during invokes) */
222         gboolean disable_breakpoints;
223
224         /*
225          * Number of times this thread has been resumed using resume_thread ().
226          */
227         guint32 resume_count;
228
229         MonoInternalThread *thread;
230
231         /*
232          * Information about the frame which transitioned to native code for running
233          * threads.
234          */
235         StackFrameInfo async_last_frame;
236
237         /*
238          * The context where the stack walk can be started for running threads.
239          */
240         MonoThreadUnwindState async_state;
241
242         /*
243      * The context used for filter clauses
244      */
245         MonoThreadUnwindState filter_state;
246
247         /*
248          * The callee address of the last mono_runtime_invoke call
249          */
250         gpointer invoke_addr;
251
252         gboolean abort_requested;
253
254         /*
255          * The current mono_runtime_invoke invocation.
256          */
257         InvokeData *invoke;
258
259         /*
260          * The context where single stepping should resume while the thread is suspended because
261          * of an EXCEPTION event.
262          */
263         MonoThreadUnwindState catch_state;
264
265         /*
266          * The context which needs to be restored after handling a single step/breakpoint
267          * event. This is the same as the ctx at step/breakpoint site, but includes changes
268          * to caller saved registers done by set_var ().
269          */
270         MonoContext restore_ctx;
271
272         /* The currently unloading appdomain */
273         MonoDomain *domain_unloading;
274 } DebuggerTlsData;
275
276 typedef struct {
277         const char *name;
278         void (*connect) (const char *address);
279         void (*close1) (void);
280         void (*close2) (void);
281         gboolean (*send) (void *buf, int len);
282         int (*recv) (void *buf, int len);
283 } DebuggerTransport;
284
285 /* 
286  * Wire Protocol definitions
287  */
288
289 #define HEADER_LENGTH 11
290
291 #define MAJOR_VERSION 2
292 #define MINOR_VERSION 38
293
294 typedef enum {
295         CMD_SET_VM = 1,
296         CMD_SET_OBJECT_REF = 9,
297         CMD_SET_STRING_REF = 10,
298         CMD_SET_THREAD = 11,
299         CMD_SET_ARRAY_REF = 13,
300         CMD_SET_EVENT_REQUEST = 15,
301         CMD_SET_STACK_FRAME = 16,
302         CMD_SET_APPDOMAIN = 20,
303         CMD_SET_ASSEMBLY = 21,
304         CMD_SET_METHOD = 22,
305         CMD_SET_TYPE = 23,
306         CMD_SET_MODULE = 24,
307         CMD_SET_FIELD = 25,
308         CMD_SET_EVENT = 64
309 } CommandSet;
310
311 typedef enum {
312         EVENT_KIND_VM_START = 0,
313         EVENT_KIND_VM_DEATH = 1,
314         EVENT_KIND_THREAD_START = 2,
315         EVENT_KIND_THREAD_DEATH = 3,
316         EVENT_KIND_APPDOMAIN_CREATE = 4,
317         EVENT_KIND_APPDOMAIN_UNLOAD = 5,
318         EVENT_KIND_METHOD_ENTRY = 6,
319         EVENT_KIND_METHOD_EXIT = 7,
320         EVENT_KIND_ASSEMBLY_LOAD = 8,
321         EVENT_KIND_ASSEMBLY_UNLOAD = 9,
322         EVENT_KIND_BREAKPOINT = 10,
323         EVENT_KIND_STEP = 11,
324         EVENT_KIND_TYPE_LOAD = 12,
325         EVENT_KIND_EXCEPTION = 13,
326         EVENT_KIND_KEEPALIVE = 14,
327         EVENT_KIND_USER_BREAK = 15,
328         EVENT_KIND_USER_LOG = 16
329 } EventKind;
330
331 typedef enum {
332         SUSPEND_POLICY_NONE = 0,
333         SUSPEND_POLICY_EVENT_THREAD = 1,
334         SUSPEND_POLICY_ALL = 2
335 } SuspendPolicy;
336
337 typedef enum {
338         ERR_NONE = 0,
339         ERR_INVALID_OBJECT = 20,
340         ERR_INVALID_FIELDID = 25,
341         ERR_INVALID_FRAMEID = 30,
342         ERR_NOT_IMPLEMENTED = 100,
343         ERR_NOT_SUSPENDED = 101,
344         ERR_INVALID_ARGUMENT = 102,
345         ERR_UNLOADED = 103,
346         ERR_NO_INVOCATION = 104,
347         ERR_ABSENT_INFORMATION = 105,
348         ERR_NO_SEQ_POINT_AT_IL_OFFSET = 106,
349         ERR_LOADER_ERROR = 200, /*XXX extend the protocol to pass this information down the pipe */
350 } ErrorCode;
351
352 typedef enum {
353         MOD_KIND_COUNT = 1,
354         MOD_KIND_THREAD_ONLY = 3,
355         MOD_KIND_LOCATION_ONLY = 7,
356         MOD_KIND_EXCEPTION_ONLY = 8,
357         MOD_KIND_STEP = 10,
358         MOD_KIND_ASSEMBLY_ONLY = 11,
359         MOD_KIND_SOURCE_FILE_ONLY = 12,
360         MOD_KIND_TYPE_NAME_ONLY = 13,
361         MOD_KIND_NONE = 14
362 } ModifierKind;
363
364 typedef enum {
365         STEP_DEPTH_INTO = 0,
366         STEP_DEPTH_OVER = 1,
367         STEP_DEPTH_OUT = 2
368 } StepDepth;
369
370 typedef enum {
371         STEP_SIZE_MIN = 0,
372         STEP_SIZE_LINE = 1
373 } StepSize;
374
375 typedef enum {
376         STEP_FILTER_NONE = 0,
377         STEP_FILTER_STATIC_CTOR = 1,
378         STEP_FILTER_DEBUGGER_HIDDEN = 2,
379         STEP_FILTER_DEBUGGER_STEP_THROUGH = 4,
380         STEP_FILTER_DEBUGGER_NON_USER_CODE = 8
381 } StepFilter;
382
383 typedef enum {
384         TOKEN_TYPE_STRING = 0,
385         TOKEN_TYPE_TYPE = 1,
386         TOKEN_TYPE_FIELD = 2,
387         TOKEN_TYPE_METHOD = 3,
388         TOKEN_TYPE_UNKNOWN = 4
389 } DebuggerTokenType;
390
391 typedef enum {
392         VALUE_TYPE_ID_NULL = 0xf0,
393         VALUE_TYPE_ID_TYPE = 0xf1,
394         VALUE_TYPE_ID_PARENT_VTYPE = 0xf2
395 } ValueTypeId;
396
397 typedef enum {
398         FRAME_FLAG_DEBUGGER_INVOKE = 1,
399         FRAME_FLAG_NATIVE_TRANSITION = 2
400 } StackFrameFlags;
401
402 typedef enum {
403         INVOKE_FLAG_DISABLE_BREAKPOINTS = 1,
404         INVOKE_FLAG_SINGLE_THREADED = 2,
405         INVOKE_FLAG_RETURN_OUT_THIS = 4,
406         INVOKE_FLAG_RETURN_OUT_ARGS = 8,
407         INVOKE_FLAG_VIRTUAL = 16
408 } InvokeFlags;
409
410 typedef enum {
411         BINDING_FLAGS_IGNORE_CASE = 0x70000000,
412 } BindingFlagsExtensions;
413
414 typedef enum {
415         CMD_VM_VERSION = 1,
416         CMD_VM_ALL_THREADS = 2,
417         CMD_VM_SUSPEND = 3,
418         CMD_VM_RESUME = 4,
419         CMD_VM_EXIT = 5,
420         CMD_VM_DISPOSE = 6,
421         CMD_VM_INVOKE_METHOD = 7,
422         CMD_VM_SET_PROTOCOL_VERSION = 8,
423         CMD_VM_ABORT_INVOKE = 9,
424         CMD_VM_SET_KEEPALIVE = 10,
425         CMD_VM_GET_TYPES_FOR_SOURCE_FILE = 11,
426         CMD_VM_GET_TYPES = 12,
427         CMD_VM_INVOKE_METHODS = 13,
428         CMD_VM_START_BUFFERING = 14,
429         CMD_VM_STOP_BUFFERING = 15
430 } CmdVM;
431
432 typedef enum {
433         CMD_THREAD_GET_FRAME_INFO = 1,
434         CMD_THREAD_GET_NAME = 2,
435         CMD_THREAD_GET_STATE = 3,
436         CMD_THREAD_GET_INFO = 4,
437         CMD_THREAD_GET_ID = 5,
438         CMD_THREAD_GET_TID = 6,
439         CMD_THREAD_SET_IP = 7
440 } CmdThread;
441
442 typedef enum {
443         CMD_EVENT_REQUEST_SET = 1,
444         CMD_EVENT_REQUEST_CLEAR = 2,
445         CMD_EVENT_REQUEST_CLEAR_ALL_BREAKPOINTS = 3
446 } CmdEvent;
447
448 typedef enum {
449         CMD_COMPOSITE = 100
450 } CmdComposite;
451
452 typedef enum {
453         CMD_APPDOMAIN_GET_ROOT_DOMAIN = 1,
454         CMD_APPDOMAIN_GET_FRIENDLY_NAME = 2,
455         CMD_APPDOMAIN_GET_ASSEMBLIES = 3,
456         CMD_APPDOMAIN_GET_ENTRY_ASSEMBLY = 4,
457         CMD_APPDOMAIN_CREATE_STRING = 5,
458         CMD_APPDOMAIN_GET_CORLIB = 6,
459         CMD_APPDOMAIN_CREATE_BOXED_VALUE = 7
460 } CmdAppDomain;
461
462 typedef enum {
463         CMD_ASSEMBLY_GET_LOCATION = 1,
464         CMD_ASSEMBLY_GET_ENTRY_POINT = 2,
465         CMD_ASSEMBLY_GET_MANIFEST_MODULE = 3,
466         CMD_ASSEMBLY_GET_OBJECT = 4,
467         CMD_ASSEMBLY_GET_TYPE = 5,
468         CMD_ASSEMBLY_GET_NAME = 6
469 } CmdAssembly;
470
471 typedef enum {
472         CMD_MODULE_GET_INFO = 1,
473 } CmdModule;
474
475 typedef enum {
476         CMD_FIELD_GET_INFO = 1,
477 } CmdField;
478
479 typedef enum {
480         CMD_METHOD_GET_NAME = 1,
481         CMD_METHOD_GET_DECLARING_TYPE = 2,
482         CMD_METHOD_GET_DEBUG_INFO = 3,
483         CMD_METHOD_GET_PARAM_INFO = 4,
484         CMD_METHOD_GET_LOCALS_INFO = 5,
485         CMD_METHOD_GET_INFO = 6,
486         CMD_METHOD_GET_BODY = 7,
487         CMD_METHOD_RESOLVE_TOKEN = 8,
488         CMD_METHOD_GET_CATTRS = 9,
489         CMD_METHOD_MAKE_GENERIC_METHOD = 10
490 } CmdMethod;
491
492 typedef enum {
493         CMD_TYPE_GET_INFO = 1,
494         CMD_TYPE_GET_METHODS = 2,
495         CMD_TYPE_GET_FIELDS = 3,
496         CMD_TYPE_GET_VALUES = 4,
497         CMD_TYPE_GET_OBJECT = 5,
498         CMD_TYPE_GET_SOURCE_FILES = 6,
499         CMD_TYPE_SET_VALUES = 7,
500         CMD_TYPE_IS_ASSIGNABLE_FROM = 8,
501         CMD_TYPE_GET_PROPERTIES = 9,
502         CMD_TYPE_GET_CATTRS = 10,
503         CMD_TYPE_GET_FIELD_CATTRS = 11,
504         CMD_TYPE_GET_PROPERTY_CATTRS = 12,
505         CMD_TYPE_GET_SOURCE_FILES_2 = 13,
506         CMD_TYPE_GET_VALUES_2 = 14,
507         CMD_TYPE_GET_METHODS_BY_NAME_FLAGS = 15,
508         CMD_TYPE_GET_INTERFACES = 16,
509         CMD_TYPE_GET_INTERFACE_MAP = 17,
510         CMD_TYPE_IS_INITIALIZED = 18,
511         CMD_TYPE_CREATE_INSTANCE = 19
512 } CmdType;
513
514 typedef enum {
515         CMD_STACK_FRAME_GET_VALUES = 1,
516         CMD_STACK_FRAME_GET_THIS = 2,
517         CMD_STACK_FRAME_SET_VALUES = 3,
518         CMD_STACK_FRAME_GET_DOMAIN = 4,
519 } CmdStackFrame;
520
521 typedef enum {
522         CMD_ARRAY_REF_GET_LENGTH = 1,
523         CMD_ARRAY_REF_GET_VALUES = 2,
524         CMD_ARRAY_REF_SET_VALUES = 3,
525 } CmdArray;
526
527 typedef enum {
528         CMD_STRING_REF_GET_VALUE = 1,
529         CMD_STRING_REF_GET_LENGTH = 2,
530         CMD_STRING_REF_GET_CHARS = 3
531 } CmdString;
532
533 typedef enum {
534         CMD_OBJECT_REF_GET_TYPE = 1,
535         CMD_OBJECT_REF_GET_VALUES = 2,
536         CMD_OBJECT_REF_IS_COLLECTED = 3,
537         CMD_OBJECT_REF_GET_ADDRESS = 4,
538         CMD_OBJECT_REF_GET_DOMAIN = 5,
539         CMD_OBJECT_REF_SET_VALUES = 6,
540         CMD_OBJECT_REF_GET_INFO = 7,
541 } CmdObject;
542
543 typedef struct {
544         ModifierKind kind;
545         union {
546                 int count; /* For kind == MOD_KIND_COUNT */
547                 MonoInternalThread *thread; /* For kind == MOD_KIND_THREAD_ONLY */
548                 MonoClass *exc_class; /* For kind == MONO_KIND_EXCEPTION_ONLY */
549                 MonoAssembly **assemblies; /* For kind == MONO_KIND_ASSEMBLY_ONLY */
550                 GHashTable *source_files; /* For kind == MONO_KIND_SOURCE_FILE_ONLY */
551                 GHashTable *type_names; /* For kind == MONO_KIND_TYPE_NAME_ONLY */
552                 StepFilter filter; /* For kind == MOD_KIND_STEP */
553         } data;
554         gboolean caught, uncaught, subclasses; /* For kind == MOD_KIND_EXCEPTION_ONLY */
555 } Modifier;
556
557 typedef struct{
558         int id;
559         int event_kind;
560         int suspend_policy;
561         int nmodifiers;
562         gpointer info;
563         Modifier modifiers [MONO_ZERO_LEN_ARRAY];
564 } EventRequest;
565
566 /*
567  * Describes a single step request.
568  */
569 typedef struct {
570         EventRequest *req;
571         MonoInternalThread *thread;
572         StepDepth depth;
573         StepSize size;
574         StepFilter filter;
575         gpointer last_sp;
576         gpointer start_sp;
577         MonoMethod *last_method;
578         int last_line;
579         /* Whenever single stepping is performed using start/stop_single_stepping () */
580         gboolean global;
581         /* The list of breakpoints used to implement step-over */
582         GSList *bps;
583         /* The number of frames at the start of a step-over */
584         int nframes;
585 } SingleStepReq;
586
587 /*
588  * Contains additional information for an event
589  */
590 typedef struct {
591         /* For EVENT_KIND_EXCEPTION */
592         MonoObject *exc;
593         MonoContext catch_ctx;
594         gboolean caught;
595         /* For EVENT_KIND_USER_LOG */
596         int level;
597         char *category, *message;
598         /* For EVENT_KIND_TYPE_LOAD */
599         MonoClass *klass;
600 } EventInfo;
601
602 /* Dummy structure used for the profiler callbacks */
603 typedef struct {
604         void* dummy;
605 } DebuggerProfiler;
606
607 typedef struct {
608         guint8 *buf, *p, *end;
609 } Buffer;
610
611 typedef struct ReplyPacket {
612         int id;
613         int error;
614         Buffer *data;
615 } ReplyPacket;
616
617 #define DEBUG(level,s) do { if (G_UNLIKELY ((level) <= log_level)) { s; fflush (log_file); } } while (0)
618
619 #ifdef HOST_WIN32
620 #define get_last_sock_error() WSAGetLastError()
621 #define MONO_EWOULDBLOCK WSAEWOULDBLOCK
622 #define MONO_EINTR WSAEINTR
623 #else
624 #define get_last_sock_error() errno
625 #define MONO_EWOULDBLOCK EWOULDBLOCK
626 #define MONO_EINTR EINTR
627 #endif
628
629 #define CHECK_PROTOCOL_VERSION(major,minor) \
630         (protocol_version_set && (major_version > (major) || (major_version == (major) && minor_version >= (minor))))
631
632 /*
633  * Globals
634  */
635
636 static AgentConfig agent_config;
637
638 /* 
639  * Whenever the agent is fully initialized.
640  * When using the onuncaught or onthrow options, only some parts of the agent are
641  * initialized on startup, and the full initialization which includes connection
642  * establishment and the startup of the agent thread is only done in response to
643  * an event.
644  */
645 static gint32 inited;
646
647 #ifndef DISABLE_SOCKET_TRANSPORT
648 static int conn_fd;
649 static int listen_fd;
650 #endif
651
652 static int packet_id = 0;
653
654 static int objref_id = 0;
655
656 static int event_request_id = 0;
657
658 static int frame_id = 0;
659
660 static GPtrArray *event_requests;
661
662 static MonoNativeTlsKey debugger_tls_id;
663
664 static gboolean vm_start_event_sent, vm_death_event_sent, disconnected;
665
666 /* Maps MonoInternalThread -> DebuggerTlsData */
667 static MonoGHashTable *thread_to_tls;
668
669 /* Maps tid -> MonoInternalThread */
670 static MonoGHashTable *tid_to_thread;
671
672 /* Maps tid -> MonoThread (not MonoInternalThread) */
673 static MonoGHashTable *tid_to_thread_obj;
674
675 static gsize debugger_thread_id;
676
677 static HANDLE debugger_thread_handle;
678
679 static int log_level;
680
681 static gboolean embedding;
682
683 static FILE *log_file;
684
685 /* Assemblies whose assembly load event has no been sent yet */
686 /* Protected by the dbg lock */
687 static GPtrArray *pending_assembly_loads;
688
689 /* Whenever the debugger thread has exited */
690 static gboolean debugger_thread_exited;
691
692 /* Cond variable used to wait for debugger_thread_exited becoming true */
693 static mono_cond_t debugger_thread_exited_cond;
694
695 /* Mutex for the cond var above */
696 static mono_mutex_t debugger_thread_exited_mutex;
697
698 static DebuggerProfiler debugger_profiler;
699
700 /* The single step request instance */
701 static SingleStepReq *ss_req;
702 static gpointer ss_invoke_addr;
703
704 #ifdef MONO_ARCH_SOFT_DEBUG_SUPPORTED
705 /* Number of single stepping operations in progress */
706 static int ss_count;
707 #endif
708
709 /* The protocol version of the client */
710 static int major_version, minor_version;
711
712 /* Whenever the variables above are set by the client */
713 static gboolean protocol_version_set;
714
715 /* A hash table containing all active domains */
716 static GHashTable *domains;
717
718 /* The number of times the runtime is suspended */
719 static gint32 suspend_count;
720
721 /* Whenever to buffer reply messages and send them together */
722 static gboolean buffer_replies;
723
724 /* Buffered reply packets */
725 static ReplyPacket reply_packets [128];
726 int nreply_packets;
727
728 #define dbg_lock() mono_mutex_lock (&debug_mutex)
729 #define dbg_unlock() mono_mutex_unlock (&debug_mutex)
730 static mono_mutex_t debug_mutex;
731
732 static void transport_init (void);
733 static void transport_connect (const char *address);
734 static gboolean transport_handshake (void);
735 static void register_transport (DebuggerTransport *trans);
736
737 static guint32 WINAPI debugger_thread (void *arg);
738
739 static void runtime_initialized (MonoProfiler *prof);
740
741 static void runtime_shutdown (MonoProfiler *prof);
742
743 static void thread_startup (MonoProfiler *prof, uintptr_t tid);
744
745 static void thread_end (MonoProfiler *prof, uintptr_t tid);
746
747 static void appdomain_load (MonoProfiler *prof, MonoDomain *domain, int result);
748
749 static void appdomain_start_unload (MonoProfiler *prof, MonoDomain *domain);
750
751 static void appdomain_unload (MonoProfiler *prof, MonoDomain *domain);
752
753 static void emit_appdomain_load (gpointer key, gpointer value, gpointer user_data);
754
755 static void emit_thread_start (gpointer key, gpointer value, gpointer user_data);
756
757 static void invalidate_each_thread (gpointer key, gpointer value, gpointer user_data);
758
759 static void assembly_load (MonoProfiler *prof, MonoAssembly *assembly, int result);
760
761 static void assembly_unload (MonoProfiler *prof, MonoAssembly *assembly);
762
763 static void emit_assembly_load (gpointer assembly, gpointer user_data);
764
765 static void emit_type_load (gpointer key, gpointer type, gpointer user_data);
766
767 static void start_runtime_invoke (MonoProfiler *prof, MonoMethod *method);
768
769 static void end_runtime_invoke (MonoProfiler *prof, MonoMethod *method);
770
771 static void jit_end (MonoProfiler *prof, MonoMethod *method, MonoJitInfo *jinfo, int result);
772
773 static void add_pending_breakpoints (MonoMethod *method, MonoJitInfo *jinfo);
774
775 static void start_single_stepping (void);
776
777 static void stop_single_stepping (void);
778
779 static void suspend_current (void);
780
781 static void clear_event_requests_for_assembly (MonoAssembly *assembly);
782
783 static void clear_types_for_assembly (MonoAssembly *assembly);
784
785 static void clear_breakpoints_for_domain (MonoDomain *domain);
786
787 static void process_profiler_event (EventKind event, gpointer arg);
788
789 /* Submodule init/cleanup */
790 static void breakpoints_init (void);
791 static void breakpoints_cleanup (void);
792
793 static void objrefs_init (void);
794 static void objrefs_cleanup (void);
795
796 static void ids_init (void);
797 static void ids_cleanup (void);
798
799 static void suspend_init (void);
800
801 static void ss_start (SingleStepReq *ss_req, MonoMethod *method, SeqPoint *sp, MonoSeqPointInfo *info, MonoContext *ctx, DebuggerTlsData *tls, gboolean step_to_catch);
802 static ErrorCode ss_create (MonoInternalThread *thread, StepSize size, StepDepth depth, EventRequest *req);
803 static void ss_destroy (SingleStepReq *req);
804
805 static void start_debugger_thread (void);
806 static void stop_debugger_thread (void);
807
808 static void finish_agent_init (gboolean on_startup);
809
810 static void process_profiler_event (EventKind event, gpointer arg);
811
812 static void invalidate_frames (DebuggerTlsData *tls);
813
814 #ifndef DISABLE_SOCKET_TRANSPORT
815 static void
816 register_socket_transport (void);
817 #endif
818
819 static inline gboolean
820 is_debugger_thread (void)
821 {
822         return GetCurrentThreadId () == debugger_thread_id;
823 }
824
825 static int
826 parse_address (char *address, char **host, int *port)
827 {
828         char *pos = strchr (address, ':');
829
830         if (pos == NULL || pos == address)
831                 return 1;
832
833         *host = g_malloc (pos - address + 1);
834         strncpy (*host, address, pos - address);
835         (*host) [pos - address] = '\0';
836
837         *port = atoi (pos + 1);
838
839         return 0;
840 }
841
842 static void
843 print_usage (void)
844 {
845         fprintf (stderr, "Usage: mono --debugger-agent=[<option>=<value>,...] ...\n");
846         fprintf (stderr, "Available options:\n");
847         fprintf (stderr, "  transport=<transport>\t\tTransport to use for connecting to the debugger (mandatory, possible values: 'dt_socket')\n");
848         fprintf (stderr, "  address=<hostname>:<port>\tAddress to connect to (mandatory)\n");
849         fprintf (stderr, "  loglevel=<n>\t\t\tLog level (defaults to 0)\n");
850         fprintf (stderr, "  logfile=<file>\t\tFile to log to (defaults to stdout)\n");
851         fprintf (stderr, "  suspend=y/n\t\t\tWhether to suspend after startup.\n");
852         fprintf (stderr, "  timeout=<n>\t\t\tTimeout for connecting in milliseconds.\n");
853         fprintf (stderr, "  server=y/n\t\t\tWhether to listen for a client connection.\n");
854         fprintf (stderr, "  keepalive=<n>\t\t\tSend keepalive events every n milliseconds.\n");
855         fprintf (stderr, "  setpgid=y/n\t\t\tWhether to call setpid(0, 0) after startup.\n");
856         fprintf (stderr, "  help\t\t\t\tPrint this help.\n");
857 }
858
859 static gboolean
860 parse_flag (const char *option, char *flag)
861 {
862         if (!strcmp (flag, "y"))
863                 return TRUE;
864         else if (!strcmp (flag, "n"))
865                 return FALSE;
866         else {
867                 fprintf (stderr, "debugger-agent: The valid values for the '%s' option are 'y' and 'n'.\n", option);
868                 exit (1);
869                 return FALSE;
870         }
871 }
872
873 void
874 mono_debugger_agent_parse_options (char *options)
875 {
876         char **args, **ptr;
877         char *host;
878         int port;
879         const char *extra;
880
881 #ifndef MONO_ARCH_SOFT_DEBUG_SUPPORTED
882         fprintf (stderr, "--debugger-agent is not supported on this platform.\n");
883         exit (1);
884 #endif
885
886         extra = g_getenv ("MONO_SDB_ENV_OPTIONS");
887         if (extra)
888                 options = g_strdup_printf ("%s,%s", options, extra);
889
890         agent_config.enabled = TRUE;
891         agent_config.suspend = TRUE;
892         agent_config.server = FALSE;
893         agent_config.defer = FALSE;
894         agent_config.address = NULL;
895
896         //agent_config.log_level = 10;
897
898         args = g_strsplit (options, ",", -1);
899         for (ptr = args; ptr && *ptr; ptr ++) {
900                 char *arg = *ptr;
901
902                 if (strncmp (arg, "transport=", 10) == 0) {
903                         agent_config.transport = g_strdup (arg + 10);
904                 } else if (strncmp (arg, "address=", 8) == 0) {
905                         agent_config.address = g_strdup (arg + 8);
906                 } else if (strncmp (arg, "loglevel=", 9) == 0) {
907                         agent_config.log_level = atoi (arg + 9);
908                 } else if (strncmp (arg, "logfile=", 8) == 0) {
909                         agent_config.log_file = g_strdup (arg + 8);
910                 } else if (strncmp (arg, "suspend=", 8) == 0) {
911                         agent_config.suspend = parse_flag ("suspend", arg + 8);
912                 } else if (strncmp (arg, "server=", 7) == 0) {
913                         agent_config.server = parse_flag ("server", arg + 7);
914                 } else if (strncmp (arg, "onuncaught=", 11) == 0) {
915                         agent_config.onuncaught = parse_flag ("onuncaught", arg + 11);
916                 } else if (strncmp (arg, "onthrow=", 8) == 0) {
917                         /* We support multiple onthrow= options */
918                         agent_config.onthrow = g_slist_append (agent_config.onthrow, g_strdup (arg + 8));
919                 } else if (strncmp (arg, "onthrow", 7) == 0) {
920                         agent_config.onthrow = g_slist_append (agent_config.onthrow, g_strdup (""));
921                 } else if (strncmp (arg, "help", 4) == 0) {
922                         print_usage ();
923                         exit (0);
924                 } else if (strncmp (arg, "timeout=", 8) == 0) {
925                         agent_config.timeout = atoi (arg + 8);
926                 } else if (strncmp (arg, "launch=", 7) == 0) {
927                         agent_config.launch = g_strdup (arg + 7);
928                 } else if (strncmp (arg, "embedding=", 10) == 0) {
929                         agent_config.embedding = atoi (arg + 10) == 1;
930                 } else if (strncmp (arg, "keepalive=", 10) == 0) {
931                         agent_config.keepalive = atoi (arg + 10);
932                 } else if (strncmp (arg, "setpgid=", 8) == 0) {
933                         agent_config.setpgid = parse_flag ("setpgid", arg + 8);
934                 } else {
935                         print_usage ();
936                         exit (1);
937                 }
938         }
939
940         if (agent_config.server && !agent_config.suspend) {
941                 /* Waiting for deferred attachment */
942                 agent_config.defer = TRUE;
943                 if (agent_config.address == NULL) {
944                         agent_config.address = g_strdup_printf ("0.0.0.0:%u", 56000 + (getpid () % 1000));
945                 }
946         }
947
948         //agent_config.log_level = 0;
949
950         if (agent_config.transport == NULL) {
951                 fprintf (stderr, "debugger-agent: The 'transport' option is mandatory.\n");
952                 exit (1);
953         }
954
955         if (agent_config.address == NULL && !agent_config.server) {
956                 fprintf (stderr, "debugger-agent: The 'address' option is mandatory.\n");
957                 exit (1);
958         }
959
960         // FIXME:
961         if (!strcmp (agent_config.transport, "dt_socket")) {
962                 if (agent_config.address && parse_address (agent_config.address, &host, &port)) {
963                         fprintf (stderr, "debugger-agent: The format of the 'address' options is '<host>:<port>'\n");
964                         exit (1);
965                 }
966         }
967 }
968
969 void
970 mono_debugger_agent_init (void)
971 {
972         mono_mutex_init_recursive (&debug_mutex);
973
974         if (!agent_config.enabled)
975                 return;
976
977         transport_init ();
978
979         /* Need to know whenever a thread has acquired the loader mutex */
980         mono_loader_lock_track_ownership (TRUE);
981
982         event_requests = g_ptr_array_new ();
983
984         mono_mutex_init (&debugger_thread_exited_mutex);
985         mono_cond_init (&debugger_thread_exited_cond, NULL);
986
987         mono_profiler_install ((MonoProfiler*)&debugger_profiler, runtime_shutdown);
988         mono_profiler_set_events (MONO_PROFILE_APPDOMAIN_EVENTS | MONO_PROFILE_THREADS | MONO_PROFILE_ASSEMBLY_EVENTS | MONO_PROFILE_JIT_COMPILATION | MONO_PROFILE_METHOD_EVENTS);
989         mono_profiler_install_runtime_initialized (runtime_initialized);
990         mono_profiler_install_appdomain (NULL, appdomain_load, appdomain_start_unload, appdomain_unload);
991         mono_profiler_install_thread (thread_startup, thread_end);
992         mono_profiler_install_assembly (NULL, assembly_load, assembly_unload, NULL);
993         mono_profiler_install_jit_end (jit_end);
994         mono_profiler_install_method_invoke (start_runtime_invoke, end_runtime_invoke);
995
996         mono_native_tls_alloc (&debugger_tls_id, NULL);
997
998         thread_to_tls = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_KEY_GC);
999         MONO_GC_REGISTER_ROOT_FIXED (thread_to_tls);
1000
1001         tid_to_thread = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
1002         MONO_GC_REGISTER_ROOT_FIXED (tid_to_thread);
1003
1004         tid_to_thread_obj = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
1005         MONO_GC_REGISTER_ROOT_FIXED (tid_to_thread_obj);
1006
1007         pending_assembly_loads = g_ptr_array_new ();
1008         domains = g_hash_table_new (mono_aligned_addr_hash, NULL);
1009
1010         log_level = agent_config.log_level;
1011
1012         embedding = agent_config.embedding;
1013         disconnected = TRUE;
1014
1015         if (agent_config.log_file) {
1016                 log_file = fopen (agent_config.log_file, "w+");
1017                 if (!log_file) {
1018                         fprintf (stderr, "Unable to create log file '%s': %s.\n", agent_config.log_file, strerror (errno));
1019                         exit (1);
1020                 }
1021         } else {
1022                 log_file = stdout;
1023         }
1024
1025         ids_init ();
1026         objrefs_init ();
1027         breakpoints_init ();
1028         suspend_init ();
1029
1030         mini_get_debug_options ()->gen_seq_points = TRUE;
1031         /* 
1032          * This is needed because currently we don't handle liveness info.
1033          */
1034         mini_get_debug_options ()->mdb_optimizations = TRUE;
1035
1036 #ifndef MONO_ARCH_HAVE_CONTEXT_SET_INT_REG
1037         /* This is needed because we can't set local variables in registers yet */
1038         mono_disable_optimizations (MONO_OPT_LINEARS);
1039 #endif
1040
1041         /*
1042          * The stack walk done from thread_interrupt () needs to be signal safe, but it
1043          * isn't, since it can call into mono_aot_find_jit_info () which is not signal
1044          * safe (#3411). So load AOT info eagerly when the debugger is running as a
1045          * workaround.
1046          */
1047         mini_get_debug_options ()->load_aot_jit_info_eagerly = TRUE;
1048
1049 #ifdef HAVE_SETPGID
1050         if (agent_config.setpgid)
1051                 setpgid (0, 0);
1052 #endif
1053
1054         if (!agent_config.onuncaught && !agent_config.onthrow)
1055                 finish_agent_init (TRUE);
1056 }
1057
1058 /*
1059  * finish_agent_init:
1060  *
1061  *   Finish the initialization of the agent. This involves connecting the transport
1062  * and starting the agent thread. This is either done at startup, or
1063  * in response to some event like an unhandled exception.
1064  */
1065 static void
1066 finish_agent_init (gboolean on_startup)
1067 {
1068         int res;
1069
1070         if (InterlockedCompareExchange (&inited, 1, 0) == 1)
1071                 return;
1072
1073         if (agent_config.launch) {
1074                 char *argv [16];
1075
1076                 // FIXME: Generated address
1077                 // FIXME: Races with transport_connect ()
1078
1079                 argv [0] = agent_config.launch;
1080                 argv [1] = agent_config.transport;
1081                 argv [2] = agent_config.address;
1082                 argv [3] = NULL;
1083
1084                 res = g_spawn_async_with_pipes (NULL, argv, NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
1085                 if (!res) {
1086                         fprintf (stderr, "Failed to execute '%s'.\n", agent_config.launch);
1087                         exit (1);
1088                 }
1089         }
1090
1091         transport_connect (agent_config.address);
1092
1093         if (!on_startup) {
1094                 /* Do some which is usually done after sending the VMStart () event */
1095                 vm_start_event_sent = TRUE;
1096                 start_debugger_thread ();
1097         }
1098 }
1099
1100 static void
1101 mono_debugger_agent_cleanup (void)
1102 {
1103         if (!inited)
1104                 return;
1105
1106         stop_debugger_thread ();
1107
1108         breakpoints_cleanup ();
1109         objrefs_cleanup ();
1110         ids_cleanup ();
1111         
1112         mono_mutex_destroy (&debugger_thread_exited_mutex);
1113         mono_cond_destroy (&debugger_thread_exited_cond);
1114 }
1115
1116 /*
1117  * SOCKET TRANSPORT
1118  */
1119
1120 #ifndef DISABLE_SOCKET_TRANSPORT
1121
1122 /*
1123  * recv_length:
1124  *
1125  * recv() + handle incomplete reads and EINTR
1126  */
1127 static int
1128 socket_transport_recv (void *buf, int len)
1129 {
1130         int res;
1131         int total = 0;
1132         int fd = conn_fd;
1133         int flags = 0;
1134         static gint32 last_keepalive;
1135         gint32 msecs;
1136
1137         do {
1138         again:
1139                 res = recv (fd, (char *) buf + total, len - total, flags);
1140                 if (res > 0)
1141                         total += res;
1142                 if (agent_config.keepalive) {
1143                         gboolean need_keepalive = FALSE;
1144                         if (res == -1 && get_last_sock_error () == MONO_EWOULDBLOCK) {
1145                                 need_keepalive = TRUE;
1146                         } else if (res == -1) {
1147                                 /* This could happen if recv () is interrupted repeatedly */
1148                                 msecs = mono_msec_ticks ();
1149                                 if (msecs - last_keepalive >= agent_config.keepalive) {
1150                                         need_keepalive = TRUE;
1151                                         last_keepalive = msecs;
1152                                 }
1153                         }
1154                         if (need_keepalive) {
1155                                 process_profiler_event (EVENT_KIND_KEEPALIVE, NULL);
1156                                 goto again;
1157                         }
1158                 }
1159         } while ((res > 0 && total < len) || (res == -1 && get_last_sock_error () == MONO_EINTR));
1160         return total;
1161 }
1162
1163 #ifndef TARGET_PS3
1164 #define HAVE_GETADDRINFO 1
1165 #endif
1166  
1167 static void
1168 set_keepalive (void)
1169 {
1170         struct timeval tv;
1171         int result;
1172
1173         if (!agent_config.keepalive || !conn_fd)
1174                 return;
1175
1176         tv.tv_sec = agent_config.keepalive / 1000;
1177         tv.tv_usec = (agent_config.keepalive % 1000) * 1000;
1178
1179         result = setsockopt (conn_fd, SOL_SOCKET, SO_RCVTIMEO, (char *) &tv, sizeof(struct timeval));
1180         g_assert (result >= 0);
1181 }
1182
1183 static int
1184 socket_transport_accept (int socket_fd)
1185 {
1186         conn_fd = accept (socket_fd, NULL, NULL);
1187         if (conn_fd == -1) {
1188                 fprintf (stderr, "debugger-agent: Unable to listen on %d\n", socket_fd);
1189         } else {
1190                 DEBUG (1, fprintf (log_file, "Accepted connection from client, connection fd=%d.\n", conn_fd));
1191         }
1192         
1193         return conn_fd;
1194 }
1195
1196 static gboolean
1197 socket_transport_send (void *data, int len)
1198 {
1199         int res;
1200
1201         do {
1202                 res = send (conn_fd, data, len, 0);
1203         } while (res == -1 && get_last_sock_error () == MONO_EINTR);
1204         if (res != len)
1205                 return FALSE;
1206         else
1207                 return TRUE;
1208 }
1209
1210 /*
1211  * socket_transport_connect:
1212  *
1213  *   Connect/Listen on HOST:PORT. If HOST is NULL, generate an address and listen on it.
1214  */
1215 static void
1216 socket_transport_connect (const char *address)
1217 {
1218 #ifdef HAVE_GETADDRINFO
1219         struct addrinfo hints;
1220         struct addrinfo *result, *rp;
1221 #else
1222         struct hostent *result;
1223 #endif
1224         int sfd = -1, s, res;
1225         char port_string [128];
1226         char *host;
1227         int port;
1228
1229         if (agent_config.address) {
1230                 res = parse_address (agent_config.address, &host, &port);
1231                 g_assert (res == 0);
1232         } else {
1233                 host = NULL;
1234                 port = 0;
1235         }
1236
1237         conn_fd = -1;
1238         listen_fd = -1;
1239
1240         if (host) {
1241                 sprintf (port_string, "%d", port);
1242
1243                 mono_network_init ();
1244
1245                 /* Obtain address(es) matching host/port */
1246 #ifdef HAVE_GETADDRINFO
1247                 memset (&hints, 0, sizeof (struct addrinfo));
1248                 hints.ai_family = AF_UNSPEC;    /* Allow IPv4 or IPv6 */
1249                 hints.ai_socktype = SOCK_STREAM; /* Datagram socket */
1250                 hints.ai_flags = 0;
1251                 hints.ai_protocol = 0;          /* Any protocol */
1252
1253                 s = getaddrinfo (host, port_string, &hints, &result);
1254                 if (s != 0) {
1255                         fprintf (stderr, "debugger-agent: Unable to resolve %s:%d: %s\n", host, port, gai_strerror (s));
1256                         exit (1);
1257                 }
1258 #else
1259                 /* The PS3 doesn't even have _r or hstrerror () */
1260                 result = gethostbyname (host);
1261                 if (!result) {
1262                         fprintf (stderr, "debugger-agent: Unable to resolve %s:%d: %d\n", host, port, h_errno);
1263                 }
1264 #endif
1265         }
1266
1267         if (agent_config.server) {
1268 #ifdef HAVE_GETADDRINFO
1269                 /* Wait for a connection */
1270                 if (!host) {
1271                         struct sockaddr_in addr;
1272                         socklen_t addrlen;
1273
1274                         /* No address, generate one */
1275                         sfd = socket (AF_INET, SOCK_STREAM, 0);
1276                         g_assert (sfd);
1277
1278                         /* This will bind the socket to a random port */
1279                         res = listen (sfd, 16);
1280                         if (res == -1) {
1281                                 fprintf (stderr, "debugger-agent: Unable to setup listening socket: %s\n", strerror (get_last_sock_error ()));
1282                                 exit (1);
1283                         }
1284                         listen_fd = sfd;
1285
1286                         addrlen = sizeof (addr);
1287                         memset (&addr, 0, sizeof (addr));
1288                         res = getsockname (sfd, (struct sockaddr*)&addr, &addrlen);
1289                         g_assert (res == 0);
1290
1291                         host = (char*)"127.0.0.1";
1292                         port = ntohs (addr.sin_port);
1293
1294                         /* Emit the address to stdout */
1295                         /* FIXME: Should print another interface, not localhost */
1296                         printf ("%s:%d\n", host, port);
1297                 } else {
1298                         /* Listen on the provided address */
1299                         for (rp = result; rp != NULL; rp = rp->ai_next) {
1300                                 int n = 1;
1301
1302                                 sfd = socket (rp->ai_family, rp->ai_socktype,
1303                                                           rp->ai_protocol);
1304                                 if (sfd == -1)
1305                                         continue;
1306
1307                                 if (setsockopt (sfd, SOL_SOCKET, SO_REUSEADDR, &n, sizeof(n)) == -1)
1308                                         continue;
1309
1310                                 res = bind (sfd, rp->ai_addr, rp->ai_addrlen);
1311                                 if (res == -1)
1312                                         continue;
1313
1314                                 res = listen (sfd, 16);
1315                                 if (res == -1)
1316                                         continue;
1317                                 listen_fd = sfd;
1318                                 break;
1319                         }
1320
1321 #ifndef HOST_WIN32
1322                         /*
1323                          * this function is not present on win2000 which we still support, and the
1324                          * workaround described here:
1325                          * http://msdn.microsoft.com/en-us/library/ms737931(VS.85).aspx
1326                          * only works with MSVC.
1327                          */
1328 #ifdef HAVE_GETADDRINFO
1329                         freeaddrinfo (result);
1330 #endif
1331 #endif
1332                 }
1333
1334                 if (agent_config.defer)
1335                         return;
1336
1337                 DEBUG (1, fprintf (log_file, "Listening on %s:%d (timeout=%d ms)...\n", host, port, agent_config.timeout));
1338
1339                 if (agent_config.timeout) {
1340                         fd_set readfds;
1341                         struct timeval tv;
1342
1343                         tv.tv_sec = 0;
1344                         tv.tv_usec = agent_config.timeout * 1000;
1345                         FD_ZERO (&readfds);
1346                         FD_SET (sfd, &readfds);
1347                         res = select (sfd + 1, &readfds, NULL, NULL, &tv);
1348                         if (res == 0) {
1349                                 fprintf (stderr, "debugger-agent: Timed out waiting to connect.\n");
1350                                 exit (1);
1351                         }
1352                 }
1353
1354                 conn_fd = socket_transport_accept (sfd);
1355                 if (conn_fd == -1)
1356                         exit (1);
1357
1358                 DEBUG (1, fprintf (log_file, "Accepted connection from client, socket fd=%d.\n", conn_fd));
1359 #else
1360                 NOT_IMPLEMENTED;
1361 #endif /* HAVE_GETADDRINFO */
1362         } else {
1363                 /* Connect to the specified address */
1364 #ifdef HAVE_GETADDRINFO
1365                 /* FIXME: Respect the timeout */
1366                 for (rp = result; rp != NULL; rp = rp->ai_next) {
1367                         sfd = socket (rp->ai_family, rp->ai_socktype,
1368                                                   rp->ai_protocol);
1369                         if (sfd == -1)
1370                                 continue;
1371
1372                         if (connect (sfd, rp->ai_addr, rp->ai_addrlen) != -1)
1373                                 break;       /* Success */
1374                         
1375                         close (sfd);
1376                 }
1377
1378                 if (rp == 0) {
1379                         fprintf (stderr, "debugger-agent: Unable to connect to %s:%d\n", host, port);
1380                         exit (1);
1381                 }
1382 #else
1383                         sfd = socket (result->h_addrtype, SOCK_STREAM, 0);
1384                         if (sfd == -1)
1385                                 g_assert_not_reached ();
1386                         res = connect (sfd, (void*)result->h_addr_list [0], result->h_length);
1387                         if (res == -1)
1388                                 g_assert_not_reached ();
1389 #endif
1390
1391                 conn_fd = sfd;
1392
1393 #ifndef HOST_WIN32
1394                 /* See the comment above */
1395 #ifdef HAVE_GETADDRINFO
1396                 freeaddrinfo (result);
1397 #endif
1398 #endif
1399         }
1400         
1401         if (!transport_handshake ())
1402                 exit (1);
1403 }
1404
1405 static void
1406 socket_transport_close1 (void)
1407 {
1408         /* This will interrupt the agent thread */
1409         /* Close the read part only so it can still send back replies */
1410         /* Also shut down the connection listener so that we can exit normally */
1411 #ifdef HOST_WIN32
1412         /* SD_RECEIVE doesn't break the recv in the debugger thread */
1413         shutdown (conn_fd, SD_BOTH);
1414         shutdown (listen_fd, SD_BOTH);
1415         closesocket (listen_fd);
1416 #else
1417         shutdown (conn_fd, SHUT_RD);
1418         shutdown (listen_fd, SHUT_RDWR);
1419         close (listen_fd);
1420 #endif
1421 }
1422
1423 static void
1424 socket_transport_close2 (void)
1425 {
1426 #ifdef HOST_WIN32
1427         shutdown (conn_fd, SD_BOTH);
1428 #else
1429         shutdown (conn_fd, SHUT_RDWR);
1430 #endif
1431 }
1432
1433 static void
1434 register_socket_transport (void)
1435 {
1436         DebuggerTransport trans;
1437
1438         trans.name = "dt_socket";
1439         trans.connect = socket_transport_connect;
1440         trans.close1 = socket_transport_close1;
1441         trans.close2 = socket_transport_close2;
1442         trans.send = socket_transport_send;
1443         trans.recv = socket_transport_recv;
1444
1445         register_transport (&trans);
1446 }
1447
1448 /*
1449  * socket_fd_transport_connect:
1450  *
1451  */
1452 static void
1453 socket_fd_transport_connect (const char *address)
1454 {
1455         int res;
1456
1457         res = sscanf (address, "%d", &conn_fd);
1458         if (res != 1) {
1459                 fprintf (stderr, "debugger-agent: socket-fd transport address is invalid: '%s'\n", address);
1460                 exit (1);
1461         }
1462
1463         if (!transport_handshake ())
1464                 exit (1);
1465 }
1466
1467 static void
1468 register_socket_fd_transport (void)
1469 {
1470         DebuggerTransport trans;
1471
1472         /* This is the same as the 'dt_socket' transport, but receives an already connected socket fd */
1473         trans.name = "socket-fd";
1474         trans.connect = socket_fd_transport_connect;
1475         trans.close1 = socket_transport_close1;
1476         trans.close2 = socket_transport_close2;
1477         trans.send = socket_transport_send;
1478         trans.recv = socket_transport_recv;
1479
1480         register_transport (&trans);
1481 }
1482
1483 #endif /* DISABLE_SOCKET_TRANSPORT */
1484
1485 /*
1486  * TRANSPORT CODE
1487  */
1488
1489 #define MAX_TRANSPORTS 16
1490
1491 static DebuggerTransport *transport;
1492
1493 static DebuggerTransport transports [MAX_TRANSPORTS];
1494 static int ntransports;
1495
1496 void
1497 mono_debugger_agent_register_transport (DebuggerTransport *trans);
1498
1499 void
1500 mono_debugger_agent_register_transport (DebuggerTransport *trans)
1501 {
1502         register_transport (trans);
1503 }
1504
1505 static void
1506 register_transport (DebuggerTransport *trans)
1507 {
1508         g_assert (ntransports < MAX_TRANSPORTS);
1509
1510         memcpy (&transports [ntransports], trans, sizeof (DebuggerTransport));
1511         ntransports ++;
1512 }
1513
1514 static void
1515 transport_init (void)
1516 {
1517         int i;
1518
1519 #ifndef DISABLE_SOCKET_TRANSPORT
1520         register_socket_transport ();
1521         register_socket_fd_transport ();
1522 #endif
1523
1524         for (i = 0; i < ntransports; ++i) {
1525                 if (!strcmp (agent_config.transport, transports [i].name))
1526                         break;
1527         }
1528         if (i == ntransports) {
1529                 fprintf (stderr, "debugger-agent: The supported values for the 'transport' option are: ");
1530                 for (i = 0; i < ntransports; ++i)
1531                         fprintf (stderr, "%s'%s'", i > 0 ? ", " : "", transports [i].name);
1532                 fprintf (stderr, "\n");
1533                 exit (1);
1534         }
1535         transport = &transports [i];
1536 }
1537
1538 void
1539 transport_connect (const char *address)
1540 {
1541         transport->connect (address);
1542 }
1543
1544 static void
1545 transport_close1 (void)
1546 {
1547         transport->close1 ();
1548 }
1549
1550 static void
1551 transport_close2 (void)
1552 {
1553         transport->close2 ();
1554 }
1555
1556 static int
1557 transport_send (void *buf, int len)
1558 {
1559         return transport->send (buf, len);
1560 }
1561
1562 static int
1563 transport_recv (void *buf, int len)
1564 {
1565         return transport->recv (buf, len);
1566 }
1567
1568 gboolean
1569 mono_debugger_agent_transport_handshake (void)
1570 {
1571         return transport_handshake ();
1572 }
1573
1574 static gboolean
1575 transport_handshake (void)
1576 {
1577         char handshake_msg [128];
1578         guint8 buf [128];
1579         int res;
1580         
1581         disconnected = TRUE;
1582         
1583         /* Write handshake message */
1584         sprintf (handshake_msg, "DWP-Handshake");
1585         do {
1586                 res = transport_send (handshake_msg, strlen (handshake_msg));
1587         } while (res == -1 && get_last_sock_error () == MONO_EINTR);
1588         g_assert (res != -1);
1589
1590         /* Read answer */
1591         res = transport_recv (buf, strlen (handshake_msg));
1592         if ((res != strlen (handshake_msg)) || (memcmp (buf, handshake_msg, strlen (handshake_msg)) != 0)) {
1593                 fprintf (stderr, "debugger-agent: DWP handshake failed.\n");
1594                 return FALSE;
1595         }
1596
1597         /*
1598          * To support older clients, the client sends its protocol version after connecting
1599          * using a command. Until that is received, default to our protocol version.
1600          */
1601         major_version = MAJOR_VERSION;
1602         minor_version = MINOR_VERSION;
1603         protocol_version_set = FALSE;
1604
1605 #ifndef DISABLE_SOCKET_TRANSPORT
1606         // FIXME: Move this somewhere else
1607         /* 
1608          * Set TCP_NODELAY on the socket so the client receives events/command
1609          * results immediately.
1610          */
1611         if (conn_fd) {
1612                 int flag = 1;
1613                 int result = setsockopt (conn_fd,
1614                                  IPPROTO_TCP,
1615                                  TCP_NODELAY,
1616                                  (char *) &flag,
1617                                  sizeof(int));
1618                 g_assert (result >= 0);
1619         }
1620
1621         set_keepalive ();
1622 #endif
1623         
1624         disconnected = FALSE;
1625         return TRUE;
1626 }
1627
1628 static void
1629 stop_debugger_thread (void)
1630 {
1631         if (!inited)
1632                 return;
1633
1634         transport_close1 ();
1635
1636         /* 
1637          * Wait for the thread to exit.
1638          *
1639          * If we continue with the shutdown without waiting for it, then the client might
1640          * not receive an answer to its last command like a resume.
1641          * The WaitForSingleObject infrastructure doesn't seem to work during shutdown, so
1642          * use pthreads.
1643          */
1644         //WaitForSingleObject (debugger_thread_handle, INFINITE);
1645         if (GetCurrentThreadId () != debugger_thread_id) {
1646                 do {
1647                         mono_mutex_lock (&debugger_thread_exited_mutex);
1648                         if (!debugger_thread_exited) {
1649 #ifdef HOST_WIN32
1650                                 if (WAIT_TIMEOUT == WaitForSingleObject(debugger_thread_exited_cond, 0)) {
1651                                         mono_mutex_unlock (&debugger_thread_exited_mutex);
1652                                         Sleep(1);
1653                                         mono_mutex_lock (&debugger_thread_exited_mutex);
1654                                 }
1655 #else
1656                                 mono_cond_wait (&debugger_thread_exited_cond, &debugger_thread_exited_mutex);
1657 #endif
1658                         }
1659                         mono_mutex_unlock (&debugger_thread_exited_mutex);
1660                 } while (!debugger_thread_exited);
1661         }
1662
1663         transport_close2 ();
1664 }
1665
1666 static void
1667 start_debugger_thread (void)
1668 {
1669         debugger_thread_handle = mono_threads_create_thread (debugger_thread, NULL, 0, 0, NULL);
1670         g_assert (debugger_thread_handle);
1671 }
1672
1673 /*
1674  * Functions to decode protocol data
1675  */
1676
1677 static inline int
1678 decode_byte (guint8 *buf, guint8 **endbuf, guint8 *limit)
1679 {
1680         *endbuf = buf + 1;
1681         g_assert (*endbuf <= limit);
1682         return buf [0];
1683 }
1684
1685 static inline int
1686 decode_int (guint8 *buf, guint8 **endbuf, guint8 *limit)
1687 {
1688         *endbuf = buf + 4;
1689         g_assert (*endbuf <= limit);
1690
1691         return (((int)buf [0]) << 24) | (((int)buf [1]) << 16) | (((int)buf [2]) << 8) | (((int)buf [3]) << 0);
1692 }
1693
1694 static inline gint64
1695 decode_long (guint8 *buf, guint8 **endbuf, guint8 *limit)
1696 {
1697         guint32 high = decode_int (buf, &buf, limit);
1698         guint32 low = decode_int (buf, &buf, limit);
1699
1700         *endbuf = buf;
1701
1702         return ((((guint64)high) << 32) | ((guint64)low));
1703 }
1704
1705 static inline int
1706 decode_id (guint8 *buf, guint8 **endbuf, guint8 *limit)
1707 {
1708         return decode_int (buf, endbuf, limit);
1709 }
1710
1711 static inline char*
1712 decode_string (guint8 *buf, guint8 **endbuf, guint8 *limit)
1713 {
1714         int len = decode_int (buf, &buf, limit);
1715         char *s;
1716
1717         if (len < 0) {
1718                 *endbuf = buf;
1719                 return NULL;
1720         }
1721
1722         s = g_malloc (len + 1);
1723         g_assert (s);
1724
1725         memcpy (s, buf, len);
1726         s [len] = '\0';
1727         buf += len;
1728         *endbuf = buf;
1729
1730         return s;
1731 }
1732
1733 /*
1734  * Functions to encode protocol data
1735  */
1736
1737 static inline void
1738 buffer_init (Buffer *buf, int size)
1739 {
1740         buf->buf = g_malloc (size);
1741         buf->p = buf->buf;
1742         buf->end = buf->buf + size;
1743 }
1744
1745 static inline int
1746 buffer_len (Buffer *buf)
1747 {
1748         return buf->p - buf->buf;
1749 }
1750
1751 static inline void
1752 buffer_make_room (Buffer *buf, int size)
1753 {
1754         if (buf->end - buf->p < size) {
1755                 int new_size = buf->end - buf->buf + size + 32;
1756                 guint8 *p = g_realloc (buf->buf, new_size);
1757                 size = buf->p - buf->buf;
1758                 buf->buf = p;
1759                 buf->p = p + size;
1760                 buf->end = buf->buf + new_size;
1761         }
1762 }
1763
1764 static inline void
1765 buffer_add_byte (Buffer *buf, guint8 val)
1766 {
1767         buffer_make_room (buf, 1);
1768         buf->p [0] = val;
1769         buf->p++;
1770 }
1771
1772 static inline void
1773 buffer_add_short (Buffer *buf, guint32 val)
1774 {
1775         buffer_make_room (buf, 2);
1776         buf->p [0] = (val >> 8) & 0xff;
1777         buf->p [1] = (val >> 0) & 0xff;
1778         buf->p += 2;
1779 }
1780
1781 static inline void
1782 buffer_add_int (Buffer *buf, guint32 val)
1783 {
1784         buffer_make_room (buf, 4);
1785         buf->p [0] = (val >> 24) & 0xff;
1786         buf->p [1] = (val >> 16) & 0xff;
1787         buf->p [2] = (val >> 8) & 0xff;
1788         buf->p [3] = (val >> 0) & 0xff;
1789         buf->p += 4;
1790 }
1791
1792 static inline void
1793 buffer_add_long (Buffer *buf, guint64 l)
1794 {
1795         buffer_add_int (buf, (l >> 32) & 0xffffffff);
1796         buffer_add_int (buf, (l >> 0) & 0xffffffff);
1797 }
1798
1799 static inline void
1800 buffer_add_id (Buffer *buf, int id)
1801 {
1802         buffer_add_int (buf, (guint64)id);
1803 }
1804
1805 static inline void
1806 buffer_add_data (Buffer *buf, guint8 *data, int len)
1807 {
1808         buffer_make_room (buf, len);
1809         memcpy (buf->p, data, len);
1810         buf->p += len;
1811 }
1812
1813 static inline void
1814 buffer_add_string (Buffer *buf, const char *str)
1815 {
1816         int len;
1817
1818         if (str == NULL) {
1819                 buffer_add_int (buf, 0);
1820         } else {
1821                 len = strlen (str);
1822                 buffer_add_int (buf, len);
1823                 buffer_add_data (buf, (guint8*)str, len);
1824         }
1825 }
1826
1827 static inline void
1828 buffer_add_buffer (Buffer *buf, Buffer *data)
1829 {
1830         buffer_add_data (buf, data->buf, buffer_len (data));
1831 }
1832
1833 static inline void
1834 buffer_free (Buffer *buf)
1835 {
1836         g_free (buf->buf);
1837 }
1838
1839 static gboolean
1840 send_packet (int command_set, int command, Buffer *data)
1841 {
1842         Buffer buf;
1843         int len, id;
1844         gboolean res;
1845
1846         id = InterlockedIncrement (&packet_id);
1847
1848         len = data->p - data->buf + 11;
1849         buffer_init (&buf, len);
1850         buffer_add_int (&buf, len);
1851         buffer_add_int (&buf, id);
1852         buffer_add_byte (&buf, 0); /* flags */
1853         buffer_add_byte (&buf, command_set);
1854         buffer_add_byte (&buf, command);
1855         memcpy (buf.buf + 11, data->buf, data->p - data->buf);
1856
1857         res = transport_send (buf.buf, len);
1858
1859         buffer_free (&buf);
1860
1861         return res;
1862 }
1863
1864 static gboolean
1865 send_reply_packets (int npackets, ReplyPacket *packets)
1866 {
1867         Buffer buf;
1868         int i, len;
1869         gboolean res;
1870
1871         len = 0;
1872         for (i = 0; i < npackets; ++i)
1873                 len += buffer_len (packets [i].data) + 11;
1874         buffer_init (&buf, len);
1875         for (i = 0; i < npackets; ++i) {
1876                 buffer_add_int (&buf, buffer_len (packets [i].data) + 11);
1877                 buffer_add_int (&buf, packets [i].id);
1878                 buffer_add_byte (&buf, 0x80); /* flags */
1879                 buffer_add_byte (&buf, (packets [i].error >> 8) & 0xff);
1880                 buffer_add_byte (&buf, packets [i].error);
1881                 buffer_add_buffer (&buf, packets [i].data);
1882         }
1883         res = transport_send (buf.buf, len);
1884
1885         buffer_free (&buf);
1886
1887         return res;
1888 }
1889
1890 static gboolean
1891 send_reply_packet (int id, int error, Buffer *data)
1892 {
1893         ReplyPacket packet;
1894
1895         memset (&packet, 0, sizeof (ReplyPacket));
1896         packet.id = id;
1897         packet.error = error;
1898         packet.data = data;
1899
1900         return send_reply_packets (1, &packet);
1901 }
1902
1903 static void
1904 send_buffered_reply_packets (void)
1905 {
1906         int i;
1907
1908         send_reply_packets (nreply_packets, reply_packets);
1909         for (i = 0; i < nreply_packets; ++i)
1910                 buffer_free (reply_packets [i].data);
1911         DEBUG (1, fprintf (log_file, "[dbg] Sent %d buffered reply packets [at=%lx].\n", nreply_packets, (long)mono_100ns_ticks () / 10000));
1912         nreply_packets = 0;
1913 }
1914
1915 static void
1916 buffer_reply_packet (int id, int error, Buffer *data)
1917 {
1918         ReplyPacket *p;
1919
1920         if (nreply_packets == 128)
1921                 send_buffered_reply_packets ();
1922
1923         p = &reply_packets [nreply_packets];
1924         p->id = id;
1925         p->error = error;
1926         p->data = g_new0 (Buffer, 1);
1927         buffer_init (p->data, buffer_len (data));
1928         buffer_add_buffer (p->data, data);
1929         nreply_packets ++;
1930 }
1931
1932 /*
1933  * OBJECT IDS
1934  */
1935
1936 /*
1937  * Represents an object accessible by the debugger client.
1938  */
1939 typedef struct {
1940         /* Unique id used in the wire protocol to refer to objects */
1941         int id;
1942         /*
1943          * A weakref gc handle pointing to the object. The gc handle is used to 
1944          * detect if the object was garbage collected.
1945          */
1946         guint32 handle;
1947 } ObjRef;
1948
1949 /* Maps objid -> ObjRef */
1950 static GHashTable *objrefs;
1951 static GHashTable *obj_to_objref;
1952 /* Protected by the dbg lock */
1953 static MonoGHashTable *suspended_objs;
1954
1955 static void
1956 free_objref (gpointer value)
1957 {
1958         ObjRef *o = value;
1959
1960         mono_gchandle_free (o->handle);
1961
1962         g_free (o);
1963 }
1964
1965 static void
1966 objrefs_init (void)
1967 {
1968         objrefs = g_hash_table_new_full (NULL, NULL, NULL, free_objref);
1969         obj_to_objref = g_hash_table_new (NULL, NULL);
1970         suspended_objs = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_KEY_GC);
1971         MONO_GC_REGISTER_ROOT_FIXED (suspended_objs);
1972 }
1973
1974 static void
1975 objrefs_cleanup (void)
1976 {
1977         g_hash_table_destroy (objrefs);
1978         objrefs = NULL;
1979 }
1980
1981 /*
1982  * Return an ObjRef for OBJ.
1983  */
1984 static ObjRef*
1985 get_objref (MonoObject *obj)
1986 {
1987         ObjRef *ref;
1988         GSList *reflist = NULL, *l;
1989         int hash = 0;
1990
1991         if (obj == NULL)
1992                 return 0;
1993
1994         if (suspend_count) {
1995                 /*
1996                  * Have to keep object refs created during suspensions alive for the duration of the suspension, so GCs during invokes don't collect them.
1997                  */
1998                 dbg_lock ();
1999                 mono_g_hash_table_insert (suspended_objs, obj, NULL);
2000                 dbg_unlock ();
2001         }
2002
2003         mono_loader_lock ();
2004         
2005         /* FIXME: The tables can grow indefinitely */
2006
2007         if (mono_gc_is_moving ()) {
2008                 /*
2009                  * Objects can move, so use a hash table mapping hash codes to lists of
2010                  * ObjRef structures.
2011                  */
2012                 hash = mono_object_hash (obj);
2013
2014                 reflist = g_hash_table_lookup (obj_to_objref, GINT_TO_POINTER (hash));
2015                 for (l = reflist; l; l = l->next) {
2016                         ref = l->data;
2017                         if (ref && mono_gchandle_get_target (ref->handle) == obj) {
2018                                 mono_loader_unlock ();
2019                                 return ref;
2020                         }
2021                 }
2022         } else {
2023                 /* Use a hash table with masked pointers to internalize object references */
2024                 ref = g_hash_table_lookup (obj_to_objref, GINT_TO_POINTER (~((gsize)obj)));
2025                 /* ref might refer to a different object with the same addr which was GCd */
2026                 if (ref && mono_gchandle_get_target (ref->handle) == obj) {
2027                         mono_loader_unlock ();
2028                         return ref;
2029                 }
2030         }
2031
2032         ref = g_new0 (ObjRef, 1);
2033         ref->id = InterlockedIncrement (&objref_id);
2034         ref->handle = mono_gchandle_new_weakref (obj, FALSE);
2035
2036         g_hash_table_insert (objrefs, GINT_TO_POINTER (ref->id), ref);
2037
2038         if (mono_gc_is_moving ()) {
2039                 reflist = g_slist_append (reflist, ref);
2040                 g_hash_table_insert (obj_to_objref, GINT_TO_POINTER (hash), reflist);
2041         } else {
2042                 g_hash_table_insert (obj_to_objref, GINT_TO_POINTER (~((gsize)obj)), ref);
2043         }
2044
2045         mono_loader_unlock ();
2046
2047         return ref;
2048 }
2049
2050 static gboolean
2051 true_pred (gpointer key, gpointer value, gpointer user_data)
2052 {
2053         return TRUE;
2054 }
2055
2056 static void
2057 clear_suspended_objs (void)
2058 {
2059         dbg_lock ();
2060         mono_g_hash_table_foreach_remove (suspended_objs, true_pred, NULL);
2061         dbg_unlock ();
2062 }
2063
2064 static inline int
2065 get_objid (MonoObject *obj)
2066 {
2067         return get_objref (obj)->id;
2068 }
2069
2070 /*
2071  * Set OBJ to the object identified by OBJID.
2072  * Returns 0 or an error code if OBJID is invalid or the object has been garbage
2073  * collected.
2074  */
2075 static ErrorCode
2076 get_object_allow_null (int objid, MonoObject **obj)
2077 {
2078         ObjRef *ref;
2079
2080         if (objid == 0) {
2081                 *obj = NULL;
2082                 return 0;
2083         }
2084
2085         if (!objrefs)
2086                 return ERR_INVALID_OBJECT;
2087
2088         mono_loader_lock ();
2089
2090         ref = g_hash_table_lookup (objrefs, GINT_TO_POINTER (objid));
2091
2092         if (ref) {
2093                 *obj = mono_gchandle_get_target (ref->handle);
2094                 mono_loader_unlock ();
2095                 if (!(*obj))
2096                         return ERR_INVALID_OBJECT;
2097                 return 0;
2098         } else {
2099                 mono_loader_unlock ();
2100                 return ERR_INVALID_OBJECT;
2101         }
2102 }
2103
2104 static ErrorCode
2105 get_object (int objid, MonoObject **obj)
2106 {
2107         int err = get_object_allow_null (objid, obj);
2108
2109         if (err)
2110                 return err;
2111         if (!(*obj))
2112                 return ERR_INVALID_OBJECT;
2113         return 0;
2114 }
2115
2116 static inline int
2117 decode_objid (guint8 *buf, guint8 **endbuf, guint8 *limit)
2118 {
2119         return decode_id (buf, endbuf, limit);
2120 }
2121
2122 static inline void
2123 buffer_add_objid (Buffer *buf, MonoObject *o)
2124 {
2125         buffer_add_id (buf, get_objid (o));
2126 }
2127
2128 /*
2129  * IDS
2130  */
2131
2132 typedef enum {
2133         ID_ASSEMBLY = 0,
2134         ID_MODULE = 1,
2135         ID_TYPE = 2,
2136         ID_METHOD = 3,
2137         ID_FIELD = 4,
2138         ID_DOMAIN = 5,
2139         ID_PROPERTY = 6,
2140         ID_NUM
2141 } IdType;
2142
2143 /*
2144  * Represents a runtime structure accessible to the debugger client
2145  */
2146 typedef struct {
2147         /* Unique id used in the wire protocol */
2148         int id;
2149         /* Domain of the runtime structure, NULL if the domain was unloaded */
2150         MonoDomain *domain;
2151         union {
2152                 gpointer val;
2153                 MonoClass *klass;
2154                 MonoMethod *method;
2155                 MonoImage *image;
2156                 MonoAssembly *assembly;
2157                 MonoClassField *field;
2158                 MonoDomain *domain;
2159                 MonoProperty *property;
2160         } data;
2161 } Id;
2162
2163 typedef struct {
2164         /* Maps runtime structure -> Id */
2165         GHashTable *val_to_id [ID_NUM];
2166         /* Classes whose class load event has been sent */
2167         GHashTable *loaded_classes;
2168         /* Maps MonoClass->GPtrArray of file names */
2169         GHashTable *source_files;
2170         /* Maps source file basename -> GSList of classes */
2171         GHashTable *source_file_to_class;
2172         /* Same with ignore-case */
2173         GHashTable *source_file_to_class_ignorecase;
2174 } AgentDomainInfo;
2175
2176 /* Maps id -> Id */
2177 /* Protected by the dbg lock */
2178 static GPtrArray *ids [ID_NUM];
2179
2180 static void
2181 ids_init (void)
2182 {
2183         int i;
2184
2185         for (i = 0; i < ID_NUM; ++i)
2186                 ids [i] = g_ptr_array_new ();
2187 }
2188
2189 static void
2190 ids_cleanup (void)
2191 {
2192         int i, j;
2193
2194         for (i = 0; i < ID_NUM; ++i) {
2195                 if (ids [i]) {
2196                         for (j = 0; j < ids [i]->len; ++j)
2197                                 g_free (g_ptr_array_index (ids [i], j));
2198                         g_ptr_array_free (ids [i], TRUE);
2199                 }
2200                 ids [i] = NULL;
2201         }
2202 }
2203
2204 void
2205 mono_debugger_agent_free_domain_info (MonoDomain *domain)
2206 {
2207         AgentDomainInfo *info = domain_jit_info (domain)->agent_info;
2208         int i, j;
2209         GHashTableIter iter;
2210         GPtrArray *file_names;
2211         char *basename;
2212         GSList *l;
2213
2214         if (info) {
2215                 for (i = 0; i < ID_NUM; ++i)
2216                         if (info->val_to_id [i])
2217                                 g_hash_table_destroy (info->val_to_id [i]);
2218                 g_hash_table_destroy (info->loaded_classes);
2219
2220                 g_hash_table_iter_init (&iter, info->source_files);
2221                 while (g_hash_table_iter_next (&iter, NULL, (void**)&file_names)) {
2222                         for (i = 0; i < file_names->len; ++i)
2223                                 g_free (g_ptr_array_index (file_names, i));
2224                         g_ptr_array_free (file_names, TRUE);
2225                 }
2226
2227                 g_hash_table_iter_init (&iter, info->source_file_to_class);
2228                 while (g_hash_table_iter_next (&iter, (void**)&basename, (void**)&l)) {
2229                         g_free (basename);
2230                         g_slist_free (l);
2231                 }
2232
2233                 g_hash_table_iter_init (&iter, info->source_file_to_class_ignorecase);
2234                 while (g_hash_table_iter_next (&iter, (void**)&basename, (void**)&l)) {
2235                         g_free (basename);
2236                         g_slist_free (l);
2237                 }
2238
2239                 g_free (info);
2240         }
2241
2242         domain_jit_info (domain)->agent_info = NULL;
2243
2244         /* Clear ids referencing structures in the domain */
2245         dbg_lock ();
2246         for (i = 0; i < ID_NUM; ++i) {
2247                 if (ids [i]) {
2248                         for (j = 0; j < ids [i]->len; ++j) {
2249                                 Id *id = g_ptr_array_index (ids [i], j);
2250                                 if (id->domain == domain)
2251                                         id->domain = NULL;
2252                         }
2253                 }
2254         }
2255         dbg_unlock ();
2256
2257         mono_loader_lock ();
2258         g_hash_table_remove (domains, domain);
2259         mono_loader_unlock ();
2260 }
2261
2262 static AgentDomainInfo*
2263 get_agent_domain_info (MonoDomain *domain)
2264 {
2265         AgentDomainInfo *info = NULL;
2266
2267         mono_domain_lock (domain);
2268
2269         info = domain_jit_info (domain)->agent_info;
2270         if (!info) {
2271                 info = domain_jit_info (domain)->agent_info = g_new0 (AgentDomainInfo, 1);
2272                 info->loaded_classes = g_hash_table_new (mono_aligned_addr_hash, NULL);
2273                 info->source_files = g_hash_table_new (mono_aligned_addr_hash, NULL);
2274                 info->source_file_to_class = g_hash_table_new (g_str_hash, g_str_equal);
2275                 info->source_file_to_class_ignorecase = g_hash_table_new (g_str_hash, g_str_equal);
2276         }
2277
2278         mono_domain_unlock (domain);
2279
2280         return info;
2281 }
2282
2283 static int
2284 get_id (MonoDomain *domain, IdType type, gpointer val)
2285 {
2286         Id *id;
2287         AgentDomainInfo *info;
2288
2289         if (val == NULL)
2290                 return 0;
2291
2292         mono_loader_lock ();
2293
2294         mono_domain_lock (domain);
2295
2296         info = get_agent_domain_info (domain);
2297
2298         if (info->val_to_id [type] == NULL)
2299                 info->val_to_id [type] = g_hash_table_new (mono_aligned_addr_hash, NULL);
2300
2301         id = g_hash_table_lookup (info->val_to_id [type], val);
2302         if (id) {
2303                 mono_domain_unlock (domain);
2304                 mono_loader_unlock ();
2305                 return id->id;
2306         }
2307
2308         dbg_lock ();
2309
2310         id = g_new0 (Id, 1);
2311         /* Reserve id 0 */
2312         id->id = ids [type]->len + 1;
2313         id->domain = domain;
2314         id->data.val = val;
2315
2316         g_hash_table_insert (info->val_to_id [type], val, id);
2317         g_ptr_array_add (ids [type], id);
2318
2319         dbg_unlock ();
2320
2321         mono_domain_unlock (domain);
2322
2323         mono_loader_unlock ();
2324
2325         return id->id;
2326 }
2327
2328 static inline gpointer
2329 decode_ptr_id (guint8 *buf, guint8 **endbuf, guint8 *limit, IdType type, MonoDomain **domain, int *err)
2330 {
2331         Id *res;
2332
2333         int id = decode_id (buf, endbuf, limit);
2334
2335         *err = 0;
2336         if (domain)
2337                 *domain = NULL;
2338
2339         if (id == 0)
2340                 return NULL;
2341
2342         // FIXME: error handling
2343         dbg_lock ();
2344         g_assert (id > 0 && id <= ids [type]->len);
2345
2346         res = g_ptr_array_index (ids [type], GPOINTER_TO_INT (id - 1));
2347         dbg_unlock ();
2348
2349         if (res->domain == NULL) {
2350                 DEBUG (0, fprintf (log_file, "ERR_UNLOADED, id=%d, type=%d.\n", id, type));
2351                 *err = ERR_UNLOADED;
2352                 return NULL;
2353         }
2354
2355         if (domain)
2356                 *domain = res->domain;
2357
2358         return res->data.val;
2359 }
2360
2361 static inline int
2362 buffer_add_ptr_id (Buffer *buf, MonoDomain *domain, IdType type, gpointer val)
2363 {
2364         int id = get_id (domain, type, val);
2365
2366         buffer_add_id (buf, id);
2367         return id;
2368 }
2369
2370 static inline MonoClass*
2371 decode_typeid (guint8 *buf, guint8 **endbuf, guint8 *limit, MonoDomain **domain, int *err)
2372 {
2373         MonoClass *klass;
2374
2375         klass = decode_ptr_id (buf, endbuf, limit, ID_TYPE, domain, err);
2376         if (G_UNLIKELY (log_level >= 2) && klass) {
2377                 char *s;
2378
2379                 s = mono_type_full_name (&klass->byval_arg);
2380                 DEBUG(2, fprintf (log_file, "[dbg]   recv class [%s]\n", s));
2381                 g_free (s);
2382         }
2383         return klass;
2384 }
2385
2386 static inline MonoAssembly*
2387 decode_assemblyid (guint8 *buf, guint8 **endbuf, guint8 *limit, MonoDomain **domain, int *err)
2388 {
2389         return decode_ptr_id (buf, endbuf, limit, ID_ASSEMBLY, domain, err);
2390 }
2391
2392 static inline MonoImage*
2393 decode_moduleid (guint8 *buf, guint8 **endbuf, guint8 *limit, MonoDomain **domain, int *err)
2394 {
2395         return decode_ptr_id (buf, endbuf, limit, ID_MODULE, domain, err);
2396 }
2397
2398 static inline MonoMethod*
2399 decode_methodid (guint8 *buf, guint8 **endbuf, guint8 *limit, MonoDomain **domain, int *err)
2400 {
2401         MonoMethod *m;
2402
2403         m = decode_ptr_id (buf, endbuf, limit, ID_METHOD, domain, err);
2404         if (G_UNLIKELY (log_level >= 2) && m) {
2405                 char *s;
2406
2407                 s = mono_method_full_name (m, TRUE);
2408                 DEBUG(2, fprintf (log_file, "[dbg]   recv method [%s]\n", s));
2409                 g_free (s);
2410         }
2411         return m;
2412 }
2413
2414 static inline MonoClassField*
2415 decode_fieldid (guint8 *buf, guint8 **endbuf, guint8 *limit, MonoDomain **domain, int *err)
2416 {
2417         return decode_ptr_id (buf, endbuf, limit, ID_FIELD, domain, err);
2418 }
2419
2420 static inline MonoDomain*
2421 decode_domainid (guint8 *buf, guint8 **endbuf, guint8 *limit, MonoDomain **domain, int *err)
2422 {
2423         return decode_ptr_id (buf, endbuf, limit, ID_DOMAIN, domain, err);
2424 }
2425
2426 static inline MonoProperty*
2427 decode_propertyid (guint8 *buf, guint8 **endbuf, guint8 *limit, MonoDomain **domain, int *err)
2428 {
2429         return decode_ptr_id (buf, endbuf, limit, ID_PROPERTY, domain, err);
2430 }
2431
2432 static inline void
2433 buffer_add_typeid (Buffer *buf, MonoDomain *domain, MonoClass *klass)
2434 {
2435         buffer_add_ptr_id (buf, domain, ID_TYPE, klass);
2436         if (G_UNLIKELY (log_level >= 2) && klass) {
2437                 char *s;
2438
2439                 s = mono_type_full_name (&klass->byval_arg);
2440                 if (GetCurrentThreadId () == debugger_thread_id)
2441                         DEBUG(2, fprintf (log_file, "[dbg]   send class [%s]\n", s));
2442                 else
2443                         DEBUG(2, fprintf (log_file, "[%p]   send class [%s]\n", (gpointer)GetCurrentThreadId (), s));
2444                 g_free (s);
2445         }
2446 }
2447
2448 static inline void
2449 buffer_add_methodid (Buffer *buf, MonoDomain *domain, MonoMethod *method)
2450 {
2451         buffer_add_ptr_id (buf, domain, ID_METHOD, method);
2452         if (G_UNLIKELY (log_level >= 2) && method) {
2453                 char *s;
2454
2455                 s = mono_method_full_name (method, 1);
2456                 DEBUG(2, fprintf (log_file, "[dbg]   send method [%s]\n", s));
2457                 g_free (s);
2458         }
2459 }
2460
2461 static inline void
2462 buffer_add_assemblyid (Buffer *buf, MonoDomain *domain, MonoAssembly *assembly)
2463 {
2464         int id;
2465
2466         id = buffer_add_ptr_id (buf, domain, ID_ASSEMBLY, assembly);
2467         if (G_UNLIKELY (log_level >= 2) && assembly)
2468                 DEBUG(2, fprintf (log_file, "[dbg]   send assembly [%s][%s][%d]\n", assembly->aname.name, domain->friendly_name, id));
2469 }
2470
2471 static inline void
2472 buffer_add_moduleid (Buffer *buf, MonoDomain *domain, MonoImage *image)
2473 {
2474         buffer_add_ptr_id (buf, domain, ID_MODULE, image);
2475 }
2476
2477 static inline void
2478 buffer_add_fieldid (Buffer *buf, MonoDomain *domain, MonoClassField *field)
2479 {
2480         buffer_add_ptr_id (buf, domain, ID_FIELD, field);
2481 }
2482
2483 static inline void
2484 buffer_add_propertyid (Buffer *buf, MonoDomain *domain, MonoProperty *property)
2485 {
2486         buffer_add_ptr_id (buf, domain, ID_PROPERTY, property);
2487 }
2488
2489 static inline void
2490 buffer_add_domainid (Buffer *buf, MonoDomain *domain)
2491 {
2492         buffer_add_ptr_id (buf, domain, ID_DOMAIN, domain);
2493 }
2494
2495 static void invoke_method (void);
2496
2497 /*
2498  * SUSPEND/RESUME
2499  */
2500
2501 /*
2502  * save_thread_context:
2503  *
2504  *   Set CTX as the current threads context which is used for computing stack traces.
2505  * This function is signal-safe.
2506  */
2507 static void
2508 save_thread_context (MonoContext *ctx)
2509 {
2510         DebuggerTlsData *tls;
2511
2512         tls = mono_native_tls_get_value (debugger_tls_id);
2513         g_assert (tls);
2514
2515         if (ctx)
2516                 mono_thread_state_init_from_monoctx (&tls->context, ctx);
2517         else
2518                 mono_thread_state_init_from_current (&tls->context);
2519 }
2520
2521 /* Number of threads suspended */
2522 /* 
2523  * If this is equal to the size of thread_to_tls, the runtime is considered
2524  * suspended.
2525  */
2526 static gint32 threads_suspend_count;
2527
2528 static mono_mutex_t suspend_mutex;
2529
2530 /* Cond variable used to wait for suspend_count becoming 0 */
2531 static mono_cond_t suspend_cond;
2532
2533 /* Semaphore used to wait for a thread becoming suspended */
2534 static MonoSemType suspend_sem;
2535
2536 static void
2537 suspend_init (void)
2538 {
2539         mono_mutex_init (&suspend_mutex);
2540         mono_cond_init (&suspend_cond, NULL);   
2541         MONO_SEM_INIT (&suspend_sem, 0);
2542 }
2543
2544 typedef struct
2545 {
2546         StackFrameInfo last_frame;
2547         gboolean last_frame_set;
2548         MonoContext ctx;
2549         gpointer lmf;
2550 } GetLastFrameUserData;
2551
2552 static gboolean
2553 get_last_frame (StackFrameInfo *info, MonoContext *ctx, gpointer user_data)
2554 {
2555         GetLastFrameUserData *data = user_data;
2556
2557         if (info->type == FRAME_TYPE_MANAGED_TO_NATIVE)
2558                 return FALSE;
2559
2560         if (!data->last_frame_set) {
2561                 /* Store the last frame */
2562                 memcpy (&data->last_frame, info, sizeof (StackFrameInfo));
2563                 data->last_frame_set = TRUE;
2564                 return FALSE;
2565         } else {
2566                 /* Store the context/lmf for the frame above the last frame */
2567                 memcpy (&data->ctx, ctx, sizeof (MonoContext));
2568                 data->lmf = info->lmf;
2569                 return TRUE;
2570         }
2571 }
2572
2573 /*
2574  * thread_interrupt:
2575  *
2576  *   Process interruption of a thread. If SIGCTX is set, process the current thread. If
2577  * INFO is set, process the thread described by INFO.
2578  * This should be signal safe.
2579  */
2580 static gboolean
2581 thread_interrupt (DebuggerTlsData *tls, MonoThreadInfo *info, void *sigctx, MonoJitInfo *ji)
2582 {
2583         gboolean res;
2584         gpointer ip;
2585         MonoNativeThreadId tid;
2586
2587         /*
2588          * OSX can (and will) coalesce signals, so sending multiple pthread_kills does not
2589          * guarantee the signal handler will be called that many times.  Instead of tracking
2590          * interrupt_count on osx, we use this as a boolean flag to determine if a interrupt
2591          * has been requested that hasn't been handled yet, otherwise we can have threads
2592          * refuse to die when VM_EXIT is called
2593          */
2594 #if defined(__APPLE__)
2595         if (InterlockedCompareExchange (&tls->interrupt_count, 0, 1) == 0)
2596                 return FALSE;
2597 #else
2598         /*
2599          * We use interrupt_count to determine whenever this interrupt should be processed
2600          * by us or the normal interrupt processing code in the signal handler.
2601          * There is no race here with notify_thread (), since the signal is sent after
2602          * incrementing interrupt_count.
2603          */
2604         if (tls->interrupt_count == 0)
2605                 return FALSE;
2606
2607         InterlockedDecrement (&tls->interrupt_count);
2608 #endif
2609
2610         if (sigctx)
2611                 ip = mono_arch_ip_from_context (sigctx);
2612         else if (info)
2613                 ip = MONO_CONTEXT_GET_IP (&info->suspend_state.ctx);
2614         else
2615                 ip = NULL;
2616
2617         if (info)
2618                 tid = mono_thread_info_get_tid (info);
2619         else
2620                 tid = (MonoNativeThreadId)GetCurrentThreadId ();
2621
2622         // FIXME: Races when the thread leaves managed code before hitting a single step
2623         // event.
2624
2625         if (ji) {
2626                 /* Running managed code, will be suspended by the single step code */
2627                 DEBUG (1, fprintf (log_file, "[%p] Received interrupt while at %s(%p), continuing.\n", (gpointer)(gsize)tid, jinfo_get_method (ji)->name, ip));
2628                 return TRUE;
2629         } else {
2630                 /* 
2631                  * Running native code, will be suspended when it returns to/enters 
2632                  * managed code. Treat it as already suspended.
2633                  * This might interrupt the code in process_single_step_inner (), we use the
2634                  * tls->suspending flag to avoid races when that happens.
2635                  */
2636                 if (!tls->suspended && !tls->suspending) {
2637                         MonoContext ctx;
2638                         GetLastFrameUserData data;
2639
2640                         // FIXME: printf is not signal safe, but this is only used during
2641                         // debugger debugging
2642                         if (ip)
2643                                 DEBUG (1, fprintf (log_file, "[%p] Received interrupt while at %p, treating as suspended.\n", (gpointer)(gsize)tid, ip));
2644                         //save_thread_context (&ctx);
2645
2646                         if (!tls->thread)
2647                                 /* Already terminated */
2648                                 return TRUE;
2649
2650                         /*
2651                          * We are in a difficult position: we want to be able to provide stack
2652                          * traces for this thread, but we can't use the current ctx+lmf, since
2653                          * the thread is still running, so it might return to managed code,
2654                          * making these invalid.
2655                          * So we start a stack walk and save the first frame, along with the
2656                          * parent frame's ctx+lmf. This (hopefully) works because the thread will be 
2657                          * suspended when it returns to managed code, so the parent's ctx should
2658                          * remain valid.
2659                          */
2660                         data.last_frame_set = FALSE;
2661                         if (sigctx) {
2662                                 mono_sigctx_to_monoctx (sigctx, &ctx);
2663                                 /* 
2664                                  * Don't pass MONO_UNWIND_ACTUAL_METHOD, its not signal safe, and
2665                                  * get_last_frame () doesn't need it, the last frame cannot be a ginst
2666                                  * since we are not in a JITted method.
2667                                  */
2668                                 mono_walk_stack_with_ctx (get_last_frame, &ctx, MONO_UNWIND_NONE, &data);
2669                         } else if (info) {
2670                                 mono_get_eh_callbacks ()->mono_walk_stack_with_state (get_last_frame, &info->suspend_state, MONO_UNWIND_SIGNAL_SAFE, &data);
2671                         }
2672                         if (data.last_frame_set) {
2673                                 memcpy (&tls->async_last_frame, &data.last_frame, sizeof (StackFrameInfo));
2674                                 res = mono_thread_state_init_from_monoctx (&tls->async_state, &ctx);
2675                                 g_assert (res);
2676                                 mono_thread_state_init_from_monoctx (&tls->context, &ctx);
2677                                 g_assert (res);
2678
2679                                 memcpy (&tls->async_state.ctx, &data.ctx, sizeof (MonoContext));
2680                                 tls->async_state.unwind_data [MONO_UNWIND_DATA_LMF] = data.lmf;
2681                                 tls->async_state.unwind_data [MONO_UNWIND_DATA_JIT_TLS] = tls->thread->jit_data;
2682                         } else {
2683                                 tls->async_state.valid = FALSE;
2684                         }
2685
2686                         mono_memory_barrier ();
2687
2688                         tls->suspended = TRUE;
2689                         MONO_SEM_POST (&suspend_sem);
2690                 }
2691                 return TRUE;
2692         }
2693 }
2694
2695 /*
2696  * mono_debugger_agent_thread_interrupt:
2697  *
2698  *   Called by the abort signal handler.
2699  * Should be signal safe.
2700  */
2701 gboolean
2702 mono_debugger_agent_thread_interrupt (void *sigctx, MonoJitInfo *ji)
2703 {
2704         DebuggerTlsData *tls;
2705
2706         if (!inited)
2707                 return FALSE;
2708
2709         tls = mono_native_tls_get_value (debugger_tls_id);
2710         if (!tls) {
2711                 DEBUG (1, fprintf (log_file, "[%p] Received interrupt with no TLS, continuing.\n", (gpointer)GetCurrentThreadId ()));
2712                 return FALSE;
2713         }
2714
2715         return thread_interrupt (tls, NULL, sigctx, ji);
2716 }
2717
2718 #ifdef HOST_WIN32
2719 static void CALLBACK notify_thread_apc (ULONG_PTR param)
2720 {
2721         //DebugBreak ();
2722         mono_debugger_agent_thread_interrupt (NULL, NULL);
2723 }
2724 #endif /* HOST_WIN32 */
2725
2726 /*
2727  * reset_native_thread_suspend_state:
2728  * 
2729  *   Reset the suspended flag and state on native threads
2730  */
2731 static void
2732 reset_native_thread_suspend_state (gpointer key, gpointer value, gpointer user_data)
2733 {
2734         DebuggerTlsData *tls = value;
2735
2736         if (!tls->really_suspended && tls->suspended) {
2737                 tls->suspended = FALSE;
2738                 /*
2739                  * The thread might still be running if it was executing native code, so the state won't be invalided by
2740                  * suspend_current ().
2741                  */
2742                 tls->context.valid = FALSE;
2743                 tls->async_state.valid = FALSE;
2744                 invalidate_frames (tls);
2745         }
2746 }
2747
2748 /*
2749  * notify_thread:
2750  *
2751  *   Notify a thread that it needs to suspend.
2752  */
2753 static void
2754 notify_thread (gpointer key, gpointer value, gpointer user_data)
2755 {
2756         MonoInternalThread *thread = key;
2757         DebuggerTlsData *tls = value;
2758         gsize tid = thread->tid;
2759 #ifndef HOST_WIN32
2760         int res;
2761 #endif
2762
2763         if (GetCurrentThreadId () == tid || tls->terminated)
2764                 return;
2765
2766         DEBUG(1, fprintf (log_file, "[%p] Interrupting %p...\n", (gpointer)GetCurrentThreadId (), (gpointer)tid));
2767
2768         /*
2769          * OSX can (and will) coalesce signals, so sending multiple pthread_kills does not
2770          * guarantee the signal handler will be called that many times.  Instead of tracking
2771          * interrupt_count on osx, we use this as a boolean flag to determine if a interrupt
2772          * has been requested that hasn't been handled yet, otherwise we can have threads
2773          * refuse to die when VM_EXIT is called
2774          */
2775 #if defined(__APPLE__)
2776         if (InterlockedCompareExchange (&tls->interrupt_count, 1, 0) == 1)
2777                 return;
2778 #else
2779         /*
2780          * Maybe we could use the normal interrupt infrastructure, but that does a lot
2781          * of things like breaking waits etc. which we don't want.
2782          */
2783         InterlockedIncrement (&tls->interrupt_count);
2784 #endif
2785
2786         /* This is _not_ equivalent to ves_icall_System_Threading_Thread_Abort () */
2787         if (mono_thread_info_new_interrupt_enabled ()) {
2788                 MonoThreadInfo *info;
2789                 MonoJitInfo *ji;
2790
2791                 info = mono_thread_info_safe_suspend_sync ((MonoNativeThreadId)(gpointer)(gsize)thread->tid, FALSE);
2792                 if (!info) {
2793                         DEBUG(1, fprintf (log_file, "[%p] mono_thread_info_suspend_sync () failed for %p...\n", (gpointer)GetCurrentThreadId (), (gpointer)tid));
2794                         /* 
2795                          * Attached thread which died without detaching.
2796                          */
2797                         tls->terminated = TRUE;
2798                 } else {
2799                         ji = mono_jit_info_table_find (info->suspend_state.unwind_data [MONO_UNWIND_DATA_DOMAIN], MONO_CONTEXT_GET_IP (&info->suspend_state.ctx));
2800
2801                         thread_interrupt (tls, info, NULL, ji);
2802
2803                         mono_thread_info_finish_suspend_and_resume (info);
2804                 }
2805         } else {
2806 #ifdef HOST_WIN32
2807                 // FIXME: Remove this since new interrupt is used on win32 now
2808                 QueueUserAPC (notify_thread_apc, thread->handle, (ULONG_PTR)NULL);
2809 #else
2810                 res = mono_thread_kill (thread, mono_thread_get_abort_signal ());
2811                 if (res) {
2812                         DEBUG(1, fprintf (log_file, "[%p] mono_thread_kill () failed for %p: %d...\n", (gpointer)GetCurrentThreadId (), (gpointer)tid, res));
2813                         /* 
2814                          * Attached thread which died without detaching.
2815                          */
2816                         tls->terminated = TRUE;
2817                 }
2818 #endif
2819         }
2820 }
2821
2822 static void
2823 process_suspend (DebuggerTlsData *tls, MonoContext *ctx)
2824 {
2825         guint8 *ip = MONO_CONTEXT_GET_IP (ctx);
2826         MonoJitInfo *ji;
2827         MonoMethod *method;
2828
2829         if (mono_loader_lock_is_owned_by_self ()) {
2830                 /*
2831                  * Shortcut for the check in suspend_current (). This speeds up processing
2832                  * when executing long running code inside the loader lock, i.e. assembly load
2833                  * hooks.
2834                  */
2835                 return;
2836         }
2837
2838         if (debugger_thread_id == GetCurrentThreadId ())
2839                 return;
2840
2841         /* Prevent races with mono_debugger_agent_thread_interrupt () */
2842         if (suspend_count - tls->resume_count > 0)
2843                 tls->suspending = TRUE;
2844
2845         DEBUG(1, fprintf (log_file, "[%p] Received single step event for suspending.\n", (gpointer)GetCurrentThreadId ()));
2846
2847         if (suspend_count - tls->resume_count == 0) {
2848                 /* 
2849                  * We are executing a single threaded invoke but the single step for 
2850                  * suspending is still active.
2851                  * FIXME: This slows down single threaded invokes.
2852                  */
2853                 DEBUG(1, fprintf (log_file, "[%p] Ignored during single threaded invoke.\n", (gpointer)GetCurrentThreadId ()));
2854                 return;
2855         }
2856
2857         ji = mini_jit_info_table_find (mono_domain_get (), (char*)ip, NULL);
2858
2859         /* Can't suspend in these methods */
2860         method = jinfo_get_method (ji);
2861         if (method->klass == mono_defaults.string_class && (!strcmp (method->name, "memset") || strstr (method->name, "memcpy")))
2862                 return;
2863
2864         save_thread_context (ctx);
2865
2866         suspend_current ();
2867 }
2868
2869 /*
2870  * suspend_vm:
2871  *
2872  * Increase the suspend count of the VM. While the suspend count is greater 
2873  * than 0, runtime threads are suspended at certain points during execution.
2874  */
2875 static void
2876 suspend_vm (void)
2877 {
2878         mono_loader_lock ();
2879
2880         mono_mutex_lock (&suspend_mutex);
2881
2882         suspend_count ++;
2883
2884         DEBUG(1, fprintf (log_file, "[%p] Suspending vm...\n", (gpointer)GetCurrentThreadId ()));
2885
2886         if (suspend_count == 1) {
2887                 // FIXME: Is it safe to call this inside the lock ?
2888                 start_single_stepping ();
2889                 mono_g_hash_table_foreach (thread_to_tls, notify_thread, NULL);
2890         }
2891
2892         mono_mutex_unlock (&suspend_mutex);
2893
2894         if (suspend_count == 1)
2895                 /*
2896                  * Suspend creation of new threadpool threads, since they cannot run
2897                  */
2898                 mono_thread_pool_suspend ();
2899
2900         mono_loader_unlock ();
2901 }
2902
2903 /*
2904  * resume_vm:
2905  *
2906  * Decrease the suspend count of the VM. If the count reaches 0, runtime threads
2907  * are resumed.
2908  */
2909 static void
2910 resume_vm (void)
2911 {
2912         int err;
2913
2914         g_assert (debugger_thread_id == GetCurrentThreadId ());
2915
2916         mono_loader_lock ();
2917
2918         mono_mutex_lock (&suspend_mutex);
2919
2920         g_assert (suspend_count > 0);
2921         suspend_count --;
2922
2923         DEBUG(1, fprintf (log_file, "[%p] Resuming vm, suspend count=%d...\n", (gpointer)GetCurrentThreadId (), suspend_count));
2924
2925         if (suspend_count == 0) {
2926                 // FIXME: Is it safe to call this inside the lock ?
2927                 stop_single_stepping ();
2928                 mono_g_hash_table_foreach (thread_to_tls, reset_native_thread_suspend_state, NULL);
2929         }
2930
2931         /* Signal this even when suspend_count > 0, since some threads might have resume_count > 0 */
2932         err = mono_cond_broadcast (&suspend_cond);
2933         g_assert (err == 0);
2934
2935         mono_mutex_unlock (&suspend_mutex);
2936         //g_assert (err == 0);
2937
2938         if (suspend_count == 0)
2939                 mono_thread_pool_resume ();
2940
2941         mono_loader_unlock ();
2942 }
2943
2944 /*
2945  * resume_thread:
2946  *
2947  *   Resume just one thread.
2948  */
2949 static void
2950 resume_thread (MonoInternalThread *thread)
2951 {
2952         int err;
2953         DebuggerTlsData *tls;
2954
2955         g_assert (debugger_thread_id == GetCurrentThreadId ());
2956
2957         mono_loader_lock ();
2958
2959         tls = mono_g_hash_table_lookup (thread_to_tls, thread);
2960         g_assert (tls);
2961         
2962         mono_mutex_lock (&suspend_mutex);
2963
2964         g_assert (suspend_count > 0);
2965
2966         DEBUG(1, fprintf (log_file, "[sdb] Resuming thread %p...\n", (gpointer)(gssize)thread->tid));
2967
2968         tls->resume_count += suspend_count;
2969
2970         /* 
2971          * Signal suspend_count without decreasing suspend_count, the threads will wake up
2972          * but only the one whose resume_count field is > 0 will be resumed.
2973          */
2974         err = mono_cond_broadcast (&suspend_cond);
2975         g_assert (err == 0);
2976
2977         mono_mutex_unlock (&suspend_mutex);
2978         //g_assert (err == 0);
2979
2980         mono_loader_unlock ();
2981 }
2982
2983 static void
2984 invalidate_frames (DebuggerTlsData *tls)
2985 {
2986         int i;
2987
2988         if (!tls)
2989                 tls = mono_native_tls_get_value (debugger_tls_id);
2990         g_assert (tls);
2991
2992         for (i = 0; i < tls->frame_count; ++i) {
2993                 if (tls->frames [i]->jit)
2994                         mono_debug_free_method_jit_info (tls->frames [i]->jit);
2995                 g_free (tls->frames [i]);
2996         }
2997         g_free (tls->frames);
2998         tls->frame_count = 0;
2999         tls->frames = NULL;
3000 }
3001
3002 /*
3003  * suspend_current:
3004  *
3005  *   Suspend the current thread until the runtime is resumed. If the thread has a 
3006  * pending invoke, then the invoke is executed before this function returns. 
3007  */
3008 static void
3009 suspend_current (void)
3010 {
3011 #ifndef HOST_WIN32
3012         int err;
3013 #endif
3014         DebuggerTlsData *tls;
3015
3016         g_assert (debugger_thread_id != GetCurrentThreadId ());
3017
3018         if (mono_loader_lock_is_owned_by_self ()) {
3019                 /*
3020                  * If we own the loader mutex, can't suspend until we release it, since the
3021                  * whole runtime can deadlock otherwise.
3022                  */
3023                 return;
3024         }
3025
3026         tls = mono_native_tls_get_value (debugger_tls_id);
3027         g_assert (tls);
3028
3029         mono_mutex_lock (&suspend_mutex);
3030
3031         tls->suspending = FALSE;
3032         tls->really_suspended = TRUE;
3033
3034         if (!tls->suspended) {
3035                 tls->suspended = TRUE;
3036                 MONO_SEM_POST (&suspend_sem);
3037         }
3038
3039         DEBUG(1, fprintf (log_file, "[%p] Suspended.\n", (gpointer)GetCurrentThreadId ()));
3040
3041         while (suspend_count - tls->resume_count > 0) {
3042 #ifdef HOST_WIN32
3043                 if (WAIT_TIMEOUT == WaitForSingleObject(suspend_cond, 0))
3044                 {
3045                         mono_mutex_unlock (&suspend_mutex);
3046                         Sleep(1);
3047                         mono_mutex_lock (&suspend_mutex);
3048                 }
3049                 else
3050                 {
3051                 }
3052 #else
3053                 err = mono_cond_wait (&suspend_cond, &suspend_mutex);
3054                 g_assert (err == 0);
3055 #endif
3056         }
3057
3058         tls->suspended = FALSE;
3059         tls->really_suspended = FALSE;
3060
3061         threads_suspend_count --;
3062
3063         mono_mutex_unlock (&suspend_mutex);
3064
3065         DEBUG(1, fprintf (log_file, "[%p] Resumed.\n", (gpointer)GetCurrentThreadId ()));
3066
3067         if (tls->pending_invoke) {
3068                 /* Save the original context */
3069                 tls->pending_invoke->has_ctx = TRUE;
3070                 tls->pending_invoke->ctx = tls->context.ctx;
3071
3072                 invoke_method ();
3073         }
3074
3075         /* The frame info becomes invalid after a resume */
3076         tls->context.valid = FALSE;
3077         tls->async_state.valid = FALSE;
3078         invalidate_frames (tls);
3079 }
3080
3081 static void
3082 count_thread (gpointer key, gpointer value, gpointer user_data)
3083 {
3084         DebuggerTlsData *tls = value;
3085
3086         if (!tls->suspended && !tls->terminated)
3087                 *(int*)user_data = *(int*)user_data + 1;
3088 }
3089
3090 static int
3091 count_threads_to_wait_for (void)
3092 {
3093         int count = 0;
3094
3095         mono_loader_lock ();
3096         mono_g_hash_table_foreach (thread_to_tls, count_thread, &count);
3097         mono_loader_unlock ();
3098
3099         return count;
3100 }       
3101
3102 /*
3103  * wait_for_suspend:
3104  *
3105  *   Wait until the runtime is completely suspended.
3106  */
3107 static void
3108 wait_for_suspend (void)
3109 {
3110         int nthreads, nwait, err;
3111         gboolean waited = FALSE;
3112
3113         // FIXME: Threads starting/stopping ?
3114         mono_loader_lock ();
3115         nthreads = mono_g_hash_table_size (thread_to_tls);
3116         mono_loader_unlock ();
3117
3118         while (TRUE) {
3119                 nwait = count_threads_to_wait_for ();
3120                 if (nwait) {
3121                         DEBUG(1, fprintf (log_file, "Waiting for %d(%d) threads to suspend...\n", nwait, nthreads));
3122                         err = MONO_SEM_WAIT (&suspend_sem);
3123                         g_assert (err == 0);
3124                         waited = TRUE;
3125                 } else {
3126                         break;
3127                 }
3128         }
3129
3130         if (waited)
3131                 DEBUG(1, fprintf (log_file, "%d threads suspended.\n", nthreads));
3132 }
3133
3134 /*
3135  * is_suspended:
3136  *
3137  *   Return whenever the runtime is suspended.
3138  */
3139 static gboolean
3140 is_suspended (void)
3141 {
3142         return count_threads_to_wait_for () == 0;
3143 }
3144
3145 static MonoSeqPointInfo*
3146 get_seq_points (MonoDomain *domain, MonoMethod *method)
3147 {
3148         MonoSeqPointInfo *seq_points;
3149
3150         mono_domain_lock (domain);
3151         seq_points = g_hash_table_lookup (domain_jit_info (domain)->seq_points, method);
3152         if (!seq_points && method->is_inflated) {
3153                 /* generic sharing + aot */
3154                 seq_points = g_hash_table_lookup (domain_jit_info (domain)->seq_points, mono_method_get_declaring_generic_method (method));
3155                 if (!seq_points)
3156                         seq_points = g_hash_table_lookup (domain_jit_info (domain)->seq_points, mini_get_shared_method (method));
3157         }
3158         mono_domain_unlock (domain);
3159
3160         return seq_points;
3161 }
3162
3163 static void
3164 no_seq_points_found (MonoMethod *method)
3165 {
3166         /*
3167          * This can happen in full-aot mode with assemblies AOTed without the 'soft-debug' option to save space.
3168          */
3169         printf ("Unable to find seq points for method '%s'.\n", mono_method_full_name (method, TRUE));
3170 }
3171
3172 /*
3173  * find_next_seq_point_for_native_offset:
3174  *
3175  *   Find the first sequence point after NATIVE_OFFSET.
3176  */
3177 static SeqPoint*
3178 find_next_seq_point_for_native_offset (MonoDomain *domain, MonoMethod *method, gint32 native_offset, MonoSeqPointInfo **info)
3179 {
3180         MonoSeqPointInfo *seq_points;
3181         int i;
3182
3183         seq_points = get_seq_points (domain, method);
3184         if (!seq_points) {
3185                 if (info)
3186                         *info = NULL;
3187                 return NULL;
3188         }
3189         g_assert (seq_points);
3190         if (info)
3191                 *info = seq_points;
3192
3193         for (i = 0; i < seq_points->len; ++i) {
3194                 if (seq_points->seq_points [i].native_offset >= native_offset)
3195                         return &seq_points->seq_points [i];
3196         }
3197
3198         return NULL;
3199 }
3200
3201 /*
3202  * find_prev_seq_point_for_native_offset:
3203  *
3204  *   Find the first sequence point before NATIVE_OFFSET.
3205  */
3206 static SeqPoint*
3207 find_prev_seq_point_for_native_offset (MonoDomain *domain, MonoMethod *method, gint32 native_offset, MonoSeqPointInfo **info)
3208 {
3209         MonoSeqPointInfo *seq_points;
3210         int i;
3211
3212         seq_points = get_seq_points (domain, method);
3213         if (info)
3214                 *info = seq_points;
3215         if (!seq_points)
3216                 return NULL;
3217
3218         for (i = seq_points->len - 1; i >= 0; --i) {
3219                 if (seq_points->seq_points [i].native_offset <= native_offset)
3220                         return &seq_points->seq_points [i];
3221         }
3222
3223         return NULL;
3224 }
3225
3226 /*
3227  * find_seq_point:
3228  *
3229  *   Find the sequence point corresponding to the IL offset IL_OFFSET, which
3230  * should be the location of a sequence point.
3231  */
3232 static G_GNUC_UNUSED SeqPoint*
3233 find_seq_point (MonoDomain *domain, MonoMethod *method, gint32 il_offset, MonoSeqPointInfo **info)
3234 {
3235         MonoSeqPointInfo *seq_points;
3236         int i;
3237
3238         *info = NULL;
3239
3240         seq_points = get_seq_points (domain, method);
3241         if (!seq_points)
3242                 return NULL;
3243         *info = seq_points;
3244
3245         for (i = 0; i < seq_points->len; ++i) {
3246                 if (seq_points->seq_points [i].il_offset == il_offset)
3247                         return &seq_points->seq_points [i];
3248         }
3249
3250         return NULL;
3251 }
3252
3253 typedef struct {
3254         DebuggerTlsData *tls;
3255         GSList *frames;
3256 } ComputeFramesUserData;
3257
3258 static gboolean
3259 process_frame (StackFrameInfo *info, MonoContext *ctx, gpointer user_data)
3260 {
3261         ComputeFramesUserData *ud = user_data;
3262         StackFrame *frame;
3263         MonoMethod *method, *actual_method, *api_method;
3264         SeqPoint *sp;
3265         int flags = 0;
3266
3267         if (info->type != FRAME_TYPE_MANAGED) {
3268                 if (info->type == FRAME_TYPE_DEBUGGER_INVOKE) {
3269                         /* Mark the last frame as an invoke frame */
3270                         if (ud->frames)
3271                                 ((StackFrame*)g_slist_last (ud->frames)->data)->flags |= FRAME_FLAG_DEBUGGER_INVOKE;
3272                 }
3273                 return FALSE;
3274         }
3275
3276         if (info->ji)
3277                 method = jinfo_get_method (info->ji);
3278         else
3279                 method = info->method;
3280         actual_method = info->actual_method;
3281         api_method = method;
3282
3283         if (!method)
3284                 return FALSE;
3285
3286         if (!method || (method->wrapper_type && method->wrapper_type != MONO_WRAPPER_DYNAMIC_METHOD && method->wrapper_type != MONO_WRAPPER_MANAGED_TO_NATIVE))
3287                 return FALSE;
3288
3289         if (info->il_offset == -1) {
3290                 /* mono_debug_il_offset_from_address () doesn't seem to be precise enough (#2092) */
3291                 if (ud->frames == NULL) {
3292                         sp = find_prev_seq_point_for_native_offset (info->domain, method, info->native_offset, NULL);
3293                         if (sp)
3294                                 info->il_offset = sp->il_offset;
3295                 }
3296                 if (info->il_offset == -1)
3297                         info->il_offset = mono_debug_il_offset_from_address (method, info->domain, info->native_offset);
3298         }
3299
3300         DEBUG (1, fprintf (log_file, "\tFrame: %s:%x(%x) %d\n", mono_method_full_name (method, TRUE), info->il_offset, info->native_offset, info->managed));
3301
3302         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE) {
3303                 if (!CHECK_PROTOCOL_VERSION (2, 17))
3304                         /* Older clients can't handle this flag */
3305                         return FALSE;
3306                 api_method = mono_marshal_method_from_wrapper (method);
3307                 if (!api_method)
3308                         return FALSE;
3309                 actual_method = api_method;
3310                 flags |= FRAME_FLAG_NATIVE_TRANSITION;
3311         }
3312
3313         frame = g_new0 (StackFrame, 1);
3314         frame->method = method;
3315         frame->actual_method = actual_method;
3316         frame->api_method = api_method;
3317         frame->il_offset = info->il_offset;
3318         frame->native_offset = info->native_offset;
3319         frame->flags = flags;
3320         frame->ji = info->ji;
3321         if (info->reg_locations)
3322                 memcpy (frame->reg_locations, info->reg_locations, MONO_MAX_IREGS * sizeof (mgreg_t*));
3323         if (ctx) {
3324                 frame->ctx = *ctx;
3325                 frame->has_ctx = TRUE;
3326         }
3327         frame->domain = info->domain;
3328
3329         ud->frames = g_slist_append (ud->frames, frame);
3330
3331         return FALSE;
3332 }
3333
3334 static gboolean
3335 process_filter_frame (StackFrameInfo *info, MonoContext *ctx, gpointer user_data)
3336 {
3337         ComputeFramesUserData *ud = user_data;
3338
3339         /*
3340          * 'tls->filter_ctx' is the location of the throw site.
3341          *
3342          * mono_walk_stack() will never actually hit the throw site, but unwind
3343          * directly from the filter to the call site; we abort stack unwinding here
3344          * once this happens and resume from the throw site.
3345          */
3346
3347         if (MONO_CONTEXT_GET_SP (ctx) >= MONO_CONTEXT_GET_SP (&ud->tls->filter_state.ctx))
3348                 return TRUE;
3349
3350         return process_frame (info, ctx, user_data);
3351 }
3352
3353 static void
3354 compute_frame_info (MonoInternalThread *thread, DebuggerTlsData *tls)
3355 {
3356         ComputeFramesUserData user_data;
3357         GSList *tmp;
3358         int i, findex, new_frame_count;
3359         StackFrame **new_frames, *f;
3360         MonoUnwindOptions opts = MONO_UNWIND_DEFAULT|MONO_UNWIND_REG_LOCATIONS;
3361
3362         // FIXME: Locking on tls
3363         if (tls->frames && tls->frames_up_to_date)
3364                 return;
3365
3366         DEBUG(1, fprintf (log_file, "Frames for %p(tid=%lx):\n", thread, (glong)thread->tid));
3367
3368         user_data.tls = tls;
3369         user_data.frames = NULL;
3370         if (tls->terminated) {
3371                 tls->frame_count = 0;
3372                 return;
3373         } if (!tls->really_suspended && tls->async_state.valid) {
3374                 /* Have to use the state saved by the signal handler */
3375                 process_frame (&tls->async_last_frame, NULL, &user_data);
3376                 mono_walk_stack_with_state (process_frame, &tls->async_state, opts, &user_data);
3377         } else if (tls->filter_state.valid) {
3378                 /*
3379                  * We are inside an exception filter.
3380                  *
3381                  * First we add all the frames from inside the filter; 'tls->ctx' has the current context.
3382                  */
3383                 if (tls->context.valid)
3384                         mono_walk_stack_with_state (process_filter_frame, &tls->context, opts, &user_data);
3385                 /*
3386                  * After that, we resume unwinding from the location where the exception has been thrown.
3387                  */
3388                 mono_walk_stack_with_state (process_frame, &tls->filter_state, opts, &user_data);
3389         } else if (tls->context.valid) {
3390                 mono_walk_stack_with_state (process_frame, &tls->context, opts, &user_data);
3391         } else {
3392                 // FIXME:
3393                 tls->frame_count = 0;
3394                 return;
3395         }
3396
3397         new_frame_count = g_slist_length (user_data.frames);
3398         new_frames = g_new0 (StackFrame*, new_frame_count);
3399         findex = 0;
3400         for (tmp = user_data.frames; tmp; tmp = tmp->next) {
3401                 f = tmp->data;
3402
3403                 /* 
3404                  * Reuse the id for already existing stack frames, so invokes don't invalidate
3405                  * the still valid stack frames.
3406                  */
3407                 for (i = 0; i < tls->frame_count; ++i) {
3408                         if (MONO_CONTEXT_GET_SP (&tls->frames [i]->ctx) == MONO_CONTEXT_GET_SP (&f->ctx)) {
3409                                 f->id = tls->frames [i]->id;
3410                                 break;
3411                         }
3412                 }
3413
3414                 if (i >= tls->frame_count)
3415                         f->id = InterlockedIncrement (&frame_id);
3416
3417                 new_frames [findex ++] = f;
3418         }
3419
3420         g_slist_free (user_data.frames);
3421
3422         invalidate_frames (tls);
3423
3424         tls->frames = new_frames;
3425         tls->frame_count = new_frame_count;
3426         tls->frames_up_to_date = TRUE;
3427 }
3428
3429 /*
3430  * GHFunc to emit an appdomain creation event
3431  * @param key Don't care
3432  * @param value A loaded appdomain
3433  * @param user_data Don't care
3434  */
3435 static void
3436 emit_appdomain_load (gpointer key, gpointer value, gpointer user_data)
3437 {
3438         process_profiler_event (EVENT_KIND_APPDOMAIN_CREATE, value);
3439         g_hash_table_foreach (get_agent_domain_info (value)->loaded_classes, emit_type_load, NULL);
3440 }
3441
3442 /*
3443  * GHFunc to emit a thread start event
3444  * @param key A thread id
3445  * @param value A thread object
3446  * @param user_data Don't care
3447  */
3448 static void
3449 emit_thread_start (gpointer key, gpointer value, gpointer user_data)
3450 {
3451         if (GPOINTER_TO_INT (key) != debugger_thread_id)
3452                 process_profiler_event (EVENT_KIND_THREAD_START, value);
3453 }
3454
3455 /*
3456  * GFunc to emit an assembly load event
3457  * @param value A loaded assembly
3458  * @param user_data Don't care
3459  */
3460 static void
3461 emit_assembly_load (gpointer value, gpointer user_data)
3462 {
3463         process_profiler_event (EVENT_KIND_ASSEMBLY_LOAD, value);
3464 }
3465
3466 /*
3467  * GFunc to emit a type load event
3468  * @param value A loaded type
3469  * @param user_data Don't care
3470  */
3471 static void
3472 emit_type_load (gpointer key, gpointer value, gpointer user_data)
3473 {
3474         process_profiler_event (EVENT_KIND_TYPE_LOAD, value);
3475 }
3476
3477 static char*
3478 strdup_tolower (char *s)
3479 {
3480         char *s2, *p;
3481
3482         s2 = g_strdup (s);
3483         for (p = s2; *p; ++p)
3484                 *p = tolower (*p);
3485         return s2;
3486 }
3487
3488 /*
3489  * EVENT HANDLING
3490  */
3491
3492 /*
3493  * create_event_list:
3494  *
3495  *   Return a list of event request ids matching EVENT, starting from REQS, which
3496  * can be NULL to include all event requests. Set SUSPEND_POLICY to the suspend
3497  * policy.
3498  * We return request ids, instead of requests, to simplify threading, since 
3499  * requests could be deleted anytime when the loader lock is not held.
3500  * LOCKING: Assumes the loader lock is held.
3501  */
3502 static GSList*
3503 create_event_list (EventKind event, GPtrArray *reqs, MonoJitInfo *ji, EventInfo *ei, int *suspend_policy)
3504 {
3505         int i, j;
3506         GSList *events = NULL;
3507
3508         *suspend_policy = SUSPEND_POLICY_NONE;
3509
3510         if (!reqs)
3511                 reqs = event_requests;
3512
3513         if (!reqs)
3514                 return NULL;
3515
3516         for (i = 0; i < reqs->len; ++i) {
3517                 EventRequest *req = g_ptr_array_index (reqs, i);
3518                 if (req->event_kind == event) {
3519                         gboolean filtered = FALSE;
3520
3521                         /* Apply filters */
3522                         for (j = 0; j < req->nmodifiers; ++j) {
3523                                 Modifier *mod = &req->modifiers [j];
3524
3525                                 if (mod->kind == MOD_KIND_COUNT) {
3526                                         filtered = TRUE;
3527                                         if (mod->data.count > 0) {
3528                                                 if (mod->data.count > 0) {
3529                                                         mod->data.count --;
3530                                                         if (mod->data.count == 0)
3531                                                                 filtered = FALSE;
3532                                                 }
3533                                         }
3534                                 } else if (mod->kind == MOD_KIND_THREAD_ONLY) {
3535                                         if (mod->data.thread != mono_thread_internal_current ())
3536                                                 filtered = TRUE;
3537                                 } else if (mod->kind == MOD_KIND_EXCEPTION_ONLY && ei) {
3538                                         if (mod->data.exc_class && mod->subclasses && !mono_class_is_assignable_from (mod->data.exc_class, ei->exc->vtable->klass))
3539                                                 filtered = TRUE;
3540                                         if (mod->data.exc_class && !mod->subclasses && mod->data.exc_class != ei->exc->vtable->klass)
3541                                                 filtered = TRUE;
3542                                         if (ei->caught && !mod->caught)
3543                                                 filtered = TRUE;
3544                                         if (!ei->caught && !mod->uncaught)
3545                                                 filtered = TRUE;
3546                                 } else if (mod->kind == MOD_KIND_ASSEMBLY_ONLY && ji) {
3547                                         int k;
3548                                         gboolean found = FALSE;
3549                                         MonoAssembly **assemblies = mod->data.assemblies;
3550
3551                                         if (assemblies) {
3552                                                 for (k = 0; assemblies [k]; ++k)
3553                                                         if (assemblies [k] == jinfo_get_method (ji)->klass->image->assembly)
3554                                                                 found = TRUE;
3555                                         }
3556                                         if (!found)
3557                                                 filtered = TRUE;
3558                                 } else if (mod->kind == MOD_KIND_SOURCE_FILE_ONLY && ei && ei->klass) {
3559                                         gpointer iter = NULL;
3560                                         MonoMethod *method;
3561                                         MonoDebugSourceInfo *sinfo;
3562                                         char *source_file, *s;
3563                                         gboolean found = FALSE;
3564                                         int i;
3565                                         GPtrArray *source_file_list;
3566
3567                                         while ((method = mono_class_get_methods (ei->klass, &iter))) {
3568                                                 MonoDebugMethodInfo *minfo = mono_debug_lookup_method (method);
3569
3570                                                 if (minfo) {
3571                                                         mono_debug_symfile_get_line_numbers_full (minfo, &source_file, &source_file_list, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
3572                                                         for (i = 0; i < source_file_list->len; ++i) {
3573                                                                 sinfo = g_ptr_array_index (source_file_list, i);
3574                                                                 /*
3575                                                                  * Do a case-insesitive match by converting the file name to
3576                                                                  * lowercase.
3577                                                                  */
3578                                                                 s = strdup_tolower (sinfo->source_file);
3579                                                                 if (g_hash_table_lookup (mod->data.source_files, s))
3580                                                                         found = TRUE;
3581                                                                 else {
3582                                                                         char *s2 = g_path_get_basename (sinfo->source_file);
3583                                                                         char *s3 = strdup_tolower (s2);
3584
3585                                                                         if (g_hash_table_lookup (mod->data.source_files, s3))
3586                                                                                 found = TRUE;
3587                                                                         g_free (s2);
3588                                                                         g_free (s3);
3589                                                                 }
3590                                                                 g_free (s);
3591                                                         }
3592                                                         g_ptr_array_free (source_file_list, TRUE);
3593                                                 }
3594                                         }
3595                                         if (!found)
3596                                                 filtered = TRUE;
3597                                 } else if (mod->kind == MOD_KIND_TYPE_NAME_ONLY && ei && ei->klass) {
3598                                         char *s;
3599
3600                                         s = mono_type_full_name (&ei->klass->byval_arg);
3601                                         if (!g_hash_table_lookup (mod->data.type_names, s))
3602                                                 filtered = TRUE;
3603                                         g_free (s);
3604                                 } else if (mod->kind == MOD_KIND_STEP) {
3605                                         if ((mod->data.filter & STEP_FILTER_STATIC_CTOR) && ji &&
3606                                                 (jinfo_get_method (ji)->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) &&
3607                                                 !strcmp (jinfo_get_method (ji)->name, ".cctor"))
3608                                                 filtered = TRUE;
3609                                         if ((mod->data.filter & STEP_FILTER_DEBUGGER_HIDDEN) && ji) {
3610                                                 MonoCustomAttrInfo *ainfo;
3611                                                 static MonoClass *klass;
3612
3613                                                 if (!klass) {
3614                                                         klass = mono_class_from_name (mono_defaults.corlib, "System.Diagnostics", "DebuggerHiddenAttribute");
3615                                                         g_assert (klass);
3616                                                 }
3617                                                 if (!ji->dbg_hidden_inited) {
3618                                                         ainfo = mono_custom_attrs_from_method (jinfo_get_method (ji));
3619                                                         if (ainfo) {
3620                                                                 if (mono_custom_attrs_has_attr (ainfo, klass))
3621                                                                         ji->dbg_hidden = TRUE;
3622                                                                 mono_custom_attrs_free (ainfo);
3623                                                         }
3624                                                         ji->dbg_hidden_inited = TRUE;
3625                                                 }
3626                                                 if (ji->dbg_hidden)
3627                                                         filtered = TRUE;
3628                                         }
3629                                         if ((mod->data.filter & STEP_FILTER_DEBUGGER_STEP_THROUGH) && ji) {
3630                                                 MonoCustomAttrInfo *ainfo;
3631                                                 static MonoClass *klass;
3632
3633                                                 if (!klass) {
3634                                                         klass = mono_class_from_name (mono_defaults.corlib, "System.Diagnostics", "DebuggerStepThroughAttribute");
3635                                                         g_assert (klass);
3636                                                 }
3637                                                 if (!ji->dbg_step_through_inited) {
3638                                                         ainfo = mono_custom_attrs_from_method (jinfo_get_method (ji));
3639                                                         if (ainfo) {
3640                                                                 if (mono_custom_attrs_has_attr (ainfo, klass))
3641                                                                         ji->dbg_step_through = TRUE;
3642                                                                 mono_custom_attrs_free (ainfo);
3643                                                         }
3644                                                         ainfo = mono_custom_attrs_from_class (jinfo_get_method (ji)->klass);
3645                                                         if (ainfo) {
3646                                                                 if (mono_custom_attrs_has_attr (ainfo, klass))
3647                                                                         ji->dbg_step_through = TRUE;
3648                                                                 mono_custom_attrs_free (ainfo);
3649                                                         }
3650                                                         ji->dbg_step_through_inited = TRUE;
3651                                                 }
3652                                                 if (ji->dbg_step_through)
3653                                                         filtered = TRUE;
3654                                         }
3655                                         if ((mod->data.filter & STEP_FILTER_DEBUGGER_NON_USER_CODE) && ji) {
3656                                                 MonoCustomAttrInfo *ainfo;
3657                                                 static MonoClass *klass;
3658
3659                                                 if (!klass) {
3660                                                         klass = mono_class_from_name (mono_defaults.corlib, "System.Diagnostics", "DebuggerNonUserCodeAttribute");
3661                                                         g_assert (klass);
3662                                                 }
3663                                                 if (!ji->dbg_non_user_code_inited) {
3664                                                         ainfo = mono_custom_attrs_from_method (jinfo_get_method (ji));
3665                                                         if (ainfo) {
3666                                                                 if (mono_custom_attrs_has_attr (ainfo, klass))
3667                                                                         ji->dbg_non_user_code = TRUE;
3668                                                                 mono_custom_attrs_free (ainfo);
3669                                                         }
3670                                                         ainfo = mono_custom_attrs_from_class (jinfo_get_method (ji)->klass);
3671                                                         if (ainfo) {
3672                                                                 if (mono_custom_attrs_has_attr (ainfo, klass))
3673                                                                         ji->dbg_non_user_code = TRUE;
3674                                                                 mono_custom_attrs_free (ainfo);
3675                                                         }
3676                                                         ji->dbg_non_user_code_inited = TRUE;
3677                                                 }
3678                                                 if (ji->dbg_non_user_code)
3679                                                         filtered = TRUE;
3680                                         }
3681                                 }
3682                         }
3683
3684                         if (!filtered) {
3685                                 *suspend_policy = MAX (*suspend_policy, req->suspend_policy);
3686                                 events = g_slist_append (events, GINT_TO_POINTER (req->id));
3687                         }
3688                 }
3689         }
3690
3691         /* Send a VM START/DEATH event by default */
3692         if (event == EVENT_KIND_VM_START)
3693                 events = g_slist_append (events, GINT_TO_POINTER (0));
3694         if (event == EVENT_KIND_VM_DEATH)
3695                 events = g_slist_append (events, GINT_TO_POINTER (0));
3696
3697         return events;
3698 }
3699
3700 static G_GNUC_UNUSED const char*
3701 event_to_string (EventKind event)
3702 {
3703         switch (event) {
3704         case EVENT_KIND_VM_START: return "VM_START";
3705         case EVENT_KIND_VM_DEATH: return "VM_DEATH";
3706         case EVENT_KIND_THREAD_START: return "THREAD_START";
3707         case EVENT_KIND_THREAD_DEATH: return "THREAD_DEATH";
3708         case EVENT_KIND_APPDOMAIN_CREATE: return "APPDOMAIN_CREATE";
3709         case EVENT_KIND_APPDOMAIN_UNLOAD: return "APPDOMAIN_UNLOAD";
3710         case EVENT_KIND_METHOD_ENTRY: return "METHOD_ENTRY";
3711         case EVENT_KIND_METHOD_EXIT: return "METHOD_EXIT";
3712         case EVENT_KIND_ASSEMBLY_LOAD: return "ASSEMBLY_LOAD";
3713         case EVENT_KIND_ASSEMBLY_UNLOAD: return "ASSEMBLY_UNLOAD";
3714         case EVENT_KIND_BREAKPOINT: return "BREAKPOINT";
3715         case EVENT_KIND_STEP: return "STEP";
3716         case EVENT_KIND_TYPE_LOAD: return "TYPE_LOAD";
3717         case EVENT_KIND_EXCEPTION: return "EXCEPTION";
3718         case EVENT_KIND_KEEPALIVE: return "KEEPALIVE";
3719         case EVENT_KIND_USER_BREAK: return "USER_BREAK";
3720         case EVENT_KIND_USER_LOG: return "USER_LOG";
3721         default:
3722                 g_assert_not_reached ();
3723                 return "";
3724         }
3725 }
3726
3727 /*
3728  * process_event:
3729  *
3730  *   Send an event to the client, suspending the vm if needed.
3731  * LOCKING: Since this can suspend the calling thread, no locks should be held
3732  * by the caller.
3733  * The EVENTS list is freed by this function.
3734  */
3735 static void
3736 process_event (EventKind event, gpointer arg, gint32 il_offset, MonoContext *ctx, GSList *events, int suspend_policy)
3737 {
3738         Buffer buf;
3739         GSList *l;
3740         MonoDomain *domain = mono_domain_get ();
3741         MonoThread *thread = NULL;
3742         MonoObject *keepalive_obj = NULL;
3743         gboolean send_success = FALSE;
3744         static int ecount;
3745         int nevents;
3746
3747         if (!inited) {
3748                 DEBUG (2, fprintf (log_file, "Debugger agent not initialized yet: dropping %s\n", event_to_string (event)));
3749                 return;
3750         }
3751
3752         if (!vm_start_event_sent && event != EVENT_KIND_VM_START) {
3753                 // FIXME: We miss those events
3754                 DEBUG (2, fprintf (log_file, "VM start event not sent yet: dropping %s\n", event_to_string (event)));
3755                 return;
3756         }
3757
3758         if (vm_death_event_sent) {
3759                 DEBUG (2, fprintf (log_file, "VM death event has been sent: dropping %s\n", event_to_string (event)));
3760                 return;
3761         }
3762
3763         if (mono_runtime_is_shutting_down () && event != EVENT_KIND_VM_DEATH) {
3764                 DEBUG (2, fprintf (log_file, "Mono runtime is shutting down: dropping %s\n", event_to_string (event)));
3765                 return;
3766         }
3767
3768         if (disconnected) {
3769                 DEBUG (2, fprintf (log_file, "Debugger client is not connected: dropping %s\n", event_to_string (event)));
3770                 return;
3771         }
3772
3773         if (event == EVENT_KIND_KEEPALIVE)
3774                 suspend_policy = SUSPEND_POLICY_NONE;
3775         else {
3776                 if (events == NULL)
3777                         return;
3778
3779                 if (agent_config.defer) {
3780                         /* Make sure the thread id is always set when doing deferred debugging */
3781                         if (debugger_thread_id == GetCurrentThreadId ()) {
3782                                 /* Don't suspend on events from the debugger thread */
3783                                 suspend_policy = SUSPEND_POLICY_NONE;
3784                                 thread = mono_thread_get_main ();
3785                         }
3786                         else thread = mono_thread_current ();
3787                 } else {
3788                         if (debugger_thread_id == GetCurrentThreadId () && event != EVENT_KIND_VM_DEATH)
3789                                 // FIXME: Send these with a NULL thread, don't suspend the current thread
3790                                 return;
3791                 }
3792         }
3793
3794         nevents = g_slist_length (events);
3795         buffer_init (&buf, 128);
3796         buffer_add_byte (&buf, suspend_policy);
3797         buffer_add_int (&buf, nevents);
3798
3799         for (l = events; l; l = l->next) {
3800                 buffer_add_byte (&buf, event); // event kind
3801                 buffer_add_int (&buf, GPOINTER_TO_INT (l->data)); // request id
3802
3803                 ecount ++;
3804
3805                 if (!thread)
3806                         thread = mono_thread_current ();
3807
3808                 if (event == EVENT_KIND_VM_START && arg != NULL)
3809                         thread = arg;
3810
3811                 buffer_add_objid (&buf, (MonoObject*)thread); // thread
3812
3813                 switch (event) {
3814                 case EVENT_KIND_THREAD_START:
3815                 case EVENT_KIND_THREAD_DEATH:
3816                         break;
3817                 case EVENT_KIND_APPDOMAIN_CREATE:
3818                 case EVENT_KIND_APPDOMAIN_UNLOAD:
3819                         buffer_add_domainid (&buf, arg);
3820                         break;
3821                 case EVENT_KIND_METHOD_ENTRY:
3822                 case EVENT_KIND_METHOD_EXIT:
3823                         buffer_add_methodid (&buf, domain, arg);
3824                         break;
3825                 case EVENT_KIND_ASSEMBLY_LOAD:
3826                         buffer_add_assemblyid (&buf, domain, arg);
3827                         break;
3828                 case EVENT_KIND_ASSEMBLY_UNLOAD: {
3829                         DebuggerTlsData *tls;
3830
3831                         /* The domain the assembly belonged to is not equal to the current domain */
3832                         tls = mono_native_tls_get_value (debugger_tls_id);
3833                         g_assert (tls);
3834                         g_assert (tls->domain_unloading);
3835
3836                         buffer_add_assemblyid (&buf, tls->domain_unloading, arg);
3837                         break;
3838                 }
3839                 case EVENT_KIND_TYPE_LOAD:
3840                         buffer_add_typeid (&buf, domain, arg);
3841                         break;
3842                 case EVENT_KIND_BREAKPOINT:
3843                 case EVENT_KIND_STEP:
3844                         buffer_add_methodid (&buf, domain, arg);
3845                         buffer_add_long (&buf, il_offset);
3846                         break;
3847                 case EVENT_KIND_VM_START:
3848                         buffer_add_domainid (&buf, mono_get_root_domain ());
3849                         break;
3850                 case EVENT_KIND_VM_DEATH:
3851                         if (CHECK_PROTOCOL_VERSION (2, 27))
3852                                 buffer_add_int (&buf, mono_environment_exitcode_get ());
3853                         break;
3854                 case EVENT_KIND_EXCEPTION: {
3855                         EventInfo *ei = arg;
3856                         buffer_add_objid (&buf, ei->exc);
3857                         /*
3858                          * We are not yet suspending, so get_objref () will not keep this object alive. So we need to do it
3859                          * later after the suspension. (#12494).
3860                          */
3861                         keepalive_obj = ei->exc;
3862                         break;
3863                 }
3864                 case EVENT_KIND_USER_BREAK:
3865                         break;
3866                 case EVENT_KIND_USER_LOG: {
3867                         EventInfo *ei = arg;
3868                         buffer_add_int (&buf, ei->level);
3869                         buffer_add_string (&buf, ei->category ? ei->category : "");
3870                         buffer_add_string (&buf, ei->message ? ei->message : "");
3871                         break;
3872                 }
3873                 case EVENT_KIND_KEEPALIVE:
3874                         suspend_policy = SUSPEND_POLICY_NONE;
3875                         break;
3876                 default:
3877                         g_assert_not_reached ();
3878                 }
3879         }
3880
3881         if (event == EVENT_KIND_VM_START) {
3882                 suspend_policy = agent_config.suspend ? SUSPEND_POLICY_ALL : SUSPEND_POLICY_NONE;
3883                 if (!agent_config.defer)
3884                         start_debugger_thread ();
3885         }
3886    
3887         if (event == EVENT_KIND_VM_DEATH) {
3888                 vm_death_event_sent = TRUE;
3889                 suspend_policy = SUSPEND_POLICY_NONE;
3890         }
3891
3892         if (mono_runtime_is_shutting_down ())
3893                 suspend_policy = SUSPEND_POLICY_NONE;
3894
3895         if (suspend_policy != SUSPEND_POLICY_NONE) {
3896                 /* 
3897                  * Save the thread context and start suspending before sending the packet,
3898                  * since we could be receiving the resume request before send_packet ()
3899                  * returns.
3900                  */
3901                 save_thread_context (ctx);
3902                 suspend_vm ();
3903
3904                 if (keepalive_obj)
3905                         /* This will keep this object alive */
3906                         get_objref (keepalive_obj);
3907         }
3908
3909         send_success = send_packet (CMD_SET_EVENT, CMD_COMPOSITE, &buf);
3910
3911         buffer_free (&buf);
3912
3913         g_slist_free (events);
3914         events = NULL;
3915
3916         if (!send_success) {
3917                 DEBUG (2, fprintf (log_file, "Sending command %s failed.\n", event_to_string (event)));
3918                 return;
3919         }
3920         
3921         if (event == EVENT_KIND_VM_START) {
3922                 vm_start_event_sent = TRUE;
3923         }
3924
3925         DEBUG (1, fprintf (log_file, "[%p] Sent %d events %s(%d), suspend=%d.\n", (gpointer)GetCurrentThreadId (), nevents, event_to_string (event), ecount, suspend_policy));
3926
3927         switch (suspend_policy) {
3928         case SUSPEND_POLICY_NONE:
3929                 break;
3930         case SUSPEND_POLICY_ALL:
3931                 suspend_current ();
3932                 break;
3933         case SUSPEND_POLICY_EVENT_THREAD:
3934                 NOT_IMPLEMENTED;
3935                 break;
3936         default:
3937                 g_assert_not_reached ();
3938         }
3939 }
3940
3941 static void
3942 process_profiler_event (EventKind event, gpointer arg)
3943 {
3944         int suspend_policy;
3945         GSList *events;
3946         EventInfo ei, *ei_arg = NULL;
3947
3948         if (event == EVENT_KIND_TYPE_LOAD) {
3949                 ei.klass = arg;
3950                 ei_arg = &ei;
3951         }
3952
3953         mono_loader_lock ();
3954         events = create_event_list (event, NULL, NULL, ei_arg, &suspend_policy);
3955         mono_loader_unlock ();
3956
3957         process_event (event, arg, 0, NULL, events, suspend_policy);
3958 }
3959
3960 static void
3961 runtime_initialized (MonoProfiler *prof)
3962 {
3963         process_profiler_event (EVENT_KIND_VM_START, mono_thread_current ());
3964         if (agent_config.defer)
3965                 start_debugger_thread ();
3966 }
3967
3968 static void
3969 runtime_shutdown (MonoProfiler *prof)
3970 {
3971         process_profiler_event (EVENT_KIND_VM_DEATH, mono_thread_current ());
3972
3973         mono_debugger_agent_cleanup ();
3974 }
3975
3976 static void
3977 thread_startup (MonoProfiler *prof, uintptr_t tid)
3978 {
3979         MonoInternalThread *thread = mono_thread_internal_current ();
3980         MonoInternalThread *old_thread;
3981         DebuggerTlsData *tls;
3982
3983         if (tid == debugger_thread_id)
3984                 return;
3985
3986         g_assert (thread->tid == tid);
3987
3988         mono_loader_lock ();
3989         old_thread = mono_g_hash_table_lookup (tid_to_thread, (gpointer)tid);
3990         mono_loader_unlock ();
3991         if (old_thread) {
3992                 if (thread == old_thread) {
3993                         /* 
3994                          * For some reason, thread_startup () might be called for the same thread
3995                          * multiple times (attach ?).
3996                          */
3997                         DEBUG (1, fprintf (log_file, "[%p] thread_start () called multiple times for %p, ignored.\n", (gpointer)tid, (gpointer)tid));
3998                         return;
3999                 } else {
4000                         /*
4001                          * thread_end () might not be called for some threads, and the tid could
4002                          * get reused.
4003                          */
4004                         DEBUG (1, fprintf (log_file, "[%p] Removing stale data for tid %p.\n", (gpointer)tid, (gpointer)tid));
4005                         mono_loader_lock ();
4006                         mono_g_hash_table_remove (thread_to_tls, old_thread);
4007                         mono_g_hash_table_remove (tid_to_thread, (gpointer)tid);
4008                         mono_g_hash_table_remove (tid_to_thread_obj, (gpointer)tid);
4009                         mono_loader_unlock ();
4010                 }
4011         }
4012
4013         tls = mono_native_tls_get_value (debugger_tls_id);
4014         g_assert (!tls);
4015         // FIXME: Free this somewhere
4016         tls = g_new0 (DebuggerTlsData, 1);
4017         MONO_GC_REGISTER_ROOT_SINGLE (tls->thread);
4018         tls->thread = thread;
4019         mono_native_tls_set_value (debugger_tls_id, tls);
4020
4021         DEBUG (1, fprintf (log_file, "[%p] Thread started, obj=%p, tls=%p.\n", (gpointer)tid, thread, tls));
4022
4023         mono_loader_lock ();
4024         mono_g_hash_table_insert (thread_to_tls, thread, tls);
4025         mono_g_hash_table_insert (tid_to_thread, (gpointer)tid, thread);
4026         mono_g_hash_table_insert (tid_to_thread_obj, (gpointer)tid, mono_thread_current ());
4027         mono_loader_unlock ();
4028
4029         process_profiler_event (EVENT_KIND_THREAD_START, thread);
4030
4031         /* 
4032          * suspend_vm () could have missed this thread, so wait for a resume.
4033          */
4034         suspend_current ();
4035 }
4036
4037 static void
4038 thread_end (MonoProfiler *prof, uintptr_t tid)
4039 {
4040         MonoInternalThread *thread;
4041         DebuggerTlsData *tls = NULL;
4042
4043         mono_loader_lock ();
4044         thread = mono_g_hash_table_lookup (tid_to_thread, (gpointer)tid);
4045         if (thread) {
4046                 mono_g_hash_table_remove (tid_to_thread_obj, (gpointer)tid);
4047                 tls = mono_g_hash_table_lookup (thread_to_tls, thread);
4048                 if (tls) {
4049                         /* FIXME: Maybe we need to free this instead, but some code can't handle that */
4050                         tls->terminated = TRUE;
4051                         /* Can't remove from tid_to_thread, as that would defeat the check in thread_start () */
4052                         MONO_GC_UNREGISTER_ROOT (tls->thread);
4053                         tls->thread = NULL;
4054                 }
4055         }
4056         mono_loader_unlock ();
4057
4058         /* We might be called for threads started before we registered the start callback */
4059         if (thread) {
4060                 DEBUG (1, fprintf (log_file, "[%p] Thread terminated, obj=%p, tls=%p.\n", (gpointer)tid, thread, tls));
4061                 process_profiler_event (EVENT_KIND_THREAD_DEATH, thread);
4062         }
4063 }
4064
4065 static void
4066 appdomain_load (MonoProfiler *prof, MonoDomain *domain, int result)
4067 {
4068         mono_loader_lock ();
4069         g_hash_table_insert (domains, domain, domain);
4070         mono_loader_unlock ();
4071
4072         process_profiler_event (EVENT_KIND_APPDOMAIN_CREATE, domain);
4073 }
4074
4075 static void
4076 appdomain_start_unload (MonoProfiler *prof, MonoDomain *domain)
4077 {
4078         DebuggerTlsData *tls;
4079
4080         /* This might be called during shutdown on the debugger thread from the CMD_VM_EXIT code */
4081         if (is_debugger_thread ())
4082                 return;
4083
4084         /*
4085          * Remember the currently unloading appdomain as it is needed to generate
4086          * proper ids for unloading assemblies.
4087          */
4088         tls = mono_native_tls_get_value (debugger_tls_id);
4089         g_assert (tls);
4090         tls->domain_unloading = domain;
4091 }
4092
4093 static void
4094 appdomain_unload (MonoProfiler *prof, MonoDomain *domain)
4095 {
4096         DebuggerTlsData *tls;
4097
4098         if (is_debugger_thread ())
4099                 return;
4100
4101         tls = mono_native_tls_get_value (debugger_tls_id);
4102         g_assert (tls);
4103         tls->domain_unloading = NULL;
4104
4105         clear_breakpoints_for_domain (domain);
4106         
4107         mono_loader_lock ();
4108         /* Invalidate each thread's frame stack */
4109         mono_g_hash_table_foreach (thread_to_tls, invalidate_each_thread, NULL);
4110         mono_loader_unlock ();
4111         
4112         process_profiler_event (EVENT_KIND_APPDOMAIN_UNLOAD, domain);
4113 }
4114
4115 /*
4116  * invalidate_each_thread:
4117  *
4118  *   A GHFunc to invalidate frames.
4119  *   value must be a DebuggerTlsData*
4120  */
4121 static void
4122 invalidate_each_thread (gpointer key, gpointer value, gpointer user_data)
4123 {
4124         invalidate_frames (value);
4125 }
4126
4127 static void
4128 assembly_load (MonoProfiler *prof, MonoAssembly *assembly, int result)
4129 {
4130         /* Sent later in jit_end () */
4131         dbg_lock ();
4132         g_ptr_array_add (pending_assembly_loads, assembly);
4133         dbg_unlock ();
4134 }
4135
4136 static void
4137 assembly_unload (MonoProfiler *prof, MonoAssembly *assembly)
4138 {
4139         process_profiler_event (EVENT_KIND_ASSEMBLY_UNLOAD, assembly);
4140
4141         clear_event_requests_for_assembly (assembly);
4142         clear_types_for_assembly (assembly);
4143 }
4144
4145 static void
4146 start_runtime_invoke (MonoProfiler *prof, MonoMethod *method)
4147 {
4148 #if defined(HOST_WIN32) && !defined(__GNUC__)
4149         gpointer stackptr = ((guint64)_AddressOfReturnAddress () - sizeof (void*));
4150 #else
4151         gpointer stackptr = __builtin_frame_address (1);
4152 #endif
4153         MonoInternalThread *thread = mono_thread_internal_current ();
4154         DebuggerTlsData *tls;
4155
4156         mono_loader_lock ();
4157         
4158         tls = mono_g_hash_table_lookup (thread_to_tls, thread);
4159         /* Could be the debugger thread with assembly/type load hooks */
4160         if (tls)
4161                 tls->invoke_addr = stackptr;
4162
4163         mono_loader_unlock ();
4164 }
4165
4166 static void
4167 end_runtime_invoke (MonoProfiler *prof, MonoMethod *method)
4168 {
4169         int i;
4170 #if defined(HOST_WIN32) && !defined(__GNUC__)
4171         gpointer stackptr = ((guint64)_AddressOfReturnAddress () - sizeof (void*));
4172 #else
4173         gpointer stackptr = __builtin_frame_address (1);
4174 #endif
4175
4176         if (!embedding || ss_req == NULL || stackptr != ss_invoke_addr || ss_req->thread != mono_thread_internal_current ())
4177                 return;
4178
4179         /*
4180          * We need to stop single stepping when exiting a runtime invoke, since if it is
4181          * a step out, it may return to native code, and thus never end.
4182          */
4183         mono_loader_lock ();
4184         ss_invoke_addr = NULL;
4185
4186         for (i = 0; i < event_requests->len; ++i) {
4187                 EventRequest *req = g_ptr_array_index (event_requests, i);
4188
4189                 if (req->event_kind == EVENT_KIND_STEP) {
4190                         ss_destroy (req->info);
4191                         g_ptr_array_remove_index_fast (event_requests, i);
4192                         g_free (req);
4193                         break;
4194                 }
4195         }
4196         mono_loader_unlock ();
4197 }
4198
4199 static void
4200 send_type_load (MonoClass *klass)
4201 {
4202         gboolean type_load = FALSE;
4203         MonoDomain *domain = mono_domain_get ();
4204         AgentDomainInfo *info = NULL;
4205
4206         mono_loader_lock ();
4207         mono_domain_lock (domain);
4208
4209         info = get_agent_domain_info (domain);
4210
4211         if (!g_hash_table_lookup (info->loaded_classes, klass)) {
4212                 type_load = TRUE;
4213                 g_hash_table_insert (info->loaded_classes, klass, klass);
4214         }
4215
4216         mono_domain_unlock (domain);
4217         mono_loader_unlock ();
4218         if (type_load)
4219                 emit_type_load (klass, klass, NULL);
4220 }
4221
4222 /*
4223  * Emit load events for all types currently loaded in the domain.
4224  * Takes the loader and domain locks.
4225  * user_data is unused.
4226  */
4227 static void
4228 send_types_for_domain (MonoDomain *domain, void *user_data)
4229 {
4230         AgentDomainInfo *info = NULL;
4231         
4232         mono_loader_lock ();
4233         mono_domain_lock (domain);
4234         info =  get_agent_domain_info (domain);
4235         g_assert (info);
4236         g_hash_table_foreach (info->loaded_classes, emit_type_load, NULL);
4237         mono_domain_unlock (domain);
4238         mono_loader_unlock ();
4239 }
4240
4241 static void
4242 jit_end (MonoProfiler *prof, MonoMethod *method, MonoJitInfo *jinfo, int result)
4243 {
4244         /*
4245          * We emit type load events when the first method of the type is JITted,
4246          * since the class load profiler callbacks might be called with the
4247          * loader lock held. They could also occur in the debugger thread.
4248          * Same for assembly load events.
4249          */
4250         while (TRUE) {
4251                 MonoAssembly *assembly = NULL;
4252
4253                 // FIXME: Maybe store this in TLS so the thread of the event is correct ?
4254                 dbg_lock ();
4255                 if (pending_assembly_loads->len > 0) {
4256                         assembly = g_ptr_array_index (pending_assembly_loads, 0);
4257                         g_ptr_array_remove_index (pending_assembly_loads, 0);
4258                 }
4259                 dbg_unlock ();
4260
4261                 if (assembly) {
4262                         process_profiler_event (EVENT_KIND_ASSEMBLY_LOAD, assembly);
4263                 } else {
4264                         break;
4265                 }
4266         }
4267
4268         send_type_load (method->klass);
4269
4270         if (!result)
4271                 add_pending_breakpoints (method, jinfo);
4272 }
4273
4274 /*
4275  * BREAKPOINTS/SINGLE STEPPING
4276  */
4277
4278 /* 
4279  * Contains information about an inserted breakpoint.
4280  */
4281 typedef struct {
4282         long il_offset, native_offset;
4283         guint8 *ip;
4284         MonoJitInfo *ji;
4285         MonoDomain *domain;
4286         SeqPoint *sp;
4287 } BreakpointInstance;
4288
4289 /*
4290  * Contains generic information about a breakpoint.
4291  */
4292 typedef struct {
4293         /* 
4294          * The method where the breakpoint is placed. Can be NULL in which case it 
4295          * is inserted into every method. This is used to implement method entry/
4296          * exit events. Can be a generic method definition, in which case the
4297          * breakpoint is inserted into every instance.
4298          */
4299         MonoMethod *method;
4300         long il_offset;
4301         EventRequest *req;
4302         /* 
4303          * A list of BreakpointInstance structures describing where the breakpoint
4304          * was inserted. There could be more than one because of 
4305          * generics/appdomains/method entry/exit.
4306          */
4307         GPtrArray *children;
4308 } MonoBreakpoint;
4309
4310 /* List of breakpoints */
4311 static GPtrArray *breakpoints;
4312 /* Maps breakpoint locations to the number of breakpoints at that location */
4313 static GHashTable *bp_locs;
4314
4315 static void
4316 breakpoints_init (void)
4317 {
4318         breakpoints = g_ptr_array_new ();
4319         bp_locs = g_hash_table_new (NULL, NULL);
4320 }       
4321
4322 /*
4323  * insert_breakpoint:
4324  *
4325  *   Insert the breakpoint described by BP into the method described by
4326  * JI.
4327  */
4328 static void
4329 insert_breakpoint (MonoSeqPointInfo *seq_points, MonoDomain *domain, MonoJitInfo *ji, MonoBreakpoint *bp, MonoError *error)
4330 {
4331         int i, count;
4332         BreakpointInstance *inst;
4333         SeqPoint *sp = NULL;
4334
4335         if (error)
4336                 mono_error_init (error);
4337
4338         for (i = 0; i < seq_points->len; ++i) {
4339                 sp = &seq_points->seq_points [i];
4340
4341                 if (sp->il_offset == bp->il_offset)
4342                         break;
4343         }
4344
4345         if (i == seq_points->len) {
4346                 /*
4347                  * The set of IL offsets with seq points doesn't completely match the
4348                  * info returned by CMD_METHOD_GET_DEBUG_INFO (#407).
4349                  */
4350                 for (i = 0; i < seq_points->len; ++i) {
4351                         sp = &seq_points->seq_points [i];
4352
4353                         if (sp->il_offset != METHOD_ENTRY_IL_OFFSET && sp->il_offset != METHOD_EXIT_IL_OFFSET && sp->il_offset + 1 == bp->il_offset)
4354                                 break;
4355                 }
4356         }
4357
4358         if (i == seq_points->len) {
4359                 char *s = g_strdup_printf ("Unable to insert breakpoint at %s:%d, seq_points=%d\n", mono_method_full_name (jinfo_get_method (ji), TRUE), bp->il_offset, seq_points->len);
4360
4361                 for (i = 0; i < seq_points->len; ++i)
4362                         DEBUG (1, fprintf (log_file, "%d\n", seq_points->seq_points [i].il_offset));
4363
4364                 if (error) {
4365                         mono_error_set_error (error, MONO_ERROR_GENERIC, "%s", s);
4366                         g_warning ("%s", s);
4367                         g_free (s);
4368                         return;
4369                 } else {
4370                         g_warning ("%s", s);
4371                         g_free (s);
4372                         return;
4373                 }
4374         }
4375
4376         inst = g_new0 (BreakpointInstance, 1);
4377         inst->sp = sp;
4378         inst->native_offset = sp->native_offset;
4379         inst->ip = (guint8*)ji->code_start + sp->native_offset;
4380         inst->ji = ji;
4381         inst->domain = domain;
4382
4383         mono_loader_lock ();
4384
4385         g_ptr_array_add (bp->children, inst);
4386
4387         mono_loader_unlock ();
4388
4389         dbg_lock ();
4390         count = GPOINTER_TO_INT (g_hash_table_lookup (bp_locs, inst->ip));
4391         g_hash_table_insert (bp_locs, inst->ip, GINT_TO_POINTER (count + 1));
4392         dbg_unlock ();
4393
4394         if (sp->native_offset == SEQ_POINT_NATIVE_OFFSET_DEAD_CODE) {
4395                 DEBUG (1, fprintf (log_file, "[dbg] Attempting to insert seq point at dead IL offset %d, ignoring.\n", (int)bp->il_offset));
4396         } else if (count == 0) {
4397 #ifdef MONO_ARCH_SOFT_DEBUG_SUPPORTED
4398                 mono_arch_set_breakpoint (ji, inst->ip);
4399 #else
4400                 NOT_IMPLEMENTED;
4401 #endif
4402         }
4403
4404         DEBUG(1, fprintf (log_file, "[dbg] Inserted breakpoint at %s:0x%x [%p](%d).\n", mono_method_full_name (jinfo_get_method (ji), TRUE), (int)sp->il_offset, inst->ip, count));
4405 }
4406
4407 static void
4408 remove_breakpoint (BreakpointInstance *inst)
4409 {
4410 #ifdef MONO_ARCH_SOFT_DEBUG_SUPPORTED
4411         int count;
4412         MonoJitInfo *ji = inst->ji;
4413         guint8 *ip = inst->ip;
4414
4415         dbg_lock ();
4416         count = GPOINTER_TO_INT (g_hash_table_lookup (bp_locs, ip));
4417         g_hash_table_insert (bp_locs, ip, GINT_TO_POINTER (count - 1));
4418         dbg_unlock ();
4419
4420         g_assert (count > 0);
4421
4422         if (count == 1 && inst->native_offset != SEQ_POINT_NATIVE_OFFSET_DEAD_CODE) {
4423                 mono_arch_clear_breakpoint (ji, ip);
4424                 DEBUG(1, fprintf (log_file, "[dbg] Clear breakpoint at %s [%p].\n", mono_method_full_name (jinfo_get_method (ji), TRUE), ip));
4425         }
4426 #else
4427         NOT_IMPLEMENTED;
4428 #endif
4429 }       
4430
4431 static inline gboolean
4432 bp_matches_method (MonoBreakpoint *bp, MonoMethod *method)
4433 {
4434         int i;
4435
4436         if (!bp->method)
4437                 return TRUE;
4438         if (method == bp->method)
4439                 return TRUE;
4440         if (method->is_inflated && ((MonoMethodInflated*)method)->declaring == bp->method)
4441                 return TRUE;
4442
4443         if (bp->method->is_inflated && method->is_inflated) {
4444                 MonoMethodInflated *bpimethod = (MonoMethodInflated*)bp->method;
4445                 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4446
4447                 /* Open generic methods should match closed generic methods of the same class */
4448                 if (bpimethod->declaring == imethod->declaring && bpimethod->context.class_inst == imethod->context.class_inst && bpimethod->context.method_inst && bpimethod->context.method_inst->is_open) {
4449                         for (i = 0; i < bpimethod->context.method_inst->type_argc; ++i) {
4450                                 MonoType *t1 = bpimethod->context.method_inst->type_argv [i];
4451
4452                                 /* FIXME: Handle !mvar */
4453                                 if (t1->type != MONO_TYPE_MVAR)
4454                                         return FALSE;
4455                         }
4456                         return TRUE;
4457                 }
4458         }
4459
4460         return FALSE;
4461 }
4462
4463 /*
4464  * add_pending_breakpoints:
4465  *
4466  *   Insert pending breakpoints into the newly JITted method METHOD.
4467  */
4468 static void
4469 add_pending_breakpoints (MonoMethod *method, MonoJitInfo *ji)
4470 {
4471         int i, j;
4472         MonoSeqPointInfo *seq_points;
4473         MonoDomain *domain;
4474         MonoMethod *jmethod;
4475
4476         if (!breakpoints)
4477                 return;
4478
4479         domain = mono_domain_get ();
4480
4481         mono_loader_lock ();
4482
4483         for (i = 0; i < breakpoints->len; ++i) {
4484                 MonoBreakpoint *bp = g_ptr_array_index (breakpoints, i);
4485                 gboolean found = FALSE;
4486
4487                 if (!bp_matches_method (bp, method))
4488                         continue;
4489
4490                 for (j = 0; j < bp->children->len; ++j) {
4491                         BreakpointInstance *inst = g_ptr_array_index (bp->children, j);
4492
4493                         if (inst->ji == ji)
4494                                 found = TRUE;
4495                 }
4496
4497                 if (!found) {
4498                         jmethod = jinfo_get_method (ji);
4499                         mono_domain_lock (domain);
4500                         seq_points = g_hash_table_lookup (domain_jit_info (domain)->seq_points, jmethod);
4501                         if (!seq_points && jmethod->is_inflated)
4502                                 seq_points = g_hash_table_lookup (domain_jit_info (domain)->seq_points, mono_method_get_declaring_generic_method (jmethod));
4503                         mono_domain_unlock (domain);
4504                         if (!seq_points)
4505                                 /* Could be AOT code */
4506                                 continue;
4507                         g_assert (seq_points);
4508
4509                         insert_breakpoint (seq_points, domain, ji, bp, NULL);
4510                 }
4511         }
4512
4513         mono_loader_unlock ();
4514 }
4515
4516 static void
4517 set_bp_in_method (MonoDomain *domain, MonoMethod *method, MonoSeqPointInfo *seq_points, MonoBreakpoint *bp, MonoError *error)
4518 {
4519         gpointer code;
4520         MonoJitInfo *ji;
4521
4522         if (error)
4523                 mono_error_init (error);
4524
4525         code = mono_jit_find_compiled_method_with_jit_info (domain, method, &ji);
4526         if (!code) {
4527                 /* Might be AOTed code */
4528                 code = mono_aot_get_method (domain, method);
4529                 g_assert (code);
4530                 ji = mono_jit_info_table_find (domain, code);
4531                 g_assert (ji);
4532         }
4533         g_assert (code);
4534
4535         insert_breakpoint (seq_points, domain, ji, bp, error);
4536 }
4537
4538 static void
4539 clear_breakpoint (MonoBreakpoint *bp);
4540
4541 /*
4542  * set_breakpoint:
4543  *
4544  *   Set a breakpoint at IL_OFFSET in METHOD.
4545  * METHOD can be NULL, in which case a breakpoint is placed in all methods.
4546  * METHOD can also be a generic method definition, in which case a breakpoint
4547  * is placed in all instances of the method.
4548  * If ERROR is non-NULL, then it is set and NULL is returnd if some breakpoints couldn't be
4549  * inserted.
4550  */
4551 static MonoBreakpoint*
4552 set_breakpoint (MonoMethod *method, long il_offset, EventRequest *req, MonoError *error)
4553 {
4554         MonoBreakpoint *bp;
4555         GHashTableIter iter, iter2;
4556         MonoDomain *domain;
4557         MonoMethod *m;
4558         MonoSeqPointInfo *seq_points;
4559
4560         if (error)
4561                 mono_error_init (error);
4562
4563         // FIXME:
4564         // - suspend/resume the vm to prevent code patching problems
4565         // - multiple breakpoints on the same location
4566         // - dynamic methods
4567         // - races
4568
4569         bp = g_new0 (MonoBreakpoint, 1);
4570         bp->method = method;
4571         bp->il_offset = il_offset;
4572         bp->req = req;
4573         bp->children = g_ptr_array_new ();
4574
4575         DEBUG(1, fprintf (log_file, "[dbg] Setting %sbreakpoint at %s:0x%x.\n", (req->event_kind == EVENT_KIND_STEP) ? "single step " : "", method ? mono_method_full_name (method, TRUE) : "<all>", (int)il_offset));
4576
4577         mono_loader_lock ();
4578
4579         g_hash_table_iter_init (&iter, domains);
4580         while (g_hash_table_iter_next (&iter, (void**)&domain, NULL)) {
4581                 mono_domain_lock (domain);
4582
4583                 g_hash_table_iter_init (&iter2, domain_jit_info (domain)->seq_points);
4584                 while (g_hash_table_iter_next (&iter2, (void**)&m, (void**)&seq_points)) {
4585                         if (bp_matches_method (bp, m))
4586                                 set_bp_in_method (domain, m, seq_points, bp, error);
4587                 }
4588
4589                 mono_domain_unlock (domain);
4590         }
4591
4592         mono_loader_unlock ();
4593
4594         mono_loader_lock ();
4595         g_ptr_array_add (breakpoints, bp);
4596         mono_loader_unlock ();
4597
4598         if (error && !mono_error_ok (error)) {
4599                 clear_breakpoint (bp);
4600                 return NULL;
4601         }
4602
4603         return bp;
4604 }
4605
4606 static void
4607 clear_breakpoint (MonoBreakpoint *bp)
4608 {
4609         int i;
4610
4611         // FIXME: locking, races
4612         for (i = 0; i < bp->children->len; ++i) {
4613                 BreakpointInstance *inst = g_ptr_array_index (bp->children, i);
4614
4615                 remove_breakpoint (inst);
4616
4617                 g_free (inst);
4618         }
4619
4620         mono_loader_lock ();
4621         g_ptr_array_remove (breakpoints, bp);
4622         mono_loader_unlock ();
4623
4624         g_ptr_array_free (bp->children, TRUE);
4625         g_free (bp);
4626 }
4627
4628 static void
4629 breakpoints_cleanup (void)
4630 {
4631         int i;
4632
4633         mono_loader_lock ();
4634         i = 0;
4635         while (i < event_requests->len) {
4636                 EventRequest *req = g_ptr_array_index (event_requests, i);
4637
4638                 if (req->event_kind == EVENT_KIND_BREAKPOINT) {
4639                         clear_breakpoint (req->info);
4640                         g_ptr_array_remove_index_fast (event_requests, i);
4641                         g_free (req);
4642                 } else {
4643                         i ++;
4644                 }
4645         }
4646
4647         for (i = 0; i < breakpoints->len; ++i)
4648                 g_free (g_ptr_array_index (breakpoints, i));
4649
4650         g_ptr_array_free (breakpoints, TRUE);
4651         g_hash_table_destroy (bp_locs);
4652
4653         breakpoints = NULL;
4654         bp_locs = NULL;
4655
4656         mono_loader_unlock ();
4657 }
4658
4659 /*
4660  * clear_breakpoints_for_domain:
4661  *
4662  *   Clear breakpoint instances which reference DOMAIN.
4663  */
4664 static void
4665 clear_breakpoints_for_domain (MonoDomain *domain)
4666 {
4667         int i, j;
4668
4669         /* This could be called after shutdown */
4670         if (!breakpoints)
4671                 return;
4672
4673         mono_loader_lock ();
4674         for (i = 0; i < breakpoints->len; ++i) {
4675                 MonoBreakpoint *bp = g_ptr_array_index (breakpoints, i);
4676
4677                 j = 0;
4678                 while (j < bp->children->len) {
4679                         BreakpointInstance *inst = g_ptr_array_index (bp->children, j);
4680
4681                         if (inst->domain == domain) {
4682                                 remove_breakpoint (inst);
4683
4684                                 g_free (inst);
4685
4686                                 g_ptr_array_remove_index_fast (bp->children, j);
4687                         } else {
4688                                 j ++;
4689                         }
4690                 }
4691         }
4692         mono_loader_unlock ();
4693 }
4694
4695 /*
4696  * ss_update:
4697  *
4698  * Return FALSE if single stepping needs to continue.
4699  */
4700 static gboolean
4701 ss_update (SingleStepReq *req, MonoJitInfo *ji, SeqPoint *sp, DebuggerTlsData *tls, MonoContext *ctx)
4702 {
4703         MonoDebugMethodInfo *minfo;
4704         MonoDebugSourceLocation *loc = NULL;
4705         gboolean hit = TRUE;
4706         MonoMethod *method;
4707
4708         if (req->depth == STEP_DEPTH_OVER && (sp->flags & MONO_SEQ_POINT_FLAG_NONEMPTY_STACK)) {
4709                 /*
4710                  * These seq points are inserted by the JIT after calls, step over needs to skip them.
4711                  */
4712                 DEBUG (1, fprintf (log_file, "[%p] Seq point at nonempty stack %x while stepping over, continuing single stepping.\n", (gpointer)GetCurrentThreadId (), sp->il_offset));
4713                 return FALSE;
4714         }
4715
4716         if (req->depth == STEP_DEPTH_OVER && hit) {
4717                 if (!tls->context.valid)
4718                         mono_thread_state_init_from_monoctx (&tls->context, ctx);
4719                 compute_frame_info (tls->thread, tls);
4720                 if (req->nframes && tls->frame_count && tls->frame_count > req->nframes) {
4721                         /* Hit the breakpoint in a recursive call */
4722                         DEBUG (1, fprintf (log_file, "[%p] Breakpoint at lower frame while stepping over, continuing single stepping.\n", (gpointer)GetCurrentThreadId ()));
4723                         return FALSE;
4724                 }
4725         }
4726
4727         if (req->size != STEP_SIZE_LINE)
4728                 return TRUE;
4729
4730         /* Have to check whenever a different source line was reached */
4731         method = jinfo_get_method (ji);
4732         minfo = mono_debug_lookup_method (method);
4733
4734         if (minfo)
4735                 loc = mono_debug_symfile_lookup_location (minfo, sp->il_offset);
4736
4737         if (!loc || (loc && method == ss_req->last_method && loc->row == ss_req->last_line)) {
4738                 /* Have to continue single stepping */
4739                 if (!loc)
4740                         DEBUG(1, fprintf (log_file, "[%p] No line number info for il offset %x, continuing single stepping.\n", (gpointer)GetCurrentThreadId (), sp->il_offset));
4741                 else
4742                         DEBUG(1, fprintf (log_file, "[%p] Same source line (%d), continuing single stepping.\n", (gpointer)GetCurrentThreadId (), loc->row));
4743                 hit = FALSE;
4744         }
4745                                 
4746         if (loc) {
4747                 ss_req->last_method = method;
4748                 ss_req->last_line = loc->row;
4749                 mono_debug_free_source_location (loc);
4750         }
4751
4752         return hit;
4753 }
4754
4755 static gboolean
4756 breakpoint_matches_assembly (MonoBreakpoint *bp, MonoAssembly *assembly)
4757 {
4758         return bp->method && bp->method->klass->image->assembly == assembly;
4759 }
4760
4761 static void
4762 process_breakpoint_inner (DebuggerTlsData *tls)
4763 {
4764         MonoJitInfo *ji;
4765         guint8 *ip;
4766         int i, j, suspend_policy;
4767         guint32 native_offset;
4768         MonoBreakpoint *bp;
4769         BreakpointInstance *inst;
4770         GPtrArray *bp_reqs, *ss_reqs_orig, *ss_reqs;
4771         GSList *bp_events = NULL, *ss_events = NULL, *enter_leave_events = NULL;
4772         EventKind kind = EVENT_KIND_BREAKPOINT;
4773         MonoContext *ctx = &tls->restore_ctx;
4774         MonoMethod *method;
4775         MonoSeqPointInfo *info;
4776         SeqPoint *sp;
4777
4778         // FIXME: Speed this up
4779
4780         ip = MONO_CONTEXT_GET_IP (ctx);
4781         ji = mini_jit_info_table_find (mono_domain_get (), (char*)ip, NULL);
4782         g_assert (ji);
4783         method = jinfo_get_method (ji);
4784
4785         /* Compute the native offset of the breakpoint from the ip */
4786         native_offset = ip - (guint8*)ji->code_start;   
4787
4788         /* 
4789          * Skip the instruction causing the breakpoint signal.
4790          */
4791         mono_arch_skip_breakpoint (ctx, ji);
4792
4793         if (method->wrapper_type || tls->disable_breakpoints)
4794                 return;
4795
4796         bp_reqs = g_ptr_array_new ();
4797         ss_reqs = g_ptr_array_new ();
4798         ss_reqs_orig = g_ptr_array_new ();
4799
4800         mono_loader_lock ();
4801
4802         /*
4803          * The ip points to the instruction causing the breakpoint event, which is after
4804          * the offset recorded in the seq point map, so find the prev seq point before ip.
4805          */
4806         sp = find_prev_seq_point_for_native_offset (mono_domain_get (), method, native_offset, &info);
4807         if (!sp)
4808                 no_seq_points_found (method);
4809         g_assert (sp);
4810
4811         DEBUG(1, fprintf (log_file, "[%p] Breakpoint hit, method=%s, ip=%p, offset=0x%x, sp il offset=0x%x.\n", (gpointer)GetCurrentThreadId (), method->name, ip, native_offset, sp ? sp->il_offset : -1));
4812
4813         bp = NULL;
4814         for (i = 0; i < breakpoints->len; ++i) {
4815                 bp = g_ptr_array_index (breakpoints, i);
4816
4817                 if (!bp->method)
4818                         continue;
4819
4820                 for (j = 0; j < bp->children->len; ++j) {
4821                         inst = g_ptr_array_index (bp->children, j);
4822                         if (inst->ji == ji && inst->sp == sp) {
4823                                 if (bp->req->event_kind == EVENT_KIND_STEP) {
4824                                         g_ptr_array_add (ss_reqs_orig, bp->req);
4825                                 } else {
4826                                         g_ptr_array_add (bp_reqs, bp->req);
4827                                 }
4828                         }
4829                 }
4830         }
4831         if (bp_reqs->len == 0 && ss_reqs_orig->len == 0) {
4832                 /* Maybe a method entry/exit event */
4833                 if (sp->il_offset == METHOD_ENTRY_IL_OFFSET)
4834                         kind = EVENT_KIND_METHOD_ENTRY;
4835                 else if (sp->il_offset == METHOD_EXIT_IL_OFFSET)
4836                         kind = EVENT_KIND_METHOD_EXIT;
4837         }
4838
4839         /* Process single step requests */
4840         for (i = 0; i < ss_reqs_orig->len; ++i) {
4841                 EventRequest *req = g_ptr_array_index (ss_reqs_orig, i);
4842                 SingleStepReq *ss_req = req->info;
4843                 gboolean hit;
4844
4845                 if (mono_thread_internal_current () != ss_req->thread)
4846                         continue;
4847
4848                 hit = ss_update (ss_req, ji, sp, tls, ctx);
4849                 if (hit)
4850                         g_ptr_array_add (ss_reqs, req);
4851
4852                 /* Start single stepping again from the current sequence point */
4853                 ss_start (ss_req, method, sp, info, ctx, tls, FALSE);
4854         }
4855         
4856         if (ss_reqs->len > 0)
4857                 ss_events = create_event_list (EVENT_KIND_STEP, ss_reqs, ji, NULL, &suspend_policy);
4858         if (bp_reqs->len > 0)
4859                 bp_events = create_event_list (EVENT_KIND_BREAKPOINT, bp_reqs, ji, NULL, &suspend_policy);
4860         if (kind != EVENT_KIND_BREAKPOINT)
4861                 enter_leave_events = create_event_list (kind, NULL, ji, NULL, &suspend_policy);
4862
4863         mono_loader_unlock ();
4864
4865         g_ptr_array_free (bp_reqs, TRUE);
4866         g_ptr_array_free (ss_reqs, TRUE);
4867
4868         /* 
4869          * FIXME: The first event will suspend, so the second will only be sent after the
4870          * resume.
4871          */
4872         if (ss_events)
4873                 process_event (EVENT_KIND_STEP, method, 0, ctx, ss_events, suspend_policy);
4874         if (bp_events)
4875                 process_event (kind, method, 0, ctx, bp_events, suspend_policy);
4876         if (enter_leave_events)
4877                 process_event (kind, method, 0, ctx, enter_leave_events, suspend_policy);
4878 }
4879
4880 /* Process a breakpoint/single step event after resuming from a signal handler */
4881 static void
4882 process_signal_event (void (*func) (DebuggerTlsData*))
4883 {
4884         DebuggerTlsData *tls;
4885         MonoContext orig_restore_ctx, ctx;
4886
4887         tls = mono_native_tls_get_value (debugger_tls_id);
4888         /* Have to save/restore the restore_ctx as we can be called recursively during invokes etc. */
4889         memcpy (&orig_restore_ctx, &tls->restore_ctx, sizeof (MonoContext));
4890         memcpy (&tls->restore_ctx, &tls->handler_ctx, sizeof (MonoContext));
4891
4892         func (tls);
4893
4894         /* This is called when resuming from a signal handler, so it shouldn't return */
4895         memcpy (&ctx, &tls->restore_ctx, sizeof (MonoContext));
4896         memcpy (&tls->restore_ctx, &orig_restore_ctx, sizeof (MonoContext));
4897         mono_restore_context (&ctx);
4898         g_assert_not_reached ();
4899 }
4900
4901 static void
4902 process_breakpoint (void)
4903 {
4904         process_signal_event (process_breakpoint_inner);
4905 }
4906
4907 static void
4908 resume_from_signal_handler (void *sigctx, void *func)
4909 {
4910         DebuggerTlsData *tls;
4911         MonoContext ctx;
4912
4913         /* Save the original context in TLS */
4914         // FIXME: This might not work on an altstack ?
4915         tls = mono_native_tls_get_value (debugger_tls_id);
4916         if (!tls)
4917                 fprintf (stderr, "Thread %p is not attached to the JIT.\n", (gpointer)GetCurrentThreadId ());
4918         g_assert (tls);
4919
4920         // FIXME: MonoContext usually doesn't include the fp registers, so these are 
4921         // clobbered by a single step/breakpoint event. If this turns out to be a problem,
4922         // clob:c could be added to op_seq_point.
4923
4924         mono_sigctx_to_monoctx (sigctx, &ctx);
4925         memcpy (&tls->handler_ctx, &ctx, sizeof (MonoContext));
4926 #ifdef MONO_ARCH_HAVE_SETUP_RESUME_FROM_SIGNAL_HANDLER_CTX
4927         mono_arch_setup_resume_sighandler_ctx (&ctx, func);
4928 #else
4929         MONO_CONTEXT_SET_IP (&ctx, func);
4930 #endif
4931         mono_monoctx_to_sigctx (&ctx, sigctx);
4932
4933 #ifdef PPC_USES_FUNCTION_DESCRIPTOR
4934         mono_ppc_set_func_into_sigctx (sigctx, func);
4935 #endif
4936 }
4937
4938 void
4939 mono_debugger_agent_breakpoint_hit (void *sigctx)
4940 {
4941         /*
4942          * We are called from a signal handler, and running code there causes all kinds of
4943          * problems, like the original signal is disabled, libgc can't handle altstack, etc.
4944          * So set up the signal context to return to the real breakpoint handler function.
4945          */
4946         resume_from_signal_handler (sigctx, process_breakpoint);
4947 }
4948
4949 static gboolean
4950 user_break_cb (StackFrameInfo *frame, MonoContext *ctx, gpointer data)
4951 {
4952         if (frame->managed) {
4953                 *(MonoContext*)data = *ctx;
4954
4955                 return TRUE;
4956         } else {
4957                 return FALSE;
4958         }
4959 }
4960
4961 /*
4962  * Called by System.Diagnostics.Debugger:Break ().
4963  */
4964 void
4965 mono_debugger_agent_user_break (void)
4966 {
4967         if (agent_config.enabled) {
4968                 MonoContext ctx;
4969                 int suspend_policy;
4970                 GSList *events;
4971
4972                 /* Obtain a context */
4973                 MONO_CONTEXT_SET_IP (&ctx, NULL);
4974                 mono_walk_stack_with_ctx (user_break_cb, NULL, 0, &ctx);
4975                 g_assert (MONO_CONTEXT_GET_IP (&ctx) != NULL);
4976
4977                 mono_loader_lock ();
4978                 events = create_event_list (EVENT_KIND_USER_BREAK, NULL, NULL, NULL, &suspend_policy);
4979                 mono_loader_unlock ();
4980
4981                 process_event (EVENT_KIND_USER_BREAK, NULL, 0, &ctx, events, suspend_policy);
4982         } else {
4983                 G_BREAKPOINT ();
4984         }
4985 }
4986
4987 static const char*
4988 ss_depth_to_string (StepDepth depth)
4989 {
4990         switch (depth) {
4991         case STEP_DEPTH_OVER:
4992                 return "over";
4993         case STEP_DEPTH_OUT:
4994                 return "out";
4995         case STEP_DEPTH_INTO:
4996                 return "into";
4997         default:
4998                 g_assert_not_reached ();
4999                 return NULL;
5000         }
5001 }
5002
5003 static void
5004 process_single_step_inner (DebuggerTlsData *tls)
5005 {
5006         MonoJitInfo *ji;
5007         guint8 *ip;
5008         GPtrArray *reqs;
5009         int il_offset, suspend_policy;
5010         MonoDomain *domain;
5011         GSList *events;
5012         MonoContext *ctx = &tls->restore_ctx;
5013         MonoMethod *method;
5014         SeqPoint *sp;
5015         MonoSeqPointInfo *info;
5016
5017         ip = MONO_CONTEXT_GET_IP (ctx);
5018
5019         /* Skip the instruction causing the single step */
5020         mono_arch_skip_single_step (ctx);
5021
5022         if (suspend_count > 0) {
5023                 process_suspend (tls, ctx);
5024                 return;
5025         }
5026
5027         if (!ss_req)
5028                 // FIXME: A suspend race
5029                 return;
5030
5031         if (mono_thread_internal_current () != ss_req->thread)
5032                 return;
5033
5034         if (log_level > 0) {
5035                 ji = mini_jit_info_table_find (mono_domain_get (), (char*)ip, &domain);
5036
5037                 DEBUG (1, fprintf (log_file, "[%p] Single step event (depth=%s) at %s (%p), sp %p, last sp %p\n", (gpointer)GetCurrentThreadId (), ss_depth_to_string (ss_req->depth), mono_method_full_name (jinfo_get_method (ji), TRUE), MONO_CONTEXT_GET_IP (ctx), MONO_CONTEXT_GET_SP (ctx), ss_req->last_sp));
5038         }
5039
5040         ji = mini_jit_info_table_find (mono_domain_get (), (char*)ip, &domain);
5041         g_assert (ji);
5042         method = jinfo_get_method (ji);
5043         g_assert (method);
5044
5045         if (method->wrapper_type && method->wrapper_type != MONO_WRAPPER_DYNAMIC_METHOD)
5046                 return;
5047
5048         /* 
5049          * FIXME:
5050          * Stopping in memset makes half-initialized vtypes visible.
5051          * Stopping in memcpy makes half-copied vtypes visible.
5052          */
5053         if (method->klass == mono_defaults.string_class && (!strcmp (method->name, "memset") || strstr (method->name, "memcpy")))
5054                 return;
5055
5056         /*
5057          * The ip points to the instruction causing the single step event, which is before
5058          * the offset recorded in the seq point map, so find the next seq point after ip.
5059          */
5060         sp = find_next_seq_point_for_native_offset (domain, method, (guint8*)ip - (guint8*)ji->code_start, &info);
5061         if (!sp)
5062                 return;
5063         il_offset = sp->il_offset;
5064
5065         if (!ss_update (ss_req, ji, sp, tls, ctx))
5066                 return;
5067
5068         /* Start single stepping again from the current sequence point */
5069         ss_start (ss_req, method, sp, info, ctx, tls, FALSE);
5070
5071         if ((ss_req->filter & STEP_FILTER_STATIC_CTOR) &&
5072                 (method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) &&
5073                 !strcmp (method->name, ".cctor"))
5074                 return;
5075
5076         // FIXME: Has to lock earlier
5077
5078         reqs = g_ptr_array_new ();
5079
5080         mono_loader_lock ();
5081
5082         g_ptr_array_add (reqs, ss_req->req);
5083
5084         events = create_event_list (EVENT_KIND_STEP, reqs, ji, NULL, &suspend_policy);
5085
5086         g_ptr_array_free (reqs, TRUE);
5087
5088         mono_loader_unlock ();
5089
5090         process_event (EVENT_KIND_STEP, jinfo_get_method (ji), il_offset, ctx, events, suspend_policy);
5091 }
5092
5093 static void
5094 process_single_step (void)
5095 {
5096         process_signal_event (process_single_step_inner);
5097 }
5098
5099 /*
5100  * mono_debugger_agent_single_step_event:
5101  *
5102  *   Called from a signal handler to handle a single step event.
5103  */
5104 void
5105 mono_debugger_agent_single_step_event (void *sigctx)
5106 {
5107         /* Resume to process_single_step through the signal context */
5108
5109         // FIXME: Since step out/over is implemented using step in, the step in case should
5110         // be as fast as possible. Move the relevant code from process_single_step_inner ()
5111         // here
5112
5113         if (GetCurrentThreadId () == debugger_thread_id) {
5114                 /* 
5115                  * This could happen despite our best effors when the runtime calls 
5116                  * assembly/type resolve hooks.
5117                  * FIXME: Breakpoints too.
5118                  */
5119                 MonoContext ctx;
5120
5121                 mono_sigctx_to_monoctx (sigctx, &ctx);
5122                 mono_arch_skip_single_step (&ctx);
5123                 mono_monoctx_to_sigctx (&ctx, sigctx);
5124                 return;
5125         }
5126
5127         resume_from_signal_handler (sigctx, process_single_step);
5128 }
5129
5130 void
5131 debugger_agent_single_step_from_context (MonoContext *ctx)
5132 {
5133         DebuggerTlsData *tls;
5134         MonoContext orig_restore_ctx;
5135
5136         tls = mono_native_tls_get_value (debugger_tls_id);
5137         g_assert (tls);
5138
5139         /* Have to save/restore the restore_ctx as we can be called recursively during invokes etc. */
5140         memcpy (&orig_restore_ctx, &tls->restore_ctx, sizeof (MonoContext));
5141         memcpy (&tls->restore_ctx, ctx, sizeof (MonoContext));
5142
5143         process_single_step_inner (tls);
5144
5145         memcpy (ctx, &tls->restore_ctx, sizeof (MonoContext));
5146         memcpy (&tls->restore_ctx, &orig_restore_ctx, sizeof (MonoContext));
5147 }
5148
5149 void
5150 debugger_agent_breakpoint_from_context (MonoContext *ctx)
5151 {
5152         DebuggerTlsData *tls;
5153         MonoContext orig_restore_ctx;
5154
5155         tls = mono_native_tls_get_value (debugger_tls_id);
5156         g_assert (tls);
5157         memcpy (&orig_restore_ctx, &tls->restore_ctx, sizeof (MonoContext));
5158         memcpy (&tls->restore_ctx, ctx, sizeof (MonoContext));
5159
5160         process_breakpoint_inner (tls);
5161
5162         memcpy (ctx, &tls->restore_ctx, sizeof (MonoContext));
5163         memcpy (&tls->restore_ctx, &orig_restore_ctx, sizeof (MonoContext));
5164 }
5165
5166 /*
5167  * start_single_stepping:
5168  *
5169  *   Turn on single stepping. Can be called multiple times, for example,
5170  * by a single step event request + a suspend.
5171  */
5172 static void
5173 start_single_stepping (void)
5174 {
5175 #ifdef MONO_ARCH_SOFT_DEBUG_SUPPORTED
5176         int val = InterlockedIncrement (&ss_count);
5177
5178         if (val == 1)
5179                 mono_arch_start_single_stepping ();
5180
5181         if (ss_req != NULL && ss_invoke_addr == NULL) {
5182                 DebuggerTlsData *tls;
5183         
5184                 mono_loader_lock ();
5185         
5186                 tls = mono_g_hash_table_lookup (thread_to_tls, ss_req->thread);
5187                 ss_invoke_addr = tls->invoke_addr;
5188                 
5189                 mono_loader_unlock ();
5190         }
5191 #else
5192         g_assert_not_reached ();
5193 #endif
5194 }
5195
5196 static void
5197 stop_single_stepping (void)
5198 {
5199 #ifdef MONO_ARCH_SOFT_DEBUG_SUPPORTED
5200         int val = InterlockedDecrement (&ss_count);
5201
5202         if (val == 0)
5203                 mono_arch_stop_single_stepping ();
5204         if (ss_req != NULL)
5205                 ss_invoke_addr = NULL;
5206 #else
5207         g_assert_not_reached ();
5208 #endif
5209 }
5210
5211 /*
5212  * ss_stop:
5213  *
5214  *   Stop the single stepping operation given by SS_REQ.
5215  */
5216 static void
5217 ss_stop (SingleStepReq *ss_req)
5218 {
5219         if (ss_req->bps) {
5220                 GSList *l;
5221
5222                 for (l = ss_req->bps; l; l = l->next) {
5223                         clear_breakpoint (l->data);
5224                 }
5225                 g_slist_free (ss_req->bps);
5226                 ss_req->bps = NULL;
5227         }
5228
5229         if (ss_req->global) {
5230                 stop_single_stepping ();
5231                 ss_req->global = FALSE;
5232         }
5233 }
5234
5235 /*
5236  * ss_start:
5237  *
5238  *   Start the single stepping operation given by SS_REQ from the sequence point SP.
5239  * If CTX is not set, then this can target any thread. If CTX is set, then TLS should
5240  * belong to the same thread as CTX.
5241  */
5242 static void
5243 ss_start (SingleStepReq *ss_req, MonoMethod *method, SeqPoint *sp, MonoSeqPointInfo *info, MonoContext *ctx, DebuggerTlsData *tls, gboolean step_to_catch)
5244 {
5245         int i, j, frame_index;
5246         SeqPoint *next_sp;
5247         MonoBreakpoint *bp;
5248         gboolean enable_global = FALSE;
5249
5250         /* Stop the previous operation */
5251         ss_stop (ss_req);
5252
5253         /*
5254          * Implement single stepping using breakpoints if possible.
5255          */
5256         if (step_to_catch) {
5257                 bp = set_breakpoint (method, sp->il_offset, ss_req->req, NULL);
5258                 ss_req->bps = g_slist_append (ss_req->bps, bp);
5259         } else {
5260                 frame_index = 1;
5261
5262                 if ((!sp || sp->next_len == 0 || ss_req->depth == STEP_DEPTH_OUT || ss_req->depth == STEP_DEPTH_OVER) && ctx) {
5263                         /* Need parent frames */
5264                         if (!tls->context.valid)
5265                                 mono_thread_state_init_from_monoctx (&tls->context, ctx);
5266                         compute_frame_info (tls->thread, tls);
5267                 }
5268
5269                 /*
5270                  * Find the first sequence point in the current or in a previous frame which
5271                  * is not the last in its method.
5272                  */
5273                 if (ss_req->depth == STEP_DEPTH_OUT) {
5274                         /* Ignore seq points in current method */
5275                         while (frame_index < tls->frame_count) {
5276                                 StackFrame *frame = tls->frames [frame_index];
5277
5278                                 method = frame->method;
5279                                 sp = find_prev_seq_point_for_native_offset (frame->domain, frame->method, frame->native_offset, &info);
5280                                 frame_index ++;
5281                                 if (sp && sp->next_len != 0)
5282                                         break;
5283                         }
5284                         // There could be method calls before the next seq point in the caller when using nested calls
5285                         //enable_global = TRUE;
5286                 } else {
5287                         if (sp && sp->next_len == 0) {
5288                                 sp = NULL;
5289                                 while (frame_index < tls->frame_count) {
5290                                         StackFrame *frame = tls->frames [frame_index];
5291
5292                                         method = frame->method;
5293                                         sp = find_prev_seq_point_for_native_offset (frame->domain, frame->method, frame->native_offset, &info);
5294                                         if (sp && sp->next_len != 0)
5295                                                 break;
5296                                         sp = NULL;
5297                                         frame_index ++;
5298                                 }
5299                         }
5300                 }
5301
5302                 if (sp && sp->next_len > 0) {
5303                         for (i = 0; i < sp->next_len; ++i) {
5304                                 next_sp = &info->seq_points [sp->next [i]];
5305
5306                                 bp = set_breakpoint (method, next_sp->il_offset, ss_req->req, NULL);
5307                                 ss_req->bps = g_slist_append (ss_req->bps, bp);
5308                         }
5309                 }
5310
5311                 if (ss_req->depth == STEP_DEPTH_OVER) {
5312                         if (ss_req->nframes == 0)
5313                                 ss_req->nframes = tls->frame_count;
5314                         /* Need to stop in catch clauses as well */
5315                         for (i = 0; i < tls->frame_count; ++i) {
5316                                 StackFrame *frame = tls->frames [i];
5317
5318                                 if (frame->ji) {
5319                                         MonoJitInfo *jinfo = frame->ji;
5320                                         for (j = 0; j < jinfo->num_clauses; ++j) {
5321                                                 MonoJitExceptionInfo *ei = &jinfo->clauses [j];
5322
5323                                                 sp = find_next_seq_point_for_native_offset (frame->domain, frame->method, (char*)ei->handler_start - (char*)jinfo->code_start, NULL);
5324                                                 if (sp) {
5325                                                         bp = set_breakpoint (frame->method, sp->il_offset, ss_req->req, NULL);
5326                                                         ss_req->bps = g_slist_append (ss_req->bps, bp);
5327                                                 }
5328                                         }
5329                                 }
5330                         }
5331                 }
5332
5333
5334                 if (ss_req->depth == STEP_DEPTH_INTO) {
5335                         /* Enable global stepping so we stop at method entry too */
5336                         enable_global = TRUE;
5337                 }
5338
5339                 /*
5340                  * The ctx/frame info computed above will become invalid when we continue.
5341                  */
5342                 tls->context.valid = FALSE;
5343                 tls->async_state.valid = FALSE;
5344                 invalidate_frames (tls);
5345         }
5346
5347         if (enable_global) {
5348                 DEBUG (1, fprintf (log_file, "[dbg] Turning on global single stepping.\n"));
5349                 ss_req->global = TRUE;
5350                 start_single_stepping ();
5351         } else if (!ss_req->bps) {
5352                 DEBUG (1, fprintf (log_file, "[dbg] Turning on global single stepping.\n"));
5353                 ss_req->global = TRUE;
5354                 start_single_stepping ();
5355         } else {
5356                 ss_req->global = FALSE;
5357         }
5358 }
5359
5360 /*
5361  * Start single stepping of thread THREAD
5362  */
5363 static ErrorCode
5364 ss_create (MonoInternalThread *thread, StepSize size, StepDepth depth, EventRequest *req)
5365 {
5366         DebuggerTlsData *tls;
5367         MonoSeqPointInfo *info = NULL;
5368         SeqPoint *sp = NULL;
5369         MonoMethod *method = NULL;
5370         MonoDebugMethodInfo *minfo;
5371         gboolean step_to_catch = FALSE;
5372
5373         if (suspend_count == 0)
5374                 return ERR_NOT_SUSPENDED;
5375
5376         wait_for_suspend ();
5377
5378         // FIXME: Multiple requests
5379         if (ss_req) {
5380                 DEBUG (0, fprintf (log_file, "Received a single step request while the previous one was still active.\n"));
5381                 return ERR_NOT_IMPLEMENTED;
5382         }
5383
5384         DEBUG (1, fprintf (log_file, "[dbg] Starting single step of thread %p (depth=%s).\n", thread, ss_depth_to_string (depth)));
5385
5386         ss_req = g_new0 (SingleStepReq, 1);
5387         ss_req->req = req;
5388         ss_req->thread = thread;
5389         ss_req->size = size;
5390         ss_req->depth = depth;
5391         req->info = ss_req;
5392
5393         mono_loader_lock ();
5394         tls = mono_g_hash_table_lookup (thread_to_tls, thread);
5395         mono_loader_unlock ();
5396         g_assert (tls);
5397         g_assert (tls->context.valid);
5398         ss_req->start_sp = ss_req->last_sp = MONO_CONTEXT_GET_SP (&tls->context.ctx);
5399
5400         if (tls->catch_state.valid) {
5401                 gboolean res;
5402                 StackFrameInfo frame;
5403                 MonoContext new_ctx;
5404                 MonoLMF *lmf = NULL;
5405
5406                 /*
5407                  * We are stopped at a throw site. Stepping should go to the catch site.
5408                  */
5409
5410                 /* Find the the jit info for the catch context */
5411                 res = mono_find_jit_info_ext (tls->catch_state.unwind_data [MONO_UNWIND_DATA_DOMAIN], thread->jit_data, NULL, &tls->catch_state.ctx, &new_ctx, NULL, &lmf, NULL, &frame);
5412                 g_assert (res);
5413                 g_assert (frame.type == FRAME_TYPE_MANAGED);
5414
5415                 /*
5416                  * Find the seq point corresponding to the landing site ip, which is the first seq
5417                  * point after ip.
5418                  */
5419                 sp = find_next_seq_point_for_native_offset (frame.domain, frame.method, frame.native_offset, &info);
5420                 if (!sp)
5421                         no_seq_points_found (frame.method);
5422                 g_assert (sp);
5423
5424                 method = frame.method;
5425
5426                 step_to_catch = TRUE;
5427                 /* This make sure the seq point is not skipped by process_single_step () */
5428                 ss_req->last_sp = NULL;
5429         }
5430
5431         if (!step_to_catch && ss_req->size == STEP_SIZE_LINE) {
5432                 StackFrame *frame;
5433
5434                 /* Compute the initial line info */
5435                 compute_frame_info (thread, tls);
5436
5437                 if (tls->frame_count) {
5438                         frame = tls->frames [0];
5439
5440                         ss_req->last_method = frame->method;
5441                         ss_req->last_line = -1;
5442
5443                         minfo = mono_debug_lookup_method (frame->method);
5444                         if (minfo && frame->il_offset != -1) {
5445                                 MonoDebugSourceLocation *loc = mono_debug_symfile_lookup_location (minfo, frame->il_offset);
5446
5447                                 if (loc) {
5448                                         ss_req->last_line = loc->row;
5449                                         g_free (loc);
5450                                 }
5451                         }
5452                 }
5453         }
5454
5455         if (!step_to_catch) {
5456                 StackFrame *frame;
5457
5458                 compute_frame_info (thread, tls);
5459
5460                 if (tls->frame_count) {
5461                         frame = tls->frames [0];
5462
5463                         if (!method && frame->il_offset != -1) {
5464                                 /* FIXME: Sort the table and use a binary search */
5465                                 sp = find_prev_seq_point_for_native_offset (frame->domain, frame->method, frame->native_offset, &info);
5466                                 if (!sp)
5467                                         no_seq_points_found (frame->method);
5468                                 g_assert (sp);
5469                                 method = frame->method;
5470                         }
5471                 }
5472         }
5473
5474         ss_start (ss_req, method, sp, info, &tls->context.ctx, tls, step_to_catch);
5475
5476         return 0;
5477 }
5478
5479 static void
5480 ss_destroy (SingleStepReq *req)
5481 {
5482         // FIXME: Locking
5483         g_assert (ss_req == req);
5484
5485         ss_stop (ss_req);
5486
5487         g_free (ss_req);
5488         ss_req = NULL;
5489 }
5490
5491 static void
5492 ss_clear_for_assembly (SingleStepReq *req, MonoAssembly *assembly)
5493 {
5494         GSList *l;
5495         gboolean found = TRUE;
5496
5497         while (found) {
5498                 found = FALSE;
5499                 for (l = ss_req->bps; l; l = l->next) {
5500                         if (breakpoint_matches_assembly (l->data, assembly)) {
5501                                 clear_breakpoint (l->data);
5502                                 ss_req->bps = g_slist_delete_link (ss_req->bps, l);
5503                                 found = TRUE;
5504                                 break;
5505                         }
5506                 }
5507         }
5508 }
5509
5510 /*
5511  * Called from metadata by the icall for System.Diagnostics.Debugger:Log ().
5512  */
5513 void
5514 mono_debugger_agent_debug_log (int level, MonoString *category, MonoString *message)
5515 {
5516         int suspend_policy;
5517         GSList *events;
5518         EventInfo ei;
5519
5520         if (!agent_config.enabled)
5521                 return;
5522
5523         mono_loader_lock ();
5524         events = create_event_list (EVENT_KIND_USER_LOG, NULL, NULL, NULL, &suspend_policy);
5525         mono_loader_unlock ();
5526
5527         ei.level = level;
5528         ei.category = category ? mono_string_to_utf8 (category) : NULL;
5529         ei.message = message ? mono_string_to_utf8 (message) : NULL;
5530
5531         process_event (EVENT_KIND_USER_LOG, &ei, 0, NULL, events, suspend_policy);
5532
5533         g_free (ei.category);
5534         g_free (ei.message);
5535 }
5536
5537 gboolean
5538 mono_debugger_agent_debug_log_is_enabled (void)
5539 {
5540         /* Treat this as true even if there is no event request for EVENT_KIND_USER_LOG */
5541         return agent_config.enabled;
5542 }
5543
5544 #if defined(PLATFORM_ANDROID) || defined(TARGET_ANDROID)
5545 void
5546 mono_debugger_agent_unhandled_exception (MonoException *exc)
5547 {
5548         int suspend_policy;
5549         GSList *events;
5550         EventInfo ei;
5551
5552         if (!inited)
5553                 return;
5554
5555         memset (&ei, 0, sizeof (EventInfo));
5556         ei.exc = (MonoObject*)exc;
5557
5558         mono_loader_lock ();
5559         events = create_event_list (EVENT_KIND_EXCEPTION, NULL, NULL, &ei, &suspend_policy);
5560         mono_loader_unlock ();
5561
5562         process_event (EVENT_KIND_EXCEPTION, &ei, 0, NULL, events, suspend_policy);
5563 }
5564 #endif
5565
5566 void
5567 mono_debugger_agent_handle_exception (MonoException *exc, MonoContext *throw_ctx, 
5568                                       MonoContext *catch_ctx)
5569 {
5570         int i, j, suspend_policy;
5571         GSList *events;
5572         MonoJitInfo *ji, *catch_ji;
5573         EventInfo ei;
5574         DebuggerTlsData *tls = NULL;
5575
5576         if (thread_to_tls != NULL) {
5577                 MonoInternalThread *thread = mono_thread_internal_current ();
5578
5579                 mono_loader_lock ();
5580                 tls = mono_g_hash_table_lookup (thread_to_tls, thread);
5581                 mono_loader_unlock ();
5582
5583                 if (tls && tls->abort_requested)
5584                         return;
5585                 if (tls && tls->disable_breakpoints)
5586                         return;
5587         }
5588
5589         memset (&ei, 0, sizeof (EventInfo));
5590
5591         /* Just-In-Time debugging */
5592         if (!catch_ctx) {
5593                 if (agent_config.onuncaught && !inited) {
5594                         finish_agent_init (FALSE);
5595
5596                         /*
5597                          * Send an unsolicited EXCEPTION event with a dummy request id.
5598                          */
5599                         events = g_slist_append (NULL, GUINT_TO_POINTER (0xffffff));
5600                         ei.exc = (MonoObject*)exc;
5601                         process_event (EVENT_KIND_EXCEPTION, &ei, 0, throw_ctx, events, SUSPEND_POLICY_ALL);
5602                         return;
5603                 }
5604         } else if (agent_config.onthrow && !inited) {
5605                 GSList *l;
5606                 gboolean found = FALSE;
5607
5608                 for (l = agent_config.onthrow; l; l = l->next) {
5609                         char *ex_type = l->data;
5610                         char *f = mono_type_full_name (&exc->object.vtable->klass->byval_arg);
5611
5612                         if (!strcmp (ex_type, "") || !strcmp (ex_type, f))
5613                                 found = TRUE;
5614
5615                         g_free (f);
5616                 }
5617
5618                 if (found) {
5619                         finish_agent_init (FALSE);
5620
5621                         /*
5622                          * Send an unsolicited EXCEPTION event with a dummy request id.
5623                          */
5624                         events = g_slist_append (NULL, GUINT_TO_POINTER (0xffffff));
5625                         ei.exc = (MonoObject*)exc;
5626                         process_event (EVENT_KIND_EXCEPTION, &ei, 0, throw_ctx, events, SUSPEND_POLICY_ALL);
5627                         return;
5628                 }
5629         }
5630
5631         if (!inited)
5632                 return;
5633
5634         ji = mini_jit_info_table_find (mono_domain_get (), MONO_CONTEXT_GET_IP (throw_ctx), NULL);
5635         if (catch_ctx)
5636                 catch_ji = mini_jit_info_table_find (mono_domain_get (), MONO_CONTEXT_GET_IP (catch_ctx), NULL);
5637         else
5638                 catch_ji = NULL;
5639
5640         ei.exc = (MonoObject*)exc;
5641         ei.caught = catch_ctx != NULL;
5642
5643         mono_loader_lock ();
5644
5645         /* Treat exceptions which are caught in non-user code as unhandled */
5646         for (i = 0; i < event_requests->len; ++i) {
5647                 EventRequest *req = g_ptr_array_index (event_requests, i);
5648                 if (req->event_kind != EVENT_KIND_EXCEPTION)
5649                         continue;
5650
5651                 for (j = 0; j < req->nmodifiers; ++j) {
5652                         Modifier *mod = &req->modifiers [j];
5653
5654                         if (mod->kind == MOD_KIND_ASSEMBLY_ONLY && catch_ji) {
5655                                 int k;
5656                                 gboolean found = FALSE;
5657                                 MonoAssembly **assemblies = mod->data.assemblies;
5658
5659                                 if (assemblies) {
5660                                         for (k = 0; assemblies [k]; ++k)
5661                                                 if (assemblies [k] == jinfo_get_method (catch_ji)->klass->image->assembly)
5662                                                         found = TRUE;
5663                                 }
5664                                 if (!found)
5665                                         ei.caught = FALSE;
5666                         }
5667                 }
5668         }
5669
5670         events = create_event_list (EVENT_KIND_EXCEPTION, NULL, ji, &ei, &suspend_policy);
5671         mono_loader_unlock ();
5672
5673         if (tls && ei.caught && catch_ctx) {
5674                 memset (&tls->catch_state, 0, sizeof (tls->catch_state));
5675                 tls->catch_state.ctx = *catch_ctx;
5676                 tls->catch_state.unwind_data [MONO_UNWIND_DATA_DOMAIN] = mono_domain_get ();
5677                 tls->catch_state.valid = TRUE;
5678         }
5679
5680         process_event (EVENT_KIND_EXCEPTION, &ei, 0, throw_ctx, events, suspend_policy);
5681
5682         if (tls)
5683                 tls->catch_state.valid = FALSE;
5684 }
5685
5686 void
5687 mono_debugger_agent_begin_exception_filter (MonoException *exc, MonoContext *ctx, MonoContext *orig_ctx)
5688 {
5689         DebuggerTlsData *tls;
5690
5691         if (!inited)
5692                 return;
5693
5694         tls = mono_native_tls_get_value (debugger_tls_id);
5695         if (!tls)
5696                 return;
5697
5698         /*
5699          * We're about to invoke an exception filter during the first pass of exception handling.
5700          *
5701          * 'ctx' is the context that'll get passed to the filter ('call_filter (ctx, ei->data.filter)'),
5702          * 'orig_ctx' is the context where the exception has been thrown.
5703          *
5704          *
5705          * See mcs/class/Mono.Debugger.Soft/Tests/dtest-excfilter.il for an example.
5706          *
5707          * If we're stopped in Filter(), normal stack unwinding would first unwind to
5708          * the call site (line 37) and then continue to Main(), but it would never
5709          * include the throw site (line 32).
5710          *
5711          * Since exception filters are invoked during the first pass of exception handling,
5712          * the stack frames of the throw site are still intact, so we should include them
5713          * in a stack trace.
5714          *
5715          * We do this here by saving the context of the throw site in 'tls->filter_state'.
5716          *
5717          * Exception filters are used by MonoDroid, where we want to stop inside a call filter,
5718          * but report the location of the 'throw' to the user.
5719          *
5720          */
5721
5722         g_assert (mono_thread_state_init_from_monoctx (&tls->filter_state, orig_ctx));
5723 }
5724
5725 void
5726 mono_debugger_agent_end_exception_filter (MonoException *exc, MonoContext *ctx, MonoContext *orig_ctx)
5727 {
5728         DebuggerTlsData *tls;
5729
5730         if (!inited)
5731                 return;
5732
5733         tls = mono_native_tls_get_value (debugger_tls_id);
5734         if (!tls)
5735                 return;
5736
5737         tls->filter_state.valid = FALSE;
5738 }
5739
5740 /*
5741  * buffer_add_value_full:
5742  *
5743  *   Add the encoding of the value at ADDR described by T to the buffer.
5744  * AS_VTYPE determines whenever to treat primitive types as primitive types or
5745  * vtypes.
5746  */
5747 static void
5748 buffer_add_value_full (Buffer *buf, MonoType *t, void *addr, MonoDomain *domain,
5749                                            gboolean as_vtype, GHashTable *parent_vtypes)
5750 {
5751         MonoObject *obj;
5752         gboolean boxed_vtype = FALSE;
5753
5754         if (t->byref) {
5755                 if (!(*(void**)addr)) {
5756                         /* This can happen with compiler generated locals */
5757                         //printf ("%s\n", mono_type_full_name (t));
5758                         buffer_add_byte (buf, VALUE_TYPE_ID_NULL);
5759                         return;
5760                 }
5761                 g_assert (*(void**)addr);
5762                 addr = *(void**)addr;
5763         }
5764
5765         if (as_vtype) {
5766                 switch (t->type) {
5767                 case MONO_TYPE_BOOLEAN:
5768                 case MONO_TYPE_I1:
5769                 case MONO_TYPE_U1:
5770                 case MONO_TYPE_CHAR:
5771                 case MONO_TYPE_I2:
5772                 case MONO_TYPE_U2:
5773                 case MONO_TYPE_I4:
5774                 case MONO_TYPE_U4:
5775                 case MONO_TYPE_R4:
5776                 case MONO_TYPE_I8:
5777                 case MONO_TYPE_U8:
5778                 case MONO_TYPE_R8:
5779                 case MONO_TYPE_I:
5780                 case MONO_TYPE_U:
5781                 case MONO_TYPE_PTR:
5782                         goto handle_vtype;
5783                         break;
5784                 default:
5785                         break;
5786                 }
5787         }
5788
5789         switch (t->type) {
5790         case MONO_TYPE_VOID:
5791                 buffer_add_byte (buf, t->type);
5792                 break;
5793         case MONO_TYPE_BOOLEAN:
5794         case MONO_TYPE_I1:
5795         case MONO_TYPE_U1:
5796                 buffer_add_byte (buf, t->type);
5797                 buffer_add_int (buf, *(gint8*)addr);
5798                 break;
5799         case MONO_TYPE_CHAR:
5800         case MONO_TYPE_I2:
5801         case MONO_TYPE_U2:
5802                 buffer_add_byte (buf, t->type);
5803                 buffer_add_int (buf, *(gint16*)addr);
5804                 break;
5805         case MONO_TYPE_I4:
5806         case MONO_TYPE_U4:
5807         case MONO_TYPE_R4:
5808                 buffer_add_byte (buf, t->type);
5809                 buffer_add_int (buf, *(gint32*)addr);
5810                 break;
5811         case MONO_TYPE_I8:
5812         case MONO_TYPE_U8:
5813         case MONO_TYPE_R8:
5814                 buffer_add_byte (buf, t->type);
5815                 buffer_add_long (buf, *(gint64*)addr);
5816                 break;
5817         case MONO_TYPE_I:
5818         case MONO_TYPE_U:
5819                 /* Treat it as a vtype */
5820                 goto handle_vtype;
5821         case MONO_TYPE_PTR: {
5822                 gssize val = *(gssize*)addr;
5823                 
5824                 buffer_add_byte (buf, t->type);
5825                 buffer_add_long (buf, val);
5826                 break;
5827         }
5828         handle_ref:
5829         case MONO_TYPE_STRING:
5830         case MONO_TYPE_SZARRAY:
5831         case MONO_TYPE_OBJECT:
5832         case MONO_TYPE_CLASS:
5833         case MONO_TYPE_ARRAY:
5834                 obj = *(MonoObject**)addr;
5835
5836                 if (!obj) {
5837                         buffer_add_byte (buf, VALUE_TYPE_ID_NULL);
5838                 } else {
5839                         if (obj->vtable->klass->valuetype) {
5840                                 t = &obj->vtable->klass->byval_arg;
5841                                 addr = mono_object_unbox (obj);
5842                                 boxed_vtype = TRUE;
5843                                 goto handle_vtype;
5844                         } else if (obj->vtable->klass->rank) {
5845                                 buffer_add_byte (buf, obj->vtable->klass->byval_arg.type);
5846                         } else if (obj->vtable->klass->byval_arg.type == MONO_TYPE_GENERICINST) {
5847                                 buffer_add_byte (buf, MONO_TYPE_CLASS);
5848                         } else {
5849                                 buffer_add_byte (buf, obj->vtable->klass->byval_arg.type);
5850                         }
5851                         buffer_add_objid (buf, obj);
5852                 }
5853                 break;
5854         handle_vtype:
5855         case MONO_TYPE_VALUETYPE: {
5856                 int nfields;
5857                 gpointer iter;
5858                 MonoClassField *f;
5859                 MonoClass *klass = mono_class_from_mono_type (t);
5860                 int vtype_index;
5861
5862                 if (boxed_vtype) {
5863                         /*
5864                          * Handle boxed vtypes recursively referencing themselves using fields.
5865                          */
5866                         if (!parent_vtypes)
5867                                 parent_vtypes = g_hash_table_new (NULL, NULL);
5868                         vtype_index = GPOINTER_TO_INT (g_hash_table_lookup (parent_vtypes, addr));
5869                         if (vtype_index) {
5870                                 if (CHECK_PROTOCOL_VERSION (2, 33)) {
5871                                         buffer_add_byte (buf, VALUE_TYPE_ID_PARENT_VTYPE);
5872                                         buffer_add_int (buf, vtype_index - 1);
5873                                 } else {
5874                                         /* The client can't handle PARENT_VTYPE */
5875                                         buffer_add_byte (buf, VALUE_TYPE_ID_NULL);
5876                                 }
5877                                 break;
5878                         } else {
5879                                 g_hash_table_insert (parent_vtypes, addr, GINT_TO_POINTER (g_hash_table_size (parent_vtypes) + 1));
5880                         }
5881                 }
5882
5883                 buffer_add_byte (buf, MONO_TYPE_VALUETYPE);
5884                 buffer_add_byte (buf, klass->enumtype);
5885                 buffer_add_typeid (buf, domain, klass);
5886
5887                 nfields = 0;
5888                 iter = NULL;
5889                 while ((f = mono_class_get_fields (klass, &iter))) {
5890                         if (f->type->attrs & FIELD_ATTRIBUTE_STATIC)
5891                                 continue;
5892                         if (mono_field_is_deleted (f))
5893                                 continue;
5894                         nfields ++;
5895                 }
5896                 buffer_add_int (buf, nfields);
5897
5898                 iter = NULL;
5899                 while ((f = mono_class_get_fields (klass, &iter))) {
5900                         if (f->type->attrs & FIELD_ATTRIBUTE_STATIC)
5901                                 continue;
5902                         if (mono_field_is_deleted (f))
5903                                 continue;
5904                         buffer_add_value_full (buf, f->type, (guint8*)addr + f->offset - sizeof (MonoObject), domain, FALSE, parent_vtypes);
5905                 }
5906
5907                 if (boxed_vtype) {
5908                         g_hash_table_remove (parent_vtypes, addr);
5909                         if (g_hash_table_size (parent_vtypes) == 0) {
5910                                 g_hash_table_destroy (parent_vtypes);
5911                                 parent_vtypes = NULL;
5912                         }
5913                 }
5914                 break;
5915         }
5916         case MONO_TYPE_GENERICINST:
5917                 if (mono_type_generic_inst_is_valuetype (t)) {
5918                         goto handle_vtype;
5919                 } else {
5920                         goto handle_ref;
5921                 }
5922                 break;
5923         default:
5924                 NOT_IMPLEMENTED;
5925         }
5926 }
5927
5928 static void
5929 buffer_add_value (Buffer *buf, MonoType *t, void *addr, MonoDomain *domain)
5930 {
5931         buffer_add_value_full (buf, t, addr, domain, FALSE, NULL);
5932 }
5933
5934 static gboolean
5935 obj_is_of_type (MonoObject *obj, MonoType *t)
5936 {
5937         MonoClass *klass = obj->vtable->klass;
5938         if (!mono_class_is_assignable_from (mono_class_from_mono_type (t), klass)) {
5939                 if (mono_class_is_transparent_proxy (klass)) {
5940                         klass = ((MonoTransparentProxy *)obj)->remote_class->proxy_class;
5941                         if (mono_class_is_assignable_from (mono_class_from_mono_type (t), klass)) {
5942                                 return TRUE;
5943                         }
5944                 }
5945                 return FALSE;
5946         }
5947         return TRUE;
5948 }
5949
5950 static ErrorCode
5951 decode_value (MonoType *t, MonoDomain *domain, guint8 *addr, guint8 *buf, guint8 **endbuf, guint8 *limit);
5952
5953 static ErrorCode
5954 decode_vtype (MonoType *t, MonoDomain *domain, guint8 *addr, guint8 *buf, guint8 **endbuf, guint8 *limit)
5955 {
5956         gboolean is_enum;
5957         MonoClass *klass;
5958         MonoClassField *f;
5959         int nfields;
5960         gpointer iter = NULL;
5961         MonoDomain *d;
5962         int err;
5963
5964         is_enum = decode_byte (buf, &buf, limit);
5965         /* Enums are sent as a normal vtype */
5966         if (is_enum)
5967                 return ERR_NOT_IMPLEMENTED;
5968         klass = decode_typeid (buf, &buf, limit, &d, &err);
5969         if (err)
5970                 return err;
5971
5972         if (t && klass != mono_class_from_mono_type (t)) {
5973                 char *name = mono_type_full_name (t);
5974                 char *name2 = mono_type_full_name (&klass->byval_arg);
5975                 DEBUG(1, fprintf (log_file, "[%p] Expected value of type %s, got %s.\n", (gpointer)GetCurrentThreadId (), name, name2));
5976                 g_free (name);
5977                 g_free (name2);
5978                 return ERR_INVALID_ARGUMENT;
5979         }
5980
5981         nfields = decode_int (buf, &buf, limit);
5982         while ((f = mono_class_get_fields (klass, &iter))) {
5983                 if (f->type->attrs & FIELD_ATTRIBUTE_STATIC)
5984                         continue;
5985                 if (mono_field_is_deleted (f))
5986                         continue;
5987                 err = decode_value (f->type, domain, (guint8*)addr + f->offset - sizeof (MonoObject), buf, &buf, limit);
5988                 if (err)
5989                         return err;
5990                 nfields --;
5991         }
5992         g_assert (nfields == 0);
5993
5994         *endbuf = buf;
5995
5996         return 0;
5997 }
5998
5999 static ErrorCode
6000 decode_value_internal (MonoType *t, int type, MonoDomain *domain, guint8 *addr, guint8 *buf, guint8 **endbuf, guint8 *limit)
6001 {
6002         int err;
6003
6004         if (type != t->type && !MONO_TYPE_IS_REFERENCE (t) &&
6005                 !(t->type == MONO_TYPE_I && type == MONO_TYPE_VALUETYPE) &&
6006                 !(t->type == MONO_TYPE_U && type == MONO_TYPE_VALUETYPE) &&
6007                 !(t->type == MONO_TYPE_PTR && type == MONO_TYPE_I8) &&
6008                 !(t->type == MONO_TYPE_GENERICINST && type == MONO_TYPE_VALUETYPE)) {
6009                 char *name = mono_type_full_name (t);
6010                 DEBUG(1, fprintf (log_file, "[%p] Expected value of type %s, got 0x%0x.\n", (gpointer)GetCurrentThreadId (), name, type));
6011                 g_free (name);
6012                 return ERR_INVALID_ARGUMENT;
6013         }
6014
6015         switch (t->type) {
6016         case MONO_TYPE_BOOLEAN:
6017                 *(guint8*)addr = decode_int (buf, &buf, limit);
6018                 break;
6019         case MONO_TYPE_CHAR:
6020                 *(gunichar2*)addr = decode_int (buf, &buf, limit);
6021                 break;
6022         case MONO_TYPE_I1:
6023                 *(gint8*)addr = decode_int (buf, &buf, limit);
6024                 break;
6025         case MONO_TYPE_U1:
6026                 *(guint8*)addr = decode_int (buf, &buf, limit);
6027                 break;
6028         case MONO_TYPE_I2:
6029                 *(gint16*)addr = decode_int (buf, &buf, limit);
6030                 break;
6031         case MONO_TYPE_U2:
6032                 *(guint16*)addr = decode_int (buf, &buf, limit);
6033                 break;
6034         case MONO_TYPE_I4:
6035                 *(gint32*)addr = decode_int (buf, &buf, limit);
6036                 break;
6037         case MONO_TYPE_U4:
6038                 *(guint32*)addr = decode_int (buf, &buf, limit);
6039                 break;
6040         case MONO_TYPE_I8:
6041                 *(gint64*)addr = decode_long (buf, &buf, limit);
6042                 break;
6043         case MONO_TYPE_U8:
6044                 *(guint64*)addr = decode_long (buf, &buf, limit);
6045                 break;
6046         case MONO_TYPE_R4:
6047                 *(guint32*)addr = decode_int (buf, &buf, limit);
6048                 break;
6049         case MONO_TYPE_R8:
6050                 *(guint64*)addr = decode_long (buf, &buf, limit);
6051                 break;
6052         case MONO_TYPE_PTR:
6053                 /* We send these as I8, so we get them back as such */
6054                 g_assert (type == MONO_TYPE_I8);
6055                 *(gssize*)addr = decode_long (buf, &buf, limit);
6056                 break;
6057         case MONO_TYPE_GENERICINST:
6058                 if (MONO_TYPE_ISSTRUCT (t)) {
6059                         /* The client sends these as a valuetype */
6060                         goto handle_vtype;
6061                 } else {
6062                         goto handle_ref;
6063                 }
6064                 break;
6065         case MONO_TYPE_I:
6066         case MONO_TYPE_U:
6067                 /* We send these as vtypes, so we get them back as such */
6068                 g_assert (type == MONO_TYPE_VALUETYPE);
6069                 /* Fall through */
6070                 handle_vtype:
6071         case MONO_TYPE_VALUETYPE:
6072                 err = decode_vtype (t, domain, addr,buf, &buf, limit);
6073                 if (err)
6074                         return err;
6075                 break;
6076         handle_ref:
6077         default:
6078                 if (MONO_TYPE_IS_REFERENCE (t)) {
6079                         if (type == MONO_TYPE_OBJECT) {
6080                                 int objid = decode_objid (buf, &buf, limit);
6081                                 int err;
6082                                 MonoObject *obj;
6083
6084                                 err = get_object (objid, (MonoObject**)&obj);
6085                                 if (err)
6086                                         return err;
6087
6088                                 if (obj) {
6089                                         if (!obj_is_of_type (obj, t)) {
6090                                                 DEBUG (1, fprintf (log_file, "Expected type '%s', got '%s'\n", mono_type_full_name (t), obj->vtable->klass->name));
6091                                                 return ERR_INVALID_ARGUMENT;
6092                                         }
6093                                 }
6094                                 if (obj && obj->vtable->domain != domain)
6095                                         return ERR_INVALID_ARGUMENT;
6096
6097                                 mono_gc_wbarrier_generic_store (addr, obj);
6098                         } else if (type == VALUE_TYPE_ID_NULL) {
6099                                 *(MonoObject**)addr = NULL;
6100                         } else if (type == MONO_TYPE_VALUETYPE) {
6101                                 guint8 *buf2;
6102                                 gboolean is_enum;
6103                                 MonoClass *klass;
6104                                 MonoDomain *d;
6105                                 guint8 *vtype_buf;
6106                                 int vtype_buf_size;
6107
6108                                 /* This can happen when round-tripping boxed vtypes */
6109                                 /*
6110                                  * Obtain vtype class.
6111                                  * Same as the beginning of the handle_vtype case above.
6112                                  */
6113                                 buf2 = buf;
6114                                 is_enum = decode_byte (buf, &buf, limit);
6115                                 if (is_enum)
6116                                         return ERR_NOT_IMPLEMENTED;
6117                                 klass = decode_typeid (buf, &buf, limit, &d, &err);
6118                                 if (err)
6119                                         return err;
6120
6121                                 /* Decode the vtype into a temporary buffer, then box it. */
6122                                 vtype_buf_size = mono_class_value_size (klass, NULL);
6123                                 vtype_buf = g_malloc0 (vtype_buf_size);
6124                                 g_assert (vtype_buf);
6125
6126                                 buf = buf2;
6127                                 err = decode_vtype (NULL, domain, vtype_buf, buf, &buf, limit);
6128                                 if (err) {
6129                                         g_free (vtype_buf);
6130                                         return err;
6131                                 }
6132                                 *(MonoObject**)addr = mono_value_box (d, klass, vtype_buf);
6133                                 g_free (vtype_buf);
6134                         } else {
6135                                 char *name = mono_type_full_name (t);
6136                                 DEBUG(1, fprintf (log_file, "[%p] Expected value of type %s, got 0x%0x.\n", (gpointer)GetCurrentThreadId (), name, type));
6137                                 g_free (name);
6138                                 return ERR_INVALID_ARGUMENT;
6139                         }
6140                 } else {
6141                         NOT_IMPLEMENTED;
6142                 }
6143                 break;
6144         }
6145
6146         *endbuf = buf;
6147
6148         return 0;
6149 }
6150
6151 static ErrorCode
6152 decode_value (MonoType *t, MonoDomain *domain, guint8 *addr, guint8 *buf, guint8 **endbuf, guint8 *limit)
6153 {
6154         int err;
6155         int type = decode_byte (buf, &buf, limit);
6156
6157         if (t->type == MONO_TYPE_GENERICINST && mono_class_is_nullable (mono_class_from_mono_type (t))) {
6158                 MonoType *targ = t->data.generic_class->context.class_inst->type_argv [0];
6159                 guint8 *nullable_buf;
6160
6161                 /*
6162                  * First try decoding it as a Nullable`1
6163                  */
6164                 err = decode_value_internal (t, type, domain, addr, buf, endbuf, limit);
6165                 if (!err)
6166                         return err;
6167
6168                 /*
6169                  * Then try decoding as a primitive value or null.
6170                  */
6171                 if (targ->type == type) {
6172                         nullable_buf = g_malloc (mono_class_instance_size (mono_class_from_mono_type (targ)));
6173                         err = decode_value_internal (targ, type, domain, nullable_buf, buf, endbuf, limit);
6174                         if (err) {
6175                                 g_free (nullable_buf);
6176                                 return err;
6177                         }
6178                         mono_nullable_init (addr, mono_value_box (domain, mono_class_from_mono_type (targ), nullable_buf), mono_class_from_mono_type (t));
6179                         g_free (nullable_buf);
6180                         *endbuf = buf;
6181                         return ERR_NONE;
6182                 } else if (type == VALUE_TYPE_ID_NULL) {
6183                         mono_nullable_init (addr, NULL, mono_class_from_mono_type (t));
6184                         *endbuf = buf;
6185                         return ERR_NONE;
6186                 }
6187         }
6188
6189         return decode_value_internal (t, type, domain, addr, buf, endbuf, limit);
6190 }
6191
6192 static void
6193 add_var (Buffer *buf, MonoDebugMethodJitInfo *jit, MonoType *t, MonoDebugVarInfo *var, MonoContext *ctx, MonoDomain *domain, gboolean as_vtype)
6194 {
6195         guint32 flags;
6196         int reg;
6197         guint8 *addr, *gaddr;
6198         mgreg_t reg_val;
6199
6200         flags = var->index & MONO_DEBUG_VAR_ADDRESS_MODE_FLAGS;
6201         reg = var->index & ~MONO_DEBUG_VAR_ADDRESS_MODE_FLAGS;
6202
6203         switch (flags) {
6204         case MONO_DEBUG_VAR_ADDRESS_MODE_REGISTER:
6205                 reg_val = mono_arch_context_get_int_reg (ctx, reg);
6206
6207                 buffer_add_value_full (buf, t, &reg_val, domain, as_vtype, NULL);
6208                 break;
6209         case MONO_DEBUG_VAR_ADDRESS_MODE_REGOFFSET:
6210                 addr = (gpointer)mono_arch_context_get_int_reg (ctx, reg);
6211                 addr += (gint32)var->offset;
6212
6213                 //printf ("[R%d+%d] = %p\n", reg, var->offset, addr);
6214
6215                 buffer_add_value_full (buf, t, addr, domain, as_vtype, NULL);
6216                 break;
6217         case MONO_DEBUG_VAR_ADDRESS_MODE_DEAD:
6218                 NOT_IMPLEMENTED;
6219                 break;
6220         case MONO_DEBUG_VAR_ADDRESS_MODE_REGOFFSET_INDIR:
6221         case MONO_DEBUG_VAR_ADDRESS_MODE_VTADDR:
6222                 /* Same as regoffset, but with an indirection */
6223                 addr = (gpointer)mono_arch_context_get_int_reg (ctx, reg);
6224                 addr += (gint32)var->offset;
6225
6226                 gaddr = *(gpointer*)addr;
6227                 g_assert (gaddr);
6228                 buffer_add_value_full (buf, t, gaddr, domain, as_vtype, NULL);
6229                 break;
6230         case MONO_DEBUG_VAR_ADDRESS_MODE_GSHAREDVT_LOCAL: {
6231                 MonoDebugVarInfo *info_var = jit->gsharedvt_info_var;
6232                 MonoDebugVarInfo *locals_var = jit->gsharedvt_locals_var;
6233                 MonoGSharedVtMethodRuntimeInfo *info;
6234                 guint8 *locals;
6235                 int idx;
6236
6237                 idx = reg;
6238
6239                 g_assert (info_var);
6240                 g_assert (locals_var);
6241
6242                 flags = info_var->index & MONO_DEBUG_VAR_ADDRESS_MODE_FLAGS;
6243                 reg = info_var->index & ~MONO_DEBUG_VAR_ADDRESS_MODE_FLAGS;
6244                 if (flags == MONO_DEBUG_VAR_ADDRESS_MODE_REGOFFSET) {
6245                         addr = (gpointer)mono_arch_context_get_int_reg (ctx, reg);
6246                         addr += (gint32)info_var->offset;
6247                         info = *(gpointer*)addr;
6248                 } else if (flags == MONO_DEBUG_VAR_ADDRESS_MODE_REGISTER) {
6249                         info = (gpointer)mono_arch_context_get_int_reg (ctx, reg);
6250                 } else {
6251                         g_assert_not_reached ();
6252                 }
6253                 g_assert (info);
6254
6255                 flags = locals_var->index & MONO_DEBUG_VAR_ADDRESS_MODE_FLAGS;
6256                 reg = locals_var->index & ~MONO_DEBUG_VAR_ADDRESS_MODE_FLAGS;
6257                 if (flags == MONO_DEBUG_VAR_ADDRESS_MODE_REGOFFSET) {
6258                         addr = (gpointer)mono_arch_context_get_int_reg (ctx, reg);
6259                         addr += (gint32)locals_var->offset;
6260                         locals = *(gpointer*)addr;
6261                 } else if (flags == MONO_DEBUG_VAR_ADDRESS_MODE_REGISTER) {
6262                         locals = (gpointer)mono_arch_context_get_int_reg (ctx, reg);
6263                 } else {
6264                         g_assert_not_reached ();
6265                 }
6266                 g_assert (locals);
6267
6268                 addr = locals + GPOINTER_TO_INT (info->entries [idx]);
6269
6270                 buffer_add_value_full (buf, t, addr, domain, as_vtype, NULL);
6271                 break;
6272         }
6273
6274         default:
6275                 g_assert_not_reached ();
6276         }
6277 }
6278
6279 static void
6280 set_var (MonoType *t, MonoDebugVarInfo *var, MonoContext *ctx, MonoDomain *domain, guint8 *val, mgreg_t **reg_locations, MonoContext *restore_ctx)
6281 {
6282         guint32 flags;
6283         int reg, size;
6284         guint8 *addr, *gaddr;
6285
6286         flags = var->index & MONO_DEBUG_VAR_ADDRESS_MODE_FLAGS;
6287         reg = var->index & ~MONO_DEBUG_VAR_ADDRESS_MODE_FLAGS;
6288
6289         if (MONO_TYPE_IS_REFERENCE (t))
6290                 size = sizeof (gpointer);
6291         else
6292                 size = mono_class_value_size (mono_class_from_mono_type (t), NULL);
6293
6294         switch (flags) {
6295         case MONO_DEBUG_VAR_ADDRESS_MODE_REGISTER: {
6296 #ifdef MONO_ARCH_HAVE_CONTEXT_SET_INT_REG
6297                 mgreg_t v;
6298                 gboolean is_signed = FALSE;
6299
6300                 if (t->byref) {
6301                         addr = (gpointer)mono_arch_context_get_int_reg (ctx, reg);
6302
6303                         if (addr) {
6304                                 // FIXME: Write barriers
6305                                 mono_gc_memmove_atomic (addr, val, size);
6306                         }
6307                         break;
6308                 }
6309
6310                 if (!t->byref && (t->type == MONO_TYPE_I1 || t->type == MONO_TYPE_I2 || t->type == MONO_TYPE_I4 || t->type == MONO_TYPE_I8))
6311                         is_signed = TRUE;
6312
6313                 switch (size) {
6314                 case 1:
6315                         v = is_signed ? *(gint8*)val : *(guint8*)val;
6316                         break;
6317                 case 2:
6318                         v = is_signed ? *(gint16*)val : *(guint16*)val;
6319                         break;
6320                 case 4:
6321                         v = is_signed ? *(gint32*)val : *(guint32*)val;
6322                         break;
6323                 case 8:
6324                         v = is_signed ? *(gint64*)val : *(guint64*)val;
6325                         break;
6326                 default:
6327                         g_assert_not_reached ();
6328                 }
6329
6330                 /* Set value on the stack or in the return ctx */
6331                 if (reg_locations [reg]) {
6332                         /* Saved on the stack */
6333                         DEBUG (1, fprintf (log_file, "[dbg] Setting stack location %p for reg %x to %p.\n", reg_locations [reg], reg, (gpointer)v));
6334                         *(reg_locations [reg]) = v;
6335                 } else {
6336                         /* Not saved yet */
6337                         DEBUG (1, fprintf (log_file, "[dbg] Setting context location for reg %x to %p.\n", reg, (gpointer)v));
6338                         mono_arch_context_set_int_reg (restore_ctx, reg, v);
6339                 }                       
6340
6341                 // FIXME: Move these to mono-context.h/c.
6342                 mono_arch_context_set_int_reg (ctx, reg, v);
6343 #else
6344                 // FIXME: Can't set registers, so we disable linears
6345                 NOT_IMPLEMENTED;
6346 #endif
6347                 break;
6348         }
6349         case MONO_DEBUG_VAR_ADDRESS_MODE_REGOFFSET:
6350                 addr = (gpointer)mono_arch_context_get_int_reg (ctx, reg);
6351                 addr += (gint32)var->offset;
6352
6353                 //printf ("[R%d+%d] = %p\n", reg, var->offset, addr);
6354
6355                 if (t->byref) {
6356                         addr = *(guint8**)addr;
6357
6358                         if (!addr)
6359                                 break;
6360                 }
6361                         
6362                 // FIXME: Write barriers
6363                 mono_gc_memmove_atomic (addr, val, size);
6364                 break;
6365         case MONO_DEBUG_VAR_ADDRESS_MODE_REGOFFSET_INDIR:
6366                 /* Same as regoffset, but with an indirection */
6367                 addr = (gpointer)mono_arch_context_get_int_reg (ctx, reg);
6368                 addr += (gint32)var->offset;
6369
6370                 gaddr = *(gpointer*)addr;
6371                 g_assert (gaddr);
6372                 // FIXME: Write barriers
6373                 mono_gc_memmove_atomic (gaddr, val, size);
6374                 break;
6375         case MONO_DEBUG_VAR_ADDRESS_MODE_DEAD:
6376                 NOT_IMPLEMENTED;
6377                 break;
6378         default:
6379                 g_assert_not_reached ();
6380         }
6381 }
6382
6383 static void
6384 clear_event_request (int req_id, int etype)
6385 {
6386         int i;
6387
6388         mono_loader_lock ();
6389         for (i = 0; i < event_requests->len; ++i) {
6390                 EventRequest *req = g_ptr_array_index (event_requests, i);
6391
6392                 if (req->id == req_id && req->event_kind == etype) {
6393                         if (req->event_kind == EVENT_KIND_BREAKPOINT)
6394                                 clear_breakpoint (req->info);
6395                         if (req->event_kind == EVENT_KIND_STEP)
6396                                 ss_destroy (req->info);
6397                         if (req->event_kind == EVENT_KIND_METHOD_ENTRY)
6398                                 clear_breakpoint (req->info);
6399                         if (req->event_kind == EVENT_KIND_METHOD_EXIT)
6400                                 clear_breakpoint (req->info);
6401                         g_ptr_array_remove_index_fast (event_requests, i);
6402                         g_free (req);
6403                         break;
6404                 }
6405         }
6406         mono_loader_unlock ();
6407 }
6408
6409 static void
6410 clear_assembly_from_modifier (EventRequest *req, Modifier *m, MonoAssembly *assembly)
6411 {
6412         int i;
6413
6414         if (m->kind == MOD_KIND_EXCEPTION_ONLY && m->data.exc_class && m->data.exc_class->image->assembly == assembly)
6415                 m->kind = MOD_KIND_NONE;
6416         if (m->kind == MOD_KIND_ASSEMBLY_ONLY && m->data.assemblies) {
6417                 int count = 0, match_count = 0, pos;
6418                 MonoAssembly **newassemblies;
6419
6420                 for (i = 0; m->data.assemblies [i]; ++i) {
6421                         count ++;
6422                         if (m->data.assemblies [i] == assembly)
6423                                 match_count ++;
6424                 }
6425
6426                 if (match_count) {
6427                         newassemblies = g_new0 (MonoAssembly*, count - match_count);
6428
6429                         pos = 0;
6430                         for (i = 0; i < count; ++i)
6431                                 if (m->data.assemblies [i] != assembly)
6432                                         newassemblies [pos ++] = m->data.assemblies [i];
6433                         g_assert (pos == count - match_count);
6434                         g_free (m->data.assemblies);
6435                         m->data.assemblies = newassemblies;
6436                 }
6437         }
6438 }
6439
6440 static void
6441 clear_assembly_from_modifiers (EventRequest *req, MonoAssembly *assembly)
6442 {
6443         int i;
6444
6445         for (i = 0; i < req->nmodifiers; ++i) {
6446                 Modifier *m = &req->modifiers [i];
6447
6448                 clear_assembly_from_modifier (req, m, assembly);
6449         }
6450 }
6451
6452 /*
6453  * clear_event_requests_for_assembly:
6454  *
6455  *   Clear all events requests which reference ASSEMBLY.
6456  */
6457 static void
6458 clear_event_requests_for_assembly (MonoAssembly *assembly)
6459 {
6460         int i;
6461         gboolean found;
6462
6463         mono_loader_lock ();
6464         found = TRUE;
6465         while (found) {
6466                 found = FALSE;
6467                 for (i = 0; i < event_requests->len; ++i) {
6468                         EventRequest *req = g_ptr_array_index (event_requests, i);
6469
6470                         clear_assembly_from_modifiers (req, assembly);
6471
6472                         if (req->event_kind == EVENT_KIND_BREAKPOINT && breakpoint_matches_assembly (req->info, assembly)) {
6473                                 clear_event_request (req->id, req->event_kind);
6474                                 found = TRUE;
6475                                 break;
6476                         }
6477
6478                         if (req->event_kind == EVENT_KIND_STEP)
6479                                 ss_clear_for_assembly (req->info, assembly);
6480                 }
6481         }
6482         mono_loader_unlock ();
6483 }
6484
6485 /*
6486  * type_comes_from_assembly:
6487  *
6488  *   GHRFunc that returns TRUE if klass comes from assembly
6489  */
6490 static gboolean
6491 type_comes_from_assembly (gpointer klass, gpointer also_klass, gpointer assembly)
6492 {
6493         return (mono_class_get_image ((MonoClass*)klass) == mono_assembly_get_image ((MonoAssembly*)assembly));
6494 }
6495
6496 /*
6497  * clear_types_for_assembly:
6498  *
6499  *   Clears types from loaded_classes for a given assembly
6500  */
6501 static void
6502 clear_types_for_assembly (MonoAssembly *assembly)
6503 {
6504         MonoDomain *domain = mono_domain_get ();
6505         AgentDomainInfo *info = NULL;
6506
6507         mono_loader_lock ();
6508         info = get_agent_domain_info (domain);
6509         g_hash_table_foreach_remove (info->loaded_classes, type_comes_from_assembly, assembly);
6510         mono_loader_unlock ();
6511 }
6512
6513 static void
6514 add_thread (gpointer key, gpointer value, gpointer user_data)
6515 {
6516         MonoInternalThread *thread = value;
6517         Buffer *buf = user_data;
6518
6519         buffer_add_objid (buf, (MonoObject*)thread);
6520 }
6521
6522 static ErrorCode
6523 do_invoke_method (DebuggerTlsData *tls, Buffer *buf, InvokeData *invoke, guint8 *p, guint8 **endp)
6524 {
6525         guint8 *end = invoke->endp;
6526         MonoMethod *m;
6527         int i, err, nargs;
6528         MonoMethodSignature *sig;
6529         guint8 **arg_buf;
6530         void **args;
6531         MonoObject *this, *res, *exc;
6532         MonoDomain *domain;
6533         guint8 *this_buf;
6534 #ifdef MONO_ARCH_SOFT_DEBUG_SUPPORTED
6535         MonoLMFExt ext;
6536 #endif
6537         MonoStopwatch watch;
6538
6539         if (invoke->method) {
6540                 /* 
6541                  * Invoke this method directly, currently only Environment.Exit () is supported.
6542                  */
6543                 this = NULL;
6544                 DEBUG (1, fprintf (log_file, "[%p] Invoking method '%s' on receiver '%s'.\n", (gpointer)GetCurrentThreadId (), mono_method_full_name (invoke->method, TRUE), this ? this->vtable->klass->name : "<null>"));
6545                 mono_runtime_invoke (invoke->method, NULL, invoke->args, &exc);
6546                 g_assert_not_reached ();
6547         }
6548
6549         m = decode_methodid (p, &p, end, &domain, &err);
6550         if (err)
6551                 return err;
6552         sig = mono_method_signature (m);
6553
6554         if (m->klass->valuetype)
6555                 this_buf = g_alloca (mono_class_instance_size (m->klass));
6556         else
6557                 this_buf = g_alloca (sizeof (MonoObject*));
6558         if (m->klass->valuetype && (m->flags & METHOD_ATTRIBUTE_STATIC)) {
6559                 /* Should be null */
6560                 int type = decode_byte (p, &p, end);
6561                 if (type != VALUE_TYPE_ID_NULL) {
6562                         DEBUG (1, fprintf (log_file, "[%p] Error: Static vtype method invoked with this argument.\n", (gpointer)GetCurrentThreadId ()));
6563                         return ERR_INVALID_ARGUMENT;
6564                 }
6565                 memset (this_buf, 0, mono_class_instance_size (m->klass));
6566         } else {
6567                 err = decode_value (&m->klass->byval_arg, domain, this_buf, p, &p, end);
6568                 if (err)
6569                         return err;
6570         }
6571
6572         if (!m->klass->valuetype)
6573                 this = *(MonoObject**)this_buf;
6574         else
6575                 this = NULL;
6576
6577         if (MONO_CLASS_IS_INTERFACE (m->klass)) {
6578                 if (!this) {
6579                         DEBUG (1, fprintf (log_file, "[%p] Error: Interface method invoked without this argument.\n", (gpointer)GetCurrentThreadId ()));
6580                         return ERR_INVALID_ARGUMENT;
6581                 }
6582                 m = mono_object_get_virtual_method (this, m);
6583         } else if (invoke->flags & INVOKE_FLAG_VIRTUAL) {
6584                 if (!this) {
6585                         DEBUG (1, fprintf (log_file, "[%p] Error: invoke with INVOKE_FLAG_VIRTUAL flag set without this argument.\n", (gpointer)GetCurrentThreadId ()));
6586                         return ERR_INVALID_ARGUMENT;
6587                 }
6588                 m = mono_object_get_virtual_method (this, m);
6589         }
6590
6591         DEBUG (1, fprintf (log_file, "[%p] Invoking method '%s' on receiver '%s'.\n", (gpointer)GetCurrentThreadId (), mono_method_full_name (m, TRUE), this ? this->vtable->klass->name : "<null>"));
6592
6593         if (this && this->vtable->domain != domain)
6594                 NOT_IMPLEMENTED;
6595
6596         if (!m->klass->valuetype && !(m->flags & METHOD_ATTRIBUTE_STATIC) && !this) {
6597                 if (!strcmp (m->name, ".ctor")) {
6598                         if (m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT)
6599                                 return ERR_INVALID_ARGUMENT;
6600                         else
6601                                 this = mono_object_new (domain, m->klass);
6602                 } else {
6603                         return ERR_INVALID_ARGUMENT;
6604                 }
6605         }
6606
6607         if (this && !obj_is_of_type (this, &m->klass->byval_arg))
6608                 return ERR_INVALID_ARGUMENT;
6609
6610         nargs = decode_int (p, &p, end);
6611         if (nargs != sig->param_count)
6612                 return ERR_INVALID_ARGUMENT;
6613         /* Use alloca to get gc tracking */
6614         arg_buf = g_alloca (nargs * sizeof (gpointer));
6615         memset (arg_buf, 0, nargs * sizeof (gpointer));
6616         args = g_alloca (nargs * sizeof (gpointer));
6617         for (i = 0; i < nargs; ++i) {
6618                 if (MONO_TYPE_IS_REFERENCE (sig->params [i])) {
6619                         err = decode_value (sig->params [i], domain, (guint8*)&args [i], p, &p, end);
6620                         if (err)
6621                                 break;
6622                         if (args [i] && ((MonoObject*)args [i])->vtable->domain != domain)
6623                                 NOT_IMPLEMENTED;
6624
6625                         if (sig->params [i]->byref) {
6626                                 arg_buf [i] = g_alloca (sizeof (mgreg_t));
6627                                 *(gpointer*)arg_buf [i] = args [i];
6628                                 args [i] = arg_buf [i];
6629                         }
6630                 } else {
6631                         arg_buf [i] = g_alloca (mono_class_instance_size (mono_class_from_mono_type (sig->params [i])));
6632                         err = decode_value (sig->params [i], domain, arg_buf [i], p, &p, end);
6633                         if (err)
6634                                 break;
6635                         args [i] = arg_buf [i];
6636                 }
6637         }
6638
6639         if (i < nargs)
6640                 return err;
6641
6642         if (invoke->flags & INVOKE_FLAG_DISABLE_BREAKPOINTS)
6643                 tls->disable_breakpoints = TRUE;
6644         else
6645                 tls->disable_breakpoints = FALSE;
6646
6647         /* 
6648          * Add an LMF frame to link the stack frames on the invoke method with our caller.
6649          */
6650 #ifdef MONO_ARCH_SOFT_DEBUG_SUPPORTED
6651         if (invoke->has_ctx) {
6652                 MonoLMF **lmf_addr;
6653
6654                 lmf_addr = mono_get_lmf_addr ();
6655
6656                 /* Setup our lmf */
6657                 memset (&ext, 0, sizeof (ext));
6658                 mono_arch_init_lmf_ext (&ext, *lmf_addr);
6659
6660                 ext.debugger_invoke = TRUE;
6661                 memcpy (&ext.ctx, &invoke->ctx, sizeof (MonoContext));
6662
6663                 mono_set_lmf ((MonoLMF*)&ext);
6664         }
6665 #endif
6666
6667         mono_stopwatch_start (&watch);
6668         if (m->klass->valuetype)
6669                 res = mono_runtime_invoke (m, this_buf, args, &exc);
6670         else
6671                 res = mono_runtime_invoke (m, this, args, &exc);
6672         mono_stopwatch_stop (&watch);
6673         DEBUG (1, fprintf (log_file, "[%p] Invoke result: %p, exc: %s, time: %ld ms.\n", (gpointer)GetCurrentThreadId (), res, exc ? exc->vtable->klass->name : NULL, (long)mono_stopwatch_elapsed_ms (&watch)));
6674         if (exc) {
6675                 buffer_add_byte (buf, 0);
6676                 buffer_add_value (buf, &mono_defaults.object_class->byval_arg, &exc, domain);
6677         } else {
6678                 gboolean out_this = FALSE;
6679                 gboolean out_args = FALSE;
6680
6681                 if ((invoke->flags & INVOKE_FLAG_RETURN_OUT_THIS) && CHECK_PROTOCOL_VERSION (2, 35))
6682                         out_this = TRUE;
6683                 if ((invoke->flags & INVOKE_FLAG_RETURN_OUT_ARGS) && CHECK_PROTOCOL_VERSION (2, 35))
6684                         out_args = TRUE;
6685                 buffer_add_byte (buf, 1 + (out_this ? 2 : 0) + (out_args ? 4 : 0));
6686                 if (sig->ret->type == MONO_TYPE_VOID) {
6687                         if (!strcmp (m->name, ".ctor") && !m->klass->valuetype) {
6688                                 buffer_add_value (buf, &mono_defaults.object_class->byval_arg, &this, domain);
6689                         }
6690                         else
6691                                 buffer_add_value (buf, &mono_defaults.void_class->byval_arg, NULL, domain);
6692                 } else if (MONO_TYPE_IS_REFERENCE (sig->ret)) {
6693                         buffer_add_value (buf, sig->ret, &res, domain);
6694                 } else if (mono_class_from_mono_type (sig->ret)->valuetype || sig->ret->type == MONO_TYPE_PTR || sig->ret->type == MONO_TYPE_FNPTR) {
6695                         if (mono_class_is_nullable (mono_class_from_mono_type (sig->ret))) {
6696                                 MonoClass *k = mono_class_from_mono_type (sig->ret);
6697                                 guint8 *nullable_buf = g_alloca (mono_class_value_size (k, NULL));
6698
6699                                 g_assert (nullable_buf);
6700                                 mono_nullable_init (nullable_buf, res, k);
6701                                 buffer_add_value (buf, sig->ret, nullable_buf, domain);
6702                         } else {
6703                                 g_assert (res);
6704                                 buffer_add_value (buf, sig->ret, mono_object_unbox (res), domain);
6705                         }
6706                 } else {
6707                         NOT_IMPLEMENTED;
6708                 }
6709                 if (out_this)
6710                         /* Return the new value of the receiver after the call */
6711                         buffer_add_value (buf, &m->klass->byval_arg, this_buf, domain);
6712                 if (out_args) {
6713                         buffer_add_int (buf, nargs);
6714                         for (i = 0; i < nargs; ++i) {
6715                                 if (MONO_TYPE_IS_REFERENCE (sig->params [i]))
6716                                         buffer_add_value (buf, sig->params [i], &args [i], domain);
6717                                 else if (sig->params [i]->byref)
6718                                         /* add_value () does an indirection */
6719                                         buffer_add_value (buf, sig->params [i], &arg_buf [i], domain);
6720                                 else
6721                                         buffer_add_value (buf, sig->params [i], arg_buf [i], domain);
6722                         }
6723                 }
6724         }
6725
6726         tls->disable_breakpoints = FALSE;
6727
6728 #ifdef MONO_ARCH_SOFT_DEBUG_SUPPORTED
6729         if (invoke->has_ctx)
6730                 mono_set_lmf ((gpointer)(((gssize)ext.lmf.previous_lmf) & ~3));
6731 #endif
6732
6733         *endp = p;
6734         // FIXME: byref arguments
6735         // FIXME: varargs
6736         return ERR_NONE;
6737 }
6738
6739 /*
6740  * invoke_method:
6741  *
6742  *   Invoke the method given by tls->pending_invoke in the current thread.
6743  */
6744 static void
6745 invoke_method (void)
6746 {
6747         DebuggerTlsData *tls;
6748         InvokeData *invoke;
6749         int id;
6750         int i, err, mindex;
6751         Buffer buf;
6752         MonoContext restore_ctx;
6753         guint8 *p;
6754
6755         tls = mono_native_tls_get_value (debugger_tls_id);
6756         g_assert (tls);
6757
6758         /*
6759          * Store the `InvokeData *' in `tls->invoke' until we're done with
6760          * the invocation, so CMD_VM_ABORT_INVOKE can check it.
6761          */
6762
6763         mono_loader_lock ();
6764
6765         invoke = tls->pending_invoke;
6766         g_assert (invoke);
6767         tls->pending_invoke = NULL;
6768
6769         invoke->last_invoke = tls->invoke;
6770         tls->invoke = invoke;
6771
6772         mono_loader_unlock ();
6773
6774         tls->frames_up_to_date = FALSE;
6775
6776         id = invoke->id;
6777
6778         p = invoke->p;
6779         err = 0;
6780         for (mindex = 0; mindex < invoke->nmethods; ++mindex) {
6781                 buffer_init (&buf, 128);
6782
6783                 if (err) {
6784                         /* Fail the other invokes as well */
6785                 } else {
6786                         err = do_invoke_method (tls, &buf, invoke, p, &p);
6787                 }
6788
6789                 /* Start suspending before sending the reply */
6790                 if (mindex == invoke->nmethods - 1) {
6791                         if (!(invoke->flags & INVOKE_FLAG_SINGLE_THREADED)) {
6792                                 for (i = 0; i < invoke->suspend_count; ++i)
6793                                         suspend_vm ();
6794                         }
6795                 }
6796
6797                 send_reply_packet (id, err, &buf);
6798         
6799                 buffer_free (&buf);
6800         }
6801
6802         memcpy (&restore_ctx, &invoke->ctx, sizeof (MonoContext));
6803
6804         if (invoke->has_ctx)
6805                 save_thread_context (&restore_ctx);
6806
6807         if (invoke->flags & INVOKE_FLAG_SINGLE_THREADED) {
6808                 g_assert (tls->resume_count);
6809                 tls->resume_count -= invoke->suspend_count;
6810         }
6811
6812         DEBUG (1, fprintf (log_file, "[%p] Invoke finished (%d), resume_count = %d.\n", (gpointer)GetCurrentThreadId (), err, tls->resume_count));
6813
6814         /*
6815          * Take the loader lock to avoid race conditions with CMD_VM_ABORT_INVOKE:
6816          *
6817          * It is possible that ves_icall_System_Threading_Thread_Abort () was called
6818          * after the mono_runtime_invoke() already returned, but it doesn't matter
6819          * because we reset the abort here.
6820          */
6821
6822         mono_loader_lock ();
6823
6824         if (tls->abort_requested)
6825                 mono_thread_internal_reset_abort (tls->thread);
6826
6827         tls->invoke = tls->invoke->last_invoke;
6828         tls->abort_requested = FALSE;
6829
6830         mono_loader_unlock ();
6831
6832         g_free (invoke->p);
6833         g_free (invoke);
6834
6835         suspend_current ();
6836 }
6837
6838 static gboolean
6839 is_really_suspended (gpointer key, gpointer value, gpointer user_data)
6840 {
6841         MonoThread *thread = value;
6842         DebuggerTlsData *tls;
6843         gboolean res;
6844
6845         mono_loader_lock ();
6846         tls = mono_g_hash_table_lookup (thread_to_tls, thread);
6847         g_assert (tls);
6848         res = tls->really_suspended;
6849         mono_loader_unlock ();
6850
6851         return res;
6852 }
6853
6854 static GPtrArray*
6855 get_source_files_for_type (MonoClass *klass)
6856 {
6857         gpointer iter = NULL;
6858         MonoMethod *method;
6859         MonoDebugSourceInfo *sinfo;
6860         GPtrArray *files;
6861         int i, j;
6862
6863         files = g_ptr_array_new ();
6864
6865         while ((method = mono_class_get_methods (klass, &iter))) {
6866                 MonoDebugMethodInfo *minfo = mono_debug_lookup_method (method);
6867                 GPtrArray *source_file_list;
6868
6869                 if (minfo) {
6870                         mono_debug_symfile_get_line_numbers_full (minfo, NULL, &source_file_list, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
6871                         for (j = 0; j < source_file_list->len; ++j) {
6872                                 sinfo = g_ptr_array_index (source_file_list, j);
6873                                 for (i = 0; i < files->len; ++i)
6874                                         if (!strcmp (g_ptr_array_index (files, i), sinfo->source_file))
6875                                                 break;
6876                                 if (i == files->len)
6877                                         g_ptr_array_add (files, g_strdup (sinfo->source_file));
6878                         }
6879                         g_ptr_array_free (source_file_list, TRUE);
6880                 }
6881         }
6882
6883         return files;
6884 }
6885
6886 static ErrorCode
6887 vm_commands (int command, int id, guint8 *p, guint8 *end, Buffer *buf)
6888 {
6889         switch (command) {
6890         case CMD_VM_VERSION: {
6891                 char *build_info, *version;
6892
6893                 build_info = mono_get_runtime_build_info ();
6894                 version = g_strdup_printf ("mono %s", build_info);
6895
6896                 buffer_add_string (buf, version); /* vm version */
6897                 buffer_add_int (buf, MAJOR_VERSION);
6898                 buffer_add_int (buf, MINOR_VERSION);
6899                 g_free (build_info);
6900                 g_free (version);
6901                 break;
6902         }
6903         case CMD_VM_SET_PROTOCOL_VERSION: {
6904                 major_version = decode_int (p, &p, end);
6905                 minor_version = decode_int (p, &p, end);
6906                 protocol_version_set = TRUE;
6907                 DEBUG(1, fprintf (log_file, "[dbg] Protocol version %d.%d, client protocol version %d.%d.\n", MAJOR_VERSION, MINOR_VERSION, major_version, minor_version));
6908                 break;
6909         }
6910         case CMD_VM_ALL_THREADS: {
6911                 // FIXME: Domains
6912                 mono_loader_lock ();
6913                 buffer_add_int (buf, mono_g_hash_table_size (tid_to_thread_obj));
6914                 mono_g_hash_table_foreach (tid_to_thread_obj, add_thread, buf);
6915                 mono_loader_unlock ();
6916                 break;
6917         }
6918         case CMD_VM_SUSPEND:
6919                 suspend_vm ();
6920                 wait_for_suspend ();
6921                 break;
6922         case CMD_VM_RESUME:
6923                 if (suspend_count == 0)
6924                         return ERR_NOT_SUSPENDED;
6925                 resume_vm ();
6926                 clear_suspended_objs ();
6927                 break;
6928         case CMD_VM_DISPOSE:
6929                 /* Clear all event requests */
6930                 mono_loader_lock ();
6931                 while (event_requests->len > 0) {
6932                         EventRequest *req = g_ptr_array_index (event_requests, 0);
6933
6934                         clear_event_request (req->id, req->event_kind);
6935                 }
6936                 mono_loader_unlock ();
6937
6938                 while (suspend_count > 0)
6939                         resume_vm ();
6940                 disconnected = TRUE;
6941                 vm_start_event_sent = FALSE;
6942                 break;
6943         case CMD_VM_EXIT: {
6944                 MonoInternalThread *thread;
6945                 DebuggerTlsData *tls;
6946 #ifdef TRY_MANAGED_SYSTEM_ENVIRONMENT_EXIT
6947                 MonoClass *env_class;
6948 #endif
6949                 MonoMethod *exit_method = NULL;
6950                 gpointer *args;
6951                 int exit_code;
6952
6953                 exit_code = decode_int (p, &p, end);
6954
6955                 // FIXME: What if there is a VM_DEATH event request with SUSPEND_ALL ?
6956
6957                 /* Have to send a reply before exiting */
6958                 send_reply_packet (id, 0, buf);
6959
6960                 /* Clear all event requests */
6961                 mono_loader_lock ();
6962                 while (event_requests->len > 0) {
6963                         EventRequest *req = g_ptr_array_index (event_requests, 0);
6964
6965                         clear_event_request (req->id, req->event_kind);
6966                 }
6967                 mono_loader_unlock ();
6968
6969                 /*
6970                  * The JDWP documentation says that the shutdown is not orderly. It doesn't
6971                  * specify whenever a VM_DEATH event is sent. We currently do an orderly
6972                  * shutdown by hijacking a thread to execute Environment.Exit (). This is
6973                  * better than doing the shutdown ourselves, since it avoids various races.
6974                  */
6975
6976                 suspend_vm ();
6977                 wait_for_suspend ();
6978
6979 #ifdef TRY_MANAGED_SYSTEM_ENVIRONMENT_EXIT
6980                 env_class = mono_class_from_name (mono_defaults.corlib, "System", "Environment");
6981                 if (env_class)
6982                         exit_method = mono_class_get_method_from_name (env_class, "Exit", 1);
6983 #endif
6984
6985                 mono_loader_lock ();
6986                 thread = mono_g_hash_table_find (tid_to_thread, is_really_suspended, NULL);
6987                 mono_loader_unlock ();
6988
6989                 if (thread && exit_method) {
6990                         mono_loader_lock ();
6991                         tls = mono_g_hash_table_lookup (thread_to_tls, thread);
6992                         mono_loader_unlock ();
6993
6994                         args = g_new0 (gpointer, 1);
6995                         args [0] = g_malloc (sizeof (int));
6996                         *(int*)(args [0]) = exit_code;
6997
6998                         tls->pending_invoke = g_new0 (InvokeData, 1);
6999                         tls->pending_invoke->method = exit_method;
7000                         tls->pending_invoke->args = args;
7001                         tls->pending_invoke->nmethods = 1;
7002
7003                         while (suspend_count > 0)
7004                                 resume_vm ();
7005                 } else {
7006                         /* 
7007                          * No thread found, do it ourselves.
7008                          * FIXME: This can race with normal shutdown etc.
7009                          */
7010                         while (suspend_count > 0)
7011                                 resume_vm ();
7012
7013                         if (!mono_runtime_try_shutdown ())
7014                                 break;
7015
7016                         mono_environment_exitcode_set (exit_code);
7017
7018                         /* Suspend all managed threads since the runtime is going away */
7019                         DEBUG(1, fprintf (log_file, "Suspending all threads...\n"));
7020                         mono_thread_suspend_all_other_threads ();
7021                         DEBUG(1, fprintf (log_file, "Shutting down the runtime...\n"));
7022                         mono_runtime_quit ();
7023                         transport_close2 ();
7024                         DEBUG(1, fprintf (log_file, "Exiting...\n"));
7025
7026                         exit (exit_code);
7027                 }
7028                 break;
7029         }               
7030         case CMD_VM_INVOKE_METHOD:
7031         case CMD_VM_INVOKE_METHODS: {
7032                 int objid = decode_objid (p, &p, end);
7033                 MonoThread *thread;
7034                 DebuggerTlsData *tls;
7035                 int i, count, err, flags, nmethods;
7036
7037                 err = get_object (objid, (MonoObject**)&thread);
7038                 if (err)
7039                         return err;
7040
7041                 flags = decode_int (p, &p, end);
7042
7043                 if (command == CMD_VM_INVOKE_METHODS)
7044                         nmethods = decode_int (p, &p, end);
7045                 else
7046                         nmethods = 1;
7047
7048                 // Wait for suspending if it already started
7049                 if (suspend_count)
7050                         wait_for_suspend ();
7051                 if (!is_suspended ())
7052                         return ERR_NOT_SUSPENDED;
7053
7054                 mono_loader_lock ();
7055                 tls = mono_g_hash_table_lookup (thread_to_tls, THREAD_TO_INTERNAL (thread));
7056                 mono_loader_unlock ();
7057                 g_assert (tls);
7058
7059                 if (!tls->really_suspended)
7060                         /* The thread is still running native code, can't do invokes */
7061                         return ERR_NOT_SUSPENDED;
7062
7063                 /* 
7064                  * Store the invoke data into tls, the thread will execute it after it is
7065                  * resumed.
7066                  */
7067                 if (tls->pending_invoke)
7068                         return ERR_NOT_SUSPENDED;
7069                 tls->pending_invoke = g_new0 (InvokeData, 1);
7070                 tls->pending_invoke->id = id;
7071                 tls->pending_invoke->flags = flags;
7072                 tls->pending_invoke->p = g_malloc (end - p);
7073                 memcpy (tls->pending_invoke->p, p, end - p);
7074                 tls->pending_invoke->endp = tls->pending_invoke->p + (end - p);
7075                 tls->pending_invoke->suspend_count = suspend_count;
7076                 tls->pending_invoke->nmethods = nmethods;
7077
7078                 if (flags & INVOKE_FLAG_SINGLE_THREADED) {
7079                         resume_thread (THREAD_TO_INTERNAL (thread));
7080                 }
7081                 else {
7082                         count = suspend_count;
7083                         for (i = 0; i < count; ++i)
7084                                 resume_vm ();
7085                 }
7086                 break;
7087         }
7088         case CMD_VM_ABORT_INVOKE: {
7089                 int objid = decode_objid (p, &p, end);
7090                 MonoThread *thread;
7091                 DebuggerTlsData *tls;
7092                 int invoke_id, err;
7093
7094                 err = get_object (objid, (MonoObject**)&thread);
7095                 if (err)
7096                         return err;
7097
7098                 invoke_id = decode_int (p, &p, end);
7099
7100                 mono_loader_lock ();
7101                 tls = mono_g_hash_table_lookup (thread_to_tls, THREAD_TO_INTERNAL (thread));
7102                 g_assert (tls);
7103
7104                 if (tls->abort_requested) {
7105                         mono_loader_unlock ();
7106                         break;
7107                 }
7108
7109                 /*
7110                  * Check whether we're still inside the mono_runtime_invoke() and that it's
7111                  * actually the correct invocation.
7112                  *
7113                  * Careful, we do not stop the thread that's doing the invocation, so we can't
7114                  * inspect its stack.  However, invoke_method() also acquires the loader lock
7115                  * when it's done, so we're safe here.
7116                  *
7117                  */
7118
7119                 if (!tls->invoke || (tls->invoke->id != invoke_id)) {
7120                         mono_loader_unlock ();
7121                         return ERR_NO_INVOCATION;
7122                 }
7123
7124                 tls->abort_requested = TRUE;
7125
7126                 ves_icall_System_Threading_Thread_Abort (THREAD_TO_INTERNAL (thread), NULL);
7127                 mono_loader_unlock ();
7128                 break;
7129         }
7130
7131         case CMD_VM_SET_KEEPALIVE: {
7132                 int timeout = decode_int (p, &p, end);
7133                 agent_config.keepalive = timeout;
7134                 // FIXME:
7135 #ifndef DISABLE_SOCKET_TRANSPORT
7136                 set_keepalive ();
7137 #else
7138                 NOT_IMPLEMENTED;
7139 #endif
7140                 break;
7141         }
7142         case CMD_VM_GET_TYPES_FOR_SOURCE_FILE: {
7143                 GHashTableIter iter, kiter;
7144                 MonoDomain *domain;
7145                 MonoClass *klass;
7146                 GPtrArray *files;
7147                 int i;
7148                 char *fname, *basename;
7149                 gboolean ignore_case;
7150                 GSList *class_list, *l;
7151                 GPtrArray *res_classes, *res_domains;
7152
7153                 fname = decode_string (p, &p, end);
7154                 ignore_case = decode_byte (p, &p, end);
7155
7156                 basename = g_path_get_basename (fname);
7157
7158                 res_classes = g_ptr_array_new ();
7159                 res_domains = g_ptr_array_new ();
7160
7161                 mono_loader_lock ();
7162                 g_hash_table_iter_init (&iter, domains);
7163                 while (g_hash_table_iter_next (&iter, NULL, (void**)&domain)) {
7164                         AgentDomainInfo *info = domain_jit_info (domain)->agent_info;
7165
7166                         /* Update 'source_file_to_class' cache */
7167                         g_hash_table_iter_init (&kiter, info->loaded_classes);
7168                         while (g_hash_table_iter_next (&kiter, NULL, (void**)&klass)) {
7169                                 if (!g_hash_table_lookup (info->source_files, klass)) {
7170                                         files = get_source_files_for_type (klass);
7171                                         g_hash_table_insert (info->source_files, klass, files);
7172
7173                                         for (i = 0; i < files->len; ++i) {
7174                                                 char *s = g_ptr_array_index (files, i);
7175                                                 char *s2 = g_path_get_basename (s);
7176                                                 char *s3;
7177
7178                                                 class_list = g_hash_table_lookup (info->source_file_to_class, s2);
7179                                                 if (!class_list) {
7180                                                         class_list = g_slist_prepend (class_list, klass);
7181                                                         g_hash_table_insert (info->source_file_to_class, g_strdup (s2), class_list);
7182                                                 } else {
7183                                                         class_list = g_slist_prepend (class_list, klass);
7184                                                         g_hash_table_insert (info->source_file_to_class, s2, class_list);
7185                                                 }
7186
7187                                                 /* The _ignorecase hash contains the lowercase path */
7188                                                 s3 = strdup_tolower (s2);
7189                                                 class_list = g_hash_table_lookup (info->source_file_to_class_ignorecase, s3);
7190                                                 if (!class_list) {
7191                                                         class_list = g_slist_prepend (class_list, klass);
7192                                                         g_hash_table_insert (info->source_file_to_class_ignorecase, g_strdup (s3), class_list);
7193                                                 } else {
7194                                                         class_list = g_slist_prepend (class_list, klass);
7195                                                         g_hash_table_insert (info->source_file_to_class_ignorecase, s3, class_list);
7196                                                 }
7197
7198                                                 g_free (s2);
7199                                                 g_free (s3);
7200                                         }
7201                                 }
7202                         }
7203
7204                         if (ignore_case) {
7205                                 char *s;
7206
7207                                 s = strdup_tolower (basename);
7208                                 class_list = g_hash_table_lookup (info->source_file_to_class_ignorecase, s);
7209                                 g_free (s);
7210                         } else {
7211                                 class_list = g_hash_table_lookup (info->source_file_to_class, basename);
7212                         }
7213
7214                         for (l = class_list; l; l = l->next) {
7215                                 klass = l->data;
7216
7217                                 g_ptr_array_add (res_classes, klass);
7218                                 g_ptr_array_add (res_domains, domain);
7219                         }
7220                 }
7221                 mono_loader_unlock ();
7222
7223                 g_free (fname);
7224                 g_free (basename);
7225
7226                 buffer_add_int (buf, res_classes->len);
7227                 for (i = 0; i < res_classes->len; ++i)
7228                         buffer_add_typeid (buf, g_ptr_array_index (res_domains, i), g_ptr_array_index (res_classes, i));
7229                 g_ptr_array_free (res_classes, TRUE);
7230                 g_ptr_array_free (res_domains, TRUE);
7231                 break;
7232         }
7233         case CMD_VM_GET_TYPES: {
7234                 GHashTableIter iter;
7235                 MonoDomain *domain;
7236                 int i;
7237                 char *name;
7238                 gboolean ignore_case;
7239                 GPtrArray *res_classes, *res_domains;
7240                 MonoTypeNameParse info;
7241
7242                 name = decode_string (p, &p, end);
7243                 ignore_case = decode_byte (p, &p, end);
7244
7245                 if (!mono_reflection_parse_type (name, &info)) {
7246                         g_free (name);
7247                         mono_reflection_free_type_info (&info);
7248                         return ERR_INVALID_ARGUMENT;
7249                 }
7250
7251                 res_classes = g_ptr_array_new ();
7252                 res_domains = g_ptr_array_new ();
7253
7254                 mono_loader_lock ();
7255                 g_hash_table_iter_init (&iter, domains);
7256                 while (g_hash_table_iter_next (&iter, NULL, (void**)&domain)) {
7257                         MonoAssembly *ass;
7258                         gboolean type_resolve;
7259                         MonoType *t;
7260                         GSList *tmp;
7261
7262                         mono_domain_assemblies_lock (domain);
7263                         for (tmp = domain->domain_assemblies; tmp; tmp = tmp->next) {
7264                                 ass = tmp->data;
7265
7266                                 if (ass->image) {
7267                                         type_resolve = TRUE;
7268                                         t = mono_reflection_get_type (ass->image, &info, ignore_case, &type_resolve);
7269                                         if (t) {
7270                                                 g_ptr_array_add (res_classes, mono_type_get_class (t));
7271                                                 g_ptr_array_add (res_domains, domain);
7272                                         }
7273                                 }
7274                         }
7275                         mono_domain_assemblies_unlock (domain);
7276                 }
7277                 mono_loader_unlock ();
7278
7279                 g_free (name);
7280                 mono_reflection_free_type_info (&info);
7281
7282                 buffer_add_int (buf, res_classes->len);
7283                 for (i = 0; i < res_classes->len; ++i)
7284                         buffer_add_typeid (buf, g_ptr_array_index (res_domains, i), g_ptr_array_index (res_classes, i));
7285                 g_ptr_array_free (res_classes, TRUE);
7286                 g_ptr_array_free (res_domains, TRUE);
7287                 break;
7288         }
7289         case CMD_VM_START_BUFFERING:
7290         case CMD_VM_STOP_BUFFERING:
7291                 /* Handled in the main loop */
7292                 break;
7293         default:
7294                 return ERR_NOT_IMPLEMENTED;
7295         }
7296
7297         return ERR_NONE;
7298 }
7299
7300 static ErrorCode
7301 event_commands (int command, guint8 *p, guint8 *end, Buffer *buf)
7302 {
7303         int err;
7304         MonoError error;
7305
7306         switch (command) {
7307         case CMD_EVENT_REQUEST_SET: {
7308                 EventRequest *req;
7309                 int i, event_kind, suspend_policy, nmodifiers, mod;
7310                 MonoMethod *method;
7311                 long location = 0;
7312                 MonoThread *step_thread;
7313                 int size = 0, depth = 0, filter = 0, step_thread_id = 0;
7314                 MonoDomain *domain;
7315                 Modifier *modifier;
7316
7317                 event_kind = decode_byte (p, &p, end);
7318                 suspend_policy = decode_byte (p, &p, end);
7319                 nmodifiers = decode_byte (p, &p, end);
7320
7321                 req = g_malloc0 (sizeof (EventRequest) + (nmodifiers * sizeof (Modifier)));
7322                 req->id = InterlockedIncrement (&event_request_id);
7323                 req->event_kind = event_kind;
7324                 req->suspend_policy = suspend_policy;
7325                 req->nmodifiers = nmodifiers;
7326
7327                 method = NULL;
7328                 for (i = 0; i < nmodifiers; ++i) {
7329                         mod = decode_byte (p, &p, end);
7330
7331                         req->modifiers [i].kind = mod;
7332                         if (mod == MOD_KIND_COUNT) {
7333                                 req->modifiers [i].data.count = decode_int (p, &p, end);
7334                         } else if (mod == MOD_KIND_LOCATION_ONLY) {
7335                                 method = decode_methodid (p, &p, end, &domain, &err);
7336                                 if (err)
7337                                         return err;
7338                                 location = decode_long (p, &p, end);
7339                         } else if (mod == MOD_KIND_STEP) {
7340                                 step_thread_id = decode_id (p, &p, end);
7341                                 size = decode_int (p, &p, end);
7342                                 depth = decode_int (p, &p, end);
7343                                 if (CHECK_PROTOCOL_VERSION (2, 16))
7344                                         filter = decode_int (p, &p, end);
7345                                 req->modifiers [i].data.filter = filter;
7346                                 if (!CHECK_PROTOCOL_VERSION (2, 26) && (req->modifiers [i].data.filter & STEP_FILTER_DEBUGGER_HIDDEN))
7347                                         /* Treat STEP_THOUGH the same as HIDDEN */
7348                                         req->modifiers [i].data.filter |= STEP_FILTER_DEBUGGER_STEP_THROUGH;
7349                         } else if (mod == MOD_KIND_THREAD_ONLY) {
7350                                 int id = decode_id (p, &p, end);
7351
7352                                 err = get_object (id, (MonoObject**)&req->modifiers [i].data.thread);
7353                                 if (err) {
7354                                         g_free (req);
7355                                         return err;
7356                                 }
7357                         } else if (mod == MOD_KIND_EXCEPTION_ONLY) {
7358                                 MonoClass *exc_class = decode_typeid (p, &p, end, &domain, &err);
7359
7360                                 if (err)
7361                                         return err;
7362                                 req->modifiers [i].caught = decode_byte (p, &p, end);
7363                                 req->modifiers [i].uncaught = decode_byte (p, &p, end);
7364                                 if (CHECK_PROTOCOL_VERSION (2, 25))
7365                                         req->modifiers [i].subclasses = decode_byte (p, &p, end);
7366                                 else
7367                                         req->modifiers [i].subclasses = TRUE;
7368                                 DEBUG(1, fprintf (log_file, "[dbg] \tEXCEPTION_ONLY filter (%s%s%s%s).\n", exc_class ? exc_class->name : "all", req->modifiers [i].caught ? ", caught" : "", req->modifiers [i].uncaught ? ", uncaught" : "", req->modifiers [i].subclasses ? ", include-subclasses" : ""));
7369                                 if (exc_class) {
7370                                         req->modifiers [i].data.exc_class = exc_class;
7371
7372                                         if (!mono_class_is_assignable_from (mono_defaults.exception_class, exc_class)) {
7373                                                 g_free (req);
7374                                                 return ERR_INVALID_ARGUMENT;
7375                                         }
7376                                 }
7377                         } else if (mod == MOD_KIND_ASSEMBLY_ONLY) {
7378                                 int n = decode_int (p, &p, end);
7379                                 int j;
7380
7381                                 req->modifiers [i].data.assemblies = g_new0 (MonoAssembly*, n);
7382                                 for (j = 0; j < n; ++j) {
7383                                         req->modifiers [i].data.assemblies [j] = decode_assemblyid (p, &p, end, &domain, &err);
7384                                         if (err) {
7385                                                 g_free (req->modifiers [i].data.assemblies);
7386                                                 return err;
7387                                         }
7388                                 }
7389                         } else if (mod == MOD_KIND_SOURCE_FILE_ONLY) {
7390                                 int n = decode_int (p, &p, end);
7391                                 int j;
7392
7393                                 modifier = &req->modifiers [i];
7394                                 modifier->data.source_files = g_hash_table_new (g_str_hash, g_str_equal);
7395                                 for (j = 0; j < n; ++j) {
7396                                         char *s = decode_string (p, &p, end);
7397                                         char *s2;
7398
7399                                         if (s) {
7400                                                 s2 = strdup_tolower (s);
7401                                                 g_hash_table_insert (modifier->data.source_files, s2, s2);
7402                                                 g_free (s);
7403                                         }
7404                                 }
7405                         } else if (mod == MOD_KIND_TYPE_NAME_ONLY) {
7406                                 int n = decode_int (p, &p, end);
7407                                 int j;
7408
7409                                 modifier = &req->modifiers [i];
7410                                 modifier->data.type_names = g_hash_table_new (g_str_hash, g_str_equal);
7411                                 for (j = 0; j < n; ++j) {
7412                                         char *s = decode_string (p, &p, end);
7413
7414                                         if (s)
7415                                                 g_hash_table_insert (modifier->data.type_names, s, s);
7416                                 }
7417                         } else {
7418                                 g_free (req);
7419                                 return ERR_NOT_IMPLEMENTED;
7420                         }
7421                 }
7422
7423                 if (req->event_kind == EVENT_KIND_BREAKPOINT) {
7424                         g_assert (method);
7425
7426                         req->info = set_breakpoint (method, location, req, &error);
7427                         if (!mono_error_ok (&error)) {
7428                                 g_free (req);
7429                                 DEBUG(1, fprintf (log_file, "[dbg] Failed to set breakpoint: %s\n", mono_error_get_message (&error)));
7430                                 mono_error_cleanup (&error);
7431                                 return ERR_NO_SEQ_POINT_AT_IL_OFFSET;
7432                         }
7433                 } else if (req->event_kind == EVENT_KIND_STEP) {
7434                         g_assert (step_thread_id);
7435
7436                         err = get_object (step_thread_id, (MonoObject**)&step_thread);
7437                         if (err) {
7438                                 g_free (req);
7439                                 return err;
7440                         }
7441
7442                         err = ss_create (THREAD_TO_INTERNAL (step_thread), size, depth, req);
7443                         if (err) {
7444                                 g_free (req);
7445                                 return err;
7446                         }
7447                 } else if (req->event_kind == EVENT_KIND_METHOD_ENTRY) {
7448                         req->info = set_breakpoint (NULL, METHOD_ENTRY_IL_OFFSET, req, NULL);
7449                 } else if (req->event_kind == EVENT_KIND_METHOD_EXIT) {
7450                         req->info = set_breakpoint (NULL, METHOD_EXIT_IL_OFFSET, req, NULL);
7451                 } else if (req->event_kind == EVENT_KIND_EXCEPTION) {
7452                 } else if (req->event_kind == EVENT_KIND_TYPE_LOAD) {
7453                 } else {
7454                         if (req->nmodifiers) {
7455                                 g_free (req);
7456                                 return ERR_NOT_IMPLEMENTED;
7457                         }
7458                 }
7459
7460                 mono_loader_lock ();
7461                 g_ptr_array_add (event_requests, req);
7462                 
7463                 if (agent_config.defer) {
7464                         /* Transmit cached data to the client on receipt of the event request */
7465                         switch (req->event_kind) {
7466                         case EVENT_KIND_APPDOMAIN_CREATE:
7467                                 /* Emit load events for currently loaded domains */
7468                                 g_hash_table_foreach (domains, emit_appdomain_load, NULL);
7469                                 break;
7470                         case EVENT_KIND_ASSEMBLY_LOAD:
7471                                 /* Emit load events for currently loaded assemblies */
7472                                 mono_assembly_foreach (emit_assembly_load, NULL);
7473                                 break;
7474                         case EVENT_KIND_THREAD_START:
7475                                 /* Emit start events for currently started threads */
7476                                 mono_g_hash_table_foreach (tid_to_thread, emit_thread_start, NULL);
7477                                 break;
7478                         case EVENT_KIND_TYPE_LOAD:
7479                                 /* Emit type load events for currently loaded types */
7480                                 mono_domain_foreach (send_types_for_domain, NULL);
7481                                 break;
7482                         default:
7483                                 break;
7484                         }
7485                 }
7486                 mono_loader_unlock ();
7487
7488                 buffer_add_int (buf, req->id);
7489                 break;
7490         }
7491         case CMD_EVENT_REQUEST_CLEAR: {
7492                 int etype = decode_byte (p, &p, end);
7493                 int req_id = decode_int (p, &p, end);
7494
7495                 // FIXME: Make a faster mapping from req_id to request
7496                 mono_loader_lock ();
7497                 clear_event_request (req_id, etype);
7498                 mono_loader_unlock ();
7499                 break;
7500         }
7501         case CMD_EVENT_REQUEST_CLEAR_ALL_BREAKPOINTS: {
7502                 int i;
7503
7504                 mono_loader_lock ();
7505                 i = 0;
7506                 while (i < event_requests->len) {
7507                         EventRequest *req = g_ptr_array_index (event_requests, i);
7508
7509                         if (req->event_kind == EVENT_KIND_BREAKPOINT) {
7510                                 clear_breakpoint (req->info);
7511
7512                                 g_ptr_array_remove_index_fast (event_requests, i);
7513                                 g_free (req);
7514                         } else {
7515                                 i ++;
7516                         }
7517                 }
7518                 mono_loader_unlock ();
7519                 break;
7520         }
7521         default:
7522                 return ERR_NOT_IMPLEMENTED;
7523         }
7524
7525         return ERR_NONE;
7526 }
7527
7528 static ErrorCode
7529 domain_commands (int command, guint8 *p, guint8 *end, Buffer *buf)
7530 {
7531         int err;
7532         MonoDomain *domain;
7533
7534         switch (command) {
7535         case CMD_APPDOMAIN_GET_ROOT_DOMAIN: {
7536                 buffer_add_domainid (buf, mono_get_root_domain ());
7537                 break;
7538         }
7539         case CMD_APPDOMAIN_GET_FRIENDLY_NAME: {
7540                 domain = decode_domainid (p, &p, end, NULL, &err);
7541                 if (err)
7542                         return err;
7543                 buffer_add_string (buf, domain->friendly_name);
7544                 break;
7545         }
7546         case CMD_APPDOMAIN_GET_ASSEMBLIES: {
7547                 GSList *tmp;
7548                 MonoAssembly *ass;
7549                 int count;
7550
7551                 domain = decode_domainid (p, &p, end, NULL, &err);
7552                 if (err)
7553                         return err;
7554                 mono_loader_lock ();
7555                 count = 0;
7556                 for (tmp = domain->domain_assemblies; tmp; tmp = tmp->next) {
7557                         count ++;
7558                 }
7559                 buffer_add_int (buf, count);
7560                 for (tmp = domain->domain_assemblies; tmp; tmp = tmp->next) {
7561                         ass = tmp->data;
7562                         buffer_add_assemblyid (buf, domain, ass);
7563                 }
7564                 mono_loader_unlock ();
7565                 break;
7566         }
7567         case CMD_APPDOMAIN_GET_ENTRY_ASSEMBLY: {
7568                 domain = decode_domainid (p, &p, end, NULL, &err);
7569                 if (err)
7570                         return err;
7571
7572                 buffer_add_assemblyid (buf, domain, domain->entry_assembly);
7573                 break;
7574         }
7575         case CMD_APPDOMAIN_GET_CORLIB: {
7576                 domain = decode_domainid (p, &p, end, NULL, &err);
7577                 if (err)
7578                         return err;
7579
7580                 buffer_add_assemblyid (buf, domain, domain->domain->mbr.obj.vtable->klass->image->assembly);
7581                 break;
7582         }
7583         case CMD_APPDOMAIN_CREATE_STRING: {
7584                 char *s;
7585                 MonoString *o;
7586
7587                 domain = decode_domainid (p, &p, end, NULL, &err);
7588                 if (err)
7589                         return err;
7590                 s = decode_string (p, &p, end);
7591
7592                 o = mono_string_new (domain, s);
7593                 buffer_add_objid (buf, (MonoObject*)o);
7594                 break;
7595         }
7596         case CMD_APPDOMAIN_CREATE_BOXED_VALUE: {
7597                 MonoClass *klass;
7598                 MonoDomain *domain2;
7599                 MonoObject *o;
7600
7601                 domain = decode_domainid (p, &p, end, NULL, &err);
7602                 if (err)
7603                         return err;
7604                 klass = decode_typeid (p, &p, end, &domain2, &err);
7605                 if (err)
7606                         return err;
7607
7608                 // FIXME:
7609                 g_assert (domain == domain2);
7610
7611                 o = mono_object_new (domain, klass);
7612
7613                 err = decode_value (&klass->byval_arg, domain, mono_object_unbox (o), p, &p, end);
7614                 if (err)
7615                         return err;
7616
7617                 buffer_add_objid (buf, o);
7618                 break;
7619         }
7620         default:
7621                 return ERR_NOT_IMPLEMENTED;
7622         }
7623
7624         return ERR_NONE;
7625 }
7626
7627 static ErrorCode
7628 assembly_commands (int command, guint8 *p, guint8 *end, Buffer *buf)
7629 {
7630         int err;
7631         MonoAssembly *ass;
7632         MonoDomain *domain;
7633
7634         ass = decode_assemblyid (p, &p, end, &domain, &err);
7635         if (err)
7636                 return err;
7637
7638         switch (command) {
7639         case CMD_ASSEMBLY_GET_LOCATION: {
7640                 buffer_add_string (buf, mono_image_get_filename (ass->image));
7641                 break;                  
7642         }
7643         case CMD_ASSEMBLY_GET_ENTRY_POINT: {
7644                 guint32 token;
7645                 MonoMethod *m;
7646
7647                 if (ass->image->dynamic) {
7648                         buffer_add_id (buf, 0);
7649                 } else {
7650                         token = mono_image_get_entry_point (ass->image);
7651                         if (token == 0) {
7652                                 buffer_add_id (buf, 0);
7653                         } else {
7654                                 m = mono_get_method (ass->image, token, NULL);
7655                                 buffer_add_methodid (buf, domain, m);
7656                         }
7657                 }
7658                 break;                  
7659         }
7660         case CMD_ASSEMBLY_GET_MANIFEST_MODULE: {
7661                 buffer_add_moduleid (buf, domain, ass->image);
7662                 break;
7663         }
7664         case CMD_ASSEMBLY_GET_OBJECT: {
7665                 MonoObject *o = (MonoObject*)mono_assembly_get_object (domain, ass);
7666                 buffer_add_objid (buf, o);
7667                 break;
7668         }
7669         case CMD_ASSEMBLY_GET_TYPE: {
7670                 char *s = decode_string (p, &p, end);
7671                 gboolean ignorecase = decode_byte (p, &p, end);
7672                 MonoTypeNameParse info;
7673                 MonoType *t;
7674                 gboolean type_resolve, res;
7675                 MonoDomain *d = mono_domain_get ();
7676
7677                 /* This is needed to be able to find referenced assemblies */
7678                 res = mono_domain_set (domain, FALSE);
7679                 g_assert (res);
7680
7681                 if (!mono_reflection_parse_type (s, &info)) {
7682                         t = NULL;
7683                 } else {
7684                         if (info.assembly.name)
7685                                 NOT_IMPLEMENTED;
7686                         t = mono_reflection_get_type (ass->image, &info, ignorecase, &type_resolve);
7687                 }
7688                 buffer_add_typeid (buf, domain, t ? mono_class_from_mono_type (t) : NULL);
7689                 mono_reflection_free_type_info (&info);
7690                 g_free (s);
7691
7692                 mono_domain_set (d, TRUE);
7693
7694                 break;
7695         }
7696         case CMD_ASSEMBLY_GET_NAME: {
7697                 gchar *name;
7698                 MonoAssembly *mass = ass;
7699
7700                 name = g_strdup_printf (
7701                   "%s, Version=%d.%d.%d.%d, Culture=%s, PublicKeyToken=%s%s",
7702                   mass->aname.name,
7703                   mass->aname.major, mass->aname.minor, mass->aname.build, mass->aname.revision,
7704                   mass->aname.culture && *mass->aname.culture? mass->aname.culture: "neutral",
7705                   mass->aname.public_key_token [0] ? (char *)mass->aname.public_key_token : "null",
7706                   (mass->aname.flags & ASSEMBLYREF_RETARGETABLE_FLAG) ? ", Retargetable=Yes" : "");
7707
7708                 buffer_add_string (buf, name);
7709                 g_free (name);
7710                 break;
7711         }
7712         default:
7713                 return ERR_NOT_IMPLEMENTED;
7714         }
7715
7716         return ERR_NONE;
7717 }
7718
7719 static ErrorCode
7720 module_commands (int command, guint8 *p, guint8 *end, Buffer *buf)
7721 {
7722         int err;
7723         MonoDomain *domain;
7724
7725         switch (command) {
7726         case CMD_MODULE_GET_INFO: {
7727                 MonoImage *image = decode_moduleid (p, &p, end, &domain, &err);
7728                 char *basename;
7729
7730                 basename = g_path_get_basename (image->name);
7731                 buffer_add_string (buf, basename); // name
7732                 buffer_add_string (buf, image->module_name); // scopename
7733                 buffer_add_string (buf, image->name); // fqname
7734                 buffer_add_string (buf, mono_image_get_guid (image)); // guid
7735                 buffer_add_assemblyid (buf, domain, image->assembly); // assembly
7736                 g_free (basename);
7737                 break;                  
7738         }
7739         default:
7740                 return ERR_NOT_IMPLEMENTED;
7741         }
7742
7743         return ERR_NONE;
7744 }
7745
7746 static ErrorCode
7747 field_commands (int command, guint8 *p, guint8 *end, Buffer *buf)
7748 {
7749         int err;
7750         MonoDomain *domain;
7751
7752         switch (command) {
7753         case CMD_FIELD_GET_INFO: {
7754                 MonoClassField *f = decode_fieldid (p, &p, end, &domain, &err);
7755
7756                 buffer_add_string (buf, f->name);
7757                 buffer_add_typeid (buf, domain, f->parent);
7758                 buffer_add_typeid (buf, domain, mono_class_from_mono_type (f->type));
7759                 buffer_add_int (buf, f->type->attrs);
7760                 break;
7761         }
7762         default:
7763                 return ERR_NOT_IMPLEMENTED;
7764         }
7765
7766         return ERR_NONE;
7767 }
7768
7769 static void
7770 buffer_add_cattr_arg (Buffer *buf, MonoType *t, MonoDomain *domain, MonoObject *val)
7771 {
7772         if (val && val->vtable->klass == mono_defaults.monotype_class) {
7773                 /* Special case these so the client doesn't have to handle Type objects */
7774                 
7775                 buffer_add_byte (buf, VALUE_TYPE_ID_TYPE);
7776                 buffer_add_typeid (buf, domain, mono_class_from_mono_type (((MonoReflectionType*)val)->type));
7777         } else if (MONO_TYPE_IS_REFERENCE (t))
7778                 buffer_add_value (buf, t, &val, domain);
7779         else
7780                 buffer_add_value (buf, t, mono_object_unbox (val), domain);
7781 }
7782
7783 static int
7784 buffer_add_cattrs (Buffer *buf, MonoDomain *domain, MonoImage *image, MonoClass *attr_klass, MonoCustomAttrInfo *cinfo)
7785 {
7786         int i, j;
7787         int nattrs = 0;
7788
7789         if (!cinfo) {
7790                 buffer_add_int (buf, 0);
7791                 return ERR_NONE;
7792         }
7793
7794         for (i = 0; i < cinfo->num_attrs; ++i) {
7795                 if (!attr_klass || mono_class_has_parent (cinfo->attrs [i].ctor->klass, attr_klass))
7796                         nattrs ++;
7797         }
7798         buffer_add_int (buf, nattrs);
7799
7800         for (i = 0; i < cinfo->num_attrs; ++i) {
7801                 MonoCustomAttrEntry *attr = &cinfo->attrs [i];
7802                 if (!attr_klass || mono_class_has_parent (attr->ctor->klass, attr_klass)) {
7803                         MonoArray *typed_args, *named_args;
7804                         MonoType *t;
7805                         CattrNamedArg *arginfo = NULL;
7806                         MonoError error;
7807
7808                         mono_reflection_create_custom_attr_data_args (image, attr->ctor, attr->data, attr->data_size, &typed_args, &named_args, &arginfo, &error);
7809                         if (!mono_error_ok (&error)) {
7810                                 DEBUG(2, fprintf (log_file, "[dbg] mono_reflection_create_custom_attr_data_args () failed with: '%s'\n", mono_error_get_message (&error)));
7811                                 mono_error_cleanup (&error);
7812                                 return ERR_LOADER_ERROR;
7813                         }
7814
7815                         buffer_add_methodid (buf, domain, attr->ctor);
7816
7817                         /* Ctor args */
7818                         if (typed_args) {
7819                                 buffer_add_int (buf, mono_array_length (typed_args));
7820                                 for (j = 0; j < mono_array_length (typed_args); ++j) {
7821                                         MonoObject *val = mono_array_get (typed_args, MonoObject*, j);
7822
7823                                         t = mono_method_signature (attr->ctor)->params [j];
7824
7825                                         buffer_add_cattr_arg (buf, t, domain, val);
7826                                 }
7827                         } else {
7828                                 buffer_add_int (buf, 0);
7829                         }
7830
7831                         /* Named args */
7832                         if (named_args) {
7833                                 buffer_add_int (buf, mono_array_length (named_args));
7834
7835                                 for (j = 0; j < mono_array_length (named_args); ++j) {
7836                                         MonoObject *val = mono_array_get (named_args, MonoObject*, j);
7837
7838                                         if (arginfo [j].prop) {
7839                                                 buffer_add_byte (buf, 0x54);
7840                                                 buffer_add_propertyid (buf, domain, arginfo [j].prop);
7841                                         } else if (arginfo [j].field) {
7842                                                 buffer_add_byte (buf, 0x53);
7843                                                 buffer_add_fieldid (buf, domain, arginfo [j].field);
7844                                         } else {
7845                                                 g_assert_not_reached ();
7846                                         }
7847
7848                                         buffer_add_cattr_arg (buf, arginfo [j].type, domain, val);
7849                                 }
7850                         } else {
7851                                 buffer_add_int (buf, 0);
7852                         }
7853                         g_free (arginfo);
7854                 }
7855         }
7856
7857         return ERR_NONE;
7858 }
7859
7860 /* FIXME: Code duplication with icall.c */
7861 static void
7862 collect_interfaces (MonoClass *klass, GHashTable *ifaces, MonoError *error)
7863 {
7864         int i;
7865         MonoClass *ic;
7866
7867         mono_class_setup_interfaces (klass, error);
7868         if (!mono_error_ok (error))
7869                 return;
7870
7871         for (i = 0; i < klass->interface_count; i++) {
7872                 ic = klass->interfaces [i];
7873                 g_hash_table_insert (ifaces, ic, ic);
7874
7875                 collect_interfaces (ic, ifaces, error);
7876                 if (!mono_error_ok (error))
7877                         return;
7878         }
7879 }
7880
7881 static ErrorCode
7882 type_commands_internal (int command, MonoClass *klass, MonoDomain *domain, guint8 *p, guint8 *end, Buffer *buf)
7883 {
7884         MonoClass *nested;
7885         MonoType *type;
7886         gpointer iter;
7887         guint8 b;
7888         int err, nnested;
7889         char *name;
7890
7891         switch (command) {
7892         case CMD_TYPE_GET_INFO: {
7893                 buffer_add_string (buf, klass->name_space);
7894                 buffer_add_string (buf, klass->name);
7895                 // FIXME: byref
7896                 name = mono_type_get_name_full (&klass->byval_arg, MONO_TYPE_NAME_FORMAT_FULL_NAME);
7897                 buffer_add_string (buf, name);
7898                 g_free (name);
7899                 buffer_add_assemblyid (buf, domain, klass->image->assembly);
7900                 buffer_add_moduleid (buf, domain, klass->image);
7901                 buffer_add_typeid (buf, domain, klass->parent);
7902                 if (klass->rank || klass->byval_arg.type == MONO_TYPE_PTR)
7903                         buffer_add_typeid (buf, domain, klass->element_class);
7904                 else
7905                         buffer_add_id (buf, 0);
7906                 buffer_add_int (buf, klass->type_token);
7907                 buffer_add_byte (buf, klass->rank);
7908                 buffer_add_int (buf, klass->flags);
7909                 b = 0;
7910                 type = &klass->byval_arg;
7911                 // FIXME: Can't decide whenever a class represents a byref type
7912                 if (FALSE)
7913                         b |= (1 << 0);
7914                 if (type->type == MONO_TYPE_PTR)
7915                         b |= (1 << 1);
7916                 if (!type->byref && (((type->type >= MONO_TYPE_BOOLEAN) && (type->type <= MONO_TYPE_R8)) || (type->type == MONO_TYPE_I) || (type->type == MONO_TYPE_U)))
7917                         b |= (1 << 2);
7918                 if (type->type == MONO_TYPE_VALUETYPE)
7919                         b |= (1 << 3);
7920                 if (klass->enumtype)
7921                         b |= (1 << 4);
7922                 if (klass->generic_container)
7923                         b |= (1 << 5);
7924                 if (klass->generic_container || klass->generic_class)
7925                         b |= (1 << 6);
7926                 buffer_add_byte (buf, b);
7927                 nnested = 0;
7928                 iter = NULL;
7929                 while ((nested = mono_class_get_nested_types (klass, &iter)))
7930                         nnested ++;
7931                 buffer_add_int (buf, nnested);
7932                 iter = NULL;
7933                 while ((nested = mono_class_get_nested_types (klass, &iter)))
7934                         buffer_add_typeid (buf, domain, nested);
7935                 if (CHECK_PROTOCOL_VERSION (2, 12)) {
7936                         if (klass->generic_container)
7937                                 buffer_add_typeid (buf, domain, klass);
7938                         else if (klass->generic_class)
7939                                 buffer_add_typeid (buf, domain, klass->generic_class->container_class);
7940                         else
7941                                 buffer_add_id (buf, 0);
7942                 }
7943                 if (CHECK_PROTOCOL_VERSION (2, 15)) {
7944                         int count, i;
7945
7946                         if (klass->generic_class) {
7947                                 MonoGenericInst *inst = klass->generic_class->context.class_inst;
7948
7949                                 count = inst->type_argc;
7950                                 buffer_add_int (buf, count);
7951                                 for (i = 0; i < count; i++)
7952                                         buffer_add_typeid (buf, domain, mono_class_from_mono_type (inst->type_argv [i]));
7953                         } else if (klass->generic_container) {
7954                                 MonoGenericContainer *container = klass->generic_container;
7955                                 MonoClass *pklass;
7956
7957                                 count = container->type_argc;
7958                                 buffer_add_int (buf, count);
7959                                 for (i = 0; i < count; i++) {
7960                                         pklass = mono_class_from_generic_parameter (mono_generic_container_get_param (container, i), klass->image, FALSE);
7961                                         buffer_add_typeid (buf, domain, pklass);
7962                                 }
7963                         } else {
7964                                 buffer_add_int (buf, 0);
7965                         }
7966                 }
7967                 break;
7968         }
7969         case CMD_TYPE_GET_METHODS: {
7970                 int nmethods;
7971                 int i = 0;
7972                 gpointer iter = NULL;
7973                 MonoMethod *m;
7974
7975                 mono_class_setup_methods (klass);
7976
7977                 nmethods = mono_class_num_methods (klass);
7978
7979                 buffer_add_int (buf, nmethods);
7980
7981                 while ((m = mono_class_get_methods (klass, &iter))) {
7982                         buffer_add_methodid (buf, domain, m);
7983                         i ++;
7984                 }
7985                 g_assert (i == nmethods);
7986                 break;
7987         }
7988         case CMD_TYPE_GET_FIELDS: {
7989                 int nfields;
7990                 int i = 0;
7991                 gpointer iter = NULL;
7992                 MonoClassField *f;
7993
7994                 nfields = mono_class_num_fields (klass);
7995
7996                 buffer_add_int (buf, nfields);
7997
7998                 while ((f = mono_class_get_fields (klass, &iter))) {
7999                         buffer_add_fieldid (buf, domain, f);
8000                         buffer_add_string (buf, f->name);
8001                         buffer_add_typeid (buf, domain, mono_class_from_mono_type (f->type));
8002                         buffer_add_int (buf, f->type->attrs);
8003                         i ++;
8004                 }
8005                 g_assert (i == nfields);
8006                 break;
8007         }
8008         case CMD_TYPE_GET_PROPERTIES: {
8009                 int nprops;
8010                 int i = 0;
8011                 gpointer iter = NULL;
8012                 MonoProperty *p;
8013
8014                 nprops = mono_class_num_properties (klass);
8015
8016                 buffer_add_int (buf, nprops);
8017
8018                 while ((p = mono_class_get_properties (klass, &iter))) {
8019                         buffer_add_propertyid (buf, domain, p);
8020                         buffer_add_string (buf, p->name);
8021                         buffer_add_methodid (buf, domain, p->get);
8022                         buffer_add_methodid (buf, domain, p->set);
8023                         buffer_add_int (buf, p->attrs);
8024                         i ++;
8025                 }
8026                 g_assert (i == nprops);
8027                 break;
8028         }
8029         case CMD_TYPE_GET_CATTRS: {
8030                 MonoClass *attr_klass;
8031                 MonoCustomAttrInfo *cinfo;
8032
8033                 attr_klass = decode_typeid (p, &p, end, NULL, &err);
8034                 /* attr_klass can be NULL */
8035                 if (err)
8036                         return err;
8037
8038                 cinfo = mono_custom_attrs_from_class (klass);
8039
8040                 err = buffer_add_cattrs (buf, domain, klass->image, attr_klass, cinfo);
8041                 if (err)
8042                         return err;
8043                 break;
8044         }
8045         case CMD_TYPE_GET_FIELD_CATTRS: {
8046                 MonoClass *attr_klass;
8047                 MonoCustomAttrInfo *cinfo;
8048                 MonoClassField *field;
8049
8050                 field = decode_fieldid (p, &p, end, NULL, &err);
8051                 if (err)
8052                         return err;
8053                 attr_klass = decode_typeid (p, &p, end, NULL, &err);
8054                 if (err)
8055                         return err;
8056
8057                 cinfo = mono_custom_attrs_from_field (klass, field);
8058
8059                 err = buffer_add_cattrs (buf, domain, klass->image, attr_klass, cinfo);
8060                 if (err)
8061                         return err;
8062                 break;
8063         }
8064         case CMD_TYPE_GET_PROPERTY_CATTRS: {
8065                 MonoClass *attr_klass;
8066                 MonoCustomAttrInfo *cinfo;
8067                 MonoProperty *prop;
8068
8069                 prop = decode_propertyid (p, &p, end, NULL, &err);
8070                 if (err)
8071                         return err;
8072                 attr_klass = decode_typeid (p, &p, end, NULL, &err);
8073                 if (err)
8074                         return err;
8075
8076                 cinfo = mono_custom_attrs_from_property (klass, prop);
8077
8078                 err = buffer_add_cattrs (buf, domain, klass->image, attr_klass, cinfo);
8079                 if (err)
8080                         return err;
8081                 break;
8082         }
8083         case CMD_TYPE_GET_VALUES:
8084         case CMD_TYPE_GET_VALUES_2: {
8085                 guint8 *val;
8086                 MonoClassField *f;
8087                 MonoVTable *vtable;
8088                 MonoClass *k;
8089                 int len, i;
8090                 gboolean found;
8091                 MonoThread *thread_obj;
8092                 MonoInternalThread *thread = NULL;
8093                 guint32 special_static_type;
8094
8095                 if (command == CMD_TYPE_GET_VALUES_2) {
8096                         int objid = decode_objid (p, &p, end);
8097                         int err;
8098
8099                         err = get_object (objid, (MonoObject**)&thread_obj);
8100                         if (err)
8101                                 return err;
8102
8103                         thread = THREAD_TO_INTERNAL (thread_obj);
8104                 }
8105
8106                 len = decode_int (p, &p, end);
8107                 for (i = 0; i < len; ++i) {
8108                         f = decode_fieldid (p, &p, end, NULL, &err);
8109                         if (err)
8110                                 return err;
8111
8112                         if (!(f->type->attrs & FIELD_ATTRIBUTE_STATIC))
8113                                 return ERR_INVALID_FIELDID;
8114                         special_static_type = mono_class_field_get_special_static_type (f);
8115                         if (special_static_type != SPECIAL_STATIC_NONE) {
8116                                 if (!(thread && special_static_type == SPECIAL_STATIC_THREAD))
8117                                         return ERR_INVALID_FIELDID;
8118                         }
8119
8120                         /* Check that the field belongs to the object */
8121                         found = FALSE;
8122                         for (k = klass; k; k = k->parent) {
8123                                 if (k == f->parent) {
8124                                         found = TRUE;
8125                                         break;
8126                                 }
8127                         }
8128                         if (!found)
8129                                 return ERR_INVALID_FIELDID;
8130
8131                         vtable = mono_class_vtable (domain, f->parent);
8132                         val = g_malloc (mono_class_instance_size (mono_class_from_mono_type (f->type)));
8133                         mono_field_static_get_value_for_thread (thread ? thread : mono_thread_internal_current (), vtable, f, val);
8134                         buffer_add_value (buf, f->type, val, domain);
8135                         g_free (val);
8136                 }
8137                 break;
8138         }
8139         case CMD_TYPE_SET_VALUES: {
8140                 guint8 *val;
8141                 MonoClassField *f;
8142                 MonoVTable *vtable;
8143                 MonoClass *k;
8144                 int len, i;
8145                 gboolean found;
8146
8147                 len = decode_int (p, &p, end);
8148                 for (i = 0; i < len; ++i) {
8149                         f = decode_fieldid (p, &p, end, NULL, &err);
8150                         if (err)
8151                                 return err;
8152
8153                         if (!(f->type->attrs & FIELD_ATTRIBUTE_STATIC))
8154                                 return ERR_INVALID_FIELDID;
8155                         if (mono_class_field_is_special_static (f))
8156                                 return ERR_INVALID_FIELDID;
8157
8158                         /* Check that the field belongs to the object */
8159                         found = FALSE;
8160                         for (k = klass; k; k = k->parent) {
8161                                 if (k == f->parent) {
8162                                         found = TRUE;
8163                                         break;
8164                                 }
8165                         }
8166                         if (!found)
8167                                 return ERR_INVALID_FIELDID;
8168
8169                         // FIXME: Check for literal/const
8170
8171                         vtable = mono_class_vtable (domain, f->parent);
8172                         val = g_malloc (mono_class_instance_size (mono_class_from_mono_type (f->type)));
8173                         err = decode_value (f->type, domain, val, p, &p, end);
8174                         if (err) {
8175                                 g_free (val);
8176                                 return err;
8177                         }
8178                         if (MONO_TYPE_IS_REFERENCE (f->type))
8179                                 mono_field_static_set_value (vtable, f, *(gpointer*)val);
8180                         else
8181                                 mono_field_static_set_value (vtable, f, val);
8182                         g_free (val);
8183                 }
8184                 break;
8185         }
8186         case CMD_TYPE_GET_OBJECT: {
8187                 MonoObject *o = (MonoObject*)mono_type_get_object (domain, &klass->byval_arg);
8188                 buffer_add_objid (buf, o);
8189                 break;
8190         }
8191         case CMD_TYPE_GET_SOURCE_FILES:
8192         case CMD_TYPE_GET_SOURCE_FILES_2: {
8193                 char *source_file, *base;
8194                 GPtrArray *files;
8195                 int i;
8196
8197                 files = get_source_files_for_type (klass);
8198
8199                 buffer_add_int (buf, files->len);
8200                 for (i = 0; i < files->len; ++i) {
8201                         source_file = g_ptr_array_index (files, i);
8202                         if (command == CMD_TYPE_GET_SOURCE_FILES_2) {
8203                                 buffer_add_string (buf, source_file);
8204                         } else {
8205                                 base = g_path_get_basename (source_file);
8206                                 buffer_add_string (buf, base);
8207                                 g_free (base);
8208                         }
8209                         g_free (source_file);
8210                 }
8211                 g_ptr_array_free (files, TRUE);
8212                 break;
8213         }
8214         case CMD_TYPE_IS_ASSIGNABLE_FROM: {
8215                 MonoClass *oklass = decode_typeid (p, &p, end, NULL, &err);
8216
8217                 if (err)
8218                         return err;
8219                 if (mono_class_is_assignable_from (klass, oklass))
8220                         buffer_add_byte (buf, 1);
8221                 else
8222                         buffer_add_byte (buf, 0);
8223                 break;
8224         }
8225         case CMD_TYPE_GET_METHODS_BY_NAME_FLAGS: {
8226                 char *name = decode_string (p, &p, end);
8227                 int i, flags = decode_int (p, &p, end);
8228                 MonoException *ex = NULL;
8229                 GPtrArray *array = mono_class_get_methods_by_name (klass, name, flags & ~BINDING_FLAGS_IGNORE_CASE, (flags & BINDING_FLAGS_IGNORE_CASE) != 0, TRUE, &ex);
8230
8231                 if (!array)
8232                         return ERR_LOADER_ERROR;
8233                 buffer_add_int (buf, array->len);
8234                 for (i = 0; i < array->len; ++i) {
8235                         MonoMethod *method = g_ptr_array_index (array, i);
8236                         buffer_add_methodid (buf, domain, method);
8237                 }
8238
8239                 g_ptr_array_free (array, TRUE);
8240                 g_free (name);
8241                 break;
8242         }
8243         case CMD_TYPE_GET_INTERFACES: {
8244                 MonoClass *parent;
8245                 GHashTable *iface_hash = g_hash_table_new (NULL, NULL);
8246                 MonoError error;
8247                 MonoClass *tclass, *iface;
8248                 GHashTableIter iter;
8249
8250                 tclass = klass;
8251
8252                 for (parent = tclass; parent; parent = parent->parent) {
8253                         mono_class_setup_interfaces (parent, &error);
8254                         if (!mono_error_ok (&error))
8255                                 return ERR_LOADER_ERROR;
8256                         collect_interfaces (parent, iface_hash, &error);
8257                         if (!mono_error_ok (&error))
8258                                 return ERR_LOADER_ERROR;
8259                 }
8260
8261                 buffer_add_int (buf, g_hash_table_size (iface_hash));
8262
8263                 g_hash_table_iter_init (&iter, iface_hash);
8264                 while (g_hash_table_iter_next (&iter, NULL, (void**)&iface))
8265                         buffer_add_typeid (buf, domain, iface);
8266                 g_hash_table_destroy (iface_hash);
8267                 break;
8268         }
8269         case CMD_TYPE_GET_INTERFACE_MAP: {
8270                 int tindex, ioffset;
8271                 gboolean variance_used;
8272                 MonoClass *iclass;
8273                 int len, nmethods, i;
8274                 gpointer iter;
8275                 MonoMethod *method;
8276
8277                 len = decode_int (p, &p, end);
8278                 mono_class_setup_vtable (klass);
8279
8280                 for (tindex = 0; tindex < len; ++tindex) {
8281                         iclass = decode_typeid (p, &p, end, NULL, &err);
8282                         if (err)
8283                                 return err;
8284
8285                         ioffset = mono_class_interface_offset_with_variance (klass, iclass, &variance_used);
8286                         if (ioffset == -1)
8287                                 return ERR_INVALID_ARGUMENT;
8288
8289                         nmethods = mono_class_num_methods (iclass);
8290                         buffer_add_int (buf, nmethods);
8291
8292                         iter = NULL;
8293                         while ((method = mono_class_get_methods (iclass, &iter))) {
8294                                 buffer_add_methodid (buf, domain, method);
8295                         }
8296                         for (i = 0; i < nmethods; ++i)
8297                                 buffer_add_methodid (buf, domain, klass->vtable [i + ioffset]);
8298                 }
8299                 break;
8300         }
8301         case CMD_TYPE_IS_INITIALIZED: {
8302                 MonoVTable *vtable = mono_class_vtable (domain, klass);
8303
8304                 if (vtable)
8305                         buffer_add_int (buf, (vtable->initialized || vtable->init_failed) ? 1 : 0);
8306                 else
8307                         buffer_add_int (buf, 0);
8308                 break;
8309         }
8310         case CMD_TYPE_CREATE_INSTANCE: {
8311                 MonoObject *obj;
8312
8313                 obj = mono_object_new (domain, klass);
8314                 buffer_add_objid (buf, obj);
8315                 break;
8316         }
8317         default:
8318                 return ERR_NOT_IMPLEMENTED;
8319         }
8320
8321         return ERR_NONE;
8322 }
8323
8324 static ErrorCode
8325 type_commands (int command, guint8 *p, guint8 *end, Buffer *buf)
8326 {
8327         MonoClass *klass;
8328         MonoDomain *old_domain;
8329         MonoDomain *domain;
8330         int err;
8331
8332         klass = decode_typeid (p, &p, end, &domain, &err);
8333         if (err)
8334                 return err;
8335
8336         old_domain = mono_domain_get ();
8337
8338         mono_domain_set (domain, TRUE);
8339
8340         err = type_commands_internal (command, klass, domain, p, end, buf);
8341
8342         mono_domain_set (old_domain, TRUE);
8343
8344         return err;
8345 }
8346
8347 static ErrorCode
8348 method_commands_internal (int command, MonoMethod *method, MonoDomain *domain, guint8 *p, guint8 *end, Buffer *buf)
8349 {
8350         MonoMethodHeader *header;
8351         int err;
8352
8353         switch (command) {
8354         case CMD_METHOD_GET_NAME: {
8355                 buffer_add_string (buf, method->name);
8356                 break;                  
8357         }
8358         case CMD_METHOD_GET_DECLARING_TYPE: {
8359                 buffer_add_typeid (buf, domain, method->klass);
8360                 break;
8361         }
8362         case CMD_METHOD_GET_DEBUG_INFO: {
8363                 MonoDebugMethodInfo *minfo;
8364                 char *source_file;
8365                 int i, j, n_il_offsets;
8366                 int *il_offsets;
8367                 int *line_numbers;
8368                 int *column_numbers;
8369                 int *end_line_numbers;
8370                 int *end_column_numbers;
8371                 int *source_files;
8372                 GPtrArray *source_file_list;
8373
8374                 header = mono_method_get_header (method);
8375                 if (!header) {
8376                         buffer_add_int (buf, 0);
8377                         buffer_add_string (buf, "");
8378                         buffer_add_int (buf, 0);
8379                         break;
8380                 }
8381
8382                 minfo = mono_debug_lookup_method (method);
8383                 if (!minfo) {
8384                         buffer_add_int (buf, header->code_size);
8385                         buffer_add_string (buf, "");
8386                         buffer_add_int (buf, 0);
8387                         mono_metadata_free_mh (header);
8388                         break;
8389                 }
8390
8391                 mono_debug_symfile_get_line_numbers_full (minfo, &source_file, &source_file_list, &n_il_offsets, &il_offsets, &line_numbers, &column_numbers, &source_files, &end_line_numbers, &end_column_numbers);
8392                 buffer_add_int (buf, header->code_size);
8393                 if (CHECK_PROTOCOL_VERSION (2, 13)) {
8394                         buffer_add_int (buf, source_file_list->len);
8395                         for (i = 0; i < source_file_list->len; ++i) {
8396                                 MonoDebugSourceInfo *sinfo = g_ptr_array_index (source_file_list, i);
8397                                 buffer_add_string (buf, sinfo->source_file);
8398                                 if (CHECK_PROTOCOL_VERSION (2, 14)) {
8399                                         for (j = 0; j < 16; ++j)
8400                                                 buffer_add_byte (buf, sinfo->hash [j]);
8401                                 }
8402                         }
8403                 } else {
8404                         buffer_add_string (buf, source_file);
8405                 }
8406                 buffer_add_int (buf, n_il_offsets);
8407                 DEBUG (10, fprintf (log_file, "Line number table for method %s:\n", mono_method_full_name (method,  TRUE)));
8408                 for (i = 0; i < n_il_offsets; ++i) {
8409                         const char *srcfile = "";
8410
8411                         if (source_files [i] != -1) {
8412                                 MonoDebugSourceInfo *sinfo = g_ptr_array_index (source_file_list, source_files [i]);
8413                                 srcfile = sinfo->source_file;
8414                         }
8415                         DEBUG (10, fprintf (log_file, "IL%x -> %s:%d %d\n", il_offsets [i], srcfile, line_numbers [i], column_numbers ? column_numbers [i] : -1));
8416                         buffer_add_int (buf, il_offsets [i]);
8417                         buffer_add_int (buf, line_numbers [i]);
8418                         if (CHECK_PROTOCOL_VERSION (2, 13))
8419                                 buffer_add_int (buf, source_files [i]);
8420                         if (CHECK_PROTOCOL_VERSION (2, 19))
8421                                 buffer_add_int (buf, column_numbers ? column_numbers [i] : -1);
8422                         if (CHECK_PROTOCOL_VERSION (2, 32)) {
8423                                 buffer_add_int (buf, end_line_numbers ? end_line_numbers [i] : -1);
8424                                 buffer_add_int (buf, end_column_numbers ? end_column_numbers [i] : -1);
8425                         }
8426                 }
8427                 g_free (source_file);
8428                 g_free (il_offsets);
8429                 g_free (line_numbers);
8430                 g_free (column_numbers);
8431                 g_free (end_line_numbers);
8432                 g_free (end_column_numbers);
8433                 g_free (source_files);
8434                 g_ptr_array_free (source_file_list, TRUE);
8435                 mono_metadata_free_mh (header);
8436                 break;
8437         }
8438         case CMD_METHOD_GET_PARAM_INFO: {
8439                 MonoMethodSignature *sig = mono_method_signature (method);
8440                 guint32 i;
8441                 char **names;
8442
8443                 /* FIXME: mono_class_from_mono_type () and byrefs */
8444
8445                 /* FIXME: Use a smaller encoding */
8446                 buffer_add_int (buf, sig->call_convention);
8447                 buffer_add_int (buf, sig->param_count);
8448                 buffer_add_int (buf, sig->generic_param_count);
8449                 buffer_add_typeid (buf, domain, mono_class_from_mono_type (sig->ret));
8450                 for (i = 0; i < sig->param_count; ++i) {
8451                         /* FIXME: vararg */
8452                         buffer_add_typeid (buf, domain, mono_class_from_mono_type (sig->params [i]));
8453                 }
8454
8455                 /* Emit parameter names */
8456                 names = g_new (char *, sig->param_count);
8457                 mono_method_get_param_names (method, (const char **) names);
8458                 for (i = 0; i < sig->param_count; ++i)
8459                         buffer_add_string (buf, names [i]);
8460                 g_free (names);
8461
8462                 break;
8463         }
8464         case CMD_METHOD_GET_LOCALS_INFO: {
8465                 int i, j, num_locals;
8466                 MonoDebugLocalsInfo *locals;
8467
8468                 header = mono_method_get_header (method);
8469                 if (!header)
8470                         return ERR_INVALID_ARGUMENT;
8471
8472                 buffer_add_int (buf, header->num_locals);
8473
8474                 /* Types */
8475                 for (i = 0; i < header->num_locals; ++i)
8476                         buffer_add_typeid (buf, domain, mono_class_from_mono_type (header->locals [i]));
8477
8478                 /* Names */
8479                 locals = mono_debug_lookup_locals (method);
8480                 if (locals)
8481                         num_locals = locals->num_locals;
8482                 else
8483                         num_locals = 0;
8484                 for (i = 0; i < header->num_locals; ++i) {
8485                         for (j = 0; j < num_locals; ++j)
8486                                 if (locals->locals [j].index == i)
8487                                         break;
8488                         if (j < num_locals)
8489                                 buffer_add_string (buf, locals->locals [j].name);
8490                         else
8491                                 buffer_add_string (buf, "");
8492                 }
8493
8494                 /* Scopes */
8495                 for (i = 0; i < header->num_locals; ++i) {
8496                         for (j = 0; j < num_locals; ++j)
8497                                 if (locals->locals [j].index == i)
8498                                         break;
8499                         if (j < num_locals && locals->locals [j].block) {
8500                                 buffer_add_int (buf, locals->locals [j].block->start_offset);
8501                                 buffer_add_int (buf, locals->locals [j].block->end_offset);
8502                         } else {
8503                                 buffer_add_int (buf, 0);
8504                                 buffer_add_int (buf, header->code_size);
8505                         }
8506                 }
8507                 mono_metadata_free_mh (header);
8508
8509                 if (locals)
8510                         mono_debug_symfile_free_locals (locals);
8511
8512                 break;
8513         }
8514         case CMD_METHOD_GET_INFO:
8515                 buffer_add_int (buf, method->flags);
8516                 buffer_add_int (buf, method->iflags);
8517                 buffer_add_int (buf, method->token);
8518                 if (CHECK_PROTOCOL_VERSION (2, 12)) {
8519                         guint8 attrs = 0;
8520                         if (method->is_generic)
8521                                 attrs |= (1 << 0);
8522                         if (mono_method_signature (method)->generic_param_count)
8523                                 attrs |= (1 << 1);
8524                         buffer_add_byte (buf, attrs);
8525                         if (method->is_generic || method->is_inflated) {
8526                                 MonoMethod *result;
8527
8528                                 if (method->is_generic) {
8529                                         result = method;
8530                                 } else {
8531                                         MonoMethodInflated *imethod = (MonoMethodInflated *)method;
8532                                         
8533                                         result = imethod->declaring;
8534                                         if (imethod->context.class_inst) {
8535                                                 MonoClass *klass = ((MonoMethod *) imethod)->klass;
8536                                                 /*Generic methods gets the context of the GTD.*/
8537                                                 if (mono_class_get_context (klass))
8538                                                         result = mono_class_inflate_generic_method_full (result, klass, mono_class_get_context (klass));
8539                                         }
8540                                 }
8541
8542                                 buffer_add_methodid (buf, domain, result);
8543                         } else {
8544                                 buffer_add_id (buf, 0);
8545                         }
8546                         if (CHECK_PROTOCOL_VERSION (2, 15)) {
8547                                 if (mono_method_signature (method)->generic_param_count) {
8548                                         int count, i;
8549
8550                                         if (method->is_inflated) {
8551                                                 MonoGenericInst *inst = mono_method_get_context (method)->method_inst;
8552                                                 if (inst) {
8553                                                         count = inst->type_argc;
8554                                                         buffer_add_int (buf, count);
8555
8556                                                         for (i = 0; i < count; i++)
8557                                                                 buffer_add_typeid (buf, domain, mono_class_from_mono_type (inst->type_argv [i]));
8558                                                 } else {
8559                                                         buffer_add_int (buf, 0);
8560                                                 }
8561                                         } else if (method->is_generic) {
8562                                                 MonoGenericContainer *container = mono_method_get_generic_container (method);
8563
8564                                                 count = mono_method_signature (method)->generic_param_count;
8565                                                 buffer_add_int (buf, count);
8566                                                 for (i = 0; i < count; i++) {
8567                                                         MonoGenericParam *param = mono_generic_container_get_param (container, i);
8568                                                         MonoClass *pklass = mono_class_from_generic_parameter (param, method->klass->image, TRUE);
8569                                                         buffer_add_typeid (buf, domain, pklass);
8570                                                 }
8571                                         } else {
8572                                                 buffer_add_int (buf, 0);
8573                                         }
8574                                 } else {
8575                                         buffer_add_int (buf, 0);
8576                                 }
8577                         }
8578                 }
8579                 break;
8580         case CMD_METHOD_GET_BODY: {
8581                 int i;
8582
8583                 header = mono_method_get_header (method);
8584                 if (!header) {
8585                         buffer_add_int (buf, 0);
8586
8587                         if (CHECK_PROTOCOL_VERSION (2, 18))
8588                                 buffer_add_int (buf, 0);
8589                 } else {
8590                         buffer_add_int (buf, header->code_size);
8591                         for (i = 0; i < header->code_size; ++i)
8592                                 buffer_add_byte (buf, header->code [i]);
8593
8594                         if (CHECK_PROTOCOL_VERSION (2, 18)) {
8595                                 buffer_add_int (buf, header->num_clauses);
8596                                 for (i = 0; i < header->num_clauses; ++i) {
8597                                         MonoExceptionClause *clause = &header->clauses [i];
8598
8599                                         buffer_add_int (buf, clause->flags);
8600                                         buffer_add_int (buf, clause->try_offset);
8601                                         buffer_add_int (buf, clause->try_len);
8602                                         buffer_add_int (buf, clause->handler_offset);
8603                                         buffer_add_int (buf, clause->handler_len);
8604                                         if (clause->flags == MONO_EXCEPTION_CLAUSE_NONE)
8605                                                 buffer_add_typeid (buf, domain, clause->data.catch_class);
8606                                         else if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
8607                                                 buffer_add_int (buf, clause->data.filter_offset);
8608                                 }
8609                         }
8610
8611                         mono_metadata_free_mh (header);
8612                 }
8613
8614                 break;
8615         }
8616         case CMD_METHOD_RESOLVE_TOKEN: {
8617                 guint32 token = decode_int (p, &p, end);
8618
8619                 // FIXME: Generics
8620                 switch (mono_metadata_token_code (token)) {
8621                 case MONO_TOKEN_STRING: {
8622                         MonoString *s;
8623                         char *s2;
8624
8625                         s = mono_ldstr (domain, method->klass->image, mono_metadata_token_index (token));
8626                         g_assert (s);
8627
8628                         s2 = mono_string_to_utf8 (s);
8629
8630                         buffer_add_byte (buf, TOKEN_TYPE_STRING);
8631                         buffer_add_string (buf, s2);
8632                         g_free (s2);
8633                         break;
8634                 }
8635                 default: {
8636                         gpointer val;
8637                         MonoClass *handle_class;
8638
8639                         if (method->wrapper_type == MONO_WRAPPER_DYNAMIC_METHOD) {
8640                                 val = mono_method_get_wrapper_data (method, token);
8641                                 handle_class = mono_method_get_wrapper_data (method, token + 1);
8642
8643                                 if (handle_class == NULL) {
8644                                         // Can't figure out the token type
8645                                         buffer_add_byte (buf, TOKEN_TYPE_UNKNOWN);
8646                                         break;
8647                                 }
8648                         } else {
8649                                 val = mono_ldtoken (method->klass->image, token, &handle_class, NULL);
8650                                 g_assert (val);
8651                         }
8652
8653                         if (handle_class == mono_defaults.typehandle_class) {
8654                                 buffer_add_byte (buf, TOKEN_TYPE_TYPE);
8655                                 if (method->wrapper_type == MONO_WRAPPER_DYNAMIC_METHOD)
8656                                         buffer_add_typeid (buf, domain, (MonoClass *) val);
8657                                 else
8658                                         buffer_add_typeid (buf, domain, mono_class_from_mono_type ((MonoType*)val));
8659                         } else if (handle_class == mono_defaults.fieldhandle_class) {
8660                                 buffer_add_byte (buf, TOKEN_TYPE_FIELD);
8661                                 buffer_add_fieldid (buf, domain, val);
8662                         } else if (handle_class == mono_defaults.methodhandle_class) {
8663                                 buffer_add_byte (buf, TOKEN_TYPE_METHOD);
8664                                 buffer_add_methodid (buf, domain, val);
8665                         } else if (handle_class == mono_defaults.string_class) {
8666                                 char *s;
8667
8668                                 s = mono_string_to_utf8 (val);
8669                                 buffer_add_byte (buf, TOKEN_TYPE_STRING);
8670                                 buffer_add_string (buf, s);
8671                                 g_free (s);
8672                         } else {
8673                                 g_assert_not_reached ();
8674                         }
8675                         break;
8676                 }
8677                 }
8678                 break;
8679         }
8680         case CMD_METHOD_GET_CATTRS: {
8681                 MonoClass *attr_klass;
8682                 MonoCustomAttrInfo *cinfo;
8683
8684                 attr_klass = decode_typeid (p, &p, end, NULL, &err);
8685                 /* attr_klass can be NULL */
8686                 if (err)
8687                         return err;
8688
8689                 cinfo = mono_custom_attrs_from_method (method);
8690
8691                 err = buffer_add_cattrs (buf, domain, method->klass->image, attr_klass, cinfo);
8692                 if (err)
8693                         return err;
8694                 break;
8695         }
8696         case CMD_METHOD_MAKE_GENERIC_METHOD: {
8697                 MonoType **type_argv;
8698                 int i, type_argc;
8699                 MonoDomain *d;
8700                 MonoClass *klass;
8701                 MonoGenericInst *ginst;
8702                 MonoGenericContext tmp_context;
8703                 MonoMethod *inflated;
8704
8705                 type_argc = decode_int (p, &p, end);
8706                 type_argv = g_new0 (MonoType*, type_argc);
8707                 for (i = 0; i < type_argc; ++i) {
8708                         klass = decode_typeid (p, &p, end, &d, &err);
8709                         if (err) {
8710                                 g_free (type_argv);
8711                                 return err;
8712                         }
8713                         if (domain != d) {
8714                                 g_free (type_argv);
8715                                 return ERR_INVALID_ARGUMENT;
8716                         }
8717                         type_argv [i] = &klass->byval_arg;
8718                 }
8719                 ginst = mono_metadata_get_generic_inst (type_argc, type_argv);
8720                 g_free (type_argv);
8721                 tmp_context.class_inst = method->klass->generic_class ? method->klass->generic_class->context.class_inst : NULL;
8722                 tmp_context.method_inst = ginst;
8723
8724                 inflated = mono_class_inflate_generic_method (method, &tmp_context);
8725                 if (!mono_verifier_is_method_valid_generic_instantiation (inflated))
8726                         return ERR_INVALID_ARGUMENT;
8727                 buffer_add_methodid (buf, domain, inflated);
8728                 break;
8729         }
8730         default:
8731                 return ERR_NOT_IMPLEMENTED;
8732         }
8733
8734         return ERR_NONE;
8735 }
8736
8737 static ErrorCode
8738 method_commands (int command, guint8 *p, guint8 *end, Buffer *buf)
8739 {
8740         int err;
8741         MonoDomain *old_domain;
8742         MonoDomain *domain;
8743         MonoMethod *method;
8744
8745         method = decode_methodid (p, &p, end, &domain, &err);
8746         if (err)
8747                 return err;
8748
8749         old_domain = mono_domain_get ();
8750
8751         mono_domain_set (domain, TRUE);
8752
8753         err = method_commands_internal (command, method, domain, p, end, buf);
8754
8755         mono_domain_set (old_domain, TRUE);
8756
8757         return err;
8758 }
8759
8760 static ErrorCode
8761 thread_commands (int command, guint8 *p, guint8 *end, Buffer *buf)
8762 {
8763         int objid = decode_objid (p, &p, end);
8764         int err;
8765         MonoThread *thread_obj;
8766         MonoInternalThread *thread;
8767
8768         err = get_object (objid, (MonoObject**)&thread_obj);
8769         if (err)
8770                 return err;
8771
8772         thread = THREAD_TO_INTERNAL (thread_obj);
8773            
8774         switch (command) {
8775         case CMD_THREAD_GET_NAME: {
8776                 guint32 name_len;
8777                 gunichar2 *s = mono_thread_get_name (thread, &name_len);
8778
8779                 if (!s) {
8780                         buffer_add_int (buf, 0);
8781                 } else {
8782                         char *name;
8783                         glong len;
8784
8785                         name = g_utf16_to_utf8 (s, name_len, NULL, &len, NULL);
8786                         g_assert (name);
8787                         buffer_add_int (buf, len);
8788                         buffer_add_data (buf, (guint8*)name, len);
8789                         g_free (s);
8790                 }
8791                 break;
8792         }
8793         case CMD_THREAD_GET_FRAME_INFO: {
8794                 DebuggerTlsData *tls;
8795                 int i, start_frame, length;
8796
8797                 // Wait for suspending if it already started
8798                 // FIXME: Races with suspend_count
8799                 while (!is_suspended ()) {
8800                         if (suspend_count)
8801                                 wait_for_suspend ();
8802                 }
8803                 /*
8804                 if (suspend_count)
8805                         wait_for_suspend ();
8806                 if (!is_suspended ())
8807                         return ERR_NOT_SUSPENDED;
8808                 */
8809
8810                 start_frame = decode_int (p, &p, end);
8811                 length = decode_int (p, &p, end);
8812
8813                 if (start_frame != 0 || length != -1)
8814                         return ERR_NOT_IMPLEMENTED;
8815
8816                 mono_loader_lock ();
8817                 tls = mono_g_hash_table_lookup (thread_to_tls, thread);
8818                 mono_loader_unlock ();
8819                 g_assert (tls);
8820
8821                 compute_frame_info (thread, tls);
8822
8823                 buffer_add_int (buf, tls->frame_count);
8824                 for (i = 0; i < tls->frame_count; ++i) {
8825                         buffer_add_int (buf, tls->frames [i]->id);
8826                         buffer_add_methodid (buf, tls->frames [i]->domain, tls->frames [i]->actual_method);
8827                         buffer_add_int (buf, tls->frames [i]->il_offset);
8828                         /*
8829                          * Instead of passing the frame type directly to the client, we associate
8830                          * it with the previous frame using a set of flags. This avoids lots of
8831                          * conditional code in the client, since a frame whose type isn't 
8832                          * FRAME_TYPE_MANAGED has no method, location, etc.
8833                          */
8834                         buffer_add_byte (buf, tls->frames [i]->flags);
8835                 }
8836
8837                 break;
8838         }
8839         case CMD_THREAD_GET_STATE:
8840                 buffer_add_int (buf, thread->state);
8841                 break;
8842         case CMD_THREAD_GET_INFO:
8843                 buffer_add_byte (buf, thread->threadpool_thread);
8844                 break;
8845         case CMD_THREAD_GET_ID:
8846                 buffer_add_long (buf, (guint64)(gsize)thread);
8847                 break;
8848         case CMD_THREAD_GET_TID:
8849                 buffer_add_long (buf, (guint64)thread->tid);
8850                 break;
8851         case CMD_THREAD_SET_IP: {
8852                 DebuggerTlsData *tls;
8853                 MonoMethod *method;
8854                 MonoDomain *domain;
8855                 MonoSeqPointInfo *seq_points;
8856                 SeqPoint *sp = NULL;
8857                 gint64 il_offset;
8858                 int i;
8859
8860                 method = decode_methodid (p, &p, end, &domain, &err);
8861                 if (err)
8862                         return err;
8863                 il_offset = decode_long (p, &p, end);
8864
8865                 while (!is_suspended ()) {
8866                         if (suspend_count)
8867                                 wait_for_suspend ();
8868                 }
8869
8870                 mono_loader_lock ();
8871                 tls = mono_g_hash_table_lookup (thread_to_tls, thread);
8872                 mono_loader_unlock ();
8873                 g_assert (tls);
8874
8875                 compute_frame_info (thread, tls);
8876                 if (tls->frame_count == 0 || tls->frames [0]->actual_method != method)
8877                         return ERR_INVALID_ARGUMENT;
8878
8879                 seq_points = get_seq_points (domain, method);
8880                 g_assert (seq_points);
8881
8882                 for (i = 0; i < seq_points->len; ++i) {
8883                         sp = &seq_points->seq_points [i];
8884
8885                         if (sp->il_offset == il_offset)
8886                                 break;
8887                 }
8888                 if (i == seq_points->len)
8889                         return ERR_INVALID_ARGUMENT;
8890
8891                 // FIXME: Check that the ip change is safe
8892
8893                 DEBUG (1, fprintf (log_file, "[dbg] Setting IP to %s:0x%0x(0x%0x)\n", tls->frames [0]->actual_method->name, (int)sp->il_offset, (int)sp->native_offset));
8894                 MONO_CONTEXT_SET_IP (&tls->restore_ctx, (guint8*)tls->frames [0]->ji->code_start + sp->native_offset);
8895                 break;
8896         }
8897         default:
8898                 return ERR_NOT_IMPLEMENTED;
8899         }
8900
8901         return ERR_NONE;
8902 }
8903
8904 static ErrorCode
8905 frame_commands (int command, guint8 *p, guint8 *end, Buffer *buf)
8906 {
8907         int objid;
8908         int err;
8909         MonoThread *thread_obj;
8910         MonoInternalThread *thread;
8911         int pos, i, len, frame_idx;
8912         DebuggerTlsData *tls;
8913         StackFrame *frame;
8914         MonoDebugMethodJitInfo *jit;
8915         MonoDebugVarInfo *var;
8916         MonoMethodSignature *sig;
8917         gssize id;
8918         MonoMethodHeader *header;
8919
8920         objid = decode_objid (p, &p, end);
8921         err = get_object (objid, (MonoObject**)&thread_obj);
8922         if (err)
8923                 return err;
8924
8925         thread = THREAD_TO_INTERNAL (thread_obj);
8926
8927         id = decode_id (p, &p, end);
8928
8929         mono_loader_lock ();
8930         tls = mono_g_hash_table_lookup (thread_to_tls, thread);
8931         mono_loader_unlock ();
8932         g_assert (tls);
8933
8934         for (i = 0; i < tls->frame_count; ++i) {
8935                 if (tls->frames [i]->id == id)
8936                         break;
8937         }
8938         if (i == tls->frame_count)
8939                 return ERR_INVALID_FRAMEID;
8940
8941         frame_idx = i;
8942         frame = tls->frames [frame_idx];
8943
8944         if (!frame->has_ctx)
8945                 return ERR_ABSENT_INFORMATION;
8946
8947         if (!frame->jit) {
8948                 frame->jit = mono_debug_find_method (frame->api_method, frame->domain);
8949                 if (!frame->jit && frame->api_method->is_inflated)
8950                         frame->jit = mono_debug_find_method (mono_method_get_declaring_generic_method (frame->api_method), frame->domain);
8951                 if (!frame->jit) {
8952                         char *s;
8953
8954                         /* This could happen for aot images with no jit debug info */
8955                         s = mono_method_full_name (frame->api_method, TRUE);
8956                         DEBUG (1, fprintf (log_file, "[dbg] No debug information found for '%s'.\n", s));
8957                         g_free (s);
8958                         return ERR_ABSENT_INFORMATION;
8959                 }
8960         }
8961         jit = frame->jit;
8962
8963         sig = mono_method_signature (frame->actual_method);
8964
8965         if (!get_seq_points (frame->domain, frame->actual_method))
8966                 /*
8967                  * The method is probably from an aot image compiled without soft-debug, variables might be dead, etc.
8968                  */
8969                 return ERR_ABSENT_INFORMATION;
8970
8971         switch (command) {
8972         case CMD_STACK_FRAME_GET_VALUES: {
8973                 len = decode_int (p, &p, end);
8974                 header = mono_method_get_header (frame->actual_method);
8975
8976                 for (i = 0; i < len; ++i) {
8977                         pos = decode_int (p, &p, end);
8978
8979                         if (pos < 0) {
8980                                 pos = - pos - 1;
8981
8982                                 g_assert (pos >= 0 && pos < jit->num_params);
8983
8984                                 var = &jit->params [pos];
8985
8986                                 add_var (buf, jit, sig->params [pos], &jit->params [pos], &frame->ctx, frame->domain, FALSE);
8987                         } else {
8988                                 g_assert (pos >= 0 && pos < jit->num_locals);
8989
8990                                 var = &jit->locals [pos];
8991                                 
8992                                 add_var (buf, jit, header->locals [pos], &jit->locals [pos], &frame->ctx, frame->domain, FALSE);
8993                         }
8994                 }
8995                 mono_metadata_free_mh (header);
8996                 break;
8997         }
8998         case CMD_STACK_FRAME_GET_THIS: {
8999                 if (frame->api_method->klass->valuetype) {
9000                         if (!sig->hasthis) {
9001                                 MonoObject *p = NULL;
9002                                 buffer_add_value (buf, &mono_defaults.object_class->byval_arg, &p, frame->domain);
9003                         } else {
9004                                 add_var (buf, jit, &frame->actual_method->klass->this_arg, jit->this_var, &frame->ctx, frame->domain, TRUE);
9005                         }
9006                 } else {
9007                         if (!sig->hasthis) {
9008                                 MonoObject *p = NULL;
9009                                 buffer_add_value (buf, &frame->actual_method->klass->byval_arg, &p, frame->domain);
9010                         } else {
9011                                 add_var (buf, jit, &frame->api_method->klass->byval_arg, jit->this_var, &frame->ctx, frame->domain, TRUE);
9012                         }
9013                 }
9014                 break;
9015         }
9016         case CMD_STACK_FRAME_SET_VALUES: {
9017                 guint8 *val_buf;
9018                 MonoType *t;
9019                 MonoDebugVarInfo *var;
9020
9021                 len = decode_int (p, &p, end);
9022                 header = mono_method_get_header (frame->actual_method);
9023
9024                 for (i = 0; i < len; ++i) {
9025                         pos = decode_int (p, &p, end);
9026
9027                         if (pos < 0) {
9028                                 pos = - pos - 1;
9029
9030                                 g_assert (pos >= 0 && pos < jit->num_params);
9031
9032                                 t = sig->params [pos];
9033                                 var = &jit->params [pos];
9034                         } else {
9035                                 g_assert (pos >= 0 && pos < jit->num_locals);
9036
9037                                 t = header->locals [pos];
9038                                 var = &jit->locals [pos];
9039                         }
9040
9041                         if (MONO_TYPE_IS_REFERENCE (t))
9042                                 val_buf = g_alloca (sizeof (MonoObject*));
9043                         else
9044                                 val_buf = g_alloca (mono_class_instance_size (mono_class_from_mono_type (t)));
9045                         err = decode_value (t, frame->domain, val_buf, p, &p, end);
9046                         if (err)
9047                                 return err;
9048
9049                         set_var (t, var, &frame->ctx, frame->domain, val_buf, frame->reg_locations, &tls->restore_ctx);
9050                 }
9051                 mono_metadata_free_mh (header);
9052                 break;
9053         }
9054         case CMD_STACK_FRAME_GET_DOMAIN: {
9055                 if (CHECK_PROTOCOL_VERSION (2, 38))
9056                         buffer_add_domainid (buf, frame->domain);
9057                 break;
9058         }
9059         default:
9060                 return ERR_NOT_IMPLEMENTED;
9061         }
9062
9063         return ERR_NONE;
9064 }
9065
9066 static ErrorCode
9067 array_commands (int command, guint8 *p, guint8 *end, Buffer *buf)
9068 {
9069         MonoArray *arr;
9070         int objid, err, index, len, i, esize;
9071         gpointer elem;
9072
9073         objid = decode_objid (p, &p, end);
9074         err = get_object (objid, (MonoObject**)&arr);
9075         if (err)
9076                 return err;
9077
9078         switch (command) {
9079         case CMD_ARRAY_REF_GET_LENGTH:
9080                 buffer_add_int (buf, arr->obj.vtable->klass->rank);
9081                 if (!arr->bounds) {
9082                         buffer_add_int (buf, arr->max_length);
9083                         buffer_add_int (buf, 0);
9084                 } else {
9085                         for (i = 0; i < arr->obj.vtable->klass->rank; ++i) {
9086                                 buffer_add_int (buf, arr->bounds [i].length);
9087                                 buffer_add_int (buf, arr->bounds [i].lower_bound);
9088                         }
9089                 }
9090                 break;
9091         case CMD_ARRAY_REF_GET_VALUES:
9092                 index = decode_int (p, &p, end);
9093                 len = decode_int (p, &p, end);
9094
9095                 g_assert (index >= 0 && len >= 0);
9096                 // Reordered to avoid integer overflow
9097                 g_assert (!(index > arr->max_length - len));
9098
9099                 esize = mono_array_element_size (arr->obj.vtable->klass);
9100                 for (i = index; i < index + len; ++i) {
9101                         elem = (gpointer*)((char*)arr->vector + (i * esize));
9102                         buffer_add_value (buf, &arr->obj.vtable->klass->element_class->byval_arg, elem, arr->obj.vtable->domain);
9103                 }
9104                 break;
9105         case CMD_ARRAY_REF_SET_VALUES:
9106                 index = decode_int (p, &p, end);
9107                 len = decode_int (p, &p, end);
9108
9109                 g_assert (index >= 0 && len >= 0);
9110                 // Reordered to avoid integer overflow
9111                 g_assert (!(index > arr->max_length - len));
9112
9113                 esize = mono_array_element_size (arr->obj.vtable->klass);
9114                 for (i = index; i < index + len; ++i) {
9115                         elem = (gpointer*)((char*)arr->vector + (i * esize));
9116
9117                         decode_value (&arr->obj.vtable->klass->element_class->byval_arg, arr->obj.vtable->domain, elem, p, &p, end);
9118                 }
9119                 break;
9120         default:
9121                 return ERR_NOT_IMPLEMENTED;
9122         }
9123
9124         return ERR_NONE;
9125 }
9126
9127 static ErrorCode
9128 string_commands (int command, guint8 *p, guint8 *end, Buffer *buf)
9129 {
9130         int objid, err;
9131         MonoString *str;
9132         char *s;
9133         int i, index, length;
9134         gunichar2 *c;
9135
9136         objid = decode_objid (p, &p, end);
9137         err = get_object (objid, (MonoObject**)&str);
9138         if (err)
9139                 return err;
9140
9141         switch (command) {
9142         case CMD_STRING_REF_GET_VALUE:
9143                 s = mono_string_to_utf8 (str);
9144                 buffer_add_string (buf, s);
9145                 g_free (s);
9146                 break;
9147         case CMD_STRING_REF_GET_LENGTH:
9148                 buffer_add_long (buf, mono_string_length (str));
9149                 break;
9150         case CMD_STRING_REF_GET_CHARS:
9151                 index = decode_long (p, &p, end);
9152                 length = decode_long (p, &p, end);
9153                 if (index > mono_string_length (str) - length)
9154                         return ERR_INVALID_ARGUMENT;
9155                 c = mono_string_chars (str) + index;
9156                 for (i = 0; i < length; ++i)
9157                         buffer_add_short (buf, c [i]);
9158                 break;
9159         default:
9160                 return ERR_NOT_IMPLEMENTED;
9161         }
9162
9163         return ERR_NONE;
9164 }
9165
9166 static ErrorCode
9167 object_commands (int command, guint8 *p, guint8 *end, Buffer *buf)
9168 {
9169         int objid, err;
9170         MonoObject *obj;
9171         int len, i;
9172         MonoClassField *f;
9173         MonoClass *k;
9174         gboolean found;
9175
9176         if (command == CMD_OBJECT_REF_IS_COLLECTED) {
9177                 objid = decode_objid (p, &p, end);
9178                 err = get_object (objid, &obj);
9179                 if (err)
9180                         buffer_add_int (buf, 1);
9181                 else
9182                         buffer_add_int (buf, 0);
9183                 return 0;
9184         }
9185
9186         objid = decode_objid (p, &p, end);
9187         err = get_object (objid, &obj);
9188         if (err)
9189                 return err;
9190
9191         switch (command) {
9192         case CMD_OBJECT_REF_GET_TYPE:
9193                 /* This handles transparent proxies too */
9194                 buffer_add_typeid (buf, obj->vtable->domain, mono_class_from_mono_type (((MonoReflectionType*)obj->vtable->type)->type));
9195                 break;
9196         case CMD_OBJECT_REF_GET_VALUES:
9197                 len = decode_int (p, &p, end);
9198
9199                 for (i = 0; i < len; ++i) {
9200                         MonoClassField *f = decode_fieldid (p, &p, end, NULL, &err);
9201                         if (err)
9202                                 return err;
9203
9204                         /* Check that the field belongs to the object */
9205                         found = FALSE;
9206                         for (k = obj->vtable->klass; k; k = k->parent) {
9207                                 if (k == f->parent) {
9208                                         found = TRUE;
9209                                         break;
9210                                 }
9211                         }
9212                         if (!found)
9213                                 return ERR_INVALID_FIELDID;
9214
9215                         if (f->type->attrs & FIELD_ATTRIBUTE_STATIC) {
9216                                 guint8 *val;
9217                                 MonoVTable *vtable;
9218
9219                                 if (mono_class_field_is_special_static (f))
9220                                         return ERR_INVALID_FIELDID;
9221
9222                                 g_assert (f->type->attrs & FIELD_ATTRIBUTE_STATIC);
9223                                 vtable = mono_class_vtable (obj->vtable->domain, f->parent);
9224                                 val = g_malloc (mono_class_instance_size (mono_class_from_mono_type (f->type)));
9225                                 mono_field_static_get_value (vtable, f, val);
9226                                 buffer_add_value (buf, f->type, val, obj->vtable->domain);
9227                                 g_free (val);
9228                         } else {
9229                                 buffer_add_value (buf, f->type, (guint8*)obj + f->offset, obj->vtable->domain);
9230                         }
9231                 }
9232                 break;
9233         case CMD_OBJECT_REF_SET_VALUES:
9234                 len = decode_int (p, &p, end);
9235
9236                 for (i = 0; i < len; ++i) {
9237                         f = decode_fieldid (p, &p, end, NULL, &err);
9238                         if (err)
9239                                 return err;
9240
9241                         /* Check that the field belongs to the object */
9242                         found = FALSE;
9243                         for (k = obj->vtable->klass; k; k = k->parent) {
9244                                 if (k == f->parent) {
9245                                         found = TRUE;
9246                                         break;
9247                                 }
9248                         }
9249                         if (!found)
9250                                 return ERR_INVALID_FIELDID;
9251
9252                         if (f->type->attrs & FIELD_ATTRIBUTE_STATIC) {
9253                                 guint8 *val;
9254                                 MonoVTable *vtable;
9255
9256                                 if (mono_class_field_is_special_static (f))
9257                                         return ERR_INVALID_FIELDID;
9258
9259                                 g_assert (f->type->attrs & FIELD_ATTRIBUTE_STATIC);
9260                                 vtable = mono_class_vtable (obj->vtable->domain, f->parent);
9261
9262                                 val = g_malloc (mono_class_instance_size (mono_class_from_mono_type (f->type)));
9263                                 err = decode_value (f->type, obj->vtable->domain, val, p, &p, end);
9264                                 if (err) {
9265                                         g_free (val);
9266                                         return err;
9267                                 }
9268                                 mono_field_static_set_value (vtable, f, val);
9269                                 g_free (val);
9270                         } else {
9271                                 err = decode_value (f->type, obj->vtable->domain, (guint8*)obj + f->offset, p, &p, end);
9272                                 if (err)
9273                                         return err;
9274                         }
9275                 }
9276                 break;
9277         case CMD_OBJECT_REF_GET_ADDRESS:
9278                 buffer_add_long (buf, (gssize)obj);
9279                 break;
9280         case CMD_OBJECT_REF_GET_DOMAIN:
9281                 buffer_add_domainid (buf, obj->vtable->domain);
9282                 break;
9283         case CMD_OBJECT_REF_GET_INFO:
9284                 buffer_add_typeid (buf, obj->vtable->domain, mono_class_from_mono_type (((MonoReflectionType*)obj->vtable->type)->type));
9285                 buffer_add_domainid (buf, obj->vtable->domain);
9286                 break;
9287         default:
9288                 return ERR_NOT_IMPLEMENTED;
9289         }
9290
9291         return ERR_NONE;
9292 }
9293
9294 static const char*
9295 command_set_to_string (CommandSet command_set)
9296 {
9297         switch (command_set) {
9298         case CMD_SET_VM:
9299                 return "VM";
9300         case CMD_SET_OBJECT_REF:
9301                 return "OBJECT_REF";
9302         case CMD_SET_STRING_REF:
9303                 return "STRING_REF";
9304         case CMD_SET_THREAD:
9305                 return "THREAD";
9306         case CMD_SET_ARRAY_REF:
9307                 return "ARRAY_REF";
9308         case CMD_SET_EVENT_REQUEST:
9309                 return "EVENT_REQUEST";
9310         case CMD_SET_STACK_FRAME:
9311                 return "STACK_FRAME";
9312         case CMD_SET_APPDOMAIN:
9313                 return "APPDOMAIN";
9314         case CMD_SET_ASSEMBLY:
9315                 return "ASSEMBLY";
9316         case CMD_SET_METHOD:
9317                 return "METHOD";
9318         case CMD_SET_TYPE:
9319                 return "TYPE";
9320         case CMD_SET_MODULE:
9321                 return "MODULE";
9322         case CMD_SET_FIELD:
9323                 return "FIELD";
9324         case CMD_SET_EVENT:
9325                 return "EVENT";
9326         default:
9327                 return "";
9328         }
9329 }
9330
9331 static const char* vm_cmds_str [] = {
9332         "VERSION",
9333         "ALL_THREADS",
9334         "SUSPEND",
9335         "RESUME",
9336         "EXIT",
9337         "DISPOSE",
9338         "INVOKE_METHOD",
9339         "SET_PROTOCOL_VERSION",
9340         "ABORT_INVOKE",
9341         "SET_KEEPALIVE"
9342         "GET_TYPES_FOR_SOURCE_FILE",
9343         "GET_TYPES",
9344         "INVOKE_METHODS"
9345 };
9346
9347 static const char* thread_cmds_str[] = {
9348         "GET_FRAME_INFO",
9349         "GET_NAME",
9350         "GET_STATE",
9351         "GET_INFO",
9352         "GET_ID",
9353         "GET_TID",
9354         "SET_IP"
9355 };
9356
9357 static const char* event_cmds_str[] = {
9358         "REQUEST_SET",
9359         "REQUEST_CLEAR",
9360         "REQUEST_CLEAR_ALL_BREAKPOINTS"
9361 };
9362
9363 static const char* appdomain_cmds_str[] = {
9364         "GET_ROOT_DOMAIN",
9365         "GET_FRIENDLY_NAME",
9366         "GET_ASSEMBLIES",
9367         "GET_ENTRY_ASSEMBLY",
9368         "CREATE_STRING",
9369         "GET_CORLIB",
9370         "CREATE_BOXED_VALUE"
9371 };
9372
9373 static const char* assembly_cmds_str[] = {
9374         "GET_LOCATION",
9375         "GET_ENTRY_POINT",
9376         "GET_MANIFEST_MODULE",
9377         "GET_OBJECT",
9378         "GET_TYPE",
9379         "GET_NAME"
9380 };
9381
9382 static const char* module_cmds_str[] = {
9383         "GET_INFO",
9384 };
9385
9386 static const char* field_cmds_str[] = {
9387         "GET_INFO",
9388 };
9389
9390 static const char* method_cmds_str[] = {
9391         "GET_NAME",
9392         "GET_DECLARING_TYPE",
9393         "GET_DEBUG_INFO",
9394         "GET_PARAM_INFO",
9395         "GET_LOCALS_INFO",
9396         "GET_INFO",
9397         "GET_BODY",
9398         "RESOLVE_TOKEN",
9399         "GET_CATTRS ",
9400         "MAKE_GENERIC_METHOD"
9401 };
9402
9403 static const char* type_cmds_str[] = {
9404         "GET_INFO",
9405         "GET_METHODS",
9406         "GET_FIELDS",
9407         "GET_VALUES",
9408         "GET_OBJECT",
9409         "GET_SOURCE_FILES",
9410         "SET_VALUES",
9411         "IS_ASSIGNABLE_FROM",
9412         "GET_PROPERTIES ",
9413         "GET_CATTRS",
9414         "GET_FIELD_CATTRS",
9415         "GET_PROPERTY_CATTRS",
9416         "GET_SOURCE_FILES_2",
9417         "GET_VALUES_2",
9418         "GET_METHODS_BY_NAME_FLAGS",
9419         "GET_INTERFACES",
9420         "GET_INTERFACE_MAP",
9421         "IS_INITIALIZED"
9422 };
9423
9424 static const char* stack_frame_cmds_str[] = {
9425         "GET_VALUES",
9426         "GET_THIS",
9427         "SET_VALUES",
9428         "GET_DOMAIN",
9429 };
9430
9431 static const char* array_cmds_str[] = {
9432         "GET_LENGTH",
9433         "GET_VALUES",
9434         "SET_VALUES",
9435 };
9436
9437 static const char* string_cmds_str[] = {
9438         "GET_VALUE",
9439         "GET_LENGTH",
9440         "GET_CHARS"
9441 };
9442
9443 static const char* object_cmds_str[] = {
9444         "GET_TYPE",
9445         "GET_VALUES",
9446         "IS_COLLECTED",
9447         "GET_ADDRESS",
9448         "GET_DOMAIN",
9449         "SET_VALUES",
9450         "GET_INFO",
9451 };
9452
9453 static const char*
9454 cmd_to_string (CommandSet set, int command)
9455 {
9456         const char **cmds;
9457         int cmds_len = 0;
9458
9459         switch (set) {
9460         case CMD_SET_VM:
9461                 cmds = vm_cmds_str;
9462                 cmds_len = G_N_ELEMENTS (vm_cmds_str);
9463                 break;
9464         case CMD_SET_OBJECT_REF:
9465                 cmds = object_cmds_str;
9466                 cmds_len = G_N_ELEMENTS (object_cmds_str);
9467                 break;
9468         case CMD_SET_STRING_REF:
9469                 cmds = string_cmds_str;
9470                 cmds_len = G_N_ELEMENTS (string_cmds_str);
9471                 break;
9472         case CMD_SET_THREAD:
9473                 cmds = thread_cmds_str;
9474                 cmds_len = G_N_ELEMENTS (thread_cmds_str);
9475                 break;
9476         case CMD_SET_ARRAY_REF:
9477                 cmds = array_cmds_str;
9478                 cmds_len = G_N_ELEMENTS (array_cmds_str);
9479                 break;
9480         case CMD_SET_EVENT_REQUEST:
9481                 cmds = event_cmds_str;
9482                 cmds_len = G_N_ELEMENTS (event_cmds_str);
9483                 break;
9484         case CMD_SET_STACK_FRAME:
9485                 cmds = stack_frame_cmds_str;
9486                 cmds_len = G_N_ELEMENTS (stack_frame_cmds_str);
9487                 break;
9488         case CMD_SET_APPDOMAIN:
9489                 cmds = appdomain_cmds_str;
9490                 cmds_len = G_N_ELEMENTS (appdomain_cmds_str);
9491                 break;
9492         case CMD_SET_ASSEMBLY:
9493                 cmds = assembly_cmds_str;
9494                 cmds_len = G_N_ELEMENTS (assembly_cmds_str);
9495                 break;
9496         case CMD_SET_METHOD:
9497                 cmds = method_cmds_str;
9498                 cmds_len = G_N_ELEMENTS (method_cmds_str);
9499                 break;
9500         case CMD_SET_TYPE:
9501                 cmds = type_cmds_str;
9502                 cmds_len = G_N_ELEMENTS (type_cmds_str);
9503                 break;
9504         case CMD_SET_MODULE:
9505                 cmds = module_cmds_str;
9506                 cmds_len = G_N_ELEMENTS (module_cmds_str);
9507                 break;
9508         case CMD_SET_FIELD:
9509                 cmds = field_cmds_str;
9510                 cmds_len = G_N_ELEMENTS (field_cmds_str);
9511                 break;
9512         case CMD_SET_EVENT:
9513                 cmds = event_cmds_str;
9514                 cmds_len = G_N_ELEMENTS (event_cmds_str);
9515                 break;
9516         default:
9517                 return NULL;
9518         }
9519         if (command > 0 && command <= cmds_len)
9520                 return cmds [command - 1];
9521         else
9522                 return NULL;
9523 }
9524
9525 static gboolean
9526 wait_for_attach (void)
9527 {
9528 #ifndef DISABLE_SOCKET_TRANSPORT
9529         if (listen_fd == -1) {
9530                 DEBUG (1, fprintf (log_file, "[dbg] Invalid listening socket\n"));
9531                 return FALSE;
9532         }
9533
9534         /* Block and wait for client connection */
9535         conn_fd = socket_transport_accept (listen_fd);
9536         DEBUG (1, fprintf (log_file, "Accepted connection on %d\n", conn_fd));
9537         if (conn_fd == -1) {
9538                 DEBUG (1, fprintf (log_file, "[dbg] Bad client connection\n"));
9539                 return FALSE;
9540         }
9541 #else
9542         g_assert_not_reached ();
9543 #endif
9544
9545         /* Handshake */
9546         disconnected = !transport_handshake ();
9547         if (disconnected) {
9548                 DEBUG (1, fprintf (log_file, "Transport handshake failed!\n"));
9549                 return FALSE;
9550         }
9551         
9552         return TRUE;
9553 }
9554
9555 /*
9556  * debugger_thread:
9557  *
9558  *   This thread handles communication with the debugger client using a JDWP
9559  * like protocol.
9560  */
9561 static guint32 WINAPI
9562 debugger_thread (void *arg)
9563 {
9564         int res, len, id, flags, command_set = 0, command = 0;
9565         guint8 header [HEADER_LENGTH];
9566         guint8 *data, *p, *end;
9567         Buffer buf;
9568         ErrorCode err;
9569         gboolean no_reply;
9570         gboolean attach_failed = FALSE;
9571
9572         DEBUG (1, fprintf (log_file, "[dbg] Agent thread started, pid=%p\n", (gpointer)GetCurrentThreadId ()));
9573
9574         debugger_thread_id = GetCurrentThreadId ();
9575
9576         mono_jit_thread_attach (mono_get_root_domain ());
9577
9578         mono_thread_internal_current ()->flags |= MONO_THREAD_FLAG_DONT_MANAGE;
9579
9580         mono_set_is_debugger_attached (TRUE);
9581         
9582         if (agent_config.defer) {
9583                 if (!wait_for_attach ()) {
9584                         DEBUG (1, fprintf (log_file, "[dbg] Can't attach, aborting debugger thread.\n"));
9585                         attach_failed = TRUE; // Don't abort process when we can't listen
9586                 } else {
9587                         /* Send start event to client */
9588                         process_profiler_event (EVENT_KIND_VM_START, mono_thread_get_main ());
9589                 }
9590         }
9591         
9592         while (!attach_failed) {
9593                 res = transport_recv (header, HEADER_LENGTH);
9594
9595                 /* This will break if the socket is closed during shutdown too */
9596                 if (res != HEADER_LENGTH) {
9597                         DEBUG (1, fprintf (log_file, "[dbg] transport_recv () returned %d, expected %d.\n", res, HEADER_LENGTH));
9598                         break;
9599                 }
9600
9601                 p = header;
9602                 end = header + HEADER_LENGTH;
9603
9604                 len = decode_int (p, &p, end);
9605                 id = decode_int (p, &p, end);
9606                 flags = decode_byte (p, &p, end);
9607                 command_set = decode_byte (p, &p, end);
9608                 command = decode_byte (p, &p, end);
9609
9610                 g_assert (flags == 0);
9611
9612                 if (log_level) {
9613                         const char *cmd_str;
9614                         char cmd_num [256];
9615
9616                         cmd_str = cmd_to_string (command_set, command);
9617                         if (!cmd_str) {
9618                                 sprintf (cmd_num, "%d", command);
9619                                 cmd_str = cmd_num;
9620                         }
9621                         
9622                         DEBUG (1, fprintf (log_file, "[dbg] Command %s(%s) [%d][at=%lx].\n", command_set_to_string (command_set), cmd_str, id, (long)mono_100ns_ticks () / 10000));
9623                 }
9624
9625                 data = g_malloc (len - HEADER_LENGTH);
9626                 if (len - HEADER_LENGTH > 0)
9627                 {
9628                         res = transport_recv (data, len - HEADER_LENGTH);
9629                         if (res != len - HEADER_LENGTH) {
9630                                 DEBUG (1, fprintf (log_file, "[dbg] transport_recv () returned %d, expected %d.\n", res, len - HEADER_LENGTH));
9631                                 break;
9632                         }
9633                 }
9634
9635                 p = data;
9636                 end = data + (len - HEADER_LENGTH);
9637
9638                 buffer_init (&buf, 128);
9639
9640                 err = ERR_NONE;
9641                 no_reply = FALSE;
9642
9643                 /* Process the request */
9644                 switch (command_set) {
9645                 case CMD_SET_VM:
9646                         err = vm_commands (command, id, p, end, &buf);
9647                         if (!err && command == CMD_VM_INVOKE_METHOD)
9648                                 /* Sent after the invoke is complete */
9649                                 no_reply = TRUE;
9650                         break;
9651                 case CMD_SET_EVENT_REQUEST:
9652                         err = event_commands (command, p, end, &buf);
9653                         break;
9654                 case CMD_SET_APPDOMAIN:
9655                         err = domain_commands (command, p, end, &buf);
9656                         break;
9657                 case CMD_SET_ASSEMBLY:
9658                         err = assembly_commands (command, p, end, &buf);
9659                         break;
9660                 case CMD_SET_MODULE:
9661                         err = module_commands (command, p, end, &buf);
9662                         break;
9663                 case CMD_SET_FIELD:
9664                         err = field_commands (command, p, end, &buf);
9665                         break;
9666                 case CMD_SET_TYPE:
9667                         err = type_commands (command, p, end, &buf);
9668                         break;
9669                 case CMD_SET_METHOD:
9670                         err = method_commands (command, p, end, &buf);
9671                         break;
9672                 case CMD_SET_THREAD:
9673                         err = thread_commands (command, p, end, &buf);
9674                         break;
9675                 case CMD_SET_STACK_FRAME:
9676                         err = frame_commands (command, p, end, &buf);
9677                         break;
9678                 case CMD_SET_ARRAY_REF:
9679                         err = array_commands (command, p, end, &buf);
9680                         break;
9681                 case CMD_SET_STRING_REF:
9682                         err = string_commands (command, p, end, &buf);
9683                         break;
9684                 case CMD_SET_OBJECT_REF:
9685                         err = object_commands (command, p, end, &buf);
9686                         break;
9687                 default:
9688                         err = ERR_NOT_IMPLEMENTED;
9689                 }               
9690
9691                 if (command_set == CMD_SET_VM && command == CMD_VM_START_BUFFERING) {
9692                         buffer_replies = TRUE;
9693                 }
9694
9695                 if (!no_reply) {
9696                         if (buffer_replies) {
9697                                 buffer_reply_packet (id, err, &buf);
9698                         } else {
9699                                 send_reply_packet (id, err, &buf);
9700                                 //DEBUG (1, fprintf (log_file, "[dbg] Sent reply to %d [at=%lx].\n", id, (long)mono_100ns_ticks () / 10000));
9701                         }
9702                 }
9703
9704                 if (!err && command_set == CMD_SET_VM && command == CMD_VM_STOP_BUFFERING) {
9705                         send_buffered_reply_packets ();
9706                         buffer_replies = FALSE;
9707                 }
9708
9709                 g_free (data);
9710                 buffer_free (&buf);
9711
9712                 if (command_set == CMD_SET_VM && (command == CMD_VM_DISPOSE || command == CMD_VM_EXIT))
9713                         break;
9714         }
9715
9716         mono_set_is_debugger_attached (FALSE);
9717         
9718         mono_mutex_lock (&debugger_thread_exited_mutex);
9719         debugger_thread_exited = TRUE;
9720         mono_cond_signal (&debugger_thread_exited_cond);
9721         mono_mutex_unlock (&debugger_thread_exited_mutex);
9722
9723         DEBUG (1, fprintf (log_file, "[dbg] Debugger thread exited.\n"));
9724         
9725         if (!attach_failed && command_set == CMD_SET_VM && command == CMD_VM_DISPOSE && !(vm_death_event_sent || mono_runtime_is_shutting_down ())) {
9726                 DEBUG (2, fprintf (log_file, "[dbg] Detached - restarting clean debugger thread.\n"));
9727                 start_debugger_thread ();
9728         }
9729         
9730         return 0;
9731 }
9732
9733 #else /* DISABLE_DEBUGGER_AGENT */
9734
9735 void
9736 mono_debugger_agent_parse_options (char *options)
9737 {
9738         g_error ("This runtime is configured with the debugger agent disabled.");
9739 }
9740
9741 void
9742 mono_debugger_agent_init (void)
9743 {
9744 }
9745
9746 void
9747 mono_debugger_agent_breakpoint_hit (void *sigctx)
9748 {
9749 }
9750
9751 void
9752 mono_debugger_agent_single_step_event (void *sigctx)
9753 {
9754 }
9755
9756 void
9757 mono_debugger_agent_free_domain_info (MonoDomain *domain)
9758 {
9759 }
9760
9761 gboolean
9762 mono_debugger_agent_thread_interrupt (void *sigctx, MonoJitInfo *ji)
9763 {
9764         return FALSE;
9765 }
9766
9767 void
9768 mono_debugger_agent_handle_exception (MonoException *ext, MonoContext *throw_ctx,
9769                                                                           MonoContext *catch_ctx)
9770 {
9771 }
9772
9773 void
9774 mono_debugger_agent_begin_exception_filter (MonoException *exc, MonoContext *ctx, MonoContext *orig_ctx)
9775 {
9776 }
9777
9778 void
9779 mono_debugger_agent_end_exception_filter (MonoException *exc, MonoContext *ctx, MonoContext *orig_ctx)
9780 {
9781 }
9782
9783 void
9784 mono_debugger_agent_user_break (void)
9785 {
9786         G_BREAKPOINT ();
9787 }
9788
9789 void
9790 mono_debugger_agent_debug_log (int level, MonoString *category, MonoString *message)
9791 {
9792 }
9793
9794 gboolean
9795 mono_debugger_agent_debug_log_is_enabled (void)
9796 {
9797         return FALSE;
9798 }
9799
9800 void
9801 mono_debugger_agent_unhandled_exception (MonoException *exc)
9802 {
9803         g_assert_not_reached ();
9804 }
9805
9806 #endif
9807