Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 30 Mar 2021 14:37:04 GMT
From:      Mitchell Horne <mhorne@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org
Subject:   git: 4beb385813c8 - main - gdb: allow setting/removing hardware watchpoints
Message-ID:  <202103301437.12UEb4OP039851@gitrepo.freebsd.org>

next in thread | raw e-mail | index | archive | help
The branch main has been updated by mhorne:

URL: https://cgit.FreeBSD.org/src/commit/?id=4beb385813c8b1014f8250a31b07fdc09a059713

commit 4beb385813c8b1014f8250a31b07fdc09a059713
Author:     Mitchell Horne <mhorne@FreeBSD.org>
AuthorDate: 2021-03-08 19:03:45 +0000
Commit:     Mitchell Horne <mhorne@FreeBSD.org>
CommitDate: 2021-03-30 14:36:41 +0000

    gdb: allow setting/removing hardware watchpoints
    
    Handle the 'z' and 'Z' remote packets for manipulating hardware
    watchpoints.
    
    This could be expanded quite easily to support hardware or software
    breakpoints as well.
    
    https://sourceware.org/gdb/onlinedocs/gdb/Packets.html
    
    Reviewed by:    cem, markj
    MFC after:      3 weeks
    Sponsored by:   NetApp, Inc.
    Sponsored by:   Klara, Inc.
    NetApp PR:      51
    Differential Revision:  https://reviews.freebsd.org/D29173
---
 sys/arm64/arm64/debug_monitor.c |   5 +-
 sys/conf/files.arm              |   3 +-
 sys/conf/files.x86              |   2 +-
 sys/gdb/gdb_main.c              | 102 ++++++++++++++++++++++++++++++++++++++++
 sys/x86/x86/mp_x86.c            |   3 +-
 5 files changed, 110 insertions(+), 5 deletions(-)

diff --git a/sys/arm64/arm64/debug_monitor.c b/sys/arm64/arm64/debug_monitor.c
index 845784129b4c..c3dce1883e68 100644
--- a/sys/arm64/arm64/debug_monitor.c
+++ b/sys/arm64/arm64/debug_monitor.c
@@ -28,6 +28,7 @@
  */
 
 #include "opt_ddb.h"
+#include "opt_gdb.h"
 
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
@@ -181,7 +182,7 @@ dbg_wb_write_reg(int reg, int n, uint64_t val)
 	isb();
 }
 
-#ifdef DDB
+#if defined(DDB) || defined(GDB)
 void
 kdb_cpu_set_singlestep(void)
 {
@@ -254,7 +255,9 @@ kdb_cpu_clr_watchpoint(vm_offset_t addr, vm_size_t size)
 
 	return (dbg_remove_watchpoint(NULL, addr, size));
 }
+#endif /* DDB || GDB */
 
+#ifdef DDB
 static const char *
 dbg_watchtype_str(uint32_t type)
 {
diff --git a/sys/conf/files.arm b/sys/conf/files.arm
index 69986585bdf6..a3b0d166f020 100644
--- a/sys/conf/files.arm
+++ b/sys/conf/files.arm
@@ -19,8 +19,7 @@ arm/arm/cpu_asm-v6.S		standard
 arm/arm/db_disasm.c		optional	ddb
 arm/arm/db_interface.c		optional	ddb
 arm/arm/db_trace.c		optional	ddb
-arm/arm/debug_monitor.c		optional	ddb armv6
-arm/arm/debug_monitor.c		optional	ddb armv7
+arm/arm/debug_monitor.c		optional	ddb | gdb
 arm/arm/disassem.c		optional	ddb
 arm/arm/dump_machdep.c		standard
 arm/arm/elf_machdep.c		standard
diff --git a/sys/conf/files.x86 b/sys/conf/files.x86
index fd31d95fa162..0f83126e99a6 100644
--- a/sys/conf/files.x86
+++ b/sys/conf/files.x86
@@ -320,7 +320,7 @@ x86/x86/bus_machdep.c		standard
 x86/x86/busdma_bounce.c		standard
 x86/x86/busdma_machdep.c	standard
 x86/x86/cpu_machdep.c		standard
-x86/x86/dbreg.c			optional	ddb
+x86/x86/dbreg.c			optional	ddb | gdb
 x86/x86/dump_machdep.c		standard
 x86/x86/fdt_machdep.c		optional	fdt
 x86/x86/identcpu.c		standard
diff --git a/sys/gdb/gdb_main.c b/sys/gdb/gdb_main.c
index a9e935ebfbb5..a4469fdf4997 100644
--- a/sys/gdb/gdb_main.c
+++ b/sys/gdb/gdb_main.c
@@ -618,6 +618,100 @@ gdb_handle_detach(void)
 #endif
 }
 
