[kgtp] r1574 committed - Add $watch_prev_val

  • From: kgtp@xxxxxxxxxxxxxx
  • To: kgtp@xxxxxxxxxxxxx
  • Date: Wed, 29 May 2013 05:14:33 +0000

Revision: 1574
Author:   teawater
Date:     Tue May 28 22:14:05 2013
Log:      Add $watch_prev_val

http://code.google.com/p/kgtp/source/detail?r=1574

Modified:
 /trunk/gtp.c
 /trunk/gtp.h

=======================================
--- /trunk/gtp.c        Thu May  9 05:33:59 2013
+++ /trunk/gtp.c        Tue May 28 22:14:05 2013
@@ -508,6 +508,10 @@
        int                     size;
        int                     type;

+       /* The previous of the address that this watch tracepoint
+          watch on.  */
+       int64_t                 prev_val;
+
        /* This is the num and address that setup this hardware
           breakpoints.
           For the static watch, this is the num and address of this
@@ -793,13 +797,14 @@
        GTP_WATCH_TRACE_ADDR_ID                 = 40,
        GTP_WATCH_ADDR_ID                       = 41,
        GTP_WATCH_VAL_ID                        = 42,
+       GTP_WATCH_PREV_VAL_ID                   = 46,
        GTP_WATCH_COUNT_ID                      = 43,

        GTP_STEP_COUNT_ID                       = 44,
        GTP_STEP_ID_ID                          = 45,

        GTP_VAR_SPECIAL_MIN                     = GTP_VAR_VERSION_ID,
-       GTP_VAR_SPECIAL_MAX                     = GTP_STEP_ID_ID,
+       GTP_VAR_SPECIAL_MAX                     = GTP_WATCH_PREV_VAL_ID,
 };

 enum pe_tv_id {
@@ -1751,10 +1756,56 @@
        .agent_get_val = gtp_watch_get_val,
 };

+static int     gtp_get_addr_val(CORE_ADDR addr, int size, int64_t *val);
+
 static int
 gtp_watch_val_get_val(struct gtp_trace_s *gts, struct gtp_var *gtv,
                      int64_t *val)
 {
+       int     ret;
+
+       if (gts->tpe->type == gtp_entry_kprobe)
+               return -EINVAL;
+
+       if (gts->hwb_current_val_gotten) {
+               *val = gts->hwb_current_val;
+               return 0;
+       }
+
+       ret = gtp_get_addr_val(gts->hwb->addr, gts->hwb->size, val);
+       if (ret == 0) {
+               gts->hwb_current_val = *val;
+               gts->hwb_current_val_gotten = 1;
+       }
+
+       return ret;
+}
+
+static struct gtp_var_hooks    gtp_watch_val_hooks = {
+       .agent_get_val = gtp_watch_val_get_val,
+};
+
+static int
+gtp_watch_prev_val_get_val(struct gtp_trace_s *gts, struct gtp_var *gtv,
+                          int64_t *val)
+{
+       if (gts->tpe->type == gtp_entry_kprobe)
+               return -EINVAL;
+
+       *val = gts->hwb->prev_val;
+       return 0;
+}
+
+static struct gtp_var_hooks    gtp_watch_prev_val_hooks = {
+       .agent_get_val = gtp_watch_prev_val_get_val,
+};
+#endif
+
+static int
+gtp_get_addr_val(CORE_ADDR addr, int size, int64_t *val)
+{
+       int     ret = -EINVAL;
+
        union {
                union {
                        uint8_t bytes[1];
@@ -1774,40 +1825,44 @@
                } u64;
        } cnv;

-       if (gts->tpe->type == gtp_entry_kprobe)
-               return -1;
-
-       switch (gts->hwb->size) {
+       switch (size) {
        case 1:
-               if (probe_kernel_read(cnv.u8.bytes, (void *)gts->hwb->addr, 1))
-                       return -1;
+               ret = probe_kernel_read(cnv.u8.bytes, (void *)addr, 1);
+               if (ret)
+                       goto error;
                *val = (int64_t) cnv.u8.val;
                break;
        case 2:
-               if (probe_kernel_read(cnv.u16.bytes, (void *)gts->hwb->addr, 2))
-                       return -1;
+               ret = probe_kernel_read(cnv.u16.bytes, (void *)addr, 2);
+               if (ret)
+                       goto error;
                *val = (int64_t) cnv.u16.val;
                break;
        case 4:
-               if (probe_kernel_read(cnv.u32.bytes, (void *)gts->hwb->addr, 4))
-                       return -1;
+               ret = probe_kernel_read(cnv.u32.bytes, (void *)addr, 4);
+               if (ret)
+                       goto error;
                *val = (int64_t) cnv.u32.val;
                break;
        case 8:
-               if (probe_kernel_read(cnv.u64.bytes, (void *)gts->hwb->addr, 8))
-                       return -1;
+               ret = probe_kernel_read(cnv.u64.bytes, (void *)addr, 8);
+               if (ret)
+                       goto error;
                *val = (int64_t) cnv.u64.val;
                break;
+       default:
+               goto error;
+               break;
        }

        return 0;
+
+error:
+       printk(KERN_WARNING "KGTP: fail get value from address %p size %d.\n",
+              (void *)addr, size);
+       return ret;
 }

-static struct gtp_var_hooks    gtp_watch_val_hooks = {
-       .agent_get_val = gtp_watch_val_get_val,
-};
-#endif
-
 #ifdef GTP_RB
 static int
 gtp_step_count_hooks_get_val(struct gtp_trace_s *gts, struct gtp_var *gtv,
@@ -2059,6 +2114,10 @@
        var = gtp_var_special_add(GTP_WATCH_VAL_ID, 0, 0,
                                  "watch_val", &gtp_watch_val_hooks);
        if (IS_ERR(var))
+               return PTR_ERR(var);
+       var = gtp_var_special_add(GTP_WATCH_PREV_VAL_ID, 0, 0,
+                                 "watch_prev_val", &gtp_watch_prev_val_hooks);
+       if (IS_ERR(var))
                return PTR_ERR(var);
        var = gtp_var_special_add(GTP_WATCH_COUNT_ID, 0, 0,
                                  "watch_count", &gtp_watch_get_hooks);
@@ -5622,6 +5681,28 @@

        return 0;
 }
+
+static void
+gtp_hw_breakpoint_handler_1 (struct gtp_hwb_s *hwb, struct pt_regs *regs)
+{
+       struct gtp_trace_s      gts;
+
+       preempt_disable();
+
+       memset(&gts, 0, sizeof(struct gtp_trace_s));
+       gts.tpe = hwb->watch;
+       gts.regs = regs;
+       gts.hwb = hwb;
+       gtp_handler(&gts);
+
+       preempt_enable_no_resched();
+
+       /* Update hwb->prev_val.  */
+       if (gts.hwb_current_val_gotten)
+               hwb->prev_val = gts.hwb_current_val;
+       else
+               gtp_get_addr_val(hwb->addr, hwb->size, &(hwb->prev_val));
+}

 #ifdef CONFIG_X86
 #define ADDR_PREFIX_OPCODE 0x67
