if (exec_bfd)
{
+ const unsigned solib_add_generation
+ = current_program_space->solib_add_generation;
+
/* Create the hooks to handle shared library load and unload
events. */
#ifdef SOLIB_CREATE_INFERIOR_HOOK
#else
solib_create_inferior_hook (from_tty);
#endif
- }
-
- /* If the solist is global across processes, there's no need to
- refetch it here. */
- if (exec_bfd && !gdbarch_has_global_solist (target_gdbarch))
- {
- /* Sometimes the platform-specific hook loads initial shared
- libraries, and sometimes it doesn't. If it doesn't FROM_TTY will be
- incorrectly 0 but such solib targets should be fixed anyway. If we
- made all the inferior hook methods consistent, this call could be
- removed. Call it only after the solib target has been initialized by
- solib_create_inferior_hook. */
+ if (current_program_space->solib_add_generation == solib_add_generation)
+ {
+ /* The platform-specific hook should load initial shared libraries,
+ but didn't. FROM_TTY will be incorrectly 0 but such solib
+ targets should be fixed anyway. Call it only after the solib
+ target has been initialized by solib_create_inferior_hook. */
+
+ if (info_verbose)
+ warning (_("platform-specific solib_create_inferior_hook did "
+ "not load initial shared libraries."));
+
+ /* If the solist is global across processes, there's no need to
+ refetch it here. */
+ if (!gdbarch_has_global_solist (target_gdbarch))
+ {
#ifdef SOLIB_ADD
- SOLIB_ADD (NULL, 0, target, auto_solib_add);
+ SOLIB_ADD (NULL, 0, target, auto_solib_add);
#else
- solib_add (NULL, 0, target, auto_solib_add);
+ solib_add (NULL, 0, target, auto_solib_add);
#endif
+ }
+ }
}
/* If the user sets watchpoints before execution having started,
char *exec_file;
struct cleanup *old_chain;
ptid_t ptid;
+ struct ui_out *uiout = current_uiout;
dont_repeat ();
proceed(), via step_once(). Basically it is like step_once and
step_1_continuation are co-recursive. */
static void
-step_1_continuation (void *args)
+step_1_continuation (void *args, int err)
{
struct step_1_continuation_args *a = args;
struct thread_info *tp;
tp = inferior_thread ();
- if (tp->step_multi && tp->control.stop_step)
+ if (!err
+ && tp->step_multi && tp->control.stop_step)
{
/* There are more steps to make, and we did stop due to
ending a stepping range. Do another step. */
tp->step_multi = 0;
}
- /* We either stopped for some reason that is not stepping, or there
- are no further steps to make. Cleanup. */
+ /* We either hit an error, or stopped for some reason that is
+ not stepping, or there are no further steps to make.
+ Cleanup. */
if (!a->single_inst || a->skip_subroutines)
delete_longjmp_breakpoint (a->thread);
}
proceed ((CORE_ADDR) -1, oursig, 0);
}
+/* Continuation args to be passed to the "until" command
+ continuation. */
+struct until_next_continuation_args
+{
+ /* The thread that was current when the command was executed. */
+ int thread;
+};
+
/* A continuation callback for until_next_command. */
static void
-until_next_continuation (void *arg)
+until_next_continuation (void *arg, int err)
{
- struct thread_info *tp = arg;
+ struct until_next_continuation_args *a = arg;
- delete_longjmp_breakpoint (tp->num);
+ delete_longjmp_breakpoint (a->thread);
}
/* Proceed until we reach a different source line with pc greater than
if (target_can_async_p () && is_running (inferior_ptid))
{
+ struct until_next_continuation_args *cont_args;
+
discard_cleanups (old_chain);
- add_continuation (tp, until_next_continuation, tp, NULL);
+ cont_args = XNEW (struct until_next_continuation_args);
+ cont_args->thread = inferior_thread ()->num;
+
+ add_continuation (tp, until_next_continuation, cont_args, xfree);
}
else
do_cleanups (old_chain);
struct cleanup *old_chain;
struct ui_stream *stb;
struct value *value;
+ struct ui_out *uiout = current_uiout;
CHECK_TYPEDEF (value_type);
gdb_assert (TYPE_CODE (value_type) != TYPE_CODE_VOID);
impossible to do all the stuff as part of the finish_command
function itself. The only chance we have to complete this command
is in fetch_inferior_event, which is called by the event loop as
- soon as it detects that the target has stopped. This function is
- called via the cmd_continuation pointer. */
+ soon as it detects that the target has stopped. */
struct finish_command_continuation_args
{
+ /* The thread that as current when the command was executed. */
+ int thread;
struct breakpoint *breakpoint;
struct symbol *function;
};
static void
-finish_command_continuation (void *arg)
+finish_command_continuation (void *arg, int err)
{
struct finish_command_continuation_args *a = arg;
- struct thread_info *tp = NULL;
- bpstat bs = NULL;
- if (!ptid_equal (inferior_ptid, null_ptid)
- && target_has_execution
- && is_stopped (inferior_ptid))
+ if (!err)
{
- tp = inferior_thread ();
- bs = tp->control.stop_bpstat;
- }
-
- if (bpstat_find_breakpoint (bs, a->breakpoint) != NULL
- && a->function != NULL)
- {
- struct type *value_type;
+ struct thread_info *tp = NULL;
+ bpstat bs = NULL;
- value_type = TYPE_TARGET_TYPE (SYMBOL_TYPE (a->function));
- if (!value_type)
- internal_error (__FILE__, __LINE__,
- _("finish_command: function has no target type"));
+ if (!ptid_equal (inferior_ptid, null_ptid)
+ && target_has_execution
+ && is_stopped (inferior_ptid))
+ {
+ tp = inferior_thread ();
+ bs = tp->control.stop_bpstat;
+ }
- if (TYPE_CODE (value_type) != TYPE_CODE_VOID)
+ if (bpstat_find_breakpoint (bs, a->breakpoint) != NULL
+ && a->function != NULL)
{
- volatile struct gdb_exception ex;
+ struct type *value_type;
+
+ value_type = TYPE_TARGET_TYPE (SYMBOL_TYPE (a->function));
+ if (!value_type)
+ internal_error (__FILE__, __LINE__,
+ _("finish_command: function has no target type"));
- TRY_CATCH (ex, RETURN_MASK_ALL)
+ if (TYPE_CODE (value_type) != TYPE_CODE_VOID)
{
- /* print_return_value can throw an exception in some
- circumstances. We need to catch this so that we still
- delete the breakpoint. */
- print_return_value (SYMBOL_TYPE (a->function), value_type);
+ volatile struct gdb_exception ex;
+
+ TRY_CATCH (ex, RETURN_MASK_ALL)
+ {
+ /* print_return_value can throw an exception in some
+ circumstances. We need to catch this so that we still
+ delete the breakpoint. */
+ print_return_value (SYMBOL_TYPE (a->function), value_type);
+ }
+ if (ex.reason < 0)
+ exception_print (gdb_stdout, ex);
}
- if (ex.reason < 0)
- exception_print (gdb_stdout, ex);
}
+
+ /* We suppress normal call of normal_stop observer and do it
+ here so that the *stopped notification includes the return
+ value. */
+ if (bs != NULL && tp->control.proceed_to_finish)
+ observer_notify_normal_stop (bs, 1 /* print frame */);
}
- /* We suppress normal call of normal_stop observer and do it here so
- that the *stopped notification includes the return value. */
- if (bs != NULL && tp->control.proceed_to_finish)
- observer_notify_normal_stop (bs, 1 /* print frame */);
delete_breakpoint (a->breakpoint);
- delete_longjmp_breakpoint (inferior_thread ()->num);
+ delete_longjmp_breakpoint (a->thread);
}
static void
tp->control.proceed_to_finish = 1;
cargs = xmalloc (sizeof (*cargs));
+ cargs->thread = thread;
cargs->breakpoint = breakpoint;
cargs->function = function;
add_continuation (tp, finish_command_continuation, cargs,
discard_cleanups (old_chain);
if (!target_can_async_p ())
- do_all_continuations ();
+ do_all_continuations (0);
}
/* "finish": Set a temporary breakpoint at the place the selected
};
static void
-attach_command_continuation (void *args)
+attach_command_continuation (void *args, int err)
{
struct attach_command_continuation_args *a = args;
+ if (err)
+ return;
+
attach_command_post_wait (a->args, a->from_tty, a->async_exec);
}