From 84346e11ea3d9a98216ce8eded615888d80b7cad Mon Sep 17 00:00:00 2001 From: Mark Kettenis Date: Wed, 21 Mar 2001 21:22:49 +0000 Subject: 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 . (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. --- gdb/i386-linux-nat.c | 107 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 107 insertions(+) (limited to 'gdb/i386-linux-nat.c') diff --git a/gdb/i386-linux-nat.c b/gdb/i386-linux-nat.c index 62fe3d4..aac9289 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 #include #include @@ -31,6 +32,26 @@ #include #endif +#ifdef HAVE_SYS_DEBUGREG_H +#include +#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. -- cgit v1.1