diff --git a/sys/arm64/arm64/debug_monitor.c b/sys/arm64/arm64/debug_monitor.c --- 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 __FBSDID("$FreeBSD$"); @@ -181,7 +182,7 @@ isb(); } -#ifdef DDB +#if defined(DDB) || defined(GDB) void kdb_cpu_set_singlestep(void) { @@ -254,7 +255,9 @@ 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 --- a/sys/conf/files.arm +++ b/sys/conf/files.arm @@ -19,8 +19,7 @@ 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 --- a/sys/conf/files.x86 +++ b/sys/conf/files.x86 @@ -320,7 +320,7 @@ 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 --- a/sys/gdb/gdb_main.c +++ b/sys/gdb/gdb_main.c @@ -618,6 +618,100 @@ #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_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 --- a/sys/x86/x86/mp_x86.c +++ b/sys/x86/x86/mp_x86.c @@ -32,6 +32,7 @@ #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 @@ */ invltlb_glob(); -#if defined(__amd64__) && defined(DDB) +#if defined(__amd64__) && (defined(DDB) || defined(GDB)) amd64_db_resume_dbreg(); #endif