X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Finfrun.c;h=51a032b8ae5aba39ab7ba6c8ad5edca138c0244a;hb=f9e148520a52325c43e325984cd1cfea952b8ad8;hp=54794867260197338644707dd1aa3ee67f4e87b7;hpb=47b1906506da6096ba01fcc66f712d89feb312c9;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/infrun.c b/gdb/infrun.c index 5479486726..51a032b8ae 100644 --- a/gdb/infrun.c +++ b/gdb/infrun.c @@ -1,7 +1,7 @@ /* Target-struct-independent code to start (run) and stop an inferior process. - Copyright (C) 1986-2012 Free Software Foundation, Inc. + Copyright (C) 1986-2013 Free Software Foundation, Inc. This file is part of GDB. @@ -49,6 +49,7 @@ #include "mi/mi-common.h" #include "event-top.h" #include "record.h" +#include "record-full.h" #include "inline-frame.h" #include "jit.h" #include "tracepoint.h" @@ -58,6 +59,7 @@ #include "probe.h" #include "objfiles.h" #include "completer.h" +#include "target-descriptions.h" /* Prototypes for local functions */ @@ -317,6 +319,12 @@ static unsigned char *signal_stop; static unsigned char *signal_print; static unsigned char *signal_program; +/* Table of signals that are registered with "catch signal". A + non-zero entry indicates that the signal is caught by some "catch + signal" command. This has size GDB_SIGNAL_LAST, to accommodate all + signals. */ +static unsigned char *signal_catch; + /* Table of signals that the target may silently handle. This is automatically determined from the flags above, and simply cached here. */ @@ -362,6 +370,16 @@ static struct symbol *step_start_function; /* Nonzero if we want to give control to the user when we're notified of shared library events by the dynamic linker. */ int stop_on_solib_events; + +/* Enable or disable optional shared library event breakpoints + as appropriate when the above flag is changed. */ + +static void +set_stop_on_solib_events (char *args, int from_tty, struct cmd_list_element *c) +{ + update_solib_breakpoints (); +} + static void show_stop_on_solib_events (struct ui_file *file, int from_tty, struct cmd_list_element *c, const char *value) @@ -396,7 +414,7 @@ static void context_switch (ptid_t ptid); void init_thread_stepping_state (struct thread_info *tss); -void init_infwait_state (void); +static void init_infwait_state (void); static const char follow_fork_mode_child[] = "child"; static const char follow_fork_mode_parent[] = "parent"; @@ -663,7 +681,18 @@ handle_vfork_child_exec_or_exit (int exec) /* follow-fork child, detach-on-fork on. */ - old_chain = make_cleanup_restore_current_thread (); + inf->vfork_parent->pending_detach = 0; + + if (!exec) + { + /* If we're handling a child exit, then inferior_ptid + points at the inferior's pid, not to a thread. */ + old_chain = save_inferior_ptid (); + save_current_program_space (); + save_current_inferior (); + } + else + old_chain = save_current_space_and_thread (); /* We're letting loose of the parent. */ tp = any_live_thread_of_process (inf->vfork_parent->pid); @@ -787,7 +816,7 @@ handle_vfork_child_exec_or_exit (int exec) } } -/* Enum strings for "set|show displaced-stepping". */ +/* Enum strings for "set|show follow-exec-mode". */ static const char follow_exec_mode_new[] = "new"; static const char follow_exec_mode_same[] = "same"; @@ -902,6 +931,16 @@ follow_exec (ptid_t pid, char *execd_pathname) set_current_inferior (inf); set_current_program_space (pspace); } + else + { + /* The old description may no longer be fit for the new image. + E.g, a 64-bit process exec'ed a 32-bit process. Clear the + old description; we'll read a new one below. No need to do + this on "follow-exec-mode new", as the old inferior stays + around (its description is later cleared/refetched on + restart). */ + target_clear_description (); + } gdb_assert (current_program_space == inf->pspace); @@ -921,11 +960,15 @@ follow_exec (ptid_t pid, char *execd_pathname) if ((inf->symfile_flags & SYMFILE_NO_READ) == 0) set_initial_language (); -#ifdef SOLIB_CREATE_INFERIOR_HOOK - SOLIB_CREATE_INFERIOR_HOOK (PIDGET (inferior_ptid)); -#else + /* If the target can specify a description, read it. Must do this + after flipping to the new executable (because the target supplied + description must be compatible with the executable's + architecture, and the old executable may e.g., be 32-bit, while + the new one 64-bit), and before anything involving memory or + registers. */ + target_find_description (); + solib_create_inferior_hook (0); -#endif jit_inferior_created_hook (); @@ -1278,6 +1321,7 @@ static int displaced_step_prepare (ptid_t ptid) { struct cleanup *old_cleanups, *ignore_cleanups; + struct thread_info *tp = find_thread_ptid (ptid); struct regcache *regcache = get_thread_regcache (ptid); struct gdbarch *gdbarch = get_regcache_arch (regcache); CORE_ADDR original, copy; @@ -1290,6 +1334,12 @@ displaced_step_prepare (ptid_t ptid) support displaced stepping. */ gdb_assert (gdbarch_displaced_step_copy_insn_p (gdbarch)); + /* Disable range stepping while executing in the scratch pad. We + want a single-step even if executing the displaced instruction in + the scratch buffer lands within the stepping range (e.g., a + jump/branch). */ + tp->control.may_range_step = 0; + /* We have to displaced step one thread at a time, as we only have access to a single scratch space per inferior. */ @@ -1745,6 +1795,11 @@ how to step past a permanent breakpoint on this architecture. Try using\n\ a command like `return' or `jump' to continue execution.")); } + /* If we have a breakpoint to step over, make sure to do a single + step only. Same if we have software watchpoints. */ + if (tp->control.trap_expected || bpstat_should_step ()) + tp->control.may_range_step = 0; + /* If enabled, step over breakpoints by executing a copy of the instruction at a different address. @@ -1906,6 +1961,16 @@ a command like `return' or `jump' to continue execution.")); displaced_step_dump_bytes (gdb_stdlog, buf, sizeof (buf)); } + if (tp->control.may_range_step) + { + /* If we're resuming a thread with the PC out of the step + range, then we're doing some nested/finer run control + operation, like stepping the thread out of the dynamic + linker or the displaced stepping scratch pad. We + shouldn't have allowed a range step then. */ + gdb_assert (pc_in_thread_step_range (pc, tp)); + } + /* Install inferior's terminal modes. */ target_terminal_inferior (); @@ -1947,6 +2012,7 @@ clear_proceed_status_thread (struct thread_info *tp) tp->control.trap_expected = 0; tp->control.step_range_start = 0; tp->control.step_range_end = 0; + tp->control.may_range_step = 0; tp->control.step_frame_id = null_frame_id; tp->control.step_stack_frame_id = null_frame_id; tp->control.step_over_calls = STEP_OVER_UNDEBUGGABLE; @@ -2103,7 +2169,8 @@ proceed (CORE_ADDR addr, enum gdb_signal siggnal, int step) struct thread_info *tp; CORE_ADDR pc; struct address_space *aspace; - int oneproc = 0; + /* GDB may force the inferior to step due to various reasons. */ + int force_step = 0; /* If we're stopped at a fork/vfork, follow the branch set by the "set follow-fork-mode" command; otherwise, we'll just proceed @@ -2143,13 +2210,13 @@ proceed (CORE_ADDR addr, enum gdb_signal siggnal, int step) actually be executing the breakpoint insn anyway. We'll be (un-)executing the previous instruction. */ - oneproc = 1; + force_step = 1; else if (gdbarch_single_step_through_delay_p (gdbarch) && gdbarch_single_step_through_delay (gdbarch, get_current_frame ())) /* We stepped onto an instruction that needs to be stepped again before re-inserting the breakpoint, do so. */ - oneproc = 1; + force_step = 1; } else { @@ -2180,13 +2247,13 @@ proceed (CORE_ADDR addr, enum gdb_signal siggnal, int step) is required it returns TRUE and sets the current thread to the old thread. */ if (prepare_to_proceed (step)) - oneproc = 1; + force_step = 1; } /* prepare_to_proceed may change the current thread. */ tp = inferior_thread (); - if (oneproc) + if (force_step) { tp->control.trap_expected = 1; /* If displaced stepping is enabled, we can step over the @@ -2274,7 +2341,8 @@ proceed (CORE_ADDR addr, enum gdb_signal siggnal, int step) init_infwait_state (); /* Resume inferior. */ - resume (oneproc || step || bpstat_should_step (), tp->suspend.stop_signal); + resume (force_step || step || bpstat_should_step (), + tp->suspend.stop_signal); /* Wait for it to stop (if not standalone) and in any case decode why it stopped, and act accordingly. */ @@ -2362,7 +2430,7 @@ enum infwait_states ptid_t waiton_ptid; /* Current inferior wait state. */ -enum infwait_states infwait_state; +static enum infwait_states infwait_state; /* Data to be passed around while handling an event. This data is discarded between events. */ @@ -2969,10 +3037,10 @@ adjust_pc_after_break (struct execution_control_state *ecs) if (software_breakpoint_inserted_here_p (aspace, breakpoint_pc) || (non_stop && moribund_breakpoint_here_p (aspace, breakpoint_pc))) { - struct cleanup *old_cleanups = NULL; + struct cleanup *old_cleanups = make_cleanup (null_cleanup, NULL); if (RECORD_IS_USED) - old_cleanups = record_gdb_operation_disable_set (); + record_full_gdb_operation_disable_set (); /* When using hardware single-step, a SIGTRAP is reported for both a completed single-step and a software breakpoint. Need to @@ -2998,32 +3066,17 @@ adjust_pc_after_break (struct execution_control_state *ecs) || ecs->event_thread->prev_pc == breakpoint_pc) regcache_write_pc (regcache, breakpoint_pc); - if (RECORD_IS_USED) - do_cleanups (old_cleanups); + do_cleanups (old_cleanups); } } -void +static void init_infwait_state (void) { waiton_ptid = pid_to_ptid (-1); infwait_state = infwait_normal_state; } -void -error_is_running (void) -{ - error (_("Cannot execute this command while " - "the selected thread is running.")); -} - -void -ensure_not_running (void) -{ - if (is_running (inferior_ptid)) - error_is_running (); -} - static int stepped_in_from (struct frame_info *frame, struct frame_id step_frame_id) { @@ -3049,20 +3102,20 @@ static int handle_syscall_event (struct execution_control_state *ecs) { struct regcache *regcache; - struct gdbarch *gdbarch; int syscall_number; if (!ptid_equal (ecs->ptid, inferior_ptid)) context_switch (ecs->ptid); regcache = get_thread_regcache (ecs->ptid); - gdbarch = get_regcache_arch (regcache); syscall_number = ecs->ws.value.syscall_number; stop_pc = regcache_read_pc (regcache); if (catch_syscall_enabled () > 0 && catching_syscall_number (syscall_number) > 0) { + enum bpstat_signal_value sval; + if (debug_infrun) fprintf_unfiltered (gdb_stdlog, "infrun: syscall number = '%d'\n", syscall_number); @@ -3070,8 +3123,9 @@ handle_syscall_event (struct execution_control_state *ecs) ecs->event_thread->control.stop_bpstat = bpstat_stop_status (get_regcache_aspace (regcache), stop_pc, ecs->ptid, &ecs->ws); - ecs->random_signal - = !bpstat_explains_signal (ecs->event_thread->control.stop_bpstat); + + sval = bpstat_explains_signal (ecs->event_thread->control.stop_bpstat); + ecs->random_signal = sval == BPSTAT_SIGNAL_NO; if (!ecs->random_signal) { @@ -3201,6 +3255,10 @@ handle_inferior_event (struct execution_control_state *ecs) /* If it's a new thread, add it to the thread database. */ if (ecs->event_thread == NULL) ecs->event_thread = add_thread (ecs->ptid); + + /* Disable range stepping. If the next step request could use a + range, this will be end up re-enabled then. */ + ecs->event_thread->control.may_range_step = 0; } /* Dependent on valid ECS->EVENT_THREAD. */ @@ -3303,6 +3361,7 @@ handle_inferior_event (struct execution_control_state *ecs) if (stop_soon == NO_STOP_QUIETLY) { struct regcache *regcache; + enum bpstat_signal_value sval; if (!ptid_equal (ecs->ptid, inferior_ptid)) context_switch (ecs->ptid); @@ -3313,8 +3372,10 @@ handle_inferior_event (struct execution_control_state *ecs) ecs->event_thread->control.stop_bpstat = bpstat_stop_status (get_regcache_aspace (regcache), stop_pc, ecs->ptid, &ecs->ws); - ecs->random_signal - = !bpstat_explains_signal (ecs->event_thread->control.stop_bpstat); + + sval + = bpstat_explains_signal (ecs->event_thread->control.stop_bpstat); + ecs->random_signal = sval == BPSTAT_SIGNAL_NO; if (!ecs->random_signal) { @@ -3370,23 +3431,38 @@ handle_inferior_event (struct execution_control_state *ecs) return; case TARGET_WAITKIND_EXITED: + case TARGET_WAITKIND_SIGNALLED: if (debug_infrun) - fprintf_unfiltered (gdb_stdlog, "infrun: TARGET_WAITKIND_EXITED\n"); + { + if (ecs->ws.kind == TARGET_WAITKIND_EXITED) + fprintf_unfiltered (gdb_stdlog, + "infrun: TARGET_WAITKIND_EXITED\n"); + else + fprintf_unfiltered (gdb_stdlog, + "infrun: TARGET_WAITKIND_SIGNALLED\n"); + } + inferior_ptid = ecs->ptid; set_current_inferior (find_inferior_pid (ptid_get_pid (ecs->ptid))); set_current_program_space (current_inferior ()->pspace); handle_vfork_child_exec_or_exit (0); target_terminal_ours (); /* Must do this before mourn anyway. */ - print_exited_reason (ecs->ws.value.integer); - /* Record the exit code in the convenience variable $_exitcode, so - that the user can inspect this again later. */ - set_internalvar_integer (lookup_internalvar ("_exitcode"), - (LONGEST) ecs->ws.value.integer); + if (ecs->ws.kind == TARGET_WAITKIND_EXITED) + { + /* Record the exit code in the convenience variable $_exitcode, so + 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; - /* Also record this in the inferior itself. */ - current_inferior ()->has_exit_code = 1; - current_inferior ()->exit_code = (LONGEST) ecs->ws.value.integer; + print_exited_reason (ecs->ws.value.integer); + } + else + print_signal_exited_reason (ecs->ws.value.sig); gdb_flush (gdb_stdout); target_mourn_inferior (); @@ -3396,24 +3472,6 @@ handle_inferior_event (struct execution_control_state *ecs) stop_stepping (ecs); return; - case TARGET_WAITKIND_SIGNALLED: - if (debug_infrun) - fprintf_unfiltered (gdb_stdlog, "infrun: TARGET_WAITKIND_SIGNALLED\n"); - inferior_ptid = ecs->ptid; - set_current_inferior (find_inferior_pid (ptid_get_pid (ecs->ptid))); - set_current_program_space (current_inferior ()->pspace); - handle_vfork_child_exec_or_exit (0); - stop_print_frame = 0; - target_terminal_ours (); /* Must do this before mourn anyway. */ - - target_mourn_inferior (); - - print_signal_exited_reason (ecs->ws.value.sig); - singlestep_breakpoints_inserted_p = 0; - cancel_single_step_breakpoints (); - stop_stepping (ecs); - return; - /* The following are the only cases in which we keep going; the above cases end in a continue or goto. */ case TARGET_WAITKIND_FORKED: @@ -3615,7 +3673,8 @@ handle_inferior_event (struct execution_control_state *ecs) = bpstat_stop_status (get_regcache_aspace (get_current_regcache ()), stop_pc, ecs->ptid, &ecs->ws); ecs->random_signal - = !bpstat_explains_signal (ecs->event_thread->control.stop_bpstat); + = (bpstat_explains_signal (ecs->event_thread->control.stop_bpstat) + == BPSTAT_SIGNAL_NO); /* Note that this may be referenced from inside bpstat_stop_status above, through inferior_has_execd. */ @@ -3756,7 +3815,7 @@ handle_inferior_event (struct execution_control_state *ecs) context_switch (saved_singlestep_ptid); if (deprecated_context_hook) - deprecated_context_hook (pid_to_thread_id (ecs->ptid)); + deprecated_context_hook (pid_to_thread_id (saved_singlestep_ptid)); resume (1, GDB_SIGNAL_0); prepare_to_wait (ecs); @@ -4120,128 +4179,121 @@ handle_inferior_event (struct execution_control_state *ecs) will be made according to the signal handling tables. */ if (ecs->event_thread->suspend.stop_signal == GDB_SIGNAL_TRAP - || stop_soon == STOP_QUIETLY || stop_soon == STOP_QUIETLY_NO_SIGSTOP - || stop_soon == STOP_QUIETLY_REMOTE) + && stop_after_trap) { - if (ecs->event_thread->suspend.stop_signal == GDB_SIGNAL_TRAP - && stop_after_trap) - { - if (debug_infrun) - fprintf_unfiltered (gdb_stdlog, "infrun: stopped\n"); - stop_print_frame = 0; - stop_stepping (ecs); - return; - } - - /* This is originated from start_remote(), start_inferior() and - shared libraries hook functions. */ - if (stop_soon == STOP_QUIETLY || stop_soon == STOP_QUIETLY_REMOTE) - { - if (debug_infrun) - fprintf_unfiltered (gdb_stdlog, "infrun: quietly stopped\n"); - stop_stepping (ecs); - return; - } + if (debug_infrun) + fprintf_unfiltered (gdb_stdlog, "infrun: stopped\n"); + stop_print_frame = 0; + stop_stepping (ecs); + return; + } - /* This originates from attach_command(). We need to overwrite - the stop_signal here, because some kernels don't ignore a - SIGSTOP in a subsequent ptrace(PTRACE_CONT,SIGSTOP) call. - See more comments in inferior.h. On the other hand, if we - get a non-SIGSTOP, report it to the user - assume the backend - will handle the SIGSTOP if it should show up later. - - Also consider that the attach is complete when we see a - SIGTRAP. Some systems (e.g. Windows), and stubs supporting - target extended-remote report it instead of a SIGSTOP - (e.g. gdbserver). We already rely on SIGTRAP being our - signal, so this is no exception. - - Also consider that the attach is complete when we see a - GDB_SIGNAL_0. In non-stop mode, GDB will explicitly tell - the target to stop all threads of the inferior, in case the - low level attach operation doesn't stop them implicitly. If - they weren't stopped implicitly, then the stub will report a - GDB_SIGNAL_0, meaning: stopped for no particular reason - other than GDB's request. */ - if (stop_soon == STOP_QUIETLY_NO_SIGSTOP - && (ecs->event_thread->suspend.stop_signal == GDB_SIGNAL_STOP - || ecs->event_thread->suspend.stop_signal == GDB_SIGNAL_TRAP - || ecs->event_thread->suspend.stop_signal == GDB_SIGNAL_0)) - { - stop_stepping (ecs); - ecs->event_thread->suspend.stop_signal = GDB_SIGNAL_0; - return; - } + /* This is originated from start_remote(), start_inferior() and + shared libraries hook functions. */ + if (stop_soon == STOP_QUIETLY || stop_soon == STOP_QUIETLY_REMOTE) + { + if (debug_infrun) + fprintf_unfiltered (gdb_stdlog, "infrun: quietly stopped\n"); + stop_stepping (ecs); + return; + } - /* See if there is a breakpoint/watchpoint/catchpoint/etc. that - handles this event. */ - ecs->event_thread->control.stop_bpstat - = bpstat_stop_status (get_regcache_aspace (get_current_regcache ()), - stop_pc, ecs->ptid, &ecs->ws); + /* This originates from attach_command(). We need to overwrite + the stop_signal here, because some kernels don't ignore a + SIGSTOP in a subsequent ptrace(PTRACE_CONT,SIGSTOP) call. + See more comments in inferior.h. On the other hand, if we + get a non-SIGSTOP, report it to the user - assume the backend + will handle the SIGSTOP if it should show up later. + + Also consider that the attach is complete when we see a + SIGTRAP. Some systems (e.g. Windows), and stubs supporting + target extended-remote report it instead of a SIGSTOP + (e.g. gdbserver). We already rely on SIGTRAP being our + signal, so this is no exception. + + Also consider that the attach is complete when we see a + GDB_SIGNAL_0. In non-stop mode, GDB will explicitly tell + the target to stop all threads of the inferior, in case the + low level attach operation doesn't stop them implicitly. If + they weren't stopped implicitly, then the stub will report a + GDB_SIGNAL_0, meaning: stopped for no particular reason + other than GDB's request. */ + if (stop_soon == STOP_QUIETLY_NO_SIGSTOP + && (ecs->event_thread->suspend.stop_signal == GDB_SIGNAL_STOP + || ecs->event_thread->suspend.stop_signal == GDB_SIGNAL_TRAP + || ecs->event_thread->suspend.stop_signal == GDB_SIGNAL_0)) + { + stop_stepping (ecs); + ecs->event_thread->suspend.stop_signal = GDB_SIGNAL_0; + return; + } - /* Following in case break condition called a - 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->suspend.stop_signal == GDB_SIGNAL_TRAP - && !bpstat_explains_signal (ecs->event_thread->control.stop_bpstat) - && stopped_by_watchpoint) - fprintf_unfiltered (gdb_stdlog, - "infrun: no user watchpoint explains " - "watchpoint SIGTRAP, ignoring\n"); + /* See if there is a breakpoint/watchpoint/catchpoint/etc. that + handles this event. */ + ecs->event_thread->control.stop_bpstat + = bpstat_stop_status (get_regcache_aspace (get_current_regcache ()), + stop_pc, ecs->ptid, &ecs->ws); - /* 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 - comment, that went with the test, read: + /* Following in case break condition called a + function. */ + stop_print_frame = 1; - ``End of a stack dummy. Some systems (e.g. Sony news) give - another signal besides SIGTRAP, so check here as well as - above.'' + /* 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->suspend.stop_signal == GDB_SIGNAL_TRAP + && (bpstat_explains_signal (ecs->event_thread->control.stop_bpstat) + == BPSTAT_SIGNAL_NO) + && stopped_by_watchpoint) + fprintf_unfiltered (gdb_stdlog, + "infrun: no user watchpoint explains " + "watchpoint SIGTRAP, ignoring\n"); - If someone ever tries to get call dummys on a - non-executable stack to work (where the target would stop - with something like a SIGSEGV), then those tests might need - to be re-instated. Given, however, that the tests were only - enabled when momentary breakpoints were not being used, I - suspect that it won't be the case. + /* 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 + comment, that went with the test, read: - NOTE: kettenis/2004-02-05: Indeed such checks don't seem to - be necessary for call dummies on a non-executable stack on - SPARC. */ + ``End of a stack dummy. Some systems (e.g. Sony news) give + another signal besides SIGTRAP, so check here as well as + above.'' - if (ecs->event_thread->suspend.stop_signal == GDB_SIGNAL_TRAP) - ecs->random_signal - = !(bpstat_explains_signal (ecs->event_thread->control.stop_bpstat) - || stopped_by_watchpoint - || ecs->event_thread->control.trap_expected - || (ecs->event_thread->control.step_range_end - && (ecs->event_thread->control.step_resume_breakpoint - == NULL))); - else - { - ecs->random_signal = !bpstat_explains_signal - (ecs->event_thread->control.stop_bpstat); - if (!ecs->random_signal) - ecs->event_thread->suspend.stop_signal = GDB_SIGNAL_TRAP; - } - } + If someone ever tries to get call dummys on a + non-executable stack to work (where the target would stop + with something like a SIGSEGV), then those tests might need + to be re-instated. Given, however, that the tests were only + enabled when momentary breakpoints were not being used, I + suspect that it won't be the case. - /* When we reach this point, we've pretty much decided - that the reason for stopping must've been a random - (unexpected) signal. */ + NOTE: kettenis/2004-02-05: Indeed such checks don't seem to + be necessary for call dummies on a non-executable stack on + SPARC. */ + if (ecs->event_thread->suspend.stop_signal == GDB_SIGNAL_TRAP) + ecs->random_signal + = !((bpstat_explains_signal (ecs->event_thread->control.stop_bpstat) + != BPSTAT_SIGNAL_NO) + || stopped_by_watchpoint + || ecs->event_thread->control.trap_expected + || (ecs->event_thread->control.step_range_end + && (ecs->event_thread->control.step_resume_breakpoint + == NULL))); else - ecs->random_signal = 1; + { + enum bpstat_signal_value sval; + + sval = bpstat_explains_signal (ecs->event_thread->control.stop_bpstat); + ecs->random_signal = (sval == BPSTAT_SIGNAL_NO); + + if (sval == BPSTAT_SIGNAL_HIDE) + ecs->event_thread->suspend.stop_signal = GDB_SIGNAL_TRAP; + } process_event_stop_test: @@ -4321,8 +4373,7 @@ process_event_stop_test: if (ecs->event_thread->control.step_range_end != 0 && ecs->event_thread->suspend.stop_signal != GDB_SIGNAL_0 - && (ecs->event_thread->control.step_range_start <= stop_pc - && stop_pc < ecs->event_thread->control.step_range_end) + && pc_in_thread_step_range (stop_pc, ecs->event_thread) && frame_id_eq (get_stack_frame_id (frame), ecs->event_thread->control.step_stack_frame_id) && ecs->event_thread->control.step_resume_breakpoint == NULL) @@ -4691,8 +4742,7 @@ process_event_stop_test: through a function epilogue and therefore must detect when the current-frame changes in the middle of a line. */ - if (stop_pc >= ecs->event_thread->control.step_range_start - && stop_pc < ecs->event_thread->control.step_range_end + if (pc_in_thread_step_range (stop_pc, ecs->event_thread) && (execution_direction != EXEC_REVERSE || frame_id_eq (get_frame_id (frame), ecs->event_thread->control.step_frame_id))) @@ -4703,6 +4753,11 @@ process_event_stop_test: paddress (gdbarch, ecs->event_thread->control.step_range_start), paddress (gdbarch, ecs->event_thread->control.step_range_end)); + /* Tentatively re-enable range stepping; `resume' disables it if + necessary (e.g., if we're stepping over a breakpoint or we + have software watchpoints). */ + ecs->event_thread->control.may_range_step = 1; + /* When stepping backward, stop at beginning of line range (unless it's the function entry point, in which case keep going back to the call point). */ @@ -4963,7 +5018,8 @@ process_event_stop_test: tmp_sal = find_pc_line (ecs->stop_func_start, 0); if (tmp_sal.line != 0 - && !function_pc_is_marked_for_skip (ecs->stop_func_start)) + && !function_name_is_marked_for_skip (ecs->stop_func_name, + &tmp_sal)) { if (execution_direction == EXEC_REVERSE) handle_step_into_function_backward (gdbarch, ecs); @@ -5218,6 +5274,7 @@ process_event_stop_test: ecs->event_thread->control.step_range_start = stop_pc_sal.pc; ecs->event_thread->control.step_range_end = stop_pc_sal.end; + ecs->event_thread->control.may_range_step = 1; set_step_info (frame, stop_pc_sal); if (debug_infrun) @@ -6191,7 +6248,8 @@ signal_cache_update (int signo) signal_pass[signo] = (signal_stop[signo] == 0 && signal_print[signo] == 0 - && signal_program[signo] == 1); + && signal_program[signo] == 1 + && signal_catch[signo] == 0); } int @@ -6224,6 +6282,20 @@ signal_pass_update (int signo, int state) return ret; } +/* Update the global 'signal_catch' from INFO and notify the + target. */ + +void +signal_catch_update (const unsigned int *info) +{ + int i; + + for (i = 0; i < GDB_SIGNAL_LAST; ++i) + signal_catch[i] = info[i] > 0; + signal_cache_update (-1); + target_pass_signals ((int) GDB_SIGNAL_LAST, signal_pass); +} + static void sig_print_header (void) { @@ -6435,7 +6507,7 @@ Are you sure you want to change it? "), static VEC (char_ptr) * handle_completer (struct cmd_list_element *ignore, - char *text, char *word) + const char *text, const char *word) { VEC (char_ptr) *vec_signals, *vec_keywords, *return_val; static const char * const keywords[] = @@ -6708,7 +6780,9 @@ save_infcall_suspend_state (void) { struct infcall_suspend_state *inf_state; struct thread_info *tp = inferior_thread (); +#if 0 struct inferior *inf = current_inferior (); +#endif struct regcache *regcache = get_current_regcache (); struct gdbarch *gdbarch = get_regcache_arch (regcache); gdb_byte *siginfo_data = NULL; @@ -6763,7 +6837,9 @@ void restore_infcall_suspend_state (struct infcall_suspend_state *inf_state) { struct thread_info *tp = inferior_thread (); +#if 0 struct inferior *inf = current_inferior (); +#endif struct regcache *regcache = get_current_regcache (); struct gdbarch *gdbarch = get_regcache_arch (regcache); @@ -7209,6 +7285,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_catch = (unsigned char *) + xmalloc (sizeof (signal_catch[0]) * numsigs); signal_pass = (unsigned char *) xmalloc (sizeof (signal_program[0]) * numsigs); for (i = 0; i < numsigs; i++) @@ -7216,6 +7294,7 @@ leave it stopped or free to run as needed."), signal_stop[i] = 1; signal_print[i] = 1; signal_program[i] = 1; + signal_catch[i] = 0; } /* Signals caused by debugger's own actions @@ -7264,7 +7343,7 @@ Show stopping for shared library events."), _("\ If nonzero, gdb will give control to the user when the dynamic linker\n\ notifies gdb of shared library events. The most common event of interest\n\ to the user would be loading/unloading of a new library."), - NULL, + set_stop_on_solib_events, show_stop_on_solib_events, &setlist, &showlist);