6936d2e317663309a6b8c2106749858818647823
[mono.git] / mono / mini / debugger-agent.c
1 /*
2  * debugger-agent.c: Debugger back-end module
3  *
4  * Author:
5  *   Zoltan Varga (vargaz@gmail.com)
6  *
7  * (C) 2009 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_SOCKET_H
18 #include <sys/socket.h>
19 #endif
20 #ifdef HAVE_NETINET_TCP_H
21 #include <netinet/tcp.h>
22 #endif
23 #ifdef HAVE_NETINET_IN_H
24 #include <netinet/in.h>
25 #endif
26 #ifdef HAVE_NETDB_H
27 #include <netdb.h>
28 #endif
29 #ifdef HAVE_UNISTD_H
30 #include <unistd.h>
31 #endif
32 #include <errno.h>
33 #include <glib.h>
34
35 #ifdef HAVE_PTHREAD_H
36 #include <pthread.h>
37 #endif
38
39 #include <mono/metadata/mono-debug.h>
40 #include <mono/metadata/mono-debug-debugger.h>
41 #include <mono/metadata/debug-mono-symfile.h>
42 #include <mono/metadata/gc-internal.h>
43 #include <mono/metadata/threads-types.h>
44 #include <mono/utils/mono-semaphore.h>
45 #include "debugger-agent.h"
46 #include "mini.h"
47
48 #ifndef MONO_ARCH_SOFT_DEBUG_SUPPORTED
49 #define DISABLE_DEBUGGER_AGENT 1
50 #endif
51
52 #ifndef DISABLE_DEBUGGER_AGENT
53 #include <mono/io-layer/mono-mutex.h>
54
55 typedef struct {
56         gboolean enabled;
57         char *transport;
58         char *address;
59         int log_level;
60         char *log_file;
61         gboolean suspend;
62         gboolean server;
63         gboolean onuncaught;
64         GSList *onthrow;
65         int timeout;
66         char *launch;
67 } AgentConfig;
68
69 typedef struct
70 {
71         int id;
72         guint32 il_offset;
73         MonoDomain *domain;
74         MonoMethod *method;
75         MonoContext ctx;
76         MonoDebugMethodJitInfo *jit;
77         int flags;
78 } StackFrame;
79
80 typedef struct
81 {
82         int id;
83         guint8 *p;
84         guint8 *endp;
85         /* This is the context which needs to be restored after the invoke */
86         MonoContext ctx;
87         gboolean has_ctx;
88 } InvokeData;
89
90 typedef struct {
91         MonoContext ctx;
92         MonoLMF *lmf;
93         MonoDomain *domain;
94         gboolean has_context;
95         gpointer resume_event;
96         /* This is computed on demand when it is requested using the wire protocol */
97         /* It is freed up when the thread is resumed */
98         int frame_count;
99         StackFrame **frames;
100         /* 
101          * Whenever the frame info is up-to-date. If not, compute_frame_info () will need to
102          * re-compute it.
103          */
104         gboolean frames_up_to_date;
105         /* 
106          * Points to data about a pending invoke which needs to be executed after the thread
107          * resumes.
108          */
109         InvokeData *invoke;
110         /*
111          * Set to TRUE if this thread is suspended in suspend_current () or it is executing
112          * native code.
113          */
114         gboolean suspended;
115         /* Used to pass the context to the breakpoint/single step handler */
116         MonoContext handler_ctx;
117         /* Whenever thread_stop () was called for this thread */
118         gboolean terminated;
119
120         /* Number of thread interruptions not yet processed */
121         gint32 interrupt_count;
122 } DebuggerTlsData;
123
124 /* 
125  * Wire Protocol definitions
126  */
127
128 #define HEADER_LENGTH 11
129
130 #define MAJOR_VERSION 0
131 #define MINOR_VERSION 2
132
133 typedef enum {
134         CMD_SET_VM = 1,
135         CMD_SET_OBJECT_REF = 9,
136         CMD_SET_STRING_REF = 10,
137         CMD_SET_THREAD = 11,
138         CMD_SET_ARRAY_REF = 13,
139         CMD_SET_EVENT_REQUEST = 15,
140         CMD_SET_STACK_FRAME = 16,
141         CMD_SET_APPDOMAIN = 20,
142         CMD_SET_ASSEMBLY = 21,
143         CMD_SET_METHOD = 22,
144         CMD_SET_TYPE = 23,
145         CMD_SET_MODULE = 24,
146         CMD_SET_EVENT = 64
147 } CommandSet;
148
149 typedef enum {
150         EVENT_KIND_VM_START = 0,
151         EVENT_KIND_VM_DEATH = 1,
152         EVENT_KIND_THREAD_START = 2,
153         EVENT_KIND_THREAD_DEATH = 3,
154         EVENT_KIND_APPDOMAIN_CREATE = 4,
155         EVENT_KIND_APPDOMAIN_UNLOAD = 5,
156         EVENT_KIND_METHOD_ENTRY = 6,
157         EVENT_KIND_METHOD_EXIT = 7,
158         EVENT_KIND_ASSEMBLY_LOAD = 8,
159         EVENT_KIND_ASSEMBLY_UNLOAD = 9,
160         EVENT_KIND_BREAKPOINT = 10,
161         EVENT_KIND_STEP = 11,
162         EVENT_KIND_TYPE_LOAD = 12,
163         EVENT_KIND_EXCEPTION = 13
164 } EventKind;
165
166 typedef enum {
167         SUSPEND_POLICY_NONE = 0,
168         SUSPEND_POLICY_EVENT_THREAD = 1,
169         SUSPEND_POLICY_ALL = 2
170 } SuspendPolicy;
171
172 typedef enum {
173         ERR_NONE = 0,
174         ERR_INVALID_OBJECT = 20,
175         ERR_INVALID_FIELDID = 25,
176         ERR_INVALID_FRAMEID = 30,
177         ERR_NOT_IMPLEMENTED = 100,
178         ERR_NOT_SUSPENDED = 101,
179         ERR_INVALID_ARGUMENT = 102,
180         ERR_UNLOADED = 103
181 } ErrorCode;
182
183 typedef enum {
184         MOD_KIND_COUNT = 1,
185         MOD_KIND_THREAD_ONLY = 3,
186         MOD_KIND_LOCATION_ONLY = 7,
187         MOD_KIND_EXCEPTION_ONLY = 8,
188         MOD_KIND_STEP = 10,
189         MOD_KIND_ASSEMBLY_ONLY = 11
190 } ModifierKind;
191
192 typedef enum {
193         STEP_DEPTH_INTO = 0,
194         STEP_DEPTH_OVER = 1,
195         STEP_DEPTH_OUT = 2
196 } StepDepth;
197
198 typedef enum {
199         STEP_SIZE_MIN = 0,
200         STEP_SIZE_LINE = 1
201 } StepSize;
202
203 typedef enum {
204         TOKEN_TYPE_STRING = 0,
205         TOKEN_TYPE_TYPE = 1,
206         TOKEN_TYPE_FIELD = 2,
207         TOKEN_TYPE_METHOD = 3,
208         TOKEN_TYPE_UNKNOWN = 4
209 } DebuggerTokenType;
210
211 typedef enum {
212         VALUE_TYPE_ID_NULL = 0xf0,
213         VALUE_TYPE_ID_TYPE = 0xf1
214 } ValueTypeId;
215
216 typedef enum {
217         FRAME_FLAG_DEBUGGER_INVOKE = 1
218 } StackFrameFlags;
219
220 typedef enum {
221         CMD_VM_VERSION = 1,
222         CMD_VM_ALL_THREADS = 2,
223         CMD_VM_SUSPEND = 3,
224         CMD_VM_RESUME = 4,
225         CMD_VM_EXIT = 5,
226         CMD_VM_DISPOSE = 6,
227         CMD_VM_INVOKE_METHOD = 7
228 } CmdVM;
229
230 typedef enum {
231         CMD_THREAD_GET_FRAME_INFO = 1,
232         CMD_THREAD_GET_NAME = 2,
233         CMD_THREAD_GET_STATE = 3,
234         CMD_THREAD_GET_INFO = 4
235 } CmdThread;
236
237 typedef enum {
238         CMD_EVENT_REQUEST_SET = 1,
239         CMD_EVENT_REQUEST_CLEAR = 2,
240         CMD_EVENT_REQUEST_CLEAR_ALL_BREAKPOINTS = 3
241 } CmdEvent;
242
243 typedef enum {
244         CMD_COMPOSITE = 100
245 } CmdComposite;
246
247 typedef enum {
248         CMD_APPDOMAIN_GET_ROOT_DOMAIN = 1,
249         CMD_APPDOMAIN_GET_FRIENDLY_NAME = 2,
250         CMD_APPDOMAIN_GET_ASSEMBLIES = 3,
251         CMD_APPDOMAIN_GET_ENTRY_ASSEMBLY = 4,
252         CMD_APPDOMAIN_CREATE_STRING = 5,
253         CMD_APPDOMAIN_GET_CORLIB = 6
254 } CmdAppDomain;
255
256 typedef enum {
257         CMD_ASSEMBLY_GET_LOCATION = 1,
258         CMD_ASSEMBLY_GET_ENTRY_POINT = 2,
259         CMD_ASSEMBLY_GET_MANIFEST_MODULE = 3,
260         CMD_ASSEMBLY_GET_OBJECT = 4,
261         CMD_ASSEMBLY_GET_TYPE = 5,
262 } CmdAssembly;
263
264 typedef enum {
265         CMD_MODULE_GET_INFO = 1,
266 } CmdModule;
267
268 typedef enum {
269         CMD_METHOD_GET_NAME = 1,
270         CMD_METHOD_GET_DECLARING_TYPE = 2,
271         CMD_METHOD_GET_DEBUG_INFO = 3,
272         CMD_METHOD_GET_PARAM_INFO = 4,
273         CMD_METHOD_GET_LOCALS_INFO = 5,
274         CMD_METHOD_GET_INFO = 6,
275         CMD_METHOD_GET_BODY = 7,
276         CMD_METHOD_RESOLVE_TOKEN = 8,
277 } CmdMethod;
278
279 typedef enum {
280         CMD_TYPE_GET_INFO = 1,
281         CMD_TYPE_GET_METHODS = 2,
282         CMD_TYPE_GET_FIELDS = 3,
283         CMD_TYPE_GET_VALUES = 4,
284         CMD_TYPE_GET_OBJECT = 5,
285         CMD_TYPE_GET_SOURCE_FILES = 6,
286         CMD_TYPE_SET_VALUES = 7,
287         CMD_TYPE_IS_ASSIGNABLE_FROM = 8,
288         CMD_TYPE_GET_PROPERTIES = 9,
289         CMD_TYPE_GET_CATTRS = 10,
290         CMD_TYPE_GET_FIELD_CATTRS = 11,
291         CMD_TYPE_GET_PROPERTY_CATTRS = 12
292 } CmdType;
293
294 typedef enum {
295         CMD_STACK_FRAME_GET_VALUES = 1,
296         CMD_STACK_FRAME_GET_THIS = 2,
297         CMD_STACK_FRAME_SET_VALUES = 3
298 } CmdStackFrame;
299
300 typedef enum {
301         CMD_ARRAY_REF_GET_LENGTH = 1,
302         CMD_ARRAY_REF_GET_VALUES = 2,
303         CMD_ARRAY_REF_SET_VALUES = 3,
304 } CmdArray;
305
306 typedef enum {
307         CMD_STRING_REF_GET_VALUE = 1,
308 } CmdString;
309
310 typedef enum {
311         CMD_OBJECT_REF_GET_TYPE = 1,
312         CMD_OBJECT_REF_GET_VALUES = 2,
313         CMD_OBJECT_REF_IS_COLLECTED = 3,
314         CMD_OBJECT_REF_GET_ADDRESS = 4,
315         CMD_OBJECT_REF_GET_DOMAIN = 5,
316         CMD_OBJECT_REF_SET_VALUES = 6
317 } CmdObject;
318
319 typedef struct {
320         ModifierKind kind;
321         union {
322                 int count; /* For kind == MOD_KIND_COUNT */
323                 MonoInternalThread *thread; /* For kind == MOD_KIND_THREAD_ONLY */
324                 MonoClass *exc_class; /* For kind == MONO_KIND_EXCEPTION_ONLY */
325                 MonoAssembly **assemblies; /* For kind == MONO_KIND_ASSEMBLY_ONLY */
326         } data;
327 } Modifier;
328
329 typedef struct{
330         int id;
331         int event_kind;
332         int suspend_policy;
333         int nmodifiers;
334         gpointer info;
335         Modifier modifiers [MONO_ZERO_LEN_ARRAY];
336 } EventRequest;
337
338 /*
339  * Describes a single step request.
340  */
341 typedef struct {
342         EventRequest *req;
343         MonoInternalThread *thread;
344         StepDepth depth;
345         StepSize size;
346         gpointer last_sp;
347         gpointer start_sp;
348         MonoMethod *last_method;
349         int last_line;
350 } MonoSingleStepReq;
351
352 /* Dummy structure used for the profiler callbacks */
353 typedef struct {
354         void* dummy;
355 } DebuggerProfiler;
356
357 #define DEBUG(level,s) do { if (G_UNLIKELY ((level) <= log_level)) { s; fflush (log_file); } } while (0)
358
359 /*
360  * Globals
361  */
362
363 static AgentConfig agent_config;
364
365 /* 
366  * Whenever the agent is fully initialized.
367  * When using the onuncaught or onthrow options, only some parts of the agent are
368  * initialized on startup, and the full initialization which includes connection
369  * establishment and the startup of the agent thread is only done in response to
370  * an event.
371  */
372 static gint32 inited;
373
374 static int conn_fd;
375
376 static int packet_id = 0;
377
378 static int objref_id = 0;
379
380 static int event_request_id = 0;
381
382 static int frame_id = 0;
383
384 static GPtrArray *event_requests;
385
386 static guint32 debugger_tls_id;
387
388 static gboolean vm_start_event_sent, vm_death_event_sent, disconnected;
389
390 /* Maps MonoInternalThread -> DebuggerTlsData */
391 static MonoGHashTable *thread_to_tls;
392
393 /* Maps tid -> MonoInternalThread */
394 static MonoGHashTable *tid_to_thread;
395
396 /* Maps tid -> MonoThread (not MonoInternalThread) */
397 static MonoGHashTable *tid_to_thread_obj;
398
399 static gsize debugger_thread_id;
400
401 static HANDLE debugger_thread_handle;
402
403 static int log_level;
404
405 static FILE *log_file;
406
407 /* Classes whose class load event has been sent */
408 static GHashTable *loaded_classes;
409
410 /* Assemblies whose assembly load event has no been sent yet */
411 static GPtrArray *pending_assembly_loads;
412
413 /* Whenever the debugger thread has exited */
414 static gboolean debugger_thread_exited;
415
416 /* Cond variable used to wait for debugger_thread_exited becoming true */
417 static mono_cond_t debugger_thread_exited_cond = MONO_COND_INITIALIZER;
418
419 /* Mutex for the cond var above */
420 static mono_mutex_t debugger_thread_exited_mutex = MONO_MUTEX_INITIALIZER;
421
422 static DebuggerProfiler debugger_profiler;
423
424 /* The single step request instance */
425 static MonoSingleStepReq *ss_req = NULL;
426
427 #ifdef MONO_ARCH_SOFT_DEBUG_SUPPORTED
428 /* Number of single stepping operations in progress */
429 static int ss_count;
430 #endif
431
432 static void transport_connect (const char *host, int port);
433
434 static guint32 WINAPI debugger_thread (void *arg);
435
436 static void runtime_initialized (MonoProfiler *prof);
437
438 static void runtime_shutdown (MonoProfiler *prof);
439
440 static void thread_startup (MonoProfiler *prof, gsize tid);
441
442 static void thread_end (MonoProfiler *prof, gsize tid);
443
444 static void appdomain_load (MonoProfiler *prof, MonoDomain *domain, int result);
445
446 static void appdomain_unload (MonoProfiler *prof, MonoDomain *domain);
447
448 static void assembly_load (MonoProfiler *prof, MonoAssembly *assembly, int result);
449
450 static void assembly_unload (MonoProfiler *prof, MonoAssembly *assembly);
451
452 static void start_runtime_invoke (MonoProfiler *prof, MonoMethod *method);
453
454 static void end_runtime_invoke (MonoProfiler *prof, MonoMethod *method);
455
456 static void jit_end (MonoProfiler *prof, MonoMethod *method, MonoJitInfo *jinfo, int result);
457
458 static void add_pending_breakpoints (MonoMethod *method, MonoJitInfo *jinfo);
459
460 static void start_single_stepping (void);
461
462 static void stop_single_stepping (void);
463
464 static void suspend_current (void);
465
466 /* Submodule init/cleanup */
467 static void breakpoints_init (void);
468 static void breakpoints_cleanup (void);
469
470 static void objrefs_init (void);
471 static void objrefs_cleanup (void);
472
473 static void ids_init (void);
474 static void ids_cleanup (void);
475
476 static void suspend_init (void);
477
478 static ErrorCode ss_start (MonoInternalThread *thread, StepSize size, StepDepth depth, EventRequest *req);
479 static void ss_stop (EventRequest *req);
480
481 static void start_debugger_thread (void);
482
483 static void finish_agent_init (gboolean on_startup);
484
485 static int
486 parse_address (char *address, char **host, int *port)
487 {
488         char *pos = strchr (address, ':');
489
490         if (pos == NULL || pos == address)
491                 return 1;
492
493         *host = g_malloc (pos - address + 1);
494         strncpy (*host, address, pos - address);
495         (*host) [pos - address] = '\0';
496
497         *port = atoi (pos + 1);
498
499         return 0;
500 }
501
502 static void
503 print_usage (void)
504 {
505         fprintf (stderr, "Usage: mono --debugger-agent=[<option>=<value>,...] ...\n");
506         fprintf (stderr, "Available options:\n");
507         fprintf (stderr, "  transport=<transport>\t\tTransport to use for connecting to the debugger (mandatory, possible values: 'dt_socket')\n");
508         fprintf (stderr, "  address=<hostname>:<port>\tAddress to connect to (mandatory)\n");
509         fprintf (stderr, "  loglevel=<n>\t\t\tLog level (defaults to 0)\n");
510         fprintf (stderr, "  logfile=<file>\t\tFile to log to (defaults to stdout)\n");
511         fprintf (stderr, "  suspend=y/n\t\t\tWhenever to suspend after startup.\n");
512         fprintf (stderr, "  timeout=<n>\t\t\tTimeout for connecting in milliseconds.\n");
513         fprintf (stderr, "  help\t\t\t\tPrint this help.\n");
514 }
515
516 static gboolean
517 parse_flag (const char *option, char *flag)
518 {
519         if (!strcmp (flag, "y"))
520                 return TRUE;
521         else if (!strcmp (flag, "n"))
522                 return FALSE;
523         else {
524                 fprintf (stderr, "debugger-agent: The valid values for the '%s' option are 'y' and 'n'.\n", option);
525                 exit (1);
526                 return FALSE;
527         }
528 }
529
530 void
531 mono_debugger_agent_parse_options (char *options)
532 {
533         char **args, **ptr;
534         char *host;
535         int port;
536
537 #ifndef MONO_ARCH_SOFT_DEBUG_SUPPORTED
538         fprintf (stderr, "--debugger-agent is not supported on this platform.\n");
539         exit (1);
540 #endif
541
542         agent_config.enabled = TRUE;
543         agent_config.suspend = TRUE;
544         agent_config.server = FALSE;
545
546         args = g_strsplit (options, ",", -1);
547         for (ptr = args; ptr && *ptr; ptr ++) {
548                 char *arg = *ptr;
549
550                 if (strncmp (arg, "transport=", 10) == 0) {
551                         agent_config.transport = g_strdup (arg + 10);
552                 } else if (strncmp (arg, "address=", 8) == 0) {
553                         agent_config.address = g_strdup (arg + 8);
554                 } else if (strncmp (arg, "loglevel=", 9) == 0) {
555                         agent_config.log_level = atoi (arg + 9);
556                 } else if (strncmp (arg, "logfile=", 8) == 0) {
557                         agent_config.log_file = g_strdup (arg + 8);
558                 } else if (strncmp (arg, "suspend=", 8) == 0) {
559                         agent_config.suspend = parse_flag ("suspend", arg + 8);
560                 } else if (strncmp (arg, "server=", 7) == 0) {
561                         agent_config.server = parse_flag ("server", arg + 7);
562                 } else if (strncmp (arg, "onuncaught=", 11) == 0) {
563                         agent_config.onuncaught = parse_flag ("onuncaught", arg + 11);
564                 } else if (strncmp (arg, "onthrow=", 8) == 0) {
565                         /* We support multiple onthrow= options */
566                         agent_config.onthrow = g_slist_append (agent_config.onthrow, g_strdup (arg + 8));
567                 } else if (strncmp (arg, "help", 4) == 0) {
568                         print_usage ();
569                         exit (0);
570                 } else if (strncmp (arg, "timeout=", 8) == 0) {
571                         agent_config.timeout = atoi (arg + 8);
572                 } else if (strncmp (arg, "launch=", 7) == 0) {
573                         agent_config.launch = g_strdup (arg + 7);
574                 } else {
575                         print_usage ();
576                         exit (1);
577                 }
578         }
579
580         if (agent_config.transport == NULL) {
581                 fprintf (stderr, "debugger-agent: The 'transport' option is mandatory.\n");
582                 exit (1);
583         }
584         if (strcmp (agent_config.transport, "dt_socket") != 0) {
585                 fprintf (stderr, "debugger-agent: The only supported value for the 'transport' option is 'dt_socket'.\n");
586                 exit (1);
587         }
588
589         if (agent_config.address == NULL && !agent_config.server) {
590                 fprintf (stderr, "debugger-agent: The 'address' option is mandatory.\n");
591                 exit (1);
592         }
593
594         if (agent_config.address && parse_address (agent_config.address, &host, &port)) {
595                 fprintf (stderr, "debugger-agent: The format of the 'address' options is '<host>:<port>'\n");
596                 exit (1);
597         }
598 }
599
600 void
601 mono_debugger_agent_init (void)
602 {
603         if (!agent_config.enabled)
604                 return;
605
606         /* Need to know whenever a thread has acquired the loader mutex */
607         mono_loader_lock_track_ownership (TRUE);
608
609         event_requests = g_ptr_array_new ();
610
611         mono_profiler_install ((MonoProfiler*)&debugger_profiler, runtime_shutdown);
612         mono_profiler_set_events (MONO_PROFILE_APPDOMAIN_EVENTS | MONO_PROFILE_THREADS | MONO_PROFILE_ASSEMBLY_EVENTS | MONO_PROFILE_JIT_COMPILATION | MONO_PROFILE_METHOD_EVENTS);
613         mono_profiler_install_runtime_initialized (runtime_initialized);
614         mono_profiler_install_appdomain (NULL, appdomain_load, appdomain_unload, NULL);
615         mono_profiler_install_thread (thread_startup, thread_end);
616         mono_profiler_install_assembly (NULL, assembly_load, assembly_unload, NULL);
617         mono_profiler_install_jit_end (jit_end);
618         mono_profiler_install_method_invoke (start_runtime_invoke, end_runtime_invoke);
619
620         debugger_tls_id = TlsAlloc ();
621
622         thread_to_tls = mono_g_hash_table_new (NULL, NULL);
623         MONO_GC_REGISTER_ROOT (thread_to_tls);
624
625         tid_to_thread = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
626         MONO_GC_REGISTER_ROOT (tid_to_thread);
627
628         tid_to_thread_obj = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
629         MONO_GC_REGISTER_ROOT (tid_to_thread_obj);
630
631         loaded_classes = g_hash_table_new (mono_aligned_addr_hash, NULL);
632         pending_assembly_loads = g_ptr_array_new ();
633
634         log_level = agent_config.log_level;
635
636         if (agent_config.log_file) {
637                 log_file = fopen (agent_config.log_file, "w+");
638                 if (!log_file) {
639                         fprintf (stderr, "Unable to create log file '%s': %s.\n", agent_config.log_file, strerror (errno));
640                         exit (1);
641                 }
642         } else {
643                 log_file = stdout;
644         }
645
646         ids_init ();
647         objrefs_init ();
648         breakpoints_init ();
649         suspend_init ();
650
651         mini_get_debug_options ()->gen_seq_points = TRUE;
652         /* 
653          * This is needed because currently we don't handle liveness info.
654          */
655         mini_get_debug_options ()->mdb_optimizations = TRUE;
656
657         /* This is needed because we can't set local variables in registers yet */
658         mono_disable_optimizations (MONO_OPT_LINEARS);
659
660         if (!agent_config.onuncaught && !agent_config.onthrow)
661                 finish_agent_init (TRUE);
662 }
663
664 /*
665  * finish_agent_init:
666  *
667  *   Finish the initialization of the agent. This involves connecting the transport
668  * and starting the agent thread. This is either done at startup, or
669  * in response to some event like an unhandled exception.
670  */
671 static void
672 finish_agent_init (gboolean on_startup)
673 {
674         char *host;
675         int port;
676         int res;
677
678         if (InterlockedCompareExchange (&inited, 1, 0) == 1)
679                 return;
680
681         if (agent_config.launch) {
682                 char *argv [16];
683
684                 // FIXME: Generated address
685                 // FIXME: Races with transport_connect ()
686
687                 argv [0] = agent_config.launch;
688                 argv [1] = agent_config.transport;
689                 argv [2] = agent_config.address;
690                 argv [3] = NULL;
691
692                 res = g_spawn_async_with_pipes (NULL, argv, NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
693                 if (!res) {
694                         fprintf (stderr, "Failed to execute '%s'.\n", agent_config.launch);
695                         exit (1);
696                 }
697         }
698
699         if (agent_config.address) {
700                 res = parse_address (agent_config.address, &host, &port);
701                 g_assert (res == 0);
702         } else {
703                 host = NULL;
704                 port = 0;
705         }
706
707         transport_connect (host, port);
708
709         if (!on_startup) {
710                 /* Do some which is usually done after sending the VMStart () event */
711                 vm_start_event_sent = TRUE;
712                 start_debugger_thread ();
713         }
714 }
715
716 static void
717 mono_debugger_agent_cleanup (void)
718 {
719         if (!inited)
720                 return;
721
722         /* This will interrupt the agent thread */
723         /* Close the read part only so it can still send back replies */
724 #ifdef PLATFORM_WIN32
725         shutdown (conn_fd, SD_RECEIVE);
726 #else
727         shutdown (conn_fd, SHUT_RD);
728 #endif
729
730         /* 
731          * Wait for the thread to exit.
732          *
733          * If we continue with the shutdown without waiting for it, then the client might
734          * not receive an answer to its last command like a resume.
735          * The WaitForSingleObject infrastructure doesn't seem to work during shutdown, so
736          * use pthreads.
737          */
738         //WaitForSingleObject (debugger_thread_handle, INFINITE);
739         if (GetCurrentThreadId () != debugger_thread_id) {
740                 mono_mutex_lock (&debugger_thread_exited_mutex);
741                 if (!debugger_thread_exited)
742                         mono_cond_wait (&debugger_thread_exited_cond, &debugger_thread_exited_mutex);
743                 mono_mutex_unlock (&debugger_thread_exited_mutex);
744         }
745
746         breakpoints_cleanup ();
747         objrefs_cleanup ();
748         ids_cleanup ();
749 }
750
751 /*
752  * transport_connect:
753  *
754  *   Connect/Listen on HOST:PORT. If HOST is NULL, generate an address and listen on it.
755  */
756 static void
757 transport_connect (const char *host, int port)
758 {
759         struct addrinfo hints;
760         struct addrinfo *result, *rp;
761         int sfd, s, res;
762         char port_string [128];
763         char handshake_msg [128];
764         guint8 buf [128];
765
766         conn_fd = -1;
767
768         if (host) {
769                 sprintf (port_string, "%d", port);
770
771                 /* Obtain address(es) matching host/port */
772
773                 memset (&hints, 0, sizeof (struct addrinfo));
774                 hints.ai_family = AF_UNSPEC;    /* Allow IPv4 or IPv6 */
775                 hints.ai_socktype = SOCK_STREAM; /* Datagram socket */
776                 hints.ai_flags = 0;
777                 hints.ai_protocol = 0;          /* Any protocol */
778
779                 s = getaddrinfo (host, port_string, &hints, &result);
780                 if (s != 0) {
781                         fprintf (stderr, "debugger-agent: Unable to connect to %s:%d: %s\n", host, port, gai_strerror (s));
782                         exit (1);
783                 }
784         }
785
786         if (agent_config.server) {
787                 /* Wait for a connection */
788                 if (!host) {
789                         struct sockaddr_in addr;
790                         socklen_t addrlen;
791
792                         /* No address, generate one */
793                         sfd = socket (AF_INET, SOCK_STREAM, 0);
794                         g_assert (sfd);
795
796                         /* This will bind the socket to a random port */
797                         res = listen (sfd, 16);
798                         if (res == -1) {
799                                 fprintf (stderr, "debugger-agent: Unable to setup listening socket: %s\n", strerror (errno));
800                                 exit (1);
801                         }
802
803                         addrlen = sizeof (addr);
804                         memset (&addr, 0, sizeof (addr));
805                         res = getsockname (sfd, &addr, &addrlen);
806                         g_assert (res == 0);
807
808                         host = "127.0.0.1";
809                         port = ntohs (addr.sin_port);
810
811                         /* Emit the address to stdout */
812                         /* FIXME: Should print another interface, not localhost */
813                         printf ("%s:%d\n", host, port);
814                 } else {
815                         /* Listen on the provided address */
816                         for (rp = result; rp != NULL; rp = rp->ai_next) {
817                                 sfd = socket (rp->ai_family, rp->ai_socktype,
818                                                           rp->ai_protocol);
819                                 if (sfd == -1)
820                                         continue;
821
822                                 res = bind (sfd, rp->ai_addr, rp->ai_addrlen);
823                                 if (res == -1)
824                                         continue;
825
826                                 res = listen (sfd, 16);
827                                 if (res == -1)
828                                         continue;
829                                 break;
830                         }
831
832                         freeaddrinfo (result);
833                 }
834
835                 DEBUG (1, fprintf (log_file, "Listening on %s:%d (timeout=%d ms)...\n", host, port, agent_config.timeout));
836
837                 if (agent_config.timeout) {
838                         fd_set readfds;
839                         struct timeval tv;
840
841                         tv.tv_sec = 0;
842                         tv.tv_usec = agent_config.timeout * 1000;
843                         FD_ZERO (&readfds);
844                         FD_SET (sfd, &readfds);
845                         res = select (sfd + 1, &readfds, NULL, NULL, &tv);
846                         if (res == 0) {
847                                 fprintf (stderr, "debugger-agent: Timed out waiting to connect.\n");
848                                 exit (1);
849                         }
850                 }
851
852                 conn_fd = accept (sfd, NULL, NULL);
853                 if (conn_fd == -1) {
854                         fprintf (stderr, "debugger-agent: Unable to listen on %s:%d\n", host, port);
855                         exit (1);
856                 }
857
858                 DEBUG (1, fprintf (log_file, "Accepted connection from client, socket fd=%d.\n", conn_fd));
859         } else {
860                 /* Connect to the specified address */
861                 /* FIXME: Respect the timeout */
862                 for (rp = result; rp != NULL; rp = rp->ai_next) {
863                         sfd = socket (rp->ai_family, rp->ai_socktype,
864                                                   rp->ai_protocol);
865                         if (sfd == -1)
866                                 continue;
867
868                         if (connect (sfd, rp->ai_addr, rp->ai_addrlen) != -1)
869                                 break;       /* Success */
870                         
871                         close (sfd);
872                 }
873
874                 conn_fd = sfd;
875
876                 freeaddrinfo (result);
877
878                 if (rp == 0) {
879                         fprintf (stderr, "debugger-agent: Unable to connect to %s:%d\n", host, port);
880                         exit (1);
881                 }
882         }
883         
884         /* Write handshake message */
885         sprintf (handshake_msg, "DWP-Handshake");
886         res = write (conn_fd, handshake_msg, strlen (handshake_msg));
887         g_assert (res != -1);
888
889         /* Read answer */
890         res = read (conn_fd, buf, strlen (handshake_msg));
891         if ((res != strlen (handshake_msg)) || (memcmp (buf, handshake_msg, strlen (handshake_msg) != 0))) {
892                 fprintf (stderr, "debugger-agent: DWP handshake failed.\n");
893                 exit (1);
894         }
895
896         /* 
897          * Set TCP_NODELAY on the socket so the client receives events/command
898          * results immediately.
899          */
900         {
901                 int flag = 1;
902                 int result = setsockopt(conn_fd,
903                                  IPPROTO_TCP,
904                                  TCP_NODELAY,
905                                  (char *) &flag,
906                                  sizeof(int));
907                 g_assert (result >= 0);
908         }
909 }
910
911 static gboolean
912 transport_send (guint8 *data, int len)
913 {
914         int res;
915
916         res = write (conn_fd, data, len);
917         if (res != len)
918                 return FALSE;
919         else
920                 return TRUE;
921 }
922
923 static void
924 start_debugger_thread (void)
925 {
926         gsize tid;
927
928         debugger_thread_handle = mono_create_thread (NULL, 0, debugger_thread, NULL, 0, &tid);
929         g_assert (debugger_thread_handle);
930 }
931
932 /*
933  * Functions to decode protocol data
934  */
935
936 static inline int
937 decode_byte (guint8 *buf, guint8 **endbuf, guint8 *limit)
938 {
939         *endbuf = buf + 1;
940         g_assert (*endbuf <= limit);
941         return buf [0];
942 }
943
944 static inline int
945 decode_int (guint8 *buf, guint8 **endbuf, guint8 *limit)
946 {
947         *endbuf = buf + 4;
948         g_assert (*endbuf <= limit);
949
950         return (((int)buf [0]) << 24) | (((int)buf [1]) << 16) | (((int)buf [2]) << 8) | (((int)buf [3]) << 0);
951 }
952
953 static inline gint64
954 decode_long (guint8 *buf, guint8 **endbuf, guint8 *limit)
955 {
956         guint32 high = decode_int (buf, &buf, limit);
957         guint32 low = decode_int (buf, &buf, limit);
958
959         *endbuf = buf;
960
961         return ((((guint64)high) << 32) | ((guint64)low));
962 }
963
964 static inline int
965 decode_id (guint8 *buf, guint8 **endbuf, guint8 *limit)
966 {
967         return decode_int (buf, endbuf, limit);
968 }
969
970 static inline char*
971 decode_string (guint8 *buf, guint8 **endbuf, guint8 *limit)
972 {
973         int len = decode_int (buf, &buf, limit);
974         char *s;
975
976         s = g_malloc (len + 1);
977         g_assert (s);
978
979         memcpy (s, buf, len);
980         s [len] = '\0';
981         buf += len;
982         *endbuf = buf;
983
984         return s;
985 }
986
987 /*
988  * Functions to encode protocol data
989  */
990
991 typedef struct {
992         guint8 *buf, *p, *end;
993 } Buffer;
994
995 static inline void
996 buffer_init (Buffer *buf, int size)
997 {
998         buf->buf = g_malloc (size);
999         buf->p = buf->buf;
1000         buf->end = buf->buf + size;
1001 }
1002
1003 static inline void
1004 buffer_make_room (Buffer *buf, int size)
1005 {
1006         if (buf->end - buf->p < size) {
1007                 int new_size = buf->end - buf->buf + size + 32;
1008                 guint8 *p = g_realloc (buf->buf, new_size);
1009                 size = buf->p - buf->buf;
1010                 buf->buf = p;
1011                 buf->p = p + size;
1012                 buf->end = buf->buf + new_size;
1013         }
1014 }
1015
1016 static inline void
1017 buffer_add_byte (Buffer *buf, guint8 val)
1018 {
1019         buffer_make_room (buf, 1);
1020         buf->p [0] = val;
1021         buf->p++;
1022 }
1023
1024 static inline void
1025 buffer_add_int (Buffer *buf, guint32 val)
1026 {
1027         buffer_make_room (buf, 4);
1028         buf->p [0] = (val >> 24) & 0xff;
1029         buf->p [1] = (val >> 16) & 0xff;
1030         buf->p [2] = (val >> 8) & 0xff;
1031         buf->p [3] = (val >> 0) & 0xff;
1032         buf->p += 4;
1033 }
1034
1035 static inline void
1036 buffer_add_long (Buffer *buf, guint64 l)
1037 {
1038         buffer_add_int (buf, (l >> 32) & 0xffffffff);
1039         buffer_add_int (buf, (l >> 0) & 0xffffffff);
1040 }
1041
1042 static inline void
1043 buffer_add_id (Buffer *buf, int id)
1044 {
1045         buffer_add_int (buf, (guint64)id);
1046 }
1047
1048 static inline void
1049 buffer_add_data (Buffer *buf, guint8 *data, int len)
1050 {
1051         buffer_make_room (buf, len);
1052         memcpy (buf->p, data, len);
1053         buf->p += len;
1054 }
1055
1056 static inline void
1057 buffer_add_string (Buffer *buf, const char *str)
1058 {
1059         int len;
1060
1061         if (str == NULL) {
1062                 buffer_add_int (buf, 0);
1063         } else {
1064                 len = strlen (str);
1065                 buffer_add_int (buf, len);
1066                 buffer_add_data (buf, (guint8*)str, len);
1067         }
1068 }
1069
1070 static inline void
1071 buffer_free (Buffer *buf)
1072 {
1073         g_free (buf->buf);
1074 }
1075
1076 static gboolean
1077 send_packet (int command_set, int command, Buffer *data)
1078 {
1079         Buffer buf;
1080         int len, id;
1081         gboolean res;
1082
1083         id = InterlockedIncrement (&packet_id);
1084
1085         len = data->p - data->buf + 11;
1086         buffer_init (&buf, len);
1087         buffer_add_int (&buf, len);
1088         buffer_add_int (&buf, id);
1089         buffer_add_byte (&buf, 0); /* flags */
1090         buffer_add_byte (&buf, command_set);
1091         buffer_add_byte (&buf, command);
1092         memcpy (buf.buf + 11, data->buf, data->p - data->buf);
1093
1094         res = transport_send (buf.buf, len);
1095
1096         buffer_free (&buf);
1097
1098         return res;
1099 }
1100
1101 static gboolean
1102 send_reply_packet (int id, int error, Buffer *data)
1103 {
1104         Buffer buf;
1105         int len;
1106         gboolean res;
1107         
1108         len = data->p - data->buf + 11;
1109         buffer_init (&buf, len);
1110         buffer_add_int (&buf, len);
1111         buffer_add_int (&buf, id);
1112         buffer_add_byte (&buf, 0x80); /* flags */
1113         buffer_add_byte (&buf, (error >> 8) & 0xff);
1114         buffer_add_byte (&buf, error);
1115         memcpy (buf.buf + 11, data->buf, data->p - data->buf);
1116
1117         res = transport_send (buf.buf, len);
1118
1119         buffer_free (&buf);
1120
1121         return res;
1122 }
1123
1124 /*
1125  * OBJECT IDS
1126  */
1127
1128 /*
1129  * Represents an object accessible by the debugger client.
1130  */
1131 typedef struct {
1132         /* Unique id used in the wire protocol to refer to objects */
1133         int id;
1134         /*
1135          * A weakref gc handle pointing to the object. The gc handle is used to 
1136          * detect if the object was garbage collected.
1137          */
1138         guint32 handle;
1139 } ObjRef;
1140
1141 /* Maps objid -> ObjRef */
1142 static GHashTable *objrefs;
1143
1144 static void
1145 free_objref (gpointer value)
1146 {
1147         ObjRef *o = value;
1148
1149         mono_gchandle_free (o->handle);
1150
1151         g_free (o);
1152 }
1153
1154 static void
1155 objrefs_init (void)
1156 {
1157         objrefs = g_hash_table_new_full (NULL, NULL, NULL, free_objref);
1158 }
1159
1160 static void
1161 objrefs_cleanup (void)
1162 {
1163         g_hash_table_destroy (objrefs);
1164         objrefs = NULL;
1165 }
1166
1167 static GHashTable *obj_to_objref;
1168
1169 /*
1170  * Return an ObjRef for OBJ.
1171  */
1172 static ObjRef*
1173 get_objref (MonoObject *obj)
1174 {
1175         ObjRef *ref;
1176
1177         if (obj == NULL)
1178                 return 0;
1179
1180 #ifdef HAVE_SGEN_GC
1181         NOT_IMPLEMENTED;
1182 #endif
1183
1184         /* Use a hash table with masked pointers to internalize object references */
1185         /* FIXME: This can grow indefinitely */
1186         mono_loader_lock ();
1187
1188         if (!obj_to_objref)
1189                 obj_to_objref = g_hash_table_new (NULL, NULL);
1190
1191         ref = g_hash_table_lookup (obj_to_objref, GINT_TO_POINTER (~((gsize)obj)));
1192         /* ref might refer to a different object with the same addr which was GCd */
1193         if (ref && mono_gchandle_get_target (ref->handle) == obj) {
1194                 mono_loader_unlock ();
1195                 return ref;
1196         }
1197
1198         ref = g_new0 (ObjRef, 1);
1199         ref->id = InterlockedIncrement (&objref_id);
1200         ref->handle = mono_gchandle_new_weakref (obj, FALSE);
1201
1202         g_hash_table_insert (objrefs, GINT_TO_POINTER (ref->id), ref);
1203         g_hash_table_insert (obj_to_objref, GINT_TO_POINTER (~((gsize)obj)), ref);
1204
1205         mono_loader_unlock ();
1206
1207         return ref;
1208 }
1209
1210 static inline int
1211 get_objid (MonoObject *obj)
1212 {
1213         return get_objref (obj)->id;
1214 }
1215
1216 /*
1217  * Set OBJ to the object identified by OBJID.
1218  * Returns 0 or an error code if OBJID is invalid or the object has been garbage
1219  * collected.
1220  */
1221 static ErrorCode
1222 get_object_allow_null (int objid, MonoObject **obj)
1223 {
1224         ObjRef *ref;
1225
1226         if (objid == 0) {
1227                 *obj = NULL;
1228                 return 0;
1229         }
1230
1231         if (!objrefs)
1232                 return ERR_INVALID_OBJECT;
1233
1234         mono_loader_lock ();
1235
1236         ref = g_hash_table_lookup (objrefs, GINT_TO_POINTER (objid));
1237
1238         if (ref) {
1239                 *obj = mono_gchandle_get_target (ref->handle);
1240                 mono_loader_unlock ();
1241                 if (!(*obj))
1242                         return ERR_INVALID_OBJECT;
1243                 return 0;
1244         } else {
1245                 mono_loader_unlock ();
1246                 return ERR_INVALID_OBJECT;
1247         }
1248 }
1249
1250 static ErrorCode
1251 get_object (int objid, MonoObject **obj)
1252 {
1253         int err = get_object_allow_null (objid, obj);
1254
1255         if (err)
1256                 return err;
1257         if (!(*obj))
1258                 return ERR_INVALID_OBJECT;
1259         return 0;
1260 }
1261
1262 static inline int
1263 decode_objid (guint8 *buf, guint8 **endbuf, guint8 *limit)
1264 {
1265         return decode_id (buf, endbuf, limit);
1266 }
1267
1268 static inline void
1269 buffer_add_objid (Buffer *buf, MonoObject *o)
1270 {
1271         buffer_add_id (buf, get_objid (o));
1272 }
1273
1274 /*
1275  * IDS
1276  */
1277
1278 typedef enum {
1279         ID_ASSEMBLY = 0,
1280         ID_MODULE = 1,
1281         ID_TYPE = 2,
1282         ID_METHOD = 3,
1283         ID_FIELD = 4,
1284         ID_DOMAIN = 5,
1285         ID_PROPERTY = 6,
1286         ID_NUM
1287 } IdType;
1288
1289 /*
1290  * Represents a runtime structure accessible to the debugger client
1291  */
1292 typedef struct {
1293         /* Unique id used in the wire protocol */
1294         int id;
1295         /* Domain of the runtime structure, NULL if the domain was unloaded */
1296         MonoDomain *domain;
1297         union {
1298                 gpointer val;
1299                 MonoClass *klass;
1300                 MonoMethod *method;
1301                 MonoImage *image;
1302                 MonoAssembly *assembly;
1303                 MonoClassField *field;
1304                 MonoDomain *domain;
1305                 MonoProperty *property;
1306         } data;
1307 } Id;
1308
1309 typedef struct {
1310         /* Maps runtime structure -> Id */
1311         GHashTable *val_to_id [ID_NUM];
1312 } AgentDomainInfo;
1313
1314 /* Maps id -> Id */
1315 static GPtrArray *ids [ID_NUM];
1316
1317 static void
1318 ids_init (void)
1319 {
1320         int i;
1321
1322         for (i = 0; i < ID_NUM; ++i)
1323                 ids [i] = g_ptr_array_new ();
1324 }
1325
1326 static void
1327 ids_cleanup (void)
1328 {
1329         int i, j;
1330
1331         for (i = 0; i < ID_NUM; ++i) {
1332                 if (ids [i]) {
1333                         for (j = 0; j < ids [i]->len; ++j)
1334                                 g_free (g_ptr_array_index (ids [i], j));
1335                         g_ptr_array_free (ids [i], TRUE);
1336                 }
1337                 ids [i] = NULL;
1338         }
1339 }
1340
1341 void
1342 mono_debugger_agent_free_domain_info (MonoDomain *domain)
1343 {
1344         AgentDomainInfo *info = domain_jit_info (domain)->agent_info;
1345         int i, j;
1346
1347         if (info) {
1348                 for (i = 0; i < ID_NUM; ++i)
1349                         if (info->val_to_id [i])
1350                                 g_hash_table_destroy (info->val_to_id [i]);
1351                 g_free (info);
1352         }
1353
1354         domain_jit_info (domain)->agent_info = NULL;
1355
1356         /* Clear ids referencing structures in the domain */
1357         for (i = 0; i < ID_NUM; ++i) {
1358                 if (ids [i]) {
1359                         for (j = 0; j < ids [i]->len; ++j) {
1360                                 Id *id = g_ptr_array_index (ids [i], j);
1361                                 if (id->domain == domain)
1362                                         id->domain = NULL;
1363                         }
1364                 }
1365         }
1366 }
1367
1368 static int
1369 get_id (MonoDomain *domain, IdType type, gpointer val)
1370 {
1371         Id *id;
1372         AgentDomainInfo *info;
1373
1374         if (val == NULL)
1375                 return 0;
1376
1377         mono_loader_lock ();
1378
1379         mono_domain_lock (domain);
1380
1381         if (!domain_jit_info (domain)->agent_info)
1382                 domain_jit_info (domain)->agent_info = g_new0 (AgentDomainInfo, 1);
1383         info = domain_jit_info (domain)->agent_info;
1384         if (info->val_to_id [type] == NULL)
1385                 info->val_to_id [type] = g_hash_table_new (mono_aligned_addr_hash, NULL);
1386
1387         id = g_hash_table_lookup (info->val_to_id [type], val);
1388         if (id) {
1389                 mono_domain_unlock (domain);
1390                 mono_loader_unlock ();
1391                 return id->id;
1392         }
1393
1394         id = g_new0 (Id, 1);
1395         /* Reserve id 0 */
1396         id->id = ids [type]->len + 1;
1397         id->domain = domain;
1398         id->data.val = val;
1399
1400         g_hash_table_insert (info->val_to_id [type], val, id);
1401
1402         mono_domain_unlock (domain);
1403
1404         g_ptr_array_add (ids [type], id);
1405
1406         mono_loader_unlock ();
1407
1408         return id->id;
1409 }
1410
1411 static inline gpointer
1412 decode_ptr_id (guint8 *buf, guint8 **endbuf, guint8 *limit, IdType type, MonoDomain **domain, int *err)
1413 {
1414         Id *res;
1415
1416         int id = decode_id (buf, endbuf, limit);
1417
1418         *err = 0;
1419         if (domain)
1420                 *domain = NULL;
1421
1422         if (id == 0)
1423                 return NULL;
1424
1425         // FIXME: error handling
1426         mono_loader_lock ();
1427         g_assert (id > 0 && id <= ids [type]->len);
1428
1429         res = g_ptr_array_index (ids [type], GPOINTER_TO_INT (id - 1));
1430         mono_loader_unlock ();
1431
1432         if (res->domain == NULL) {
1433                 *err = ERR_UNLOADED;
1434                 return NULL;
1435         }
1436
1437         if (domain)
1438                 *domain = res->domain;
1439
1440         return res->data.val;
1441 }
1442
1443 static inline void
1444 buffer_add_ptr_id (Buffer *buf, MonoDomain *domain, IdType type, gpointer val)
1445 {
1446         buffer_add_id (buf, get_id (domain, type, val));
1447 }
1448
1449 static inline MonoClass*
1450 decode_typeid (guint8 *buf, guint8 **endbuf, guint8 *limit, MonoDomain **domain, int *err)
1451 {
1452         return decode_ptr_id (buf, endbuf, limit, ID_TYPE, domain, err);
1453 }
1454
1455 static inline MonoAssembly*
1456 decode_assemblyid (guint8 *buf, guint8 **endbuf, guint8 *limit, MonoDomain **domain, int *err)
1457 {
1458         return decode_ptr_id (buf, endbuf, limit, ID_ASSEMBLY, domain, err);
1459 }
1460
1461 static inline MonoImage*
1462 decode_moduleid (guint8 *buf, guint8 **endbuf, guint8 *limit, MonoDomain **domain, int *err)
1463 {
1464         return decode_ptr_id (buf, endbuf, limit, ID_MODULE, domain, err);
1465 }
1466
1467 static inline MonoMethod*
1468 decode_methodid (guint8 *buf, guint8 **endbuf, guint8 *limit, MonoDomain **domain, int *err)
1469 {
1470         return decode_ptr_id (buf, endbuf, limit, ID_METHOD, domain, err);
1471 }
1472
1473 static inline MonoClassField*
1474 decode_fieldid (guint8 *buf, guint8 **endbuf, guint8 *limit, MonoDomain **domain, int *err)
1475 {
1476         return decode_ptr_id (buf, endbuf, limit, ID_FIELD, domain, err);
1477 }
1478
1479 static inline MonoDomain*
1480 decode_domainid (guint8 *buf, guint8 **endbuf, guint8 *limit, MonoDomain **domain, int *err)
1481 {
1482         return decode_ptr_id (buf, endbuf, limit, ID_DOMAIN, domain, err);
1483 }
1484
1485 static inline MonoProperty*
1486 decode_propertyid (guint8 *buf, guint8 **endbuf, guint8 *limit, MonoDomain **domain, int *err)
1487 {
1488         return decode_ptr_id (buf, endbuf, limit, ID_PROPERTY, domain, err);
1489 }
1490
1491 static inline void
1492 buffer_add_typeid (Buffer *buf, MonoDomain *domain, MonoClass *klass)
1493 {
1494         buffer_add_ptr_id (buf, domain, ID_TYPE, klass);
1495 }
1496
1497 static inline void
1498 buffer_add_methodid (Buffer *buf, MonoDomain *domain, MonoMethod *method)
1499 {
1500         buffer_add_ptr_id (buf, domain, ID_METHOD, method);
1501 }
1502
1503 static inline void
1504 buffer_add_assemblyid (Buffer *buf, MonoDomain *domain, MonoAssembly *assembly)
1505 {
1506         buffer_add_ptr_id (buf, domain, ID_ASSEMBLY, assembly);
1507 }
1508
1509 static inline void
1510 buffer_add_moduleid (Buffer *buf, MonoDomain *domain, MonoImage *image)
1511 {
1512         buffer_add_ptr_id (buf, domain, ID_MODULE, image);
1513 }
1514
1515 static inline void
1516 buffer_add_fieldid (Buffer *buf, MonoDomain *domain, MonoClassField *field)
1517 {
1518         buffer_add_ptr_id (buf, domain, ID_FIELD, field);
1519 }
1520
1521 static inline void
1522 buffer_add_propertyid (Buffer *buf, MonoDomain *domain, MonoProperty *property)
1523 {
1524         buffer_add_ptr_id (buf, domain, ID_PROPERTY, property);
1525 }
1526
1527 static inline void
1528 buffer_add_domainid (Buffer *buf, MonoDomain *domain)
1529 {
1530         buffer_add_ptr_id (buf, domain, ID_DOMAIN, domain);
1531 }
1532
1533 static void invoke_method (void);
1534
1535 /*
1536  * SUSPEND/RESUME
1537  */
1538
1539 static void
1540 save_thread_context (MonoContext *ctx)
1541 {
1542         DebuggerTlsData *tls;
1543
1544         tls = TlsGetValue (debugger_tls_id);
1545         g_assert (tls);
1546
1547         if (ctx) {
1548                 memcpy (&tls->ctx, ctx, sizeof (MonoContext));
1549         } else {
1550 #ifdef MONO_INIT_CONTEXT_FROM_CURRENT
1551                 MONO_INIT_CONTEXT_FROM_CURRENT (&tls->ctx);
1552 #else
1553                 MONO_INIT_CONTEXT_FROM_FUNC (&tls->ctx, save_thread_context);
1554 #endif
1555         }
1556
1557         tls->lmf = mono_get_lmf ();
1558         tls->domain = mono_domain_get ();
1559         tls->has_context = TRUE;
1560 }
1561
1562 /* The number of times the runtime is suspended */
1563 static gint32 suspend_count;
1564
1565 /* Number of threads suspended */
1566 /* 
1567  * If this is equal to the size of thread_to_tls, the runtime is considered
1568  * suspended.
1569  */
1570 static gint32 threads_suspend_count;
1571
1572 static mono_mutex_t suspend_mutex = MONO_MUTEX_INITIALIZER;
1573
1574 /* Cond variable used to wait for suspend_count becoming 0 */
1575 static mono_cond_t suspend_cond = MONO_COND_INITIALIZER;
1576
1577 /* Semaphore used to wait for a thread becoming suspended */
1578 static MonoSemType suspend_sem;
1579
1580 static void
1581 suspend_init (void)
1582 {
1583         MONO_SEM_INIT (&suspend_sem, 0);
1584 }
1585
1586 /*
1587  * mono_debugger_agent_thread_interrupt:
1588  *
1589  *   Called by the abort signal handler.
1590  */
1591 gboolean
1592 mono_debugger_agent_thread_interrupt (MonoJitInfo *ji)
1593 {
1594         DebuggerTlsData *tls;
1595
1596         if (!inited)
1597                 return FALSE;
1598
1599         tls = TlsGetValue (debugger_tls_id);
1600         if (!tls)
1601                 return FALSE;
1602
1603         /*
1604          * We use interrupt_count to determine whenever this interrupt should be processed
1605          * by us or the normal interrupt processing code in the signal handler.
1606          * There is no race here with notify_thread (), since the signal is sent after
1607          * incrementing interrupt_count.
1608          */
1609         if (tls->interrupt_count == 0)
1610                 return FALSE;
1611
1612         InterlockedDecrement (&tls->interrupt_count);
1613
1614         // FIXME: Races when the thread leaves managed code before hitting a single step
1615         // event.
1616
1617         if (ji) {
1618                 /* Running managed code, will be suspended by the single step code */
1619                 //printf ("S1: %p\n", GetCurrentThreadId ());
1620                 return TRUE;
1621         } else {
1622                 /* 
1623                  * Running native code, will be suspended when it returns to/enters 
1624                  * managed code. Treat it as already suspended.
1625                  */
1626                 //printf ("S2: %p\n", GetCurrentThreadId ());
1627                 if (!tls->suspended) {
1628                         tls->suspended = TRUE;
1629                         MONO_SEM_POST (&suspend_sem);
1630                 }
1631                 return TRUE;
1632         }
1633 }
1634
1635 /*
1636  * notify_thread:
1637  *
1638  *   Notify a thread that it needs to suspend.
1639  */
1640 static void
1641 notify_thread (gpointer key, gpointer value, gpointer user_data)
1642 {
1643         MonoInternalThread *thread = key;
1644         DebuggerTlsData *tls = value;
1645         gsize tid = thread->tid;
1646
1647         if (GetCurrentThreadId () != tid) {
1648                 DEBUG(1, fprintf (log_file, "[%p] Interrupting %p...\n", (gpointer)GetCurrentThreadId (), (gpointer)tid));
1649                 /*
1650                  * Maybe we could use the normal interrupt infrastructure, but that does a lot
1651                  * of things like breaking waits etc. which we don't want.
1652                  */
1653                 InterlockedIncrement (&tls->interrupt_count);
1654 #ifdef PLATFORM_WIN32
1655                 /*FIXME: Abort thread */
1656 #else
1657                 pthread_kill ((pthread_t) tid, mono_thread_get_abort_signal ());
1658 #endif
1659         }
1660 }
1661
1662 /*
1663  * suspend_vm:
1664  *
1665  * Increase the suspend count of the VM. While the suspend count is greater 
1666  * than 0, runtime threads are suspended at certain points during execution.
1667  */
1668 static void
1669 suspend_vm (void)
1670 {
1671         mono_loader_lock ();
1672
1673         mono_mutex_lock (&suspend_mutex);
1674
1675         suspend_count ++;
1676
1677         DEBUG(1, fprintf (log_file, "[%p] Suspending vm...\n", (gpointer)GetCurrentThreadId ()));
1678
1679         if (suspend_count == 1) {
1680                 // FIXME: Is it safe to call this inside the lock ?
1681                 start_single_stepping ();
1682                 mono_g_hash_table_foreach (thread_to_tls, notify_thread, NULL);
1683         }
1684
1685         mono_mutex_unlock (&suspend_mutex);
1686
1687         mono_loader_unlock ();
1688 }
1689
1690 /*
1691  * resume_vm:
1692  *
1693  * Decrease the suspend count of the VM. If the count reaches 0, runtime threads
1694  * are resumed.
1695  */
1696 static void
1697 resume_vm (void)
1698 {
1699         int err;
1700
1701         g_assert (debugger_thread_id == GetCurrentThreadId ());
1702
1703         mono_loader_lock ();
1704
1705         mono_mutex_lock (&suspend_mutex);
1706
1707         g_assert (suspend_count > 0);
1708         suspend_count --;
1709
1710         DEBUG(1, fprintf (log_file, "[%p] Resuming vm...\n", (gpointer)GetCurrentThreadId ()));
1711
1712         if (suspend_count == 0) {
1713                 // FIXME: Is it safe to call this inside the lock ?
1714                 stop_single_stepping ();
1715                 err = mono_cond_broadcast (&suspend_cond);
1716                 g_assert (err == 0);
1717         }
1718
1719         err = mono_mutex_unlock (&suspend_mutex);
1720         g_assert (err == 0);
1721
1722         mono_loader_unlock ();
1723 }
1724
1725 static void
1726 invalidate_frames (DebuggerTlsData *tls)
1727 {
1728         int i;
1729
1730         if (!tls)
1731                 tls = TlsGetValue (debugger_tls_id);
1732         g_assert (tls);
1733
1734         for (i = 0; i < tls->frame_count; ++i) {
1735                 if (tls->frames [i]->jit)
1736                         mono_debug_free_method_jit_info (tls->frames [i]->jit);
1737                 g_free (tls->frames [i]);
1738         }
1739         g_free (tls->frames);
1740         tls->frame_count = 0;
1741         tls->frames = NULL;
1742 }
1743
1744 /*
1745  * suspend_current:
1746  *
1747  *   Suspend the current thread until the runtime is resumed. If the thread has a 
1748  * pending invoke, then the invoke is executed before this function returns. 
1749  */
1750 static void
1751 suspend_current (void)
1752 {
1753         int err;
1754         DebuggerTlsData *tls;
1755
1756         g_assert (debugger_thread_id != GetCurrentThreadId ());
1757
1758         if (mono_loader_lock_is_owned_by_self ()) {
1759                 /*
1760                  * If we own the loader mutex, can't suspend until we release it, since the
1761                  * whole runtime can deadlock otherwise.
1762                  */
1763                 return;
1764         }
1765
1766         tls = TlsGetValue (debugger_tls_id);
1767         g_assert (tls);
1768
1769         mono_mutex_lock (&suspend_mutex);
1770
1771         if (!tls->suspended) {
1772                 tls->suspended = TRUE;
1773                 MONO_SEM_POST (&suspend_sem);
1774         }
1775
1776         DEBUG(1, fprintf (log_file, "[%p] Suspended.\n", (gpointer)GetCurrentThreadId ()));
1777
1778         while (suspend_count > 0) {
1779                 err = mono_cond_wait (&suspend_cond, &suspend_mutex);
1780                 g_assert (err == 0);
1781         }
1782
1783         tls->suspended = FALSE;
1784
1785         threads_suspend_count --;
1786
1787         mono_mutex_unlock (&suspend_mutex);
1788
1789         DEBUG(1, fprintf (log_file, "[%p] Resumed.\n", (gpointer)GetCurrentThreadId ()));
1790
1791         if (tls->invoke) {
1792                 /* Save the original context */
1793                 tls->invoke->has_ctx = TRUE;
1794                 memcpy (&tls->invoke->ctx, &tls->ctx, sizeof (MonoContext));
1795
1796                 invoke_method ();
1797         }
1798
1799         /* The frame info becomes invalid after a resume */
1800         tls->has_context = FALSE;
1801         invalidate_frames (NULL);
1802 }
1803
1804 static void
1805 count_thread (gpointer key, gpointer value, gpointer user_data)
1806 {
1807         DebuggerTlsData *tls = value;
1808
1809         if (!tls->suspended && !tls->terminated)
1810                 *(int*)user_data = *(int*)user_data + 1;
1811 }
1812
1813 static int
1814 count_threads_to_wait_for (void)
1815 {
1816         int count = 0;
1817
1818         mono_loader_lock ();
1819         mono_g_hash_table_foreach (thread_to_tls, count_thread, &count);
1820         mono_loader_unlock ();
1821
1822         return count;
1823 }       
1824
1825 /*
1826  * wait_for_suspend:
1827  *
1828  *   Wait until the runtime is completely suspended.
1829  */
1830 static void
1831 wait_for_suspend (void)
1832 {
1833         int nthreads, nwait, err;
1834         gboolean waited = FALSE;
1835
1836         // FIXME: Threads starting/stopping ?
1837         mono_loader_lock ();
1838         nthreads = mono_g_hash_table_size (thread_to_tls);
1839         mono_loader_unlock ();
1840
1841         while (TRUE) {
1842                 nwait = count_threads_to_wait_for ();
1843                 if (nwait) {
1844                         DEBUG(1, fprintf (log_file, "Waiting for %d(%d) threads to suspend...\n", nwait, nthreads));
1845                         err = MONO_SEM_WAIT (&suspend_sem);
1846                         g_assert (err == 0);
1847                         waited = TRUE;
1848                 } else {
1849                         break;
1850                 }
1851         }
1852
1853         if (waited)
1854                 DEBUG(1, fprintf (log_file, "%d threads suspended.\n", nthreads));
1855 }
1856
1857 /*
1858  * is_suspended:
1859  *
1860  *   Return whenever the runtime is suspended.
1861  */
1862 static gboolean
1863 is_suspended (void)
1864 {
1865         return count_threads_to_wait_for () == 0;
1866 }
1867
1868 /*
1869  * compute_il_offset:
1870  *
1871  *    Compute the IL offset corresponding to NATIVE_OFFSET, which should be
1872  * a location of a sequence point.
1873  * We use this function instead of mono_debug_il_offset_from_address () etc,
1874  * which doesn't seem to work in a lot of cases.
1875  */
1876 static gint32
1877 compute_il_offset (MonoDomain *domain, MonoMethod *method, gint32 native_offset)
1878 {
1879         GPtrArray *seq_points;
1880         int i, last_il_offset, seq_il_offset, seq_native_offset;
1881
1882         mono_domain_lock (domain);
1883         seq_points = g_hash_table_lookup (domain_jit_info (domain)->seq_points, method);
1884         mono_domain_unlock (domain);
1885         g_assert (seq_points);
1886
1887         last_il_offset = -1;
1888
1889         /* Find the sequence point */
1890         for (i = 0; i < seq_points->len; i += 2) {
1891                 seq_il_offset = GPOINTER_TO_UINT (g_ptr_array_index (seq_points, i));
1892                 seq_native_offset = GPOINTER_TO_UINT (g_ptr_array_index (seq_points, i + 1));
1893
1894                 if (seq_native_offset > native_offset)
1895                         break;
1896                 last_il_offset = seq_il_offset;
1897         }
1898
1899         return last_il_offset;
1900 }
1901
1902 typedef struct {
1903         DebuggerTlsData *tls;
1904         GSList *frames;
1905 } ComputeFramesUserData;
1906
1907 static gboolean
1908 process_frame (StackFrameInfo *info, MonoContext *ctx, gpointer user_data)
1909 {
1910         ComputeFramesUserData *ud = user_data;
1911         StackFrame *frame;
1912         MonoMethod *method;
1913
1914         if (info->type != FRAME_TYPE_MANAGED) {
1915                 if (info->type == FRAME_TYPE_DEBUGGER_INVOKE) {
1916                         /* Mark the last frame as an invoke frame */
1917                         if (ud->frames)
1918                                 ((StackFrame*)ud->frames->data)->flags |= FRAME_FLAG_DEBUGGER_INVOKE;
1919                 }
1920                 return FALSE;
1921         }
1922
1923         if (info->ji)
1924                 method = info->ji->method;
1925         else
1926                 method = info->method;
1927
1928         if (!method || (method->wrapper_type && method->wrapper_type != MONO_WRAPPER_DYNAMIC_METHOD))
1929                 return FALSE;
1930
1931         if (info->il_offset == -1) {
1932                 /* Can't use compute_il_offset () since ip doesn't point precisely at at a seq point */
1933                 info->il_offset = mono_debug_il_offset_from_address (method, info->domain, info->native_offset);
1934         }
1935
1936         DEBUG (1, fprintf (stderr, "\tFrame: %s %d %d %d\n", mono_method_full_name (method, TRUE), info->native_offset, info->il_offset, info->managed));
1937
1938         if (!info->managed && method->wrapper_type != MONO_WRAPPER_DYNAMIC_METHOD) {
1939                 /*
1940                  * mono_arch_find_jit_info () returns the context stored in the LMF for 
1941                  * native frames, but it should unwind once. This is why we have duplicate
1942                  * frames on the stack sometimes.
1943                  * !managed also seems to be set for dynamic methods.
1944                  */
1945                 return FALSE;
1946         }
1947
1948         frame = g_new0 (StackFrame, 1);
1949         frame->method = method;
1950         frame->il_offset = info->il_offset;
1951         frame->ctx = *ctx;
1952         frame->domain = info->domain;
1953
1954         ud->frames = g_slist_append (ud->frames, frame);
1955
1956         return FALSE;
1957 }
1958
1959 static void
1960 compute_frame_info (MonoInternalThread *thread, DebuggerTlsData *tls)
1961 {
1962         ComputeFramesUserData user_data;
1963         GSList *tmp;
1964         int i, findex, new_frame_count;
1965         StackFrame **new_frames, *f;
1966
1967         // FIXME: Locking on tls
1968         if (tls->frames && tls->frames_up_to_date)
1969                 return;
1970
1971         DEBUG(1, fprintf (log_file, "Frames for %p(tid=%lx):\n", thread, (glong)thread->tid));
1972
1973         user_data.tls = tls;
1974         user_data.frames = NULL;
1975         if (tls->has_context) {
1976                 mono_jit_walk_stack_from_ctx_in_thread (process_frame, tls->domain, &tls->ctx, FALSE, thread, tls->lmf, &user_data);
1977         } else {
1978                 // FIXME:
1979                 tls->frame_count = 0;
1980                 return;
1981         }
1982
1983         new_frame_count = g_slist_length (user_data.frames);
1984         new_frames = g_new0 (StackFrame*, new_frame_count);
1985         findex = 0;
1986         for (tmp = user_data.frames; tmp; tmp = tmp->next) {
1987                 f = tmp->data;
1988
1989                 /* 
1990                  * Reuse the id for already existing stack frames, so invokes don't invalidate
1991                  * the still valid stack frames.
1992                  */
1993                 for (i = 0; i < tls->frame_count; ++i) {
1994                         if (MONO_CONTEXT_GET_SP (&tls->frames [i]->ctx) == MONO_CONTEXT_GET_SP (&f->ctx)) {
1995                                 f->id = tls->frames [i]->id;
1996                                 break;
1997                         }
1998                 }
1999
2000                 if (i >= tls->frame_count)
2001                         f->id = InterlockedIncrement (&frame_id);
2002
2003                 new_frames [findex ++] = f;
2004         }
2005
2006         g_slist_free (user_data.frames);
2007
2008         invalidate_frames (tls);
2009
2010         tls->frames = new_frames;
2011         tls->frame_count = new_frame_count;
2012         tls->frames_up_to_date = TRUE;
2013 }
2014
2015 /*
2016  * EVENT HANDLING
2017  */
2018
2019 /*
2020  * create_event_list:
2021  *
2022  *   Return a list of event request ids matching EVENT, starting from REQS, which
2023  * can be NULL to include all event requests. Set SUSPEND_POLICY to the suspend
2024  * policy.
2025  * We return request ids, instead of requests, to simplify threading, since 
2026  * requests could be deleted anytime when the loader lock is not held.
2027  * LOCKING: Assumes the loader lock is held.
2028  */
2029 static GSList*
2030 create_event_list (EventKind event, GPtrArray *reqs, MonoJitInfo *ji, MonoException *exc, int *suspend_policy)
2031 {
2032         int i, j;
2033         GSList *events = NULL;
2034
2035         *suspend_policy = SUSPEND_POLICY_NONE;
2036
2037         if (!reqs)
2038                 reqs = event_requests;
2039
2040         if (!reqs)
2041                 return NULL;
2042
2043         for (i = 0; i < reqs->len; ++i) {
2044                 EventRequest *req = g_ptr_array_index (reqs, i);
2045                 if (req->event_kind == event) {
2046                         gboolean filtered = FALSE;
2047
2048                         /* Apply filters */
2049                         for (j = 0; j < req->nmodifiers; ++j) {
2050                                 Modifier *mod = &req->modifiers [j];
2051
2052                                 if (mod->kind == MOD_KIND_COUNT) {
2053                                         filtered = TRUE;
2054                                         if (mod->data.count > 0) {
2055                                                 if (mod->data.count > 0) {
2056                                                         mod->data.count --;
2057                                                         if (mod->data.count == 0)
2058                                                                 filtered = FALSE;
2059                                                 }
2060                                         }
2061                                 } else if (mod->kind == MOD_KIND_THREAD_ONLY) {
2062                                         if (mod->data.thread != mono_thread_internal_current ())
2063                                                 filtered = TRUE;
2064                                 } else if (mod->kind == MOD_KIND_EXCEPTION_ONLY && exc) {
2065                                         if (mod->data.exc_class && !mono_class_is_assignable_from (mod->data.exc_class, exc->object.vtable->klass))
2066                                                 filtered = TRUE;
2067                                 } else if (mod->kind == MOD_KIND_ASSEMBLY_ONLY && ji) {
2068                                         int k;
2069                                         gboolean found = FALSE;
2070                                         MonoAssembly **assemblies = mod->data.assemblies;
2071
2072                                         for (k = 0; assemblies [k]; ++k)
2073                                                 if (assemblies [k] == ji->method->klass->image->assembly)
2074                                                         found = TRUE;
2075                                         if (!found)
2076                                                 filtered = TRUE;
2077                                 }
2078                         }
2079
2080                         if (!filtered) {
2081                                 *suspend_policy = MAX (*suspend_policy, req->suspend_policy);
2082                                 events = g_slist_append (events, GINT_TO_POINTER (req->id));
2083                         }
2084                 }
2085         }
2086
2087         /* Send a VM START/DEATH event by default */
2088         if (event == EVENT_KIND_VM_START)
2089                 events = g_slist_append (events, GINT_TO_POINTER (0));
2090         if (event == EVENT_KIND_VM_DEATH)
2091                 events = g_slist_append (events, GINT_TO_POINTER (0));
2092
2093         return events;
2094 }
2095
2096 static G_GNUC_UNUSED const char*
2097 event_to_string (EventKind event)
2098 {
2099         switch (event) {
2100         case EVENT_KIND_VM_START: return "VM_START";
2101         case EVENT_KIND_VM_DEATH: return "VM_DEATH";
2102         case EVENT_KIND_THREAD_START: return "THREAD_START";
2103         case EVENT_KIND_THREAD_DEATH: return "THREAD_DEATH";
2104         case EVENT_KIND_APPDOMAIN_CREATE: return "APPDOMAIN_CREATE";
2105         case EVENT_KIND_APPDOMAIN_UNLOAD: return "APPDOMAIN_UNLOAD";
2106         case EVENT_KIND_METHOD_ENTRY: return "METHOD_ENTRY";
2107         case EVENT_KIND_METHOD_EXIT: return "METHOD_EXIT";
2108         case EVENT_KIND_ASSEMBLY_LOAD: return "ASSEMBLY_LOAD";
2109         case EVENT_KIND_ASSEMBLY_UNLOAD: return "ASSEMBLY_UNLOAD";
2110         case EVENT_KIND_BREAKPOINT: return "BREAKPOINT";
2111         case EVENT_KIND_STEP: return "STEP";
2112         case EVENT_KIND_TYPE_LOAD: return "TYPE_LOAD";
2113         case EVENT_KIND_EXCEPTION: return "EXCEPTION";
2114         default:
2115                 g_assert_not_reached ();
2116         }
2117 }
2118
2119 /*
2120  * process_event:
2121  *
2122  *   Send an event to the client, suspending the vm if needed.
2123  * LOCKING: Since this can suspend the calling thread, no locks should be held
2124  * by the caller.
2125  * The EVENTS list is freed by this function.
2126  */
2127 static void
2128 process_event (EventKind event, gpointer arg, gint32 il_offset, MonoContext *ctx, GSList *events, int suspend_policy)
2129 {
2130         Buffer buf;
2131         GSList *l;
2132         MonoDomain *domain = mono_domain_get ();
2133         MonoThread *thread;
2134
2135         if (!inited)
2136                 return;
2137
2138         if (!vm_start_event_sent && event != EVENT_KIND_VM_START)
2139                 // FIXME: We miss those events
2140                 return;
2141
2142         if (vm_death_event_sent)
2143                 return;
2144
2145         if (mono_runtime_is_shutting_down () && event != EVENT_KIND_VM_DEATH)
2146                 return;
2147
2148         if (disconnected)
2149                 return;
2150
2151         if (events == NULL)
2152                 return;
2153
2154         if (debugger_thread_id == GetCurrentThreadId () && event != EVENT_KIND_VM_DEATH)
2155                 // FIXME: Send these with a NULL thread, don't suspend the current thread
2156                 return;
2157
2158         buffer_init (&buf, 128);
2159         buffer_add_byte (&buf, suspend_policy);
2160         buffer_add_int (&buf, g_slist_length (events)); // n of events
2161
2162         for (l = events; l; l = l->next) {
2163                 buffer_add_byte (&buf, event); // event kind
2164                 buffer_add_int (&buf, GPOINTER_TO_INT (l->data)); // request id
2165
2166                 thread = mono_thread_current ();
2167
2168                 if (event == EVENT_KIND_VM_START)
2169                         thread = arg;
2170                 else if (event == EVENT_KIND_THREAD_START)
2171                         g_assert (mono_thread_internal_current () == arg);
2172
2173                 buffer_add_objid (&buf, (MonoObject*)thread); // thread
2174
2175                 switch (event) {
2176                 case EVENT_KIND_THREAD_START:
2177                 case EVENT_KIND_THREAD_DEATH:
2178                         break;
2179                 case EVENT_KIND_APPDOMAIN_CREATE:
2180                 case EVENT_KIND_APPDOMAIN_UNLOAD:
2181                         buffer_add_domainid (&buf, arg);
2182                         break;
2183                 case EVENT_KIND_METHOD_ENTRY:
2184                 case EVENT_KIND_METHOD_EXIT:
2185                         buffer_add_methodid (&buf, domain, arg);
2186                         break;
2187                 case EVENT_KIND_ASSEMBLY_LOAD:
2188                 case EVENT_KIND_ASSEMBLY_UNLOAD:
2189                         buffer_add_assemblyid (&buf, domain, arg);
2190                         break;
2191                 case EVENT_KIND_TYPE_LOAD:
2192                         buffer_add_typeid (&buf, domain, arg);
2193                         break;
2194                 case EVENT_KIND_BREAKPOINT:
2195                 case EVENT_KIND_STEP:
2196                         buffer_add_methodid (&buf, domain, arg);
2197                         buffer_add_long (&buf, il_offset);
2198                         break;
2199                 case EVENT_KIND_VM_START:
2200                         buffer_add_domainid (&buf, mono_get_root_domain ());
2201                         break;
2202                 case EVENT_KIND_VM_DEATH:
2203                         break;
2204                 case EVENT_KIND_EXCEPTION:
2205                         buffer_add_objid (&buf, (MonoObject*)arg);
2206                         break;
2207                 default:
2208                         g_assert_not_reached ();
2209                 }
2210         }
2211
2212         if (event == EVENT_KIND_VM_START) {
2213                 suspend_policy = agent_config.suspend ? SUSPEND_POLICY_ALL : SUSPEND_POLICY_NONE;
2214                 start_debugger_thread ();
2215         }
2216    
2217         if (event == EVENT_KIND_VM_DEATH) {
2218                 vm_death_event_sent = TRUE;
2219
2220                 suspend_policy = SUSPEND_POLICY_NONE;
2221         }
2222
2223         if (mono_runtime_is_shutting_down ())
2224                 suspend_policy = SUSPEND_POLICY_NONE;
2225
2226         if (suspend_policy != SUSPEND_POLICY_NONE) {
2227                 /* 
2228                  * Save the thread context and start suspending before sending the packet,
2229                  * since we could be receiving the resume request before send_packet ()
2230                  * returns.
2231                  */
2232                 save_thread_context (ctx);
2233                 suspend_vm ();
2234         }
2235
2236         send_packet (CMD_SET_EVENT, CMD_COMPOSITE, &buf);
2237
2238         g_slist_free (events);
2239         events = NULL;
2240
2241         if (event == EVENT_KIND_VM_START)
2242                 vm_start_event_sent = TRUE;
2243
2244         DEBUG (1, fprintf (log_file, "[%p] Sent event %s, suspend=%d.\n", (gpointer)GetCurrentThreadId (), event_to_string (event), suspend_policy));
2245
2246         buffer_free (&buf);
2247
2248         switch (suspend_policy) {
2249         case SUSPEND_POLICY_NONE:
2250                 break;
2251         case SUSPEND_POLICY_ALL:
2252                 suspend_current ();
2253                 break;
2254         case SUSPEND_POLICY_EVENT_THREAD:
2255                 NOT_IMPLEMENTED;
2256                 break;
2257         default:
2258                 g_assert_not_reached ();
2259         }
2260 }
2261
2262 static void
2263 process_profiler_event (EventKind event, gpointer arg)
2264 {
2265         int suspend_policy;
2266         GSList *events;
2267
2268         mono_loader_lock ();
2269         events = create_event_list (event, NULL, NULL, NULL, &suspend_policy);
2270         mono_loader_unlock ();
2271
2272         process_event (event, arg, 0, NULL, events, suspend_policy);
2273 }
2274
2275 static void
2276 runtime_initialized (MonoProfiler *prof)
2277 {
2278         process_profiler_event (EVENT_KIND_VM_START, mono_thread_current ());
2279 }       
2280
2281 static void
2282 runtime_shutdown (MonoProfiler *prof)
2283 {
2284         process_profiler_event (EVENT_KIND_VM_DEATH, mono_thread_current ());
2285
2286         mono_debugger_agent_cleanup ();
2287 }
2288
2289 static void
2290 thread_startup (MonoProfiler *prof, gsize tid)
2291 {
2292         MonoInternalThread *thread = mono_thread_internal_current ();
2293         MonoInternalThread *old_thread;
2294         DebuggerTlsData *tls;
2295
2296         if (tid == debugger_thread_id)
2297                 return;
2298
2299         g_assert (thread->tid == tid);
2300
2301         mono_loader_lock ();
2302         old_thread = mono_g_hash_table_lookup (tid_to_thread, (gpointer)tid);
2303         mono_loader_unlock ();
2304         if (old_thread) {
2305                 if (thread == old_thread) {
2306                         /* 
2307                          * For some reason, thread_startup () might be called for the same thread
2308                          * multiple times (attach ?).
2309                          */
2310                         DEBUG (1, fprintf (log_file, "[%p] thread_start () called multiple times for %p, ignored.\n", (gpointer)tid, (gpointer)tid));
2311                         return;
2312                 } else {
2313                         /*
2314                          * thread_end () might not be called for some threads, and the tid could
2315                          * get reused.
2316                          */
2317                         DEBUG (1, fprintf (log_file, "[%p] Removing stale data for tid %p.\n", (gpointer)tid, (gpointer)tid));
2318                         mono_loader_lock ();
2319                         mono_g_hash_table_remove (thread_to_tls, old_thread);
2320                         mono_g_hash_table_remove (tid_to_thread, (gpointer)tid);
2321                         mono_g_hash_table_remove (tid_to_thread_obj, (gpointer)tid);
2322                         mono_loader_unlock ();
2323                 }
2324         }
2325
2326         tls = TlsGetValue (debugger_tls_id);
2327         g_assert (!tls);
2328         // FIXME: Free this somewhere
2329         tls = g_new0 (DebuggerTlsData, 1);
2330         tls->resume_event = CreateEvent (NULL, FALSE, FALSE, NULL);
2331         TlsSetValue (debugger_tls_id, tls);
2332
2333         DEBUG (1, fprintf (log_file, "[%p] Thread started, obj=%p, tls=%p.\n", (gpointer)tid, thread, tls));
2334
2335         mono_loader_lock ();
2336         mono_g_hash_table_insert (thread_to_tls, thread, tls);
2337         mono_g_hash_table_insert (tid_to_thread, (gpointer)tid, thread);
2338         mono_g_hash_table_insert (tid_to_thread_obj, (gpointer)tid, mono_thread_current ());
2339         mono_loader_unlock ();
2340
2341         process_profiler_event (EVENT_KIND_THREAD_START, thread);
2342
2343         /* 
2344          * suspend_vm () could have missed this thread, so wait for a resume.
2345          */
2346         suspend_current ();
2347 }
2348
2349 static void
2350 thread_end (MonoProfiler *prof, gsize tid)
2351 {
2352         MonoInternalThread *thread;
2353         DebuggerTlsData *tls = NULL;
2354
2355         mono_loader_lock ();
2356         thread = mono_g_hash_table_lookup (tid_to_thread, (gpointer)tid);
2357         if (thread) {
2358                 tls = mono_g_hash_table_lookup (thread_to_tls, thread);
2359                 /* FIXME: Maybe we need to free this instead, but some code can't handle that */
2360                 tls->terminated = TRUE;
2361                 mono_g_hash_table_remove (tid_to_thread_obj, (gpointer)tid);
2362                 /* Can't remove from tid_to_thread, as that would defeat the check in thread_start () */
2363         }
2364         mono_loader_unlock ();
2365
2366         /* We might be called for threads started before we registered the start callback */
2367         if (thread) {
2368                 DEBUG (1, fprintf (log_file, "[%p] Thread terminated, obj=%p, tls=%p.\n", (gpointer)tid, thread, tls));
2369                 process_profiler_event (EVENT_KIND_THREAD_DEATH, thread);
2370         }
2371 }
2372
2373 static void
2374 appdomain_load (MonoProfiler *prof, MonoDomain *domain, int result)
2375 {
2376         process_profiler_event (EVENT_KIND_APPDOMAIN_CREATE, domain);
2377 }
2378
2379 static void
2380 appdomain_unload (MonoProfiler *prof, MonoDomain *domain)
2381 {
2382         process_profiler_event (EVENT_KIND_APPDOMAIN_UNLOAD, domain);
2383 }
2384
2385 static void
2386 assembly_load (MonoProfiler *prof, MonoAssembly *assembly, int result)
2387 {
2388         /* Sent later in jit_end () */
2389         mono_loader_lock ();
2390         g_ptr_array_add (pending_assembly_loads, assembly);
2391         mono_loader_unlock ();
2392 }
2393
2394 static void
2395 assembly_unload (MonoProfiler *prof, MonoAssembly *assembly)
2396 {
2397         process_profiler_event (EVENT_KIND_ASSEMBLY_UNLOAD, assembly);
2398 }
2399
2400 static void
2401 start_runtime_invoke (MonoProfiler *prof, MonoMethod *method)
2402 {
2403 }
2404
2405 static void
2406 end_runtime_invoke (MonoProfiler *prof, MonoMethod *method)
2407 {
2408         int i;
2409 #ifdef PLATFORM_WIN32
2410         gpointer stackptr = ((guint64)_AddressOfReturnAddress () - sizeof (void*));
2411 #else
2412         gpointer stackptr = __builtin_frame_address (0);
2413 #endif
2414
2415         if (ss_req == NULL || ss_req->start_sp > stackptr || ss_req->thread != mono_thread_internal_current ())
2416                 return;
2417
2418         /*
2419          * We need to stop single stepping when exiting a runtime invoke, since if it is
2420          * a step out, it may return to native code, and thus never end.
2421          */
2422         mono_loader_lock ();
2423         for (i = 0; i < event_requests->len; ++i) {
2424                 EventRequest *req = g_ptr_array_index (event_requests, i);
2425
2426                 if (req->event_kind == EVENT_KIND_STEP) {
2427                         ss_stop (req);
2428                         g_ptr_array_remove_index_fast (event_requests, i);
2429                         g_free (req);
2430                         break;
2431                 }
2432         }
2433         mono_loader_unlock ();
2434
2435 }
2436
2437 static void
2438 jit_end (MonoProfiler *prof, MonoMethod *method, MonoJitInfo *jinfo, int result)
2439 {
2440         /*
2441          * We emit type load events when the first method of the type is JITted,
2442          * since the class load profiler callbacks might be called with the
2443          * loader lock held. They could also occur in the debugger thread.
2444          * Same for assembly load events.
2445          */
2446         gboolean type_load = FALSE;
2447
2448         while (TRUE) {
2449                 MonoAssembly *assembly = NULL;
2450
2451                 // FIXME: Maybe store this in TLS so the thread of the event is correct ?
2452                 mono_loader_lock ();
2453                 if (pending_assembly_loads->len > 0) {
2454                         assembly = g_ptr_array_index (pending_assembly_loads, 0);
2455                         g_ptr_array_remove_index (pending_assembly_loads, 0);
2456                 }
2457                 mono_loader_unlock ();
2458
2459                 if (assembly)
2460                         process_profiler_event (EVENT_KIND_ASSEMBLY_LOAD, assembly);
2461                 else
2462                         break;
2463         }
2464
2465         mono_loader_lock ();
2466         if (!g_hash_table_lookup (loaded_classes, method->klass)) {
2467                 type_load = TRUE;
2468                 g_hash_table_insert (loaded_classes, method->klass, method->klass);
2469         }
2470         mono_loader_unlock ();
2471         if (type_load)
2472                 process_profiler_event (EVENT_KIND_TYPE_LOAD, method->klass);
2473
2474         if (!result)
2475                 add_pending_breakpoints (method, jinfo);
2476 }
2477
2478 /*
2479  * BREAKPOINTS/SINGLE STEPPING
2480  */
2481
2482 /* 
2483  * Contains information about an inserted breakpoint.
2484  */
2485 typedef struct {
2486         long il_offset, native_offset;
2487         guint8 *ip;
2488         gboolean pending, entry;
2489         MonoJitInfo *ji;
2490 } BreakpointInstance;
2491
2492 /*
2493  * Contains generic information about a breakpoint.
2494  */
2495 typedef struct {
2496         /* 
2497          * The method where the breakpoint is placed. Can be NULL in which case it 
2498          * is inserted into every method. This is used to implement method entry/
2499          * exit events. Can be a generic method definition, in which case the
2500          * breakpoint is inserted into every instance.
2501          */
2502         MonoMethod *method;
2503         long il_offset;
2504         gboolean pending, entry;
2505         EventRequest *req;
2506         /* 
2507          * A list of BreakpointInstance structures describing where the breakpoint
2508          * was inserted. There could be more than one because of 
2509          * generics/appdomains/method entry/exit.
2510          */
2511         GPtrArray *children;
2512 } MonoBreakpoint;
2513
2514 /* List of breakpoints */
2515 static GPtrArray *breakpoints;
2516 /* Maps breakpoint locations to the number of breakpoints at that location */
2517 static GHashTable *bp_locs;
2518
2519 static void
2520 breakpoints_init (void)
2521 {
2522         breakpoints = g_ptr_array_new ();
2523         bp_locs = g_hash_table_new (NULL, NULL);
2524 }       
2525
2526 static void
2527 breakpoints_cleanup (void)
2528 {
2529         int i;
2530
2531         mono_loader_lock ();
2532
2533         for (i = 0; i < breakpoints->len; ++i)
2534                 g_free (g_ptr_array_index (breakpoints, i));
2535
2536         g_ptr_array_free (breakpoints, TRUE);
2537         g_hash_table_destroy (bp_locs);
2538
2539         mono_loader_unlock ();
2540 }
2541
2542 /*
2543  * insert_breakpoint:
2544  *
2545  *   Insert the breakpoint described by BP into the method described by
2546  * JI.
2547  */
2548 static void
2549 insert_breakpoint (GPtrArray *seq_points, MonoJitInfo *ji, MonoBreakpoint *bp)
2550 {
2551         int i, count;
2552         gint32 il_offset, native_offset;
2553         BreakpointInstance *inst;
2554
2555         native_offset = 0;
2556         for (i = 0; i < seq_points->len; i += 2) {
2557                 il_offset = GPOINTER_TO_INT (g_ptr_array_index (seq_points, i));
2558                 native_offset = GPOINTER_TO_INT (g_ptr_array_index (seq_points, i + 1));
2559
2560                 if (il_offset == bp->il_offset)
2561                         break;
2562         }
2563
2564         if (i == seq_points->len)
2565                 /* Have to handle this somehow */
2566                 NOT_IMPLEMENTED;
2567
2568         inst = g_new0 (BreakpointInstance, 1);
2569         inst->native_offset = native_offset;
2570         inst->ip = (guint8*)ji->code_start + native_offset;
2571         inst->ji = ji;
2572
2573         mono_loader_lock ();
2574
2575         g_ptr_array_add (bp->children, inst);
2576
2577         count = GPOINTER_TO_INT (g_hash_table_lookup (bp_locs, inst->ip));
2578         g_hash_table_insert (bp_locs, inst->ip, GINT_TO_POINTER (count + 1));
2579         mono_loader_unlock ();
2580
2581         if (count == 0) {
2582 #ifdef MONO_ARCH_SOFT_DEBUG_SUPPORTED
2583                 mono_arch_set_breakpoint (ji, inst->ip);
2584 #else
2585                 NOT_IMPLEMENTED;
2586 #endif
2587         }
2588 }
2589
2590 static void
2591 remove_breakpoint (BreakpointInstance *inst)
2592 {
2593 #ifdef MONO_ARCH_SOFT_DEBUG_SUPPORTED
2594         int count;
2595         MonoJitInfo *ji = inst->ji;
2596         guint8 *ip = inst->ip;
2597
2598         mono_loader_lock ();
2599         count = GPOINTER_TO_INT (g_hash_table_lookup (bp_locs, ip));
2600         g_hash_table_insert (bp_locs, ip, GINT_TO_POINTER (count - 1));
2601         mono_loader_unlock ();
2602
2603         g_assert (count > 0);
2604
2605         if (count == 1) {
2606                 mono_arch_clear_breakpoint (ji, ip);
2607         }
2608 #else
2609         NOT_IMPLEMENTED;
2610 #endif
2611 }       
2612
2613 /*
2614  * add_pending_breakpoints:
2615  *
2616  *   Insert pending breakpoints into the newly JITted method METHOD.
2617  */
2618 static void
2619 add_pending_breakpoints (MonoMethod *method, MonoJitInfo *ji)
2620 {
2621         int i;
2622         GPtrArray *seq_points;
2623         MonoDomain *domain;
2624
2625         if (!breakpoints)
2626                 return;
2627
2628         domain = mono_domain_get ();
2629
2630         mono_loader_lock ();
2631
2632         for (i = 0; i < breakpoints->len; ++i) {
2633                 MonoBreakpoint *bp = g_ptr_array_index (breakpoints, i);
2634
2635                 if (bp->pending && (bp->method == method || !bp->method || (method->is_inflated && ((MonoMethodInflated*)method)->declaring == bp->method))) {
2636                         mono_domain_lock (domain);
2637                         seq_points = g_hash_table_lookup (domain_jit_info (domain)->seq_points, ji->method);
2638                         mono_domain_unlock (domain);
2639                         if (!seq_points)
2640                                 /* Could be AOT code */
2641                                 continue;
2642                         g_assert (seq_points);
2643
2644                         insert_breakpoint (seq_points, ji, bp);
2645                 }
2646         }
2647
2648         mono_loader_unlock ();
2649 }
2650
2651 static void
2652 set_bp_in_method (MonoDomain *domain, MonoMethod *method, GPtrArray *seq_points, MonoBreakpoint *bp)
2653 {
2654         gpointer code;
2655         MonoJitInfo *ji;
2656
2657         code = mono_jit_find_compiled_method_with_jit_info (domain, method, &ji);
2658         if (!code) {
2659                 /* Might be AOTed code */
2660                 code = mono_aot_get_method (domain, method);
2661                 g_assert (code);
2662                 ji = mono_jit_info_table_find (domain, code);
2663                 g_assert (ji);
2664         }
2665         g_assert (code);
2666
2667         insert_breakpoint (seq_points, ji, bp);
2668 }
2669
2670 static void
2671 set_bp_in_method_cb (gpointer key, gpointer value, gpointer user_data)
2672 {
2673         MonoMethod *method = key;
2674         GPtrArray *seq_points = value;
2675         MonoBreakpoint *bp = user_data;
2676         MonoDomain *domain = mono_domain_get ();
2677
2678         if (bp->method) {
2679                 if (method->is_inflated && ((MonoMethodInflated*)method)->declaring == bp->method) {
2680                         /* Generic instance */
2681                         set_bp_in_method (domain, method, seq_points, bp);
2682                 }
2683         } else {
2684                 /* Method entry/exit */
2685                 set_bp_in_method (domain, method, seq_points, bp);
2686         }
2687 }
2688
2689 /*
2690  * set_breakpoint:
2691  *
2692  *   Set a breakpoint at IL_OFFSET in METHOD.
2693  * METHOD can be NULL, in which case a breakpoint is placed in all methods.
2694  * METHOD can also be a generic method definition, in which case a breakpoint
2695  * is placed in all instances of the method.
2696  */
2697 static MonoBreakpoint*
2698 set_breakpoint (MonoMethod *method, long il_offset, EventRequest *req)
2699 {
2700         GPtrArray *seq_points;
2701         MonoDomain *domain;
2702         MonoBreakpoint *bp;
2703
2704         // FIXME: 
2705         // - suspend/resume the vm to prevent code patching problems
2706         // - appdomains
2707         // - multiple breakpoints on the same location
2708         // - dynamic methods
2709         // - races
2710
2711         bp = g_new0 (MonoBreakpoint, 1);
2712         bp->method = method;
2713         bp->il_offset = il_offset;
2714         bp->req = req;
2715         bp->children = g_ptr_array_new ();
2716
2717         DEBUG(1, fprintf (log_file, "[dbg] Setting breakpoint at %s:0x%x.\n", mono_method_full_name (method, TRUE), (int)il_offset));
2718
2719         domain = mono_domain_get ();
2720         mono_domain_lock (domain);
2721         if (method) {
2722                 seq_points = g_hash_table_lookup (domain_jit_info (domain)->seq_points, method);
2723                 if (seq_points) {
2724                         set_bp_in_method (domain, method, seq_points, bp);
2725                 } else {
2726                         if (method->is_generic)
2727                                 /* There might be already JITted instances */
2728                                 g_hash_table_foreach (domain_jit_info (domain)->seq_points, set_bp_in_method_cb, bp);
2729
2730                         /* Not yet JITted */
2731                         bp->pending = TRUE;
2732                 }
2733         } else {
2734                 g_hash_table_foreach (domain_jit_info (domain)->seq_points, set_bp_in_method_cb, bp);
2735                 bp->pending = TRUE;
2736         }
2737         mono_domain_unlock (domain);
2738
2739         mono_loader_lock ();
2740         g_ptr_array_add (breakpoints, bp);
2741         mono_loader_unlock ();
2742
2743         return bp;
2744 }
2745
2746 static void
2747 clear_breakpoint (MonoBreakpoint *bp)
2748 {
2749         int i;
2750
2751         // FIXME: locking, races
2752         for (i = 0; i < bp->children->len; ++i) {
2753                 BreakpointInstance *inst = g_ptr_array_index (bp->children, i);
2754
2755                 remove_breakpoint (inst);
2756
2757                 g_free (inst);
2758         }
2759
2760         mono_loader_lock ();
2761         g_ptr_array_remove (breakpoints, bp);
2762         mono_loader_unlock ();
2763
2764         g_ptr_array_free (bp->children, TRUE);
2765         g_free (bp);
2766 }
2767
2768 static void
2769 process_breakpoint_inner (MonoContext *ctx)
2770 {
2771         MonoJitInfo *ji;
2772         guint8 *orig_ip, *ip;
2773         int i, j, suspend_policy;
2774         guint32 native_offset;
2775         MonoBreakpoint *bp;
2776         BreakpointInstance *inst;
2777         GPtrArray *reqs;
2778         GSList *events = NULL;
2779         EventKind kind = EVENT_KIND_BREAKPOINT;
2780
2781         // FIXME: Speed this up
2782
2783         orig_ip = ip = MONO_CONTEXT_GET_IP (ctx);
2784         ji = mono_jit_info_table_find (mono_domain_get (), (char*)ip);
2785         g_assert (ji);
2786         g_assert (ji->method);
2787
2788         /* Compute the native offset of the breakpoint from the ip */
2789 #ifdef MONO_ARCH_SOFT_DEBUG_SUPPORTED
2790         ip = mono_arch_get_ip_for_breakpoint (ji, ctx);
2791         native_offset = ip - (guint8*)ji->code_start;   
2792 #else
2793         NOT_IMPLEMENTED;
2794 #endif
2795
2796         /* 
2797          * Skip the instruction causing the breakpoint signal.
2798          */
2799         mono_arch_skip_breakpoint (ctx);
2800
2801         if (ji->method->wrapper_type)
2802                 return;
2803
2804         reqs = g_ptr_array_new ();
2805
2806         DEBUG(1, fprintf (log_file, "[%p] Breakpoint hit, method=%s, offset=0x%x.\n", (gpointer)GetCurrentThreadId (), ji->method->name, native_offset));
2807
2808         mono_loader_lock ();
2809
2810         bp = NULL;
2811         for (i = 0; i < breakpoints->len; ++i) {
2812                 bp = g_ptr_array_index (breakpoints, i);
2813
2814                 if (!bp->method)
2815                         continue;
2816
2817                 for (j = 0; j < bp->children->len; ++j) {
2818                         inst = g_ptr_array_index (bp->children, j);
2819                         if (inst->ji == ji && inst->native_offset == native_offset)
2820                                 g_ptr_array_add (reqs, bp->req);
2821                 }
2822         }
2823         if (reqs->len == 0) {
2824                 GPtrArray *seq_points;
2825                 int seq_il_offset, seq_native_offset;
2826                 MonoDomain *domain = mono_domain_get ();
2827
2828                 /* Maybe a method entry/exit event */
2829                 mono_domain_lock (domain);
2830                 seq_points = g_hash_table_lookup (domain_jit_info (domain)->seq_points, ji->method);
2831                 mono_domain_unlock (domain);
2832                 if (!seq_points) {
2833                         // FIXME: Generic sharing */
2834                         mono_loader_unlock ();
2835                         return;
2836                 }
2837                 g_assert (seq_points);
2838
2839                 for (i = 0; i < seq_points->len; i += 2) {
2840                         seq_il_offset = GPOINTER_TO_INT (g_ptr_array_index (seq_points, i));
2841                         seq_native_offset = GPOINTER_TO_INT (g_ptr_array_index (seq_points, i + 1));
2842
2843                         if (native_offset == seq_native_offset) {
2844                                 if (seq_il_offset == METHOD_ENTRY_IL_OFFSET)
2845                                         kind = EVENT_KIND_METHOD_ENTRY;
2846                                 else if (seq_il_offset == METHOD_EXIT_IL_OFFSET)
2847                                         kind = EVENT_KIND_METHOD_EXIT;
2848                                 break;
2849                         }
2850                 }
2851         }
2852         
2853         if (reqs->len > 0)
2854                 events = create_event_list (EVENT_KIND_BREAKPOINT, reqs, ji, NULL, &suspend_policy);
2855         else if (kind != EVENT_KIND_BREAKPOINT)
2856                 events = create_event_list (kind, NULL, ji, NULL, &suspend_policy);
2857
2858         g_ptr_array_free (reqs, TRUE);
2859
2860         mono_loader_unlock ();
2861
2862         if (events)
2863                 process_event (kind, ji->method, 0, ctx, events, suspend_policy);
2864 }
2865
2866 static void
2867 process_breakpoint (void)
2868 {
2869         DebuggerTlsData *tls;
2870         MonoContext ctx;
2871         static void (*restore_context) (void *);
2872
2873         if (!restore_context)
2874                 restore_context = mono_get_restore_context ();
2875
2876         tls = TlsGetValue (debugger_tls_id);
2877         memcpy (&ctx, &tls->handler_ctx, sizeof (MonoContext));
2878
2879         process_breakpoint_inner (&ctx);
2880
2881         /* This is called when resuming from a signal handler, so it shouldn't return */
2882         restore_context (&ctx);
2883         g_assert_not_reached ();
2884 }
2885
2886 void
2887 mono_debugger_agent_breakpoint_hit (void *sigctx)
2888 {
2889         DebuggerTlsData *tls;
2890         MonoContext ctx;
2891
2892         /*
2893          * We are called from a signal handler, and running code there causes all kinds of
2894          * problems, like the original signal is disabled, libgc can't handle altstack, etc.
2895          * So set up the signal context to return to the real breakpoint handler function.
2896          */
2897
2898         // FIXME: This might not work on an altstack ?
2899         tls = TlsGetValue (debugger_tls_id);
2900         g_assert (tls);
2901
2902         mono_arch_sigctx_to_monoctx (sigctx, &ctx);
2903         memcpy (&tls->handler_ctx, &ctx, sizeof (MonoContext));
2904         
2905         MONO_CONTEXT_SET_IP (&ctx, process_breakpoint);
2906
2907         mono_arch_monoctx_to_sigctx (&ctx, sigctx);
2908 }
2909
2910 static void
2911 process_single_step_inner (MonoContext *ctx)
2912 {
2913         MonoJitInfo *ji;
2914         guint8 *ip;
2915         GPtrArray *reqs;
2916         int il_offset, suspend_policy;
2917         MonoDomain *domain = mono_domain_get ();
2918         GSList *events;
2919
2920         // FIXME: Speed this up
2921
2922         ip = MONO_CONTEXT_GET_IP (ctx);
2923
2924         /* Skip the instruction causing the single step */
2925         mono_arch_skip_single_step (ctx);
2926
2927         if (suspend_count > 0) {
2928                 if (debugger_thread_id == GetCurrentThreadId ())
2929                         return;
2930
2931                 DEBUG(1, fprintf (log_file, "[%p] Received single step event for suspending.\n", (gpointer)GetCurrentThreadId ()));
2932
2933                 ji = mono_jit_info_table_find (mono_domain_get (), (char*)ip);
2934
2935                 /* See the comment below */
2936                 if (ji->method->klass == mono_defaults.string_class && (!strcmp (ji->method->name, "memset") || strstr (ji->method->name, "memcpy")))
2937                         return;
2938
2939                 save_thread_context (ctx);
2940                 suspend_current ();
2941                 return;
2942         }
2943
2944         if (!ss_req)
2945                 // FIXME: A suspend race
2946                 return;
2947
2948         if (mono_thread_internal_current () != ss_req->thread)
2949                 return;
2950
2951         if (log_level > 0) {
2952                 const char *depth = NULL;
2953
2954                 ji = mono_jit_info_table_find (mono_domain_get (), (char*)ip);
2955
2956                 switch (ss_req->depth) {
2957                 case STEP_DEPTH_OVER:
2958                         depth = "over";
2959                         break;
2960                 case STEP_DEPTH_OUT:
2961                         depth = "out";
2962                         break;
2963                 case STEP_DEPTH_INTO:
2964                         depth = "into";
2965                         break;
2966                 default:
2967                         g_assert_not_reached ();
2968                 }
2969                         
2970                 DEBUG (1, fprintf (log_file, "[%p] Single step event (depth=%s) at %s (%p), sp %p, last sp %p\n", (gpointer)GetCurrentThreadId (), ss_req->depth == STEP_DEPTH_OVER ? "over" : "out", mono_method_full_name (ji->method, TRUE), MONO_CONTEXT_GET_IP (ctx), MONO_CONTEXT_GET_SP (ctx), ss_req->last_sp));
2971         }
2972
2973         /*
2974          * We implement step over/out by single stepping until we reach the same 
2975          * frame/parent frame.
2976          * FIXME:
2977          * - this is slow
2978          * - stack growing upward
2979          * - localloc
2980          * - exceptions
2981          */
2982         if (ss_req->depth != STEP_DEPTH_INTO) {
2983                 if (ss_req->depth == STEP_DEPTH_OVER && MONO_CONTEXT_GET_SP (ctx) < ss_req->last_sp)
2984                         return;
2985                 if (ss_req->depth == STEP_DEPTH_OUT && MONO_CONTEXT_GET_SP (ctx) <= ss_req->last_sp)
2986                         return;
2987
2988                 ss_req->last_sp = MONO_CONTEXT_GET_SP (ctx);
2989         }
2990
2991         ji = mono_jit_info_table_find (mono_domain_get (), (char*)ip);
2992         g_assert (ji);
2993         g_assert (ji->method);
2994
2995         if (ji->method->wrapper_type && ji->method->wrapper_type != MONO_WRAPPER_DYNAMIC_METHOD)
2996                 return;
2997
2998         /* 
2999          * FIXME: 
3000          * Stopping in memset makes half-initialized vtypes visible.
3001          * Stopping in memcpy makes half-copied vtypes visible.
3002          */
3003         if (ji->method->klass == mono_defaults.string_class && (!strcmp (ji->method->name, "memset") || strstr (ji->method->name, "memcpy")))
3004                 return;
3005
3006         /* 
3007          * The ip points to the instruction causing the single step event, convert it
3008          * to the offset stored in seq_points.
3009          */
3010 #ifdef MONO_ARCH_SOFT_DEBUG_SUPPORTED
3011         ip = mono_arch_get_ip_for_single_step (ji, ctx);
3012 #else
3013         g_assert_not_reached ();
3014 #endif
3015
3016         /* 
3017          * mono_debug_lookup_source_location () doesn't work for IL offset 0 for 
3018          * example, so do things by hand.
3019          */
3020         il_offset = compute_il_offset (domain, ji->method, (guint8*)ip - (guint8*)ji->code_start);
3021
3022         if (il_offset == -1)
3023                 return;
3024
3025         if (ss_req->size == STEP_SIZE_LINE) {
3026                 /* Step until a different source line is reached */
3027                 MonoDebugMethodInfo *minfo;
3028
3029                 minfo = mono_debug_lookup_method (ji->method);
3030
3031                 if (minfo) {
3032                         MonoDebugSourceLocation *loc = mono_debug_symfile_lookup_location (minfo, il_offset);
3033
3034                         if (loc && ji->method == ss_req->last_method && loc->row == ss_req->last_line) {
3035                                 mono_debug_free_source_location (loc);
3036                                 return;
3037                         }
3038                         if (!loc)
3039                                 /*
3040                                  * Step until we reach a location with line number info, 
3041                                  * otherwise the client can't show a location.
3042                                  * This can happen for example with statics initialized inline
3043                                  * outside of a cctor.
3044                                  */
3045                                 return;
3046
3047                         if (loc) {
3048                                 ss_req->last_method = ji->method;
3049                                 ss_req->last_line = loc->row;
3050                                 mono_debug_free_source_location (loc);
3051                         }
3052                 }
3053         }
3054
3055         // FIXME: Has to lock earlier
3056
3057         reqs = g_ptr_array_new ();
3058
3059         mono_loader_lock ();
3060
3061         g_ptr_array_add (reqs, ss_req->req);
3062
3063         events = create_event_list (EVENT_KIND_STEP, reqs, ji, NULL, &suspend_policy);
3064
3065         g_ptr_array_free (reqs, TRUE);
3066
3067         mono_loader_unlock ();
3068
3069         process_event (EVENT_KIND_STEP, ji->method, il_offset, ctx, events, suspend_policy);
3070 }
3071
3072 static void
3073 process_single_step (void)
3074 {
3075         DebuggerTlsData *tls;
3076         MonoContext ctx;
3077         static void (*restore_context) (void *);
3078
3079         if (!restore_context)
3080                 restore_context = mono_get_restore_context ();
3081
3082         tls = TlsGetValue (debugger_tls_id);
3083         memcpy (&ctx, &tls->handler_ctx, sizeof (MonoContext));
3084
3085         process_single_step_inner (&ctx);
3086
3087         /* This is called when resuming from a signal handler, so it shouldn't return */
3088         restore_context (&ctx);
3089         g_assert_not_reached ();
3090 }
3091
3092 /*
3093  * mono_debugger_agent_single_step_event:
3094  *
3095  *   Called from a signal handler to handle a single step event.
3096  */
3097 void
3098 mono_debugger_agent_single_step_event (void *sigctx)
3099 {
3100         DebuggerTlsData *tls;
3101         MonoContext ctx;
3102
3103         /* Resume to process_single_step through the signal context */
3104
3105         // FIXME: Since step out/over is implemented using step in, the step in case should
3106         // be as fast as possible. Move the relevant code from process_single_step_inner ()
3107         // here
3108
3109         /* Save the original context in TLS */
3110         // FIXME: This might not work on an altstack ?
3111         tls = TlsGetValue (debugger_tls_id);
3112         g_assert (tls);
3113         mono_arch_sigctx_to_monoctx (sigctx, &ctx);
3114         memcpy (&tls->handler_ctx, &ctx, sizeof (MonoContext));
3115         
3116         MONO_CONTEXT_SET_IP (&ctx, process_single_step);
3117
3118         mono_arch_monoctx_to_sigctx (&ctx, sigctx);
3119 }
3120
3121 /*
3122  * start_single_stepping:
3123  *
3124  *   Turn on single stepping. Can be called multiple times, for example,
3125  * by a single step event request + a suspend.
3126  */
3127 static void
3128 start_single_stepping (void)
3129 {
3130 #ifdef MONO_ARCH_SOFT_DEBUG_SUPPORTED
3131         int val = InterlockedIncrement (&ss_count);
3132
3133         if (val == 1)
3134                 mono_arch_start_single_stepping ();
3135 #else
3136         g_assert_not_reached ();
3137 #endif
3138 }
3139
3140 static void
3141 stop_single_stepping (void)
3142 {
3143 #ifdef MONO_ARCH_SOFT_DEBUG_SUPPORTED
3144         int val = InterlockedDecrement (&ss_count);
3145
3146         if (val == 0)
3147                 mono_arch_stop_single_stepping ();
3148 #else
3149         g_assert_not_reached ();
3150 #endif
3151 }
3152
3153 /*
3154  * Start single stepping of thread THREAD
3155  */
3156 static ErrorCode
3157 ss_start (MonoInternalThread *thread, StepSize size, StepDepth depth, EventRequest *req)
3158 {
3159         DebuggerTlsData *tls;
3160
3161         if (suspend_count == 0)
3162                 return ERR_NOT_SUSPENDED;
3163
3164         wait_for_suspend ();
3165
3166         // FIXME: Multiple requests
3167         if (ss_req)
3168                 return ERR_NOT_IMPLEMENTED;
3169
3170         ss_req = g_new0 (MonoSingleStepReq, 1);
3171         ss_req->req = req;
3172         ss_req->thread = thread;
3173         ss_req->size = size;
3174         ss_req->depth = depth;
3175         req->info = ss_req;
3176
3177         mono_loader_lock ();
3178         tls = mono_g_hash_table_lookup (thread_to_tls, thread);
3179         mono_loader_unlock ();
3180         g_assert (tls);
3181         g_assert (tls->has_context);
3182         ss_req->start_sp = ss_req->last_sp = MONO_CONTEXT_GET_SP (&tls->ctx);
3183
3184         if (ss_req->size == STEP_SIZE_LINE) {
3185                 StackFrame *frame;
3186                 MonoDebugMethodInfo *minfo;
3187
3188                 /* Compute the initial line info */
3189                 compute_frame_info (thread, tls);
3190
3191                 g_assert (tls->frame_count);
3192                 frame = tls->frames [0];
3193
3194                 ss_req->last_method = frame->method;
3195                 ss_req->last_line = -1;
3196
3197                 minfo = mono_debug_lookup_method (frame->method);
3198                 if (minfo && frame->il_offset != -1) {
3199                         MonoDebugSourceLocation *loc = mono_debug_symfile_lookup_location (minfo, frame->il_offset);
3200
3201                         if (loc) {
3202                                 ss_req->last_line = loc->row;
3203                                 g_free (loc);
3204                         }
3205                 }
3206         }
3207
3208         start_single_stepping ();
3209
3210         return 0;
3211 }
3212
3213 static void
3214 ss_stop (EventRequest *req)
3215 {
3216         // FIXME: Locking
3217         g_assert (ss_req);
3218         g_assert (ss_req->req == req);
3219
3220         g_free (ss_req);
3221         ss_req = NULL;
3222
3223         stop_single_stepping ();
3224 }
3225
3226 void
3227 mono_debugger_agent_handle_exception (MonoException *exc, MonoContext *ctx)
3228 {
3229         int suspend_policy;
3230         GSList *events;
3231
3232         /* Just-In-Time debugging */
3233         if (agent_config.onthrow && !inited) {
3234                 GSList *l;
3235                 gboolean found = FALSE;
3236
3237                 for (l = agent_config.onthrow; l; l = l->next) {
3238                         char *ex_type = l->data;
3239                         char *f = mono_type_full_name (&exc->object.vtable->klass->byval_arg);
3240
3241                         if (!strcmp (ex_type, f))
3242                                 found = TRUE;
3243
3244                         g_free (f);
3245                 }
3246
3247                 if (found) {
3248                         finish_agent_init (FALSE);
3249
3250                         /*
3251                          * Send an unsolicited EXCEPTION event with a dummy request id.
3252                          */
3253                         events = g_slist_append (NULL, GUINT_TO_POINTER (0xffffff));
3254                         process_event (EVENT_KIND_EXCEPTION, exc, 0, ctx, events, SUSPEND_POLICY_ALL);
3255                         return;
3256                 }
3257         }
3258
3259         if (!inited)
3260                 return;
3261
3262         mono_loader_lock ();
3263         events = create_event_list (EVENT_KIND_EXCEPTION, NULL, NULL, exc, &suspend_policy);
3264         mono_loader_unlock ();
3265
3266         process_event (EVENT_KIND_EXCEPTION, exc, 0, ctx, events, suspend_policy);
3267 }
3268
3269 void
3270 mono_debugger_agent_handle_unhandled_exception (MonoException *exc, MonoContext *ctx)
3271 {
3272         GSList *events;
3273
3274         if (!agent_config.onuncaught)
3275                 return;
3276
3277         finish_agent_init (FALSE);
3278
3279         /*
3280          * Send an unsolicited EXCEPTION event with a dummy request id.
3281          */
3282         events = g_slist_append (NULL, GUINT_TO_POINTER (0xffffff));
3283         process_event (EVENT_KIND_EXCEPTION, exc, 0, ctx, events, SUSPEND_POLICY_ALL);
3284 }
3285
3286 /*
3287  * buffer_add_value:
3288  *
3289  *   Add the encoding of the value at ADDR described by T to the buffer.
3290  */
3291 static void
3292 buffer_add_value (Buffer *buf, MonoType *t, void *addr, MonoDomain *domain)
3293 {
3294         MonoObject *obj;
3295
3296         if (t->byref) {
3297                 g_assert (*(void**)addr);
3298                 addr = *(void**)addr;
3299         }
3300
3301         switch (t->type) {
3302         case MONO_TYPE_VOID:
3303                 buffer_add_byte (buf, t->type);
3304                 break;
3305         case MONO_TYPE_BOOLEAN:
3306         case MONO_TYPE_I1:
3307         case MONO_TYPE_U1:
3308                 buffer_add_byte (buf, t->type);
3309                 buffer_add_int (buf, *(gint8*)addr);
3310                 break;
3311         case MONO_TYPE_CHAR:
3312         case MONO_TYPE_I2:
3313         case MONO_TYPE_U2:
3314                 buffer_add_byte (buf, t->type);
3315                 buffer_add_int (buf, *(gint16*)addr);
3316                 break;
3317         case MONO_TYPE_I4:
3318         case MONO_TYPE_U4:
3319         case MONO_TYPE_R4:
3320                 buffer_add_byte (buf, t->type);
3321                 buffer_add_int (buf, *(gint32*)addr);
3322                 break;
3323         case MONO_TYPE_I8:
3324         case MONO_TYPE_U8:
3325         case MONO_TYPE_R8:
3326                 buffer_add_byte (buf, t->type);
3327                 buffer_add_long (buf, *(gint64*)addr);
3328                 break;
3329         case MONO_TYPE_I:
3330         case MONO_TYPE_U:
3331         case MONO_TYPE_PTR: {
3332                 gssize val = *(gssize*)addr;
3333                 
3334                 buffer_add_byte (buf, t->type);
3335                 buffer_add_long (buf, val);
3336                 break;
3337         }
3338         handle_ref:
3339         case MONO_TYPE_STRING:
3340         case MONO_TYPE_SZARRAY:
3341         case MONO_TYPE_OBJECT:
3342         case MONO_TYPE_CLASS:
3343         case MONO_TYPE_ARRAY:
3344                 obj = *(MonoObject**)addr;
3345
3346                 if (!obj) {
3347                         buffer_add_byte (buf, VALUE_TYPE_ID_NULL);
3348                 } else {
3349                         if (obj->vtable->klass->valuetype) {
3350                                 t = &obj->vtable->klass->byval_arg;
3351                                 addr = mono_object_unbox (obj);
3352                                 goto handle_vtype;
3353                         } else if (obj->vtable->klass->rank) {
3354                                 buffer_add_byte (buf, obj->vtable->klass->byval_arg.type);
3355                         } else if (obj->vtable->klass->byval_arg.type == MONO_TYPE_GENERICINST) {
3356                                 buffer_add_byte (buf, MONO_TYPE_CLASS);
3357                         } else {
3358                                 buffer_add_byte (buf, obj->vtable->klass->byval_arg.type);
3359                         }
3360                         buffer_add_objid (buf, obj);
3361                 }
3362                 break;
3363         handle_vtype:
3364         case MONO_TYPE_VALUETYPE: {
3365                 int nfields;
3366                 gpointer iter;
3367                 MonoClassField *f;
3368                 MonoClass *klass = mono_class_from_mono_type (t);
3369
3370                 buffer_add_byte (buf, MONO_TYPE_VALUETYPE);
3371                 buffer_add_byte (buf, klass->enumtype);
3372                 buffer_add_typeid (buf, domain, klass);
3373
3374                 nfields = 0;
3375                 iter = NULL;
3376                 while ((f = mono_class_get_fields (klass, &iter))) {
3377                         if (f->type->attrs & FIELD_ATTRIBUTE_STATIC)
3378                                 continue;
3379                         if (mono_field_is_deleted (f))
3380                                 continue;
3381                         nfields ++;
3382                 }
3383                 buffer_add_int (buf, nfields);
3384
3385                 iter = NULL;
3386                 while ((f = mono_class_get_fields (klass, &iter))) {
3387                         if (f->type->attrs & FIELD_ATTRIBUTE_STATIC)
3388                                 continue;
3389                         if (mono_field_is_deleted (f))
3390                                 continue;
3391                         buffer_add_value (buf, f->type, (guint8*)addr + f->offset - sizeof (MonoObject), domain);
3392                 }
3393                 break;
3394         }
3395         case MONO_TYPE_GENERICINST:
3396                 if (mono_type_generic_inst_is_valuetype (t)) {
3397                         goto handle_vtype;
3398                 } else {
3399                         goto handle_ref;
3400                 }
3401                 break;
3402         default:
3403                 NOT_IMPLEMENTED;
3404         }
3405 }
3406
3407 static ErrorCode
3408 decode_value (MonoType *t, MonoDomain *domain, guint8 *addr, guint8 *buf, guint8 **endbuf, guint8 *limit)
3409 {
3410         int err;
3411         int type = decode_byte (buf, &buf, limit);
3412
3413         if (type != t->type && !MONO_TYPE_IS_REFERENCE (t)) {
3414                 DEBUG(1, fprintf (log_file, "Expected value of type %d, got %d.\n", t->type, type));
3415                 return ERR_INVALID_ARGUMENT;
3416         }
3417
3418         switch (t->type) {
3419         case MONO_TYPE_BOOLEAN:
3420                 *(guint8*)addr = decode_int (buf, &buf, limit);
3421                 break;
3422         case MONO_TYPE_CHAR:
3423                 *(gunichar2*)addr = decode_int (buf, &buf, limit);
3424                 break;
3425         case MONO_TYPE_I1:
3426                 *(gint8*)addr = decode_int (buf, &buf, limit);
3427                 break;
3428         case MONO_TYPE_U1:
3429                 *(guint8*)addr = decode_int (buf, &buf, limit);
3430                 break;
3431         case MONO_TYPE_I2:
3432                 *(gint16*)addr = decode_int (buf, &buf, limit);
3433                 break;
3434         case MONO_TYPE_U2:
3435                 *(guint16*)addr = decode_int (buf, &buf, limit);
3436                 break;
3437         case MONO_TYPE_I4:
3438                 *(gint32*)addr = decode_int (buf, &buf, limit);
3439                 break;
3440         case MONO_TYPE_U4:
3441                 *(guint32*)addr = decode_int (buf, &buf, limit);
3442                 break;
3443         case MONO_TYPE_I8:
3444                 *(gint64*)addr = decode_long (buf, &buf, limit);
3445                 break;
3446         case MONO_TYPE_U8:
3447                 *(guint64*)addr = decode_long (buf, &buf, limit);
3448                 break;
3449         case MONO_TYPE_R4:
3450                 *(guint32*)addr = decode_int (buf, &buf, limit);
3451                 break;
3452         case MONO_TYPE_R8:
3453                 *(guint64*)addr = decode_long (buf, &buf, limit);
3454                 break;
3455         case MONO_TYPE_VALUETYPE: {
3456                 gboolean is_enum = decode_byte (buf, &buf, limit);
3457                 MonoClass *klass;
3458                 MonoClassField *f;
3459                 int nfields;
3460                 gpointer iter = NULL;
3461                 MonoDomain *d;
3462
3463                 /* Enums are sent as a normal vtype */
3464                 if (is_enum)
3465                         return ERR_NOT_IMPLEMENTED;
3466                 klass = decode_typeid (buf, &buf, limit, &d, &err);
3467                 if (err)
3468                         return err;
3469
3470                 if (klass != mono_class_from_mono_type (t))
3471                         return ERR_INVALID_ARGUMENT;
3472
3473                 nfields = decode_int (buf, &buf, limit);
3474                 while ((f = mono_class_get_fields (klass, &iter))) {
3475                         if (f->type->attrs & FIELD_ATTRIBUTE_STATIC)
3476                                 continue;
3477                         if (mono_field_is_deleted (f))
3478                                 continue;
3479                         err = decode_value (f->type, domain, (guint8*)addr + f->offset - sizeof (MonoObject), buf, &buf, limit);
3480                         if (err)
3481                                 return err;
3482                         nfields --;
3483                 }
3484                 g_assert (nfields == 0);
3485                 break;
3486         }
3487         default:
3488                 if (MONO_TYPE_IS_REFERENCE (t)) {
3489                         if (type == MONO_TYPE_OBJECT) {
3490                                 int objid = decode_objid (buf, &buf, limit);
3491                                 int err;
3492                                 MonoObject *obj;
3493
3494                                 err = get_object (objid, (MonoObject**)&obj);
3495                                 if (err)
3496                                         return err;
3497
3498                                 if (obj && !mono_class_is_assignable_from (mono_class_from_mono_type (t), obj->vtable->klass))
3499                                         return ERR_INVALID_ARGUMENT;
3500                                 if (obj && obj->vtable->domain != domain)
3501                                         return ERR_INVALID_ARGUMENT;
3502
3503                                 mono_gc_wbarrier_generic_store (addr, obj);
3504                         } else if (type == VALUE_TYPE_ID_NULL) {
3505                                 *(MonoObject**)addr = NULL;
3506                         } else {
3507                                 return ERR_INVALID_ARGUMENT;
3508                         }
3509                 } else {
3510                         NOT_IMPLEMENTED;
3511                 }
3512                 break;
3513         }
3514
3515         *endbuf = buf;
3516
3517         return 0;
3518 }
3519
3520 static void
3521 add_var (Buffer *buf, MonoType *t, MonoDebugVarInfo *var, MonoContext *ctx, MonoDomain *domain)
3522 {
3523         guint32 flags;
3524         int reg;
3525         guint8 *addr;
3526         gpointer reg_val;
3527
3528         flags = var->index & MONO_DEBUG_VAR_ADDRESS_MODE_FLAGS;
3529         reg = var->index & ~MONO_DEBUG_VAR_ADDRESS_MODE_FLAGS;
3530
3531         switch (flags) {
3532         case MONO_DEBUG_VAR_ADDRESS_MODE_REGISTER:
3533                 reg_val = mono_arch_context_get_int_reg (ctx, reg);
3534
3535                 buffer_add_value (buf, t, &reg_val, domain);
3536                 break;
3537         case MONO_DEBUG_VAR_ADDRESS_MODE_REGOFFSET:
3538                 addr = mono_arch_context_get_int_reg (ctx, reg);
3539                 addr += (gint32)var->offset;
3540
3541                 //printf ("[R%d+%d] = %p\n", reg, var->offset, addr);
3542
3543                 buffer_add_value (buf, t, addr, domain);
3544                 break;
3545         case MONO_DEBUG_VAR_ADDRESS_MODE_DEAD:
3546                 NOT_IMPLEMENTED;
3547                 break;
3548         default:
3549                 g_assert_not_reached ();
3550         }
3551 }
3552
3553 static void
3554 set_var (MonoType *t, MonoDebugVarInfo *var, MonoContext *ctx, MonoDomain *domain, guint8 *val)
3555 {
3556         guint32 flags;
3557         int reg, size;
3558         guint8 *addr;
3559
3560         flags = var->index & MONO_DEBUG_VAR_ADDRESS_MODE_FLAGS;
3561         reg = var->index & ~MONO_DEBUG_VAR_ADDRESS_MODE_FLAGS;
3562
3563         if (MONO_TYPE_IS_REFERENCE (t))
3564                 size = sizeof (gpointer);
3565         else
3566                 size = mono_class_value_size (mono_class_from_mono_type (t), NULL);
3567
3568         switch (flags) {
3569         case MONO_DEBUG_VAR_ADDRESS_MODE_REGISTER:
3570                 // FIXME: Can't set registers, so we disable linears
3571                 NOT_IMPLEMENTED;
3572                 break;
3573         case MONO_DEBUG_VAR_ADDRESS_MODE_REGOFFSET:
3574                 addr = mono_arch_context_get_int_reg (ctx, reg);
3575                 addr += (gint32)var->offset;
3576
3577                 //printf ("[R%d+%d] = %p\n", reg, var->offset, addr);
3578
3579                 // FIXME: Write barriers
3580                 memcpy (addr, val, size);
3581                 break;
3582         case MONO_DEBUG_VAR_ADDRESS_MODE_DEAD:
3583                 NOT_IMPLEMENTED;
3584                 break;
3585         default:
3586                 g_assert_not_reached ();
3587         }
3588 }
3589
3590 static void
3591 clear_event_request (int req_id, int etype)
3592 {
3593         int i;
3594
3595         mono_loader_lock ();
3596         for (i = 0; i < event_requests->len; ++i) {
3597                 EventRequest *req = g_ptr_array_index (event_requests, i);
3598
3599                 if (req->id == req_id && req->event_kind == etype) {
3600                         if (req->event_kind == EVENT_KIND_BREAKPOINT)
3601                                 clear_breakpoint (req->info);
3602                         if (req->event_kind == EVENT_KIND_STEP)
3603                                 ss_stop (req);
3604                         g_ptr_array_remove_index_fast (event_requests, i);
3605                         g_free (req);
3606                         break;
3607                 }
3608         }
3609         mono_loader_unlock ();
3610 }
3611
3612 static void
3613 add_thread (gpointer key, gpointer value, gpointer user_data)
3614 {
3615         MonoInternalThread *thread = value;
3616         Buffer *buf = user_data;
3617
3618         buffer_add_objid (buf, (MonoObject*)thread);
3619 }
3620
3621 static ErrorCode
3622 do_invoke_method (Buffer *buf, InvokeData *invoke)
3623 {
3624         guint8 *p = invoke->p;
3625         guint8 *end = invoke->endp;
3626         MonoMethod *m;
3627         int i, err, nargs;
3628         MonoMethodSignature *sig;
3629         guint8 **arg_buf;
3630         void **args;
3631         MonoObject *this, *res, *exc;
3632         MonoDomain *domain;
3633         guint8 *this_buf;
3634 #ifdef MONO_ARCH_HAVE_FIND_JIT_INFO_EXT
3635         MonoLMFExt ext;
3636 #endif
3637
3638         m = decode_methodid (p, &p, end, &domain, &err);
3639         if (err)
3640                 return err;
3641         sig = mono_method_signature (m);
3642
3643         if (m->klass->valuetype)
3644                 this_buf = g_alloca (mono_class_instance_size (m->klass));
3645         else
3646                 this_buf = g_alloca (sizeof (MonoObject*));
3647         err = decode_value (&m->klass->byval_arg, domain, this_buf, p, &p, end);
3648         if (err)
3649                 return err;
3650
3651         if (!m->klass->valuetype)
3652                 this = *(MonoObject**)this_buf;
3653         else
3654                 this = NULL;
3655
3656         DEBUG (1, printf ("[%p] Invoking method '%s' on receiver '%s'.\n", (gpointer)GetCurrentThreadId (), mono_method_full_name (m, TRUE), this ? this->vtable->klass->name : "<null>"));
3657
3658         if (this && this->vtable->domain != domain)
3659                 NOT_IMPLEMENTED;
3660
3661         if (!m->klass->valuetype && !(m->flags & METHOD_ATTRIBUTE_STATIC) && !this) {
3662                 if (!strcmp (m->name, ".ctor")) {
3663                         if (m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT)
3664                                 return ERR_INVALID_ARGUMENT;
3665                         else
3666                                 this = mono_object_new (domain, m->klass);
3667                 } else {
3668                         return ERR_INVALID_ARGUMENT;
3669                 }
3670         }
3671
3672         if (this && !mono_class_is_assignable_from (m->klass, this->vtable->klass))
3673                 return ERR_INVALID_ARGUMENT;
3674
3675         nargs = decode_int (p, &p, end);
3676         if (nargs != sig->param_count)
3677                 return ERR_INVALID_ARGUMENT;
3678         /* Use alloca to get gc tracking */
3679         arg_buf = g_alloca (nargs * sizeof (gpointer));
3680         memset (arg_buf, 0, nargs * sizeof (gpointer));
3681         args = g_alloca (nargs * sizeof (gpointer));
3682         for (i = 0; i < nargs; ++i) {
3683                 if (MONO_TYPE_IS_REFERENCE (sig->params [i])) {
3684                         err = decode_value (sig->params [i], domain, (guint8*)&args [i], p, &p, end);
3685                         if (err)
3686                                 break;
3687
3688                         if (args [i] && ((MonoObject*)args [i])->vtable->domain != domain)
3689                                 NOT_IMPLEMENTED;
3690                 } else {
3691                         arg_buf [i] = g_alloca (mono_class_instance_size (mono_class_from_mono_type (sig->params [i])));
3692                         err = decode_value (sig->params [i], domain, arg_buf [i], p, &p, end);
3693                         if (err)
3694                                 break;
3695                         args [i] = arg_buf [i];
3696                 }
3697         }
3698
3699         if (i < nargs)
3700                 return err;
3701
3702         /* 
3703          * Add an LMF frame to link the stack frames on the invoke method with our caller.
3704          */
3705         /* FIXME: Move this to arch specific code */
3706 #ifdef MONO_ARCH_HAVE_FIND_JIT_INFO_EXT
3707         if (invoke->has_ctx) {
3708                 MonoLMF **lmf_addr;
3709
3710                 lmf_addr = mono_get_lmf_addr ();
3711
3712                 /* Setup our lmf */
3713                 memset (&ext, 0, sizeof (ext));
3714 #ifdef TARGET_AMD64
3715                 ext.lmf.previous_lmf = *(lmf_addr);
3716                 /* Mark that this is a MonoLMFExt */
3717                 ext.lmf.previous_lmf = (gpointer)(((gssize)ext.lmf.previous_lmf) | 2);
3718                 ext.lmf.rsp = (gssize)&ext;
3719 #elif defined(TARGET_X86)
3720                 ext.lmf.previous_lmf = (gsize)*(lmf_addr);
3721                 /* Mark that this is a MonoLMFExt */
3722                 ext.lmf.previous_lmf = (gsize)(gpointer)(((gssize)ext.lmf.previous_lmf) | 2);
3723                 ext.lmf.ebp = (gssize)&ext;
3724 #elif defined(TARGET_ARM)
3725                 ext.lmf.previous_lmf = *(lmf_addr);
3726                 /* Mark that this is a MonoLMFExt */
3727                 ext.lmf.previous_lmf = (gpointer)(((gssize)ext.lmf.previous_lmf) | 2);
3728                 ext.lmf.ebp = (gssize)&ext;
3729 #else
3730                 g_assert_not_reached ();
3731 #endif
3732
3733                 ext.debugger_invoke = TRUE;
3734                 memcpy (&ext.ctx, &invoke->ctx, sizeof (MonoContext));
3735
3736                 mono_set_lmf ((MonoLMF*)&ext);
3737         }
3738 #endif
3739
3740         if (m->klass->valuetype)
3741                 res = mono_runtime_invoke (m, this_buf, args, &exc);
3742         else
3743                 res = mono_runtime_invoke (m, this, args, &exc);
3744         if (exc) {
3745                 buffer_add_byte (buf, 0);
3746                 buffer_add_value (buf, &mono_defaults.object_class->byval_arg, &exc, domain);
3747         } else {
3748                 buffer_add_byte (buf, 1);
3749                 if (sig->ret->type == MONO_TYPE_VOID) {
3750                         if (!strcmp (m->name, ".ctor") && !m->klass->valuetype) {
3751                                 buffer_add_value (buf, &mono_defaults.object_class->byval_arg, &this, domain);
3752                         }
3753                         else
3754                                 buffer_add_value (buf, &mono_defaults.void_class->byval_arg, NULL, domain);
3755                 } else if (MONO_TYPE_IS_REFERENCE (sig->ret)) {
3756                         buffer_add_value (buf, sig->ret, &res, domain);
3757                 } else if (mono_class_from_mono_type (sig->ret)->valuetype) {
3758                         g_assert (res);
3759                         buffer_add_value (buf, sig->ret, mono_object_unbox (res), domain);
3760                 } else {
3761                         NOT_IMPLEMENTED;
3762                 }
3763         }
3764
3765 #ifdef MONO_ARCH_HAVE_FIND_JIT_INFO_EXT
3766         if (invoke->has_ctx)
3767                 mono_set_lmf ((gpointer)(((gssize)ext.lmf.previous_lmf) & ~3));
3768 #endif
3769
3770         // FIXME: byref arguments
3771         // FIXME: varargs
3772         return ERR_NONE;
3773 }
3774
3775 /*
3776  * invoke_method:
3777  *
3778  *   Invoke the method given by tls->invoke in the current thread.
3779  */
3780 static void
3781 invoke_method (void)
3782 {
3783         DebuggerTlsData *tls;
3784         InvokeData *invoke;
3785         int id;
3786         int err;
3787         Buffer buf;
3788         static void (*restore_context) (void *);
3789         MonoContext restore_ctx;
3790
3791         if (!restore_context)
3792                 restore_context = mono_get_restore_context ();
3793
3794         tls = TlsGetValue (debugger_tls_id);
3795         g_assert (tls);
3796
3797         invoke = tls->invoke;
3798         g_assert (invoke);
3799         tls->invoke = NULL;
3800
3801         tls->frames_up_to_date = FALSE;
3802
3803         id = invoke->id;
3804
3805         buffer_init (&buf, 128);
3806
3807         err = do_invoke_method (&buf, invoke);
3808
3809         /* Start suspending before sending the reply */
3810         suspend_vm ();
3811
3812         send_reply_packet (id, err, &buf);
3813         
3814         buffer_free (&buf);
3815
3816         memcpy (&restore_ctx, &invoke->ctx, sizeof (MonoContext));
3817
3818         if (invoke->has_ctx)
3819                 save_thread_context (&restore_ctx);
3820
3821         g_free (invoke->p);
3822         g_free (invoke);
3823
3824         suspend_current ();
3825 }
3826
3827 static ErrorCode
3828 vm_commands (int command, int id, guint8 *p, guint8 *end, Buffer *buf)
3829 {
3830         switch (command) {
3831         case CMD_VM_VERSION: {
3832                 char *build_info, *version;
3833
3834                 build_info = mono_get_runtime_build_info ();
3835                 version = g_strdup_printf ("mono %s", build_info);
3836
3837                 buffer_add_string (buf, version); /* vm version */
3838                 buffer_add_int (buf, MAJOR_VERSION);
3839                 buffer_add_int (buf, MINOR_VERSION);
3840                 g_free (build_info);
3841                 g_free (version);
3842                 break;
3843         }
3844         case CMD_VM_ALL_THREADS: {
3845                 // FIXME: Domains
3846                 mono_loader_lock ();
3847                 buffer_add_int (buf, mono_g_hash_table_size (tid_to_thread_obj));
3848                 mono_g_hash_table_foreach (tid_to_thread_obj, add_thread, buf);
3849                 mono_loader_unlock ();
3850                 break;
3851         }
3852         case CMD_VM_SUSPEND:
3853                 suspend_vm ();
3854                 wait_for_suspend ();
3855                 break;
3856         case CMD_VM_RESUME:
3857                 if (suspend_count == 0)
3858                         return ERR_NOT_SUSPENDED;
3859                 resume_vm ();
3860                 break;
3861         case CMD_VM_DISPOSE:
3862                 /* Clear all event requests */
3863                 mono_loader_lock ();
3864                 while (event_requests->len > 0) {
3865                         EventRequest *req = g_ptr_array_index (event_requests, 0);
3866
3867                         clear_event_request (req->id, req->event_kind);
3868                 }
3869                 mono_loader_unlock ();
3870
3871                 // FIXME: Count resumes
3872                 resume_vm ();
3873                 disconnected = TRUE;
3874                 break;
3875         case CMD_VM_EXIT: {
3876                 int exit_code = decode_int (p, &p, end);
3877
3878                 // FIXME: What if there is a VM_DEATH event request with SUSPEND_ALL ?
3879
3880                 /* Have to send a reply before exiting */
3881                 send_reply_packet (id, 0, buf);
3882
3883                 /* Clear all event requests */
3884                 mono_loader_lock ();
3885                 while (event_requests->len > 0) {
3886                         EventRequest *req = g_ptr_array_index (event_requests, 0);
3887
3888                         clear_event_request (req->id, req->event_kind);
3889                 }
3890                 mono_loader_unlock ();
3891
3892                 /* FIXME: Races with normal shutdown */
3893                 while (suspend_count > 0)
3894                         resume_vm ();
3895
3896                 /*
3897                  * The JDWP documentation says that the shutdown is not orderly. It doesn't
3898                  * specify whenever a VM_DEATH event is sent. We currently do an orderly
3899                  * shutdown similar to Environment.Exit ().
3900                  */
3901                 mono_runtime_set_shutting_down ();
3902
3903                 mono_threads_set_shutting_down ();
3904
3905                 /* Suspend all managed threads since the runtime is going away */
3906                 DEBUG(1, fprintf (log_file, "Suspending all threads...\n"));
3907                 mono_thread_suspend_all_other_threads ();
3908                 DEBUG(1, fprintf (log_file, "Shutting down the runtime...\n"));
3909                 mono_runtime_quit ();
3910 #ifdef PLATFORM_WIN32
3911                 shutdown (conn_fd, SD_BOTH);
3912 #else
3913                 shutdown (conn_fd, SHUT_RDWR);
3914 #endif
3915                 DEBUG(1, fprintf (log_file, "Exiting...\n"));
3916
3917                 exit (exit_code);
3918         }               
3919         case CMD_VM_INVOKE_METHOD: {
3920                 int objid = decode_objid (p, &p, end);
3921                 MonoThread *thread;
3922                 DebuggerTlsData *tls;
3923                 int err;
3924
3925                 err = get_object (objid, (MonoObject**)&thread);
3926                 if (err)
3927                         return err;
3928
3929                 // Wait for suspending if it already started
3930                 if (suspend_count)
3931                         wait_for_suspend ();
3932                 if (!is_suspended ())
3933                         return ERR_NOT_SUSPENDED;
3934
3935                 mono_loader_lock ();
3936                 tls = mono_g_hash_table_lookup (thread_to_tls, thread->internal_thread);
3937                 mono_loader_unlock ();
3938                 g_assert (tls);
3939
3940                 /* 
3941                  * Store the invoke data into tls, the thread will execute it after it is
3942                  * resumed.
3943                  */
3944                 if (tls->invoke)
3945                         NOT_IMPLEMENTED;
3946                 tls->invoke = g_new0 (InvokeData, 1);
3947                 tls->invoke->id = id;
3948                 tls->invoke->p = g_malloc (end - p);
3949                 memcpy (tls->invoke->p, p, end - p);
3950                 tls->invoke->endp = tls->invoke->p + (end - p);
3951
3952                 resume_vm ();
3953                 break;
3954         }
3955         default:
3956                 return ERR_NOT_IMPLEMENTED;
3957         }
3958
3959         return ERR_NONE;
3960 }
3961
3962 static ErrorCode
3963 event_commands (int command, guint8 *p, guint8 *end, Buffer *buf)
3964 {
3965         int err;
3966
3967         switch (command) {
3968         case CMD_EVENT_REQUEST_SET: {
3969                 EventRequest *req;
3970                 int i, event_kind, suspend_policy, nmodifiers, mod;
3971                 MonoMethod *method;
3972                 long location;
3973                 MonoThread *step_thread;
3974                 int size, depth, step_thread_id;
3975                 MonoDomain *domain;
3976
3977                 event_kind = decode_byte (p, &p, end);
3978                 suspend_policy = decode_byte (p, &p, end);
3979                 nmodifiers = decode_byte (p, &p, end);
3980
3981                 req = g_malloc0 (sizeof (EventRequest) + (nmodifiers * sizeof (Modifier)));
3982                 req->id = InterlockedIncrement (&event_request_id);
3983                 req->event_kind = event_kind;
3984                 req->suspend_policy = suspend_policy;
3985                 req->nmodifiers = nmodifiers;
3986
3987                 method = NULL;
3988                 for (i = 0; i < nmodifiers; ++i) {
3989                         mod = decode_byte (p, &p, end);
3990
3991                         req->modifiers [i].kind = mod;
3992                         if (mod == MOD_KIND_COUNT) {
3993                                 req->modifiers [i].data.count = decode_int (p, &p, end);
3994                         } else if (mod == MOD_KIND_LOCATION_ONLY) {
3995                                 method = decode_methodid (p, &p, end, &domain, &err);
3996                                 if (err)
3997                                         return err;
3998                                 location = decode_long (p, &p, end);
3999                         } else if (mod == MOD_KIND_STEP) {
4000                                 step_thread_id = decode_id (p, &p, end);
4001                                 size = decode_int (p, &p, end);
4002                                 depth = decode_int (p, &p, end);
4003                         } else if (mod == MOD_KIND_THREAD_ONLY) {
4004                                 int id = decode_id (p, &p, end);
4005
4006                                 err = get_object (id, (MonoObject**)&req->modifiers [i].data.thread);
4007                                 if (err) {
4008                                         g_free (req);
4009                                         return err;
4010                                 }
4011                         } else if (mod == MOD_KIND_EXCEPTION_ONLY) {
4012                                 MonoClass *exc_class = decode_typeid (p, &p, end, &domain, &err);
4013
4014                                 if (err)
4015                                         return err;
4016                                 if (exc_class) {
4017                                         req->modifiers [i].data.exc_class = exc_class;
4018
4019                                         if (!mono_class_is_assignable_from (mono_defaults.exception_class, exc_class)) {
4020                                                 g_free (req);
4021                                                 return ERR_INVALID_ARGUMENT;
4022                                         }
4023                                 }
4024                         } else if (mod == MOD_KIND_ASSEMBLY_ONLY) {
4025                                 int n = decode_int (p, &p, end);
4026                                 int j;
4027
4028                                 req->modifiers [i].data.assemblies = g_new0 (MonoAssembly*, n);
4029                                 for (j = 0; j < n; ++j) {
4030                                         req->modifiers [i].data.assemblies [j] = decode_assemblyid (p, &p, end, &domain, &err);
4031                                         if (err) {
4032                                                 g_free (req->modifiers [i].data.assemblies);
4033                                                 return err;
4034                                         }
4035                                 }
4036                         } else {
4037                                 g_free (req);
4038                                 return ERR_NOT_IMPLEMENTED;
4039                         }
4040                 }
4041
4042                 if (req->event_kind == EVENT_KIND_BREAKPOINT) {
4043                         g_assert (method);
4044
4045                         req->info = set_breakpoint (method, location, req);
4046                 } else if (req->event_kind == EVENT_KIND_STEP) {
4047                         g_assert (step_thread_id);
4048
4049                         err = get_object (step_thread_id, (MonoObject**)&step_thread);
4050                         if (err) {
4051                                 g_free (req);
4052                                 return err;
4053                         }
4054
4055                         err = ss_start (step_thread->internal_thread, size, depth, req);
4056                         if (err) {
4057                                 g_free (req);
4058                                 return err;
4059                         }
4060                 } else if (req->event_kind == EVENT_KIND_METHOD_ENTRY) {
4061                         req->info = set_breakpoint (NULL, METHOD_ENTRY_IL_OFFSET, req);
4062                 } else if (req->event_kind == EVENT_KIND_METHOD_EXIT) {
4063                         req->info = set_breakpoint (NULL, METHOD_EXIT_IL_OFFSET, req);
4064                 } else if (req->event_kind == EVENT_KIND_EXCEPTION) {
4065                 } else {
4066                         if (req->nmodifiers) {
4067                                 g_free (req);
4068                                 return ERR_NOT_IMPLEMENTED;
4069                         }
4070                 }
4071
4072                 mono_loader_lock ();
4073                 g_ptr_array_add (event_requests, req);
4074                 mono_loader_unlock ();
4075
4076                 buffer_add_int (buf, req->id);
4077                 break;
4078         }
4079         case CMD_EVENT_REQUEST_CLEAR: {
4080                 int etype = decode_byte (p, &p, end);
4081                 int req_id = decode_int (p, &p, end);
4082
4083                 // FIXME: Make a faster mapping from req_id to request
4084                 mono_loader_lock ();
4085                 clear_event_request (req_id, etype);
4086                 mono_loader_unlock ();
4087                 break;
4088         }
4089         case CMD_EVENT_REQUEST_CLEAR_ALL_BREAKPOINTS: {
4090                 int i;
4091
4092                 mono_loader_lock ();
4093                 i = 0;
4094                 while (i < event_requests->len) {
4095                         EventRequest *req = g_ptr_array_index (event_requests, i);
4096
4097                         if (req->event_kind == EVENT_KIND_BREAKPOINT) {
4098                                 clear_breakpoint (req->info);
4099
4100                                 g_ptr_array_remove_index_fast (event_requests, i);
4101                                 g_free (req);
4102                         } else {
4103                                 i ++;
4104                         }
4105                 }
4106                 mono_loader_unlock ();
4107                 break;
4108         }
4109         default:
4110                 return ERR_NOT_IMPLEMENTED;
4111         }
4112
4113         return ERR_NONE;
4114 }
4115
4116 static ErrorCode
4117 domain_commands (int command, guint8 *p, guint8 *end, Buffer *buf)
4118 {
4119         int err;
4120         MonoDomain *domain;
4121
4122         switch (command) {
4123         case CMD_APPDOMAIN_GET_ROOT_DOMAIN: {
4124                 buffer_add_domainid (buf, mono_get_root_domain ());
4125                 break;
4126         }
4127         case CMD_APPDOMAIN_GET_FRIENDLY_NAME: {
4128                 domain = decode_domainid (p, &p, end, NULL, &err);
4129                 if (err)
4130                         return err;
4131                 buffer_add_string (buf, domain->friendly_name);
4132                 break;
4133         }
4134         case CMD_APPDOMAIN_GET_ASSEMBLIES: {
4135                 GSList *tmp;
4136                 MonoAssembly *ass;
4137                 int count;
4138
4139                 domain = decode_domainid (p, &p, end, NULL, &err);
4140                 if (err)
4141                         return err;
4142                 mono_loader_lock ();
4143                 count = 0;
4144                 for (tmp = domain->domain_assemblies; tmp; tmp = tmp->next) {
4145                         count ++;
4146                 }
4147                 buffer_add_int (buf, count);
4148                 for (tmp = domain->domain_assemblies; tmp; tmp = tmp->next) {
4149                         ass = tmp->data;
4150                         buffer_add_assemblyid (buf, domain, ass);
4151                 }
4152                 mono_loader_unlock ();
4153                 break;
4154         }
4155         case CMD_APPDOMAIN_GET_ENTRY_ASSEMBLY: {
4156                 domain = decode_domainid (p, &p, end, NULL, &err);
4157                 if (err)
4158                         return err;
4159
4160                 buffer_add_assemblyid (buf, domain, domain->entry_assembly);
4161                 break;
4162         }
4163         case CMD_APPDOMAIN_GET_CORLIB: {
4164                 domain = decode_domainid (p, &p, end, NULL, &err);
4165                 if (err)
4166                         return err;
4167
4168                 buffer_add_assemblyid (buf, domain, domain->domain->mbr.obj.vtable->klass->image->assembly);
4169                 break;
4170         }
4171         case CMD_APPDOMAIN_CREATE_STRING: {
4172                 char *s;
4173                 MonoString *o;
4174
4175                 domain = decode_domainid (p, &p, end, NULL, &err);
4176                 if (err)
4177                         return err;
4178                 s = decode_string (p, &p, end);
4179
4180                 o = mono_string_new (domain, s);
4181                 buffer_add_objid (buf, (MonoObject*)o);
4182                 break;
4183         }
4184         default:
4185                 return ERR_NOT_IMPLEMENTED;
4186         }
4187
4188         return ERR_NONE;
4189 }
4190
4191 static ErrorCode
4192 assembly_commands (int command, guint8 *p, guint8 *end, Buffer *buf)
4193 {
4194         int err;
4195         MonoAssembly *ass;
4196         MonoDomain *domain;
4197
4198         ass = decode_assemblyid (p, &p, end, &domain, &err);
4199         if (err)
4200                 return err;
4201
4202         switch (command) {
4203         case CMD_ASSEMBLY_GET_LOCATION: {
4204                 buffer_add_string (buf, mono_image_get_filename (ass->image));
4205                 break;                  
4206         }
4207         case CMD_ASSEMBLY_GET_ENTRY_POINT: {
4208                 guint32 token;
4209                 MonoMethod *m;
4210
4211                 if (ass->image->dynamic) {
4212                         buffer_add_id (buf, 0);
4213                 } else {
4214                         token = mono_image_get_entry_point (ass->image);
4215                         if (token == 0) {
4216                                 buffer_add_id (buf, 0);
4217                         } else {
4218                                 m = mono_get_method (ass->image, token, NULL);
4219                                 buffer_add_methodid (buf, domain, m);
4220                         }
4221                 }
4222                 break;                  
4223         }
4224         case CMD_ASSEMBLY_GET_MANIFEST_MODULE: {
4225                 buffer_add_moduleid (buf, domain, ass->image);
4226                 break;
4227         }
4228         case CMD_ASSEMBLY_GET_OBJECT: {
4229                 MonoObject *o = (MonoObject*)mono_assembly_get_object (mono_domain_get (), ass);
4230                 buffer_add_objid (buf, o);
4231                 break;
4232         }
4233         case CMD_ASSEMBLY_GET_TYPE: {
4234                 char *s = decode_string (p, &p, end);
4235                 gboolean ignorecase = decode_byte (p, &p, end);
4236                 MonoTypeNameParse info;
4237                 MonoType *t;
4238                 gboolean type_resolve;
4239
4240                 if (!mono_reflection_parse_type (s, &info)) {
4241                         t = NULL;
4242                 } else {
4243                         if (info.assembly.name)
4244                                 NOT_IMPLEMENTED;
4245                         t = mono_reflection_get_type (ass->image, &info, ignorecase, &type_resolve);
4246                 }
4247                 buffer_add_typeid (buf, domain, t ? mono_class_from_mono_type (t) : NULL);
4248                 mono_reflection_free_type_info (&info);
4249                 g_free (s);
4250
4251                 break;
4252         }
4253         default:
4254                 return ERR_NOT_IMPLEMENTED;
4255         }
4256
4257         return ERR_NONE;
4258 }
4259
4260 static ErrorCode
4261 module_commands (int command, guint8 *p, guint8 *end, Buffer *buf)
4262 {
4263         int err;
4264         MonoDomain *domain;
4265
4266         switch (command) {
4267         case CMD_MODULE_GET_INFO: {
4268                 MonoImage *image = decode_moduleid (p, &p, end, &domain, &err);
4269                 char *basename;
4270
4271                 basename = g_path_get_basename (image->name);
4272                 buffer_add_string (buf, basename); // name
4273                 buffer_add_string (buf, image->module_name); // scopename
4274                 buffer_add_string (buf, image->name); // fqname
4275                 buffer_add_string (buf, mono_image_get_guid (image)); // guid
4276                 buffer_add_assemblyid (buf, domain, image->assembly); // assembly
4277                 g_free (basename);
4278                 break;                  
4279         }
4280         default:
4281                 return ERR_NOT_IMPLEMENTED;
4282         }
4283
4284         return ERR_NONE;
4285 }
4286
4287 static void
4288 buffer_add_cattr_arg (Buffer *buf, MonoType *t, MonoDomain *domain, MonoObject *val)
4289 {
4290         if (val && val->vtable->klass == mono_defaults.monotype_class) {
4291                 /* Special case these so the client doesn't have to handle Type objects */
4292                 
4293                 buffer_add_byte (buf, VALUE_TYPE_ID_TYPE);
4294                 buffer_add_typeid (buf, domain, mono_class_from_mono_type (((MonoReflectionType*)val)->type));
4295         } else if (MONO_TYPE_IS_REFERENCE (t))
4296                 buffer_add_value (buf, t, &val, domain);
4297         else
4298                 buffer_add_value (buf, t, mono_object_unbox (val), domain);
4299 }
4300
4301 static void
4302 buffer_add_cattrs (Buffer *buf, MonoDomain *domain, MonoImage *image, MonoClass *attr_klass, MonoCustomAttrInfo *cinfo)
4303 {
4304         int i, j;
4305         int nattrs = 0;
4306
4307         if (!cinfo) {
4308                 buffer_add_int (buf, 0);
4309                 return;
4310         }
4311
4312         for (i = 0; i < cinfo->num_attrs; ++i) {
4313                 if (!attr_klass || mono_class_has_parent (cinfo->attrs [i].ctor->klass, attr_klass))
4314                         nattrs ++;
4315         }
4316         buffer_add_int (buf, nattrs);
4317
4318         for (i = 0; i < cinfo->num_attrs; ++i) {
4319                 MonoCustomAttrEntry *attr = &cinfo->attrs [i];
4320                 if (!attr_klass || mono_class_has_parent (attr->ctor->klass, attr_klass)) {
4321                         MonoArray *typed_args, *named_args;
4322                         MonoType *t;
4323                         CattrNamedArg *arginfo;
4324
4325                         mono_reflection_create_custom_attr_data_args (image, attr->ctor, attr->data, attr->data_size, &typed_args, &named_args, &arginfo);
4326
4327                         buffer_add_methodid (buf, domain, attr->ctor);
4328
4329                         /* Ctor args */
4330                         if (typed_args) {
4331                                 buffer_add_int (buf, mono_array_length (typed_args));
4332                                 for (j = 0; j < mono_array_length (typed_args); ++j) {
4333                                         MonoObject *val = mono_array_get (typed_args, MonoObject*, j);
4334
4335                                         t = mono_method_signature (attr->ctor)->params [j];
4336
4337                                         buffer_add_cattr_arg (buf, t, domain, val);
4338                                 }
4339                         } else {
4340                                 buffer_add_int (buf, 0);
4341                         }
4342
4343                         /* Named args */
4344                         if (named_args) {
4345                                 buffer_add_int (buf, mono_array_length (named_args));
4346
4347                                 for (j = 0; j < mono_array_length (named_args); ++j) {
4348                                         MonoObject *val = mono_array_get (named_args, MonoObject*, j);
4349
4350                                         if (arginfo [j].prop) {
4351                                                 buffer_add_byte (buf, 0x54);
4352                                                 buffer_add_propertyid (buf, domain, arginfo [j].prop);
4353                                         } else if (arginfo [j].field) {
4354                                                 buffer_add_byte (buf, 0x53);
4355                                         } else {
4356                                                 g_assert_not_reached ();
4357                                         }
4358
4359                                         buffer_add_cattr_arg (buf, t, domain, val);
4360                                 }
4361                         } else {
4362                                 buffer_add_int (buf, 0);
4363                         }
4364                 }
4365         }
4366 }
4367
4368 static ErrorCode
4369 type_commands (int command, guint8 *p, guint8 *end, Buffer *buf)
4370 {
4371         MonoClass *klass;
4372         MonoDomain *domain;
4373         MonoClass *nested;
4374         MonoType *type;
4375         gpointer iter;
4376         guint8 b;
4377         int err, nnested;
4378         char *name;
4379
4380         klass = decode_typeid (p, &p, end, &domain, &err);
4381         if (err)
4382                 return err;
4383
4384         switch (command) {
4385         case CMD_TYPE_GET_INFO: {
4386                 buffer_add_string (buf, klass->name_space);
4387                 buffer_add_string (buf, klass->name);
4388                 // FIXME: byref
4389                 name = mono_type_get_name_full (&klass->byval_arg, MONO_TYPE_NAME_FORMAT_FULL_NAME);
4390                 buffer_add_string (buf, name);
4391                 g_free (name);
4392                 buffer_add_assemblyid (buf, domain, klass->image->assembly);
4393                 buffer_add_moduleid (buf, domain, klass->image);
4394                 buffer_add_typeid (buf, domain, klass->parent);
4395                 if (klass->rank || klass->byval_arg.type == MONO_TYPE_PTR)
4396                         buffer_add_typeid (buf, domain, klass->element_class);
4397                 else
4398                         buffer_add_id (buf, 0);
4399                 buffer_add_int (buf, klass->type_token);
4400                 buffer_add_byte (buf, klass->rank);
4401                 buffer_add_int (buf, klass->flags);
4402                 b = 0;
4403                 type = &klass->byval_arg;
4404                 // FIXME: Can't decide whenever a class represents a byref type
4405                 if (FALSE)
4406                         b |= (1 << 0);
4407                 if (type->type == MONO_TYPE_PTR)
4408                         b |= (1 << 1);
4409                 if (!type->byref && (((type->type >= MONO_TYPE_BOOLEAN) && (type->type <= MONO_TYPE_R8)) || (type->type == MONO_TYPE_I) || (type->type == MONO_TYPE_U)))
4410                         b |= (1 << 2);
4411                 if (type->type == MONO_TYPE_VALUETYPE)
4412                         b |= (1 << 3);
4413                 buffer_add_byte (buf, b);
4414                 nnested = 0;
4415                 iter = NULL;
4416                 while ((nested = mono_class_get_nested_types (klass, &iter)))
4417                         nnested ++;
4418                 buffer_add_int (buf, nnested);
4419                 iter = NULL;
4420                 while ((nested = mono_class_get_nested_types (klass, &iter)))
4421                         buffer_add_typeid (buf, domain, nested);
4422                 break;
4423         }
4424         case CMD_TYPE_GET_METHODS: {
4425                 int nmethods;
4426                 int i = 0;
4427                 gpointer iter = NULL;
4428                 MonoMethod *m;
4429
4430                 nmethods = mono_class_num_methods (klass);
4431
4432                 buffer_add_int (buf, nmethods);
4433
4434                 while ((m = mono_class_get_methods (klass, &iter))) {
4435                         buffer_add_methodid (buf, domain, m);
4436                         i ++;
4437                 }
4438                 g_assert (i == nmethods);
4439                 break;
4440         }
4441         case CMD_TYPE_GET_FIELDS: {
4442                 int nfields;
4443                 int i = 0;
4444                 gpointer iter = NULL;
4445                 MonoClassField *f;
4446
4447                 nfields = mono_class_num_fields (klass);
4448
4449                 buffer_add_int (buf, nfields);
4450
4451                 while ((f = mono_class_get_fields (klass, &iter))) {
4452                         buffer_add_fieldid (buf, domain, f);
4453                         buffer_add_string (buf, f->name);
4454                         buffer_add_typeid (buf, domain, mono_class_from_mono_type (f->type));
4455                         buffer_add_int (buf, f->type->attrs);
4456                         i ++;
4457                 }
4458                 g_assert (i == nfields);
4459                 break;
4460         }
4461         case CMD_TYPE_GET_PROPERTIES: {
4462                 int nprops;
4463                 int i = 0;
4464                 gpointer iter = NULL;
4465                 MonoProperty *p;
4466
4467                 nprops = mono_class_num_properties (klass);
4468
4469                 buffer_add_int (buf, nprops);
4470
4471                 while ((p = mono_class_get_properties (klass, &iter))) {
4472                         buffer_add_propertyid (buf, domain, p);
4473                         buffer_add_string (buf, p->name);
4474                         buffer_add_methodid (buf, domain, p->get);
4475                         buffer_add_methodid (buf, domain, p->set);
4476                         buffer_add_int (buf, p->attrs);
4477                         i ++;
4478                 }
4479                 g_assert (i == nprops);
4480                 break;
4481         }
4482         case CMD_TYPE_GET_CATTRS: {
4483                 MonoClass *attr_klass = decode_typeid (p, &p, end, NULL, &err);
4484                 MonoCustomAttrInfo *cinfo;
4485
4486                 cinfo = mono_custom_attrs_from_class (klass);
4487
4488                 buffer_add_cattrs (buf, domain, klass->image, attr_klass, cinfo);
4489                 break;
4490         }
4491         case CMD_TYPE_GET_FIELD_CATTRS: {
4492                 MonoClass *attr_klass;
4493                 MonoCustomAttrInfo *cinfo;
4494                 MonoClassField *field;
4495
4496                 field = decode_fieldid (p, &p, end, NULL, &err);
4497                 if (err)
4498                         return err;
4499                 attr_klass = decode_typeid (p, &p, end, NULL, &err);
4500                 if (err)
4501                         return err;
4502
4503                 cinfo = mono_custom_attrs_from_field (klass, field);
4504
4505                 buffer_add_cattrs (buf, domain, klass->image, attr_klass, cinfo);
4506                 break;
4507         }
4508         case CMD_TYPE_GET_PROPERTY_CATTRS: {
4509                 MonoClass *attr_klass;
4510                 MonoCustomAttrInfo *cinfo;
4511                 MonoProperty *prop;
4512
4513                 prop = decode_propertyid (p, &p, end, NULL, &err);
4514                 if (err)
4515                         return err;
4516                 attr_klass = decode_typeid (p, &p, end, NULL, &err);
4517                 if (err)
4518                         return err;
4519
4520                 cinfo = mono_custom_attrs_from_property (klass, prop);
4521
4522                 buffer_add_cattrs (buf, domain, klass->image, attr_klass, cinfo);
4523                 break;
4524         }
4525         case CMD_TYPE_GET_VALUES: {
4526                 guint8 *val;
4527                 MonoClassField *f;
4528                 MonoVTable *vtable;
4529                 MonoClass *k;
4530                 int len, i;
4531                 gboolean found;
4532
4533                 len = decode_int (p, &p, end);
4534                 for (i = 0; i < len; ++i) {
4535                         f = decode_fieldid (p, &p, end, NULL, &err);
4536                         if (err)
4537                                 return err;
4538
4539                         if (!(f->type->attrs & FIELD_ATTRIBUTE_STATIC))
4540                                 return ERR_INVALID_FIELDID;
4541                         if (mono_class_field_is_special_static (f))
4542                                 return ERR_INVALID_FIELDID;
4543
4544                         /* Check that the field belongs to the object */
4545                         found = FALSE;
4546                         for (k = klass; k; k = k->parent) {
4547                                 if (k == f->parent) {
4548                                         found = TRUE;
4549                                         break;
4550                                 }
4551                         }
4552                         if (!found)
4553                                 return ERR_INVALID_FIELDID;
4554
4555                         vtable = mono_class_vtable (domain, f->parent);
4556                         val = g_malloc (mono_class_instance_size (mono_class_from_mono_type (f->type)));
4557                         mono_field_static_get_value (vtable, f, val);
4558                         buffer_add_value (buf, f->type, val, domain);
4559                         g_free (val);
4560                 }
4561                 break;
4562         }
4563         case CMD_TYPE_SET_VALUES: {
4564                 guint8 *val;
4565                 MonoClassField *f;
4566                 MonoVTable *vtable;
4567                 MonoClass *k;
4568                 int len, i;
4569                 gboolean found;
4570
4571                 len = decode_int (p, &p, end);
4572                 for (i = 0; i < len; ++i) {
4573                         f = decode_fieldid (p, &p, end, NULL, &err);
4574                         if (err)
4575                                 return err;
4576
4577                         if (!(f->type->attrs & FIELD_ATTRIBUTE_STATIC))
4578                                 return ERR_INVALID_FIELDID;
4579                         if (mono_class_field_is_special_static (f))
4580                                 return ERR_INVALID_FIELDID;
4581
4582                         /* Check that the field belongs to the object */
4583                         found = FALSE;
4584                         for (k = klass; k; k = k->parent) {
4585                                 if (k == f->parent) {
4586                                         found = TRUE;
4587                                         break;
4588                                 }
4589                         }
4590                         if (!found)
4591                                 return ERR_INVALID_FIELDID;
4592
4593                         // FIXME: Check for literal/const
4594
4595                         vtable = mono_class_vtable (domain, f->parent);
4596                         val = g_malloc (mono_class_instance_size (mono_class_from_mono_type (f->type)));
4597                         err = decode_value (f->type, domain, val, p, &p, end);
4598                         if (err) {
4599                                 g_free (val);
4600                                 return err;
4601                         }
4602                         mono_field_static_set_value (vtable, f, val);
4603                         g_free (val);
4604                 }
4605                 break;
4606         }
4607         case CMD_TYPE_GET_OBJECT: {
4608                 MonoObject *o = (MonoObject*)mono_type_get_object (mono_domain_get (), &klass->byval_arg);
4609                 buffer_add_objid (buf, o);
4610                 break;
4611         }
4612         case CMD_TYPE_GET_SOURCE_FILES: {
4613                 gpointer iter = NULL;
4614                 MonoMethod *method;
4615                 char *source_file, *base;
4616                 GPtrArray *files;
4617                 int i;
4618
4619                 files = g_ptr_array_new ();
4620
4621                 while ((method = mono_class_get_methods (klass, &iter))) {
4622                         MonoDebugMethodInfo *minfo = mono_debug_lookup_method (method);
4623
4624                         if (minfo) {
4625                                 mono_debug_symfile_get_line_numbers (minfo, &source_file, NULL, NULL, NULL);
4626
4627                                 for (i = 0; i < files->len; ++i)
4628                                         if (!strcmp (g_ptr_array_index (files, i), source_file))
4629                                                 break;
4630                                 if (i == files->len)
4631                                         g_ptr_array_add (files, g_strdup (source_file));
4632                                 g_free (source_file);
4633                         }
4634                 }
4635
4636                 buffer_add_int (buf, files->len);
4637                 for (i = 0; i < files->len; ++i) {
4638                         source_file = g_ptr_array_index (files, i);
4639                         base = g_path_get_basename (source_file);
4640                         buffer_add_string (buf, base);
4641                         g_free (base);
4642                         g_free (source_file);
4643                 }
4644                 g_ptr_array_free (files, TRUE);
4645                 break;
4646         }
4647         case CMD_TYPE_IS_ASSIGNABLE_FROM: {
4648                 MonoClass *oklass = decode_typeid (p, &p, end, NULL, &err);
4649
4650                 if (err)
4651                         return err;
4652                 if (mono_class_is_assignable_from (klass, oklass))
4653                         buffer_add_byte (buf, 1);
4654                 else
4655                         buffer_add_byte (buf, 0);
4656                 break;
4657         }
4658         default:
4659                 return ERR_NOT_IMPLEMENTED;
4660         }
4661
4662         return ERR_NONE;
4663 }
4664
4665 static ErrorCode
4666 method_commands (int command, guint8 *p, guint8 *end, Buffer *buf)
4667 {
4668         int err;
4669         MonoDomain *domain;
4670         MonoMethod *method;
4671         MonoMethodHeader *header;
4672
4673         method = decode_methodid (p, &p, end, &domain, &err);
4674         if (err)
4675                 return err;
4676
4677         switch (command) {
4678         case CMD_METHOD_GET_NAME: {
4679                 buffer_add_string (buf, method->name);
4680                 break;                  
4681         }
4682         case CMD_METHOD_GET_DECLARING_TYPE: {
4683                 buffer_add_typeid (buf, domain, method->klass);
4684                 break;
4685         }
4686         case CMD_METHOD_GET_DEBUG_INFO: {
4687                 MonoDebugMethodInfo *minfo;
4688                 char *source_file;
4689                 int i, n_il_offsets;
4690                 int *il_offsets;
4691                 int *line_numbers;
4692
4693                 header = mono_method_get_header (method);
4694                 if (!header) {
4695                         buffer_add_int (buf, 0);
4696                         buffer_add_string (buf, "");
4697                         buffer_add_int (buf, 0);
4698                         break;
4699                 }
4700
4701                 minfo = mono_debug_lookup_method (method);
4702                 if (!minfo) {
4703                         buffer_add_int (buf, header->code_size);
4704                         buffer_add_string (buf, "");
4705                         buffer_add_int (buf, 0);
4706                         break;
4707                 }
4708
4709                 mono_debug_symfile_get_line_numbers (minfo, &source_file, &n_il_offsets, &il_offsets, &line_numbers);
4710                 buffer_add_int (buf, header->code_size);
4711                 buffer_add_string (buf, source_file);
4712                 buffer_add_int (buf, n_il_offsets);
4713                 //printf ("Line number table for method %s:\n", mono_method_full_name (method,  TRUE));
4714                 for (i = 0; i < n_il_offsets; ++i) {
4715                         //printf ("IL%d -> %d\n", il_offsets [i], line_numbers [i]);
4716                         buffer_add_int (buf, il_offsets [i]);
4717                         buffer_add_int (buf, line_numbers [i]);
4718                 }
4719                 g_free (source_file);
4720                 g_free (il_offsets);
4721                 g_free (line_numbers);
4722                 break;
4723         }
4724         case CMD_METHOD_GET_PARAM_INFO: {
4725                 MonoMethodSignature *sig = mono_method_signature (method);
4726                 guint32 i;
4727                 char **names;
4728
4729                 /* FIXME: mono_class_from_mono_type () and byrefs */
4730
4731                 /* FIXME: Use a smaller encoding */
4732                 buffer_add_int (buf, sig->call_convention);
4733                 buffer_add_int (buf, sig->param_count);
4734                 buffer_add_int (buf, sig->generic_param_count);
4735                 buffer_add_typeid (buf, domain, mono_class_from_mono_type (sig->ret));
4736                 for (i = 0; i < sig->param_count; ++i) {
4737                         /* FIXME: vararg */
4738                         buffer_add_typeid (buf, domain, mono_class_from_mono_type (sig->params [i]));
4739                 }
4740
4741                 /* Emit parameter names */
4742                 names = g_new (char *, sig->param_count);
4743                 mono_method_get_param_names (method, (const char **) names);
4744                 for (i = 0; i < sig->param_count; ++i)
4745                         buffer_add_string (buf, names [i]);
4746                 g_free (names);
4747
4748                 break;
4749         }
4750         case CMD_METHOD_GET_LOCALS_INFO: {
4751                 int i, j, num_locals;
4752                 char **local_names;
4753                 int *local_indexes;
4754
4755                 header = mono_method_get_header (method);
4756                 g_assert (header);
4757
4758                 buffer_add_int (buf, header->num_locals);
4759
4760                 /* Types */
4761                 for (i = 0; i < header->num_locals; ++i)
4762                         buffer_add_typeid (buf, domain, mono_class_from_mono_type (header->locals [i]));
4763
4764                 /* Names */
4765                 num_locals = mono_debug_lookup_locals (method, &local_names, &local_indexes);
4766                 for (i = 0; i < header->num_locals; ++i) {
4767                         for (j = 0; j < num_locals; ++j)
4768                                 if (local_indexes [j] == i)
4769                                         break;
4770                         if (j < num_locals)
4771                                 buffer_add_string (buf, local_names [j]);
4772                         else
4773                                 buffer_add_string (buf, "");
4774                 }
4775                 g_free (local_names);
4776                 g_free (local_indexes);
4777
4778                 /* Live ranges */
4779                 /* FIXME: This works because we set debug_options.mdb_optimizations */
4780                 for (i = 0; i < header->num_locals; ++i) {
4781                         buffer_add_int (buf, 0);
4782                         buffer_add_int (buf, header->code_size);
4783                 }
4784
4785                 break;
4786         }
4787         case CMD_METHOD_GET_INFO:
4788                 buffer_add_int (buf, method->flags);
4789                 buffer_add_int (buf, method->iflags);
4790                 buffer_add_int (buf, method->token);
4791                 break;
4792         case CMD_METHOD_GET_BODY: {
4793                 int i;
4794
4795                 header = mono_method_get_header (method);
4796                 if (!header) {
4797                         buffer_add_int (buf, 0);
4798                 } else {
4799                         buffer_add_int (buf, header->code_size);
4800                         for (i = 0; i < header->code_size; ++i)
4801                                 buffer_add_byte (buf, header->code [i]);
4802                 }
4803                 break;
4804         }
4805         case CMD_METHOD_RESOLVE_TOKEN: {
4806                 guint32 token = decode_int (p, &p, end);
4807
4808                 // FIXME: Generics
4809                 switch (mono_metadata_token_code (token)) {
4810                 case MONO_TOKEN_STRING: {
4811                         MonoString *s;
4812                         char *s2;
4813
4814                         s = mono_ldstr (domain, method->klass->image, mono_metadata_token_index (token));
4815                         g_assert (s);
4816
4817                         s2 = mono_string_to_utf8 (s);
4818
4819                         buffer_add_byte (buf, TOKEN_TYPE_STRING);
4820                         buffer_add_string (buf, s2);
4821                         g_free (s2);
4822                         break;
4823                 }
4824                 default: {
4825                         gpointer val;
4826                         MonoClass *handle_class;
4827
4828                         if (method->wrapper_type == MONO_WRAPPER_DYNAMIC_METHOD) {
4829                                 val = mono_method_get_wrapper_data (method, token);
4830                                 handle_class = mono_method_get_wrapper_data (method, token + 1);
4831
4832                                 if (handle_class == NULL) {
4833                                         // Can't figure out the token type
4834                                         buffer_add_byte (buf, TOKEN_TYPE_UNKNOWN);
4835                                         break;
4836                                 }
4837                         } else {
4838                                 val = mono_ldtoken (method->klass->image, token, &handle_class, NULL);
4839                                 g_assert (val);
4840                         }
4841
4842                         if (handle_class == mono_defaults.typehandle_class) {
4843                                 buffer_add_byte (buf, TOKEN_TYPE_TYPE);
4844                                 buffer_add_typeid (buf, domain, mono_class_from_mono_type ((MonoType*)val));
4845                         } else if (handle_class == mono_defaults.fieldhandle_class) {
4846                                 buffer_add_byte (buf, TOKEN_TYPE_FIELD);
4847                                 buffer_add_fieldid (buf, domain, val);
4848                         } else if (handle_class == mono_defaults.methodhandle_class) {
4849                                 buffer_add_byte (buf, TOKEN_TYPE_METHOD);
4850                                 buffer_add_methodid (buf, domain, val);
4851                         } else if (handle_class == mono_defaults.string_class) {
4852                                 char *s;
4853
4854                                 s = mono_string_to_utf8 (val);
4855                                 buffer_add_byte (buf, TOKEN_TYPE_STRING);
4856                                 buffer_add_string (buf, s);
4857                                 g_free (s);
4858                         } else {
4859                                 g_assert_not_reached ();
4860                         }
4861                         break;
4862                 }
4863                 }
4864                 break;
4865         }
4866         default:
4867                 return ERR_NOT_IMPLEMENTED;
4868         }
4869
4870         return ERR_NONE;
4871 }
4872
4873 static ErrorCode
4874 thread_commands (int command, guint8 *p, guint8 *end, Buffer *buf)
4875 {
4876         int objid = decode_objid (p, &p, end);
4877         int err;
4878         MonoThread *thread_obj;
4879         MonoInternalThread *thread;
4880
4881         err = get_object (objid, (MonoObject**)&thread_obj);
4882         if (err)
4883                 return err;
4884
4885         thread = thread_obj->internal_thread;
4886            
4887         switch (command) {
4888         case CMD_THREAD_GET_NAME: {
4889                 guint32 name_len;
4890                 gunichar2 *s = mono_thread_get_name (thread, &name_len);
4891
4892                 if (!s) {
4893                         buffer_add_int (buf, 0);
4894                 } else {
4895                         char *name;
4896                         glong len;
4897
4898                         name = g_utf16_to_utf8 (s, name_len, NULL, &len, NULL);
4899                         g_assert (name);
4900                         buffer_add_int (buf, len);
4901                         buffer_add_data (buf, (guint8*)name, len);
4902                         g_free (s);
4903                 }
4904                 break;
4905         }
4906         case CMD_THREAD_GET_FRAME_INFO: {
4907                 DebuggerTlsData *tls;
4908                 int i, start_frame, length;
4909
4910                 // Wait for suspending if it already started
4911                 if (suspend_count)
4912                         wait_for_suspend ();
4913                 if (!is_suspended ())
4914                         return ERR_NOT_SUSPENDED;
4915
4916                 start_frame = decode_int (p, &p, end);
4917                 length = decode_int (p, &p, end);
4918
4919                 if (start_frame != 0 || length != -1)
4920                         return ERR_NOT_IMPLEMENTED;
4921
4922                 mono_loader_lock ();
4923                 tls = mono_g_hash_table_lookup (thread_to_tls, thread);
4924                 mono_loader_unlock ();
4925                 g_assert (tls);
4926
4927                 compute_frame_info (thread, tls);
4928
4929                 buffer_add_int (buf, tls->frame_count);
4930                 for (i = 0; i < tls->frame_count; ++i) {
4931                         buffer_add_int (buf, tls->frames [i]->id);
4932                         buffer_add_methodid (buf, tls->frames [i]->domain, tls->frames [i]->method);
4933                         buffer_add_int (buf, tls->frames [i]->il_offset);
4934                         /*
4935                          * Instead of passing the frame type directly to the client, we associate
4936                          * it with the previous frame using a set of flags. This avoids lots of
4937                          * conditional code in the client, since a frame whose type isn't 
4938                          * FRAME_TYPE_MANAGED has no method, location, etc.
4939                          */
4940                         buffer_add_byte (buf, tls->frames [i]->flags);
4941                 }
4942
4943                 break;
4944         }
4945         case CMD_THREAD_GET_STATE:
4946                 buffer_add_int (buf, thread->state);
4947                 break;
4948         case CMD_THREAD_GET_INFO:
4949                 buffer_add_byte (buf, thread->threadpool_thread);
4950                 break;
4951         default:
4952                 return ERR_NOT_IMPLEMENTED;
4953         }
4954
4955         return ERR_NONE;
4956 }
4957
4958 static ErrorCode
4959 frame_commands (int command, guint8 *p, guint8 *end, Buffer *buf)
4960 {
4961         int objid;
4962         int err;
4963         MonoThread *thread_obj;
4964         MonoInternalThread *thread;
4965         int pos, i, len;
4966         DebuggerTlsData *tls;
4967         StackFrame *frame;
4968         MonoDebugMethodJitInfo *jit;
4969         MonoDebugVarInfo *var;
4970         MonoMethodSignature *sig;
4971         gssize id;
4972         MonoMethodHeader *header;
4973
4974         objid = decode_objid (p, &p, end);
4975         err = get_object (objid, (MonoObject**)&thread_obj);
4976         if (err)
4977                 return err;
4978
4979         thread = thread_obj->internal_thread;
4980
4981         id = decode_id (p, &p, end);
4982
4983         mono_loader_lock ();
4984         tls = mono_g_hash_table_lookup (thread_to_tls, thread);
4985         mono_loader_unlock ();
4986         g_assert (tls);
4987
4988         for (i = 0; i < tls->frame_count; ++i) {
4989                 if (tls->frames [i]->id == id)
4990                         break;
4991         }
4992         if (i == tls->frame_count)
4993                 return ERR_INVALID_FRAMEID;
4994
4995         frame = tls->frames [i];
4996
4997         if (!frame->jit) {
4998                 frame->jit = mono_debug_find_method (frame->method, frame->domain);
4999                 g_assert (frame->jit);
5000         }
5001         jit = frame->jit;
5002
5003         sig = mono_method_signature (frame->method);
5004
5005         switch (command) {
5006         case CMD_STACK_FRAME_GET_VALUES: {
5007                 len = decode_int (p, &p, end);
5008                 header = mono_method_get_header (frame->method);
5009
5010                 for (i = 0; i < len; ++i) {
5011                         pos = decode_int (p, &p, end);
5012
5013                         if (pos < 0) {
5014                                 pos = - pos - 1;
5015
5016                                 g_assert (pos >= 0 && pos < jit->num_params);
5017
5018                                 var = &jit->params [pos];
5019
5020                                 add_var (buf, sig->params [pos], &jit->params [pos], &frame->ctx, frame->domain);
5021                         } else {
5022                                 g_assert (pos >= 0 && pos < jit->num_locals);
5023
5024                                 var = &jit->locals [pos];
5025                                 
5026                                 add_var (buf, header->locals [pos], &jit->locals [pos], &frame->ctx, frame->domain);
5027                         }
5028                 }
5029                 break;
5030         }
5031         case CMD_STACK_FRAME_GET_THIS: {
5032                 if (frame->method->klass->valuetype) {
5033                         if (!sig->hasthis) {
5034                                 MonoObject *p = NULL;
5035                                 buffer_add_value (buf, &mono_defaults.object_class->byval_arg, &p, frame->domain);
5036                         } else {
5037                                 add_var (buf, &frame->method->klass->this_arg, jit->this_var, &frame->ctx, frame->domain);
5038                         }
5039                 } else {
5040                         if (!sig->hasthis) {
5041                                 MonoObject *p = NULL;
5042                                 buffer_add_value (buf, &frame->method->klass->byval_arg, &p, frame->domain);
5043                         } else {
5044                                 add_var (buf, &frame->method->klass->byval_arg, jit->this_var, &frame->ctx, frame->domain);
5045                         }
5046                 }
5047                 break;
5048         }
5049         case CMD_STACK_FRAME_SET_VALUES: {
5050                 guint8 *val_buf;
5051                 MonoType *t;
5052                 MonoDebugVarInfo *var;
5053
5054                 len = decode_int (p, &p, end);
5055                 header = mono_method_get_header (frame->method);
5056
5057                 for (i = 0; i < len; ++i) {
5058                         pos = decode_int (p, &p, end);
5059
5060                         if (pos < 0) {
5061                                 pos = - pos - 1;
5062
5063                                 g_assert (pos >= 0 && pos < jit->num_params);
5064
5065                                 t = sig->params [pos];
5066                                 var = &jit->params [pos];
5067                         } else {
5068                                 g_assert (pos >= 0 && pos < jit->num_locals);
5069
5070                                 t = header->locals [pos];
5071                                 var = &jit->locals [pos];
5072                         }
5073
5074                         if (MONO_TYPE_IS_REFERENCE (t))
5075                                 val_buf = g_alloca (sizeof (MonoObject*));
5076                         else
5077                                 val_buf = g_alloca (mono_class_instance_size (mono_class_from_mono_type (t)));
5078                         err = decode_value (t, frame->domain, val_buf, p, &p, end);
5079                         if (err)
5080                                 return err;
5081
5082                         set_var (t, var, &frame->ctx, frame->domain, val_buf);
5083                 }
5084                 break;
5085         }
5086         default:
5087                 return ERR_NOT_IMPLEMENTED;
5088         }
5089
5090         return ERR_NONE;
5091 }
5092
5093 static ErrorCode
5094 array_commands (int command, guint8 *p, guint8 *end, Buffer *buf)
5095 {
5096         MonoArray *arr;
5097         int objid, err, index, len, i, esize;
5098         gpointer elem;
5099
5100         objid = decode_objid (p, &p, end);
5101         err = get_object (objid, (MonoObject**)&arr);
5102         if (err)
5103                 return err;
5104
5105         switch (command) {
5106         case CMD_ARRAY_REF_GET_LENGTH:
5107                 buffer_add_int (buf, arr->obj.vtable->klass->rank);
5108                 if (!arr->bounds) {
5109                         buffer_add_int (buf, arr->max_length);
5110                         buffer_add_int (buf, 0);
5111                 } else {
5112                         for (i = 0; i < arr->obj.vtable->klass->rank; ++i) {
5113                                 buffer_add_int (buf, arr->bounds [i].length);
5114                                 buffer_add_int (buf, arr->bounds [i].lower_bound);
5115                         }
5116                 }
5117                 break;
5118         case CMD_ARRAY_REF_GET_VALUES:
5119                 index = decode_int (p, &p, end);
5120                 len = decode_int (p, &p, end);
5121
5122                 g_assert (index >= 0 && len >= 0);
5123                 // Reordered to avoid integer overflow
5124                 g_assert (!(index > arr->max_length - len));
5125
5126                 esize = mono_array_element_size (arr->obj.vtable->klass);
5127                 for (i = index; i < index + len; ++i) {
5128                         elem = (gpointer*)((char*)arr->vector + (i * esize));
5129                         buffer_add_value (buf, &arr->obj.vtable->klass->element_class->byval_arg, elem, arr->obj.vtable->domain);
5130                 }
5131                 break;
5132         case CMD_ARRAY_REF_SET_VALUES:
5133                 index = decode_int (p, &p, end);
5134                 len = decode_int (p, &p, end);
5135
5136                 g_assert (index >= 0 && len >= 0);
5137                 // Reordered to avoid integer overflow
5138                 g_assert (!(index > arr->max_length - len));
5139
5140                 esize = mono_array_element_size (arr->obj.vtable->klass);
5141                 for (i = index; i < index + len; ++i) {
5142                         elem = (gpointer*)((char*)arr->vector + (i * esize));
5143
5144                         decode_value (&arr->obj.vtable->klass->element_class->byval_arg, arr->obj.vtable->domain, elem, p, &p, end);
5145                 }
5146                 break;
5147         default:
5148                 return ERR_NOT_IMPLEMENTED;
5149         }
5150
5151         return ERR_NONE;
5152 }
5153
5154 static ErrorCode
5155 string_commands (int command, guint8 *p, guint8 *end, Buffer *buf)
5156 {
5157         int objid, err;
5158         MonoString *str;
5159         char *s;
5160
5161         objid = decode_objid (p, &p, end);
5162         err = get_object (objid, (MonoObject**)&str);
5163         if (err)
5164                 return err;
5165
5166         switch (command) {
5167         case CMD_STRING_REF_GET_VALUE:
5168                 s = mono_string_to_utf8 (str);
5169                 buffer_add_string (buf, s);
5170                 g_free (s);
5171                 break;
5172         default:
5173                 return ERR_NOT_IMPLEMENTED;
5174         }
5175
5176         return ERR_NONE;
5177 }
5178
5179 static ErrorCode
5180 object_commands (int command, guint8 *p, guint8 *end, Buffer *buf)
5181 {
5182         int objid, err;
5183         MonoObject *obj;
5184         int len, i;
5185         MonoClassField *f;
5186         MonoClass *k;
5187         gboolean found;
5188
5189         if (command == CMD_OBJECT_REF_IS_COLLECTED) {
5190                 objid = decode_objid (p, &p, end);
5191                 err = get_object (objid, &obj);
5192                 if (err)
5193                         buffer_add_int (buf, 1);
5194                 else
5195                         buffer_add_int (buf, 0);
5196                 return 0;
5197         }
5198
5199         objid = decode_objid (p, &p, end);
5200         err = get_object (objid, &obj);
5201         if (err)
5202                 return err;
5203
5204         switch (command) {
5205         case CMD_OBJECT_REF_GET_TYPE:
5206                 buffer_add_typeid (buf, obj->vtable->domain, obj->vtable->klass);
5207                 break;
5208         case CMD_OBJECT_REF_GET_VALUES:
5209                 len = decode_int (p, &p, end);
5210
5211                 for (i = 0; i < len; ++i) {
5212                         MonoClassField *f = decode_fieldid (p, &p, end, NULL, &err);
5213                         if (err)
5214                                 return err;
5215
5216                         /* Check that the field belongs to the object */
5217                         found = FALSE;
5218                         for (k = obj->vtable->klass; k; k = k->parent) {
5219                                 if (k == f->parent) {
5220                                         found = TRUE;
5221                                         break;
5222                                 }
5223                         }
5224                         if (!found)
5225                                 return ERR_INVALID_FIELDID;
5226
5227                         if (f->type->attrs & FIELD_ATTRIBUTE_STATIC) {
5228                                 guint8 *val;
5229                                 MonoVTable *vtable;
5230
5231                                 if (mono_class_field_is_special_static (f))
5232                                         return ERR_INVALID_FIELDID;
5233
5234                                 g_assert (f->type->attrs & FIELD_ATTRIBUTE_STATIC);
5235                                 vtable = mono_class_vtable (obj->vtable->domain, f->parent);
5236                                 val = g_malloc (mono_class_instance_size (mono_class_from_mono_type (f->type)));
5237                                 mono_field_static_get_value (vtable, f, val);
5238                                 buffer_add_value (buf, f->type, val, obj->vtable->domain);
5239                                 g_free (val);
5240                         } else {
5241                                 buffer_add_value (buf, f->type, (guint8*)obj + f->offset, obj->vtable->domain);
5242                         }
5243                 }
5244                 break;
5245         case CMD_OBJECT_REF_SET_VALUES:
5246                 len = decode_int (p, &p, end);
5247
5248                 for (i = 0; i < len; ++i) {
5249                         f = decode_fieldid (p, &p, end, NULL, &err);
5250                         if (err)
5251                                 return err;
5252
5253                         /* Check that the field belongs to the object */
5254                         found = FALSE;
5255                         for (k = obj->vtable->klass; k; k = k->parent) {
5256                                 if (k == f->parent) {
5257                                         found = TRUE;
5258                                         break;
5259                                 }
5260                         }
5261                         if (!found)
5262                                 return ERR_INVALID_FIELDID;
5263
5264                         if (f->type->attrs & FIELD_ATTRIBUTE_STATIC) {
5265                                 guint8 *val;
5266                                 MonoVTable *vtable;
5267
5268                                 if (mono_class_field_is_special_static (f))
5269                                         return ERR_INVALID_FIELDID;
5270
5271                                 g_assert (f->type->attrs & FIELD_ATTRIBUTE_STATIC);
5272                                 vtable = mono_class_vtable (obj->vtable->domain, f->parent);
5273
5274                                 val = g_malloc (mono_class_instance_size (mono_class_from_mono_type (f->type)));
5275                                 err = decode_value (f->type, obj->vtable->domain, val, p, &p, end);
5276                                 if (err) {
5277                                         g_free (val);
5278                                         return err;
5279                                 }
5280                                 mono_field_static_set_value (vtable, f, val);
5281                                 g_free (val);
5282                         } else {
5283                                 err = decode_value (f->type, obj->vtable->domain, (guint8*)obj + f->offset, p, &p, end);
5284                                 if (err)
5285                                         return err;
5286                         }
5287                 }
5288                 break;
5289         case CMD_OBJECT_REF_GET_ADDRESS:
5290                 buffer_add_long (buf, (gssize)obj);
5291                 break;
5292         case CMD_OBJECT_REF_GET_DOMAIN:
5293                 buffer_add_domainid (buf, obj->vtable->domain);
5294                 break;
5295         default:
5296                 return ERR_NOT_IMPLEMENTED;
5297         }
5298
5299         return ERR_NONE;
5300 }
5301
5302 static const char*
5303 command_set_to_string (CommandSet command_set)
5304 {
5305         switch (command_set) {
5306         case CMD_SET_VM:
5307                 return "VM";
5308         case CMD_SET_OBJECT_REF:
5309                 return "OBJECT_REF";
5310         case CMD_SET_STRING_REF:
5311                 return "STRING_REF"; 
5312         case CMD_SET_THREAD:
5313                 return "THREAD"; 
5314         case CMD_SET_ARRAY_REF:
5315                 return "ARRAY_REF"; 
5316         case CMD_SET_EVENT_REQUEST:
5317                 return "EVENT_REQUEST"; 
5318         case CMD_SET_STACK_FRAME:
5319                 return "STACK_FRAME"; 
5320         case CMD_SET_APPDOMAIN:
5321                 return "APPDOMAIN"; 
5322         case CMD_SET_ASSEMBLY:
5323                 return "ASSEMBLY"; 
5324         case CMD_SET_METHOD:
5325                 return "METHOD"; 
5326         case CMD_SET_TYPE:
5327                 return "TYPE"; 
5328         case CMD_SET_MODULE:
5329                 return "MODULE"; 
5330         case CMD_SET_EVENT:
5331                 return "EVENT"; 
5332         default:
5333                 return "";
5334         }
5335 }
5336
5337 /*
5338  * debugger_thread:
5339  *
5340  *   This thread handles communication with the debugger client using a JDWP
5341  * like protocol.
5342  */
5343 static guint32 WINAPI
5344 debugger_thread (void *arg)
5345 {
5346         int res, len, id, flags, command_set, command;
5347         guint8 header [HEADER_LENGTH];
5348         guint8 *data, *p, *end;
5349         Buffer buf;
5350         ErrorCode err;
5351         gboolean no_reply;
5352
5353         DEBUG (1, fprintf (log_file, "[dbg] Agent thread started, pid=%p\n", (gpointer)GetCurrentThreadId ()));
5354
5355         debugger_thread_id = GetCurrentThreadId ();
5356
5357         mono_jit_thread_attach (mono_get_root_domain ());
5358
5359         mono_thread_internal_current ()->flags |= MONO_THREAD_FLAG_DONT_MANAGE;
5360
5361         mono_set_is_debugger_attached (TRUE);
5362
5363         while (TRUE) {
5364                 res = read (conn_fd, header, HEADER_LENGTH);
5365
5366                 /* This will break if the socket is closed during shutdown too */
5367                 if (res != HEADER_LENGTH)
5368                         break;
5369
5370                 p = header;
5371                 end = header + HEADER_LENGTH;
5372
5373                 len = decode_int (p, &p, end);
5374                 id = decode_int (p, &p, end);
5375                 flags = decode_byte (p, &p, end);
5376                 command_set = decode_byte (p, &p, end);
5377                 command = decode_byte (p, &p, end);
5378
5379                 g_assert (flags == 0);
5380
5381                 DEBUG (1, fprintf (log_file, "[dbg] Received command %s(%d), id=%d.\n", command_set_to_string (command_set), command, id));
5382
5383                 data = g_malloc (len - HEADER_LENGTH);
5384                 res = read (conn_fd, data, len - HEADER_LENGTH);
5385                 if (res != len - HEADER_LENGTH)
5386                         break;
5387
5388                 p = data;
5389                 end = data + (len - HEADER_LENGTH);
5390
5391                 buffer_init (&buf, 128);
5392
5393                 err = ERR_NONE;
5394                 no_reply = FALSE;
5395
5396                 /* Process the request */
5397                 switch (command_set) {
5398                 case CMD_SET_VM:
5399                         err = vm_commands (command, id, p, end, &buf);
5400                         if (!err && command == CMD_VM_INVOKE_METHOD)
5401                                 /* Sent after the invoke is complete */
5402                                 no_reply = TRUE;
5403                         break;
5404                 case CMD_SET_EVENT_REQUEST:
5405                         err = event_commands (command, p, end, &buf);
5406                         break;
5407                 case CMD_SET_APPDOMAIN:
5408                         err = domain_commands (command, p, end, &buf);
5409                         break;
5410                 case CMD_SET_ASSEMBLY:
5411                         err = assembly_commands (command, p, end, &buf);
5412                         break;
5413                 case CMD_SET_MODULE:
5414                         err = module_commands (command, p, end, &buf);
5415                         break;
5416                 case CMD_SET_TYPE:
5417                         err = type_commands (command, p, end, &buf);
5418                         break;
5419                 case CMD_SET_METHOD:
5420                         err = method_commands (command, p, end, &buf);
5421                         break;
5422                 case CMD_SET_THREAD:
5423                         err = thread_commands (command, p, end, &buf);
5424                         break;
5425                 case CMD_SET_STACK_FRAME:
5426                         err = frame_commands (command, p, end, &buf);
5427                         break;
5428                 case CMD_SET_ARRAY_REF:
5429                         err = array_commands (command, p, end, &buf);
5430                         break;
5431                 case CMD_SET_STRING_REF:
5432                         err = string_commands (command, p, end, &buf);
5433                         break;
5434                 case CMD_SET_OBJECT_REF:
5435                         err = object_commands (command, p, end, &buf);
5436                         break;
5437                 default:
5438                         err = ERR_NOT_IMPLEMENTED;
5439                 }               
5440
5441                 if (!no_reply)
5442                         send_reply_packet (id, err, &buf);
5443
5444                 g_free (data);
5445                 buffer_free (&buf);
5446
5447                 if (command_set == CMD_SET_VM && command == CMD_VM_DISPOSE)
5448                         break;
5449         }
5450
5451         mono_set_is_debugger_attached (FALSE);
5452
5453         mono_mutex_lock (&debugger_thread_exited_mutex);
5454         debugger_thread_exited = TRUE;
5455         mono_cond_signal (&debugger_thread_exited_cond);
5456         mono_mutex_unlock (&debugger_thread_exited_mutex);
5457
5458 #ifdef PLATFORM_WIN32
5459         shutdown (conn_fd, SD_BOTH);
5460 #else
5461         shutdown (conn_fd, SHUT_RDWR);
5462 #endif
5463
5464         return 0;
5465 }
5466
5467 #else /* DISABLE_DEBUGGER_AGENT */
5468
5469 void
5470 mono_debugger_agent_parse_options (char *options)
5471 {
5472         g_error ("This runtime is configure with the debugger agent disabled.");
5473 }
5474
5475 void
5476 mono_debugger_agent_init (void)
5477 {
5478 }
5479
5480 void
5481 mono_debugger_agent_cleanup (void)
5482 {
5483 }
5484
5485 void
5486 mono_debugger_agent_breakpoint_hit (void *sigctx)
5487 {
5488 }
5489
5490 void
5491 mono_debugger_agent_single_step_event (void *sigctx)
5492 {
5493 }
5494
5495 void
5496 mono_debugger_agent_free_domain_info (MonoDomain *domain)
5497 {
5498 }
5499
5500 gboolean mono_debugger_agent_thread_interrupt (MonoJitInfo *ji)
5501 {
5502 }
5503
5504 void
5505 mono_debugger_agent_handle_exception (MonoException *ext, MonoContext *ctx)
5506 {
5507 }
5508
5509 #endif
5510