gdb: Eliminate the 'stop_pc' global

In my multi-target work, I need to add a few more
scoped_restore_current_thread and switch_to_thread calls in some
places, and in some lower-level places I was fighting against the fact
that switch_to_thread reads/refreshes the stop_pc global.

Instead of piling on workarounds, let's just finally eliminate the
stop_pc global.  We already have the per-thread
thread_info->suspend.stop_pc field, so it's mainly a matter of using
that more/instead.

gdb/ChangeLog:
2018-06-28  Pedro Alves  <palves@redhat.com>

	* gdbthread.h (struct thread_suspend_state) <stop_pc>: Extend
	comments.
	(switch_to_thread_no_regs): Adjust comment.
	* infcmd.c (stop_pc): Delete.
	(post_create_inferior, info_program_command): Replace references
	to stop_pc with references to thread_info->suspend.stop_pc.
	* inferior.h (stop_pc): Delete declaration.
	* infrun.c (proceed, handle_syscall_event, fill_in_stop_func)
	(handle_inferior_event_1, handle_signal_stop)
	(process_event_stop_test, keep_going_stepped_thread)
	(handle_step_into_function, handle_step_into_function_backward)
	(print_stop_location): Replace references to stop_pc with
	references to thread_info->suspend.stop_pc.
	(struct infcall_suspend_state) <stop_pc>: Delete field.
	(save_infcall_suspend_state, restore_infcall_suspend_state):
	Remove references to inf_stat->stop_pc.
	* linux-fork.c (fork_load_infrun_state): Likewise.
	* record-btrace.c (record_btrace_set_replay): Likewise.
	* record-full.c (record_full_goto_entry): Likewise.
	* remote.c (print_one_stopped_thread): Likewise.
	* target.c (target_resume): Extend comment.
	* thread.c (set_executing_thread): New.
	(set_executing): Use it.
	(switch_to_thread_no_regs, switch_to_no_thread, switch_to_thread):
	Remove references to stop_pc.
This commit is contained in:
Pedro Alves 2018-06-28 20:18:24 +01:00
parent ecdc3a72c8
commit f2ffa92bbc
11 changed files with 139 additions and 79 deletions

View File

@ -1,3 +1,31 @@
2018-06-28 Pedro Alves <palves@redhat.com>
* gdbthread.h (struct thread_suspend_state) <stop_pc>: Extend
comments.
(switch_to_thread_no_regs): Adjust comment.
* infcmd.c (stop_pc): Delete.
(post_create_inferior, info_program_command): Replace references
to stop_pc with references to thread_info->suspend.stop_pc.
* inferior.h (stop_pc): Delete declaration.
* infrun.c (proceed, handle_syscall_event, fill_in_stop_func)
(handle_inferior_event_1, handle_signal_stop)
(process_event_stop_test, keep_going_stepped_thread)
(handle_step_into_function, handle_step_into_function_backward)
(print_stop_location): Replace references to stop_pc with
references to thread_info->suspend.stop_pc.
(struct infcall_suspend_state) <stop_pc>: Delete field.
(save_infcall_suspend_state, restore_infcall_suspend_state):
Remove references to inf_stat->stop_pc.
* linux-fork.c (fork_load_infrun_state): Likewise.
* record-btrace.c (record_btrace_set_replay): Likewise.
* record-full.c (record_full_goto_entry): Likewise.
* remote.c (print_one_stopped_thread): Likewise.
* target.c (target_resume): Extend comment.
* thread.c (set_executing_thread): New.
(set_executing): Use it.
(switch_to_thread_no_regs, switch_to_no_thread, switch_to_thread):
Remove references to stop_pc.
2018-06-28 Pedro Alves <palves@redhat.com> 2018-06-28 Pedro Alves <palves@redhat.com>
* infrun.c (handle_inferior_event_1) <TARGET_WAITKIND_EXECD>: * infrun.c (handle_inferior_event_1) <TARGET_WAITKIND_EXECD>:

View File

