From 56ea90edf1ab510c50c5c8b329fac15041308fbc Mon Sep 17 00:00:00 2001 From: Jonathan Chambers Date: Sat, 9 Mar 2019 10:08:47 -0500 Subject: [PATCH 1/3] Initial work to allow debugger attaching without performance impact. --- mono/metadata/domain-internals.h | 2 + mono/mini/debugger-agent.c | 84 ++++++++++++++++++++++++-------- mono/mini/mini.c | 2 + 3 files changed, 68 insertions(+), 20 deletions(-) diff --git a/mono/metadata/domain-internals.h b/mono/metadata/domain-internals.h index a55277ff94eb..1df75583c36d 100644 --- a/mono/metadata/domain-internals.h +++ b/mono/metadata/domain-internals.h @@ -246,6 +246,8 @@ struct _MonoJitInfo { /* Whenever this jit info refers to an interpreter method */ gboolean is_interp:1; + gboolean dbg_ignore : 1; + /* FIXME: Embed this after the structure later*/ gpointer gc_info; /* Currently only used by SGen */ diff --git a/mono/mini/debugger-agent.c b/mono/mini/debugger-agent.c index 449fd7c8eaed..a391371596f9 100644 --- a/mono/mini/debugger-agent.c +++ b/mono/mini/debugger-agent.c @@ -1050,6 +1050,61 @@ mono_debugger_agent_parse_options (char *options) } } +static gboolean disable_optimizations = TRUE; + +static void +update_mdb_optimizations () +{ + gboolean enable = disable_optimizations; +#ifndef RUNTIME_IL2CPP + mini_get_debug_options ()->gen_sdb_seq_points = enable; + /* + * This is needed because currently we don't handle liveness info. + */ + mini_get_debug_options ()->mdb_optimizations = enable; + +#ifndef MONO_ARCH_HAVE_CONTEXT_SET_INT_REG + /* This is needed because we can't set local variables in registers yet */ + mono_disable_optimizations (MONO_OPT_LINEARS); +#endif + + /* + * The stack walk done from thread_interrupt () needs to be signal safe, but it + * isn't, since it can call into mono_aot_find_jit_info () which is not signal + * safe (#3411). So load AOT info eagerly when the debugger is running as a + * workaround. + */ + mini_get_debug_options ()->load_aot_jit_info_eagerly = enable; +#endif // !RUNTIME_IL2CPP +} + +MONO_API void +mono_debugger_set_generate_debug_info (gboolean enable) +{ + disable_optimizations = enable; + update_mdb_optimizations (); +} + +MONO_API gboolean +mono_debugger_get_generate_debug_info () +{ + return disable_optimizations; +} + +MONO_API void +mono_debugger_disconnect (const char *message) +{ + stop_debugger_thread (); +} + +typedef void (*MonoDebuggerAttachFunc)(gboolean attached); +static MonoDebuggerAttachFunc attach_func; +MONO_API void +mono_debugger_install_attach_detach_callback (MonoDebuggerAttachFunc func) +{ + attach_func = func; +} + void mono_debugger_agent_init (void) { @@ -1117,26 +1172,7 @@ mono_debugger_agent_init (void) breakpoints_init (); suspend_init (); -#ifndef RUNTIME_IL2CPP - mini_get_debug_options ()->gen_sdb_seq_points = TRUE; - /* - * This is needed because currently we don't handle liveness info. - */ - mini_get_debug_options ()->mdb_optimizations = TRUE; - -#ifndef MONO_ARCH_HAVE_CONTEXT_SET_INT_REG - /* This is needed because we can't set local variables in registers yet */ - mono_disable_optimizations (MONO_OPT_LINEARS); -#endif - - /* - * The stack walk done from thread_interrupt () needs to be signal safe, but it - * isn't, since it can call into mono_aot_find_jit_info () which is not signal - * safe (#3411). So load AOT info eagerly when the debugger is running as a - * workaround. - */ - mini_get_debug_options ()->load_aot_jit_info_eagerly = TRUE; -#endif // !RUNTIME_IL2CPP + update_mdb_optimizations (); #ifdef HAVE_SETPGID if (agent_config.setpgid) @@ -4659,6 +4695,8 @@ insert_breakpoint (MonoSeqPointInfo *seq_points, MonoDomain *domain, MonoJitInfo mini_get_interp_callbacks ()->set_breakpoint (ji, inst->ip); } else { #ifdef MONO_ARCH_SOFT_DEBUG_SUPPORTED + if (ji->dbg_ignore) + return; mono_arch_set_breakpoint (ji, inst->ip); #else NOT_IMPLEMENTED; @@ -11992,6 +12030,8 @@ debugger_thread (void *arg) attach_failed = TRUE; // Don't abort process when we can't listen } else { mono_set_is_debugger_attached (TRUE); + if (attach_func) + attach_func (TRUE); /* Send start event to client */ process_profiler_event (EVENT_KIND_VM_START, mono_thread_get_main ()); #ifdef RUNTIME_IL2CPP @@ -12008,6 +12048,8 @@ debugger_thread (void *arg) } } else { mono_set_is_debugger_attached (TRUE); + if (attach_func) + attach_func (TRUE); } while (!attach_failed) { @@ -12142,6 +12184,8 @@ debugger_thread (void *arg) } mono_set_is_debugger_attached (FALSE); + if (attach_func) + attach_func (FALSE); #ifdef RUNTIME_IL2CPP il2cpp_mono_free_method_signatures(); diff --git a/mono/mini/mini.c b/mono/mini/mini.c index d4c7936eb185..13a0295b46fc 100644 --- a/mono/mini/mini.c +++ b/mono/mini/mini.c @@ -2809,6 +2809,8 @@ create_jit_info (MonoCompile *cfg, MonoMethod *method_to_compile) jinfo->unwind_info = cfg->used_int_regs; } + jinfo->dbg_ignore = !cfg->gen_sdb_seq_points; + return jinfo; } From c46f9908abb54eff6b266d4e9d82d4bb37cd2781 Mon Sep 17 00:00:00 2001 From: Jonathan Chambers Date: Sat, 9 Mar 2019 10:08:47 -0500 Subject: [PATCH 2/3] Initial work to allow debugger attaching without performance impact. --- mono/metadata/domain-internals.h | 2 + mono/mini/debugger-agent.c | 84 ++++++++++++++++++++++++-------- mono/mini/mini.c | 2 + 3 files changed, 68 insertions(+), 20 deletions(-) diff --git a/mono/metadata/domain-internals.h b/mono/metadata/domain-internals.h index a55277ff94eb..1df75583c36d 100644 --- a/mono/metadata/domain-internals.h +++ b/mono/metadata/domain-internals.h @@ -246,6 +246,8 @@ struct _MonoJitInfo { /* Whenever this jit info refers to an interpreter method */ gboolean is_interp:1; + gboolean dbg_ignore : 1; + /* FIXME: Embed this after the structure later*/ gpointer gc_info; /* Currently only used by SGen */ diff --git a/mono/mini/debugger-agent.c b/mono/mini/debugger-agent.c index 449fd7c8eaed..a391371596f9 100644 --- a/mono/mini/debugger-agent.c +++ b/mono/mini/debugger-agent.c @@ -1050,6 +1050,61 @@ mono_debugger_agent_parse_options (char *options) } } +static gboolean disable_optimizations = TRUE; + +static void +update_mdb_optimizations () +{ + gboolean enable = disable_optimizations; +#ifndef RUNTIME_IL2CPP + mini_get_debug_options ()->gen_sdb_seq_points = enable; + /* + * This is needed because currently we don't handle liveness info. + */ + mini_get_debug_options ()->mdb_optimizations = enable; + +#ifndef MONO_ARCH_HAVE_CONTEXT_SET_INT_REG + /* This is needed because we can't set local variables in registers yet */ + mono_disable_optimizations (MONO_OPT_LINEARS); +#endif + + /* + * The stack walk done from thread_interrupt () needs to be signal safe, but it + * isn't, since it can call into mono_aot_find_jit_info () which is not signal + * safe (#3411). So load AOT info eagerly when the debugger is running as a + * workaround. + */ + mini_get_debug_options ()->load_aot_jit_info_eagerly = enable; +#endif // !RUNTIME_IL2CPP +} + +MONO_API void +mono_debugger_set_generate_debug_info (gboolean enable) +{ + disable_optimizations = enable; + update_mdb_optimizations (); +} + +MONO_API gboolean +mono_debugger_get_generate_debug_info () +{ + return disable_optimizations; +} + +MONO_API void +mono_debugger_disconnect (const char *message) +{ + stop_debugger_thread (); +} + +typedef void (*MonoDebuggerAttachFunc)(gboolean attached); +static MonoDebuggerAttachFunc attach_func; +MONO_API void +mono_debugger_install_attach_detach_callback (MonoDebuggerAttachFunc func) +{ + attach_func = func; +} + void mono_debugger_agent_init (void) { @@ -1117,26 +1172,7 @@ mono_debugger_agent_init (void) breakpoints_init (); suspend_init (); -#ifndef RUNTIME_IL2CPP - mini_get_debug_options ()->gen_sdb_seq_points = TRUE; - /* - * This is needed because currently we don't handle liveness info. - */ - mini_get_debug_options ()->mdb_optimizations = TRUE; - -#ifndef MONO_ARCH_HAVE_CONTEXT_SET_INT_REG - /* This is needed because we can't set local variables in registers yet */ - mono_disable_optimizations (MONO_OPT_LINEARS); -#endif - - /* - * The stack walk done from thread_interrupt () needs to be signal safe, but it - * isn't, since it can call into mono_aot_find_jit_info () which is not signal - * safe (#3411). So load AOT info eagerly when the debugger is running as a - * workaround. - */ - mini_get_debug_options ()->load_aot_jit_info_eagerly = TRUE; -#endif // !RUNTIME_IL2CPP + update_mdb_optimizations (); #ifdef HAVE_SETPGID if (agent_config.setpgid) @@ -4659,6 +4695,8 @@ insert_breakpoint (MonoSeqPointInfo *seq_points, MonoDomain *domain, MonoJitInfo mini_get_interp_callbacks ()->set_breakpoint (ji, inst->ip); } else { #ifdef MONO_ARCH_SOFT_DEBUG_SUPPORTED + if (ji->dbg_ignore) + return; mono_arch_set_breakpoint (ji, inst->ip); #else NOT_IMPLEMENTED; @@ -11992,6 +12030,8 @@ debugger_thread (void *arg) attach_failed = TRUE; // Don't abort process when we can't listen } else { mono_set_is_debugger_attached (TRUE); + if (attach_func) + attach_func (TRUE); /* Send start event to client */ process_profiler_event (EVENT_KIND_VM_START, mono_thread_get_main ()); #ifdef RUNTIME_IL2CPP @@ -12008,6 +12048,8 @@ debugger_thread (void *arg) } } else { mono_set_is_debugger_attached (TRUE); + if (attach_func) + attach_func (TRUE); } while (!attach_failed) { @@ -12142,6 +12184,8 @@ debugger_thread (void *arg) } mono_set_is_debugger_attached (FALSE); + if (attach_func) + attach_func (FALSE); #ifdef RUNTIME_IL2CPP il2cpp_mono_free_method_signatures(); diff --git a/mono/mini/mini.c b/mono/mini/mini.c index d4c7936eb185..13a0295b46fc 100644 --- a/mono/mini/mini.c +++ b/mono/mini/mini.c @@ -2809,6 +2809,8 @@ create_jit_info (MonoCompile *cfg, MonoMethod *method_to_compile) jinfo->unwind_info = cfg->used_int_regs; } + jinfo->dbg_ignore = !cfg->gen_sdb_seq_points; + return jinfo; } From a269b9d1924e6f955be5a0167c5110f16699b616 Mon Sep 17 00:00:00 2001 From: eneko Date: Wed, 29 May 2019 14:53:07 +0200 Subject: [PATCH 3/3] [debugger-agent] modify mono_debugger_disconnect method so the transport socket is opened after stopping the debugger thread and start a new debugger thread --- mono/mini/debugger-agent.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/mono/mini/debugger-agent.c b/mono/mini/debugger-agent.c index a391371596f9..2dfb599a1ce9 100644 --- a/mono/mini/debugger-agent.c +++ b/mono/mini/debugger-agent.c @@ -1092,9 +1092,11 @@ mono_debugger_get_generate_debug_info () } MONO_API void -mono_debugger_disconnect (const char *message) +mono_debugger_disconnect () { stop_debugger_thread (); + transport_connect (agent_config.address); + start_debugger_thread (); } typedef void (*MonoDebuggerAttachFunc)(gboolean attached);