Merge pull request #273 from joncham/bug-getpid
[mono.git] / mono / mini / debugger-agent.c
old mode 100755 (executable)
new mode 100644 (file)
index 4b509eb..9eb0c29
@@ -285,7 +285,7 @@ typedef struct {
 #define HEADER_LENGTH 11
 
 #define MAJOR_VERSION 2
-#define MINOR_VERSION 27
+#define MINOR_VERSION 29
 
 typedef enum {
        CMD_SET_VM = 1,
@@ -300,6 +300,7 @@ typedef enum {
        CMD_SET_METHOD = 22,
        CMD_SET_TYPE = 23,
        CMD_SET_MODULE = 24,
+       CMD_SET_FIELD = 25,
        CMD_SET_EVENT = 64
 } CommandSet;
 
@@ -422,7 +423,8 @@ typedef enum {
        CMD_THREAD_GET_STATE = 3,
        CMD_THREAD_GET_INFO = 4,
        CMD_THREAD_GET_ID = 5,
-       CMD_THREAD_GET_TID = 6
+       CMD_THREAD_GET_TID = 6,
+       CMD_THREAD_SET_IP = 7
 } CmdThread;
 
 typedef enum {
@@ -458,6 +460,10 @@ typedef enum {
        CMD_MODULE_GET_INFO = 1,
 } CmdModule;
 
+typedef enum {
+       CMD_FIELD_GET_INFO = 1,
+} CmdField;
+
 typedef enum {
        CMD_METHOD_GET_NAME = 1,
        CMD_METHOD_GET_DECLARING_TYPE = 2,
@@ -889,7 +895,7 @@ mono_debugger_agent_parse_options (char *options)
                /* Waiting for deferred attachment */
                agent_config.defer = TRUE;
                if (agent_config.address == NULL) {
-                       agent_config.address = g_strdup_printf ("0.0.0.0:%u", 56000 + (GetCurrentProcessId () % 1000));
+                       agent_config.address = g_strdup_printf ("0.0.0.0:%u", 56000 + (getpid () % 1000));
                }
        }
 
@@ -1576,9 +1582,7 @@ stop_debugger_thread (void)
 static void
 start_debugger_thread (void)
 {
-       gsize tid;
-
-       debugger_thread_handle = mono_create_thread (NULL, 0, debugger_thread, NULL, 0, &tid);
+       debugger_thread_handle = mono_threads_create_thread (debugger_thread, NULL, 0, 0, NULL);
        g_assert (debugger_thread_handle);
 }
 
@@ -2201,6 +2205,7 @@ decode_ptr_id (guint8 *buf, guint8 **endbuf, guint8 *limit, IdType type, MonoDom
        mono_loader_unlock ();
 
        if (res->domain == NULL) {
+               DEBUG (0, fprintf (log_file, "ERR_UNLOADED, id=%d, type=%d.\n", id, type));
                *err = ERR_UNLOADED;
                return NULL;
        }
@@ -2806,7 +2811,7 @@ resume_thread (MonoInternalThread *thread)
 
        g_assert (suspend_count > 0);
 
-       DEBUG(1, fprintf (log_file, "[%p] Resuming thread...\n", (gpointer)(gssize)thread->tid));
+       DEBUG(1, fprintf (log_file, "[sdb] Resuming thread %p...\n", (gpointer)(gssize)thread->tid));
 
        tls->resume_count += suspend_count;
 
@@ -6020,6 +6025,16 @@ set_var (MonoType *t, MonoDebugVarInfo *var, MonoContext *ctx, MonoDomain *domai
                mgreg_t v;
                gboolean is_signed = FALSE;
 
+               if (t->byref) {
+                       addr = (gpointer)mono_arch_context_get_int_reg (ctx, reg);
+
+                       if (addr) {
+                               // FIXME: Write barriers
+                               mono_gc_memmove_atomic (addr, val, size);
+                       }
+                       break;
+               }
+
                if (!t->byref && (t->type == MONO_TYPE_I1 || t->type == MONO_TYPE_I2 || t->type == MONO_TYPE_I4 || t->type == MONO_TYPE_I8))
                        is_signed = TRUE;
 
@@ -6040,9 +6055,6 @@ set_var (MonoType *t, MonoDebugVarInfo *var, MonoContext *ctx, MonoDomain *domai
                        g_assert_not_reached ();
                }
 
-               if (t->byref)
-                       NOT_IMPLEMENTED;
-
                /* Set value on the stack or in the return ctx */
                if (reg_locations [reg]) {
                        /* Saved on the stack */
@@ -6076,7 +6088,7 @@ set_var (MonoType *t, MonoDebugVarInfo *var, MonoContext *ctx, MonoDomain *domai
                }
                        
                // FIXME: Write barriers
-               mono_gc_memmove (addr, val, size);
+               mono_gc_memmove_atomic (addr, val, size);
                break;
        case MONO_DEBUG_VAR_ADDRESS_MODE_REGOFFSET_INDIR:
                /* Same as regoffset, but with an indirection */
@@ -6086,7 +6098,7 @@ set_var (MonoType *t, MonoDebugVarInfo *var, MonoContext *ctx, MonoDomain *domai
                gaddr = *(gpointer*)addr;
                g_assert (gaddr);
                // FIXME: Write barriers
-               mono_gc_memmove (gaddr, val, size);
+               mono_gc_memmove_atomic (gaddr, val, size);
                break;
        case MONO_DEBUG_VAR_ADDRESS_MODE_DEAD:
                NOT_IMPLEMENTED;
@@ -7400,6 +7412,29 @@ module_commands (int command, guint8 *p, guint8 *end, Buffer *buf)
        return ERR_NONE;
 }
 
+static ErrorCode
+field_commands (int command, guint8 *p, guint8 *end, Buffer *buf)
+{
+       int err;
+       MonoDomain *domain;
+
+       switch (command) {
+       case CMD_FIELD_GET_INFO: {
+               MonoClassField *f = decode_fieldid (p, &p, end, &domain, &err);
+
+               buffer_add_string (buf, f->name);
+               buffer_add_typeid (buf, domain, f->parent);
+               buffer_add_typeid (buf, domain, mono_class_from_mono_type (f->type));
+               buffer_add_int (buf, f->type->attrs);
+               break;
+       }
+       default:
+               return ERR_NOT_IMPLEMENTED;
+       }
+
+       return ERR_NONE;
+}
+
 static void
 buffer_add_cattr_arg (Buffer *buf, MonoType *t, MonoDomain *domain, MonoObject *val)
 {
@@ -8452,6 +8487,52 @@ thread_commands (int command, guint8 *p, guint8 *end, Buffer *buf)
        case CMD_THREAD_GET_TID:
                buffer_add_long (buf, (guint64)thread->tid);
                break;
+       case CMD_THREAD_SET_IP: {
+               DebuggerTlsData *tls;
+               MonoMethod *method;
+               MonoDomain *domain;
+               MonoSeqPointInfo *seq_points;
+               SeqPoint *sp = NULL;
+               gint64 il_offset;
+               int i;
+
+               method = decode_methodid (p, &p, end, &domain, &err);
+               if (err)
+                       return err;
+               il_offset = decode_long (p, &p, end);
+
+               while (!is_suspended ()) {
+                       if (suspend_count)
+                               wait_for_suspend ();
+               }
+
+               mono_loader_lock ();
+               tls = mono_g_hash_table_lookup (thread_to_tls, thread);
+               mono_loader_unlock ();
+               g_assert (tls);
+
+               compute_frame_info (thread, tls);
+               if (tls->frame_count == 0 || tls->frames [0]->actual_method != method)
+                       return ERR_INVALID_ARGUMENT;
+
+               seq_points = get_seq_points (domain, method);
+               g_assert (seq_points);
+
+               for (i = 0; i < seq_points->len; ++i) {
+                       sp = &seq_points->seq_points [i];
+
+                       if (sp->il_offset == il_offset)
+                               break;
+               }
+               if (i == seq_points->len)
+                       return ERR_INVALID_ARGUMENT;
+
+               // 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);
+               break;
+       }
        default:
                return ERR_NOT_IMPLEMENTED;
        }
@@ -8853,27 +8934,29 @@ command_set_to_string (CommandSet command_set)
        case CMD_SET_OBJECT_REF:
                return "OBJECT_REF";
        case CMD_SET_STRING_REF:
-               return "STRING_REF"; 
+               return "STRING_REF";
        case CMD_SET_THREAD:
-               return "THREAD"; 
+               return "THREAD";
        case CMD_SET_ARRAY_REF:
-               return "ARRAY_REF"; 
+               return "ARRAY_REF";
        case CMD_SET_EVENT_REQUEST:
-               return "EVENT_REQUEST"; 
+               return "EVENT_REQUEST";
        case CMD_SET_STACK_FRAME:
-               return "STACK_FRAME"; 
+               return "STACK_FRAME";
        case CMD_SET_APPDOMAIN:
-               return "APPDOMAIN"; 
+               return "APPDOMAIN";
        case CMD_SET_ASSEMBLY:
-               return "ASSEMBLY"; 
+               return "ASSEMBLY";
        case CMD_SET_METHOD:
-               return "METHOD"; 
+               return "METHOD";
        case CMD_SET_TYPE:
-               return "TYPE"; 
+               return "TYPE";
        case CMD_SET_MODULE:
-               return "MODULE"; 
+               return "MODULE";
+       case CMD_SET_FIELD:
+               return "FIELD";
        case CMD_SET_EVENT:
-               return "EVENT"; 
+               return "EVENT";
        default:
                return "";
        }
@@ -8901,7 +8984,8 @@ static const char* thread_cmds_str[] = {
        "GET_STATE",
        "GET_INFO",
        "GET_ID",
-       "GET_TID"
+       "GET_TID",
+       "SET_IP"
 };
 
 static const char* event_cmds_str[] = {
@@ -8933,6 +9017,10 @@ static const char* module_cmds_str[] = {
        "GET_INFO",
 };
 
+static const char* field_cmds_str[] = {
+       "GET_INFO",
+};
+
 static const char* method_cmds_str[] = {
        "GET_NAME",
        "GET_DECLARING_TYPE",
@@ -9050,6 +9138,10 @@ cmd_to_string (CommandSet set, int command)
                cmds = module_cmds_str;
                cmds_len = G_N_ELEMENTS (module_cmds_str);
                break;
+       case CMD_SET_FIELD:
+               cmds = field_cmds_str;
+               cmds_len = G_N_ELEMENTS (field_cmds_str);
+               break;
        case CMD_SET_EVENT:
                cmds = event_cmds_str;
                cmds_len = G_N_ELEMENTS (event_cmds_str);
@@ -9201,6 +9293,9 @@ debugger_thread (void *arg)
                case CMD_SET_MODULE:
                        err = module_commands (command, p, end, &buf);
                        break;
+               case CMD_SET_FIELD:
+                       err = field_commands (command, p, end, &buf);
+                       break;
                case CMD_SET_TYPE:
                        err = type_commands (command, p, end, &buf);
                        break;