#include <mono/metadata/socket-io.h>
#include <mono/metadata/assembly.h>
#include <mono/metadata/runtime.h>
+#include <mono/metadata/threadpool.h>
+#include <mono/metadata/verify-internals.h>
#include <mono/utils/mono-semaphore.h>
#include <mono/utils/mono-error-internals.h>
#include <mono/utils/mono-stack-unwinding.h>
#ifndef DISABLE_DEBUGGER_AGENT
-#include <mono/io-layer/mono-mutex.h>
+#include <mono/utils/mono-mutex.h>
/* Definitions to make backporting to 2.6 easier */
//#define MonoInternalThread MonoThread
#define HEADER_LENGTH 11
#define MAJOR_VERSION 2
-#define MINOR_VERSION 23
+#define MINOR_VERSION 24
typedef enum {
CMD_SET_VM = 1,
CMD_METHOD_GET_BODY = 7,
CMD_METHOD_RESOLVE_TOKEN = 8,
CMD_METHOD_GET_CATTRS = 9,
+ CMD_METHOD_MAKE_GENERIC_METHOD = 10
} CmdMethod;
typedef enum {
event_requests = g_ptr_array_new ();
- mono_mutex_init (&debugger_thread_exited_mutex, NULL);
+ mono_mutex_init (&debugger_thread_exited_mutex);
mono_cond_init (&debugger_thread_exited_cond, NULL);
mono_profiler_install ((MonoProfiler*)&debugger_profiler, runtime_shutdown);
static void
suspend_init (void)
{
- mono_mutex_init (&suspend_mutex, NULL);
+ mono_mutex_init (&suspend_mutex);
mono_cond_init (&suspend_cond, NULL);
MONO_SEM_INIT (&suspend_sem, 0);
}
mono_mutex_unlock (&suspend_mutex);
+ if (suspend_count == 1)
+ /*
+ * Suspend creation of new threadpool threads, since they cannot run
+ */
+ mono_thread_pool_suspend ();
+
mono_loader_unlock ();
}
mono_mutex_unlock (&suspend_mutex);
//g_assert (err == 0);
+ if (suspend_count == 0)
+ mono_thread_pool_resume ();
+
mono_loader_unlock ();
}
GSList *l;
MonoDomain *domain = mono_domain_get ();
MonoThread *thread = NULL;
+ MonoObject *keepalive_obj = NULL;
gboolean send_success = FALSE;
static int ecount;
int nevents;
case EVENT_KIND_EXCEPTION: {
EventInfo *ei = arg;
buffer_add_objid (&buf, ei->exc);
+ /*
+ * We are not yet suspending, so get_objref () will not keep this object alive. So we need to do it
+ * later after the suspension. (#12494).
+ */
+ keepalive_obj = ei->exc;
break;
}
case EVENT_KIND_USER_BREAK:
*/
save_thread_context (ctx);
suspend_vm ();
+
+ if (keepalive_obj)
+ /* This will keep this object alive */
+ get_objref (keepalive_obj);
}
send_success = send_packet (CMD_SET_EVENT, CMD_COMPOSITE, &buf);
g_hash_table_insert (bp_locs, inst->ip, GINT_TO_POINTER (count + 1));
mono_loader_unlock ();
- if (count == 0) {
+ if (sp->native_offset == SEQ_POINT_NATIVE_OFFSET_DEAD_CODE) {
+ DEBUG (1, fprintf (log_file, "[dbg] Attempting to insert seq point at dead IL offset %d, ignoring.\n", (int)bp->il_offset));
+ } else if (count == 0) {
#ifdef MONO_ARCH_SOFT_DEBUG_SUPPORTED
mono_arch_set_breakpoint (ji, inst->ip);
#else
g_assert (count > 0);
- if (count == 1) {
+ if (count == 1 && inst->native_offset != SEQ_POINT_NATIVE_OFFSET_DEAD_CODE) {
mono_arch_clear_breakpoint (ji, ip);
}
#else
if (val == 0)
mono_arch_stop_single_stepping ();
+ if (ss_req != NULL)
+ ss_invoke_addr = NULL;
#else
g_assert_not_reached ();
#endif
}
static void
-add_var (Buffer *buf, MonoType *t, MonoDebugVarInfo *var, MonoContext *ctx, MonoDomain *domain, gboolean as_vtype)
+add_var (Buffer *buf, MonoDebugMethodJitInfo *jit, MonoType *t, MonoDebugVarInfo *var, MonoContext *ctx, MonoDomain *domain, gboolean as_vtype)
{
guint32 flags;
int reg;
- guint8 *addr;
+ guint8 *addr, *gaddr;
mgreg_t reg_val;
flags = var->index & MONO_DEBUG_VAR_ADDRESS_MODE_FLAGS;
case MONO_DEBUG_VAR_ADDRESS_MODE_DEAD:
NOT_IMPLEMENTED;
break;
+ case MONO_DEBUG_VAR_ADDRESS_MODE_REGOFFSET_INDIR:
+ /* Same as regoffset, but with an indirection */
+ addr = (gpointer)mono_arch_context_get_int_reg (ctx, reg);
+ addr += (gint32)var->offset;
+
+ gaddr = *(gpointer*)addr;
+ g_assert (gaddr);
+ buffer_add_value_full (buf, t, gaddr, domain, as_vtype);
+ break;
+ case MONO_DEBUG_VAR_ADDRESS_MODE_GSHAREDVT_LOCAL: {
+ MonoDebugVarInfo *info_var = jit->gsharedvt_info_var;
+ MonoDebugVarInfo *locals_var = jit->gsharedvt_locals_var;
+ MonoGSharedVtMethodRuntimeInfo *info;
+ guint8 *locals;
+ int idx;
+
+ idx = reg;
+
+ g_assert (info_var);
+ g_assert (locals_var);
+
+ flags = info_var->index & MONO_DEBUG_VAR_ADDRESS_MODE_FLAGS;
+ reg = info_var->index & ~MONO_DEBUG_VAR_ADDRESS_MODE_FLAGS;
+ if (flags == MONO_DEBUG_VAR_ADDRESS_MODE_REGOFFSET) {
+ addr = (gpointer)mono_arch_context_get_int_reg (ctx, reg);
+ addr += (gint32)info_var->offset;
+ info = *(gpointer*)addr;
+ } else if (flags == MONO_DEBUG_VAR_ADDRESS_MODE_REGISTER) {
+ info = (gpointer)mono_arch_context_get_int_reg (ctx, reg);
+ } else {
+ g_assert_not_reached ();
+ }
+ g_assert (info);
+
+ flags = locals_var->index & MONO_DEBUG_VAR_ADDRESS_MODE_FLAGS;
+ reg = locals_var->index & ~MONO_DEBUG_VAR_ADDRESS_MODE_FLAGS;
+ if (flags == MONO_DEBUG_VAR_ADDRESS_MODE_REGOFFSET) {
+ addr = (gpointer)mono_arch_context_get_int_reg (ctx, reg);
+ addr += (gint32)locals_var->offset;
+ locals = *(gpointer*)addr;
+ } else if (flags == MONO_DEBUG_VAR_ADDRESS_MODE_REGISTER) {
+ locals = (gpointer)mono_arch_context_get_int_reg (ctx, reg);
+ } else {
+ g_assert_not_reached ();
+ }
+ g_assert (locals);
+
+ addr = locals + GPOINTER_TO_INT (info->entries [idx]);
+
+ buffer_add_value_full (buf, t, addr, domain, as_vtype);
+ break;
+ }
+
default:
g_assert_not_reached ();
}
{
guint32 flags;
int reg, size;
- guint8 *addr;
+ guint8 *addr, *gaddr;
flags = var->index & MONO_DEBUG_VAR_ADDRESS_MODE_FLAGS;
reg = var->index & ~MONO_DEBUG_VAR_ADDRESS_MODE_FLAGS;
// FIXME: Write barriers
mono_gc_memmove (addr, val, size);
break;
+ case MONO_DEBUG_VAR_ADDRESS_MODE_REGOFFSET_INDIR:
+ /* Same as regoffset, but with an indirection */
+ addr = (gpointer)mono_arch_context_get_int_reg (ctx, reg);
+ addr += (gint32)var->offset;
+
+ gaddr = *(gpointer*)addr;
+ g_assert (gaddr);
+ // FIXME: Write barriers
+ mono_gc_memmove (gaddr, val, size);
+ break;
case MONO_DEBUG_VAR_ADDRESS_MODE_DEAD:
NOT_IMPLEMENTED;
break;
case CMD_VM_EXIT: {
MonoInternalThread *thread;
DebuggerTlsData *tls;
- MonoClass *env_class;
#ifdef TRY_MANAGED_SYSTEM_ENVIRONMENT_EXIT
- MonoMethod *exit_method = NULL;
+ MonoClass *env_class;
#endif
+ MonoMethod *exit_method = NULL;
gpointer *args;
int exit_code;
while (suspend_count > 0)
resume_vm ();
- mono_runtime_shutdown ();
+ if (!mono_runtime_try_shutdown ())
+ break;
/* Suspend all managed threads since the runtime is going away */
DEBUG(1, fprintf (log_file, "Suspending all threads...\n"));
buffer_add_cattrs (buf, domain, method->klass->image, attr_klass, cinfo);
break;
}
+ case CMD_METHOD_MAKE_GENERIC_METHOD: {
+ MonoType **type_argv;
+ int i, type_argc;
+ MonoDomain *d;
+ MonoClass *klass;
+ MonoGenericInst *ginst;
+ MonoGenericContext tmp_context;
+ MonoMethod *inflated;
+
+ type_argc = decode_int (p, &p, end);
+ type_argv = g_new0 (MonoType*, type_argc);
+ for (i = 0; i < type_argc; ++i) {
+ klass = decode_typeid (p, &p, end, &d, &err);
+ if (err) {
+ g_free (type_argv);
+ return err;
+ }
+ if (domain != d) {
+ g_free (type_argv);
+ return ERR_INVALID_ARGUMENT;
+ }
+ type_argv [i] = &klass->byval_arg;
+ }
+ ginst = mono_metadata_get_generic_inst (type_argc, type_argv);
+ g_free (type_argv);
+ tmp_context.class_inst = method->klass->generic_class ? method->klass->generic_class->context.class_inst : NULL;
+ tmp_context.method_inst = ginst;
+
+ inflated = mono_class_inflate_generic_method (method, &tmp_context);
+ if (!mono_verifier_is_method_valid_generic_instantiation (inflated))
+ return ERR_INVALID_ARGUMENT;
+ buffer_add_methodid (buf, domain, inflated);
+ break;
+ }
default:
return ERR_NOT_IMPLEMENTED;
}
frame = tls->frames [frame_idx];
if (!frame->has_ctx)
- // FIXME:
- return ERR_INVALID_FRAMEID;
+ return ERR_ABSENT_INFORMATION;
if (!frame->jit) {
frame->jit = mono_debug_find_method (frame->api_method, frame->domain);
var = &jit->params [pos];
- add_var (buf, sig->params [pos], &jit->params [pos], &frame->ctx, frame->domain, FALSE);
+ add_var (buf, jit, sig->params [pos], &jit->params [pos], &frame->ctx, frame->domain, FALSE);
} else {
g_assert (pos >= 0 && pos < jit->num_locals);
var = &jit->locals [pos];
- add_var (buf, header->locals [pos], &jit->locals [pos], &frame->ctx, frame->domain, FALSE);
+ add_var (buf, jit, header->locals [pos], &jit->locals [pos], &frame->ctx, frame->domain, FALSE);
}
}
mono_metadata_free_mh (header);
MonoObject *p = NULL;
buffer_add_value (buf, &mono_defaults.object_class->byval_arg, &p, frame->domain);
} else {
- add_var (buf, &frame->actual_method->klass->this_arg, jit->this_var, &frame->ctx, frame->domain, TRUE);
+ add_var (buf, jit, &frame->actual_method->klass->this_arg, jit->this_var, &frame->ctx, frame->domain, TRUE);
}
} else {
if (!sig->hasthis) {
MonoObject *p = NULL;
buffer_add_value (buf, &frame->actual_method->klass->byval_arg, &p, frame->domain);
} else {
- add_var (buf, &frame->api_method->klass->byval_arg, jit->this_var, &frame->ctx, frame->domain, TRUE);
+ add_var (buf, jit, &frame->api_method->klass->byval_arg, jit->this_var, &frame->ctx, frame->domain, TRUE);
}
}
break;
g_free (data);
buffer_free (&buf);
- if (command_set == CMD_SET_VM && command == CMD_VM_DISPOSE)
+ if (command_set == CMD_SET_VM && (command == CMD_VM_DISPOSE || command == CMD_VM_EXIT))
break;
}