-/* Target-struct-independent code to start (run) and stop an inferior process.
- Copyright 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995,
- 1996, 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
+/* Target-struct-independent code to start (run) and stop an inferior
+ process.
+
+ Copyright 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994,
+ 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 Free Software
+ Foundation, Inc.
This file is part of GDB.
#include "gdb_wait.h"
#include "gdbcore.h"
#include "gdbcmd.h"
+#include "cli/cli-script.h"
#include "target.h"
#include "gdbthread.h"
#include "annotate.h"
#include <signal.h>
#include "inf-loop.h"
#include "regcache.h"
+#include "value.h"
/* Prototypes for local functions */
static int may_follow_exec = MAY_FOLLOW_EXEC;
-/* GET_LONGJMP_TARGET returns the PC at which longjmp() will resume the
- program. It needs to examine the jmp_buf argument and extract the PC
- from it. The return value is non-zero on success, zero otherwise. */
-
-#ifndef GET_LONGJMP_TARGET
-#define GET_LONGJMP_TARGET(PC_ADDR) 0
-#endif
-
-
-/* Some machines have trampoline code that sits between function callers
- and the actual functions themselves. If this machine doesn't have
- such things, disable their processing. */
-
-#ifndef SKIP_TRAMPOLINE_CODE
-#define SKIP_TRAMPOLINE_CODE(pc) 0
-#endif
-
/* Dynamic function trampolines are similar to solib trampolines in that they
are between the caller and the callee. The difference is that when you
enter a dynamic trampoline, you can't determine the callee's address. Some
The simple approach is to single-step until control leaves the
dynamic linker.
- However, on some systems (e.g., Red Hat Linux 5.2) the dynamic
- linker calls functions in the shared C library, so you can't tell
- from the PC alone whether the dynamic linker is still running. In
- this case, we use a step-resume breakpoint to get us past the
- dynamic linker, as if we were using "next" to step over a function
- call.
+ However, on some systems (e.g., Red Hat's 5.2 distribution) the
+ dynamic linker calls functions in the shared C library, so you
+ can't tell from the PC alone whether the dynamic linker is still
+ running. In this case, we use a step-resume breakpoint to get us
+ past the dynamic linker, as if we were using "next" to step over a
+ function call.
IN_SOLIB_DYNSYM_RESOLVE_CODE says whether we're in the dynamic
linker code or not. Normally, this means we single-step. However,
#define SKIP_SOLIB_RESOLVER(pc) 0
#endif
-/* For SVR4 shared libraries, each call goes through a small piece of
- trampoline code in the ".plt" section. IN_SOLIB_CALL_TRAMPOLINE evaluates
- to nonzero if we are current stopped in one of these. */
-
-#ifndef IN_SOLIB_CALL_TRAMPOLINE
-#define IN_SOLIB_CALL_TRAMPOLINE(pc,name) 0
-#endif
-
/* In some shared library schemes, the return path from a shared library
call may need to go through a trampoline too. */
static void
default_skip_permanent_breakpoint (void)
{
- error_begin ();
- fprintf_filtered (gdb_stderr, "\
+ error ("\
The program is stopped at a permanent breakpoint, but GDB does not know\n\
how to step past a permanent breakpoint on this architecture. Try using\n\
-a command like `return' or `jump' to continue execution.\n");
- return_to_top_level (RETURN_ERROR);
+a command like `return' or `jump' to continue execution.");
}
#endif
static void
set_schedlock_func (char *args, int from_tty, struct cmd_list_element *c)
{
- if (c->type == set_cmd)
+ /* NOTE: cagney/2002-03-17: The add_show_from_set() function clones
+ 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
+ ``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?). */
+ if (cmd_type (c) == set_cmd)
if (!target_can_lock_scheduler)
{
scheduler_mode = schedlock_off;
{
add_thread (ecs->ptid);
-#ifdef UI_OUT
ui_out_text (uiout, "[New ");
ui_out_text (uiout, target_pid_or_tid_to_str (ecs->ptid));
ui_out_text (uiout, "]\n");
-#else
- printf_filtered ("[New %s]\n", target_pid_or_tid_to_str (ecs->ptid));
-#endif
#if 0
/* NOTE: This block is ONLY meant to be invoked in case of a
remove_breakpoints ();
/* Check for any newly added shared libraries if we're
- supposed to be adding them automatically. */
- if (auto_solib_add)
- {
- /* Switch terminal for any messages produced by
- breakpoint_re_set. */
- target_terminal_ours_for_output ();
- SOLIB_ADD (NULL, 0, NULL);
- target_terminal_inferior ();
- }
+ supposed to be adding them automatically. Switch
+ terminal for any messages produced by
+ breakpoint_re_set. */
+ target_terminal_ours_for_output ();
+ SOLIB_ADD (NULL, 0, NULL, auto_solib_add);
+ target_terminal_inferior ();
/* Reinsert breakpoints and continue. */
if (breakpoints_inserted)
disable_longjmp_breakpoint ();
remove_breakpoints ();
breakpoints_inserted = 0;
- if (!GET_LONGJMP_TARGET (&jmp_buf_pc))
+ if (!GET_LONGJMP_TARGET_P ()
+ || !GET_LONGJMP_TARGET (&jmp_buf_pc))
{
keep_going (ecs);
return;
breakpoints_inserted = 0;
/* Check for any newly added shared libraries if we're
- supposed to be adding them automatically. */
- if (auto_solib_add)
- {
- /* Switch terminal for any messages produced by
- breakpoint_re_set. */
- target_terminal_ours_for_output ();
- SOLIB_ADD (NULL, 0, NULL);
- target_terminal_inferior ();
- }
+ supposed to be adding them automatically. Switch
+ terminal for any messages produced by
+ breakpoint_re_set. */
+ target_terminal_ours_for_output ();
+ SOLIB_ADD (NULL, 0, NULL, auto_solib_add);
+ target_terminal_inferior ();
/* Try to reenable shared library breakpoints, additional
code segments in shared libraries might be mapped in now. */
ecs->update_step_sp = 1;
/* Did we just take a signal? */
- if (IN_SIGTRAMP (stop_pc, ecs->stop_func_name)
- && !IN_SIGTRAMP (prev_pc, prev_func_name)
+ if (PC_IN_SIGTRAMP (stop_pc, ecs->stop_func_name)
+ && !PC_IN_SIGTRAMP (prev_pc, prev_func_name)
&& INNER_THAN (read_sp (), step_sp))
{
/* We've just taken a signal; go until we are back to
{
/* We're doing a "next". */
- if (IN_SIGTRAMP (stop_pc, ecs->stop_func_name)
+ if (PC_IN_SIGTRAMP (stop_pc, ecs->stop_func_name)
&& INNER_THAN (step_frame_address, read_sp()))
/* We stepped out of a signal handler, and into its
calling trampoline. This is misdetected as a
check_sigtramp2 (struct execution_control_state *ecs)
{
if (trap_expected
- && IN_SIGTRAMP (stop_pc, ecs->stop_func_name)
- && !IN_SIGTRAMP (prev_pc, prev_func_name)
+ && PC_IN_SIGTRAMP (stop_pc, ecs->stop_func_name)
+ && !PC_IN_SIGTRAMP (prev_pc, prev_func_name)
&& INNER_THAN (read_sp (), step_sp))
{
/* What has happened here is that we have just stepped the
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 (ui_out_is_mi_like_p (uiout))
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 (ui_out_is_mi_like_p (uiout))
ui_out_field_string (uiout, "reason", "exited-signalled");
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)
{
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 ();
+ if (ui_out_is_mi_like_p (uiout))
+ ui_out_field_string (uiout, "reason", "signal-received");
ui_out_field_string (uiout, "signal-name", target_signal_to_name (stop_info));
annotate_signal_name_end ();
ui_out_text (uiout, ", ");
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 (__FILE__, __LINE__,
target_terminal_ours ();
- /* Look up the hook_stop and run it if it exists. */
-
- if (stop_command && stop_command->hook_pre)
- {
- catch_errors (hook_stop_stub, stop_command->hook_pre,
- "Error while running hook_stop:\n", RETURN_MASK_ALL);
- }
+ /* Look up the hook_stop and run it (CLI internally handles problem
+ of stop_command's pre-hook not existing). */
+ if (stop_command)
+ catch_errors (hook_stop_stub, stop_command,
+ "Error while running hook_stop:\n", RETURN_MASK_ALL);
if (!target_has_stack)
{
if (!stop_stack_dummy)
{
- select_frame (get_current_frame (), 0);
+ select_frame (get_current_frame ());
/* Print current location without a level number, if
we have changed functions or hit a breakpoint.
internal_error (__FILE__, __LINE__,
"Unknown value.");
}
-#ifdef UI_OUT
/* For mi, have the same behavior every time we stop:
print everything but the source line. */
if (ui_out_is_mi_like_p (uiout))
source_flag = LOC_AND_ADDRESS;
-#endif
-#ifdef UI_OUT
if (ui_out_is_mi_like_p (uiout))
ui_out_field_int (uiout, "thread-id",
pid_to_thread_id (inferior_ptid));
-#endif
/* The behavior of this routine with respect to the source
flag is:
SRC_LINE: Print only source line
Can't rely on restore_inferior_status because that only gets
called if we don't stop in the called function. */
stop_pc = read_pc ();
- select_frame (get_current_frame (), 0);
+ select_frame (get_current_frame ());
}
-
- TUIDO (((TuiOpaqueFuncPtr) tui_vCheckDataValues, selected_frame));
-
done:
annotate_stopped ();
}
static int
hook_stop_stub (void *cmd)
{
- execute_user_command ((struct cmd_list_element *) cmd, 0);
+ execute_cmd_pre_hook ((struct cmd_list_element *) cmd);
return (0);
}
\f
CORE_ADDR step_resume_break_address;
int stop_after_trap;
int stop_soon_quietly;
- CORE_ADDR selected_frame_address;
char *stop_registers;
/* These are here because if call_function_by_hand has written some
any registers. */
char *registers;
- int selected_level;
+ /* A frame unique identifier. */
+ struct frame_id selected_frame_id;
+
int breakpoint_proceeded;
int restore_stack_info;
int proceed_to_finish;
read_register_bytes (0, inf_status->registers, REGISTER_BYTES);
- record_selected_frame (&(inf_status->selected_frame_address),
- &(inf_status->selected_level));
+ get_frame_id (selected_frame, &inf_status->selected_frame_id);
return inf_status;
}
-struct restore_selected_frame_args
-{
- CORE_ADDR frame_address;
- int level;
-};
-
static int
restore_selected_frame (void *args)
{
- struct restore_selected_frame_args *fr =
- (struct restore_selected_frame_args *) args;
+ struct frame_id *fid = (struct frame_id *) args;
struct frame_info *frame;
- int level = fr->level;
- frame = find_relative_frame (get_current_frame (), &level);
+ frame = frame_find_by_id (*fid);
/* If inf_status->selected_frame_address is NULL, there was no
previously selected frame. */
- if (frame == NULL ||
- /* FRAME_FP (frame) != fr->frame_address || */
- /* elz: deleted this check as a quick fix to the problem that
- for function called by hand gdb creates no internal frame
- structure and the real stack and gdb's idea of stack are
- different if nested calls by hands are made.
-
- mvs: this worries me. */
- level != 0)
+ if (frame == NULL)
{
warning ("Unable to restore previously selected frame.\n");
return 0;
}
- select_frame (frame, fr->level);
+ select_frame (frame);
return (1);
}
if (target_has_stack && inf_status->restore_stack_info)
{
- struct restore_selected_frame_args fr;
- fr.level = inf_status->selected_level;
- fr.frame_address = inf_status->selected_frame_address;
/* The point of catch_errors is that if the stack is clobbered,
- walking the stack might encounter a garbage pointer and error()
- trying to dereference it. */
- if (catch_errors (restore_selected_frame, &fr,
+ walking the stack might encounter a garbage pointer and
+ error() trying to dereference it. */
+ if (catch_errors (restore_selected_frame, &inf_status->selected_frame_id,
"Unable to restore previously selected frame:\n",
RETURN_MASK_ERROR) == 0)
/* Error in restoring the selected frame. Select the innermost
frame. */
-
-
- select_frame (get_current_frame (), 0);
+ select_frame (get_current_frame ());
}
For \"parent\" or \"child\", the unfollowed process will run free.\n\
By default, the debugger will follow the parent process.",
&setlist);
-/* c->function.sfunc = ; */
add_show_from_set (c, &showlist);
c = add_set_enum_cmd ("scheduler-locking", class_run,
Other threads may run while stepping over a function call ('next').",
&setlist);
- c->function.sfunc = set_schedlock_func; /* traps on target vector */
+ set_cmd_sfunc (c, set_schedlock_func); /* traps on target vector */
add_show_from_set (c, &showlist);
c = add_set_cmd ("step-mode", class_run,