diff -u -r valgrind-3.6.0~svn20100212/memcheck/mc_main.c /home/gopalv/hacks/valgrind-3.6.0~svn20100212/memcheck/mc_main.c
--- valgrind-3.6.0~svn20100212/memcheck/mc_main.c	2010-02-12 19:00:14.000000000 +0530
+++ /home/gopalv/hacks/valgrind-3.6.0~svn20100212/memcheck/mc_main.c	2010-07-16 00:50:24.000000000 +0530
@@ -264,7 +264,28 @@
 }
 
 typedef 
+   struct Watchpoint {
+      UInt id;
+      Addr a;
+      SizeT len;
+      UInt count;
+      UInt enabled;
+      struct Watchpoint *next;
+      struct Watchpoint *prev;
+   }
+   Watchpoint;
+
+typedef 
+   struct WatchpointData {
+      Watchpoint *wp;
+      struct WatchpointData *next;
+      struct WatchpointData *prev;
+   }
+   WatchpointData;
+
+typedef 
    struct {
+      WatchpointData *watchpoints;
       UChar vabits8[SM_CHUNKS];
    }
    SecMap;
@@ -1653,6 +1674,224 @@
    }
 }
 
+static UInt current_watchpoint = 0;
+static UInt watchpoint_count = 0;
+static Watchpoint* watchpoints = NULL;
+
+static UInt mc_set_watchpoint(ThreadId tid, Addr a, SizeT len)
+{
+   Watchpoint *p;
+   Addr b, c;
+   
+   p = VG_(malloc)("mc_set_watchpoint",sizeof(Watchpoint));
+   p->id = current_watchpoint++;
+   p->count = 0;
+   p->a = a;
+   p->len = len;
+
+   watchpoint_count++;
+
+   if(watchpoints == NULL) 
+   {
+      watchpoints = p;
+      p->prev = NULL;
+      p->next = NULL;
+   }
+   else
+   {
+      Watchpoint* i = watchpoints;
+      while(i->next) i = i->next;
+      i->next = p;
+      p->prev = i;
+      p->next = NULL;
+   }
+
+
+   b = start_of_this_sm(a);
+   c = start_of_this_sm(a + len) + SM_SIZE; /* next sm */
+
+   while(b < c) 
+   {
+      SecMap *sm = get_secmap_for_writing(b);
+      WatchpointData *d = VG_(malloc)("mc_set_watchpoint", sizeof(WatchpointData));
+
+      d->wp = p;
+      d->next = sm->watchpoints;
+      d->prev = NULL;
+      if(d->next) d->next->prev = d;
+      sm->watchpoints = d;
+      b += SM_SIZE;
+   }
+
+   if (VG_(clo_xml)) 
+   {
+      VG_(printf_xml)("<watchpoint id=\"%d\" addr=\"%p\" len=\"%ld\">\n", p->id, (void*)p->a, (long)p->len);
+      VG_(printf_xml)("  <location>\n");
+      VG_(pp_ExeContext)(VG_(record_ExeContext(tid, 0)));
+      VG_(printf_xml)("  </location>\n</watchpoint>\n");
+   }
+   else
+   {
+      VG_(message)(Vg_UserMsg, "Created watchpoint %d for %p[+%ld]\n", p->id, (void*)p->a, (long)p->len);
+   }
+
+   return p->id;
+}
+
+static UInt mc_clear_watchpoint(UInt wpid)
+{
+   Watchpoint *p;
+   Addr b, c;
+
+   for(p = watchpoints; p; p = p->next)
+   {
+      if(p->id == wpid)
+      {
+         if(p->prev) p->prev->next = p->next;
+         else watchpoints = p->next;
+
+         if(p->next) p->next->prev = p->prev;
+         break;
+      }
+   }
+
+   if(p == NULL)
+   {
+      return 0;
+   }
+
+   b = start_of_this_sm(p->a);
+   c = start_of_this_sm(p->a + p->len) + SM_SIZE; /* next sm */
+
+   while(b < c) 
+   {
+      SecMap *sm = get_secmap_for_writing(b);
+      WatchpointData *d = sm->watchpoints;
+
+      while(d) 
+      {
+         if(d->wp == p)
+         {
+            if(d->prev) d->prev->next = d->next;
+            else sm->watchpoints = d->next;
+
+            if(d->next) d->next->prev = d->prev;
+            VG_(free)(d);
+            break;
+         }
+         d = d->next;
+      }
+
+      b += SM_SIZE;
+   }
+
+   if(VG_(clo_xml)) 
+   {
+   }
+   else
+   {
+      VG_(message)(Vg_UserMsg, "Cleared watchpoint %d\n", p->id);
+   }
+   VG_(free)(p);
+
+   return 1;
+}
+
+static UInt mc_flip_watchpoint(UInt wpid, UInt status)
+{
+   Watchpoint *p;
+
+   for(p = watchpoints; p; p = p->next)
+   {
+      if(p->id == wpid)
+      {
+         break;
+      }
+   }
+
+   if(p == NULL)
+   {
+      return 0;
+   }
+
+   p->enabled = status;
+
+   if(VG_(clo_xml)) 
+   {
+   }
+   else
+   {
+      VG_(message)(Vg_UserMsg, "%s watchpoint %d\n", status?"Enabling":"Disabling", p->id);
+   }
+
+   return 1;
+}
+
+static void mc_watchpoint_message(Char* event, Watchpoint *wp, Addr a, SizeT len, ExeContext *e) 
+{
+   if(VG_(clo_xml)) 
+   {
+      VG_(printf_xml)("<watchpointevent id=\"%d\" event=\"%s\">\n", wp->id, event);
+      VG_(printf_xml)("  <watch addr=\"%p\" len=\"%ld\">\n", (void*)wp->a, (long)wp->len);
+      VG_(printf_xml)("     <write addr=\"%p\" len=\"%ld\" />\n", (void*)a, (long)len);
+      VG_(printf_xml)("  </watch>\n");
+
+      VG_(printf_xml)("  <location>\n");
+      VG_(pp_ExeContext)(e);
+      VG_(printf_xml)("  </location>\n</watchpointevent>\n");
+   }
+   else
+   {
+      VG_(message)(Vg_UserMsg, "Hit watchpoint %d (%s)\n", wp->id, event);
+   }
+}
+
+static Bool mc_check_watchpoint(Addr a, SizeT len, Watchpoint **wp_ptr)
+{
+   Addr b = start_of_this_sm(a);
+   Addr c = start_of_this_sm(a + len) + SM_SIZE; /* next sm */
+
+   while(b < c)
+   {
+      SecMap *sm = get_secmap_for_reading(b);
+      WatchpointData *d;
+
+      for(d = sm->watchpoints; d; d = d->next)
+      {
+         Watchpoint *wp = d->wp; 
+         Addr end, wp_end;
+
+         end = a+len-1;
+         wp_end = wp->a + wp->len-1;
+
+         if(!wp->enabled) continue;
+
+         if(
+            (a >= wp->a && a <= (wp_end)) ||     // starts inside
+            ((end >= wp->a) && (end <= wp_end))  // ends inside
+            )
+         {
+            *wp_ptr = wp;
+            wp->count++;
+            return True;
+         }
+      }
+
+      b += SM_SIZE;
+   }
+
+   return False;
+}
+
+#define CHECK_WATCHPOINT(op, a, len)\
+   do {\
+      Watchpoint *wp;\
+      if(watchpoint_count && mc_check_watchpoint((a), (len), &wp)) {\
+         mc_watchpoint_message((op), wp, (a), (len), VG_(record_ExeContext)(VG_(get_running_tid)(), 0));\
+      }\
+   } while(0)
+
+
 /* --- Block-copy permissions (needed for implementing realloc() and
        sys_mremap). --- */
 
