#include "defs.h"
#include "gdb_string.h"
#include <ctype.h>
#include "symtab.h"
#include "frame.h"
#include "inferior.h"
#include "exceptions.h"
#include "breakpoint.h"
#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 "symfile.h"
#include "top.h"
#include <signal.h>
#include "inf-loop.h"
#include "event-top.h"
#include "regcache.h"
#include "value.h"
#include "observer.h"
#include "language.h"
#include "solib.h"
#include "gdb_assert.h"
#include "mi/mi-common.h"
#include "inlining.h"
#include "objfiles.h"
#if TM_NEXTSTEP && TARGET_POWERPC
#include "ppc-macosx-regnums.h"
#endif
#if !defined(TARGET_DISABLE_HW_WATCHPOINTS)
#define TARGET_DISABLE_HW_WATCHPOINTS(pid)
#endif
#if !defined(TARGET_ENABLE_HW_WATCHPOINTS)
#define TARGET_ENABLE_HW_WATCHPOINTS(pid)
#endif
#include "checkpoint.h"
static void signals_info (char *, int);
static void handle_command (char *, int);
static void sig_print_info (enum target_signal);
static void sig_print_header (void);
static void resume_cleanups (void *);
static int hook_stop_stub (void *);
static int restore_selected_frame (void *);
static void build_infrun (void);
static int follow_fork (void);
static void set_schedlock_func (char *args, int from_tty,
struct cmd_list_element *c);
struct execution_control_state;
static int currently_stepping (struct execution_control_state *ecs);
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;
int inferior_ignoring_leading_exec_events = 0;
int step_stop_if_no_debug = 0;
static void
show_step_stop_if_no_debug (struct ui_file *file, int from_tty,
struct cmd_list_element *c, const char *value)
{
fprintf_filtered (file, _("Mode of the step operation is %s.\n"), value);
}
int sync_execution = 1;
static ptid_t previous_inferior_ptid;
#ifndef MAY_FOLLOW_EXEC
#define MAY_FOLLOW_EXEC (0)
#endif
static int may_follow_exec = MAY_FOLLOW_EXEC;
static int debug_infrun = 0;
static void
show_debug_infrun (struct ui_file *file, int from_tty,
struct cmd_list_element *c, const char *value)
{
fprintf_filtered (file, _("Inferior debugging is %s.\n"), value);
}
#ifndef SOLIB_IN_DYNAMIC_LINKER
#define SOLIB_IN_DYNAMIC_LINKER(pid,pc) 0
#endif
#ifndef SKIP_PERMANENT_BREAKPOINT
#define SKIP_PERMANENT_BREAKPOINT (default_skip_permanent_breakpoint)
static void
default_skip_permanent_breakpoint (void)
{
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."));
}
#endif
#ifndef HAVE_STEPPABLE_WATCHPOINT
#define HAVE_STEPPABLE_WATCHPOINT 0
#else
#undef HAVE_STEPPABLE_WATCHPOINT
#define HAVE_STEPPABLE_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
static unsigned char *signal_stop;
static unsigned char *signal_print;
static unsigned char *signal_program;
#define SET_SIGS(nsigs,sigs,flags) \
do { \
int signum = (nsigs); \
while (signum-- > 0) \
if ((sigs)[signum]) \
(flags)[signum] = 1; \
} while (0)
#define UNSET_SIGS(nsigs,sigs,flags) \
do { \
int signum = (nsigs); \
while (signum-- > 0) \
if ((sigs)[signum]) \
(flags)[signum] = 0; \
} while (0)
#define RESUME_ALL (pid_to_ptid (-1))
static struct cmd_list_element *stop_command;
static int breakpoints_inserted;
static struct symbol *step_start_function;
static int trap_expected;
static int stop_on_solib_events;
static struct breakpoint *solib_step_bp;
static struct breakpoint *solib_finish_bp;
#ifdef HP_OS_BUG
static int trap_expected_after_continue;
#endif
static void
show_stop_on_solib_events (struct ui_file *file, int from_tty,
struct cmd_list_element *c, const char *value)
{
fprintf_filtered (file, _("Stopping for shared library events is %s.\n"),
value);
}
int stop_after_trap;
enum stop_kind stop_soon;
int proceed_to_finish;
struct regcache *stop_registers;
static int breakpoints_failed;
static int stop_print_frame;
static struct breakpoint *step_resume_breakpoint = NULL;
static ptid_t target_last_wait_ptid;
static struct target_waitstatus target_last_waitstatus;
static struct
{
enum target_waitkind kind;
struct
{
int parent_pid;
int child_pid;
}
fork_event;
char *execd_pathname;
}
pending_follow;
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_child,
follow_fork_mode_parent,
NULL
};
static const char *follow_fork_mode_string = follow_fork_mode_parent;
static void
show_follow_fork_mode_string (struct ui_file *file, int from_tty,
struct cmd_list_element *c, const char *value)
{
fprintf_filtered (file, _("\
Debugger response to a program call of fork or vfork is \"%s\".\n"),
value);
}
static int
follow_fork (void)
{
int follow_child = (follow_fork_mode_string == follow_fork_mode_child);
return target_follow_fork (follow_child);
}
void
follow_inferior_reset_breakpoints (void)
{
if (step_resume_breakpoint)
breakpoint_re_set_thread (step_resume_breakpoint);
breakpoint_re_set (NULL);
insert_breakpoints ();
}
static void
follow_exec (int pid, char *execd_pathname)
{
int saved_pid = pid;
struct target_ops *tgt;
if (!may_follow_exec)
return;
update_breakpoints_after_exec ();
step_resume_breakpoint = NULL;
step_range_start = 0;
step_range_end = 0;
stepping_over_inlined_subroutine = 0;
finishing_inlined_subroutine = 0;
stepping_ranges = NULL;
printf_unfiltered (_("Executing new program: %s\n"), execd_pathname);
tgt = find_run_target ();
if (tgt == NULL)
error (_("Could find run target to save before following exec"));
gdb_flush (gdb_stdout);
target_mourn_inferior ();
inferior_ptid = pid_to_ptid (saved_pid);
push_target (tgt);
exec_file_attach (execd_pathname, 0);
symbol_file_add_main (execd_pathname, 0);
#if defined(SOLIB_RESTART)
SOLIB_RESTART ();
#endif
#ifdef SOLIB_CREATE_INFERIOR_HOOK
SOLIB_CREATE_INFERIOR_HOOK (PIDGET (inferior_ptid));
#else
solib_create_inferior_hook ();
#endif
insert_breakpoints ();
}
static int singlestep_breakpoints_inserted_p = 0;
static ptid_t singlestep_ptid;
static ptid_t saved_singlestep_ptid;
static int stepping_past_singlestep_breakpoint;
static void
resume_cleanups (void *ignore)
{
normal_stop ();
}
static const char schedlock_off[] = "off";
static const char schedlock_on[] = "on";
static const char schedlock_step[] = "step";
static const char *scheduler_enums[] = {
schedlock_off,
schedlock_on,
schedlock_step,
NULL
};
static const char *scheduler_mode = schedlock_off;
static struct ptid scheduler_lock_ptid;
struct ptid get_scheduler_lock_ptid ()
{
return scheduler_lock_ptid;
}
void
scheduler_run_this_ptid (struct ptid this_ptid)
{
scheduler_lock_ptid = this_ptid;
}
int
scheduler_lock_on_p ()
{
return ((scheduler_mode == schedlock_on)
|| (scheduler_mode == schedlock_step));
}
static void
set_schedlock_helper (void)
{
if (!target_can_lock_scheduler)
{
scheduler_mode = schedlock_off;
error ("Target '%s' does not support scheduler locking.", target_shortname);
}
if (scheduler_mode == schedlock_on)
scheduler_run_this_ptid (inferior_ptid);
else
scheduler_run_this_ptid (minus_one_ptid);
}
enum scheduler_locking_mode
set_scheduler_locking_mode (enum scheduler_locking_mode new_mode)
{
enum scheduler_locking_mode old_mode;
if (scheduler_mode == schedlock_off)
old_mode = scheduler_locking_off;
else if (scheduler_mode == schedlock_on)
old_mode = scheduler_locking_on;
else if (scheduler_mode == schedlock_step)
old_mode = scheduler_locking_step;
else
error ("Invalid old scheduler mode: %d", (int) scheduler_mode);
switch (new_mode)
{
case scheduler_locking_off:
scheduler_mode = schedlock_off;
break;
case scheduler_locking_on:
scheduler_mode = schedlock_on;
break;
case scheduler_locking_step:
scheduler_mode = schedlock_step;
break;
default:
error ("Invalid new scheduler mode: %d", new_mode);
}
set_schedlock_helper ();
return old_mode;
}
static void
show_scheduler_mode (struct ui_file *file, int from_tty,
struct cmd_list_element *c, const char *value)
{
fprintf_filtered (file, _("\
Mode for locking scheduler during execution is \"%s\".\n"),
value);
}
static void
set_schedlock_func (char *args, int from_tty, struct cmd_list_element *c)
{
set_schedlock_helper ();
}
void
resume (int step, enum target_signal sig)
{
int should_resume = 1;
struct cleanup *old_cleanups = make_cleanup (resume_cleanups, 0);
QUIT;
if (debug_infrun)
fprintf_unfiltered (gdb_stdlog, "infrun: resume (step=%d, signal=%d)\n",
step, sig);
if (CANNOT_STEP_HW_WATCHPOINTS && step && breakpoints_inserted)
remove_hw_watchpoints ();
if (breakpoint_here_p (read_pc ()) == permanent_breakpoint_here)
SKIP_PERMANENT_BREAKPOINT ();
if (SOFTWARE_SINGLE_STEP_P () && step)
{
SOFTWARE_SINGLE_STEP (sig, 1 );
step = 0;
singlestep_breakpoints_inserted_p = 1;
singlestep_ptid = inferior_ptid;
}
switch (pending_follow.kind)
{
case TARGET_WAITKIND_FORKED:
case TARGET_WAITKIND_VFORKED:
pending_follow.kind = TARGET_WAITKIND_SPURIOUS;
if (follow_fork ())
should_resume = 0;
break;
case TARGET_WAITKIND_EXECD:
pending_follow.kind = TARGET_WAITKIND_SPURIOUS;
break;
default:
break;
}
target_terminal_inferior ();
if (should_resume)
{
ptid_t resume_ptid;
resume_ptid = RESUME_ALL;
if ((step || singlestep_breakpoints_inserted_p)
&& (stepping_past_singlestep_breakpoint
|| (!breakpoints_inserted && breakpoint_here_p (read_pc ()))))
{
resume_ptid = inferior_ptid;
}
if (scheduler_mode == schedlock_on)
{
if (ptid_equal (scheduler_lock_ptid, minus_one_ptid)
|| !in_thread_list (scheduler_lock_ptid))
scheduler_run_this_ptid (inferior_ptid);
resume_ptid = scheduler_lock_ptid;
}
else if ((scheduler_mode == schedlock_step &&
(step || singlestep_breakpoints_inserted_p)))
{
resume_ptid = inferior_ptid;
}
if (CANNOT_STEP_BREAKPOINT)
{
if (step && breakpoints_inserted && breakpoint_here_p (read_pc ()))
step = 0;
}
target_resume (resume_ptid, step, sig);
}
discard_cleanups (old_cleanups);
}
void
clear_proceed_status (void)
{
trap_expected = 0;
step_range_start = 0;
step_range_end = 0;
step_frame_id = null_frame_id;
stepping_over_inlined_subroutine = 0;
step_over_calls = STEP_OVER_UNDEBUGGABLE;
stop_after_trap = 0;
stop_soon = NO_STOP_QUIETLY;
proceed_to_finish = 0;
finishing_inlined_subroutine = 0;
stepping_ranges = NULL;
breakpoint_proceeded = 1;
bpstat_clear (&stop_bpstat);
}
static int
prepare_to_proceed (void)
{
ptid_t wait_ptid;
struct target_waitstatus wait_status;
get_last_target_status (&wait_ptid, &wait_status);
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))
{
CORE_ADDR wait_pc = read_pc_pid (wait_ptid);
if (wait_pc != read_pc ())
{
inferior_ptid = wait_ptid;
flush_cached_frames ();
registers_changed ();
stop_pc = wait_pc;
if (stop_pc != inlined_function_call_stack_pc ())
inlined_function_update_call_stack (stop_pc);
select_frame (get_current_frame ());
}
if (breakpoint_here_p (wait_pc))
return 1;
}
return 0;
}
static CORE_ADDR prev_pc;
void
proceed (CORE_ADDR addr, enum target_signal siggnal, int step)
{
int oneproc = 0;
#if 0
{
extern int rolled_back;
static int warned_proceed = 0;
if (rolled_back && !warned_proceed && from_tty)
{
int go_p = query (_("Proceeding from a rollback; are you sure? "));
warned_proceed = 1;
if (!go_p)
return;
}
}
#endif
if (step > 0)
step_start_function = find_pc_function (read_pc ());
if (step < 0)
stop_after_trap = 1;
if (addr == (CORE_ADDR) -1)
{
if (read_pc () == stop_pc && breakpoint_here_p (read_pc ()))
oneproc = 1;
else if (gdbarch_single_step_through_delay_p (current_gdbarch)
&& gdbarch_single_step_through_delay (current_gdbarch,
get_current_frame ()))
oneproc = 1;
}
else
{
write_pc (addr);
}
if (debug_infrun)
fprintf_unfiltered (gdb_stdlog,
"infrun: proceed (addr=0x%s, signal=%d, step=%d)\n",
paddr_nz (addr), siggnal, step);
if (prepare_to_proceed () && breakpoint_here_p (read_pc ()))
oneproc = 1;
if (oneproc)
trap_expected = 1;
else
{
insert_breakpoints ();
breakpoints_inserted = 1;
}
if (siggnal != TARGET_SIGNAL_DEFAULT)
stop_signal = siggnal;
else if (!signal_program[stop_signal])
stop_signal = TARGET_SIGNAL_0;
annotate_starting ();
gdb_flush (gdb_stdout);
prev_pc = read_pc ();
resume (oneproc || step || bpstat_should_step (), stop_signal);
if (!target_can_async_p ())
{
wait_for_inferior ();
normal_stop ();
target_executing = 0;
}
}
void
start_remote (void)
{
init_thread_list ();
init_wait_for_inferior ();
stop_soon = STOP_QUIETLY;
trap_expected = 0;
wait_for_inferior ();
normal_stop ();
}
void
init_wait_for_inferior (void)
{
prev_pc = 0;
breakpoints_inserted = 0;
breakpoint_init_inferior (inf_starting);
stop_signal = TARGET_SIGNAL_0;
pending_follow.kind = TARGET_WAITKIND_SPURIOUS;
scheduler_lock_ptid = minus_one_ptid;
clear_proceed_status ();
stepping_past_singlestep_breakpoint = 0;
}
enum infwait_states
{
infwait_normal_state,
infwait_thread_hop_state,
infwait_nonstep_watch_state
};
enum inferior_stop_reason
{
STOP_UNKNOWN,
END_STEPPING_RANGE,
BREAKPOINT_HIT,
SIGNAL_EXITED,
EXITED,
SIGNAL_RECEIVED
};
struct execution_control_state
{
struct target_waitstatus ws;
struct target_waitstatus *wp;
int another_trap;
int random_signal;
CORE_ADDR stop_func_start;
CORE_ADDR stop_func_end;
char *stop_func_name;
struct symtab_and_line sal;
int current_line;
struct symtab *current_symtab;
int handling_longjmp;
ptid_t ptid;
ptid_t saved_inferior_ptid;
int step_after_step_resume_breakpoint;
int stepping_through_solib_after_catch;
bpstat stepping_through_solib_catchpoints;
int enable_hw_watchpoints_after_wait;
int new_thread_event;
struct target_waitstatus tmpstatus;
enum infwait_states infwait_state;
ptid_t waiton_ptid;
int wait_some_more;
};
void init_execution_control_state (struct execution_control_state *ecs);
void handle_inferior_event (struct execution_control_state *ecs);
static void step_into_function (struct execution_control_state *ecs);
static void insert_step_resume_breakpoint_at_frame (struct frame_info *step_frame);
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);
void
wait_for_inferior (void)
{
struct cleanup *old_cleanups;
struct execution_control_state ecss;
struct execution_control_state *ecs;
if (debug_infrun)
fprintf_unfiltered (gdb_stdlog, "infrun: wait_for_inferior\n");
old_cleanups = make_cleanup (delete_step_resume_breakpoint,
&step_resume_breakpoint);
ecs = &ecss;
init_execution_control_state (ecs);
previous_inferior_ptid = inferior_ptid;
overlay_cache_invalid = 1;
registers_changed ();
while (1)
{
if (deprecated_target_wait_hook)
ecs->ptid = deprecated_target_wait_hook (ecs->waiton_ptid, ecs->wp, NULL);
else
ecs->ptid = target_wait (ecs->waiton_ptid, ecs->wp, NULL);
handle_inferior_event (ecs);
if (!ecs->wait_some_more)
break;
}
do_cleanups (old_cleanups);
}
struct execution_control_state async_ecss;
struct execution_control_state *async_ecs;
void
fetch_inferior_event (void *client_data)
{
static struct cleanup *old_cleanups;
async_ecs = &async_ecss;
if (!async_ecs->wait_some_more)
{
old_cleanups = make_exec_cleanup (delete_step_resume_breakpoint,
&step_resume_breakpoint);
init_execution_control_state (async_ecs);
previous_inferior_ptid = inferior_ptid;
overlay_cache_invalid = 1;
registers_changed ();
}
if (deprecated_target_wait_hook)
async_ecs->ptid =
deprecated_target_wait_hook (async_ecs->waiton_ptid, async_ecs->wp, client_data);
else
async_ecs->ptid = target_wait (async_ecs->waiton_ptid, async_ecs->wp, client_data);
handle_inferior_event (async_ecs);
if (!async_ecs->wait_some_more)
{
do_exec_cleanups (old_cleanups);
normal_stop ();
if (step_multi && stop_step)
inferior_event_handler (INF_EXEC_CONTINUE, NULL);
else
{
target_executing = 0;
inferior_event_handler (INF_EXEC_COMPLETE, NULL);
}
}
}
void
init_execution_control_state (struct execution_control_state *ecs)
{
ecs->random_signal = 0;
ecs->step_after_step_resume_breakpoint = 0;
ecs->handling_longjmp = 0;
ecs->stepping_through_solib_after_catch = 0;
ecs->stepping_through_solib_catchpoints = NULL;
ecs->enable_hw_watchpoints_after_wait = 0;
ecs->sal = find_pc_line (prev_pc, 0);
ecs->current_line = ecs->sal.line;
ecs->current_symtab = ecs->sal.symtab;
ecs->infwait_state = infwait_normal_state;
ecs->waiton_ptid = pid_to_ptid (-1);
ecs->ws.code = -1;
ecs->wp = &(ecs->ws);
}
void
get_last_target_status (ptid_t *ptidp, struct target_waitstatus *status)
{
*ptidp = target_last_wait_ptid;
*status = target_last_waitstatus;
}
static void
context_switch (struct execution_control_state *ecs)
{
if (in_thread_list (inferior_ptid) && in_thread_list (ecs->ptid))
{
save_infrun_state (inferior_ptid, prev_pc,
trap_expected, step_resume_breakpoint,
step_range_start,
step_range_end, stepping_ranges, &step_frame_id,
ecs->handling_longjmp, ecs->another_trap,
ecs->stepping_through_solib_after_catch,
ecs->stepping_through_solib_catchpoints,
ecs->current_line, ecs->current_symtab);
load_infrun_state (ecs->ptid, &prev_pc,
&trap_expected, &step_resume_breakpoint,
&step_range_start,
&step_range_end, &stepping_ranges, &step_frame_id,
&ecs->handling_longjmp, &ecs->another_trap,
&ecs->stepping_through_solib_after_catch,
&ecs->stepping_through_solib_catchpoints,
&ecs->current_line, &ecs->current_symtab);
}
inferior_ptid = ecs->ptid;
}
static void
adjust_pc_after_break (struct execution_control_state *ecs)
{
CORE_ADDR breakpoint_pc;
if (DECR_PC_AFTER_BREAK == 0)
return;
if (ecs->ws.kind != TARGET_WAITKIND_STOPPED)
return;
if (ecs->ws.value.sig != TARGET_SIGNAL_TRAP)
return;
breakpoint_pc = read_pc_pid (ecs->ptid) - DECR_PC_AFTER_BREAK;
if (SOFTWARE_SINGLE_STEP_P ())
{
if (singlestep_breakpoints_inserted_p)
write_pc_pid (breakpoint_pc, ecs->ptid);
else if (software_breakpoint_inserted_here_p (breakpoint_pc))
write_pc_pid (breakpoint_pc, ecs->ptid);
}
else
{
if (currently_stepping (ecs))
{
if (prev_pc == breakpoint_pc
&& software_breakpoint_inserted_here_p (breakpoint_pc))
write_pc_pid (breakpoint_pc, ecs->ptid);
}
else
{
if (software_breakpoint_inserted_here_p (breakpoint_pc))
write_pc_pid (breakpoint_pc, ecs->ptid);
}
}
}
int stepped_after_stopped_by_watchpoint;
void
handle_inferior_event (struct execution_control_state *ecs)
{
int sw_single_step_trap_p = 0;
int stopped_by_watchpoint = -1;
target_last_wait_ptid = ecs->ptid;
target_last_waitstatus = *ecs->wp;
adjust_pc_after_break (ecs);
switch (ecs->infwait_state)
{
case infwait_thread_hop_state:
if (debug_infrun)
fprintf_unfiltered (gdb_stdlog, "infrun: infwait_thread_hop_state\n");
ecs->waiton_ptid = pid_to_ptid (-1);
if (ecs->enable_hw_watchpoints_after_wait)
{
TARGET_ENABLE_HW_WATCHPOINTS (PIDGET (inferior_ptid));
ecs->enable_hw_watchpoints_after_wait = 0;
}
stepped_after_stopped_by_watchpoint = 0;
break;
case infwait_normal_state:
if (debug_infrun)
fprintf_unfiltered (gdb_stdlog, "infrun: infwait_normal_state\n");
if (ecs->enable_hw_watchpoints_after_wait)
{
TARGET_ENABLE_HW_WATCHPOINTS (PIDGET (inferior_ptid));
ecs->enable_hw_watchpoints_after_wait = 0;
}
stepped_after_stopped_by_watchpoint = 0;
break;
case infwait_nonstep_watch_state:
if (debug_infrun)
fprintf_unfiltered (gdb_stdlog,
"infrun: infwait_nonstep_watch_state\n");
insert_breakpoints ();
stepped_after_stopped_by_watchpoint = 1;
break;
default:
internal_error (__FILE__, __LINE__, _("bad switch"));
}
ecs->infwait_state = infwait_normal_state;
flush_cached_frames ();
ecs->new_thread_event = (!ptid_equal (ecs->ptid, inferior_ptid)
&& !ptid_equal (ecs->ptid, minus_one_ptid)
&& !in_thread_list (ecs->ptid));
if (ecs->ws.kind != TARGET_WAITKIND_EXITED
&& ecs->ws.kind != TARGET_WAITKIND_SIGNALLED && ecs->new_thread_event)
{
add_thread (ecs->ptid);
ui_out_text (uiout, "[New ");
ui_out_text (uiout, target_pid_or_tid_to_str (ecs->ptid));
ui_out_text (uiout, "]\n");
}
switch (ecs->ws.kind)
{
case TARGET_WAITKIND_LOADED:
if (debug_infrun)
fprintf_unfiltered (gdb_stdlog, "infrun: TARGET_WAITKIND_LOADED\n");
#ifdef SOLIB_ADD
if (stop_soon == NO_STOP_QUIETLY)
{
if (breakpoints_inserted)
remove_breakpoints ();
target_terminal_ours_for_output ();
SOLIB_ADD (NULL, 0, ¤t_target, auto_solib_add);
target_terminal_inferior ();
if (breakpoints_inserted)
insert_breakpoints ();
}
#endif
resume (0, TARGET_SIGNAL_0);
prepare_to_wait (ecs);
return;
case TARGET_WAITKIND_SPURIOUS:
if (debug_infrun)
fprintf_unfiltered (gdb_stdlog, "infrun: TARGET_WAITKIND_SPURIOUS\n");
resume (0, TARGET_SIGNAL_0);
prepare_to_wait (ecs);
return;
case TARGET_WAITKIND_EXITED:
if (debug_infrun)
fprintf_unfiltered (gdb_stdlog, "infrun: TARGET_WAITKIND_EXITED\n");
target_terminal_ours ();
print_stop_reason (EXITED, ecs->ws.value.integer);
set_internalvar (lookup_internalvar ("_exitcode"),
value_from_longest (builtin_type_int,
(LONGEST) ecs->ws.value.integer));
gdb_flush (gdb_stdout);
target_mourn_inferior ();
singlestep_breakpoints_inserted_p = 0;
stop_print_frame = 0;
if (state_change_hook)
state_change_hook (STATE_INFERIOR_EXITED);
stop_stepping (ecs);
return;
case TARGET_WAITKIND_SIGNALLED:
if (debug_infrun)
fprintf_unfiltered (gdb_stdlog, "infrun: TARGET_WAITKIND_SIGNALLED\n");
stop_print_frame = 0;
stop_signal = ecs->ws.value.sig;
target_terminal_ours ();
target_mourn_inferior ();
print_stop_reason (SIGNAL_EXITED, stop_signal);
singlestep_breakpoints_inserted_p = 0;
if (state_change_hook)
state_change_hook (STATE_INFERIOR_EXITED);
stop_stepping (ecs);
return;
case TARGET_WAITKIND_FORKED:
case TARGET_WAITKIND_VFORKED:
if (debug_infrun)
fprintf_unfiltered (gdb_stdlog, "infrun: TARGET_WAITKIND_FORKED\n");
stop_signal = TARGET_SIGNAL_TRAP;
pending_follow.kind = ecs->ws.kind;
pending_follow.fork_event.parent_pid = PIDGET (ecs->ptid);
pending_follow.fork_event.child_pid = ecs->ws.value.related_pid;
stop_pc = read_pc ();
if (stop_pc != inlined_function_call_stack_pc ())
inlined_function_update_call_stack (stop_pc);
stop_bpstat = bpstat_stop_status (stop_pc, ecs->ptid, 0);
ecs->random_signal = !bpstat_explains_signal (stop_bpstat);
if (ecs->random_signal)
{
stop_signal = TARGET_SIGNAL_0;
keep_going (ecs);
return;
}
goto process_event_stop_test;
case TARGET_WAITKIND_EXECD:
if (debug_infrun)
fprintf_unfiltered (gdb_stdlog, "infrun: TARGET_WAITKIND_EXECED\n");
stop_signal = TARGET_SIGNAL_TRAP;
if (inferior_ignoring_leading_exec_events)
{
inferior_ignoring_leading_exec_events--;
if (pending_follow.kind == TARGET_WAITKIND_VFORKED)
ENSURE_VFORKING_PARENT_REMAINS_STOPPED (pending_follow.fork_event.
parent_pid);
target_resume (ecs->ptid, 0, TARGET_SIGNAL_0);
prepare_to_wait (ecs);
return;
}
inferior_ignoring_leading_exec_events =
target_reported_exec_events_per_exec_call () - 1;
pending_follow.execd_pathname =
savestring (ecs->ws.value.execd_pathname,
strlen (ecs->ws.value.execd_pathname));
follow_exec (PIDGET (inferior_ptid), pending_follow.execd_pathname);
xfree (pending_follow.execd_pathname);
stop_pc = read_pc_pid (ecs->ptid);
if (stop_pc != inlined_function_call_stack_pc ())
inlined_function_update_call_stack (stop_pc);
ecs->saved_inferior_ptid = inferior_ptid;
inferior_ptid = ecs->ptid;
stop_bpstat = bpstat_stop_status (stop_pc, ecs->ptid, 0);
ecs->random_signal = !bpstat_explains_signal (stop_bpstat);
inferior_ptid = ecs->saved_inferior_ptid;
if (ecs->random_signal)
{
stop_signal = TARGET_SIGNAL_0;
keep_going (ecs);
return;
}
goto process_event_stop_test;
case TARGET_WAITKIND_SYSCALL_ENTRY:
if (debug_infrun)
fprintf_unfiltered (gdb_stdlog, "infrun: TARGET_WAITKIND_SYSCALL_ENTRY\n");
resume (0, TARGET_SIGNAL_0);
prepare_to_wait (ecs);
return;
case TARGET_WAITKIND_SYSCALL_RETURN:
if (debug_infrun)
fprintf_unfiltered (gdb_stdlog, "infrun: TARGET_WAITKIND_SYSCALL_RETURN\n");
target_resume (ecs->ptid, 1, TARGET_SIGNAL_0);
prepare_to_wait (ecs);
return;
case TARGET_WAITKIND_STOPPED:
if (debug_infrun)
fprintf_unfiltered (gdb_stdlog, "infrun: TARGET_WAITKIND_STOPPED\n");
stop_signal = ecs->ws.value.sig;
break;
case TARGET_WAITKIND_IGNORE:
if (debug_infrun)
fprintf_unfiltered (gdb_stdlog, "infrun: TARGET_WAITKIND_IGNORE\n");
prepare_to_wait (ecs);
return;
}
if (ecs->new_thread_event)
{
target_resume (RESUME_ALL, 0, TARGET_SIGNAL_0);
prepare_to_wait (ecs);
return;
}
stop_pc = read_pc_pid (ecs->ptid);
if (stop_pc != inlined_function_call_stack_pc ())
inlined_function_update_call_stack (stop_pc);
if (debug_infrun)
fprintf_unfiltered (gdb_stdlog, "infrun: stop_pc = 0x%s\n", paddr_nz (stop_pc));
if (stepping_past_singlestep_breakpoint)
{
gdb_assert (SOFTWARE_SINGLE_STEP_P ()
&& singlestep_breakpoints_inserted_p);
gdb_assert (ptid_equal (singlestep_ptid, ecs->ptid));
gdb_assert (!ptid_equal (singlestep_ptid, saved_singlestep_ptid));
stepping_past_singlestep_breakpoint = 0;
if (stop_signal == TARGET_SIGNAL_TRAP)
{
if (debug_infrun)
fprintf_unfiltered (gdb_stdlog, "infrun: stepping_past_singlestep_breakpoint\n");
SOFTWARE_SINGLE_STEP (0, 0);
singlestep_breakpoints_inserted_p = 0;
ecs->random_signal = 0;
ecs->ptid = saved_singlestep_ptid;
context_switch (ecs);
if (deprecated_context_hook)
deprecated_context_hook (pid_to_thread_id (ecs->ptid));
resume (1, TARGET_SIGNAL_0);
prepare_to_wait (ecs);
return;
}
}
stepping_past_singlestep_breakpoint = 0;
if (stop_signal == TARGET_SIGNAL_TRAP)
{
int thread_hop_needed = 0;
if (breakpoints_inserted && breakpoint_here_p (stop_pc))
{
ecs->random_signal = 0;
if (!breakpoint_thread_match (stop_pc, ecs->ptid))
thread_hop_needed = 1;
}
else if (SOFTWARE_SINGLE_STEP_P () && singlestep_breakpoints_inserted_p)
{
ecs->random_signal = 0;
if (!ptid_equal (singlestep_ptid, ecs->ptid)
&& in_thread_list (singlestep_ptid))
{
thread_hop_needed = 1;
stepping_past_singlestep_breakpoint = 1;
saved_singlestep_ptid = singlestep_ptid;
}
}
if (thread_hop_needed)
{
int remove_status;
if (debug_infrun)
fprintf_unfiltered (gdb_stdlog, "infrun: thread_hop_needed\n");
if (SOFTWARE_SINGLE_STEP_P () && singlestep_breakpoints_inserted_p)
{
SOFTWARE_SINGLE_STEP (0, 0);
singlestep_breakpoints_inserted_p = 0;
}
remove_status = remove_breakpoints ();
if (remove_status != 0)
{
write_pc_pid (stop_pc + 4, ecs->ptid);
if (scheduler_mode == schedlock_on)
target_resume (ecs->ptid,
currently_stepping (ecs), TARGET_SIGNAL_0);
else
target_resume (RESUME_ALL,
currently_stepping (ecs), TARGET_SIGNAL_0);
prepare_to_wait (ecs);
return;
}
else
{
breakpoints_inserted = 0;
if (!ptid_equal (inferior_ptid, ecs->ptid))
context_switch (ecs);
ecs->waiton_ptid = ecs->ptid;
ecs->wp = &(ecs->ws);
ecs->another_trap = 1;
ecs->infwait_state = infwait_thread_hop_state;
keep_going (ecs);
registers_changed ();
return;
}
}
else if (SOFTWARE_SINGLE_STEP_P () && singlestep_breakpoints_inserted_p)
{
sw_single_step_trap_p = 1;
ecs->random_signal = 0;
}
}
else
ecs->random_signal = 1;
if (!ptid_equal (ecs->ptid, inferior_ptid))
{
if (debug_infrun)
fprintf_unfiltered (gdb_stdlog, "infrun: context switch\n");
context_switch (ecs);
if (deprecated_context_hook)
deprecated_context_hook (pid_to_thread_id (ecs->ptid));
if (ui_out_is_mi_like_p (uiout))
{
target_terminal_ours_for_output ();
printf_filtered ("[Switching to %s]\n",
target_pid_or_tid_to_str (inferior_ptid));
}
flush_cached_frames ();
}
if (SOFTWARE_SINGLE_STEP_P () && singlestep_breakpoints_inserted_p)
{
SOFTWARE_SINGLE_STEP (0, 0);
singlestep_breakpoints_inserted_p = 0;
}
if (HAVE_STEPPABLE_WATCHPOINT && STOPPED_BY_WATCHPOINT (ecs->ws))
{
if (debug_infrun)
fprintf_unfiltered (gdb_stdlog, "infrun: STOPPED_BY_WATCHPOINT\n");
resume (1, 0);
prepare_to_wait (ecs);
return;
}
if (HAVE_NONSTEPPABLE_WATCHPOINT && STOPPED_BY_WATCHPOINT (ecs->ws))
{
if (debug_infrun)
fprintf_unfiltered (gdb_stdlog, "infrun: STOPPED_BY_WATCHPOINT\n");
remove_breakpoints ();
registers_changed ();
if (SOFTWARE_SINGLE_STEP_P ())
{
SOFTWARE_SINGLE_STEP (TARGET_SIGNAL_0, 1 );
singlestep_breakpoints_inserted_p = 1;
singlestep_ptid = ecs->ptid;
target_resume (ecs->ptid, 0, TARGET_SIGNAL_0);
}
else
target_resume (ecs->ptid, 1, TARGET_SIGNAL_0);
ecs->waiton_ptid = ecs->ptid;
ecs->wp = &(ecs->ws);
ecs->infwait_state = infwait_nonstep_watch_state;
prepare_to_wait (ecs);
return;
}
if (HAVE_CONTINUABLE_WATCHPOINT)
stopped_by_watchpoint = STOPPED_BY_WATCHPOINT (ecs->ws);
ecs->stop_func_start = 0;
ecs->stop_func_end = 0;
ecs->stop_func_name = 0;
find_pc_partial_function (stop_pc, &ecs->stop_func_name,
&ecs->stop_func_start, &ecs->stop_func_end);
ecs->stop_func_start += DEPRECATED_FUNCTION_START_OFFSET;
ecs->another_trap = 0;
bpstat_clear (&stop_bpstat);
stop_step = 0;
stop_stack_dummy = 0;
stop_print_frame = 1;
ecs->random_signal = 0;
stopped_by_random_signal = 0;
breakpoints_failed = 0;
if (stop_signal == TARGET_SIGNAL_TRAP
&& trap_expected
&& gdbarch_single_step_through_delay_p (current_gdbarch)
&& currently_stepping (ecs))
{
int step_through_delay
= gdbarch_single_step_through_delay (current_gdbarch,
get_current_frame ());
if (debug_infrun && step_through_delay)
fprintf_unfiltered (gdb_stdlog, "infrun: step through delay\n");
if (step_range_end == 0 && step_through_delay)
{
ecs->another_trap = 1;
keep_going (ecs);
return;
}
else if (step_through_delay)
{
ecs->another_trap = 1;
}
}
if (stop_signal == TARGET_SIGNAL_TRAP
|| (breakpoints_inserted
&& (stop_signal == TARGET_SIGNAL_ILL
|| stop_signal == TARGET_SIGNAL_SEGV
|| stop_signal == TARGET_SIGNAL_EMT))
|| stop_soon == STOP_QUIETLY || stop_soon == STOP_QUIETLY_NO_SIGSTOP)
{
if (stop_signal == TARGET_SIGNAL_TRAP && stop_after_trap)
{
if (debug_infrun)
fprintf_unfiltered (gdb_stdlog, "infrun: stopped\n");
stop_print_frame = 0;
stop_stepping (ecs);
return;
}
if (stop_soon == STOP_QUIETLY)
{
if (debug_infrun)
fprintf_unfiltered (gdb_stdlog, "infrun: quietly stopped\n");
stop_stepping (ecs);
return;
}
if (stop_soon == STOP_QUIETLY_NO_SIGSTOP)
{
stop_stepping (ecs);
if (stop_signal == TARGET_SIGNAL_STOP)
stop_signal = TARGET_SIGNAL_0;
return;
}
if (stop_signal == TARGET_SIGNAL_TRAP && trap_expected)
{
if (debug_infrun)
fprintf_unfiltered (gdb_stdlog, "infrun: trap expected\n");
bpstat_clear (&stop_bpstat);
}
else
{
stop_bpstat = bpstat_stop_status (stop_pc, ecs->ptid,
stopped_by_watchpoint);
stop_print_frame = 1;
}
if (stop_signal == TARGET_SIGNAL_TRAP)
ecs->random_signal
= !(bpstat_explains_signal (stop_bpstat)
|| trap_expected
|| (step_range_end && step_resume_breakpoint == NULL));
else
{
ecs->random_signal = !bpstat_explains_signal (stop_bpstat);
if (!ecs->random_signal)
stop_signal = TARGET_SIGNAL_TRAP;
}
}
else
ecs->random_signal = 1;
process_event_stop_test:
if (ecs->random_signal)
{
int printed = 0;
if (debug_infrun)
fprintf_unfiltered (gdb_stdlog, "infrun: random signal %d\n", stop_signal);
stopped_by_random_signal = 1;
if (signal_print[stop_signal])
{
printed = 1;
target_terminal_ours_for_output ();
print_stop_reason (SIGNAL_RECEIVED, stop_signal);
#ifdef NM_NEXTSTEP
extern void macosx_print_extra_stop_info (int, CORE_ADDR);
if (ecs->ws.code != -1)
macosx_print_extra_stop_info (ecs->ws.code, ecs->ws.address);
#endif
}
if (signal_stop[stop_signal])
{
stop_stepping (ecs);
return;
}
else if (printed)
target_terminal_inferior ();
if (signal_program[stop_signal] == 0)
stop_signal = TARGET_SIGNAL_0;
if (prev_pc == read_pc ()
&& !breakpoints_inserted
&& breakpoint_here_p (read_pc ())
&& step_resume_breakpoint == NULL)
{
insert_step_resume_breakpoint_at_frame (get_current_frame ());
ecs->step_after_step_resume_breakpoint = 1;
keep_going (ecs);
return;
}
if (step_range_end != 0
&& stop_signal != TARGET_SIGNAL_0
&& ((stop_pc >= step_range_start && stop_pc < step_range_end)
|| (is_within_stepping_ranges (stop_pc)))
&& frame_id_eq (get_frame_id (get_current_frame ()),
step_frame_id)
&& step_resume_breakpoint == NULL)
{
insert_step_resume_breakpoint_at_frame (get_current_frame ());
keep_going (ecs);
return;
}
keep_going (ecs);
return;
}
{
CORE_ADDR jmp_buf_pc;
struct bpstat_what what;
what = bpstat_what (stop_bpstat);
if (what.call_dummy)
{
stop_stack_dummy = 1;
}
switch (what.main_action)
{
case BPSTAT_WHAT_SET_LONGJMP_RESUME:
if (debug_infrun)
fprintf_unfiltered (gdb_stdlog, "infrun: BPSTATE_WHAT_SET_LONGJMP_RESUME\n");
disable_longjmp_breakpoint ();
remove_breakpoints ();
breakpoints_inserted = 0;
if (!GET_LONGJMP_TARGET_P () || !GET_LONGJMP_TARGET (&jmp_buf_pc))
{
keep_going (ecs);
return;
}
if (step_resume_breakpoint != NULL)
{
delete_step_resume_breakpoint (&step_resume_breakpoint);
}
set_longjmp_resume_breakpoint (jmp_buf_pc, null_frame_id);
ecs->handling_longjmp = 1;
keep_going (ecs);
return;
case BPSTAT_WHAT_CLEAR_LONGJMP_RESUME:
case BPSTAT_WHAT_CLEAR_LONGJMP_RESUME_SINGLE:
if (debug_infrun)
fprintf_unfiltered (gdb_stdlog, "infrun: BPSTATE_WHAT_CLEAR_LONGJMP_RESUME\n");
remove_breakpoints ();
breakpoints_inserted = 0;
disable_longjmp_breakpoint ();
ecs->handling_longjmp = 0;
if (what.main_action == BPSTAT_WHAT_CLEAR_LONGJMP_RESUME)
break;
case BPSTAT_WHAT_SINGLE:
if (debug_infrun)
fprintf_unfiltered (gdb_stdlog, "infrun: BPSTATE_WHAT_SINGLE\n");
if (breakpoints_inserted)
{
remove_breakpoints ();
}
breakpoints_inserted = 0;
ecs->another_trap = 1;
break;
case BPSTAT_WHAT_STOP_NOISY:
if (debug_infrun)
fprintf_unfiltered (gdb_stdlog, "infrun: BPSTATE_WHAT_STOP_NOISY\n");
stop_print_frame = 1;
stop_stepping (ecs);
return;
case BPSTAT_WHAT_STOP_SILENT:
if (debug_infrun)
fprintf_unfiltered (gdb_stdlog, "infrun: BPSTATE_WHAT_STOP_SILENT\n");
stop_print_frame = 0;
stop_stepping (ecs);
return;
case BPSTAT_WHAT_STEP_RESUME:
if (debug_infrun)
fprintf_unfiltered (gdb_stdlog, "infrun: BPSTATE_WHAT_STEP_RESUME\n");
if (step_resume_breakpoint == NULL)
{
step_resume_breakpoint =
bpstat_find_step_resume_breakpoint (stop_bpstat);
}
delete_step_resume_breakpoint (&step_resume_breakpoint);
if (ecs->step_after_step_resume_breakpoint)
{
ecs->step_after_step_resume_breakpoint = 0;
remove_breakpoints ();
breakpoints_inserted = 0;
ecs->another_trap = 1;
keep_going (ecs);
return;
}
break;
case BPSTAT_WHAT_THROUGH_SIGTRAMP:
if (debug_infrun)
fprintf_unfiltered (gdb_stdlog, "infrun: BPSTATE_WHAT_THROUGH_SIGTRAMP\n");
if (trap_expected)
ecs->another_trap = 1;
break;
case BPSTAT_WHAT_CHECK_SHLIBS:
case BPSTAT_WHAT_CHECK_SHLIBS_RESUME_FROM_HOOK:
{
int was_sync_execution = 0;
int solib_changed = 0;
if (debug_infrun)
fprintf_unfiltered (gdb_stdlog, "infrun: BPSTATE_WHAT_CHECK_SHLIBS\n");
if (breakpoints_inserted)
remove_breakpoints ();
breakpoints_inserted = 0;
was_sync_execution = sync_execution;
target_terminal_ours_for_output ();
solib_changed =
#ifdef SOLIB_ADD
SOLIB_ADD (NULL, 0, ¤t_target, auto_solib_add);
#else
solib_add (NULL, 0, ¤t_target, auto_solib_add);
#endif
if (was_sync_execution && !sync_execution)
async_disable_stdin();
target_terminal_inferior ();
re_enable_breakpoints_in_shlibs (0);
if ((stop_on_solib_events && solib_changed) || stop_stack_dummy)
{
char addr_string[80];
struct breakpoint *b;
stop_stepping (ecs);
if (((b = step_resume_breakpoint) != NULL)
|| ((b = find_finish_breakpoint ()) != NULL))
{
struct symtab_and_line fsr_sal;
struct breakpoint *new_bp;
if (b == step_resume_breakpoint)
new_bp = solib_step_bp;
else
new_bp = solib_finish_bp;
init_sal (&fsr_sal);
fsr_sal.symtab = NULL;
fsr_sal.line = 0;
fsr_sal.pc = b->loc->address;
new_bp = set_breakpoint_sal (fsr_sal);
new_bp->disposition = disp_del;
new_bp->frame_id = b->frame_id;
sprintf (addr_string, "*0x%s", paddr (new_bp->loc->address));
new_bp->addr_string = xstrdup (addr_string);
if (breakpoints_inserted)
insert_breakpoints ();
}
return;
}
else if (what.main_action
== BPSTAT_WHAT_CHECK_SHLIBS_RESUME_FROM_HOOK)
{
bpstat_get_triggered_catchpoints (stop_bpstat,
&ecs->
stepping_through_solib_catchpoints);
ecs->stepping_through_solib_after_catch = 1;
ecs->another_trap = 1;
break;
}
else
{
ecs->another_trap = 1;
break;
}
}
break;
case BPSTAT_WHAT_LAST:
case BPSTAT_WHAT_KEEP_CHECKING:
break;
}
}
if (ecs->stepping_through_solib_after_catch)
{
#if defined(SOLIB_ADD)
if (SOLIB_IN_DYNAMIC_LINKER (PIDGET (ecs->ptid), stop_pc))
{
if (debug_infrun)
fprintf_unfiltered (gdb_stdlog, "infrun: stepping in dynamic linker\n");
ecs->another_trap = 1;
keep_going (ecs);
return;
}
#endif
if (debug_infrun)
fprintf_unfiltered (gdb_stdlog, "infrun: step past dynamic linker\n");
ecs->stepping_through_solib_after_catch = 0;
bpstat_clear (&stop_bpstat);
stop_bpstat = bpstat_copy (ecs->stepping_through_solib_catchpoints);
bpstat_clear (&ecs->stepping_through_solib_catchpoints);
stop_print_frame = 1;
stop_stepping (ecs);
return;
}
if (step_resume_breakpoint)
{
if (debug_infrun)
fprintf_unfiltered (gdb_stdlog, "infrun: step-resume breakpoint\n");
keep_going (ecs);
return;
}
if (step_range_end == 0)
{
if (debug_infrun)
fprintf_unfiltered (gdb_stdlog, "infrun: no stepping, continue\n");
keep_going (ecs);
return;
}
if ((stop_pc >= step_range_start && stop_pc < step_range_end)
|| (is_within_stepping_ranges (stop_pc)))
{
if (debug_infrun)
fprintf_unfiltered (gdb_stdlog, "infrun: stepping inside range [0x%s-0x%s]\n",
paddr_nz (step_range_start),
paddr_nz (step_range_end));
keep_going (ecs);
return;
}
if (step_over_calls == STEP_OVER_UNDEBUGGABLE
#ifdef IN_SOLIB_DYNSYM_RESOLVE_CODE
&& IN_SOLIB_DYNSYM_RESOLVE_CODE (stop_pc)
#else
&& in_solib_dynsym_resolve_code (stop_pc)
#endif
)
{
CORE_ADDR pc_after_resolver =
gdbarch_skip_solib_resolver (current_gdbarch, stop_pc);
if (debug_infrun)
fprintf_unfiltered (gdb_stdlog, "infrun: stepped into dynsym resolve code\n");
if (pc_after_resolver)
{
struct symtab_and_line sr_sal;
init_sal (&sr_sal);
sr_sal.pc = pc_after_resolver;
insert_step_resume_breakpoint_at_sal (sr_sal, null_frame_id);
}
keep_going (ecs);
return;
}
if (step_range_end != 1
&& (step_over_calls == STEP_OVER_UNDEBUGGABLE
|| step_over_calls == STEP_OVER_ALL)
&& get_frame_type (get_current_frame ()) == SIGTRAMP_FRAME)
{
if (debug_infrun)
fprintf_unfiltered (gdb_stdlog, "infrun: stepped into signal trampoline\n");
keep_going (ecs);
return;
}
if (ecs->stop_func_name == NULL
&& step_range_end == 1
&& step_over_calls > 0
&& !in_prologue (stop_pc, stop_pc))
{
stop_step = 1;
print_stop_reason (END_STEPPING_RANGE, 0);
stop_stepping (ecs);
return;
}
{
int load_state;
load_state = pc_set_load_state (stop_pc, OBJF_SYM_ALL, 0);
if (load_state != OBJF_SYM_ALL)
{
find_pc_partial_function (stop_pc, &ecs->stop_func_name,
&ecs->stop_func_start, &ecs->stop_func_end);
}
}
if (frame_id_eq (frame_unwind_id (get_current_frame ()), step_frame_id)
|| stepping_over_inlined_subroutine)
{
CORE_ADDR real_stop_pc;
char *file_name;
int line;
int column;
if (debug_infrun)
fprintf_unfiltered (gdb_stdlog, "infrun: stepped into subroutine\n");
if ((step_over_calls == STEP_OVER_NONE)
|| ((step_range_end == 1)
&& in_prologue (prev_pc, ecs->stop_func_start)))
{
stop_step = 1;
print_stop_reason (END_STEPPING_RANGE, 0);
stop_stepping (ecs);
return;
}
if (step_over_calls == STEP_OVER_ALL)
{
struct frame_info *prev_frame = get_prev_frame (get_current_frame ());
if (stepping_over_inlined_subroutine
&& (stop_pc == step_range_end
|| is_at_stepping_ranges_end (stop_pc)))
{
stop_step = 1;
print_stop_reason (END_STEPPING_RANGE, 0);
stop_stepping (ecs);
return;
}
else if (stepping_over_inlined_subroutine
&& frame_id_eq (get_frame_id (prev_frame), step_frame_id)
&& get_frame_type (get_current_frame ()) == INLINED_FRAME
&& at_inlined_call_site_p (&file_name, &line, &column )
&& current_inlined_subroutine_call_stack_start_pc ()
== stop_pc)
{
stop_step = 1;
print_stop_reason (END_STEPPING_RANGE, 0);
stop_stepping (ecs);
return;
}
else if (prev_frame)
{
insert_step_resume_breakpoint_at_frame (prev_frame);
keep_going (ecs);
return;
}
else
{
warning ("Couldn't find previous frame to set return breakpoint, stopping now.");
stop_stepping (ecs);
return;
}
}
if (step_range_start == 1
&& ecs->stop_func_start != 0
&& stop_pc > ecs->stop_func_start)
{
stop_step = 1;
print_stop_reason (END_STEPPING_RANGE, 0);
stop_stepping (ecs);
return;
}
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 (
#ifdef IN_SOLIB_DYNSYM_RESOLVE_CODE
IN_SOLIB_DYNSYM_RESOLVE_CODE (ecs->stop_func_start)
#else
in_solib_dynsym_resolve_code (ecs->stop_func_start)
#endif
)
{
struct symtab_and_line sr_sal;
init_sal (&sr_sal);
sr_sal.pc = ecs->stop_func_start;
insert_step_resume_breakpoint_at_sal (sr_sal, null_frame_id);
keep_going (ecs);
return;
}
{
struct symtab_and_line tmp_sal;
if (real_stop_pc != 0)
pc_set_load_state (ecs->stop_func_start, OBJF_SYM_ALL, 0);
tmp_sal = find_pc_line (ecs->stop_func_start, 0);
if (tmp_sal.line != 0)
{
step_into_function (ecs);
return;
}
}
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;
}
{
struct frame_info *prev_frame = get_prev_frame (get_current_frame ());
if (prev_frame)
{
insert_step_resume_breakpoint_at_frame (prev_frame);
keep_going (ecs);
return;
}
else
{
warning ("Couldn't find previous frame to set return breakpoint, stopping now.");
stop_stepping (ecs);
return;
}
}
}
if (IN_SOLIB_RETURN_TRAMPOLINE (stop_pc, ecs->stop_func_name))
{
CORE_ADDR real_stop_pc = SKIP_TRAMPOLINE_CODE (stop_pc);
if (real_stop_pc != inlined_function_call_stack_pc ())
inlined_function_update_call_stack (real_stop_pc);
if (debug_infrun)
fprintf_unfiltered (gdb_stdlog, "infrun: stepped into solib return tramp\n");
if (real_stop_pc)
{
struct symtab_and_line sr_sal;
init_sal (&sr_sal);
sr_sal.pc = real_stop_pc;
sr_sal.section = find_pc_overlay (sr_sal.pc);
insert_step_resume_breakpoint_at_sal (sr_sal, null_frame_id);
keep_going (ecs);
return;
}
}
ecs->sal = find_pc_line (stop_pc, 0);
if (step_over_calls == STEP_OVER_UNDEBUGGABLE
&& ecs->stop_func_name == NULL
&& ecs->sal.line == 0)
{
if (debug_infrun)
fprintf_unfiltered (gdb_stdlog, "infrun: stepped into undebuggable function\n");
if (step_stop_if_no_debug)
{
stop_step = 1;
print_stop_reason (END_STEPPING_RANGE, 0);
stop_stepping (ecs);
return;
}
else
{
struct frame_info *prev_frame = get_prev_frame (get_current_frame ());
if (prev_frame)
{
insert_step_resume_breakpoint_at_frame (prev_frame);
keep_going (ecs);
return;
}
else
{
warning ("Couldn't find previous frame to set return breakpoint, stopping now.");
stop_stepping (ecs);
return;
}
}
}
if (step_range_end == 1)
{
if (debug_infrun)
fprintf_unfiltered (gdb_stdlog, "infrun: stepi/nexti\n");
stop_step = 1;
print_stop_reason (END_STEPPING_RANGE, 0);
stop_stepping (ecs);
return;
}
if (ecs->sal.line == 0)
{
if (debug_infrun)
fprintf_unfiltered (gdb_stdlog, "infrun: no line number info\n");
stop_step = 1;
print_stop_reason (END_STEPPING_RANGE, 0);
stop_stepping (ecs);
return;
}
if ((stop_pc == ecs->sal.pc)
&& (ecs->current_line != ecs->sal.line
|| ecs->current_symtab != ecs->sal.symtab
|| (get_frame_type (get_current_frame ()) == INLINED_FRAME
&& step_range_end != 1)))
{
if (debug_infrun)
fprintf_unfiltered (gdb_stdlog, "infrun: stepped to a different line\n");
stop_step = 1;
print_stop_reason (END_STEPPING_RANGE, 0);
stop_stepping (ecs);
return;
}
if (ecs->stop_func_end && ecs->sal.end >= ecs->stop_func_end)
{
if (debug_infrun)
fprintf_unfiltered (gdb_stdlog, "infrun: stepped to a different function\n");
stop_step = 1;
print_stop_reason (END_STEPPING_RANGE, 0);
stop_stepping (ecs);
return;
}
step_range_start = ecs->sal.pc;
step_range_end = ecs->sal.end;
stepping_over_inlined_subroutine = 0;
stepping_ranges = NULL;
step_frame_id = get_frame_id (get_current_frame ());
ecs->current_line = ecs->sal.line;
ecs->current_symtab = ecs->sal.symtab;
#if 0
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;
#endif
{
struct frame_id current_frame = get_frame_id (get_current_frame ());
if (!(frame_id_inner (current_frame, step_frame_id)))
step_frame_id = current_frame;
}
if (debug_infrun)
fprintf_unfiltered (gdb_stdlog, "infrun: keep going\n");
keep_going (ecs);
}
static int
currently_stepping (struct execution_control_state *ecs)
{
return ((!ecs->handling_longjmp
&& ((step_range_end && step_resume_breakpoint == NULL)
|| trap_expected))
|| ecs->stepping_through_solib_after_catch
|| bpstat_should_step ());
}
static void
step_into_function (struct execution_control_state *ecs)
{
struct symtab *s;
struct symtab_and_line sr_sal;
s = find_pc_symtab (stop_pc);
if (s && s->language != language_asm)
ecs->stop_func_start = SKIP_PROLOGUE (ecs->stop_func_start);
ecs->sal = find_pc_line (ecs->stop_func_start, 0);
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;
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)
{
stop_step = 1;
print_stop_reason (END_STEPPING_RANGE, 0);
stop_stepping (ecs);
return;
}
else
{
init_sal (&sr_sal);
sr_sal.pc = ecs->stop_func_start;
sr_sal.section = find_pc_overlay (ecs->stop_func_start);
insert_step_resume_breakpoint_at_sal (sr_sal, null_frame_id);
step_range_end = step_range_start;
}
keep_going (ecs);
}
void
insert_step_resume_breakpoint_at_sal (struct symtab_and_line sr_sal,
struct frame_id sr_id)
{
gdb_assert (step_resume_breakpoint == NULL);
step_resume_breakpoint = set_momentary_breakpoint (sr_sal, sr_id,
bp_step_resume);
if (inlined_function_end_of_inlined_code_p (sr_sal.pc))
adjust_current_inlined_subroutine_stack_position (-1);
if (breakpoints_inserted)
insert_breakpoints ();
}
static void
insert_step_resume_breakpoint_at_frame (struct frame_info *return_frame)
{
struct symtab_and_line sr_sal;
init_sal (&sr_sal);
sr_sal.pc = ADDR_BITS_REMOVE (get_frame_pc (return_frame));
sr_sal.section = find_pc_overlay (sr_sal.pc);
if (stepping_over_inlined_subroutine)
insert_step_resume_breakpoint_at_sal (sr_sal, step_frame_id);
else
insert_step_resume_breakpoint_at_sal (sr_sal, get_frame_id (return_frame));
}
static void
stop_stepping (struct execution_control_state *ecs)
{
if (debug_infrun)
fprintf_unfiltered (gdb_stdlog, "infrun: stop_stepping\n");
ecs->wait_some_more = 0;
}
static void
keep_going (struct execution_control_state *ecs)
{
prev_pc = read_pc ();
if (trap_expected && stop_signal != TARGET_SIGNAL_TRAP)
{
resume (currently_stepping (ecs), stop_signal);
}
else
{
if (!breakpoints_inserted && !ecs->another_trap)
{
breakpoints_failed = insert_breakpoints ();
if (breakpoints_failed)
{
stop_stepping (ecs);
return;
}
breakpoints_inserted = 1;
}
trap_expected = ecs->another_trap;
if (stop_signal == TARGET_SIGNAL_TRAP && !signal_program[stop_signal])
stop_signal = TARGET_SIGNAL_0;
resume (currently_stepping (ecs), stop_signal);
}
prepare_to_wait (ecs);
}
static void
prepare_to_wait (struct execution_control_state *ecs)
{
if (debug_infrun)
fprintf_unfiltered (gdb_stdlog, "infrun: prepare_to_wait\n");
if (ecs->infwait_state == infwait_normal_state)
{
overlay_cache_invalid = 1;
registers_changed ();
ecs->waiton_ptid = pid_to_ptid (-1);
ecs->wp = &(ecs->ws);
}
ecs->wait_some_more = 1;
}
static void
print_stop_reason (enum inferior_stop_reason stop_reason, int stop_info)
{
switch (stop_reason)
{
case STOP_UNKNOWN:
break;
case END_STEPPING_RANGE:
if (!step_multi || !stop_step)
if (ui_out_is_mi_like_p (uiout))
{
if (finishing_inlined_subroutine)
ui_out_field_string
(uiout, "reason",
async_reason_lookup (EXEC_ASYNC_FUNCTION_FINISHED));
else
ui_out_field_string
(uiout, "reason",
async_reason_lookup (EXEC_ASYNC_END_STEPPING_RANGE));
}
break;
case BREAKPOINT_HIT:
break;
case SIGNAL_EXITED:
annotate_signalled ();
if (ui_out_is_mi_like_p (uiout))
ui_out_field_string
(uiout, "reason",
async_reason_lookup (EXEC_ASYNC_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");
break;
case EXITED:
annotate_exited (stop_info);
if (stop_info)
{
if (ui_out_is_mi_like_p (uiout))
ui_out_field_string (uiout, "reason",
async_reason_lookup (EXEC_ASYNC_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 (ui_out_is_mi_like_p (uiout))
ui_out_field_string
(uiout, "reason",
async_reason_lookup (EXEC_ASYNC_EXITED_NORMALLY));
ui_out_text (uiout, "\nProgram exited normally.\n");
}
break;
case SIGNAL_RECEIVED:
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", async_reason_lookup (EXEC_ASYNC_SIGNAL_RECEIVED));
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");
break;
default:
internal_error (__FILE__, __LINE__,
_("print_stop_reason: unrecognized enum value"));
break;
}
}
void
rollback_stop (void)
{
stop_print_frame = 1;
normal_stop ();
}
void
normal_stop (void)
{
struct target_waitstatus last;
ptid_t last_ptid;
get_last_target_status (&last_ptid, &last);
if (!ptid_equal (previous_inferior_ptid, inferior_ptid)
&& target_has_execution
&& last.kind != TARGET_WAITKIND_SIGNALLED
&& last.kind != TARGET_WAITKIND_EXITED)
{
target_terminal_ours_for_output ();
printf_filtered (_("[Switching to %s]\n"),
target_pid_or_tid_to_str (inferior_ptid));
previous_inferior_ptid = inferior_ptid;
}
if (target_has_execution)
deprecated_update_frame_pc_hack (get_current_frame (), read_pc ());
if (target_has_execution && breakpoints_inserted)
{
if (remove_breakpoints ())
{
target_terminal_ours_for_output ();
printf_filtered (_("\
Cannot remove breakpoints because program is no longer writable.\n\
It might be running in another process.\n\
Further execution is probably impossible.\n"));
}
}
breakpoints_inserted = 0;
if (stopped_by_random_signal)
disable_current_display ();
if (step_multi && stop_step)
goto done;
target_terminal_ours ();
if (!target_has_stack)
{
if (stop_command)
catch_errors (hook_stop_stub, stop_command,
"Error while running hook_stop:\n", RETURN_MASK_ALL);
goto done;
}
if (!stop_stack_dummy)
{
select_frame (get_current_frame ());
if (stop_print_frame && deprecated_selected_frame)
{
int bpstat_ret;
int solib_step_bpstat_p = 0;
int source_flag = -1;
int do_frame_printing = 1;
#ifdef SOLIB_ADD
if (stop_on_solib_events)
{
if (solib_step_bp != NULL)
{
bpstat bs = stop_bpstat;
int num = bpstat_num (&bs);
if (num != 0)
{
int nother = bpstat_num (&bs);
if (nother == 0
&& num == solib_step_bp->number)
{
solib_step_bpstat_p = 1;
print_stop_reason (END_STEPPING_RANGE, 0);
solib_step_bp = NULL;
}
}
}
else if (solib_finish_bp != NULL)
{
bpstat bs = stop_bpstat;
int num = bpstat_num (&bs);
if (num == solib_finish_bp->number)
{
solib_step_bpstat_p = 1;
if (interpreter_p && strcmp (interpreter_p, "mi") == 0)
ui_out_field_string (uiout, "reason",
"function-finished");
solib_finish_bp = NULL;
}
}
}
#endif
if (!solib_step_bpstat_p)
{
bpstat_ret = bpstat_print (stop_bpstat);
switch (bpstat_ret)
{
case PRINT_UNKNOWN:
if (stop_step
&& frame_id_eq (step_frame_id,
get_frame_id (get_current_frame ()))
&& step_start_function == find_pc_function (stop_pc))
{
if (finishing_inlined_subroutine)
source_flag = SRC_AND_LOC;
else
source_flag = SRC_LINE;
}
else
source_flag = SRC_AND_LOC;
break;
case PRINT_SRC_AND_LOC:
source_flag = SRC_AND_LOC;
break;
case PRINT_SRC_ONLY:
source_flag = SRC_LINE;
break;
case PRINT_NOTHING:
source_flag = SRC_LINE;
do_frame_printing = 0;
break;
default:
internal_error (__FILE__, __LINE__, _("Unknown value."));
}
}
if (ui_out_is_mi_like_p (uiout))
source_flag = LOC_AND_ADDRESS;
if (ui_out_is_mi_like_p (uiout))
ui_out_field_int (uiout, "thread-id",
pid_to_thread_id (inferior_ptid));
if (do_frame_printing)
if (!interpreter_p || strncmp (interpreter_p, "mi", 2) != 0)
{
print_stack_frame (get_selected_frame (NULL), 0, source_flag);
clear_inlined_subroutine_print_frames ();
}
do_displays ();
}
}
if (stop_command)
catch_errors (hook_stop_stub, stop_command,
"Error while running hook_stop:\n", RETURN_MASK_ALL);
if (proceed_to_finish)
regcache_cpy (stop_registers, current_regcache);
if (stop_stack_dummy)
{
frame_pop (get_current_frame ());
stop_pc = read_pc ();
inlined_subroutine_restore_after_dummy_call ();
if (stop_pc != inlined_function_call_stack_pc ())
inlined_function_update_call_stack (stop_pc);
select_frame (get_current_frame ());
}
done:
breakpoint_auto_delete (stop_bpstat);
if (!stop_stack_dummy)
{
if (PIDGET (inferior_ptid) != 0)
{
if (state_change_hook)
{
state_change_hook (STATE_INFERIOR_STOPPED);
}
}
if ((stack_changed_hook != NULL) &&
(! frame_id_eq (step_frame_id, get_frame_id (get_current_frame ())) ||
step_start_function != find_pc_function (stop_pc)))
{
stack_changed_hook ();
}
}
annotate_stopped ();
observer_notify_normal_stop (stop_bpstat);
{
void maybe_create_checkpoint (void);
if (auto_checkpointing)
maybe_create_checkpoint ();
}
}
static int suppress_hook_stop_p;
static void
do_cleanup_suppress_hook_stop (void *arg)
{
suppress_hook_stop_p = (int) arg;
}
struct cleanup *
make_cleanup_suppress_hook_stop ()
{
int old_value = suppress_hook_stop_p;
suppress_hook_stop_p = 1;
return make_cleanup (do_cleanup_suppress_hook_stop, (void *) old_value);
}
static int
hook_stop_stub (void *cmd)
{
if (!suppress_hook_stop_p)
execute_cmd_pre_hook ((struct cmd_list_element *) cmd);
return (0);
}
int
signal_stop_state (int signo)
{
return signal_stop[signo];
}
int
signal_print_state (int signo)
{
return signal_print[signo];
}
int
signal_pass_state (int signo)
{
return signal_program[signo];
}
int
signal_stop_update (int signo, int state)
{
int ret = signal_stop[signo];
signal_stop[signo] = state;
return ret;
}
int
signal_print_update (int signo, int state)
{
int ret = signal_print[signo];
signal_print[signo] = state;
return ret;
}
int
signal_pass_update (int signo, int state)
{
int ret = signal_program[signo];
signal_program[signo] = state;
return ret;
}
static void
sig_print_header (void)
{
printf_filtered (_("\
Signal Stop\tPrint\tPass to program\tDescription\n"));
}
static void
sig_print_info (enum target_signal oursig)
{
char *name = target_signal_to_name (oursig);
int name_padding = 13 - strlen (name);
if (name_padding <= 0)
name_padding = 0;
printf_filtered ("%s", name);
printf_filtered ("%*.*s ", name_padding, name_padding, " ");
printf_filtered ("%s\t", signal_stop[oursig] ? "Yes" : "No");
printf_filtered ("%s\t", signal_print[oursig] ? "Yes" : "No");
printf_filtered ("%s\t\t", signal_program[oursig] ? "Yes" : "No");
printf_filtered ("%s\n", target_signal_to_string (oursig));
}
static void
handle_command (char *args, int from_tty)
{
char **argv;
int digits, wordlen;
int sigfirst, signum, siglast;
enum target_signal oursig;
int allsigs;
int nsigs;
unsigned char *sigs;
struct cleanup *old_chain;
if (args == NULL)
{
error_no_arg (_("signal to handle"));
}
nsigs = (int) TARGET_SIGNAL_LAST;
sigs = (unsigned char *) alloca (nsigs);
memset (sigs, 0, nsigs);
argv = buildargv (args);
if (argv == NULL)
{
nomem (0);
}
old_chain = make_cleanup_freeargv (argv);
while (*argv != NULL)
{
wordlen = strlen (*argv);
for (digits = 0; isdigit ((*argv)[digits]); digits++)
{;
}
allsigs = 0;
sigfirst = siglast = -1;
if (wordlen >= 1 && !strncmp (*argv, "all", wordlen))
{
allsigs = 1;
sigfirst = 0;
siglast = nsigs - 1;
}
else if (wordlen >= 1 && !strncmp (*argv, "stop", wordlen))
{
SET_SIGS (nsigs, sigs, signal_stop);
SET_SIGS (nsigs, sigs, signal_print);
}
else if (wordlen >= 1 && !strncmp (*argv, "ignore", wordlen))
{
UNSET_SIGS (nsigs, sigs, signal_program);
}
else if (wordlen >= 2 && !strncmp (*argv, "print", wordlen))
{
SET_SIGS (nsigs, sigs, signal_print);
}
else if (wordlen >= 2 && !strncmp (*argv, "pass", wordlen))
{
SET_SIGS (nsigs, sigs, signal_program);
}
else if (wordlen >= 3 && !strncmp (*argv, "nostop", wordlen))
{
UNSET_SIGS (nsigs, sigs, signal_stop);
}
else if (wordlen >= 3 && !strncmp (*argv, "noignore", wordlen))
{
SET_SIGS (nsigs, sigs, signal_program);
}
else if (wordlen >= 4 && !strncmp (*argv, "noprint", wordlen))
{
UNSET_SIGS (nsigs, sigs, signal_print);
UNSET_SIGS (nsigs, sigs, signal_stop);
}
else if (wordlen >= 4 && !strncmp (*argv, "nopass", wordlen))
{
UNSET_SIGS (nsigs, sigs, signal_program);
}
else if (digits > 0)
{
sigfirst = siglast = (int)
target_signal_from_command (atoi (*argv));
if ((*argv)[digits] == '-')
{
siglast = (int)
target_signal_from_command (atoi ((*argv) + digits + 1));
}
if (sigfirst > siglast)
{
signum = sigfirst;
sigfirst = siglast;
siglast = signum;
}
}
else
{
oursig = target_signal_from_name (*argv);
if (oursig != TARGET_SIGNAL_UNKNOWN)
{
sigfirst = siglast = (int) oursig;
}
else
{
error (_("Unrecognized or ambiguous flag word: \"%s\"."), *argv);
}
}
for (signum = sigfirst; signum >= 0 && signum <= siglast; signum++)
{
switch ((enum target_signal) signum)
{
case TARGET_SIGNAL_TRAP:
case TARGET_SIGNAL_INT:
if (!allsigs && !sigs[signum])
{
if (query ("%s is used by the debugger.\n\
Are you sure you want to change it? ", target_signal_to_name ((enum target_signal) signum)))
{
sigs[signum] = 1;
}
else
{
printf_unfiltered (_("Not confirmed, unchanged.\n"));
gdb_flush (gdb_stdout);
}
}
break;
case TARGET_SIGNAL_0:
case TARGET_SIGNAL_DEFAULT:
case TARGET_SIGNAL_UNKNOWN:
break;
default:
sigs[signum] = 1;
break;
}
}
argv++;
}
target_notice_signals (inferior_ptid);
if (from_tty)
{
sig_print_header ();
for (signum = 0; signum < nsigs; signum++)
{
if (sigs[signum])
{
sig_print_info (signum);
}
}
}
do_cleanups (old_chain);
}
static void
xdb_handle_command (char *args, int from_tty)
{
char **argv;
struct cleanup *old_chain;
argv = buildargv (args);
if (argv == NULL)
{
nomem (0);
}
old_chain = make_cleanup_freeargv (argv);
if (argv[1] != (char *) NULL)
{
char *argBuf;
int bufLen;
bufLen = strlen (argv[0]) + 20;
argBuf = (char *) xmalloc (bufLen);
if (argBuf)
{
int validFlag = 1;
enum target_signal oursig;
oursig = target_signal_from_name (argv[0]);
memset (argBuf, 0, bufLen);
if (strcmp (argv[1], "Q") == 0)
sprintf (argBuf, "%s %s", argv[0], "noprint");
else
{
if (strcmp (argv[1], "s") == 0)
{
if (!signal_stop[oursig])
sprintf (argBuf, "%s %s", argv[0], "stop");
else
sprintf (argBuf, "%s %s", argv[0], "nostop");
}
else if (strcmp (argv[1], "i") == 0)
{
if (!signal_program[oursig])
sprintf (argBuf, "%s %s", argv[0], "pass");
else
sprintf (argBuf, "%s %s", argv[0], "nopass");
}
else if (strcmp (argv[1], "r") == 0)
{
if (!signal_print[oursig])
sprintf (argBuf, "%s %s", argv[0], "print");
else
sprintf (argBuf, "%s %s", argv[0], "noprint");
}
else
validFlag = 0;
}
if (validFlag)
handle_command (argBuf, from_tty);
else
printf_filtered (_("Invalid signal handling flag.\n"));
if (argBuf)
xfree (argBuf);
}
}
do_cleanups (old_chain);
}
static void
signals_info (char *signum_exp, int from_tty)
{
enum target_signal oursig;
sig_print_header ();
if (signum_exp)
{
oursig = target_signal_from_name (signum_exp);
if (oursig == TARGET_SIGNAL_UNKNOWN)
{
oursig =
target_signal_from_command (parse_and_eval_long (signum_exp));
}
sig_print_info (oursig);
return;
}
printf_filtered ("\n");
for (oursig = TARGET_SIGNAL_FIRST;
(int) oursig < (int) TARGET_SIGNAL_LAST;
oursig = (enum target_signal) ((int) oursig + 1))
{
QUIT;
if (oursig != TARGET_SIGNAL_UNKNOWN
&& oursig != TARGET_SIGNAL_DEFAULT && oursig != TARGET_SIGNAL_0)
sig_print_info (oursig);
}
printf_filtered (_("\nUse the \"handle\" command to change these tables.\n"));
}
struct inferior_status
{
ptid_t stop_ptid;
enum target_signal stop_signal;
CORE_ADDR stop_pc;
bpstat stop_bpstat;
int stop_step;
int stop_stack_dummy;
int stopped_by_random_signal;
int trap_expected;
CORE_ADDR step_range_start;
CORE_ADDR step_range_end;
struct address_range_list *stepping_ranges;
struct frame_id step_frame_id;
enum step_over_calls_kind step_over_calls;
CORE_ADDR step_resume_break_address;
int stop_after_trap;
int stop_soon;
struct regcache *stop_registers;
struct regcache *registers;
struct frame_id selected_frame_id;
int breakpoint_proceeded;
int restore_stack_info;
int proceed_to_finish;
};
void
write_inferior_status_register (struct inferior_status *inf_status, int regno,
LONGEST val)
{
int size = register_size (current_gdbarch, regno);
void *buf = alloca (size);
store_signed_integer (buf, size, val);
regcache_raw_write (inf_status->registers, regno, buf);
}
struct inferior_status *
save_inferior_status (int restore_stack_info)
{
struct inferior_status *inf_status = XMALLOC (struct inferior_status);
inf_status->stop_signal = stop_signal;
inf_status->stop_pc = stop_pc;
inf_status->stop_step = stop_step;
inf_status->stop_stack_dummy = stop_stack_dummy;
inf_status->stopped_by_random_signal = stopped_by_random_signal;
inf_status->trap_expected = trap_expected;
inf_status->step_range_start = step_range_start;
inf_status->step_range_end = step_range_end;
inf_status->stepping_ranges = stepping_ranges;
inf_status->step_frame_id = step_frame_id;
inf_status->step_over_calls = step_over_calls;
inf_status->stop_after_trap = stop_after_trap;
inf_status->stop_soon = stop_soon;
inf_status->stop_bpstat = stop_bpstat;
stop_bpstat = bpstat_copy (stop_bpstat);
inf_status->breakpoint_proceeded = breakpoint_proceeded;
inf_status->restore_stack_info = restore_stack_info;
inf_status->proceed_to_finish = proceed_to_finish;
inf_status->stop_registers = regcache_dup_no_passthrough (stop_registers);
inf_status->registers = regcache_dup (current_regcache);
inf_status->selected_frame_id = get_frame_id (deprecated_selected_frame);
inf_status->stop_ptid = inferior_ptid;
return inf_status;
}
static int
restore_selected_frame (void *args)
{
struct frame_id *fid = (struct frame_id *) args;
struct frame_info *frame;
frame = frame_find_by_id (*fid);
if (frame == NULL)
{
warning (_("Unable to restore previously selected frame."));
return 0;
}
select_frame (frame);
return (1);
}
void
restore_inferior_status (struct inferior_status *inf_status)
{
inferior_ptid = inf_status->stop_ptid;
stop_signal = inf_status->stop_signal;
stop_pc = inf_status->stop_pc;
stop_step = inf_status->stop_step;
stop_stack_dummy = inf_status->stop_stack_dummy;
stopped_by_random_signal = inf_status->stopped_by_random_signal;
trap_expected = inf_status->trap_expected;
step_range_start = inf_status->step_range_start;
step_range_end = inf_status->step_range_end;
stepping_ranges = inf_status->stepping_ranges;
step_frame_id = inf_status->step_frame_id;
step_over_calls = inf_status->step_over_calls;
stop_after_trap = inf_status->stop_after_trap;
stop_soon = inf_status->stop_soon;
bpstat_clear (&stop_bpstat);
stop_bpstat = inf_status->stop_bpstat;
breakpoint_proceeded = inf_status->breakpoint_proceeded;
proceed_to_finish = inf_status->proceed_to_finish;
regcache_xfree (stop_registers);
stop_registers = inf_status->stop_registers;
if (target_has_execution)
regcache_cpy (current_regcache, inf_status->registers);
regcache_xfree (inf_status->registers);
if (target_has_stack && inf_status->restore_stack_info)
{
if (catch_errors
(restore_selected_frame, &inf_status->selected_frame_id,
"Unable to restore previously selected frame:\n",
RETURN_MASK_ERROR) == 0)
select_frame (get_current_frame ());
}
xfree (inf_status);
}
static void
do_restore_inferior_status_cleanup (void *sts)
{
restore_inferior_status (sts);
}
struct cleanup *
make_cleanup_restore_inferior_status (struct inferior_status *inf_status)
{
return make_cleanup (do_restore_inferior_status_cleanup, inf_status);
}
void
discard_inferior_status (struct inferior_status *inf_status)
{
bpstat_clear (&inf_status->stop_bpstat);
regcache_xfree (inf_status->registers);
regcache_xfree (inf_status->stop_registers);
xfree (inf_status);
}
int
inferior_has_forked (int pid, int *child_pid)
{
struct target_waitstatus last;
ptid_t last_ptid;
get_last_target_status (&last_ptid, &last);
if (last.kind != TARGET_WAITKIND_FORKED)
return 0;
if (ptid_get_pid (last_ptid) != pid)
return 0;
*child_pid = last.value.related_pid;
return 1;
}
int
inferior_has_vforked (int pid, int *child_pid)
{
struct target_waitstatus last;
ptid_t last_ptid;
get_last_target_status (&last_ptid, &last);
if (last.kind != TARGET_WAITKIND_VFORKED)
return 0;
if (ptid_get_pid (last_ptid) != pid)
return 0;
*child_pid = last.value.related_pid;
return 1;
}
int
inferior_has_execd (int pid, char **execd_pathname)
{
struct target_waitstatus last;
ptid_t last_ptid;
get_last_target_status (&last_ptid, &last);
if (last.kind != TARGET_WAITKIND_EXECD)
return 0;
if (ptid_get_pid (last_ptid) != pid)
return 0;
*execd_pathname = xstrdup (last.value.execd_pathname);
return 1;
}
ptid_t null_ptid;
ptid_t minus_one_ptid;
ptid_t
ptid_build (int pid, long lwp, long tid)
{
ptid_t ptid;
ptid.pid = pid;
ptid.lwp = lwp;
ptid.tid = tid;
return ptid;
}
ptid_t
pid_to_ptid (int pid)
{
return ptid_build (pid, 0, 0);
}
int
ptid_get_pid (ptid_t ptid)
{
return ptid.pid;
}
long
ptid_get_lwp (ptid_t ptid)
{
return ptid.lwp;
}
long
ptid_get_tid (ptid_t ptid)
{
return ptid.tid;
}
int
ptid_equal (ptid_t ptid1, ptid_t ptid2)
{
return (ptid1.pid == ptid2.pid && ptid1.lwp == ptid2.lwp
&& ptid1.tid == ptid2.tid);
}
static void
restore_inferior_ptid (void *arg)
{
ptid_t *saved_ptid_ptr = arg;
inferior_ptid = *saved_ptid_ptr;
xfree (arg);
}
struct cleanup *
save_inferior_ptid (void)
{
ptid_t *saved_ptid_ptr;
saved_ptid_ptr = xmalloc (sizeof (ptid_t));
*saved_ptid_ptr = inferior_ptid;
return make_cleanup (restore_inferior_ptid, saved_ptid_ptr);
}
static void
build_infrun (void)
{
stop_registers = regcache_xmalloc (current_gdbarch);
}
void
_initialize_infrun (void)
{
int i;
int numsigs;
DEPRECATED_REGISTER_GDBARCH_SWAP (stop_registers);
deprecated_register_gdbarch_swap (NULL, 0, build_infrun);
add_info ("signals", signals_info, _("\
What debugger does when program gets various signals.\n\
Specify a signal as argument to print info on that signal only."));
add_info_alias ("handle", "signals", 0);
add_com ("handle", class_run, handle_command, _("\
Specify how to handle a signal.\n\
Args are signals and actions to apply to those signals.\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\
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."));
if (xdb_commands)
{
add_com ("lz", class_info, signals_info, _("\
What debugger does when program gets various signals.\n\
Specify a signal as argument to print info on that signal only."));
add_com ("z", class_run, xdb_handle_command, _("\
Specify how to handle a signal.\n\
Args are signals and actions to apply to those signals.\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\
Recognized actions include \"s\" (toggles between stop and nostop), \n\
\"r\" (toggles between print and noprint), \"i\" (toggles between pass and \
nopass), \"Q\" (noprint)\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."));
}
if (!dbx_commands)
stop_command = add_cmd ("stop", class_obscure,
not_just_help_class_command, _("\
There is no `stop' command, but you can set a hook on `stop'.\n\
This allows you to set a list of commands to be run each time execution\n\
of the program stops."), &cmdlist);
add_setshow_zinteger_cmd ("infrun", class_maintenance, &debug_infrun, _("\
Set inferior debugging."), _("\
Show inferior debugging."), _("\
When non-zero, inferior specific debugging is enabled."),
NULL,
show_debug_infrun,
&setdebuglist, &showdebuglist);
numsigs = (int) TARGET_SIGNAL_LAST;
signal_stop = (unsigned char *) xmalloc (sizeof (signal_stop[0]) * numsigs);
signal_print = (unsigned char *)
xmalloc (sizeof (signal_print[0]) * numsigs);
signal_program = (unsigned char *)
xmalloc (sizeof (signal_program[0]) * numsigs);
for (i = 0; i < numsigs; i++)
{
signal_stop[i] = 1;
signal_print[i] = 1;
signal_program[i] = 1;
}
signal_program[TARGET_SIGNAL_TRAP] = 0;
signal_program[TARGET_SIGNAL_INT] = 0;
signal_stop[TARGET_SIGNAL_ALRM] = 0;
signal_print[TARGET_SIGNAL_ALRM] = 0;
signal_stop[TARGET_SIGNAL_VTALRM] = 0;
signal_print[TARGET_SIGNAL_VTALRM] = 0;
signal_stop[TARGET_SIGNAL_PROF] = 0;
signal_print[TARGET_SIGNAL_PROF] = 0;
signal_stop[TARGET_SIGNAL_CHLD] = 0;
signal_print[TARGET_SIGNAL_CHLD] = 0;
signal_stop[TARGET_SIGNAL_IO] = 0;
signal_print[TARGET_SIGNAL_IO] = 0;
signal_stop[TARGET_SIGNAL_POLL] = 0;
signal_print[TARGET_SIGNAL_POLL] = 0;
signal_stop[TARGET_SIGNAL_URG] = 0;
signal_print[TARGET_SIGNAL_URG] = 0;
signal_stop[TARGET_SIGNAL_WINCH] = 0;
signal_print[TARGET_SIGNAL_WINCH] = 0;
signal_stop[TARGET_SIGNAL_LWP] = 0;
signal_print[TARGET_SIGNAL_LWP] = 0;
signal_stop[TARGET_SIGNAL_WAITING] = 0;
signal_print[TARGET_SIGNAL_WAITING] = 0;
signal_stop[TARGET_SIGNAL_CANCEL] = 0;
signal_print[TARGET_SIGNAL_CANCEL] = 0;
add_setshow_zinteger_cmd ("stop-on-solib-events", class_support,
&stop_on_solib_events, _("\
Set stopping for shared library events."), _("\
Show stopping for shared library events."), _("\
If nonzero, gdb will give control to the user when the dynamic linker\n\
notifies gdb of shared library events. The most common event of interest\n\
to the user would be loading/unloading of a new library."),
NULL,
show_stop_on_solib_events,
&setlist, &showlist);
add_setshow_enum_cmd ("follow-fork-mode", class_run,
follow_fork_mode_kind_names,
&follow_fork_mode_string, _("\
Set debugger response to a program call of fork or vfork."), _("\
Show debugger response to a program call of fork or vfork."), _("\
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\
The unfollowed process will continue to run.\n\
By default, the debugger will follow the parent process."),
NULL,
show_follow_fork_mode_string,
&setlist, &showlist);
add_setshow_enum_cmd ("scheduler-locking", class_run,
scheduler_enums, &scheduler_mode, _("\
Set mode for locking scheduler during execution."), _("\
Show mode for locking scheduler during execution."), _("\
off == no locking (threads may preempt at any time)\n\
on == full locking (no thread except the current thread may run)\n\
step == scheduler locked during every single-step operation.\n\
In this mode, no other thread may run during a step command.\n\
Other threads may run while stepping over a function call ('next')."),
set_schedlock_func,
show_scheduler_mode,
&setlist, &showlist);
scheduler_run_this_ptid (minus_one_ptid);
add_setshow_boolean_cmd ("step-mode", class_run, &step_stop_if_no_debug, _("\
Set mode of the step operation."), _("\
Show mode of the step operation."), _("\
When set, doing a step over a function without debug line information\n\
will stop at the first instruction of that function. Otherwise, the\n\
function is skipped and the step command stops at a different source line."),
NULL,
show_step_stop_if_no_debug,
&setlist, &showlist);
null_ptid = ptid_build (0, 0, 0);
minus_one_ptid = ptid_build (-1, 0, 0);
inferior_ptid = null_ptid;
target_last_wait_ptid = minus_one_ptid;
}