#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
#endif
-#ifdef HAVE_NETDB_H
-#include <netdb.h>
-#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <process.h>
#endif
#include <ws2tcpip.h>
-#ifdef __GNUC__
-/* cygwin's headers do not seem to define these */
-void WSAAPI freeaddrinfo (struct addrinfo*);
-int WSAAPI getaddrinfo (const char*,const char*,const struct addrinfo*,
- struct addrinfo**);
-int WSAAPI getnameinfo(const struct sockaddr*,socklen_t,char*,DWORD,
- char*,DWORD,int);
-#endif
#endif
#ifdef PLATFORM_ANDROID
#include <mono/utils/mono-stack-unwinding.h>
#include <mono/utils/mono-time.h>
#include <mono/utils/mono-threads.h>
+#include <mono/utils/networking.h>
#include "debugger-agent.h"
#include "mini.h"
#include "seq-points.h"
* event. This is the same as the ctx at step/breakpoint site, but includes changes
* to caller saved registers done by set_var ().
*/
- MonoContext restore_ctx;
+ MonoThreadUnwindState restore_state;
+ /* Frames computed from restore_state */
+ int restore_frame_count;
+ StackFrame **restore_frames;
/* The currently unloading appdomain */
MonoDomain *domain_unloading;
#define HEADER_LENGTH 11
#define MAJOR_VERSION 2
-#define MINOR_VERSION 38
+#define MINOR_VERSION 40
typedef enum {
CMD_SET_VM = 1,
StepFilter filter;
gpointer last_sp;
gpointer start_sp;
+ MonoMethod *start_method;
MonoMethod *last_method;
int last_line;
/* Whenever single stepping is performed using start/stop_single_stepping () */
#define DEBUG(level,s) do { if (G_UNLIKELY ((level) <= log_level)) { s; fflush (log_file); } } while (0)
+#ifdef PLATFORM_ANDROID
+#define DEBUG_PRINTF(level, ...) do { if (G_UNLIKELY ((level) <= log_level)) { g_print (__VA_ARGS__); } } while (0)
+#else
+#define DEBUG_PRINTF(level, ...) do { if (G_UNLIKELY ((level) <= log_level)) { fprintf (log_file, __VA_ARGS__); fflush (log_file); } } while (0)
+#endif
+
#ifdef HOST_WIN32
#define get_last_sock_error() WSAGetLastError()
#define MONO_EWOULDBLOCK WSAEWOULDBLOCK
static void suspend_init (void);
-static void ss_start (SingleStepReq *ss_req, MonoMethod *method, SeqPoint *sp, MonoSeqPointInfo *info, MonoContext *ctx, DebuggerTlsData *tls, gboolean step_to_catch);
-static ErrorCode ss_create (MonoInternalThread *thread, StepSize size, StepDepth depth, EventRequest *req);
+static void ss_start (SingleStepReq *ss_req, MonoMethod *method, SeqPoint *sp, MonoSeqPointInfo *info, MonoContext *ctx, DebuggerTlsData *tls, gboolean step_to_catch,
+ StackFrame **frames, int nframes);
+static ErrorCode ss_create (MonoInternalThread *thread, StepSize size, StepDepth depth, StepFilter filter, EventRequest *req);
static void ss_destroy (SingleStepReq *req);
static void start_debugger_thread (void);
} while ((res > 0 && total < len) || (res == -1 && get_last_sock_error () == MONO_EINTR));
return total;
}
-
-#ifndef TARGET_PS3
-#define HAVE_GETADDRINFO 1
-#endif
static void
set_keepalive (void)
if (conn_fd == -1) {
fprintf (stderr, "debugger-agent: Unable to listen on %d\n", socket_fd);
} else {
- DEBUG (1, fprintf (log_file, "Accepted connection from client, connection fd=%d.\n", conn_fd));
+ DEBUG_PRINTF (1, "Accepted connection from client, connection fd=%d.\n", conn_fd);
}
return conn_fd;
static void
socket_transport_connect (const char *address)
{
-#ifdef HAVE_GETADDRINFO
- struct addrinfo hints;
- struct addrinfo *result, *rp;
-#else
- struct hostent *result;
-#endif
+ MonoAddressInfo *result;
+ MonoAddressEntry *rp;
int sfd = -1, s, res;
- char port_string [128];
char *host;
int port;
listen_fd = -1;
if (host) {
- sprintf (port_string, "%d", port);
mono_network_init ();
/* Obtain address(es) matching host/port */
-#ifdef HAVE_GETADDRINFO
- memset (&hints, 0, sizeof (struct addrinfo));
- hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */
- hints.ai_socktype = SOCK_STREAM; /* Datagram socket */
- hints.ai_flags = 0;
- hints.ai_protocol = 0; /* Any protocol */
-
- s = getaddrinfo (host, port_string, &hints, &result);
+ s = mono_get_address_info (host, port, MONO_HINT_UNSPECIFIED, &result);
if (s != 0) {
- fprintf (stderr, "debugger-agent: Unable to resolve %s:%d: %s\n", host, port, gai_strerror (s));
+ fprintf (stderr, "debugger-agent: Unable to resolve %s:%d: %d\n", host, port, s); // FIXME add portable error conversion functions
exit (1);
}
-#else
- /* The PS3 doesn't even have _r or hstrerror () */
- result = gethostbyname (host);
- if (!result) {
- fprintf (stderr, "debugger-agent: Unable to resolve %s:%d: %d\n", host, port, h_errno);
- }
-#endif
}
if (agent_config.server) {
-#ifdef HAVE_GETADDRINFO
/* Wait for a connection */
if (!host) {
struct sockaddr_in addr;
printf ("%s:%d\n", host, port);
} else {
/* Listen on the provided address */
- for (rp = result; rp != NULL; rp = rp->ai_next) {
+ for (rp = result->entries; rp != NULL; rp = rp->next) {
+ MonoSocketAddress sockaddr;
+ socklen_t sock_len;
int n = 1;
- sfd = socket (rp->ai_family, rp->ai_socktype,
- rp->ai_protocol);
+ mono_socket_address_init (&sockaddr, &sock_len, rp->family, &rp->address, port);
+
+ sfd = socket (rp->family, rp->socktype,
+ rp->protocol);
if (sfd == -1)
continue;
if (setsockopt (sfd, SOL_SOCKET, SO_REUSEADDR, &n, sizeof(n)) == -1)
continue;
- res = bind (sfd, rp->ai_addr, rp->ai_addrlen);
+ res = bind (sfd, &sockaddr.addr, sock_len);
if (res == -1)
continue;
break;
}
-#ifndef HOST_WIN32
- /*
- * this function is not present on win2000 which we still support, and the
- * workaround described here:
- * http://msdn.microsoft.com/en-us/library/ms737931(VS.85).aspx
- * only works with MSVC.
- */
-#ifdef HAVE_GETADDRINFO
- freeaddrinfo (result);
-#endif
-#endif
+ mono_free_address_info (result);
}
if (agent_config.defer)
return;
- DEBUG (1, fprintf (log_file, "Listening on %s:%d (timeout=%d ms)...\n", host, port, agent_config.timeout));
+ DEBUG_PRINTF (1, "Listening on %s:%d (timeout=%d ms)...\n", host, port, agent_config.timeout);
if (agent_config.timeout) {
fd_set readfds;
if (conn_fd == -1)
exit (1);
- DEBUG (1, fprintf (log_file, "Accepted connection from client, socket fd=%d.\n", conn_fd));
-#else
- NOT_IMPLEMENTED;
-#endif /* HAVE_GETADDRINFO */
+ DEBUG_PRINTF (1, "Accepted connection from client, socket fd=%d.\n", conn_fd);
} else {
/* Connect to the specified address */
-#ifdef HAVE_GETADDRINFO
/* FIXME: Respect the timeout */
- for (rp = result; rp != NULL; rp = rp->ai_next) {
- sfd = socket (rp->ai_family, rp->ai_socktype,
- rp->ai_protocol);
+ for (rp = result->entries; rp != NULL; rp = rp->next) {
+ MonoSocketAddress sockaddr;
+ socklen_t sock_len;
+
+ mono_socket_address_init (&sockaddr, &sock_len, rp->family, &rp->address, port);
+
+ sfd = socket (rp->family, rp->socktype,
+ rp->protocol);
if (sfd == -1)
continue;
- if (connect (sfd, rp->ai_addr, rp->ai_addrlen) != -1)
+ if (connect (sfd, &sockaddr.addr, sock_len) != -1)
break; /* Success */
close (sfd);
fprintf (stderr, "debugger-agent: Unable to connect to %s:%d\n", host, port);
exit (1);
}
-#else
- sfd = socket (result->h_addrtype, SOCK_STREAM, 0);
- if (sfd == -1)
- g_assert_not_reached ();
- res = connect (sfd, (void*)result->h_addr_list [0], result->h_length);
- if (res == -1)
- g_assert_not_reached ();
-#endif
conn_fd = sfd;
-#ifndef HOST_WIN32
- /* See the comment above */
-#ifdef HAVE_GETADDRINFO
- freeaddrinfo (result);
-#endif
-#endif
+ mono_free_address_info (result);
}
if (!transport_handshake ())
static DebuggerTransport transports [MAX_TRANSPORTS];
static int ntransports;
-void
+MONO_API void
mono_debugger_agent_register_transport (DebuggerTransport *trans);
void
send_reply_packets (nreply_packets, reply_packets);
for (i = 0; i < nreply_packets; ++i)
buffer_free (reply_packets [i].data);
- DEBUG (1, fprintf (log_file, "[dbg] Sent %d buffered reply packets [at=%lx].\n", nreply_packets, (long)mono_100ns_ticks () / 10000));
+ DEBUG_PRINTF (1, "[dbg] Sent %d buffered reply packets [at=%lx].\n", nreply_packets, (long)mono_100ns_ticks () / 10000);
nreply_packets = 0;
}
dbg_unlock ();
if (res->domain == NULL) {
- DEBUG (0, fprintf (log_file, "ERR_UNLOADED, id=%d, type=%d.\n", id, type));
+ DEBUG_PRINTF (0, "ERR_UNLOADED, id=%d, type=%d.\n", id, type);
*err = ERR_UNLOADED;
return NULL;
}
char *s;
s = mono_type_full_name (&klass->byval_arg);
- DEBUG(2, fprintf (log_file, "[dbg] recv class [%s]\n", s));
+ DEBUG_PRINTF (2, "[dbg] recv class [%s]\n", s);
g_free (s);
}
return klass;
char *s;
s = mono_method_full_name (m, TRUE);
- DEBUG(2, fprintf (log_file, "[dbg] recv method [%s]\n", s));
+ DEBUG_PRINTF (2, "[dbg] recv method [%s]\n", s);
g_free (s);
}
return m;
s = mono_type_full_name (&klass->byval_arg);
if (GetCurrentThreadId () == debugger_thread_id)
- DEBUG(2, fprintf (log_file, "[dbg] send class [%s]\n", s));
+ DEBUG_PRINTF (2, "[dbg] send class [%s]\n", s);
else
- DEBUG(2, fprintf (log_file, "[%p] send class [%s]\n", (gpointer)GetCurrentThreadId (), s));
+ DEBUG_PRINTF (2, "[%p] send class [%s]\n", (gpointer)GetCurrentThreadId (), s);
g_free (s);
}
}
char *s;
s = mono_method_full_name (method, 1);
- DEBUG(2, fprintf (log_file, "[dbg] send method [%s]\n", s));
+ DEBUG_PRINTF (2, "[dbg] send method [%s]\n", s);
g_free (s);
}
}
id = buffer_add_ptr_id (buf, domain, ID_ASSEMBLY, assembly);
if (G_UNLIKELY (log_level >= 2) && assembly)
- DEBUG(2, fprintf (log_file, "[dbg] send assembly [%s][%s][%d]\n", assembly->aname.name, domain->friendly_name, id));
+ DEBUG_PRINTF (2, "[dbg] send assembly [%s][%s][%d]\n", assembly->aname.name, domain->friendly_name, id);
}
static inline void
if (sigctx)
ip = mono_arch_ip_from_context (sigctx);
else if (info)
- ip = MONO_CONTEXT_GET_IP (&info->suspend_state.ctx);
+ ip = MONO_CONTEXT_GET_IP (&mono_thread_info_get_suspend_state (info)->ctx);
else
ip = NULL;
if (ji) {
/* Running managed code, will be suspended by the single step code */
- DEBUG (1, fprintf (log_file, "[%p] Received interrupt while at %s(%p), continuing.\n", (gpointer)(gsize)tid, jinfo_get_method (ji)->name, ip));
+ DEBUG_PRINTF (1, "[%p] Received interrupt while at %s(%p), continuing.\n", (gpointer)(gsize)tid, jinfo_get_method (ji)->name, ip);
return TRUE;
} else {
/*
// FIXME: printf is not signal safe, but this is only used during
// debugger debugging
if (ip)
- DEBUG (1, fprintf (log_file, "[%p] Received interrupt while at %p, treating as suspended.\n", (gpointer)(gsize)tid, ip));
+ DEBUG_PRINTF (1, "[%p] Received interrupt while at %p, treating as suspended.\n", (gpointer)(gsize)tid, ip);
//save_thread_context (&ctx);
if (!tls->thread)
*/
mono_walk_stack_with_ctx (get_last_frame, &ctx, MONO_UNWIND_NONE, &data);
} else if (info) {
- mono_get_eh_callbacks ()->mono_walk_stack_with_state (get_last_frame, &info->suspend_state, MONO_UNWIND_SIGNAL_SAFE, &data);
+ mono_get_eh_callbacks ()->mono_walk_stack_with_state (get_last_frame, mono_thread_info_get_suspend_state (info), MONO_UNWIND_SIGNAL_SAFE, &data);
}
if (data.last_frame_set) {
memcpy (&tls->async_last_frame, &data.last_frame, sizeof (StackFrameInfo));
tls = mono_native_tls_get_value (debugger_tls_id);
if (!tls) {
- DEBUG (1, fprintf (log_file, "[%p] Received interrupt with no TLS, continuing.\n", (gpointer)GetCurrentThreadId ()));
+ DEBUG_PRINTF (1, "[%p] Received interrupt with no TLS, continuing.\n", (gpointer)GetCurrentThreadId ());
return FALSE;
}
}
}
+typedef struct {
+ DebuggerTlsData *tls;
+ gboolean valid_info;
+} InterruptData;
+
+static SuspendThreadResult
+debugger_interrupt_critical (MonoThreadInfo *info, gpointer user_data)
+{
+ InterruptData *data = user_data;
+ 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));
+
+ thread_interrupt (data->tls, info, NULL, ji);
+ return MonoResumeThread;
+}
+
/*
* notify_thread:
*
if (GetCurrentThreadId () == tid || tls->terminated)
return;
- DEBUG(1, fprintf (log_file, "[%p] Interrupting %p...\n", (gpointer)GetCurrentThreadId (), (gpointer)tid));
+ DEBUG_PRINTF (1, "[%p] Interrupting %p...\n", (gpointer)GetCurrentThreadId (), (gpointer)tid);
/*
* OSX can (and will) coalesce signals, so sending multiple pthread_kills does not
/* This is _not_ equivalent to ves_icall_System_Threading_Thread_Abort () */
if (mono_thread_info_new_interrupt_enabled ()) {
- MonoThreadInfo *info;
- MonoJitInfo *ji;
+ InterruptData interrupt_data = { 0 };
+ interrupt_data.tls = tls;
- info = mono_thread_info_safe_suspend_sync ((MonoNativeThreadId)(gpointer)(gsize)thread->tid, FALSE);
- if (!info) {
- DEBUG(1, fprintf (log_file, "[%p] mono_thread_info_suspend_sync () failed for %p...\n", (gpointer)GetCurrentThreadId (), (gpointer)tid));
+ mono_thread_info_safe_suspend_and_run ((MonoNativeThreadId)(gpointer)(gsize)thread->tid, FALSE, debugger_interrupt_critical, &interrupt_data);
+ if (!interrupt_data.valid_info) {
+ DEBUG_PRINTF (1, "[%p] mono_thread_info_suspend_sync () failed for %p...\n", (gpointer)GetCurrentThreadId (), (gpointer)tid);
/*
* Attached thread which died without detaching.
*/
tls->terminated = TRUE;
- } else {
- ji = mono_jit_info_table_find (info->suspend_state.unwind_data [MONO_UNWIND_DATA_DOMAIN], MONO_CONTEXT_GET_IP (&info->suspend_state.ctx));
-
- thread_interrupt (tls, info, NULL, ji);
-
- mono_thread_info_finish_suspend_and_resume (info);
}
} else {
#ifdef HOST_WIN32
#else
res = mono_thread_kill (thread, mono_thread_get_abort_signal ());
if (res) {
- DEBUG(1, fprintf (log_file, "[%p] mono_thread_kill () failed for %p: %d...\n", (gpointer)GetCurrentThreadId (), (gpointer)tid, res));
+ DEBUG_PRINTF (1, "[%p] mono_thread_kill () failed for %p: %d...\n", (gpointer)GetCurrentThreadId (), (gpointer)tid, res);
/*
* Attached thread which died without detaching.
*/
if (suspend_count - tls->resume_count > 0)
tls->suspending = TRUE;
- DEBUG(1, fprintf (log_file, "[%p] Received single step event for suspending.\n", (gpointer)GetCurrentThreadId ()));
+ DEBUG_PRINTF (1, "[%p] Received single step event for suspending.\n", (gpointer)GetCurrentThreadId ());
if (suspend_count - tls->resume_count == 0) {
/*
* suspending is still active.
* FIXME: This slows down single threaded invokes.
*/
- DEBUG(1, fprintf (log_file, "[%p] Ignored during single threaded invoke.\n", (gpointer)GetCurrentThreadId ()));
+ DEBUG_PRINTF (1, "[%p] Ignored during single threaded invoke.\n", (gpointer)GetCurrentThreadId ());
return;
}
suspend_count ++;
- DEBUG(1, fprintf (log_file, "[%p] Suspending vm...\n", (gpointer)GetCurrentThreadId ()));
+ DEBUG_PRINTF (1, "[%p] Suspending vm...\n", (gpointer)GetCurrentThreadId ());
if (suspend_count == 1) {
// FIXME: Is it safe to call this inside the lock ?
g_assert (suspend_count > 0);
suspend_count --;
- DEBUG(1, fprintf (log_file, "[%p] Resuming vm, suspend count=%d...\n", (gpointer)GetCurrentThreadId (), suspend_count));
+ DEBUG_PRINTF (1, "[%p] Resuming vm, suspend count=%d...\n", (gpointer)GetCurrentThreadId (), suspend_count);
if (suspend_count == 0) {
// FIXME: Is it safe to call this inside the lock ?
g_assert (suspend_count > 0);
- DEBUG(1, fprintf (log_file, "[sdb] Resuming thread %p...\n", (gpointer)(gssize)thread->tid));
+ DEBUG_PRINTF (1, "[sdb] Resuming thread %p...\n", (gpointer)(gssize)thread->tid);
tls->resume_count += suspend_count;
}
static void
-invalidate_frames (DebuggerTlsData *tls)
+free_frames (StackFrame **frames, int nframes)
{
int i;
+ for (i = 0; i < nframes; ++i) {
+ if (frames [i]->jit)
+ mono_debug_free_method_jit_info (frames [i]->jit);
+ g_free (frames [i]);
+ }
+ g_free (frames);
+}
+
+static void
+invalidate_frames (DebuggerTlsData *tls)
+{
if (!tls)
tls = mono_native_tls_get_value (debugger_tls_id);
g_assert (tls);
- for (i = 0; i < tls->frame_count; ++i) {
- if (tls->frames [i]->jit)
- mono_debug_free_method_jit_info (tls->frames [i]->jit);
- g_free (tls->frames [i]);
- }
- g_free (tls->frames);
+ free_frames (tls->frames, tls->frame_count);
tls->frame_count = 0;
tls->frames = NULL;
+
+ free_frames (tls->restore_frames, tls->restore_frame_count);
+ tls->restore_frame_count = 0;
+ tls->restore_frames = NULL;
}
/*
MONO_SEM_POST (&suspend_sem);
}
- DEBUG(1, fprintf (log_file, "[%p] Suspended.\n", (gpointer)GetCurrentThreadId ()));
+ DEBUG_PRINTF (1, "[%p] Suspended.\n", (gpointer)GetCurrentThreadId ());
while (suspend_count - tls->resume_count > 0) {
#ifdef HOST_WIN32
mono_mutex_unlock (&suspend_mutex);
- DEBUG(1, fprintf (log_file, "[%p] Resumed.\n", (gpointer)GetCurrentThreadId ()));
+ DEBUG_PRINTF (1, "[%p] Resumed.\n", (gpointer)GetCurrentThreadId ());
if (tls->pending_invoke) {
/* Save the original context */
while (TRUE) {
nwait = count_threads_to_wait_for ();
if (nwait) {
- DEBUG(1, fprintf (log_file, "Waiting for %d(%d) threads to suspend...\n", nwait, nthreads));
+ DEBUG_PRINTF (1, "Waiting for %d(%d) threads to suspend...\n", nwait, nthreads);
err = MONO_SEM_WAIT (&suspend_sem);
g_assert (err == 0);
waited = TRUE;
}
if (waited)
- DEBUG(1, fprintf (log_file, "%d threads suspended.\n", nthreads));
+ DEBUG_PRINTF (1, "%d threads suspended.\n", nthreads);
}
/*
info->il_offset = mono_debug_il_offset_from_address (method, info->domain, info->native_offset);
}
- DEBUG (1, fprintf (log_file, "\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:%x(%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))
return process_frame (info, ctx, user_data);
}
+/*
+ * Return a malloc-ed list of StackFrame structures.
+ */
+static StackFrame**
+compute_frame_info_from (MonoInternalThread *thread, DebuggerTlsData *tls, MonoThreadUnwindState *state, int *out_nframes)
+{
+ ComputeFramesUserData user_data;
+ MonoUnwindOptions opts = MONO_UNWIND_DEFAULT|MONO_UNWIND_REG_LOCATIONS;
+ StackFrame **res;
+ int i, nframes;
+ GSList *l;
+
+ user_data.tls = tls;
+ user_data.frames = NULL;
+
+ mono_walk_stack_with_state (process_frame, state, opts, &user_data);
+
+ nframes = g_slist_length (user_data.frames);
+ res = g_new0 (StackFrame*, nframes);
+ l = user_data.frames;
+ for (i = 0; i < nframes; ++i) {
+ res [i] = l->data;
+ l = l->next;
+ }
+ *out_nframes = nframes;
+
+ return res;
+}
+
static void
compute_frame_info (MonoInternalThread *thread, DebuggerTlsData *tls)
{
if (tls->frames && tls->frames_up_to_date)
return;
- DEBUG(1, fprintf (log_file, "Frames for %p(tid=%lx):\n", thread, (glong)thread->tid));
+ DEBUG_PRINTF (1, "Frames for %p(tid=%lx):\n", thread, (glong)thread->tid);
user_data.tls = tls;
user_data.frames = NULL;
return s2;
}
+/*
+ * Same as g_path_get_basename () but handles windows paths as well,
+ * which can occur in .mdb files created by pdb2mdb.
+ */
+static char*
+dbg_path_get_basename (const char *filename)
+{
+ char *r;
+
+ if (!filename || strchr (filename, '/') || !strchr (filename, '\\'))
+ return g_path_get_basename (filename);
+
+ /* From gpath.c */
+
+ /* No separator -> filename */
+ r = strrchr (filename, '\\');
+ if (r == NULL)
+ return g_strdup (filename);
+
+ /* Trailing slash, remove component */
+ if (r [1] == 0){
+ char *copy = g_strdup (filename);
+ copy [r-filename] = 0;
+ r = strrchr (copy, '\\');
+
+ if (r == NULL){
+ g_free (copy);
+ return g_strdup ("/");
+ }
+ r = g_strdup (&r[1]);
+ g_free (copy);
+ return r;
+ }
+
+ return g_strdup (&r[1]);
+}
+
+static void
+init_jit_info_dbg_attrs (MonoJitInfo *ji)
+{
+ static MonoClass *hidden_klass, *step_through_klass, *non_user_klass;
+ MonoCustomAttrInfo *ainfo;
+
+ if (ji->dbg_attrs_inited)
+ return;
+
+ if (!hidden_klass) {
+ hidden_klass = mono_class_from_name (mono_defaults.corlib, "System.Diagnostics", "DebuggerHiddenAttribute");
+ g_assert (hidden_klass);
+ }
+ if (!step_through_klass) {
+ step_through_klass = mono_class_from_name (mono_defaults.corlib, "System.Diagnostics", "DebuggerStepThroughAttribute");
+ g_assert (step_through_klass);
+ }
+ if (!non_user_klass) {
+ non_user_klass = mono_class_from_name (mono_defaults.corlib, "System.Diagnostics", "DebuggerNonUserCodeAttribute");
+ g_assert (non_user_klass);
+ }
+
+ ainfo = mono_custom_attrs_from_method (jinfo_get_method (ji));
+ if (ainfo) {
+ if (mono_custom_attrs_has_attr (ainfo, hidden_klass))
+ ji->dbg_hidden = TRUE;
+ if (mono_custom_attrs_has_attr (ainfo, step_through_klass))
+ ji->dbg_step_through = TRUE;
+ if (mono_custom_attrs_has_attr (ainfo, non_user_klass))
+ ji->dbg_non_user_code = TRUE;
+ mono_custom_attrs_free (ainfo);
+ }
+
+ ainfo = mono_custom_attrs_from_class (jinfo_get_method (ji)->klass);
+ if (ainfo) {
+ if (mono_custom_attrs_has_attr (ainfo, step_through_klass))
+ ji->dbg_step_through = TRUE;
+ if (mono_custom_attrs_has_attr (ainfo, non_user_klass))
+ ji->dbg_non_user_code = TRUE;
+ mono_custom_attrs_free (ainfo);
+ }
+
+ mono_memory_barrier ();
+ ji->dbg_attrs_inited = TRUE;
+}
+
/*
* EVENT HANDLING
*/
if (g_hash_table_lookup (mod->data.source_files, s))
found = TRUE;
else {
- char *s2 = g_path_get_basename (sinfo->source_file);
+ char *s2 = dbg_path_get_basename (sinfo->source_file);
char *s3 = strdup_tolower (s2);
if (g_hash_table_lookup (mod->data.source_files, s3))
} else if (mod->kind == MOD_KIND_STEP) {
if ((mod->data.filter & STEP_FILTER_STATIC_CTOR) && ji &&
(jinfo_get_method (ji)->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) &&
- !strcmp (jinfo_get_method (ji)->name, ".cctor"))
+ !strcmp (jinfo_get_method (ji)->name, ".cctor") &&
+ (jinfo_get_method (ji) != ((SingleStepReq*)req->info)->start_method))
filtered = TRUE;
if ((mod->data.filter & STEP_FILTER_DEBUGGER_HIDDEN) && ji) {
- MonoCustomAttrInfo *ainfo;
- static MonoClass *klass;
-
- if (!klass) {
- klass = mono_class_from_name (mono_defaults.corlib, "System.Diagnostics", "DebuggerHiddenAttribute");
- g_assert (klass);
- }
- if (!ji->dbg_hidden_inited) {
- ainfo = mono_custom_attrs_from_method (jinfo_get_method (ji));
- if (ainfo) {
- if (mono_custom_attrs_has_attr (ainfo, klass))
- ji->dbg_hidden = TRUE;
- mono_custom_attrs_free (ainfo);
- }
- ji->dbg_hidden_inited = TRUE;
- }
+ init_jit_info_dbg_attrs (ji);
if (ji->dbg_hidden)
filtered = TRUE;
}
if ((mod->data.filter & STEP_FILTER_DEBUGGER_STEP_THROUGH) && ji) {
- MonoCustomAttrInfo *ainfo;
- static MonoClass *klass;
-
- if (!klass) {
- klass = mono_class_from_name (mono_defaults.corlib, "System.Diagnostics", "DebuggerStepThroughAttribute");
- g_assert (klass);
- }
- if (!ji->dbg_step_through_inited) {
- ainfo = mono_custom_attrs_from_method (jinfo_get_method (ji));
- if (ainfo) {
- if (mono_custom_attrs_has_attr (ainfo, klass))
- ji->dbg_step_through = TRUE;
- mono_custom_attrs_free (ainfo);
- }
- ainfo = mono_custom_attrs_from_class (jinfo_get_method (ji)->klass);
- if (ainfo) {
- if (mono_custom_attrs_has_attr (ainfo, klass))
- ji->dbg_step_through = TRUE;
- mono_custom_attrs_free (ainfo);
- }
- ji->dbg_step_through_inited = TRUE;
- }
+ init_jit_info_dbg_attrs (ji);
if (ji->dbg_step_through)
filtered = TRUE;
}
if ((mod->data.filter & STEP_FILTER_DEBUGGER_NON_USER_CODE) && ji) {
- MonoCustomAttrInfo *ainfo;
- static MonoClass *klass;
-
- if (!klass) {
- klass = mono_class_from_name (mono_defaults.corlib, "System.Diagnostics", "DebuggerNonUserCodeAttribute");
- g_assert (klass);
- }
- if (!ji->dbg_non_user_code_inited) {
- ainfo = mono_custom_attrs_from_method (jinfo_get_method (ji));
- if (ainfo) {
- if (mono_custom_attrs_has_attr (ainfo, klass))
- ji->dbg_non_user_code = TRUE;
- mono_custom_attrs_free (ainfo);
- }
- ainfo = mono_custom_attrs_from_class (jinfo_get_method (ji)->klass);
- if (ainfo) {
- if (mono_custom_attrs_has_attr (ainfo, klass))
- ji->dbg_non_user_code = TRUE;
- mono_custom_attrs_free (ainfo);
- }
- ji->dbg_non_user_code_inited = TRUE;
- }
+ init_jit_info_dbg_attrs (ji);
if (ji->dbg_non_user_code)
filtered = TRUE;
}
int nevents;
if (!inited) {
- DEBUG (2, fprintf (log_file, "Debugger agent not initialized yet: dropping %s\n", event_to_string (event)));
+ DEBUG_PRINTF (2, "Debugger agent not initialized yet: dropping %s\n", event_to_string (event));
return;
}
if (!vm_start_event_sent && event != EVENT_KIND_VM_START) {
// FIXME: We miss those events
- DEBUG (2, fprintf (log_file, "VM start event not sent yet: dropping %s\n", event_to_string (event)));
+ DEBUG_PRINTF (2, "VM start event not sent yet: dropping %s\n", event_to_string (event));
return;
}
if (vm_death_event_sent) {
- DEBUG (2, fprintf (log_file, "VM death event has been sent: dropping %s\n", event_to_string (event)));
+ DEBUG_PRINTF (2, "VM death event has been sent: dropping %s\n", event_to_string (event));
return;
}
if (mono_runtime_is_shutting_down () && event != EVENT_KIND_VM_DEATH) {
- DEBUG (2, fprintf (log_file, "Mono runtime is shutting down: dropping %s\n", event_to_string (event)));
+ DEBUG_PRINTF (2, "Mono runtime is shutting down: dropping %s\n", event_to_string (event));
return;
}
if (disconnected) {
- DEBUG (2, fprintf (log_file, "Debugger client is not connected: dropping %s\n", event_to_string (event)));
+ DEBUG_PRINTF (2, "Debugger client is not connected: dropping %s\n", event_to_string (event));
return;
}
events = NULL;
if (!send_success) {
- DEBUG (2, fprintf (log_file, "Sending command %s failed.\n", event_to_string (event)));
+ DEBUG_PRINTF (2, "Sending command %s failed.\n", event_to_string (event));
return;
}
vm_start_event_sent = TRUE;
}
- DEBUG (1, fprintf (log_file, "[%p] Sent %d events %s(%d), suspend=%d.\n", (gpointer)GetCurrentThreadId (), nevents, event_to_string (event), ecount, suspend_policy));
+ DEBUG_PRINTF (1, "[%p] Sent %d events %s(%d), suspend=%d.\n", (gpointer)GetCurrentThreadId (), nevents, event_to_string (event), ecount, suspend_policy);
switch (suspend_policy) {
case SUSPEND_POLICY_NONE:
* For some reason, thread_startup () might be called for the same thread
* multiple times (attach ?).
*/
- DEBUG (1, fprintf (log_file, "[%p] thread_start () called multiple times for %p, ignored.\n", (gpointer)tid, (gpointer)tid));
+ DEBUG_PRINTF (1, "[%p] thread_start () called multiple times for %p, ignored.\n", (gpointer)tid, (gpointer)tid);
return;
} else {
/*
* thread_end () might not be called for some threads, and the tid could
* get reused.
*/
- DEBUG (1, fprintf (log_file, "[%p] Removing stale data for tid %p.\n", (gpointer)tid, (gpointer)tid));
+ DEBUG_PRINTF (1, "[%p] Removing stale data for tid %p.\n", (gpointer)tid, (gpointer)tid);
mono_loader_lock ();
mono_g_hash_table_remove (thread_to_tls, old_thread);
mono_g_hash_table_remove (tid_to_thread, (gpointer)tid);
tls->thread = thread;
mono_native_tls_set_value (debugger_tls_id, tls);
- DEBUG (1, fprintf (log_file, "[%p] Thread started, obj=%p, tls=%p.\n", (gpointer)tid, thread, tls));
+ DEBUG_PRINTF (1, "[%p] Thread started, obj=%p, tls=%p.\n", (gpointer)tid, thread, tls);
mono_loader_lock ();
mono_g_hash_table_insert (thread_to_tls, thread, tls);
/* We might be called for threads started before we registered the start callback */
if (thread) {
- DEBUG (1, fprintf (log_file, "[%p] Thread terminated, obj=%p, tls=%p.\n", (gpointer)tid, thread, tls));
+ DEBUG_PRINTF (1, "[%p] Thread terminated, obj=%p, tls=%p.\n", (gpointer)tid, thread, tls);
+
+ if (GetCurrentThreadId () == tid && !mono_native_tls_get_value (debugger_tls_id)) {
+ /*
+ * This can happen on darwin since we deregister threads using pthread dtors.
+ * process_profiler_event () and the code it calls cannot handle a null TLS value.
+ */
+ return;
+ }
+
process_profiler_event (EVENT_KIND_THREAD_DEATH, thread);
}
}
seq_point_iterator_init (&it, seq_points);
while (seq_point_iterator_next (&it))
- DEBUG (1, fprintf (log_file, "%d\n", it.seq_point.il_offset));
+ DEBUG_PRINTF (1, "%d\n", it.seq_point.il_offset);
if (error) {
mono_error_set_error (error, MONO_ERROR_GENERIC, "%s", s);
dbg_unlock ();
if (it.seq_point.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));
+ DEBUG_PRINTF (1, "[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);
#endif
}
- DEBUG(1, fprintf (log_file, "[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:0x%x [%p](%d).\n", mono_method_full_name (jinfo_get_method (ji), TRUE), (int)it.seq_point.il_offset, inst->ip, count);
}
static void
if (count == 1 && inst->native_offset != SEQ_POINT_NATIVE_OFFSET_DEAD_CODE) {
mono_arch_clear_breakpoint (ji, ip);
- DEBUG(1, fprintf (log_file, "[dbg] Clear breakpoint at %s [%p].\n", mono_method_full_name (jinfo_get_method (ji), TRUE), ip));
+ DEBUG_PRINTF (1, "[dbg] Clear breakpoint at %s [%p].\n", mono_method_full_name (jinfo_get_method (ji), TRUE), ip);
}
#else
NOT_IMPLEMENTED;
bp->req = req;
bp->children = g_ptr_array_new ();
- DEBUG(1, fprintf (log_file, "[dbg] Setting %sbreakpoint at %s:0x%x.\n", (req->event_kind == EVENT_KIND_STEP) ? "single step " : "", method ? mono_method_full_name (method, TRUE) : "<all>", (int)il_offset));
+ DEBUG_PRINTF (1, "[dbg] Setting %sbreakpoint at %s:0x%x.\n", (req->event_kind == EVENT_KIND_STEP) ? "single step " : "", method ? mono_method_full_name (method, TRUE) : "<all>", (int)il_offset);
mono_loader_lock ();
/*
* These seq points are inserted by the JIT after calls, step over needs to skip them.
*/
- DEBUG (1, fprintf (log_file, "[%p] Seq point at nonempty stack %x while stepping over, continuing single stepping.\n", (gpointer)GetCurrentThreadId (), sp->il_offset));
+ DEBUG_PRINTF (1, "[%p] Seq point at nonempty stack %x while stepping over, continuing single stepping.\n", (gpointer)GetCurrentThreadId (), sp->il_offset);
return FALSE;
}
compute_frame_info (tls->thread, tls);
if (req->nframes && tls->frame_count && tls->frame_count > req->nframes) {
/* Hit the breakpoint in a recursive call */
- DEBUG (1, fprintf (log_file, "[%p] Breakpoint at lower frame while stepping over, continuing single stepping.\n", (gpointer)GetCurrentThreadId ()));
+ DEBUG_PRINTF (1, "[%p] Breakpoint at lower frame while stepping over, continuing single stepping.\n", (gpointer)GetCurrentThreadId ());
+ return FALSE;
+ }
+ }
+
+ if (req->depth == STEP_DEPTH_INTO && req->size == STEP_SIZE_MIN && (sp->flags & MONO_SEQ_POINT_FLAG_NONEMPTY_STACK) && ss_req->start_method){
+ method = jinfo_get_method (ji);
+ if (!tls->context.valid)
+ mono_thread_state_init_from_monoctx (&tls->context, ctx);
+ compute_frame_info (tls->thread, tls);
+ if (ss_req->start_method == method && req->nframes && tls->frame_count == req->nframes) {//Check also frame count(could be recursion)
+ DEBUG_PRINTF (1, "[%p] Seq point at nonempty stack %x while stepping in, continuing single stepping.\n", (gpointer)GetCurrentThreadId (), sp->il_offset);
return FALSE;
}
}
if (minfo)
loc = mono_debug_symfile_lookup_location (minfo, sp->il_offset);
- if (!loc || (loc && method == ss_req->last_method && loc->row == ss_req->last_line)) {
- /* Have to continue single stepping */
- if (!loc)
- DEBUG(1, fprintf (log_file, "[%p] No line number info for il offset %x, continuing single stepping.\n", (gpointer)GetCurrentThreadId (), sp->il_offset));
- else
- DEBUG(1, fprintf (log_file, "[%p] Same source line (%d), continuing single stepping.\n", (gpointer)GetCurrentThreadId (), loc->row));
+ if (!loc) {
+ DEBUG_PRINTF (1, "[%p] No line number info for il offset %x, continuing single stepping.\n", (gpointer)GetCurrentThreadId (), sp->il_offset);
+ ss_req->last_method = method;
+ hit = FALSE;
+ } else if (loc && method == ss_req->last_method && loc->row == ss_req->last_line) {
+ DEBUG_PRINTF (1, "[%p] Same source line (%d), continuing single stepping.\n", (gpointer)GetCurrentThreadId (), loc->row);
hit = FALSE;
}
GPtrArray *bp_reqs, *ss_reqs_orig, *ss_reqs;
GSList *bp_events = NULL, *ss_events = NULL, *enter_leave_events = NULL;
EventKind kind = EVENT_KIND_BREAKPOINT;
- MonoContext *ctx = &tls->restore_ctx;
+ MonoContext *ctx = &tls->restore_state.ctx;
MonoMethod *method;
MonoSeqPointInfo *info;
SeqPoint sp;
g_assert (found_sp);
- DEBUG(1, fprintf (log_file, "[%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, offset=0x%x, sp il offset=0x%x.\n", (gpointer)GetCurrentThreadId (), method->name, ip, native_offset, sp.il_offset);
bp = NULL;
for (i = 0; i < breakpoints->len; ++i) {
g_ptr_array_add (ss_reqs, req);
/* Start single stepping again from the current sequence point */
- ss_start (ss_req, method, &sp, info, ctx, tls, FALSE);
+ ss_start (ss_req, method, &sp, info, ctx, tls, FALSE, NULL, 0);
}
if (ss_reqs->len > 0)
process_signal_event (void (*func) (DebuggerTlsData*))
{
DebuggerTlsData *tls;
- MonoContext orig_restore_ctx, ctx;
+ MonoThreadUnwindState orig_restore_state;
+ MonoContext ctx;
tls = mono_native_tls_get_value (debugger_tls_id);
/* Have to save/restore the restore_ctx as we can be called recursively during invokes etc. */
- memcpy (&orig_restore_ctx, &tls->restore_ctx, sizeof (MonoContext));
- memcpy (&tls->restore_ctx, &tls->handler_ctx, sizeof (MonoContext));
+ memcpy (&orig_restore_state, &tls->restore_state, sizeof (MonoThreadUnwindState));
+ mono_thread_state_init_from_monoctx (&tls->restore_state, &tls->handler_ctx);
func (tls);
/* This is called when resuming from a signal handler, so it shouldn't return */
- memcpy (&ctx, &tls->restore_ctx, sizeof (MonoContext));
- memcpy (&tls->restore_ctx, &orig_restore_ctx, sizeof (MonoContext));
+ memcpy (&ctx, &tls->restore_state.ctx, sizeof (MonoContext));
+ memcpy (&tls->restore_state, &orig_restore_state, sizeof (MonoThreadUnwindState));
mono_restore_context (&ctx);
g_assert_not_reached ();
}
int il_offset, suspend_policy;
MonoDomain *domain;
GSList *events;
- MonoContext *ctx = &tls->restore_ctx;
+ MonoContext *ctx = &tls->restore_state.ctx;
MonoMethod *method;
SeqPoint sp;
MonoSeqPointInfo *info;
if (log_level > 0) {
ji = mini_jit_info_table_find (mono_domain_get (), (char*)ip, &domain);
- DEBUG (1, fprintf (log_file, "[%p] Single step event (depth=%s) at %s (%p), sp %p, last sp %p\n", (gpointer)GetCurrentThreadId (), ss_depth_to_string (ss_req->depth), mono_method_full_name (jinfo_get_method (ji), TRUE), MONO_CONTEXT_GET_IP (ctx), MONO_CONTEXT_GET_SP (ctx), ss_req->last_sp));
+ DEBUG_PRINTF (1, "[%p] Single step event (depth=%s) at %s (%p)[0x%x], sp %p, last sp %p\n", (gpointer)GetCurrentThreadId (), ss_depth_to_string (ss_req->depth), mono_method_full_name (jinfo_get_method (ji), TRUE), MONO_CONTEXT_GET_IP (ctx), (int)((guint8*)MONO_CONTEXT_GET_IP (ctx) - (guint8*)ji->code_start), MONO_CONTEXT_GET_SP (ctx), ss_req->last_sp);
}
ji = mini_jit_info_table_find (mono_domain_get (), (char*)ip, &domain);
return;
/* Start single stepping again from the current sequence point */
- ss_start (ss_req, method, &sp, info, ctx, tls, FALSE);
+ ss_start (ss_req, method, &sp, info, ctx, tls, FALSE, NULL, 0);
if ((ss_req->filter & STEP_FILTER_STATIC_CTOR) &&
(method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) &&
debugger_agent_single_step_from_context (MonoContext *ctx)
{
DebuggerTlsData *tls;
- MonoContext orig_restore_ctx;
+ MonoThreadUnwindState orig_restore_state;
tls = mono_native_tls_get_value (debugger_tls_id);
g_assert (tls);
/* Have to save/restore the restore_ctx as we can be called recursively during invokes etc. */
- memcpy (&orig_restore_ctx, &tls->restore_ctx, sizeof (MonoContext));
- memcpy (&tls->restore_ctx, ctx, sizeof (MonoContext));
+ memcpy (&orig_restore_state, &tls->restore_state, sizeof (MonoThreadUnwindState));
+ mono_thread_state_init_from_monoctx (&tls->restore_state, ctx);
process_single_step_inner (tls);
- memcpy (ctx, &tls->restore_ctx, sizeof (MonoContext));
- memcpy (&tls->restore_ctx, &orig_restore_ctx, sizeof (MonoContext));
+ memcpy (ctx, &tls->restore_state.ctx, sizeof (MonoContext));
+ memcpy (&tls->restore_state, &orig_restore_state, sizeof (MonoThreadUnwindState));
}
void
debugger_agent_breakpoint_from_context (MonoContext *ctx)
{
DebuggerTlsData *tls;
- MonoContext orig_restore_ctx;
+ MonoThreadUnwindState orig_restore_state;
tls = mono_native_tls_get_value (debugger_tls_id);
g_assert (tls);
- memcpy (&orig_restore_ctx, &tls->restore_ctx, sizeof (MonoContext));
- memcpy (&tls->restore_ctx, ctx, sizeof (MonoContext));
+ memcpy (&orig_restore_state, &tls->restore_state, sizeof (MonoContext));
+ mono_thread_state_init_from_monoctx (&tls->restore_state, ctx);
process_breakpoint_inner (tls);
- memcpy (ctx, &tls->restore_ctx, sizeof (MonoContext));
- memcpy (&tls->restore_ctx, &orig_restore_ctx, sizeof (MonoContext));
+ memcpy (ctx, &tls->restore_state.ctx, sizeof (MonoContext));
+ memcpy (&tls->restore_state, &orig_restore_state, sizeof (MonoThreadUnwindState));
}
/*
* Start the single stepping operation given by SS_REQ from the sequence point SP.
* If CTX is not set, then this can target any thread. If CTX is set, then TLS should
* belong to the same thread as CTX.
+ * If FRAMES is not-null, use that instead of tls->frames for placing breakpoints etc.
*/
static void
-ss_start (SingleStepReq *ss_req, MonoMethod *method, SeqPoint* sp, MonoSeqPointInfo *info, MonoContext *ctx, DebuggerTlsData *tls, gboolean step_to_catch)
+ss_start (SingleStepReq *ss_req, MonoMethod *method, SeqPoint* sp, MonoSeqPointInfo *info, MonoContext *ctx, DebuggerTlsData *tls,
+ gboolean step_to_catch, StackFrame **frames, int nframes)
{
int i, j, frame_index;
- SeqPoint *next_sp;
- SeqPoint local_sp;
+ SeqPoint *next_sp, *parent_sp = NULL;
+ SeqPoint local_sp, local_parent_sp;
gboolean found_sp;
MonoBreakpoint *bp;
+ MonoSeqPointInfo *parent_info;
+ MonoMethod *parent_sp_method = NULL;
gboolean enable_global = FALSE;
/* Stop the previous operation */
} else {
frame_index = 1;
- if ((!sp || sp->next_len == 0 || ss_req->depth == STEP_DEPTH_OUT || ss_req->depth == STEP_DEPTH_OVER) && ctx) {
+ if (ctx && !frames) {
/* Need parent frames */
if (!tls->context.valid)
mono_thread_state_init_from_monoctx (&tls->context, ctx);
compute_frame_info (tls->thread, tls);
+ frames = tls->frames;
+ nframes = tls->frame_count;
}
/*
*/
if (ss_req->depth == STEP_DEPTH_OUT) {
/* Ignore seq points in current method */
- while (frame_index < tls->frame_count) {
- StackFrame *frame = tls->frames [frame_index];
+ while (frame_index < nframes) {
+ StackFrame *frame = frames [frame_index];
method = frame->method;
found_sp = find_prev_seq_point_for_native_offset (frame->domain, frame->method, frame->native_offset, &info, &local_sp);
} else {
if (sp && sp->next_len == 0) {
sp = NULL;
- while (frame_index < tls->frame_count) {
- StackFrame *frame = tls->frames [frame_index];
+ while (frame_index < nframes) {
+ StackFrame *frame = frames [frame_index];
method = frame->method;
found_sp = find_prev_seq_point_for_native_offset (frame->domain, frame->method, frame->native_offset, &info, &local_sp);
sp = NULL;
frame_index ++;
}
+ } else {
+ /* Have to put a breakpoint into a parent frame since the seq points might not cover all control flow out of the method */
+ while (frame_index < nframes) {
+ StackFrame *frame = frames [frame_index];
+
+ parent_sp_method = frame->method;
+ found_sp = find_prev_seq_point_for_native_offset (frame->domain, frame->method, frame->native_offset, &parent_info, &local_parent_sp);
+ parent_sp = found_sp ? &local_parent_sp : NULL;
+ if (found_sp && parent_sp->next_len != 0)
+ break;
+ parent_sp = NULL;
+ frame_index ++;
+ }
}
}
g_free (next);
}
+ if (parent_sp) {
+ SeqPoint* next = g_new(SeqPoint, parent_sp->next_len);
+
+ seq_point_init_next (parent_info, *parent_sp, next);
+ for (i = 0; i < parent_sp->next_len; i++) {
+ next_sp = &next[i];
+
+ bp = set_breakpoint (parent_sp_method, next_sp->il_offset, ss_req->req, NULL);
+ ss_req->bps = g_slist_append (ss_req->bps, bp);
+ }
+ g_free (next);
+ }
+
+ if (ss_req->nframes == 0)
+ ss_req->nframes = nframes;
if (ss_req->depth == STEP_DEPTH_OVER) {
- if (ss_req->nframes == 0)
- ss_req->nframes = tls->frame_count;
/* Need to stop in catch clauses as well */
- for (i = 0; i < tls->frame_count; ++i) {
- StackFrame *frame = tls->frames [i];
+ for (i = 0; i < nframes; ++i) {
+ StackFrame *frame = frames [i];
if (frame->ji) {
MonoJitInfo *jinfo = frame->ji;
}
}
-
if (ss_req->depth == STEP_DEPTH_INTO) {
/* Enable global stepping so we stop at method entry too */
enable_global = TRUE;
}
if (enable_global) {
- DEBUG (1, fprintf (log_file, "[dbg] Turning on global single stepping.\n"));
+ DEBUG_PRINTF (1, "[dbg] Turning on global single stepping.\n");
ss_req->global = TRUE;
start_single_stepping ();
} else if (!ss_req->bps) {
- DEBUG (1, fprintf (log_file, "[dbg] Turning on global single stepping.\n"));
+ DEBUG_PRINTF (1, "[dbg] Turning on global single stepping.\n");
ss_req->global = TRUE;
start_single_stepping ();
} else {
* Start single stepping of thread THREAD
*/
static ErrorCode
-ss_create (MonoInternalThread *thread, StepSize size, StepDepth depth, EventRequest *req)
+ss_create (MonoInternalThread *thread, StepSize size, StepDepth depth, StepFilter filter, EventRequest *req)
{
DebuggerTlsData *tls;
MonoSeqPointInfo *info = NULL;
MonoMethod *method = NULL;
MonoDebugMethodInfo *minfo;
gboolean step_to_catch = FALSE;
+ gboolean set_ip = FALSE;
+ StackFrame **frames = NULL;
+ int nframes = 0;
if (suspend_count == 0)
return ERR_NOT_SUSPENDED;
// FIXME: Multiple requests
if (ss_req) {
- DEBUG (0, fprintf (log_file, "Received a single step request while the previous one was still active.\n"));
+ DEBUG_PRINTF (0, "Received a single step request while the previous one was still active.\n");
return ERR_NOT_IMPLEMENTED;
}
- DEBUG (1, fprintf (log_file, "[dbg] Starting single step of thread %p (depth=%s).\n", thread, ss_depth_to_string (depth)));
+ DEBUG_PRINTF (1, "[dbg] Starting single step of thread %p (depth=%s).\n", thread, ss_depth_to_string (depth));
ss_req = g_new0 (SingleStepReq, 1);
ss_req->req = req;
ss_req->thread = thread;
ss_req->size = size;
ss_req->depth = depth;
+ ss_req->filter = filter;
req->info = ss_req;
mono_loader_lock ();
mono_loader_unlock ();
g_assert (tls);
g_assert (tls->context.valid);
+
+ if (tls->restore_state.valid && MONO_CONTEXT_GET_IP (&tls->context.ctx) != MONO_CONTEXT_GET_IP (&tls->restore_state.ctx)) {
+ /*
+ * Need to start single stepping from restore_state and not from the current state
+ */
+ set_ip = TRUE;
+ frames = compute_frame_info_from (thread, tls, &tls->restore_state, &nframes);
+ }
+
ss_req->start_sp = ss_req->last_sp = MONO_CONTEXT_GET_SP (&tls->context.ctx);
if (tls->catch_state.valid) {
ss_req->last_sp = NULL;
}
- if (!step_to_catch && ss_req->size == STEP_SIZE_LINE) {
- StackFrame *frame;
+ if (!step_to_catch) {
+ StackFrame *frame = NULL;
- /* Compute the initial line info */
- compute_frame_info (thread, tls);
+ if (set_ip) {
+ if (frames && nframes)
+ frame = frames [0];
+ } else {
+ compute_frame_info (thread, tls);
- if (tls->frame_count) {
- frame = tls->frames [0];
+ if (tls->frame_count)
+ frame = tls->frames [0];
+ }
- ss_req->last_method = frame->method;
- ss_req->last_line = -1;
+ if (ss_req->size == STEP_SIZE_LINE) {
+ if (frame) {
+ ss_req->last_method = frame->method;
+ ss_req->last_line = -1;
- minfo = mono_debug_lookup_method (frame->method);
- if (minfo && frame->il_offset != -1) {
- MonoDebugSourceLocation *loc = mono_debug_symfile_lookup_location (minfo, frame->il_offset);
+ minfo = mono_debug_lookup_method (frame->method);
+ if (minfo && frame->il_offset != -1) {
+ MonoDebugSourceLocation *loc = mono_debug_symfile_lookup_location (minfo, frame->il_offset);
- if (loc) {
- ss_req->last_line = loc->row;
- g_free (loc);
+ if (loc) {
+ ss_req->last_line = loc->row;
+ g_free (loc);
+ }
}
}
}
- }
-
- if (!step_to_catch) {
- StackFrame *frame;
-
- compute_frame_info (thread, tls);
-
- if (tls->frame_count) {
- frame = tls->frames [0];
+ if (frame) {
if (!method && frame->il_offset != -1) {
/* FIXME: Sort the table and use a binary search */
found_sp = find_prev_seq_point_for_native_offset (frame->domain, frame->method, frame->native_offset, &info, &local_sp);
}
}
- ss_start (ss_req, method, sp, info, &tls->context.ctx, tls, step_to_catch);
+ ss_req->start_method = method;
+
+ ss_start (ss_req, method, sp, info, set_ip ? &tls->restore_state.ctx : &tls->context.ctx, tls, step_to_catch, frames, nframes);
+
+ if (frames)
+ free_frames (frames, nframes);
return 0;
}
if (t && klass != mono_class_from_mono_type (t)) {
char *name = mono_type_full_name (t);
char *name2 = mono_type_full_name (&klass->byval_arg);
- DEBUG(1, fprintf (log_file, "[%p] Expected value of type %s, got %s.\n", (gpointer)GetCurrentThreadId (), name, name2));
+ DEBUG_PRINTF (1, "[%p] Expected value of type %s, got %s.\n", (gpointer)GetCurrentThreadId (), name, name2);
g_free (name);
g_free (name2);
return ERR_INVALID_ARGUMENT;
!(t->type == MONO_TYPE_PTR && type == MONO_TYPE_I8) &&
!(t->type == MONO_TYPE_GENERICINST && type == MONO_TYPE_VALUETYPE)) {
char *name = mono_type_full_name (t);
- DEBUG(1, fprintf (log_file, "[%p] Expected value of type %s, got 0x%0x.\n", (gpointer)GetCurrentThreadId (), name, type));
+ DEBUG_PRINTF (1, "[%p] Expected value of type %s, got 0x%0x.\n", (gpointer)GetCurrentThreadId (), name, type);
g_free (name);
return ERR_INVALID_ARGUMENT;
}
if (obj) {
if (!obj_is_of_type (obj, t)) {
- DEBUG (1, fprintf (log_file, "Expected type '%s', got '%s'\n", mono_type_full_name (t), obj->vtable->klass->name));
+ DEBUG_PRINTF (1, "Expected type '%s', got '%s'\n", mono_type_full_name (t), obj->vtable->klass->name);
return ERR_INVALID_ARGUMENT;
}
}
g_free (vtype_buf);
} else {
char *name = mono_type_full_name (t);
- DEBUG(1, fprintf (log_file, "[%p] Expected value of type %s, got 0x%0x.\n", (gpointer)GetCurrentThreadId (), name, type));
+ DEBUG_PRINTF (1, "[%p] Expected value of type %s, got 0x%0x.\n", (gpointer)GetCurrentThreadId (), name, type);
g_free (name);
return ERR_INVALID_ARGUMENT;
}
/* Set value on the stack or in the return ctx */
if (reg_locations [reg]) {
/* Saved on the stack */
- DEBUG (1, fprintf (log_file, "[dbg] Setting stack location %p for reg %x to %p.\n", reg_locations [reg], reg, (gpointer)v));
+ DEBUG_PRINTF (1, "[dbg] Setting stack location %p for reg %x to %p.\n", reg_locations [reg], reg, (gpointer)v);
*(reg_locations [reg]) = v;
} else {
/* Not saved yet */
- DEBUG (1, fprintf (log_file, "[dbg] Setting context location for reg %x to %p.\n", reg, (gpointer)v));
+ DEBUG_PRINTF (1, "[dbg] Setting context location for reg %x to %p.\n", reg, (gpointer)v);
mono_arch_context_set_int_reg (restore_ctx, reg, v);
}
* Invoke this method directly, currently only Environment.Exit () is supported.
*/
this = NULL;
- DEBUG (1, fprintf (log_file, "[%p] Invoking method '%s' on receiver '%s'.\n", (gpointer)GetCurrentThreadId (), mono_method_full_name (invoke->method, TRUE), this ? this->vtable->klass->name : "<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>");
mono_runtime_invoke (invoke->method, NULL, invoke->args, &exc);
g_assert_not_reached ();
}
/* Should be null */
int type = decode_byte (p, &p, end);
if (type != VALUE_TYPE_ID_NULL) {
- DEBUG (1, fprintf (log_file, "[%p] Error: Static vtype method invoked with this argument.\n", (gpointer)GetCurrentThreadId ()));
+ DEBUG_PRINTF (1, "[%p] Error: Static vtype method invoked with this argument.\n", (gpointer)GetCurrentThreadId ());
return ERR_INVALID_ARGUMENT;
}
memset (this_buf, 0, mono_class_instance_size (m->klass));
if (MONO_CLASS_IS_INTERFACE (m->klass)) {
if (!this) {
- DEBUG (1, fprintf (log_file, "[%p] Error: Interface method invoked without this argument.\n", (gpointer)GetCurrentThreadId ()));
+ 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);
- } else if (invoke->flags & INVOKE_FLAG_VIRTUAL) {
+ } else if ((m->flags & METHOD_ATTRIBUTE_VIRTUAL) && !m->klass->valuetype && invoke->flags & INVOKE_FLAG_VIRTUAL) {
if (!this) {
- DEBUG (1, fprintf (log_file, "[%p] Error: invoke with INVOKE_FLAG_VIRTUAL flag set without this argument.\n", (gpointer)GetCurrentThreadId ()));
+ 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);
}
- DEBUG (1, fprintf (log_file, "[%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 ? this->vtable->klass->name : "<null>");
if (this && this->vtable->domain != domain)
NOT_IMPLEMENTED;
else
res = mono_runtime_invoke (m, this, args, &exc);
mono_stopwatch_stop (&watch);
- DEBUG (1, fprintf (log_file, "[%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)));
+ 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) {
buffer_add_byte (buf, 0);
buffer_add_value (buf, &mono_defaults.object_class->byval_arg, &exc, domain);
tls->resume_count -= invoke->suspend_count;
}
- DEBUG (1, fprintf (log_file, "[%p] Invoke finished (%d), resume_count = %d.\n", (gpointer)GetCurrentThreadId (), err, tls->resume_count));
+ DEBUG_PRINTF (1, "[%p] Invoke finished (%d), resume_count = %d.\n", (gpointer)GetCurrentThreadId (), err, tls->resume_count);
/*
* Take the loader lock to avoid race conditions with CMD_VM_ABORT_INVOKE:
major_version = decode_int (p, &p, end);
minor_version = decode_int (p, &p, end);
protocol_version_set = TRUE;
- DEBUG(1, fprintf (log_file, "[dbg] Protocol version %d.%d, client protocol version %d.%d.\n", MAJOR_VERSION, MINOR_VERSION, major_version, minor_version));
+ DEBUG_PRINTF (1, "[dbg] Protocol version %d.%d, client protocol version %d.%d.\n", MAJOR_VERSION, MINOR_VERSION, major_version, minor_version);
break;
}
case CMD_VM_ALL_THREADS: {
mono_environment_exitcode_set (exit_code);
/* Suspend all managed threads since the runtime is going away */
- DEBUG(1, fprintf (log_file, "Suspending all threads...\n"));
+ DEBUG_PRINTF (1, "Suspending all threads...\n");
mono_thread_suspend_all_other_threads ();
- DEBUG(1, fprintf (log_file, "Shutting down the runtime...\n"));
+ DEBUG_PRINTF (1, "Shutting down the runtime...\n");
mono_runtime_quit ();
transport_close2 ();
- DEBUG(1, fprintf (log_file, "Exiting...\n"));
+ DEBUG_PRINTF (1, "Exiting...\n");
exit (exit_code);
}
fname = decode_string (p, &p, end);
ignore_case = decode_byte (p, &p, end);
- basename = g_path_get_basename (fname);
+ basename = dbg_path_get_basename (fname);
res_classes = g_ptr_array_new ();
res_domains = g_ptr_array_new ();
for (i = 0; i < files->len; ++i) {
char *s = g_ptr_array_index (files, i);
- char *s2 = g_path_get_basename (s);
+ char *s2 = dbg_path_get_basename (s);
char *s3;
class_list = g_hash_table_lookup (info->source_file_to_class, s2);
req->modifiers [i].subclasses = decode_byte (p, &p, end);
else
req->modifiers [i].subclasses = TRUE;
- DEBUG(1, fprintf (log_file, "[dbg] \tEXCEPTION_ONLY filter (%s%s%s%s).\n", exc_class ? exc_class->name : "all", req->modifiers [i].caught ? ", caught" : "", req->modifiers [i].uncaught ? ", uncaught" : "", req->modifiers [i].subclasses ? ", include-subclasses" : ""));
+ DEBUG_PRINTF (1, "[dbg] \tEXCEPTION_ONLY filter (%s%s%s%s).\n", exc_class ? exc_class->name : "all", req->modifiers [i].caught ? ", caught" : "", req->modifiers [i].uncaught ? ", uncaught" : "", req->modifiers [i].subclasses ? ", include-subclasses" : "");
if (exc_class) {
req->modifiers [i].data.exc_class = exc_class;
req->info = set_breakpoint (method, location, req, &error);
if (!mono_error_ok (&error)) {
g_free (req);
- DEBUG(1, fprintf (log_file, "[dbg] Failed to set breakpoint: %s\n", mono_error_get_message (&error)));
+ DEBUG_PRINTF (1, "[dbg] Failed to set breakpoint: %s\n", mono_error_get_message (&error));
mono_error_cleanup (&error);
return ERR_NO_SEQ_POINT_AT_IL_OFFSET;
}
return err;
}
- err = ss_create (THREAD_TO_INTERNAL (step_thread), size, depth, req);
+ err = ss_create (THREAD_TO_INTERNAL (step_thread), size, depth, filter, req);
if (err) {
g_free (req);
return err;
mono_reflection_create_custom_attr_data_args (image, attr->ctor, attr->data, attr->data_size, &typed_args, &named_args, &arginfo, &error);
if (!mono_error_ok (&error)) {
- DEBUG(2, fprintf (log_file, "[dbg] mono_reflection_create_custom_attr_data_args () failed with: '%s'\n", mono_error_get_message (&error)));
+ DEBUG_PRINTF (2, "[dbg] mono_reflection_create_custom_attr_data_args () failed with: '%s'\n", mono_error_get_message (&error));
mono_error_cleanup (&error);
return ERR_LOADER_ERROR;
}
if (command == CMD_TYPE_GET_SOURCE_FILES_2) {
buffer_add_string (buf, source_file);
} else {
- base = g_path_get_basename (source_file);
+ base = dbg_path_get_basename (source_file);
buffer_add_string (buf, base);
g_free (base);
}
buffer_add_string (buf, source_file);
}
buffer_add_int (buf, n_il_offsets);
- DEBUG (10, fprintf (log_file, "Line number table for method %s:\n", mono_method_full_name (method, TRUE)));
+ DEBUG_PRINTF (10, "Line number table for method %s:\n", mono_method_full_name (method, TRUE));
for (i = 0; i < n_il_offsets; ++i) {
const char *srcfile = "";
MonoDebugSourceInfo *sinfo = g_ptr_array_index (source_file_list, source_files [i]);
srcfile = sinfo->source_file;
}
- DEBUG (10, fprintf (log_file, "IL%x -> %s:%d %d\n", il_offsets [i], srcfile, line_numbers [i], column_numbers ? column_numbers [i] : -1));
+ DEBUG_PRINTF (10, "IL%x -> %s:%d %d %d %d\n", il_offsets [i], srcfile, line_numbers [i], column_numbers ? column_numbers [i] : -1, end_line_numbers ? end_line_numbers [i] : -1, end_column_numbers ? end_column_numbers [i] : -1);
buffer_add_int (buf, il_offsets [i]);
buffer_add_int (buf, line_numbers [i]);
if (CHECK_PROTOCOL_VERSION (2, 13))
if (imethod->context.class_inst) {
MonoClass *klass = ((MonoMethod *) imethod)->klass;
/*Generic methods gets the context of the GTD.*/
- if (mono_class_get_context (klass))
- result = mono_class_inflate_generic_method_full (result, klass, mono_class_get_context (klass));
+ if (mono_class_get_context (klass)) {
+ MonoError error;
+ result = mono_class_inflate_generic_method_full_checked (result, klass, mono_class_get_context (klass), &error);
+ g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
+ }
}
}
break;
}
} else {
- val = mono_ldtoken (method->klass->image, token, &handle_class, NULL);
- g_assert (val);
+ MonoError error;
+ val = mono_ldtoken_checked (method->klass->image, token, &handle_class, NULL, &error);
+ if (!val)
+ g_error ("Could not load token due to %s", mono_error_get_message (&error));
}
if (handle_class == mono_defaults.typehandle_class) {
break;
}
case CMD_METHOD_MAKE_GENERIC_METHOD: {
+ MonoError error;
MonoType **type_argv;
int i, type_argc;
MonoDomain *d;
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);
+ inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, &error);
+ g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
if (!mono_verifier_is_method_valid_generic_instantiation (inflated))
return ERR_INVALID_ARGUMENT;
buffer_add_methodid (buf, domain, inflated);
// FIXME: Check that the ip change is safe
- DEBUG (1, fprintf (log_file, "[dbg] Setting IP to %s:0x%0x(0x%0x)\n", tls->frames [0]->actual_method->name, (int)sp.il_offset, (int)sp.native_offset));
- MONO_CONTEXT_SET_IP (&tls->restore_ctx, (guint8*)tls->frames [0]->ji->code_start + sp.native_offset);
+ DEBUG_PRINTF (1, "[dbg] Setting IP to %s:0x%0x(0x%0x)\n", tls->frames [0]->actual_method->name, (int)sp.il_offset, (int)sp.native_offset);
+ MONO_CONTEXT_SET_IP (&tls->restore_state.ctx, (guint8*)tls->frames [0]->ji->code_start + sp.native_offset);
break;
}
default:
DebuggerTlsData *tls;
StackFrame *frame;
MonoDebugMethodJitInfo *jit;
- MonoDebugVarInfo *var;
MonoMethodSignature *sig;
gssize id;
MonoMethodHeader *header;
frame_idx = i;
frame = tls->frames [frame_idx];
+ /* This is supported for frames without has_ctx etc. set */
+ if (command == CMD_STACK_FRAME_GET_DOMAIN) {
+ if (CHECK_PROTOCOL_VERSION (2, 38))
+ buffer_add_domainid (buf, frame->domain);
+ return ERR_NONE;
+ }
+
if (!frame->has_ctx)
return ERR_ABSENT_INFORMATION;
/* This could happen for aot images with no jit debug info */
s = mono_method_full_name (frame->api_method, TRUE);
- DEBUG (1, fprintf (log_file, "[dbg] No debug information found for '%s'.\n", s));
+ DEBUG_PRINTF (1, "[dbg] No debug information found for '%s'.\n", s);
g_free (s);
return ERR_ABSENT_INFORMATION;
}
g_assert (pos >= 0 && pos < jit->num_params);
- var = &jit->params [pos];
-
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, jit, header->locals [pos], &jit->locals [pos], &frame->ctx, frame->domain, FALSE);
}
}
if (err)
return err;
- set_var (t, var, &frame->ctx, frame->domain, val_buf, frame->reg_locations, &tls->restore_ctx);
+ set_var (t, var, &frame->ctx, frame->domain, val_buf, frame->reg_locations, &tls->restore_state.ctx);
}
mono_metadata_free_mh (header);
break;
{
#ifndef DISABLE_SOCKET_TRANSPORT
if (listen_fd == -1) {
- DEBUG (1, fprintf (log_file, "[dbg] Invalid listening socket\n"));
+ DEBUG_PRINTF (1, "[dbg] Invalid listening socket\n");
return FALSE;
}
/* Block and wait for client connection */
conn_fd = socket_transport_accept (listen_fd);
- DEBUG (1, fprintf (log_file, "Accepted connection on %d\n", conn_fd));
+ DEBUG_PRINTF (1, "Accepted connection on %d\n", conn_fd);
if (conn_fd == -1) {
- DEBUG (1, fprintf (log_file, "[dbg] Bad client connection\n"));
+ DEBUG_PRINTF (1, "[dbg] Bad client connection\n");
return FALSE;
}
#else
/* Handshake */
disconnected = !transport_handshake ();
if (disconnected) {
- DEBUG (1, fprintf (log_file, "Transport handshake failed!\n"));
+ DEBUG_PRINTF (1, "Transport handshake failed!\n");
return FALSE;
}
gboolean no_reply;
gboolean attach_failed = FALSE;
- DEBUG (1, fprintf (log_file, "[dbg] Agent thread started, pid=%p\n", (gpointer)GetCurrentThreadId ()));
+ DEBUG_PRINTF (1, "[dbg] Agent thread started, pid=%p\n", (gpointer)GetCurrentThreadId ());
debugger_thread_id = GetCurrentThreadId ();
if (agent_config.defer) {
if (!wait_for_attach ()) {
- DEBUG (1, fprintf (log_file, "[dbg] Can't attach, aborting debugger thread.\n"));
+ DEBUG_PRINTF (1, "[dbg] Can't attach, aborting debugger thread.\n");
attach_failed = TRUE; // Don't abort process when we can't listen
} else {
/* Send start event to client */
/* This will break if the socket is closed during shutdown too */
if (res != HEADER_LENGTH) {
- DEBUG (1, fprintf (log_file, "[dbg] transport_recv () returned %d, expected %d.\n", res, HEADER_LENGTH));
+ DEBUG_PRINTF (1, "[dbg] transport_recv () returned %d, expected %d.\n", res, HEADER_LENGTH);
break;
}
cmd_str = cmd_num;
}
- DEBUG (1, fprintf (log_file, "[dbg] Command %s(%s) [%d][at=%lx].\n", command_set_to_string (command_set), cmd_str, id, (long)mono_100ns_ticks () / 10000));
+ DEBUG_PRINTF (1, "[dbg] Command %s(%s) [%d][at=%lx].\n", command_set_to_string (command_set), cmd_str, id, (long)mono_100ns_ticks () / 10000);
}
data = g_malloc (len - HEADER_LENGTH);
{
res = transport_recv (data, len - HEADER_LENGTH);
if (res != len - HEADER_LENGTH) {
- DEBUG (1, fprintf (log_file, "[dbg] transport_recv () returned %d, expected %d.\n", res, len - HEADER_LENGTH));
+ DEBUG_PRINTF (1, "[dbg] transport_recv () returned %d, expected %d.\n", res, len - HEADER_LENGTH);
break;
}
}
buffer_reply_packet (id, err, &buf);
} else {
send_reply_packet (id, err, &buf);
- //DEBUG (1, fprintf (log_file, "[dbg] Sent reply to %d [at=%lx].\n", id, (long)mono_100ns_ticks () / 10000));
+ //DEBUG_PRINTF (1, "[dbg] Sent reply to %d [at=%lx].\n", id, (long)mono_100ns_ticks () / 10000);
}
}
mono_cond_signal (&debugger_thread_exited_cond);
mono_mutex_unlock (&debugger_thread_exited_mutex);
- DEBUG (1, fprintf (log_file, "[dbg] Debugger thread exited.\n"));
+ DEBUG_PRINTF (1, "[dbg] Debugger thread exited.\n");
if (!attach_failed && command_set == CMD_SET_VM && command == CMD_VM_DISPOSE && !(vm_death_event_sent || mono_runtime_is_shutting_down ())) {
- DEBUG (2, fprintf (log_file, "[dbg] Detached - restarting clean debugger thread.\n"));
+ DEBUG_PRINTF (2, "[dbg] Detached - restarting clean debugger thread.\n");
start_debugger_thread ();
}