Cleanup sdb to use the new unwind state code.
[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  */
9
10 #include <config.h>
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string.h>
14 #ifdef HAVE_SYS_TYPES_H
15 #include <sys/types.h>
16 #endif
17 #ifdef HAVE_SYS_SELECT_H
18 #include <sys/select.h>
19 #endif
20 #ifdef HAVE_SYS_SOCKET_H
21 #include <sys/socket.h>
22 #endif
23 #ifdef HAVE_NETINET_TCP_H
24 #include <netinet/tcp.h>
25 #endif
26 #ifdef HAVE_NETINET_IN_H
27 #include <netinet/in.h>
28 #endif
29 #ifdef HAVE_NETDB_H
30 #include <netdb.h>
31 #endif
32 #ifdef HAVE_UNISTD_H
33 #include <unistd.h>
34 #endif
35 #include <errno.h>
36 #include <glib.h>
37
38 #ifdef HAVE_PTHREAD_H
39 #include <pthread.h>
40 #endif
41
42 #ifdef HAVE_UCONTEXT_H
43 #include <ucontext.h>
44 #endif
45
46 #ifdef HOST_WIN32
47 #ifdef _MSC_VER
48 #include <winsock2.h>
49 #endif
50 #include <ws2tcpip.h>
51 #ifdef __GNUC__
52 /* cygwin's headers do not seem to define these */
53 void WSAAPI freeaddrinfo (struct addrinfo*);
54 int WSAAPI getaddrinfo (const char*,const char*,const struct addrinfo*,
55                         struct addrinfo**);
56 int WSAAPI getnameinfo(const struct sockaddr*,socklen_t,char*,DWORD,
57                        char*,DWORD,int);
58 #endif
59 #endif
60
61 #ifdef PLATFORM_ANDROID
62 #include <linux/in.h>
63 #include <linux/tcp.h>
64 #include <sys/endian.h>
65 #endif
66
67 #include <mono/metadata/mono-debug.h>
68 #include <mono/metadata/mono-debug-debugger.h>
69 #include <mono/metadata/debug-mono-symfile.h>
70 #include <mono/metadata/gc-internal.h>
71 #include <mono/metadata/threads-types.h>
72 #include <mono/metadata/socket-io.h>
73 #include <mono/metadata/assembly.h>
74 #include <mono/utils/mono-semaphore.h>
75 #include <mono/utils/mono-error-internals.h>
76 #include <mono/utils/mono-stack-unwinding.h>
77 #include "debugger-agent.h"
78 #include "mini.h"
79
80 #ifndef MONO_ARCH_SOFT_DEBUG_SUPPORTED
81 #define DISABLE_DEBUGGER_AGENT 1
82 #endif
83
84 #ifdef DISABLE_SOFT_DEBUG
85 #define DISABLE_DEBUGGER_AGENT 1
86 #endif
87
88 #ifndef DISABLE_DEBUGGER_AGENT
89
90 #include <mono/io-layer/mono-mutex.h>
91
92 /* Definitions to make backporting to 2.6 easier */
93 //#define MonoInternalThread MonoThread
94 //#define mono_thread_internal_current mono_thread_current
95 #define THREAD_TO_INTERNAL(thread) (thread)->internal_thread
96
97 typedef struct {
98         gboolean enabled;
99         char *transport;
100         char *address;
101         int log_level;
102         char *log_file;
103         gboolean suspend;
104         gboolean server;
105         gboolean onuncaught;
106         GSList *onthrow;
107         int timeout;
108         char *launch;
109         gboolean embedding;
110         gboolean defer;
111 } AgentConfig;
112
113 typedef struct
114 {
115         int id;
116         guint32 il_offset, native_offset;
117         MonoDomain *domain;
118         MonoMethod *method;
119         /*
120          * If method is gshared, this is the actual instance, otherwise this is equal to
121          * method.
122          */
123         MonoMethod *actual_method;
124         MonoContext ctx;
125         MonoDebugMethodJitInfo *jit;
126         int flags;
127         /*
128          * Whenever ctx is set. This is FALSE for the last frame of running threads, since
129          * the frame can become invalid.
130          */
131         gboolean has_ctx;
132 } StackFrame;
133
134 typedef struct _InvokeData InvokeData;
135
136 struct _InvokeData
137 {
138         int id;
139         int flags;
140         guint8 *p;
141         guint8 *endp;
142         /* This is the context which needs to be restored after the invoke */
143         MonoContext ctx;
144         gboolean has_ctx;
145         /*
146          * If this is set, invoke this method with the arguments given by ARGS.
147          */
148         MonoMethod *method;
149         gpointer *args;
150         guint32 suspend_count;
151
152         InvokeData *last_invoke;
153 };
154
155 typedef struct {
156         MonoThreadUnwindState context;
157
158         gpointer resume_event;
159         /* This is computed on demand when it is requested using the wire protocol */
160         /* It is freed up when the thread is resumed */
161         int frame_count;
162         StackFrame **frames;
163         /* 
164          * Whenever the frame info is up-to-date. If not, compute_frame_info () will need to
165          * re-compute it.
166          */
167         gboolean frames_up_to_date;
168         /* 
169          * Points to data about a pending invoke which needs to be executed after the thread
170          * resumes.
171          */
172         InvokeData *pending_invoke;
173         /*
174          * Set to TRUE if this thread is suspended in suspend_current () or it is executing
175          * native code.
176          */
177         gboolean suspended;
178         /*
179          * Signals whenever the thread is in the process of suspending, i.e. it will suspend
180          * within a finite amount of time.
181          */
182         gboolean suspending;
183         /*
184          * Set to TRUE if this thread is suspended in suspend_current ().
185          */
186         gboolean really_suspended;
187         /* Used to pass the context to the breakpoint/single step handler */
188         MonoContext handler_ctx;
189         /* Whenever thread_stop () was called for this thread */
190         gboolean terminated;
191
192         /* Number of thread interruptions not yet processed */
193         gint32 interrupt_count;
194
195         /* Whenever to disable breakpoints (used during invokes) */
196         gboolean disable_breakpoints;
197
198         /*
199          * Number of times this thread has been resumed using resume_thread ().
200          */
201         guint32 resume_count;
202
203         MonoInternalThread *thread;
204
205         /*
206          * Information about the frame which transitioned to native code for running
207          * threads.
208          */
209         StackFrameInfo async_last_frame;
210
211         /*
212          * The context where the stack walk can be started for running threads.
213          */
214         MonoThreadUnwindState async_state;
215
216         /*
217      * The context used for filter clauses
218      */
219         MonoThreadUnwindState filter_state;
220
221         /*
222          * The callee address of the last mono_runtime_invoke call
223          */
224         gpointer invoke_addr;
225
226         gboolean abort_requested;
227
228         /*
229          * The current mono_runtime_invoke invocation.
230          */
231         InvokeData *invoke;
232
233         /*
234          * The context where single stepping should resume while the thread is suspended because
235          * of an EXCEPTION event.
236          */
237         MonoContext catch_ctx;
238
239         gboolean has_catch_ctx;
240 } DebuggerTlsData;
241
242 /* 
243  * Wire Protocol definitions
244  */
245
246 #define HEADER_LENGTH 11
247
248 #define MAJOR_VERSION 2
249 #define MINOR_VERSION 3
250
251 typedef enum {
252         CMD_SET_VM = 1,
253         CMD_SET_OBJECT_REF = 9,
254         CMD_SET_STRING_REF = 10,
255         CMD_SET_THREAD = 11,
256         CMD_SET_ARRAY_REF = 13,
257         CMD_SET_EVENT_REQUEST = 15,
258         CMD_SET_STACK_FRAME = 16,
259         CMD_SET_APPDOMAIN = 20,
260         CMD_SET_ASSEMBLY = 21,
261         CMD_SET_METHOD = 22,
262         CMD_SET_TYPE = 23,
263         CMD_SET_MODULE = 24,
264         CMD_SET_EVENT = 64
265 } CommandSet;
266
267 typedef enum {
268         EVENT_KIND_VM_START = 0,
269         EVENT_KIND_VM_DEATH = 1,
270         EVENT_KIND_THREAD_START = 2,
271         EVENT_KIND_THREAD_DEATH = 3,
272         EVENT_KIND_APPDOMAIN_CREATE = 4,
273         EVENT_KIND_APPDOMAIN_UNLOAD = 5,
274         EVENT_KIND_METHOD_ENTRY = 6,
275         EVENT_KIND_METHOD_EXIT = 7,
276         EVENT_KIND_ASSEMBLY_LOAD = 8,
277         EVENT_KIND_ASSEMBLY_UNLOAD = 9,
278         EVENT_KIND_BREAKPOINT = 10,
279         EVENT_KIND_STEP = 11,
280         EVENT_KIND_TYPE_LOAD = 12,
281         EVENT_KIND_EXCEPTION = 13
282 } EventKind;
283
284 typedef enum {
285         SUSPEND_POLICY_NONE = 0,
286         SUSPEND_POLICY_EVENT_THREAD = 1,
287         SUSPEND_POLICY_ALL = 2
288 } SuspendPolicy;
289
290 typedef enum {
291         ERR_NONE = 0,
292         ERR_INVALID_OBJECT = 20,
293         ERR_INVALID_FIELDID = 25,
294         ERR_INVALID_FRAMEID = 30,
295         ERR_NOT_IMPLEMENTED = 100,
296         ERR_NOT_SUSPENDED = 101,
297         ERR_INVALID_ARGUMENT = 102,
298         ERR_UNLOADED = 103,
299         ERR_NO_INVOCATION = 104,
300         ERR_ABSENT_INFORMATION = 105,
301         ERR_NO_SEQ_POINT_AT_IL_OFFSET = 106
302 } ErrorCode;
303
304 typedef enum {
305         MOD_KIND_COUNT = 1,
306         MOD_KIND_THREAD_ONLY = 3,
307         MOD_KIND_LOCATION_ONLY = 7,
308         MOD_KIND_EXCEPTION_ONLY = 8,
309         MOD_KIND_STEP = 10,
310         MOD_KIND_ASSEMBLY_ONLY = 11
311 } ModifierKind;
312
313 typedef enum {
314         STEP_DEPTH_INTO = 0,
315         STEP_DEPTH_OVER = 1,
316         STEP_DEPTH_OUT = 2
317 } StepDepth;
318
319 typedef enum {
320         STEP_SIZE_MIN = 0,
321         STEP_SIZE_LINE = 1
322 } StepSize;
323
324 typedef enum {
325         TOKEN_TYPE_STRING = 0,
326         TOKEN_TYPE_TYPE = 1,
327         TOKEN_TYPE_FIELD = 2,
328         TOKEN_TYPE_METHOD = 3,
329         TOKEN_TYPE_UNKNOWN = 4
330 } DebuggerTokenType;
331
332 typedef enum {
333         VALUE_TYPE_ID_NULL = 0xf0,
334         VALUE_TYPE_ID_TYPE = 0xf1
335 } ValueTypeId;
336
337 typedef enum {
338         FRAME_FLAG_DEBUGGER_INVOKE = 1
339 } StackFrameFlags;
340
341 typedef enum {
342         INVOKE_FLAG_DISABLE_BREAKPOINTS = 1,
343         INVOKE_FLAG_SINGLE_THREADED = 2
344 } InvokeFlags;
345
346 typedef enum {
347         CMD_VM_VERSION = 1,
348         CMD_VM_ALL_THREADS = 2,
349         CMD_VM_SUSPEND = 3,
350         CMD_VM_RESUME = 4,
351         CMD_VM_EXIT = 5,
352         CMD_VM_DISPOSE = 6,
353         CMD_VM_INVOKE_METHOD = 7,
354         CMD_VM_SET_PROTOCOL_VERSION = 8,
355         CMD_VM_ABORT_INVOKE = 9
356 } CmdVM;
357
358 typedef enum {
359         CMD_THREAD_GET_FRAME_INFO = 1,
360         CMD_THREAD_GET_NAME = 2,
361         CMD_THREAD_GET_STATE = 3,
362         CMD_THREAD_GET_INFO = 4,
363         CMD_THREAD_GET_ID = 5,
364         CMD_THREAD_GET_TID = 6
365 } CmdThread;
366
367 typedef enum {
368         CMD_EVENT_REQUEST_SET = 1,
369         CMD_EVENT_REQUEST_CLEAR = 2,
370         CMD_EVENT_REQUEST_CLEAR_ALL_BREAKPOINTS = 3
371 } CmdEvent;
372
373 typedef enum {
374         CMD_COMPOSITE = 100
375 } CmdComposite;
376
377 typedef enum {
378         CMD_APPDOMAIN_GET_ROOT_DOMAIN = 1,
379         CMD_APPDOMAIN_GET_FRIENDLY_NAME = 2,
380         CMD_APPDOMAIN_GET_ASSEMBLIES = 3,
381         CMD_APPDOMAIN_GET_ENTRY_ASSEMBLY = 4,
382         CMD_APPDOMAIN_CREATE_STRING = 5,
383         CMD_APPDOMAIN_GET_CORLIB = 6,
384         CMD_APPDOMAIN_CREATE_BOXED_VALUE = 7,
385 } CmdAppDomain;
386
387 typedef enum {
388         CMD_ASSEMBLY_GET_LOCATION = 1,
389         CMD_ASSEMBLY_GET_ENTRY_POINT = 2,
390         CMD_ASSEMBLY_GET_MANIFEST_MODULE = 3,
391         CMD_ASSEMBLY_GET_OBJECT = 4,
392         CMD_ASSEMBLY_GET_TYPE = 5,
393         CMD_ASSEMBLY_GET_NAME = 6
394 } CmdAssembly;
395
396 typedef enum {
397         CMD_MODULE_GET_INFO = 1,
398 } CmdModule;
399
400 typedef enum {
401         CMD_METHOD_GET_NAME = 1,
402         CMD_METHOD_GET_DECLARING_TYPE = 2,
403         CMD_METHOD_GET_DEBUG_INFO = 3,
404         CMD_METHOD_GET_PARAM_INFO = 4,
405         CMD_METHOD_GET_LOCALS_INFO = 5,
406         CMD_METHOD_GET_INFO = 6,
407         CMD_METHOD_GET_BODY = 7,
408         CMD_METHOD_RESOLVE_TOKEN = 8,
409 } CmdMethod;
410
411 typedef enum {
412         CMD_TYPE_GET_INFO = 1,
413         CMD_TYPE_GET_METHODS = 2,
414         CMD_TYPE_GET_FIELDS = 3,
415         CMD_TYPE_GET_VALUES = 4,
416         CMD_TYPE_GET_OBJECT = 5,
417         CMD_TYPE_GET_SOURCE_FILES = 6,
418         CMD_TYPE_SET_VALUES = 7,
419         CMD_TYPE_IS_ASSIGNABLE_FROM = 8,
420         CMD_TYPE_GET_PROPERTIES = 9,
421         CMD_TYPE_GET_CATTRS = 10,
422         CMD_TYPE_GET_FIELD_CATTRS = 11,
423         CMD_TYPE_GET_PROPERTY_CATTRS = 12,
424         CMD_TYPE_GET_SOURCE_FILES_2 = 13,
425         CMD_TYPE_GET_VALUES_2 = 14
426 } CmdType;
427
428 typedef enum {
429         CMD_STACK_FRAME_GET_VALUES = 1,
430         CMD_STACK_FRAME_GET_THIS = 2,
431         CMD_STACK_FRAME_SET_VALUES = 3
432 } CmdStackFrame;
433
434 typedef enum {
435         CMD_ARRAY_REF_GET_LENGTH = 1,
436         CMD_ARRAY_REF_GET_VALUES = 2,
437         CMD_ARRAY_REF_SET_VALUES = 3,
438 } CmdArray;
439
440 typedef enum {
441         CMD_STRING_REF_GET_VALUE = 1,
442 } CmdString;
443
444 typedef enum {
445         CMD_OBJECT_REF_GET_TYPE = 1,
446         CMD_OBJECT_REF_GET_VALUES = 2,
447         CMD_OBJECT_REF_IS_COLLECTED = 3,
448         CMD_OBJECT_REF_GET_ADDRESS = 4,
449         CMD_OBJECT_REF_GET_DOMAIN = 5,
450         CMD_OBJECT_REF_SET_VALUES = 6
451 } CmdObject;
452
453 typedef struct {
454         ModifierKind kind;
455         union {
456                 int count; /* For kind == MOD_KIND_COUNT */
457                 MonoInternalThread *thread; /* For kind == MOD_KIND_THREAD_ONLY */
458                 MonoClass *exc_class; /* For kind == MONO_KIND_EXCEPTION_ONLY */
459                 MonoAssembly **assemblies; /* For kind == MONO_KIND_ASSEMBLY_ONLY */
460         } data;
461         gboolean caught, uncaught; /* For kind == MOD_KIND_EXCEPTION_ONLY */
462 } Modifier;
463
464 typedef struct{
465         int id;
466         int event_kind;
467         int suspend_policy;
468         int nmodifiers;
469         gpointer info;
470         Modifier modifiers [MONO_ZERO_LEN_ARRAY];
471 } EventRequest;
472
473 /*
474  * Describes a single step request.
475  */
476 typedef struct {
477         EventRequest *req;
478         MonoInternalThread *thread;
479         StepDepth depth;
480         StepSize size;
481         gpointer last_sp;
482         gpointer start_sp;
483         MonoMethod *last_method;
484         int last_line;
485         /* Whenever single stepping is performed using start/stop_single_stepping () */
486         gboolean global;
487         /* The list of breakpoints used to implement step-over */
488         GSList *bps;
489 } SingleStepReq;
490
491 /*
492  * Contains additional information for an event
493  */
494 typedef struct {
495         /* For EVENT_KIND_EXCEPTION */
496         MonoObject *exc;
497         MonoContext catch_ctx;
498         gboolean caught;
499 } EventInfo;
500
501 /* Dummy structure used for the profiler callbacks */
502 typedef struct {
503         void* dummy;
504 } DebuggerProfiler;
505
506 #define DEBUG(level,s) do { if (G_UNLIKELY ((level) <= log_level)) { s; fflush (log_file); } } while (0)
507
508 /*
509  * Globals
510  */
511
512 static AgentConfig agent_config;
513
514 /* 
515  * Whenever the agent is fully initialized.
516  * When using the onuncaught or onthrow options, only some parts of the agent are
517  * initialized on startup, and the full initialization which includes connection
518  * establishment and the startup of the agent thread is only done in response to
519  * an event.
520  */
521 static gint32 inited;
522
523 static int conn_fd;
524 static int listen_fd;
525
526 static int packet_id = 0;
527
528 static int objref_id = 0;
529
530 static int event_request_id = 0;
531
532 static int frame_id = 0;
533
534 static GPtrArray *event_requests;
535
536 static guint32 debugger_tls_id;
537
538 static gboolean vm_start_event_sent, vm_death_event_sent, disconnected;
539
540 /* Maps MonoInternalThread -> DebuggerTlsData */
541 static MonoGHashTable *thread_to_tls;
542
543 /* Maps tid -> MonoInternalThread */
544 static MonoGHashTable *tid_to_thread;
545
546 /* Maps tid -> MonoThread (not MonoInternalThread) */
547 static MonoGHashTable *tid_to_thread_obj;
548
549 static gsize debugger_thread_id;
550
551 static HANDLE debugger_thread_handle;
552
553 static int log_level;
554
555 static gboolean embedding;
556
557 static FILE *log_file;
558
559 /* Assemblies whose assembly load event has no been sent yet */
560 static GPtrArray *pending_assembly_loads;
561
562 /* Whenever the debugger thread has exited */
563 static gboolean debugger_thread_exited;
564
565 /* Cond variable used to wait for debugger_thread_exited becoming true */
566 static mono_cond_t debugger_thread_exited_cond;
567
568 /* Mutex for the cond var above */
569 static mono_mutex_t debugger_thread_exited_mutex;
570
571 static DebuggerProfiler debugger_profiler;
572
573 /* The single step request instance */
574 static SingleStepReq *ss_req = NULL;
575 static gpointer ss_invoke_addr = NULL;
576
577 #ifdef MONO_ARCH_SOFT_DEBUG_SUPPORTED
578 /* Number of single stepping operations in progress */
579 static int ss_count;
580 #endif
581
582 /* The protocol version of the client */
583 static int major_version, minor_version;
584
585 /* Whenever the variables above are set by the client */
586 static gboolean protocol_version_set;
587
588 /* A hash table containing all active domains */
589 static GHashTable *domains;
590
591 static void transport_connect (const char *host, int port);
592
593 static guint32 WINAPI debugger_thread (void *arg);
594
595 static void runtime_initialized (MonoProfiler *prof);
596
597 static void runtime_shutdown (MonoProfiler *prof);
598
599 static void thread_startup (MonoProfiler *prof, uintptr_t tid);
600
601 static void thread_end (MonoProfiler *prof, uintptr_t tid);
602
603 static void appdomain_load (MonoProfiler *prof, MonoDomain *domain, int result);
604
605 static void appdomain_unload (MonoProfiler *prof, MonoDomain *domain);
606
607 static void emit_appdomain_load (gpointer key, gpointer value, gpointer user_data);
608
609 static void emit_thread_start (gpointer key, gpointer value, gpointer user_data);
610
611 static void invalidate_each_thread (gpointer key, gpointer value, gpointer user_data);
612
613 static void assembly_load (MonoProfiler *prof, MonoAssembly *assembly, int result);
614
615 static void assembly_unload (MonoProfiler *prof, MonoAssembly *assembly);
616
617 static void emit_assembly_load (gpointer assembly, gpointer user_data);
618
619 static void emit_type_load (gpointer key, gpointer type, gpointer user_data);
620
621 static void start_runtime_invoke (MonoProfiler *prof, MonoMethod *method);
622
623 static void end_runtime_invoke (MonoProfiler *prof, MonoMethod *method);
624
625 static void jit_end (MonoProfiler *prof, MonoMethod *method, MonoJitInfo *jinfo, int result);
626
627 static void add_pending_breakpoints (MonoMethod *method, MonoJitInfo *jinfo);
628
629 static void start_single_stepping (void);
630
631 static void stop_single_stepping (void);
632
633 static void suspend_current (void);
634
635 static void clear_event_requests_for_assembly (MonoAssembly *assembly);
636
637 static void clear_types_for_assembly (MonoAssembly *assembly);
638
639 static void clear_breakpoints_for_domain (MonoDomain *domain);
640
641 static void process_profiler_event (EventKind event, gpointer arg);
642
643 /* Submodule init/cleanup */
644 static void breakpoints_init (void);
645 static void breakpoints_cleanup (void);
646
647 static void objrefs_init (void);
648 static void objrefs_cleanup (void);
649
650 static void ids_init (void);
651 static void ids_cleanup (void);
652
653 static void suspend_init (void);
654
655 static void ss_start (SingleStepReq *ss_req, MonoMethod *method, SeqPoint *sp, MonoSeqPointInfo *info, MonoContext *ctx, DebuggerTlsData *tls, gboolean step_to_catch);
656 static ErrorCode ss_create (MonoInternalThread *thread, StepSize size, StepDepth depth, EventRequest *req);
657 static void ss_destroy (SingleStepReq *req);
658
659 static void start_debugger_thread (void);
660 static void stop_debugger_thread (void);
661
662 static void finish_agent_init (gboolean on_startup);
663
664 static int
665 parse_address (char *address, char **host, int *port)
666 {
667         char *pos = strchr (address, ':');
668
669         if (pos == NULL || pos == address)
670                 return 1;
671
672         *host = g_malloc (pos - address + 1);
673         strncpy (*host, address, pos - address);
674         (*host) [pos - address] = '\0';
675
676         *port = atoi (pos + 1);
677
678         return 0;
679 }
680
681 static void
682 print_usage (void)
683 {
684         fprintf (stderr, "Usage: mono --debugger-agent=[<option>=<value>,...] ...\n");
685         fprintf (stderr, "Available options:\n");
686         fprintf (stderr, "  transport=<transport>\t\tTransport to use for connecting to the debugger (mandatory, possible values: 'dt_socket')\n");
687         fprintf (stderr, "  address=<hostname>:<port>\tAddress to connect to (mandatory)\n");
688         fprintf (stderr, "  loglevel=<n>\t\t\tLog level (defaults to 0)\n");
689         fprintf (stderr, "  logfile=<file>\t\tFile to log to (defaults to stdout)\n");
690         fprintf (stderr, "  suspend=y/n\t\t\tWhether to suspend after startup.\n");
691         fprintf (stderr, "  timeout=<n>\t\t\tTimeout for connecting in milliseconds.\n");
692         fprintf (stderr, "  server=y/n\t\t\tWhether to listen for a client connection.\n");
693         fprintf (stderr, "  help\t\t\t\tPrint this help.\n");
694 }
695
696 static gboolean
697 parse_flag (const char *option, char *flag)
698 {
699         if (!strcmp (flag, "y"))
700                 return TRUE;
701         else if (!strcmp (flag, "n"))
702                 return FALSE;
703         else {
704                 fprintf (stderr, "debugger-agent: The valid values for the '%s' option are 'y' and 'n'.\n", option);
705                 exit (1);
706                 return FALSE;
707         }
708 }
709
710 void
711 mono_debugger_agent_parse_options (char *options)
712 {
713         char **args, **ptr;
714         char *host;
715         int port;
716
717 #ifndef MONO_ARCH_SOFT_DEBUG_SUPPORTED
718         fprintf (stderr, "--debugger-agent is not supported on this platform.\n");
719         exit (1);
720 #endif
721
722         agent_config.enabled = TRUE;
723         agent_config.suspend = TRUE;
724         agent_config.server = FALSE;
725         agent_config.defer = FALSE;
726         agent_config.address = NULL;
727
728         args = g_strsplit (options, ",", -1);
729         for (ptr = args; ptr && *ptr; ptr ++) {
730                 char *arg = *ptr;
731
732                 if (strncmp (arg, "transport=", 10) == 0) {
733                         agent_config.transport = g_strdup (arg + 10);
734                 } else if (strncmp (arg, "address=", 8) == 0) {
735                         agent_config.address = g_strdup (arg + 8);
736                 } else if (strncmp (arg, "loglevel=", 9) == 0) {
737                         agent_config.log_level = atoi (arg + 9);
738                 } else if (strncmp (arg, "logfile=", 8) == 0) {
739                         agent_config.log_file = g_strdup (arg + 8);
740                 } else if (strncmp (arg, "suspend=", 8) == 0) {
741                         agent_config.suspend = parse_flag ("suspend", arg + 8);
742                 } else if (strncmp (arg, "server=", 7) == 0) {
743                         agent_config.server = parse_flag ("server", arg + 7);
744                 } else if (strncmp (arg, "onuncaught=", 11) == 0) {
745                         agent_config.onuncaught = parse_flag ("onuncaught", arg + 11);
746                 } else if (strncmp (arg, "onthrow=", 8) == 0) {
747                         /* We support multiple onthrow= options */
748                         agent_config.onthrow = g_slist_append (agent_config.onthrow, g_strdup (arg + 8));
749                 } else if (strncmp (arg, "onthrow", 7) == 0) {
750                         agent_config.onthrow = g_slist_append (agent_config.onthrow, g_strdup (""));
751                 } else if (strncmp (arg, "help", 4) == 0) {
752                         print_usage ();
753                         exit (0);
754                 } else if (strncmp (arg, "timeout=", 8) == 0) {
755                         agent_config.timeout = atoi (arg + 8);
756                 } else if (strncmp (arg, "launch=", 7) == 0) {
757                         agent_config.launch = g_strdup (arg + 7);
758                 } else if (strncmp (arg, "embedding=", 10) == 0) {
759                         agent_config.embedding = atoi (arg + 10) == 1;
760                 } else {
761                         print_usage ();
762                         exit (1);
763                 }
764         }
765
766         if (agent_config.server && !agent_config.suspend) {
767                 /* Waiting for deferred attachment */
768                 agent_config.defer = TRUE;
769                 if (agent_config.address == NULL) {
770                         agent_config.address = g_strdup_printf ("0.0.0.0:%u", 56000 + (GetCurrentProcessId () % 1000));
771                 }
772         }
773
774         if (agent_config.transport == NULL) {
775                 fprintf (stderr, "debugger-agent: The 'transport' option is mandatory.\n");
776                 exit (1);
777         }
778         if (strcmp (agent_config.transport, "dt_socket") != 0) {
779                 fprintf (stderr, "debugger-agent: The only supported value for the 'transport' option is 'dt_socket'.\n");
780                 exit (1);
781         }
782
783         if (agent_config.address == NULL && !agent_config.server) {
784                 fprintf (stderr, "debugger-agent: The 'address' option is mandatory.\n");
785                 exit (1);
786         }
787
788         if (agent_config.address && parse_address (agent_config.address, &host, &port)) {
789                 fprintf (stderr, "debugger-agent: The format of the 'address' options is '<host>:<port>'\n");
790                 exit (1);
791         }
792 }
793
794 void
795 mono_debugger_agent_init (void)
796 {
797         if (!agent_config.enabled)
798                 return;
799
800         /* Need to know whenever a thread has acquired the loader mutex */
801         mono_loader_lock_track_ownership (TRUE);
802
803         event_requests = g_ptr_array_new ();
804
805         mono_mutex_init (&debugger_thread_exited_mutex, NULL);
806         mono_cond_init (&debugger_thread_exited_cond, NULL);
807
808         mono_profiler_install ((MonoProfiler*)&debugger_profiler, runtime_shutdown);
809         mono_profiler_set_events (MONO_PROFILE_APPDOMAIN_EVENTS | MONO_PROFILE_THREADS | MONO_PROFILE_ASSEMBLY_EVENTS | MONO_PROFILE_JIT_COMPILATION | MONO_PROFILE_METHOD_EVENTS);
810         mono_profiler_install_runtime_initialized (runtime_initialized);
811         mono_profiler_install_appdomain (NULL, appdomain_load, NULL, appdomain_unload);
812         mono_profiler_install_thread (thread_startup, thread_end);
813         mono_profiler_install_assembly (NULL, assembly_load, assembly_unload, NULL);
814         mono_profiler_install_jit_end (jit_end);
815         mono_profiler_install_method_invoke (start_runtime_invoke, end_runtime_invoke);
816
817         debugger_tls_id = TlsAlloc ();
818
819         thread_to_tls = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_KEY_GC);
820         MONO_GC_REGISTER_ROOT_FIXED (thread_to_tls);
821
822         tid_to_thread = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
823         MONO_GC_REGISTER_ROOT_FIXED (tid_to_thread);
824
825         tid_to_thread_obj = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
826         MONO_GC_REGISTER_ROOT_FIXED (tid_to_thread_obj);
827
828         pending_assembly_loads = g_ptr_array_new ();
829         domains = g_hash_table_new (mono_aligned_addr_hash, NULL);
830
831         log_level = agent_config.log_level;
832
833         embedding = agent_config.embedding;
834         disconnected = TRUE;
835
836         if (agent_config.log_file) {
837                 log_file = fopen (agent_config.log_file, "w+");
838                 if (!log_file) {
839                         fprintf (stderr, "Unable to create log file '%s': %s.\n", agent_config.log_file, strerror (errno));
840                         exit (1);
841                 }
842         } else {
843                 log_file = stdout;
844         }
845
846         ids_init ();
847         objrefs_init ();
848         breakpoints_init ();
849         suspend_init ();
850
851         mini_get_debug_options ()->gen_seq_points = TRUE;
852         /* 
853          * This is needed because currently we don't handle liveness info.
854          */
855         mini_get_debug_options ()->mdb_optimizations = TRUE;
856
857         /* This is needed because we can't set local variables in registers yet */
858         mono_disable_optimizations (MONO_OPT_LINEARS);
859
860         if (!agent_config.onuncaught && !agent_config.onthrow)
861                 finish_agent_init (TRUE);
862 }
863
864 /*
865  * finish_agent_init:
866  *
867  *   Finish the initialization of the agent. This involves connecting the transport
868  * and starting the agent thread. This is either done at startup, or
869  * in response to some event like an unhandled exception.
870  */
871 static void
872 finish_agent_init (gboolean on_startup)
873 {
874         char *host;
875         int port;
876         int res;
877
878         if (InterlockedCompareExchange (&inited, 1, 0) == 1)
879                 return;
880
881         if (agent_config.launch) {
882                 char *argv [16];
883
884                 // FIXME: Generated address
885                 // FIXME: Races with transport_connect ()
886
887                 argv [0] = agent_config.launch;
888                 argv [1] = agent_config.transport;
889                 argv [2] = agent_config.address;
890                 argv [3] = NULL;
891
892                 res = g_spawn_async_with_pipes (NULL, argv, NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
893                 if (!res) {
894                         fprintf (stderr, "Failed to execute '%s'.\n", agent_config.launch);
895                         exit (1);
896                 }
897         }
898
899         if (agent_config.address) {
900                 res = parse_address (agent_config.address, &host, &port);
901                 g_assert (res == 0);
902         } else {
903                 host = NULL;
904                 port = 0;
905         }
906
907         transport_connect (host, port);
908
909         if (!on_startup) {
910                 /* Do some which is usually done after sending the VMStart () event */
911                 vm_start_event_sent = TRUE;
912                 start_debugger_thread ();
913         }
914 }
915
916 static void
917 mono_debugger_agent_cleanup (void)
918 {
919         if (!inited)
920                 return;
921
922         stop_debugger_thread ();
923
924         breakpoints_cleanup ();
925         objrefs_cleanup ();
926         ids_cleanup ();
927         
928         mono_mutex_destroy (&debugger_thread_exited_mutex);
929         mono_cond_destroy (&debugger_thread_exited_cond);
930 }
931
932 /*
933  * recv_length:
934  *
935  * recv() + handle incomplete reads and EINTR
936  */
937 static int
938 recv_length (int fd, void *buf, int len, int flags)
939 {
940         int res;
941         int total = 0;
942
943         do {
944                 res = recv (fd, (char *) buf + total, len - total, flags);
945                 if (res > 0)
946                         total += res;
947         } while ((res > 0 && total < len) || (res == -1 && errno == EINTR));
948         return total;
949 }
950
951 #ifndef TARGET_PS3
952 #define HAVE_GETADDRINFO 1
953 #endif
954  
955 static int
956 transport_accept (int socket_fd)
957 {
958         conn_fd = accept (socket_fd, NULL, NULL);
959         if (conn_fd == -1) {
960                 fprintf (stderr, "debugger-agent: Unable to listen on %d\n", socket_fd);
961         } else {
962                 DEBUG (1, fprintf (log_file, "Accepted connection from client, connection fd=%d.\n", conn_fd));
963         }
964         
965         return conn_fd;
966 }
967
968 static gboolean
969 transport_handshake (void)
970 {
971         char handshake_msg [128];
972         guint8 buf [128];
973         int res;
974         
975         /* Write handshake message */
976         sprintf (handshake_msg, "DWP-Handshake");
977         do {
978                 res = send (conn_fd, handshake_msg, strlen (handshake_msg), 0);
979         } while (res == -1 && errno == EINTR);
980         g_assert (res != -1);
981
982         /* Read answer */
983         res = recv_length (conn_fd, buf, strlen (handshake_msg), 0);
984         if ((res != strlen (handshake_msg)) || (memcmp (buf, handshake_msg, strlen (handshake_msg) != 0))) {
985                 fprintf (stderr, "debugger-agent: DWP handshake failed.\n");
986                 return FALSE;
987         }
988
989         /*
990          * To support older clients, the client sends its protocol version after connecting
991          * using a command. Until that is received, default to our protocol version.
992          */
993         major_version = MAJOR_VERSION;
994         minor_version = MINOR_VERSION;
995         protocol_version_set = FALSE;
996
997         /* 
998          * Set TCP_NODELAY on the socket so the client receives events/command
999          * results immediately.
1000          */
1001         {
1002                 int flag = 1;
1003                 int result = setsockopt (conn_fd,
1004                                  IPPROTO_TCP,
1005                                  TCP_NODELAY,
1006                                  (char *) &flag,
1007                                  sizeof(int));
1008                 g_assert (result >= 0);
1009         }
1010         
1011         return TRUE;
1012 }
1013
1014 /*
1015  * transport_connect:
1016  *
1017  *   Connect/Listen on HOST:PORT. If HOST is NULL, generate an address and listen on it.
1018  */
1019 static void
1020 transport_connect (const char *host, int port)
1021 {
1022 #ifdef HAVE_GETADDRINFO
1023         struct addrinfo hints;
1024         struct addrinfo *result, *rp;
1025 #else
1026         struct hostent *result;
1027 #endif
1028         int sfd, s, res;
1029         char port_string [128];
1030
1031         conn_fd = -1;
1032         listen_fd = -1;
1033
1034         if (host) {
1035                 sprintf (port_string, "%d", port);
1036
1037                 mono_network_init ();
1038
1039                 /* Obtain address(es) matching host/port */
1040 #ifdef HAVE_GETADDRINFO
1041                 memset (&hints, 0, sizeof (struct addrinfo));
1042                 hints.ai_family = AF_UNSPEC;    /* Allow IPv4 or IPv6 */
1043                 hints.ai_socktype = SOCK_STREAM; /* Datagram socket */
1044                 hints.ai_flags = 0;
1045                 hints.ai_protocol = 0;          /* Any protocol */
1046
1047                 s = getaddrinfo (host, port_string, &hints, &result);
1048                 if (s != 0) {
1049                         fprintf (stderr, "debugger-agent: Unable to resolve %s:%d: %s\n", host, port, gai_strerror (s));
1050                         exit (1);
1051                 }
1052 #else
1053                 /* The PS3 doesn't even have _r or hstrerror () */
1054                 result = gethostbyname (host);
1055                 if (!result) {
1056                         fprintf (stderr, "debugger-agent: Unable to resolve %s:%d: %d\n", host, port, h_errno);
1057                 }
1058 #endif
1059         }
1060
1061         if (agent_config.server) {
1062 #ifdef HAVE_GETADDRINFO
1063                 /* Wait for a connection */
1064                 if (!host) {
1065                         struct sockaddr_in addr;
1066                         socklen_t addrlen;
1067
1068                         /* No address, generate one */
1069                         sfd = socket (AF_INET, SOCK_STREAM, 0);
1070                         g_assert (sfd);
1071
1072                         /* This will bind the socket to a random port */
1073                         res = listen (sfd, 16);
1074                         if (res == -1) {
1075                                 fprintf (stderr, "debugger-agent: Unable to setup listening socket: %s\n", strerror (errno));
1076                                 exit (1);
1077                         }
1078                         listen_fd = sfd;
1079
1080                         addrlen = sizeof (addr);
1081                         memset (&addr, 0, sizeof (addr));
1082                         res = getsockname (sfd, &addr, &addrlen);
1083                         g_assert (res == 0);
1084
1085                         host = "127.0.0.1";
1086                         port = ntohs (addr.sin_port);
1087
1088                         /* Emit the address to stdout */
1089                         /* FIXME: Should print another interface, not localhost */
1090                         printf ("%s:%d\n", host, port);
1091                 } else {
1092                         /* Listen on the provided address */
1093                         for (rp = result; rp != NULL; rp = rp->ai_next) {
1094                                 sfd = socket (rp->ai_family, rp->ai_socktype,
1095                                                           rp->ai_protocol);
1096                                 if (sfd == -1)
1097                                         continue;
1098
1099                                 res = bind (sfd, rp->ai_addr, rp->ai_addrlen);
1100                                 if (res == -1)
1101                                         continue;
1102
1103                                 res = listen (sfd, 16);
1104                                 if (res == -1)
1105                                         continue;
1106                                 listen_fd = sfd;
1107                                 break;
1108                         }
1109
1110 #ifndef HOST_WIN32
1111                         /*
1112                          * this function is not present on win2000 which we still support, and the
1113                          * workaround described here:
1114                          * http://msdn.microsoft.com/en-us/library/ms737931(VS.85).aspx
1115                          * only works with MSVC.
1116                          */
1117 #ifdef HAVE_GETADDRINFO
1118                         freeaddrinfo (result);
1119 #endif
1120 #endif
1121                 }
1122
1123                 if (agent_config.defer)
1124                         return;
1125
1126                 DEBUG (1, fprintf (log_file, "Listening on %s:%d (timeout=%d ms)...\n", host, port, agent_config.timeout));
1127
1128                 if (agent_config.timeout) {
1129                         fd_set readfds;
1130                         struct timeval tv;
1131
1132                         tv.tv_sec = 0;
1133                         tv.tv_usec = agent_config.timeout * 1000;
1134                         FD_ZERO (&readfds);
1135                         FD_SET (sfd, &readfds);
1136                         res = select (sfd + 1, &readfds, NULL, NULL, &tv);
1137                         if (res == 0) {
1138                                 fprintf (stderr, "debugger-agent: Timed out waiting to connect.\n");
1139                                 exit (1);
1140                         }
1141                 }
1142
1143                 conn_fd = transport_accept (sfd);
1144                 if (conn_fd == -1)
1145                         exit (1);
1146
1147                 DEBUG (1, fprintf (log_file, "Accepted connection from client, socket fd=%d.\n", conn_fd));
1148 #else
1149                 NOT_IMPLEMENTED;
1150 #endif /* HAVE_GETADDRINFO */
1151         } else {
1152                 /* Connect to the specified address */
1153 #ifdef HAVE_GETADDRINFO
1154                 /* FIXME: Respect the timeout */
1155                 for (rp = result; rp != NULL; rp = rp->ai_next) {
1156                         sfd = socket (rp->ai_family, rp->ai_socktype,
1157                                                   rp->ai_protocol);
1158                         if (sfd == -1)
1159                                 continue;
1160
1161                         if (connect (sfd, rp->ai_addr, rp->ai_addrlen) != -1)
1162                                 break;       /* Success */
1163                         
1164                         close (sfd);
1165                 }
1166
1167                 if (rp == 0) {
1168                         fprintf (stderr, "debugger-agent: Unable to connect to %s:%d\n", host, port);
1169                         exit (1);
1170                 }
1171 #else
1172                         sfd = socket (result->h_addrtype, SOCK_STREAM, 0);
1173                         if (sfd == -1)
1174                                 g_assert_not_reached ();
1175                         res = connect (sfd, (void*)result->h_addr_list [0], result->h_length);
1176                         if (res == -1)
1177                                 g_assert_not_reached ();
1178 #endif
1179
1180                 conn_fd = sfd;
1181
1182 #ifndef HOST_WIN32
1183                 /* See the comment above */
1184 #ifdef HAVE_GETADDRINFO
1185                 freeaddrinfo (result);
1186 #endif
1187 #endif
1188         }
1189         
1190         disconnected = !transport_handshake ();
1191         if (disconnected)
1192                 exit (1);
1193 }
1194
1195 static gboolean
1196 transport_send (guint8 *data, int len)
1197 {
1198         int res;
1199
1200         do {
1201                 res = send (conn_fd, data, len, 0);
1202         } while (res == -1 && errno == EINTR);
1203         if (res != len)
1204                 return FALSE;
1205         else
1206                 return TRUE;
1207 }
1208
1209 static void
1210 stop_debugger_thread (void)
1211 {
1212         if (!inited)
1213                 return;
1214
1215         /* This will interrupt the agent thread */
1216         /* Close the read part only so it can still send back replies */
1217         /* Also shut down the connection listener so that we can exit normally */
1218 #ifdef HOST_WIN32
1219         /* SD_RECEIVE doesn't break the recv in the debugger thread */
1220         shutdown (conn_fd, SD_BOTH);
1221         shutdown (listen_fd, SD_BOTH);
1222         closesocket (listen_fd);
1223 #else
1224         shutdown (conn_fd, SHUT_RD);
1225         shutdown (listen_fd, SHUT_RDWR);
1226         close (listen_fd);
1227 #endif
1228
1229         /* 
1230          * Wait for the thread to exit.
1231          *
1232          * If we continue with the shutdown without waiting for it, then the client might
1233          * not receive an answer to its last command like a resume.
1234          * The WaitForSingleObject infrastructure doesn't seem to work during shutdown, so
1235          * use pthreads.
1236          */
1237         //WaitForSingleObject (debugger_thread_handle, INFINITE);
1238         if (GetCurrentThreadId () != debugger_thread_id) {
1239                 do {
1240                         mono_mutex_lock (&debugger_thread_exited_mutex);
1241                         if (!debugger_thread_exited) {
1242 #ifdef HOST_WIN32
1243                                 if (WAIT_TIMEOUT == WaitForSingleObject(debugger_thread_exited_cond, 0)) {
1244                                         mono_mutex_unlock (&debugger_thread_exited_mutex);
1245                                         Sleep(1);
1246                                         mono_mutex_lock (&debugger_thread_exited_mutex);
1247                                 }
1248 #else
1249                                 mono_cond_wait (&debugger_thread_exited_cond, &debugger_thread_exited_mutex);
1250 #endif
1251                         }
1252                         mono_mutex_unlock (&debugger_thread_exited_mutex);
1253                 } while (!debugger_thread_exited);
1254         }
1255
1256 #ifdef HOST_WIN32
1257         shutdown (conn_fd, SD_BOTH);
1258 #else
1259         shutdown (conn_fd, SHUT_RDWR);
1260 #endif
1261 }
1262
1263 static void
1264 start_debugger_thread (void)
1265 {
1266         gsize tid;
1267
1268         debugger_thread_handle = mono_create_thread (NULL, 0, debugger_thread, NULL, 0, &tid);
1269         g_assert (debugger_thread_handle);
1270 }
1271
1272 /*
1273  * Functions to decode protocol data
1274  */
1275
1276 static inline int
1277 decode_byte (guint8 *buf, guint8 **endbuf, guint8 *limit)
1278 {
1279         *endbuf = buf + 1;
1280         g_assert (*endbuf <= limit);
1281         return buf [0];
1282 }
1283
1284 static inline int
1285 decode_int (guint8 *buf, guint8 **endbuf, guint8 *limit)
1286 {
1287         *endbuf = buf + 4;
1288         g_assert (*endbuf <= limit);
1289
1290         return (((int)buf [0]) << 24) | (((int)buf [1]) << 16) | (((int)buf [2]) << 8) | (((int)buf [3]) << 0);
1291 }
1292
1293 static inline gint64
1294 decode_long (guint8 *buf, guint8 **endbuf, guint8 *limit)
1295 {
1296         guint32 high = decode_int (buf, &buf, limit);
1297         guint32 low = decode_int (buf, &buf, limit);
1298
1299         *endbuf = buf;
1300
1301         return ((((guint64)high) << 32) | ((guint64)low));
1302 }
1303
1304 static inline int
1305 decode_id (guint8 *buf, guint8 **endbuf, guint8 *limit)
1306 {
1307         return decode_int (buf, endbuf, limit);
1308 }
1309
1310 static inline char*
1311 decode_string (guint8 *buf, guint8 **endbuf, guint8 *limit)
1312 {
1313         int len = decode_int (buf, &buf, limit);
1314         char *s;
1315
1316         s = g_malloc (len + 1);
1317         g_assert (s);
1318
1319         memcpy (s, buf, len);
1320         s [len] = '\0';
1321         buf += len;
1322         *endbuf = buf;
1323
1324         return s;
1325 }
1326
1327 /*
1328  * Functions to encode protocol data
1329  */
1330
1331 typedef struct {
1332         guint8 *buf, *p, *end;
1333 } Buffer;
1334
1335 static inline void
1336 buffer_init (Buffer *buf, int size)
1337 {
1338         buf->buf = g_malloc (size);
1339         buf->p = buf->buf;
1340         buf->end = buf->buf + size;
1341 }
1342
1343 static inline void
1344 buffer_make_room (Buffer *buf, int size)
1345 {
1346         if (buf->end - buf->p < size) {
1347                 int new_size = buf->end - buf->buf + size + 32;
1348                 guint8 *p = g_realloc (buf->buf, new_size);
1349                 size = buf->p - buf->buf;
1350                 buf->buf = p;
1351                 buf->p = p + size;
1352                 buf->end = buf->buf + new_size;
1353         }
1354 }
1355
1356 static inline void
1357 buffer_add_byte (Buffer *buf, guint8 val)
1358 {
1359         buffer_make_room (buf, 1);
1360         buf->p [0] = val;
1361         buf->p++;
1362 }
1363
1364 static inline void
1365 buffer_add_int (Buffer *buf, guint32 val)
1366 {
1367         buffer_make_room (buf, 4);
1368         buf->p [0] = (val >> 24) & 0xff;
1369         buf->p [1] = (val >> 16) & 0xff;
1370         buf->p [2] = (val >> 8) & 0xff;
1371         buf->p [3] = (val >> 0) & 0xff;
1372         buf->p += 4;
1373 }
1374
1375 static inline void
1376 buffer_add_long (Buffer *buf, guint64 l)
1377 {
1378         buffer_add_int (buf, (l >> 32) & 0xffffffff);
1379         buffer_add_int (buf, (l >> 0) & 0xffffffff);
1380 }
1381
1382 static inline void
1383 buffer_add_id (Buffer *buf, int id)
1384 {
1385         buffer_add_int (buf, (guint64)id);
1386 }
1387
1388 static inline void
1389 buffer_add_data (Buffer *buf, guint8 *data, int len)
1390 {
1391         buffer_make_room (buf, len);
1392         memcpy (buf->p, data, len);
1393         buf->p += len;
1394 }
1395
1396 static inline void
1397 buffer_add_string (Buffer *buf, const char *str)
1398 {
1399         int len;
1400
1401         if (str == NULL) {
1402                 buffer_add_int (buf, 0);
1403         } else {
1404                 len = strlen (str);
1405                 buffer_add_int (buf, len);
1406                 buffer_add_data (buf, (guint8*)str, len);
1407         }
1408 }
1409
1410 static inline void
1411 buffer_free (Buffer *buf)
1412 {
1413         g_free (buf->buf);
1414 }
1415
1416 static gboolean
1417 send_packet (int command_set, int command, Buffer *data)
1418 {
1419         Buffer buf;
1420         int len, id;
1421         gboolean res;
1422
1423         id = InterlockedIncrement (&packet_id);
1424
1425         len = data->p - data->buf + 11;
1426         buffer_init (&buf, len);
1427         buffer_add_int (&buf, len);
1428         buffer_add_int (&buf, id);
1429         buffer_add_byte (&buf, 0); /* flags */
1430         buffer_add_byte (&buf, command_set);
1431         buffer_add_byte (&buf, command);
1432         memcpy (buf.buf + 11, data->buf, data->p - data->buf);
1433
1434         res = transport_send (buf.buf, len);
1435
1436         buffer_free (&buf);
1437
1438         return res;
1439 }
1440
1441 static gboolean
1442 send_reply_packet (int id, int error, Buffer *data)
1443 {
1444         Buffer buf;
1445         int len;
1446         gboolean res;
1447         
1448         len = data->p - data->buf + 11;
1449         buffer_init (&buf, len);
1450         buffer_add_int (&buf, len);
1451         buffer_add_int (&buf, id);
1452         buffer_add_byte (&buf, 0x80); /* flags */
1453         buffer_add_byte (&buf, (error >> 8) & 0xff);
1454         buffer_add_byte (&buf, error);
1455         memcpy (buf.buf + 11, data->buf, data->p - data->buf);
1456
1457         res = transport_send (buf.buf, len);
1458
1459         buffer_free (&buf);
1460
1461         return res;
1462 }
1463
1464 /*
1465  * OBJECT IDS
1466  */
1467
1468 /*
1469  * Represents an object accessible by the debugger client.
1470  */
1471 typedef struct {
1472         /* Unique id used in the wire protocol to refer to objects */
1473         int id;
1474         /*
1475          * A weakref gc handle pointing to the object. The gc handle is used to 
1476          * detect if the object was garbage collected.
1477          */
1478         guint32 handle;
1479 } ObjRef;
1480
1481 /* Maps objid -> ObjRef */
1482 static GHashTable *objrefs;
1483
1484 static void
1485 free_objref (gpointer value)
1486 {
1487         ObjRef *o = value;
1488
1489         mono_gchandle_free (o->handle);
1490
1491         g_free (o);
1492 }
1493
1494 static void
1495 objrefs_init (void)
1496 {
1497         objrefs = g_hash_table_new_full (NULL, NULL, NULL, free_objref);
1498 }
1499
1500 static void
1501 objrefs_cleanup (void)
1502 {
1503         g_hash_table_destroy (objrefs);
1504         objrefs = NULL;
1505 }
1506
1507 static GHashTable *obj_to_objref;
1508
1509 /*
1510  * Return an ObjRef for OBJ.
1511  */
1512 static ObjRef*
1513 get_objref (MonoObject *obj)
1514 {
1515         ObjRef *ref;
1516         GSList *reflist = NULL, *l;
1517         int hash = 0;
1518
1519         if (obj == NULL)
1520                 return 0;
1521
1522         mono_loader_lock ();
1523
1524         if (!obj_to_objref)
1525                 obj_to_objref = g_hash_table_new (NULL, NULL);
1526         
1527         /* FIXME: The tables can grow indefinitely */
1528
1529         if (mono_gc_is_moving ()) {
1530                 /*
1531                  * Objects can move, so use a hash table mapping hash codes to lists of
1532                  * ObjRef structures.
1533                  */
1534                 hash = mono_object_hash (obj);
1535
1536                 reflist = g_hash_table_lookup (obj_to_objref, GINT_TO_POINTER (hash));
1537                 for (l = reflist; l; l = l->next) {
1538                         ref = l->data;
1539                         if (ref && mono_gchandle_get_target (ref->handle) == obj) {
1540                                 mono_loader_unlock ();
1541                                 return ref;
1542                         }
1543                 }
1544         } else {
1545                 /* Use a hash table with masked pointers to internalize object references */
1546                 ref = g_hash_table_lookup (obj_to_objref, GINT_TO_POINTER (~((gsize)obj)));
1547                 /* ref might refer to a different object with the same addr which was GCd */
1548                 if (ref && mono_gchandle_get_target (ref->handle) == obj) {
1549                         mono_loader_unlock ();
1550                         return ref;
1551                 }
1552         }
1553
1554         ref = g_new0 (ObjRef, 1);
1555         ref->id = InterlockedIncrement (&objref_id);
1556         ref->handle = mono_gchandle_new_weakref (obj, FALSE);
1557
1558         g_hash_table_insert (objrefs, GINT_TO_POINTER (ref->id), ref);
1559
1560         if (mono_gc_is_moving ()) {
1561                 reflist = g_slist_append (reflist, ref);
1562                 g_hash_table_insert (obj_to_objref, GINT_TO_POINTER (hash), reflist);
1563         } else {
1564                 g_hash_table_insert (obj_to_objref, GINT_TO_POINTER (~((gsize)obj)), ref);
1565         }
1566
1567         mono_loader_unlock ();
1568
1569         return ref;
1570 }
1571
1572 static inline int
1573 get_objid (MonoObject *obj)
1574 {
1575         return get_objref (obj)->id;
1576 }
1577
1578 /*
1579  * Set OBJ to the object identified by OBJID.
1580  * Returns 0 or an error code if OBJID is invalid or the object has been garbage
1581  * collected.
1582  */
1583 static ErrorCode
1584 get_object_allow_null (int objid, MonoObject **obj)
1585 {
1586         ObjRef *ref;
1587
1588         if (objid == 0) {
1589                 *obj = NULL;
1590                 return 0;
1591         }
1592
1593         if (!objrefs)
1594                 return ERR_INVALID_OBJECT;
1595
1596         mono_loader_lock ();
1597
1598         ref = g_hash_table_lookup (objrefs, GINT_TO_POINTER (objid));
1599
1600         if (ref) {
1601                 *obj = mono_gchandle_get_target (ref->handle);
1602                 mono_loader_unlock ();
1603                 if (!(*obj))
1604                         return ERR_INVALID_OBJECT;
1605                 return 0;
1606         } else {
1607                 mono_loader_unlock ();
1608                 return ERR_INVALID_OBJECT;
1609         }
1610 }
1611
1612 static ErrorCode
1613 get_object (int objid, MonoObject **obj)
1614 {
1615         int err = get_object_allow_null (objid, obj);
1616
1617         if (err)
1618                 return err;
1619         if (!(*obj))
1620                 return ERR_INVALID_OBJECT;
1621         return 0;
1622 }
1623
1624 static inline int
1625 decode_objid (guint8 *buf, guint8 **endbuf, guint8 *limit)
1626 {
1627         return decode_id (buf, endbuf, limit);
1628 }
1629
1630 static inline void
1631 buffer_add_objid (Buffer *buf, MonoObject *o)
1632 {
1633         buffer_add_id (buf, get_objid (o));
1634 }
1635
1636 /*
1637  * IDS
1638  */
1639
1640 typedef enum {
1641         ID_ASSEMBLY = 0,
1642         ID_MODULE = 1,
1643         ID_TYPE = 2,
1644         ID_METHOD = 3,
1645         ID_FIELD = 4,
1646         ID_DOMAIN = 5,
1647         ID_PROPERTY = 6,
1648         ID_NUM
1649 } IdType;
1650
1651 /*
1652  * Represents a runtime structure accessible to the debugger client
1653  */
1654 typedef struct {
1655         /* Unique id used in the wire protocol */
1656         int id;
1657         /* Domain of the runtime structure, NULL if the domain was unloaded */
1658         MonoDomain *domain;
1659         union {
1660                 gpointer val;
1661                 MonoClass *klass;
1662                 MonoMethod *method;
1663                 MonoImage *image;
1664                 MonoAssembly *assembly;
1665                 MonoClassField *field;
1666                 MonoDomain *domain;
1667                 MonoProperty *property;
1668         } data;
1669 } Id;
1670
1671 typedef struct {
1672         /* Maps runtime structure -> Id */
1673         GHashTable *val_to_id [ID_NUM];
1674         /* Classes whose class load event has been sent */
1675         GHashTable *loaded_classes;
1676 } AgentDomainInfo;
1677
1678 /* Maps id -> Id */
1679 static GPtrArray *ids [ID_NUM];
1680
1681 static void
1682 ids_init (void)
1683 {
1684         int i;
1685
1686         for (i = 0; i < ID_NUM; ++i)
1687                 ids [i] = g_ptr_array_new ();
1688 }
1689
1690 static void
1691 ids_cleanup (void)
1692 {
1693         int i, j;
1694
1695         for (i = 0; i < ID_NUM; ++i) {
1696                 if (ids [i]) {
1697                         for (j = 0; j < ids [i]->len; ++j)
1698                                 g_free (g_ptr_array_index (ids [i], j));
1699                         g_ptr_array_free (ids [i], TRUE);
1700                 }
1701                 ids [i] = NULL;
1702         }
1703 }
1704
1705 void
1706 mono_debugger_agent_free_domain_info (MonoDomain *domain)
1707 {
1708         AgentDomainInfo *info = domain_jit_info (domain)->agent_info;
1709         int i, j;
1710
1711         if (info) {
1712                 for (i = 0; i < ID_NUM; ++i)
1713                         if (info->val_to_id [i])
1714                                 g_hash_table_destroy (info->val_to_id [i]);
1715                 g_hash_table_destroy (info->loaded_classes);
1716                 g_free (info);
1717         }
1718
1719         domain_jit_info (domain)->agent_info = NULL;
1720
1721         /* Clear ids referencing structures in the domain */
1722         for (i = 0; i < ID_NUM; ++i) {
1723                 if (ids [i]) {
1724                         for (j = 0; j < ids [i]->len; ++j) {
1725                                 Id *id = g_ptr_array_index (ids [i], j);
1726                                 if (id->domain == domain)
1727                                         id->domain = NULL;
1728                         }
1729                 }
1730         }
1731
1732         mono_loader_lock ();
1733         g_hash_table_remove (domains, domain);
1734         mono_loader_unlock ();
1735 }
1736
1737 /*
1738  * Called when deferred debugger session is attached, 
1739  * after the VM start event has been sent successfully
1740  */
1741 static void
1742 mono_debugger_agent_on_attach (void)
1743 {
1744         /* Emit load events for currently loaded appdomains, assemblies, and types */
1745         mono_loader_lock ();
1746         g_hash_table_foreach (domains, emit_appdomain_load, NULL);
1747         mono_g_hash_table_foreach (tid_to_thread, emit_thread_start, NULL);
1748         mono_assembly_foreach (emit_assembly_load, NULL);
1749         mono_loader_unlock ();
1750 }
1751
1752 static AgentDomainInfo*
1753 get_agent_domain_info (MonoDomain *domain)
1754 {
1755         AgentDomainInfo *info = NULL;
1756
1757         mono_domain_lock (domain);
1758
1759         info = domain_jit_info (domain)->agent_info;
1760         if (!info) {
1761                 info = domain_jit_info (domain)->agent_info = g_new0 (AgentDomainInfo, 1);
1762                 info->loaded_classes = g_hash_table_new (mono_aligned_addr_hash, NULL);
1763         }
1764
1765         mono_domain_unlock (domain);
1766
1767         return info;
1768 }
1769
1770 static int
1771 get_id (MonoDomain *domain, IdType type, gpointer val)
1772 {
1773         Id *id;
1774         AgentDomainInfo *info;
1775
1776         if (val == NULL)
1777                 return 0;
1778
1779         mono_loader_lock ();
1780
1781         mono_domain_lock (domain);
1782
1783         info = get_agent_domain_info (domain);
1784
1785         if (info->val_to_id [type] == NULL)
1786                 info->val_to_id [type] = g_hash_table_new (mono_aligned_addr_hash, NULL);
1787
1788         id = g_hash_table_lookup (info->val_to_id [type], val);
1789         if (id) {
1790                 mono_domain_unlock (domain);
1791                 mono_loader_unlock ();
1792                 return id->id;
1793         }
1794
1795         id = g_new0 (Id, 1);
1796         /* Reserve id 0 */
1797         id->id = ids [type]->len + 1;
1798         id->domain = domain;
1799         id->data.val = val;
1800
1801         g_hash_table_insert (info->val_to_id [type], val, id);
1802
1803         mono_domain_unlock (domain);
1804
1805         g_ptr_array_add (ids [type], id);
1806
1807         mono_loader_unlock ();
1808
1809         return id->id;
1810 }
1811
1812 static inline gpointer
1813 decode_ptr_id (guint8 *buf, guint8 **endbuf, guint8 *limit, IdType type, MonoDomain **domain, int *err)
1814 {
1815         Id *res;
1816
1817         int id = decode_id (buf, endbuf, limit);
1818
1819         *err = 0;
1820         if (domain)
1821                 *domain = NULL;
1822
1823         if (id == 0)
1824                 return NULL;
1825
1826         // FIXME: error handling
1827         mono_loader_lock ();
1828         g_assert (id > 0 && id <= ids [type]->len);
1829
1830         res = g_ptr_array_index (ids [type], GPOINTER_TO_INT (id - 1));
1831         mono_loader_unlock ();
1832
1833         if (res->domain == NULL) {
1834                 *err = ERR_UNLOADED;
1835                 return NULL;
1836         }
1837
1838         if (domain)
1839                 *domain = res->domain;
1840
1841         return res->data.val;
1842 }
1843
1844 static inline void
1845 buffer_add_ptr_id (Buffer *buf, MonoDomain *domain, IdType type, gpointer val)
1846 {
1847         buffer_add_id (buf, get_id (domain, type, val));
1848 }
1849
1850 static inline MonoClass*
1851 decode_typeid (guint8 *buf, guint8 **endbuf, guint8 *limit, MonoDomain **domain, int *err)
1852 {
1853         return decode_ptr_id (buf, endbuf, limit, ID_TYPE, domain, err);
1854 }
1855
1856 static inline MonoAssembly*
1857 decode_assemblyid (guint8 *buf, guint8 **endbuf, guint8 *limit, MonoDomain **domain, int *err)
1858 {
1859         return decode_ptr_id (buf, endbuf, limit, ID_ASSEMBLY, domain, err);
1860 }
1861
1862 static inline MonoImage*
1863 decode_moduleid (guint8 *buf, guint8 **endbuf, guint8 *limit, MonoDomain **domain, int *err)
1864 {
1865         return decode_ptr_id (buf, endbuf, limit, ID_MODULE, domain, err);
1866 }
1867
1868 static inline MonoMethod*
1869 decode_methodid (guint8 *buf, guint8 **endbuf, guint8 *limit, MonoDomain **domain, int *err)
1870 {
1871         return decode_ptr_id (buf, endbuf, limit, ID_METHOD, domain, err);
1872 }
1873
1874 static inline MonoClassField*
1875 decode_fieldid (guint8 *buf, guint8 **endbuf, guint8 *limit, MonoDomain **domain, int *err)
1876 {
1877         return decode_ptr_id (buf, endbuf, limit, ID_FIELD, domain, err);
1878 }
1879
1880 static inline MonoDomain*
1881 decode_domainid (guint8 *buf, guint8 **endbuf, guint8 *limit, MonoDomain **domain, int *err)
1882 {
1883         return decode_ptr_id (buf, endbuf, limit, ID_DOMAIN, domain, err);
1884 }
1885
1886 static inline MonoProperty*
1887 decode_propertyid (guint8 *buf, guint8 **endbuf, guint8 *limit, MonoDomain **domain, int *err)
1888 {
1889         return decode_ptr_id (buf, endbuf, limit, ID_PROPERTY, domain, err);
1890 }
1891
1892 static inline void
1893 buffer_add_typeid (Buffer *buf, MonoDomain *domain, MonoClass *klass)
1894 {
1895         buffer_add_ptr_id (buf, domain, ID_TYPE, klass);
1896 }
1897
1898 static inline void
1899 buffer_add_methodid (Buffer *buf, MonoDomain *domain, MonoMethod *method)
1900 {
1901         buffer_add_ptr_id (buf, domain, ID_METHOD, method);
1902 }
1903
1904 static inline void
1905 buffer_add_assemblyid (Buffer *buf, MonoDomain *domain, MonoAssembly *assembly)
1906 {
1907         buffer_add_ptr_id (buf, domain, ID_ASSEMBLY, assembly);
1908 }
1909
1910 static inline void
1911 buffer_add_moduleid (Buffer *buf, MonoDomain *domain, MonoImage *image)
1912 {
1913         buffer_add_ptr_id (buf, domain, ID_MODULE, image);
1914 }
1915
1916 static inline void
1917 buffer_add_fieldid (Buffer *buf, MonoDomain *domain, MonoClassField *field)
1918 {
1919         buffer_add_ptr_id (buf, domain, ID_FIELD, field);
1920 }
1921
1922 static inline void
1923 buffer_add_propertyid (Buffer *buf, MonoDomain *domain, MonoProperty *property)
1924 {
1925         buffer_add_ptr_id (buf, domain, ID_PROPERTY, property);
1926 }
1927
1928 static inline void
1929 buffer_add_domainid (Buffer *buf, MonoDomain *domain)
1930 {
1931         buffer_add_ptr_id (buf, domain, ID_DOMAIN, domain);
1932 }
1933
1934 static void invoke_method (void);
1935
1936 /*
1937  * SUSPEND/RESUME
1938  */
1939
1940 /*
1941  * save_thread_context:
1942  *
1943  *   Set CTX as the current threads context which is used for computing stack traces.
1944  * This function is signal-safe.
1945  */
1946 static void
1947 save_thread_context (MonoContext *ctx)
1948 {
1949         DebuggerTlsData *tls;
1950
1951         tls = TlsGetValue (debugger_tls_id);
1952         g_assert (tls);
1953
1954         if (ctx)
1955                 mono_thread_state_init_from_monoctx (&tls->context, ctx);
1956         else
1957                 mono_thread_state_init_from_current (&tls->context);
1958 }
1959
1960 /* The number of times the runtime is suspended */
1961 static gint32 suspend_count;
1962
1963 /* Number of threads suspended */
1964 /* 
1965  * If this is equal to the size of thread_to_tls, the runtime is considered
1966  * suspended.
1967  */
1968 static gint32 threads_suspend_count;
1969
1970 static mono_mutex_t suspend_mutex;
1971
1972 /* Cond variable used to wait for suspend_count becoming 0 */
1973 static mono_cond_t suspend_cond;
1974
1975 /* Semaphore used to wait for a thread becoming suspended */
1976 static MonoSemType suspend_sem;
1977
1978 static void
1979 suspend_init (void)
1980 {
1981         mono_mutex_init (&suspend_mutex, NULL);
1982         mono_cond_init (&suspend_cond, NULL);   
1983         MONO_SEM_INIT (&suspend_sem, 0);
1984 }
1985
1986 typedef struct
1987 {
1988         StackFrameInfo last_frame;
1989         gboolean last_frame_set;
1990         MonoContext ctx;
1991         gpointer lmf;
1992 } GetLastFrameUserData;
1993
1994 static gboolean
1995 get_last_frame (StackFrameInfo *info, MonoContext *ctx, gpointer user_data)
1996 {
1997         GetLastFrameUserData *data = user_data;
1998
1999         if (info->type == FRAME_TYPE_MANAGED_TO_NATIVE)
2000                 return FALSE;
2001
2002         if (!data->last_frame_set) {
2003                 /* Store the last frame */
2004                 memcpy (&data->last_frame, info, sizeof (StackFrameInfo));
2005                 data->last_frame_set = TRUE;
2006                 return FALSE;
2007         } else {
2008                 /* Store the context/lmf for the frame above the last frame */
2009                 memcpy (&data->ctx, ctx, sizeof (MonoContext));
2010                 data->lmf = info->lmf;
2011
2012                 return TRUE;
2013         }
2014 }
2015
2016 /*
2017  * mono_debugger_agent_thread_interrupt:
2018  *
2019  *   Called by the abort signal handler.
2020  * Should be signal safe.
2021  */
2022 gboolean
2023 mono_debugger_agent_thread_interrupt (void *sigctx, MonoJitInfo *ji)
2024 {
2025         DebuggerTlsData *tls;
2026
2027         if (!inited)
2028                 return FALSE;
2029
2030         tls = TlsGetValue (debugger_tls_id);
2031         if (!tls)
2032                 return FALSE;
2033
2034         /*
2035          * OSX can (and will) coalesce signals, so sending multiple pthread_kills does not
2036          * guarantee the signal handler will be called that many times.  Instead of tracking
2037          * interrupt_count on osx, we use this as a boolean flag to determine if a interrupt
2038          * has been requested that hasn't been handled yet, otherwise we can have threads
2039          * refuse to die when VM_EXIT is called
2040          */
2041 #if defined(__APPLE__)
2042         if (InterlockedCompareExchange (&tls->interrupt_count, 0, 1) == 0)
2043                 return FALSE;
2044 #else
2045         /*
2046          * We use interrupt_count to determine whenever this interrupt should be processed
2047          * by us or the normal interrupt processing code in the signal handler.
2048          * There is no race here with notify_thread (), since the signal is sent after
2049          * incrementing interrupt_count.
2050          */
2051         if (tls->interrupt_count == 0)
2052                 return FALSE;
2053
2054         InterlockedDecrement (&tls->interrupt_count);
2055 #endif
2056
2057         // FIXME: Races when the thread leaves managed code before hitting a single step
2058         // event.
2059
2060         if (ji) {
2061                 /* Running managed code, will be suspended by the single step code */
2062                 DEBUG (1, fprintf (log_file, "[%p] Received interrupt while at %s(%p), continuing.\n", (gpointer)GetCurrentThreadId (), ji->method->name, mono_arch_ip_from_context (sigctx)));
2063                 return TRUE;
2064         } else {
2065                 /* 
2066                  * Running native code, will be suspended when it returns to/enters 
2067                  * managed code. Treat it as already suspended.
2068                  * This might interrupt the code in process_single_step_inner (), we use the
2069                  * tls->suspending flag to avoid races when that happens.
2070                  */
2071                 if (!tls->suspended && !tls->suspending) {
2072                         MonoContext ctx;
2073                         GetLastFrameUserData data;
2074
2075                         // FIXME: printf is not signal safe, but this is only used during
2076                         // debugger debugging
2077                         if (sigctx)
2078                                 DEBUG (1, fprintf (log_file, "[%p] Received interrupt while at %p, treating as suspended.\n", (gpointer)GetCurrentThreadId (), mono_arch_ip_from_context (sigctx)));
2079                         //save_thread_context (&ctx);
2080
2081                         if (!tls->thread)
2082                                 /* Already terminated */
2083                                 return TRUE;
2084
2085                         /*
2086                          * We are in a difficult position: we want to be able to provide stack
2087                          * traces for this thread, but we can't use the current ctx+lmf, since
2088                          * the thread is still running, so it might return to managed code,
2089                          * making these invalid.
2090                          * So we start a stack walk and save the first frame, along with the
2091                          * parent frame's ctx+lmf. This (hopefully) works because the thread will be 
2092                          * suspended when it returns to managed code, so the parent's ctx should
2093                          * remain valid.
2094                          */
2095                         data.last_frame_set = FALSE;
2096                         if (sigctx) {
2097                                 mono_arch_sigctx_to_monoctx (sigctx, &ctx);
2098                                 mono_walk_stack_with_ctx (get_last_frame, &ctx, MONO_UNWIND_DEFAULT, &data);
2099                         }
2100                         if (data.last_frame_set) {
2101                                 memcpy (&tls->async_last_frame, &data.last_frame, sizeof (StackFrameInfo));
2102                                 g_assert (mono_thread_state_init_from_monoctx (&tls->async_state, sigctx));
2103                                 g_assert (mono_thread_state_init_from_monoctx (&tls->context, sigctx));
2104                         } else {
2105                                 tls->async_state.valid = FALSE;
2106                         }
2107
2108                         mono_memory_barrier ();
2109
2110                         tls->suspended = TRUE;
2111                         MONO_SEM_POST (&suspend_sem);
2112                 }
2113                 return TRUE;
2114         }
2115 }
2116
2117 #ifdef HOST_WIN32
2118 static void CALLBACK notify_thread_apc (ULONG_PTR param)
2119 {
2120         //DebugBreak ();
2121         mono_debugger_agent_thread_interrupt (NULL, NULL);
2122 }
2123 #endif /* HOST_WIN32 */
2124
2125 /*
2126  * reset_native_thread_suspend_state:
2127  * 
2128  *   Reset the suspended flag on native threads
2129  */
2130 static void
2131 reset_native_thread_suspend_state (gpointer key, gpointer value, gpointer user_data)
2132 {
2133         DebuggerTlsData *tls = value;
2134
2135         if (!tls->really_suspended && tls->suspended)
2136                 tls->suspended = FALSE;
2137 }
2138
2139 /*
2140  * notify_thread:
2141  *
2142  *   Notify a thread that it needs to suspend.
2143  */
2144 static void
2145 notify_thread (gpointer key, gpointer value, gpointer user_data)
2146 {
2147         MonoInternalThread *thread = key;
2148         DebuggerTlsData *tls = value;
2149         gsize tid = thread->tid;
2150
2151         if (GetCurrentThreadId () == tid || tls->terminated)
2152                 return;
2153
2154         DEBUG(1, fprintf (log_file, "[%p] Interrupting %p...\n", (gpointer)GetCurrentThreadId (), (gpointer)tid));
2155
2156         /*
2157          * OSX can (and will) coalesce signals, so sending multiple pthread_kills does not
2158          * guarantee the signal handler will be called that many times.  Instead of tracking
2159          * interrupt_count on osx, we use this as a boolean flag to determine if a interrupt
2160          * has been requested that hasn't been handled yet, otherwise we can have threads
2161          * refuse to die when VM_EXIT is called
2162          */
2163 #if defined(__APPLE__)
2164         if (InterlockedCompareExchange (&tls->interrupt_count, 1, 0) == 1)
2165                 return;
2166 #else
2167         /*
2168          * Maybe we could use the normal interrupt infrastructure, but that does a lot
2169          * of things like breaking waits etc. which we don't want.
2170          */
2171         InterlockedIncrement (&tls->interrupt_count);
2172 #endif
2173
2174         /* This is _not_ equivalent to ves_icall_System_Threading_Thread_Abort () */
2175 #ifdef HOST_WIN32
2176         QueueUserAPC (notify_thread_apc, thread->handle, NULL);
2177 #else
2178         mono_thread_kill (thread, mono_thread_get_abort_signal ());
2179 #endif
2180 }
2181
2182 static void
2183 process_suspend (DebuggerTlsData *tls, MonoContext *ctx)
2184 {
2185         guint8 *ip = MONO_CONTEXT_GET_IP (ctx);
2186         MonoJitInfo *ji;
2187
2188         if (mono_loader_lock_is_owned_by_self ()) {
2189                 /*
2190                  * Shortcut for the check in suspend_current (). This speeds up processing
2191                  * when executing long running code inside the loader lock, i.e. assembly load
2192                  * hooks.
2193                  */
2194                 return;
2195         }
2196
2197         if (debugger_thread_id == GetCurrentThreadId ())
2198                 return;
2199
2200         /* Prevent races with mono_debugger_agent_thread_interrupt () */
2201         if (suspend_count - tls->resume_count > 0)
2202                 tls->suspending = TRUE;
2203
2204         DEBUG(1, fprintf (log_file, "[%p] Received single step event for suspending.\n", (gpointer)GetCurrentThreadId ()));
2205
2206         if (suspend_count - tls->resume_count == 0) {
2207                 /* 
2208                  * We are executing a single threaded invoke but the single step for 
2209                  * suspending is still active.
2210                  * FIXME: This slows down single threaded invokes.
2211                  */
2212                 DEBUG(1, fprintf (log_file, "[%p] Ignored during single threaded invoke.\n", (gpointer)GetCurrentThreadId ()));
2213                 return;
2214         }
2215
2216         ji = mini_jit_info_table_find (mono_domain_get (), (char*)ip, NULL);
2217
2218         /* Can't suspend in these methods */
2219         if (ji->method->klass == mono_defaults.string_class && (!strcmp (ji->method->name, "memset") || strstr (ji->method->name, "memcpy")))
2220                 return;
2221
2222         save_thread_context (ctx);
2223
2224         suspend_current ();
2225 }
2226
2227 /*
2228  * suspend_vm:
2229  *
2230  * Increase the suspend count of the VM. While the suspend count is greater 
2231  * than 0, runtime threads are suspended at certain points during execution.
2232  */
2233 static void
2234 suspend_vm (void)
2235 {
2236         mono_loader_lock ();
2237
2238         mono_mutex_lock (&suspend_mutex);
2239
2240         suspend_count ++;
2241
2242         DEBUG(1, fprintf (log_file, "[%p] Suspending vm...\n", (gpointer)GetCurrentThreadId ()));
2243
2244         if (suspend_count == 1) {
2245                 // FIXME: Is it safe to call this inside the lock ?
2246                 start_single_stepping ();
2247                 mono_g_hash_table_foreach (thread_to_tls, notify_thread, NULL);
2248         }
2249
2250         mono_mutex_unlock (&suspend_mutex);
2251
2252         mono_loader_unlock ();
2253 }
2254
2255 /*
2256  * resume_vm:
2257  *
2258  * Decrease the suspend count of the VM. If the count reaches 0, runtime threads
2259  * are resumed.
2260  */
2261 static void
2262 resume_vm (void)
2263 {
2264         int err;
2265
2266         g_assert (debugger_thread_id == GetCurrentThreadId ());
2267
2268         mono_loader_lock ();
2269
2270         mono_mutex_lock (&suspend_mutex);
2271
2272         g_assert (suspend_count > 0);
2273         suspend_count --;
2274
2275         DEBUG(1, fprintf (log_file, "[%p] Resuming vm...\n", (gpointer)GetCurrentThreadId ()));
2276
2277         if (suspend_count == 0) {
2278                 // FIXME: Is it safe to call this inside the lock ?
2279                 stop_single_stepping ();
2280                 mono_g_hash_table_foreach (thread_to_tls, reset_native_thread_suspend_state, NULL);
2281         }
2282
2283         /* Signal this even when suspend_count > 0, since some threads might have resume_count > 0 */
2284         err = mono_cond_broadcast (&suspend_cond);
2285         g_assert (err == 0);
2286
2287         mono_mutex_unlock (&suspend_mutex);
2288         //g_assert (err == 0);
2289
2290         mono_loader_unlock ();
2291 }
2292
2293 /*
2294  * resume_thread:
2295  *
2296  *   Resume just one thread.
2297  */
2298 static void
2299 resume_thread (MonoInternalThread *thread)
2300 {
2301         int err;
2302         DebuggerTlsData *tls;
2303
2304         g_assert (debugger_thread_id == GetCurrentThreadId ());
2305
2306         mono_loader_lock ();
2307
2308         tls = mono_g_hash_table_lookup (thread_to_tls, thread);
2309         g_assert (tls);
2310         
2311         mono_mutex_lock (&suspend_mutex);
2312
2313         g_assert (suspend_count > 0);
2314
2315         DEBUG(1, fprintf (log_file, "[%p] Resuming thread...\n", (gpointer)(gssize)thread->tid));
2316
2317         tls->resume_count += suspend_count;
2318
2319         /* 
2320          * Signal suspend_count without decreasing suspend_count, the threads will wake up
2321          * but only the one whose resume_count field is > 0 will be resumed.
2322          */
2323         err = mono_cond_broadcast (&suspend_cond);
2324         g_assert (err == 0);
2325
2326         mono_mutex_unlock (&suspend_mutex);
2327         //g_assert (err == 0);
2328
2329         mono_loader_unlock ();
2330 }
2331
2332 static void
2333 invalidate_frames (DebuggerTlsData *tls)
2334 {
2335         int i;
2336
2337         if (!tls)
2338                 tls = TlsGetValue (debugger_tls_id);
2339         g_assert (tls);
2340
2341         for (i = 0; i < tls->frame_count; ++i) {
2342                 if (tls->frames [i]->jit)
2343                         mono_debug_free_method_jit_info (tls->frames [i]->jit);
2344                 g_free (tls->frames [i]);
2345         }
2346         g_free (tls->frames);
2347         tls->frame_count = 0;
2348         tls->frames = NULL;
2349 }
2350
2351 /*
2352  * suspend_current:
2353  *
2354  *   Suspend the current thread until the runtime is resumed. If the thread has a 
2355  * pending invoke, then the invoke is executed before this function returns. 
2356  */
2357 static void
2358 suspend_current (void)
2359 {
2360         int err;
2361         DebuggerTlsData *tls;
2362
2363         g_assert (debugger_thread_id != GetCurrentThreadId ());
2364
2365         if (mono_loader_lock_is_owned_by_self ()) {
2366                 /*
2367                  * If we own the loader mutex, can't suspend until we release it, since the
2368                  * whole runtime can deadlock otherwise.
2369                  */
2370                 return;
2371         }
2372
2373         tls = TlsGetValue (debugger_tls_id);
2374         g_assert (tls);
2375
2376         mono_mutex_lock (&suspend_mutex);
2377
2378         tls->suspending = FALSE;
2379         tls->really_suspended = TRUE;
2380
2381         if (!tls->suspended) {
2382                 tls->suspended = TRUE;
2383                 MONO_SEM_POST (&suspend_sem);
2384         }
2385
2386         DEBUG(1, fprintf (log_file, "[%p] Suspended.\n", (gpointer)GetCurrentThreadId ()));
2387
2388         while (suspend_count - tls->resume_count > 0) {
2389 #ifdef HOST_WIN32
2390                 if (WAIT_TIMEOUT == WaitForSingleObject(suspend_cond, 0))
2391                 {
2392                         mono_mutex_unlock (&suspend_mutex);
2393                         Sleep(1);
2394                         mono_mutex_lock (&suspend_mutex);
2395                 }
2396                 else
2397                 {
2398                 }
2399 #else
2400                 err = mono_cond_wait (&suspend_cond, &suspend_mutex);
2401                 g_assert (err == 0);
2402 #endif
2403         }
2404
2405         tls->suspended = FALSE;
2406         tls->really_suspended = FALSE;
2407
2408         threads_suspend_count --;
2409
2410         mono_mutex_unlock (&suspend_mutex);
2411
2412         DEBUG(1, fprintf (log_file, "[%p] Resumed.\n", (gpointer)GetCurrentThreadId ()));
2413
2414         if (tls->pending_invoke) {
2415                 /* Save the original context */
2416                 tls->pending_invoke->has_ctx = TRUE;
2417                 tls->pending_invoke->ctx = tls->context.ctx;
2418
2419                 invoke_method ();
2420         }
2421
2422         /* The frame info becomes invalid after a resume */
2423         tls->context.valid = FALSE;
2424         tls->async_state.valid = FALSE;
2425         invalidate_frames (NULL);
2426 }
2427
2428 static void
2429 count_thread (gpointer key, gpointer value, gpointer user_data)
2430 {
2431         DebuggerTlsData *tls = value;
2432
2433         if (!tls->suspended && !tls->terminated)
2434                 *(int*)user_data = *(int*)user_data + 1;
2435 }
2436
2437 static int
2438 count_threads_to_wait_for (void)
2439 {
2440         int count = 0;
2441
2442         mono_loader_lock ();
2443         mono_g_hash_table_foreach (thread_to_tls, count_thread, &count);
2444         mono_loader_unlock ();
2445
2446         return count;
2447 }       
2448
2449 /*
2450  * wait_for_suspend:
2451  *
2452  *   Wait until the runtime is completely suspended.
2453  */
2454 static void
2455 wait_for_suspend (void)
2456 {
2457         int nthreads, nwait, err;
2458         gboolean waited = FALSE;
2459
2460         // FIXME: Threads starting/stopping ?
2461         mono_loader_lock ();
2462         nthreads = mono_g_hash_table_size (thread_to_tls);
2463         mono_loader_unlock ();
2464
2465         while (TRUE) {
2466                 nwait = count_threads_to_wait_for ();
2467                 if (nwait) {
2468                         DEBUG(1, fprintf (log_file, "Waiting for %d(%d) threads to suspend...\n", nwait, nthreads));
2469                         err = MONO_SEM_WAIT (&suspend_sem);
2470                         g_assert (err == 0);
2471                         waited = TRUE;
2472                 } else {
2473                         break;
2474                 }
2475         }
2476
2477         if (waited)
2478                 DEBUG(1, fprintf (log_file, "%d threads suspended.\n", nthreads));
2479 }
2480
2481 /*
2482  * is_suspended:
2483  *
2484  *   Return whenever the runtime is suspended.
2485  */
2486 static gboolean
2487 is_suspended (void)
2488 {
2489         return count_threads_to_wait_for () == 0;
2490 }
2491
2492 /*
2493  * find_seq_point_for_native_offset:
2494  *
2495  *   Find the sequence point corresponding to the native offset NATIVE_OFFSET, which
2496  * should be the location of a sequence point.
2497  */
2498 static SeqPoint*
2499 find_seq_point_for_native_offset (MonoDomain *domain, MonoMethod *method, gint32 native_offset, MonoSeqPointInfo **info)
2500 {
2501         MonoSeqPointInfo *seq_points;
2502         int i;
2503
2504         mono_domain_lock (domain);
2505         seq_points = g_hash_table_lookup (domain_jit_info (domain)->seq_points, method);
2506         mono_domain_unlock (domain);
2507         g_assert (seq_points);
2508
2509         *info = seq_points;
2510
2511         for (i = 0; i < seq_points->len; ++i) {
2512                 if (seq_points->seq_points [i].native_offset == native_offset)
2513                         return &seq_points->seq_points [i];
2514         }
2515
2516         return NULL;
2517 }
2518
2519 /*
2520  * find_next_seq_point_for_native_offset:
2521  *
2522  *   Find the first sequence point after NATIVE_OFFSET.
2523  */
2524 static SeqPoint*
2525 find_next_seq_point_for_native_offset (MonoDomain *domain, MonoMethod *method, gint32 native_offset, MonoSeqPointInfo **info)
2526 {
2527         MonoSeqPointInfo *seq_points;
2528         int i;
2529
2530         mono_domain_lock (domain);
2531         seq_points = g_hash_table_lookup (domain_jit_info (domain)->seq_points, method);
2532         mono_domain_unlock (domain);
2533         g_assert (seq_points);
2534
2535         *info = seq_points;
2536
2537         for (i = 0; i < seq_points->len; ++i) {
2538                 if (seq_points->seq_points [i].native_offset >= native_offset)
2539                         return &seq_points->seq_points [i];
2540         }
2541
2542         return NULL;
2543 }
2544
2545 /*
2546  * find_prev_seq_point_for_native_offset:
2547  *
2548  *   Find the first sequence point before NATIVE_OFFSET.
2549  */
2550 static SeqPoint*
2551 find_prev_seq_point_for_native_offset (MonoDomain *domain, MonoMethod *method, gint32 native_offset, MonoSeqPointInfo **info)
2552 {
2553         MonoSeqPointInfo *seq_points;
2554         int i;
2555
2556         mono_domain_lock (domain);
2557         seq_points = g_hash_table_lookup (domain_jit_info (domain)->seq_points, method);
2558         mono_domain_unlock (domain);
2559         g_assert (seq_points);
2560
2561         *info = seq_points;
2562
2563         for (i = seq_points->len - 1; i >= 0; --i) {
2564                 if (seq_points->seq_points [i].native_offset <= native_offset)
2565                         return &seq_points->seq_points [i];
2566         }
2567
2568         return NULL;
2569 }
2570
2571 /*
2572  * find_seq_point:
2573  *
2574  *   Find the sequence point corresponding to the IL offset IL_OFFSET, which
2575  * should be the location of a sequence point.
2576  */
2577 static SeqPoint*
2578 find_seq_point (MonoDomain *domain, MonoMethod *method, gint32 il_offset, MonoSeqPointInfo **info)
2579 {
2580         MonoSeqPointInfo *seq_points;
2581         int i;
2582
2583         mono_domain_lock (domain);
2584         seq_points = g_hash_table_lookup (domain_jit_info (domain)->seq_points, method);
2585         mono_domain_unlock (domain);
2586         g_assert (seq_points);
2587
2588         *info = seq_points;
2589
2590         for (i = 0; i < seq_points->len; ++i) {
2591                 if (seq_points->seq_points [i].il_offset == il_offset)
2592                         return &seq_points->seq_points [i];
2593         }
2594
2595         return NULL;
2596 }
2597
2598 /*
2599  * compute_il_offset:
2600  *
2601  *    Compute the IL offset corresponding to NATIVE_OFFSET, which should be
2602  * a location of a sequence point.
2603  * We use this function instead of mono_debug_il_offset_from_address () etc,
2604  * which doesn't seem to work in a lot of cases.
2605  */
2606 static gint32
2607 compute_il_offset (MonoDomain *domain, MonoMethod *method, gint32 native_offset)
2608 {
2609         MonoSeqPointInfo *seq_points;
2610         int i, last_il_offset, seq_il_offset, seq_native_offset;
2611
2612         mono_domain_lock (domain);
2613         seq_points = g_hash_table_lookup (domain_jit_info (domain)->seq_points, method);
2614         mono_domain_unlock (domain);
2615         g_assert (seq_points);
2616
2617         last_il_offset = -1;
2618
2619         /* Find the sequence point */
2620         for (i = 0; i < seq_points->len; ++i) {
2621                 seq_il_offset = seq_points->seq_points [i].il_offset;
2622                 seq_native_offset = seq_points->seq_points [i].native_offset;
2623
2624                 if (seq_native_offset > native_offset)
2625                         break;
2626                 last_il_offset = seq_il_offset;
2627         }
2628
2629         return last_il_offset;
2630 }
2631
2632 typedef struct {
2633         DebuggerTlsData *tls;
2634         GSList *frames;
2635 } ComputeFramesUserData;
2636
2637 static gboolean
2638 process_frame (StackFrameInfo *info, MonoContext *ctx, gpointer user_data)
2639 {
2640         ComputeFramesUserData *ud = user_data;
2641         StackFrame *frame;
2642         MonoMethod *method, *actual_method;
2643
2644         if (info->type != FRAME_TYPE_MANAGED) {
2645                 if (info->type == FRAME_TYPE_DEBUGGER_INVOKE) {
2646                         /* Mark the last frame as an invoke frame */
2647                         if (ud->frames)
2648                                 ((StackFrame*)g_slist_last (ud->frames)->data)->flags |= FRAME_FLAG_DEBUGGER_INVOKE;
2649                 }
2650                 return FALSE;
2651         }
2652
2653         if (info->ji)
2654                 method = info->ji->method;
2655         else
2656                 method = info->method;
2657         actual_method = info->actual_method;
2658
2659         if (!method || (method->wrapper_type && method->wrapper_type != MONO_WRAPPER_DYNAMIC_METHOD))
2660                 return FALSE;
2661
2662         if (info->il_offset == -1) {
2663                 /* Can't use compute_il_offset () since ip doesn't point precisely at at a seq point */
2664                 info->il_offset = mono_debug_il_offset_from_address (method, info->domain, info->native_offset);
2665         }
2666
2667         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));
2668
2669         if (!info->managed && method->wrapper_type != MONO_WRAPPER_DYNAMIC_METHOD) {
2670                 /*
2671                  * mono_arch_find_jit_info () returns the context stored in the LMF for 
2672                  * native frames, but it should unwind once. This is why we have duplicate
2673                  * frames on the stack sometimes.
2674                  * !managed also seems to be set for dynamic methods.
2675                  */
2676                 return FALSE;
2677         }
2678
2679         frame = g_new0 (StackFrame, 1);
2680         frame->method = method;
2681         frame->actual_method = actual_method;
2682         frame->il_offset = info->il_offset;
2683         frame->native_offset = info->native_offset;
2684         if (ctx) {
2685                 frame->ctx = *ctx;
2686                 frame->has_ctx = TRUE;
2687         }
2688         frame->domain = info->domain;
2689
2690         ud->frames = g_slist_append (ud->frames, frame);
2691
2692         return FALSE;
2693 }
2694
2695 static gboolean
2696 process_filter_frame (StackFrameInfo *info, MonoContext *ctx, gpointer user_data)
2697 {
2698         ComputeFramesUserData *ud = user_data;
2699
2700         /*
2701          * 'tls->filter_ctx' is the location of the throw site.
2702          *
2703          * mono_walk_stack() will never actually hit the throw site, but unwind
2704          * directly from the filter to the call site; we abort stack unwinding here
2705          * once this happens and resume from the throw site.
2706          */
2707
2708         if (MONO_CONTEXT_GET_SP (ctx) >= MONO_CONTEXT_GET_SP (&ud->tls->filter_state.ctx))
2709                 return TRUE;
2710
2711         return process_frame (info, ctx, user_data);
2712 }
2713
2714 static void
2715 compute_frame_info (MonoInternalThread *thread, DebuggerTlsData *tls)
2716 {
2717         ComputeFramesUserData user_data;
2718         GSList *tmp;
2719         int i, findex, new_frame_count;
2720         StackFrame **new_frames, *f;
2721
2722         // FIXME: Locking on tls
2723         if (tls->frames && tls->frames_up_to_date)
2724                 return;
2725
2726         DEBUG(1, fprintf (log_file, "Frames for %p(tid=%lx):\n", thread, (glong)thread->tid));
2727
2728         user_data.tls = tls;
2729         user_data.frames = NULL;
2730         if (tls->terminated) {
2731                 tls->frame_count = 0;
2732                 return;
2733         } if (!tls->really_suspended && tls->async_state.valid) {
2734                 /* Have to use the state saved by the signal handler */
2735                 process_frame (&tls->async_last_frame, NULL, &user_data);
2736                 mono_walk_stack_with_state (process_frame, &tls->async_state, MONO_UNWIND_DEFAULT, &user_data);
2737         } else if (tls->filter_state.valid) {
2738                 /*
2739                  * We are inside an exception filter.
2740                  *
2741                  * First we add all the frames from inside the filter; 'tls->ctx' has the current context.
2742                  */
2743                 if (tls->context.valid)
2744                         mono_walk_stack_with_state (process_filter_frame, &tls->context, MONO_UNWIND_DEFAULT, &user_data);
2745                 /*
2746                  * After that, we resume unwinding from the location where the exception has been thrown.
2747                  */
2748                 mono_walk_stack_with_state (process_frame, &tls->filter_state, MONO_UNWIND_DEFAULT, &user_data);
2749         } else if (tls->context.valid) {
2750                 mono_walk_stack_with_state (process_frame, &tls->context, MONO_UNWIND_DEFAULT, &user_data);
2751         } else {
2752                 // FIXME:
2753                 tls->frame_count = 0;
2754                 return;
2755         }
2756
2757         new_frame_count = g_slist_length (user_data.frames);
2758         new_frames = g_new0 (StackFrame*, new_frame_count);
2759         findex = 0;
2760         for (tmp = user_data.frames; tmp; tmp = tmp->next) {
2761                 f = tmp->data;
2762
2763                 /* 
2764                  * Reuse the id for already existing stack frames, so invokes don't invalidate
2765                  * the still valid stack frames.
2766                  */
2767                 for (i = 0; i < tls->frame_count; ++i) {
2768                         if (MONO_CONTEXT_GET_SP (&tls->frames [i]->ctx) == MONO_CONTEXT_GET_SP (&f->ctx)) {
2769                                 f->id = tls->frames [i]->id;
2770                                 break;
2771                         }
2772                 }
2773
2774                 if (i >= tls->frame_count)
2775                         f->id = InterlockedIncrement (&frame_id);
2776
2777                 new_frames [findex ++] = f;
2778         }
2779
2780         g_slist_free (user_data.frames);
2781
2782         invalidate_frames (tls);
2783
2784         tls->frames = new_frames;
2785         tls->frame_count = new_frame_count;
2786         tls->frames_up_to_date = TRUE;
2787 }
2788
2789 /*
2790  * GHFunc to emit an appdomain creation event
2791  * @param key Don't care
2792  * @param value A loaded appdomain
2793  * @param user_data Don't care
2794  */
2795 static void
2796 emit_appdomain_load (gpointer key, gpointer value, gpointer user_data)
2797 {
2798         process_profiler_event (EVENT_KIND_APPDOMAIN_CREATE, value);
2799         g_hash_table_foreach (get_agent_domain_info (value)->loaded_classes, emit_type_load, NULL);
2800 }
2801
2802 /*
2803  * GHFunc to emit a thread start event
2804  * @param key A thread id
2805  * @param value A thread object
2806  * @param user_data Don't care
2807  */
2808 static void
2809 emit_thread_start (gpointer key, gpointer value, gpointer user_data)
2810 {
2811         if (GPOINTER_TO_INT (key) != debugger_thread_id)
2812                 process_profiler_event (EVENT_KIND_THREAD_START, value);
2813 }
2814
2815 /*
2816  * GFunc to emit an assembly load event
2817  * @param value A loaded assembly
2818  * @param user_data Don't care
2819  */
2820 static void
2821 emit_assembly_load (gpointer value, gpointer user_data)
2822 {
2823         process_profiler_event (EVENT_KIND_ASSEMBLY_LOAD, value);
2824 }
2825
2826 /*
2827  * GFunc to emit a type load event
2828  * @param value A loaded type
2829  * @param user_data Don't care
2830  */
2831 static void
2832 emit_type_load (gpointer key, gpointer value, gpointer user_data)
2833 {
2834         process_profiler_event (EVENT_KIND_TYPE_LOAD, value);
2835 }
2836
2837
2838 /*
2839  * EVENT HANDLING
2840  */
2841
2842 /*
2843  * create_event_list:
2844  *
2845  *   Return a list of event request ids matching EVENT, starting from REQS, which
2846  * can be NULL to include all event requests. Set SUSPEND_POLICY to the suspend
2847  * policy.
2848  * We return request ids, instead of requests, to simplify threading, since 
2849  * requests could be deleted anytime when the loader lock is not held.
2850  * LOCKING: Assumes the loader lock is held.
2851  */
2852 static GSList*
2853 create_event_list (EventKind event, GPtrArray *reqs, MonoJitInfo *ji, EventInfo *ei, int *suspend_policy)
2854 {
2855         int i, j;
2856         GSList *events = NULL;
2857
2858         *suspend_policy = SUSPEND_POLICY_NONE;
2859
2860         if (!reqs)
2861                 reqs = event_requests;
2862
2863         if (!reqs)
2864                 return NULL;
2865
2866         for (i = 0; i < reqs->len; ++i) {
2867                 EventRequest *req = g_ptr_array_index (reqs, i);
2868                 if (req->event_kind == event) {
2869                         gboolean filtered = FALSE;
2870
2871                         /* Apply filters */
2872                         for (j = 0; j < req->nmodifiers; ++j) {
2873                                 Modifier *mod = &req->modifiers [j];
2874
2875                                 if (mod->kind == MOD_KIND_COUNT) {
2876                                         filtered = TRUE;
2877                                         if (mod->data.count > 0) {
2878                                                 if (mod->data.count > 0) {
2879                                                         mod->data.count --;
2880                                                         if (mod->data.count == 0)
2881                                                                 filtered = FALSE;
2882                                                 }
2883                                         }
2884                                 } else if (mod->kind == MOD_KIND_THREAD_ONLY) {
2885                                         if (mod->data.thread != mono_thread_internal_current ())
2886                                                 filtered = TRUE;
2887                                 } else if (mod->kind == MOD_KIND_EXCEPTION_ONLY && ei) {
2888                                         if (mod->data.exc_class && !mono_class_is_assignable_from (mod->data.exc_class, ei->exc->vtable->klass))
2889                                                 filtered = TRUE;
2890                                         if (ei->caught && !mod->caught)
2891                                                 filtered = TRUE;
2892                                         if (!ei->caught && !mod->uncaught)
2893                                                 filtered = TRUE;
2894                                 } else if (mod->kind == MOD_KIND_ASSEMBLY_ONLY && ji) {
2895                                         int k;
2896                                         gboolean found = FALSE;
2897                                         MonoAssembly **assemblies = mod->data.assemblies;
2898
2899                                         if (assemblies) {
2900                                                 for (k = 0; assemblies [k]; ++k)
2901                                                         if (assemblies [k] == ji->method->klass->image->assembly)
2902                                                                 found = TRUE;
2903                                         }
2904                                         if (!found)
2905                                                 filtered = TRUE;
2906                                 }
2907                         }
2908
2909                         if (!filtered) {
2910                                 *suspend_policy = MAX (*suspend_policy, req->suspend_policy);
2911                                 events = g_slist_append (events, GINT_TO_POINTER (req->id));
2912                         }
2913                 }
2914         }
2915
2916         /* Send a VM START/DEATH event by default */
2917         if (event == EVENT_KIND_VM_START)
2918                 events = g_slist_append (events, GINT_TO_POINTER (0));
2919         if (event == EVENT_KIND_VM_DEATH)
2920                 events = g_slist_append (events, GINT_TO_POINTER (0));
2921
2922         return events;
2923 }
2924
2925 static G_GNUC_UNUSED const char*
2926 event_to_string (EventKind event)
2927 {
2928         switch (event) {
2929         case EVENT_KIND_VM_START: return "VM_START";
2930         case EVENT_KIND_VM_DEATH: return "VM_DEATH";
2931         case EVENT_KIND_THREAD_START: return "THREAD_START";
2932         case EVENT_KIND_THREAD_DEATH: return "THREAD_DEATH";
2933         case EVENT_KIND_APPDOMAIN_CREATE: return "APPDOMAIN_CREATE";
2934         case EVENT_KIND_APPDOMAIN_UNLOAD: return "APPDOMAIN_UNLOAD";
2935         case EVENT_KIND_METHOD_ENTRY: return "METHOD_ENTRY";
2936         case EVENT_KIND_METHOD_EXIT: return "METHOD_EXIT";
2937         case EVENT_KIND_ASSEMBLY_LOAD: return "ASSEMBLY_LOAD";
2938         case EVENT_KIND_ASSEMBLY_UNLOAD: return "ASSEMBLY_UNLOAD";
2939         case EVENT_KIND_BREAKPOINT: return "BREAKPOINT";
2940         case EVENT_KIND_STEP: return "STEP";
2941         case EVENT_KIND_TYPE_LOAD: return "TYPE_LOAD";
2942         case EVENT_KIND_EXCEPTION: return "EXCEPTION";
2943         default:
2944                 g_assert_not_reached ();
2945         }
2946 }
2947
2948 /*
2949  * process_event:
2950  *
2951  *   Send an event to the client, suspending the vm if needed.
2952  * LOCKING: Since this can suspend the calling thread, no locks should be held
2953  * by the caller.
2954  * The EVENTS list is freed by this function.
2955  */
2956 static void
2957 process_event (EventKind event, gpointer arg, gint32 il_offset, MonoContext *ctx, GSList *events, int suspend_policy)
2958 {
2959         Buffer buf;
2960         GSList *l;
2961         MonoDomain *domain = mono_domain_get ();
2962         MonoThread *thread = NULL;
2963         gboolean send_success = FALSE;
2964
2965         if (!inited) {
2966                 DEBUG (2, fprintf (log_file, "Debugger agent not initialized yet: dropping %s\n", event_to_string (event)));
2967                 return;
2968         }
2969
2970         if (!vm_start_event_sent && event != EVENT_KIND_VM_START) {
2971                 // FIXME: We miss those events
2972                 DEBUG (2, fprintf (log_file, "VM start event not sent yet: dropping %s\n", event_to_string (event)));
2973                 return;
2974         }
2975
2976         if (vm_death_event_sent) {
2977                 DEBUG (2, fprintf (log_file, "VM death event has been sent: dropping %s\n", event_to_string (event)));
2978                 return;
2979         }
2980
2981         if (mono_runtime_is_shutting_down () && event != EVENT_KIND_VM_DEATH) {
2982                 DEBUG (2, fprintf (log_file, "Mono runtime is shutting down: dropping %s\n", event_to_string (event)));
2983                 return;
2984         }
2985
2986         if (disconnected) {
2987                 DEBUG (2, fprintf (log_file, "Debugger client is not connected: dropping %s\n", event_to_string (event)));
2988                 return;
2989         }
2990
2991         if (events == NULL)
2992                 return;
2993         
2994         if (agent_config.defer) {
2995                 /* Make sure the thread id is always set when doing deferred debugging */
2996                 if (debugger_thread_id == GetCurrentThreadId ())
2997                         thread = mono_thread_get_main ();
2998                 else thread = mono_thread_current ();
2999         } else {
3000                 if (debugger_thread_id == GetCurrentThreadId () && event != EVENT_KIND_VM_DEATH)
3001                         // FIXME: Send these with a NULL thread, don't suspend the current thread
3002                         return;
3003         }
3004
3005         buffer_init (&buf, 128);
3006         buffer_add_byte (&buf, suspend_policy);
3007         buffer_add_int (&buf, g_slist_length (events)); // n of events
3008
3009         for (l = events; l; l = l->next) {
3010                 buffer_add_byte (&buf, event); // event kind
3011                 buffer_add_int (&buf, GPOINTER_TO_INT (l->data)); // request id
3012
3013                 if (!thread)
3014                         thread = mono_thread_current ();
3015
3016                 if (event == EVENT_KIND_VM_START && arg != NULL)
3017                         thread = arg;
3018
3019                 buffer_add_objid (&buf, (MonoObject*)thread); // thread
3020
3021                 switch (event) {
3022                 case EVENT_KIND_THREAD_START:
3023                 case EVENT_KIND_THREAD_DEATH:
3024                         break;
3025                 case EVENT_KIND_APPDOMAIN_CREATE:
3026                 case EVENT_KIND_APPDOMAIN_UNLOAD:
3027                         buffer_add_domainid (&buf, arg);
3028                         break;
3029                 case EVENT_KIND_METHOD_ENTRY:
3030                 case EVENT_KIND_METHOD_EXIT:
3031                         buffer_add_methodid (&buf, domain, arg);
3032                         break;
3033                 case EVENT_KIND_ASSEMBLY_LOAD:
3034                 case EVENT_KIND_ASSEMBLY_UNLOAD:
3035                         buffer_add_assemblyid (&buf, domain, arg);
3036                         break;
3037                 case EVENT_KIND_TYPE_LOAD:
3038                         buffer_add_typeid (&buf, domain, arg);
3039                         break;
3040                 case EVENT_KIND_BREAKPOINT:
3041                 case EVENT_KIND_STEP:
3042                         buffer_add_methodid (&buf, domain, arg);
3043                         buffer_add_long (&buf, il_offset);
3044                         break;
3045                 case EVENT_KIND_VM_START:
3046                         buffer_add_domainid (&buf, mono_get_root_domain ());
3047                         break;
3048                 case EVENT_KIND_VM_DEATH:
3049                         break;
3050                 case EVENT_KIND_EXCEPTION: {
3051                         EventInfo *ei = arg;
3052                         buffer_add_objid (&buf, ei->exc);
3053                         break;
3054                 }
3055                 default:
3056                         g_assert_not_reached ();
3057                 }
3058         }
3059
3060         if (event == EVENT_KIND_VM_START) {
3061                 suspend_policy = agent_config.suspend ? SUSPEND_POLICY_ALL : SUSPEND_POLICY_NONE;
3062                 if (!agent_config.defer)
3063                         start_debugger_thread ();
3064         }
3065    
3066         if (event == EVENT_KIND_VM_DEATH) {
3067                 vm_death_event_sent = TRUE;
3068                 suspend_policy = SUSPEND_POLICY_NONE;
3069         }
3070
3071         if (mono_runtime_is_shutting_down ())
3072                 suspend_policy = SUSPEND_POLICY_NONE;
3073
3074         if (suspend_policy != SUSPEND_POLICY_NONE) {
3075                 /* 
3076                  * Save the thread context and start suspending before sending the packet,
3077                  * since we could be receiving the resume request before send_packet ()
3078                  * returns.
3079                  */
3080                 save_thread_context (ctx);
3081                 suspend_vm ();
3082         }
3083
3084         send_success = send_packet (CMD_SET_EVENT, CMD_COMPOSITE, &buf);
3085
3086         buffer_free (&buf);
3087
3088         g_slist_free (events);
3089         events = NULL;
3090
3091         if (!send_success) {
3092                 DEBUG (2, fprintf (log_file, "Sending command %s failed.\n", event_to_string (event)));
3093                 return;
3094         }
3095         
3096         if (event == EVENT_KIND_VM_START) {
3097                 vm_start_event_sent = TRUE;
3098                 if (agent_config.defer)
3099                         mono_debugger_agent_on_attach ();
3100         }
3101         
3102         DEBUG (1, fprintf (log_file, "[%p] Sent event %s, suspend=%d.\n", (gpointer)GetCurrentThreadId (), event_to_string (event), suspend_policy));
3103
3104
3105         switch (suspend_policy) {
3106         case SUSPEND_POLICY_NONE:
3107                 break;
3108         case SUSPEND_POLICY_ALL:
3109                 suspend_current ();
3110                 break;
3111         case SUSPEND_POLICY_EVENT_THREAD:
3112                 NOT_IMPLEMENTED;
3113                 break;
3114         default:
3115                 g_assert_not_reached ();
3116         }
3117 }
3118
3119 static void
3120 process_profiler_event (EventKind event, gpointer arg)
3121 {
3122         int suspend_policy;
3123         GSList *events;
3124
3125         mono_loader_lock ();
3126         events = create_event_list (event, NULL, NULL, NULL, &suspend_policy);
3127         mono_loader_unlock ();
3128
3129         process_event (event, arg, 0, NULL, events, suspend_policy);
3130 }
3131
3132 static void
3133 runtime_initialized (MonoProfiler *prof)
3134 {
3135         process_profiler_event (EVENT_KIND_VM_START, mono_thread_current ());
3136         if (agent_config.defer)
3137                 start_debugger_thread ();
3138 }
3139
3140 static void
3141 runtime_shutdown (MonoProfiler *prof)
3142 {
3143         process_profiler_event (EVENT_KIND_VM_DEATH, mono_thread_current ());
3144
3145         mono_debugger_agent_cleanup ();
3146 }
3147
3148 static void
3149 thread_startup (MonoProfiler *prof, uintptr_t tid)
3150 {
3151         MonoInternalThread *thread = mono_thread_internal_current ();
3152         MonoInternalThread *old_thread;
3153         DebuggerTlsData *tls;
3154
3155         if (tid == debugger_thread_id)
3156                 return;
3157
3158         g_assert (thread->tid == tid);
3159
3160         mono_loader_lock ();
3161         old_thread = mono_g_hash_table_lookup (tid_to_thread, (gpointer)tid);
3162         mono_loader_unlock ();
3163         if (old_thread) {
3164                 if (thread == old_thread) {
3165                         /* 
3166                          * For some reason, thread_startup () might be called for the same thread
3167                          * multiple times (attach ?).
3168                          */
3169                         DEBUG (1, fprintf (log_file, "[%p] thread_start () called multiple times for %p, ignored.\n", (gpointer)tid, (gpointer)tid));
3170                         return;
3171                 } else {
3172                         /*
3173                          * thread_end () might not be called for some threads, and the tid could
3174                          * get reused.
3175                          */
3176                         DEBUG (1, fprintf (log_file, "[%p] Removing stale data for tid %p.\n", (gpointer)tid, (gpointer)tid));
3177                         mono_loader_lock ();
3178                         mono_g_hash_table_remove (thread_to_tls, old_thread);
3179                         mono_g_hash_table_remove (tid_to_thread, (gpointer)tid);
3180                         mono_g_hash_table_remove (tid_to_thread_obj, (gpointer)tid);
3181                         mono_loader_unlock ();
3182                 }
3183         }
3184
3185         tls = TlsGetValue (debugger_tls_id);
3186         g_assert (!tls);
3187         // FIXME: Free this somewhere
3188         tls = g_new0 (DebuggerTlsData, 1);
3189         tls->resume_event = CreateEvent (NULL, FALSE, FALSE, NULL);
3190         MONO_GC_REGISTER_ROOT_SINGLE (tls->thread);
3191         tls->thread = thread;
3192         TlsSetValue (debugger_tls_id, tls);
3193
3194         DEBUG (1, fprintf (log_file, "[%p] Thread started, obj=%p, tls=%p.\n", (gpointer)tid, thread, tls));
3195
3196         mono_loader_lock ();
3197         mono_g_hash_table_insert (thread_to_tls, thread, tls);
3198         mono_g_hash_table_insert (tid_to_thread, (gpointer)tid, thread);
3199         mono_g_hash_table_insert (tid_to_thread_obj, (gpointer)tid, mono_thread_current ());
3200         mono_loader_unlock ();
3201
3202         process_profiler_event (EVENT_KIND_THREAD_START, thread);
3203
3204         /* 
3205          * suspend_vm () could have missed this thread, so wait for a resume.
3206          */
3207         suspend_current ();
3208 }
3209
3210 static void
3211 thread_end (MonoProfiler *prof, uintptr_t tid)
3212 {
3213         MonoInternalThread *thread;
3214         DebuggerTlsData *tls = NULL;
3215
3216         mono_loader_lock ();
3217         thread = mono_g_hash_table_lookup (tid_to_thread, (gpointer)tid);
3218         if (thread) {
3219                 tls = mono_g_hash_table_lookup (thread_to_tls, thread);
3220                 /* FIXME: Maybe we need to free this instead, but some code can't handle that */
3221                 tls->terminated = TRUE;
3222                 mono_g_hash_table_remove (tid_to_thread_obj, (gpointer)tid);
3223                 /* Can't remove from tid_to_thread, as that would defeat the check in thread_start () */
3224                 MONO_GC_UNREGISTER_ROOT (tls->thread);
3225                 tls->thread = NULL;
3226         }
3227         mono_loader_unlock ();
3228
3229         /* We might be called for threads started before we registered the start callback */
3230         if (thread) {
3231                 DEBUG (1, fprintf (log_file, "[%p] Thread terminated, obj=%p, tls=%p.\n", (gpointer)tid, thread, tls));
3232                 process_profiler_event (EVENT_KIND_THREAD_DEATH, thread);
3233         }
3234 }
3235
3236 static void
3237 appdomain_load (MonoProfiler *prof, MonoDomain *domain, int result)
3238 {
3239         mono_loader_lock ();
3240         g_hash_table_insert (domains, domain, domain);
3241         mono_loader_unlock ();
3242
3243         process_profiler_event (EVENT_KIND_APPDOMAIN_CREATE, domain);
3244 }
3245
3246 static void
3247 appdomain_unload (MonoProfiler *prof, MonoDomain *domain)
3248 {
3249         clear_breakpoints_for_domain (domain);
3250         
3251         mono_loader_lock ();
3252         /* Invalidate each thread's frame stack */
3253         mono_g_hash_table_foreach (thread_to_tls, invalidate_each_thread, NULL);
3254         mono_loader_unlock ();
3255         
3256         process_profiler_event (EVENT_KIND_APPDOMAIN_UNLOAD, domain);
3257 }
3258
3259 /*
3260  * invalidate_each_thread:
3261  *
3262  *   A GHFunc to invalidate frames.
3263  *   value must be a DebuggerTlsData*
3264  */
3265 static void
3266 invalidate_each_thread (gpointer key, gpointer value, gpointer user_data)
3267 {
3268         invalidate_frames (value);
3269 }
3270
3271 static void
3272 assembly_load (MonoProfiler *prof, MonoAssembly *assembly, int result)
3273 {
3274         /* Sent later in jit_end () */
3275         mono_loader_lock ();
3276         g_ptr_array_add (pending_assembly_loads, assembly);
3277         mono_loader_unlock ();
3278 }
3279
3280 static void
3281 assembly_unload (MonoProfiler *prof, MonoAssembly *assembly)
3282 {
3283         process_profiler_event (EVENT_KIND_ASSEMBLY_UNLOAD, assembly);
3284
3285         clear_event_requests_for_assembly (assembly);
3286         clear_types_for_assembly (assembly);
3287 }
3288
3289 static void
3290 start_runtime_invoke (MonoProfiler *prof, MonoMethod *method)
3291 {
3292 #if defined(HOST_WIN32) && !defined(__GNUC__)
3293         gpointer stackptr = ((guint64)_AddressOfReturnAddress () - sizeof (void*));
3294 #else
3295         gpointer stackptr = __builtin_frame_address (1);
3296 #endif
3297         MonoInternalThread *thread = mono_thread_internal_current ();
3298         DebuggerTlsData *tls;
3299
3300         mono_loader_lock ();
3301         
3302         tls = mono_g_hash_table_lookup (thread_to_tls, thread);
3303         /* Could be the debugger thread with assembly/type load hooks */
3304         if (tls)
3305                 tls->invoke_addr = stackptr;
3306
3307         mono_loader_unlock ();
3308 }
3309
3310 static void
3311 end_runtime_invoke (MonoProfiler *prof, MonoMethod *method)
3312 {
3313         int i;
3314 #if defined(HOST_WIN32) && !defined(__GNUC__)
3315         gpointer stackptr = ((guint64)_AddressOfReturnAddress () - sizeof (void*));
3316 #else
3317         gpointer stackptr = __builtin_frame_address (1);
3318 #endif
3319
3320         if (!embedding || ss_req == NULL || stackptr != ss_invoke_addr || ss_req->thread != mono_thread_internal_current ())
3321                 return;
3322
3323         /*
3324          * We need to stop single stepping when exiting a runtime invoke, since if it is
3325          * a step out, it may return to native code, and thus never end.
3326          */
3327         mono_loader_lock ();
3328         ss_invoke_addr = NULL;
3329
3330         for (i = 0; i < event_requests->len; ++i) {
3331                 EventRequest *req = g_ptr_array_index (event_requests, i);
3332
3333                 if (req->event_kind == EVENT_KIND_STEP) {
3334                         ss_destroy (req->info);
3335                         g_ptr_array_remove_index_fast (event_requests, i);
3336                         g_free (req);
3337                         break;
3338                 }
3339         }
3340         mono_loader_unlock ();
3341 }
3342
3343 static void
3344 send_type_load (MonoClass *klass)
3345 {
3346         gboolean type_load = FALSE;
3347         MonoDomain *domain = mono_domain_get ();
3348         AgentDomainInfo *info = NULL;
3349
3350         mono_loader_lock ();
3351         mono_domain_lock (domain);
3352
3353         info = get_agent_domain_info (domain);
3354
3355         if (!g_hash_table_lookup (info->loaded_classes, klass)) {
3356                 type_load = TRUE;
3357                 g_hash_table_insert (info->loaded_classes, klass, klass);
3358         }
3359
3360         mono_domain_unlock (domain);
3361         mono_loader_unlock ();
3362         if (type_load)
3363                 emit_type_load (klass, klass, NULL);
3364 }
3365
3366 static void
3367 jit_end (MonoProfiler *prof, MonoMethod *method, MonoJitInfo *jinfo, int result)
3368 {
3369         /*
3370          * We emit type load events when the first method of the type is JITted,
3371          * since the class load profiler callbacks might be called with the
3372          * loader lock held. They could also occur in the debugger thread.
3373          * Same for assembly load events.
3374          */
3375         while (TRUE) {
3376                 MonoAssembly *assembly = NULL;
3377
3378                 // FIXME: Maybe store this in TLS so the thread of the event is correct ?
3379                 mono_loader_lock ();
3380                 if (pending_assembly_loads->len > 0) {
3381                         assembly = g_ptr_array_index (pending_assembly_loads, 0);
3382                         g_ptr_array_remove_index (pending_assembly_loads, 0);
3383                 }
3384                 mono_loader_unlock ();
3385
3386                 if (assembly) {
3387                         process_profiler_event (EVENT_KIND_ASSEMBLY_LOAD, assembly);
3388                 } else {
3389                         break;
3390                 }
3391         }
3392
3393         send_type_load (method->klass);
3394
3395         if (!result)
3396                 add_pending_breakpoints (method, jinfo);
3397 }
3398
3399 /*
3400  * BREAKPOINTS/SINGLE STEPPING
3401  */
3402
3403 /* 
3404  * Contains information about an inserted breakpoint.
3405  */
3406 typedef struct {
3407         long il_offset, native_offset;
3408         guint8 *ip;
3409         MonoJitInfo *ji;
3410         MonoDomain *domain;
3411 } BreakpointInstance;
3412
3413 /*
3414  * Contains generic information about a breakpoint.
3415  */
3416 typedef struct {
3417         /* 
3418          * The method where the breakpoint is placed. Can be NULL in which case it 
3419          * is inserted into every method. This is used to implement method entry/
3420          * exit events. Can be a generic method definition, in which case the
3421          * breakpoint is inserted into every instance.
3422          */
3423         MonoMethod *method;
3424         long il_offset;
3425         EventRequest *req;
3426         /* 
3427          * A list of BreakpointInstance structures describing where the breakpoint
3428          * was inserted. There could be more than one because of 
3429          * generics/appdomains/method entry/exit.
3430          */
3431         GPtrArray *children;
3432 } MonoBreakpoint;
3433
3434 /* List of breakpoints */
3435 static GPtrArray *breakpoints;
3436 /* Maps breakpoint locations to the number of breakpoints at that location */
3437 static GHashTable *bp_locs;
3438
3439 static void
3440 breakpoints_init (void)
3441 {
3442         breakpoints = g_ptr_array_new ();
3443         bp_locs = g_hash_table_new (NULL, NULL);
3444 }       
3445
3446 /*
3447  * insert_breakpoint:
3448  *
3449  *   Insert the breakpoint described by BP into the method described by
3450  * JI.
3451  */
3452 static void
3453 insert_breakpoint (MonoSeqPointInfo *seq_points, MonoDomain *domain, MonoJitInfo *ji, MonoBreakpoint *bp, MonoError *error)
3454 {
3455         int i, count;
3456         gint32 il_offset = -1, native_offset;
3457         BreakpointInstance *inst;
3458
3459         if (error)
3460                 mono_error_init (error);
3461
3462         native_offset = 0;
3463         for (i = 0; i < seq_points->len; ++i) {
3464                 il_offset = seq_points->seq_points [i].il_offset;
3465                 native_offset = seq_points->seq_points [i].native_offset;
3466
3467                 if (il_offset == bp->il_offset)
3468                         break;
3469         }
3470
3471         if (i == seq_points->len) {
3472                 char *s = g_strdup_printf ("Unable to insert breakpoint at %s:%d, seq_points=%d\n", mono_method_full_name (ji->method, TRUE), bp->il_offset, seq_points->len);
3473                 if (error) {
3474                         mono_error_set_error (error, MONO_ERROR_GENERIC, "%s", s);
3475                         g_free (s);
3476                         return;
3477                 } else {
3478                         g_error ("%s", s);
3479                         g_free (s);
3480                 }
3481         }
3482
3483         inst = g_new0 (BreakpointInstance, 1);
3484         inst->native_offset = native_offset;
3485         inst->ip = (guint8*)ji->code_start + native_offset;
3486         inst->ji = ji;
3487         inst->domain = domain;
3488
3489         mono_loader_lock ();
3490
3491         g_ptr_array_add (bp->children, inst);
3492
3493         count = GPOINTER_TO_INT (g_hash_table_lookup (bp_locs, inst->ip));
3494         g_hash_table_insert (bp_locs, inst->ip, GINT_TO_POINTER (count + 1));
3495         mono_loader_unlock ();
3496
3497         if (count == 0) {
3498 #ifdef MONO_ARCH_SOFT_DEBUG_SUPPORTED
3499                 mono_arch_set_breakpoint (ji, inst->ip);
3500 #else
3501                 NOT_IMPLEMENTED;
3502 #endif
3503         }
3504
3505         DEBUG(1, fprintf (log_file, "[dbg] Inserted breakpoint at %s:0x%x.\n", mono_method_full_name (ji->method, TRUE), (int)il_offset));      
3506 }
3507
3508 static void
3509 remove_breakpoint (BreakpointInstance *inst)
3510 {
3511 #ifdef MONO_ARCH_SOFT_DEBUG_SUPPORTED
3512         int count;
3513         MonoJitInfo *ji = inst->ji;
3514         guint8 *ip = inst->ip;
3515
3516         mono_loader_lock ();
3517         count = GPOINTER_TO_INT (g_hash_table_lookup (bp_locs, ip));
3518         g_hash_table_insert (bp_locs, ip, GINT_TO_POINTER (count - 1));
3519         mono_loader_unlock ();
3520
3521         g_assert (count > 0);
3522
3523         if (count == 1) {
3524                 mono_arch_clear_breakpoint (ji, ip);
3525         }
3526 #else
3527         NOT_IMPLEMENTED;
3528 #endif
3529 }       
3530
3531 static inline gboolean
3532 bp_matches_method (MonoBreakpoint *bp, MonoMethod *method)
3533 {
3534         return (!bp->method || method == bp->method || (method->is_inflated && ((MonoMethodInflated*)method)->declaring == bp->method));
3535 }
3536
3537 /*
3538  * add_pending_breakpoints:
3539  *
3540  *   Insert pending breakpoints into the newly JITted method METHOD.
3541  */
3542 static void
3543 add_pending_breakpoints (MonoMethod *method, MonoJitInfo *ji)
3544 {
3545         int i, j;
3546         MonoSeqPointInfo *seq_points;
3547         MonoDomain *domain;
3548
3549         if (!breakpoints)
3550                 return;
3551
3552         domain = mono_domain_get ();
3553
3554         mono_loader_lock ();
3555
3556         for (i = 0; i < breakpoints->len; ++i) {
3557                 MonoBreakpoint *bp = g_ptr_array_index (breakpoints, i);
3558                 gboolean found = FALSE;
3559
3560                 if (!bp_matches_method (bp, method))
3561                         continue;
3562
3563                 for (j = 0; j < bp->children->len; ++j) {
3564                         BreakpointInstance *inst = g_ptr_array_index (bp->children, j);
3565
3566                         if (inst->ji == ji)
3567                                 found = TRUE;
3568                 }
3569
3570                 if (!found) {
3571                         mono_domain_lock (domain);
3572                         seq_points = g_hash_table_lookup (domain_jit_info (domain)->seq_points, ji->method);
3573                         mono_domain_unlock (domain);
3574                         if (!seq_points)
3575                                 /* Could be AOT code */
3576                                 continue;
3577                         g_assert (seq_points);
3578
3579                         insert_breakpoint (seq_points, domain, ji, bp, NULL);
3580                 }
3581         }
3582
3583         mono_loader_unlock ();
3584 }
3585
3586 static void
3587 set_bp_in_method (MonoDomain *domain, MonoMethod *method, MonoSeqPointInfo *seq_points, MonoBreakpoint *bp, MonoError *error)
3588 {
3589         gpointer code;
3590         MonoJitInfo *ji;
3591
3592         if (error)
3593                 mono_error_init (error);
3594
3595         code = mono_jit_find_compiled_method_with_jit_info (domain, method, &ji);
3596         if (!code) {
3597                 /* Might be AOTed code */
3598                 code = mono_aot_get_method (domain, method);
3599                 g_assert (code);
3600                 ji = mono_jit_info_table_find (domain, code);
3601                 g_assert (ji);
3602         }
3603         g_assert (code);
3604
3605         insert_breakpoint (seq_points, domain, ji, bp, error);
3606 }
3607
3608 static void
3609 clear_breakpoint (MonoBreakpoint *bp);
3610
3611 /*
3612  * set_breakpoint:
3613  *
3614  *   Set a breakpoint at IL_OFFSET in METHOD.
3615  * METHOD can be NULL, in which case a breakpoint is placed in all methods.
3616  * METHOD can also be a generic method definition, in which case a breakpoint
3617  * is placed in all instances of the method.
3618  * If ERROR is non-NULL, then it is set and NULL is returnd if some breakpoints couldn't be
3619  * inserted.
3620  */
3621 static MonoBreakpoint*
3622 set_breakpoint (MonoMethod *method, long il_offset, EventRequest *req, MonoError *error)
3623 {
3624         MonoBreakpoint *bp;
3625         GHashTableIter iter, iter2;
3626         MonoDomain *domain;
3627         MonoMethod *m;
3628         MonoSeqPointInfo *seq_points;
3629
3630         if (error)
3631                 mono_error_init (error);
3632
3633         // FIXME:
3634         // - suspend/resume the vm to prevent code patching problems
3635         // - multiple breakpoints on the same location
3636         // - dynamic methods
3637         // - races
3638
3639         bp = g_new0 (MonoBreakpoint, 1);
3640         bp->method = method;
3641         bp->il_offset = il_offset;
3642         bp->req = req;
3643         bp->children = g_ptr_array_new ();
3644
3645         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));
3646
3647         mono_loader_lock ();
3648
3649         g_hash_table_iter_init (&iter, domains);
3650         while (g_hash_table_iter_next (&iter, (void**)&domain, NULL)) {
3651                 mono_domain_lock (domain);
3652
3653                 g_hash_table_iter_init (&iter2, domain_jit_info (domain)->seq_points);
3654                 while (g_hash_table_iter_next (&iter2, (void**)&m, (void**)&seq_points)) {
3655                         if (bp_matches_method (bp, m))
3656                                 set_bp_in_method (domain, m, seq_points, bp, error);
3657                 }
3658
3659                 mono_domain_unlock (domain);
3660         }
3661
3662         mono_loader_unlock ();
3663
3664         mono_loader_lock ();
3665         g_ptr_array_add (breakpoints, bp);
3666         mono_loader_unlock ();
3667
3668         if (error && !mono_error_ok (error)) {
3669                 clear_breakpoint (bp);
3670                 return NULL;
3671         }
3672
3673         return bp;
3674 }
3675
3676 static void
3677 clear_breakpoint (MonoBreakpoint *bp)
3678 {
3679         int i;
3680
3681         // FIXME: locking, races
3682         for (i = 0; i < bp->children->len; ++i) {
3683                 BreakpointInstance *inst = g_ptr_array_index (bp->children, i);
3684
3685                 remove_breakpoint (inst);
3686
3687                 g_free (inst);
3688         }
3689
3690         mono_loader_lock ();
3691         g_ptr_array_remove (breakpoints, bp);
3692         mono_loader_unlock ();
3693
3694         g_ptr_array_free (bp->children, TRUE);
3695         g_free (bp);
3696 }
3697
3698 static void
3699 breakpoints_cleanup (void)
3700 {
3701         int i;
3702
3703         mono_loader_lock ();
3704         i = 0;
3705         while (i < event_requests->len) {
3706                 EventRequest *req = g_ptr_array_index (event_requests, i);
3707
3708                 if (req->event_kind == EVENT_KIND_BREAKPOINT) {
3709                         clear_breakpoint (req->info);
3710                         g_ptr_array_remove_index_fast (event_requests, i);
3711                         g_free (req);
3712                 } else {
3713                         i ++;
3714                 }
3715         }
3716
3717         for (i = 0; i < breakpoints->len; ++i)
3718                 g_free (g_ptr_array_index (breakpoints, i));
3719
3720         g_ptr_array_free (breakpoints, TRUE);
3721         g_hash_table_destroy (bp_locs);
3722
3723         breakpoints = NULL;
3724         bp_locs = NULL;
3725
3726         mono_loader_unlock ();
3727 }
3728
3729 /*
3730  * clear_breakpoints_for_domain:
3731  *
3732  *   Clear breakpoint instances which reference DOMAIN.
3733  */
3734 static void
3735 clear_breakpoints_for_domain (MonoDomain *domain)
3736 {
3737         int i, j;
3738
3739         /* This could be called after shutdown */
3740         if (!breakpoints)
3741                 return;
3742
3743         mono_loader_lock ();
3744         for (i = 0; i < breakpoints->len; ++i) {
3745                 MonoBreakpoint *bp = g_ptr_array_index (breakpoints, i);
3746
3747                 j = 0;
3748                 while (j < bp->children->len) {
3749                         BreakpointInstance *inst = g_ptr_array_index (bp->children, j);
3750
3751                         if (inst->domain == domain) {
3752                                 remove_breakpoint (inst);
3753
3754                                 g_free (inst);
3755
3756                                 g_ptr_array_remove_index_fast (bp->children, j);
3757                         } else {
3758                                 j ++;
3759                         }
3760                 }
3761         }
3762         mono_loader_unlock ();
3763 }
3764
3765 static gboolean
3766 breakpoint_matches_assembly (MonoBreakpoint *bp, MonoAssembly *assembly)
3767 {
3768         return bp->method && bp->method->klass->image->assembly == assembly;
3769 }
3770
3771 static void
3772 process_breakpoint_inner (DebuggerTlsData *tls, MonoContext *ctx)
3773 {
3774         MonoJitInfo *ji;
3775         guint8 *orig_ip, *ip;
3776         int i, j, suspend_policy;
3777         guint32 native_offset;
3778         MonoBreakpoint *bp;
3779         BreakpointInstance *inst;
3780         GPtrArray *bp_reqs, *ss_reqs_orig, *ss_reqs;
3781         GSList *bp_events = NULL, *ss_events = NULL, *enter_leave_events = NULL;
3782         EventKind kind = EVENT_KIND_BREAKPOINT;
3783
3784         // FIXME: Speed this up
3785
3786         orig_ip = ip = MONO_CONTEXT_GET_IP (ctx);
3787         ji = mini_jit_info_table_find (mono_domain_get (), (char*)ip, NULL);
3788         g_assert (ji);
3789         g_assert (ji->method);
3790
3791         /* Compute the native offset of the breakpoint from the ip */
3792 #ifdef MONO_ARCH_SOFT_DEBUG_SUPPORTED
3793         ip = mono_arch_get_ip_for_breakpoint (ji, ctx);
3794         native_offset = ip - (guint8*)ji->code_start;   
3795 #else
3796         NOT_IMPLEMENTED;
3797 #endif
3798
3799         /* 
3800          * Skip the instruction causing the breakpoint signal.
3801          */
3802         mono_arch_skip_breakpoint (ctx);
3803
3804         if (ji->method->wrapper_type || tls->disable_breakpoints)
3805                 return;
3806
3807         bp_reqs = g_ptr_array_new ();
3808         ss_reqs = g_ptr_array_new ();
3809         ss_reqs_orig = g_ptr_array_new ();
3810
3811         DEBUG(1, fprintf (log_file, "[%p] Breakpoint hit, method=%s, offset=0x%x.\n", (gpointer)GetCurrentThreadId (), ji->method->name, native_offset));
3812
3813         mono_loader_lock ();
3814
3815         bp = NULL;
3816         for (i = 0; i < breakpoints->len; ++i) {
3817                 bp = g_ptr_array_index (breakpoints, i);
3818
3819                 if (!bp->method)
3820                         continue;
3821
3822                 for (j = 0; j < bp->children->len; ++j) {
3823                         inst = g_ptr_array_index (bp->children, j);
3824                         if (inst->ji == ji && inst->native_offset == native_offset) {
3825                                 if (bp->req->event_kind == EVENT_KIND_STEP) {
3826                                         g_ptr_array_add (ss_reqs_orig, bp->req);
3827                                 } else {
3828                                         g_ptr_array_add (bp_reqs, bp->req);
3829                                 }
3830                         }
3831                 }
3832         }
3833         if (bp_reqs->len == 0 && ss_reqs_orig->len == 0) {
3834                 MonoSeqPointInfo *seq_points;
3835                 int seq_il_offset, seq_native_offset;
3836                 MonoDomain *domain = mono_domain_get ();
3837
3838                 /* Maybe a method entry/exit event */
3839                 mono_domain_lock (domain);
3840                 seq_points = g_hash_table_lookup (domain_jit_info (domain)->seq_points, ji->method);
3841                 mono_domain_unlock (domain);
3842                 if (!seq_points) {
3843                         // FIXME: Generic sharing */
3844                         mono_loader_unlock ();
3845                         return;
3846                 }
3847                 g_assert (seq_points);
3848
3849                 for (i = 0; i < seq_points->len; ++i) {
3850                         seq_il_offset = seq_points->seq_points [i].il_offset;
3851                         seq_native_offset = seq_points->seq_points [i].native_offset;
3852
3853                         if (native_offset == seq_native_offset) {
3854                                 if (seq_il_offset == METHOD_ENTRY_IL_OFFSET)
3855                                         kind = EVENT_KIND_METHOD_ENTRY;
3856                                 else if (seq_il_offset == METHOD_EXIT_IL_OFFSET)
3857                                         kind = EVENT_KIND_METHOD_EXIT;
3858                                 break;
3859                         }
3860                 }
3861         }
3862
3863         /* Process single step requests */
3864         for (i = 0; i < ss_reqs_orig->len; ++i) {
3865                 EventRequest *req = g_ptr_array_index (ss_reqs_orig, i);
3866                 SingleStepReq *ss_req = req->info;
3867                 gboolean hit = TRUE;
3868                 MonoSeqPointInfo *info;
3869                 SeqPoint *sp;
3870
3871                 sp = find_seq_point_for_native_offset (mono_domain_get (), ji->method, native_offset, &info);
3872                 g_assert (sp);
3873
3874                 if (ss_req->size == STEP_SIZE_LINE) {
3875                         /* Have to check whenever a different source line was reached */
3876                         MonoDebugMethodInfo *minfo;
3877                         MonoDebugSourceLocation *loc = NULL;
3878
3879                         minfo = mono_debug_lookup_method (ji->method);
3880
3881                         if (minfo)
3882                                 loc = mono_debug_symfile_lookup_location (minfo, sp->il_offset);
3883
3884                         if (!loc || (loc && ji->method == ss_req->last_method && loc->row == ss_req->last_line))
3885                                 /* Have to continue single stepping */
3886                                 hit = FALSE;
3887                                 
3888                         if (loc) {
3889                                 ss_req->last_method = ji->method;
3890                                 ss_req->last_line = loc->row;
3891                                 mono_debug_free_source_location (loc);
3892                         }
3893                 }
3894
3895                 if (hit)
3896                         g_ptr_array_add (ss_reqs, req);
3897
3898                 /* Start single stepping again from the current sequence point */
3899                 ss_start (ss_req, ji->method, sp, info, ctx, NULL, FALSE);
3900         }
3901         
3902         if (ss_reqs->len > 0)
3903                 ss_events = create_event_list (EVENT_KIND_STEP, ss_reqs, ji, NULL, &suspend_policy);
3904         if (bp_reqs->len > 0)
3905                 bp_events = create_event_list (EVENT_KIND_BREAKPOINT, bp_reqs, ji, NULL, &suspend_policy);
3906         if (kind != EVENT_KIND_BREAKPOINT)
3907                 enter_leave_events = create_event_list (kind, NULL, ji, NULL, &suspend_policy);
3908
3909         mono_loader_unlock ();
3910
3911         g_ptr_array_free (bp_reqs, TRUE);
3912         g_ptr_array_free (ss_reqs, TRUE);
3913
3914         /* 
3915          * FIXME: The first event will suspend, so the second will only be sent after the
3916          * resume.
3917          */
3918         if (ss_events)
3919                 process_event (EVENT_KIND_STEP, ji->method, 0, ctx, ss_events, suspend_policy);
3920         if (bp_events)
3921                 process_event (kind, ji->method, 0, ctx, bp_events, suspend_policy);
3922         if (enter_leave_events)
3923                 process_event (kind, ji->method, 0, ctx, enter_leave_events, suspend_policy);
3924 }
3925
3926 static void
3927 process_breakpoint (void)
3928 {
3929         DebuggerTlsData *tls;
3930         MonoContext ctx;
3931         static void (*restore_context) (void *);
3932
3933         if (!restore_context)
3934                 restore_context = mono_get_restore_context ();
3935
3936         tls = TlsGetValue (debugger_tls_id);
3937         memcpy (&ctx, &tls->handler_ctx, sizeof (MonoContext));
3938
3939         process_breakpoint_inner (tls, &ctx);
3940
3941         /* This is called when resuming from a signal handler, so it shouldn't return */
3942         restore_context (&ctx);
3943         g_assert_not_reached ();
3944 }
3945
3946 static void
3947 resume_from_signal_handler (void *sigctx, void *func)
3948 {
3949         DebuggerTlsData *tls;
3950         MonoContext ctx;
3951
3952         /* Save the original context in TLS */
3953         // FIXME: This might not work on an altstack ?
3954         tls = TlsGetValue (debugger_tls_id);
3955         g_assert (tls);
3956
3957         // FIXME: MonoContext usually doesn't include the fp registers, so these are 
3958         // clobbered by a single step/breakpoint event. If this turns out to be a problem,
3959         // clob:c could be added to op_seq_point.
3960
3961         mono_arch_sigctx_to_monoctx (sigctx, &ctx);
3962         memcpy (&tls->handler_ctx, &ctx, sizeof (MonoContext));
3963 #ifdef MONO_ARCH_HAVE_SETUP_RESUME_FROM_SIGNAL_HANDLER_CTX
3964         mono_arch_setup_resume_sighandler_ctx (&ctx, func);
3965 #else
3966         MONO_CONTEXT_SET_IP (&ctx, func);
3967 #endif
3968         mono_arch_monoctx_to_sigctx (&ctx, sigctx);
3969
3970 #ifdef PPC_USES_FUNCTION_DESCRIPTOR
3971         mono_ppc_set_func_into_sigctx (sigctx, func);
3972 #endif
3973 }
3974
3975 void
3976 mono_debugger_agent_breakpoint_hit (void *sigctx)
3977 {
3978         /*
3979          * We are called from a signal handler, and running code there causes all kinds of
3980          * problems, like the original signal is disabled, libgc can't handle altstack, etc.
3981          * So set up the signal context to return to the real breakpoint handler function.
3982          */
3983
3984         resume_from_signal_handler (sigctx, process_breakpoint);
3985 }
3986
3987 static const char*
3988 ss_depth_to_string (StepDepth depth)
3989 {
3990         switch (depth) {
3991         case STEP_DEPTH_OVER:
3992                 return "over";
3993         case STEP_DEPTH_OUT:
3994                 return "out";
3995         case STEP_DEPTH_INTO:
3996                 return "into";
3997         default:
3998                 g_assert_not_reached ();
3999                 return NULL;
4000         }
4001 }
4002
4003 static void
4004 process_single_step_inner (DebuggerTlsData *tls, MonoContext *ctx)
4005 {
4006         MonoJitInfo *ji;
4007         guint8 *ip;
4008         GPtrArray *reqs;
4009         int il_offset, suspend_policy;
4010         MonoDomain *domain;
4011         GSList *events;
4012
4013         // FIXME: Speed this up
4014
4015         ip = MONO_CONTEXT_GET_IP (ctx);
4016
4017         /* Skip the instruction causing the single step */
4018         mono_arch_skip_single_step (ctx);
4019
4020         if (suspend_count > 0) {
4021                 process_suspend (tls, ctx);
4022                 return;
4023         }
4024
4025         if (!ss_req)
4026                 // FIXME: A suspend race
4027                 return;
4028
4029         if (mono_thread_internal_current () != ss_req->thread)
4030                 return;
4031
4032         if (log_level > 0) {
4033                 ji = mini_jit_info_table_find (mono_domain_get (), (char*)ip, &domain);
4034
4035                 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 (ji->method, TRUE), MONO_CONTEXT_GET_IP (ctx), MONO_CONTEXT_GET_SP (ctx), ss_req->last_sp));
4036         }
4037
4038         /*
4039          * We implement step over/out by single stepping until we reach the same 
4040          * frame/parent frame.
4041          * FIXME:
4042          * - this is slow
4043          * - stack growing upward
4044          * - localloc
4045          * - exceptions
4046          */
4047         if (ss_req->depth != STEP_DEPTH_INTO) {
4048                 if (ss_req->depth == STEP_DEPTH_OVER && MONO_CONTEXT_GET_SP (ctx) < ss_req->last_sp)
4049                         return;
4050                 if (ss_req->depth == STEP_DEPTH_OUT && MONO_CONTEXT_GET_SP (ctx) <= ss_req->last_sp)
4051                         return;
4052
4053                 ss_req->last_sp = MONO_CONTEXT_GET_SP (ctx);
4054         }
4055
4056         ji = mini_jit_info_table_find (mono_domain_get (), (char*)ip, &domain);
4057         g_assert (ji);
4058         g_assert (ji->method);
4059
4060         if (ji->method->wrapper_type && ji->method->wrapper_type != MONO_WRAPPER_DYNAMIC_METHOD)
4061                 return;
4062
4063         /* 
4064          * FIXME: 
4065          * Stopping in memset makes half-initialized vtypes visible.
4066          * Stopping in memcpy makes half-copied vtypes visible.
4067          */
4068         if (ji->method->klass == mono_defaults.string_class && (!strcmp (ji->method->name, "memset") || strstr (ji->method->name, "memcpy")))
4069                 return;
4070
4071         /* 
4072          * The ip points to the instruction causing the single step event, convert it
4073          * to the offset stored in seq_points.
4074          */
4075 #ifdef MONO_ARCH_SOFT_DEBUG_SUPPORTED
4076         ip = mono_arch_get_ip_for_single_step (ji, ctx);
4077 #else
4078         g_assert_not_reached ();
4079 #endif
4080
4081         /* 
4082          * mono_debug_lookup_source_location () doesn't work for IL offset 0 for 
4083          * example, so do things by hand.
4084          */
4085         il_offset = compute_il_offset (domain, ji->method, (guint8*)ip - (guint8*)ji->code_start);
4086
4087         if (il_offset == -1)
4088                 return;
4089
4090         if (ss_req->size == STEP_SIZE_LINE) {
4091                 /* Step until a different source line is reached */
4092                 MonoDebugMethodInfo *minfo;
4093
4094                 minfo = mono_debug_lookup_method (ji->method);
4095
4096                 if (minfo) {
4097                         MonoDebugSourceLocation *loc = mono_debug_symfile_lookup_location (minfo, il_offset);
4098
4099                         if (loc && ji->method == ss_req->last_method && loc->row == ss_req->last_line) {
4100                                 mono_debug_free_source_location (loc);
4101                                 return;
4102                         }
4103                         if (!loc)
4104                                 /*
4105                                  * Step until we reach a location with line number info, 
4106                                  * otherwise the client can't show a location.
4107                                  * This can happen for example with statics initialized inline
4108                                  * outside of a cctor.
4109                                  */
4110                                 return;
4111
4112                         if (loc) {
4113                                 ss_req->last_method = ji->method;
4114                                 ss_req->last_line = loc->row;
4115                                 mono_debug_free_source_location (loc);
4116                         }
4117                 }
4118         }
4119
4120         // FIXME: Has to lock earlier
4121
4122         reqs = g_ptr_array_new ();
4123
4124         mono_loader_lock ();
4125
4126         g_ptr_array_add (reqs, ss_req->req);
4127
4128         events = create_event_list (EVENT_KIND_STEP, reqs, ji, NULL, &suspend_policy);
4129
4130         g_ptr_array_free (reqs, TRUE);
4131
4132         mono_loader_unlock ();
4133
4134         process_event (EVENT_KIND_STEP, ji->method, il_offset, ctx, events, suspend_policy);
4135 }
4136
4137 static void
4138 process_single_step (void)
4139 {
4140         DebuggerTlsData *tls;
4141         MonoContext ctx;
4142         static void (*restore_context) (void *);
4143
4144         if (!restore_context)
4145                 restore_context = mono_get_restore_context ();
4146
4147         tls = TlsGetValue (debugger_tls_id);
4148         memcpy (&ctx, &tls->handler_ctx, sizeof (MonoContext));
4149
4150         process_single_step_inner (tls, &ctx);
4151
4152         /* This is called when resuming from a signal handler, so it shouldn't return */
4153         restore_context (&ctx);
4154         g_assert_not_reached ();
4155 }
4156
4157 /*
4158  * mono_debugger_agent_single_step_event:
4159  *
4160  *   Called from a signal handler to handle a single step event.
4161  */
4162 void
4163 mono_debugger_agent_single_step_event (void *sigctx)
4164 {
4165         /* Resume to process_single_step through the signal context */
4166
4167         // FIXME: Since step out/over is implemented using step in, the step in case should
4168         // be as fast as possible. Move the relevant code from process_single_step_inner ()
4169         // here
4170
4171         if (GetCurrentThreadId () == debugger_thread_id) {
4172                 /* 
4173                  * This could happen despite our best effors when the runtime calls 
4174                  * assembly/type resolve hooks.
4175                  * FIXME: Breakpoints too.
4176                  */
4177                 MonoContext ctx;
4178
4179                 mono_arch_sigctx_to_monoctx (sigctx, &ctx);
4180                 mono_arch_skip_single_step (&ctx);
4181                 mono_arch_monoctx_to_sigctx (&ctx, sigctx);
4182                 return;
4183         }
4184
4185         resume_from_signal_handler (sigctx, process_single_step);
4186 }
4187
4188 /*
4189  * start_single_stepping:
4190  *
4191  *   Turn on single stepping. Can be called multiple times, for example,
4192  * by a single step event request + a suspend.
4193  */
4194 static void
4195 start_single_stepping (void)
4196 {
4197 #ifdef MONO_ARCH_SOFT_DEBUG_SUPPORTED
4198         int val = InterlockedIncrement (&ss_count);
4199
4200         if (val == 1)
4201                 mono_arch_start_single_stepping ();
4202
4203         if (ss_req != NULL && ss_invoke_addr == NULL) {
4204                 DebuggerTlsData *tls;
4205         
4206                 mono_loader_lock ();
4207         
4208                 tls = mono_g_hash_table_lookup (thread_to_tls, ss_req->thread);
4209                 ss_invoke_addr = tls->invoke_addr;
4210                 
4211                 mono_loader_unlock ();
4212         }
4213 #else
4214         g_assert_not_reached ();
4215 #endif
4216 }
4217
4218 static void
4219 stop_single_stepping (void)
4220 {
4221 #ifdef MONO_ARCH_SOFT_DEBUG_SUPPORTED
4222         int val = InterlockedDecrement (&ss_count);
4223
4224         if (val == 0)
4225                 mono_arch_stop_single_stepping ();
4226 #else
4227         g_assert_not_reached ();
4228 #endif
4229 }
4230
4231 /*
4232  * ss_stop:
4233  *
4234  *   Stop the single stepping operation given by SS_REQ.
4235  */
4236 static void
4237 ss_stop (SingleStepReq *ss_req)
4238 {
4239         gboolean use_bps = FALSE;
4240
4241         if (ss_req->bps) {
4242                 GSList *l;
4243
4244                 use_bps = TRUE;
4245
4246                 for (l = ss_req->bps; l; l = l->next) {
4247                         clear_breakpoint (l->data);
4248                 }
4249                 g_slist_free (ss_req->bps);
4250                 ss_req->bps = NULL;
4251         }
4252
4253         if (ss_req->global) {
4254                 stop_single_stepping ();
4255                 ss_req->global = FALSE;
4256         }
4257 }
4258
4259 /*
4260  * ss_start:
4261  *
4262  *   Start the single stepping operation given by SS_REQ from the sequence point SP.
4263  */
4264 static void
4265 ss_start (SingleStepReq *ss_req, MonoMethod *method, SeqPoint *sp, MonoSeqPointInfo *info, MonoContext *ctx, DebuggerTlsData *tls, gboolean step_to_catch)
4266 {
4267         int i, frame_index;
4268         SeqPoint *next_sp;
4269         MonoBreakpoint *bp;
4270
4271         /* Stop the previous operation */
4272         ss_stop (ss_req);
4273
4274         /*
4275          * Implement single stepping using breakpoints if possible.
4276          */
4277         if (step_to_catch) {
4278                 bp = set_breakpoint (method, sp->il_offset, ss_req->req, NULL);
4279                 ss_req->bps = g_slist_append (ss_req->bps, bp);
4280         } else if (ss_req->depth == STEP_DEPTH_OVER) {
4281                 frame_index = 1;
4282                 /*
4283                  * Find the first sequence point in the current or in a previous frame which
4284                  * is not the last in its method.
4285                  */
4286                 while (sp && sp->next_len == 0) {
4287                         sp = NULL;
4288                         if (tls && frame_index < tls->frame_count) {
4289                                 StackFrame *frame = tls->frames [frame_index];
4290
4291                                 method = frame->method;
4292                                 if (frame->il_offset != -1) {
4293                                         sp = find_seq_point (frame->domain, frame->method, frame->il_offset, &info);
4294                                 }
4295                                 frame_index ++;
4296                         }
4297                 }
4298
4299                 if (sp && sp->next_len > 0) {
4300                         for (i = 0; i < sp->next_len; ++i) {
4301                                 next_sp = &info->seq_points [sp->next [i]];
4302
4303                                 bp = set_breakpoint (method, next_sp->il_offset, ss_req->req, NULL);
4304                                 ss_req->bps = g_slist_append (ss_req->bps, bp);
4305                         }
4306                 }
4307         }
4308
4309         if (!ss_req->bps) {
4310                 DEBUG (1, fprintf (log_file, "[dbg] Turning on global single stepping.\n"));
4311                 ss_req->global = TRUE;
4312                 start_single_stepping ();
4313         } else {
4314                 ss_req->global = FALSE;
4315         }
4316 }
4317
4318 /*
4319  * Start single stepping of thread THREAD
4320  */
4321 static ErrorCode
4322 ss_create (MonoInternalThread *thread, StepSize size, StepDepth depth, EventRequest *req)
4323 {
4324         DebuggerTlsData *tls;
4325         MonoSeqPointInfo *info = NULL;
4326         SeqPoint *sp = NULL;
4327         MonoMethod *method = NULL;
4328         MonoDebugMethodInfo *minfo;
4329         gboolean step_to_catch = FALSE;
4330
4331         if (suspend_count == 0)
4332                 return ERR_NOT_SUSPENDED;
4333
4334         wait_for_suspend ();
4335
4336         // FIXME: Multiple requests
4337         if (ss_req) {
4338                 DEBUG (0, fprintf (log_file, "Received a single step request while the previous one was still active.\n"));
4339                 return ERR_NOT_IMPLEMENTED;
4340         }
4341
4342         DEBUG (1, fprintf (log_file, "[dbg] Starting single step of thread %p (depth=%s).\n", thread, ss_depth_to_string (depth)));
4343
4344         ss_req = g_new0 (SingleStepReq, 1);
4345         ss_req->req = req;
4346         ss_req->thread = thread;
4347         ss_req->size = size;
4348         ss_req->depth = depth;
4349         req->info = ss_req;
4350
4351         mono_loader_lock ();
4352         tls = mono_g_hash_table_lookup (thread_to_tls, thread);
4353         mono_loader_unlock ();
4354         g_assert (tls);
4355         g_assert (tls->context.valid);
4356         ss_req->start_sp = ss_req->last_sp = MONO_CONTEXT_GET_SP (&tls->context.ctx);
4357
4358         if (tls->has_catch_ctx) {
4359                 gboolean res;
4360                 StackFrameInfo frame;
4361                 MonoContext new_ctx;
4362                 MonoLMF *lmf = NULL;
4363
4364                 /*
4365                  * We are stopped at a throw site. Stepping should go to the catch site.
4366                  */
4367
4368                 /* Find the the jit info for the catch context */
4369                 res = mono_find_jit_info_ext (mono_domain_get (), thread->jit_data, NULL, &tls->catch_ctx, &new_ctx, NULL, &lmf, NULL, &frame);
4370                 g_assert (res);
4371                 g_assert (frame.type == FRAME_TYPE_MANAGED);
4372
4373                 /*
4374                  * Find the seq point corresponding to the landing site ip, which is the first seq
4375                  * point after ip.
4376                  */
4377                 sp = find_next_seq_point_for_native_offset (frame.domain, frame.method, frame.native_offset, &info);
4378                 g_assert (sp);
4379
4380                 method = frame.method;
4381
4382                 step_to_catch = TRUE;
4383                 /* This make sure the seq point is not skipped by process_single_step () */
4384                 ss_req->last_sp = NULL;
4385         }
4386
4387         if (!step_to_catch && ss_req->size == STEP_SIZE_LINE) {
4388                 StackFrame *frame;
4389
4390                 /* Compute the initial line info */
4391                 compute_frame_info (thread, tls);
4392
4393                 g_assert (tls->frame_count);
4394                 frame = tls->frames [0];
4395
4396                 ss_req->last_method = frame->method;
4397                 ss_req->last_line = -1;
4398
4399                 minfo = mono_debug_lookup_method (frame->method);
4400                 if (minfo && frame->il_offset != -1) {
4401                         MonoDebugSourceLocation *loc = mono_debug_symfile_lookup_location (minfo, frame->il_offset);
4402
4403                         if (loc) {
4404                                 ss_req->last_line = loc->row;
4405                                 g_free (loc);
4406                         }
4407                 }
4408         }
4409
4410         if (!step_to_catch && ss_req->depth == STEP_DEPTH_OVER) {
4411                 StackFrame *frame;
4412
4413                 compute_frame_info (thread, tls);
4414
4415                 g_assert (tls->frame_count);
4416                 frame = tls->frames [0];
4417
4418                 if (!method && frame->il_offset != -1) {
4419                         /* FIXME: Sort the table and use a binary search */
4420                         sp = find_prev_seq_point_for_native_offset (frame->domain, frame->method, frame->native_offset, &info);
4421                         g_assert (sp);
4422                         method = frame->method;
4423                 }
4424         }
4425
4426         ss_start (ss_req, method, sp, info, NULL, tls, step_to_catch);
4427
4428         return 0;
4429 }
4430
4431 static void
4432 ss_destroy (SingleStepReq *req)
4433 {
4434         // FIXME: Locking
4435         g_assert (ss_req == req);
4436
4437         ss_stop (ss_req);
4438
4439         g_free (ss_req);
4440         ss_req = NULL;
4441 }
4442
4443 void
4444 mono_debugger_agent_handle_exception (MonoException *exc, MonoContext *throw_ctx, 
4445                                       MonoContext *catch_ctx)
4446 {
4447         int suspend_policy;
4448         GSList *events;
4449         MonoJitInfo *ji;
4450         EventInfo ei;
4451         DebuggerTlsData *tls = NULL;
4452
4453         if (thread_to_tls != NULL) {
4454                 MonoInternalThread *thread = mono_thread_internal_current ();
4455
4456                 mono_loader_lock ();
4457                 tls = mono_g_hash_table_lookup (thread_to_tls, thread);
4458                 mono_loader_unlock ();
4459
4460                 if (tls && tls->abort_requested)
4461                         return;
4462                 if (tls && tls->disable_breakpoints)
4463                         return;
4464         }
4465
4466         memset (&ei, 0, sizeof (EventInfo));
4467
4468         /* Just-In-Time debugging */
4469         if (!catch_ctx) {
4470                 if (agent_config.onuncaught && !inited) {
4471                         finish_agent_init (FALSE);
4472
4473                         /*
4474                          * Send an unsolicited EXCEPTION event with a dummy request id.
4475                          */
4476                         events = g_slist_append (NULL, GUINT_TO_POINTER (0xffffff));
4477                         ei.exc = (MonoObject*)exc;
4478                         process_event (EVENT_KIND_EXCEPTION, &ei, 0, throw_ctx, events, SUSPEND_POLICY_ALL);
4479                         return;
4480                 }
4481         } else if (agent_config.onthrow && !inited) {
4482                 GSList *l;
4483                 gboolean found = FALSE;
4484
4485                 for (l = agent_config.onthrow; l; l = l->next) {
4486                         char *ex_type = l->data;
4487                         char *f = mono_type_full_name (&exc->object.vtable->klass->byval_arg);
4488
4489                         if (!strcmp (ex_type, "") || !strcmp (ex_type, f))
4490                                 found = TRUE;
4491
4492                         g_free (f);
4493                 }
4494
4495                 if (found) {
4496                         finish_agent_init (FALSE);
4497
4498                         /*
4499                          * Send an unsolicited EXCEPTION event with a dummy request id.
4500                          */
4501                         events = g_slist_append (NULL, GUINT_TO_POINTER (0xffffff));
4502                         ei.exc = (MonoObject*)exc;
4503                         process_event (EVENT_KIND_EXCEPTION, &ei, 0, throw_ctx, events, SUSPEND_POLICY_ALL);
4504                         return;
4505                 }
4506         }
4507
4508         if (!inited)
4509                 return;
4510
4511         ji = mini_jit_info_table_find (mono_domain_get (), MONO_CONTEXT_GET_IP (throw_ctx), NULL);
4512
4513         ei.exc = (MonoObject*)exc;
4514         ei.caught = catch_ctx != NULL;
4515
4516         mono_loader_lock ();
4517         events = create_event_list (EVENT_KIND_EXCEPTION, NULL, ji, &ei, &suspend_policy);
4518         mono_loader_unlock ();
4519
4520         if (tls && catch_ctx) {
4521                 tls->catch_ctx = *catch_ctx;
4522                 tls->has_catch_ctx = TRUE;
4523         }
4524
4525         process_event (EVENT_KIND_EXCEPTION, &ei, 0, throw_ctx, events, suspend_policy);
4526
4527         if (tls)
4528                 tls->has_catch_ctx = FALSE;
4529 }
4530
4531 void
4532 mono_debugger_agent_begin_exception_filter (MonoException *exc, MonoContext *ctx, MonoContext *orig_ctx)
4533 {
4534         DebuggerTlsData *tls;
4535
4536         if (!inited)
4537                 return;
4538
4539         tls = TlsGetValue (debugger_tls_id);
4540         if (!tls)
4541                 return;
4542
4543         /*
4544          * We're about to invoke an exception filter during the first pass of exception handling.
4545          *
4546          * 'ctx' is the context that'll get passed to the filter ('call_filter (ctx, ei->data.filter)'),
4547          * 'orig_ctx' is the context where the exception has been thrown.
4548          *
4549          *
4550          * See mcs/class/Mono.Debugger.Soft/Tests/dtest-excfilter.il for an example.
4551          *
4552          * If we're stopped in Filter(), normal stack unwinding would first unwind to
4553          * the call site (line 37) and then continue to Main(), but it would never
4554          * include the throw site (line 32).
4555          *
4556          * Since exception filters are invoked during the first pass of exception handling,
4557          * the stack frames of the throw site are still intact, so we should include them
4558          * in a stack trace.
4559          *
4560          * We do this here by saving the context of the throw site in 'tls->filter_state'.
4561          *
4562          * Exception filters are used by MonoDroid, where we want to stop inside a call filter,
4563          * but report the location of the 'throw' to the user.
4564          *
4565          */
4566
4567         g_assert (mono_thread_state_init_from_monoctx (&tls->filter_state, orig_ctx));
4568 }
4569
4570 void
4571 mono_debugger_agent_end_exception_filter (MonoException *exc, MonoContext *ctx, MonoContext *orig_ctx)
4572 {
4573         DebuggerTlsData *tls;
4574
4575         if (!inited)
4576                 return;
4577
4578         tls = TlsGetValue (debugger_tls_id);
4579         if (!tls)
4580                 return;
4581
4582         tls->filter_state.valid = FALSE;
4583 }
4584
4585 /*
4586  * buffer_add_value_full:
4587  *
4588  *   Add the encoding of the value at ADDR described by T to the buffer.
4589  * AS_VTYPE determines whenever to treat primitive types as primitive types or
4590  * vtypes.
4591  */
4592 static void
4593 buffer_add_value_full (Buffer *buf, MonoType *t, void *addr, MonoDomain *domain,
4594                                            gboolean as_vtype)
4595 {
4596         MonoObject *obj;
4597
4598         if (t->byref) {
4599                 g_assert (*(void**)addr);
4600                 addr = *(void**)addr;
4601         }
4602
4603         if (as_vtype) {
4604                 switch (t->type) {
4605                 case MONO_TYPE_BOOLEAN:
4606                 case MONO_TYPE_I1:
4607                 case MONO_TYPE_U1:
4608                 case MONO_TYPE_CHAR:
4609                 case MONO_TYPE_I2:
4610                 case MONO_TYPE_U2:
4611                 case MONO_TYPE_I4:
4612                 case MONO_TYPE_U4:
4613                 case MONO_TYPE_R4:
4614                 case MONO_TYPE_I8:
4615                 case MONO_TYPE_U8:
4616                 case MONO_TYPE_R8:
4617                 case MONO_TYPE_I:
4618                 case MONO_TYPE_U:
4619                 case MONO_TYPE_PTR:
4620                         goto handle_vtype;
4621                         break;
4622                 default:
4623                         break;
4624                 }
4625         }
4626
4627         switch (t->type) {
4628         case MONO_TYPE_VOID:
4629                 buffer_add_byte (buf, t->type);
4630                 break;
4631         case MONO_TYPE_BOOLEAN:
4632         case MONO_TYPE_I1:
4633         case MONO_TYPE_U1:
4634                 buffer_add_byte (buf, t->type);
4635                 buffer_add_int (buf, *(gint8*)addr);
4636                 break;
4637         case MONO_TYPE_CHAR:
4638         case MONO_TYPE_I2:
4639         case MONO_TYPE_U2:
4640                 buffer_add_byte (buf, t->type);
4641                 buffer_add_int (buf, *(gint16*)addr);
4642                 break;
4643         case MONO_TYPE_I4:
4644         case MONO_TYPE_U4:
4645         case MONO_TYPE_R4:
4646                 buffer_add_byte (buf, t->type);
4647                 buffer_add_int (buf, *(gint32*)addr);
4648                 break;
4649         case MONO_TYPE_I8:
4650         case MONO_TYPE_U8:
4651         case MONO_TYPE_R8:
4652                 buffer_add_byte (buf, t->type);
4653                 buffer_add_long (buf, *(gint64*)addr);
4654                 break;
4655         case MONO_TYPE_I:
4656         case MONO_TYPE_U:
4657                 /* Treat it as a vtype */
4658                 goto handle_vtype;
4659         case MONO_TYPE_PTR: {
4660                 gssize val = *(gssize*)addr;
4661                 
4662                 buffer_add_byte (buf, t->type);
4663                 buffer_add_long (buf, val);
4664                 break;
4665         }
4666         handle_ref:
4667         case MONO_TYPE_STRING:
4668         case MONO_TYPE_SZARRAY:
4669         case MONO_TYPE_OBJECT:
4670         case MONO_TYPE_CLASS:
4671         case MONO_TYPE_ARRAY:
4672                 obj = *(MonoObject**)addr;
4673
4674                 if (!obj) {
4675                         buffer_add_byte (buf, VALUE_TYPE_ID_NULL);
4676                 } else {
4677                         if (obj->vtable->klass->valuetype) {
4678                                 t = &obj->vtable->klass->byval_arg;
4679                                 addr = mono_object_unbox (obj);
4680                                 goto handle_vtype;
4681                         } else if (obj->vtable->klass->rank) {
4682                                 buffer_add_byte (buf, obj->vtable->klass->byval_arg.type);
4683                         } else if (obj->vtable->klass->byval_arg.type == MONO_TYPE_GENERICINST) {
4684                                 buffer_add_byte (buf, MONO_TYPE_CLASS);
4685                         } else {
4686                                 buffer_add_byte (buf, obj->vtable->klass->byval_arg.type);
4687                         }
4688                         buffer_add_objid (buf, obj);
4689                 }
4690                 break;
4691         handle_vtype:
4692         case MONO_TYPE_VALUETYPE: {
4693                 int nfields;
4694                 gpointer iter;
4695                 MonoClassField *f;
4696                 MonoClass *klass = mono_class_from_mono_type (t);
4697
4698                 buffer_add_byte (buf, MONO_TYPE_VALUETYPE);
4699                 buffer_add_byte (buf, klass->enumtype);
4700                 buffer_add_typeid (buf, domain, klass);
4701
4702                 nfields = 0;
4703                 iter = NULL;
4704                 while ((f = mono_class_get_fields (klass, &iter))) {
4705                         if (f->type->attrs & FIELD_ATTRIBUTE_STATIC)
4706                                 continue;
4707                         if (mono_field_is_deleted (f))
4708                                 continue;
4709                         nfields ++;
4710                 }
4711                 buffer_add_int (buf, nfields);
4712
4713                 iter = NULL;
4714                 while ((f = mono_class_get_fields (klass, &iter))) {
4715                         if (f->type->attrs & FIELD_ATTRIBUTE_STATIC)
4716                                 continue;
4717                         if (mono_field_is_deleted (f))
4718                                 continue;
4719                         buffer_add_value_full (buf, f->type, (guint8*)addr + f->offset - sizeof (MonoObject), domain, FALSE);
4720                 }
4721                 break;
4722         }
4723         case MONO_TYPE_GENERICINST:
4724                 if (mono_type_generic_inst_is_valuetype (t)) {
4725                         goto handle_vtype;
4726                 } else {
4727                         goto handle_ref;
4728                 }
4729                 break;
4730         default:
4731                 NOT_IMPLEMENTED;
4732         }
4733 }
4734
4735 static void
4736 buffer_add_value (Buffer *buf, MonoType *t, void *addr, MonoDomain *domain)
4737 {
4738         buffer_add_value_full (buf, t, addr, domain, FALSE);
4739 }
4740
4741 static ErrorCode
4742 decode_value (MonoType *t, MonoDomain *domain, guint8 *addr, guint8 *buf, guint8 **endbuf, guint8 *limit)
4743 {
4744         int err;
4745         int type = decode_byte (buf, &buf, limit);
4746
4747         if (type != t->type && !MONO_TYPE_IS_REFERENCE (t) &&
4748                 !(t->type == MONO_TYPE_I && type == MONO_TYPE_VALUETYPE) &&
4749                 !(t->type == MONO_TYPE_U && type == MONO_TYPE_VALUETYPE) &&
4750                 !(t->type == MONO_TYPE_PTR && type == MONO_TYPE_I8) &&
4751                 !(t->type == MONO_TYPE_GENERICINST && type == MONO_TYPE_VALUETYPE)) {
4752                 char *name = mono_type_full_name (t);
4753                 DEBUG(1, fprintf (log_file, "[%p] Expected value of type %s, got 0x%0x.\n", (gpointer)GetCurrentThreadId (), name, type));
4754                 g_free (name);
4755                 return ERR_INVALID_ARGUMENT;
4756         }
4757
4758         switch (t->type) {
4759         case MONO_TYPE_BOOLEAN:
4760                 *(guint8*)addr = decode_int (buf, &buf, limit);
4761                 break;
4762         case MONO_TYPE_CHAR:
4763                 *(gunichar2*)addr = decode_int (buf, &buf, limit);
4764                 break;
4765         case MONO_TYPE_I1:
4766                 *(gint8*)addr = decode_int (buf, &buf, limit);
4767                 break;
4768         case MONO_TYPE_U1:
4769                 *(guint8*)addr = decode_int (buf, &buf, limit);
4770                 break;
4771         case MONO_TYPE_I2:
4772                 *(gint16*)addr = decode_int (buf, &buf, limit);
4773                 break;
4774         case MONO_TYPE_U2:
4775                 *(guint16*)addr = decode_int (buf, &buf, limit);
4776                 break;
4777         case MONO_TYPE_I4:
4778                 *(gint32*)addr = decode_int (buf, &buf, limit);
4779                 break;
4780         case MONO_TYPE_U4:
4781                 *(guint32*)addr = decode_int (buf, &buf, limit);
4782                 break;
4783         case MONO_TYPE_I8:
4784                 *(gint64*)addr = decode_long (buf, &buf, limit);
4785                 break;
4786         case MONO_TYPE_U8:
4787                 *(guint64*)addr = decode_long (buf, &buf, limit);
4788                 break;
4789         case MONO_TYPE_R4:
4790                 *(guint32*)addr = decode_int (buf, &buf, limit);
4791                 break;
4792         case MONO_TYPE_R8:
4793                 *(guint64*)addr = decode_long (buf, &buf, limit);
4794                 break;
4795         case MONO_TYPE_PTR:
4796                 /* We send these as I8, so we get them back as such */
4797                 g_assert (type == MONO_TYPE_I8);
4798                 *(gssize*)addr = decode_long (buf, &buf, limit);
4799                 break;
4800         case MONO_TYPE_GENERICINST:
4801                 if (MONO_TYPE_ISSTRUCT (t)) {
4802                         /* The client sends these as a valuetype */
4803                         goto handle_vtype;
4804                 } else {
4805                         goto handle_ref;
4806                 }
4807                 break;
4808         case MONO_TYPE_I:
4809         case MONO_TYPE_U:
4810                 /* We send these as vtypes, so we get them back as such */
4811                 g_assert (type == MONO_TYPE_VALUETYPE);
4812                 /* Fall through */
4813                 handle_vtype:
4814         case MONO_TYPE_VALUETYPE: {
4815                 gboolean is_enum = decode_byte (buf, &buf, limit);
4816                 MonoClass *klass;
4817                 MonoClassField *f;
4818                 int nfields;
4819                 gpointer iter = NULL;
4820                 MonoDomain *d;
4821
4822                 /* Enums are sent as a normal vtype */
4823                 if (is_enum)
4824                         return ERR_NOT_IMPLEMENTED;
4825                 klass = decode_typeid (buf, &buf, limit, &d, &err);
4826                 if (err)
4827                         return err;
4828
4829                 if (klass != mono_class_from_mono_type (t))
4830                         return ERR_INVALID_ARGUMENT;
4831
4832                 nfields = decode_int (buf, &buf, limit);
4833                 while ((f = mono_class_get_fields (klass, &iter))) {
4834                         if (f->type->attrs & FIELD_ATTRIBUTE_STATIC)
4835                                 continue;
4836                         if (mono_field_is_deleted (f))
4837                                 continue;
4838                         err = decode_value (f->type, domain, (guint8*)addr + f->offset - sizeof (MonoObject), buf, &buf, limit);
4839                         if (err)
4840                                 return err;
4841                         nfields --;
4842                 }
4843                 g_assert (nfields == 0);
4844                 break;
4845         }
4846         handle_ref:
4847         default:
4848                 if (MONO_TYPE_IS_REFERENCE (t)) {
4849                         if (type == MONO_TYPE_OBJECT) {
4850                                 int objid = decode_objid (buf, &buf, limit);
4851                                 int err;
4852                                 MonoObject *obj;
4853
4854                                 err = get_object (objid, (MonoObject**)&obj);
4855                                 if (err)
4856                                         return err;
4857
4858                                 if (obj && !mono_class_is_assignable_from (mono_class_from_mono_type (t), obj->vtable->klass))
4859                                         return ERR_INVALID_ARGUMENT;
4860                                 if (obj && obj->vtable->domain != domain)
4861                                         return ERR_INVALID_ARGUMENT;
4862
4863                                 mono_gc_wbarrier_generic_store (addr, obj);
4864                         } else if (type == VALUE_TYPE_ID_NULL) {
4865                                 *(MonoObject**)addr = NULL;
4866                         } else {
4867                                 return ERR_INVALID_ARGUMENT;
4868                         }
4869                 } else {
4870                         NOT_IMPLEMENTED;
4871                 }
4872                 break;
4873         }
4874
4875         *endbuf = buf;
4876
4877         return 0;
4878 }
4879
4880 static void
4881 add_var (Buffer *buf, MonoType *t, MonoDebugVarInfo *var, MonoContext *ctx, MonoDomain *domain, gboolean as_vtype)
4882 {
4883         guint32 flags;
4884         int reg;
4885         guint8 *addr;
4886         gpointer reg_val;
4887
4888         flags = var->index & MONO_DEBUG_VAR_ADDRESS_MODE_FLAGS;
4889         reg = var->index & ~MONO_DEBUG_VAR_ADDRESS_MODE_FLAGS;
4890
4891         switch (flags) {
4892         case MONO_DEBUG_VAR_ADDRESS_MODE_REGISTER:
4893                 reg_val = mono_arch_context_get_int_reg (ctx, reg);
4894
4895                 buffer_add_value_full (buf, t, &reg_val, domain, as_vtype);
4896                 break;
4897         case MONO_DEBUG_VAR_ADDRESS_MODE_REGOFFSET:
4898                 addr = mono_arch_context_get_int_reg (ctx, reg);
4899                 addr += (gint32)var->offset;
4900
4901                 //printf ("[R%d+%d] = %p\n", reg, var->offset, addr);
4902
4903                 buffer_add_value_full (buf, t, addr, domain, as_vtype);
4904                 break;
4905         case MONO_DEBUG_VAR_ADDRESS_MODE_DEAD:
4906                 NOT_IMPLEMENTED;
4907                 break;
4908         default:
4909                 g_assert_not_reached ();
4910         }
4911 }
4912
4913 static void
4914 set_var (MonoType *t, MonoDebugVarInfo *var, MonoContext *ctx, MonoDomain *domain, guint8 *val)
4915 {
4916         guint32 flags;
4917         int reg, size;
4918         guint8 *addr;
4919
4920         flags = var->index & MONO_DEBUG_VAR_ADDRESS_MODE_FLAGS;
4921         reg = var->index & ~MONO_DEBUG_VAR_ADDRESS_MODE_FLAGS;
4922
4923         if (MONO_TYPE_IS_REFERENCE (t))
4924                 size = sizeof (gpointer);
4925         else
4926                 size = mono_class_value_size (mono_class_from_mono_type (t), NULL);
4927
4928         switch (flags) {
4929         case MONO_DEBUG_VAR_ADDRESS_MODE_REGISTER:
4930                 // FIXME: Can't set registers, so we disable linears
4931                 NOT_IMPLEMENTED;
4932                 break;
4933         case MONO_DEBUG_VAR_ADDRESS_MODE_REGOFFSET:
4934                 addr = mono_arch_context_get_int_reg (ctx, reg);
4935                 addr += (gint32)var->offset;
4936
4937                 //printf ("[R%d+%d] = %p\n", reg, var->offset, addr);
4938
4939                 // FIXME: Write barriers
4940                 memcpy (addr, val, size);
4941                 break;
4942         case MONO_DEBUG_VAR_ADDRESS_MODE_DEAD:
4943                 NOT_IMPLEMENTED;
4944                 break;
4945         default:
4946                 g_assert_not_reached ();
4947         }
4948 }
4949
4950 static void
4951 clear_event_request (int req_id, int etype)
4952 {
4953         int i;
4954
4955         mono_loader_lock ();
4956         for (i = 0; i < event_requests->len; ++i) {
4957                 EventRequest *req = g_ptr_array_index (event_requests, i);
4958
4959                 if (req->id == req_id && req->event_kind == etype) {
4960                         if (req->event_kind == EVENT_KIND_BREAKPOINT)
4961                                 clear_breakpoint (req->info);
4962                         if (req->event_kind == EVENT_KIND_STEP)
4963                                 ss_destroy (req->info);
4964                         if (req->event_kind == EVENT_KIND_METHOD_ENTRY)
4965                                 clear_breakpoint (req->info);
4966                         if (req->event_kind == EVENT_KIND_METHOD_EXIT)
4967                                 clear_breakpoint (req->info);
4968                         g_ptr_array_remove_index_fast (event_requests, i);
4969                         g_free (req);
4970                         break;
4971                 }
4972         }
4973         mono_loader_unlock ();
4974 }
4975
4976 static gboolean
4977 event_req_matches_assembly (EventRequest *req, MonoAssembly *assembly)
4978 {
4979         if (req->event_kind == EVENT_KIND_BREAKPOINT)
4980                 return breakpoint_matches_assembly (req->info, assembly);
4981         else {
4982                 int i, j;
4983
4984                 for (i = 0; i < req->nmodifiers; ++i) {
4985                         Modifier *m = &req->modifiers [i];
4986
4987                         if (m->kind == MOD_KIND_EXCEPTION_ONLY && m->data.exc_class && m->data.exc_class->image->assembly == assembly)
4988                                 return TRUE;
4989                         if (m->kind == MOD_KIND_ASSEMBLY_ONLY && m->data.assemblies) {
4990                                 for (j = 0; m->data.assemblies [j]; ++j)
4991                                         if (m->data.assemblies [j] == assembly)
4992                                                 return TRUE;
4993                         }
4994                 }
4995         }
4996
4997         return FALSE;
4998 }
4999
5000 /*
5001  * clear_event_requests_for_assembly:
5002  *
5003  *   Clear all events requests which reference ASSEMBLY.
5004  */
5005 static void
5006 clear_event_requests_for_assembly (MonoAssembly *assembly)
5007 {
5008         int i;
5009         gboolean found;
5010
5011         mono_loader_lock ();
5012         found = TRUE;
5013         while (found) {
5014                 found = FALSE;
5015                 for (i = 0; i < event_requests->len; ++i) {
5016                         EventRequest *req = g_ptr_array_index (event_requests, i);
5017
5018                         if (event_req_matches_assembly (req, assembly)) {
5019                                 clear_event_request (req->id, req->event_kind);
5020                                 found = TRUE;
5021                                 break;
5022                         }
5023                 }
5024         }
5025         mono_loader_unlock ();
5026 }
5027
5028 /*
5029  * type_comes_from_assembly:
5030  *
5031  *   GHRFunc that returns TRUE if klass comes from assembly
5032  */
5033 static gboolean
5034 type_comes_from_assembly (gpointer klass, gpointer also_klass, gpointer assembly)
5035 {
5036         return (mono_class_get_image ((MonoClass*)klass) == mono_assembly_get_image ((MonoAssembly*)assembly));
5037 }
5038
5039 /*
5040  * clear_types_for_assembly:
5041  *
5042  *   Clears types from loaded_classes for a given assembly
5043  */
5044 static void
5045 clear_types_for_assembly (MonoAssembly *assembly)
5046 {
5047         MonoDomain *domain = mono_domain_get ();
5048         AgentDomainInfo *info = NULL;
5049
5050         mono_loader_lock ();
5051         info = get_agent_domain_info (domain);
5052         g_hash_table_foreach_remove (info->loaded_classes, type_comes_from_assembly, assembly);
5053         mono_loader_unlock ();
5054 }
5055
5056 static void
5057 add_thread (gpointer key, gpointer value, gpointer user_data)
5058 {
5059         MonoInternalThread *thread = value;
5060         Buffer *buf = user_data;
5061
5062         buffer_add_objid (buf, (MonoObject*)thread);
5063 }
5064
5065 static ErrorCode
5066 do_invoke_method (DebuggerTlsData *tls, Buffer *buf, InvokeData *invoke)
5067 {
5068         guint8 *p = invoke->p;
5069         guint8 *end = invoke->endp;
5070         MonoMethod *m;
5071         int i, err, nargs;
5072         MonoMethodSignature *sig;
5073         guint8 **arg_buf;
5074         void **args;
5075         MonoObject *this, *res, *exc;
5076         MonoDomain *domain;
5077         guint8 *this_buf;
5078 #ifdef MONO_ARCH_SOFT_DEBUG_SUPPORTED
5079         MonoLMFExt ext;
5080 #endif
5081
5082         if (invoke->method) {
5083                 /* 
5084                  * Invoke this method directly, currently only Environment.Exit () is supported.
5085                  */
5086                 this = NULL;
5087                 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>"));
5088                 mono_runtime_invoke (invoke->method, NULL, invoke->args, &exc);
5089                 g_assert_not_reached ();
5090         }
5091
5092         m = decode_methodid (p, &p, end, &domain, &err);
5093         if (err)
5094                 return err;
5095         sig = mono_method_signature (m);
5096
5097         if (m->klass->valuetype)
5098                 this_buf = g_alloca (mono_class_instance_size (m->klass));
5099         else
5100                 this_buf = g_alloca (sizeof (MonoObject*));
5101         if (m->klass->valuetype && (m->flags & METHOD_ATTRIBUTE_STATIC)) {
5102                 /* Should be null */
5103                 int type = decode_byte (p, &p, end);
5104                 if (type != VALUE_TYPE_ID_NULL)
5105                         return ERR_INVALID_ARGUMENT;
5106                 memset (this_buf, 0, mono_class_instance_size (m->klass));
5107         } else {
5108                 err = decode_value (&m->klass->byval_arg, domain, this_buf, p, &p, end);
5109                 if (err)
5110                         return err;
5111         }
5112
5113         if (!m->klass->valuetype)
5114                 this = *(MonoObject**)this_buf;
5115         else
5116                 this = NULL;
5117
5118         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>"));
5119
5120         if (this && this->vtable->domain != domain)
5121                 NOT_IMPLEMENTED;
5122
5123         if (!m->klass->valuetype && !(m->flags & METHOD_ATTRIBUTE_STATIC) && !this) {
5124                 if (!strcmp (m->name, ".ctor")) {
5125                         if (m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT)
5126                                 return ERR_INVALID_ARGUMENT;
5127                         else
5128                                 this = mono_object_new (domain, m->klass);
5129                 } else {
5130                         return ERR_INVALID_ARGUMENT;
5131                 }
5132         }
5133
5134         if (this && !mono_class_is_assignable_from (m->klass, this->vtable->klass))
5135                 return ERR_INVALID_ARGUMENT;
5136
5137         nargs = decode_int (p, &p, end);
5138         if (nargs != sig->param_count)
5139                 return ERR_INVALID_ARGUMENT;
5140         /* Use alloca to get gc tracking */
5141         arg_buf = g_alloca (nargs * sizeof (gpointer));
5142         memset (arg_buf, 0, nargs * sizeof (gpointer));
5143         args = g_alloca (nargs * sizeof (gpointer));
5144         for (i = 0; i < nargs; ++i) {
5145                 if (MONO_TYPE_IS_REFERENCE (sig->params [i])) {
5146                         err = decode_value (sig->params [i], domain, (guint8*)&args [i], p, &p, end);
5147                         if (err)
5148                                 break;
5149
5150                         if (args [i] && ((MonoObject*)args [i])->vtable->domain != domain)
5151                                 NOT_IMPLEMENTED;
5152                 } else {
5153                         arg_buf [i] = g_alloca (mono_class_instance_size (mono_class_from_mono_type (sig->params [i])));
5154                         err = decode_value (sig->params [i], domain, arg_buf [i], p, &p, end);
5155                         if (err)
5156                                 break;
5157                         args [i] = arg_buf [i];
5158                 }
5159         }
5160
5161         if (i < nargs)
5162                 return err;
5163
5164         if (invoke->flags & INVOKE_FLAG_DISABLE_BREAKPOINTS)
5165                 tls->disable_breakpoints = TRUE;
5166         else
5167                 tls->disable_breakpoints = FALSE;
5168
5169         /* 
5170          * Add an LMF frame to link the stack frames on the invoke method with our caller.
5171          */
5172         /* FIXME: Move this to arch specific code */
5173 #ifdef MONO_ARCH_SOFT_DEBUG_SUPPORTED
5174         if (invoke->has_ctx) {
5175                 MonoLMF **lmf_addr;
5176
5177                 lmf_addr = mono_get_lmf_addr ();
5178
5179                 /* Setup our lmf */
5180                 memset (&ext, 0, sizeof (ext));
5181 #ifdef TARGET_AMD64
5182                 ext.lmf.previous_lmf = *(lmf_addr);
5183                 /* Mark that this is a MonoLMFExt */
5184                 ext.lmf.previous_lmf = (gpointer)(((gssize)ext.lmf.previous_lmf) | 2);
5185                 ext.lmf.rsp = (gssize)&ext;
5186 #elif defined(TARGET_X86)
5187                 ext.lmf.previous_lmf = (gsize)*(lmf_addr);
5188                 /* Mark that this is a MonoLMFExt */
5189                 ext.lmf.previous_lmf = (gsize)(gpointer)(((gssize)ext.lmf.previous_lmf) | 2);
5190                 ext.lmf.ebp = (gssize)&ext;
5191 #elif defined(TARGET_ARM)
5192                 ext.lmf.previous_lmf = *(lmf_addr);
5193                 /* Mark that this is a MonoLMFExt */
5194                 ext.lmf.previous_lmf = (gpointer)(((gssize)ext.lmf.previous_lmf) | 2);
5195 #elif defined(TARGET_POWERPC)
5196                 ext.lmf.previous_lmf = *(lmf_addr);
5197                 /* Mark that this is a MonoLMFExt */
5198                 ext.lmf.previous_lmf = (gpointer)(((gssize)ext.lmf.previous_lmf) | 2);
5199                 ext.lmf.ebp = (gssize)&ext;
5200 #else
5201                 g_assert_not_reached ();
5202 #endif
5203
5204                 ext.debugger_invoke = TRUE;
5205                 memcpy (&ext.ctx, &invoke->ctx, sizeof (MonoContext));
5206
5207                 mono_set_lmf ((MonoLMF*)&ext);
5208         }
5209 #endif
5210
5211         if (m->klass->valuetype)
5212                 res = mono_runtime_invoke (m, this_buf, args, &exc);
5213         else
5214                 res = mono_runtime_invoke (m, this, args, &exc);
5215         if (exc) {
5216                 buffer_add_byte (buf, 0);
5217                 buffer_add_value (buf, &mono_defaults.object_class->byval_arg, &exc, domain);
5218         } else {
5219                 buffer_add_byte (buf, 1);
5220                 if (sig->ret->type == MONO_TYPE_VOID) {
5221                         if (!strcmp (m->name, ".ctor") && !m->klass->valuetype) {
5222                                 buffer_add_value (buf, &mono_defaults.object_class->byval_arg, &this, domain);
5223                         }
5224                         else
5225                                 buffer_add_value (buf, &mono_defaults.void_class->byval_arg, NULL, domain);
5226                 } else if (MONO_TYPE_IS_REFERENCE (sig->ret)) {
5227                         buffer_add_value (buf, sig->ret, &res, domain);
5228                 } else if (mono_class_from_mono_type (sig->ret)->valuetype) {
5229                         if (mono_class_is_nullable (mono_class_from_mono_type (sig->ret))) {
5230                                 if (!res)
5231                                         buffer_add_value (buf, &mono_defaults.object_class->byval_arg, &res, domain);
5232                                 else
5233                                         buffer_add_value (buf, sig->ret, mono_object_unbox (res), domain);
5234                         } else {
5235                                 g_assert (res);
5236                                 buffer_add_value (buf, sig->ret, mono_object_unbox (res), domain);
5237                         }
5238                 } else {
5239                         NOT_IMPLEMENTED;
5240                 }
5241         }
5242
5243         tls->disable_breakpoints = FALSE;
5244
5245 #ifdef MONO_ARCH_SOFT_DEBUG_SUPPORTED
5246         if (invoke->has_ctx)
5247                 mono_set_lmf ((gpointer)(((gssize)ext.lmf.previous_lmf) & ~3));
5248 #endif
5249
5250         // FIXME: byref arguments
5251         // FIXME: varargs
5252         return ERR_NONE;
5253 }
5254
5255 /*
5256  * invoke_method:
5257  *
5258  *   Invoke the method given by tls->pending_invoke in the current thread.
5259  */
5260 static void
5261 invoke_method (void)
5262 {
5263         DebuggerTlsData *tls;
5264         InvokeData *invoke;
5265         int id;
5266         int err;
5267         Buffer buf;
5268         static void (*restore_context) (void *);
5269         MonoContext restore_ctx;
5270
5271         if (!restore_context)
5272                 restore_context = mono_get_restore_context ();
5273
5274         tls = TlsGetValue (debugger_tls_id);
5275         g_assert (tls);
5276
5277         /*
5278          * Store the `InvokeData *' in `tls->invoke' until we're done with
5279          * the invocation, so CMD_VM_ABORT_INVOKE can check it.
5280          */
5281
5282         mono_loader_lock ();
5283
5284         invoke = tls->pending_invoke;
5285         g_assert (invoke);
5286         tls->pending_invoke = NULL;
5287
5288         invoke->last_invoke = tls->invoke;
5289         tls->invoke = invoke;
5290
5291         mono_loader_unlock ();
5292
5293         tls->frames_up_to_date = FALSE;
5294
5295         id = invoke->id;
5296
5297         buffer_init (&buf, 128);
5298
5299         err = do_invoke_method (tls, &buf, invoke);
5300
5301         /* Start suspending before sending the reply */
5302         if (!(invoke->flags & INVOKE_FLAG_SINGLE_THREADED))
5303                 suspend_vm ();
5304
5305         send_reply_packet (id, err, &buf);
5306         
5307         buffer_free (&buf);
5308
5309         memcpy (&restore_ctx, &invoke->ctx, sizeof (MonoContext));
5310
5311         if (invoke->has_ctx)
5312                 save_thread_context (&restore_ctx);
5313
5314         if (invoke->flags & INVOKE_FLAG_SINGLE_THREADED) {
5315                 g_assert (tls->resume_count);
5316                 tls->resume_count -= invoke->suspend_count;
5317         }
5318
5319         DEBUG (1, fprintf (log_file, "[%p] Invoke finished, resume_count = %d.\n", (gpointer)GetCurrentThreadId (), tls->resume_count));
5320
5321         /*
5322          * Take the loader lock to avoid race conditions with CMD_VM_ABORT_INVOKE:
5323          *
5324          * It is possible that ves_icall_System_Threading_Thread_Abort () was called
5325          * after the mono_runtime_invoke() already returned, but it doesn't matter
5326          * because we reset the abort here.
5327          */
5328
5329         mono_loader_lock ();
5330
5331         if (tls->abort_requested)
5332                 mono_thread_internal_reset_abort (tls->thread);
5333
5334         tls->invoke = tls->invoke->last_invoke;
5335         tls->abort_requested = FALSE;
5336
5337         mono_loader_unlock ();
5338
5339         g_free (invoke->p);
5340         g_free (invoke);
5341
5342         suspend_current ();
5343 }
5344
5345 static gboolean
5346 is_really_suspended (gpointer key, gpointer value, gpointer user_data)
5347 {
5348         MonoThread *thread = value;
5349         DebuggerTlsData *tls;
5350         gboolean res;
5351
5352         mono_loader_lock ();
5353         tls = mono_g_hash_table_lookup (thread_to_tls, thread);
5354         g_assert (tls);
5355         res = tls->really_suspended;
5356         mono_loader_unlock ();
5357
5358         return res;
5359 }
5360
5361 static ErrorCode
5362 vm_commands (int command, int id, guint8 *p, guint8 *end, Buffer *buf)
5363 {
5364         switch (command) {
5365         case CMD_VM_VERSION: {
5366                 char *build_info, *version;
5367
5368                 build_info = mono_get_runtime_build_info ();
5369                 version = g_strdup_printf ("mono %s", build_info);
5370
5371                 buffer_add_string (buf, version); /* vm version */
5372                 buffer_add_int (buf, MAJOR_VERSION);
5373                 buffer_add_int (buf, MINOR_VERSION);
5374                 g_free (build_info);
5375                 g_free (version);
5376                 break;
5377         }
5378         case CMD_VM_SET_PROTOCOL_VERSION: {
5379                 major_version = decode_int (p, &p, end);
5380                 minor_version = decode_int (p, &p, end);
5381                 protocol_version_set = TRUE;
5382                 DEBUG(1, fprintf (log_file, "[dbg] Protocol version %d.%d, client protocol version %d.%d.\n", MAJOR_VERSION, MINOR_VERSION, major_version, minor_version));
5383                 break;
5384         }
5385         case CMD_VM_ALL_THREADS: {
5386                 // FIXME: Domains
5387                 mono_loader_lock ();
5388                 buffer_add_int (buf, mono_g_hash_table_size (tid_to_thread_obj));
5389                 mono_g_hash_table_foreach (tid_to_thread_obj, add_thread, buf);
5390                 mono_loader_unlock ();
5391                 break;
5392         }
5393         case CMD_VM_SUSPEND:
5394                 suspend_vm ();
5395                 wait_for_suspend ();
5396                 break;
5397         case CMD_VM_RESUME:
5398                 if (suspend_count == 0)
5399                         return ERR_NOT_SUSPENDED;
5400                 resume_vm ();
5401                 break;
5402         case CMD_VM_DISPOSE:
5403                 /* Clear all event requests */
5404                 mono_loader_lock ();
5405                 while (event_requests->len > 0) {
5406                         EventRequest *req = g_ptr_array_index (event_requests, 0);
5407
5408                         clear_event_request (req->id, req->event_kind);
5409                 }
5410                 mono_loader_unlock ();
5411
5412                 while (suspend_count > 0)
5413                         resume_vm ();
5414                 disconnected = TRUE;
5415                 vm_start_event_sent = FALSE;
5416                 break;
5417         case CMD_VM_EXIT: {
5418                 MonoInternalThread *thread;
5419                 DebuggerTlsData *tls;
5420                 MonoClass *env_class;
5421                 MonoMethod *exit_method;
5422                 gpointer *args;
5423                 int exit_code;
5424
5425                 exit_code = decode_int (p, &p, end);
5426
5427                 // FIXME: What if there is a VM_DEATH event request with SUSPEND_ALL ?
5428
5429                 /* Have to send a reply before exiting */
5430                 send_reply_packet (id, 0, buf);
5431
5432                 /* Clear all event requests */
5433                 mono_loader_lock ();
5434                 while (event_requests->len > 0) {
5435                         EventRequest *req = g_ptr_array_index (event_requests, 0);
5436
5437                         clear_event_request (req->id, req->event_kind);
5438                 }
5439                 mono_loader_unlock ();
5440
5441                 /*
5442                  * The JDWP documentation says that the shutdown is not orderly. It doesn't
5443                  * specify whenever a VM_DEATH event is sent. We currently do an orderly
5444                  * shutdown by hijacking a thread to execute Environment.Exit (). This is
5445                  * better than doing the shutdown ourselves, since it avoids various races.
5446                  */
5447
5448                 suspend_vm ();
5449                 wait_for_suspend ();
5450
5451                 env_class = mono_class_from_name (mono_defaults.corlib, "System", "Environment");
5452                 if (env_class)
5453                         exit_method = mono_class_get_method_from_name (env_class, "Exit", 1);
5454
5455                 mono_loader_lock ();
5456                 thread = mono_g_hash_table_find (tid_to_thread, is_really_suspended, NULL);
5457                 mono_loader_unlock ();
5458
5459                 if (thread && exit_method) {
5460                         mono_loader_lock ();
5461                         tls = mono_g_hash_table_lookup (thread_to_tls, thread);
5462                         mono_loader_unlock ();
5463
5464                         args = g_new0 (gpointer, 1);
5465                         args [0] = g_malloc (sizeof (int));
5466                         *(int*)(args [0]) = exit_code;
5467
5468                         tls->pending_invoke = g_new0 (InvokeData, 1);
5469                         tls->pending_invoke->method = exit_method;
5470                         tls->pending_invoke->args = args;
5471
5472                         while (suspend_count > 0)
5473                                 resume_vm ();
5474                 } else {
5475                         /* 
5476                          * No thread found, do it ourselves.
5477                          * FIXME: This can race with normal shutdown etc.
5478                          */
5479                         while (suspend_count > 0)
5480                                 resume_vm ();
5481
5482                         mono_runtime_set_shutting_down ();
5483
5484                         mono_threads_set_shutting_down ();
5485
5486                         /* Suspend all managed threads since the runtime is going away */
5487                         DEBUG(1, fprintf (log_file, "Suspending all threads...\n"));
5488                         mono_thread_suspend_all_other_threads ();
5489                         DEBUG(1, fprintf (log_file, "Shutting down the runtime...\n"));
5490                         mono_runtime_quit ();
5491 #ifdef HOST_WIN32
5492                         shutdown (conn_fd, SD_BOTH);
5493 #else
5494                         shutdown (conn_fd, SHUT_RDWR);
5495 #endif
5496                         DEBUG(1, fprintf (log_file, "Exiting...\n"));
5497
5498                         exit (exit_code);
5499                 }
5500                 break;
5501         }               
5502         case CMD_VM_INVOKE_METHOD: {
5503                 int objid = decode_objid (p, &p, end);
5504                 MonoThread *thread;
5505                 DebuggerTlsData *tls;
5506                 int err, flags;
5507
5508                 err = get_object (objid, (MonoObject**)&thread);
5509                 if (err)
5510                         return err;
5511
5512                 flags = decode_int (p, &p, end);
5513
5514                 // Wait for suspending if it already started
5515                 if (suspend_count)
5516                         wait_for_suspend ();
5517                 if (!is_suspended ())
5518                         return ERR_NOT_SUSPENDED;
5519
5520                 mono_loader_lock ();
5521                 tls = mono_g_hash_table_lookup (thread_to_tls, THREAD_TO_INTERNAL (thread));
5522                 mono_loader_unlock ();
5523                 g_assert (tls);
5524
5525                 if (!tls->really_suspended)
5526                         /* The thread is still running native code, can't do invokes */
5527                         return ERR_NOT_SUSPENDED;
5528
5529                 /* 
5530                  * Store the invoke data into tls, the thread will execute it after it is
5531                  * resumed.
5532                  */
5533                 if (tls->pending_invoke)
5534                         NOT_IMPLEMENTED;
5535                 tls->pending_invoke = g_new0 (InvokeData, 1);
5536                 tls->pending_invoke->id = id;
5537                 tls->pending_invoke->flags = flags;
5538                 tls->pending_invoke->p = g_malloc (end - p);
5539                 memcpy (tls->pending_invoke->p, p, end - p);
5540                 tls->pending_invoke->endp = tls->pending_invoke->p + (end - p);
5541                 tls->pending_invoke->suspend_count = suspend_count;
5542
5543                 if (flags & INVOKE_FLAG_SINGLE_THREADED)
5544                         resume_thread (THREAD_TO_INTERNAL (thread));
5545                 else
5546                         resume_vm ();
5547                 break;
5548         }
5549         case CMD_VM_ABORT_INVOKE: {
5550                 int objid = decode_objid (p, &p, end);
5551                 MonoThread *thread;
5552                 DebuggerTlsData *tls;
5553                 int invoke_id, err;
5554
5555                 err = get_object (objid, (MonoObject**)&thread);
5556                 if (err)
5557                         return err;
5558
5559                 invoke_id = decode_int (p, &p, end);
5560
5561                 mono_loader_lock ();
5562                 tls = mono_g_hash_table_lookup (thread_to_tls, THREAD_TO_INTERNAL (thread));
5563                 g_assert (tls);
5564
5565                 if (tls->abort_requested) {
5566                         mono_loader_unlock ();
5567                         break;
5568                 }
5569
5570                 /*
5571                  * Check whether we're still inside the mono_runtime_invoke() and that it's
5572                  * actually the correct invocation.
5573                  *
5574                  * Careful, we do not stop the thread that's doing the invocation, so we can't
5575                  * inspect its stack.  However, invoke_method() also acquires the loader lock
5576                  * when it's done, so we're safe here.
5577                  *
5578                  */
5579
5580                 if (!tls->invoke || (tls->invoke->id != invoke_id)) {
5581                         mono_loader_unlock ();
5582                         return ERR_NO_INVOCATION;
5583                 }
5584
5585                 tls->abort_requested = TRUE;
5586
5587                 ves_icall_System_Threading_Thread_Abort (THREAD_TO_INTERNAL (thread), NULL);
5588                 mono_loader_unlock ();
5589                 break;
5590         }
5591
5592         default:
5593                 return ERR_NOT_IMPLEMENTED;
5594         }
5595
5596         return ERR_NONE;
5597 }
5598
5599 static ErrorCode
5600 event_commands (int command, guint8 *p, guint8 *end, Buffer *buf)
5601 {
5602         int err;
5603         MonoError error;
5604
5605         switch (command) {
5606         case CMD_EVENT_REQUEST_SET: {
5607                 EventRequest *req;
5608                 int i, event_kind, suspend_policy, nmodifiers, mod;
5609                 MonoMethod *method;
5610                 long location = 0;
5611                 MonoThread *step_thread;
5612                 int size = 0, depth = 0, step_thread_id = 0;
5613                 MonoDomain *domain;
5614
5615                 event_kind = decode_byte (p, &p, end);
5616                 suspend_policy = decode_byte (p, &p, end);
5617                 nmodifiers = decode_byte (p, &p, end);
5618
5619                 req = g_malloc0 (sizeof (EventRequest) + (nmodifiers * sizeof (Modifier)));
5620                 req->id = InterlockedIncrement (&event_request_id);
5621                 req->event_kind = event_kind;
5622                 req->suspend_policy = suspend_policy;
5623                 req->nmodifiers = nmodifiers;
5624
5625                 method = NULL;
5626                 for (i = 0; i < nmodifiers; ++i) {
5627                         mod = decode_byte (p, &p, end);
5628
5629                         req->modifiers [i].kind = mod;
5630                         if (mod == MOD_KIND_COUNT) {
5631                                 req->modifiers [i].data.count = decode_int (p, &p, end);
5632                         } else if (mod == MOD_KIND_LOCATION_ONLY) {
5633                                 method = decode_methodid (p, &p, end, &domain, &err);
5634                                 if (err)
5635                                         return err;
5636                                 location = decode_long (p, &p, end);
5637                         } else if (mod == MOD_KIND_STEP) {
5638                                 step_thread_id = decode_id (p, &p, end);
5639                                 size = decode_int (p, &p, end);
5640                                 depth = decode_int (p, &p, end);
5641                         } else if (mod == MOD_KIND_THREAD_ONLY) {
5642                                 int id = decode_id (p, &p, end);
5643
5644                                 err = get_object (id, (MonoObject**)&req->modifiers [i].data.thread);
5645                                 if (err) {
5646                                         g_free (req);
5647                                         return err;
5648                                 }
5649                         } else if (mod == MOD_KIND_EXCEPTION_ONLY) {
5650                                 MonoClass *exc_class = decode_typeid (p, &p, end, &domain, &err);
5651
5652                                 if (err)
5653                                         return err;
5654                                 req->modifiers [i].caught = decode_byte (p, &p, end);
5655                                 req->modifiers [i].uncaught = decode_byte (p, &p, end);
5656                                 DEBUG(1, fprintf (log_file, "[dbg] \tEXCEPTION_ONLY filter (%s%s%s).\n", exc_class ? exc_class->name : "all", req->modifiers [i].caught ? ", caught" : "", req->modifiers [i].uncaught ? ", uncaught" : ""));
5657                                 if (exc_class) {
5658                                         req->modifiers [i].data.exc_class = exc_class;
5659
5660                                         if (!mono_class_is_assignable_from (mono_defaults.exception_class, exc_class)) {
5661                                                 g_free (req);
5662                                                 return ERR_INVALID_ARGUMENT;
5663                                         }
5664                                 }
5665                         } else if (mod == MOD_KIND_ASSEMBLY_ONLY) {
5666                                 int n = decode_int (p, &p, end);
5667                                 int j;
5668
5669                                 req->modifiers [i].data.assemblies = g_new0 (MonoAssembly*, n);
5670                                 for (j = 0; j < n; ++j) {
5671                                         req->modifiers [i].data.assemblies [j] = decode_assemblyid (p, &p, end, &domain, &err);
5672                                         if (err) {
5673                                                 g_free (req->modifiers [i].data.assemblies);
5674                                                 return err;
5675                                         }
5676                                 }
5677                         } else {
5678                                 g_free (req);
5679                                 return ERR_NOT_IMPLEMENTED;
5680                         }
5681                 }
5682
5683                 if (req->event_kind == EVENT_KIND_BREAKPOINT) {
5684                         g_assert (method);
5685
5686                         req->info = set_breakpoint (method, location, req, &error);
5687                         if (!mono_error_ok (&error)) {
5688                                 g_free (req);
5689                                 DEBUG(1, fprintf (log_file, "[dbg] Failed to set breakpoint: %s\n", mono_error_get_message (&error)));
5690                                 mono_error_cleanup (&error);
5691                                 return ERR_NO_SEQ_POINT_AT_IL_OFFSET;
5692                         }
5693                 } else if (req->event_kind == EVENT_KIND_STEP) {
5694                         g_assert (step_thread_id);
5695
5696                         err = get_object (step_thread_id, (MonoObject**)&step_thread);
5697                         if (err) {
5698                                 g_free (req);
5699                                 return err;
5700                         }
5701
5702                         err = ss_create (THREAD_TO_INTERNAL (step_thread), size, depth, req);
5703                         if (err) {
5704                                 g_free (req);
5705                                 return err;
5706                         }
5707                 } else if (req->event_kind == EVENT_KIND_METHOD_ENTRY) {
5708                         req->info = set_breakpoint (NULL, METHOD_ENTRY_IL_OFFSET, req, NULL);
5709                 } else if (req->event_kind == EVENT_KIND_METHOD_EXIT) {
5710                         req->info = set_breakpoint (NULL, METHOD_EXIT_IL_OFFSET, req, NULL);
5711                 } else if (req->event_kind == EVENT_KIND_EXCEPTION) {
5712                 } else {
5713                         if (req->nmodifiers) {
5714                                 g_free (req);
5715                                 return ERR_NOT_IMPLEMENTED;
5716                         }
5717                 }
5718
5719                 mono_loader_lock ();
5720                 g_ptr_array_add (event_requests, req);
5721                 mono_loader_unlock ();
5722
5723                 buffer_add_int (buf, req->id);
5724                 break;
5725         }
5726         case CMD_EVENT_REQUEST_CLEAR: {
5727                 int etype = decode_byte (p, &p, end);
5728                 int req_id = decode_int (p, &p, end);
5729
5730                 // FIXME: Make a faster mapping from req_id to request
5731                 mono_loader_lock ();
5732                 clear_event_request (req_id, etype);
5733                 mono_loader_unlock ();
5734                 break;
5735         }
5736         case CMD_EVENT_REQUEST_CLEAR_ALL_BREAKPOINTS: {
5737                 int i;
5738
5739                 mono_loader_lock ();
5740                 i = 0;
5741                 while (i < event_requests->len) {
5742                         EventRequest *req = g_ptr_array_index (event_requests, i);
5743
5744                         if (req->event_kind == EVENT_KIND_BREAKPOINT) {
5745                                 clear_breakpoint (req->info);
5746
5747                                 g_ptr_array_remove_index_fast (event_requests, i);
5748                                 g_free (req);
5749                         } else {
5750                                 i ++;
5751                         }
5752                 }
5753                 mono_loader_unlock ();
5754                 break;
5755         }
5756         default:
5757                 return ERR_NOT_IMPLEMENTED;
5758         }
5759
5760         return ERR_NONE;
5761 }
5762
5763 static ErrorCode
5764 domain_commands (int command, guint8 *p, guint8 *end, Buffer *buf)
5765 {
5766         int err;
5767         MonoDomain *domain;
5768
5769         switch (command) {
5770         case CMD_APPDOMAIN_GET_ROOT_DOMAIN: {
5771                 buffer_add_domainid (buf, mono_get_root_domain ());
5772                 break;
5773         }
5774         case CMD_APPDOMAIN_GET_FRIENDLY_NAME: {
5775                 domain = decode_domainid (p, &p, end, NULL, &err);
5776                 if (err)
5777                         return err;
5778                 buffer_add_string (buf, domain->friendly_name);
5779                 break;
5780         }
5781         case CMD_APPDOMAIN_GET_ASSEMBLIES: {
5782                 GSList *tmp;
5783                 MonoAssembly *ass;
5784                 int count;
5785
5786                 domain = decode_domainid (p, &p, end, NULL, &err);
5787                 if (err)
5788                         return err;
5789                 mono_loader_lock ();
5790                 count = 0;
5791                 for (tmp = domain->domain_assemblies; tmp; tmp = tmp->next) {
5792                         count ++;
5793                 }
5794                 buffer_add_int (buf, count);
5795                 for (tmp = domain->domain_assemblies; tmp; tmp = tmp->next) {
5796                         ass = tmp->data;
5797                         buffer_add_assemblyid (buf, domain, ass);
5798                 }
5799                 mono_loader_unlock ();
5800                 break;
5801         }
5802         case CMD_APPDOMAIN_GET_ENTRY_ASSEMBLY: {
5803                 domain = decode_domainid (p, &p, end, NULL, &err);
5804                 if (err)
5805                         return err;
5806
5807                 buffer_add_assemblyid (buf, domain, domain->entry_assembly);
5808                 break;
5809         }
5810         case CMD_APPDOMAIN_GET_CORLIB: {
5811                 domain = decode_domainid (p, &p, end, NULL, &err);
5812                 if (err)
5813                         return err;
5814
5815                 buffer_add_assemblyid (buf, domain, domain->domain->mbr.obj.vtable->klass->image->assembly);
5816                 break;
5817         }
5818         case CMD_APPDOMAIN_CREATE_STRING: {
5819                 char *s;
5820                 MonoString *o;
5821
5822                 domain = decode_domainid (p, &p, end, NULL, &err);
5823                 if (err)
5824                         return err;
5825                 s = decode_string (p, &p, end);
5826
5827                 o = mono_string_new (domain, s);
5828                 buffer_add_objid (buf, (MonoObject*)o);
5829                 break;
5830         }
5831         case CMD_APPDOMAIN_CREATE_BOXED_VALUE: {
5832                 MonoClass *klass;
5833                 MonoDomain *domain2;
5834                 MonoObject *o;
5835
5836                 domain = decode_domainid (p, &p, end, NULL, &err);
5837                 if (err)
5838                         return err;
5839                 klass = decode_typeid (p, &p, end, &domain2, &err);
5840                 if (err)
5841                         return err;
5842
5843                 // FIXME:
5844                 g_assert (domain == domain2);
5845
5846                 o = mono_object_new (domain, klass);
5847
5848                 err = decode_value (&klass->byval_arg, domain, mono_object_unbox (o), p, &p, end);
5849                 if (err)
5850                         return err;
5851
5852                 buffer_add_objid (buf, o);
5853                 break;
5854         }
5855         default:
5856                 return ERR_NOT_IMPLEMENTED;
5857         }
5858
5859         return ERR_NONE;
5860 }
5861
5862 static ErrorCode
5863 assembly_commands (int command, guint8 *p, guint8 *end, Buffer *buf)
5864 {
5865         int err;
5866         MonoAssembly *ass;
5867         MonoDomain *domain;
5868
5869         ass = decode_assemblyid (p, &p, end, &domain, &err);
5870         if (err)
5871                 return err;
5872
5873         switch (command) {
5874         case CMD_ASSEMBLY_GET_LOCATION: {
5875                 buffer_add_string (buf, mono_image_get_filename (ass->image));
5876                 break;                  
5877         }
5878         case CMD_ASSEMBLY_GET_ENTRY_POINT: {
5879                 guint32 token;
5880                 MonoMethod *m;
5881
5882                 if (ass->image->dynamic) {
5883                         buffer_add_id (buf, 0);
5884                 } else {
5885                         token = mono_image_get_entry_point (ass->image);
5886                         if (token == 0) {
5887                                 buffer_add_id (buf, 0);
5888                         } else {
5889                                 m = mono_get_method (ass->image, token, NULL);
5890                                 buffer_add_methodid (buf, domain, m);
5891                         }
5892                 }
5893                 break;                  
5894         }
5895         case CMD_ASSEMBLY_GET_MANIFEST_MODULE: {
5896                 buffer_add_moduleid (buf, domain, ass->image);
5897                 break;
5898         }
5899         case CMD_ASSEMBLY_GET_OBJECT: {
5900                 MonoObject *o = (MonoObject*)mono_assembly_get_object (mono_domain_get (), ass);
5901                 buffer_add_objid (buf, o);
5902                 break;
5903         }
5904         case CMD_ASSEMBLY_GET_TYPE: {
5905                 char *s = decode_string (p, &p, end);
5906                 gboolean ignorecase = decode_byte (p, &p, end);
5907                 MonoTypeNameParse info;
5908                 MonoType *t;
5909                 gboolean type_resolve;
5910
5911                 if (!mono_reflection_parse_type (s, &info)) {
5912                         t = NULL;
5913                 } else {
5914                         if (info.assembly.name)
5915                                 NOT_IMPLEMENTED;
5916                         t = mono_reflection_get_type (ass->image, &info, ignorecase, &type_resolve);
5917                 }
5918                 buffer_add_typeid (buf, domain, t ? mono_class_from_mono_type (t) : NULL);
5919                 mono_reflection_free_type_info (&info);
5920                 g_free (s);
5921
5922                 break;
5923         }
5924         case CMD_ASSEMBLY_GET_NAME: {
5925                 gchar *name;
5926                 MonoAssembly *mass = ass;
5927
5928                 name = g_strdup_printf (
5929                   "%s, Version=%d.%d.%d.%d, Culture=%s, PublicKeyToken=%s%s",
5930                   mass->aname.name,
5931                   mass->aname.major, mass->aname.minor, mass->aname.build, mass->aname.revision,
5932                   mass->aname.culture && *mass->aname.culture? mass->aname.culture: "neutral",
5933                   mass->aname.public_key_token [0] ? (char *)mass->aname.public_key_token : "null",
5934                   (mass->aname.flags & ASSEMBLYREF_RETARGETABLE_FLAG) ? ", Retargetable=Yes" : "");
5935
5936                 buffer_add_string (buf, name);
5937                 g_free (name);
5938                 break;
5939         }
5940         default:
5941                 return ERR_NOT_IMPLEMENTED;
5942         }
5943
5944         return ERR_NONE;
5945 }
5946
5947 static ErrorCode
5948 module_commands (int command, guint8 *p, guint8 *end, Buffer *buf)
5949 {
5950         int err;
5951         MonoDomain *domain;
5952
5953         switch (command) {
5954         case CMD_MODULE_GET_INFO: {
5955                 MonoImage *image = decode_moduleid (p, &p, end, &domain, &err);
5956                 char *basename;
5957
5958                 basename = g_path_get_basename (image->name);
5959                 buffer_add_string (buf, basename); // name
5960                 buffer_add_string (buf, image->module_name); // scopename
5961                 buffer_add_string (buf, image->name); // fqname
5962                 buffer_add_string (buf, mono_image_get_guid (image)); // guid
5963                 buffer_add_assemblyid (buf, domain, image->assembly); // assembly
5964                 g_free (basename);
5965                 break;                  
5966         }
5967         default:
5968                 return ERR_NOT_IMPLEMENTED;
5969         }
5970
5971         return ERR_NONE;
5972 }
5973
5974 static void
5975 buffer_add_cattr_arg (Buffer *buf, MonoType *t, MonoDomain *domain, MonoObject *val)
5976 {
5977         if (val && val->vtable->klass == mono_defaults.monotype_class) {
5978                 /* Special case these so the client doesn't have to handle Type objects */
5979                 
5980                 buffer_add_byte (buf, VALUE_TYPE_ID_TYPE);
5981                 buffer_add_typeid (buf, domain, mono_class_from_mono_type (((MonoReflectionType*)val)->type));
5982         } else if (MONO_TYPE_IS_REFERENCE (t))
5983                 buffer_add_value (buf, t, &val, domain);
5984         else
5985                 buffer_add_value (buf, t, mono_object_unbox (val), domain);
5986 }
5987
5988 static void
5989 buffer_add_cattrs (Buffer *buf, MonoDomain *domain, MonoImage *image, MonoClass *attr_klass, MonoCustomAttrInfo *cinfo)
5990 {
5991         int i, j;
5992         int nattrs = 0;
5993
5994         if (!cinfo) {
5995                 buffer_add_int (buf, 0);
5996                 return;
5997         }
5998
5999         for (i = 0; i < cinfo->num_attrs; ++i) {
6000                 if (!attr_klass || mono_class_has_parent (cinfo->attrs [i].ctor->klass, attr_klass))
6001                         nattrs ++;
6002         }
6003         buffer_add_int (buf, nattrs);
6004
6005         for (i = 0; i < cinfo->num_attrs; ++i) {
6006                 MonoCustomAttrEntry *attr = &cinfo->attrs [i];
6007                 if (!attr_klass || mono_class_has_parent (attr->ctor->klass, attr_klass)) {
6008                         MonoArray *typed_args, *named_args;
6009                         MonoType *t;
6010                         CattrNamedArg *arginfo;
6011
6012                         mono_reflection_create_custom_attr_data_args (image, attr->ctor, attr->data, attr->data_size, &typed_args, &named_args, &arginfo);
6013
6014                         buffer_add_methodid (buf, domain, attr->ctor);
6015
6016                         /* Ctor args */
6017                         if (typed_args) {
6018                                 buffer_add_int (buf, mono_array_length (typed_args));
6019                                 for (j = 0; j < mono_array_length (typed_args); ++j) {
6020                                         MonoObject *val = mono_array_get (typed_args, MonoObject*, j);
6021
6022                                         t = mono_method_signature (attr->ctor)->params [j];
6023
6024                                         buffer_add_cattr_arg (buf, t, domain, val);
6025                                 }
6026                         } else {
6027                                 buffer_add_int (buf, 0);
6028                         }
6029
6030                         /* Named args */
6031                         if (named_args) {
6032                                 buffer_add_int (buf, mono_array_length (named_args));
6033
6034                                 for (j = 0; j < mono_array_length (named_args); ++j) {
6035                                         MonoObject *val = mono_array_get (named_args, MonoObject*, j);
6036
6037                                         if (arginfo [j].prop) {
6038                                                 buffer_add_byte (buf, 0x54);
6039                                                 buffer_add_propertyid (buf, domain, arginfo [j].prop);
6040                                         } else if (arginfo [j].field) {
6041                                                 buffer_add_byte (buf, 0x53);
6042                                         } else {
6043                                                 g_assert_not_reached ();
6044                                         }
6045
6046                                         buffer_add_cattr_arg (buf, arginfo [j].type, domain, val);
6047                                 }
6048                         } else {
6049                                 buffer_add_int (buf, 0);
6050                         }
6051                 }
6052         }
6053 }
6054
6055 static ErrorCode
6056 type_commands_internal (int command, MonoClass *klass, MonoDomain *domain, guint8 *p, guint8 *end, Buffer *buf)
6057 {
6058         MonoClass *nested;
6059         MonoType *type;
6060         gpointer iter;
6061         guint8 b;
6062         int err, nnested;
6063         char *name;
6064
6065         switch (command) {
6066         case CMD_TYPE_GET_INFO: {
6067                 buffer_add_string (buf, klass->name_space);
6068                 buffer_add_string (buf, klass->name);
6069                 // FIXME: byref
6070                 name = mono_type_get_name_full (&klass->byval_arg, MONO_TYPE_NAME_FORMAT_FULL_NAME);
6071                 buffer_add_string (buf, name);
6072                 g_free (name);
6073                 buffer_add_assemblyid (buf, domain, klass->image->assembly);
6074                 buffer_add_moduleid (buf, domain, klass->image);
6075                 buffer_add_typeid (buf, domain, klass->parent);
6076                 if (klass->rank || klass->byval_arg.type == MONO_TYPE_PTR)
6077                         buffer_add_typeid (buf, domain, klass->element_class);
6078                 else
6079                         buffer_add_id (buf, 0);
6080                 buffer_add_int (buf, klass->type_token);
6081                 buffer_add_byte (buf, klass->rank);
6082                 buffer_add_int (buf, klass->flags);
6083                 b = 0;
6084                 type = &klass->byval_arg;
6085                 // FIXME: Can't decide whenever a class represents a byref type
6086                 if (FALSE)
6087                         b |= (1 << 0);
6088                 if (type->type == MONO_TYPE_PTR)
6089                         b |= (1 << 1);
6090                 if (!type->byref && (((type->type >= MONO_TYPE_BOOLEAN) && (type->type <= MONO_TYPE_R8)) || (type->type == MONO_TYPE_I) || (type->type == MONO_TYPE_U)))
6091                         b |= (1 << 2);
6092                 if (type->type == MONO_TYPE_VALUETYPE)
6093                         b |= (1 << 3);
6094                 if (klass->enumtype)
6095                         b |= (1 << 4);
6096                 buffer_add_byte (buf, b);
6097                 nnested = 0;
6098                 iter = NULL;
6099                 while ((nested = mono_class_get_nested_types (klass, &iter)))
6100                         nnested ++;
6101                 buffer_add_int (buf, nnested);
6102                 iter = NULL;
6103                 while ((nested = mono_class_get_nested_types (klass, &iter)))
6104                         buffer_add_typeid (buf, domain, nested);
6105                 break;
6106         }
6107         case CMD_TYPE_GET_METHODS: {
6108                 int nmethods;
6109                 int i = 0;
6110                 gpointer iter = NULL;
6111                 MonoMethod *m;
6112
6113                 mono_class_setup_methods (klass);
6114
6115                 nmethods = mono_class_num_methods (klass);
6116
6117                 buffer_add_int (buf, nmethods);
6118
6119                 while ((m = mono_class_get_methods (klass, &iter))) {
6120                         buffer_add_methodid (buf, domain, m);
6121                         i ++;
6122                 }
6123                 g_assert (i == nmethods);
6124                 break;
6125         }
6126         case CMD_TYPE_GET_FIELDS: {
6127                 int nfields;
6128                 int i = 0;
6129                 gpointer iter = NULL;
6130                 MonoClassField *f;
6131
6132                 nfields = mono_class_num_fields (klass);
6133
6134                 buffer_add_int (buf, nfields);
6135
6136                 while ((f = mono_class_get_fields (klass, &iter))) {
6137                         buffer_add_fieldid (buf, domain, f);
6138                         buffer_add_string (buf, f->name);
6139                         buffer_add_typeid (buf, domain, mono_class_from_mono_type (f->type));
6140                         buffer_add_int (buf, f->type->attrs);
6141                         i ++;
6142                 }
6143                 g_assert (i == nfields);
6144                 break;
6145         }
6146         case CMD_TYPE_GET_PROPERTIES: {
6147                 int nprops;
6148                 int i = 0;
6149                 gpointer iter = NULL;
6150                 MonoProperty *p;
6151
6152                 nprops = mono_class_num_properties (klass);
6153
6154                 buffer_add_int (buf, nprops);
6155
6156                 while ((p = mono_class_get_properties (klass, &iter))) {
6157                         buffer_add_propertyid (buf, domain, p);
6158                         buffer_add_string (buf, p->name);
6159                         buffer_add_methodid (buf, domain, p->get);
6160                         buffer_add_methodid (buf, domain, p->set);
6161                         buffer_add_int (buf, p->attrs);
6162                         i ++;
6163                 }
6164                 g_assert (i == nprops);
6165                 break;
6166         }
6167         case CMD_TYPE_GET_CATTRS: {
6168                 MonoClass *attr_klass = decode_typeid (p, &p, end, NULL, &err);
6169                 MonoCustomAttrInfo *cinfo;
6170
6171                 cinfo = mono_custom_attrs_from_class (klass);
6172
6173                 buffer_add_cattrs (buf, domain, klass->image, attr_klass, cinfo);
6174                 break;
6175         }
6176         case CMD_TYPE_GET_FIELD_CATTRS: {
6177                 MonoClass *attr_klass;
6178                 MonoCustomAttrInfo *cinfo;
6179                 MonoClassField *field;
6180
6181                 field = decode_fieldid (p, &p, end, NULL, &err);
6182                 if (err)
6183                         return err;
6184                 attr_klass = decode_typeid (p, &p, end, NULL, &err);
6185                 if (err)
6186                         return err;
6187
6188                 cinfo = mono_custom_attrs_from_field (klass, field);
6189
6190                 buffer_add_cattrs (buf, domain, klass->image, attr_klass, cinfo);
6191                 break;
6192         }
6193         case CMD_TYPE_GET_PROPERTY_CATTRS: {
6194                 MonoClass *attr_klass;
6195                 MonoCustomAttrInfo *cinfo;
6196                 MonoProperty *prop;
6197
6198                 prop = decode_propertyid (p, &p, end, NULL, &err);
6199                 if (err)
6200                         return err;
6201                 attr_klass = decode_typeid (p, &p, end, NULL, &err);
6202                 if (err)
6203                         return err;
6204
6205                 cinfo = mono_custom_attrs_from_property (klass, prop);
6206
6207                 buffer_add_cattrs (buf, domain, klass->image, attr_klass, cinfo);
6208                 break;
6209         }
6210         case CMD_TYPE_GET_VALUES:
6211         case CMD_TYPE_GET_VALUES_2: {
6212                 guint8 *val;
6213                 MonoClassField *f;
6214                 MonoVTable *vtable;
6215                 MonoClass *k;
6216                 int len, i;
6217                 gboolean found;
6218                 MonoThread *thread_obj;
6219                 MonoInternalThread *thread = NULL;
6220                 guint32 special_static_type;
6221
6222                 if (command == CMD_TYPE_GET_VALUES_2) {
6223                         int objid = decode_objid (p, &p, end);
6224                         int err;
6225
6226                         err = get_object (objid, (MonoObject**)&thread_obj);
6227                         if (err)
6228                                 return err;
6229
6230                         thread = THREAD_TO_INTERNAL (thread_obj);
6231                 }
6232
6233                 len = decode_int (p, &p, end);
6234                 for (i = 0; i < len; ++i) {
6235                         f = decode_fieldid (p, &p, end, NULL, &err);
6236                         if (err)
6237                                 return err;
6238
6239                         if (!(f->type->attrs & FIELD_ATTRIBUTE_STATIC))
6240                                 return ERR_INVALID_FIELDID;
6241                         special_static_type = mono_class_field_get_special_static_type (f);
6242                         if (special_static_type != SPECIAL_STATIC_NONE) {
6243                                 if (!(thread && special_static_type == SPECIAL_STATIC_THREAD))
6244                                         return ERR_INVALID_FIELDID;
6245                         }
6246
6247                         /* Check that the field belongs to the object */
6248                         found = FALSE;
6249                         for (k = klass; k; k = k->parent) {
6250                                 if (k == f->parent) {
6251                                         found = TRUE;
6252                                         break;
6253                                 }
6254                         }
6255                         if (!found)
6256                                 return ERR_INVALID_FIELDID;
6257
6258                         vtable = mono_class_vtable (domain, f->parent);
6259                         val = g_malloc (mono_class_instance_size (mono_class_from_mono_type (f->type)));
6260                         mono_field_static_get_value_for_thread (thread ? thread : mono_thread_internal_current (), vtable, f, val);
6261                         buffer_add_value (buf, f->type, val, domain);
6262                         g_free (val);
6263                 }
6264                 break;
6265         }
6266         case CMD_TYPE_SET_VALUES: {
6267                 guint8 *val;
6268                 MonoClassField *f;
6269                 MonoVTable *vtable;
6270                 MonoClass *k;
6271                 int len, i;
6272                 gboolean found;
6273
6274                 len = decode_int (p, &p, end);
6275                 for (i = 0; i < len; ++i) {
6276                         f = decode_fieldid (p, &p, end, NULL, &err);
6277                         if (err)
6278                                 return err;
6279
6280                         if (!(f->type->attrs & FIELD_ATTRIBUTE_STATIC))
6281                                 return ERR_INVALID_FIELDID;
6282                         if (mono_class_field_is_special_static (f))
6283                                 return ERR_INVALID_FIELDID;
6284
6285                         /* Check that the field belongs to the object */
6286                         found = FALSE;
6287                         for (k = klass; k; k = k->parent) {
6288                                 if (k == f->parent) {
6289                                         found = TRUE;
6290                                         break;
6291                                 }
6292                         }
6293                         if (!found)
6294                                 return ERR_INVALID_FIELDID;
6295
6296                         // FIXME: Check for literal/const
6297
6298                         vtable = mono_class_vtable (domain, f->parent);
6299                         val = g_malloc (mono_class_instance_size (mono_class_from_mono_type (f->type)));
6300                         err = decode_value (f->type, domain, val, p, &p, end);
6301                         if (err) {
6302                                 g_free (val);
6303                                 return err;
6304                         }
6305                         if (MONO_TYPE_IS_REFERENCE (f->type))
6306                                 mono_field_static_set_value (vtable, f, *(gpointer*)val);
6307                         else
6308                                 mono_field_static_set_value (vtable, f, val);
6309                         g_free (val);
6310                 }
6311                 break;
6312         }
6313         case CMD_TYPE_GET_OBJECT: {
6314                 MonoObject *o = (MonoObject*)mono_type_get_object (mono_domain_get (), &klass->byval_arg);
6315                 buffer_add_objid (buf, o);
6316                 break;
6317         }
6318         case CMD_TYPE_GET_SOURCE_FILES:
6319         case CMD_TYPE_GET_SOURCE_FILES_2: {
6320                 gpointer iter = NULL;
6321                 MonoMethod *method;
6322                 char *source_file, *base;
6323                 GPtrArray *files;
6324                 int i;
6325
6326                 files = g_ptr_array_new ();
6327
6328                 while ((method = mono_class_get_methods (klass, &iter))) {
6329                         MonoDebugMethodInfo *minfo = mono_debug_lookup_method (method);
6330
6331                         if (minfo) {
6332                                 mono_debug_symfile_get_line_numbers (minfo, &source_file, NULL, NULL, NULL);
6333                                 if (!source_file)
6334                                         continue;
6335
6336                                 for (i = 0; i < files->len; ++i)
6337                                         if (!strcmp (g_ptr_array_index (files, i), source_file))
6338                                                 break;
6339                                 if (i == files->len)
6340                                         g_ptr_array_add (files, g_strdup (source_file));
6341                                 g_free (source_file);
6342                         }
6343                 }
6344
6345                 buffer_add_int (buf, files->len);
6346                 for (i = 0; i < files->len; ++i) {
6347                         source_file = g_ptr_array_index (files, i);
6348                         if (command == CMD_TYPE_GET_SOURCE_FILES_2) {
6349                                 buffer_add_string (buf, source_file);
6350                         } else {
6351                                 base = g_path_get_basename (source_file);
6352                                 buffer_add_string (buf, base);
6353                                 g_free (base);
6354                         }
6355                         g_free (source_file);
6356                 }
6357                 g_ptr_array_free (files, TRUE);
6358                 break;
6359         }
6360         case CMD_TYPE_IS_ASSIGNABLE_FROM: {
6361                 MonoClass *oklass = decode_typeid (p, &p, end, NULL, &err);
6362
6363                 if (err)
6364                         return err;
6365                 if (mono_class_is_assignable_from (klass, oklass))
6366                         buffer_add_byte (buf, 1);
6367                 else
6368                         buffer_add_byte (buf, 0);
6369                 break;
6370         }
6371         default:
6372                 return ERR_NOT_IMPLEMENTED;
6373         }
6374
6375         return ERR_NONE;
6376 }
6377
6378 static ErrorCode
6379 type_commands (int command, guint8 *p, guint8 *end, Buffer *buf)
6380 {
6381         MonoClass *klass;
6382         MonoDomain *old_domain;
6383         MonoDomain *domain;
6384         int err;
6385
6386         klass = decode_typeid (p, &p, end, &domain, &err);
6387         if (err)
6388                 return err;
6389
6390         old_domain = mono_domain_get ();
6391
6392         mono_domain_set (domain, TRUE);
6393
6394         err = type_commands_internal (command, klass, domain, p, end, buf);
6395
6396         mono_domain_set (old_domain, TRUE);
6397
6398         return err;
6399 }
6400
6401 static ErrorCode
6402 method_commands_internal (int command, MonoMethod *method, MonoDomain *domain, guint8 *p, guint8 *end, Buffer *buf)
6403 {
6404         MonoMethodHeader *header;
6405
6406         switch (command) {
6407         case CMD_METHOD_GET_NAME: {
6408                 buffer_add_string (buf, method->name);
6409                 break;                  
6410         }
6411         case CMD_METHOD_GET_DECLARING_TYPE: {
6412                 buffer_add_typeid (buf, domain, method->klass);
6413                 break;
6414         }
6415         case CMD_METHOD_GET_DEBUG_INFO: {
6416                 MonoDebugMethodInfo *minfo;
6417                 char *source_file;
6418                 int i, n_il_offsets;
6419                 int *il_offsets;
6420                 int *line_numbers;
6421
6422                 header = mono_method_get_header (method);
6423                 if (!header) {
6424                         buffer_add_int (buf, 0);
6425                         buffer_add_string (buf, "");
6426                         buffer_add_int (buf, 0);
6427                         break;
6428                 }
6429
6430                 minfo = mono_debug_lookup_method (method);
6431                 if (!minfo) {
6432                         buffer_add_int (buf, header->code_size);
6433                         buffer_add_string (buf, "");
6434                         buffer_add_int (buf, 0);
6435                         mono_metadata_free_mh (header);
6436                         break;
6437                 }
6438
6439                 mono_debug_symfile_get_line_numbers (minfo, &source_file, &n_il_offsets, &il_offsets, &line_numbers);
6440                 buffer_add_int (buf, header->code_size);
6441                 buffer_add_string (buf, source_file);
6442                 buffer_add_int (buf, n_il_offsets);
6443                 //printf ("Line number table for method %s:\n", mono_method_full_name (method,  TRUE));
6444                 for (i = 0; i < n_il_offsets; ++i) {
6445                         //printf ("IL%d -> %d\n", il_offsets [i], line_numbers [i]);
6446                         buffer_add_int (buf, il_offsets [i]);
6447                         buffer_add_int (buf, line_numbers [i]);
6448                 }
6449                 g_free (source_file);
6450                 g_free (il_offsets);
6451                 g_free (line_numbers);
6452                 mono_metadata_free_mh (header);
6453                 break;
6454         }
6455         case CMD_METHOD_GET_PARAM_INFO: {
6456                 MonoMethodSignature *sig = mono_method_signature (method);
6457                 guint32 i;
6458                 char **names;
6459
6460                 /* FIXME: mono_class_from_mono_type () and byrefs */
6461
6462                 /* FIXME: Use a smaller encoding */
6463                 buffer_add_int (buf, sig->call_convention);
6464                 buffer_add_int (buf, sig->param_count);
6465                 buffer_add_int (buf, sig->generic_param_count);
6466                 buffer_add_typeid (buf, domain, mono_class_from_mono_type (sig->ret));
6467                 for (i = 0; i < sig->param_count; ++i) {
6468                         /* FIXME: vararg */
6469                         buffer_add_typeid (buf, domain, mono_class_from_mono_type (sig->params [i]));
6470                 }
6471
6472                 /* Emit parameter names */
6473                 names = g_new (char *, sig->param_count);
6474                 mono_method_get_param_names (method, (const char **) names);
6475                 for (i = 0; i < sig->param_count; ++i)
6476                         buffer_add_string (buf, names [i]);
6477                 g_free (names);
6478
6479                 break;
6480         }
6481         case CMD_METHOD_GET_LOCALS_INFO: {
6482                 int i, j, num_locals;
6483                 MonoDebugLocalsInfo *locals;
6484
6485                 header = mono_method_get_header (method);
6486                 g_assert (header);
6487
6488                 buffer_add_int (buf, header->num_locals);
6489
6490                 /* Types */
6491                 for (i = 0; i < header->num_locals; ++i)
6492                         buffer_add_typeid (buf, domain, mono_class_from_mono_type (header->locals [i]));
6493
6494                 /* Names */
6495                 locals = mono_debug_lookup_locals (method);
6496                 if (locals)
6497                         num_locals = locals->num_locals;
6498                 else
6499                         num_locals = 0;
6500                 for (i = 0; i < header->num_locals; ++i) {
6501                         for (j = 0; j < num_locals; ++j)
6502                                 if (locals->locals [j].index == i)
6503                                         break;
6504                         if (j < num_locals)
6505                                 buffer_add_string (buf, locals->locals [j].name);
6506                         else
6507                                 buffer_add_string (buf, "");
6508                 }
6509
6510                 /* Scopes */
6511                 for (i = 0; i < header->num_locals; ++i) {
6512                         for (j = 0; j < num_locals; ++j)
6513                                 if (locals->locals [j].index == i)
6514                                         break;
6515                         if (j < num_locals && locals->locals [j].block) {
6516                                 buffer_add_int (buf, locals->locals [j].block->start_offset);
6517                                 buffer_add_int (buf, locals->locals [j].block->end_offset);
6518                         } else {
6519                                 buffer_add_int (buf, 0);
6520                                 buffer_add_int (buf, header->code_size);
6521                         }
6522                 }
6523                 mono_metadata_free_mh (header);
6524
6525                 if (locals)
6526                         mono_debug_symfile_free_locals (locals);
6527
6528                 break;
6529         }
6530         case CMD_METHOD_GET_INFO:
6531                 buffer_add_int (buf, method->flags);
6532                 buffer_add_int (buf, method->iflags);
6533                 buffer_add_int (buf, method->token);
6534                 break;
6535         case CMD_METHOD_GET_BODY: {
6536                 int i;
6537
6538                 header = mono_method_get_header (method);
6539                 if (!header) {
6540                         buffer_add_int (buf, 0);
6541                 } else {
6542                         buffer_add_int (buf, header->code_size);
6543                         for (i = 0; i < header->code_size; ++i)
6544                                 buffer_add_byte (buf, header->code [i]);
6545                 }
6546                 mono_metadata_free_mh (header);
6547                 break;
6548         }
6549         case CMD_METHOD_RESOLVE_TOKEN: {
6550                 guint32 token = decode_int (p, &p, end);
6551
6552                 // FIXME: Generics
6553                 switch (mono_metadata_token_code (token)) {
6554                 case MONO_TOKEN_STRING: {
6555                         MonoString *s;
6556                         char *s2;
6557
6558                         s = mono_ldstr (domain, method->klass->image, mono_metadata_token_index (token));
6559                         g_assert (s);
6560
6561                         s2 = mono_string_to_utf8 (s);
6562
6563                         buffer_add_byte (buf, TOKEN_TYPE_STRING);
6564                         buffer_add_string (buf, s2);
6565                         g_free (s2);
6566                         break;
6567                 }
6568                 default: {
6569                         gpointer val;
6570                         MonoClass *handle_class;
6571
6572                         if (method->wrapper_type == MONO_WRAPPER_DYNAMIC_METHOD) {
6573                                 val = mono_method_get_wrapper_data (method, token);
6574                                 handle_class = mono_method_get_wrapper_data (method, token + 1);
6575
6576                                 if (handle_class == NULL) {
6577                                         // Can't figure out the token type
6578                                         buffer_add_byte (buf, TOKEN_TYPE_UNKNOWN);
6579                                         break;
6580                                 }
6581                         } else {
6582                                 val = mono_ldtoken (method->klass->image, token, &handle_class, NULL);
6583                                 g_assert (val);
6584                         }
6585
6586                         if (handle_class == mono_defaults.typehandle_class) {
6587                                 buffer_add_byte (buf, TOKEN_TYPE_TYPE);
6588                                 if (method->wrapper_type == MONO_WRAPPER_DYNAMIC_METHOD)
6589                                         buffer_add_typeid (buf, domain, (MonoClass *) val);
6590                                 else
6591                                         buffer_add_typeid (buf, domain, mono_class_from_mono_type ((MonoType*)val));
6592                         } else if (handle_class == mono_defaults.fieldhandle_class) {
6593                                 buffer_add_byte (buf, TOKEN_TYPE_FIELD);
6594                                 buffer_add_fieldid (buf, domain, val);
6595                         } else if (handle_class == mono_defaults.methodhandle_class) {
6596                                 buffer_add_byte (buf, TOKEN_TYPE_METHOD);
6597                                 buffer_add_methodid (buf, domain, val);
6598                         } else if (handle_class == mono_defaults.string_class) {
6599                                 char *s;
6600
6601                                 s = mono_string_to_utf8 (val);
6602                                 buffer_add_byte (buf, TOKEN_TYPE_STRING);
6603                                 buffer_add_string (buf, s);
6604                                 g_free (s);
6605                         } else {
6606                                 g_assert_not_reached ();
6607                         }
6608                         break;
6609                 }
6610                 }
6611                 break;
6612         }
6613         default:
6614                 return ERR_NOT_IMPLEMENTED;
6615         }
6616
6617         return ERR_NONE;
6618 }
6619
6620 static ErrorCode
6621 method_commands (int command, guint8 *p, guint8 *end, Buffer *buf)
6622 {
6623         int err;
6624         MonoDomain *old_domain;
6625         MonoDomain *domain;
6626         MonoMethod *method;
6627
6628         method = decode_methodid (p, &p, end, &domain, &err);
6629         if (err)
6630                 return err;
6631
6632         old_domain = mono_domain_get ();
6633
6634         mono_domain_set (domain, TRUE);
6635
6636         err = method_commands_internal (command, method, domain, p, end, buf);
6637
6638         mono_domain_set (old_domain, TRUE);
6639
6640         return err;
6641 }
6642
6643 static ErrorCode
6644 thread_commands (int command, guint8 *p, guint8 *end, Buffer *buf)
6645 {
6646         int objid = decode_objid (p, &p, end);
6647         int err;
6648         MonoThread *thread_obj;
6649         MonoInternalThread *thread;
6650
6651         err = get_object (objid, (MonoObject**)&thread_obj);
6652         if (err)
6653                 return err;
6654
6655         thread = THREAD_TO_INTERNAL (thread_obj);
6656            
6657         switch (command) {
6658         case CMD_THREAD_GET_NAME: {
6659                 guint32 name_len;
6660                 gunichar2 *s = mono_thread_get_name (thread, &name_len);
6661
6662                 if (!s) {
6663                         buffer_add_int (buf, 0);
6664                 } else {
6665                         char *name;
6666                         glong len;
6667
6668                         name = g_utf16_to_utf8 (s, name_len, NULL, &len, NULL);
6669                         g_assert (name);
6670                         buffer_add_int (buf, len);
6671                         buffer_add_data (buf, (guint8*)name, len);
6672                         g_free (s);
6673                 }
6674                 break;
6675         }
6676         case CMD_THREAD_GET_FRAME_INFO: {
6677                 DebuggerTlsData *tls;
6678                 int i, start_frame, length;
6679
6680                 // Wait for suspending if it already started
6681                 if (suspend_count)
6682                         wait_for_suspend ();
6683                 if (!is_suspended ())
6684                         return ERR_NOT_SUSPENDED;
6685
6686                 start_frame = decode_int (p, &p, end);
6687                 length = decode_int (p, &p, end);
6688
6689                 if (start_frame != 0 || length != -1)
6690                         return ERR_NOT_IMPLEMENTED;
6691
6692                 mono_loader_lock ();
6693                 tls = mono_g_hash_table_lookup (thread_to_tls, thread);
6694                 mono_loader_unlock ();
6695                 g_assert (tls);
6696
6697                 compute_frame_info (thread, tls);
6698
6699                 buffer_add_int (buf, tls->frame_count);
6700                 for (i = 0; i < tls->frame_count; ++i) {
6701                         buffer_add_int (buf, tls->frames [i]->id);
6702                         buffer_add_methodid (buf, tls->frames [i]->domain, tls->frames [i]->actual_method);
6703                         buffer_add_int (buf, tls->frames [i]->il_offset);
6704                         /*
6705                          * Instead of passing the frame type directly to the client, we associate
6706                          * it with the previous frame using a set of flags. This avoids lots of
6707                          * conditional code in the client, since a frame whose type isn't 
6708                          * FRAME_TYPE_MANAGED has no method, location, etc.
6709                          */
6710                         buffer_add_byte (buf, tls->frames [i]->flags);
6711                 }
6712
6713                 break;
6714         }
6715         case CMD_THREAD_GET_STATE:
6716                 buffer_add_int (buf, thread->state);
6717                 break;
6718         case CMD_THREAD_GET_INFO:
6719                 buffer_add_byte (buf, thread->threadpool_thread);
6720                 break;
6721         case CMD_THREAD_GET_ID:
6722                 buffer_add_long (buf, (guint64)(gsize)thread);
6723                 break;
6724         case CMD_THREAD_GET_TID:
6725                 buffer_add_long (buf, (guint64)thread->tid);
6726                 break;
6727         default:
6728                 return ERR_NOT_IMPLEMENTED;
6729         }
6730
6731         return ERR_NONE;
6732 }
6733
6734 static ErrorCode
6735 frame_commands (int command, guint8 *p, guint8 *end, Buffer *buf)
6736 {
6737         int objid;
6738         int err;
6739         MonoThread *thread_obj;
6740         MonoInternalThread *thread;
6741         int pos, i, len;
6742         DebuggerTlsData *tls;
6743         StackFrame *frame;
6744         MonoDebugMethodJitInfo *jit;
6745         MonoDebugVarInfo *var;
6746         MonoMethodSignature *sig;
6747         gssize id;
6748         MonoMethodHeader *header;
6749
6750         objid = decode_objid (p, &p, end);
6751         err = get_object (objid, (MonoObject**)&thread_obj);
6752         if (err)
6753                 return err;
6754
6755         thread = THREAD_TO_INTERNAL (thread_obj);
6756
6757         id = decode_id (p, &p, end);
6758
6759         mono_loader_lock ();
6760         tls = mono_g_hash_table_lookup (thread_to_tls, thread);
6761         mono_loader_unlock ();
6762         g_assert (tls);
6763
6764         for (i = 0; i < tls->frame_count; ++i) {
6765                 if (tls->frames [i]->id == id)
6766                         break;
6767         }
6768         if (i == tls->frame_count)
6769                 return ERR_INVALID_FRAMEID;
6770
6771         frame = tls->frames [i];
6772
6773         if (!frame->has_ctx)
6774                 // FIXME:
6775                 return ERR_INVALID_FRAMEID;
6776
6777         if (!frame->jit) {
6778                 frame->jit = mono_debug_find_method (frame->method, frame->domain);
6779                 if (!frame->jit)
6780                         /* This could happen for aot images with no jit debug info */
6781                         return ERR_ABSENT_INFORMATION;
6782         }
6783         jit = frame->jit;
6784
6785         sig = mono_method_signature (frame->actual_method);
6786
6787         switch (command) {
6788         case CMD_STACK_FRAME_GET_VALUES: {
6789                 len = decode_int (p, &p, end);
6790                 header = mono_method_get_header (frame->actual_method);
6791
6792                 for (i = 0; i < len; ++i) {
6793                         pos = decode_int (p, &p, end);
6794
6795                         if (pos < 0) {
6796                                 pos = - pos - 1;
6797
6798                                 g_assert (pos >= 0 && pos < jit->num_params);
6799
6800                                 var = &jit->params [pos];
6801
6802                                 add_var (buf, sig->params [pos], &jit->params [pos], &frame->ctx, frame->domain, FALSE);
6803                         } else {
6804                                 g_assert (pos >= 0 && pos < jit->num_locals);
6805
6806                                 var = &jit->locals [pos];
6807                                 
6808                                 add_var (buf, header->locals [pos], &jit->locals [pos], &frame->ctx, frame->domain, FALSE);
6809                         }
6810                 }
6811                 mono_metadata_free_mh (header);
6812                 break;
6813         }
6814         case CMD_STACK_FRAME_GET_THIS: {
6815                 if (frame->method->klass->valuetype) {
6816                         if (!sig->hasthis) {
6817                                 MonoObject *p = NULL;
6818                                 buffer_add_value (buf, &mono_defaults.object_class->byval_arg, &p, frame->domain);
6819                         } else {
6820                                 add_var (buf, &frame->actual_method->klass->this_arg, jit->this_var, &frame->ctx, frame->domain, TRUE);
6821                         }
6822                 } else {
6823                         if (!sig->hasthis) {
6824                                 MonoObject *p = NULL;
6825                                 buffer_add_value (buf, &frame->actual_method->klass->byval_arg, &p, frame->domain);
6826                         } else {
6827                                 add_var (buf, &frame->method->klass->byval_arg, jit->this_var, &frame->ctx, frame->domain, TRUE);
6828                         }
6829                 }
6830                 break;
6831         }
6832         case CMD_STACK_FRAME_SET_VALUES: {
6833                 guint8 *val_buf;
6834                 MonoType *t;
6835                 MonoDebugVarInfo *var;
6836
6837                 len = decode_int (p, &p, end);
6838                 header = mono_method_get_header (frame->actual_method);
6839
6840                 for (i = 0; i < len; ++i) {
6841                         pos = decode_int (p, &p, end);
6842
6843                         if (pos < 0) {
6844                                 pos = - pos - 1;
6845
6846                                 g_assert (pos >= 0 && pos < jit->num_params);
6847
6848                                 t = sig->params [pos];
6849                                 var = &jit->params [pos];
6850                         } else {
6851                                 g_assert (pos >= 0 && pos < jit->num_locals);
6852
6853                                 t = header->locals [pos];
6854                                 var = &jit->locals [pos];
6855                         }
6856
6857                         if (MONO_TYPE_IS_REFERENCE (t))
6858                                 val_buf = g_alloca (sizeof (MonoObject*));
6859                         else
6860                                 val_buf = g_alloca (mono_class_instance_size (mono_class_from_mono_type (t)));
6861                         err = decode_value (t, frame->domain, val_buf, p, &p, end);
6862                         if (err)
6863                                 return err;
6864
6865                         set_var (t, var, &frame->ctx, frame->domain, val_buf);
6866                 }
6867                 mono_metadata_free_mh (header);
6868                 break;
6869         }
6870         default:
6871                 return ERR_NOT_IMPLEMENTED;
6872         }
6873
6874         return ERR_NONE;
6875 }
6876
6877 static ErrorCode
6878 array_commands (int command, guint8 *p, guint8 *end, Buffer *buf)
6879 {
6880         MonoArray *arr;
6881         int objid, err, index, len, i, esize;
6882         gpointer elem;
6883
6884         objid = decode_objid (p, &p, end);
6885         err = get_object (objid, (MonoObject**)&arr);
6886         if (err)
6887                 return err;
6888
6889         switch (command) {
6890         case CMD_ARRAY_REF_GET_LENGTH:
6891                 buffer_add_int (buf, arr->obj.vtable->klass->rank);
6892                 if (!arr->bounds) {
6893                         buffer_add_int (buf, arr->max_length);
6894                         buffer_add_int (buf, 0);
6895                 } else {
6896                         for (i = 0; i < arr->obj.vtable->klass->rank; ++i) {
6897                                 buffer_add_int (buf, arr->bounds [i].length);
6898                                 buffer_add_int (buf, arr->bounds [i].lower_bound);
6899                         }
6900                 }
6901                 break;
6902         case CMD_ARRAY_REF_GET_VALUES:
6903                 index = decode_int (p, &p, end);
6904                 len = decode_int (p, &p, end);
6905
6906                 g_assert (index >= 0 && len >= 0);
6907                 // Reordered to avoid integer overflow
6908                 g_assert (!(index > arr->max_length - len));
6909
6910                 esize = mono_array_element_size (arr->obj.vtable->klass);
6911                 for (i = index; i < index + len; ++i) {
6912                         elem = (gpointer*)((char*)arr->vector + (i * esize));
6913                         buffer_add_value (buf, &arr->obj.vtable->klass->element_class->byval_arg, elem, arr->obj.vtable->domain);
6914                 }
6915                 break;
6916         case CMD_ARRAY_REF_SET_VALUES:
6917                 index = decode_int (p, &p, end);
6918                 len = decode_int (p, &p, end);
6919
6920                 g_assert (index >= 0 && len >= 0);
6921                 // Reordered to avoid integer overflow
6922                 g_assert (!(index > arr->max_length - len));
6923
6924                 esize = mono_array_element_size (arr->obj.vtable->klass);
6925                 for (i = index; i < index + len; ++i) {
6926                         elem = (gpointer*)((char*)arr->vector + (i * esize));
6927
6928                         decode_value (&arr->obj.vtable->klass->element_class->byval_arg, arr->obj.vtable->domain, elem, p, &p, end);
6929                 }
6930                 break;
6931         default:
6932                 return ERR_NOT_IMPLEMENTED;
6933         }
6934
6935         return ERR_NONE;
6936 }
6937
6938 static ErrorCode
6939 string_commands (int command, guint8 *p, guint8 *end, Buffer *buf)
6940 {
6941         int objid, err;
6942         MonoString *str;
6943         char *s;
6944
6945         objid = decode_objid (p, &p, end);
6946         err = get_object (objid, (MonoObject**)&str);
6947         if (err)
6948                 return err;
6949
6950         switch (command) {
6951         case CMD_STRING_REF_GET_VALUE:
6952                 s = mono_string_to_utf8 (str);
6953                 buffer_add_string (buf, s);
6954                 g_free (s);
6955                 break;
6956         default:
6957                 return ERR_NOT_IMPLEMENTED;
6958         }
6959
6960         return ERR_NONE;
6961 }
6962
6963 static ErrorCode
6964 object_commands (int command, guint8 *p, guint8 *end, Buffer *buf)
6965 {
6966         int objid, err;
6967         MonoObject *obj;
6968         int len, i;
6969         MonoClassField *f;
6970         MonoClass *k;
6971         gboolean found;
6972
6973         if (command == CMD_OBJECT_REF_IS_COLLECTED) {
6974                 objid = decode_objid (p, &p, end);
6975                 err = get_object (objid, &obj);
6976                 if (err)
6977                         buffer_add_int (buf, 1);
6978                 else
6979                         buffer_add_int (buf, 0);
6980                 return 0;
6981         }
6982
6983         objid = decode_objid (p, &p, end);
6984         err = get_object (objid, &obj);
6985         if (err)
6986                 return err;
6987
6988         switch (command) {
6989         case CMD_OBJECT_REF_GET_TYPE:
6990                 buffer_add_typeid (buf, obj->vtable->domain, obj->vtable->klass);
6991                 break;
6992         case CMD_OBJECT_REF_GET_VALUES:
6993                 len = decode_int (p, &p, end);
6994
6995                 for (i = 0; i < len; ++i) {
6996                         MonoClassField *f = decode_fieldid (p, &p, end, NULL, &err);
6997                         if (err)
6998                                 return err;
6999
7000                         /* Check that the field belongs to the object */
7001                         found = FALSE;
7002                         for (k = obj->vtable->klass; k; k = k->parent) {
7003                                 if (k == f->parent) {
7004                                         found = TRUE;
7005                                         break;
7006                                 }
7007                         }
7008                         if (!found)
7009                                 return ERR_INVALID_FIELDID;
7010
7011                         if (f->type->attrs & FIELD_ATTRIBUTE_STATIC) {
7012                                 guint8 *val;
7013                                 MonoVTable *vtable;
7014
7015                                 if (mono_class_field_is_special_static (f))
7016                                         return ERR_INVALID_FIELDID;
7017
7018                                 g_assert (f->type->attrs & FIELD_ATTRIBUTE_STATIC);
7019                                 vtable = mono_class_vtable (obj->vtable->domain, f->parent);
7020                                 val = g_malloc (mono_class_instance_size (mono_class_from_mono_type (f->type)));
7021                                 mono_field_static_get_value (vtable, f, val);
7022                                 buffer_add_value (buf, f->type, val, obj->vtable->domain);
7023                                 g_free (val);
7024                         } else {
7025                                 buffer_add_value (buf, f->type, (guint8*)obj + f->offset, obj->vtable->domain);
7026                         }
7027                 }
7028                 break;
7029         case CMD_OBJECT_REF_SET_VALUES:
7030                 len = decode_int (p, &p, end);
7031
7032                 for (i = 0; i < len; ++i) {
7033                         f = decode_fieldid (p, &p, end, NULL, &err);
7034                         if (err)
7035                                 return err;
7036
7037                         /* Check that the field belongs to the object */
7038                         found = FALSE;
7039                         for (k = obj->vtable->klass; k; k = k->parent) {
7040                                 if (k == f->parent) {
7041                                         found = TRUE;
7042                                         break;
7043                                 }
7044                         }
7045                         if (!found)
7046                                 return ERR_INVALID_FIELDID;
7047
7048                         if (f->type->attrs & FIELD_ATTRIBUTE_STATIC) {
7049                                 guint8 *val;
7050                                 MonoVTable *vtable;
7051
7052                                 if (mono_class_field_is_special_static (f))
7053                                         return ERR_INVALID_FIELDID;
7054
7055                                 g_assert (f->type->attrs & FIELD_ATTRIBUTE_STATIC);
7056                                 vtable = mono_class_vtable (obj->vtable->domain, f->parent);
7057
7058                                 val = g_malloc (mono_class_instance_size (mono_class_from_mono_type (f->type)));
7059                                 err = decode_value (f->type, obj->vtable->domain, val, p, &p, end);
7060                                 if (err) {
7061                                         g_free (val);
7062                                         return err;
7063                                 }
7064                                 mono_field_static_set_value (vtable, f, val);
7065                                 g_free (val);
7066                         } else {
7067                                 err = decode_value (f->type, obj->vtable->domain, (guint8*)obj + f->offset, p, &p, end);
7068                                 if (err)
7069                                         return err;
7070                         }
7071                 }
7072                 break;
7073         case CMD_OBJECT_REF_GET_ADDRESS:
7074                 buffer_add_long (buf, (gssize)obj);
7075                 break;
7076         case CMD_OBJECT_REF_GET_DOMAIN:
7077                 buffer_add_domainid (buf, obj->vtable->domain);
7078                 break;
7079         default:
7080                 return ERR_NOT_IMPLEMENTED;
7081         }
7082
7083         return ERR_NONE;
7084 }
7085
7086 static const char*
7087 command_set_to_string (CommandSet command_set)
7088 {
7089         switch (command_set) {
7090         case CMD_SET_VM:
7091                 return "VM";
7092         case CMD_SET_OBJECT_REF:
7093                 return "OBJECT_REF";
7094         case CMD_SET_STRING_REF:
7095                 return "STRING_REF"; 
7096         case CMD_SET_THREAD:
7097                 return "THREAD"; 
7098         case CMD_SET_ARRAY_REF:
7099                 return "ARRAY_REF"; 
7100         case CMD_SET_EVENT_REQUEST:
7101                 return "EVENT_REQUEST"; 
7102         case CMD_SET_STACK_FRAME:
7103                 return "STACK_FRAME"; 
7104         case CMD_SET_APPDOMAIN:
7105                 return "APPDOMAIN"; 
7106         case CMD_SET_ASSEMBLY:
7107                 return "ASSEMBLY"; 
7108         case CMD_SET_METHOD:
7109                 return "METHOD"; 
7110         case CMD_SET_TYPE:
7111                 return "TYPE"; 
7112         case CMD_SET_MODULE:
7113                 return "MODULE"; 
7114         case CMD_SET_EVENT:
7115                 return "EVENT"; 
7116         default:
7117                 return "";
7118         }
7119 }
7120
7121 static const char*
7122 cmd_to_string (CommandSet set, int command)
7123 {
7124         switch (set) {
7125         case CMD_SET_VM: {
7126                 switch (command) {
7127                 case CMD_VM_VERSION:
7128                         return "VERSION";
7129                 case CMD_VM_ALL_THREADS:
7130                         return "ALL_THREADS";
7131                 case CMD_VM_SUSPEND:
7132                         return "SUSPEND";
7133                 case CMD_VM_RESUME:
7134                         return "RESUME";
7135                 case CMD_VM_EXIT:
7136                         return "EXIT";
7137                 case CMD_VM_DISPOSE:
7138                         return "DISPOSE";
7139                 case CMD_VM_INVOKE_METHOD:
7140                         return "INVOKE_METHOD";
7141                 case CMD_VM_SET_PROTOCOL_VERSION:
7142                         return "SET_PROTOCOL_VERSION";
7143                 case CMD_VM_ABORT_INVOKE:
7144                         return "ABORT_INVOKE";
7145                 default:
7146                         break;
7147                 }
7148                 break;
7149         }
7150         default:
7151                 break;
7152         }
7153         return NULL;
7154 }
7155
7156 static gboolean
7157 wait_for_attach (void)
7158 {
7159         if (listen_fd == -1) {
7160                 DEBUG (1, fprintf (log_file, "[dbg] Invalid listening socket\n"));
7161                 return FALSE;
7162         }
7163
7164         /* Block and wait for client connection */
7165         conn_fd = transport_accept (listen_fd);
7166         DEBUG (1, fprintf (log_file, "Accepted connection on %d\n", conn_fd));
7167         if (conn_fd == -1) {
7168                 DEBUG (1, fprintf (log_file, "[dbg] Bad client connection\n"));
7169                 return FALSE;
7170         }
7171         
7172         /* Handshake */
7173         disconnected = !transport_handshake ();
7174         if (disconnected) {
7175                 DEBUG (1, fprintf (log_file, "Transport handshake failed!\n"));
7176                 return FALSE;
7177         }
7178         
7179         return TRUE;
7180 }
7181
7182 /*
7183  * debugger_thread:
7184  *
7185  *   This thread handles communication with the debugger client using a JDWP
7186  * like protocol.
7187  */
7188 static guint32 WINAPI
7189 debugger_thread (void *arg)
7190 {
7191         int res, len, id, flags, command_set, command;
7192         guint8 header [HEADER_LENGTH];
7193         guint8 *data, *p, *end;
7194         Buffer buf;
7195         ErrorCode err;
7196         gboolean no_reply;
7197         gboolean attach_failed = FALSE;
7198
7199         DEBUG (1, fprintf (log_file, "[dbg] Agent thread started, pid=%p\n", (gpointer)GetCurrentThreadId ()));
7200
7201         debugger_thread_id = GetCurrentThreadId ();
7202
7203         mono_jit_thread_attach (mono_get_root_domain ());
7204
7205         mono_thread_internal_current ()->flags |= MONO_THREAD_FLAG_DONT_MANAGE;
7206
7207         mono_set_is_debugger_attached (TRUE);
7208         
7209         if (agent_config.defer) {
7210                 if (!wait_for_attach ()) {
7211                         DEBUG (1, fprintf (log_file, "[dbg] Can't attach, aborting debugger thread.\n"));
7212                         attach_failed = TRUE; // Don't abort process when we can't listen
7213                 } else {
7214                         /* Send start event to client */
7215                         process_profiler_event (EVENT_KIND_VM_START, mono_thread_get_main ());
7216                 }
7217         }
7218         
7219         while (!attach_failed) {
7220                 res = recv_length (conn_fd, header, HEADER_LENGTH, 0);
7221
7222                 /* This will break if the socket is closed during shutdown too */
7223                 if (res != HEADER_LENGTH)
7224                         break;
7225
7226                 p = header;
7227                 end = header + HEADER_LENGTH;
7228
7229                 len = decode_int (p, &p, end);
7230                 id = decode_int (p, &p, end);
7231                 flags = decode_byte (p, &p, end);
7232                 command_set = decode_byte (p, &p, end);
7233                 command = decode_byte (p, &p, end);
7234
7235                 g_assert (flags == 0);
7236
7237                 if (log_level) {
7238                         const char *cmd_str;
7239                         char cmd_num [256];
7240
7241                         cmd_str = cmd_to_string (command_set, command);
7242                         if (!cmd_str) {
7243                                 sprintf (cmd_num, "%d", command);
7244                                 cmd_str = cmd_num;
7245                         }
7246                         
7247                         DEBUG (1, fprintf (log_file, "[dbg] Received command %s(%s), id=%d.\n", command_set_to_string (command_set), cmd_str, id));
7248                 }
7249
7250                 data = g_malloc (len - HEADER_LENGTH);
7251                 if (len - HEADER_LENGTH > 0)
7252                 {
7253                         res = recv_length (conn_fd, data, len - HEADER_LENGTH, 0);
7254                         if (res != len - HEADER_LENGTH)
7255                                 break;
7256                 }
7257
7258                 p = data;
7259                 end = data + (len - HEADER_LENGTH);
7260
7261                 buffer_init (&buf, 128);
7262
7263                 err = ERR_NONE;
7264                 no_reply = FALSE;
7265
7266                 /* Process the request */
7267                 switch (command_set) {
7268                 case CMD_SET_VM:
7269                         err = vm_commands (command, id, p, end, &buf);
7270                         if (!err && command == CMD_VM_INVOKE_METHOD)
7271                                 /* Sent after the invoke is complete */
7272                                 no_reply = TRUE;
7273                         break;
7274                 case CMD_SET_EVENT_REQUEST:
7275                         err = event_commands (command, p, end, &buf);
7276                         break;
7277                 case CMD_SET_APPDOMAIN:
7278                         err = domain_commands (command, p, end, &buf);
7279                         break;
7280                 case CMD_SET_ASSEMBLY:
7281                         err = assembly_commands (command, p, end, &buf);
7282                         break;
7283                 case CMD_SET_MODULE:
7284                         err = module_commands (command, p, end, &buf);
7285                         break;
7286                 case CMD_SET_TYPE:
7287                         err = type_commands (command, p, end, &buf);
7288                         break;
7289                 case CMD_SET_METHOD:
7290                         err = method_commands (command, p, end, &buf);
7291                         break;
7292                 case CMD_SET_THREAD:
7293                         err = thread_commands (command, p, end, &buf);
7294                         break;
7295                 case CMD_SET_STACK_FRAME:
7296                         err = frame_commands (command, p, end, &buf);
7297                         break;
7298                 case CMD_SET_ARRAY_REF:
7299                         err = array_commands (command, p, end, &buf);
7300                         break;
7301                 case CMD_SET_STRING_REF:
7302                         err = string_commands (command, p, end, &buf);
7303                         break;
7304                 case CMD_SET_OBJECT_REF:
7305                         err = object_commands (command, p, end, &buf);
7306                         break;
7307                 default:
7308                         err = ERR_NOT_IMPLEMENTED;
7309                 }               
7310
7311                 if (!no_reply)
7312                         send_reply_packet (id, err, &buf);
7313
7314                 g_free (data);
7315                 buffer_free (&buf);
7316
7317                 if (command_set == CMD_SET_VM && command == CMD_VM_DISPOSE)
7318                         break;
7319         }
7320
7321         mono_set_is_debugger_attached (FALSE);
7322         
7323         mono_mutex_lock (&debugger_thread_exited_mutex);
7324         debugger_thread_exited = TRUE;
7325         mono_cond_signal (&debugger_thread_exited_cond);
7326         mono_mutex_unlock (&debugger_thread_exited_mutex);
7327
7328         DEBUG (1, fprintf (log_file, "[dbg] Debugger thread exited.\n"));
7329         
7330         if (!attach_failed && command_set == CMD_SET_VM && command == CMD_VM_DISPOSE && !(vm_death_event_sent || mono_runtime_is_shutting_down ())) {
7331                 DEBUG (2, fprintf (log_file, "[dbg] Detached - restarting clean debugger thread.\n"));
7332                 start_debugger_thread ();
7333         }
7334         
7335         return 0;
7336 }
7337
7338 #else /* DISABLE_DEBUGGER_AGENT */
7339
7340 void
7341 mono_debugger_agent_parse_options (char *options)
7342 {
7343         g_error ("This runtime is configured with the debugger agent disabled.");
7344 }
7345
7346 void
7347 mono_debugger_agent_init (void)
7348 {
7349 }
7350
7351 void
7352 mono_debugger_agent_breakpoint_hit (void *sigctx)
7353 {
7354 }
7355
7356 void
7357 mono_debugger_agent_single_step_event (void *sigctx)
7358 {
7359 }
7360
7361 void
7362 mono_debugger_agent_free_domain_info (MonoDomain *domain)
7363 {
7364 }
7365
7366 gboolean
7367 mono_debugger_agent_thread_interrupt (void *sigctx, MonoJitInfo *ji)
7368 {
7369         return FALSE;
7370 }
7371
7372 void
7373 mono_debugger_agent_handle_exception (MonoException *ext, MonoContext *throw_ctx,
7374                                                                           MonoContext *catch_ctx)
7375 {
7376 }
7377
7378 void
7379 mono_debugger_agent_begin_exception_filter (MonoException *exc, MonoContext *ctx, MonoContext *orig_ctx)
7380 {
7381 }
7382
7383 void
7384 mono_debugger_agent_end_exception_filter (MonoException *exc, MonoContext *ctx, MonoContext *orig_ctx)
7385 {
7386 }
7387
7388 #endif
7389