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