process.
Copyright 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994,
- 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003 Free Software
- Foundation, Inc.
+ 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free
+ Software Foundation, Inc.
This file is part of GDB.
static void delete_breakpoint_current_contents (void *);
-static void set_follow_fork_mode_command (char *arg, int from_tty,
- struct cmd_list_element *c);
-
static int restore_selected_frame (void *);
static void build_infrun (void);
static void xdb_handle_command (char *args, int from_tty);
+static int prepare_to_proceed (void);
+
void _initialize_infrun (void);
int inferior_ignoring_startup_exec_events = 0;
#define IN_SOLIB_DYNSYM_RESOLVE_CODE(pc) 0
#endif
-#ifndef SKIP_SOLIB_RESOLVER
-#define SKIP_SOLIB_RESOLVER(pc) 0
-#endif
-
/* This function returns TRUE if pc is the address of an instruction
that lies within the dynamic linker (such as the event hook, or the
dld itself).
}
pending_follow;
-static const char follow_fork_mode_ask[] = "ask";
static const char follow_fork_mode_child[] = "child";
static const char follow_fork_mode_parent[] = "parent";
static const char *follow_fork_mode_kind_names[] = {
- follow_fork_mode_ask,
follow_fork_mode_child,
follow_fork_mode_parent,
NULL
static int
follow_fork (void)
{
- const char *follow_mode = follow_fork_mode_string;
- int follow_child = (follow_mode == follow_fork_mode_child);
-
- /* Or, did the user not know, and want us to ask? */
- if (follow_fork_mode_string == follow_fork_mode_ask)
- {
- internal_error (__FILE__, __LINE__,
- "follow_inferior_fork: \"ask\" mode not implemented");
- /* follow_mode = follow_fork_mode_...; */
- }
+ int follow_child = (follow_fork_mode_string == follow_fork_mode_child);
return target_follow_fork (follow_child);
}
\f
/* Things to clean up if we QUIT out of resume (). */
-/* ARGSUSED */
static void
resume_cleanups (void *ignore)
{
the set command passed as a parameter. The clone operation will
include (BUG?) any ``set'' command callback, if present.
Commands like ``info set'' call all the ``show'' command
- callbacks. Unfortunatly, for ``show'' commands cloned from
+ callbacks. Unfortunately, for ``show'' commands cloned from
``set'', this includes callbacks belonging to ``set'' commands.
Making this worse, this only occures if add_show_from_set() is
called after add_cmd_sfunc() (BUG?). */
bpstat_clear (&stop_bpstat);
}
+/* This should be suitable for any targets that support threads. */
+
+static int
+prepare_to_proceed (void)
+{
+ ptid_t wait_ptid;
+ struct target_waitstatus wait_status;
+
+ /* Get the last target status returned by target_wait(). */
+ get_last_target_status (&wait_ptid, &wait_status);
+
+ /* Make sure we were stopped either at a breakpoint, or because
+ of a Ctrl-C. */
+ if (wait_status.kind != TARGET_WAITKIND_STOPPED
+ || (wait_status.value.sig != TARGET_SIGNAL_TRAP &&
+ wait_status.value.sig != TARGET_SIGNAL_INT))
+ {
+ return 0;
+ }
+
+ if (!ptid_equal (wait_ptid, minus_one_ptid)
+ && !ptid_equal (inferior_ptid, wait_ptid))
+ {
+ /* Switched over from WAIT_PID. */
+ CORE_ADDR wait_pc = read_pc_pid (wait_ptid);
+
+ if (wait_pc != read_pc ())
+ {
+ /* Switch back to WAIT_PID thread. */
+ inferior_ptid = wait_ptid;
+
+ /* FIXME: This stuff came from switch_to_thread() in
+ thread.c (which should probably be a public function). */
+ flush_cached_frames ();
+ registers_changed ();
+ stop_pc = wait_pc;
+ select_frame (get_current_frame ());
+ }
+
+ /* We return 1 to indicate that there is a breakpoint here,
+ so we need to step over it before continuing to avoid
+ hitting it straight away. */
+ if (breakpoint_here_p (wait_pc))
+ return 1;
+ }
+
+ return 0;
+
+}
/* Record the pc of the program the last time it stopped. This is
just used internally by wait_for_inferior, but need to be preserved
write_pc (addr);
}
-#ifdef PREPARE_TO_PROCEED
/* In a multi-threaded task we may select another thread
and then continue or step.
any execution (i.e. it will report a breakpoint hit
incorrectly). So we must step over it first.
- PREPARE_TO_PROCEED checks the current thread against the thread
+ prepare_to_proceed checks the current thread against the thread
that reported the most recent event. If a step-over is required
it returns TRUE and sets the current thread to the old thread. */
- if (PREPARE_TO_PROCEED (1) && breakpoint_here_p (read_pc ()))
- {
- oneproc = 1;
- }
-
-#endif /* PREPARE_TO_PROCEED */
+ if (prepare_to_proceed () && breakpoint_here_p (read_pc ()))
+ oneproc = 1;
#ifdef HP_OS_BUG
if (trap_expected_after_continue)
void init_execution_control_state (struct execution_control_state *ecs);
+static void handle_step_into_function (struct execution_control_state *ecs);
void handle_inferior_event (struct execution_control_state *ecs);
static void check_sigtramp2 (struct execution_control_state *ecs);
return PC_IN_SIGTRAMP (pc, name);
}
+/* Handle the inferior event in the cases when we just stepped
+ into a function. */
+
+static void
+handle_step_into_function (struct execution_control_state *ecs)
+{
+ CORE_ADDR real_stop_pc;
+
+ if ((step_over_calls == STEP_OVER_NONE)
+ || ((step_range_end == 1)
+ && in_prologue (prev_pc, ecs->stop_func_start)))
+ {
+ /* I presume that step_over_calls is only 0 when we're
+ supposed to be stepping at the assembly language level
+ ("stepi"). Just stop. */
+ /* Also, maybe we just did a "nexti" inside a prolog,
+ so we thought it was a subroutine call but it was not.
+ Stop as well. FENN */
+ stop_step = 1;
+ print_stop_reason (END_STEPPING_RANGE, 0);
+ stop_stepping (ecs);
+ return;
+ }
+
+ if (step_over_calls == STEP_OVER_ALL || IGNORE_HELPER_CALL (stop_pc))
+ {
+ /* We're doing a "next". */
+
+ if (pc_in_sigtramp (stop_pc)
+ && frame_id_inner (step_frame_id,
+ frame_id_build (read_sp (), 0)))
+ /* We stepped out of a signal handler, and into its
+ calling trampoline. This is misdetected as a
+ subroutine call, but stepping over the signal
+ trampoline isn't such a bad idea. In order to do that,
+ we have to ignore the value in step_frame_id, since
+ that doesn't represent the frame that'll reach when we
+ return from the signal trampoline. Otherwise we'll
+ probably continue to the end of the program. */
+ step_frame_id = null_frame_id;
+
+ step_over_function (ecs);
+ keep_going (ecs);
+ return;
+ }
+
+ /* If we are in a function call trampoline (a stub between
+ the calling routine and the real function), locate the real
+ function. That's what tells us (a) whether we want to step
+ into it at all, and (b) what prologue we want to run to
+ the end of, if we do step into it. */
+ real_stop_pc = skip_language_trampoline (stop_pc);
+ if (real_stop_pc == 0)
+ real_stop_pc = SKIP_TRAMPOLINE_CODE (stop_pc);
+ if (real_stop_pc != 0)
+ ecs->stop_func_start = real_stop_pc;
+
+ /* If we have line number information for the function we
+ are thinking of stepping into, step into it.
+
+ If there are several symtabs at that PC (e.g. with include
+ files), just want to know whether *any* of them have line
+ numbers. find_pc_line handles this. */
+ {
+ struct symtab_and_line tmp_sal;
+
+ tmp_sal = find_pc_line (ecs->stop_func_start, 0);
+ if (tmp_sal.line != 0)
+ {
+ step_into_function (ecs);
+ return;
+ }
+ }
+
+ /* If we have no line number and the step-stop-if-no-debug
+ is set, we stop the step so that the user has a chance to
+ switch in assembly mode. */
+ if (step_over_calls == STEP_OVER_UNDEBUGGABLE && step_stop_if_no_debug)
+ {
+ stop_step = 1;
+ print_stop_reason (END_STEPPING_RANGE, 0);
+ stop_stepping (ecs);
+ return;
+ }
+
+ step_over_function (ecs);
+ keep_going (ecs);
+ return;
+}
/* Given an execution control state that has been freshly filled in
by an event from the inferior, figure out what it means and take
void
handle_inferior_event (struct execution_control_state *ecs)
{
- CORE_ADDR real_stop_pc;
/* NOTE: cagney/2003-03-28: If you're looking at this code and
thinking that the variable stepped_after_stopped_by_watchpoint
isn't used, then you're wrong! The macro STOPPED_BY_WATCHPOINT,
terminal for any messages produced by
breakpoint_re_set. */
target_terminal_ours_for_output ();
- SOLIB_ADD (NULL, 0, NULL, auto_solib_add);
+ /* NOTE: cagney/2003-11-25: Make certain that the target
+ stack's section table is kept up-to-date. Architectures,
+ (e.g., PPC64), use the section table to perform
+ operations such as address => section name and hence
+ require the table to contain all sections (including
+ those found in shared libraries). */
+ /* NOTE: cagney/2003-11-25: Pass current_target and not
+ exec_ops to SOLIB_ADD. This is because current GDB is
+ only tooled to propagate section_table changes out from
+ the "current_target" (see target_resize_to_sections), and
+ not up from the exec stratum. This, of course, isn't
+ right. "infrun.c" should only interact with the
+ exec/process stratum, instead relying on the target stack
+ to propagate relevant changes (stop, section table
+ changed, ...) up to other layers. */
+ SOLIB_ADD (NULL, 0, ¤t_target, auto_solib_add);
target_terminal_inferior ();
/* Reinsert breakpoints and continue. */
terminal for any messages produced by
breakpoint_re_set. */
target_terminal_ours_for_output ();
- SOLIB_ADD (NULL, 0, NULL, auto_solib_add);
+ /* NOTE: cagney/2003-11-25: Make certain that the target
+ stack's section table is kept up-to-date. Architectures,
+ (e.g., PPC64), use the section table to perform
+ operations such as address => section name and hence
+ require the table to contain all sections (including
+ those found in shared libraries). */
+ /* NOTE: cagney/2003-11-25: Pass current_target and not
+ exec_ops to SOLIB_ADD. This is because current GDB is
+ only tooled to propagate section_table changes out from
+ the "current_target" (see target_resize_to_sections), and
+ not up from the exec stratum. This, of course, isn't
+ right. "infrun.c" should only interact with the
+ exec/process stratum, instead relying on the target stack
+ to propagate relevant changes (stop, section table
+ changed, ...) up to other layers. */
+ SOLIB_ADD (NULL, 0, ¤t_target, auto_solib_add);
target_terminal_inferior ();
/* Try to reenable shared library breakpoints, additional
if (step_over_calls == STEP_OVER_UNDEBUGGABLE
&& IN_SOLIB_DYNSYM_RESOLVE_CODE (stop_pc))
{
- CORE_ADDR pc_after_resolver = SKIP_SOLIB_RESOLVER (stop_pc);
+ CORE_ADDR pc_after_resolver =
+ gdbarch_skip_solib_resolver (current_gdbarch, stop_pc);
if (pc_after_resolver)
{
return;
}
- if (stop_pc == ecs->stop_func_start /* Quick test */
- || (in_prologue (stop_pc, ecs->stop_func_start) &&
- !IN_SOLIB_RETURN_TRAMPOLINE (stop_pc, ecs->stop_func_name))
+ if (((stop_pc == ecs->stop_func_start /* Quick test */
+ || in_prologue (stop_pc, ecs->stop_func_start))
+ && !IN_SOLIB_RETURN_TRAMPOLINE (stop_pc, ecs->stop_func_name))
|| IN_SOLIB_CALL_TRAMPOLINE (stop_pc, ecs->stop_func_name)
|| ecs->stop_func_name == 0)
{
/* It's a subroutine call. */
-
- if ((step_over_calls == STEP_OVER_NONE)
- || ((step_range_end == 1)
- && in_prologue (prev_pc, ecs->stop_func_start)))
- {
- /* I presume that step_over_calls is only 0 when we're
- supposed to be stepping at the assembly language level
- ("stepi"). Just stop. */
- /* Also, maybe we just did a "nexti" inside a prolog,
- so we thought it was a subroutine call but it was not.
- Stop as well. FENN */
- stop_step = 1;
- print_stop_reason (END_STEPPING_RANGE, 0);
- stop_stepping (ecs);
- return;
- }
-
- if (step_over_calls == STEP_OVER_ALL || IGNORE_HELPER_CALL (stop_pc))
- {
- /* We're doing a "next". */
-
- if (pc_in_sigtramp (stop_pc)
- && frame_id_inner (step_frame_id,
- frame_id_build (read_sp (), 0)))
- /* We stepped out of a signal handler, and into its
- calling trampoline. This is misdetected as a
- subroutine call, but stepping over the signal
- trampoline isn't such a bad idea. In order to do that,
- we have to ignore the value in step_frame_id, since
- that doesn't represent the frame that'll reach when we
- return from the signal trampoline. Otherwise we'll
- probably continue to the end of the program. */
- step_frame_id = null_frame_id;
-
- step_over_function (ecs);
- keep_going (ecs);
- return;
- }
-
- /* If we are in a function call trampoline (a stub between
- the calling routine and the real function), locate the real
- function. That's what tells us (a) whether we want to step
- into it at all, and (b) what prologue we want to run to
- the end of, if we do step into it. */
- real_stop_pc = skip_language_trampoline (stop_pc);
- if (real_stop_pc == 0)
- real_stop_pc = SKIP_TRAMPOLINE_CODE (stop_pc);
- if (real_stop_pc != 0)
- ecs->stop_func_start = real_stop_pc;
-
- /* If we have line number information for the function we
- are thinking of stepping into, step into it.
-
- If there are several symtabs at that PC (e.g. with include
- files), just want to know whether *any* of them have line
- numbers. find_pc_line handles this. */
- {
- struct symtab_and_line tmp_sal;
-
- tmp_sal = find_pc_line (ecs->stop_func_start, 0);
- if (tmp_sal.line != 0)
- {
- step_into_function (ecs);
- return;
- }
- }
-
- /* If we have no line number and the step-stop-if-no-debug
- is set, we stop the step so that the user has a chance to
- switch in assembly mode. */
- if (step_over_calls == STEP_OVER_UNDEBUGGABLE && step_stop_if_no_debug)
- {
- stop_step = 1;
- print_stop_reason (END_STEPPING_RANGE, 0);
- stop_stepping (ecs);
- return;
- }
-
- step_over_function (ecs);
- keep_going (ecs);
+ handle_step_into_function (ecs);
return;
-
}
/* We've wandered out of the step range. */
if (IN_SOLIB_RETURN_TRAMPOLINE (stop_pc, ecs->stop_func_name))
{
/* Determine where this trampoline returns. */
- real_stop_pc = SKIP_TRAMPOLINE_CODE (stop_pc);
+ CORE_ADDR real_stop_pc = SKIP_TRAMPOLINE_CODE (stop_pc);
/* Only proceed through if we know where it's going. */
if (real_stop_pc)
/* In the case where we just stepped out of a function into the
middle of a line of the caller, continue stepping, but
step_frame_id must be modified to current frame */
+#if 0
+ /* NOTE: cagney/2003-10-16: I think this frame ID inner test is too
+ generous. It will trigger on things like a step into a frameless
+ stackless leaf function. I think the logic should instead look
+ at the unwound frame ID has that should give a more robust
+ indication of what happened. */
+ if (step-ID == current-ID)
+ still stepping in same function;
+ else if (step-ID == unwind (current-ID))
+ stepped into a function;
+ else
+ stepped out of a function;
+ /* Of course this assumes that the frame ID unwind code is robust
+ and we're willing to introduce frame unwind logic into this
+ function. Fortunately, those days are nearly upon us. */
+#endif
{
struct frame_id current_frame = get_frame_id (get_current_frame ());
if (!(frame_id_inner (current_frame, step_frame_id)))
/* If the prologue ends in the middle of a source line, continue to
the end of that source line (if it is still within the function).
Otherwise, just go to end of prologue. */
-#ifdef PROLOGUE_FIRSTLINE_OVERLAP
- /* no, don't either. It skips any code that's legitimately on the
- first line. */
-#else
if (ecs->sal.end
&& ecs->sal.pc != ecs->stop_func_start
&& ecs->sal.end < ecs->stop_func_end)
ecs->stop_func_start = ecs->sal.end;
-#endif
+
+ /* Architectures which require breakpoint adjustment might not be able
+ to place a breakpoint at the computed address. If so, the test
+ ``ecs->stop_func_start == stop_pc'' will never succeed. Adjust
+ ecs->stop_func_start to an address at which a breakpoint may be
+ legitimately placed.
+
+ Note: kevinb/2004-01-19: On FR-V, if this adjustment is not
+ made, GDB will enter an infinite loop when stepping through
+ optimized code consisting of VLIW instructions which contain
+ subinstructions corresponding to different source lines. On
+ FR-V, it's not permitted to place a breakpoint on any but the
+ first subinstruction of a VLIW instruction. When a breakpoint is
+ set, GDB will adjust the breakpoint address to the beginning of
+ the VLIW instruction. Thus, we need to make the corresponding
+ adjustment here when computing the stop address. */
+
+ if (gdbarch_adjust_breakpoint_address_p (current_gdbarch))
+ {
+ ecs->stop_func_start
+ = gdbarch_adjust_breakpoint_address (current_gdbarch,
+ ecs->stop_func_start);
+ }
if (ecs->stop_func_start == stop_pc)
{
- avoid handling the case where the PC hasn't been saved in the
prologue analyzer
- Unfortunatly, not five lines further down, is a call to
+ Unfortunately, not five lines further down, is a call to
get_frame_id() and that is guarenteed to trigger the prologue
analyzer.
if (stop_signal == TARGET_SIGNAL_TRAP && !signal_program[stop_signal])
stop_signal = TARGET_SIGNAL_0;
-#ifdef SHIFT_INST_REGS
- /* I'm not sure when this following segment applies. I do know,
- now, that we shouldn't rewrite the regs when we were stopped
- by a random signal from the inferior process. */
- /* FIXME: Shouldn't this be based on the valid bit of the SXIP?
- (this is only used on the 88k). */
-
- if (!bpstat_explains_signal (stop_bpstat)
- && (stop_signal != TARGET_SIGNAL_CHLD) && !stopped_by_random_signal)
- SHIFT_INST_REGS ();
-#endif /* SHIFT_INST_REGS */
resume (currently_stepping (ecs), stop_signal);
}
void
normal_stop (void)
{
+ struct target_waitstatus last;
+ ptid_t last_ptid;
+
+ get_last_target_status (&last_ptid, &last);
+
/* As with the notification of thread events, we want to delay
notifying the user that we've switched thread context until
the inferior actually stops.
- (Note that there's no point in saying anything if the inferior
- has exited!) */
+ There's no point in saying anything if the inferior has exited.
+ Note that SIGNALLED here means "exited with a signal", not
+ "received a signal". */
if (!ptid_equal (previous_inferior_ptid, inferior_ptid)
- && target_has_execution)
+ && target_has_execution
+ && last.kind != TARGET_WAITKIND_SIGNALLED
+ && last.kind != TARGET_WAITKIND_EXITED)
{
target_terminal_ours_for_output ();
printf_filtered ("[Switching to %s]\n",
write_inferior_status_register (struct inferior_status *inf_status, int regno,
LONGEST val)
{
- int size = REGISTER_RAW_SIZE (regno);
+ int size = DEPRECATED_REGISTER_RAW_SIZE (regno);
void *buf = alloca (size);
store_signed_integer (buf, size, val);
regcache_raw_write (inf_status->registers, regno, buf);
void
_initialize_infrun (void)
{
- register int i;
- register int numsigs;
+ int i;
+ int numsigs;
struct cmd_list_element *c;
register_gdbarch_swap (&stop_registers, sizeof (stop_registers), NULL);
c = add_set_enum_cmd ("follow-fork-mode",
class_run,
follow_fork_mode_kind_names, &follow_fork_mode_string,
-/* ??rehrauer: The "both" option is broken, by what may be a 10.20
- kernel problem. It's also not terribly useful without a GUI to
- help the user drive two debuggers. So for now, I'm disabling
- the "both" option. */
-/* "Set debugger response to a program call of fork \
- or vfork.\n\
- A fork or vfork creates a new process. follow-fork-mode can be:\n\
- parent - the original process is debugged after a fork\n\
- child - the new process is debugged after a fork\n\
- both - both the parent and child are debugged after a fork\n\
- ask - the debugger will ask for one of the above choices\n\
- For \"both\", another copy of the debugger will be started to follow\n\
- the new child process. The original debugger will continue to follow\n\
- the original parent process. To distinguish their prompts, the\n\
- debugger copy's prompt will be changed.\n\
- For \"parent\" or \"child\", the unfollowed process will run free.\n\
- By default, the debugger will follow the parent process.",
- */
"Set debugger response to a program call of fork \
or vfork.\n\
A fork or vfork creates a new process. follow-fork-mode can be:\n\
parent - the original process is debugged after a fork\n\
child - the new process is debugged after a fork\n\
- ask - the debugger will ask for one of the above choices\n\
-For \"parent\" or \"child\", the unfollowed process will run free.\n\
+The unfollowed process will continue to run.\n\
By default, the debugger will follow the parent process.", &setlist);
add_show_from_set (c, &showlist);