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