a7dbac95b44f5fc0d5d2b1ee3925b9b7e06a1ead
[mono.git] / mono / mini / debug-debugger.c
1 #include <config.h>
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 #define _IN_THE_MONO_DEBUGGER
7 #include <mono/metadata/mono-debug-debugger.h>
8 #include <libgc/include/libgc-mono-debugger.h>
9 #include "mini.h"
10 #include <unistd.h>
11 #include <locale.h>
12 #include <string.h>
13
14 static GPtrArray *thread_array = NULL;
15
16 static gpointer main_started_cond;
17 static gpointer main_ready_cond;
18
19 static MonoMethod *debugger_main_method;
20
21 static guint64 debugger_insert_breakpoint (guint64 method_argument, const gchar *string_argument);
22 static guint64 debugger_remove_breakpoint (guint64 breakpoint);
23 static guint64 debugger_compile_method (guint64 method_arg);
24 static guint64 debugger_get_virtual_method (guint64 class_arg, guint64 method_arg);
25 static guint64 debugger_get_boxed_object (guint64 klass_arg, guint64 val_arg);
26 static guint64 debugger_create_string (guint64 dummy_argument, const gchar *string_argument);
27 static guint64 debugger_class_get_static_field_data (guint64 klass);
28 static guint64 debugger_lookup_class (guint64 image_argument, guint64 token_arg);
29 static guint64 debugger_lookup_type (guint64 dummy_argument, const gchar *string_argument);
30 static guint64 debugger_lookup_assembly (guint64 dummy_argument, const gchar *string_argument);
31 static guint64 debugger_run_finally (guint64 argument1, guint64 argument2);
32
33 void (*mono_debugger_notification_function) (guint64 command, guint64 data, guint64 data2);
34
35 /*
36  * This is a global data symbol which is read by the debugger.
37  */
38 MonoDebuggerInfo MONO_DEBUGGER__debugger_info = {
39         MONO_DEBUGGER_MAGIC,
40         MONO_DEBUGGER_VERSION,
41         sizeof (MonoDebuggerInfo),
42         sizeof (MonoSymbolTable),
43         0,
44         mono_trampoline_code,
45         &mono_symbol_table,
46         &debugger_compile_method,
47         &debugger_get_virtual_method,
48         &debugger_get_boxed_object,
49         &debugger_insert_breakpoint,
50         &debugger_remove_breakpoint,
51         &mono_debugger_runtime_invoke,
52         &debugger_create_string,
53         &debugger_class_get_static_field_data,
54         &debugger_lookup_class,
55         &debugger_lookup_type,
56         &debugger_lookup_assembly,
57         &debugger_run_finally
58 };
59
60 typedef struct {
61         gpointer end_stack;
62         gpointer start_stack;
63         gpointer func;
64         guint64 tid;
65 } MonoDebuggerThread;
66
67 typedef struct {
68         guint32 size;
69         guint32 thread_size;
70         gpointer main_function;
71         gpointer notification_address;
72         MonoDebuggerThread *main_thread;
73         guint32 main_tid;
74 } MonoDebuggerManager;
75
76 MonoDebuggerManager MONO_DEBUGGER__manager = {
77         sizeof (MonoDebuggerManager),
78         sizeof (MonoDebuggerThread),
79         NULL, NULL, NULL, 0
80 };
81
82 static guint64
83 debugger_insert_breakpoint (guint64 method_argument, const gchar *string_argument)
84 {
85         MonoMethodDesc *desc;
86
87         desc = mono_method_desc_new (string_argument, TRUE);
88         if (!desc)
89                 return 0;
90
91         return (guint64) mono_debugger_insert_breakpoint_full (desc);
92 }
93
94 static guint64
95 debugger_remove_breakpoint (guint64 breakpoint)
96 {
97         return mono_debugger_remove_breakpoint (breakpoint);
98 }
99
100 static gpointer
101 debugger_compile_method_cb (MonoMethod *method)
102 {
103         gpointer retval;
104
105         mono_debugger_lock ();
106         retval = mono_compile_method (method);
107         mono_debugger_unlock ();
108
109         mono_debugger_notification_function (MONO_DEBUGGER_EVENT_METHOD_COMPILED, GPOINTER_TO_UINT (retval), 0);
110
111         return retval;
112 }
113
114 static guint64
115 debugger_compile_method (guint64 method_arg)
116 {
117         MonoMethod *method = (MonoMethod *) GUINT_TO_POINTER ((gssize) method_arg);
118
119         return GPOINTER_TO_UINT (debugger_compile_method_cb (method));
120 }
121
122 static guint64
123 debugger_get_virtual_method (guint64 object_arg, guint64 method_arg)
124 {
125         MonoObject *object = (MonoObject *) GUINT_TO_POINTER ((gssize) object_arg);
126         MonoMethod *method = (MonoMethod *) GUINT_TO_POINTER ((gssize) method_arg);
127
128         if (mono_class_is_valuetype (mono_method_get_class (method)))
129                 return method_arg;
130
131         return GPOINTER_TO_UINT (mono_object_get_virtual_method (object, method));
132 }
133
134 static guint64
135 debugger_get_boxed_object (guint64 klass_arg, guint64 val_arg)
136 {
137         static MonoObject *last_boxed_object = NULL;
138         MonoClass *klass = (MonoClass *) GUINT_TO_POINTER ((gssize) klass_arg);
139         gpointer val = (gpointer) GUINT_TO_POINTER ((gssize) val_arg);
140         MonoObject *boxed;
141
142         if (!mono_class_is_valuetype (klass))
143                 return val_arg;
144
145         boxed = mono_value_box (mono_domain_get (), klass, val);
146         last_boxed_object = boxed; // Protect the object from being garbage collected
147
148         return GPOINTER_TO_UINT (boxed);
149 }
150
151 static guint64
152 debugger_create_string (guint64 dummy_argument, const gchar *string_argument)
153 {
154         return GPOINTER_TO_UINT (mono_string_new_wrapper (string_argument));
155 }
156
157 static guint64
158 debugger_lookup_type (guint64 dummy_argument, const gchar *string_argument)
159 {
160         guint64 retval;
161
162         mono_debugger_lock ();
163         // retval = mono_debugger_lookup_type (string_argument);
164         retval = -1;
165         mono_debugger_unlock ();
166         return retval;
167 }
168
169 static guint64
170 debugger_lookup_class (guint64 image_argument, guint64 token_argument)
171 {
172         MonoImage *image = (MonoImage *) GUINT_TO_POINTER ((gssize) image_argument);
173         guint32 token = (guint32) token_argument;
174         MonoClass *klass;
175
176         klass = mono_class_get (image, token);
177         if (klass)
178                 mono_class_init (klass);
179
180         return GPOINTER_TO_UINT (klass);
181 }
182
183 static guint64
184 debugger_lookup_assembly (guint64 dummy_argument, const gchar *string_argument)
185 {
186         gint64 retval;
187
188         mono_debugger_lock ();
189         retval = mono_debugger_lookup_assembly (string_argument);
190         mono_debugger_unlock ();
191         return retval;
192 }
193
194 static guint64
195 debugger_run_finally (guint64 context_argument, guint64 dummy)
196 {
197         mono_debugger_run_finally (GUINT_TO_POINTER (context_argument));
198         return 0;
199 }
200
201 static guint64
202 debugger_class_get_static_field_data (guint64 value)
203 {
204         MonoClass *klass = GUINT_TO_POINTER ((gssize) value);
205         MonoVTable *vtable = mono_class_vtable (mono_domain_get (), klass);
206         return GPOINTER_TO_UINT (mono_vtable_get_static_field_data (vtable));
207 }
208
209 static void
210 debugger_event_handler (MonoDebuggerEvent event, guint64 data, guint64 arg)
211 {
212         mono_debugger_notification_function (event, data, arg);
213 }
214
215 static void
216 debugger_thread_manager_thread_created (MonoDebuggerThread *thread)
217 {
218         if (!thread_array)
219                 thread_array = g_ptr_array_new ();
220
221         g_ptr_array_add (thread_array, thread);
222 }
223
224 static void
225 debugger_thread_manager_add_thread (gsize tid, gpointer start_stack, gpointer func)
226 {
227         MonoDebuggerThread *thread = g_new0 (MonoDebuggerThread, 1);
228
229         thread->tid = tid;
230         thread->func = func;
231         thread->start_stack = start_stack;
232
233         mono_debugger_notification_function (
234                 MONO_DEBUGGER_EVENT_THREAD_CREATED, GPOINTER_TO_UINT (thread), tid);
235
236         debugger_thread_manager_thread_created (thread);
237 }
238
239 static void
240 debugger_thread_manager_start_resume (gsize tid)
241 {
242 }
243
244 static void
245 debugger_thread_manager_end_resume (gsize tid)
246 {
247 }
248
249 extern void GC_push_all_stack (gpointer b, gpointer t);
250
251 static void
252 debugger_gc_stop_world (void)
253 {
254         mono_debugger_notification_function (
255                 MONO_DEBUGGER_EVENT_ACQUIRE_GLOBAL_THREAD_LOCK, 0, 0);
256 }
257
258 static void
259 debugger_gc_start_world (void)
260 {
261         mono_debugger_notification_function (
262                 MONO_DEBUGGER_EVENT_RELEASE_GLOBAL_THREAD_LOCK, 0, 0);
263 }
264
265 static void
266 debugger_gc_push_all_stacks (void)
267 {
268         int i, tid;
269
270         tid = GetCurrentThreadId ();
271
272         if (!thread_array)
273                 return;
274
275         for (i = 0; i < thread_array->len; i++) {
276                 MonoDebuggerThread *thread = g_ptr_array_index (thread_array, i);
277                 gpointer end_stack = (thread->tid == tid) ? &i : thread->end_stack;
278
279                 GC_push_all_stack (end_stack, thread->start_stack);
280         }
281 }
282
283 static GCThreadFunctions debugger_thread_vtable = {
284         NULL,
285
286         debugger_gc_stop_world,
287         debugger_gc_push_all_stacks,
288         debugger_gc_start_world
289 };
290
291 static void
292 debugger_thread_manager_init (void)
293 {
294         if (!thread_array)
295                 thread_array = g_ptr_array_new ();
296
297         gc_thread_vtable = &debugger_thread_vtable;
298 }
299
300 static MonoThreadCallbacks thread_callbacks = {
301         &debugger_compile_method_cb,
302         &debugger_thread_manager_add_thread,
303         &debugger_thread_manager_start_resume,
304         &debugger_thread_manager_end_resume
305 };
306
307 void
308 mono_debugger_init (void)
309 {
310         main_started_cond = CreateSemaphore (NULL, 0, 1, NULL);
311         main_ready_cond = CreateSemaphore (NULL, 0, 1, NULL);
312
313         mono_debugger_notification_function = mono_debugger_create_notification_function
314                 (&MONO_DEBUGGER__manager.notification_address);
315 }
316
317 typedef struct 
318 {
319         MonoDomain *domain;
320         const char *file;
321 } DebuggerThreadArgs;
322
323 typedef struct
324 {
325         MonoDomain *domain;
326         MonoMethod *method;
327         int argc;
328         char **argv;
329 } MainThreadArgs;
330
331 static guint32
332 main_thread_handler (gpointer user_data)
333 {
334         MainThreadArgs *main_args = (MainThreadArgs *) user_data;
335         int retval;
336
337         MONO_DEBUGGER__manager.main_tid = GetCurrentThreadId ();
338         MONO_DEBUGGER__manager.main_thread = g_new0 (MonoDebuggerThread, 1);
339         MONO_DEBUGGER__manager.main_thread->tid = GetCurrentThreadId ();
340         MONO_DEBUGGER__manager.main_thread->start_stack = &main_args;
341
342         debugger_thread_manager_thread_created (MONO_DEBUGGER__manager.main_thread);
343
344         ReleaseSemaphore (main_started_cond, 1, NULL);
345
346         /*
347          * Wait until everything is ready.
348          */
349         WaitForSingleObject (main_ready_cond, INFINITE);
350
351         retval = mono_runtime_run_main (main_args->method, main_args->argc, main_args->argv, NULL);
352         /*
353          * This will never return.
354          */
355         mono_debugger_notification_function (MONO_DEBUGGER_EVENT_MAIN_EXITED, 0, GPOINTER_TO_UINT (retval));
356
357         return retval;
358 }
359
360 int
361 mono_debugger_main (MonoDomain *domain, MonoAssembly *assembly, int argc, char **argv)
362 {
363         MainThreadArgs main_args;
364         MonoImage *image;
365
366         /*
367          * Get and compile the main function.
368          */
369
370         image = mono_assembly_get_image (assembly);
371         debugger_main_method = mono_get_method (
372                 image, mono_image_get_entry_point (image), NULL);
373         MONO_DEBUGGER__manager.main_function = mono_compile_method (debugger_main_method);
374
375         /*
376          * Start the main thread and wait until it's ready.
377          */
378
379         main_args.domain = domain;
380         main_args.method = debugger_main_method;
381         main_args.argc = argc - 2;
382         main_args.argv = argv + 2;
383
384         mono_thread_create (domain, main_thread_handler, &main_args);
385         WaitForSingleObject (main_started_cond, INFINITE);
386
387         /*
388          * Initialize the thread manager.
389          */
390
391         mono_debugger_event_handler = debugger_event_handler;
392         mono_install_thread_callbacks (&thread_callbacks);
393         debugger_thread_manager_init ();
394
395         /*
396          * Reload symbol tables.
397          */
398         mono_debugger_notification_function (MONO_DEBUGGER_EVENT_INITIALIZE_MANAGED_CODE, 0, 0);
399         mono_debugger_notification_function (MONO_DEBUGGER_EVENT_INITIALIZE_THREAD_MANAGER, 0, 0);
400
401         mono_debugger_unlock ();
402
403         /*
404          * Signal the main thread that it can execute the managed Main().
405          */
406         ReleaseSemaphore (main_ready_cond, 1, NULL);
407
408         /*
409          * This will never return.
410          */
411         mono_debugger_notification_function (MONO_DEBUGGER_EVENT_WRAPPER_MAIN, 0, 0);
412
413         return 0;
414 }