static MonoDebugHandle *mono_debug_handle = NULL;
static gconstpointer debugger_notification_address = NULL;
+#ifndef PLATFORM_WIN32
static pthread_cond_t debugger_thread_cond = PTHREAD_COND_INITIALIZER;
static pthread_mutex_t debugger_thread_mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
+static pthread_cond_t debugger_finished_cond = PTHREAD_COND_INITIALIZER;
+static pthread_mutex_t debugger_finished_mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
static pthread_cond_t debugger_start_cond = PTHREAD_COND_INITIALIZER;
static pthread_mutex_t debugger_start_mutex = PTHREAD_MUTEX_INITIALIZER;
+static gboolean debugger_signalled = FALSE;
+#endif
+static gboolean must_send_finished = FALSE;
+extern void (*mono_debugger_class_init_func) (MonoClass *klass);
static guint64 debugger_insert_breakpoint (guint64 method_argument, const gchar *string_argument);
static guint64 debugger_remove_breakpoint (guint64 breakpoint);
static int debugger_update_symbol_file_table (void);
+static gpointer debugger_compile_method (MonoMethod *method);
static void mono_debug_add_assembly (MonoAssembly *assembly, gpointer user_data);
static void mono_debug_close_assembly (AssemblyDebugInfo* info);
&mono_generic_trampoline_code,
&mono_breakpoint_trampoline_code,
&debugger_symbol_file_table_generation,
+ &debugger_symbol_file_table_modified,
&debugger_notification_address,
&debugger_symbol_file_table,
- &mono_compile_method,
+ &debugger_compile_method,
&debugger_insert_breakpoint,
&debugger_remove_breakpoint,
&mono_runtime_invoke
static void
mono_debugger_lock (void)
{
+#ifndef PLATFORM_WIN32
pthread_mutex_lock (&debugger_thread_mutex);
+#endif
}
static void
mono_debugger_unlock (void)
{
+#ifndef PLATFORM_WIN32
pthread_mutex_unlock (&debugger_thread_mutex);
+#endif
}
static void
-mono_debugger_signal (void)
+mono_debugger_signal (gboolean modified)
{
- mono_debugger_lock ();
- if (!debugger_symbol_file_table_modified) {
+#ifndef PLATFORM_WIN32
+ if (modified)
debugger_symbol_file_table_modified = TRUE;
+ if (!debugger_signalled) {
+ debugger_signalled = TRUE;
pthread_cond_signal (&debugger_thread_cond);
}
- mono_debugger_unlock ();
+#endif
+}
+
+static void
+mono_debugger_wait (void)
+{
+#ifndef PLATFORM_WIN32
+ pthread_cond_wait (&debugger_finished_cond, &debugger_finished_mutex);
+#endif
}
static void
}
break;
case MONO_DEBUG_FORMAT_MONO:
+ case MONO_DEBUG_FORMAT_MONO_DEBUGGER:
debug->flags |= MONO_DEBUG_FLAGS_DONT_UPDATE_IL_FILES |
MONO_DEBUG_FLAGS_DONT_CREATE_IL_FILES;
break;
break;
}
- if (debug->format != MONO_DEBUG_FORMAT_MONO) {
+ if ((debug->format != MONO_DEBUG_FORMAT_MONO) &&
+ (debug->format != MONO_DEBUG_FORMAT_MONO_DEBUGGER)) {
if (!strcmp (arg, "dont_assemble")) {
debug->flags |= MONO_DEBUG_FLAGS_DONT_ASSEMBLE;
continue;
debug->flags |= MONO_DEBUG_FLAGS_DONT_CREATE_IL_FILES;
continue;
}
- } else {
- if (!strcmp (arg, "internal_mono_debugger")) {
- debug->flags |= MONO_DEBUG_FLAGS_MONO_DEBUGGER;
- initialize_debugger_support ();
- continue;
- }
}
message = g_strdup_printf ("Unknown argument `%s'.", arg);
debug->objfile = g_strdup_printf ("%s.o", g_basename (debug->name));
break;
case MONO_DEBUG_FORMAT_MONO:
+ mono_debugger_class_init_func = mono_debug_add_type;
+ break;
+ case MONO_DEBUG_FORMAT_MONO_DEBUGGER:
+ mono_debugger_class_init_func = mono_debug_add_type;
+ initialize_debugger_support ();
break;
default:
g_assert_not_reached ();
mono_debug_add_type (mono_defaults.serializationinfo_class);
mono_debug_add_type (mono_defaults.streamingcontext_class);
- g_message (G_STRLOC);
+ debugger_update_symbol_file_table ();
+
mono_debugger_unlock ();
return debug;
info->ilfile = g_strdup_printf ("%s.il", info->name);
break;
case MONO_DEBUG_FORMAT_MONO:
+ case MONO_DEBUG_FORMAT_MONO_DEBUGGER:
info->filename = replace_suffix (image->name, "dbg");
if (g_file_test (info->filename, G_FILE_TEST_EXISTS))
info->symfile = mono_debug_open_mono_symbol_file (info->image, info->filename, TRUE);
- else if (debug->flags & MONO_DEBUG_FLAGS_MONO_DEBUGGER)
+ else if (info->format == MONO_DEBUG_FORMAT_MONO_DEBUGGER)
info->symfile = mono_debug_create_mono_symbol_file (info->image);
debugger_symbol_file_table_generation++;
break;
break;
}
- if (debug->format != MONO_DEBUG_FORMAT_MONO)
+ if ((debug->format != MONO_DEBUG_FORMAT_MONO) && (debug->format != MONO_DEBUG_FORMAT_MONO_DEBUGGER))
debug_load_method_lines (info);
return info;
mono_debug_write_dwarf2 (debug);
break;
case MONO_DEBUG_FORMAT_MONO:
+ case MONO_DEBUG_FORMAT_MONO_DEBUGGER:
break;
default:
g_assert_not_reached ();
void
mono_debug_make_symbols (void)
{
- release_symbol_file_table ();
-
if (!mono_debug_handle || !mono_debug_handle->dirty)
return;
mono_debug_write_dwarf2 (mono_debug_handle);
break;
case MONO_DEBUG_FORMAT_MONO:
+ case MONO_DEBUG_FORMAT_MONO_DEBUGGER:
debugger_update_symbol_file_table ();
break;
default:
{
switch (info->format) {
case MONO_DEBUG_FORMAT_MONO:
+ case MONO_DEBUG_FORMAT_MONO_DEBUGGER:
if (info->symfile != NULL)
mono_debug_close_mono_symbol_file (info->symfile);
break;
info = mono_debug_get_image (mono_debug_handle, klass->image);
g_assert (info);
- if (mono_debug_handle->format != MONO_DEBUG_FORMAT_MONO)
+ if ((mono_debug_handle->format != MONO_DEBUG_FORMAT_MONO) &&
+ (mono_debug_handle->format != MONO_DEBUG_FORMAT_MONO_DEBUGGER))
return;
if (info->symfile) {
mono_debugger_lock ();
mono_debug_symfile_add_type (info->symfile, klass);
- mono_debugger_signal ();
+ mono_debugger_signal (TRUE);
mono_debugger_unlock ();
}
}
}
debug_generate_method_lines (info, minfo, cfg);
- if (info->format == MONO_DEBUG_FORMAT_MONO)
+ if ((info->format == MONO_DEBUG_FORMAT_MONO) || (info->format == MONO_DEBUG_FORMAT_MONO_DEBUGGER))
debug_update_il_offsets (info, minfo, cfg);
if (!method->iflags & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
if (info->symfile) {
mono_debug_symfile_add_method (info->symfile, method);
- mono_debugger_signal ();
+ mono_debugger_signal (TRUE);
}
mono_debugger_unlock ();
{
AssemblyDebugInfo *info = (AssemblyDebugInfo *) value;
- if (!info->symfile || (info->format != MONO_DEBUG_FORMAT_MONO))
+ if (!info->symfile)
+ return;
+ if ((info->format != MONO_DEBUG_FORMAT_MONO) && (info->format != MONO_DEBUG_FORMAT_MONO_DEBUGGER))
return;
++ (* (int *) user_data);
AssemblyDebugInfo *info = (AssemblyDebugInfo *) value;
struct SymfileTableData *data = (struct SymfileTableData *) user_data;
- if (!info->symfile || (info->format != MONO_DEBUG_FORMAT_MONO))
+ if (!info->symfile)
+ return;
+ if ((info->format != MONO_DEBUG_FORMAT_MONO) && (info->format != MONO_DEBUG_FORMAT_MONO_DEBUGGER))
return;
data->symfile_table->symfiles [data->index++] = info->symfile;
symfile_table->total_size = size;
symfile_table->count = count;
symfile_table->generation = debugger_symbol_file_table_generation;
+ symfile_table->global_symfile = mono_debugger_global_symbol_file;
data.symfile_table = symfile_table;
data.index = 0;
return TRUE;
}
-extern void (*mono_debugger_class_init_func) (MonoClass *klass);
-
static gboolean has_mono_debugger_support = FALSE;
+#ifndef PLATFORM_WIN32
/*
* NOTE: We must not call any functions here which we ever may want to debug !
*/
/* Wait for an event. */
pthread_cond_wait (&debugger_thread_cond, &debugger_thread_mutex);
- if (!debugger_symbol_file_table_modified)
- continue;
-
/* Reload the symbol file table if necessary. */
if (debugger_symbol_file_table_generation > last_generation) {
debugger_update_symbol_file_table ();
*/
notification_code ();
- /* Clear modified flag. */
+ /* Clear modified and signalled flag. */
debugger_symbol_file_table_modified = FALSE;
+ debugger_signalled = FALSE;
+
+ if (must_send_finished) {
+ pthread_mutex_lock (&debugger_finished_mutex);
+ pthread_cond_signal (&debugger_finished_cond);
+ must_send_finished = FALSE;
+ pthread_mutex_unlock (&debugger_finished_mutex);
+ }
}
return NULL;
}
+#endif
static void
initialize_debugger_support ()
{
guint8 *buf, *ptr;
+#ifndef PLATFORM_WIN32
pthread_t thread;
int ret;
+#endif
if (has_mono_debugger_support)
return;
has_mono_debugger_support = TRUE;
- mono_debugger_class_init_func = mono_debug_add_type;
-
ptr = buf = g_malloc0 (16);
x86_breakpoint (buf);
debugger_notification_address = buf;
x86_ret (buf);
+#ifndef PLATFORM_WIN32
pthread_mutex_lock (&debugger_start_mutex);
+ /*
+ * This mutex is only unlocked by the pthread_cond_wait() in
+ * mono_debugger_wait().
+ */
+ pthread_mutex_lock (&debugger_finished_mutex);
+
ret = pthread_create (&thread, NULL, debugger_thread_func, ptr);
g_assert (ret == 0);
* debugger attached to it.
*/
pthread_cond_wait (&debugger_start_cond, &debugger_start_mutex);
+
+ /*
+ * We keep this mutex until mono_debugger_jit_exec().
+ */
+ pthread_mutex_lock (&debugger_thread_mutex);
+#endif
}
static GPtrArray *breakpoints = NULL;
return 0;
}
+static gpointer
+debugger_compile_method (MonoMethod *method)
+{
+ gpointer retval;
+
+ mono_debugger_lock ();
+ retval = mono_compile_method (method);
+ mono_debugger_signal (FALSE);
+ mono_debugger_unlock ();
+ return retval;
+}
+
int
mono_remove_breakpoint (int breakpoint_id)
{
return 0;
}
+
+void
+mono_debugger_trampoline_breakpoint_callback (void)
+{
+ mono_debugger_lock ();
+ must_send_finished = TRUE;
+ mono_debugger_signal (FALSE);
+ mono_debugger_unlock ();
+
+ mono_debugger_wait ();
+}
+
+/*
+ * This is a custom version of mono_jit_exec() which is used when we're being run inside
+ * the Mono Debugger.
+ */
+int
+mono_debugger_jit_exec (MonoDomain *domain, MonoAssembly *assembly, int argc, char *argv[])
+{
+ MonoImage *image = assembly->image;
+ MonoMethod *method;
+ gpointer addr;
+
+ method = mono_get_method (image, mono_image_get_entry_point (image), NULL);
+
+ addr = mono_compile_method (method);
+
+ /*
+ * The mutex has been locked in initialize_debugger_support(); we keep it locked
+ * until we compiled the main method and signalled the debugger.
+ */
+ must_send_finished = TRUE;
+ mono_debugger_signal (TRUE);
+ mono_debugger_unlock ();
+
+ /*
+ * Wait until the debugger has loaded the initial symbol tables.
+ */
+ mono_debugger_wait ();
+
+ return mono_runtime_run_main (method, argc, argv, NULL);
+}