diff options
author | Mark Kettenis <kettenis@gnu.org> | 2001-03-31 18:09:03 +0000 |
---|---|---|
committer | Mark Kettenis <kettenis@gnu.org> | 2001-03-31 18:09:03 +0000 |
commit | 0afdd43759e75acf6c34338ac95d406aad497a08 (patch) | |
tree | c39e6549935fbcbd99f1edbcbe416b3b1882ed60 /gdb/i386bsd-nat.c | |
parent | 4bcc394469c492857bf7b70a32338cdde27c108d (diff) | |
download | gdb-0afdd43759e75acf6c34338ac95d406aad497a08.zip gdb-0afdd43759e75acf6c34338ac95d406aad497a08.tar.gz gdb-0afdd43759e75acf6c34338ac95d406aad497a08.tar.bz2 |
* i386bsd-nat.c: Include "gdb_assert.h".
[HAVE_PT_GETDBREGS] (DBREG_DRX): Define if not
already defined.
[HAVE_PT_GETDBREGS] (i386bsd_dr_set, i386bsd_dr_set_control,
i386bsd_dr_set_addr, i386bsd_dr_reset_addr,
i386bsd_dr_get_status): New functions.
* config/i386/nm-fbsd.h [HAVE_PT_GETDBREGS]
(I386_USE_GENERIC_WATCHPOINTS): Define.
Include "i386/nm-i386.h".
(I386_DR_LOW_SET_CONTROL, I386_DR_LOW_SET_ADDR,
I386_DR_LOW_RESET_ADDR, I386_DR_LOW_GET_STATUS): New macros.
(i386bsd_dr_set_control, i386bsd_dr_set_addr,
i386bsd_dr_reset_addr, i386bsd_dr_get_status): New prototypes.
* acconfig.h (HAVE_PT_GETDBREGS): New configure macro.
* configure.in: Cleanup a few comments. Check for PT_GETDBREGS
ptrace request.
* config.in, configure: Regenerate.
Diffstat (limited to 'gdb/i386bsd-nat.c')
-rw-r--r-- | gdb/i386bsd-nat.c | 75 |
1 files changed, 75 insertions, 0 deletions
diff --git a/gdb/i386bsd-nat.c b/gdb/i386bsd-nat.c index e991ba0..3fdda7b 100644 --- a/gdb/i386bsd-nat.c +++ b/gdb/i386bsd-nat.c @@ -22,6 +22,7 @@ #include "inferior.h" #include "regcache.h" +#include "gdb_assert.h" #include <sys/types.h> #include <sys/ptrace.h> #include <machine/reg.h> @@ -215,6 +216,80 @@ store_inferior_registers (int regno) } +/* Support for debug registers. */ + +#ifdef HAVE_PT_GETDBREGS + +/* Not all versions of FreeBSD/i386 that support the debug registers + have this macro. */ +#ifndef DBREG_DRX +#define DBREG_DRX(d, x) ((&d->dr0)[x]) +#endif + +static void +i386bsd_dr_set (int regnum, unsigned int value) +{ + struct dbreg dbregs; + + if (ptrace (PT_GETDBREGS, inferior_pid, (PTRACE_ARG3_TYPE) &dbregs, 0) == -1) + perror_with_name ("Couldn't get debug registers"); + + /* For some mysterious reason, some of the reserved bits in the + debug control register get set. Mask these off, otherwise the + ptrace call below will fail. */ + dbregs.dr7 &= ~(0x0000fc00); + + DBREG_DRX ((&dbregs), regnum) = value; + + if (ptrace (PT_SETDBREGS, inferior_pid, (PTRACE_ARG3_TYPE) &dbregs, 0) == -1) + perror_with_name ("Couldn't write debug registers"); +} + +void +i386bsd_dr_set_control (unsigned long control) +{ + i386bsd_dr_set (7, control); +} + +void +i386bsd_dr_set_addr (int regnum, CORE_ADDR addr) +{ + gdb_assert (regnum >= 0 && regnum <= 4); + + i386bsd_dr_set (regnum, addr); +} + +void +i386bsd_dr_reset_addr (int regnum) +{ + gdb_assert (regnum >= 0 && regnum <= 4); + + i386bsd_dr_set (regnum, 0); +} + +unsigned long +i386bsd_dr_get_status (void) +{ + struct dbreg dbregs; + + /* FIXME: kettenis/2001-03-31: Calling perror_with_name if the + ptrace call fails breaks debugging remote targets. The correct + way to fix this is to add the hardware breakpoint and watchpoint + stuff to the target vectore. For now, just return zero if the + ptrace call fails. */ + if (ptrace (PT_GETDBREGS, inferior_pid, (PTRACE_ARG3_TYPE) &dbregs, 0) == -1) +#if 0 + perror_with_name ("Couldn't read debug registers"); +#else + return 0; +#endif + + return dbregs.dr6; +} + +#endif /* PT_GETDBREGS */ + + /* Support for the user struct. */ /* Return the address register REGNO. BLOCKEND is the value of |