@@ -4058,6 +4297,8 @@
 {
    PROF_EVENT(210, "mc_STOREV64");
 
+   CHECK_WATCHPOINT("mc_STOREV64", a, 8); 
+
 #ifndef PERF_FAST_STOREV
    // XXX: this slow case seems to be marginally faster than the fast case!
    // Investigate further.
@@ -4167,6 +4408,7 @@
 void mc_STOREV32 ( Addr a, UWord vbits32, Bool isBigEndian )
 {
    PROF_EVENT(230, "mc_STOREV32");
+   CHECK_WATCHPOINT("mc_STOREV32", a, 4); 
 
 #ifndef PERF_FAST_STOREV
    mc_STOREVn_slow( a, 32, (ULong)vbits32, isBigEndian );
@@ -4285,6 +4527,7 @@
 void mc_STOREV16 ( Addr a, UWord vbits16, Bool isBigEndian )
 {
    PROF_EVENT(250, "mc_STOREV16");
+   CHECK_WATCHPOINT("mc_STOREV16", a, 2); 
 
 #ifndef PERF_FAST_STOREV
    mc_STOREVn_slow( a, 16, (ULong)vbits16, isBigEndian );
@@ -4388,6 +4631,7 @@
 void MC_(helperc_STOREV8) ( Addr a, UWord vbits8 )
 {
    PROF_EVENT(270, "mc_STOREV8");
+   CHECK_WATCHPOINT("mc_STOREV8", a, 1); 
 
 #ifndef PERF_FAST_STOREV
    mc_STOREVn_slow( a, 8, (ULong)vbits8, False/*irrelevant*/ );
@@ -4603,12 +4847,15 @@
    /* Build the 3 distinguished secondaries */
    sm = &sm_distinguished[SM_DIST_NOACCESS];
    for (i = 0; i < SM_CHUNKS; i++) sm->vabits8[i] = VA_BITS8_NOACCESS;
+   sm->watchpoints = NULL;
 
    sm = &sm_distinguished[SM_DIST_UNDEFINED];
    for (i = 0; i < SM_CHUNKS; i++) sm->vabits8[i] = VA_BITS8_UNDEFINED;
+   sm->watchpoints = NULL;
 
    sm = &sm_distinguished[SM_DIST_DEFINED];
    for (i = 0; i < SM_CHUNKS; i++) sm->vabits8[i] = VA_BITS8_DEFINED;
+   sm->watchpoints = NULL;
 
    /* Set up the primary map. */
    /* These entries gradually get overwritten as the used address
@@ -5199,6 +5446,27 @@
 	 return True;
       }
 
+      case VG_USERREQ__SET_WATCHPOINT: {
+      	 Addr a = (Addr)arg[1];
+      	 SizeT len = (Addr)arg[2];
+      	 *ret = mc_set_watchpoint(tid, a, len);
+      	 return True;
+      }
+
+      case VG_USERREQ__CLEAR_WATCHPOINT: {
+      	 UInt wpid = (UInt)arg[1];
+      	 *ret = mc_clear_watchpoint(wpid);
+      	 return True;
+      }
+
+      case VG_USERREQ__ENABLE_WATCHPOINT:
+      case VG_USERREQ__DISABLE_WATCHPOINT: {
+      	 UInt wpid = (UInt)arg[1];
+          UInt status = (UInt)arg[2];
+      	 *ret = mc_flip_watchpoint(wpid, status);
+      	 return True;
+      }
+
 
       default:
          VG_(message)(
diff -u -r valgrind-3.6.0~svn20100212/memcheck/memcheck.h /home/gopalv/hacks/valgrind-3.6.0~svn20100212/memcheck/memcheck.h
--- valgrind-3.6.0~svn20100212/memcheck/memcheck.h	2010-02-12 19:00:14.000000000 +0530
+++ /home/gopalv/hacks/valgrind-3.6.0~svn20100212/memcheck/memcheck.h	2010-07-15 23:49:23.000000000 +0530
@@ -95,6 +95,10 @@
 
       /* Not next to VG_USERREQ__COUNT_LEAKS because it was added later. */
       VG_USERREQ__COUNT_LEAK_BLOCKS,
+      VG_USERREQ__SET_WATCHPOINT,
+      VG_USERREQ__CLEAR_WATCHPOINT,
+      VG_USERREQ__ENABLE_WATCHPOINT,
+      VG_USERREQ__DISABLE_WATCHPOINT,
 
       /* This is just for memcheck's internal use - don't use it */
       _VG_USERREQ__MEMCHECK_RECORD_OVERLAP_ERROR 
@@ -305,5 +309,39 @@
     _qzz_res;                                                    \
    }))
 
+
+#define VALGRIND_SET_WATCHPOINT(_qzz_addr,_qzz_len)        \
+   (__extension__({unsigned long _qzz_res;                       \
+    VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0,                      \
+                            VG_USERREQ__SET_WATCHPOINT,    \
+                            _qzz_addr, _qzz_len, 0, 0, 0);       \
+    _qzz_res;                                                    \
+   }))
+
+#define VALGRIND_ENABLE_WATCHPOINT(_qzz_wpid)        \
+   (__extension__({unsigned long _qzz_res;                       \
+    VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0,                      \
+                            VG_USERREQ__ENABLE_WATCHPOINT,    \
+                            _qzz_wpid, 1, 0, 0, 0);       \
+    _qzz_res;                                                    \
+   }))
+
+#define VALGRIND_DISABLE_WATCHPOINT(_qzz_wpid)        \
+   (__extension__({unsigned long _qzz_res;                       \
+    VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0,                      \
+                            VG_USERREQ__DISABLE_WATCHPOINT,    \
+                            _qzz_wpid, 0, 0, 0, 0);       \
+    _qzz_res;                                                    \
+   }))
+
+
+#define VALGRIND_CLEAR_WATCHPOINT(_qzz_wpid)        \
+   (__extension__({unsigned long _qzz_res;                       \
+    VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0,                      \
+                            VG_USERREQ__CLEAR_WATCHPOINT,    \
+                            _qzz_wpid, 0, 0, 0, 0);       \
+    _qzz_res;                                                    \
+   }))
+
 #endif
 
