#include <mono/metadata/mono-debug-debugger.h>
#include "debug-mini.h"
-#ifdef HAVE_VALGRIND_H
-#include <valgrind/valgrind.h>
-#endif
+#include <mono/utils/valgrind.h>
#ifdef MONO_DEBUGGER_SUPPORTED
#include <libgc/include/libgc-mono-debugger.h>
guint32 stopped_on_unhandled : 1;
} MonoDebuggerExceptionState;
+typedef enum {
+ MONO_DEBUGGER_THREAD_FLAGS_NONE = 0,
+ MONO_DEBUGGER_THREAD_FLAGS_INTERNAL = 1,
+ MONO_DEBUGGER_THREAD_FLAGS_THREADPOOL = 2
+} MonoDebuggerThreadFlags;
+
+typedef enum {
+ MONO_DEBUGGER_INTERNAL_THREAD_FLAGS_NONE = 0,
+ MONO_DEBUGGER_INTERNAL_THREAD_FLAGS_IN_RUNTIME_INVOKE = 1,
+ MONO_DEBUGGER_INTERNAL_THREAD_FLAGS_ABORT_REQUESTED = 2
+} MonoDebuggerInternalThreadFlags;
+
struct _MonoDebuggerThreadInfo {
guint64 tid;
guint64 lmf_addr;
guint32 stack_size;
guint32 signal_stack_size;
- MonoDebuggerExceptionState exception_state;
+ guint32 thread_flags;
/*
* The debugger doesn't access anything beyond this point.
*/
+ MonoDebuggerExceptionState exception_state;
+
+ guint32 internal_flags;
+
MonoJitTlsData *jit_tls;
- MonoThread *thread;
+ MonoInternalThread *thread;
};
typedef struct {
guint32 stop_unhandled;
} MonoDebuggerExceptionInfo;
-typedef enum {
- MONO_DEBUGGER_EXCEPTION_ACTION_NONE = 0,
- MONO_DEBUGGER_EXCEPTION_ACTION_STOP = 1,
- MONO_DEBUGGER_EXCEPTION_ACTION_STOP_UNHANDLED = 2
-} MonoDebuggerExceptionAction;
-
MonoDebuggerThreadInfo *mono_debugger_thread_table = NULL;
static inline void
mono_class_init (cfg->method->klass);
- header = mono_method_get_header (cfg->method);
+ header = cfg->header;
g_assert (header);
info->jit = jit = g_new0 (MonoDebugMethodJitInfo, 1);
var->index = inst->dreg | MONO_DEBUG_VAR_ADDRESS_MODE_REGISTER;
else if (inst->flags & MONO_INST_IS_DEAD)
var->index = MONO_DEBUG_VAR_ADDRESS_MODE_DEAD;
- else {
+ else if (inst->opcode == OP_REGOFFSET) {
/* the debug interface needs fixing to allow 0(%base) address */
var->index = inst->inst_basereg | MONO_DEBUG_VAR_ADDRESS_MODE_REGOFFSET;
var->offset = inst->inst_offset;
+ } else if (inst->opcode == OP_GSHAREDVT_ARG_REGOFFSET) {
+ var->index = inst->inst_basereg | MONO_DEBUG_VAR_ADDRESS_MODE_REGOFFSET_INDIR;
+ var->offset = inst->inst_offset;
+ } else if (inst->opcode == OP_GSHAREDVT_LOCAL) {
+ var->index = inst->inst_imm | MONO_DEBUG_VAR_ADDRESS_MODE_GSHAREDVT_LOCAL;
+ } else if (inst->opcode == OP_VTARG_ADDR) {
+ var->offset = inst->inst_offset;
+ var->index = inst->inst_basereg | MONO_DEBUG_VAR_ADDRESS_MODE_VTADDR;
+ } else {
+ g_assert_not_reached ();
}
}
g_free (addresses);
g_free (lines);
+ mono_metadata_free_mh (header);
#endif /* VALGRIND_ADD_LINE_INFO */
}
}
method = cfg->method;
- header = mono_method_get_header (method);
+ header = cfg->header;
sig = mono_method_signature (method);
jit = info->jit;
for (i = 0; i < jit->num_params; i++)
write_variable (cfg->args [i + sig->hasthis], &jit->params [i]);
+ if (cfg->gsharedvt_info_var) {
+ jit->gsharedvt_info_var = g_new0 (MonoDebugVarInfo, 1);
+ jit->gsharedvt_locals_var = g_new0 (MonoDebugVarInfo, 1);
+ write_variable (cfg->gsharedvt_info_var, jit->gsharedvt_info_var);
+ write_variable (cfg->gsharedvt_locals_var, jit->gsharedvt_locals_var);
+ }
+
jit->num_line_numbers = info->line_numbers->len;
jit->line_numbers = g_new0 (MonoDebugLineNumberEntry, jit->num_line_numbers);
for (i = 0; i < jit->num_line_numbers; i++)
jit->line_numbers [i] = g_array_index (info->line_numbers, MonoDebugLineNumberEntry, i);
- debug_info = mono_debug_add_method (method, jit, cfg->domain);
+ debug_info = mono_debug_add_method (cfg->method_to_register, jit, cfg->domain);
mono_debug_add_vg_method (method, jit);
mono_debugger_check_breakpoints (method, debug_info);
mono_debug_free_method_jit_info (jit);
- g_array_free (info->line_numbers, TRUE);
- g_free (info);
+ mono_debug_free_method (cfg);
+}
+
+void
+mono_debug_free_method (MonoCompile *cfg)
+{
+ MiniDebugMethodInfo *info;
+
+ info = (MiniDebugMethodInfo *) cfg->debug_info;
+ if (info) {
+ if (info->line_numbers)
+ g_array_free (info->line_numbers, TRUE);
+ g_free (info);
+ cfg->debug_info = NULL;
+ }
}
void
if (!info || !info->jit || !ins->cil_code)
return;
- header = mono_method_get_header (cfg->method);
+ header = cfg->header;
g_assert (header);
if ((ins->cil_code < header->code) ||
if (!info || !info->jit || !bb->cil_code)
return;
- header = mono_method_get_header (cfg->method);
+ header = cfg->header;
g_assert (header);
if ((bb->cil_code < header->code) ||
case MONO_DEBUG_VAR_ADDRESS_MODE_REGISTER:
break;
case MONO_DEBUG_VAR_ADDRESS_MODE_REGOFFSET:
+ case MONO_DEBUG_VAR_ADDRESS_MODE_REGOFFSET_INDIR:
encode_value (var->offset, p, &p);
break;
+ case MONO_DEBUG_VAR_ADDRESS_MODE_GSHAREDVT_LOCAL:
+ case MONO_DEBUG_VAR_ADDRESS_MODE_VTADDR:
case MONO_DEBUG_VAR_ADDRESS_MODE_DEAD:
break;
default:
for (i = 0; i < jit->num_locals; i++)
serialize_variable (&jit->locals [i], p, &p);
+ if (jit->gsharedvt_info_var) {
+ encode_value (1, p, &p);
+ serialize_variable (jit->gsharedvt_info_var, p, &p);
+ serialize_variable (jit->gsharedvt_locals_var, p, &p);
+ } else {
+ encode_value (0, p, &p);
+ }
+
encode_value (jit->num_line_numbers, p, &p);
prev_offset = 0;
case MONO_DEBUG_VAR_ADDRESS_MODE_REGISTER:
break;
case MONO_DEBUG_VAR_ADDRESS_MODE_REGOFFSET:
+ case MONO_DEBUG_VAR_ADDRESS_MODE_REGOFFSET_INDIR:
var->offset = decode_value (p, &p);
break;
+ case MONO_DEBUG_VAR_ADDRESS_MODE_GSHAREDVT_LOCAL:
+ case MONO_DEBUG_VAR_ADDRESS_MODE_VTADDR:
case MONO_DEBUG_VAR_ADDRESS_MODE_DEAD:
break;
default:
for (i = 0; i < jit->num_locals; i++)
deserialize_variable (&jit->locals [i], p, &p);
+ if (decode_value (p, &p)) {
+ jit->gsharedvt_info_var = g_new0 (MonoDebugVarInfo, 1);
+ jit->gsharedvt_locals_var = g_new0 (MonoDebugVarInfo, 1);
+ deserialize_variable (jit->gsharedvt_info_var, p, &p);
+ deserialize_variable (jit->gsharedvt_locals_var, p, &p);
+ }
+
jit->num_line_numbers = decode_value (p, &p);
jit->line_numbers = g_new0 (MonoDebugLineNumberEntry, jit->num_line_numbers);
prev_native_offset = native_offset;
}
+ mono_metadata_free_mh (header);
return jit;
}
case MONO_DEBUG_VAR_ADDRESS_MODE_REGOFFSET:
g_print ("%s %s (%d) in memory: base register %s + %d\n", type, name, idx, mono_arch_regname (info->index & (~MONO_DEBUG_VAR_ADDRESS_MODE_FLAGS)), info->offset);
break;
+ case MONO_DEBUG_VAR_ADDRESS_MODE_REGOFFSET_INDIR:
+ g_print ("%s %s (%d) in indir memory: base register %s + %d\n", type, name, idx, mono_arch_regname (info->index & (~MONO_DEBUG_VAR_ADDRESS_MODE_FLAGS)), info->offset);
+ break;
+ case MONO_DEBUG_VAR_ADDRESS_MODE_GSHAREDVT_LOCAL:
+ g_print ("%s %s (%d) gsharedvt local.\n", type, name, idx);
+ break;
+ case MONO_DEBUG_VAR_ADDRESS_MODE_VTADDR:
+ g_print ("%s %s (%d) vt address: base register %s + %d\n", type, name, idx, mono_arch_regname (info->index & (~MONO_DEBUG_VAR_ADDRESS_MODE_FLAGS)), info->offset);
+ break;
case MONO_DEBUG_VAR_ADDRESS_MODE_TWO_REGISTERS:
default:
g_assert_not_reached ();
{
int i;
- if (!breakpoints || ((method->wrapper_type != MONO_WRAPPER_NONE) &&
- (method->wrapper_type != MONO_WRAPPER_DYNAMIC_METHOD)))
+ if (!breakpoints)
return 0;
for (i = 0; i < breakpoints->len; i++) {
}
void
-mono_debugger_thread_created (gsize tid, MonoThread *thread, MonoJitTlsData *jit_tls)
+mono_debugger_thread_created (gsize tid, MonoThread *thread, MonoJitTlsData *jit_tls, gpointer func)
{
#ifdef MONO_DEBUGGER_SUPPORTED
size_t stsize = 0;
info = g_new0 (MonoDebuggerThreadInfo, 1);
info->tid = tid;
- info->thread = thread;
+ info->thread = thread->internal_thread;
info->stack_start = (guint64) (gsize) staddr;
info->signal_stack_start = (guint64) (gsize) jit_tls->signal_stack;
info->stack_size = stsize;
info->lmf_addr = (guint64) (gsize) mono_get_lmf_addr ();
info->jit_tls = jit_tls;
+ if (func)
+ info->thread_flags = MONO_DEBUGGER_THREAD_FLAGS_INTERNAL;
+ if (thread->internal_thread->threadpool_thread)
+ info->thread_flags |= MONO_DEBUGGER_THREAD_FLAGS_THREADPOOL;
+
info->next = mono_debugger_thread_table;
mono_debugger_thread_table = info;
{
#ifdef MONO_DEBUGGER_SUPPORTED
MonoDebuggerThreadInfo **ptr;
- MonoThread *thread = mono_thread_current ();
+ MonoInternalThread *thread = mono_thread_internal_current ();
if (!mono_debug_using_mono_debugger ())
return;
}
void
-mono_debugger_trampoline_compiled (MonoMethod *method, const guint8 *code)
+mono_debugger_trampoline_compiled (const guint8 *trampoline, MonoMethod *method, const guint8 *code)
{
- mono_debugger_extended_notification (MONO_DEBUGGER_EVENT_TRAMPOLINE,
+#ifdef MONO_DEBUGGER_SUPPORTED
+ struct {
+ const guint8 * trampoline;
+ MonoMethod *method;
+ const guint8 *code;
+ } info = { trampoline, method, code };
+
+ mono_debugger_extended_notification (MONO_DEBUGGER_EVENT_OLD_TRAMPOLINE,
(guint64) (gsize) method, (guint64) (gsize) code);
+ mono_debugger_extended_notification (MONO_DEBUGGER_EVENT_TRAMPOLINE,
+ (guint64) (gsize) &info, 0);
+#endif
}
#if MONO_DEBUGGER_SUPPORTED
static MonoDebuggerThreadInfo *
-find_debugger_thread_info (MonoThread *thread)
+find_debugger_thread_info (MonoInternalThread *thread)
{
MonoDebuggerThreadInfo **ptr;
}
#endif
-static MonoDebuggerExceptionAction
+MonoDebuggerExceptionAction
_mono_debugger_throw_exception (gpointer addr, gpointer stack, MonoObject *exc)
{
#ifdef MONO_DEBUGGER_SUPPORTED
mono_debugger_lock ();
- thread_info = find_debugger_thread_info (mono_thread_current ());
+ thread_info = find_debugger_thread_info (mono_thread_internal_current ());
if (!thread_info) {
mono_debugger_unlock ();
return MONO_DEBUGGER_EXCEPTION_ACTION_NONE;
}
+ if ((thread_info->internal_flags & MONO_DEBUGGER_INTERNAL_THREAD_FLAGS_ABORT_REQUESTED) != 0) {
+ mono_debugger_unlock ();
+ return MONO_DEBUGGER_EXCEPTION_ACTION_NONE;
+ }
+
if (thread_info->exception_state.stopped_on_exception ||
thread_info->exception_state.stopped_on_unhandled) {
thread_info->exception_state.stopped_on_exception = 0;
return MONO_DEBUGGER_EXCEPTION_ACTION_NONE;
}
-static gboolean
+gboolean
_mono_debugger_unhandled_exception (gpointer addr, gpointer stack, MonoObject *exc)
{
#ifdef MONO_DEBUGGER_SUPPORTED
mono_debugger_lock ();
- thread_info = find_debugger_thread_info (mono_thread_current ());
+ thread_info = find_debugger_thread_info (mono_thread_internal_current ());
if (!thread_info) {
mono_debugger_unlock ();
return FALSE;
}
+ if ((thread_info->internal_flags & MONO_DEBUGGER_INTERNAL_THREAD_FLAGS_ABORT_REQUESTED) != 0) {
+ mono_debugger_unlock ();
+ return FALSE;
+ }
+
if (thread_info->exception_state.stopped_on_unhandled) {
thread_info->exception_state.stopped_on_unhandled = 0;
mono_debugger_unlock ();
mono_debugger_lock ();
- thread_info = find_debugger_thread_info (mono_thread_current ());
+ thread_info = find_debugger_thread_info (mono_thread_internal_current ());
if (!thread_info) {
mono_debugger_unlock ();
return;
}
+ if ((thread_info->internal_flags & MONO_DEBUGGER_INTERNAL_THREAD_FLAGS_ABORT_REQUESTED) != 0) {
+ mono_debugger_unlock ();
+ return;
+ }
+
// Prevent the object from being finalized.
thread_info->exception_state.last_exception = exc;
#endif
}
-/*
- * mono_debugger_handle_exception:
- *
- * Notify the debugger about exceptions. Returns TRUE if the debugger wants us to stop
- * at the exception and FALSE to resume with the normal exception handling.
- *
- * The arch code is responsible to setup @ctx in a way that MONO_CONTEXT_GET_IP () and
- * MONO_CONTEXT_GET_SP () point to the throw instruction; ie. before executing the
- * `callq throw' instruction.
- */
-gboolean
-mono_debugger_handle_exception (MonoContext *ctx, MonoObject *obj)
-{
- MonoDebuggerExceptionAction action;
-
- if (!mono_debug_using_mono_debugger ())
- return FALSE;
-
- if (!obj) {
- MonoException *ex = mono_get_exception_null_reference ();
- MONO_OBJECT_SETREF (ex, message, mono_string_new (mono_domain_get (), "Object reference not set to an instance of an object"));
- obj = (MonoObject *)ex;
- }
-
- action = _mono_debugger_throw_exception (MONO_CONTEXT_GET_IP (ctx), MONO_CONTEXT_GET_SP (ctx), obj);
-
- if (action == MONO_DEBUGGER_EXCEPTION_ACTION_STOP) {
- /*
- * The debugger wants us to stop on the `throw' instruction.
- * By the time we get here, it already inserted a breakpoint there.
- */
- return TRUE;
- } else if (action == MONO_DEBUGGER_EXCEPTION_ACTION_STOP_UNHANDLED) {
- MonoContext ctx_cp = *ctx;
-
- /*
- * The debugger wants us to stop only if this exception is user-unhandled.
- */
-
- if (!mono_handle_exception (&ctx_cp, obj, MONO_CONTEXT_GET_IP (ctx), TRUE)) {
- /*
- * The exception is user-unhandled - tell the debugger to stop.
- */
- return _mono_debugger_unhandled_exception (MONO_CONTEXT_GET_IP (ctx), MONO_CONTEXT_GET_SP (ctx), obj);
- }
-
- /*
- * The exception is catched somewhere - resume with the normal exception handling and don't
- * stop in the debugger.
- */
- }
-
- return FALSE;
-}
-
#ifdef MONO_DEBUGGER_SUPPORTED
static gchar *
mono_debugger_lock ();
- thread_info = find_debugger_thread_info (mono_thread_current ());
+ thread_info = find_debugger_thread_info (mono_thread_internal_current ());
if (!thread_info) {
mono_debugger_unlock ();
return NULL;
thread_info->exception_state.stopped_on_unhandled = 0;
thread_info->exception_state.stopped_on_exception = 0;
+ thread_info->internal_flags |= MONO_DEBUGGER_INTERNAL_THREAD_FLAGS_IN_RUNTIME_INVOKE;
+
mono_debugger_unlock ();
if (!strcmp (method->name, ".ctor")) {
mono_debugger_lock ();
- thread_info = find_debugger_thread_info (mono_thread_current ());
- if (thread_info)
- thread_info->exception_state = saved_exception_state;
+ thread_info->exception_state = saved_exception_state;
+ thread_info->internal_flags &= ~MONO_DEBUGGER_INTERNAL_THREAD_FLAGS_IN_RUNTIME_INVOKE;
+
+ if ((thread_info->internal_flags & MONO_DEBUGGER_INTERNAL_THREAD_FLAGS_ABORT_REQUESTED) != 0) {
+ thread_info->internal_flags &= ~MONO_DEBUGGER_INTERNAL_THREAD_FLAGS_ABORT_REQUESTED;
+ mono_thread_internal_reset_abort (thread_info->thread);
+
+ mono_debugger_unlock ();
+
+ *exc = NULL;
+ return NULL;
+ }
mono_debugger_unlock ();
return retval;
}
+gboolean
+mono_debugger_abort_runtime_invoke ()
+{
+ MonoInternalThread *thread = mono_thread_internal_current ();
+ MonoDebuggerThreadInfo *thread_info;
+
+ mono_debugger_lock ();
+
+ thread_info = find_debugger_thread_info (thread);
+ if (!thread_info) {
+ mono_debugger_unlock ();
+ return FALSE;
+ }
+
+ if ((thread_info->internal_flags & MONO_DEBUGGER_INTERNAL_THREAD_FLAGS_IN_RUNTIME_INVOKE) == 0) {
+ mono_debugger_unlock ();
+ return FALSE;
+ }
+
+ if ((thread_info->internal_flags & MONO_DEBUGGER_INTERNAL_THREAD_FLAGS_ABORT_REQUESTED) != 0) {
+ mono_debugger_unlock ();
+ return TRUE;
+ }
+
+ thread_info->internal_flags |= MONO_DEBUGGER_INTERNAL_THREAD_FLAGS_ABORT_REQUESTED;
+ ves_icall_System_Threading_Thread_Abort (thread_info->thread, NULL);
+
+ mono_debugger_unlock ();
+ return TRUE;
+}
+
#endif