/* Target-struct-independent code to start (run) and stop an inferior process.
- Copyright 1986-1989, 1991-1999 Free Software Foundation, Inc.
+ Copyright 1986-1989, 1991-2000 Free Software Foundation, Inc.
This file is part of GDB.
#include "frame.h"
#include "inferior.h"
#include "breakpoint.h"
-#include "wait.h"
+#include "gdb_wait.h"
#include "gdbcore.h"
#include "gdbcmd.h"
#include "target.h"
#include "symfile.h" /* for overlay functions */
#include "top.h"
#include <signal.h>
-#include "event-loop.h"
-#include "event-top.h"
-#include "remote.h" /* For cleanup_sigint_signal_handler. */
+#include "inf-loop.h"
/* Prototypes for local functions */
static void set_follow_fork_mode_command (char *arg, int from_tty,
struct cmd_list_element * c);
-static void complete_execution (void);
-
static struct inferior_status *xmalloc_inferior_status (void);
static void free_inferior_status (struct inferior_status *);
static void set_schedlock_func (char *args, int from_tty,
struct cmd_list_element * c);
-static int is_internal_shlib_eventpoint (struct breakpoint * ep);
-
-static int stopped_for_internal_shlib_event (bpstat bs);
-
struct execution_control_state;
static int currently_stepping (struct execution_control_state *ecs);
when the inferior stopped in a different thread than it had been
running in. */
-static int switched_from_inferior_pid;
-
-/* This will be true for configurations that may actually report an
- inferior pid different from the original. At present this is only
- true for HP-UX native. */
-
-#ifndef MAY_SWITCH_FROM_INFERIOR_PID
-#define MAY_SWITCH_FROM_INFERIOR_PID (0)
-#endif
-
-static int may_switch_from_inferior_pid = MAY_SWITCH_FROM_INFERIOR_PID;
+static int previous_inferior_pid;
/* This is true for configurations that may follow through execl() and
similar functions. At present this is only true for HP-UX native. */
#ifndef SKIP_PERMANENT_BREAKPOINT
#define SKIP_PERMANENT_BREAKPOINT (default_skip_permanent_breakpoint)
static void
-default_skip_permanent_breakpoint ()
+default_skip_permanent_breakpoint (void)
{
error_begin ();
fprintf_filtered (gdb_stderr, "\
#define HAVE_CONTINUABLE_WATCHPOINT 1
#endif
+#ifndef CANNOT_STEP_HW_WATCHPOINTS
+#define CANNOT_STEP_HW_WATCHPOINTS 0
+#else
+#undef CANNOT_STEP_HW_WATCHPOINTS
+#define CANNOT_STEP_HW_WATCHPOINTS 1
+#endif
+
/* Tables of how to react to signals; the user sets them. */
static unsigned char *signal_stop;
step = 0;
#endif
+ /* Some targets (e.g. Solaris x86) have a kernel bug when stepping
+ over an instruction that causes a page fault without triggering
+ a hardware watchpoint. The kernel properly notices that it shouldn't
+ stop, because the hardware watchpoint is not triggered, but it forgets
+ the step request and continues the program normally.
+ Work around the problem by removing hardware watchpoints if a step is
+ requested, GDB will check for a hardware watchpoint trigger after the
+ step anyway. */
+ if (CANNOT_STEP_HW_WATCHPOINTS && step && breakpoints_inserted)
+ remove_hw_watchpoints ();
+
+
/* Normally, by the time we reach `resume', the breakpoints are either
removed or inserted, as appropriate. The exception is if we're sitting
at a permanent breakpoint; we need to step over it, but permanent
if (should_resume)
{
+ int resume_pid;
+
if (use_thread_step_needed && thread_step_needed)
{
/* We stopped on a BPT instruction;
{
/* Breakpoint deleted: ok to do regular resume
where all the threads either step or continue. */
- target_resume (-1, step, sig);
+ resume_pid = -1;
}
else
{
trap_expected = 1;
step = 1;
}
-
- target_resume (inferior_pid, step, sig);
+ resume_pid = inferior_pid;
}
}
else
{
/* Vanilla resume. */
-
if ((scheduler_mode == schedlock_on) ||
(scheduler_mode == schedlock_step && step != 0))
- target_resume (inferior_pid, step, sig);
+ resume_pid = inferior_pid;
else
- target_resume (-1, step, sig);
+ resume_pid = -1;
}
+ target_resume (resume_pid, step, sig);
}
discard_cleanups (old_cleanups);
if (step < 0)
stop_after_trap = 1;
- if (addr == (CORE_ADDR) - 1)
+ if (addr == (CORE_ADDR) -1)
{
/* If there is a breakpoint at the address we will resume at,
step one instruction before inserting breakpoints
and in any case decode why it stopped, and act accordingly. */
/* Do this only if we are not using the event loop, or if the target
does not support asynchronous execution. */
- if (!async_p || !target_has_async)
+ if (!event_loop_p || !target_can_async_p ())
{
wait_for_inferior ();
normal_stop ();
stop_soon_quietly = 1;
trap_expected = 0;
- /* Go on waiting only in case gdb is not started in async mode, or
- in case the target doesn't support async execution. */
- if (!async_p || !target_has_async)
- {
- wait_for_inferior ();
- normal_stop ();
- }
- else
- {
- /* The 'tar rem' command should always look synchronous,
- i.e. display the prompt only once it has connected and
- started the target. */
- sync_execution = 1;
- push_prompt ("", "", "");
- delete_file_handler (input_fd);
- target_executing = 1;
- }
+ /* Always go on waiting for the target, regardless of the mode. */
+ /* FIXME: cagney/1999-09-23: At present it isn't possible to
+ indicate th wait_for_inferior that a target should timeout if
+ nothing is returned (instead of just blocking). Because of this,
+ targets expecting an immediate response need to, internally, set
+ things up so that the target_wait() is forced to eventually
+ timeout. */
+ /* FIXME: cagney/1999-09-24: It isn't possible for target_open() to
+ differentiate to its caller what the state of the target is after
+ the initial open has been performed. Here we're assuming that
+ the target has stopped. It should be possible to eventually have
+ target_open() return to the caller an indication that the target
+ is currently running and GDB state should be set to the same as
+ for an async run. */
+ wait_for_inferior ();
+ normal_stop ();
}
/* Initialize static vars when a new inferior begins. */
infwait_nonstep_watch_state
};
+/* Why did the inferior stop? Used to print the appropriate messages
+ to the interface from within handle_inferior_event(). */
+enum inferior_stop_reason
+{
+ /* We don't know why. */
+ STOP_UNKNOWN,
+ /* Step, next, nexti, stepi finished. */
+ END_STEPPING_RANGE,
+ /* Found breakpoint. */
+ BREAKPOINT_HIT,
+ /* Inferior terminated by signal. */
+ SIGNAL_EXITED,
+ /* Inferior exited. */
+ EXITED,
+ /* Inferior received signal, and user asked to be notified. */
+ SIGNAL_RECEIVED
+};
+
/* This structure contains what used to be local variables in
wait_for_inferior. Probably many of them can return to being
locals in handle_inferior_event. */
static void stop_stepping (struct execution_control_state *ecs);
static void prepare_to_wait (struct execution_control_state *ecs);
static void keep_going (struct execution_control_state *ecs);
+static void print_stop_reason (enum inferior_stop_reason stop_reason, int stop_info);
/* Wait for control to return from inferior to debugger.
If inferior gets a signal, we may decide to start it up again
thread_step_needed = 0;
/* We'll update this if & when we switch to a new thread. */
- if (may_switch_from_inferior_pid)
- switched_from_inferior_pid = inferior_pid;
+ previous_inferior_pid = inferior_pid;
overlay_cache_invalid = 1;
void
fetch_inferior_event (client_data)
- gdb_client_data client_data;
+ void *client_data;
{
static struct cleanup *old_cleanups;
thread_step_needed = 0;
/* We'll update this if & when we switch to a new thread. */
- if (may_switch_from_inferior_pid)
- switched_from_inferior_pid = inferior_pid;
+ previous_inferior_pid = inferior_pid;
overlay_cache_invalid = 1;
if there are any. */
do_exec_cleanups (old_cleanups);
normal_stop ();
- /* Is there anything left to do for the command issued to
- complete? */
- do_all_continuations ();
- /* Reset things after target has stopped for the async commands. */
- complete_execution ();
+ if (step_multi && stop_step)
+ inferior_event_handler (INF_EXEC_CONTINUE, NULL);
+ else
+ inferior_event_handler (INF_EXEC_COMPLETE, NULL);
}
}
void
init_execution_control_state (struct execution_control_state *ecs)
{
+ /* ecs->another_trap? */
ecs->random_signal = 0;
ecs->remove_breakpoints_on_following_step = 0;
ecs->handling_longjmp = 0; /* FIXME */
{
add_thread (ecs->pid);
+#ifdef UI_OUT
+ ui_out_text (uiout, "[New ");
+ ui_out_text (uiout, target_pid_or_tid_to_str (ecs->pid));
+ ui_out_text (uiout, "]\n");
+#else
printf_filtered ("[New %s]\n", target_pid_or_tid_to_str (ecs->pid));
+#endif
#if 0
/* NOTE: This block is ONLY meant to be invoked in case of a
case TARGET_WAITKIND_EXITED:
target_terminal_ours (); /* Must do this before mourn anyway */
- annotate_exited (ecs->ws.value.integer);
- if (ecs->ws.value.integer)
- printf_filtered ("\nProgram exited with code 0%o.\n",
- (unsigned int) ecs->ws.value.integer);
- else
- printf_filtered ("\nProgram exited normally.\n");
+ print_stop_reason (EXITED, ecs->ws.value.integer);
/* Record the exit code in the convenience variable $_exitcode, so
that the user can inspect this again later. */
stop_print_frame = 0;
stop_signal = ecs->ws.value.sig;
target_terminal_ours (); /* Must do this before mourn anyway */
- annotate_signalled ();
-
- /* This looks pretty bogus to me. Doesn't TARGET_WAITKIND_SIGNALLED
- mean it is already dead? This has been here since GDB 2.8, so
- perhaps it means rms didn't understand unix waitstatuses?
- For the moment I'm just kludging around this in remote.c
- rather than trying to change it here --kingdon, 5 Dec 1994. */
- target_kill (); /* kill mourns as well */
-
- printf_filtered ("\nProgram terminated with signal ");
- annotate_signal_name ();
- printf_filtered ("%s", target_signal_to_name (stop_signal));
- annotate_signal_name_end ();
- printf_filtered (", ");
- annotate_signal_string ();
- printf_filtered ("%s", target_signal_to_string (stop_signal));
- annotate_signal_string_end ();
- printf_filtered (".\n");
-
- printf_filtered ("The program no longer exists.\n");
- gdb_flush (gdb_stdout);
+
+ /* 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_stop_reason (SIGNAL_EXITED, stop_signal);
singlestep_breakpoints_inserted_p = 0; /*SOFTWARE_SINGLE_STEP_P */
stop_stepping (ecs);
return;
stop_pc = read_pc_pid (ecs->pid);
ecs->saved_inferior_pid = inferior_pid;
inferior_pid = ecs->pid;
- stop_bpstat = bpstat_stop_status
- (&stop_pc,
- (DECR_PC_AFTER_BREAK ?
- (prev_pc != stop_pc - DECR_PC_AFTER_BREAK
- && currently_stepping (ecs))
- : 0)
- );
+ stop_bpstat = bpstat_stop_status (&stop_pc, currently_stepping (ecs));
ecs->random_signal = !bpstat_explains_signal (stop_bpstat);
inferior_pid = ecs->saved_inferior_pid;
goto process_event_stop_test;
}
stop_pc = read_pc ();
- stop_bpstat = bpstat_stop_status
- (&stop_pc,
- (DECR_PC_AFTER_BREAK ?
- (prev_pc != stop_pc - DECR_PC_AFTER_BREAK
- && currently_stepping (ecs))
- : 0)
- );
+ stop_bpstat = bpstat_stop_status (&stop_pc, currently_stepping (ecs));
ecs->random_signal = !bpstat_explains_signal (stop_bpstat);
goto process_event_stop_test;
stop_pc = read_pc_pid (ecs->pid);
ecs->saved_inferior_pid = inferior_pid;
inferior_pid = ecs->pid;
- stop_bpstat = bpstat_stop_status
- (&stop_pc,
- (DECR_PC_AFTER_BREAK ?
- (prev_pc != stop_pc - DECR_PC_AFTER_BREAK
- && currently_stepping (ecs))
- : 0)
- );
+ stop_bpstat = bpstat_stop_status (&stop_pc, currently_stepping (ecs));
ecs->random_signal = !bpstat_explains_signal (stop_bpstat);
inferior_pid = ecs->saved_inferior_pid;
goto process_event_stop_test;
case TARGET_WAITKIND_STOPPED:
stop_signal = ecs->ws.value.sig;
break;
+
+ /* We had an event in the inferior, but we are not interested
+ in handling it at this level. The lower layers have already
+ done what needs to be done, if anything. This case can
+ occur only when the target is async or extended-async. One
+ of the circumstamces for this to happen is when the
+ inferior produces output for the console. The inferior has
+ not stopped, and we are ignoring the event. */
+ case TARGET_WAITKIND_IGNORE:
+ ecs->wait_some_more = 1;
+ return;
}
/* We may want to consider not doing a resume here in order to give
/* It's a SIGTRAP or a signal we're interested in. Switch threads,
and fall into the rest of wait_for_inferior(). */
- /* Save infrun state for the old thread. */
- save_infrun_state (inferior_pid, prev_pc,
- prev_func_start, prev_func_name,
- trap_expected, step_resume_breakpoint,
- through_sigtramp_breakpoint,
- step_range_start, step_range_end,
- step_frame_address, ecs->handling_longjmp,
- ecs->another_trap,
- ecs->stepping_through_solib_after_catch,
- ecs->stepping_through_solib_catchpoints,
- ecs->stepping_through_sigtramp);
-
- if (may_switch_from_inferior_pid)
- switched_from_inferior_pid = inferior_pid;
+ /* Caution: it may happen that the new thread (or the old one!)
+ is not in the thread list. In this case we must not attempt
+ to "switch context", or we run the risk that our context may
+ be lost. This may happen as a result of the target module
+ mishandling thread creation. */
+
+ if (in_thread_list (inferior_pid) && in_thread_list (ecs->pid))
+ { /* Perform infrun state context switch: */
+ /* Save infrun state for the old thread. */
+ save_infrun_state (inferior_pid, prev_pc,
+ prev_func_start, prev_func_name,
+ trap_expected, step_resume_breakpoint,
+ through_sigtramp_breakpoint,
+ step_range_start, step_range_end,
+ step_frame_address, ecs->handling_longjmp,
+ ecs->another_trap,
+ ecs->stepping_through_solib_after_catch,
+ ecs->stepping_through_solib_catchpoints,
+ ecs->stepping_through_sigtramp);
+
+ /* Load infrun state for the new thread. */
+ load_infrun_state (ecs->pid, &prev_pc,
+ &prev_func_start, &prev_func_name,
+ &trap_expected, &step_resume_breakpoint,
+ &through_sigtramp_breakpoint,
+ &step_range_start, &step_range_end,
+ &step_frame_address, &ecs->handling_longjmp,
+ &ecs->another_trap,
+ &ecs->stepping_through_solib_after_catch,
+ &ecs->stepping_through_solib_catchpoints,
+ &ecs->stepping_through_sigtramp);
+ }
inferior_pid = ecs->pid;
- /* Load infrun state for the new thread. */
- load_infrun_state (inferior_pid, &prev_pc,
- &prev_func_start, &prev_func_name,
- &trap_expected, &step_resume_breakpoint,
- &through_sigtramp_breakpoint,
- &step_range_start, &step_range_end,
- &step_frame_address, &ecs->handling_longjmp,
- &ecs->another_trap,
- &ecs->stepping_through_solib_after_catch,
- &ecs->stepping_through_solib_catchpoints,
- &ecs->stepping_through_sigtramp);
-
if (context_hook)
context_hook (pid_to_thread_id (ecs->pid));
- printf_filtered ("[Switching to %s]\n", target_pid_to_str (ecs->pid));
flush_cached_frames ();
}
/* See if there is a breakpoint at the current PC. */
stop_bpstat = bpstat_stop_status
(&stop_pc,
- (DECR_PC_AFTER_BREAK ?
- /* Notice the case of stepping through a jump
- that lands just after a breakpoint.
- Don't confuse that with hitting the breakpoint.
- What we check for is that 1) stepping is going on
- and 2) the pc before the last insn does not match
- the address of the breakpoint before the current pc
- and 3) we didn't hit a breakpoint in a signal handler
- without an intervening stop in sigtramp, which is
- detected by a new stack pointer value below
- any usual function calling stack adjustments. */
+ /* Pass TRUE if our reason for stopping is something other
+ than hitting a breakpoint. We do this by checking that
+ 1) stepping is going on and 2) we didn't hit a breakpoint
+ in a signal handler without an intervening stop in
+ sigtramp, which is detected by a new stack pointer value
+ below any usual function calling stack adjustments. */
(currently_stepping (ecs)
- && prev_pc != stop_pc - DECR_PC_AFTER_BREAK
&& !(step_range_end
- && INNER_THAN (read_sp (), (step_sp - 16)))) :
- 0)
+ && INNER_THAN (read_sp (), (step_sp - 16))))
);
/* Following in case break condition called a
function. */
{
printed = 1;
target_terminal_ours_for_output ();
- annotate_signal ();
- printf_filtered ("\nProgram received signal ");
- annotate_signal_name ();
- printf_filtered ("%s", target_signal_to_name (stop_signal));
- annotate_signal_name_end ();
- printf_filtered (", ");
- annotate_signal_string ();
- printf_filtered ("%s", target_signal_to_string (stop_signal));
- annotate_signal_string_end ();
- printf_filtered (".\n");
- gdb_flush (gdb_stdout);
+ print_stop_reason (SIGNAL_RECEIVED, stop_signal);
}
if (signal_stop[stop_signal])
{
dynamically loaded objects (among other things). */
if (stop_on_solib_events)
{
- stop_print_frame = 0;
stop_stepping (ecs);
return;
}
supposed to be stepping at the assembly language level
("stepi"). Just stop. */
stop_step = 1;
+ print_stop_reason (END_STEPPING_RANGE, 0);
stop_stepping (ecs);
return;
}
/* It is stepi or nexti. We always want to stop stepping after
one instruction. */
stop_step = 1;
+ print_stop_reason (END_STEPPING_RANGE, 0);
stop_stepping (ecs);
return;
}
when we do "s" in a function with no line numbers,
or can this happen as a result of a return or longjmp?). */
stop_step = 1;
+ print_stop_reason (END_STEPPING_RANGE, 0);
stop_stepping (ecs);
return;
}
That is said to make things like for (;;) statements work
better. */
stop_step = 1;
+ print_stop_reason (END_STEPPING_RANGE, 0);
stop_stepping (ecs);
return;
}
in which after skipping the prologue we better stop even though
we will be in mid-line. */
stop_step = 1;
+ print_stop_reason (END_STEPPING_RANGE, 0);
stop_stepping (ecs);
return;
}
{
/* We are already there: stop now. */
stop_step = 1;
+ print_stop_reason (END_STEPPING_RANGE, 0);
stop_stepping (ecs);
return;
}
ecs->wait_some_more = 1;
}
-/* This function returns TRUE if ep is an internal breakpoint
- set to catch generic shared library (aka dynamically-linked
- library) events. (This is *NOT* the same as a catchpoint for a
- shlib event. The latter is something a user can set; this is
- something gdb sets for its own use, and isn't ever shown to a
- user.) */
-static int
-is_internal_shlib_eventpoint (struct breakpoint *ep)
-{
- return
- (ep->type == bp_shlib_event)
- ;
-}
-
-/* This function returns TRUE if bs indicates that the inferior
- stopped due to a shared library (aka dynamically-linked library)
- event. */
-
-static int
-stopped_for_internal_shlib_event (bpstat bs)
-{
- /* Note that multiple eventpoints may've caused the stop. Any
- that are associated with shlib events will be accepted. */
- for (; bs != NULL; bs = bs->next)
- {
- if ((bs->breakpoint_at != NULL)
- && is_internal_shlib_eventpoint (bs->breakpoint_at))
- return 1;
- }
-
- /* If we get here, then no candidate was found. */
- return 0;
-}
-\f
-/* Reset proper settings after an asynchronous command has finished.
- If the execution command was in synchronous mode, register stdin
- with the event loop, and reset the prompt. */
-
+/* Print why the inferior has stopped. We always print something when
+ the inferior exits, or receives a signal. The rest of the cases are
+ dealt with later on in normal_stop() and print_it_typical(). Ideally
+ there should be a call to this function from handle_inferior_event()
+ each time stop_stepping() is called.*/
static void
-complete_execution (void)
+print_stop_reason (enum inferior_stop_reason stop_reason, int stop_info)
{
- target_executing = 0;
- if (sync_execution)
+ switch (stop_reason)
{
- add_file_handler (input_fd, stdin_event_handler, 0);
- pop_prompt ();
- sync_execution = 0;
- cleanup_sigint_signal_handler ();
- display_gdb_prompt (0);
- }
- else
- {
- if (exec_done_display_p)
- printf_unfiltered ("completed.\n");
+ case STOP_UNKNOWN:
+ /* We don't deal with these cases from handle_inferior_event()
+ yet. */
+ break;
+ case END_STEPPING_RANGE:
+ /* We are done with a step/next/si/ni command. */
+ /* For now print nothing. */
+#ifdef UI_OUT
+ /* Print a message only if not in the middle of doing a "step n"
+ operation for n > 1 */
+ if (!step_multi || !stop_step)
+ if (interpreter_p && strcmp (interpreter_p, "mi") == 0)
+ ui_out_field_string (uiout, "reason", "end-stepping-range");
+#endif
+ break;
+ case BREAKPOINT_HIT:
+ /* We found a breakpoint. */
+ /* For now print nothing. */
+ break;
+ case SIGNAL_EXITED:
+ /* The inferior was terminated by a signal. */
+#ifdef UI_OUT
+ annotate_signalled ();
+ if (interpreter_p && strcmp (interpreter_p, "mi") == 0)
+ ui_out_field_string (uiout, "reason", "exited-signalled");
+ ui_out_text (uiout, "\nProgram terminated with signal ");
+ annotate_signal_name ();
+ ui_out_field_string (uiout, "signal-name", target_signal_to_name (stop_info));
+ annotate_signal_name_end ();
+ ui_out_text (uiout, ", ");
+ annotate_signal_string ();
+ ui_out_field_string (uiout, "signal-meaning", target_signal_to_string (stop_info));
+ annotate_signal_string_end ();
+ ui_out_text (uiout, ".\n");
+ ui_out_text (uiout, "The program no longer exists.\n");
+#else
+ annotate_signalled ();
+ printf_filtered ("\nProgram terminated with signal ");
+ annotate_signal_name ();
+ printf_filtered ("%s", target_signal_to_name (stop_info));
+ annotate_signal_name_end ();
+ printf_filtered (", ");
+ annotate_signal_string ();
+ printf_filtered ("%s", target_signal_to_string (stop_info));
+ annotate_signal_string_end ();
+ printf_filtered (".\n");
+
+ printf_filtered ("The program no longer exists.\n");
+ gdb_flush (gdb_stdout);
+#endif
+ break;
+ case EXITED:
+ /* The inferior program is finished. */
+#ifdef UI_OUT
+ annotate_exited (stop_info);
+ if (stop_info)
+ {
+ if (interpreter_p && strcmp (interpreter_p, "mi") == 0)
+ ui_out_field_string (uiout, "reason", "exited");
+ ui_out_text (uiout, "\nProgram exited with code ");
+ ui_out_field_fmt (uiout, "exit-code", "0%o", (unsigned int) stop_info);
+ ui_out_text (uiout, ".\n");
+ }
+ else
+ {
+ if (interpreter_p && strcmp (interpreter_p, "mi") == 0)
+ ui_out_field_string (uiout, "reason", "exited-normally");
+ ui_out_text (uiout, "\nProgram exited normally.\n");
+ }
+#else
+ annotate_exited (stop_info);
+ if (stop_info)
+ printf_filtered ("\nProgram exited with code 0%o.\n",
+ (unsigned int) stop_info);
+ else
+ printf_filtered ("\nProgram exited normally.\n");
+#endif
+ break;
+ case SIGNAL_RECEIVED:
+ /* Signal received. The signal table tells us to print about
+ it. */
+#ifdef UI_OUT
+ annotate_signal ();
+ ui_out_text (uiout, "\nProgram received signal ");
+ annotate_signal_name ();
+ ui_out_field_string (uiout, "signal-name", target_signal_to_name (stop_info));
+ annotate_signal_name_end ();
+ ui_out_text (uiout, ", ");
+ annotate_signal_string ();
+ ui_out_field_string (uiout, "signal-meaning", target_signal_to_string (stop_info));
+ annotate_signal_string_end ();
+ ui_out_text (uiout, ".\n");
+#else
+ annotate_signal ();
+ printf_filtered ("\nProgram received signal ");
+ annotate_signal_name ();
+ printf_filtered ("%s", target_signal_to_name (stop_info));
+ annotate_signal_name_end ();
+ printf_filtered (", ");
+ annotate_signal_string ();
+ printf_filtered ("%s", target_signal_to_string (stop_info));
+ annotate_signal_string_end ();
+ printf_filtered (".\n");
+ gdb_flush (gdb_stdout);
+#endif
+ break;
+ default:
+ internal_error ("print_stop_reason: unrecognized enum value");
+ break;
}
}
+\f
/* Here to return control to GDB when the inferior stops for real.
Print appropriate messages, remove breakpoints, give terminal our modes.
(Note that there's no point in saying anything if the inferior
has exited!) */
- if (may_switch_from_inferior_pid
- && (switched_from_inferior_pid != inferior_pid)
+ if ((previous_inferior_pid != inferior_pid)
&& target_has_execution)
{
target_terminal_ours_for_output ();
- printf_filtered ("[Switched to %s]\n",
+ printf_filtered ("[Switching to %s]\n",
target_pid_or_tid_to_str (inferior_pid));
- switched_from_inferior_pid = inferior_pid;
+ previous_inferior_pid = inferior_pid;
}
/* Make sure that the current_frame's pc is correct. This
target_terminal_ours ();
- /* Did we stop because the user set the stop_on_solib_events
- variable? (If so, we report this as a generic, "Stopped due
- to shlib event" message.) */
- if (stopped_for_internal_shlib_event (stop_bpstat))
- {
- printf_filtered ("Stopped due to shared library event\n");
- }
-
/* Look up the hook_stop and run it if it exists. */
if (stop_command && stop_command->hook)
bpstat_print() contains the logic deciding in detail
what to print, based on the event(s) that just occurred. */
- if (stop_print_frame)
+ if (stop_print_frame
+ && selected_frame)
{
int bpstat_ret;
int source_flag;
+ int do_frame_printing = 1;
bpstat_ret = bpstat_print (stop_bpstat);
- /* bpstat_print() returned one of:
- -1: Didn't print anything
- 0: Printed preliminary "Breakpoint n, " message, desires
- location tacked on
- 1: Printed something, don't tack on location */
-
- if (bpstat_ret == -1)
- if (stop_step
- && step_frame_address == FRAME_FP (get_current_frame ())
- && step_start_function == find_pc_function (stop_pc))
- source_flag = -1; /* finished step, just print source line */
- else
- source_flag = 1; /* print location and source line */
- else if (bpstat_ret == 0) /* hit bpt, desire location */
- source_flag = 1; /* print location and source line */
- else /* bpstat_ret == 1, hit bpt, do not desire location */
- source_flag = -1; /* just print source line */
+ switch (bpstat_ret)
+ {
+ case PRINT_UNKNOWN:
+ if (stop_step
+ && step_frame_address == FRAME_FP (get_current_frame ())
+ && step_start_function == find_pc_function (stop_pc))
+ source_flag = SRC_LINE; /* finished step, just print source line */
+ else
+ source_flag = SRC_AND_LOC; /* print location and source line */
+ break;
+ case PRINT_SRC_AND_LOC:
+ source_flag = SRC_AND_LOC; /* print location and source line */
+ break;
+ case PRINT_SRC_ONLY:
+ source_flag = SRC_LINE;
+ break;
+ case PRINT_NOTHING:
+ do_frame_printing = 0;
+ break;
+ default:
+ internal_error ("Unknown value.");
+ }
+#ifdef UI_OUT
+ /* For mi, have the same behavior every time we stop:
+ print everything but the source line. */
+ if (interpreter_p && strcmp (interpreter_p, "mi") == 0)
+ source_flag = LOC_AND_ADDRESS;
+#endif
+#ifdef UI_OUT
+ if (interpreter_p && strcmp (interpreter_p, "mi") == 0)
+ ui_out_field_int (uiout, "thread-id", pid_to_thread_id (inferior_pid));
+#endif
/* The behavior of this routine with respect to the source
flag is:
- -1: Print only source line
- 0: Print only location
- 1: Print location and source line */
- show_and_print_stack_frame (selected_frame, -1, source_flag);
+ SRC_LINE: Print only source line
+ LOCATION: Print only location
+ SRC_AND_LOC: Print location and source line */
+ if (do_frame_printing)
+ show_and_print_stack_frame (selected_frame, -1, source_flag);
/* Display the auto-display expressions. */
do_displays ();