summaryrefslogtreecommitdiff
path: root/gdb/i386-linux-nat.c
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@gnu.org>2001-03-21 21:22:49 +0000
committerMark Kettenis <kettenis@gnu.org>2001-03-21 21:22:49 +0000
commit8fde336b131963bfcdfd0060b21c0da0afdfbb62 (patch)
treeb08331af0755f5c6731a6bc61abab33c92303125 /gdb/i386-linux-nat.c
parent30a57d4c40f7fe60ef338b58113ee86e28f7275a (diff)
downloadgdb-8fde336b131963bfcdfd0060b21c0da0afdfbb62.tar.gz
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.
Diffstat (limited to 'gdb/i386-linux-nat.c')
-rw-r--r--gdb/i386-linux-nat.c107
1 files changed, 107 insertions, 0 deletions
diff --git a/gdb/i386-linux-nat.c b/gdb/i386-linux-nat.c
index 62fe3d4191b..aac92896343 100644
--- a/gdb/i386-linux-nat.c
+++ b/gdb/i386-linux-nat.c
@@ -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.