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;
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;
44 void (*mono_debugger_event_handler) (MonoDebuggerEvent event, guint64 data, guint64 arg) = NULL;
46 #define WRITE_UINT32(ptr,value) G_STMT_START { \
47 * ((guint32 *) ptr) = value; \
51 #define WRITE_POINTER(ptr,value) G_STMT_START { \
52 * ((gpointer *) ptr) = (gpointer) (value); \
53 ptr += sizeof (gpointer); \
56 #define WRITE_STRING(ptr,value) G_STMT_START { \
57 memcpy (ptr, value, strlen (value)+1); \
58 ptr += strlen (value)+1; \
62 gpointer stack_pointer;
63 MonoObject *exception_obj;
65 } MonoDebuggerExceptionInfo;
67 #ifndef PLATFORM_WIN32
69 MonoDebuggerIOLayer mono_debugger_io_layer = {
70 InitializeCriticalSection, DeleteCriticalSection, TryEnterCriticalSection,
71 EnterCriticalSection, LeaveCriticalSection, WaitForSingleObjectEx, SignalObjectAndWait,
72 WaitForMultipleObjectsEx, CreateSemaphore, ReleaseSemaphore, CreateThread,
78 static int initialized = 0;
81 mono_debugger_lock (void)
83 g_assert (initialized);
84 EnterCriticalSection (&debugger_lock_mutex);
85 debugger_lock_level++;
89 mono_debugger_unlock (void)
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;
99 debugger_lock_level--;
100 LeaveCriticalSection (&debugger_lock_mutex);
104 mono_debugger_initialize (gboolean use_debugger)
106 MONO_GC_REGISTER_ROOT (last_exception);
108 g_assert (!mono_debugger_use_debugger);
110 InitializeCriticalSection (&debugger_lock_mutex);
111 mono_debugger_use_debugger = use_debugger;
116 mono_debugger_add_symbol_file (MonoDebugHandle *handle)
118 g_assert (mono_debugger_use_debugger);
120 mono_debugger_lock ();
121 mono_debugger_event (MONO_DEBUGGER_EVENT_ADD_MODULE, GPOINTER_TO_UINT (handle), 0);
122 mono_debugger_unlock ();
126 mono_debugger_add_builtin_types (MonoDebugHandle *symfile)
128 MonoDebuggerMetadataInfo *info;
131 mono_symbol_table->corlib = symfile;
132 mono_symbol_table->metadata_info = info = g_new0 (MonoDebuggerMetadataInfo, 1);
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);
154 mono_debugger_start_add_type (MonoDebugHandle *symfile, MonoClass *klass)
156 must_reload_symtabs = TRUE;
160 mono_debugger_event (MonoDebuggerEvent event, guint64 data, guint64 arg)
162 if (mono_debugger_event_handler)
163 (* mono_debugger_event_handler) (event, data, arg);
167 mono_debugger_cleanup (void)
169 /* Do nothing yet. */
173 * Debugger breakpoint interface.
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.
180 static GPtrArray *breakpoints = NULL;
183 mono_debugger_insert_breakpoint_full (MonoMethodDesc *desc)
185 static int last_breakpoint_id = 0;
186 MonoDebuggerBreakpointInfo *info;
188 info = g_new0 (MonoDebuggerBreakpointInfo, 1);
190 info->index = ++last_breakpoint_id;
193 breakpoints = g_ptr_array_new ();
195 g_ptr_array_add (breakpoints, info);
201 mono_debugger_remove_breakpoint (int breakpoint_id)
208 for (i = 0; i < breakpoints->len; i++) {
209 MonoDebuggerBreakpointInfo *info = g_ptr_array_index (breakpoints, i);
211 if (info->index != breakpoint_id)
214 mono_method_desc_free (info->desc);
215 g_ptr_array_remove (breakpoints, info);
224 mono_debugger_insert_breakpoint (const gchar *method_name, gboolean include_namespace)
226 MonoMethodDesc *desc;
228 desc = mono_method_desc_new (method_name, include_namespace);
232 return mono_debugger_insert_breakpoint_full (desc);
236 mono_debugger_method_has_breakpoint (MonoMethod *method)
240 if (!breakpoints || (method->wrapper_type != MONO_WRAPPER_NONE))
243 for (i = 0; i < breakpoints->len; i++) {
244 MonoDebuggerBreakpointInfo *info = g_ptr_array_index (breakpoints, i);
246 if (!mono_method_desc_full_match (info->desc, method))
256 mono_debugger_breakpoint_callback (MonoMethod *method, guint32 index)
258 mono_debugger_event (MONO_DEBUGGER_EVENT_BREAKPOINT, GPOINTER_TO_UINT (method), index);
262 mono_debugger_unhandled_exception (gpointer addr, gpointer stack, MonoObject *exc)
264 if (!mono_debugger_use_debugger)
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));
275 mono_debugger_handle_exception (gpointer addr, gpointer stack, MonoObject *exc)
277 MonoDebuggerExceptionInfo info;
279 if (!mono_debugger_use_debugger)
282 // Prevent the object from being finalized.
283 last_exception = exc;
285 info.stack_pointer = stack;
286 info.exception_obj = exc;
289 mono_debugger_event (MONO_DEBUGGER_EVENT_EXCEPTION, GPOINTER_TO_UINT (&info),
290 GPOINTER_TO_UINT (addr));
294 mono_debugger_throw_exception (gpointer addr, gpointer stack, MonoObject *exc)
296 MonoDebuggerExceptionInfo info;
298 if (!mono_debugger_use_debugger)
301 // Prevent the object from being finalized.
302 last_exception = exc;
304 info.stack_pointer = stack;
305 info.exception_obj = exc;
308 mono_debugger_event (MONO_DEBUGGER_EVENT_THROW_EXCEPTION, GPOINTER_TO_UINT (&info),
309 GPOINTER_TO_UINT (addr));
310 return info.stop != 0;
314 get_exception_message (MonoObject *exc)
316 char *message = NULL;
322 if (mono_object_isinst (exc, mono_defaults.exception_class)) {
323 klass = exc->vtable->klass;
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) {
338 klass = klass->parent;
343 str = (MonoString *) mono_runtime_invoke (method, exc, NULL, NULL);
345 message = mono_string_to_utf8 (str);
352 mono_debugger_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObject **exc)
357 if (!strcmp (method->name, ".ctor")) {
358 retval = obj = mono_object_new (mono_domain_get (), method->klass);
360 mono_runtime_invoke (method, obj, params, exc);
362 retval = mono_runtime_invoke (method, obj, params, exc);
364 if (!exc || (*exc == NULL))
367 message = get_exception_message (*exc);
369 *exc = (MonoObject *) mono_string_new_wrapper (message);
377 mono_debugger_lookup_type (const gchar *type_name)
380 mono_debugger_lock ();
382 for (i = 0; i < mono_symbol_table->num_symbol_files; i++) {
383 MonoDebugHandle *symfile = mono_symbol_table->symbol_files [i];
388 name = g_strdup (type_name);
389 type = mono_reflection_type_from_name (name, symfile->image);
394 klass = mono_class_from_mono_type (type);
396 mono_class_init (klass);
398 mono_debugger_unlock ();
402 mono_debugger_unlock ();
407 mono_debugger_lookup_assembly (const gchar *name)
409 MonoAssembly *assembly;
410 MonoImageOpenStatus status;
413 mono_debugger_lock ();
416 for (i = 0; i < mono_symbol_table->num_symbol_files; i++) {
417 MonoDebugHandle *symfile = mono_symbol_table->symbol_files [i];
419 if (!strcmp (symfile->image_file, name)) {
420 mono_debugger_unlock ();
425 assembly = mono_assembly_open (name, &status);
427 if (status != MONO_IMAGE_OK) {
428 g_warning (G_STRLOC ": Cannot open image `%s'", name);
429 mono_debugger_unlock ();
433 must_reload_symtabs = TRUE;