#include <mono/metadata/gc-internal.h>
#include <mono/metadata/environment.h>
#include <mono/metadata/threads-types.h>
+#include <mono/metadata/threadpool-ms.h>
#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>
int nreply_packets;
#define dbg_lock() do { \
- MONO_TRY_BLOCKING \
+ MONO_TRY_BLOCKING; \
mono_mutex_lock (&debug_mutex); \
- MONO_FINISH_TRY_BLOCKING \
+ MONO_FINISH_TRY_BLOCKING; \
} while (0)
#define dbg_unlock() mono_mutex_unlock (&debug_mutex)
}
}
- MONO_PREPARE_BLOCKING
+ MONO_PREPARE_BLOCKING;
transport_connect (agent_config.address);
- MONO_FINISH_BLOCKING
+ MONO_FINISH_BLOCKING;
if (!on_startup) {
/* Do some which is usually done after sending the VMStart () event */
}
}
- MONO_PREPARE_BLOCKING
+ MONO_PREPARE_BLOCKING;
conn_fd = socket_transport_accept (sfd);
- MONO_FINISH_BLOCKING
+ MONO_FINISH_BLOCKING;
if (conn_fd == -1)
exit (1);
/* Write handshake message */
sprintf (handshake_msg, "DWP-Handshake");
/* Must use try blocking as this can nest into code that runs blocking */
- MONO_TRY_BLOCKING
+ MONO_TRY_BLOCKING;
do {
res = transport_send (handshake_msg, strlen (handshake_msg));
} while (res == -1 && get_last_sock_error () == MONO_EINTR);
- MONO_FINISH_TRY_BLOCKING
+ MONO_FINISH_TRY_BLOCKING;
g_assert (res != -1);
/* Read answer */
- MONO_TRY_BLOCKING
+ MONO_TRY_BLOCKING;
res = transport_recv (buf, strlen (handshake_msg));
- MONO_FINISH_TRY_BLOCKING
+ MONO_FINISH_TRY_BLOCKING;
if ((res != strlen (handshake_msg)) || (memcmp (buf, handshake_msg, strlen (handshake_msg)) != 0)) {
fprintf (stderr, "debugger-agent: DWP handshake failed.\n");
return FALSE;
if (!inited)
return;
- MONO_PREPARE_BLOCKING
+ MONO_PREPARE_BLOCKING;
transport_close1 ();
- MONO_FINISH_BLOCKING
+ MONO_FINISH_BLOCKING;
/*
* Wait for the thread to exit.
*/
if (GetCurrentThreadId () != debugger_thread_id) {
do {
- MONO_TRY_BLOCKING
+ MONO_TRY_BLOCKING;
mono_mutex_lock (&debugger_thread_exited_mutex);
if (!debugger_thread_exited)
mono_cond_wait (&debugger_thread_exited_cond, &debugger_thread_exited_mutex);
mono_mutex_unlock (&debugger_thread_exited_mutex);
- MONO_FINISH_TRY_BLOCKING
+ MONO_FINISH_TRY_BLOCKING;
} while (!debugger_thread_exited);
}
- MONO_PREPARE_BLOCKING
+ MONO_PREPARE_BLOCKING;
transport_close2 ();
- MONO_FINISH_BLOCKING
+ MONO_FINISH_BLOCKING;
}
static void
buffer_add_byte (&buf, command);
memcpy (buf.buf + 11, data->buf, data->p - data->buf);
- MONO_PREPARE_BLOCKING
+ MONO_PREPARE_BLOCKING;
res = transport_send (buf.buf, len);
- MONO_FINISH_BLOCKING
+ MONO_FINISH_BLOCKING;
buffer_free (&buf);
buffer_add_buffer (&buf, packets [i].data);
}
- MONO_PREPARE_BLOCKING
+ MONO_PREPARE_BLOCKING;
res = transport_send (buf.buf, len);
- MONO_FINISH_BLOCKING
+ MONO_FINISH_BLOCKING;
buffer_free (&buf);
{
GetLastFrameUserData *data = user_data;
- if (info->type == FRAME_TYPE_MANAGED_TO_NATIVE)
+ if (info->type == FRAME_TYPE_MANAGED_TO_NATIVE || info->type == FRAME_TYPE_TRAMPOLINE)
return FALSE;
if (!data->last_frame_set) {
// FIXME: Races when the thread leaves managed code before hitting a single step
// event.
- if (ji) {
+ if (ji && !ji->is_trampoline) {
/* Running managed code, will be suspended by the single step code */
DEBUG_PRINTF (1, "[%p] Received interrupt while at %s(%p), continuing.\n", (gpointer)(gsize)tid, jinfo_get_method (ji)->name, ip);
} else {
MonoJitInfo *ji;
data->valid_info = TRUE;
- ji = mono_jit_info_table_find (mono_thread_info_get_suspend_state (info)->unwind_data [MONO_UNWIND_DATA_DOMAIN], MONO_CONTEXT_GET_IP (&mono_thread_info_get_suspend_state (info)->ctx));
+ ji = mono_jit_info_table_find_internal (
+ mono_thread_info_get_suspend_state (info)->unwind_data [MONO_UNWIND_DATA_DOMAIN],
+ MONO_CONTEXT_GET_IP (&mono_thread_info_get_suspend_state (info)->ctx),
+ TRUE,
+ TRUE);
/* This is signal safe */
thread_interrupt (data->tls, info, ji);
{
mono_loader_lock ();
- MONO_TRY_BLOCKING
+ MONO_TRY_BLOCKING;
mono_mutex_lock (&suspend_mutex);
- MONO_FINISH_TRY_BLOCKING
+ MONO_FINISH_TRY_BLOCKING;
suspend_count ++;
/*
* Suspend creation of new threadpool threads, since they cannot run
*/
- mono_thread_pool_suspend ();
+ mono_threadpool_ms_suspend ();
mono_loader_unlock ();
}
mono_loader_lock ();
- MONO_TRY_BLOCKING
+ MONO_TRY_BLOCKING;
mono_mutex_lock (&suspend_mutex);
- MONO_FINISH_TRY_BLOCKING
+ MONO_FINISH_TRY_BLOCKING;
g_assert (suspend_count > 0);
suspend_count --;
//g_assert (err == 0);
if (suspend_count == 0)
- mono_thread_pool_resume ();
+ mono_threadpool_ms_resume ();
mono_loader_unlock ();
}
tls = mono_g_hash_table_lookup (thread_to_tls, thread);
g_assert (tls);
- MONO_TRY_BLOCKING
+ MONO_TRY_BLOCKING;
mono_mutex_lock (&suspend_mutex);
- MONO_FINISH_TRY_BLOCKING
+ MONO_FINISH_TRY_BLOCKING;
g_assert (suspend_count > 0);
tls = mono_native_tls_get_value (debugger_tls_id);
g_assert (tls);
- MONO_TRY_BLOCKING
+ MONO_TRY_BLOCKING;
mono_mutex_lock (&suspend_mutex);
- MONO_FINISH_TRY_BLOCKING
+ MONO_FINISH_TRY_BLOCKING;
tls->suspending = FALSE;
tls->really_suspended = TRUE;
DEBUG_PRINTF (1, "[%p] Suspended.\n", (gpointer)GetCurrentThreadId ());
- MONO_TRY_BLOCKING
+ MONO_TRY_BLOCKING;
while (suspend_count - tls->resume_count > 0) {
err = mono_cond_wait (&suspend_cond, &suspend_mutex);
g_assert (err == 0);
}
- MONO_FINISH_TRY_BLOCKING
+ MONO_FINISH_TRY_BLOCKING;
tls->suspended = FALSE;
tls->really_suspended = FALSE;
info->il_offset = mono_debug_il_offset_from_address (method, info->domain, info->native_offset);
}
- DEBUG_PRINTF (1, "\tFrame: %s:%x(%x) %d\n", mono_method_full_name (method, TRUE), info->il_offset, info->native_offset, info->managed);
+ DEBUG_PRINTF (1, "\tFrame: %s:[il=0x%x, native=0x%x] %d\n", mono_method_full_name (method, TRUE), info->il_offset, info->native_offset, info->managed);
if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE) {
if (!CHECK_PROTOCOL_VERSION (2, 17))
#endif
}
- DEBUG_PRINTF (1, "[dbg] Inserted breakpoint at %s:0x%x [%p](%d).\n", mono_method_full_name (jinfo_get_method (ji), TRUE), (int)it.seq_point.il_offset, inst->ip, count);
+ DEBUG_PRINTF (1, "[dbg] Inserted breakpoint at %s:[il=0x%x,native=0x%x] [%p](%d).\n", mono_method_full_name (jinfo_get_method (ji), TRUE), (int)it.seq_point.il_offset, (int)it.seq_point.native_offset, inst->ip, count);
}
static void
ip = MONO_CONTEXT_GET_IP (ctx);
ji = mini_jit_info_table_find (mono_domain_get (), (char*)ip, NULL);
- g_assert (ji);
+ g_assert (ji && !ji->is_trampoline);
method = jinfo_get_method (ji);
/* Compute the native offset of the breakpoint from the ip */
g_assert (found_sp);
- DEBUG_PRINTF (1, "[%p] Breakpoint hit, method=%s, ip=%p, offset=0x%x, sp il offset=0x%x.\n", (gpointer)GetCurrentThreadId (), method->name, ip, native_offset, sp.il_offset);
+ DEBUG_PRINTF (1, "[%p] Breakpoint hit, method=%s, ip=%p, [il=0x%x,native=0x%x].\n", (gpointer)GetCurrentThreadId (), method->name, ip, sp.il_offset, native_offset);
bp = NULL;
for (i = 0; i < breakpoints->len; ++i) {
}
ji = mini_jit_info_table_find (mono_domain_get (), (char*)ip, &domain);
- g_assert (ji);
+ g_assert (ji && !ji->is_trampoline);
method = jinfo_get_method (ji);
g_assert (method);
!(t->type == MONO_TYPE_I && type == MONO_TYPE_VALUETYPE) &&
!(t->type == MONO_TYPE_U && type == MONO_TYPE_VALUETYPE) &&
!(t->type == MONO_TYPE_PTR && type == MONO_TYPE_I8) &&
- !(t->type == MONO_TYPE_GENERICINST && type == MONO_TYPE_VALUETYPE)) {
+ !(t->type == MONO_TYPE_GENERICINST && type == MONO_TYPE_VALUETYPE) &&
+ !(t->type == MONO_TYPE_VALUETYPE && type == MONO_TYPE_OBJECT)) {
char *name = mono_type_full_name (t);
DEBUG_PRINTF (1, "[%p] Expected value of type %s, got 0x%0x.\n", (gpointer)GetCurrentThreadId (), name, type);
g_free (name);
/* Fall through */
handle_vtype:
case MONO_TYPE_VALUETYPE:
- err = decode_vtype (t, domain, addr,buf, &buf, limit);
- if (err)
- return err;
+ if (type == MONO_TYPE_OBJECT) {
+ /* Boxed vtype */
+ int objid = decode_objid (buf, &buf, limit);
+ int err;
+ MonoObject *obj;
+
+ err = get_object (objid, (MonoObject**)&obj);
+ if (err)
+ return err;
+ if (!obj)
+ return ERR_INVALID_ARGUMENT;
+ if (obj->vtable->klass != mono_class_from_mono_type (t)) {
+ DEBUG_PRINTF (1, "Expected type '%s', got object '%s'\n", mono_type_full_name (t), obj->vtable->klass->name);
+ return ERR_INVALID_ARGUMENT;
+ }
+ memcpy (addr, mono_object_unbox (obj), mono_class_value_size (obj->vtable->klass, NULL));
+ } else {
+ err = decode_vtype (t, domain, addr, buf, &buf, limit);
+ if (err)
+ return err;
+ }
break;
handle_ref:
default:
MonoMethodSignature *sig;
guint8 **arg_buf;
void **args;
- MonoObject *this, *res, *exc;
+ MonoObject *this_arg, *res, *exc;
MonoDomain *domain;
guint8 *this_buf;
#ifdef MONO_ARCH_SOFT_DEBUG_SUPPORTED
/*
* Invoke this method directly, currently only Environment.Exit () is supported.
*/
- this = NULL;
- DEBUG_PRINTF (1, "[%p] Invoking method '%s' on receiver '%s'.\n", (gpointer)GetCurrentThreadId (), mono_method_full_name (invoke->method, TRUE), this ? this->vtable->klass->name : "<null>");
+ this_arg = NULL;
+ DEBUG_PRINTF (1, "[%p] Invoking method '%s' on receiver '%s'.\n", (gpointer)GetCurrentThreadId (), mono_method_full_name (invoke->method, TRUE), this_arg ? this_arg->vtable->klass->name : "<null>");
mono_runtime_invoke (invoke->method, NULL, invoke->args, &exc);
g_assert_not_reached ();
}
return ERR_INVALID_ARGUMENT;
}
memset (this_buf, 0, mono_class_instance_size (m->klass));
+ } else if (m->klass->valuetype && !strcmp (m->name, ".ctor")) {
+ /* Could be null */
+ guint8 *tmp_p;
+
+ int type = decode_byte (p, &tmp_p, end);
+ if (type == VALUE_TYPE_ID_NULL) {
+ memset (this_buf, 0, mono_class_instance_size (m->klass));
+ p = tmp_p;
+ } else {
+ err = decode_value (&m->klass->byval_arg, domain, this_buf, p, &p, end);
+ if (err)
+ return err;
+ }
} else {
err = decode_value (&m->klass->byval_arg, domain, this_buf, p, &p, end);
if (err)
}
if (!m->klass->valuetype)
- this = *(MonoObject**)this_buf;
+ this_arg = *(MonoObject**)this_buf;
else
- this = NULL;
+ this_arg = NULL;
if (MONO_CLASS_IS_INTERFACE (m->klass)) {
- if (!this) {
+ if (!this_arg) {
DEBUG_PRINTF (1, "[%p] Error: Interface method invoked without this argument.\n", (gpointer)GetCurrentThreadId ());
return ERR_INVALID_ARGUMENT;
}
- m = mono_object_get_virtual_method (this, m);
+ m = mono_object_get_virtual_method (this_arg, m);
+ /* Transform this to the format the rest of the code expects it to be */
+ if (m->klass->valuetype) {
+ this_buf = g_alloca (mono_class_instance_size (m->klass));
+ memcpy (this_buf, mono_object_unbox (this_arg), mono_class_instance_size (m->klass));
+ }
} else if ((m->flags & METHOD_ATTRIBUTE_VIRTUAL) && !m->klass->valuetype && invoke->flags & INVOKE_FLAG_VIRTUAL) {
- if (!this) {
+ if (!this_arg) {
DEBUG_PRINTF (1, "[%p] Error: invoke with INVOKE_FLAG_VIRTUAL flag set without this argument.\n", (gpointer)GetCurrentThreadId ());
return ERR_INVALID_ARGUMENT;
}
- m = mono_object_get_virtual_method (this, m);
+ m = mono_object_get_virtual_method (this_arg, m);
+ if (m->klass->valuetype) {
+ this_buf = g_alloca (mono_class_instance_size (m->klass));
+ memcpy (this_buf, mono_object_unbox (this_arg), mono_class_instance_size (m->klass));
+ }
}
- DEBUG_PRINTF (1, "[%p] Invoking method '%s' on receiver '%s'.\n", (gpointer)GetCurrentThreadId (), mono_method_full_name (m, TRUE), this ? this->vtable->klass->name : "<null>");
+ DEBUG_PRINTF (1, "[%p] Invoking method '%s' on receiver '%s'.\n", (gpointer)GetCurrentThreadId (), mono_method_full_name (m, TRUE), this_arg ? this_arg->vtable->klass->name : "<null>");
- if (this && this->vtable->domain != domain)
+ if (this_arg && this_arg->vtable->domain != domain)
NOT_IMPLEMENTED;
- if (!m->klass->valuetype && !(m->flags & METHOD_ATTRIBUTE_STATIC) && !this) {
+ if (!m->klass->valuetype && !(m->flags & METHOD_ATTRIBUTE_STATIC) && !this_arg) {
if (!strcmp (m->name, ".ctor")) {
if (m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT)
return ERR_INVALID_ARGUMENT;
else
- this = mono_object_new (domain, m->klass);
+ this_arg = mono_object_new (domain, m->klass);
} else {
return ERR_INVALID_ARGUMENT;
}
}
- if (this && !obj_is_of_type (this, &m->klass->byval_arg))
+ if (this_arg && !obj_is_of_type (this_arg, &m->klass->byval_arg))
return ERR_INVALID_ARGUMENT;
nargs = decode_int (p, &p, end);
if (m->klass->valuetype)
res = mono_runtime_invoke (m, this_buf, args, &exc);
else
- res = mono_runtime_invoke (m, this, args, &exc);
+ res = mono_runtime_invoke (m, this_arg, args, &exc);
mono_stopwatch_stop (&watch);
DEBUG_PRINTF (1, "[%p] Invoke result: %p, exc: %s, time: %ld ms.\n", (gpointer)GetCurrentThreadId (), res, exc ? exc->vtable->klass->name : NULL, (long)mono_stopwatch_elapsed_ms (&watch));
if (exc) {
out_args = TRUE;
buffer_add_byte (buf, 1 + (out_this ? 2 : 0) + (out_args ? 4 : 0));
if (sig->ret->type == MONO_TYPE_VOID) {
- if (!strcmp (m->name, ".ctor") && !m->klass->valuetype) {
- buffer_add_value (buf, &mono_defaults.object_class->byval_arg, &this, domain);
- }
- else
+ if (!strcmp (m->name, ".ctor")) {
+ if (!m->klass->valuetype)
+ buffer_add_value (buf, &mono_defaults.object_class->byval_arg, &this_arg, domain);
+ else
+ buffer_add_value (buf, &m->klass->byval_arg, this_buf, domain);
+ } else {
buffer_add_value (buf, &mono_defaults.void_class->byval_arg, NULL, domain);
+ }
} else if (MONO_TYPE_IS_REFERENCE (sig->ret)) {
buffer_add_value (buf, sig->ret, &res, domain);
} else if (mono_class_from_mono_type (sig->ret)->valuetype || sig->ret->type == MONO_TYPE_PTR || sig->ret->type == MONO_TYPE_FNPTR) {
if (pos < 0) {
pos = - pos - 1;
+ DEBUG_PRINTF (4, "[dbg] send arg %d.\n", pos);
+
g_assert (pos >= 0 && pos < jit->num_params);
add_var (buf, jit, sig->params [pos], &jit->params [pos], &frame->ctx, frame->domain, FALSE);
} else {
+ MonoDebugLocalsInfo *locals;
+
+ locals = mono_debug_lookup_locals (frame->method);
+ if (locals) {
+ g_assert (pos < locals->num_locals);
+ pos = locals->locals [pos].index;
+ mono_debug_free_locals (locals);
+ }
g_assert (pos >= 0 && pos < jit->num_locals);
+ DEBUG_PRINTF (4, "[dbg] send local %d.\n", pos);
+
add_var (buf, jit, header->locals [pos], &jit->locals [pos], &frame->ctx, frame->domain, FALSE);
}
}
t = sig->params [pos];
var = &jit->params [pos];
} else {
+ MonoDebugLocalsInfo *locals;
+
+ locals = mono_debug_lookup_locals (frame->method);
+ if (locals) {
+ g_assert (pos < locals->num_locals);
+ pos = locals->locals [pos].index;
+ mono_debug_free_locals (locals);
+ }
g_assert (pos >= 0 && pos < jit->num_locals);
t = header->locals [pos];
if (err)
return err;
+ MonoClass *obj_type;
+
+ obj_type = obj->vtable->klass;
+ if (mono_class_is_transparent_proxy (obj_type))
+ obj_type = ((MonoTransparentProxy *)obj)->remote_class->proxy_class;
+
+ g_assert (obj_type);
+
switch (command) {
case CMD_OBJECT_REF_GET_TYPE:
/* This handles transparent proxies too */
/* Check that the field belongs to the object */
found = FALSE;
- for (k = obj->vtable->klass; k; k = k->parent) {
+ for (k = obj_type; k; k = k->parent) {
if (k == f->parent) {
found = TRUE;
break;
/* Check that the field belongs to the object */
found = FALSE;
- for (k = obj->vtable->klass; k; k = k->parent) {
+ for (k = obj_type; k; k = k->parent) {
if (k == f->parent) {
found = TRUE;
break;
}
/* Block and wait for client connection */
- MONO_PREPARE_BLOCKING
+ MONO_PREPARE_BLOCKING;
conn_fd = socket_transport_accept (listen_fd);
- MONO_FINISH_BLOCKING
+ MONO_FINISH_BLOCKING;
DEBUG_PRINTF (1, "Accepted connection on %d\n", conn_fd);
if (conn_fd == -1) {
}
while (!attach_failed) {
- MONO_PREPARE_BLOCKING
+ MONO_PREPARE_BLOCKING;
res = transport_recv (header, HEADER_LENGTH);
- MONO_FINISH_BLOCKING
+ MONO_FINISH_BLOCKING;
/* This will break if the socket is closed during shutdown too */
if (res != HEADER_LENGTH) {
data = g_malloc (len - HEADER_LENGTH);
if (len - HEADER_LENGTH > 0)
{
- MONO_PREPARE_BLOCKING
+ MONO_PREPARE_BLOCKING;
res = transport_recv (data, len - HEADER_LENGTH);
- MONO_FINISH_BLOCKING
+ MONO_FINISH_BLOCKING;
if (res != len - HEADER_LENGTH) {
DEBUG_PRINTF (1, "[dbg] transport_recv () returned %d, expected %d.\n", res, len - HEADER_LENGTH);
break;
mono_set_is_debugger_attached (FALSE);
- MONO_TRY_BLOCKING
+ MONO_TRY_BLOCKING;
mono_mutex_lock (&debugger_thread_exited_mutex);
debugger_thread_exited = TRUE;
mono_cond_signal (&debugger_thread_exited_cond);
mono_mutex_unlock (&debugger_thread_exited_mutex);
- MONO_FINISH_TRY_BLOCKING
+ MONO_FINISH_TRY_BLOCKING;
DEBUG_PRINTF (1, "[dbg] Debugger thread exited.\n");