Re: watchpoint work failed

"Stanislav" <[email protected]> Sun, 14 Apr 2013 22:37:10 +0300
Newsgroups gmane.comp.emulators.bochs.devel
Message-ID <[email protected]>
Please see the patch (originally submitted to the sourceforge patches
tracker) which was attempting to add watchpoints to the gdb support in
Bochs.
As far as I understood the patch was incomplete and therefore never merged
to main sources tree.
If you could make it work and submit new usable patch - I will be glad to
merge it.

Thanks,
Stanislav

-----Original Message-----
From: ishare [mailto:[email protected]] 
Sent: Saturday, April 06, 2013 4:58 PM
To: [email protected]
Subject: [Bochs-developers] watchpoint work failed


 Does bochs support watchpoint ?

 every time I want to use one watchpoint ,it always tell me : can't insert
watchpoint xx,you probably use too much watchpoint.
 but actually ,I only insert only one point.

 what is the root reason ?  If watchpoint can work fine ,it will be a
benefit for debug :) 

 Thanks!

----------------------------------------------------------------------------
--
Minimize network downtime and maximize team effectiveness.
Reduce network management and security costs.Learn how to hire the most
talented Cisco Certified professionals. Visit the Employer Resources Portal
http://www.cisco.com/web/learning/employer_resources/index.html
_______________________________________________
bochs-developers mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/bochs-developers

------------------------------------------------------------------------------
Precog is a next-generation analytics platform capable of advanced
analytics on semi-structured data. The platform includes APIs for building
apps and a phenomenal toolset for data science. Developers can use
our toolset for easy data analysis & visualization. Get a free account!
http://www2.precog.com/precogplatform/slashdotnewsletter

