Fix watchpoints across inferior fork.
	* amd64-linux-nat.c (update_debug_registers_callback): Update the
	comment for linux_nat_iterate_watchpoint_lwps.
	(amd64_linux_dr_set_control, amd64_linux_dr_set_addr): Use
	linux_nat_iterate_watchpoint_lwps.
	(amd64_linux_prepare_to_resume): New comment on Linux kernel.
	* i386-linux-nat.c (update_debug_registers_callback): Update the
	comment for linux_nat_iterate_watchpoint_lwps.
	(i386_linux_dr_set_control, i386_linux_dr_set_addr): Use
	linux_nat_iterate_watchpoint_lwps.
	(i386_linux_prepare_to_resume): New comment on Linux kernel.
	* i386-nat.c: Include inferior.h.
	(dr_mirror): Remove.
	(i386_inferior_data, struct i386_inferior_data)
	(i386_inferior_data_get): New.
	(i386_debug_reg_state): Use i386_inferior_data_get.
	(i386_cleanup_dregs, i386_update_inferior_debug_regs)
	(i386_insert_watchpoint, i386_remove_watchpoint)
	(i386_stopped_data_address, i386_insert_hw_breakpoint)
	(i386_remove_hw_breakpoint): New variable state, use
	i386_debug_reg_state instead of DR_MIRROR.
	* linux-nat.c (delete_lwp): New declaration.
	(num_lwps): Move here from downwards.
	(delete_lwp_cleanup): New.
	(linux_child_follow_fork): Create new child_lp, call
	linux_nat_new_thread and linux_nat_prepare_to_resume before calling
	PTRACE_DETACH.
	(num_lwps): Move upwards.
	(linux_nat_iterate_watchpoint_lwps): New.
	* linux-nat.h (linux_nat_iterate_watchpoint_lwps_ftype): New.
	(linux_nat_iterate_watchpoint_lwps_ftype): New declaration.

gdb/testsuite/
	Fix watchpoints across inferior fork.
	* gdb.threads/watchpoint-fork-child.c: New file.
	* gdb.threads/watchpoint-fork-mt.c: New file.
	* gdb.threads/watchpoint-fork-parent.c: New file.
	* gdb.threads/watchpoint-fork-st.c: New file.
	* gdb.threads/watchpoint-fork.exp: New file.
	* gdb.threads/watchpoint-fork.h: New file.
This commit is contained in:
Jan Kratochvil 2012-01-24 13:46:55 +00:00
parent 2992c9a711
commit 4403d8e9b3
13 changed files with 896 additions and 68 deletions

View file

@ -336,8 +336,8 @@ amd64_linux_dr_get_status (void)
return amd64_linux_dr_get (inferior_ptid, DR_STATUS);
}
/* Callback for iterate_over_lwps. Update the debug registers of
LWP. */
/* Callback for linux_nat_iterate_watchpoint_lwps. Update the debug registers
of LWP. */
static int
update_debug_registers_callback (struct lwp_info *lwp, void *arg)
@ -363,9 +363,7 @@ update_debug_registers_callback (struct lwp_info *lwp, void *arg)
static void
amd64_linux_dr_set_control (unsigned long control)
{
ptid_t pid_ptid = pid_to_ptid (ptid_get_pid (inferior_ptid));
iterate_over_lwps (pid_ptid, update_debug_registers_callback, NULL);
linux_nat_iterate_watchpoint_lwps (update_debug_registers_callback, NULL);
}
/* Set address REGNUM (zero based) to ADDR in all LWPs of the current
@ -374,11 +372,9 @@ amd64_linux_dr_set_control (unsigned long control)
static void
amd64_linux_dr_set_addr (int regnum, CORE_ADDR addr)
{
ptid_t pid_ptid = pid_to_ptid (ptid_get_pid (inferior_ptid));
gdb_assert (regnum >= 0 && regnum <= DR_LASTADDR - DR_FIRSTADDR);
iterate_over_lwps (pid_ptid, update_debug_registers_callback, NULL);
linux_nat_iterate_watchpoint_lwps (update_debug_registers_callback, NULL);
}
/* Called when resuming a thread.
@ -400,6 +396,13 @@ amd64_linux_prepare_to_resume (struct lwp_info *lwp)
struct i386_debug_reg_state *state = i386_debug_reg_state ();
int i;
/* On Linux kernel before 2.6.33 commit
72f674d203cd230426437cdcf7dd6f681dad8b0d
if you enable a breakpoint by the DR_CONTROL bits you need to have
already written the corresponding DR_FIRSTADDR...DR_LASTADDR registers.
Ensure DR_CONTROL gets written as the very last register here. */
for (i = DR_FIRSTADDR; i <= DR_LASTADDR; i++)
if (state->dr_ref_count[i] > 0)
{