#include "symtab.h"
#include "frame.h"
#include "inferior.h"
+#include "exceptions.h"
#include "breakpoint.h"
#include "gdb_wait.h"
#include "gdbcore.h"
#include "value.h"
#include "observer.h"
#include "language.h"
+#include "solib.h"
+
#include "gdb_assert.h"
+#include "mi/mi-common.h"
/* Prototypes for local functions */
no line number information. The normal behavior is that we step
over such function. */
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);
+}
/* In asynchronous mode, but simulating synchronous execution. */
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);
+}
+
/* If the program uses ELF-style shared libraries, then calls to
functions in shared libraries go through stubs, which live in a
table called the PLT (Procedure Linkage Table). The first time the
signalling an error, which will obscure the change in the
inferior's state. */
-#ifndef IN_SOLIB_DYNSYM_RESOLVE_CODE
-#define IN_SOLIB_DYNSYM_RESOLVE_CODE(pc) 0
-#endif
-
/* This function returns TRUE if pc is the address of an instruction
that lies within the dynamic linker (such as the event hook, or the
dld itself).
#define SOLIB_IN_DYNAMIC_LINKER(pid,pc) 0
#endif
-/* On some systems, the PC may be left pointing at an instruction that won't
- actually be executed. This is usually indicated by a bit in the PSW. If
- we find ourselves in such a state, then we step the target beyond the
- nullified instruction before returning control to the user so as to avoid
- confusion. */
-
-#ifndef INSTRUCTION_NULLIFIED
-#define INSTRUCTION_NULLIFIED 0
-#endif
-
/* We can't step off a permanent breakpoint in the ordinary way, because we
can't remove it. Instead, we have to advance the PC to the next
instruction. This macro should expand to a pointer to a function that
static void
default_skip_permanent_breakpoint (void)
{
- error ("\
+ 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.");
+a command like `return' or `jump' to continue execution."));
}
#endif
static int trap_expected;
-#ifdef SOLIB_ADD
/* Nonzero if we want to give control to the user when we're notified
of shared library events by the dynamic linker. */
static int stop_on_solib_events;
-#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);
+}
/* Nonzero means expecting a trace trap
and should stop the inferior and return silently when it happens. */
static struct breakpoint *step_resume_breakpoint = NULL;
-/* On some platforms (e.g., HP-UX), hardware watchpoints have bad
- interactions with an inferior that is running a kernel function
- (aka, a system call or "syscall"). wait_for_inferior therefore
- may have a need to know when the inferior is in a syscall. This
- is a count of the number of inferior threads which are known to
- currently be running in a syscall. */
-static int number_of_threads_in_syscalls;
-
/* This is a cached copy of the pid/waitstatus of the last event
returned by target_wait()/deprecated_target_wait_hook(). This
information is returned by get_last_target_status(). */
};
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);
+}
\f
static int
step_range_end = 0;
/* What is this a.out's name? */
- printf_unfiltered ("Executing new program: %s\n", execd_pathname);
+ printf_unfiltered (_("Executing new program: %s\n"), execd_pathname);
/* We've followed the inferior through an exec. Therefore, the
inferior has essentially been killed & reborn. */
tgt = find_run_target ();
/* If we can't find one, things are in a very strange state... */
if (tgt == NULL)
- error ("Could find run target to save before following exec");
+ error (_("Could find run target to save before following exec"));
gdb_flush (gdb_stdout);
target_mourn_inferior ();
#endif
#ifdef SOLIB_CREATE_INFERIOR_HOOK
SOLIB_CREATE_INFERIOR_HOOK (PIDGET (inferior_ptid));
+#else
+ solib_create_inferior_hook ();
#endif
/* Reinsert all breakpoints. (Those which were symbolic have
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 const char *scheduler_mode = schedlock_off;
+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)
{
- /* NOTE: cagney/2002-03-17: The deprecated_add_show_from_set()
- function clones the set command passed as a parameter. The clone
- operation will include (BUG?) any ``set'' command callback, if
- present. Commands like ``info set'' call all the ``show''
- command callbacks. Unfortunately, for ``show'' commands cloned
- from ``set'', this includes callbacks belonging to ``set''
- commands. Making this worse, this only occures if
- deprecated_add_show_from_set() is called after add_cmd_sfunc()
- (BUG?). */
- if (cmd_type (c) == set_cmd)
- if (!target_can_lock_scheduler)
- {
- scheduler_mode = schedlock_off;
- error ("Target '%s' cannot support this command.", target_shortname);
- }
+ if (!target_can_lock_scheduler)
+ {
+ scheduler_mode = schedlock_off;
+ error (_("Target '%s' cannot support this command."), target_shortname);
+ }
}
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);
+
/* FIXME: calling breakpoint_here_p (read_pc ()) three times! */
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);
+
/* In a multi-threaded task we may select another thread
and then continue or step.
/* The first resume is not following a fork/vfork/exec. */
pending_follow.kind = TARGET_WAITKIND_SPURIOUS; /* I.e., none. */
- /* See wait_for_inferior's handling of SYSCALL_ENTRY/RETURN events. */
- number_of_threads_in_syscalls = 0;
-
clear_proceed_status ();
stepping_past_singlestep_breakpoint = 0;
{
infwait_normal_state,
infwait_thread_hop_state,
- infwait_nullified_state,
infwait_nonstep_watch_state
};
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;
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);
void
init_execution_control_state (struct execution_control_state *ecs)
{
- /* ecs->another_trap? */
+ ecs->another_trap = 0;
ecs->random_signal = 0;
ecs->step_after_step_resume_breakpoint = 0;
ecs->handling_longjmp = 0; /* FIXME */
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;
/* When using hardware single-step, a SIGTRAP is reported for
both a completed single-step and a software breakpoint. Need
to differentiate between the two as the latter needs
- adjusting but the former does not. */
- if (currently_stepping (ecs))
+ adjusting but the former does not.
+
+ When the thread to be examined does not match the current thread
+ context we can't use currently_stepping, so assume no
+ single-stepping in this case. */
+ if (ptid_equal (ecs->ptid, inferior_ptid) && currently_stepping (ecs))
{
if (prev_pc == breakpoint_pc
&& software_breakpoint_inserted_here_p (breakpoint_pc))
void
handle_inferior_event (struct execution_control_state *ecs)
{
- /* NOTE: cagney/2003-03-28: If you're looking at this code and
- thinking that the variable stepped_after_stopped_by_watchpoint
- isn't used, then you're wrong! The macro STOPPED_BY_WATCHPOINT,
- defined in the file "config/pa/nm-hppah.h", accesses the variable
- indirectly. Mutter something rude about the HP merge. */
+ /* NOTE: bje/2005-05-02: If you're looking at this code and thinking
+ that the variable stepped_after_stopped_by_watchpoint isn't used,
+ then you're wrong! See remote.c:remote_stopped_data_address. */
+
int sw_single_step_trap_p = 0;
int stopped_by_watchpoint = -1; /* Mark as unknown. */
switch (ecs->infwait_state)
{
case infwait_thread_hop_state:
+ if (debug_infrun)
+ fprintf_unfiltered (gdb_stdlog, "infrun: infwait_thread_hop_state\n");
/* Cancel the waiton_ptid. */
ecs->waiton_ptid = pid_to_ptid (-1);
- /* See comments where a TARGET_WAITKIND_SYSCALL_RETURN event
- is serviced in this loop, below. */
- 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:
- /* See comments where a TARGET_WAITKIND_SYSCALL_RETURN event
- is serviced in this loop, below. */
- 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:
+ if (debug_infrun)
+ fprintf_unfiltered (gdb_stdlog, "infrun: infwait_normal_state\n");
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 ();
/* FIXME-maybe: is this cleaner than setting a flag? Does it
break;
default:
- internal_error (__FILE__, __LINE__, "bad switch");
+ internal_error (__FILE__, __LINE__, _("bad switch"));
}
ecs->infwait_state = infwait_normal_state;
switch (ecs->ws.kind)
{
case TARGET_WAITKIND_LOADED:
+ if (debug_infrun)
+ fprintf_unfiltered (gdb_stdlog, "infrun: TARGET_WAITKIND_LOADED\n");
/* Ignore gracefully during startup of the inferior, as it
might be the shell which has just loaded some objects,
otherwise add the symbols for the newly loaded objects. */
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 (); /* Must do this before mourn anyway */
print_stop_reason (EXITED, ecs->ws.value.integer);
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 (); /* Must do this before mourn anyway */
the above cases end in a continue or goto. */
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;
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;
/* NOTE drow/2002-12-05: This code should be pushed down into the
}
goto process_event_stop_test;
- /* These syscall events are returned on HP-UX, as part of its
- implementation of page-protection-based "hardware" watchpoints.
- HP-UX has unfortunate interactions between page-protections and
- some system calls. Our solution is to disable hardware watches
- when a system call is entered, and reenable them when the syscall
- completes. The downside of this is that we may miss the precise
- point at which a watched piece of memory is modified. "Oh well."
-
- Note that we may have multiple threads running, which may each
- enter syscalls at roughly the same time. Since we don't have a
- good notion currently of whether a watched piece of memory is
- thread-private, we'd best not have any page-protections active
- when any thread is in a syscall. Thus, we only want to reenable
- hardware watches when no threads are in a syscall.
-
- Also, be careful not to try to gather much state about a thread
- that's in a syscall. It's frequently a losing proposition. */
+ /* Be careful not to try to gather much state about a thread
+ that's in a syscall. It's frequently a losing proposition. */
case TARGET_WAITKIND_SYSCALL_ENTRY:
- number_of_threads_in_syscalls++;
- if (number_of_threads_in_syscalls == 1)
- {
- TARGET_DISABLE_HW_WATCHPOINTS (PIDGET (inferior_ptid));
- }
+ if (debug_infrun)
+ fprintf_unfiltered (gdb_stdlog, "infrun: TARGET_WAITKIND_SYSCALL_ENTRY\n");
resume (0, TARGET_SIGNAL_0);
prepare_to_wait (ecs);
return;
get it entirely out of the syscall. (We get notice of the
event when the thread is just on the verge of exiting a
syscall. Stepping one instruction seems to get it back
- into user code.)
-
- Note that although the logical place to reenable h/w watches
- is here, we cannot. We cannot reenable them before stepping
- the thread (this causes the next wait on the thread to hang).
-
- Nor can we enable them after stepping until we've done a wait.
- Thus, we simply set the flag ecs->enable_hw_watchpoints_after_wait
- here, which will be serviced immediately after the target
- is waited on. */
+ into user code.) */
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);
-
- 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:
+ if (debug_infrun)
+ fprintf_unfiltered (gdb_stdlog, "infrun: TARGET_WAITKIND_STOPPED\n");
stop_signal = ecs->ws.value.sig;
break;
circumstance is any event which the lower level knows will be
reported multiple times without an intervening resume. */
case TARGET_WAITKIND_IGNORE:
+ if (debug_infrun)
+ fprintf_unfiltered (gdb_stdlog, "infrun: TARGET_WAITKIND_IGNORE\n");
prepare_to_wait (ecs);
return;
}
stop_pc = read_pc_pid (ecs->ptid);
+ 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 ()
we could tell, but we can't reliably. */
if (stop_signal == TARGET_SIGNAL_TRAP)
{
+ if (debug_infrun)
+ fprintf_unfiltered (gdb_stdlog, "infrun: stepping_past_singlestep_breakpoint\n");
/* Pull the single step breakpoints out of the target. */
SOFTWARE_SINGLE_STEP (0, 0);
singlestep_breakpoints_inserted_p = 0;
{
int remove_status;
+ if (debug_infrun)
+ fprintf_unfiltered (gdb_stdlog, "infrun: thread_hop_needed\n");
+
/* Saw a breakpoint, but it was hit by the wrong thread.
Just continue. */
so, then switch to that thread. */
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)
singlestep_breakpoints_inserted_p = 0;
}
- /* If PC is pointing at a nullified instruction, then step beyond
- it so that the user won't be confused when GDB appears to be ready
- to execute it. */
-
- /* if (INSTRUCTION_NULLIFIED && currently_stepping (ecs)) */
- if (INSTRUCTION_NULLIFIED)
- {
- registers_changed ();
- target_resume (ecs->ptid, 1, TARGET_SIGNAL_0);
-
- /* We may have received a signal that we want to pass to
- the inferior; therefore, we must not clobber the waitstatus
- in WS. */
-
- ecs->infwait_state = infwait_nullified_state;
- ecs->waiton_ptid = ecs->ptid;
- ecs->wp = &(ecs->tmpstatus);
- prepare_to_wait (ecs);
- return;
- }
-
/* It may not be necessary to disable the watchpoint to stop over
it. For example, the PA can (with some kernel cooperation)
single step over a watchpoint without disabling the watchpoint. */
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;
includes evaluating watchpoints, things will come to a
stop in the correct manner. */
+ if (debug_infrun)
+ fprintf_unfiltered (gdb_stdlog, "infrun: STOPPED_BY_WATCHPOINT\n");
remove_breakpoints ();
registers_changed ();
target_resume (ecs->ptid, 1, TARGET_SIGNAL_0); /* Single step */
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)
{
/* The user issued a continue when stopped at a breakpoint.
{
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;
shared libraries hook functions. */
if (stop_soon == STOP_QUIETLY)
{
+ if (debug_infrun)
+ fprintf_unfiltered (gdb_stdlog, "infrun: quietly stopped\n");
stop_stepping (ecs);
return;
}
/* Don't even think about breakpoints if just proceeded over a
breakpoint. */
if (stop_signal == TARGET_SIGNAL_TRAP && trap_expected)
- bpstat_clear (&stop_bpstat);
+ {
+ if (debug_infrun)
+ fprintf_unfiltered (gdb_stdlog, "infrun: trap expected\n");
+ bpstat_clear (&stop_bpstat);
+ }
else
{
/* See if there is a breakpoint at the current PC. */
/* Signal not for debugging purposes. */
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])
breakpoint. */
insert_step_resume_breakpoint_at_frame (get_current_frame ());
ecs->step_after_step_resume_breakpoint = 1;
+ keep_going (ecs);
+ return;
}
- else if (step_range_end != 0
- && stop_signal != TARGET_SIGNAL_0
- && stop_pc >= step_range_start && stop_pc < step_range_end
- && frame_id_eq (get_frame_id (get_current_frame ()),
- step_frame_id))
+
+ if (step_range_end != 0
+ && stop_signal != TARGET_SIGNAL_0
+ && stop_pc >= step_range_start && stop_pc < step_range_end
+ && frame_id_eq (get_frame_id (get_current_frame ()),
+ step_frame_id)
+ && step_resume_breakpoint == NULL)
{
/* The inferior is about to take a signal that will take it
out of the single step range. Set a breakpoint at the
while in the single-step range. Nested signals aren't a
problem as they eventually all return. */
insert_step_resume_breakpoint_at_frame (get_current_frame ());
+ keep_going (ecs);
+ return;
}
+
+ /* Note: step_resume_breakpoint may be non-NULL. This occures
+ when either there's a nested signal, or when there's a
+ pending signal enabled just as the signal handler returns
+ (leaving the inferior at the step-resume-breakpoint without
+ actually executing it). Either way continue until the
+ breakpoint is really hit. */
keep_going (ecs);
return;
}
/* If we hit the breakpoint at longjmp, disable it for the
duration of this command. Then, install a temporary
breakpoint at the target of the jmp_buf. */
+ if (debug_infrun)
+ fprintf_unfiltered (gdb_stdlog, "infrun: BPSTATE_WHAT_SET_LONGJMP_RESUME\n");
disable_longjmp_breakpoint ();
remove_breakpoints ();
breakpoints_inserted = 0;
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 ();
/* else fallthrough */
case BPSTAT_WHAT_SINGLE:
+ if (debug_infrun)
+ fprintf_unfiltered (gdb_stdlog, "infrun: BPSTATE_WHAT_SINGLE\n");
if (breakpoints_inserted)
{
remove_breakpoints ();
break;
case BPSTAT_WHAT_STOP_NOISY:
+ if (debug_infrun)
+ fprintf_unfiltered (gdb_stdlog, "infrun: BPSTATE_WHAT_STOP_NOISY\n");
stop_print_frame = 1;
/* We are about to nuke the step_resume_breakpointt via the
return;
case BPSTAT_WHAT_STOP_SILENT:
+ if (debug_infrun)
+ fprintf_unfiltered (gdb_stdlog, "infrun: BPSTATE_WHAT_STOP_SILENT\n");
stop_print_frame = 0;
/* We are about to nuke the step_resume_breakpoin via the
step-resume bp, but it makes no effort to ensure that
the one deleted is the one currently stopped at. MVS */
+ if (debug_infrun)
+ fprintf_unfiltered (gdb_stdlog, "infrun: BPSTATE_WHAT_STEP_RESUME\n");
+
if (step_resume_breakpoint == NULL)
{
step_resume_breakpoint =
break;
case BPSTAT_WHAT_THROUGH_SIGTRAMP:
+ if (debug_infrun)
+ fprintf_unfiltered (gdb_stdlog, "infrun: BPSTATE_WHAT_THROUGH_SIGTRAMP\n");
/* If were waiting for a trap, hitting the step_resume_break
doesn't count as getting it. */
if (trap_expected)
case BPSTAT_WHAT_CHECK_SHLIBS:
case BPSTAT_WHAT_CHECK_SHLIBS_RESUME_FROM_HOOK:
-#ifdef SOLIB_ADD
{
+ if (debug_infrun)
+ fprintf_unfiltered (gdb_stdlog, "infrun: BPSTATE_WHAT_CHECK_SHLIBS\n");
/* Remove breakpoints, we eventually want to step over the
shlib event breakpoint, and SOLIB_ADD might adjust
breakpoint addresses via breakpoint_re_set. */
exec/process stratum, instead relying on the target stack
to propagate relevant changes (stop, section table
changed, ...) up to other layers. */
+#ifdef SOLIB_ADD
SOLIB_ADD (NULL, 0, ¤t_target, auto_solib_add);
+#else
+ solib_add (NULL, 0, ¤t_target, auto_solib_add);
+#endif
target_terminal_inferior ();
/* Try to reenable shared library breakpoints, additional
break;
}
}
-#endif
break;
case BPSTAT_WHAT_LAST:
test for stepping. But, if not stepping,
do not stop. */
- /* Are we stepping to get the inferior out of the dynamic
- linker's hook (and possibly the dld itself) after catching
- a shlib event? */
+ /* Are we stepping to get the inferior out of the dynamic linker's
+ hook (and possibly the dld itself) after catching a shlib
+ event? */
if (ecs->stepping_through_solib_after_catch)
{
#if defined(SOLIB_ADD)
/* Have we reached our destination? If not, keep going. */
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");
/* Else, stop and report the catchpoint(s) whose triggering
caused us to begin stepping. */
ecs->stepping_through_solib_after_catch = 0;
if (step_resume_breakpoint)
{
+ if (debug_infrun)
+ fprintf_unfiltered (gdb_stdlog, "infrun: step-resume breakpoint\n");
+
/* Having a step-resume breakpoint overrides anything
else having to do with stepping commands until
that breakpoint is reached. */
if (step_range_end == 0)
{
+ if (debug_infrun)
+ fprintf_unfiltered (gdb_stdlog, "infrun: no stepping, continue\n");
/* Likewise if we aren't even stepping. */
keep_going (ecs);
return;
within it! */
if (stop_pc >= step_range_start && stop_pc < step_range_end)
{
+ 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;
}
until we exit the run time loader code and reach the callee's
address. */
if (step_over_calls == STEP_OVER_UNDEBUGGABLE
- && IN_SOLIB_DYNSYM_RESOLVE_CODE (stop_pc))
+#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)
{
/* Set up a step-resume breakpoint at the address
|| 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");
/* The inferior, while doing a "step" or "next", has ended up in
a signal trampoline (either by a signal being delivered or by
the signal handler returning). Just single-step until the
/* It's a subroutine call. */
CORE_ADDR real_stop_pc;
+ 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)))
if (real_stop_pc != 0)
ecs->stop_func_start = real_stop_pc;
- if (IN_SOLIB_DYNSYM_RESOLVE_CODE (ecs->stop_func_start))
+ 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);
/* Determine where this trampoline returns. */
CORE_ADDR real_stop_pc = SKIP_TRAMPOLINE_CODE (stop_pc);
+ if (debug_infrun)
+ fprintf_unfiltered (gdb_stdlog, "infrun: stepped into solib return tramp\n");
+
/* Only proceed through if we know where it's going. */
if (real_stop_pc)
{
}
}
+ ecs->sal = find_pc_line (stop_pc, 0);
+
/* NOTE: tausq/2004-05-24: This if block used to be done before all
the trampoline processing logic, however, there are some trampolines
that have no names, so we should do trampoline handling first. */
if (step_over_calls == STEP_OVER_UNDEBUGGABLE
- && ecs->stop_func_name == NULL)
+ && ecs->stop_func_name == NULL
+ && ecs->sal.line == 0)
{
+ if (debug_infrun)
+ fprintf_unfiltered (gdb_stdlog, "infrun: stepped into undebuggable function\n");
+
/* The inferior just stepped into, or returned to, an
- undebuggable function (where there is no symbol, not even a
- minimal symbol, corresponding to the address where the
+ undebuggable function (where there is no debugging information
+ and no line number corresponding to the address where the
inferior stopped). Since we want to skip this kind of code,
we keep going until the inferior returns from this
function. */
{
/* It is stepi or nexti. We always want to stop stepping after
one instruction. */
+ 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;
}
- ecs->sal = find_pc_line (stop_pc, 0);
-
if (ecs->sal.line == 0)
{
/* We have no line number information. That means to stop
stepping (does this always happen right after one instruction,
when we do "s" in a function with no line numbers,
or can this happen as a result of a return or longjmp?). */
+ 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);
we don't stop if we step into the middle of a different line.
That is said to make things like for (;;) statements work
better. */
+ 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);
This is particularly necessary for a one-line function,
in which after skipping the prologue we better stop even though
we will be in mid-line. */
+ 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);
step_frame_id = current_frame;
}
+ if (debug_infrun)
+ fprintf_unfiltered (gdb_stdlog, "infrun: keep going\n");
keep_going (ecs);
}
static void
stop_stepping (struct execution_control_state *ecs)
{
+ if (debug_infrun)
+ fprintf_unfiltered (gdb_stdlog, "infrun: stop_stepping\n");
+
/* Let callers know we don't want to wait for the inferior anymore. */
ecs->wait_some_more = 0;
}
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;
operation for n > 1 */
if (!step_multi || !stop_step)
if (ui_out_is_mi_like_p (uiout))
- ui_out_field_string (uiout, "reason", "end-stepping-range");
+ ui_out_field_string
+ (uiout, "reason",
+ async_reason_lookup (EXEC_ASYNC_END_STEPPING_RANGE));
break;
case BREAKPOINT_HIT:
/* We found a breakpoint. */
/* The inferior was terminated by a signal. */
annotate_signalled ();
if (ui_out_is_mi_like_p (uiout))
- ui_out_field_string (uiout, "reason", "exited-signalled");
+ 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",
if (stop_info)
{
if (ui_out_is_mi_like_p (uiout))
- ui_out_field_string (uiout, "reason", "exited");
+ 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);
else
{
if (ui_out_is_mi_like_p (uiout))
- ui_out_field_string (uiout, "reason", "exited-normally");
+ ui_out_field_string
+ (uiout, "reason",
+ async_reason_lookup (EXEC_ASYNC_EXITED_NORMALLY));
ui_out_text (uiout, "\nProgram exited normally.\n");
}
+ {
+ /* Support the --return-child-result option. */
+ extern int return_child_result_value;
+ return_child_result_value = stop_info;
+ }
break;
case SIGNAL_RECEIVED:
/* Signal received. The signal table tells us to print about
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, "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 ();
break;
default:
internal_error (__FILE__, __LINE__,
- "print_stop_reason: unrecognized enum value");
+ _("print_stop_reason: unrecognized enum value"));
break;
}
}
&& last.kind != TARGET_WAITKIND_EXITED)
{
target_terminal_ours_for_output ();
- printf_filtered ("[Switching to %s]\n",
+ printf_filtered (_("[Switching to %s]\n"),
target_pid_or_tid_to_str (inferior_ptid));
previous_inferior_ptid = inferior_ptid;
}
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");
+ 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;
do_frame_printing = 0;
break;
default:
- internal_error (__FILE__, __LINE__, "Unknown value.");
+ internal_error (__FILE__, __LINE__, _("Unknown value."));
}
/* For mi, have the same behavior every time we stop:
print everything but the source line. */
static void
sig_print_header (void)
{
- printf_filtered ("\
-Signal Stop\tPrint\tPass to program\tDescription\n");
+ printf_filtered (_("\
+Signal Stop\tPrint\tPass to program\tDescription\n"));
}
static void
if (args == NULL)
{
- error_no_arg ("signal to handle");
+ error_no_arg (_("signal to handle"));
}
/* Allocate and zero an array of flags for which signals to handle. */
else
{
/* Not a number and not a recognized flag word => complain. */
- error ("Unrecognized or ambiguous flag word: \"%s\".", *argv);
+ error (_("Unrecognized or ambiguous flag word: \"%s\"."), *argv);
}
}
}
else
{
- printf_unfiltered ("Not confirmed, unchanged.\n");
+ printf_unfiltered (_("Not confirmed, unchanged.\n"));
gdb_flush (gdb_stdout);
}
}
if (validFlag)
handle_command (argBuf, from_tty);
else
- printf_filtered ("Invalid signal handling flag.\n");
+ printf_filtered (_("Invalid signal handling flag.\n"));
if (argBuf)
xfree (argBuf);
}
sig_print_info (oursig);
}
- printf_filtered ("\nUse the \"handle\" command to change these tables.\n");
+ printf_filtered (_("\nUse the \"handle\" command to change these tables.\n"));
}
\f
struct inferior_status
selected frame. */
if (frame == NULL)
{
- warning ("Unable to restore previously selected frame.\n");
+ warning (_("Unable to restore previously selected frame."));
return 0;
}
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 ("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\
+ 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\
+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));
+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,
- concat ("Specify how to handle a signal.\n\
+ 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\
+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));
+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\
+ 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);
+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_stop[TARGET_SIGNAL_CANCEL] = 0;
signal_print[TARGET_SIGNAL_CANCEL] = 0;
-#ifdef SOLIB_ADD
- deprecated_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\
+ 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.\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\
+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.", &setlist);
- deprecated_add_show_from_set (c, &showlist);
-
- c = add_set_enum_cmd ("scheduler-locking", class_run, scheduler_enums, /* array of string names */
- &scheduler_mode, /* current mode */
- "Set mode for locking scheduler during execution.\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').", &setlist);
-
- set_cmd_sfunc (c, set_schedlock_func); /* traps on target vector */
- deprecated_add_show_from_set (c, &showlist);
-
- 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);
- deprecated_add_show_from_set (c, &showlist);
+ Other threads may run while stepping over a function call ('next')."),
+ set_schedlock_func, /* traps on target vector */
+ show_scheduler_mode,
+ &setlist, &showlist);
+
+ 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);
/* ptid initializations */
null_ptid = ptid_build (0, 0, 0);