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 gboolean mono_debugger_use_debugger = FALSE;
33 static MonoObject *last_exception = NULL;
34 volatile gint32 _mono_debugger_interruption_request = 0;
36 void (*mono_debugger_event_handler) (MonoDebuggerEvent event, guint64 data, guint64 arg) = NULL;
42 MonoDebugMethodAddressList *address_list;
43 } MethodBreakpointInfo;
55 guint32 shadow_path_len;
58 MonoAppDomainSetup *setup;
61 static GPtrArray *class_init_callbacks = NULL;
63 static int initialized = 0;
66 mono_debugger_lock (void)
68 g_assert (initialized);
69 EnterCriticalSection (&debugger_lock_mutex);
70 debugger_lock_level++;
74 mono_debugger_unlock (void)
76 g_assert (initialized);
77 debugger_lock_level--;
78 LeaveCriticalSection (&debugger_lock_mutex);
82 mono_debugger_initialize (gboolean use_debugger)
84 MONO_GC_REGISTER_ROOT (last_exception);
86 g_assert (!mono_debugger_use_debugger);
88 InitializeCriticalSection (&debugger_lock_mutex);
89 mono_debugger_use_debugger = use_debugger;
94 mono_debugger_event (MonoDebuggerEvent event, guint64 data, guint64 arg)
96 if (mono_debugger_event_handler)
97 (* mono_debugger_event_handler) (event, data, arg);
101 mono_debugger_event_create_appdomain (MonoDomain *domain, gchar *shadow_path)
103 AppDomainSetupInfo info;
105 info.id = mono_domain_get_id (domain);
106 info.shadow_path_len = shadow_path ? strlen (shadow_path) : 0;
107 info.shadow_path = shadow_path;
109 info.domain = domain;
110 info.setup = domain->setup;
112 mono_debugger_event (MONO_DEBUGGER_EVENT_CREATE_APPDOMAIN, (guint64) (gsize) &info, 0);
116 mono_debugger_event_unload_appdomain (MonoDomain *domain)
118 mono_debugger_event (MONO_DEBUGGER_EVENT_UNLOAD_APPDOMAIN,
119 (guint64) (gsize) domain, (guint64) mono_domain_get_id (domain));
123 mono_debugger_cleanup (void)
125 mono_debugger_event (MONO_DEBUGGER_EVENT_FINALIZE_MANAGED_CODE, 0, 0);
126 mono_debugger_event_handler = NULL;
130 mono_debugger_check_interruption (void)
132 if (!_mono_debugger_interruption_request)
135 mono_debugger_lock ();
136 mono_debugger_event (MONO_DEBUGGER_EVENT_INTERRUPTION_REQUEST, 0, 0);
137 mono_debugger_unlock ();
141 * Debugger breakpoint interface.
143 * This interface is used to insert breakpoints on methods which are not yet JITed.
144 * The debugging code keeps a list of all such breakpoints and automatically inserts the
145 * breakpoint when the method is JITed.
148 static GPtrArray *method_breakpoints = NULL;
150 MonoDebugMethodAddressList *
151 mono_debugger_insert_method_breakpoint (MonoMethod *method, guint64 index)
153 MethodBreakpointInfo *info;
155 info = g_new0 (MethodBreakpointInfo, 1);
156 info->method = method;
159 info->address_list = mono_debug_lookup_method_addresses (method);
161 if (!method_breakpoints)
162 method_breakpoints = g_ptr_array_new ();
164 g_ptr_array_add (method_breakpoints, info);
166 return info->address_list;
170 mono_debugger_remove_method_breakpoint (guint64 index)
174 if (!method_breakpoints)
177 for (i = 0; i < method_breakpoints->len; i++) {
178 MethodBreakpointInfo *info = g_ptr_array_index (method_breakpoints, i);
180 if (info->index != index)
183 g_ptr_array_remove (method_breakpoints, info);
184 g_free (info->address_list);
193 mono_debugger_check_breakpoints (MonoMethod *method, MonoDebugMethodAddress *debug_info)
197 if (method->is_inflated)
198 method = ((MonoMethodInflated *) method)->declaring;
200 if (method_breakpoints) {
201 for (i = 0; i < method_breakpoints->len; i++) {
202 MethodBreakpointInfo *info = g_ptr_array_index (method_breakpoints, i);
204 if (method != info->method)
207 mono_debugger_event (MONO_DEBUGGER_EVENT_JIT_BREAKPOINT,
208 (guint64) (gsize) debug_info, info->index);
212 if (class_init_callbacks) {
213 for (i = 0; i < class_init_callbacks->len; i++) {
214 ClassInitCallback *info = g_ptr_array_index (class_init_callbacks, i);
216 if ((method->token != info->token) || (method->klass->image != info->image))
219 mono_debugger_event (MONO_DEBUGGER_EVENT_JIT_BREAKPOINT,
220 (guint64) (gsize) debug_info, info->index);
226 mono_debugger_register_class_init_callback (MonoImage *image, const gchar *full_name,
227 guint32 method_token, guint32 index)
229 ClassInitCallback *info;
231 gchar *name_space, *name, *pos;
233 name = g_strdup (full_name);
235 pos = strrchr (name, '.');
246 klass = mono_class_from_name (image, name_space ? name_space : "", name);
248 info = g_new0 (ClassInitCallback, 1);
251 info->token = method_token;
252 info->name_space = name_space;
255 if (!class_init_callbacks)
256 class_init_callbacks = g_ptr_array_new ();
258 g_ptr_array_add (class_init_callbacks, info);
259 mono_loader_unlock ();
264 mono_debugger_remove_class_init_callback (int index)
268 if (!class_init_callbacks)
271 for (i = 0; i < class_init_callbacks->len; i++) {
272 ClassInitCallback *info = g_ptr_array_index (class_init_callbacks, i);
274 if (info->index != index)
277 g_ptr_array_remove (class_init_callbacks, info);
278 if (info->name_space)
279 g_free (info->name_space);
287 mono_debugger_class_initialized (MonoClass *klass)
291 if (!class_init_callbacks)
295 for (i = 0; i < class_init_callbacks->len; i++) {
296 ClassInitCallback *info = g_ptr_array_index (class_init_callbacks, i);
298 if (info->name_space && strcmp (info->name_space, klass->name_space))
300 if (strcmp (info->name, klass->name))
303 mono_debugger_event (MONO_DEBUGGER_EVENT_CLASS_INITIALIZED,
304 (guint64) (gsize) klass, info->index);
309 for (j = 0; j < klass->method.count; j++) {
310 if (klass->methods [j]->token != info->token)
313 mono_debugger_insert_method_breakpoint (klass->methods [j], info->index);
317 g_ptr_array_remove (class_init_callbacks, info);
318 if (info->name_space)
319 g_free (info->name_space);