+/*
+ * Handle a 'Z' packet: set a breakpoint or watchpoint.
+ *
+ * Currently, only watchpoints are supported.
+ */
+static void
+gdb_z_insert(void)
+{
+	intmax_t addr, length;
+	char ztype;
+	int error;
+
+	ztype = gdb_rx_char();
+	if (gdb_rx_char() != ',' || gdb_rx_varhex(&addr) ||
+	    gdb_rx_char() != ',' || gdb_rx_varhex(&length)) {
+		error = EINVAL;
+		goto fail;
+	}
+
+	switch (ztype) {
+	case '2': /* write watchpoint */
+		error = kdb_cpu_set_watchpoint((vm_offset_t)addr,
+		    (vm_size_t)length, KDB_DBG_ACCESS_W);
+		break;
+	case '3': /* read watchpoint */
+		error = kdb_cpu_set_watchpoint((vm_offset_t)addr,
+		    (vm_size_t)length, KDB_DBG_ACCESS_R);
+		break;
+	case '4': /* access (RW) watchpoint */
+		error = kdb_cpu_set_watchpoint((vm_offset_t)addr,
+		    (vm_size_t)length, KDB_DBG_ACCESS_RW);
+		break;
+	case '1': /* hardware breakpoint */
+	case '0': /* software breakpoint */
+		/* Not implemented. */
+		gdb_tx_empty();
+		return;
+	default:
+		error = EINVAL;
+		break;
+	}
+	if (error != 0)
+		goto fail;
+	gdb_tx_ok();
+	return;
+fail:
+	gdb_tx_err(error);
+	return;
+}
+
+/*
+ * Handle a 'z' packet; clear a breakpoint or watchpoint.
+ *
+ * Currently, only watchpoints are supported.
+ */
+static void
+gdb_z_remove(void)
+{
+	intmax_t addr, length;
+	char ztype;
+	int error;
+
+	ztype = gdb_rx_char();
+	if (gdb_rx_char() != ',' || gdb_rx_varhex(&addr) ||
+	    gdb_rx_char() != ',' || gdb_rx_varhex(&length)) {
+		error = EINVAL;
+		goto fail;
+	}
+
+	switch (ztype) {
+	case '2': /* write watchpoint */
+	case '3': /* read watchpoint */
+	case '4': /* access (RW) watchpoint */
+		error = kdb_cpu_clr_watchpoint((vm_offset_t)addr,
+		    (vm_size_t)length);
+		break;
+	case '1': /* hardware breakpoint */
+	case '0': /* software breakpoint */
+		/* Not implemented. */
+		gdb_tx_empty();
+		return;
+	default:
+		error = EINVAL;
+		break;
+	}
+	if (error != 0)
+		goto fail;
+	gdb_tx_ok();
+	return;
+fail:
+	gdb_tx_err(error);
+	return;
+}
+
 static int
 gdb_trap(int type, int code)
 {
@@ -868,6 +962,14 @@ gdb_trap(int type, int code)
 				gdb_tx_err(ENOENT);
 			break;
 		}
+		case 'z': {	/* Remove watchpoint. */
+			gdb_z_remove();
+			break;
+		}
+		case 'Z': {	/* Set watchpoint. */
+			gdb_z_insert();
+			break;
+		}
 		case EOF:
 			/* Empty command. Treat as unknown command. */
 			/* FALLTHROUGH */
diff --git a/sys/x86/x86/mp_x86.c b/sys/x86/x86/mp_x86.c
index 0f528f6567ee..2dcdf923c467 100644
--- a/sys/x86/x86/mp_x86.c
+++ b/sys/x86/x86/mp_x86.c
@@ -32,6 +32,7 @@ __FBSDID("$FreeBSD$");
 #endif
 #include "opt_cpu.h"
 #include "opt_ddb.h"
+#include "opt_gdb.h"
 #include "opt_kstack_pages.h"
 #include "opt_pmap.h"
 #include "opt_sched.h"
@@ -1520,7 +1521,7 @@ cpustop_handler_post(u_int cpu)
 	 */
 	invltlb_glob();
 
-#if defined(__amd64__) && defined(DDB)
+#if defined(__amd64__) && (defined(DDB) || defined(GDB))
 	amd64_db_resume_dbreg();
 #endif
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202103301437.12UEb4OP039851>