/* 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"
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. */
#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);
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;
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;
{
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
stop_signal = ecs->ws.value.sig;
target_terminal_ours (); /* Must do this before mourn anyway */
- /* 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 */
+ /* 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 */
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
&ecs->stepping_through_solib_catchpoints,
&ecs->stepping_through_sigtramp);
}
- if (may_switch_from_inferior_pid)
- switched_from_inferior_pid = inferior_pid;
inferior_pid = ecs->pid;
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 ();
}
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. */
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 ("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 ();
annotate_signal_string_end ();
printf_filtered (".\n");
gdb_flush (gdb_stdout);
+#endif
break;
default:
internal_error ("print_stop_reason: unrecognized enum value");
(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
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;
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 */
+ source_flag = SRC_LINE; /* finished step, just print source line */
else
- source_flag = 1; /* print location and source line */
+ source_flag = SRC_AND_LOC; /* print location and source line */
break;
case PRINT_SRC_AND_LOC:
- source_flag = 1; /* print location and source line */
+ source_flag = SRC_AND_LOC; /* print location and source line */
break;
case PRINT_SRC_ONLY:
- source_flag = -1;
+ source_flag = SRC_LINE;
break;
case PRINT_NOTHING:
do_frame_printing = 0;
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 */
+ 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);