@@ -5802,17 +5883,7 @@
                        if (addr != gtp_hwb[i].addr)
                                continue;
                }
-               preempt_disable();
-               {
-                       struct gtp_trace_s      gts;
-
-                       memset(&gts, 0, sizeof(struct gtp_trace_s));
-                       gts.tpe = gtp_hwb[i].watch;
-                       gts.regs = args->regs;
-                       gts.hwb = &gtp_hwb[i];
-                       gtp_handler(&gts);
-               }
-               preempt_enable_no_resched();
+               gtp_hw_breakpoint_handler_1(&gtp_hwb[i], args->regs);
        }

        /* If the HWB need update in this CPU, just update it.  */
@@ -5874,17 +5945,7 @@
                }
        }

-       preempt_disable();
-       {
-               struct gtp_trace_s      gts;
-
-               memset(&gts, 0, sizeof(struct gtp_trace_s));
-               gts.tpe = gtp_hwb[num].watch;
-               gts.regs = regs;
-               gts.hwb = &gtp_hwb[num];
-               gtp_handler(&gts);
-       }
-       preempt_enable_no_resched();
+       gtp_hw_breakpoint_handler_1(&gtp_hwb[num], regs);

        read_unlock(&gtp_hwb_lock);
 }
@@ -6007,6 +6068,12 @@
        write_lock_irqsave(&gtp_hwb_lock, flags);
        if (!list_empty(&gtp_hwb_unused_list)) {
                int     num;
+               int64_t prev_val;
+
+               /* Get the value from address that will watch as prev value.  */
+               ret = gtp_get_addr_val(arg->addr, arg->size, &prev_val);
+               if (ret)
+                       goto out;

                hwb = list_first_entry(&gtp_hwb_unused_list, struct gtp_hwb_s, 
node);
                list_del_init(&hwb->node);
@@ -6015,6 +6082,7 @@
                memcpy((void *)&arg->node, (void *)&hwb->node, sizeof 
(hwb->node));
                memcpy(hwb, arg, sizeof(struct gtp_hwb_s));
                hwb->num = num;
+               hwb->prev_val = prev_val;

                /* Update gtp_hwb_dr7 and gtp_hwb_drx[num].  */
                /* Set Gx.  */
@@ -6048,6 +6116,7 @@

                ret = 0;
        }
+out:
        write_unlock_irqrestore(&gtp_hwb_lock, flags);

        if (ret == 0 && !nowait)
=======================================
--- /trunk/gtp.h        Fri Apr 12 00:19:48 2013
+++ /trunk/gtp.h        Tue May 28 22:14:05 2013
@@ -114,6 +114,10 @@
           HWB point to the struct.
           If not, it will set to NULL.  */
        struct gtp_hwb_s                *hwb;
+       /* hwb_current_val have the value of hwb address watch
+          when hwb_current_val_gotten is true.  */
+       int64_t                         hwb_current_val;
+       int                             hwb_current_val_gotten;

        int64_t                         printk_tmp;
        unsigned int                    printk_level;

Other related posts:

  • » [kgtp] r1574 committed - Add $watch_prev_val - kgtp