#include "defs.h"
#include "gdb_string.h"
#include <ctype.h>
#include "symtab.h"
#include "frame.h"
#include "inferior.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 "objc-lang.h"
#include <signal.h>
#include "inf-loop.h"
#include "event-top.h"
#include "regcache.h"
#include "value.h"
int metrowerks_stepping = 0;
CORE_ADDR metrowerks_step_func_start = 0;
CORE_ADDR metrowerks_step_func_end = 0;
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 void delete_breakpoint_current_contents (void *);
static void set_follow_fork_mode_command (char *arg, int from_tty,
struct cmd_list_element *c);
static int restore_selected_frame (void *);
static void build_infrun (void);
static void follow_inferior_fork (int parent_pid, int child_pid,
int has_forked, int has_vforked);
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);
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;
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;
#ifndef DYNAMIC_TRAMPOLINE_NEXTPC
#define DYNAMIC_TRAMPOLINE_NEXTPC(pc) 0
#endif
#ifndef IN_SOLIB_DYNSYM_RESOLVE_CODE
#define IN_SOLIB_DYNSYM_RESOLVE_CODE(pc) 0
#endif
#ifndef SKIP_SOLIB_RESOLVER
#define SKIP_SOLIB_RESOLVER(pc) 0
#endif
#ifndef SOLIB_IN_DYNAMIC_LINKER
#define SOLIB_IN_DYNAMIC_LINKER(pid,pc) 0
#endif
#ifndef IGNORE_HELPER_CALL
#define IGNORE_HELPER_CALL(pc) 0
#endif
#ifndef INSTRUCTION_NULLIFIED
#define INSTRUCTION_NULLIFIED 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 HAVE_CONTINUABLE_WATCHPOINT
#define HAVE_CONTINUABLE_WATCHPOINT 0
#else
#undef HAVE_CONTINUABLE_WATCHPOINT
#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
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;
#ifdef SOLIB_ADD
static int stop_on_solib_events;
static struct breakpoint *solib_step_bp;
static struct breakpoint *solib_finish_bp;
#endif
#ifdef HP_OS_BUG
static int trap_expected_after_continue;
#endif
int stop_after_trap;
int stop_soon_quietly;
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 struct breakpoint *through_sigtramp_breakpoint = NULL;
static int number_of_threads_in_syscalls;
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_ask[] = "ask";
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_ask,
follow_fork_mode_child,
follow_fork_mode_parent,
NULL
};
static const char *follow_fork_mode_string = follow_fork_mode_parent;
static int
follow_fork (void)
{
const char *follow_mode = follow_fork_mode_string;
int follow_child = (follow_mode == follow_fork_mode_child);
if (follow_fork_mode_string == follow_fork_mode_ask)
{
internal_error (__FILE__, __LINE__,
"follow_inferior_fork: \"ask\" mode not implemented");
}
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;
through_sigtramp_breakpoint = 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));
#endif
insert_breakpoints ();
}
static int singlestep_breakpoints_inserted_p = 0;
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_mode = schedlock_off;
static const char *scheduler_enums[] = {
schedlock_off,
schedlock_on,
schedlock_step,
NULL
};
static struct ptid 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' cannot support this command.", target_shortname);
}
if (scheduler_mode == schedlock_on)
scheduler_lock_ptid = inferior_ptid;
else
scheduler_lock_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 ("Unknown 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 now schedlock mode: %d", new_mode);
}
set_schedlock_helper ();
return old_mode;
}
static void
set_schedlock_func (char *args, int from_tty, struct cmd_list_element *c)
{
if (cmd_type (c) == set_cmd)
{
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 (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;
}
#ifdef DO_DEFERRED_STORES
DO_DEFERRED_STORES;
#endif
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) &&
!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_lock_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;
step_over_calls = STEP_OVER_UNDEBUGGABLE;
stop_after_trap = 0;
stop_soon_quietly = 0;
proceed_to_finish = 0;
breakpoint_proceeded = 1;
bpstat_clear (&stop_bpstat);
}
void
proceed (CORE_ADDR addr, enum target_signal siggnal, int step)
{
int oneproc = 0;
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;
#ifndef STEP_SKIPS_DELAY
#define STEP_SKIPS_DELAY(pc) (0)
#define STEP_SKIPS_DELAY_P (0)
#endif
if (STEP_SKIPS_DELAY_P
&& breakpoint_here_p (read_pc () + 4)
&& STEP_SKIPS_DELAY (read_pc ()))
oneproc = 1;
}
else
{
write_pc (addr);
}
#ifdef PREPARE_TO_PROCEED
if (PREPARE_TO_PROCEED (1) && breakpoint_here_p (read_pc ()))
{
oneproc = 1;
}
#endif
#ifdef HP_OS_BUG
if (trap_expected_after_continue)
{
oneproc = 1;
trap_expected_after_continue = 0;
}
#endif
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);
resume (oneproc || step || bpstat_should_step (), stop_signal);
if (!event_loop_p || !target_can_async_p ())
{
wait_for_inferior ();
normal_stop ();
target_executing = 0;
}
}
static CORE_ADDR prev_pc;
static CORE_ADDR prev_func_start;
static char *prev_func_name;
void
start_remote (void)
{
init_thread_list ();
init_wait_for_inferior ();
stop_soon_quietly = 1;
trap_expected = 0;
wait_for_inferior ();
normal_stop ();
}
void
init_wait_for_inferior (void)
{
prev_pc = 0;
prev_func_start = 0;
prev_func_name = NULL;
#ifdef HP_OS_BUG
trap_expected_after_continue = 0;
#endif
breakpoints_inserted = 0;
breakpoint_init_inferior (inf_starting);
stop_signal = TARGET_SIGNAL_0;
pending_follow.kind = TARGET_WAITKIND_SPURIOUS;
number_of_threads_in_syscalls = 0;
scheduler_lock_ptid = minus_one_ptid;
clear_proceed_status ();
}
static void
delete_breakpoint_current_contents (void *arg)
{
struct breakpoint **breakpointp = (struct breakpoint **) arg;
if (*breakpointp != NULL)
{
delete_breakpoint (*breakpointp);
*breakpointp = NULL;
}
}
enum infwait_states
{
infwait_normal_state,
infwait_thread_hop_state,
infwait_nullified_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 remove_breakpoints_on_following_step;
int current_line;
struct symtab *current_symtab;
int handling_longjmp;
ptid_t ptid;
ptid_t saved_inferior_ptid;
int update_step_sp;
int stepping_through_solib_after_catch;
bpstat stepping_through_solib_catchpoints;
int enable_hw_watchpoints_after_wait;
int stepping_through_sigtramp;
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 check_sigtramp2 (struct execution_control_state *ecs);
static void step_into_function (struct execution_control_state *ecs);
static void step_over_function (struct execution_control_state *ecs);
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;
old_cleanups = make_cleanup (delete_step_resume_breakpoint,
&step_resume_breakpoint);
make_cleanup (delete_breakpoint_current_contents,
&through_sigtramp_breakpoint);
ecs = &ecss;
init_execution_control_state (ecs);
previous_inferior_ptid = inferior_ptid;
overlay_cache_invalid = 1;
registers_changed ();
while (1)
{
if (target_wait_hook)
ecs->ptid = 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);
make_exec_cleanup (delete_breakpoint_current_contents,
&through_sigtramp_breakpoint);
init_execution_control_state (async_ecs);
previous_inferior_ptid = inferior_ptid;
overlay_cache_invalid = 1;
registers_changed ();
}
if (target_wait_hook)
async_ecs->ptid =
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);
if (metrowerks_stepping)
{
metrowerks_stepping = 0;
metrowerks_step_func_start = 0;
metrowerks_step_func_end = 0;
}
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->remove_breakpoints_on_following_step = 0;
ecs->handling_longjmp = 0;
ecs->update_step_sp = 0;
ecs->stepping_through_solib_after_catch = 0;
ecs->stepping_through_solib_catchpoints = NULL;
ecs->enable_hw_watchpoints_after_wait = 0;
ecs->stepping_through_sigtramp = 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->wp = &(ecs->ws);
}
static void
check_for_old_step_resume_breakpoint (void)
{
if (step_resume_breakpoint)
warning
("GDB bug: infrun.c (wait_for_inferior): dropping old step_resume breakpoint");
}
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,
prev_func_start, prev_func_name,
trap_expected, step_resume_breakpoint,
through_sigtramp_breakpoint, step_range_start,
step_range_end, &step_frame_id,
ecs->handling_longjmp, ecs->another_trap,
ecs->stepping_through_solib_after_catch,
ecs->stepping_through_solib_catchpoints,
ecs->stepping_through_sigtramp,
ecs->current_line, ecs->current_symtab, step_sp);
load_infrun_state (ecs->ptid, &prev_pc,
&prev_func_start, &prev_func_name,
&trap_expected, &step_resume_breakpoint,
&through_sigtramp_breakpoint, &step_range_start,
&step_range_end, &step_frame_id,
&ecs->handling_longjmp, &ecs->another_trap,
&ecs->stepping_through_solib_after_catch,
&ecs->stepping_through_solib_catchpoints,
&ecs->stepping_through_sigtramp,
&ecs->current_line, &ecs->current_symtab, &step_sp);
}
inferior_ptid = ecs->ptid;
}
void
handle_inferior_event (struct execution_control_state *ecs)
{
CORE_ADDR tmp;
CORE_ADDR new_stop;
int stepped_after_stopped_by_watchpoint;
int sw_single_step_trap_p = 0;
target_last_wait_ptid = ecs->ptid;
target_last_waitstatus = *ecs->wp;
switch (ecs->infwait_state)
{
case infwait_thread_hop_state:
ecs->waiton_ptid = pid_to_ptid (-1);
case infwait_normal_state:
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_nullified_state:
break;
case infwait_nonstep_watch_state:
insert_breakpoints ();
stepped_after_stopped_by_watchpoint = 1;
break;
}
ecs->infwait_state = infwait_normal_state;
flush_cached_frames ();
ecs->new_thread_event = (!ptid_equal (ecs->ptid, inferior_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");
#if 0
target_resume (RESUME_ALL, 0, TARGET_SIGNAL_0);
prepare_to_wait (ecs);
return;
#endif
}
switch (ecs->ws.kind)
{
case TARGET_WAITKIND_LOADED:
#ifdef SOLIB_ADD
if (!stop_soon_quietly)
{
if (breakpoints_inserted)
remove_breakpoints ();
target_terminal_ours_for_output ();
SOLIB_ADD (NULL, 0, NULL, 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:
resume (0, TARGET_SIGNAL_0);
prepare_to_wait (ecs);
return;
case TARGET_WAITKIND_EXITED:
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:
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:
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 ();
stop_bpstat = bpstat_stop_status (&stop_pc, 1);
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:
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);
ecs->saved_inferior_ptid = inferior_ptid;
inferior_ptid = ecs->ptid;
stop_bpstat = bpstat_stop_status (&stop_pc, 1);
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:
number_of_threads_in_syscalls++;
if (number_of_threads_in_syscalls == 1)
{
TARGET_DISABLE_HW_WATCHPOINTS (PIDGET (inferior_ptid));
}
resume (0, TARGET_SIGNAL_0);
prepare_to_wait (ecs);
return;
case TARGET_WAITKIND_SYSCALL_RETURN:
target_resume (ecs->ptid, 1, TARGET_SIGNAL_0);
if (number_of_threads_in_syscalls > 0)
{
number_of_threads_in_syscalls--;
ecs->enable_hw_watchpoints_after_wait =
(number_of_threads_in_syscalls == 0);
}
prepare_to_wait (ecs);
return;
case TARGET_WAITKIND_STOPPED:
stop_signal = ecs->ws.value.sig;
break;
case TARGET_WAITKIND_IGNORE:
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_signal == TARGET_SIGNAL_TRAP)
{
if (breakpoints_inserted
&& breakpoint_here_p (stop_pc - DECR_PC_AFTER_BREAK))
{
ecs->random_signal = 0;
if (!breakpoint_thread_match (stop_pc - DECR_PC_AFTER_BREAK,
ecs->ptid))
{
int remove_status;
if (DECR_PC_AFTER_BREAK)
write_pc_pid (stop_pc - DECR_PC_AFTER_BREAK, ecs->ptid);
remove_status = remove_breakpoints ();
if (remove_status != 0)
{
write_pc_pid (stop_pc - DECR_PC_AFTER_BREAK + 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)
{
if (DECR_PC_AFTER_BREAK)
{
stop_pc -= DECR_PC_AFTER_BREAK;
write_pc_pid (stop_pc, ecs->ptid);
}
sw_single_step_trap_p = 1;
ecs->random_signal = 0;
}
}
else
ecs->random_signal = 1;
if (!ptid_equal (ecs->ptid, inferior_ptid) &&
(pending_follow.kind == TARGET_WAITKIND_SPURIOUS))
{
int printed = 0;
if (ecs->random_signal && signal_print[stop_signal])
{
#if 0
printed = 1;
target_terminal_ours_for_output ();
printf_filtered ("\nProgram received signal %s, %s.\n",
target_signal_to_name (stop_signal),
target_signal_to_string (stop_signal));
gdb_flush (gdb_stdout);
#endif
}
if (stop_signal != TARGET_SIGNAL_TRAP && !signal_stop[stop_signal])
{
if (printed)
target_terminal_inferior ();
if (signal_program[stop_signal] == 0)
stop_signal = TARGET_SIGNAL_0;
target_resume (ecs->ptid, 0, stop_signal);
prepare_to_wait (ecs);
return;
}
context_switch (ecs);
if (context_hook)
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 (INSTRUCTION_NULLIFIED)
{
registers_changed ();
target_resume (ecs->ptid, 1, TARGET_SIGNAL_0);
ecs->infwait_state = infwait_nullified_state;
ecs->waiton_ptid = ecs->ptid;
ecs->wp = &(ecs->tmpstatus);
prepare_to_wait (ecs);
return;
}
if (HAVE_STEPPABLE_WATCHPOINT && STOPPED_BY_WATCHPOINT (ecs->ws))
{
resume (1, 0);
prepare_to_wait (ecs);
return;
}
if (HAVE_NONSTEPPABLE_WATCHPOINT && STOPPED_BY_WATCHPOINT (ecs->ws))
{
#if 0
if (DECR_PC_AFTER_BREAK)
write_pc (stop_pc - DECR_PC_AFTER_BREAK);
#endif
remove_breakpoints ();
registers_changed ();
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 (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 += 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
|| (breakpoints_inserted &&
(stop_signal == TARGET_SIGNAL_ILL
|| stop_signal == TARGET_SIGNAL_EMT)) || stop_soon_quietly)
{
if (stop_signal == TARGET_SIGNAL_TRAP && stop_after_trap)
{
stop_print_frame = 0;
stop_stepping (ecs);
return;
}
if (stop_soon_quietly)
{
stop_stepping (ecs);
return;
}
if (stop_signal == TARGET_SIGNAL_TRAP && trap_expected
&& through_sigtramp_breakpoint == NULL)
bpstat_clear (&stop_bpstat);
else
{
stop_bpstat =
bpstat_stop_status
(&stop_pc,
sw_single_step_trap_p
|| (currently_stepping (ecs)
&& prev_pc != stop_pc - DECR_PC_AFTER_BREAK
&& !(step_range_end
&& INNER_THAN (read_sp (), (step_sp - 16)))));
stop_print_frame = 1;
}
if (stop_signal == TARGET_SIGNAL_TRAP)
ecs->random_signal
= !(bpstat_explains_signal (stop_bpstat)
|| trap_expected
|| (!CALL_DUMMY_BREAKPOINT_OFFSET_P
&& DEPRECATED_PC_IN_CALL_DUMMY (stop_pc, read_sp (),
get_frame_base (get_current_frame ())))
|| (step_range_end && step_resume_breakpoint == NULL));
else
{
ecs->random_signal = !(bpstat_explains_signal (stop_bpstat)
|| (!CALL_DUMMY_BREAKPOINT_OFFSET_P
&& DEPRECATED_PC_IN_CALL_DUMMY (stop_pc, read_sp (),
get_frame_base
(get_current_frame
()))));
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;
stopped_by_random_signal = 1;
if (signal_print[stop_signal])
{
printed = 1;
target_terminal_ours_for_output ();
print_stop_reason (SIGNAL_RECEIVED, stop_signal);
}
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;
check_sigtramp2 (ecs);
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;
#ifdef HP_OS_BUG
trap_expected_after_continue = 1;
#endif
}
switch (what.main_action)
{
case BPSTAT_WHAT_SET_LONGJMP_RESUME:
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);
}
if (through_sigtramp_breakpoint != NULL)
{
delete_breakpoint (through_sigtramp_breakpoint);
through_sigtramp_breakpoint = NULL;
}
#if 0
if (step_over_calls > 0)
set_longjmp_resume_breakpoint (jmp_buf_pc, get_current_frame ());
else
#endif
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:
remove_breakpoints ();
breakpoints_inserted = 0;
#if 0
if (step_over_calls
&& (frame_id_inner (get_frame_id (get_current_frame ()),
step_frame_id)))
{
ecs->another_trap = 1;
keep_going (ecs);
return;
}
#endif
disable_longjmp_breakpoint ();
ecs->handling_longjmp = 0;
if (what.main_action == BPSTAT_WHAT_CLEAR_LONGJMP_RESUME)
break;
case BPSTAT_WHAT_SINGLE:
if (breakpoints_inserted)
{
remove_breakpoints ();
}
breakpoints_inserted = 0;
ecs->another_trap = 1;
break;
case BPSTAT_WHAT_STOP_NOISY:
stop_print_frame = 1;
stop_stepping (ecs);
return;
case BPSTAT_WHAT_STOP_SILENT:
stop_print_frame = 0;
stop_stepping (ecs);
return;
case BPSTAT_WHAT_STEP_RESUME:
if (step_resume_breakpoint == NULL)
{
step_resume_breakpoint =
bpstat_find_step_resume_breakpoint (stop_bpstat);
}
delete_step_resume_breakpoint (&step_resume_breakpoint);
break;
case BPSTAT_WHAT_THROUGH_SIGTRAMP:
if (through_sigtramp_breakpoint)
delete_breakpoint (through_sigtramp_breakpoint);
through_sigtramp_breakpoint = NULL;
if (trap_expected)
ecs->another_trap = 1;
break;
case BPSTAT_WHAT_CHECK_SHLIBS:
case BPSTAT_WHAT_CHECK_SHLIBS_RESUME_FROM_HOOK:
#ifdef SOLIB_ADD
{
int was_sync_execution = 0;
int solib_changed = 0;
if (breakpoints_inserted)
remove_breakpoints ();
breakpoints_inserted = 0;
was_sync_execution = sync_execution;
target_terminal_ours_for_output ();
solib_changed = SOLIB_ADD (NULL, 0, NULL, auto_solib_add);
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)
{
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->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->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;
}
}
#endif
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))
{
ecs->another_trap = 1;
keep_going (ecs);
return;
}
#endif
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 (!CALL_DUMMY_BREAKPOINT_OFFSET_P)
{
if (CALL_DUMMY_HAS_COMPLETED (stop_pc, read_sp (),
get_frame_base (get_current_frame ()))
&& !step_range_end)
{
stop_print_frame = 0;
stop_stack_dummy = 1;
#ifdef HP_OS_BUG
trap_expected_after_continue = 1;
#endif
stop_stepping (ecs);
return;
}
}
if (step_resume_breakpoint)
{
check_sigtramp2 (ecs);
keep_going (ecs);
return;
}
if (step_range_end == 0)
{
check_sigtramp2 (ecs);
keep_going (ecs);
return;
}
if (stop_pc >= step_range_start && stop_pc < step_range_end)
{
check_sigtramp2 (ecs);
if (metrowerks_stepping)
{
struct frame_id current_frame_id = get_frame_id (get_current_frame ());
if (! frame_id_eq (step_frame_id, current_frame_id))
step_frame_id = current_frame_id;
}
keep_going (ecs);
return;
}
if (step_over_calls == STEP_OVER_UNDEBUGGABLE
&& IN_SOLIB_DYNSYM_RESOLVE_CODE (stop_pc))
{
CORE_ADDR pc_after_resolver = SKIP_SOLIB_RESOLVER (stop_pc);
if (pc_after_resolver)
{
struct symtab_and_line sr_sal;
init_sal (&sr_sal);
sr_sal.pc = pc_after_resolver;
check_for_old_step_resume_breakpoint ();
step_resume_breakpoint =
set_momentary_breakpoint (sr_sal, null_frame_id, bp_step_resume);
if (breakpoints_inserted)
insert_breakpoints ();
}
keep_going (ecs);
return;
}
ecs->update_step_sp = 1;
if (PC_IN_SIGTRAMP (stop_pc, ecs->stop_func_name)
&& !PC_IN_SIGTRAMP (prev_pc, prev_func_name)
&& INNER_THAN (read_sp (), step_sp))
{
{
struct frame_id current_frame = get_frame_id (get_current_frame ());
if (frame_id_inner (current_frame, step_frame_id))
{
struct symtab_and_line sr_sal;
init_sal (&sr_sal);
sr_sal.symtab = NULL;
sr_sal.line = 0;
sr_sal.pc = prev_pc;
check_for_old_step_resume_breakpoint ();
step_resume_breakpoint =
set_momentary_breakpoint (sr_sal, null_frame_id, bp_step_resume);
if (breakpoints_inserted)
insert_breakpoints ();
}
else
{
find_pc_partial_function (stop_pc, &ecs->stop_func_name,
&ecs->stop_func_start,
&ecs->stop_func_end);
step_range_start = ecs->stop_func_start;
step_range_end = ecs->stop_func_end;
ecs->stepping_through_sigtramp = 1;
}
}
if (step_range_end == 1)
step_range_end = (step_range_start = prev_pc) + 1;
ecs->remove_breakpoints_on_following_step = 1;
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;
}
if (metrowerks_stepping)
{
if (stop_pc == step_range_end
|| ((metrowerks_step_func_start != 0)
&& (metrowerks_step_func_start < stop_pc
&& stop_pc <= metrowerks_step_func_end)))
{
stop_step = 1;
print_stop_reason (END_STEPPING_RANGE, 0);
stop_stepping (ecs);
return;
}
}
if (stop_pc == ecs->stop_func_start
|| ((stop_pc != ADDR_BITS_REMOVE (SAVED_PC_AFTER_CALL (get_current_frame ())))
&& (((in_prologue (stop_pc, ecs->stop_func_start) &&
!IN_SOLIB_RETURN_TRAMPOLINE (stop_pc, ecs->stop_func_name))
|| IN_SOLIB_CALL_TRAMPOLINE (stop_pc, ecs->stop_func_name)
|| (!metrowerks_stepping && ecs->stop_func_name == 0)))))
{
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 || IGNORE_HELPER_CALL (stop_pc))
{
if (PC_IN_SIGTRAMP (stop_pc, ecs->stop_func_name)
&& frame_id_inner (step_frame_id,
frame_id_build (read_sp (), 0)))
step_frame_id = null_frame_id;
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;
}
step_over_function (ecs);
keep_going (ecs);
return;
}
tmp = SKIP_TRAMPOLINE_CODE (stop_pc);
if (tmp != 0)
ecs->stop_func_start = tmp;
else
{
tmp = DYNAMIC_TRAMPOLINE_NEXTPC (stop_pc);
if (tmp)
{
struct symtab_and_line xxx;
init_sal (&xxx);
xxx.pc = tmp;
xxx.section = find_pc_overlay (xxx.pc);
check_for_old_step_resume_breakpoint ();
step_resume_breakpoint =
set_momentary_breakpoint (xxx, null_frame_id, bp_step_resume);
insert_breakpoints ();
keep_going (ecs);
return;
}
}
if (tmp)
find_objc_msgcall (tmp, &new_stop);
else
find_objc_msgcall (stop_pc, &new_stop);
if (new_stop)
ecs->stop_func_start = new_stop;
if (new_stop)
{
tmp = SKIP_TRAMPOLINE_CODE (new_stop);
if (tmp != 0)
ecs->stop_func_start = tmp;
}
{
struct symtab_and_line tmp_sal;
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;
}
step_over_function (ecs);
keep_going (ecs);
return;
}
ecs->sal = find_pc_line (stop_pc, 0);
if (step_range_end == 1)
{
stop_step = 1;
print_stop_reason (END_STEPPING_RANGE, 0);
stop_stepping (ecs);
return;
}
if (IN_SOLIB_RETURN_TRAMPOLINE (stop_pc, ecs->stop_func_name))
{
CORE_ADDR tmp;
tmp = SKIP_TRAMPOLINE_CODE (stop_pc);
if (tmp)
{
struct symtab_and_line sr_sal;
init_sal (&sr_sal);
sr_sal.pc = tmp;
sr_sal.section = find_pc_overlay (sr_sal.pc);
check_for_old_step_resume_breakpoint ();
step_resume_breakpoint =
set_momentary_breakpoint (sr_sal, null_frame_id, bp_step_resume);
if (breakpoints_inserted)
insert_breakpoints ();
keep_going (ecs);
return;
}
}
if (ecs->sal.line == 0)
{
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))
{
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)
{
stop_step = 1;
print_stop_reason (END_STEPPING_RANGE, 0);
stop_stepping (ecs);
return;
}
if (metrowerks_stepping)
{
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;
step_frame_id = get_frame_id (get_current_frame ());
ecs->current_line = ecs->sal.line;
ecs->current_symtab = ecs->sal.symtab;
{
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;
}
keep_going (ecs);
}
static int
currently_stepping (struct execution_control_state *ecs)
{
return ((through_sigtramp_breakpoint == NULL
&& !ecs->handling_longjmp
&& ((step_range_end && step_resume_breakpoint == NULL)
|| trap_expected))
|| ecs->stepping_through_solib_after_catch
|| bpstat_should_step ());
}
static void
check_sigtramp2 (struct execution_control_state *ecs)
{
if (trap_expected
&& PC_IN_SIGTRAMP (stop_pc, ecs->stop_func_name)
&& !PC_IN_SIGTRAMP (prev_pc, prev_func_name)
&& INNER_THAN (read_sp (), step_sp))
{
struct symtab_and_line sr_sal;
init_sal (&sr_sal);
sr_sal.pc = prev_pc;
sr_sal.section = find_pc_overlay (sr_sal.pc);
through_sigtramp_breakpoint =
set_momentary_breakpoint (sr_sal, null_frame_id, bp_through_sigtramp);
if (breakpoints_inserted)
insert_breakpoints ();
ecs->remove_breakpoints_on_following_step = 1;
ecs->another_trap = 1;
}
}
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);
#ifdef PROLOGUE_FIRSTLINE_OVERLAP
#else
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;
#endif
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);
check_for_old_step_resume_breakpoint ();
step_resume_breakpoint =
set_momentary_breakpoint (sr_sal, null_frame_id, bp_step_resume);
if (breakpoints_inserted)
insert_breakpoints ();
step_range_end = step_range_start;
}
keep_going (ecs);
}
static void
step_over_function (struct execution_control_state *ecs)
{
struct symtab_and_line sr_sal;
init_sal (&sr_sal);
sr_sal.pc = ADDR_BITS_REMOVE (SAVED_PC_AFTER_CALL (get_current_frame ()));
sr_sal.section = find_pc_overlay (sr_sal.pc);
check_for_old_step_resume_breakpoint ();
step_resume_breakpoint =
set_momentary_breakpoint (sr_sal, get_frame_id (get_current_frame ()),
bp_step_resume);
if (frame_id_p (step_frame_id)
&& !IN_SOLIB_DYNSYM_RESOLVE_CODE (sr_sal.pc))
step_resume_breakpoint->frame_id = step_frame_id;
if (breakpoints_inserted)
insert_breakpoints ();
}
static void
stop_stepping (struct execution_control_state *ecs)
{
if (target_has_execution)
{
prev_pc = read_pc ();
prev_func_start = ecs->stop_func_start;
prev_func_name = ecs->stop_func_name;
}
ecs->wait_some_more = 0;
}
static void
keep_going (struct execution_control_state *ecs)
{
prev_pc = read_pc ();
prev_func_start = ecs->stop_func_start;
prev_func_name = ecs->stop_func_name;
if (ecs->update_step_sp)
step_sp = read_sp ();
ecs->update_step_sp = 0;
if (trap_expected && stop_signal != TARGET_SIGNAL_TRAP)
{
resume (currently_stepping (ecs), stop_signal);
}
else
{
if (step_resume_breakpoint == NULL
&& through_sigtramp_breakpoint == NULL
&& ecs->remove_breakpoints_on_following_step)
{
ecs->remove_breakpoints_on_following_step = 0;
remove_breakpoints ();
breakpoints_inserted = 0;
}
else if (!breakpoints_inserted &&
(through_sigtramp_breakpoint != NULL || !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;
#ifdef SHIFT_INST_REGS
if (!bpstat_explains_signal (stop_bpstat)
&& (stop_signal != TARGET_SIGNAL_CHLD) && !stopped_by_random_signal)
SHIFT_INST_REGS ();
#endif
resume (currently_stepping (ecs), stop_signal);
}
prepare_to_wait (ecs);
}
static void
prepare_to_wait (struct execution_control_state *ecs)
{
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))
ui_out_field_string (uiout, "reason", "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", "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", "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", "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", "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
normal_stop (void)
{
if (!ptid_equal (previous_inferior_ptid, inferior_ptid)
&& target_has_execution)
{
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 ");
printf_filtered ("program is no longer writable.\n");
printf_filtered ("It might be running in another process.\n");
printf_filtered ("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 (stop_command)
catch_errors (hook_stop_stub, stop_command,
"Error while running hook_stop:\n", RETURN_MASK_ALL);
if (!target_has_stack)
{
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))
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 (deprecated_selected_frame, -1, source_flag);
do_displays ();
}
}
if (proceed_to_finish)
regcache_cpy (stop_registers, current_regcache);
if (stop_stack_dummy)
{
frame_pop (get_current_frame ());
stop_pc = read_pc ();
select_frame (get_current_frame ());
}
done:
breakpoint_auto_delete (stop_bpstat);
annotate_stopped ();
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 ();
}
}
}
static int
hook_stop_stub (void *cmd)
{
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
{
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 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_quietly;
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_RAW_SIZE (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->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_quietly = stop_soon_quietly;
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);
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.\n");
return 0;
}
select_frame (frame);
return (1);
}
void
restore_inferior_status (struct inferior_status *inf_status)
{
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;
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_quietly = inf_status->stop_soon_quietly;
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)
{
register int i;
register int numsigs;
struct cmd_list_element *c;
register_gdbarch_swap (&stop_registers, sizeof (stop_registers), NULL);
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,
concat ("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.", NULL));
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,
concat ("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.", NULL));
}
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);
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;
#ifdef SOLIB_ADD
add_show_from_set
(add_set_cmd ("stop-on-solib-events", class_support, var_zinteger,
(char *) &stop_on_solib_events,
"Set stopping for shared library events.\n\
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.\n", &setlist), &showlist);
#endif
c = add_set_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.\n\
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\
ask - the debugger will ask for one of the above choices\n\
For \"parent\" or \"child\", the unfollowed process will run free.\n\
By default, the debugger will follow the parent process.", &setlist);
add_show_from_set (c, &showlist);
c = add_set_enum_cmd ("scheduler-locking", class_run, scheduler_enums,
&scheduler_mode,
"Set mode for locking scheduler during execution.\n\
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').", &setlist);
set_cmd_sfunc (c, set_schedlock_func);
add_show_from_set (c, &showlist);
scheduler_lock_ptid = minus_one_ptid;
c = add_set_cmd ("step-mode", class_run,
var_boolean, (char *) &step_stop_if_no_debug,
"Set mode of the step operation. When set, doing a step over a\n\
function without debug line information will stop at the first\n\
instruction of that function. Otherwise, the function is skipped and\n\
the step command stops at a different source line.", &setlist);
add_show_from_set (c, &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;
}