mirror of
https://github.com/darlinghq/darling-gdb.git
synced 2025-02-27 12:56:07 +00:00
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:
parent
13b5765709
commit
84346e11ea
@ -1,3 +1,33 @@
|
||||
2001-03-21 Mark Kettenis <kettenis@gnu.org>
|
||||
|
||||
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.
|
||||
|
||||
2001-03-21 Jim Blandy <jimb@redhat.com>
|
||||
|
||||
* linespec.c (find_methods): Whitespace differences aren't
|
||||
|
@ -5,7 +5,7 @@ XDEPFILES=
|
||||
|
||||
NAT_FILE= nm-linux.h
|
||||
NATDEPFILES= infptrace.o inftarg.o fork-child.o corelow.o \
|
||||
core-aout.o i386v-nat.o i386-linux-nat.o i387-nat.o \
|
||||
core-aout.o i386-nat.o i386-linux-nat.o i387-nat.o \
|
||||
proc-service.o thread-db.o lin-lwp.o
|
||||
|
||||
LOADLIBES = -ldl -rdynamic
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* Native support for Linux/x86.
|
||||
Copyright 1986, 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
|
||||
1999, 2000
|
||||
1999, 2000, 2001
|
||||
Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GDB.
|
||||
@ -23,52 +23,56 @@
|
||||
#ifndef NM_LINUX_H
|
||||
#define NM_LINUX_H
|
||||
|
||||
#include "i386/nm-i386v.h"
|
||||
/* GNU/Linux supports the i386 hardware debugging registers. */
|
||||
#define I386_USE_GENERIC_WATCHPOINTS
|
||||
|
||||
#include "i386/nm-i386.h"
|
||||
#include "nm-linux.h"
|
||||
|
||||
/* Return sizeof user struct to callers in less machine dependent routines */
|
||||
/* Return sizeof user struct to callers in less machine dependent
|
||||
routines. */
|
||||
|
||||
#define KERNEL_U_SIZE kernel_u_size()
|
||||
extern int kernel_u_size (void);
|
||||
#define KERNEL_U_SIZE kernel_u_size()
|
||||
|
||||
#define U_REGS_OFFSET 0
|
||||
|
||||
/* GNU/Linux supports the 386 hardware debugging registers. */
|
||||
extern CORE_ADDR register_u_addr (CORE_ADDR blockend, int regnum);
|
||||
#define REGISTER_U_ADDR(addr, blockend, regnum) \
|
||||
(addr) = register_u_addr (blockend, regnum)
|
||||
|
||||
#define TARGET_HAS_HARDWARE_WATCHPOINTS
|
||||
/* Provide access to the i386 hardware debugging registers. */
|
||||
|
||||
#define TARGET_CAN_USE_HARDWARE_WATCHPOINT(type, cnt, ot) 1
|
||||
extern void i386_linux_dr_set_control (long control);
|
||||
#define I386_DR_LOW_SET_CONTROL(control) \
|
||||
i386_linux_dr_set_control (control)
|
||||
|
||||
/* After a watchpoint trap, the PC points to the instruction after
|
||||
the one that caused the trap. Therefore we don't need to step over it.
|
||||
But we do need to reset the status register to avoid another trap. */
|
||||
#define HAVE_CONTINUABLE_WATCHPOINT
|
||||
extern void i386_linux_dr_set_addr (int regnum, CORE_ADDR addr);
|
||||
#define I386_DR_LOW_SET_ADDR(regnum, addr) \
|
||||
i386_linux_dr_set_addr (regnum, addr)
|
||||
|
||||
#define STOPPED_BY_WATCHPOINT(W) \
|
||||
i386_stopped_by_watchpoint (inferior_pid)
|
||||
extern void i386_linux_dr_reset_addr (int regnum);
|
||||
#define I386_DR_LOW_RESET_ADDR(regnum) \
|
||||
i386_linux_dr_reset_addr (regnum)
|
||||
|
||||
/* Use these macros for watchpoint insertion/removal. */
|
||||
extern long i386_linux_dr_get_status (void);
|
||||
#define I386_DR_LOW_GET_STATUS() \
|
||||
i386_linux_dr_get_status ()
|
||||
|
||||
#define target_insert_watchpoint(addr, len, type) \
|
||||
i386_insert_watchpoint (inferior_pid, addr, len, type)
|
||||
|
||||
#define target_remove_watchpoint(addr, len, type) \
|
||||
i386_remove_watchpoint (inferior_pid, addr, len)
|
||||
|
||||
/* We define this if link.h is available, because with ELF we use SVR4 style
|
||||
shared libraries. */
|
||||
/* We define this if link.h is available, because with ELF we use SVR4
|
||||
style shared libraries. */
|
||||
|
||||
#ifdef HAVE_LINK_H
|
||||
#define SVR4_SHARED_LIBS
|
||||
#include "solib.h" /* Support for shared libraries. */
|
||||
#include "solib.h" /* Support for shared libraries. */
|
||||
#endif
|
||||
|
||||
/* Override copies of {fetch,store}_inferior_registers in `infptrace.c'. */
|
||||
#define FETCH_INFERIOR_REGISTERS
|
||||
|
||||
/* Nevertheless, define CANNOT_{FETCH,STORE}_REGISTER, because we might fall
|
||||
back on the code `infptrace.c' (well a copy of that code in
|
||||
`i386-linux-nat.c' for now) and we can access only the
|
||||
/* Nevertheless, define CANNOT_{FETCH,STORE}_REGISTER, because we
|
||||
might fall back on the code `infptrace.c' (well a copy of that code
|
||||
in `i386-linux-nat.c' for now) and we can access only the
|
||||
general-purpose registers in that way. */
|
||||
extern int cannot_fetch_register (int regno);
|
||||
extern int cannot_store_register (int regno);
|
||||
@ -78,10 +82,6 @@ extern int cannot_store_register (int regno);
|
||||
/* Override child_resume in `infptrace.c'. */
|
||||
#define CHILD_RESUME
|
||||
|
||||
extern CORE_ADDR i386_stopped_by_watchpoint (int);
|
||||
extern int i386_insert_watchpoint (int pid, CORE_ADDR addr, int len, int rw);
|
||||
extern int i386_remove_watchpoint (int pid, CORE_ADDR addr, int len);
|
||||
|
||||
/* FIXME: kettenis/2000-09-03: This should be moved to ../nm-linux.h
|
||||
once we have converted all Linux targets to use the new threads
|
||||
stuff (without the #undef of course). */
|
||||
|
@ -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.
|
||||
|
Loading…
x
Reference in New Issue
Block a user