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;
+ }
+ }
+ }
+}