Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995,
1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
- 2008, 2009 Free Software Foundation, Inc.
+ 2008, 2009, 2010 Free Software Foundation, Inc.
This file is part of GDB.
static int restore_selected_frame (void *);
-static void build_infrun (void);
-
static int follow_fork (void);
static void set_schedlock_func (char *args, int from_tty,
#ifdef SOLIB_CREATE_INFERIOR_HOOK
SOLIB_CREATE_INFERIOR_HOOK (PIDGET (inferior_ptid));
#else
- solib_create_inferior_hook ();
+ solib_create_inferior_hook (0);
#endif
jit_inferior_created_hook ();
or a return command, we often end up a few instructions forward, still
within the original line we started.
- An attempt was made to have init_execution_control_state () refresh
- the prev_pc value before calculating the line number. This approach
- did not work because on platforms that use ptrace, the pc register
- cannot be read unless the inferior is stopped. At that point, we
- are not guaranteed the inferior is stopped and so the regcache_read_pc ()
- call can fail. Setting the prev_pc value here ensures the value is
- updated correctly when the inferior is stopped. */
+ An attempt was made to refresh the prev_pc at the same time the
+ execution_control_state is initialized (for instance, just before
+ waiting for an inferior event). But this approach did not work
+ because of platforms that use ptrace, where the pc register cannot
+ be read unless the inferior is stopped. At that point, we are not
+ guaranteed the inferior is stopped and so the regcache_read_pc() call
+ can fail. Setting the prev_pc value here ensures the value is updated
+ correctly when the inferior is stopped. */
tp->prev_pc = regcache_read_pc (get_current_regcache ());
/* Fill in with reasonable starting values. */
int wait_some_more;
};
-static void init_execution_control_state (struct execution_control_state *ecs);
-
static void handle_inferior_event (struct execution_control_state *ecs);
static void handle_step_into_function (struct gdbarch *gdbarch,
tp->current_line = sal.line;
}
-/* Prepare an execution control state for looping through a
- wait_for_inferior-type loop. */
-
-static void
-init_execution_control_state (struct execution_control_state *ecs)
-{
- ecs->random_signal = 0;
-}
-
/* Clear context switchable stepping state. */
void
dynamically loaded objects (among other things). */
if (stop_on_solib_events)
{
+ /* Make sure we print "Stopped due to solib-event" in
+ normal_stop. */
+ stop_print_frame = 1;
+
stop_stepping (ecs);
return;
}
= bpstat_stop_status (get_regcache_aspace (get_current_regcache ()),
stop_pc, ecs->ptid);
- ecs->random_signal = !bpstat_explains_signal (ecs->event_thread->stop_bpstat);
+ /* Note that we're interested in knowing the bpstat actually
+ causes a stop, not just if it may explain the signal.
+ Software watchpoints, for example, always appear in the
+ bpstat. */
+ ecs->random_signal = !bpstat_causes_stop (ecs->event_thread->stop_bpstat);
/* If no catchpoint triggered for this, then keep going. */
if (ecs->random_signal)
context_switch (ecs->ptid);
current_inferior ()->waiting_for_vfork_done = 0;
+ current_inferior ()->pspace->breakpoints_not_allowed = 0;
/* This also takes care of reinserting breakpoints in the
previously locked inferior. */
keep_going (ecs);
{
struct regcache *regcache = get_thread_regcache (ecs->ptid);
struct gdbarch *gdbarch = get_regcache_arch (regcache);
+ struct cleanup *old_chain = save_inferior_ptid ();
+
+ inferior_ptid = ecs->ptid;
fprintf_unfiltered (gdb_stdlog, "infrun: stop_pc = %s\n",
paddress (gdbarch, stop_pc));
fprintf_unfiltered (gdb_stdlog,
"infrun: (no data address available)\n");
}
+
+ do_cleanups (old_chain);
}
if (stepping_past_singlestep_breakpoint)
if (ecs->event_thread->stop_signal == TARGET_SIGNAL_TRAP)
{
int thread_hop_needed = 0;
- struct address_space *aspace = get_regcache_aspace (get_current_regcache ());
+ struct address_space *aspace =
+ get_regcache_aspace (get_thread_regcache (ecs->ptid));
/* Check if a regular breakpoint has been hit before checking
for a potential single step breakpoint. Otherwise, GDB will
function. */
stop_print_frame = 1;
+ /* This is where we handle "moribund" watchpoints. Unlike
+ software breakpoints traps, hardware watchpoint traps are
+ always distinguishable from random traps. If no high-level
+ watchpoint is associated with the reported stop data address
+ anymore, then the bpstat does not explain the signal ---
+ simply make sure to ignore it if `stopped_by_watchpoint' is
+ set. */
+
+ if (debug_infrun
+ && ecs->event_thread->stop_signal == TARGET_SIGNAL_TRAP
+ && !bpstat_explains_signal (ecs->event_thread->stop_bpstat)
+ && stopped_by_watchpoint)
+ fprintf_unfiltered (gdb_stdlog, "\
+infrun: no user watchpoint explains watchpoint SIGTRAP, ignoring\n");
+
/* NOTE: cagney/2003-03-29: These two checks for a random signal
at one stage in the past included checks for an inferior
function call's call dummy's return breakpoint. The original
if (ecs->event_thread->stop_signal == TARGET_SIGNAL_TRAP)
ecs->random_signal
= !(bpstat_explains_signal (ecs->event_thread->stop_bpstat)
+ || stopped_by_watchpoint
|| ecs->event_thread->trap_expected
|| (ecs->event_thread->step_range_end
&& ecs->event_thread->step_resume_breakpoint == NULL));
return;
}
+ /* Re-fetch current thread's frame in case the code above caused
+ the frame cache to be re-initialized, making our FRAME variable
+ a dangling pointer. */
+ frame = get_current_frame ();
+
/* If stepping through a line, keep going if still within it.
Note that step_range_end is the address of the first instruction
"outermost" function. This could be fixed by marking
outermost frames as !stack_p,code_p,special_p. Then the
initial outermost frame, before sp was valid, would
- have code_addr == &_start. See the commend in frame_id_eq
+ have code_addr == &_start. See the comment in frame_id_eq
for more. */
if (!frame_id_eq (get_stack_frame_id (frame),
ecs->event_thread->step_stack_frame_id)
static void
keep_going (struct execution_control_state *ecs)
{
+ /* Make sure normal_stop is called if we get a QUIT handled before
+ reaching resume. */
+ struct cleanup *old_cleanups = make_cleanup (resume_cleanups, 0);
+
/* Save the pc before execution, to compare with pc after stop. */
ecs->event_thread->prev_pc
= regcache_read_pc (get_thread_regcache (ecs->ptid));
/* We took a signal (which we are supposed to pass through to
the inferior, else we'd not get here) and we haven't yet
gotten our trap. Simply continue. */
+
+ discard_cleanups (old_cleanups);
resume (currently_stepping (ecs->event_thread),
ecs->event_thread->stop_signal);
}
}
if (e.reason < 0)
{
+ exception_print (gdb_stderr, e);
stop_stepping (ecs);
return;
}
&& !signal_program[ecs->event_thread->stop_signal])
ecs->event_thread->stop_signal = TARGET_SIGNAL_0;
+ discard_cleanups (old_cleanups);
resume (currently_stepping (ecs->event_thread),
ecs->event_thread->stop_signal);
}