2 * mono-debug-debugger.c:
5 * Mono Project (http://www.mono-project.com)
7 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
8 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
14 #include <mono/metadata/assembly.h>
15 #include <mono/metadata/metadata.h>
16 #include <mono/metadata/tabledefs.h>
17 #include <mono/metadata/tokentype.h>
18 #include <mono/metadata/appdomain.h>
19 #include <mono/metadata/gc-internal.h>
20 #include <mono/metadata/threads.h>
21 #include <mono/metadata/gc-internal.h>
22 #include <mono/metadata/object-internals.h>
23 #include <mono/metadata/class-internals.h>
24 #include <mono/metadata/domain-internals.h>
25 #include <mono/metadata/exception.h>
26 #include <mono/metadata/mono-debug.h>
27 #include <mono/metadata/mono-debug-debugger.h>
28 #include <mono/metadata/mono-endian.h>
30 static guint32 debugger_lock_level = 0;
31 static CRITICAL_SECTION debugger_lock_mutex;
32 static MonoObject *last_exception = NULL;
33 volatile gint32 _mono_debugger_interruption_request = 0;
35 void (*mono_debugger_event_handler) (MonoDebuggerEvent event, guint64 data, guint64 arg) = NULL;
41 MonoDebugMethodAddressList *address_list;
42 } MethodBreakpointInfo;
54 guint32 shadow_path_len;
57 MonoAppDomainSetup *setup;
60 static GPtrArray *class_init_callbacks = NULL;
62 static int initialized = 0;
65 mono_debugger_lock (void)
67 g_assert (initialized);
68 EnterCriticalSection (&debugger_lock_mutex);
69 debugger_lock_level++;
73 mono_debugger_unlock (void)
75 g_assert (initialized);
76 debugger_lock_level--;
77 LeaveCriticalSection (&debugger_lock_mutex);
81 mono_debugger_initialize ()
83 MONO_GC_REGISTER_ROOT_SINGLE (last_exception);
85 InitializeCriticalSection (&debugger_lock_mutex);
90 mono_debugger_event (MonoDebuggerEvent event, guint64 data, guint64 arg)
92 if (mono_debugger_event_handler)
93 (* mono_debugger_event_handler) (event, data, arg);
97 mono_debugger_event_create_appdomain (MonoDomain *domain, gchar *shadow_path)
99 AppDomainSetupInfo info;
101 info.id = mono_domain_get_id (domain);
102 info.shadow_path_len = shadow_path ? strlen (shadow_path) : 0;
103 info.shadow_path = shadow_path;
105 info.domain = domain;
106 info.setup = domain->setup;
108 mono_debugger_event (MONO_DEBUGGER_EVENT_CREATE_APPDOMAIN, (guint64) (gsize) &info, 0);
112 mono_debugger_event_unload_appdomain (MonoDomain *domain)
114 mono_debugger_event (MONO_DEBUGGER_EVENT_UNLOAD_APPDOMAIN,
115 (guint64) (gsize) domain, (guint64) mono_domain_get_id (domain));
119 mono_debugger_cleanup (void)
121 mono_debugger_event (MONO_DEBUGGER_EVENT_FINALIZE_MANAGED_CODE, 0, 0);
122 mono_debugger_event_handler = NULL;
126 mono_debugger_check_interruption (void)
128 if (!_mono_debugger_interruption_request)
131 mono_debugger_lock ();
132 mono_debugger_event (MONO_DEBUGGER_EVENT_INTERRUPTION_REQUEST, 0, 0);
133 mono_debugger_unlock ();
137 * Debugger breakpoint interface.
139 * This interface is used to insert breakpoints on methods which are not yet JITed.
140 * The debugging code keeps a list of all such breakpoints and automatically inserts the
141 * breakpoint when the method is JITed.
144 static GPtrArray *method_breakpoints = NULL;
146 MonoDebugMethodAddressList *
147 mono_debugger_insert_method_breakpoint (MonoMethod *method, guint64 index)
149 MethodBreakpointInfo *info;
151 info = g_new0 (MethodBreakpointInfo, 1);
152 info->method = method;
155 info->address_list = mono_debug_lookup_method_addresses (method);
157 if (!method_breakpoints)
158 method_breakpoints = g_ptr_array_new ();
160 g_ptr_array_add (method_breakpoints, info);
162 return info->address_list;
166 mono_debugger_remove_method_breakpoint (guint64 index)
170 if (!method_breakpoints)
173 for (i = 0; i < method_breakpoints->len; i++) {
174 MethodBreakpointInfo *info = g_ptr_array_index (method_breakpoints, i);
176 if (info->index != index)
179 g_ptr_array_remove (method_breakpoints, info);
180 g_free (info->address_list);
189 mono_debugger_check_breakpoints (MonoMethod *method, MonoDebugMethodAddress *debug_info)
193 if (method->is_inflated)
194 method = ((MonoMethodInflated *) method)->declaring;
196 if (method_breakpoints) {
197 for (i = 0; i < method_breakpoints->len; i++) {
198 MethodBreakpointInfo *info = g_ptr_array_index (method_breakpoints, i);
200 if (method != info->method)
203 mono_debugger_event (MONO_DEBUGGER_EVENT_JIT_BREAKPOINT,
204 (guint64) (gsize) debug_info, info->index);
208 if (class_init_callbacks) {
209 for (i = 0; i < class_init_callbacks->len; i++) {
210 ClassInitCallback *info = g_ptr_array_index (class_init_callbacks, i);
212 if ((method->token != info->token) || (method->klass->image != info->image))
215 mono_debugger_event (MONO_DEBUGGER_EVENT_JIT_BREAKPOINT,
216 (guint64) (gsize) debug_info, info->index);
222 mono_debugger_register_class_init_callback (MonoImage *image, const gchar *full_name,
223 guint32 method_token, guint32 index)
225 ClassInitCallback *info;
227 gchar *name_space, *name, *pos;
229 name = g_strdup (full_name);
231 pos = strrchr (name, '.');
242 klass = mono_class_from_name (image, name_space ? name_space : "", name);
244 info = g_new0 (ClassInitCallback, 1);
247 info->token = method_token;
248 info->name_space = name_space;
251 if (!class_init_callbacks)
252 class_init_callbacks = g_ptr_array_new ();
254 g_ptr_array_add (class_init_callbacks, info);
255 mono_loader_unlock ();
260 mono_debugger_remove_class_init_callback (int index)
264 if (!class_init_callbacks)
267 for (i = 0; i < class_init_callbacks->len; i++) {
268 ClassInitCallback *info = g_ptr_array_index (class_init_callbacks, i);
270 if (info->index != index)
273 g_ptr_array_remove (class_init_callbacks, info);
274 if (info->name_space)
275 g_free (info->name_space);
283 mono_debugger_class_initialized (MonoClass *klass)
287 if (!class_init_callbacks)
291 for (i = 0; i < class_init_callbacks->len; i++) {
292 ClassInitCallback *info = g_ptr_array_index (class_init_callbacks, i);
294 if (info->name_space && strcmp (info->name_space, klass->name_space))
296 if (strcmp (info->name, klass->name))
299 mono_debugger_event (MONO_DEBUGGER_EVENT_CLASS_INITIALIZED,
300 (guint64) (gsize) klass, info->index);
305 for (j = 0; j < klass->method.count; j++) {
306 if (klass->methods [j]->token != info->token)
309 mono_debugger_insert_method_breakpoint (klass->methods [j], info->index);
313 g_ptr_array_remove (class_init_callbacks, info);
314 if (info->name_space)
315 g_free (info->name_space);