_______________________________________________
bochs-developers mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/bochs-developers
mp_gdbstub_addwatchpoints.diff (application/octet-stream, 6.3 KB)
Index: bochs.h
===================================================================
RCS file: /cvsroot/bochs/bochs/bochs.h,v
retrieving revision 1.234
diff -u -8 -p -r1.234 bochs.h
--- bochs.h	2 Oct 2008 06:49:20 -0000	1.234
+++ bochs.h	6 Oct 2008 17:48:36 -0000
@@ -107,7 +107,7 @@ extern "C" {
 #endif

 #include "osdep.h"       /* platform dependent includes and defines */
-#include "bx_debug/debug.h"
+//#include "bx_debug/debug.h"
 #include "bxversion.h"

 #include "gui/siminterface.h"
@@ -244,7 +244,7 @@ void print_tree(bx_param_c *node, int le
         bx_dbg_lin_memory_access(cpu, lin, phy, len, pl, rw, data)
 #  define BX_DBG_PHY_MEMORY_ACCESS(cpu, phy, len, rw, data) \
         bx_dbg_phy_memory_access(cpu, phy, len, rw, data)
-#else  // #if BX_DEBUGGER
+#else
 // debugger not compiled in, use empty stubs
 #  define BX_DBG_ASYNC_INTR 1
 #  define BX_DBG_ASYNC_DMA  1
@@ -253,8 +253,16 @@ void print_tree(bx_param_c *node, int le
 #  define BX_DBG_A20_REPORT(val)                                     /* empty */
 #  define BX_DBG_IO_REPORT(addr, size, op, val)                      /* empty */
 #  define BX_DBG_UCMEM_REPORT(addr, size, op, val)                   /* empty */
+#if BX_GDBSTUB
+void bx_gdb_check_memory_watchpoints(unsigned cpu, bx_phy_address phy, unsigned len, unsigned rw);
+#  define BX_DBG_LIN_MEMORY_ACCESS(cpu, lin, phy, len, pl, rw, data) \
+       bx_gdb_check_memory_watchpoints(cpu, phy, len, rw);
+#  define BX_DBG_PHY_MEMORY_ACCESS(cpu, phy, len, rw, data) \
+       bx_gdb_check_memory_watchpoints(cpu, phy, len, rw);
+#else
 #  define BX_DBG_LIN_MEMORY_ACCESS(cpu, lin, phy, len, pl, rw, data) /* empty */
 #  define BX_DBG_PHY_MEMORY_ACCESS(cpu, phy, len, rw, data)          /* empty */
+#endif
 #endif  // #if BX_DEBUGGER

 #define MAGIC_LOGNUM 0x12345678
Index: gdbstub.cc
===================================================================
RCS file: /cvsroot/bochs/bochs/gdbstub.cc,v
retrieving revision 1.33
diff -u -8 -p -r1.33 gdbstub.cc
--- gdbstub.cc	16 Aug 2008 12:29:30 -0000	1.33
+++ gdbstub.cc	6 Oct 2008 17:48:36 -0000
@@ -49,6 +49,17 @@ static BX_CPU_C *current_cpu;
 
 static int last_stop_reason = GDBSTUB_STOP_NO_REASON;
 
+// watchpoint data structure from bx_debug/dbg_main.cc 
+static struct watch {
+  bx_phy_address watch;
+  int len;
+  Bit32u handle;
+  unsigned type; // BX_READ, BX_WRITE, BX_RW
+} watchpoint[BX_DBG_MAX_WATCHPONTS];
+
+static unsigned num_watchpoints = 0;
+bx_bool watchpoint_continue = 0;
+
 #define GDBSTUB_EXECUTION_BREAKPOINT    (0xac1)
 #define GDBSTUB_TRACE                   (0xac2)
 #define GDBSTUB_USER_BREAK              (0xac3)
@@ -254,7 +265,8 @@ static int stub_trace_processor = 0;
 static int instr_count = 0;
 static int saved_eip = 0;
 static int bx_enter_gdbstub = 0;
-
+static int watchpoint_hit = -1;
+static bx_phy_address watchpoint_addr;
 void bx_gdbstub_break(void)
 {
   bx_enter_gdbstub = 1;
@@ -303,7 +315,10 @@ int bx_gdbstub_check(BX_CPU_C *cpu, unsi
       return GDBSTUB_USER_BREAK;
     }
   }
-
+  if(watchpoint_hit>=0) {
+	  last_stop_reason = GDBSTUB_EXECUTION_BREAKPOINT;
+	  return GDBSTUB_EXECUTION_BREAKPOINT;
+  }
   for (i = 0; i < nr_breakpoints; i++)
   {
     if (eip == breakpoints[i])
@@ -365,6 +380,37 @@ static void insert_breakpoint(unsigned i
   BX_INFO(("No slot for breakpoint"));
 }
 
+// Routines leveraged from bx_debug/dbg_main.cc to watch/unwatch a phys address.
+static int bx_gdb_watch(int type, bx_phy_address address, int len) {
+	BX_INFO(("setting watchpoint at type=%x, address=%llx, len=%x", type, address, len));
+	if (num_watchpoints == BX_DBG_MAX_WATCHPONTS) {
+		return 1;
+	}
+	watchpoint[num_watchpoints].watch = address;
+	watchpoint[num_watchpoints].type = type;
+	watchpoint[num_watchpoints].len = len;
+	num_watchpoints++;
+	return 0;
+}
+
+static int bx_gdb_unwatch(int type, bx_phy_address address, int len) {
+	// see if breakpoint is a physical breakpoint
+	for (unsigned i = 0; i < num_watchpoints; i++) {
+		if (watchpoint[i].watch == address && watchpoint[i].len == len) {
+			// found watchpoint, delete it by shifting remaining entries left
+			for (unsigned j = i; j < (num_watchpoints - 1); j++) {
+				watchpoint[j].watch = watchpoint[j + 1].watch;
+				watchpoint[j].type = watchpoint[j + 1].type;
+				watchpoint[j].len = watchpoint[j + 1].len;
+			}
+			num_watchpoints--;
+			return 0;
+			break;
+		}
+	}
+	return 1;
+}
+
 static void do_pc_breakpoint(int insert, unsigned long long addr, int len)
 {
   for (int i = 0; i < len; ++i)
@@ -387,6 +433,18 @@ static void do_breakpoint(int insert, ch
     do_pc_breakpoint(insert, addr, len);
     ret = 0;
     break;
+  case 2:  // Write access watchpoint
+	  if(insert) ret = bx_gdb_watch(1,addr,len);
+	  else ret = bx_gdb_unwatch(3,addr,len);
+	  break;
+  case 3:  // Read access watchpoint 
+	  if(insert) ret = bx_gdb_watch(0,addr,len);
+	  else ret = bx_gdb_unwatch(2,addr,len);
+	  break;
+  case 4:  // Read/write access watchpoint
+	  if(insert) ret = bx_gdb_watch(2,addr,len);
+	  else ret = bx_gdb_unwatch(2,addr,len);
+	  break;
   default:
     put_reply("");
     return;
@@ -486,8 +544,25 @@ void debug_loop(int processor)
 		  write_signal(&sbuf[1], 0);
 	  }
 	  sprintf(&sbuf[3],"thread:%x;",other_thread+1);
+	  if(watchpoint_hit>=0) {
+		  int end = strlen(sbuf);
+		  switch (watchpoint[watchpoint_hit].type) {
+		  case 0:
+			  sprintf(&sbuf[end],"rwatch:%llx;",watchpoint_addr);
+			  break;
+		  case 1:
+			  sprintf(&sbuf[end],"watch:%llx;",watchpoint_addr);
+			  break;
+		  case 2:
+			  sprintf(&sbuf[end],"awatch:%llx;",watchpoint_addr);
+			  break;
+		  default:
+			  break;
+		  }
+	  }
 	  put_reply(sbuf);
   }
+  watchpoint_hit = -1;
   last_stop_reason = GDBSTUB_STOP_NO_REASON;
   stub_trace_flag = 0;
   first_entry = 0;
@@ -975,3 +1050,20 @@ void bx_gdbstub_init(void)
   wait_for_connect(portn);
 
 }
+
+void bx_gdb_check_memory_watchpoints(unsigned cpu, bx_phy_address phy, unsigned len, unsigned rw)
+{
+  // Check for physical write watch points
+  // TODO: Each breakpoint should have an associated CPU#
+  for (unsigned i = 0; i < num_watchpoints; i++) {
+    if (watchpoint[i].type == rw || watchpoint[i].type == BX_RW) {
+      if (watchpoint[i].watch <= (phy + len) && (watchpoint[i].watch + watchpoint[i].len) > phy) {
+        BX_CPU(cpu)->watchpoint  = phy;
+        BX_CPU(cpu)->break_point = rw;
+        watchpoint_hit = i;
+        watchpoint_addr = phy;
+        break;
+      }
+    }
+  }
+}