[RFA/RFC 3] Remove hardware break and watchpoints at program exit.

Pierre Muller
2002-01-11T17:20:58Z

[-- Attachment #1: Type: text/plain, Size: 1577 bytes --]

After the previous discussion about the
hardware watch and breakpoint removal
about the debuggee exited. I slightly modifed my patch
by adding a test to avoid calling ptrace
in i386-linux-nat.c, i386bsd-nat.c and x86-64-linux-nat.c
i386_linux_dr_set, i386bsd_dr_set and x86_64_linux_dr_set functions
if taget_has_execution is 0.

I have a little doubt about the default value of the
HARDWARE_REGISTER_RESET macro.
What should be used as a no-op default ?

2002-01-09 Pierre Muller <muller@ics.u-strasbg.fr>

* breakpoint.c (REMOVE_HARDWARE_BREAKPOINT_AT_EXIT):
Define to 0 if not defined.
(REMOVE_HARDWARE_WATCHPOINT_AT_EXIT):
Define to 0 if not defined.
(HARDWARE_REGISTER_RESET): Default to no-op.
(breakpoint_init_inferior): Use REMOVE_HARDWARE_BREAKPOINT_AT_EXIT
and REMOVE_HARDWARE_WATCHPOINT_AT_EXIT to conditionally
remove hardware break and watchpoints at exit.
Call HARDWARE_REGISTER_RESET macro if defined at exit.

* config/i386/nm-i386.h: Define HARDWARE_REGISTER_RESET
macro to call i386_cleanup_dregs().
Set REMOVE_HARDWARE_BREAKPOINT_AT_EXIT to 1.
Set REMOVE_HARDWARE_WATCHPOINT_AT_EXIT to 1.

* go32-nat.c (go32_mourn_inferior): Remove call to i386_cleanup_dregs
as this is done in breakpoint_init_inferior().
* i386-linux-nat.c (i386_linux_dr_set): Don't call ptrace if target_has_execution is zero.
* i386bsd-nat.c (i386bsd_dr_set): Likewise.
* x86-64-linux-nat.c (x86_64_linux_dr_set): Likewise.

[-- Attachment #2: dregs.diffs --]
[-- Type: text/plain, Size: 5608 bytes --]

Index: breakpoint.c
===================================================================
RCS file: /cvs/src/src/gdb/breakpoint.c,v
retrieving revision 1.57
diff -u -p -r1.57 breakpoint.c
--- breakpoint.c 2001/11/11 16:39:59 1.57
+++ breakpoint.c 2002/01/11 16:19:11
@@ -234,6 +234,19 @@ static int executing_breakpoint_commands
B ? (TMP=B->next, 1): 0; \
B = TMP)

+#ifndef REMOVE_HARDWARE_BREAKPOINT_AT_EXIT
+#define REMOVE_HARDWARE_BREAKPOINT_AT_EXIT 0
+#endif
+
+#ifndef REMOVE_HARDWARE_WATCHPOINT_AT_EXIT
+#define REMOVE_HARDWARE_WATCHPOINT_AT_EXIT 0
+#endif
+
+
+#ifndef HARDWARE_REGISTERS_RESET
+#define HARDWARE_REGISTERS_RESET {}
+#endif
+
/* True if SHIFT_INST_REGS defined, false otherwise. */

int must_shift_inst_regs =
@@ -1440,7 +1453,17 @@ breakpoint_init_inferior (enum inf_conte

ALL_BREAKPOINTS_SAFE (b, temp)
{
- b->inserted = 0;
+ if ((((REMOVE_HARDWARE_BREAKPOINT_AT_EXIT)
+ && b->type == bp_hardware_breakpoint)
+ ||((REMOVE_HARDWARE_WATCHPOINT_AT_EXIT)
+ && (b->type == bp_hardware_watchpoint
+ || b->type == bp_access_watchpoint
+ || b->type == bp_read_watchpoint)))
+ && b->inserted
+ && context == inf_exited)
+ remove_breakpoint (b, mark_uninserted);
+
+ b->inserted = 0;

switch (b->type)
{
@@ -1487,6 +1510,8 @@ breakpoint_init_inferior (enum inf_conte
warning ("You must reinsert them explicitly.");
warning_needed = 0;
}
+ if (context == inf_exited)
+ HARDWARE_REGISTER_RESET;
}

/* breakpoint_here_p (PC) returns non-zero if an enabled breakpoint
Index: go32-nat.c
===================================================================
RCS file: /cvs/src/src/gdb/go32-nat.c,v
retrieving revision 1.26
diff -u -p -r1.26 go32-nat.c
--- go32-nat.c 2001/12/06 08:15:37 1.26
+++ go32-nat.c 2002/01/11 16:19:11
@@ -663,14 +663,6 @@ go32_create_inferior (char *exec_file, c
static void
go32_mourn_inferior (void)
{
- /* We need to make sure all the breakpoint enable bits in the DR7
- register are reset when the inferior exits. Otherwise, if they
- rerun the inferior, the uncleared bits may cause random SIGTRAPs,
- failure to set more watchpoints, and other calamities. It would
- be nice if GDB itself would take care to remove all breakpoints
- at all times, but it doesn't, probably under an assumption that
- the OS cleans up when the debuggee exits. */
- i386_cleanup_dregs ();
go32_kill_inferior ();
generic_mourn_inferior ();
}
Index: i386-linux-nat.c
===================================================================
RCS file: /cvs/src/src/gdb/i386-linux-nat.c,v
retrieving revision 1.34
diff -u -p -r1.34 i386-linux-nat.c
--- i386-linux-nat.c 2002/01/09 22:32:16 1.34
+++ i386-linux-nat.c 2002/01/11 16:19:12
@@ -738,8 +738,9 @@ i386_linux_dr_set (int regnum, unsigned
tid = PIDGET (inferior_ptid);

errno = 0;
- ptrace (PT_WRITE_U, tid,
- offsetof (struct user, u_debugreg[regnum]), value);
+ if (target_has_execution)
+ ptrace (PT_WRITE_U, tid,
+ offsetof (struct user, u_debugreg[regnum]), value);
if (errno != 0)
perror_with_name ("Couldn't write debug register");
}
Index: i386bsd-nat.c
===================================================================
RCS file: /cvs/src/src/gdb/i386bsd-nat.c,v
retrieving revision 1.11
diff -u -p -r1.11 i386bsd-nat.c
--- i386bsd-nat.c 2002/01/05 18:36:32 1.11
+++ i386bsd-nat.c 2002/01/11 16:19:12
@@ -298,8 +298,9 @@ i386bsd_dr_set (int regnum, unsigned int
{
struct dbreg dbregs;

- if (ptrace (PT_GETDBREGS, PIDGET (inferior_ptid),
- (PTRACE_ARG3_TYPE) &dbregs, 0) == -1)
+ if (target_has_execution
+ && ptrace (PT_GETDBREGS, PIDGET (inferior_ptid),
+ (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
@@ -309,8 +310,9 @@ i386bsd_dr_set (int regnum, unsigned int

DBREG_DRX ((&dbregs), regnum) = value;

- if (ptrace (PT_SETDBREGS, PIDGET (inferior_ptid),
- (PTRACE_ARG3_TYPE) &dbregs, 0) == -1)
+ if (target_has_execution
+ && ptrace (PT_SETDBREGS, PIDGET (inferior_ptid),
+ (PTRACE_ARG3_TYPE) &dbregs, 0) == -1))
perror_with_name ("Couldn't write debug registers");
}

Index: x86-64-linux-nat.c
===================================================================
RCS file: /cvs/src/src/gdb/x86-64-linux-nat.c,v
retrieving revision 1.2
diff -u -p -r1.2 x86-64-linux-nat.c
--- x86-64-linux-nat.c 2002/01/08 00:59:31 1.2
+++ x86-64-linux-nat.c 2002/01/11 16:19:12
@@ -73,8 +73,9 @@ x86_64_linux_dr_set (int regnum, unsigne
tid = PIDGET (inferior_ptid);

errno = 0;
- ptrace (PT_WRITE_U, tid,
- offsetof (struct user, u_debugreg[regnum]), value);
+ if (target_has_execution)
+ ptrace (PT_WRITE_U, tid,
+ offsetof (struct user, u_debugreg[regnum]), value);
if (errno != 0)
perror_with_name ("Couldn't write debug register");
}
Index: config/i386/nm-i386.h
===================================================================
RCS file: /cvs/src/src/gdb/config/i386/nm-i386.h,v
retrieving revision 1.2
diff -u -p -r1.2 nm-i386.h
--- nm-i386.h 2001/03/23 16:17:45 1.2
+++ nm-i386.h 2002/01/11 16:19:12
@@ -115,6 +115,12 @@ extern int i386_remove_hw_breakpoint (C

#define DECR_PC_AFTER_HW_BREAK 0

+#define REMOVE_HARDWARE_WATCHPOINT_AT_EXIT 1
+
+#define REMOVE_HARDWARE_BREAKPOINT_AT_EXIT 1
+
+#define HARDWARE_REGISTERS_RESET i386_cleanup_dregs ()
+
#endif /* I386_USE_GENERIC_WATCHPOINTS */

#endif /* NM_I386_H */

[-- Attachment #3: Type: text/plain, Size: 176 bytes --]

Pierre Muller
Institut Charles Sadron
6,rue Boussingault
F 67083 STRASBOURG CEDEX (France)
mailto:muller@ics.u-strasbg.fr
Phone : (33)-3-88-41-40-07 Fax : (33)-3-88-41-40-99