* infrun.c (normal_stop): Use has_stack_frames instead of
[deliverable/binutils-gdb.git] / gdb / infrun.c
index 92092ab9e1007dec4bf7c35b55adbd98c540c0b1..4e270fc9f625d1c5e5199a6e70e6d991a8eba0a9 100644 (file)
@@ -1230,7 +1230,8 @@ clear_proceed_status (void)
     }
 
   stop_after_trap = 0;
-  breakpoint_proceeded = 1;    /* We're about to proceed... */
+
+  observer_notify_about_to_proceed ();
 
   if (stop_registers)
     {
@@ -1660,7 +1661,7 @@ infrun_thread_stop_requested_callback (struct thread_info *info, void *arg)
    Cleanup local state that assumed the PTID was to be resumed, and
    report the stop to the frontend.  */
 
-void
+static void
 infrun_thread_stop_requested (ptid_t ptid)
 {
   struct displaced_step_request *it, *next, *prev = NULL;
@@ -1737,6 +1738,46 @@ delete_step_thread_step_resume_breakpoint_cleanup (void *arg)
   delete_step_thread_step_resume_breakpoint ();
 }
 
+/* Pretty print the results of target_wait, for debugging purposes.  */
+
+static void
+print_target_wait_results (ptid_t waiton_ptid, ptid_t result_ptid,
+                          const struct target_waitstatus *ws)
+{
+  char *status_string = target_waitstatus_to_string (ws);
+  struct ui_file *tmp_stream = mem_fileopen ();
+  char *text;
+  long len;
+
+  /* The text is split over several lines because it was getting too long.
+     Call fprintf_unfiltered (gdb_stdlog) once so that the text is still
+     output as a unit; we want only one timestamp printed if debug_timestamp
+     is set.  */
+
+  fprintf_unfiltered (tmp_stream,
+                     "infrun: target_wait (%d", PIDGET (waiton_ptid));
+  if (PIDGET (waiton_ptid) != -1)
+    fprintf_unfiltered (tmp_stream,
+                       " [%s]", target_pid_to_str (waiton_ptid));
+  fprintf_unfiltered (tmp_stream, ", status) =\n");
+  fprintf_unfiltered (tmp_stream,
+                     "infrun:   %d [%s],\n",
+                     PIDGET (result_ptid), target_pid_to_str (result_ptid));
+  fprintf_unfiltered (tmp_stream,
+                     "infrun:   %s\n",
+                     status_string);
+
+  text = ui_file_xstrdup (tmp_stream, &len);
+
+  /* This uses %s in part to handle %'s in the text, but also to avoid
+     a gcc error: the format attribute requires a string literal.  */
+  fprintf_unfiltered (gdb_stdlog, "%s", text);
+
+  xfree (status_string);
+  xfree (text);
+  ui_file_delete (tmp_stream);
+}
+
 /* Wait for control to return from inferior to debugger.
 
    If TREAT_EXEC_AS_SIGTRAP is non-zero, then handle EXEC signals
@@ -1789,6 +1830,9 @@ wait_for_inferior (int treat_exec_as_sigtrap)
       else
        ecs->ptid = target_wait (waiton_ptid, &ecs->ws);
 
+      if (debug_infrun)
+       print_target_wait_results (waiton_ptid, ecs->ptid, &ecs->ws);
+
       if (treat_exec_as_sigtrap && ecs->ws.kind == TARGET_WAITKIND_EXECD)
         {
           xfree (ecs->ws.value.execd_pathname);
@@ -1864,6 +1908,9 @@ fetch_inferior_event (void *client_data)
   else
     ecs->ptid = target_wait (waiton_ptid, &ecs->ws);
 
+  if (debug_infrun)
+    print_target_wait_results (waiton_ptid, ecs->ptid, &ecs->ws);
+
   if (non_stop
       && ecs->ws.kind != TARGET_WAITKIND_IGNORE
       && ecs->ws.kind != TARGET_WAITKIND_EXITED
@@ -4193,10 +4240,10 @@ normal_stop (void)
   if (target_has_execution)
     {
       if (!non_stop)
-       old_chain = make_cleanup (finish_thread_state_cleanup, &minus_one_ptid);
+       make_cleanup (finish_thread_state_cleanup, &minus_one_ptid);
       else if (last.kind != TARGET_WAITKIND_SIGNALLED
               && last.kind != TARGET_WAITKIND_EXITED)
-       old_chain = make_cleanup (finish_thread_state_cleanup, &inferior_ptid);
+       make_cleanup (finish_thread_state_cleanup, &inferior_ptid);
     }
 
   /* In non-stop mode, we don't want GDB to switch threads behind the
@@ -4224,17 +4271,6 @@ normal_stop (void)
       previous_inferior_ptid = inferior_ptid;
     }
 
-  /* NOTE drow/2004-01-17: Is this still necessary?  */
-  /* Make sure that the current_frame's pc is correct.  This
-     is a correction for setting up the frame info before doing
-     gdbarch_decr_pc_after_break */
-  if (target_has_execution)
-    /* FIXME: cagney/2002-12-06: Has the PC changed?  Thanks to
-       gdbarch_decr_pc_after_break, the program counter can change.  Ask the
-       frame code to check for this and sort out any resultant mess.
-       gdbarch_decr_pc_after_break needs to just go away.  */
-    deprecated_update_frame_pc_hack (get_current_frame (), read_pc ());
-
   if (!breakpoints_always_inserted_mode () && target_has_execution)
     {
       if (remove_breakpoints ())
@@ -4266,10 +4302,19 @@ Further execution is probably impossible.\n"));
   /* Set the current source location.  This will also happen if we
      display the frame below, but the current SAL will be incorrect
      during a user hook-stop function.  */
-  if (target_has_stack && !stop_stack_dummy)
+  if (has_stack_frames () && !stop_stack_dummy)
     set_current_sal_from_frame (get_current_frame (), 1);
 
-  if (!target_has_stack)
+  /* Let the user/frontend see the threads as stopped.  */
+  do_cleanups (old_chain);
+
+  /* Look up the hook_stop and run it (CLI internally handles problem
+     of stop_command's pre-hook not existing).  */
+  if (stop_command)
+    catch_errors (hook_stop_stub, stop_command,
+                 "Error while running hook_stop:\n", RETURN_MASK_ALL);
+
+  if (!has_stack_frames ())
     goto done;
 
   if (last.kind == TARGET_WAITKIND_SIGNALLED
@@ -4342,22 +4387,6 @@ Further execution is probably impossible.\n"));
              internal_error (__FILE__, __LINE__, _("Unknown value."));
            }
 
-         if (ui_out_is_mi_like_p (uiout))
-           {
-
-             ui_out_field_int (uiout, "thread-id",
-                               pid_to_thread_id (inferior_ptid));
-             if (non_stop)
-               {
-                 struct cleanup *back_to = make_cleanup_ui_out_list_begin_end 
-                   (uiout, "stopped-threads");
-                 ui_out_field_int (uiout, NULL,
-                                   pid_to_thread_id (inferior_ptid));                            
-                 do_cleanups (back_to);
-               }
-             else
-               ui_out_field_string (uiout, "stopped-threads", "all");
-           }
          /* The behavior of this routine with respect to the source
             flag is:
             SRC_LINE: Print only source line
@@ -4405,16 +4434,32 @@ Further execution is probably impossible.\n"));
 
 done:
   annotate_stopped ();
-  if (!suppress_stop_observer
-      && !(target_has_execution
-          && last.kind != TARGET_WAITKIND_SIGNALLED
-          && last.kind != TARGET_WAITKIND_EXITED
-          && inferior_thread ()->step_multi))
+
+  /* Suppress the stop observer if we're in the middle of:
+
+     - a step n (n > 1), as there still more steps to be done.
+
+     - a "finish" command, as the observer will be called in
+       finish_command_continuation, so it can include the inferior
+       function's return value.
+
+     - calling an inferior function, as we pretend we inferior didn't
+       run at all.  The return value of the call is handled by the
+       expression evaluator, through call_function_by_hand.  */
+
+  if (!target_has_execution
+      || last.kind == TARGET_WAITKIND_SIGNALLED
+      || last.kind == TARGET_WAITKIND_EXITED
+      || (!inferior_thread ()->step_multi
+         && !(inferior_thread ()->stop_bpstat
+              && inferior_thread ()->proceed_to_finish)
+         && !inferior_thread ()->in_infcall))
     {
       if (!ptid_equal (inferior_ptid, null_ptid))
-       observer_notify_normal_stop (inferior_thread ()->stop_bpstat);
+       observer_notify_normal_stop (inferior_thread ()->stop_bpstat,
+                                    stop_print_frame);
       else
-       observer_notify_normal_stop (NULL);
+       observer_notify_normal_stop (NULL, stop_print_frame);
     }
 
   if (target_has_execution)
@@ -4425,16 +4470,6 @@ done:
           Delete any breakpoint that is to be deleted at the next stop.  */
        breakpoint_auto_delete (inferior_thread ()->stop_bpstat);
     }
-
-  /* Tell the frontend about the new thread states.  */
-  do_cleanups (old_chain);
-
-  /* Look up the hook_stop and run it (CLI internally handles problem
-     of stop_command's pre-hook not existing).  */
-  if (stop_command)
-    catch_errors (hook_stop_stub, stop_command,
-                 "Error while running hook_stop:\n", RETURN_MASK_ALL);
-
 }
 
 static int
