X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Finfrun.c;h=4e270fc9f625d1c5e5199a6e70e6d991a8eba0a9;hb=d729566a19c83c452f3a962182d1c6d349562159;hp=92092ab9e1007dec4bf7c35b55adbd98c540c0b1;hpb=b89667ebd42a3a59b8f17ec9153d07dd2fc7e5e1;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/infrun.c b/gdb/infrun.c index 92092ab9e1..4e270fc9f6 100644 --- a/gdb/infrun.c +++ b/gdb/infrun.c @@ -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 (¤t_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 (¤t_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); +} + /* 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); }