Make Linux use the new unified support for hardware breakpoints

and watchpoints on x86 targets.
* i386-linux-nat.c: Doc fixes.  Include "gdb_assert.h".
[HAVE_SYS_DEBUGREG_H]: Include <sys/debugreg.h>.
(DR_FIRSTADDR, DR_LASTADDR, DR_STATUS, DR_CONTROL): Define to
appropriate value if not already defined.
(register_u_addr): New function.
(kernel_u_size): New function.
(i386_linux_dr_get, i386_linux_dr_set): New functions.
(i386_linux_dr_set_control, i386_linux_dr_set_addr,
i386_linux_reset_addr, i386_linux_dr_get_status): New functions.
* config/i386/nm-linux.h: Don't include "nm-i386v.h".
(I386_USE_GENERIC_WATCHPOINTS): Define and include "nm-i386.h".
(TARGET_HAS_HARDWARE_WATCHPOINTS,
TARGET_CAN_USE_HARDWARE_WATCHPOINTS, HAVE_CONTINUABLE_WATCHPOINT,
STOPPED_BY_WATCHPOINT, target_insert_watchpoint,
target_remove_watchpoint): Remove macros.
(i386_stopped_by_watchpoint, i386_insert_watchpoint,
i386_remove_watchpoint): Remove prototypes.
(register_u_addr): New prototype.
(REGISTER_U_ADDR): Define in terms of register_u_addr.
(i386_linux_dr_set_control, i386_linux_dr_set_addr,
i386_linux_reset_addr, i386_linux_dr_get_status): New prototypes.
(I386_DR_LOW_SET_CONTROL, I386_DR_LOW_SET_ADDR,
I386_DR_LOW_RESET_ADDR, I386_DR_LOW_GET_STATUS): New macros.
* config/i386/linux.mh (NATDEPFILES): Replace i386v-nat.o with
i386-nat.o.
This commit is contained in:
Mark Kettenis
2001-03-21 21:22:49 +00:00
parent 13b5765709
commit 84346e11ea
4 changed files with 168 additions and 31 deletions

View File

@@ -23,6 +23,7 @@
#include "gdbcore.h"
#include "regcache.h"
#include "gdb_assert.h"
#include <sys/ptrace.h>
#include <sys/user.h>
#include <sys/procfs.h>
@@ -31,6 +32,26 @@
#include <sys/reg.h>
#endif
#ifdef HAVE_SYS_DEBUGREG_H
#include <sys/debugreg.h>
#endif
#ifndef DR_FIRSTADDR
#define DR_FIRSTADDR 0
#endif
#ifndef DR_LASTADDR
#define DR_LASTADDR 3
#endif
#ifndef DR_STATUS
#define DR_STATUS 6
#endif
#ifndef DR_CONTROL
#define DR_CONTROL 7
#endif
/* Prototypes for supply_gregset etc. */
#include "gregset.h"
@@ -110,6 +131,26 @@ int have_ptrace_getfpxregs =
;
/* Support for the user struct. */
/* Return the address of register REGNUM. BLOCKEND is the value of
u.u_ar0, which should point to the registers. */
CORE_ADDR
register_u_addr (CORE_ADDR blockend, int regnum)
{
return (blockend + 4 * regmap[regnum]);
}
/* Return the size of the user struct. */
int
kernel_u_size (void)
{
return (sizeof (struct user));
}
/* Fetching registers directly from the U area, one at a time. */
/* FIXME: kettenis/2000-03-05: This duplicates code from `inptrace.c'.
@@ -660,6 +701,72 @@ store_inferior_registers (int regno)
}
static long
i386_linux_dr_get (int regnum)
{
int tid;
long value;
/* FIXME: kettenis/2001-01-29: It's not clear what we should do with
multi-threaded processes here. For now, pretend there is just
one thread. */
tid = PIDGET (inferior_pid);
errno = 0;
value = ptrace (PT_READ_U, tid,
offsetof (struct user, u_debugreg[regnum]), 0);
if (errno != 0)
perror_with_name ("Couldn't read debug register");
return value;
}
static void
i386_linux_dr_set (int regnum, long value)
{
int tid;
/* FIXME: kettenis/2001-01-29: It's not clear what we should do with
multi-threaded processes here. For now, pretend there is just
one thread. */
tid = PIDGET (inferior_pid);
errno = 0;
ptrace (PT_WRITE_U, tid,
offsetof (struct user, u_debugreg[regnum]), value);
if (errno != 0)
perror_with_name ("Couldn't write debug register");
}
void
i386_linux_dr_set_control (long control)
{
i386_linux_dr_set (DR_CONTROL, control);
}
void
i386_linux_dr_set_addr (int regnum, CORE_ADDR addr)
{
gdb_assert (regnum >= 0 && regnum <= DR_LASTADDR - DR_FIRSTADDR);
i386_linux_dr_set (DR_FIRSTADDR + regnum, addr);
}
void
i386_linux_dr_reset_addr (int regnum)
{
gdb_assert (regnum >= 0 && regnum <= DR_LASTADDR - DR_FIRSTADDR);
i386_linux_dr_set (DR_FIRSTADDR + regnum, 0L);
}
long
i386_linux_dr_get_status (void)
{
return i386_linux_dr_get (DR_STATUS);
}
/* Interpreting register set info found in core files. */
/* Provide registers to GDB from a core file.