@ -168,10 +168,19 @@ struct thread_suspend_state
/* Record the pc of the thread the last time it stopped. (This is /* Record the pc of the thread the last time it stopped. (This is
not the current thread's PC as that may have changed since the not the current thread's PC as that may have changed since the
last stop, e.g., "return" command, or "p $pc = 0xf000"). This is last stop, e.g., "return" command, or "p $pc = 0xf000").
used in coordination with stop_reason and waitstatus_pending_p:
if the thread's PC is changed since it last stopped, a pending - If the thread's PC has not changed since the thread last
breakpoint waitstatus is discarded. */ stopped, then proceed skips a breakpoint at the current PC,
otherwise we let the thread run into the breakpoint.
- If the thread has an unprocessed event pending, as indicated by
waitstatus_pending_p, this is used in coordination with
stop_reason: if the thread's PC has changed since the thread
last stopped, a pending breakpoint waitstatus is discarded.
- If the thread is running, this is set to -1, to avoid leaving
it with a stale value, to make it easier to catch bugs. */
CORE_ADDR stop_pc; CORE_ADDR stop_pc;
}; };
@ -498,8 +507,7 @@ extern void switch_to_thread (struct thread_info *thr);
/* Switch context to no thread selected. */ /* Switch context to no thread selected. */
extern void switch_to_no_thread (); extern void switch_to_no_thread ();
/* Switch from one thread to another. Does not read registers and /* Switch from one thread to another. Does not read registers. */
sets STOP_PC to -1. */
extern void switch_to_thread_no_regs (struct thread_info *thread); extern void switch_to_thread_no_regs (struct thread_info *thread);
/* Marks or clears thread(s) PTID as resumed. If PTID is /* Marks or clears thread(s) PTID as resumed. If PTID is

View File

@ -94,10 +94,6 @@ static char *inferior_io_terminal_scratch;
ptid_t inferior_ptid; ptid_t inferior_ptid;
/* Address at which inferior stopped. */
CORE_ADDR stop_pc;
/* Nonzero if stopped due to completion of a stack dummy routine. */ /* Nonzero if stopped due to completion of a stack dummy routine. */
enum stop_stack_kind stop_stack_dummy; enum stop_stack_kind stop_stack_dummy;
@ -448,10 +444,12 @@ post_create_inferior (struct target_ops *target, int from_tty)
/* Now that we know the register layout, retrieve current PC. But /* Now that we know the register layout, retrieve current PC. But
if the PC is unavailable (e.g., we're opening a core file with if the PC is unavailable (e.g., we're opening a core file with
missing registers info), ignore it. */ missing registers info), ignore it. */
stop_pc = 0; thread_info *thr = inferior_thread ();
thr->suspend.stop_pc = 0;
TRY TRY
{ {
stop_pc = regcache_read_pc (get_current_regcache ()); thr->suspend.stop_pc = regcache_read_pc (get_current_regcache ());
} }
CATCH (ex, RETURN_MASK_ERROR) CATCH (ex, RETURN_MASK_ERROR)
{ {
@ -2108,7 +2106,7 @@ info_program_command (const char *args, int from_tty)
target_files_info (); target_files_info ();
printf_filtered (_("Program stopped at %s.\n"), printf_filtered (_("Program stopped at %s.\n"),
paddress (target_gdbarch (), stop_pc)); paddress (target_gdbarch (), tp->suspend.stop_pc));
if (tp->control.stop_step) if (tp->control.stop_step)
printf_filtered (_("It stopped after being stepped.\n")); printf_filtered (_("It stopped after being stepped.\n"));
else if (stat != 0) else if (stat != 0)

View File

@ -208,10 +208,6 @@ extern void prepare_execution_command (struct target_ops *target,
the target is started up with a shell. */ the target is started up with a shell. */
extern int startup_with_shell; extern int startup_with_shell;
/* Address at which inferior stopped. */
extern CORE_ADDR stop_pc;
/* Nonzero if stopped due to completion of a stack dummy routine. */ /* Nonzero if stopped due to completion of a stack dummy routine. */
extern enum stop_stack_kind stop_stack_dummy; extern enum stop_stack_kind stop_stack_dummy;

View File

@ -3009,7 +3009,7 @@ proceed (CORE_ADDR addr, enum gdb_signal siggnal)
if (addr == (CORE_ADDR) -1) if (addr == (CORE_ADDR) -1)
{ {
if (pc == stop_pc if (pc == tp->suspend.stop_pc
&& breakpoint_here_p (aspace, pc) == ordinary_breakpoint_here && breakpoint_here_p (aspace, pc) == ordinary_breakpoint_here
&& execution_direction != EXEC_REVERSE) && execution_direction != EXEC_REVERSE)
/* There is a breakpoint at the address we will resume at, /* There is a breakpoint at the address we will resume at,
@ -4249,7 +4249,7 @@ handle_syscall_event (struct execution_control_state *ecs)
regcache = get_thread_regcache (ecs->event_thread); regcache = get_thread_regcache (ecs->event_thread);
syscall_number = ecs->ws.value.syscall_number; syscall_number = ecs->ws.value.syscall_number;
stop_pc = regcache_read_pc (regcache); ecs->event_thread->suspend.stop_pc = regcache_read_pc (regcache);
if (catch_syscall_enabled () > 0 if (catch_syscall_enabled () > 0
&& catching_syscall_number (syscall_number) > 0) && catching_syscall_number (syscall_number) > 0)
@ -4260,7 +4260,8 @@ handle_syscall_event (struct execution_control_state *ecs)
ecs->event_thread->control.stop_bpstat ecs->event_thread->control.stop_bpstat
= bpstat_stop_status (regcache->aspace (), = bpstat_stop_status (regcache->aspace (),
stop_pc, ecs->event_thread, &ecs->ws); ecs->event_thread->suspend.stop_pc,
ecs->event_thread, &ecs->ws);
if (handle_stop_requested (ecs)) if (handle_stop_requested (ecs))
return 0; return 0;
@ -4290,7 +4291,8 @@ fill_in_stop_func (struct gdbarch *gdbarch,
{ {
/* Don't care about return value; stop_func_start and stop_func_name /* Don't care about return value; stop_func_start and stop_func_name
will both be 0 if it doesn't work. */ will both be 0 if it doesn't work. */
find_pc_partial_function (stop_pc, &ecs->stop_func_name, find_pc_partial_function (ecs->event_thread->suspend.stop_pc,
&ecs->stop_func_name,
&ecs->stop_func_start, &ecs->stop_func_end); &ecs->stop_func_start, &ecs->stop_func_end);
ecs->stop_func_start ecs->stop_func_start
+= gdbarch_deprecated_function_start_offset (gdbarch); += gdbarch_deprecated_function_start_offset (gdbarch);
@ -4937,7 +4939,8 @@ handle_inferior_event_1 (struct execution_control_state *ecs)
ecs->event_thread->control.stop_bpstat ecs->event_thread->control.stop_bpstat
= bpstat_stop_status (regcache->aspace (), = bpstat_stop_status (regcache->aspace (),
stop_pc, ecs->event_thread, &ecs->ws); ecs->event_thread->suspend.stop_pc,
ecs->event_thread, &ecs->ws);
if (handle_stop_requested (ecs)) if (handle_stop_requested (ecs))
return; return;
@ -5183,11 +5186,13 @@ Cannot fill $_exitsignal with the correct signal number.\n"));
and not immediately. */ and not immediately. */
ecs->event_thread->pending_follow = ecs->ws; ecs->event_thread->pending_follow = ecs->ws;
stop_pc = regcache_read_pc (get_thread_regcache (ecs->event_thread)); ecs->event_thread->suspend.stop_pc
= regcache_read_pc (get_thread_regcache (ecs->event_thread));
ecs->event_thread->control.stop_bpstat ecs->event_thread->control.stop_bpstat
= bpstat_stop_status (get_current_regcache ()->aspace (), = bpstat_stop_status (get_current_regcache ()->aspace (),
stop_pc, ecs->event_thread, &ecs->ws); ecs->event_thread->suspend.stop_pc,
ecs->event_thread, &ecs->ws);
if (handle_stop_requested (ecs)) if (handle_stop_requested (ecs))
return; return;
@ -5294,11 +5299,13 @@ Cannot fill $_exitsignal with the correct signal number.\n"));
execd thread for that case (this is a nop otherwise). */ execd thread for that case (this is a nop otherwise). */
ecs->event_thread = inferior_thread (); ecs->event_thread = inferior_thread ();
stop_pc = regcache_read_pc (get_thread_regcache (ecs->event_thread)); ecs->event_thread->suspend.stop_pc
= regcache_read_pc (get_thread_regcache (ecs->event_thread));
ecs->event_thread->control.stop_bpstat ecs->event_thread->control.stop_bpstat
= bpstat_stop_status (get_current_regcache ()->aspace (), = bpstat_stop_status (get_current_regcache ()->aspace (),
stop_pc, ecs->event_thread, &ecs->ws); ecs->event_thread->suspend.stop_pc,
ecs->event_thread, &ecs->ws);
/* Note that this may be referenced from inside /* Note that this may be referenced from inside
bpstat_stop_status above, through inferior_has_execd. */ bpstat_stop_status above, through inferior_has_execd. */
@ -5359,7 +5366,8 @@ Cannot fill $_exitsignal with the correct signal number.\n"));
fprintf_unfiltered (gdb_stdlog, "infrun: stopped\n"); fprintf_unfiltered (gdb_stdlog, "infrun: stopped\n");
delete_just_stopped_threads_single_step_breakpoints (); delete_just_stopped_threads_single_step_breakpoints ();
stop_pc = regcache_read_pc (get_thread_regcache (inferior_thread ())); ecs->event_thread->suspend.stop_pc
= regcache_read_pc (get_thread_regcache (inferior_thread ()));
if (handle_stop_requested (ecs)) if (handle_stop_requested (ecs))
return; return;
@ -5651,7 +5659,8 @@ handle_signal_stop (struct execution_control_state *ecs)
&& ecs->event_thread->suspend.stop_signal == GDB_SIGNAL_TRAP) && ecs->event_thread->suspend.stop_signal == GDB_SIGNAL_TRAP)
ecs->event_thread->suspend.stop_signal = GDB_SIGNAL_0; ecs->event_thread->suspend.stop_signal = GDB_SIGNAL_0;
stop_pc = regcache_read_pc (get_thread_regcache (ecs->event_thread)); ecs->event_thread->suspend.stop_pc
= regcache_read_pc (get_thread_regcache (ecs->event_thread));
if (debug_infrun) if (debug_infrun)
{ {
@ -5662,7 +5671,8 @@ handle_signal_stop (struct execution_control_state *ecs)
inferior_ptid = ecs->ptid; inferior_ptid = ecs->ptid;
fprintf_unfiltered (gdb_stdlog, "infrun: stop_pc = %s\n", fprintf_unfiltered (gdb_stdlog, "infrun: stop_pc = %s\n",
paddress (gdbarch, stop_pc)); paddress (gdbarch,
ecs->event_thread->suspend.stop_pc));
if (target_stopped_by_watchpoint ()) if (target_stopped_by_watchpoint ())
{ {
CORE_ADDR addr; CORE_ADDR addr;
@ -5858,14 +5868,18 @@ handle_signal_stop (struct execution_control_state *ecs)
user had set a breakpoint on that inlined code, the missing user had set a breakpoint on that inlined code, the missing
skip_inline_frames call would break things. Fortunately skip_inline_frames call would break things. Fortunately
that's an extremely unlikely scenario. */ that's an extremely unlikely scenario. */
if (!pc_at_non_inline_function (aspace, stop_pc, &ecs->ws) if (!pc_at_non_inline_function (aspace,
ecs->event_thread->suspend.stop_pc,
&ecs->ws)
&& !(ecs->event_thread->suspend.stop_signal == GDB_SIGNAL_TRAP && !(ecs->event_thread->suspend.stop_signal == GDB_SIGNAL_TRAP
&& ecs->event_thread->control.trap_expected && ecs->event_thread->control.trap_expected
&& pc_at_non_inline_function (aspace, && pc_at_non_inline_function (aspace,
ecs->event_thread->prev_pc, ecs->event_thread->prev_pc,
&ecs->ws))) &ecs->ws)))
{ {
stop_chain = build_bpstat_chain (aspace, stop_pc, &ecs->ws); stop_chain = build_bpstat_chain (aspace,
ecs->event_thread->suspend.stop_pc,
&ecs->ws);
skip_inline_frames (ecs->event_thread, stop_chain); skip_inline_frames (ecs->event_thread, stop_chain);
/* Re-fetch current thread's frame in case that invalidated /* Re-fetch current thread's frame in case that invalidated
@ -5915,7 +5929,8 @@ handle_signal_stop (struct execution_control_state *ecs)
handles this event. */ handles this event. */
ecs->event_thread->control.stop_bpstat ecs->event_thread->control.stop_bpstat
= bpstat_stop_status (get_current_regcache ()->aspace (), = bpstat_stop_status (get_current_regcache ()->aspace (),
stop_pc, ecs->event_thread, &ecs->ws, stop_chain); ecs->event_thread->suspend.stop_pc,
ecs->event_thread, &ecs->ws, stop_chain);
/* Following in case break condition called a /* Following in case break condition called a
function. */ function. */
@ -5967,7 +5982,8 @@ handle_signal_stop (struct execution_control_state *ecs)
been removed. */ been removed. */
if (random_signal && target_stopped_by_sw_breakpoint ()) if (random_signal && target_stopped_by_sw_breakpoint ())
{ {
if (program_breakpoint_here_p (gdbarch, stop_pc)) if (program_breakpoint_here_p (gdbarch,
ecs->event_thread->suspend.stop_pc))
{ {
struct regcache *regcache; struct regcache *regcache;
int decr_pc; int decr_pc;
@ -5985,7 +6001,8 @@ handle_signal_stop (struct execution_control_state *ecs)
restore_operation_disable.emplace restore_operation_disable.emplace
(record_full_gdb_operation_disable_set ()); (record_full_gdb_operation_disable_set ());
regcache_write_pc (regcache, stop_pc + decr_pc); regcache_write_pc (regcache,
ecs->event_thread->suspend.stop_pc + decr_pc);
} }
} }
else else
@ -6077,7 +6094,7 @@ handle_signal_stop (struct execution_control_state *ecs)
if (signal_program[ecs->event_thread->suspend.stop_signal] == 0) if (signal_program[ecs->event_thread->suspend.stop_signal] == 0)
ecs->event_thread->suspend.stop_signal = GDB_SIGNAL_0; ecs->event_thread->suspend.stop_signal = GDB_SIGNAL_0;
if (ecs->event_thread->prev_pc == stop_pc if (ecs->event_thread->prev_pc == ecs->event_thread->suspend.stop_pc
&& ecs->event_thread->control.trap_expected && ecs->event_thread->control.trap_expected
&& ecs->event_thread->control.step_resume_breakpoint == NULL) && ecs->event_thread->control.step_resume_breakpoint == NULL)
{ {
@ -6109,7 +6126,8 @@ handle_signal_stop (struct execution_control_state *ecs)
} }
if (ecs->event_thread->suspend.stop_signal != GDB_SIGNAL_0 if (ecs->event_thread->suspend.stop_signal != GDB_SIGNAL_0
&& (pc_in_thread_step_range (stop_pc, ecs->event_thread) && (pc_in_thread_step_range (ecs->event_thread->suspend.stop_pc,
ecs->event_thread)
|| ecs->event_thread->control.step_range_end == 1) || ecs->event_thread->control.step_range_end == 1)
&& frame_id_eq (get_stack_frame_id (frame), && frame_id_eq (get_stack_frame_id (frame),
ecs->event_thread->control.step_stack_frame_id) ecs->event_thread->control.step_stack_frame_id)
@ -6339,7 +6357,7 @@ process_event_stop_test (struct execution_control_state *ecs)
return; return;
} }
fill_in_stop_func (gdbarch, ecs); fill_in_stop_func (gdbarch, ecs);
if (stop_pc == ecs->stop_func_start if (ecs->event_thread->suspend.stop_pc == ecs->stop_func_start
&& execution_direction == EXEC_REVERSE) && execution_direction == EXEC_REVERSE)
{ {
/* We are stepping over a function call in reverse, and just /* We are stepping over a function call in reverse, and just
@ -6472,7 +6490,8 @@ process_event_stop_test (struct execution_control_state *ecs)
through a function epilogue and therefore must detect when through a function epilogue and therefore must detect when
the current-frame changes in the middle of a line. */ the current-frame changes in the middle of a line. */
if (pc_in_thread_step_range (stop_pc, ecs->event_thread) if (pc_in_thread_step_range (ecs->event_thread->suspend.stop_pc,
ecs->event_thread)
&& (execution_direction != EXEC_REVERSE && (execution_direction != EXEC_REVERSE
|| frame_id_eq (get_frame_id (frame), || frame_id_eq (get_frame_id (frame),
ecs->event_thread->control.step_frame_id))) ecs->event_thread->control.step_frame_id)))
@ -6491,6 +6510,7 @@ process_event_stop_test (struct execution_control_state *ecs)
/* When stepping backward, stop at beginning of line range /* When stepping backward, stop at beginning of line range
(unless it's the function entry point, in which case (unless it's the function entry point, in which case
keep going back to the call point). */ keep going back to the call point). */
CORE_ADDR stop_pc = ecs->event_thread->suspend.stop_pc;
if (stop_pc == ecs->event_thread->control.step_range_start if (stop_pc == ecs->event_thread->control.step_range_start
&& stop_pc != ecs->stop_func_start && stop_pc != ecs->stop_func_start
&& execution_direction == EXEC_REVERSE) && execution_direction == EXEC_REVERSE)
@ -6517,10 +6537,11 @@ process_event_stop_test (struct execution_control_state *ecs)
if (execution_direction != EXEC_REVERSE if (execution_direction != EXEC_REVERSE
&& ecs->event_thread->control.step_over_calls == STEP_OVER_UNDEBUGGABLE && ecs->event_thread->control.step_over_calls == STEP_OVER_UNDEBUGGABLE
&& in_solib_dynsym_resolve_code (stop_pc)) && in_solib_dynsym_resolve_code (ecs->event_thread->suspend.stop_pc))
{ {
CORE_ADDR pc_after_resolver = CORE_ADDR pc_after_resolver =
gdbarch_skip_solib_resolver (gdbarch, stop_pc); gdbarch_skip_solib_resolver (gdbarch,
ecs->event_thread->suspend.stop_pc);
if (debug_infrun) if (debug_infrun)
fprintf_unfiltered (gdb_stdlog, fprintf_unfiltered (gdb_stdlog,
@ -6544,7 +6565,8 @@ process_event_stop_test (struct execution_control_state *ecs)
/* Step through an indirect branch thunk. */ /* Step through an indirect branch thunk. */
if (ecs->event_thread->control.step_over_calls != STEP_OVER_NONE if (ecs->event_thread->control.step_over_calls != STEP_OVER_NONE
&& gdbarch_in_indirect_branch_thunk (gdbarch, stop_pc)) && gdbarch_in_indirect_branch_thunk (gdbarch,
ecs->event_thread->suspend.stop_pc))
{ {
if (debug_infrun) if (debug_infrun)
fprintf_unfiltered (gdb_stdlog, fprintf_unfiltered (gdb_stdlog,
@ -6576,13 +6598,14 @@ process_event_stop_test (struct execution_control_state *ecs)
call check below as on some targets return trampolines look call check below as on some targets return trampolines look
like subroutine calls (MIPS16 return thunks). */ like subroutine calls (MIPS16 return thunks). */
if (gdbarch_in_solib_return_trampoline (gdbarch, if (gdbarch_in_solib_return_trampoline (gdbarch,
stop_pc, ecs->stop_func_name) ecs->event_thread->suspend.stop_pc,
ecs->stop_func_name)
&& ecs->event_thread->control.step_over_calls != STEP_OVER_NONE) && ecs->event_thread->control.step_over_calls != STEP_OVER_NONE)
{ {
/* Determine where this trampoline returns. */ /* Determine where this trampoline returns. */
CORE_ADDR real_stop_pc; CORE_ADDR stop_pc = ecs->event_thread->suspend.stop_pc;
CORE_ADDR real_stop_pc
real_stop_pc = gdbarch_skip_trampoline_code (gdbarch, frame, stop_pc); = gdbarch_skip_trampoline_code (gdbarch, frame, stop_pc);
if (debug_infrun) if (debug_infrun)
fprintf_unfiltered (gdb_stdlog, fprintf_unfiltered (gdb_stdlog,
@ -6634,8 +6657,9 @@ process_event_stop_test (struct execution_control_state *ecs)
&& (!frame_id_eq (ecs->event_thread->control.step_stack_frame_id, && (!frame_id_eq (ecs->event_thread->control.step_stack_frame_id,
outer_frame_id) outer_frame_id)
|| (ecs->event_thread->control.step_start_function || (ecs->event_thread->control.step_start_function
!= find_pc_function (stop_pc))))) != find_pc_function (ecs->event_thread->suspend.stop_pc)))))
{ {
CORE_ADDR stop_pc = ecs->event_thread->suspend.stop_pc;
CORE_ADDR real_stop_pc; CORE_ADDR real_stop_pc;
if (debug_infrun) if (debug_infrun)
@ -6793,6 +6817,8 @@ process_event_stop_test (struct execution_control_state *ecs)
if (execution_direction == EXEC_REVERSE if (execution_direction == EXEC_REVERSE
&& ecs->event_thread->control.step_over_calls != STEP_OVER_NONE) && ecs->event_thread->control.step_over_calls != STEP_OVER_NONE)
{ {
CORE_ADDR stop_pc = ecs->event_thread->suspend.stop_pc;
if (gdbarch_skip_trampoline_code (gdbarch, frame, stop_pc) if (gdbarch_skip_trampoline_code (gdbarch, frame, stop_pc)
|| (ecs->stop_func_start == 0 || (ecs->stop_func_start == 0
&& in_solib_dynsym_resolve_code (stop_pc))) && in_solib_dynsym_resolve_code (stop_pc)))
@ -6820,7 +6846,7 @@ process_event_stop_test (struct execution_control_state *ecs)
} }
} }
stop_pc_sal = find_pc_line (stop_pc, 0); stop_pc_sal = find_pc_line (ecs->event_thread->suspend.stop_pc, 0);
/* NOTE: tausq/2004-05-24: This if block used to be done before all /* NOTE: tausq/2004-05-24: This if block used to be done before all
the trampoline processing logic, however, there are some trampolines the trampoline processing logic, however, there are some trampolines
@ -6946,7 +6972,7 @@ process_event_stop_test (struct execution_control_state *ecs)
return; return;
} }
if ((stop_pc == stop_pc_sal.pc) if ((ecs->event_thread->suspend.stop_pc == stop_pc_sal.pc)
&& (ecs->event_thread->current_line != stop_pc_sal.line && (ecs->event_thread->current_line != stop_pc_sal.line
|| ecs->event_thread->current_symtab != stop_pc_sal.symtab)) || ecs->event_thread->current_symtab != stop_pc_sal.symtab))
{ {
@ -7180,7 +7206,7 @@ keep_going_stepped_thread (struct thread_info *tp)
reset_ecs (ecs, tp); reset_ecs (ecs, tp);
switch_to_thread (tp); switch_to_thread (tp);
stop_pc = regcache_read_pc (get_thread_regcache (tp)); tp->suspend.stop_pc = regcache_read_pc (get_thread_regcache (tp));
frame = get_current_frame (); frame = get_current_frame ();
/* If the PC of the thread we were trying to single-step has /* If the PC of the thread we were trying to single-step has
@ -7196,7 +7222,7 @@ keep_going_stepped_thread (struct thread_info *tp)
This prevents us continuously moving the single-step breakpoint This prevents us continuously moving the single-step breakpoint
forward, one instruction at a time, overstepping. */ forward, one instruction at a time, overstepping. */
if (stop_pc != tp->prev_pc) if (tp->suspend.stop_pc != tp->prev_pc)
{ {
ptid_t resume_ptid; ptid_t resume_ptid;
@ -7204,7 +7230,7 @@ keep_going_stepped_thread (struct thread_info *tp)
fprintf_unfiltered (gdb_stdlog, fprintf_unfiltered (gdb_stdlog,
"infrun: expected thread advanced also (%s -> %s)\n", "infrun: expected thread advanced also (%s -> %s)\n",
paddress (target_gdbarch (), tp->prev_pc), paddress (target_gdbarch (), tp->prev_pc),
paddress (target_gdbarch (), stop_pc)); paddress (target_gdbarch (), tp->suspend.stop_pc));
/* Clear the info of the previous step-over, as it's no longer /* Clear the info of the previous step-over, as it's no longer
valid (if the thread was trying to step over a breakpoint, it valid (if the thread was trying to step over a breakpoint, it
@ -7218,7 +7244,7 @@ keep_going_stepped_thread (struct thread_info *tp)
insert_single_step_breakpoint (get_frame_arch (frame), insert_single_step_breakpoint (get_frame_arch (frame),
get_frame_address_space (frame), get_frame_address_space (frame),
stop_pc); tp->suspend.stop_pc);
tp->resumed = 1; tp->resumed = 1;
resume_ptid = internal_resume_ptid (tp->control.stepping_command); resume_ptid = internal_resume_ptid (tp->control.stepping_command);
@ -7259,7 +7285,8 @@ handle_step_into_function (struct gdbarch *gdbarch,
{ {
fill_in_stop_func (gdbarch, ecs); fill_in_stop_func (gdbarch, ecs);
compunit_symtab *cust = find_pc_compunit_symtab (stop_pc); compunit_symtab *cust
= find_pc_compunit_symtab (ecs->event_thread->suspend.stop_pc);
if (cust != NULL && compunit_language (cust) != language_asm) if (cust != NULL && compunit_language (cust) != language_asm)
ecs->stop_func_start ecs->stop_func_start
= gdbarch_skip_prologue_noexcept (gdbarch, ecs->stop_func_start); = gdbarch_skip_prologue_noexcept (gdbarch, ecs->stop_func_start);
@ -7299,7 +7326,7 @@ handle_step_into_function (struct gdbarch *gdbarch,
ecs->stop_func_start); ecs->stop_func_start);
} }
if (ecs->stop_func_start == stop_pc) if (ecs->stop_func_start == ecs->event_thread->suspend.stop_pc)
{ {
/* We are already there: stop now. */ /* We are already there: stop now. */
end_stepping_range (ecs); end_stepping_range (ecs);
@ -7338,15 +7365,15 @@ handle_step_into_function_backward (struct gdbarch *gdbarch,
fill_in_stop_func (gdbarch, ecs); fill_in_stop_func (gdbarch, ecs);
cust = find_pc_compunit_symtab (stop_pc); cust = find_pc_compunit_symtab (ecs->event_thread->suspend.stop_pc);
if (cust != NULL && compunit_language (cust) != language_asm) if (cust != NULL && compunit_language (cust) != language_asm)
ecs->stop_func_start ecs->stop_func_start
= gdbarch_skip_prologue_noexcept (gdbarch, ecs->stop_func_start); = gdbarch_skip_prologue_noexcept (gdbarch, ecs->stop_func_start);
stop_func_sal = find_pc_line (stop_pc, 0); stop_func_sal = find_pc_line (ecs->event_thread->suspend.stop_pc, 0);
/* OK, we're just going to keep stepping here. */ /* OK, we're just going to keep stepping here. */
if (stop_func_sal.pc == stop_pc) if (stop_func_sal.pc == ecs->event_thread->suspend.stop_pc)
{ {
/* We're there already. Just stop stepping now. */ /* We're there already. Just stop stepping now. */
end_stepping_range (ecs); end_stepping_range (ecs);
@ -7981,7 +8008,8 @@ print_stop_location (struct target_waitstatus *ws)
if (tp->control.stop_step if (tp->control.stop_step
&& frame_id_eq (tp->control.step_frame_id, && frame_id_eq (tp->control.step_frame_id,
get_frame_id (get_current_frame ())) get_frame_id (get_current_frame ()))
&& tp->control.step_start_function == find_pc_function (stop_pc)) && (tp->control.step_start_function
== find_pc_function (tp->suspend.stop_pc)))
{ {
/* Finished step, just print source line. */ /* Finished step, just print source line. */
source_flag = SRC_LINE; source_flag = SRC_LINE;
@ -8785,7 +8813,6 @@ struct infcall_suspend_state
struct thread_suspend_state thread_suspend; struct thread_suspend_state thread_suspend;
/* Other fields: */ /* Other fields: */
CORE_ADDR stop_pc;
readonly_detached_regcache *registers; readonly_detached_regcache *registers;
/* Format of SIGINFO_DATA or NULL if it is not present. */ /* Format of SIGINFO_DATA or NULL if it is not present. */
@ -8840,8 +8867,6 @@ save_infcall_suspend_state (void)
GDB_SIGNAL_0 anyway. */ GDB_SIGNAL_0 anyway. */
tp->suspend.stop_signal = GDB_SIGNAL_0; tp->suspend.stop_signal = GDB_SIGNAL_0;
inf_state->stop_pc = stop_pc;
inf_state->registers = new readonly_detached_regcache (*regcache); inf_state->registers = new readonly_detached_regcache (*regcache);
return inf_state; return inf_state;
@ -8858,8 +8883,6 @@ restore_infcall_suspend_state (struct infcall_suspend_state *inf_state)
tp->suspend = inf_state->thread_suspend; tp->suspend = inf_state->thread_suspend;
stop_pc = inf_state->stop_pc;
if (inf_state->siginfo_gdbarch == gdbarch) if (inf_state->siginfo_gdbarch == gdbarch)
{ {
struct type *type = gdbarch_get_siginfo_type (gdbarch); struct type *type = gdbarch_get_siginfo_type (gdbarch);

View File

@ -267,7 +267,8 @@ fork_load_infrun_state (struct fork_info *fp)
registers_changed (); registers_changed ();
reinit_frame_cache (); reinit_frame_cache ();
stop_pc = regcache_read_pc (get_current_regcache ()); inferior_thread ()->suspend.stop_pc
= regcache_read_pc (get_current_regcache ());
nullify_last_target_wait_ptid (); nullify_last_target_wait_ptid ();
/* Now restore the file positions of open file descriptors. */ /* Now restore the file positions of open file descriptors. */

View File

@ -2805,7 +2805,8 @@ record_btrace_set_replay (struct thread_info *tp,
/* Start anew from the new replay position. */ /* Start anew from the new replay position. */
record_btrace_clear_histories (btinfo); record_btrace_clear_histories (btinfo);
stop_pc = regcache_read_pc (get_current_regcache ()); inferior_thread ()->suspend.stop_pc
= regcache_read_pc (get_current_regcache ());
print_stack_frame (get_selected_frame (NULL), 1, SRC_AND_LOC, 1); print_stack_frame (get_selected_frame (NULL), 1, SRC_AND_LOC, 1);
} }

View File

@ -2011,7 +2011,8 @@ record_full_goto_entry (struct record_full_entry *p)
registers_changed (); registers_changed ();
reinit_frame_cache (); reinit_frame_cache ();
stop_pc = regcache_read_pc (get_current_regcache ()); inferior_thread ()->suspend.stop_pc
= regcache_read_pc (get_current_regcache ());
print_stack_frame (get_selected_frame (NULL), 1, SRC_AND_LOC, 1); print_stack_frame (get_selected_frame (NULL), 1, SRC_AND_LOC, 1);
} }

View File

@ -4331,7 +4331,7 @@ print_one_stopped_thread (struct thread_info *thread)
struct target_waitstatus *ws = &thread->suspend.waitstatus; struct target_waitstatus *ws = &thread->suspend.waitstatus;
switch_to_thread (thread); switch_to_thread (thread);
stop_pc = get_frame_pc (get_current_frame ()); thread->suspend.stop_pc = get_frame_pc (get_current_frame ());
set_current_sal_from_frame (get_current_frame ()); set_current_sal_from_frame (get_current_frame ());
thread->suspend.waitstatus_pending_p = 0; thread->suspend.waitstatus_pending_p = 0;

View File

@ -2153,7 +2153,8 @@ target_resume (ptid_t ptid, int step, enum gdb_signal signal)
registers_changed_ptid (ptid); registers_changed_ptid (ptid);
/* We only set the internal executing state here. The user/frontend /* We only set the internal executing state here. The user/frontend
running state is set at a higher level. */ running state is set at a higher level. This also clears the
thread's stop_pc as side effect. */
set_executing (ptid, 1); set_executing (ptid, 1);
clear_inline_frame_state (ptid); clear_inline_frame_state (ptid);
} }

View File

@ -918,6 +918,18 @@ is_executing (ptid_t ptid)
return tp->executing; return tp->executing;
} }
/* Helper for set_executing. Set's the thread's 'executing' field
from EXECUTING, and if EXECUTING is true also clears the thread's
stop_pc. */
static void
set_executing_thread (thread_info *thr, bool executing)
{
thr->executing = executing;
if (executing)
thr->suspend.stop_pc = ~(CORE_ADDR) 0;
}
void void
set_executing (ptid_t ptid, int executing) set_executing (ptid_t ptid, int executing)
{ {
@ -928,13 +940,13 @@ set_executing (ptid_t ptid, int executing)
{ {
for (tp = thread_list; tp; tp = tp->next) for (tp = thread_list; tp; tp = tp->next)
if (all || ptid_get_pid (tp->ptid) == ptid_get_pid (ptid)) if (all || ptid_get_pid (tp->ptid) == ptid_get_pid (ptid))
tp->executing = executing; set_executing_thread (tp, executing);
} }
else else
{ {
tp = find_thread_ptid (ptid); tp = find_thread_ptid (ptid);
gdb_assert (tp); gdb_assert (tp);
tp->executing = executing; set_executing_thread (tp, executing);
} }
/* It only takes one running thread to spawn more threads.*/ /* It only takes one running thread to spawn more threads.*/
@ -1328,7 +1340,6 @@ switch_to_thread_no_regs (struct thread_info *thread)
set_current_inferior (inf); set_current_inferior (inf);
inferior_ptid = thread->ptid; inferior_ptid = thread->ptid;
stop_pc = ~(CORE_ADDR) 0;
} }
/* See gdbthread.h. */ /* See gdbthread.h. */
@ -1341,7 +1352,6 @@ switch_to_no_thread ()
inferior_ptid = null_ptid; inferior_ptid = null_ptid;
reinit_frame_cache (); reinit_frame_cache ();
stop_pc = ~(CORE_ADDR) 0;
} }
/* See gdbthread.h. */ /* See gdbthread.h. */
@ -1357,13 +1367,6 @@ switch_to_thread (thread_info *thr)
switch_to_thread_no_regs (thr); switch_to_thread_no_regs (thr);
reinit_frame_cache (); reinit_frame_cache ();
/* We don't check for is_stopped, because we're called at times
while in the TARGET_RUNNING state, e.g., while handling an
internal event. */
if (thr->state != THREAD_EXITED
&& !thr->executing)
stop_pc = regcache_read_pc (get_thread_regcache (thr));
} }
/* See common/common-gdbthread.h. */ /* See common/common-gdbthread.h. */