Initial soft debugger support for MIPS.
authorZoltan Varga <vargaz@gmail.com>
Sat, 26 Nov 2011 22:52:45 +0000 (23:52 +0100)
committerZoltan Varga <vargaz@gmail.com>
Sat, 26 Nov 2011 22:52:45 +0000 (23:52 +0100)
mono/mini/cpu-mips.md
mono/mini/mini-mips.c
mono/mini/mini-mips.h
mono/utils/mono-context.h

index 4b52d898b91384ff53a5efcebd5accf765aee24c..ef652ccda851e321286e7b4dbd1554fdcae91204 100644 (file)
@@ -59,6 +59,7 @@ jmp: len:92
 call: dest:v clob:c len:20
 br: len:16
 switch: src1:i len:40
+seq_point: len:24
 
 callvirt: dest:v clob:c len:20
 int_conv_to_r_un: dest:f src1:i len:32
index 0716591cd30bae02c2c1d4878774e9c1b7c229c6..8df3887ff08bf88ffadad1bb83c7c0a490019d15 100644 (file)
@@ -17,6 +17,7 @@
 
 #include <mono/metadata/appdomain.h>
 #include <mono/metadata/debug-helpers.h>
+#include <mono/utils/mono-mmap.h>
 
 #include <mono/arch/mips/mips-codegen.h>
 
@@ -74,6 +75,15 @@ static int ls_word_idx;
 /* Index of ls word/register */
 static int ms_word_idx;
 
+/*
+ * The code generated for sequence points reads from this location, which is
+ * made read-only when single stepping is enabled.
+ */
+static gpointer ss_trigger_page;
+
+/* Enabled breakpoints read from this trigger page */
+static gpointer bp_trigger_page;
+
 #undef DEBUG
 #define DEBUG(a) if (cfg->verbose_level > 1) a
 #undef DEBUG
@@ -556,7 +566,11 @@ mono_arch_cpu_init (void)
 void
 mono_arch_init (void)
 {
-       InitializeCriticalSection (&mini_arch_mutex);   
+       InitializeCriticalSection (&mini_arch_mutex);
+
+       ss_trigger_page = mono_valloc (NULL, mono_pagesize (), MONO_MMAP_READ|MONO_MMAP_32BIT);
+       bp_trigger_page = mono_valloc (NULL, mono_pagesize (), MONO_MMAP_READ|MONO_MMAP_32BIT);
+       mono_mprotect (bp_trigger_page, mono_pagesize (), 0);
 }
 
 /*
@@ -3193,6 +3207,26 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                case OP_NOT_REACHED:
                case OP_NOT_NULL:
                        break;
+               case OP_SEQ_POINT: {
+                       if (ins->flags & MONO_INST_SINGLE_STEP_LOC) {
+                               guint32 addr = (guint32)ss_trigger_page;
+
+                               mips_load_const (code, mips_t9, addr);
+                               mips_lw (code, mips_t9, mips_t9, 0);
+                       }
+
+                       mono_add_seq_point (cfg, bb, ins, code - cfg->native_code);
+
+                       /*
+                        * A placeholder for a possible breakpoint inserted by
+                        * mono_arch_set_breakpoint ().
+                        */
+                       /* mips_load_const () + mips_lw */
+                       mips_nop (code);
+                       mips_nop (code);
+                       mips_nop (code);
+                       break;
+               }
                case OP_TLS_GET:
                        g_assert_not_reached();
 #if 0
@@ -5594,8 +5628,7 @@ MonoInst* mono_arch_get_domain_intrinsic (MonoCompile* cfg)
 mgreg_t
 mono_arch_context_get_int_reg (MonoContext *ctx, int reg)
 {
-       /* FIXME: implement */
-       g_assert_not_reached ();
+       return ctx->sc_regs [reg];
 }
 
 #ifdef MONO_ARCH_HAVE_IMT
@@ -5774,3 +5807,130 @@ mono_arch_find_static_call_vtable (mgreg_t *regs, guint8 *code)
        NOT_IMPLEMENTED;
        return (MonoVTable*) regs [MONO_ARCH_RGCTX_REG];
 }