@@ -4644,8 +4679,8 @@ handle_command (char *args, int from_tty)
            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)))
+                 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;
                    }
@@ -4796,6 +4831,87 @@ signals_info (char *signum_exp, int from_tty)
 
   printf_filtered (_("\nUse the \"handle\" command to change these tables.\n"));
 }
+
+/* The $_siginfo convenience variable is a bit special.  We don't know
+   for sure the type of the value until we actually have a chance to
+   fetch the data.  The type can change depending on gdbarch, so it it
+   also dependent on which thread you have selected.
+
+     1. making $_siginfo be an internalvar that creates a new value on
+     access.
+
+     2. making the value of $_siginfo be an lval_computed value.  */
+
+/* This function implements the lval_computed support for reading a
+   $_siginfo value.  */
+
+static void
+siginfo_value_read (struct value *v)
+{
+  LONGEST transferred;
+
+  transferred =
+    target_read (&current_target, TARGET_OBJECT_SIGNAL_INFO,
+                NULL,
+                value_contents_all_raw (v),
+                value_offset (v),
+                TYPE_LENGTH (value_type (v)));
+
+  if (transferred != TYPE_LENGTH (value_type (v)))
+    error (_("Unable to read siginfo"));
+}
+
+/* This function implements the lval_computed support for writing a
+   $_siginfo value.  */
+
+static void
+siginfo_value_write (struct value *v, struct value *fromval)
+{
+  LONGEST transferred;
+
+  transferred = target_write (&current_target,
+                             TARGET_OBJECT_SIGNAL_INFO,
+                             NULL,
+                             value_contents_all_raw (fromval),
+                             value_offset (v),
+                             TYPE_LENGTH (value_type (fromval)));
+
+  if (transferred != TYPE_LENGTH (value_type (fromval)))
+    error (_("Unable to write siginfo"));
+}
+
+static struct lval_funcs siginfo_value_funcs =
+  {
+    siginfo_value_read,
+    siginfo_value_write
+  };
+
+/* Return a new value with the correct type for the siginfo object of
+   the current thread.  Return a void value if there's no object
+   available.  */
+
+static struct value *
+siginfo_make_value (struct internalvar *var)
+{
+  struct type *type;
+  struct gdbarch *gdbarch;
+
+  if (target_has_stack
+      && !ptid_equal (inferior_ptid, null_ptid))
+    {
+      gdbarch = get_frame_arch (get_current_frame ());
+
+      if (gdbarch_get_siginfo_type_p (gdbarch))
+       {
+         type = gdbarch_get_siginfo_type (gdbarch);
+
+         return allocate_computed_value (type, &siginfo_value_funcs, NULL);
+       }
+    }
+
+  return allocate_value (builtin_type_void);
+}
+
 \f
 /* Inferior thread state.
    These are details related to the inferior itself, and don't include
@@ -4892,8 +5008,8 @@ struct inferior_status
   /* ID if the selected frame when the inferior function call was made.  */
   struct frame_id selected_frame_id;
 
