X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Finfrun.c;h=a2916b43bb29e39169000e2811612241c2d3317f;hb=9d1807c37cfc3dd30a4a4c4ef98f94be8d13d4b0;hp=167252adca72eb7e6b57cf9a9ff6bcc99ea07583;hpb=388a856237fc981725e33eca6644d837c94918a9;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/infrun.c b/gdb/infrun.c index 167252adca..a2916b43bb 100644 --- a/gdb/infrun.c +++ b/gdb/infrun.c @@ -49,6 +49,8 @@ #include "mi/mi-common.h" #include "event-top.h" #include "record.h" +#include "inline-frame.h" +#include "jit.h" /* Prototypes for local functions */ @@ -107,6 +109,9 @@ int sync_execution = 0; static ptid_t previous_inferior_ptid; +/* Default behavior is to detach newly forked processes (legacy). */ +int detach_fork = 1; + int debug_displaced = 0; static void show_debug_displaced (struct ui_file *file, int from_tty, @@ -209,7 +214,7 @@ static unsigned char *signal_program; /* Value to pass to target_resume() to cause all threads to resume */ -#define RESUME_ALL (pid_to_ptid (-1)) +#define RESUME_ALL minus_one_ptid /* Command list pointer for the "stop" placeholder. */ @@ -459,6 +464,198 @@ follow_inferior_reset_breakpoints (void) insert_breakpoints (); } +/* The child has exited or execed: resume threads of the parent the + user wanted to be executing. */ + +static int +proceed_after_vfork_done (struct thread_info *thread, + void *arg) +{ + int pid = * (int *) arg; + + if (ptid_get_pid (thread->ptid) == pid + && is_running (thread->ptid) + && !is_executing (thread->ptid) + && !thread->stop_requested + && thread->stop_signal == TARGET_SIGNAL_0) + { + if (debug_infrun) + fprintf_unfiltered (gdb_stdlog, + "infrun: resuming vfork parent thread %s\n", + target_pid_to_str (thread->ptid)); + + switch_to_thread (thread->ptid); + clear_proceed_status (); + proceed ((CORE_ADDR) -1, TARGET_SIGNAL_DEFAULT, 0); + } + + return 0; +} + +/* Called whenever we notice an exec or exit event, to handle + detaching or resuming a vfork parent. */ + +static void +handle_vfork_child_exec_or_exit (int exec) +{ + struct inferior *inf = current_inferior (); + + if (inf->vfork_parent) + { + int resume_parent = -1; + + /* This exec or exit marks the end of the shared memory region + between the parent and the child. If the user wanted to + detach from the parent, now is the time. */ + + if (inf->vfork_parent->pending_detach) + { + struct thread_info *tp; + struct cleanup *old_chain; + struct program_space *pspace; + struct address_space *aspace; + + /* follow-fork child, detach-on-fork on */ + + old_chain = make_cleanup_restore_current_thread (); + + /* We're letting loose of the parent. */ + tp = any_live_thread_of_process (inf->vfork_parent->pid); + switch_to_thread (tp->ptid); + + /* We're about to detach from the parent, which implicitly + removes breakpoints from its address space. There's a + catch here: we want to reuse the spaces for the child, + but, parent/child are still sharing the pspace at this + point, although the exec in reality makes the kernel give + the child a fresh set of new pages. The problem here is + that the breakpoints module being unaware of this, would + likely chose the child process to write to the parent + address space. Swapping the child temporarily away from + the spaces has the desired effect. Yes, this is "sort + of" a hack. */ + + pspace = inf->pspace; + aspace = inf->aspace; + inf->aspace = NULL; + inf->pspace = NULL; + + if (debug_infrun || info_verbose) + { + target_terminal_ours (); + + if (exec) + fprintf_filtered (gdb_stdlog, + "Detaching vfork parent process %d after child exec.\n", + inf->vfork_parent->pid); + else + fprintf_filtered (gdb_stdlog, + "Detaching vfork parent process %d after child exit.\n", + inf->vfork_parent->pid); + } + + target_detach (NULL, 0); + + /* Put it back. */ + inf->pspace = pspace; + inf->aspace = aspace; + + do_cleanups (old_chain); + } + else if (exec) + { + /* We're staying attached to the parent, so, really give the + child a new address space. */ + inf->pspace = add_program_space (maybe_new_address_space ()); + inf->aspace = inf->pspace->aspace; + inf->removable = 1; + set_current_program_space (inf->pspace); + + resume_parent = inf->vfork_parent->pid; + + /* Break the bonds. */ + inf->vfork_parent->vfork_child = NULL; + } + else + { + struct cleanup *old_chain; + struct program_space *pspace; + + /* If this is a vfork child exiting, then the pspace and + aspaces were shared with the parent. Since we're + reporting the process exit, we'll be mourning all that is + found in the address space, and switching to null_ptid, + preparing to start a new inferior. But, since we don't + want to clobber the parent's address/program spaces, we + go ahead and create a new one for this exiting + inferior. */ + + /* Switch to null_ptid, so that clone_program_space doesn't want + to read the selected frame of a dead process. */ + old_chain = save_inferior_ptid (); + inferior_ptid = null_ptid; + + /* This inferior is dead, so avoid giving the breakpoints + module the option to write through to it (cloning a + program space resets breakpoints). */ + inf->aspace = NULL; + inf->pspace = NULL; + pspace = add_program_space (maybe_new_address_space ()); + set_current_program_space (pspace); + inf->removable = 1; + clone_program_space (pspace, inf->vfork_parent->pspace); + inf->pspace = pspace; + inf->aspace = pspace->aspace; + + /* Put back inferior_ptid. We'll continue mourning this + inferior. */ + do_cleanups (old_chain); + + resume_parent = inf->vfork_parent->pid; + /* Break the bonds. */ + inf->vfork_parent->vfork_child = NULL; + } + + inf->vfork_parent = NULL; + + gdb_assert (current_program_space == inf->pspace); + + if (non_stop && resume_parent != -1) + { + /* If the user wanted the parent to be running, let it go + free now. */ + struct cleanup *old_chain = make_cleanup_restore_current_thread (); + + if (debug_infrun) + fprintf_unfiltered (gdb_stdlog, "infrun: resuming vfork parent process %d\n", + resume_parent); + + iterate_over_threads (proceed_after_vfork_done, &resume_parent); + + do_cleanups (old_chain); + } + } +} + +/* Enum strings for "set|show displaced-stepping". */ + +static const char follow_exec_mode_new[] = "new"; +static const char follow_exec_mode_same[] = "same"; +static const char *follow_exec_mode_names[] = +{ + follow_exec_mode_new, + follow_exec_mode_same, + NULL, +}; + +static const char *follow_exec_mode_string = follow_exec_mode_same; +static void +show_follow_exec_mode_string (struct ui_file *file, int from_tty, + struct cmd_list_element *c, const char *value) +{ + fprintf_filtered (file, _("Follow exec mode is \"%s\".\n"), value); +} + /* EXECD_PATHNAME is assumed to be non-NULL. */ static void @@ -466,6 +663,7 @@ follow_exec (ptid_t pid, char *execd_pathname) { struct target_ops *tgt; struct thread_info *th = inferior_thread (); + struct inferior *inf = current_inferior (); /* This is an exec event that we actually wish to pay attention to. Refresh our symbol table to the newly exec'd program, remove any @@ -487,6 +685,9 @@ follow_exec (ptid_t pid, char *execd_pathname) that may write the bp's "shadow contents" (the instruction value that was overwritten witha TRAP instruction). Since we now have a new a.out, those shadow contents aren't valid. */ + + mark_breakpoints_out (); + update_breakpoints_after_exec (); /* If there was one, it's gone now. We cannot truly step-to-next @@ -504,7 +705,9 @@ follow_exec (ptid_t pid, char *execd_pathname) th->stop_requested = 0; /* What is this a.out's name? */ - printf_unfiltered (_("Executing new program: %s\n"), execd_pathname); + printf_unfiltered (_("%s is executing new program: %s\n"), + target_pid_to_str (inferior_ptid), + execd_pathname); /* We've followed the inferior through an exec. Therefore, the inferior has essentially been killed & reborn. */ @@ -523,9 +726,6 @@ follow_exec (ptid_t pid, char *execd_pathname) execd_pathname = name; } - /* That a.out is now the one to use. */ - exec_file_attach (execd_pathname, 0); - /* Reset the shared library package. This ensures that we get a shlib event when the child reaches "_start", at which point the dld will have had a chance to initialize the child. */ @@ -534,6 +734,30 @@ follow_exec (ptid_t pid, char *execd_pathname) previous incarnation of this process. */ no_shared_libraries (NULL, 0); + if (follow_exec_mode_string == follow_exec_mode_new) + { + struct program_space *pspace; + struct inferior *new_inf; + + /* The user wants to keep the old inferior and program spaces + around. Create a new fresh one, and switch to it. */ + + inf = add_inferior (current_inferior ()->pid); + pspace = add_program_space (maybe_new_address_space ()); + inf->pspace = pspace; + inf->aspace = pspace->aspace; + + exit_inferior_num_silent (current_inferior ()->num); + + set_current_inferior (inf); + set_current_program_space (pspace); + } + + gdb_assert (current_program_space == inf->pspace); + + /* That a.out is now the one to use. */ + exec_file_attach (execd_pathname, 0); + /* Load the main file's symbols. */ symbol_file_add_main (execd_pathname, 0); @@ -543,6 +767,8 @@ follow_exec (ptid_t pid, char *execd_pathname) solib_create_inferior_hook (); #endif + jit_inferior_created_hook (); + /* Reinsert all breakpoints. (Those which were symbolic have been reset to the proper address in the new a.out, thanks to symbol_file_command...) */ @@ -865,8 +1091,8 @@ displaced_step_prepare (ptid_t ptid) read_memory (copy, displaced_step_saved_copy, len); if (debug_displaced) { - fprintf_unfiltered (gdb_stdlog, "displaced: saved 0x%s: ", - paddr_nz (copy)); + fprintf_unfiltered (gdb_stdlog, "displaced: saved %s: ", + paddress (gdbarch, copy)); displaced_step_dump_bytes (gdb_stdlog, displaced_step_saved_copy, len); }; @@ -894,8 +1120,8 @@ displaced_step_prepare (ptid_t ptid) do_cleanups (old_cleanups); if (debug_displaced) - fprintf_unfiltered (gdb_stdlog, "displaced: displaced pc to 0x%s\n", - paddr_nz (copy)); + fprintf_unfiltered (gdb_stdlog, "displaced: displaced pc to %s\n", + paddress (gdbarch, copy)); return 1; } @@ -927,8 +1153,9 @@ displaced_step_fixup (ptid_t event_ptid, enum target_signal signal) write_memory_ptid (displaced_step_ptid, displaced_step_copy, displaced_step_saved_copy, len); if (debug_displaced) - fprintf_unfiltered (gdb_stdlog, "displaced: restored 0x%s\n", - paddr_nz (displaced_step_copy)); + fprintf_unfiltered (gdb_stdlog, "displaced: restored %s\n", + paddress (displaced_step_gdbarch, + displaced_step_copy)); } /* Did the instruction complete successfully? */ @@ -961,7 +1188,10 @@ displaced_step_fixup (ptid_t event_ptid, enum target_signal signal) { struct displaced_step_request *head; ptid_t ptid; + struct regcache *regcache; + struct gdbarch *gdbarch; CORE_ADDR actual_pc; + struct address_space *aspace; head = displaced_step_request_queue; ptid = head->ptid; @@ -970,9 +1200,11 @@ displaced_step_fixup (ptid_t event_ptid, enum target_signal signal) context_switch (ptid); - actual_pc = regcache_read_pc (get_thread_regcache (ptid)); + regcache = get_thread_regcache (ptid); + actual_pc = regcache_read_pc (regcache); + aspace = get_regcache_aspace (regcache); - if (breakpoint_here_p (actual_pc)) + if (breakpoint_here_p (aspace, actual_pc)) { if (debug_displaced) fprintf_unfiltered (gdb_stdlog, @@ -981,17 +1213,24 @@ displaced_step_fixup (ptid_t event_ptid, enum target_signal signal) displaced_step_prepare (ptid); + gdbarch = get_regcache_arch (regcache); + if (debug_displaced) { + CORE_ADDR actual_pc = regcache_read_pc (regcache); gdb_byte buf[4]; - fprintf_unfiltered (gdb_stdlog, "displaced: run 0x%s: ", - paddr_nz (actual_pc)); + fprintf_unfiltered (gdb_stdlog, "displaced: run %s: ", + paddress (gdbarch, actual_pc)); read_memory (actual_pc, buf, sizeof (buf)); displaced_step_dump_bytes (gdb_stdlog, buf, sizeof (buf)); } - target_resume (ptid, 1, TARGET_SIGNAL_0); + if (gdbarch_displaced_step_hw_singlestep + (gdbarch, displaced_step_closure)) + target_resume (ptid, 1, TARGET_SIGNAL_0); + else + target_resume (ptid, 0, TARGET_SIGNAL_0); /* Done, we're stepping a thread. */ break; @@ -1130,6 +1369,7 @@ resume (int step, enum target_signal sig) struct gdbarch *gdbarch = get_regcache_arch (regcache); struct thread_info *tp = inferior_thread (); CORE_ADDR pc = regcache_read_pc (regcache); + struct address_space *aspace = get_regcache_aspace (regcache); QUIT; @@ -1155,7 +1395,7 @@ resume (int step, enum target_signal sig) removed or inserted, as appropriate. The exception is if we're sitting at a permanent breakpoint; we need to step over it, but permanent breakpoints can't be removed. So we have to test for it here. */ - if (breakpoint_here_p (pc) == permanent_breakpoint_here) + if (breakpoint_here_p (aspace, pc) == permanent_breakpoint_here) { if (gdbarch_skip_permanent_breakpoint_p (gdbarch)) gdbarch_skip_permanent_breakpoint (gdbarch, regcache); @@ -1174,7 +1414,8 @@ a command like `return' or `jump' to continue execution.")); comments in the handle_inferior event for dealing with 'random signals' explain what we do instead. */ if (use_displaced_stepping (gdbarch) - && tp->trap_expected + && (tp->trap_expected + || (step && gdbarch_software_single_step_p (gdbarch))) && sig == TARGET_SIGNAL_0) { if (!displaced_step_prepare (inferior_ptid)) @@ -1189,10 +1430,13 @@ a command like `return' or `jump' to continue execution.")); discard_cleanups (old_cleanups); return; } + + step = gdbarch_displaced_step_hw_singlestep + (gdbarch, displaced_step_closure); } /* Do we need to do it the hard way, w/temp breakpoints? */ - if (step) + else if (step) step = maybe_software_singlestep (gdbarch, pc); if (should_resume) @@ -1268,7 +1512,7 @@ a command like `return' or `jump' to continue execution.")); /* Most targets can step a breakpoint instruction, thus executing it normally. But if this one cannot, just continue and we will hit it anyway. */ - if (step && breakpoint_inserted_here_p (pc)) + if (step && breakpoint_inserted_here_p (aspace, pc)) step = 0; } @@ -1277,11 +1521,12 @@ a command like `return' or `jump' to continue execution.")); && tp->trap_expected) { struct regcache *resume_regcache = get_thread_regcache (resume_ptid); + struct gdbarch *resume_gdbarch = get_regcache_arch (resume_regcache); CORE_ADDR actual_pc = regcache_read_pc (resume_regcache); gdb_byte buf[4]; - fprintf_unfiltered (gdb_stdlog, "displaced: run 0x%s: ", - paddr_nz (actual_pc)); + fprintf_unfiltered (gdb_stdlog, "displaced: run %s: ", + paddress (resume_gdbarch, actual_pc)); read_memory (actual_pc, buf, sizeof (buf)); displaced_step_dump_bytes (gdb_stdlog, buf, sizeof (buf)); } @@ -1316,6 +1561,7 @@ clear_proceed_status_thread (struct thread_info *tp) tp->step_range_start = 0; tp->step_range_end = 0; tp->step_frame_id = null_frame_id; + tp->step_stack_frame_id = null_frame_id; tp->step_over_calls = STEP_OVER_UNDEBUGGABLE; tp->stop_requested = 0; @@ -1340,23 +1586,26 @@ clear_proceed_status_callback (struct thread_info *tp, void *data) void clear_proceed_status (void) { + if (!non_stop) + { + /* In all-stop mode, delete the per-thread status of all + threads, even if inferior_ptid is null_ptid, there may be + threads on the list. E.g., we may be launching a new + process, while selecting the executable. */ + iterate_over_threads (clear_proceed_status_callback, NULL); + } + if (!ptid_equal (inferior_ptid, null_ptid)) { struct inferior *inferior; if (non_stop) { - /* If in non-stop mode, only delete the per-thread status - of the current thread. */ + /* If in non-stop mode, only delete the per-thread status of + the current thread. */ clear_proceed_status_thread (inferior_thread ()); } - else - { - /* In all-stop mode, delete the per-thread status of - *all* threads. */ - iterate_over_threads (clear_proceed_status_callback, NULL); - } - + inferior = current_inferior (); inferior->stop_soon = NO_STOP_QUIETLY; } @@ -1418,7 +1667,8 @@ prepare_to_proceed (int step) { struct regcache *regcache = get_thread_regcache (wait_ptid); - if (breakpoint_here_p (regcache_read_pc (regcache))) + if (breakpoint_here_p (get_regcache_aspace (regcache), + regcache_read_pc (regcache))) { /* If stepping, remember current thread to switch back to. */ if (step) @@ -1456,6 +1706,7 @@ proceed (CORE_ADDR addr, enum target_signal siggnal, int step) struct gdbarch *gdbarch; struct thread_info *tp; CORE_ADDR pc; + struct address_space *aspace; int oneproc = 0; /* If we're stopped at a fork/vfork, follow the branch set by the @@ -1470,6 +1721,7 @@ proceed (CORE_ADDR addr, enum target_signal siggnal, int step) regcache = get_current_regcache (); gdbarch = get_regcache_arch (regcache); + aspace = get_regcache_aspace (regcache); pc = regcache_read_pc (regcache); if (step > 0) @@ -1479,7 +1731,7 @@ proceed (CORE_ADDR addr, enum target_signal siggnal, int step) if (addr == (CORE_ADDR) -1) { - if (pc == stop_pc && breakpoint_here_p (pc) + if (pc == stop_pc && breakpoint_here_p (aspace, pc) && execution_direction != EXEC_REVERSE) /* There is a breakpoint at the address we will resume at, step one instruction before inserting breakpoints so that @@ -1505,8 +1757,8 @@ proceed (CORE_ADDR addr, enum target_signal siggnal, int step) if (debug_infrun) fprintf_unfiltered (gdb_stdlog, - "infrun: proceed (addr=0x%s, signal=%d, step=%d)\n", - paddr_nz (addr), siggnal, step); + "infrun: proceed (addr=%s, signal=%d, step=%d)\n", + paddress (gdbarch, addr), siggnal, step); if (non_stop) /* In non-stop, each thread is handled individually. The context @@ -1689,6 +1941,9 @@ init_wait_for_inferior (void) init_infwait_state (); displaced_step_clear (); + + /* Discard any skipped inlined frames. */ + clear_inline_frame_state (minus_one_ptid); } @@ -1744,9 +1999,9 @@ struct execution_control_state int wait_some_more; }; -void init_execution_control_state (struct execution_control_state *ecs); +static void init_execution_control_state (struct execution_control_state *ecs); -void handle_inferior_event (struct execution_control_state *ecs); +static void handle_inferior_event (struct execution_control_state *ecs); static void handle_step_into_function (struct gdbarch *gdbarch, struct execution_control_state *ecs); @@ -1754,9 +2009,10 @@ 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 *step_frame); static void insert_step_resume_breakpoint_at_caller (struct frame_info *); -static void insert_step_resume_breakpoint_at_sal (struct symtab_and_line sr_sal, +static void insert_step_resume_breakpoint_at_sal (struct gdbarch *gdbarch, + struct symtab_and_line sr_sal, struct frame_id sr_id); -static void insert_longjmp_resume_breakpoint (CORE_ADDR); +static void insert_longjmp_resume_breakpoint (struct gdbarch *, CORE_ADDR); static void stop_stepping (struct execution_control_state *ecs); static void prepare_to_wait (struct execution_control_state *ecs); @@ -1921,7 +2177,6 @@ print_target_wait_results (ptid_t waiton_ptid, ptid_t result_ptid, 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 @@ -1941,7 +2196,7 @@ print_target_wait_results (ptid_t waiton_ptid, ptid_t result_ptid, "infrun: %s\n", status_string); - text = ui_file_xstrdup (tmp_stream, &len); + text = ui_file_xstrdup (tmp_stream, NULL); /* 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. */ @@ -1982,23 +2237,22 @@ wait_for_inferior (int treat_exec_as_sigtrap) ecs = &ecss; memset (ecs, 0, sizeof (*ecs)); - overlay_cache_invalid = 1; - /* We'll update this if & when we switch to a new thread. */ previous_inferior_ptid = inferior_ptid; - /* We have to invalidate the registers BEFORE calling target_wait - because they can be loaded from the target while in target_wait. - This makes remote debugging a bit more efficient for those - targets that provide critical registers as part of their normal - status mechanism. */ - - registers_changed (); - while (1) { struct cleanup *old_chain; + /* We have to invalidate the registers BEFORE calling target_wait + because they can be loaded from the target while in target_wait. + This makes remote debugging a bit more efficient for those + targets that provide critical registers as part of their normal + status mechanism. */ + + overlay_cache_invalid = 1; + registers_changed (); + if (deprecated_target_wait_hook) ecs->ptid = deprecated_target_wait_hook (waiton_ptid, &ecs->ws, 0); else @@ -2019,6 +2273,10 @@ wait_for_inferior (int treat_exec_as_sigtrap) state. */ old_chain = make_cleanup (finish_thread_state_cleanup, &minus_one_ptid); + if (ecs->ws.kind == TARGET_WAITKIND_SYSCALL_ENTRY + || ecs->ws.kind == TARGET_WAITKIND_SYSCALL_RETURN) + ecs->ws.value.syscall_number = UNKNOWN_SYSCALL; + /* Now figure out what to do with the result of the result. */ handle_inferior_event (ecs); @@ -2052,14 +2310,8 @@ fetch_inferior_event (void *client_data) memset (ecs, 0, sizeof (*ecs)); - overlay_cache_invalid = 1; - - /* We can only rely on wait_for_more being correct before handling - the event in all-stop, but previous_inferior_ptid isn't used in - non-stop. */ - if (!ecs->wait_some_more) - /* We'll update this if & when we switch to a new thread. */ - previous_inferior_ptid = inferior_ptid; + /* We'll update this if & when we switch to a new thread. */ + previous_inferior_ptid = inferior_ptid; if (non_stop) /* In non-stop mode, the user/frontend should not notice a thread @@ -2074,6 +2326,7 @@ fetch_inferior_event (void *client_data) targets that provide critical registers as part of their normal status mechanism. */ + overlay_cache_invalid = 1; registers_changed (); if (deprecated_target_wait_hook) @@ -2137,10 +2390,23 @@ fetch_inferior_event (void *client_data) display_gdb_prompt (0); } +/* Record the frame and location we're currently stepping through. */ +void +set_step_info (struct frame_info *frame, struct symtab_and_line sal) +{ + struct thread_info *tp = inferior_thread (); + + tp->step_frame_id = get_frame_id (frame); + tp->step_stack_frame_id = get_stack_frame_id (frame); + + tp->current_symtab = sal.symtab; + tp->current_line = sal.line; +} + /* Prepare an execution control state for looping through a wait_for_inferior-type loop. */ -void +static void init_execution_control_state (struct execution_control_state *ecs) { ecs->random_signal = 0; @@ -2151,16 +2417,10 @@ init_execution_control_state (struct execution_control_state *ecs) void init_thread_stepping_state (struct thread_info *tss) { - struct symtab_and_line sal; - tss->stepping_over_breakpoint = 0; tss->step_after_step_resume_breakpoint = 0; tss->stepping_through_solib_after_catch = 0; tss->stepping_through_solib_catchpoints = NULL; - - sal = find_pc_line (tss->prev_pc, 0); - tss->current_line = sal.line; - tss->current_symtab = sal.symtab; } /* Return the cached copy of the last pid/waitstatus returned by @@ -2202,6 +2462,7 @@ adjust_pc_after_break (struct execution_control_state *ecs) { struct regcache *regcache; struct gdbarch *gdbarch; + struct address_space *aspace; CORE_ADDR breakpoint_pc; /* If we've hit a breakpoint, we'll normally be stopped with SIGTRAP. If @@ -2267,6 +2528,8 @@ adjust_pc_after_break (struct execution_control_state *ecs) if (gdbarch_decr_pc_after_break (gdbarch) == 0) return; + aspace = get_regcache_aspace (regcache); + /* Find the location where (if we've hit a breakpoint) the breakpoint would be. */ breakpoint_pc = regcache_read_pc (regcache) @@ -2280,8 +2543,8 @@ adjust_pc_after_break (struct execution_control_state *ecs) already queued and arrive later. To suppress those spurious SIGTRAPs, we keep a list of such breakpoint locations for a bit, and retire them after a number of stop events are reported. */ - if (software_breakpoint_inserted_here_p (breakpoint_pc) - || (non_stop && moribund_breakpoint_here_p (breakpoint_pc))) + if (software_breakpoint_inserted_here_p (aspace, breakpoint_pc) + || (non_stop && moribund_breakpoint_here_p (aspace, breakpoint_pc))) { struct cleanup *old_cleanups = NULL; if (RECORD_IS_USED) @@ -2337,11 +2600,75 @@ ensure_not_running (void) error_is_running (); } +static int +stepped_in_from (struct frame_info *frame, struct frame_id step_frame_id) +{ + for (frame = get_prev_frame (frame); + frame != NULL; + frame = get_prev_frame (frame)) + { + if (frame_id_eq (get_frame_id (frame), step_frame_id)) + return 1; + if (get_frame_type (frame) != INLINE_FRAME) + break; + } + + return 0; +} + +/* Auxiliary function that handles syscall entry/return events. + It returns 1 if the inferior should keep going (and GDB + should ignore the event), or 0 if the event deserves to be + processed. */ + +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 = gdbarch_get_syscall_number (gdbarch, ecs->ptid); + stop_pc = regcache_read_pc (regcache); + + target_last_waitstatus.value.syscall_number = syscall_number; + + if (catch_syscall_enabled () > 0 + && catching_syscall_number (syscall_number) > 0) + { + if (debug_infrun) + fprintf_unfiltered (gdb_stdlog, "infrun: syscall number = '%d'\n", + syscall_number); + + ecs->event_thread->stop_bpstat + = bpstat_stop_status (get_regcache_aspace (regcache), + stop_pc, ecs->ptid); + ecs->random_signal = !bpstat_explains_signal (ecs->event_thread->stop_bpstat); + + if (!ecs->random_signal) + { + /* Catchpoint hit. */ + ecs->event_thread->stop_signal = TARGET_SIGNAL_TRAP; + return 0; + } + } + + /* If no catchpoint triggered for this, then keep going. */ + ecs->event_thread->stop_signal = TARGET_SIGNAL_0; + keep_going (ecs); + return 1; +} + /* Given an execution control state that has been freshly filled in by an event from the inferior, figure out what it means and take appropriate action. */ -void +static void handle_inferior_event (struct execution_control_state *ecs) { struct frame_info *frame; @@ -2352,9 +2679,25 @@ handle_inferior_event (struct execution_control_state *ecs) struct symtab_and_line stop_pc_sal; enum stop_kind stop_soon; + if (ecs->ws.kind == TARGET_WAITKIND_IGNORE) + { + /* We had an event in the inferior, but we are not interested in + handling it at this level. The lower layers have already + done what needs to be done, if anything. + + One of the possible circumstances for this is when the + inferior produces output for the console. The inferior has + not stopped, and we are ignoring the event. Another possible + circumstance is any event which the lower level knows will be + reported multiple times without an intervening resume. */ + if (debug_infrun) + fprintf_unfiltered (gdb_stdlog, "infrun: TARGET_WAITKIND_IGNORE\n"); + prepare_to_wait (ecs); + return; + } + if (ecs->ws.kind != TARGET_WAITKIND_EXITED - && ecs->ws.kind != TARGET_WAITKIND_SIGNALLED - && ecs->ws.kind != TARGET_WAITKIND_IGNORE) + && ecs->ws.kind != TARGET_WAITKIND_SIGNALLED) { struct inferior *inf = find_inferior_pid (ptid_get_pid (ecs->ptid)); gdb_assert (inf); @@ -2388,30 +2731,25 @@ handle_inferior_event (struct execution_control_state *ecs) /* Dependent on the current PC value modified by adjust_pc_after_break. */ reinit_frame_cache (); - if (ecs->ws.kind != TARGET_WAITKIND_IGNORE) - { - breakpoint_retire_moribund (); - - /* Mark the non-executing threads accordingly. In all-stop, all - threads of all processes are stopped when we get any event - reported. In non-stop mode, only the event thread stops. If - we're handling a process exit in non-stop mode, there's - nothing to do, as threads of the dead process are gone, and - threads of any other process were left running. */ - if (!non_stop) - set_executing (minus_one_ptid, 0); - else if (ecs->ws.kind != TARGET_WAITKIND_SIGNALLED - && ecs->ws.kind != TARGET_WAITKIND_EXITED) - set_executing (inferior_ptid, 0); - } + breakpoint_retire_moribund (); + + /* Mark the non-executing threads accordingly. In all-stop, all + threads of all processes are stopped when we get any event + reported. In non-stop mode, only the event thread stops. If + we're handling a process exit in non-stop mode, there's nothing + to do, as threads of the dead process are gone, and threads of + any other process were left running. */ + if (!non_stop) + set_executing (minus_one_ptid, 0); + else if (ecs->ws.kind != TARGET_WAITKIND_SIGNALLED + && ecs->ws.kind != TARGET_WAITKIND_EXITED) + set_executing (inferior_ptid, 0); switch (infwait_state) { case infwait_thread_hop_state: if (debug_infrun) fprintf_unfiltered (gdb_stdlog, "infrun: infwait_thread_hop_state\n"); - /* Cancel the waiton_ptid. */ - waiton_ptid = pid_to_ptid (-1); break; case infwait_normal_state: @@ -2442,7 +2780,9 @@ handle_inferior_event (struct execution_control_state *ecs) default: internal_error (__FILE__, __LINE__, _("bad switch")); } + infwait_state = infwait_normal_state; + waiton_ptid = pid_to_ptid (-1); switch (ecs->ws.kind) { @@ -2518,6 +2858,9 @@ handle_inferior_event (struct execution_control_state *ecs) if (debug_infrun) fprintf_unfiltered (gdb_stdlog, "infrun: TARGET_WAITKIND_EXITED\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_stop_reason (EXITED, ecs->ws.value.integer); @@ -2536,6 +2879,9 @@ handle_inferior_event (struct execution_control_state *ecs) 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 */ @@ -2592,19 +2938,45 @@ handle_inferior_event (struct execution_control_state *ecs) stop_pc = regcache_read_pc (get_thread_regcache (ecs->ptid)); - ecs->event_thread->stop_bpstat = bpstat_stop_status (stop_pc, ecs->ptid); + ecs->event_thread->stop_bpstat + = bpstat_stop_status (get_regcache_aspace (get_current_regcache ()), + stop_pc, ecs->ptid); ecs->random_signal = !bpstat_explains_signal (ecs->event_thread->stop_bpstat); /* If no catchpoint triggered for this, then keep going. */ if (ecs->random_signal) { + ptid_t parent; + ptid_t child; int should_resume; + int follow_child = (follow_fork_mode_string == follow_fork_mode_child); ecs->event_thread->stop_signal = TARGET_SIGNAL_0; should_resume = follow_fork (); + parent = ecs->ptid; + child = ecs->ws.value.related_pid; + + /* In non-stop mode, also resume the other branch. */ + if (non_stop && !detach_fork) + { + if (follow_child) + switch_to_thread (parent); + else + switch_to_thread (child); + + ecs->event_thread = inferior_thread (); + ecs->ptid = inferior_ptid; + keep_going (ecs); + } + + if (follow_child) + switch_to_thread (child); + else + switch_to_thread (parent); + ecs->event_thread = inferior_thread (); ecs->ptid = inferior_ptid; @@ -2617,6 +2989,22 @@ handle_inferior_event (struct execution_control_state *ecs) ecs->event_thread->stop_signal = TARGET_SIGNAL_TRAP; goto process_event_stop_test; + case TARGET_WAITKIND_VFORK_DONE: + /* Done with the shared memory region. Re-insert breakpoints in + the parent, and keep going. */ + + if (debug_infrun) + fprintf_unfiltered (gdb_stdlog, "infrun: TARGET_WAITKIND_VFORK_DONE\n"); + + if (!ptid_equal (ecs->ptid, inferior_ptid)) + context_switch (ecs->ptid); + + current_inferior ()->waiting_for_vfork_done = 0; + /* This also takes care of reinserting breakpoints in the + previously locked inferior. */ + keep_going (ecs); + return; + case TARGET_WAITKIND_EXECD: if (debug_infrun) fprintf_unfiltered (gdb_stdlog, "infrun: TARGET_WAITKIND_EXECD\n"); @@ -2629,12 +3017,17 @@ handle_inferior_event (struct execution_control_state *ecs) stop_pc = regcache_read_pc (get_thread_regcache (ecs->ptid)); + /* Do whatever is necessary to the parent branch of the vfork. */ + handle_vfork_child_exec_or_exit (1); + /* This causes the eventpoints and symbol table to be reset. Must do this now, before trying to determine whether to stop. */ follow_exec (inferior_ptid, ecs->ws.value.execd_pathname); - ecs->event_thread->stop_bpstat = bpstat_stop_status (stop_pc, ecs->ptid); + ecs->event_thread->stop_bpstat + = bpstat_stop_status (get_regcache_aspace (get_current_regcache ()), + stop_pc, ecs->ptid); ecs->random_signal = !bpstat_explains_signal (ecs->event_thread->stop_bpstat); /* Note that this may be referenced from inside @@ -2657,9 +3050,10 @@ handle_inferior_event (struct execution_control_state *ecs) case TARGET_WAITKIND_SYSCALL_ENTRY: if (debug_infrun) fprintf_unfiltered (gdb_stdlog, "infrun: TARGET_WAITKIND_SYSCALL_ENTRY\n"); - resume (0, TARGET_SIGNAL_0); - prepare_to_wait (ecs); - return; + /* Getting the current syscall number */ + if (handle_syscall_event (ecs) != 0) + return; + goto process_event_stop_test; /* Before examining the threads further, step this thread to get it entirely out of the syscall. (We get notice of the @@ -2669,9 +3063,9 @@ handle_inferior_event (struct execution_control_state *ecs) case TARGET_WAITKIND_SYSCALL_RETURN: if (debug_infrun) fprintf_unfiltered (gdb_stdlog, "infrun: TARGET_WAITKIND_SYSCALL_RETURN\n"); - target_resume (ecs->ptid, 1, TARGET_SIGNAL_0); - prepare_to_wait (ecs); - return; + if (handle_syscall_event (ecs) != 0) + return; + goto process_event_stop_test; case TARGET_WAITKIND_STOPPED: if (debug_infrun) @@ -2685,21 +3079,6 @@ handle_inferior_event (struct execution_control_state *ecs) print_stop_reason (NO_HISTORY, 0); stop_stepping (ecs); return; - - /* We had an event in the inferior, but we are not interested - in handling it at this level. The lower layers have already - done what needs to be done, if anything. - - One of the possible circumstances for this is when the - inferior produces output for the console. The inferior has - not stopped, and we are ignoring the event. Another possible - circumstance is any event which the lower level knows will be - reported multiple times without an intervening resume. */ - case TARGET_WAITKIND_IGNORE: - if (debug_infrun) - fprintf_unfiltered (gdb_stdlog, "infrun: TARGET_WAITKIND_IGNORE\n"); - prepare_to_wait (ecs); - return; } if (ecs->new_thread_event) @@ -2718,6 +3097,8 @@ targets should add new threads to the thread list themselves in non-stop mode.") in either the OS or the native code). Therefore we need to continue all threads in order to make progress. */ + if (!ptid_equal (ecs->ptid, inferior_ptid)) + context_switch (ecs->ptid); target_resume (RESUME_ALL, 0, TARGET_SIGNAL_0); prepare_to_wait (ecs); return; @@ -2743,8 +3124,11 @@ targets should add new threads to the thread list themselves in non-stop mode.") if (debug_infrun) { - fprintf_unfiltered (gdb_stdlog, "infrun: stop_pc = 0x%s\n", - paddr_nz (stop_pc)); + struct regcache *regcache = get_thread_regcache (ecs->ptid); + struct gdbarch *gdbarch = get_regcache_arch (regcache); + + fprintf_unfiltered (gdb_stdlog, "infrun: stop_pc = %s\n", + paddress (gdbarch, stop_pc)); if (target_stopped_by_watchpoint ()) { CORE_ADDR addr; @@ -2752,8 +3136,8 @@ targets should add new threads to the thread list themselves in non-stop mode.") if (target_stopped_data_address (¤t_target, &addr)) fprintf_unfiltered (gdb_stdlog, - "infrun: stopped data address = 0x%s\n", - paddr_nz (addr)); + "infrun: stopped data address = %s\n", + paddress (gdbarch, addr)); else fprintf_unfiltered (gdb_stdlog, "infrun: (no data address available)\n"); @@ -2780,6 +3164,7 @@ targets should add new threads to the thread list themselves in non-stop mode.") singlestep_breakpoints_inserted_p = 0; ecs->random_signal = 0; + ecs->event_thread->trap_expected = 0; context_switch (saved_singlestep_ptid); if (deprecated_context_hook) @@ -2833,14 +3218,15 @@ targets should add new threads to the thread list themselves in non-stop mode.") if (ecs->event_thread->stop_signal == TARGET_SIGNAL_TRAP) { int thread_hop_needed = 0; + struct address_space *aspace = get_regcache_aspace (get_current_regcache ()); /* Check if a regular breakpoint has been hit before checking for a potential single step breakpoint. Otherwise, GDB will not see this breakpoint hit when stepping onto breakpoints. */ - if (regular_breakpoint_inserted_here_p (stop_pc)) + if (regular_breakpoint_inserted_here_p (aspace, stop_pc)) { ecs->random_signal = 0; - if (!breakpoint_thread_match (stop_pc, ecs->ptid)) + if (!breakpoint_thread_match (aspace, stop_pc, ecs->ptid)) thread_hop_needed = 1; } else if (singlestep_breakpoints_inserted_p) @@ -2964,7 +3350,6 @@ targets should add new threads to the thread list themselves in non-stop mode.") ecs->event_thread->stepping_over_breakpoint = 1; keep_going (ecs); - registers_changed (); return; } } @@ -3039,7 +3424,6 @@ targets should add new threads to the thread list themselves in non-stop mode.") /* Single step */ hw_step = maybe_software_singlestep (gdbarch, stop_pc); target_resume (ecs->ptid, hw_step, TARGET_SIGNAL_0); - registers_changed (); waiton_ptid = ecs->ptid; if (target_have_steppable_watchpoint) infwait_state = infwait_step_watch_state; @@ -3065,6 +3449,12 @@ targets should add new threads to the thread list themselves in non-stop mode.") ecs->random_signal = 0; stopped_by_random_signal = 0; + /* Hide inlined functions starting here, unless we just performed stepi or + nexti. After stepi and nexti, always show the innermost frame (not any + inline function call sites). */ + if (ecs->event_thread->step_range_end != 1) + skip_inline_frames (ecs->ptid); + if (ecs->event_thread->stop_signal == TARGET_SIGNAL_TRAP && ecs->event_thread->trap_expected && gdbarch_single_step_through_delay_p (gdbarch) @@ -3123,7 +3513,8 @@ targets should add new threads to the thread list themselves in non-stop mode.") non-standard signals can't be explained by the breakpoint. */ if (ecs->event_thread->stop_signal == TARGET_SIGNAL_TRAP || (! ecs->event_thread->trap_expected - && breakpoint_inserted_here_p (stop_pc) + && breakpoint_inserted_here_p (get_regcache_aspace (get_current_regcache ()), + stop_pc) && (ecs->event_thread->stop_signal == TARGET_SIGNAL_ILL || ecs->event_thread->stop_signal == TARGET_SIGNAL_SEGV || ecs->event_thread->stop_signal == TARGET_SIGNAL_EMT)) @@ -3180,8 +3571,10 @@ targets should add new threads to the thread list themselves in non-stop mode.") } /* See if there is a breakpoint at the current PC. */ - ecs->event_thread->stop_bpstat = bpstat_stop_status (stop_pc, ecs->ptid); - + ecs->event_thread->stop_bpstat + = bpstat_stop_status (get_regcache_aspace (get_current_regcache ()), + stop_pc, ecs->ptid); + /* Following in case break condition called a function. */ stop_print_frame = 1; @@ -3302,8 +3695,8 @@ process_event_stop_test: && ecs->event_thread->stop_signal != TARGET_SIGNAL_0 && (ecs->event_thread->step_range_start <= stop_pc && stop_pc < ecs->event_thread->step_range_end) - && frame_id_eq (get_frame_id (frame), - ecs->event_thread->step_frame_id) + && frame_id_eq (get_stack_frame_id (frame), + ecs->event_thread->step_stack_frame_id) && ecs->event_thread->step_resume_breakpoint == NULL) { /* The inferior is about to take a signal that will take it @@ -3375,7 +3768,7 @@ infrun: BPSTAT_WHAT_SET_LONGJMP_RESUME (!gdbarch_get_longjmp_target)\n"); delete_step_resume_breakpoint (ecs->event_thread); /* Insert a breakpoint at resume address. */ - insert_longjmp_resume_breakpoint (jmp_buf_pc); + insert_longjmp_resume_breakpoint (gdbarch, jmp_buf_pc); keep_going (ecs); return; @@ -3492,6 +3885,22 @@ infrun: BPSTAT_WHAT_SET_LONGJMP_RESUME (!gdbarch_get_longjmp_target)\n"); } break; + case BPSTAT_WHAT_CHECK_JIT: + if (debug_infrun) + fprintf_unfiltered (gdb_stdlog, "infrun: BPSTAT_WHAT_CHECK_JIT\n"); + + /* Switch terminal for any messages produced by breakpoint_re_set. */ + target_terminal_ours_for_output (); + + jit_event_handler (gdbarch); + + target_terminal_inferior (); + + /* We want to step over this breakpoint, then keep going. */ + ecs->event_thread->stepping_over_breakpoint = 1; + + break; + case BPSTAT_WHAT_LAST: /* Not a real code, but listed here to shut up gcc -Wall. */ @@ -3643,9 +4052,10 @@ infrun: not switching back to stepped thread, it has vanished\n"); ecs->event_thread->step_frame_id))) { if (debug_infrun) - fprintf_unfiltered (gdb_stdlog, "infrun: stepping inside range [0x%s-0x%s]\n", - paddr_nz (ecs->event_thread->step_range_start), - paddr_nz (ecs->event_thread->step_range_end)); + fprintf_unfiltered + (gdb_stdlog, "infrun: stepping inside range [%s-%s]\n", + paddress (gdbarch, ecs->event_thread->step_range_start), + paddress (gdbarch, ecs->event_thread->step_range_end)); /* When stepping backward, stop at beginning of line range (unless it's the function entry point, in which case @@ -3695,8 +4105,10 @@ infrun: not switching back to stepped thread, it has vanished\n"); struct symtab_and_line sr_sal; init_sal (&sr_sal); sr_sal.pc = pc_after_resolver; + sr_sal.pspace = get_frame_program_space (frame); - insert_step_resume_breakpoint_at_sal (sr_sal, null_frame_id); + insert_step_resume_breakpoint_at_sal (gdbarch, + sr_sal, null_frame_id); } keep_going (ecs); @@ -3727,11 +4139,22 @@ infrun: not switching back to stepped thread, it has vanished\n"); NOTE: frame_id_eq will never report two invalid frame IDs as being equal, so to get into this block, both the current and previous frame must have valid frame IDs. */ - if (!frame_id_eq (get_frame_id (frame), - ecs->event_thread->step_frame_id) - && (frame_id_eq (frame_unwind_id (frame), - ecs->event_thread->step_frame_id) - || execution_direction == EXEC_REVERSE)) + /* The outer_frame_id check is a heuristic to detect stepping + through startup code. If we step over an instruction which + sets the stack pointer from an invalid value to a valid value, + we may detect that as a subroutine call from the mythical + "outermost" function. This could be fixed by marking + outermost frames as !stack_p,code_p,special_p. Then the + initial outermost frame, before sp was valid, would + have code_addr == &_start. See the commend in frame_id_eq + for more. */ + if (!frame_id_eq (get_stack_frame_id (frame), + ecs->event_thread->step_stack_frame_id) + && (frame_id_eq (frame_unwind_caller_id (get_current_frame ()), + ecs->event_thread->step_stack_frame_id) + && (!frame_id_eq (ecs->event_thread->step_stack_frame_id, + outer_frame_id) + || step_start_function != find_pc_function (stop_pc)))) { CORE_ADDR real_stop_pc; @@ -3759,6 +4182,7 @@ infrun: not switching back to stepped thread, it has vanished\n"); /* Reverse stepping through solib trampolines. */ if (execution_direction == EXEC_REVERSE + && ecs->event_thread->step_over_calls != STEP_OVER_NONE && (gdbarch_skip_trampoline_code (gdbarch, frame, stop_pc) || (ecs->stop_func_start == 0 && in_solib_dynsym_resolve_code (stop_pc)))) @@ -3792,7 +4216,9 @@ infrun: not switching back to stepped thread, it has vanished\n"); /* Normal function call return (static or dynamic). */ init_sal (&sr_sal); sr_sal.pc = ecs->stop_func_start; - insert_step_resume_breakpoint_at_sal (sr_sal, null_frame_id); + sr_sal.pspace = get_frame_program_space (frame); + insert_step_resume_breakpoint_at_sal (gdbarch, + sr_sal, null_frame_id); } else insert_step_resume_breakpoint_at_caller (frame); @@ -3817,8 +4243,10 @@ infrun: not switching back to stepped thread, it has vanished\n"); struct symtab_and_line sr_sal; init_sal (&sr_sal); sr_sal.pc = ecs->stop_func_start; + sr_sal.pspace = get_frame_program_space (frame); - insert_step_resume_breakpoint_at_sal (sr_sal, null_frame_id); + insert_step_resume_breakpoint_at_sal (gdbarch, + sr_sal, null_frame_id); keep_going (ecs); return; } @@ -3833,6 +4261,7 @@ infrun: not switching back to stepped thread, it has vanished\n"); 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) @@ -3862,7 +4291,9 @@ infrun: not switching back to stepped thread, it has vanished\n"); struct symtab_and_line sr_sal; init_sal (&sr_sal); sr_sal.pc = ecs->stop_func_start; - insert_step_resume_breakpoint_at_sal (sr_sal, null_frame_id); + sr_sal.pspace = get_frame_program_space (frame); + insert_step_resume_breakpoint_at_sal (gdbarch, + sr_sal, null_frame_id); } else /* Set a breakpoint at callee's return address (the address @@ -3873,6 +4304,39 @@ infrun: not switching back to stepped thread, it has vanished\n"); return; } + /* Reverse stepping through solib trampolines. */ + + if (execution_direction == EXEC_REVERSE + && ecs->event_thread->step_over_calls != STEP_OVER_NONE) + { + if (gdbarch_skip_trampoline_code (gdbarch, frame, stop_pc) + || (ecs->stop_func_start == 0 + && in_solib_dynsym_resolve_code (stop_pc))) + { + /* Any solib trampoline code can be handled in reverse + by simply continuing to single-step. We have already + executed the solib function (backwards), and a few + steps will take us back through the trampoline to the + caller. */ + keep_going (ecs); + return; + } + else if (in_solib_dynsym_resolve_code (stop_pc)) + { + /* Stepped backward into the solib dynsym resolver. + Set a breakpoint at its start and continue, then + one more step will take us out. */ + struct symtab_and_line sr_sal; + init_sal (&sr_sal); + sr_sal.pc = ecs->stop_func_start; + sr_sal.pspace = get_frame_program_space (frame); + insert_step_resume_breakpoint_at_sal (gdbarch, + sr_sal, null_frame_id); + keep_going (ecs); + return; + } + } + /* If we're in the return path from a shared library trampoline, we want to proceed through the trampoline when stepping. */ if (gdbarch_in_solib_return_trampoline (gdbarch, @@ -3894,11 +4358,13 @@ infrun: not switching back to stepped thread, it has vanished\n"); init_sal (&sr_sal); /* initialize to zeroes */ sr_sal.pc = real_stop_pc; sr_sal.section = find_pc_overlay (sr_sal.pc); + sr_sal.pspace = get_frame_program_space (frame); /* Do not specify what the fp should be when we stop since on some machines the prologue is where the new fp value is established. */ - insert_step_resume_breakpoint_at_sal (sr_sal, null_frame_id); + insert_step_resume_breakpoint_at_sal (gdbarch, + sr_sal, null_frame_id); /* Restart without fiddling with the step ranges or other state. */ @@ -3928,7 +4394,7 @@ infrun: not switching back to stepped thread, it has vanished\n"); set step-mode) or we no longer know how to get back to the call site. */ if (step_stop_if_no_debug - || !frame_id_p (frame_unwind_id (frame))) + || !frame_id_p (frame_unwind_caller_id (frame))) { /* If we have no line number and the step-stop-if-no-debug is set, we stop the step so that the user has a chance to @@ -3974,6 +4440,82 @@ infrun: not switching back to stepped thread, it has vanished\n"); return; } + /* Look for "calls" to inlined functions, part one. If the inline + frame machinery detected some skipped call sites, we have entered + a new inline function. */ + + if (frame_id_eq (get_frame_id (get_current_frame ()), + ecs->event_thread->step_frame_id) + && inline_skipped_frames (ecs->ptid)) + { + struct symtab_and_line call_sal; + + if (debug_infrun) + fprintf_unfiltered (gdb_stdlog, + "infrun: stepped into inlined function\n"); + + find_frame_sal (get_current_frame (), &call_sal); + + if (ecs->event_thread->step_over_calls != STEP_OVER_ALL) + { + /* For "step", we're going to stop. But if the call site + for this inlined function is on the same source line as + we were previously stepping, go down into the function + first. Otherwise stop at the call site. */ + + if (call_sal.line == ecs->event_thread->current_line + && call_sal.symtab == ecs->event_thread->current_symtab) + step_into_inline_frame (ecs->ptid); + + ecs->event_thread->stop_step = 1; + print_stop_reason (END_STEPPING_RANGE, 0); + stop_stepping (ecs); + return; + } + else + { + /* For "next", we should stop at the call site if it is on a + different source line. Otherwise continue through the + inlined function. */ + if (call_sal.line == ecs->event_thread->current_line + && call_sal.symtab == ecs->event_thread->current_symtab) + keep_going (ecs); + else + { + ecs->event_thread->stop_step = 1; + print_stop_reason (END_STEPPING_RANGE, 0); + stop_stepping (ecs); + } + return; + } + } + + /* Look for "calls" to inlined functions, part two. If we are still + in the same real function we were stepping through, but we have + to go further up to find the exact frame ID, we are stepping + through a more inlined call beyond its call site. */ + + if (get_frame_type (get_current_frame ()) == INLINE_FRAME + && !frame_id_eq (get_frame_id (get_current_frame ()), + ecs->event_thread->step_frame_id) + && stepped_in_from (get_current_frame (), + ecs->event_thread->step_frame_id)) + { + if (debug_infrun) + fprintf_unfiltered (gdb_stdlog, + "infrun: stepping through inlined function\n"); + + if (ecs->event_thread->step_over_calls == STEP_OVER_ALL) + keep_going (ecs); + else + { + ecs->event_thread->stop_step = 1; + print_stop_reason (END_STEPPING_RANGE, 0); + stop_stepping (ecs); + } + return; + } + if ((stop_pc == stop_pc_sal.pc) && (ecs->event_thread->current_line != stop_pc_sal.line || ecs->event_thread->current_symtab != stop_pc_sal.symtab)) @@ -3999,9 +4541,7 @@ infrun: not switching back to stepped thread, it has vanished\n"); ecs->event_thread->step_range_start = stop_pc_sal.pc; ecs->event_thread->step_range_end = stop_pc_sal.end; - ecs->event_thread->step_frame_id = get_frame_id (frame); - ecs->event_thread->current_line = stop_pc_sal.line; - ecs->event_thread->current_symtab = stop_pc_sal.symtab; + set_step_info (frame, stop_pc_sal); if (debug_infrun) fprintf_unfiltered (gdb_stdlog, "infrun: keep going\n"); @@ -4098,11 +4638,12 @@ handle_step_into_function (struct gdbarch *gdbarch, init_sal (&sr_sal); /* initialize to zeroes */ sr_sal.pc = ecs->stop_func_start; sr_sal.section = find_pc_overlay (ecs->stop_func_start); + sr_sal.pspace = get_frame_program_space (get_current_frame ()); /* Do not specify what the fp should be when we stop since on some machines the prologue is where the new fp value is established. */ - insert_step_resume_breakpoint_at_sal (sr_sal, null_frame_id); + insert_step_resume_breakpoint_at_sal (gdbarch, sr_sal, null_frame_id); /* And make sure stepping stops right away then. */ ecs->event_thread->step_range_end = ecs->event_thread->step_range_start; @@ -4152,7 +4693,8 @@ 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 symtab_and_line sr_sal, +insert_step_resume_breakpoint_at_sal (struct gdbarch *gdbarch, + struct symtab_and_line sr_sal, struct frame_id sr_id) { /* There should never be more than one step-resume or longjmp-resume @@ -4162,11 +4704,11 @@ insert_step_resume_breakpoint_at_sal (struct symtab_and_line sr_sal, if (debug_infrun) fprintf_unfiltered (gdb_stdlog, - "infrun: inserting step-resume breakpoint at 0x%s\n", - paddr_nz (sr_sal.pc)); + "infrun: inserting step-resume breakpoint at %s\n", + paddress (gdbarch, sr_sal.pc)); inferior_thread ()->step_resume_breakpoint - = set_momentary_breakpoint (sr_sal, sr_id, bp_step_resume); + = set_momentary_breakpoint (gdbarch, sr_sal, sr_id, bp_step_resume); } /* Insert a "step-resume breakpoint" at RETURN_FRAME.pc. This is used @@ -4179,16 +4721,19 @@ insert_step_resume_breakpoint_at_sal (struct symtab_and_line sr_sal, static void insert_step_resume_breakpoint_at_frame (struct frame_info *return_frame) { - struct gdbarch *gdbarch = get_frame_arch (return_frame); struct symtab_and_line sr_sal; + struct gdbarch *gdbarch; gdb_assert (return_frame != NULL); init_sal (&sr_sal); /* initialize to zeros */ + gdbarch = get_frame_arch (return_frame); sr_sal.pc = gdbarch_addr_bits_remove (gdbarch, get_frame_pc (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 (sr_sal, get_frame_id (return_frame)); + insert_step_resume_breakpoint_at_sal (gdbarch, sr_sal, + get_stack_frame_id (return_frame)); } /* Similar to insert_step_resume_breakpoint_at_frame, except @@ -4204,24 +4749,28 @@ insert_step_resume_breakpoint_at_frame (struct frame_info *return_frame) This is a separate function rather than reusing insert_step_resume_breakpoint_at_frame in order to avoid get_prev_frame, which may stop prematurely (see the implementation - of frame_unwind_id for an example). */ + of frame_unwind_caller_id for an example). */ static void insert_step_resume_breakpoint_at_caller (struct frame_info *next_frame) { - struct gdbarch *gdbarch = get_frame_arch (next_frame); struct symtab_and_line sr_sal; + struct gdbarch *gdbarch; /* We shouldn't have gotten here if we don't know where the call site is. */ - gdb_assert (frame_id_p (frame_unwind_id (next_frame))); + gdb_assert (frame_id_p (frame_unwind_caller_id (next_frame))); init_sal (&sr_sal); /* initialize to zeros */ - sr_sal.pc = gdbarch_addr_bits_remove (gdbarch, frame_pc_unwind (next_frame)); + gdbarch = frame_unwind_caller_arch (next_frame); + sr_sal.pc = gdbarch_addr_bits_remove (gdbarch, + frame_unwind_caller_pc (next_frame)); sr_sal.section = find_pc_overlay (sr_sal.pc); + sr_sal.pspace = frame_unwind_program_space (next_frame); - insert_step_resume_breakpoint_at_sal (sr_sal, frame_unwind_id (next_frame)); + insert_step_resume_breakpoint_at_sal (gdbarch, sr_sal, + frame_unwind_caller_id (next_frame)); } /* Insert a "longjmp-resume" breakpoint at PC. This is used to set a @@ -4230,7 +4779,7 @@ insert_step_resume_breakpoint_at_caller (struct frame_info *next_frame) "step-resume" breakpoints. */ static void -insert_longjmp_resume_breakpoint (CORE_ADDR pc) +insert_longjmp_resume_breakpoint (struct gdbarch *gdbarch, CORE_ADDR pc) { /* There should never be more than one step-resume or longjmp-resume breakpoint per thread, so we should never be setting a new @@ -4239,11 +4788,11 @@ insert_longjmp_resume_breakpoint (CORE_ADDR pc) if (debug_infrun) fprintf_unfiltered (gdb_stdlog, - "infrun: inserting longjmp-resume breakpoint at 0x%s\n", - paddr_nz (pc)); + "infrun: inserting longjmp-resume breakpoint at %s\n", + paddress (gdbarch, pc)); inferior_thread ()->step_resume_breakpoint = - set_momentary_breakpoint_at_pc (pc, bp_longjmp_resume); + set_momentary_breakpoint_at_pc (gdbarch, pc, bp_longjmp_resume); } static void @@ -4353,19 +4902,7 @@ prepare_to_wait (struct execution_control_state *ecs) { if (debug_infrun) fprintf_unfiltered (gdb_stdlog, "infrun: prepare_to_wait\n"); - if (infwait_state == infwait_normal_state) - { - overlay_cache_invalid = 1; - - /* We have to invalidate the registers BEFORE calling - target_wait because they can be loaded from the target while - in target_wait. This makes remote debugging a bit more - efficient for those targets that provide critical registers - as part of their normal status mechanism. */ - registers_changed (); - waiton_ptid = pid_to_ptid (-1); - } /* This is the old end of the while loop. Let everybody know we want to wait for the inferior some more and get called again soon. */ @@ -4734,6 +5271,11 @@ done: Delete any breakpoint that is to be deleted at the next stop. */ breakpoint_auto_delete (inferior_thread ()->stop_bpstat); } + + /* Try to get rid of automatically added inferiors that are no + longer needed. Keeping those around slows down things linearly. + Note that this never removes the current inferior. */ + prune_inferiors (); } static int @@ -5151,29 +5693,21 @@ static struct lval_funcs siginfo_value_funcs = }; /* 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. */ + the current thread using architecture GDBARCH. Return a void value + if there's no object available. */ static struct value * -siginfo_make_value (struct internalvar *var) +siginfo_make_value (struct gdbarch *gdbarch, struct internalvar *var) { - struct type *type; - struct gdbarch *gdbarch; - if (target_has_stack - && !ptid_equal (inferior_ptid, null_ptid)) + && !ptid_equal (inferior_ptid, null_ptid) + && gdbarch_get_siginfo_type_p (gdbarch)) { - 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); - } + struct type *type = gdbarch_get_siginfo_type (gdbarch); + return allocate_computed_value (type, &siginfo_value_funcs, NULL); } - return allocate_value (builtin_type_void); + return allocate_value (builtin_type (gdbarch)->builtin_void); } @@ -5264,6 +5798,7 @@ struct inferior_status CORE_ADDR step_range_start; CORE_ADDR step_range_end; struct frame_id step_frame_id; + struct frame_id step_stack_frame_id; enum step_over_calls_kind step_over_calls; CORE_ADDR step_resume_break_address; int stop_after_trap; @@ -5293,6 +5828,7 @@ save_inferior_status (void) inf_status->step_range_start = tp->step_range_start; inf_status->step_range_end = tp->step_range_end; inf_status->step_frame_id = tp->step_frame_id; + inf_status->step_stack_frame_id = tp->step_stack_frame_id; inf_status->step_over_calls = tp->step_over_calls; inf_status->stop_after_trap = stop_after_trap; inf_status->stop_soon = inf->stop_soon; @@ -5346,6 +5882,7 @@ restore_inferior_status (struct inferior_status *inf_status) tp->step_range_start = inf_status->step_range_start; tp->step_range_end = inf_status->step_range_end; tp->step_frame_id = inf_status->step_frame_id; + tp->step_stack_frame_id = inf_status->step_stack_frame_id; tp->step_over_calls = inf_status->step_over_calls; stop_after_trap = inf_status->stop_after_trap; inf->stop_soon = inf_status->stop_soon; @@ -5446,6 +5983,25 @@ inferior_has_execd (ptid_t pid, char **execd_pathname) return 1; } +int +inferior_has_called_syscall (ptid_t pid, int *syscall_number) +{ + struct target_waitstatus last; + ptid_t last_ptid; + + get_last_target_status (&last_ptid, &last); + + if (last.kind != TARGET_WAITKIND_SYSCALL_ENTRY && + last.kind != TARGET_WAITKIND_SYSCALL_RETURN) + return 0; + + if (!ptid_equal (last_ptid, pid)) + return 0; + + *syscall_number = last.value.syscall_number; + return 1; +} + /* Oft used ptids */ ptid_t null_ptid; ptid_t minus_one_ptid; @@ -5791,6 +6347,30 @@ By default, the debugger will follow the parent process."), show_follow_fork_mode_string, &setlist, &showlist); + add_setshow_enum_cmd ("follow-exec-mode", class_run, + follow_exec_mode_names, + &follow_exec_mode_string, _("\ +Set debugger response to a program call of exec."), _("\ +Show debugger response to a program call of exec."), _("\ +An exec call replaces the program image of a process.\n\ +\n\ +follow-exec-mode can be:\n\ +\n\ + new - the debugger creates a new inferior and rebinds the process \n\ +to this new inferior. The program the process was running before\n\ +the exec call can be restarted afterwards by restarting the original\n\ +inferior.\n\ +\n\ + same - the debugger keeps the process bound to the same inferior.\n\ +The new executable image replaces the previous executable loaded in\n\ +the inferior. Restarting the inferior after the exec call restarts\n\ +the executable the process was running after the exec call.\n\ +\n\ +By default, the debugger will use the same inferior."), + NULL, + show_follow_exec_mode_string, + &setlist, &showlist); + add_setshow_enum_cmd ("scheduler-locking", class_run, scheduler_enums, &scheduler_mode, _("\ Set mode for locking scheduler during execution."), _("\ @@ -5849,6 +6429,14 @@ Options are 'forward' or 'reverse'."), set_exec_direction_func, show_exec_direction_func, &setlist, &showlist); + /* Set/show detach-on-fork: user-settable mode. */ + + add_setshow_boolean_cmd ("detach-on-fork", class_run, &detach_fork, _("\ +Set whether gdb will detach the child of a fork."), _("\ +Show whether gdb will detach the child of a fork."), _("\ +Tells gdb whether to detach the child of a fork."), + NULL, NULL, &setlist, &showlist); + /* ptid initializations */ null_ptid = ptid_build (0, 0, 0); minus_one_ptid = ptid_build (-1, 0, 0);