diff --git a/sys/amd64/amd64/gdb_machdep.c b/sys/amd64/amd64/gdb_machdep.c --- a/sys/amd64/amd64/gdb_machdep.c +++ b/sys/amd64/amd64/gdb_machdep.c @@ -49,6 +49,7 @@ #include #include +#include void * gdb_cpu_getreg(int regnum, size_t *regsz) @@ -152,6 +153,40 @@ return (SIGEMT); } +void +gdb_cpu_stop_reason(int type, int code) +{ + uintmax_t val; + + val = 0; + if (type == T_TRCTRAP) { + /* NB: 'code' contains the value of dr6 at the trap. */ + if ((code & DBREG_DR6_B(0)) != 0) { + val = rdr0(); + } + if ((code & DBREG_DR6_B(1)) != 0) { + val = rdr1(); + } + if ((code & DBREG_DR6_B(2)) != 0) { + val = rdr2(); + } + if ((code & DBREG_DR6_B(3)) != 0) { + val = rdr3(); + } + + /* + * TODO: validate the bits in DR7 to differentiate between a + * watchpoint trap and a hardware breakpoint trap (currently + * unsupported). + */ + if (val != 0) { + gdb_tx_str("watch:"); + gdb_tx_varhex(val); + gdb_tx_char(';'); + } + } +} + void * gdb_begin_write(void) { diff --git a/sys/amd64/include/gdb_machdep.h b/sys/amd64/include/gdb_machdep.h --- a/sys/amd64/include/gdb_machdep.h +++ b/sys/amd64/include/gdb_machdep.h @@ -72,5 +72,6 @@ void gdb_cpu_setreg(int, void *); int gdb_cpu_signal(int, int); void gdb_end_write(void *); +void gdb_cpu_stop_reason(int, int); #endif /* !_MACHINE_GDB_MACHDEP_H_ */ diff --git a/sys/arm/include/gdb_machdep.h b/sys/arm/include/gdb_machdep.h --- a/sys/arm/include/gdb_machdep.h +++ b/sys/arm/include/gdb_machdep.h @@ -66,6 +66,12 @@ } +static __inline void +gdb_cpu_stop_reason(int type __unused, int code __unused) +{ + +} + void *gdb_cpu_getreg(int, size_t *); void gdb_cpu_setreg(int, void *); int gdb_cpu_signal(int, int); diff --git a/sys/arm64/arm64/gdb_machdep.c b/sys/arm64/arm64/gdb_machdep.c --- a/sys/arm64/arm64/gdb_machdep.c +++ b/sys/arm64/arm64/gdb_machdep.c @@ -41,6 +41,7 @@ #include #include +#include void * gdb_cpu_getreg(int regnum, size_t *regsz) @@ -110,3 +111,14 @@ } return (SIGEMT); } + +void +gdb_cpu_stop_reason(int type, int code __unused) +{ + + if (type == EXCP_WATCHPT_EL1) { + gdb_tx_str("watch:"); + gdb_tx_varhex((uintmax_t)READ_SPECIALREG(far_el1)); + gdb_tx_char(';'); + } +} diff --git a/sys/arm64/include/gdb_machdep.h b/sys/arm64/include/gdb_machdep.h --- a/sys/arm64/include/gdb_machdep.h +++ b/sys/arm64/include/gdb_machdep.h @@ -77,5 +77,6 @@ void *gdb_cpu_getreg(int, size_t *); void gdb_cpu_setreg(int, void *); int gdb_cpu_signal(int, int); +void gdb_cpu_stop_reason(int, int); #endif /* !_MACHINE_GDB_MACHDEP_H_ */ 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 @@ -741,8 +741,9 @@ gdb_tx_char(':'); gdb_tx_reg(GDB_REG_PC); gdb_tx_char(';'); + gdb_cpu_stop_reason(type, code); gdb_tx_str("thread:"); - gdb_tx_varhex((long)kdb_thread->td_tid); + gdb_tx_varhex((uintmax_t)kdb_thread->td_tid); gdb_tx_char(';'); gdb_tx_end(); /* XXX check error condition. */ diff --git a/sys/i386/i386/gdb_machdep.c b/sys/i386/i386/gdb_machdep.c --- a/sys/i386/i386/gdb_machdep.c +++ b/sys/i386/i386/gdb_machdep.c @@ -36,13 +36,15 @@ #include #include +#include +#include #include #include +#include #include -#include -#include #include +#include void * gdb_cpu_getreg(int regnum, size_t *regsz) @@ -114,3 +116,37 @@ } return (SIGEMT); } + +void +gdb_cpu_stop_reason(int type, int code) +{ + uintmax_t val; + + val = 0; + if (type == T_TRCTRAP) { + /* NB: 'code' contains the value of dr6 at the trap. */ + if ((code & DBREG_DR6_B(0)) != 0) { + val = rdr0(); + } + if ((code & DBREG_DR6_B(1)) != 0) { + val = rdr1(); + } + if ((code & DBREG_DR6_B(2)) != 0) { + val = rdr2(); + } + if ((code & DBREG_DR6_B(3)) != 0) { + val = rdr3(); + } + + /* + * TODO: validate the bits in DR7 to differentiate between a + * watchpoint trap and a hardware breakpoint trap (currently + * unsupported). + */ + if (val != 0) { + gdb_tx_str("watch:"); + gdb_tx_varhex(val); + gdb_tx_char(';'); + } + } +} diff --git a/sys/i386/include/gdb_machdep.h b/sys/i386/include/gdb_machdep.h --- a/sys/i386/include/gdb_machdep.h +++ b/sys/i386/include/gdb_machdep.h @@ -63,5 +63,6 @@ void *gdb_cpu_getreg(int, size_t *); void gdb_cpu_setreg(int, void *); int gdb_cpu_signal(int, int); +void gdb_cpu_stop_reason(int, int); #endif /* !_MACHINE_GDB_MACHDEP_H_ */ diff --git a/sys/mips/include/gdb_machdep.h b/sys/mips/include/gdb_machdep.h --- a/sys/mips/include/gdb_machdep.h +++ b/sys/mips/include/gdb_machdep.h @@ -64,6 +64,12 @@ } +static __inline void +gdb_cpu_stop_reason(int type __unused, int code __unused) +{ + +} + void *gdb_cpu_getreg(int, size_t *); void gdb_cpu_setreg(int, void *); int gdb_cpu_signal(int, int); diff --git a/sys/powerpc/include/gdb_machdep.h b/sys/powerpc/include/gdb_machdep.h --- a/sys/powerpc/include/gdb_machdep.h +++ b/sys/powerpc/include/gdb_machdep.h @@ -128,6 +128,12 @@ } +static __inline void +gdb_cpu_stop_reason(int type __unused, int code __unused) +{ + +} + void *gdb_cpu_getreg(int, size_t *); void gdb_cpu_setreg(int, void *); int gdb_cpu_signal(int, int);