+
+/* Soft Debug support */
+#ifdef MONO_ARCH_SOFT_DEBUG_SUPPORTED
+
+/*
+ * mono_arch_set_breakpoint:
+ *
+ *   See mini-amd64.c for docs.
+ */
+void
+mono_arch_set_breakpoint (MonoJitInfo *ji, guint8 *ip)
+{
+       guint8 *code = ip;
+       guint32 addr = (guint32)bp_trigger_page;
+
+       mips_load_const (code, mips_t9, addr);
+       mips_lw (code, mips_t9, mips_t9, 0);
+
+       mono_arch_flush_icache (ip, code - ip);
+}
+
+/*
+ * mono_arch_clear_breakpoint:
+ *
+ *   See mini-amd64.c for docs.
+ */
+void
+mono_arch_clear_breakpoint (MonoJitInfo *ji, guint8 *ip)
+{
+       guint8 *code = ip;
+
+       mips_nop (code);
+       mips_nop (code);
+       mips_nop (code);
+
+       mono_arch_flush_icache (ip, code - ip);
+}
+       
+/*
+ * mono_arch_start_single_stepping:
+ *
+ *   See mini-amd64.c for docs.
+ */
+void
+mono_arch_start_single_stepping (void)
+{
+       mono_mprotect (ss_trigger_page, mono_pagesize (), 0);
+}
+       
+/*
+ * mono_arch_stop_single_stepping:
+ *
+ *   See mini-amd64.c for docs.
+ */
+void
+mono_arch_stop_single_stepping (void)
+{
+       mono_mprotect (ss_trigger_page, mono_pagesize (), MONO_MMAP_READ);
+}
+
+/*
+ * mono_arch_is_single_step_event:
+ *
+ *   See mini-amd64.c for docs.
+ */
+gboolean
+mono_arch_is_single_step_event (void *info, void *sigctx)
+{
+       siginfo_t* sinfo = (siginfo_t*) info;
+       /* Sometimes the address is off by 4 */
+       if (sinfo->si_addr >= ss_trigger_page && (guint8*)sinfo->si_addr <= (guint8*)ss_trigger_page + 128)
+               return TRUE;
+       else
+               return FALSE;
+}
+
+/*
+ * mono_arch_is_breakpoint_event:
+ *
+ *   See mini-amd64.c for docs.
+ */
+gboolean
+mono_arch_is_breakpoint_event (void *info, void *sigctx)
+{
+       siginfo_t* sinfo = (siginfo_t*) info;
+       /* Sometimes the address is off by 4 */
+       if (sinfo->si_addr >= bp_trigger_page && (guint8*)sinfo->si_addr <= (guint8*)bp_trigger_page + 128)
+               return TRUE;
+       else
+               return FALSE;
+}
+
+/*
+ * mono_arch_skip_breakpoint:
+ *
+ *   See mini-amd64.c for docs.
+ */
+void
+mono_arch_skip_breakpoint (MonoContext *ctx)
+{
+       MONO_CONTEXT_SET_IP (ctx, (guint8*)MONO_CONTEXT_GET_IP (ctx) + 4);
+}
+
+/*
+ * mono_arch_skip_single_step:
+ *
+ *   See mini-amd64.c for docs.
+ */
+void
+mono_arch_skip_single_step (MonoContext *ctx)
+{
+       MONO_CONTEXT_SET_IP (ctx, (guint8*)MONO_CONTEXT_GET_IP (ctx) + 4);
+}
+
+/*
+ * mono_arch_get_seq_point_info:
+ *
+ *   See mini-amd64.c for docs.
+ */
+gpointer
+mono_arch_get_seq_point_info (MonoDomain *domain, guint8 *code)
+{
+       NOT_IMPLEMENTED;
+       return NULL;
+}
+
+#endif /* MONO_ARCH_SOFT_DEBUG_SUPPORTED */
index b535ad436f4d2c5ea80ed51ae0d7fdae46c3748f..fd05be0c4cececa60f58def344e515e3dd6ced20 100644 (file)
@@ -272,6 +272,7 @@ typedef struct MonoCompileArch {
 #define MONO_ARCH_HAVE_DECOMPOSE_LONG_OPTS 1
 
 #define MONO_ARCH_HAVE_GENERALIZED_IMT_THUNK 1
+#define MONO_ARCH_SOFT_DEBUG_SUPPORTED 1
 
 /* XXX - a mystery, but it works */
 #define MONO_GET_CONTEXT \
index b49347ae1e24c42f6eea1c66c5c09708a3649af0..b456c8aa5b4a57cec77a92d7232cbc042d315b59 100644 (file)
@@ -362,7 +362,7 @@ mono_ia64_context_get_fp (MonoContext *ctx)
        return fp;
 }
 
-#elif defined(__mips__) && SIZEOF_REGISTER == 4 /* defined(__ia64__) */
+#elif ((defined(__mips__) && !defined(MONO_CROSS_COMPILE)) || (defined(TARGET_MIPS))) && SIZEOF_REGISTER == 4 /* defined(__ia64__) */
 
 /* we define our own structure and we'll copy the data
  * from sigcontext/ucontext/mach when we need it.
@@ -371,15 +371,15 @@ mono_ia64_context_get_fp (MonoContext *ctx)
  * the original context from the signal handler.
  */
 typedef struct {
-       gpointer        sc_pc;
-       guint32         sc_regs [32];
+       mgreg_t     sc_pc;
+       mgreg_t         sc_regs [32];
        gfloat          sc_fpregs [32];
 } MonoContext;
 
 /* we have the stack pointer, not the base pointer in sigcontext */
-#define MONO_CONTEXT_SET_IP(ctx,ip) do { (ctx)->sc_pc = (int)(ip); } while (0);
-#define MONO_CONTEXT_SET_BP(ctx,bp) do { (ctx)->sc_regs[mips_fp] = (int)(bp); } while (0);
-#define MONO_CONTEXT_SET_SP(ctx,sp) do { (ctx)->sc_regs[mips_sp] = (int)(sp); } while (0);
+#define MONO_CONTEXT_SET_IP(ctx,ip) do { (ctx)->sc_pc = (mgreg_t)(ip); } while (0);
+#define MONO_CONTEXT_SET_BP(ctx,bp) do { (ctx)->sc_regs[mips_fp] = (mgreg_t)(bp); } while (0);
+#define MONO_CONTEXT_SET_SP(ctx,sp) do { (ctx)->sc_regs[mips_sp] = (mgreg_t)(sp); } while (0);
 
 #define MONO_CONTEXT_GET_IP(ctx) ((gpointer)((ctx)->sc_pc))
 #define MONO_CONTEXT_GET_BP(ctx) ((gpointer)((ctx)->sc_regs[mips_fp]))