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
);