-  int breakpoint_proceeded;
   int proceed_to_finish;
+  int in_infcall;
 };
 
 /* Save all of the information associated with the inferior<==>gdb
@@ -4922,8 +5038,8 @@ save_inferior_status (void)
      called.  */
   inf_status->stop_bpstat = tp->stop_bpstat;
   tp->stop_bpstat = bpstat_copy (tp->stop_bpstat);
-  inf_status->breakpoint_proceeded = breakpoint_proceeded;
   inf_status->proceed_to_finish = tp->proceed_to_finish;
+  inf_status->in_infcall = tp->in_infcall;
 
   inf_status->selected_frame_id = get_frame_id (get_selected_frame (NULL));
 
@@ -4972,8 +5088,8 @@ restore_inferior_status (struct inferior_status *inf_status)
   bpstat_clear (&tp->stop_bpstat);
   tp->stop_bpstat = inf_status->stop_bpstat;
   inf_status->stop_bpstat = NULL;
-  breakpoint_proceeded = inf_status->breakpoint_proceeded;
   tp->proceed_to_finish = inf_status->proceed_to_finish;
+  tp->in_infcall = inf_status->in_infcall;
 
   if (target_has_stack)
     {
@@ -5459,4 +5575,10 @@ Options are 'forward' or 'reverse'."),
 
   observer_attach_thread_ptid_changed (infrun_thread_ptid_changed);
   observer_attach_thread_stop_requested (infrun_thread_stop_requested);
+
+  /* Explicitly create without lookup, since that tries to create a
+     value with a void typed value, and when we get here, gdbarch
+     isn't initialized yet.  At this point, we're quite sure there
+     isn't another convenience variable of the same name.  */
+  create_internalvar_type_lazy ("_siginfo", siginfo_make_value);
 }
This page took 0.029862 seconds and 4 git commands to generate.