merge -r 53370:58178
[mono.git] / mono / metadata / mono-debug-debugger.c
1 #include <config.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <mono/metadata/assembly.h>
5 #include <mono/metadata/metadata.h>
6 #include <mono/metadata/tabledefs.h>
7 #include <mono/metadata/tokentype.h>
8 #include <mono/metadata/appdomain.h>
9 #include <mono/metadata/gc-internal.h>
10 #include <mono/os/gc_wrapper.h>
11 #include <mono/metadata/object-internals.h>
12 #include <mono/metadata/class-internals.h>
13 #include <mono/metadata/exception.h>
14 #include <mono/metadata/mono-debug.h>
15 #include <mono/metadata/mono-debug-debugger.h>
16 #include <mono/metadata/mono-endian.h>
17
18 static guint32 debugger_lock_level = 0;
19 static CRITICAL_SECTION debugger_lock_mutex;
20 static gboolean must_reload_symtabs = FALSE;
21 static gboolean mono_debugger_use_debugger = FALSE;
22 static MonoObject *last_exception = NULL;
23
24 struct _MonoDebuggerMetadataInfo {
25         int size;
26         int mono_defaults_size;
27         MonoDefaults *mono_defaults;
28         int type_size;
29         int array_type_size;
30         int klass_size;
31         int klass_instance_size_offset;
32         int klass_parent_offset;
33         int klass_token_offset;
34         int klass_field_offset;
35         int klass_methods_offset;
36         int klass_method_count_offset;
37         int klass_this_arg_offset;
38         int klass_byval_arg_offset;
39         int klass_generic_class_offset;
40         int klass_generic_container_offset;
41         int field_info_size;
42 };
43
44 void (*mono_debugger_event_handler) (MonoDebuggerEvent event, guint64 data, guint64 arg) = NULL;
45
46 #define WRITE_UINT32(ptr,value) G_STMT_START {  \
47         * ((guint32 *) ptr) = value;            \
48         ptr += 4;                               \
49 } G_STMT_END
50
51 #define WRITE_POINTER(ptr,value) G_STMT_START { \
52         * ((gpointer *) ptr) = (gpointer) (value); \
53         ptr += sizeof (gpointer);               \
54 } G_STMT_END
55
56 #define WRITE_STRING(ptr,value) G_STMT_START {  \
57         memcpy (ptr, value, strlen (value)+1);  \
58         ptr += strlen (value)+1;                \
59 } G_STMT_END
60
61 typedef struct {
62         gpointer stack_pointer;
63         MonoObject *exception_obj;
64         guint32 stop;
65 } MonoDebuggerExceptionInfo;
66
67 #ifndef PLATFORM_WIN32
68
69 MonoDebuggerIOLayer mono_debugger_io_layer = {
70         InitializeCriticalSection, DeleteCriticalSection, TryEnterCriticalSection,
71         EnterCriticalSection, LeaveCriticalSection, WaitForSingleObjectEx, SignalObjectAndWait,
72         WaitForMultipleObjectsEx, CreateSemaphore, ReleaseSemaphore, CreateThread,
73         GetCurrentThreadId
74 };
75
76 #endif
77
78 static int initialized = 0;
79
80 void
81 mono_debugger_lock (void)
82 {
83         g_assert (initialized);
84         EnterCriticalSection (&debugger_lock_mutex);
85         debugger_lock_level++;
86 }
87
88 void
89 mono_debugger_unlock (void)
90 {
91         g_assert (initialized);
92         if (debugger_lock_level == 1) {
93                 if (must_reload_symtabs && mono_debugger_use_debugger) {
94                         mono_debugger_event (MONO_DEBUGGER_EVENT_RELOAD_SYMTABS, 0, 0);
95                         must_reload_symtabs = FALSE;
96                 }
97         }
98
99         debugger_lock_level--;
100         LeaveCriticalSection (&debugger_lock_mutex);
101 }
102
103 void
104 mono_debugger_initialize (gboolean use_debugger)
105 {
106         MONO_GC_REGISTER_ROOT (last_exception);
107         
108         g_assert (!mono_debugger_use_debugger);
109
110         InitializeCriticalSection (&debugger_lock_mutex);
111         mono_debugger_use_debugger = use_debugger;
112         initialized = 1;
113 }
114
115 void
116 mono_debugger_add_symbol_file (MonoDebugHandle *handle)
117 {
118         g_assert (mono_debugger_use_debugger);
119
120         mono_debugger_lock ();
121         mono_debugger_event (MONO_DEBUGGER_EVENT_ADD_MODULE, GPOINTER_TO_UINT (handle), 0);
122         mono_debugger_unlock ();
123 }
124
125 void
126 mono_debugger_add_builtin_types (MonoDebugHandle *symfile)
127 {
128         MonoDebuggerMetadataInfo *info;
129         MonoClass klass;
130
131         mono_symbol_table->corlib = symfile;
132         mono_symbol_table->metadata_info = info = g_new0 (MonoDebuggerMetadataInfo, 1);
133
134         info->size = sizeof (MonoDebuggerMetadataInfo);
135         info->mono_defaults = &mono_defaults;
136         info->mono_defaults_size = sizeof (MonoDefaults);
137         info->type_size = sizeof (MonoType);
138         info->array_type_size = sizeof (MonoArrayType);
139         info->klass_size = sizeof (MonoClass);
140         info->klass_instance_size_offset = (guint8*)&klass.instance_size - (guint8*)&klass;
141         info->klass_parent_offset = (guint8*)&klass.parent - (guint8*)&klass;
142         info->klass_token_offset = (guint8*)&klass.type_token - (guint8*)&klass;
143         info->klass_field_offset = (guint8*)&klass.fields - (guint8*)&klass;
144         info->klass_methods_offset = (guint8*)&klass.methods - (guint8*)&klass;
145         info->klass_method_count_offset = (guint8*)&klass.method.count - (guint8*)&klass;
146         info->klass_this_arg_offset = (guint8*)&klass.this_arg - (guint8*)&klass;
147         info->klass_byval_arg_offset = (guint8*)&klass.byval_arg - (guint8*)&klass;
148         info->klass_generic_class_offset = (guint8*)&klass.generic_class - (guint8*)&klass;
149         info->klass_generic_container_offset = (guint8*)&klass.generic_container - (guint8*)&klass;
150         info->field_info_size = sizeof (MonoClassField);
151 }
152
153 void
154 mono_debugger_start_add_type (MonoDebugHandle *symfile, MonoClass *klass)
155 {
156         must_reload_symtabs = TRUE;
157 }
158
159 void
160 mono_debugger_event (MonoDebuggerEvent event, guint64 data, guint64 arg)
161 {
162         if (mono_debugger_event_handler)
163                 (* mono_debugger_event_handler) (event, data, arg);
164 }
165
166 void
167 mono_debugger_cleanup (void)
168 {
169         /* Do nothing yet. */
170 }
171
172 /*
173  * Debugger breakpoint interface.
174  *
175  * This interface is used to insert breakpoints on methods which are not yet JITed.
176  * The debugging code keeps a list of all such breakpoints and automatically inserts the
177  * breakpoint when the method is JITed.
178  */
179
180 static GPtrArray *breakpoints = NULL;
181
182 int
183 mono_debugger_insert_breakpoint_full (MonoMethodDesc *desc)
184 {
185         static int last_breakpoint_id = 0;
186         MonoDebuggerBreakpointInfo *info;
187
188         info = g_new0 (MonoDebuggerBreakpointInfo, 1);
189         info->desc = desc;
190         info->index = ++last_breakpoint_id;
191
192         if (!breakpoints)
193                 breakpoints = g_ptr_array_new ();
194
195         g_ptr_array_add (breakpoints, info);
196
197         return info->index;
198 }
199
200 int
201 mono_debugger_remove_breakpoint (int breakpoint_id)
202 {
203         int i;
204
205         if (!breakpoints)
206                 return 0;
207
208         for (i = 0; i < breakpoints->len; i++) {
209                 MonoDebuggerBreakpointInfo *info = g_ptr_array_index (breakpoints, i);
210
211                 if (info->index != breakpoint_id)
212                         continue;
213
214                 mono_method_desc_free (info->desc);
215                 g_ptr_array_remove (breakpoints, info);
216                 g_free (info);
217                 return 1;
218         }
219
220         return 0;
221 }
222
223 int
224 mono_debugger_insert_breakpoint (const gchar *method_name, gboolean include_namespace)
225 {
226         MonoMethodDesc *desc;
227
228         desc = mono_method_desc_new (method_name, include_namespace);
229         if (!desc)
230                 return 0;
231
232         return mono_debugger_insert_breakpoint_full (desc);
233 }
234
235 int
236 mono_debugger_method_has_breakpoint (MonoMethod *method)
237 {
238         int i;
239
240         if (!breakpoints || (method->wrapper_type != MONO_WRAPPER_NONE))
241                 return 0;
242
243         for (i = 0; i < breakpoints->len; i++) {
244                 MonoDebuggerBreakpointInfo *info = g_ptr_array_index (breakpoints, i);
245
246                 if (!mono_method_desc_full_match (info->desc, method))
247                         continue;
248
249                 return info->index;
250         }
251
252         return 0;
253 }
254
255 void
256 mono_debugger_breakpoint_callback (MonoMethod *method, guint32 index)
257 {
258         mono_debugger_event (MONO_DEBUGGER_EVENT_BREAKPOINT, GPOINTER_TO_UINT (method), index);
259 }
260
261 gboolean
262 mono_debugger_unhandled_exception (gpointer addr, gpointer stack, MonoObject *exc)
263 {
264         if (!mono_debugger_use_debugger)
265                 return FALSE;
266
267         // Prevent the object from being finalized.
268         last_exception = exc;
269         mono_debugger_event (MONO_DEBUGGER_EVENT_UNHANDLED_EXCEPTION,
270                              GPOINTER_TO_UINT (exc), GPOINTER_TO_UINT (addr));
271         return TRUE;
272 }
273
274 void
275 mono_debugger_handle_exception (gpointer addr, gpointer stack, MonoObject *exc)
276 {
277         MonoDebuggerExceptionInfo info;
278
279         if (!mono_debugger_use_debugger)
280                 return;
281
282         // Prevent the object from being finalized.
283         last_exception = exc;
284
285         info.stack_pointer = stack;
286         info.exception_obj = exc;
287         info.stop = 0;
288
289         mono_debugger_event (MONO_DEBUGGER_EVENT_EXCEPTION, GPOINTER_TO_UINT (&info),
290                              GPOINTER_TO_UINT (addr));
291 }
292
293 gboolean
294 mono_debugger_throw_exception (gpointer addr, gpointer stack, MonoObject *exc)
295 {
296         MonoDebuggerExceptionInfo info;
297
298         if (!mono_debugger_use_debugger)
299                 return FALSE;
300
301         // Prevent the object from being finalized.
302         last_exception = exc;
303
304         info.stack_pointer = stack;
305         info.exception_obj = exc;
306         info.stop = 0;
307
308         mono_debugger_event (MONO_DEBUGGER_EVENT_THROW_EXCEPTION, GPOINTER_TO_UINT (&info),
309                              GPOINTER_TO_UINT (addr));
310         return info.stop != 0;
311 }
312
313 static gchar *
314 get_exception_message (MonoObject *exc)
315 {
316         char *message = NULL;
317         MonoString *str; 
318         MonoMethod *method;
319         MonoClass *klass;
320         gint i;
321
322         if (mono_object_isinst (exc, mono_defaults.exception_class)) {
323                 klass = exc->vtable->klass;
324                 method = NULL;
325                 while (klass && method == NULL) {
326                         for (i = 0; i < klass->method.count; ++i) {
327                                 method = klass->methods [i];
328                                 if (!strcmp ("ToString", method->name) &&
329                                     mono_method_signature (method)->param_count == 0 &&
330                                     method->flags & METHOD_ATTRIBUTE_VIRTUAL &&
331                                     method->flags & METHOD_ATTRIBUTE_PUBLIC) {
332                                         break;
333                                 }
334                                 method = NULL;
335                         }
336                         
337                         if (method == NULL)
338                                 klass = klass->parent;
339                 }
340
341                 g_assert (method);
342
343                 str = (MonoString *) mono_runtime_invoke (method, exc, NULL, NULL);
344                 if (str)
345                         message = mono_string_to_utf8 (str);
346         }
347
348         return message;
349 }
350
351 MonoObject *
352 mono_debugger_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObject **exc)
353 {
354         MonoObject *retval;
355         gchar *message;
356
357         if (!strcmp (method->name, ".ctor")) {
358                 retval = obj = mono_object_new (mono_domain_get (), method->klass);
359
360                 mono_runtime_invoke (method, obj, params, exc);
361         } else
362                 retval = mono_runtime_invoke (method, obj, params, exc);
363
364         if (!exc || (*exc == NULL))
365                 return retval;
366
367         message = get_exception_message (*exc);
368         if (message) {
369                 *exc = (MonoObject *) mono_string_new_wrapper (message);
370                 g_free (message);
371         }
372
373         return retval;
374 }
375
376 gboolean
377 mono_debugger_lookup_type (const gchar *type_name)
378 {
379         int i;
380         mono_debugger_lock ();
381
382         for (i = 0; i < mono_symbol_table->num_symbol_files; i++) {
383                 MonoDebugHandle *symfile = mono_symbol_table->symbol_files [i];
384                 MonoType *type;
385                 MonoClass* klass;
386                 gchar *name;
387
388                 name = g_strdup (type_name);
389                 type = mono_reflection_type_from_name (name, symfile->image);
390                 g_free (name);
391                 if (!type)
392                         continue;
393
394                 klass = mono_class_from_mono_type (type);
395                 if (klass)
396                         mono_class_init (klass);
397
398                 mono_debugger_unlock ();
399                 return TRUE;
400         }
401
402         mono_debugger_unlock ();
403         return FALSE;
404 }
405
406 gint32
407 mono_debugger_lookup_assembly (const gchar *name)
408 {
409         MonoAssembly *assembly;
410         MonoImageOpenStatus status;
411         int i;
412
413         mono_debugger_lock ();
414
415  again:
416         for (i = 0; i < mono_symbol_table->num_symbol_files; i++) {
417                 MonoDebugHandle *symfile = mono_symbol_table->symbol_files [i];
418
419                 if (!strcmp (symfile->image_file, name)) {
420                         mono_debugger_unlock ();
421                         return i;
422                 }
423         }
424
425         assembly = mono_assembly_open (name, &status);
426
427         if (status != MONO_IMAGE_OK) {
428                 g_warning (G_STRLOC ": Cannot open image `%s'", name);
429                 mono_debugger_unlock ();
430                 return -1;
431         }
432
433         must_reload_symtabs = TRUE;
434         goto again;
435 }
436