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