Make single-step breakpoints be per-thread

This patch finally makes each thread have its own set of single-step
breakpoints.  This paves the way to have multiple threads software
single-stepping, though this patch doesn't flip that switch on yet.
That'll be done on a subsequent patch.

gdb/
2014-10-15  Pedro Alves  <palves@redhat.com>

	* breakpoint.c (single_step_breakpoints): Delete global.
	(insert_single_step_breakpoint): Adjust to store the breakpoint
	pointer in the current thread.
	(single_step_breakpoints_inserted, remove_single_step_breakpoints)
	(cancel_single_step_breakpoints): Delete functions.
	(breakpoint_has_location_inserted_here): Make extern.
	(single_step_breakpoint_inserted_here_p): Adjust to walk the
	breakpoint list.
	* breakpoint.h (breakpoint_has_location_inserted_here): New
	declaration.
	(single_step_breakpoints_inserted, remove_single_step_breakpoints)
	(cancel_single_step_breakpoints): Remove declarations.
	* gdbthread.h (struct thread_control_state)
	<single_step_breakpoints>: New field.
	(delete_single_step_breakpoints)
	(thread_has_single_step_breakpoints_set)
	(thread_has_single_step_breakpoint_here): New declarations.
	* infrun.c (follow_exec): Also clear the single-step breakpoints.
	(singlestep_breakpoints_inserted_p, singlestep_ptid)
	(singlestep_pc): Delete globals.
	(infrun_thread_ptid_changed): Remove references to removed
	globals.
	(resume_cleanups): Delete the current thread's single-step
	breakpoints.
	(maybe_software_singlestep): Remove references to removed globals.
	(resume): Adjust to use thread_has_single_step_breakpoints_set and
	delete_single_step_breakpoints.
	(init_wait_for_inferior): Remove references to removed globals.
	(delete_thread_infrun_breakpoints): Delete the thread's
	single-step breakpoints too.
	(delete_just_stopped_threads_infrun_breakpoints): Don't delete
	single-step breakpoints here.
	(delete_stopped_threads_single_step_breakpoints): New function.
	(adjust_pc_after_break): Adjust to use
	thread_has_single_step_breakpoints_set.
	(handle_inferior_event): Remove references to removed globals.
	Use delete_stopped_threads_single_step_breakpoints.
	(handle_signal_stop): Adjust to per-thread single-step
	breakpoints.  Swap test order to do cheaper tests first.
	(switch_back_to_stepped_thread): Extend debug output.  Remove
	references to removed globals.
	* record-full.c (record_full_wait_1): Adjust to per-thread
	single-step breakpoints.
	* thread.c (delete_single_step_breakpoints)
	(thread_has_single_step_breakpoints_set)
	(thread_has_single_step_breakpoint_here): New functions.
	(clear_thread_inferior_resources): Also delete the thread's
	single-step breakpoints.
This commit is contained in:
Pedro Alves
2014-10-15 20:18:32 +01:00
parent 5b834a0a5d
commit 34b7e8a6ad
7 changed files with 174 additions and 123 deletions

View File

@@ -325,11 +325,6 @@ static struct breakpoint_ops bkpt_probe_breakpoint_ops;
/* Dynamic printf class type. */
struct breakpoint_ops dprintf_breakpoint_ops;
/* One (or perhaps two) breakpoints used for software single
stepping. */
static struct breakpoint *single_step_breakpoints;
/* The style in which to perform a dynamic printf. This is a user
option because different output options have different tradeoffs;
if GDB does the printing, there is better error handling if there
@@ -15319,57 +15314,24 @@ insert_single_step_breakpoint (struct gdbarch *gdbarch,
struct symtab_and_line sal;
CORE_ADDR pc = next_pc;
if (single_step_breakpoints == NULL)
single_step_breakpoints = new_single_step_breakpoint (tp->num, gdbarch);
if (tp->control.single_step_breakpoints == NULL)
{
tp->control.single_step_breakpoints
= new_single_step_breakpoint (tp->num, gdbarch);
}
sal = find_pc_line (pc, 0);
sal.pc = pc;
sal.section = find_pc_overlay (pc);
sal.explicit_pc = 1;
add_location_to_breakpoint (single_step_breakpoints, &sal);
add_location_to_breakpoint (tp->control.single_step_breakpoints, &sal);
update_global_location_list (UGLL_INSERT);
}
/* Check if the breakpoints used for software single stepping
were inserted or not. */
/* See breakpoint.h. */
int
single_step_breakpoints_inserted (void)
{
return (single_step_breakpoints != NULL);
}
/* Remove and delete any breakpoints used for software single step. */
void
remove_single_step_breakpoints (void)
{
gdb_assert (single_step_breakpoints != NULL);
delete_breakpoint (single_step_breakpoints);
single_step_breakpoints = NULL;
}
/* Delete software single step breakpoints without removing them from
the inferior. This is intended to be used if the inferior's address
space where they were inserted is already gone, e.g. after exit or
exec. */
void
cancel_single_step_breakpoints (void)
{
/* We don't really need to (or should) delete them here. After an
exit, breakpoint_init_inferior deletes it. After an exec,
update_breakpoints_after_exec does it. Just clear our
reference. */
single_step_breakpoints = NULL;
}
/* Check whether any location of BP is inserted at PC. */
static int
breakpoint_has_location_inserted_here (struct breakpoint *bp,
struct address_space *aspace,
CORE_ADDR pc)
@@ -15391,9 +15353,15 @@ int
single_step_breakpoint_inserted_here_p (struct address_space *aspace,
CORE_ADDR pc)
{
return (single_step_breakpoints != NULL
&& breakpoint_has_location_inserted_here (single_step_breakpoints,
aspace, pc));
struct breakpoint *bpt;
ALL_BREAKPOINTS (bpt)
{
if (bpt->type == bp_single_step
&& breakpoint_has_location_inserted_here (bpt, aspace, pc))
return 1;
}
return 0;
}
/* Returns 0 if 'bp' is NOT a syscall catchpoint,