#include "probe.h"
#include "objfiles.h"
#include "completer.h"
+#include "target-descriptions.h"
/* Prototypes for local functions */
/* follow-fork child, detach-on-fork on. */
- old_chain = make_cleanup_restore_current_thread ();
+ inf->vfork_parent->pending_detach = 0;
+
+ if (!exec)
+ {
+ /* If we're handling a child exit, then inferior_ptid
+ points at the inferior's pid, not to a thread. */
+ old_chain = save_inferior_ptid ();
+ save_current_program_space ();
+ save_current_inferior ();
+ }
+ else
+ old_chain = save_current_space_and_thread ();
/* We're letting loose of the parent. */
tp = any_live_thread_of_process (inf->vfork_parent->pid);
set_current_inferior (inf);
set_current_program_space (pspace);
}
+ else
+ {
+ /* The old description may no longer be fit for the new image.
+ E.g, a 64-bit process exec'ed a 32-bit process. Clear the
+ old description; we'll read a new one below. No need to do
+ this on "follow-exec-mode new", as the old inferior stays
+ around (its description is later cleared/refetched on
+ restart). */
+ target_clear_description ();
+ }
gdb_assert (current_program_space == inf->pspace);
if ((inf->symfile_flags & SYMFILE_NO_READ) == 0)
set_initial_language ();
+ /* If the target can specify a description, read it. Must do this
+ after flipping to the new executable (because the target supplied
+ description must be compatible with the executable's
+ architecture, and the old executable may e.g., be 32-bit, while
+ the new one 64-bit), and before anything involving memory or
+ registers. */
+ target_find_description ();
+
#ifdef SOLIB_CREATE_INFERIOR_HOOK
SOLIB_CREATE_INFERIOR_HOOK (PIDGET (inferior_ptid));
#else
ptid_t waiton_ptid;
/* Current inferior wait state. */
-enum infwait_states infwait_state;
+static enum infwait_states infwait_state;
/* Data to be passed around while handling an event. This data is
discarded between events. */
return;
case TARGET_WAITKIND_EXITED:
+ case TARGET_WAITKIND_SIGNALLED:
if (debug_infrun)
- fprintf_unfiltered (gdb_stdlog, "infrun: TARGET_WAITKIND_EXITED\n");
+ {
+ if (ecs->ws.kind == TARGET_WAITKIND_EXITED)
+ fprintf_unfiltered (gdb_stdlog,
+ "infrun: TARGET_WAITKIND_EXITED\n");
+ else
+ fprintf_unfiltered (gdb_stdlog,
+ "infrun: TARGET_WAITKIND_SIGNALLED\n");
+ }
+
inferior_ptid = ecs->ptid;
set_current_inferior (find_inferior_pid (ptid_get_pid (ecs->ptid)));
set_current_program_space (current_inferior ()->pspace);
handle_vfork_child_exec_or_exit (0);
target_terminal_ours (); /* Must do this before mourn anyway. */
- print_exited_reason (ecs->ws.value.integer);
- /* Record the exit code in the convenience variable $_exitcode, so
- that the user can inspect this again later. */
- set_internalvar_integer (lookup_internalvar ("_exitcode"),
- (LONGEST) ecs->ws.value.integer);
+ if (ecs->ws.kind == TARGET_WAITKIND_EXITED)
+ {
+ /* Record the exit code in the convenience variable $_exitcode, so
+ that the user can inspect this again later. */
+ set_internalvar_integer (lookup_internalvar ("_exitcode"),
+ (LONGEST) ecs->ws.value.integer);
- /* Also record this in the inferior itself. */
- current_inferior ()->has_exit_code = 1;
- current_inferior ()->exit_code = (LONGEST) ecs->ws.value.integer;
+ /* Also record this in the inferior itself. */
+ current_inferior ()->has_exit_code = 1;
+ current_inferior ()->exit_code = (LONGEST) ecs->ws.value.integer;
+
+ print_exited_reason (ecs->ws.value.integer);
+ }
+ else
+ print_signal_exited_reason (ecs->ws.value.sig);
gdb_flush (gdb_stdout);
target_mourn_inferior ();
stop_stepping (ecs);
return;
- case TARGET_WAITKIND_SIGNALLED:
- if (debug_infrun)
- fprintf_unfiltered (gdb_stdlog, "infrun: TARGET_WAITKIND_SIGNALLED\n");
- inferior_ptid = ecs->ptid;
- set_current_inferior (find_inferior_pid (ptid_get_pid (ecs->ptid)));
- set_current_program_space (current_inferior ()->pspace);
- handle_vfork_child_exec_or_exit (0);
- stop_print_frame = 0;
- target_terminal_ours (); /* Must do this before mourn anyway. */
-
- /* Note: By definition of TARGET_WAITKIND_SIGNALLED, we shouldn't
- reach here unless the inferior is dead. However, for years
- target_kill() was called here, which hints that fatal signals aren't
- really fatal on some systems. If that's true, then some changes
- may be needed. */
- target_mourn_inferior ();
-
- print_signal_exited_reason (ecs->ws.value.sig);
- singlestep_breakpoints_inserted_p = 0;
- cancel_single_step_breakpoints ();
- stop_stepping (ecs);
- return;
-
/* The following are the only cases in which we keep going;
the above cases end in a continue or goto. */
case TARGET_WAITKIND_FORKED:
case TARGET_WAITKIND_VFORKED:
if (debug_infrun)
- fprintf_unfiltered (gdb_stdlog, "infrun: TARGET_WAITKIND_FORKED\n");
+ {
+ if (ecs->ws.kind == TARGET_WAITKIND_FORKED)
+ fprintf_unfiltered (gdb_stdlog, "infrun: TARGET_WAITKIND_FORKED\n");
+ else
+ fprintf_unfiltered (gdb_stdlog, "infrun: TARGET_WAITKIND_VFORKED\n");
+ }
/* Check whether the inferior is displaced stepping. */
{
vfork follow are detached. */
if (ecs->ws.kind != TARGET_WAITKIND_VFORKED)
{
- int child_pid = ptid_get_pid (ecs->ws.value.related_pid);
-
/* This won't actually modify the breakpoint list, but will
physically remove the breakpoints from the child. */
- detach_breakpoints (child_pid);
+ detach_breakpoints (ecs->ws.value.related_pid);
}
if (singlestep_breakpoints_inserted_p)
context_switch (saved_singlestep_ptid);
if (deprecated_context_hook)
- deprecated_context_hook (pid_to_thread_id (ecs->ptid));
+ deprecated_context_hook (pid_to_thread_id (saved_singlestep_ptid));
resume (1, GDB_SIGNAL_0);
prepare_to_wait (ecs);
if (execution_direction == EXEC_REVERSE)
{
- struct symtab_and_line sr_sal;
-
- /* Normal function call return (static or dynamic). */
- init_sal (&sr_sal);
- sr_sal.pc = ecs->stop_func_start;
- sr_sal.pspace = get_frame_program_space (frame);
- insert_step_resume_breakpoint_at_sal (gdbarch,
- sr_sal, null_frame_id);
+ /* If we're already at the start of the function, we've either
+ just stepped backward into a single instruction function,
+ or stepped back out of a signal handler to the first instruction
+ of the function. Just keep going, which will single-step back
+ to the caller. */
+ if (ecs->stop_func_start != stop_pc)
+ {
+ struct symtab_and_line sr_sal;
+
+ /* Normal function call return (static or dynamic). */
+ init_sal (&sr_sal);
+ sr_sal.pc = ecs->stop_func_start;
+ sr_sal.pspace = get_frame_program_space (frame);
+ insert_step_resume_breakpoint_at_sal (gdbarch,
+ sr_sal, null_frame_id);
+ }
}
else
insert_step_resume_breakpoint_at_caller (frame);
if (execution_direction == EXEC_REVERSE)
{
- /* Set a breakpoint at callee's start address.
- From there we can step once and be back in the caller. */
- struct symtab_and_line sr_sal;
+ /* If we're already at the start of the function, we've either just
+ stepped backward into a single instruction function without line
+ number info, or stepped back out of a signal handler to the first
+ instruction of the function without line number info. Just keep
+ going, which will single-step back to the caller. */
+ if (ecs->stop_func_start != stop_pc)
+ {
+ /* Set a breakpoint at callee's start address.
+ From there we can step once and be back in the caller. */
+ struct symtab_and_line sr_sal;
- init_sal (&sr_sal);
- sr_sal.pc = ecs->stop_func_start;
- sr_sal.pspace = get_frame_program_space (frame);
- insert_step_resume_breakpoint_at_sal (gdbarch,
- sr_sal, null_frame_id);
+ init_sal (&sr_sal);
+ sr_sal.pc = ecs->stop_func_start;
+ sr_sal.pspace = get_frame_program_space (frame);
+ insert_step_resume_breakpoint_at_sal (gdbarch,
+ sr_sal, null_frame_id);
+ }
}
else
/* Set a breakpoint at callee's return address (the address
if (inf_state->siginfo_gdbarch == gdbarch)
{
struct type *type = gdbarch_get_siginfo_type (gdbarch);
- size_t len = TYPE_LENGTH (type);
/* Errors ignored. */
target_write (¤t_target, TARGET_OBJECT_SIGNAL_INFO, NULL,
- inf_state->siginfo_data, 0, len);
+ inf_state->siginfo_data, 0, TYPE_LENGTH (type));
}
/* The inferior can be gone if the user types "print exit(0)"
add_info_alias ("handle", "signals", 0);
c = add_com ("handle", class_run, handle_command, _("\
-Specify how to handle a signal.\n\
+Specify how to handle signals.\n\
+Usage: handle SIGNAL [ACTIONS]\n\
Args are signals and actions to apply to those signals.\n\
+If no actions are specified, the current settings for the specified signals\n\
+will be displayed instead.\n\
+\n\
Symbolic signals (e.g. SIGSEGV) are recommended but numeric signals\n\
from 1-15 are allowed for compatibility with old versions of GDB.\n\
Numeric ranges may be specified with the form LOW-HIGH (e.g. 1-5).\n\
The special arg \"all\" is recognized to mean all signals except those\n\
used by the debugger, typically SIGTRAP and SIGINT.\n\
+\n\
Recognized actions include \"stop\", \"nostop\", \"print\", \"noprint\",\n\
\"pass\", \"nopass\", \"ignore\", or \"noignore\".\n\
Stop means reenter debugger if this signal happens (implies print).\n\
Print means print a message if this signal happens.\n\
Pass means let program see this signal; otherwise program doesn't know.\n\
Ignore is a synonym for nopass and noignore is a synonym for pass.\n\
-Pass and Stop may be combined."));
+Pass and Stop may be combined.\n\
+\n\
+Multiple signals may be specified. Signal numbers and signal names\n\
+may be interspersed with actions, with the actions being performed for\n\
+all signals cumulatively specified."));
set_cmd_completer (c, handle_completer);
+
if (xdb_commands)
{
add_com ("lz", class_info, signals_info, _("\