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