X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Finfrun.c;h=2b4525e213eb91051c4c334be1c97e35095fddc0;hb=c8f2448ab76c836fc709bf4b5b9e1904f6f38576;hp=274082dc3b697262cc0b17ec4eb504c5fa632448;hpb=a42244dbec4d58c5577a84215d92c85a6c067d1a;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/infrun.c b/gdb/infrun.c index 274082dc3b..2b4525e213 100644 --- a/gdb/infrun.c +++ b/gdb/infrun.c @@ -54,6 +54,7 @@ #include "inline-frame.h" #include "jit.h" #include "tracepoint.h" +#include "continuations.h" /* Prototypes for local functions */ @@ -99,6 +100,12 @@ void _initialize_infrun (void); void nullify_last_target_wait_ptid (void); +static void insert_hp_step_resume_breakpoint_at_frame (struct frame_info *); + +static void insert_step_resume_breakpoint_at_caller (struct frame_info *); + +static void insert_longjmp_resume_breakpoint (struct gdbarch *, CORE_ADDR); + /* When set, stop the 'step' command if we enter a function which has no line number information. The normal behavior is that we step over such function. */ @@ -276,6 +283,11 @@ static unsigned char *signal_stop; static unsigned char *signal_print; static unsigned char *signal_program; +/* Table of signals that the target may silently handle. + This is automatically determined from the flags above, + and simply cached here. */ +static unsigned char *signal_pass; + #define SET_SIGS(nsigs,sigs,flags) \ do { \ int signum = (nsigs); \ @@ -1586,6 +1598,45 @@ maybe_software_singlestep (struct gdbarch *gdbarch, CORE_ADDR pc) return hw_step; } +/* Return a ptid representing the set of threads that we will proceed, + in the perspective of the user/frontend. We may actually resume + fewer threads at first, e.g., if a thread is stopped at a + breakpoint that needs stepping-off, but that should not be visible + to the user/frontend, and neither should the frontend/user be + allowed to proceed any of the threads that happen to be stopped for + internal run control handling, if a previous command wanted them + resumed. */ + +ptid_t +user_visible_resume_ptid (int step) +{ + /* By default, resume all threads of all processes. */ + ptid_t resume_ptid = RESUME_ALL; + + /* Maybe resume only all threads of the current process. */ + if (!sched_multi && target_supports_multi_process ()) + { + resume_ptid = pid_to_ptid (ptid_get_pid (inferior_ptid)); + } + + /* Maybe resume a single thread after all. */ + if (non_stop) + { + /* With non-stop mode on, threads are always handled + individually. */ + resume_ptid = inferior_ptid; + } + else if ((scheduler_mode == schedlock_on) + || (scheduler_mode == schedlock_step + && (step || singlestep_breakpoints_inserted_p))) + { + /* User-settable 'scheduler' mode requires solo thread resume. */ + resume_ptid = inferior_ptid; + } + + return resume_ptid; +} + /* Resume the inferior, but allow a QUIT. This is useful if the user wants to interrupt some lengthy single-stepping operation (for child processes, the SIGINT goes to the inferior, and so @@ -1629,8 +1680,10 @@ resume (int step, enum target_signal sig) if (debug_infrun) fprintf_unfiltered (gdb_stdlog, "infrun: resume (step=%d, signal=%d), " - "trap_expected=%d\n", - step, sig, tp->control.trap_expected); + "trap_expected=%d, current thread [%s] at %s\n", + step, sig, tp->control.trap_expected, + target_pid_to_str (inferior_ptid), + paddress (gdbarch, pc)); /* Normally, by the time we reach `resume', the breakpoints are either removed or inserted, as appropriate. The exception is if we're sitting @@ -1688,6 +1741,51 @@ a command like `return' or `jump' to continue execution.")); else if (step) step = maybe_software_singlestep (gdbarch, pc); + /* Currently, our software single-step implementation leads to different + results than hardware single-stepping in one situation: when stepping + into delivering a signal which has an associated signal handler, + hardware single-step will stop at the first instruction of the handler, + while software single-step will simply skip execution of the handler. + + For now, this difference in behavior is accepted since there is no + easy way to actually implement single-stepping into a signal handler + without kernel support. + + However, there is one scenario where this difference leads to follow-on + problems: if we're stepping off a breakpoint by removing all breakpoints + and then single-stepping. In this case, the software single-step + behavior means that even if there is a *breakpoint* in the signal + handler, GDB still would not stop. + + Fortunately, we can at least fix this particular issue. We detect + here the case where we are about to deliver a signal while software + single-stepping with breakpoints removed. In this situation, we + revert the decisions to remove all breakpoints and insert single- + step breakpoints, and instead we install a step-resume breakpoint + at the current address, deliver the signal without stepping, and + once we arrive back at the step-resume breakpoint, actually step + over the breakpoint we originally wanted to step over. */ + if (singlestep_breakpoints_inserted_p + && tp->control.trap_expected && sig != TARGET_SIGNAL_0) + { + /* If we have nested signals or a pending signal is delivered + immediately after a handler returns, might might already have + a step-resume breakpoint set on the earlier handler. We cannot + set another step-resume breakpoint; just continue on until the + original breakpoint is hit. */ + if (tp->control.step_resume_breakpoint == NULL) + { + insert_hp_step_resume_breakpoint_at_frame (get_current_frame ()); + tp->step_after_step_resume_breakpoint = 1; + } + + remove_single_step_breakpoints (); + singlestep_breakpoints_inserted_p = 0; + + insert_breakpoints (); + tp->control.trap_expected = 0; + } + if (should_resume) { ptid_t resume_ptid; @@ -1700,15 +1798,7 @@ a command like `return' or `jump' to continue execution.")); /* Decide the set of threads to ask the target to resume. Start by assuming everything will be resumed, than narrow the set by applying increasingly restricting conditions. */ - - /* By default, resume all threads of all processes. */ - resume_ptid = RESUME_ALL; - - /* Maybe resume only all threads of the current process. */ - if (!sched_multi && target_supports_multi_process ()) - { - resume_ptid = pid_to_ptid (ptid_get_pid (inferior_ptid)); - } + resume_ptid = user_visible_resume_ptid (step); /* Maybe resume a single thread after all. */ if (singlestep_breakpoints_inserted_p @@ -1742,19 +1832,6 @@ a command like `return' or `jump' to continue execution.")); breakpoint, not just the one at PC. */ resume_ptid = inferior_ptid; } - else if (non_stop) - { - /* With non-stop mode on, threads are always handled - individually. */ - resume_ptid = inferior_ptid; - } - else if ((scheduler_mode == schedlock_on) - || (scheduler_mode == schedlock_step - && (step || singlestep_breakpoints_inserted_p))) - { - /* User-settable 'scheduler' mode requires solo thread resume. */ - resume_ptid = inferior_ptid; - } if (gdbarch_cannot_step_breakpoint (gdbarch)) { @@ -1787,6 +1864,18 @@ a command like `return' or `jump' to continue execution.")); happens to apply to another thread. */ tp->suspend.stop_signal = TARGET_SIGNAL_0; + /* Advise target which signals may be handled silently. If we have + removed breakpoints because we are stepping over one (which can + happen only if we are not using displaced stepping), we need to + receive all signals to avoid accidentally skipping a breakpoint + during execution of a signal handler. */ + if ((step || singlestep_breakpoints_inserted_p) + && tp->control.trap_expected + && !use_displaced_stepping (gdbarch)) + target_pass_signals (0, NULL); + else + target_pass_signals ((int) TARGET_SIGNAL_LAST, signal_pass); + target_resume (resume_ptid, step, sig); } @@ -1929,6 +2018,12 @@ prepare_to_proceed (int step) /* Switch back to WAIT_PID thread. */ switch_to_thread (wait_ptid); + if (debug_infrun) + fprintf_unfiltered (gdb_stdlog, + "infrun: prepare_to_proceed (step=%d), " + "switched to [%s]\n", + step, target_pid_to_str (inferior_ptid)); + /* We return 1 to indicate that there is a breakpoint here, so we need to step over it before continuing to avoid hitting it straight away. */ @@ -1968,9 +2063,14 @@ proceed (CORE_ADDR addr, enum target_signal siggnal, int step) { /* The target for some reason decided not to resume. */ normal_stop (); + if (target_can_async_p ()) + inferior_event_handler (INF_EXEC_COMPLETE, NULL); return; } + /* We'll update this if & when we switch to a new thread. */ + previous_inferior_ptid = inferior_ptid; + regcache = get_current_regcache (); gdbarch = get_regcache_arch (regcache); aspace = get_regcache_aspace (regcache); @@ -2133,7 +2233,7 @@ proceed (CORE_ADDR addr, enum target_signal siggnal, int step) does not support asynchronous execution. */ if (!target_can_async_p ()) { - wait_for_inferior (0); + wait_for_inferior (); normal_stop (); } } @@ -2146,7 +2246,6 @@ start_remote (int from_tty) { struct inferior *inferior; - init_wait_for_inferior (); inferior = current_inferior (); inferior->control.stop_soon = STOP_QUIETLY_REMOTE; @@ -2164,7 +2263,7 @@ start_remote (int from_tty) target_open() return to the caller an indication that the target is currently running and GDB state should be set to the same as for an async run. */ - wait_for_inferior (0); + wait_for_inferior (); /* Now that the inferior has stopped, do any bookkeeping like loading shared libraries. We want to do this before normal_stop, @@ -2190,7 +2289,7 @@ init_wait_for_inferior (void) target_last_wait_ptid = minus_one_ptid; - previous_inferior_ptid = null_ptid; + previous_inferior_ptid = inferior_ptid; init_infwait_state (); /* Discard any skipped inlined frames. */ @@ -2240,12 +2339,6 @@ static void handle_step_into_function (struct gdbarch *gdbarch, struct execution_control_state *ecs); static void handle_step_into_function_backward (struct gdbarch *gdbarch, struct execution_control_state *ecs); -static void insert_step_resume_breakpoint_at_frame (struct frame_info *); -static void insert_step_resume_breakpoint_at_caller (struct frame_info *); -static void insert_step_resume_breakpoint_at_sal (struct gdbarch *, - struct symtab_and_line , - struct frame_id); -static void insert_longjmp_resume_breakpoint (struct gdbarch *, CORE_ADDR); static void check_exception_resume (struct execution_control_state *, struct frame_info *, struct symbol *); @@ -2299,12 +2392,10 @@ infrun_thread_stop_requested_callback (struct thread_info *info, void *arg) normal_stop (); - /* Finish off the continuations. The continations - themselves are responsible for realising the thread - didn't finish what it was supposed to do. */ + /* Finish off the continuations. */ tp = inferior_thread (); - do_all_intermediate_continuations_thread (tp); - do_all_continuations_thread (tp); + do_all_intermediate_continuations_thread (tp, 1); + do_all_continuations_thread (tp, 1); } do_cleanups (old_chain); @@ -2538,18 +2629,13 @@ prepare_for_detach (void) /* Wait for control to return from inferior to debugger. - If TREAT_EXEC_AS_SIGTRAP is non-zero, then handle EXEC signals - as if they were SIGTRAP signals. This can be useful during - the startup sequence on some targets such as HP/UX, where - we receive an EXEC event instead of the expected SIGTRAP. - If inferior gets a signal, we may decide to start it up again instead of returning. That is why there is a loop in this function. When this function actually returns it means the inferior should be left stopped and GDB should read more commands. */ void -wait_for_inferior (int treat_exec_as_sigtrap) +wait_for_inferior (void) { struct cleanup *old_cleanups; struct execution_control_state ecss; @@ -2557,8 +2643,7 @@ wait_for_inferior (int treat_exec_as_sigtrap) if (debug_infrun) fprintf_unfiltered - (gdb_stdlog, "infrun: wait_for_inferior (treat_exec_as_sigtrap=%d)\n", - treat_exec_as_sigtrap); + (gdb_stdlog, "infrun: wait_for_inferior ()\n"); old_cleanups = make_cleanup (delete_step_thread_step_resume_breakpoint_cleanup, NULL); @@ -2566,9 +2651,6 @@ wait_for_inferior (int treat_exec_as_sigtrap) ecs = &ecss; memset (ecs, 0, sizeof (*ecs)); - /* We'll update this if & when we switch to a new thread. */ - previous_inferior_ptid = inferior_ptid; - while (1) { struct cleanup *old_chain; @@ -2590,13 +2672,6 @@ wait_for_inferior (int treat_exec_as_sigtrap) 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); - ecs->ws.kind = TARGET_WAITKIND_STOPPED; - ecs->ws.value.sig = TARGET_SIGNAL_TRAP; - } - /* If an error happens while handling the event, propagate GDB's knowledge of the executing state to the frontend/user running state. */ @@ -2639,9 +2714,6 @@ fetch_inferior_event (void *client_data) memset (ecs, 0, sizeof (*ecs)); - /* We'll update this if & when we switch to a new thread. */ - previous_inferior_ptid = inferior_ptid; - /* We're handling a live event, so make sure we're doing live debugging. If we're looking at traceframes while the target is running, we're going to need to get back to that mode after @@ -2666,7 +2738,19 @@ fetch_inferior_event (void *client_data) status mechanism. */ overlay_cache_invalid = 1; - registers_changed (); + + /* But don't do it if the current thread is already stopped (hence + this is either a delayed event that will result in + TARGET_WAITKIND_IGNORE, or it's an event for another thread (and + we always clear the register and frame caches when the user + switches threads anyway). If we didn't do this, a spurious + delayed event in all-stop mode would make the user lose the + selected frame. */ + if (non_stop || is_executing (inferior_ptid)) + registers_changed (); + + make_cleanup_restore_integer (&execution_direction); + execution_direction = target_execution_direction (); if (deprecated_target_wait_hook) ecs->ptid = @@ -3005,7 +3089,6 @@ handle_inferior_event (struct execution_control_state *ecs) { struct frame_info *frame; struct gdbarch *gdbarch; - int sw_single_step_trap_p = 0; int stopped_by_watchpoint; int stepped_after_stopped_by_watchpoint = 0; struct symtab_and_line stop_pc_sal; @@ -3232,6 +3315,11 @@ handle_inferior_event (struct execution_control_state *ecs) that the user can inspect this again later. */ set_internalvar_integer (lookup_internalvar ("_exitcode"), (LONGEST) ecs->ws.value.integer); + + /* Also record this in the inferior itself. */ + current_inferior ()->has_exit_code = 1; + current_inferior ()->exit_code = (LONGEST) ecs->ws.value.integer; + gdb_flush (gdb_stdout); target_mourn_inferior (); singlestep_breakpoints_inserted_p = 0; @@ -3593,6 +3681,8 @@ handle_inferior_event (struct execution_control_state *ecs) singlestep_breakpoints_inserted_p = 0; } + ecs->event_thread->control.trap_expected = 0; + /* Note: We do not call context_switch at this point, as the context is already set up for stepping the original thread. */ switch_to_thread (deferred_step_ptid); @@ -3753,7 +3843,6 @@ handle_inferior_event (struct execution_control_state *ecs) } else if (singlestep_breakpoints_inserted_p) { - sw_single_step_trap_p = 1; ecs->random_signal = 0; } } @@ -3818,7 +3907,12 @@ handle_inferior_event (struct execution_control_state *ecs) int hw_step = 1; if (!target_have_steppable_watchpoint) - remove_breakpoints (); + { + remove_breakpoints (); + /* See comment in resume why we need to stop bypassing signals + while breakpoints have been removed. */ + target_pass_signals (0, NULL); + } /* Single step */ hw_step = maybe_software_singlestep (gdbarch, stop_pc); target_resume (ecs->ptid, hw_step, TARGET_SIGNAL_0); @@ -4088,8 +4182,10 @@ process_event_stop_test: "infrun: signal arrived while stepping over " "breakpoint\n"); - insert_step_resume_breakpoint_at_frame (frame); + insert_hp_step_resume_breakpoint_at_frame (frame); ecs->event_thread->step_after_step_resume_breakpoint = 1; + /* Reset trap_expected to ensure breakpoints are re-inserted. */ + ecs->event_thread->control.trap_expected = 0; keep_going (ecs); return; } @@ -4116,7 +4212,9 @@ process_event_stop_test: "infrun: signal may take us out of " "single-step range\n"); - insert_step_resume_breakpoint_at_frame (frame); + insert_hp_step_resume_breakpoint_at_frame (frame); + /* Reset trap_expected to ensure breakpoints are re-inserted. */ + ecs->event_thread->control.trap_expected = 0; keep_going (ecs); return; } @@ -4260,6 +4358,38 @@ process_event_stop_test: where we are stepping and step out of the right range. */ break; + case BPSTAT_WHAT_STEP_RESUME: + if (debug_infrun) + fprintf_unfiltered (gdb_stdlog, "infrun: BPSTAT_WHAT_STEP_RESUME\n"); + + delete_step_resume_breakpoint (ecs->event_thread); + if (ecs->event_thread->control.proceed_to_finish + && execution_direction == EXEC_REVERSE) + { + struct thread_info *tp = ecs->event_thread; + + /* We are finishing a function in reverse, and just hit + the step-resume breakpoint at the start address of the + function, and we're almost there -- just need to back + up by one more single-step, which should take us back + to the function call. */ + tp->control.step_range_start = tp->control.step_range_end = 1; + keep_going (ecs); + return; + } + if (stop_pc == ecs->stop_func_start + && execution_direction == EXEC_REVERSE) + { + /* We are stepping over a function call in reverse, and + just hit the step-resume breakpoint at the start + address of the function. Go back to single-stepping, + which should take us back to the function call. */ + ecs->event_thread->stepping_over_breakpoint = 1; + keep_going (ecs); + return; + } + break; + case BPSTAT_WHAT_STOP_NOISY: if (debug_infrun) fprintf_unfiltered (gdb_stdlog, "infrun: BPSTAT_WHAT_STOP_NOISY\n"); @@ -4282,9 +4412,9 @@ process_event_stop_test: stop_stepping (ecs); return; - case BPSTAT_WHAT_STEP_RESUME: + case BPSTAT_WHAT_HP_STEP_RESUME: if (debug_infrun) - fprintf_unfiltered (gdb_stdlog, "infrun: BPSTAT_WHAT_STEP_RESUME\n"); + fprintf_unfiltered (gdb_stdlog, "infrun: BPSTAT_WHAT_HP_STEP_RESUME\n"); delete_step_resume_breakpoint (ecs->event_thread); if (ecs->event_thread->step_after_step_resume_breakpoint) @@ -4297,17 +4427,6 @@ process_event_stop_test: keep_going (ecs); return; } - if (stop_pc == ecs->stop_func_start - && execution_direction == EXEC_REVERSE) - { - /* We are stepping over a function call in reverse, and - just hit the step-resume breakpoint at the start - address of the function. Go back to single-stepping, - which should take us back to the function call. */ - ecs->event_thread->stepping_over_breakpoint = 1; - keep_going (ecs); - return; - } break; case BPSTAT_WHAT_KEEP_CHECKING: @@ -4680,7 +4799,6 @@ process_event_stop_test: struct symtab_and_line tmp_sal; tmp_sal = find_pc_line (ecs->stop_func_start, 0); - tmp_sal.pspace = get_frame_program_space (frame); if (tmp_sal.line != 0) { if (execution_direction == EXEC_REVERSE) @@ -5120,14 +5238,16 @@ handle_step_into_function_backward (struct gdbarch *gdbarch, This is used to both functions and to skip over code. */ static void -insert_step_resume_breakpoint_at_sal (struct gdbarch *gdbarch, - struct symtab_and_line sr_sal, - struct frame_id sr_id) +insert_step_resume_breakpoint_at_sal_1 (struct gdbarch *gdbarch, + struct symtab_and_line sr_sal, + struct frame_id sr_id, + enum bptype sr_type) { /* There should never be more than one step-resume or longjmp-resume breakpoint per thread, so we should never be setting a new step_resume_breakpoint when one is already active. */ gdb_assert (inferior_thread ()->control.step_resume_breakpoint == NULL); + gdb_assert (sr_type == bp_step_resume || sr_type == bp_hp_step_resume); if (debug_infrun) fprintf_unfiltered (gdb_stdlog, @@ -5135,18 +5255,28 @@ insert_step_resume_breakpoint_at_sal (struct gdbarch *gdbarch, paddress (gdbarch, sr_sal.pc)); inferior_thread ()->control.step_resume_breakpoint - = set_momentary_breakpoint (gdbarch, sr_sal, sr_id, bp_step_resume); + = set_momentary_breakpoint (gdbarch, sr_sal, sr_id, sr_type); +} + +void +insert_step_resume_breakpoint_at_sal (struct gdbarch *gdbarch, + struct symtab_and_line sr_sal, + struct frame_id sr_id) +{ + insert_step_resume_breakpoint_at_sal_1 (gdbarch, + sr_sal, sr_id, + bp_step_resume); } -/* Insert a "step-resume breakpoint" at RETURN_FRAME.pc. This is used - to skip a potential signal handler. +/* Insert a "high-priority step-resume breakpoint" at RETURN_FRAME.pc. + This is used to skip a potential signal handler. This is called with the interrupted function's frame. The signal handler, when it returns, will resume the interrupted function at RETURN_FRAME.pc. */ static void -insert_step_resume_breakpoint_at_frame (struct frame_info *return_frame) +insert_hp_step_resume_breakpoint_at_frame (struct frame_info *return_frame) { struct symtab_and_line sr_sal; struct gdbarch *gdbarch; @@ -5159,14 +5289,14 @@ insert_step_resume_breakpoint_at_frame (struct frame_info *return_frame) sr_sal.section = find_pc_overlay (sr_sal.pc); sr_sal.pspace = get_frame_program_space (return_frame); - insert_step_resume_breakpoint_at_sal (gdbarch, sr_sal, - get_stack_frame_id (return_frame)); + insert_step_resume_breakpoint_at_sal_1 (gdbarch, sr_sal, + get_stack_frame_id (return_frame), + bp_hp_step_resume); } -/* Similar to insert_step_resume_breakpoint_at_frame, except - but a breakpoint at the previous frame's PC. This is used to - skip a function after stepping into it (for "next" or if the called - function has no debugging information). +/* Insert a "step-resume breakpoint" at the previous frame's PC. This + is used to skip a function after stepping into it (for "next" or if + the called function has no debugging information). The current function has almost always been reached by single stepping a call or return instruction. NEXT_FRAME belongs to the @@ -5174,7 +5304,7 @@ insert_step_resume_breakpoint_at_frame (struct frame_info *return_frame) resume address. This is a separate function rather than reusing - insert_step_resume_breakpoint_at_frame in order to avoid + insert_hp_step_resume_breakpoint_at_frame in order to avoid get_prev_frame, which may stop prematurely (see the implementation of frame_unwind_caller_id for an example). */ @@ -5488,22 +5618,33 @@ print_signal_exited_reason (enum target_signal siggnal) static void print_exited_reason (int exitstatus) { + struct inferior *inf = current_inferior (); + const char *pidstr = target_pid_to_str (pid_to_ptid (inf->pid)); + annotate_exited (exitstatus); if (exitstatus) { if (ui_out_is_mi_like_p (uiout)) ui_out_field_string (uiout, "reason", async_reason_lookup (EXEC_ASYNC_EXITED)); - ui_out_text (uiout, "\nProgram exited with code "); + ui_out_text (uiout, "[Inferior "); + ui_out_text (uiout, plongest (inf->num)); + ui_out_text (uiout, " ("); + ui_out_text (uiout, pidstr); + ui_out_text (uiout, ") exited with code "); ui_out_field_fmt (uiout, "exit-code", "0%o", (unsigned int) exitstatus); - ui_out_text (uiout, ".\n"); + ui_out_text (uiout, "]\n"); } else { if (ui_out_is_mi_like_p (uiout)) ui_out_field_string (uiout, "reason", async_reason_lookup (EXEC_ASYNC_EXITED_NORMALLY)); - ui_out_text (uiout, "\nProgram exited normally.\n"); + ui_out_text (uiout, "[Inferior "); + ui_out_text (uiout, plongest (inf->num)); + ui_out_text (uiout, " ("); + ui_out_text (uiout, pidstr); + ui_out_text (uiout, ") exited normally]\n"); } /* Support the --return-child-result option. */ return_child_result_value = exitstatus; @@ -5741,7 +5882,8 @@ normal_stop (void) /* Save the function value return registers, if we care. We might be about to restore their previous contents. */ - if (inferior_thread ()->control.proceed_to_finish) + if (inferior_thread ()->control.proceed_to_finish + && execution_direction != EXEC_REVERSE) { /* This should not be necessary. */ if (stop_registers) @@ -5843,12 +5985,29 @@ signal_pass_state (int signo) return signal_program[signo]; } +static void +signal_cache_update (int signo) +{ + if (signo == -1) + { + for (signo = 0; signo < (int) TARGET_SIGNAL_LAST; signo++) + signal_cache_update (signo); + + return; + } + + signal_pass[signo] = (signal_stop[signo] == 0 + && signal_print[signo] == 0 + && signal_program[signo] == 1); +} + int signal_stop_update (int signo, int state) { int ret = signal_stop[signo]; signal_stop[signo] = state; + signal_cache_update (signo); return ret; } @@ -5858,6 +6017,7 @@ signal_print_update (int signo, int state) int ret = signal_print[signo]; signal_print[signo] = state; + signal_cache_update (signo); return ret; } @@ -5867,6 +6027,7 @@ signal_pass_update (int signo, int state) int ret = signal_program[signo]; signal_program[signo] = state; + signal_cache_update (signo); return ret; } @@ -6058,7 +6219,8 @@ Are you sure you want to change it? "), for (signum = 0; signum < nsigs; signum++) if (sigs[signum]) { - target_notice_signals (inferior_ptid); + signal_cache_update (-1); + target_pass_signals ((int) TARGET_SIGNAL_LAST, signal_pass); if (from_tty) { @@ -6186,7 +6348,7 @@ signals_info (char *signum_exp, int from_tty) /* 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 + fetch the data. The type can change depending on gdbarch, so it is also dependent on which thread you have selected. 1. making $_siginfo be an internalvar that creates a new value on @@ -6232,7 +6394,7 @@ siginfo_value_write (struct value *v, struct value *fromval) error (_("Unable to write siginfo")); } -static struct lval_funcs siginfo_value_funcs = +static const struct lval_funcs siginfo_value_funcs = { siginfo_value_read, siginfo_value_write @@ -6686,11 +6848,6 @@ ptid_is_pid (ptid_t ptid) int ptid_match (ptid_t ptid, ptid_t filter) { - /* Since both parameters have the same type, prevent easy mistakes - from happening. */ - gdb_assert (!ptid_equal (ptid, minus_one_ptid) - && !ptid_equal (ptid, null_ptid)); - if (ptid_equal (filter, minus_one_ptid)) return 1; if (ptid_is_pid (filter) @@ -6734,7 +6891,7 @@ save_inferior_ptid (void) Set exec-direction / show exec-direction commands (returns error unless target implements to_set_exec_direction method). */ -enum exec_direction_kind execution_direction = EXEC_FORWARD; +int execution_direction = EXEC_FORWARD; static const char exec_forward[] = "forward"; static const char exec_reverse[] = "reverse"; static const char *exec_direction = exec_forward; @@ -6773,12 +6930,10 @@ show_exec_direction_func (struct ui_file *out, int from_tty, case EXEC_REVERSE: fprintf_filtered (out, _("Reverse.\n")); break; - case EXEC_ERROR: default: - fprintf_filtered (out, _("Forward (target `%s' does not " - "support exec-direction).\n"), - target_shortname); - break; + internal_error (__FILE__, __LINE__, + _("bogus execution_direction value: %d"), + (int) execution_direction); } } @@ -6915,6 +7070,8 @@ leave it stopped or free to run as needed."), xmalloc (sizeof (signal_print[0]) * numsigs); signal_program = (unsigned char *) xmalloc (sizeof (signal_program[0]) * numsigs); + signal_pass = (unsigned char *) + xmalloc (sizeof (signal_program[0]) * numsigs); for (i = 0; i < numsigs; i++) { signal_stop[i] = 1; @@ -6958,6 +7115,9 @@ leave it stopped or free to run as needed."), signal_stop[TARGET_SIGNAL_CANCEL] = 0; signal_print[TARGET_SIGNAL_CANCEL] = 0; + /* Update cached state. */ + signal_cache_update (-1); + add_setshow_zinteger_cmd ("stop-on-solib-events", class_support, &stop_on_solib_events, _("\ Set stopping for shared library events."), _("\