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>
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;
24 struct _MonoDebuggerMetadataInfo {
26 int mono_defaults_size;
27 MonoDefaults *mono_defaults;
28 int klass_field_offset;
29 int klass_methods_offset;
30 int klass_method_count_offset;
34 void (*mono_debugger_event_handler) (MonoDebuggerEvent event, guint64 data, guint64 arg) = NULL;
36 #define WRITE_UINT32(ptr,value) G_STMT_START { \
37 * ((guint32 *) ptr) = value; \
41 #define WRITE_POINTER(ptr,value) G_STMT_START { \
42 * ((gpointer *) ptr) = (gpointer) (value); \
43 ptr += sizeof (gpointer); \
46 #define WRITE_STRING(ptr,value) G_STMT_START { \
47 memcpy (ptr, value, strlen (value)+1); \
48 ptr += strlen (value)+1; \
52 gpointer stack_pointer;
53 MonoObject *exception_obj;
55 } MonoDebuggerExceptionInfo;
57 #ifndef PLATFORM_WIN32
59 MonoDebuggerIOLayer mono_debugger_io_layer = {
60 InitializeCriticalSection, DeleteCriticalSection, TryEnterCriticalSection,
61 EnterCriticalSection, LeaveCriticalSection, WaitForSingleObjectEx, SignalObjectAndWait,
62 WaitForMultipleObjectsEx, CreateSemaphore, ReleaseSemaphore, CreateThread,
69 mono_debugger_lock (void)
71 EnterCriticalSection (&debugger_lock_mutex);
72 debugger_lock_level++;
76 mono_debugger_unlock (void)
78 if (debugger_lock_level == 1) {
79 if (must_reload_symtabs && mono_debugger_use_debugger) {
80 mono_debugger_event (MONO_DEBUGGER_EVENT_RELOAD_SYMTABS, 0, 0);
81 must_reload_symtabs = FALSE;
85 debugger_lock_level--;
86 LeaveCriticalSection (&debugger_lock_mutex);
90 mono_debugger_initialize (gboolean use_debugger)
92 MONO_GC_REGISTER_ROOT (last_exception);
94 g_assert (!mono_debugger_use_debugger);
96 InitializeCriticalSection (&debugger_lock_mutex);
97 mono_debugger_use_debugger = use_debugger;
101 mono_debugger_add_symbol_file (MonoDebugHandle *handle)
103 g_assert (mono_debugger_use_debugger);
105 mono_debugger_lock ();
106 mono_debugger_event (MONO_DEBUGGER_EVENT_ADD_MODULE, GPOINTER_TO_UINT (handle), 0);
107 mono_debugger_unlock ();
111 mono_debugger_add_builtin_types (MonoDebugHandle *symfile)
113 MonoDebuggerMetadataInfo *info;
116 mono_symbol_table->corlib = symfile;
117 mono_symbol_table->metadata_info = info = g_new0 (MonoDebuggerMetadataInfo, 1);
119 info->size = sizeof (MonoDebuggerMetadataInfo);
120 info->mono_defaults = &mono_defaults;
121 info->mono_defaults_size = sizeof (MonoDefaults);
122 info->klass_field_offset = (guint8*)&klass.fields - (guint8*)&klass;
123 info->klass_methods_offset = (guint8*)&klass.methods - (guint8*)&klass;
124 info->klass_method_count_offset = (guint8*)&klass.method.count - (guint8*)&klass;
125 info->field_info_size = sizeof (MonoClassField);
129 mono_debugger_start_add_type (MonoDebugHandle *symfile, MonoClass *klass)
131 must_reload_symtabs = TRUE;
135 mono_debugger_add_type (MonoDebugHandle *symfile, MonoClass *klass)
140 mono_debugger_add_method (MonoDebugMethodJitInfo *jit)
144 MonoReflectionMethod *
145 ves_icall_MonoDebugger_GetMethod (MonoReflectionAssembly *assembly, guint32 token)
149 method = mono_get_method (mono_assembly_get_image (assembly->assembly), token, NULL);
151 return mono_method_get_object (mono_domain_get (), method, NULL);
155 ves_icall_MonoDebugger_GetMethodToken (MonoReflectionAssembly *assembly, MonoReflectionMethod *method)
157 return method->method->token;
161 ves_icall_MonoDebugger_GetType (MonoReflectionAssembly *assembly, guint32 token)
165 klass = mono_class_get (mono_assembly_get_image (assembly->assembly), token);
167 g_warning (G_STRLOC ": %x", token);
171 return mono_type_get_object (mono_domain_get (), &klass->byval_arg);
175 ves_icall_MonoDebugger_GetLocalTypeFromSignature (MonoReflectionAssembly *assembly, MonoArray *signature)
183 MONO_CHECK_ARG_NULL (assembly);
184 MONO_CHECK_ARG_NULL (signature);
186 domain = mono_domain_get();
187 image = mono_assembly_get_image (assembly->assembly);
189 ptr = mono_array_addr (signature, char, 0);
190 g_assert (*ptr++ == 0x07);
191 len = mono_metadata_decode_value (ptr, &ptr);
194 type = mono_metadata_parse_type (image, MONO_PARSE_LOCAL, 0, ptr, &ptr);
196 return mono_type_get_object (domain, type);
200 mono_debugger_event (MonoDebuggerEvent event, guint64 data, guint64 arg)
202 if (mono_debugger_event_handler)
203 (* mono_debugger_event_handler) (event, data, arg);
207 mono_debugger_cleanup (void)
209 /* Do nothing yet. */
213 * Debugger breakpoint interface.
215 * This interface is used to insert breakpoints on methods which are not yet JITed.
216 * The debugging code keeps a list of all such breakpoints and automatically inserts the
217 * breakpoint when the method is JITed.
220 static GPtrArray *breakpoints = NULL;
223 mono_debugger_insert_breakpoint_full (MonoMethodDesc *desc)
225 static int last_breakpoint_id = 0;
226 MonoDebuggerBreakpointInfo *info;
228 info = g_new0 (MonoDebuggerBreakpointInfo, 1);
230 info->index = ++last_breakpoint_id;
233 breakpoints = g_ptr_array_new ();
235 g_ptr_array_add (breakpoints, info);
241 mono_debugger_remove_breakpoint (int breakpoint_id)
248 for (i = 0; i < breakpoints->len; i++) {
249 MonoDebuggerBreakpointInfo *info = g_ptr_array_index (breakpoints, i);
251 if (info->index != breakpoint_id)
254 mono_method_desc_free (info->desc);
255 g_ptr_array_remove (breakpoints, info);
264 mono_debugger_insert_breakpoint (const gchar *method_name, gboolean include_namespace)
266 MonoMethodDesc *desc;
268 desc = mono_method_desc_new (method_name, include_namespace);
272 return mono_debugger_insert_breakpoint_full (desc);
276 mono_debugger_method_has_breakpoint (MonoMethod *method)
280 if (!breakpoints || (method->wrapper_type != MONO_WRAPPER_NONE))
283 for (i = 0; i < breakpoints->len; i++) {
284 MonoDebuggerBreakpointInfo *info = g_ptr_array_index (breakpoints, i);
286 if (!mono_method_desc_full_match (info->desc, method))
296 mono_debugger_breakpoint_callback (MonoMethod *method, guint32 index)
298 mono_debugger_event (MONO_DEBUGGER_EVENT_BREAKPOINT, GPOINTER_TO_UINT (method), index);
302 mono_debugger_unhandled_exception (gpointer addr, gpointer stack, MonoObject *exc)
304 if (!mono_debugger_use_debugger)
307 // Prevent the object from being finalized.
308 last_exception = exc;
309 mono_debugger_event (MONO_DEBUGGER_EVENT_UNHANDLED_EXCEPTION,
310 GPOINTER_TO_UINT (exc), GPOINTER_TO_UINT (addr));
315 mono_debugger_handle_exception (gpointer addr, gpointer stack, MonoObject *exc)
317 MonoDebuggerExceptionInfo info;
319 if (!mono_debugger_use_debugger)
322 // Prevent the object from being finalized.
323 last_exception = exc;
325 info.stack_pointer = stack;
326 info.exception_obj = exc;
329 mono_debugger_event (MONO_DEBUGGER_EVENT_EXCEPTION, GPOINTER_TO_UINT (&info),
330 GPOINTER_TO_UINT (addr));
334 mono_debugger_throw_exception (gpointer addr, gpointer stack, MonoObject *exc)
336 MonoDebuggerExceptionInfo info;
338 if (!mono_debugger_use_debugger)
341 // Prevent the object from being finalized.
342 last_exception = exc;
344 info.stack_pointer = stack;
345 info.exception_obj = exc;
348 mono_debugger_event (MONO_DEBUGGER_EVENT_THROW_EXCEPTION, GPOINTER_TO_UINT (&info),
349 GPOINTER_TO_UINT (addr));
350 return info.stop != 0;
354 get_exception_message (MonoObject *exc)
356 char *message = NULL;
362 if (mono_object_isinst (exc, mono_defaults.exception_class)) {
363 klass = exc->vtable->klass;
365 while (klass && method == NULL) {
366 for (i = 0; i < klass->method.count; ++i) {
367 method = klass->methods [i];
368 if (!strcmp ("ToString", method->name) &&
369 mono_method_signature (method)->param_count == 0 &&
370 method->flags & METHOD_ATTRIBUTE_VIRTUAL &&
371 method->flags & METHOD_ATTRIBUTE_PUBLIC) {
378 klass = klass->parent;
383 str = (MonoString *) mono_runtime_invoke (method, exc, NULL, NULL);
385 message = mono_string_to_utf8 (str);
392 mono_debugger_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObject **exc)
397 if (!strcmp (method->name, ".ctor")) {
398 retval = obj = mono_object_new (mono_domain_get (), method->klass);
400 mono_runtime_invoke (method, obj, params, exc);
402 retval = mono_runtime_invoke (method, obj, params, exc);
404 if (!exc || (*exc == NULL))
407 message = get_exception_message (*exc);
409 *exc = (MonoObject *) mono_string_new_wrapper (message);
417 mono_debugger_lookup_type (const gchar *type_name)
420 mono_debugger_lock ();
422 for (i = 0; i < mono_symbol_table->num_symbol_files; i++) {
423 MonoDebugHandle *symfile = mono_symbol_table->symbol_files [i];
428 name = g_strdup (type_name);
429 type = mono_reflection_type_from_name (name, symfile->image);
434 klass = mono_class_from_mono_type (type);
436 mono_class_init (klass);
438 mono_debugger_unlock ();
442 mono_debugger_unlock ();
447 mono_debugger_lookup_assembly (const gchar *name)
449 MonoAssembly *assembly;
450 MonoImageOpenStatus status;
453 mono_debugger_lock ();
456 for (i = 0; i < mono_symbol_table->num_symbol_files; i++) {
457 MonoDebugHandle *symfile = mono_symbol_table->symbol_files [i];
459 if (!strcmp (symfile->image_file, name)) {
460 mono_debugger_unlock ();
465 assembly = mono_assembly_open (name, &status);
467 if (status != MONO_IMAGE_OK) {
468 g_warning (G_STRLOC ": Cannot open image `%s'", name);
469 mono_debugger_unlock ();
473 must_reload_symtabs = TRUE;