2 #include <mono/io-layer/io-layer.h>
3 #include <mono/metadata/threads.h>
4 #include <mono/metadata/assembly.h>
5 #include <mono/metadata/mono-debug.h>
6 #include <mono/metadata/mono-config.h>
7 #define _IN_THE_MONO_DEBUGGER
8 #include "debug-debugger.h"
9 #include "debug-mini.h"
10 #include <libgc/include/libgc-mono-debugger.h>
17 * This file is only compiled on platforms where the debugger is supported - see the conditional
18 * definition of `debugger_sources' in Makefile.am.
20 * configure.in checks whether we're using the included libgc and disables the debugger if not.
23 #if !defined(MONO_DEBUGGER_SUPPORTED)
24 #error "Some clown tried to compile debug-debugger.c on an unsupported platform - fix Makefile.am!"
25 #elif !defined(USE_INCLUDED_LIBGC)
26 #error "Some clown #defined MONO_DEBUGGER_SUPPORTED without USE_INCLUDED_GC - fix configure.in!"
29 static guint64
debugger_compile_method (guint64 method_arg
);
30 static guint64
debugger_get_virtual_method (guint64 class_arg
, guint64 method_arg
);
31 static guint64
debugger_get_boxed_object (guint64 klass_arg
, guint64 val_arg
);
32 static guint64
debugger_class_get_static_field_data (guint64 klass
);
34 static guint64
debugger_run_finally (guint64 argument1
, guint64 argument2
);
35 static void debugger_initialize (void);
36 static guint64
debugger_init_code_buffer (void);
38 static void debugger_event_handler (MonoDebuggerEvent event
, guint64 data
, guint64 arg
);
40 static guint64
debugger_create_string (G_GNUC_UNUSED guint64 dummy
, G_GNUC_UNUSED guint64 dummy2
,
41 G_GNUC_UNUSED guint64 dummy3
, const gchar
*string_argument
);
42 static gint64
debugger_lookup_class (guint64 image_argument
, G_GNUC_UNUSED guint64 dummy
,
43 G_GNUC_UNUSED guint64 dummy2
, gchar
*full_name
);
44 static guint64
debugger_insert_method_breakpoint (guint64 method_argument
, guint64 index
);
45 static guint64
debugger_insert_source_breakpoint (guint64 image_argument
, guint64 token
,
46 guint64 index
, const gchar
*class_name
);
47 static void debugger_remove_breakpoint (guint64 index
, G_GNUC_UNUSED guint64 dummy
);
48 static guint64
debugger_register_class_init_callback (guint64 image_argument
, guint64 token
,
49 guint64 index
, const gchar
*class_name
);
50 static void debugger_remove_class_init_callback (guint64 index
, G_GNUC_UNUSED guint64 dummy
);
51 static guint64
debugger_get_method_signature (guint64 argument1
, G_GNUC_UNUSED guint64 argument2
);
53 #define EXECUTABLE_CODE_BUFFER_SIZE 4096
54 static guint8
*debugger_executable_code_buffer
= NULL
;
56 static GCThreadFunctions debugger_thread_vtable
;
58 static MonoDebuggerMetadataInfo debugger_metadata_info
= {
59 sizeof (MonoDebuggerMetadataInfo
),
60 sizeof (MonoDefaults
),
63 sizeof (MonoArrayType
),
66 G_STRUCT_OFFSET (MonoThread
, tid
),
67 G_STRUCT_OFFSET (MonoThread
, stack_ptr
),
68 G_STRUCT_OFFSET (MonoThread
, end_stack
),
69 G_STRUCT_OFFSET (MonoClass
, image
),
70 G_STRUCT_OFFSET (MonoClass
, instance_size
),
71 G_STRUCT_OFFSET (MonoClass
, parent
),
72 G_STRUCT_OFFSET (MonoClass
, type_token
),
73 G_STRUCT_OFFSET (MonoClass
, fields
),
74 G_STRUCT_OFFSET (MonoClass
, methods
),
75 G_STRUCT_OFFSET (MonoClass
, method
.count
),
76 G_STRUCT_OFFSET (MonoClass
, this_arg
),
77 G_STRUCT_OFFSET (MonoClass
, byval_arg
),
78 G_STRUCT_OFFSET (MonoClass
, generic_class
),
79 G_STRUCT_OFFSET (MonoClass
, generic_container
),
80 G_STRUCT_OFFSET (MonoClass
, vtable
),
81 sizeof (MonoClassField
),
82 G_STRUCT_OFFSET (MonoClassField
, type
),
83 G_STRUCT_OFFSET (MonoClassField
, offset
),
84 G_STRUCT_OFFSET (MonoDefaults
, corlib
),
85 G_STRUCT_OFFSET (MonoDefaults
, object_class
),
86 G_STRUCT_OFFSET (MonoDefaults
, byte_class
),
87 G_STRUCT_OFFSET (MonoDefaults
, void_class
),
88 G_STRUCT_OFFSET (MonoDefaults
, boolean_class
),
89 G_STRUCT_OFFSET (MonoDefaults
, sbyte_class
),
90 G_STRUCT_OFFSET (MonoDefaults
, int16_class
),
91 G_STRUCT_OFFSET (MonoDefaults
, uint16_class
),
92 G_STRUCT_OFFSET (MonoDefaults
, int32_class
),
93 G_STRUCT_OFFSET (MonoDefaults
, uint32_class
),
94 G_STRUCT_OFFSET (MonoDefaults
, int_class
),
95 G_STRUCT_OFFSET (MonoDefaults
, uint_class
),
96 G_STRUCT_OFFSET (MonoDefaults
, int64_class
),
97 G_STRUCT_OFFSET (MonoDefaults
, uint64_class
),
98 G_STRUCT_OFFSET (MonoDefaults
, single_class
),
99 G_STRUCT_OFFSET (MonoDefaults
, double_class
),
100 G_STRUCT_OFFSET (MonoDefaults
, char_class
),
101 G_STRUCT_OFFSET (MonoDefaults
, string_class
),
102 G_STRUCT_OFFSET (MonoDefaults
, enum_class
),
103 G_STRUCT_OFFSET (MonoDefaults
, array_class
),
104 G_STRUCT_OFFSET (MonoDefaults
, delegate_class
),
105 G_STRUCT_OFFSET (MonoDefaults
, exception_class
),
106 G_STRUCT_OFFSET (MonoMethod
, klass
),
107 G_STRUCT_OFFSET (MonoMethod
, token
),
108 G_STRUCT_OFFSET (MonoMethod
, name
) + sizeof (void *),
109 G_STRUCT_OFFSET (MonoMethodInflated
, declaring
),
110 G_STRUCT_OFFSET (MonoVTable
, klass
),
111 G_STRUCT_OFFSET (MonoVTable
, vtable
)
114 extern void MONO_DEBUGGER__notification_function (guint64 command
, guint64 data
, guint64 data2
);
117 * This is a global data symbol which is read by the debugger.
119 MonoDebuggerInfo MONO_DEBUGGER__debugger_info
= {
121 MONO_DEBUGGER_MAJOR_VERSION
,
122 MONO_DEBUGGER_MINOR_VERSION
,
124 sizeof (MonoDebuggerInfo
),
125 sizeof (MonoSymbolTable
),
127 mono_trampoline_code
,
128 &MONO_DEBUGGER__notification_function
,
130 &debugger_metadata_info
,
131 &mono_debug_debugger_version
,
133 &debugger_compile_method
,
134 &debugger_get_virtual_method
,
135 &debugger_get_boxed_object
,
136 &mono_debugger_runtime_invoke
,
137 &debugger_class_get_static_field_data
,
138 &debugger_run_finally
,
139 &debugger_initialize
,
141 &debugger_create_string
,
142 &debugger_lookup_class
,
144 &debugger_insert_method_breakpoint
,
145 &debugger_insert_source_breakpoint
,
146 &debugger_remove_breakpoint
,
148 &debugger_register_class_init_callback
,
149 &debugger_remove_class_init_callback
,
151 &mono_debugger_thread_table
,
153 &debugger_executable_code_buffer
,
154 mono_breakpoint_info
,
155 mono_breakpoint_info_index
,
157 EXECUTABLE_CODE_BUFFER_SIZE
,
158 MONO_BREAKPOINT_ARRAY_SIZE
,
160 debugger_get_method_signature
,
161 debugger_init_code_buffer
,
164 &debugger_thread_vtable
,
166 &mono_debugger_event_handler
,
167 debugger_event_handler
,
169 &_mono_debug_using_mono_debugger
,
170 (gint32
*)&_mono_debugger_interruption_request
174 debugger_compile_method (guint64 method_arg
)
176 MonoMethod
*method
= (MonoMethod
*) GUINT_TO_POINTER ((gsize
) method_arg
);
179 mono_debugger_lock ();
180 addr
= mono_compile_method (method
);
181 mono_debugger_unlock ();
183 return (guint64
) (gsize
) addr
;
187 debugger_get_virtual_method (guint64 object_arg
, guint64 method_arg
)
189 MonoObject
*object
= (MonoObject
*) GUINT_TO_POINTER ((gsize
) object_arg
);
190 MonoMethod
*method
= (MonoMethod
*) GUINT_TO_POINTER ((gsize
) method_arg
);
192 if (mono_class_is_valuetype (mono_method_get_class (method
)))
195 return (guint64
) (gsize
) mono_object_get_virtual_method (object
, method
);
199 debugger_get_boxed_object (guint64 klass_arg
, guint64 val_arg
)
201 static MonoObject
*last_boxed_object
= NULL
;
202 MonoClass
*klass
= (MonoClass
*) GUINT_TO_POINTER ((gsize
) klass_arg
);
203 gpointer val
= (gpointer
) GUINT_TO_POINTER ((gsize
) val_arg
);
206 if (!mono_class_is_valuetype (klass
))
209 boxed
= mono_value_box (mono_domain_get (), klass
, val
);
210 last_boxed_object
= boxed
; // Protect the object from being garbage collected
212 return (guint64
) (gsize
) boxed
;
216 debugger_create_string (G_GNUC_UNUSED guint64 dummy
, G_GNUC_UNUSED guint64 dummy2
,
217 G_GNUC_UNUSED guint64 dummy3
, const gchar
*string_argument
)
219 return (guint64
) (gsize
) mono_string_new_wrapper (string_argument
);
223 debugger_lookup_class (guint64 image_argument
, G_GNUC_UNUSED guint64 dummy
,
224 G_GNUC_UNUSED guint64 dummy2
, gchar
*full_name
)
226 MonoImage
*image
= (MonoImage
*) GUINT_TO_POINTER ((gsize
) image_argument
);
227 gchar
*name_space
, *name
, *pos
;
230 pos
= strrchr (full_name
, '.');
232 name_space
= full_name
;
240 klass
= mono_class_from_name (image
, name_space
? name_space
: "", name
);
244 mono_class_init (klass
);
245 mono_class_setup_methods (klass
);
246 return (gint64
) (gssize
) klass
;
250 debugger_run_finally (guint64 context_argument
, G_GNUC_UNUSED guint64 dummy
)
252 mono_debugger_run_finally (GUINT_TO_POINTER ((gsize
)context_argument
));
257 debugger_class_get_static_field_data (guint64 value
)
259 MonoClass
*klass
= GUINT_TO_POINTER ((gsize
) value
);
260 MonoVTable
*vtable
= mono_class_vtable (mono_domain_get (), klass
);
261 return (guint64
) (gsize
) mono_vtable_get_static_field_data (vtable
);
265 debugger_insert_method_breakpoint (guint64 method_argument
, guint64 index
)
267 MonoMethod
*method
= GUINT_TO_POINTER ((gsize
) method_argument
);
268 MonoDebugMethodAddressList
*info
;
270 mono_debugger_lock ();
272 if (method
->iflags
& METHOD_IMPL_ATTRIBUTE_RUNTIME
) {
273 const char *name
= method
->name
;
274 MonoMethod
*nm
= NULL
;
276 if (method
->klass
->parent
== mono_defaults
.multicastdelegate_class
) {
277 if (*name
== 'I' && (strcmp (name
, "Invoke") == 0))
278 nm
= mono_marshal_get_delegate_invoke (method
, NULL
);
279 else if (*name
== 'B' && (strcmp (name
, "BeginInvoke") == 0))
280 nm
= mono_marshal_get_delegate_begin_invoke (method
);
281 else if (*name
== 'E' && (strcmp (name
, "EndInvoke") == 0))
282 nm
= mono_marshal_get_delegate_end_invoke (method
);
286 mono_debugger_unlock ();
293 info
= mono_debugger_insert_method_breakpoint (method
, index
);
295 mono_debugger_unlock ();
296 return (guint64
) (gsize
) info
;
300 debugger_insert_source_breakpoint (guint64 image_argument
, guint64 token
, guint64 index
,
301 const gchar
*class_name
)
303 MonoImage
*image
= GUINT_TO_POINTER ((gsize
) image_argument
);
304 MonoDebugMethodAddressList
*info
;
308 mono_debugger_lock ();
310 klass
= mono_debugger_register_class_init_callback (image
, class_name
, token
, index
);
312 mono_debugger_unlock ();
316 for (i
= 0; i
< klass
->method
.count
; i
++) {
317 MonoMethod
*method
= klass
->methods
[i
];
319 if (method
->token
!= token
)
322 if (method
->iflags
& METHOD_IMPL_ATTRIBUTE_RUNTIME
) {
323 const char *name
= method
->name
;
324 MonoMethod
*nm
= NULL
;
326 if (method
->klass
->parent
== mono_defaults
.multicastdelegate_class
) {
327 if (*name
== 'I' && (strcmp (name
, "Invoke") == 0))
328 nm
= mono_marshal_get_delegate_invoke (method
, NULL
);
329 else if (*name
== 'B' && (strcmp (name
, "BeginInvoke") == 0))
330 nm
= mono_marshal_get_delegate_begin_invoke (method
);
331 else if (*name
== 'E' && (strcmp (name
, "EndInvoke") == 0))
332 nm
= mono_marshal_get_delegate_end_invoke (method
);
336 mono_debugger_unlock ();
343 info
= mono_debugger_insert_method_breakpoint (method
, index
);
344 mono_debugger_unlock ();
345 return (guint64
) (gsize
) info
;
348 mono_debugger_unlock ();
353 debugger_remove_breakpoint (guint64 index
, G_GNUC_UNUSED guint64 dummy
)
355 mono_debugger_lock ();
356 mono_debugger_remove_method_breakpoint (index
);
357 mono_debugger_unlock ();
361 debugger_register_class_init_callback (guint64 image_argument
, guint64 token
, guint64 index
,
362 const gchar
*class_name
)
364 MonoImage
*image
= GUINT_TO_POINTER ((gsize
) image_argument
);
367 mono_debugger_lock ();
368 klass
= mono_debugger_register_class_init_callback (image
, class_name
, token
, index
);
369 mono_debugger_unlock ();
370 return (guint64
) (gsize
) klass
;
374 debugger_remove_class_init_callback (guint64 index
, G_GNUC_UNUSED guint64 dummy
)
376 mono_debugger_lock ();
377 mono_debugger_remove_class_init_callback (index
);
378 mono_debugger_unlock ();
382 debugger_get_method_signature (guint64 method_arg
, G_GNUC_UNUSED guint64 dummy
)
384 MonoMethod
*method
= (MonoMethod
*) GUINT_TO_POINTER ((gsize
) method_arg
);
385 MonoMethodSignature
*sig
;
387 sig
= mono_method_signature (method
);
388 return (guint64
) (gsize
) sig
;
392 debugger_event_handler (MonoDebuggerEvent event
, guint64 data
, guint64 arg
)
394 MONO_DEBUGGER__notification_function (event
, data
, arg
);
398 debugger_gc_thread_created (pthread_t thread
, void *stack_ptr
)
400 mono_debugger_event (MONO_DEBUGGER_EVENT_GC_THREAD_CREATED
,
401 (guint64
) (gsize
) stack_ptr
, thread
);
405 debugger_gc_thread_exited (pthread_t thread
, void *stack_ptr
)
407 mono_debugger_event (MONO_DEBUGGER_EVENT_GC_THREAD_EXITED
,
408 (guint64
) (gsize
) stack_ptr
, thread
);
412 debugger_gc_stop_world (void)
414 mono_debugger_event (MONO_DEBUGGER_EVENT_ACQUIRE_GLOBAL_THREAD_LOCK
, 0, 0);
418 debugger_gc_start_world (void)
420 mono_debugger_event (MONO_DEBUGGER_EVENT_RELEASE_GLOBAL_THREAD_LOCK
, 0, 0);
423 static GCThreadFunctions debugger_thread_vtable
= {
426 debugger_gc_thread_created
,
427 debugger_gc_thread_exited
,
429 debugger_gc_stop_world
,
430 debugger_gc_start_world
434 debugger_init_threads (void)
436 gc_thread_vtable
= &debugger_thread_vtable
;
442 debugger_finalize_threads (void)
444 gc_thread_vtable
= NULL
;
450 debugger_init_code_buffer (void)
452 if (!debugger_executable_code_buffer
)
453 debugger_executable_code_buffer
= mono_global_codeman_reserve (EXECUTABLE_CODE_BUFFER_SIZE
);
454 return (guint64
) (gsize
) debugger_executable_code_buffer
;
457 extern MonoDebuggerInfo
*MONO_DEBUGGER__debugger_info_ptr
;
460 debugger_initialize (void)
465 mono_debugger_init (void)
467 debugger_executable_code_buffer
= mono_global_codeman_reserve (EXECUTABLE_CODE_BUFFER_SIZE
);
468 mono_debugger_event_handler
= debugger_event_handler
;
471 * Use an indirect call so gcc can't optimize it away.
473 MONO_DEBUGGER__debugger_info
.initialize ();
475 debugger_init_threads ();
478 * Initialize the thread manager.
480 * NOTE: We only reference the `MONO_DEBUGGER__debugger_info_ptr' here to prevent the
481 * linker from removing the .mdb_debug_info section.
484 mono_debugger_event (MONO_DEBUGGER_EVENT_INITIALIZE_THREAD_MANAGER
,
485 (guint64
) (gssize
) MONO_DEBUGGER__debugger_info_ptr
, 0);
492 } DebuggerThreadArgs
;
503 main_thread_handler (gpointer user_data
)
505 MainThreadArgs
*main_args
= (MainThreadArgs
*) user_data
;
507 return mono_runtime_run_main (main_args
->method
, main_args
->argc
, main_args
->argv
, NULL
);
511 mono_debugger_main (MonoDomain
*domain
, MonoAssembly
*assembly
, int argc
, char **argv
)
513 MainThreadArgs main_args
;
515 MonoMethod
*main_method
;
518 * Get and compile the main function.
521 image
= mono_assembly_get_image (assembly
);
522 main_method
= mono_get_method (image
, mono_image_get_entry_point (image
), NULL
);
525 * Initialize managed code.
527 mono_debugger_event (MONO_DEBUGGER_EVENT_INITIALIZE_MANAGED_CODE
,
528 (guint64
) (gssize
) main_method
, 0);
531 * Start the main thread and wait until it's ready.
534 main_args
.domain
= domain
;
535 main_args
.method
= main_method
;
536 main_args
.argc
= argc
;
537 main_args
.argv
= argv
;
540 mono_thread_create (domain
, main_thread_handler
, &main_args
);
542 main_thread_handler (&main_args
);
545 mono_thread_manage ();
548 * This will never return.
550 mono_debugger_event (MONO_DEBUGGER_EVENT_WRAPPER_MAIN
, 0, 0);