X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Fgdbserver%2Flinux-low.c;h=1d96ec23282f2247a96db9a230afb79ffea8d510;hb=0eb0a40713c6479e782e5a257793d28f647e38bd;hp=aa4c86884319ed7551926fcf09f4c09204d66536;hpb=94585166dfea8232c248044f9f4b1c217dc4ac2e;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c index aa4c868843..1d96ec2328 100644 --- a/gdb/gdbserver/linux-low.c +++ b/gdb/gdbserver/linux-low.c @@ -1,5 +1,5 @@ /* Low level interface to ptrace, for the remote server for GDB. - Copyright (C) 1995-2015 Free Software Foundation, Inc. + Copyright (C) 1995-2017 Free Software Foundation, Inc. This file is part of GDB. @@ -22,7 +22,7 @@ #include "agent.h" #include "tdesc.h" #include "rsp-low.h" - +#include "signals-state-save-restore.h" #include "nat/linux-nat.h" #include "nat/linux-waitpid.h" #include "gdb_wait.h" @@ -46,6 +46,10 @@ #include "filestuff.h" #include "tracepoint.h" #include "hostio.h" +#include +#include "common-inferior.h" +#include "nat/fork-inferior.h" +#include "environ.h" #ifndef ELFMAG0 /* Don't include here. If it got included by gdb_proc_service.h then ELFMAG0 will have been defined. If it didn't get included by @@ -70,16 +74,6 @@ #define O_LARGEFILE 0 #endif -#ifndef W_STOPCODE -#define W_STOPCODE(sig) ((sig) << 8 | 0x7f) -#endif - -/* This is the kernel's hard limit. Not to be confused with - SIGRTMIN. */ -#ifndef __SIGRTMIN -#define __SIGRTMIN 32 -#endif - /* Some targets did not define these ptrace constants from the start, so gdbserver defines them locally here. In the future, these may be removed after they are added to asm/ptrace.h. */ @@ -185,6 +179,14 @@ lwp_stop_reason (struct lwp_info *lwp) return lwp->stop_reason; } +/* See nat/linux-nat.h. */ + +int +lwp_is_stepping (struct lwp_info *lwp) +{ + return lwp->stepping; +} + /* A list of all unknown processes which receive stop signals. Some other process will presumably claim each of these as forked children momentarily. */ @@ -261,6 +263,7 @@ static void linux_resume_one_lwp (struct lwp_info *lwp, static void linux_resume (struct thread_resume *resume_info, size_t n); static void stop_all_lwps (int suspend, struct lwp_info *except); static void unstop_all_lwps (int unsuspend, struct lwp_info *except); +static void unsuspend_all_lwps (struct lwp_info *except); static int linux_wait_for_event_filtered (ptid_t wait_ptid, ptid_t filter_ptid, int *wstat, int options); static int linux_wait_for_event (ptid_t ptid, int *wstat, int options); @@ -274,18 +277,32 @@ static int finish_step_over (struct lwp_info *lwp); static int kill_lwp (unsigned long lwpid, int signo); static void enqueue_pending_signal (struct lwp_info *lwp, int signal, siginfo_t *info); static void complete_ongoing_step_over (void); +static int linux_low_ptrace_options (int attached); +static int check_ptrace_stopped_lwp_gone (struct lwp_info *lp); +static int proceed_one_lwp (struct inferior_list_entry *entry, void *except); /* When the event-loop is doing a step-over, this points at the thread being stepped. */ ptid_t step_over_bkpt; -/* True if the low target can hardware single-step. Such targets - don't need a BREAKPOINT_REINSERT_ADDR callback. */ +/* True if the low target can hardware single-step. */ static int can_hardware_single_step (void) { - return (the_low_target.breakpoint_reinsert_addr == NULL); + if (the_low_target.supports_hardware_single_step != NULL) + return the_low_target.supports_hardware_single_step (); + else + return 0; +} + +/* True if the low target can software single-step. Such targets + implement the GET_NEXT_PCS callback. */ + +static int +can_software_single_step (void) +{ + return (the_low_target.get_next_pcs != NULL); } /* True if the low target supports memory breakpoints. If so, we'll @@ -420,7 +437,7 @@ linux_add_process (int pid, int attached) static CORE_ADDR get_pc (struct lwp_info *lwp); -/* Implement the arch_setup target_ops method. */ +/* Call the target arch_setup function on the current thread. */ static void linux_arch_setup (void) @@ -457,6 +474,13 @@ handle_extended_wait (struct lwp_info **orig_event_lwp, int wstat) struct thread_info *event_thr = get_lwp_thread (event_lwp); struct lwp_info *new_lwp; + gdb_assert (event_lwp->waitstatus.kind == TARGET_WAITKIND_IGNORE); + + /* All extended events we currently use are mid-syscall. Only + PTRACE_EVENT_STOP is delivered more like a signal-stop, but + you have to be using PTRACE_SEIZE to get that. */ + event_lwp->syscall_state = TARGET_WAITKIND_SYSCALL_ENTRY; + if ((event == PTRACE_EVENT_FORK) || (event == PTRACE_EVENT_VFORK) || (event == PTRACE_EVENT_CLONE)) { @@ -519,8 +543,11 @@ handle_extended_wait (struct lwp_info **orig_event_lwp, int wstat) child_thr->last_status.kind = TARGET_WAITKIND_STOPPED; /* If we're suspending all threads, leave this one suspended - too. */ - if (stopping_threads == STOPPING_AND_SUSPENDING_THREADS) + too. If the fork/clone parent is stepping over a breakpoint, + all other threads have been suspended already. Leave the + child suspended too. */ + if (stopping_threads == STOPPING_AND_SUSPENDING_THREADS + || event_lwp->bp_reinsert != 0) { if (debug_threads) debug_printf ("HEW: leaving child suspended\n"); @@ -529,11 +556,21 @@ handle_extended_wait (struct lwp_info **orig_event_lwp, int wstat) parent_proc = get_thread_process (event_thr); child_proc->attached = parent_proc->attached; - clone_all_breakpoints (&child_proc->breakpoints, - &child_proc->raw_breakpoints, - parent_proc->breakpoints); - tdesc = XNEW (struct target_desc); + if (event_lwp->bp_reinsert != 0 + && can_software_single_step () + && event == PTRACE_EVENT_VFORK) + { + /* If we leave single-step breakpoints there, child will + hit it, so uninsert single-step breakpoints from parent + (and child). Once vfork child is done, reinsert + them back to parent. */ + uninsert_single_step_breakpoints (event_thr); + } + + clone_all_breakpoints (child_thr, event_thr); + + tdesc = allocate_target_description (); copy_target_description (tdesc, parent_proc->tdesc); child_proc->tdesc = tdesc; @@ -555,6 +592,28 @@ handle_extended_wait (struct lwp_info **orig_event_lwp, int wstat) event_lwp->status_pending_p = 1; event_lwp->status_pending = wstat; + /* Link the threads until the parent event is passed on to + higher layers. */ + event_lwp->fork_relative = child_lwp; + child_lwp->fork_relative = event_lwp; + + /* If the parent thread is doing step-over with single-step + breakpoints, the list of single-step breakpoints are cloned + from the parent's. Remove them from the child process. + In case of vfork, we'll reinsert them back once vforked + child is done. */ + if (event_lwp->bp_reinsert != 0 + && can_software_single_step ()) + { + /* The child process is forked and stopped, so it is safe + to access its memory without stopping all other threads + from other processes. */ + delete_single_step_breakpoints (child_thr); + + gdb_assert (has_single_step_breakpoints (event_thr)); + gdb_assert (!has_single_step_breakpoints (child_thr)); + } + /* Report the event. */ return 0; } @@ -573,9 +632,12 @@ handle_extended_wait (struct lwp_info **orig_event_lwp, int wstat) before calling linux_resume_one_lwp. */ new_lwp->stopped = 1; - /* If we're suspending all threads, leave this one suspended - too. */ - if (stopping_threads == STOPPING_AND_SUSPENDING_THREADS) + /* If we're suspending all threads, leave this one suspended + too. If the fork/clone parent is stepping over a breakpoint, + all other threads have been suspended already. Leave the + child suspended too. */ + if (stopping_threads == STOPPING_AND_SUSPENDING_THREADS + || event_lwp->bp_reinsert != 0) new_lwp->suspended = 1; /* Normally we will get the pending SIGSTOP. But in some cases @@ -587,6 +649,12 @@ handle_extended_wait (struct lwp_info **orig_event_lwp, int wstat) new_lwp->status_pending_p = 1; new_lwp->status_pending = status; } + else if (report_thread_events) + { + new_lwp->waitstatus.kind = TARGET_WAITKIND_THREAD_CREATED; + new_lwp->status_pending_p = 1; + new_lwp->status_pending = status; + } /* Don't report the event. */ return 1; @@ -595,12 +663,20 @@ handle_extended_wait (struct lwp_info **orig_event_lwp, int wstat) { event_lwp->waitstatus.kind = TARGET_WAITKIND_VFORK_DONE; + if (event_lwp->bp_reinsert != 0 && can_software_single_step ()) + { + reinsert_single_step_breakpoints (event_thr); + + gdb_assert (has_single_step_breakpoints (event_thr)); + } + /* Report the event. */ return 0; } else if (event == PTRACE_EVENT_EXEC && report_exec_events) { struct process_info *proc; + VEC (int) *syscalls_to_catch; ptid_t event_ptid; pid_t event_pid; @@ -614,8 +690,12 @@ handle_extended_wait (struct lwp_info **orig_event_lwp, int wstat) event_ptid = ptid_of (event_thr); event_pid = ptid_get_pid (event_ptid); - /* Delete the execing process and all its threads. */ + /* Save the syscall list from the execing process. */ proc = get_thread_process (event_thr); + syscalls_to_catch = proc->syscalls_to_catch; + proc->syscalls_to_catch = NULL; + + /* Delete the execing process and all its threads. */ linux_mourn (proc); current_thread = NULL; @@ -638,6 +718,14 @@ handle_extended_wait (struct lwp_info **orig_event_lwp, int wstat) event_thr->last_resume_kind = resume_continue; event_thr->last_status.kind = TARGET_WAITKIND_IGNORE; + /* Update syscall state in the new lwp, effectively mid-syscall too. */ + event_lwp->syscall_state = TARGET_WAITKIND_SYSCALL_ENTRY; + + /* Restore the list to catch. Don't rely on the client, which is free + to avoid sending a new list when the architecture doesn't change. + Also, for ANY_SYSCALL, the architecture doesn't really matter. */ + proc->syscalls_to_catch = syscalls_to_catch; + /* Report the event. */ *orig_event_lwp = event_lwp; return 0; @@ -672,32 +760,45 @@ get_pc (struct lwp_info *lwp) return pc; } -/* This function should only be called if LWP got a SIGTRAP. - The SIGTRAP could mean several things. +/* This function should only be called if LWP got a SYSCALL_SIGTRAP. + Fill *SYSNO with the syscall nr trapped. */ + +static void +get_syscall_trapinfo (struct lwp_info *lwp, int *sysno) +{ + struct thread_info *saved_thread; + struct regcache *regcache; + + if (the_low_target.get_syscall_trapinfo == NULL) + { + /* If we cannot get the syscall trapinfo, report an unknown + system call number. */ + *sysno = UNKNOWN_SYSCALL; + return; + } + + saved_thread = current_thread; + current_thread = get_lwp_thread (lwp); - On i386, where decr_pc_after_break is non-zero: + regcache = get_thread_regcache (current_thread, 1); + (*the_low_target.get_syscall_trapinfo) (regcache, sysno); - If we were single-stepping this process using PTRACE_SINGLESTEP, we - will get only the one SIGTRAP. The value of $eip will be the next - instruction. If the instruction we stepped over was a breakpoint, - we need to decrement the PC. + if (debug_threads) + debug_printf ("get_syscall_trapinfo sysno %d\n", *sysno); - If we continue the process using PTRACE_CONT, we will get a - SIGTRAP when we hit a breakpoint. The value of $eip will be - the instruction after the breakpoint (i.e. needs to be - decremented). If we report the SIGTRAP to GDB, we must also - report the undecremented PC. If the breakpoint is removed, we - must resume at the decremented PC. + current_thread = saved_thread; +} - On a non-decr_pc_after_break machine with hardware or kernel - single-step: +static int check_stopped_by_watchpoint (struct lwp_info *child); - If we either single-step a breakpoint instruction, or continue and - hit a breakpoint instruction, our PC will point at the breakpoint - instruction. */ +/* Called when the LWP stopped for a signal/trap. If it stopped for a + trap check what caused it (breakpoint, watchpoint, trace, etc.), + and save the result in the LWP's stop_reason field. If it stopped + for a breakpoint, decrement the PC if necessary on the lwp's + architecture. Returns true if we now have the LWP's stop PC. */ static int -check_stopped_by_breakpoint (struct lwp_info *lwp) +save_stop_reason (struct lwp_info *lwp) { CORE_ADDR pc; CORE_ADDR sw_breakpoint_pc; @@ -722,56 +823,39 @@ check_stopped_by_breakpoint (struct lwp_info *lwp) { if (siginfo.si_signo == SIGTRAP) { - if (GDB_ARCH_IS_TRAP_BRKPT (siginfo.si_code)) + if (GDB_ARCH_IS_TRAP_BRKPT (siginfo.si_code) + && GDB_ARCH_IS_TRAP_HWBKPT (siginfo.si_code)) { - if (debug_threads) - { - struct thread_info *thr = get_lwp_thread (lwp); - - debug_printf ("CSBB: %s stopped by software breakpoint\n", - target_pid_to_str (ptid_of (thr))); - } - - /* Back up the PC if necessary. */ - if (pc != sw_breakpoint_pc) - { - struct regcache *regcache - = get_thread_regcache (current_thread, 1); - (*the_low_target.set_pc) (regcache, sw_breakpoint_pc); - } - - lwp->stop_pc = sw_breakpoint_pc; + /* The si_code is ambiguous on this arch -- check debug + registers. */ + if (!check_stopped_by_watchpoint (lwp)) + lwp->stop_reason = TARGET_STOPPED_BY_SW_BREAKPOINT; + } + else if (GDB_ARCH_IS_TRAP_BRKPT (siginfo.si_code)) + { + /* If we determine the LWP stopped for a SW breakpoint, + trust it. Particularly don't check watchpoint + registers, because at least on s390, we'd find + stopped-by-watchpoint as long as there's a watchpoint + set. */ lwp->stop_reason = TARGET_STOPPED_BY_SW_BREAKPOINT; - current_thread = saved_thread; - return 1; } - else if (siginfo.si_code == TRAP_HWBKPT) + else if (GDB_ARCH_IS_TRAP_HWBKPT (siginfo.si_code)) { - if (debug_threads) - { - struct thread_info *thr = get_lwp_thread (lwp); - - debug_printf ("CSBB: %s stopped by hardware " - "breakpoint/watchpoint\n", - target_pid_to_str (ptid_of (thr))); - } - - lwp->stop_pc = pc; - lwp->stop_reason = TARGET_STOPPED_BY_HW_BREAKPOINT; - current_thread = saved_thread; - return 1; + /* This can indicate either a hardware breakpoint or + hardware watchpoint. Check debug registers. */ + if (!check_stopped_by_watchpoint (lwp)) + lwp->stop_reason = TARGET_STOPPED_BY_HW_BREAKPOINT; } else if (siginfo.si_code == TRAP_TRACE) { - if (debug_threads) - { - struct thread_info *thr = get_lwp_thread (lwp); - - debug_printf ("CSBB: %s stopped by trace\n", - target_pid_to_str (ptid_of (thr))); - } - - lwp->stop_reason = TARGET_STOPPED_BY_SINGLE_STEP; + /* We may have single stepped an instruction that + triggered a watchpoint. In that case, on some + architectures (such as x86), instead of TRAP_HWBKPT, + si_code indicates TRAP_TRACE, and we need to check + the debug registers separately. */ + if (!check_stopped_by_watchpoint (lwp)) + lwp->stop_reason = TARGET_STOPPED_BY_SINGLE_STEP; } } } @@ -782,6 +866,16 @@ check_stopped_by_breakpoint (struct lwp_info *lwp) case we need to report the breakpoint PC. */ if ((!lwp->stepping || lwp->stop_pc == sw_breakpoint_pc) && (*the_low_target.breakpoint_at) (sw_breakpoint_pc)) + lwp->stop_reason = TARGET_STOPPED_BY_SW_BREAKPOINT; + + if (hardware_breakpoint_inserted_here (pc)) + lwp->stop_reason = TARGET_STOPPED_BY_HW_BREAKPOINT; + + if (lwp->stop_reason == TARGET_STOPPED_BY_NO_REASON) + check_stopped_by_watchpoint (lwp); +#endif + + if (lwp->stop_reason == TARGET_STOPPED_BY_SW_BREAKPOINT) { if (debug_threads) { @@ -793,19 +887,16 @@ check_stopped_by_breakpoint (struct lwp_info *lwp) /* Back up the PC if necessary. */ if (pc != sw_breakpoint_pc) - { + { struct regcache *regcache = get_thread_regcache (current_thread, 1); (*the_low_target.set_pc) (regcache, sw_breakpoint_pc); } - lwp->stop_pc = sw_breakpoint_pc; - lwp->stop_reason = TARGET_STOPPED_BY_SW_BREAKPOINT; - current_thread = saved_thread; - return 1; + /* Update this so we record the correct stop PC below. */ + pc = sw_breakpoint_pc; } - - if (hardware_breakpoint_inserted_here (pc)) + else if (lwp->stop_reason == TARGET_STOPPED_BY_HW_BREAKPOINT) { if (debug_threads) { @@ -814,16 +905,31 @@ check_stopped_by_breakpoint (struct lwp_info *lwp) debug_printf ("CSBB: %s stopped by hardware breakpoint\n", target_pid_to_str (ptid_of (thr))); } + } + else if (lwp->stop_reason == TARGET_STOPPED_BY_WATCHPOINT) + { + if (debug_threads) + { + struct thread_info *thr = get_lwp_thread (lwp); - lwp->stop_pc = pc; - lwp->stop_reason = TARGET_STOPPED_BY_HW_BREAKPOINT; - current_thread = saved_thread; - return 1; + debug_printf ("CSBB: %s stopped by hardware watchpoint\n", + target_pid_to_str (ptid_of (thr))); + } + } + else if (lwp->stop_reason == TARGET_STOPPED_BY_SINGLE_STEP) + { + if (debug_threads) + { + struct thread_info *thr = get_lwp_thread (lwp); + + debug_printf ("CSBB: %s stopped by trace\n", + target_pid_to_str (ptid_of (thr))); + } } -#endif + lwp->stop_pc = pc; current_thread = saved_thread; - return 0; + return 1; } static struct lwp_info * @@ -843,61 +949,57 @@ add_lwp (ptid_t ptid) return lwp; } +/* Callback to be used when calling fork_inferior, responsible for + actually initiating the tracing of the inferior. */ + +static void +linux_ptrace_fun () +{ + if (ptrace (PTRACE_TRACEME, 0, (PTRACE_TYPE_ARG3) 0, + (PTRACE_TYPE_ARG4) 0) < 0) + trace_start_error_with_name ("ptrace"); + + if (setpgid (0, 0) < 0) + trace_start_error_with_name ("setpgid"); + + /* If GDBserver is connected to gdb via stdio, redirect the inferior's + stdout to stderr so that inferior i/o doesn't corrupt the connection. + Also, redirect stdin to /dev/null. */ + if (remote_connection_is_stdio ()) + { + if (close (0) < 0) + trace_start_error_with_name ("close"); + if (open ("/dev/null", O_RDONLY) < 0) + trace_start_error_with_name ("open"); + if (dup2 (2, 1) < 0) + trace_start_error_with_name ("dup2"); + if (write (2, "stdin/stdout redirected\n", + sizeof ("stdin/stdout redirected\n") - 1) < 0) + { + /* Errors ignored. */; + } + } +} + /* Start an inferior process and returns its pid. - ALLARGS is a vector of program-name and args. */ + PROGRAM is the name of the program to be started, and PROGRAM_ARGS + are its arguments. */ static int -linux_create_inferior (char *program, char **allargs) +linux_create_inferior (const char *program, + const std::vector &program_args) { struct lwp_info *new_lwp; int pid; ptid_t ptid; struct cleanup *restore_personality = maybe_disable_address_space_randomization (disable_randomization); + std::string str_program_args = stringify_argv (program_args); -#if defined(__UCLIBC__) && defined(HAS_NOMMU) - pid = vfork (); -#else - pid = fork (); -#endif - if (pid < 0) - perror_with_name ("fork"); - - if (pid == 0) - { - close_most_fds (); - ptrace (PTRACE_TRACEME, 0, (PTRACE_TYPE_ARG3) 0, (PTRACE_TYPE_ARG4) 0); - -#ifndef __ANDROID__ /* Bionic doesn't use SIGRTMIN the way glibc does. */ - signal (__SIGRTMIN + 1, SIG_DFL); -#endif - - setpgid (0, 0); - - /* If gdbserver is connected to gdb via stdio, redirect the inferior's - stdout to stderr so that inferior i/o doesn't corrupt the connection. - Also, redirect stdin to /dev/null. */ - if (remote_connection_is_stdio ()) - { - close (0); - open ("/dev/null", O_RDONLY); - dup2 (2, 1); - if (write (2, "stdin/stdout redirected\n", - sizeof ("stdin/stdout redirected\n") - 1) < 0) - { - /* Errors ignored. */; - } - } - - execv (program, allargs); - if (errno == ENOENT) - execvp (program, allargs); - - fprintf (stderr, "Cannot exec %s: %s.\n", program, - strerror (errno)); - fflush (stderr); - _exit (0177); - } + pid = fork_inferior (program, + str_program_args.c_str (), + get_environ ()->envp (), linux_ptrace_fun, + NULL, NULL, NULL, NULL); do_cleanups (restore_personality); @@ -907,9 +1009,30 @@ linux_create_inferior (char *program, char **allargs) new_lwp = add_lwp (ptid); new_lwp->must_set_ptrace_flags = 1; + post_fork_inferior (pid, program); + return pid; } +/* Implement the post_create_inferior target_ops method. */ + +static void +linux_post_create_inferior (void) +{ + struct lwp_info *lwp = get_thread_lwp (current_thread); + + linux_arch_setup (); + + if (lwp->must_set_ptrace_flags) + { + struct process_info *proc = current_process (); + int options = linux_low_ptrace_options (proc->attached); + + linux_enable_event_reporting (lwpid_of (current_thread), options); + lwp->must_set_ptrace_flags = 0; + } +} + /* Attach to an inferior process. Returns 0 on success, ERRNO on error. */ @@ -1039,12 +1162,16 @@ attach_proc_task_lwp_callback (ptid_t ptid) return 0; } +static void async_file_mark (void); + /* Attach to PID. If PID is the tgid, attach to it and all of its threads. */ static int linux_attach (unsigned long pid) { + struct process_info *proc; + struct thread_info *initial_thread; ptid_t ptid = ptid_build (pid, pid, 0); int err; @@ -1055,17 +1182,12 @@ linux_attach (unsigned long pid) error ("Cannot attach to process %ld: %s", pid, linux_ptrace_attach_fail_reason_string (ptid, err)); - linux_add_process (pid, 1); + proc = linux_add_process (pid, 1); - if (!non_stop) - { - struct thread_info *thread; - - /* Don't ignore the initial SIGSTOP if we just attached to this - process. It will be collected by wait shortly. */ - thread = find_thread_ptid (ptid_build (pid, pid, 0)); - thread->last_resume_kind = resume_stop; - } + /* Don't ignore the initial SIGSTOP if we just attached to this + process. It will be collected by wait shortly. */ + initial_thread = find_thread_ptid (ptid_build (pid, pid, 0)); + initial_thread->last_resume_kind = resume_stop; /* We must attach to every LWP. If /proc is mounted, use that to find them now. On the one hand, the inferior may be using raw @@ -1077,6 +1199,38 @@ linux_attach (unsigned long pid) that once thread_db is loaded, we'll still use it to list threads and associate pthread info with each LWP. */ linux_proc_attach_tgid_threads (pid, attach_proc_task_lwp_callback); + + /* GDB will shortly read the xml target description for this + process, to figure out the process' architecture. But the target + description is only filled in when the first process/thread in + the thread group reports its initial PTRACE_ATTACH SIGSTOP. Do + that now, otherwise, if GDB is fast enough, it could read the + target description _before_ that initial stop. */ + if (non_stop) + { + struct lwp_info *lwp; + int wstat, lwpid; + ptid_t pid_ptid = pid_to_ptid (pid); + + lwpid = linux_wait_for_event_filtered (pid_ptid, pid_ptid, + &wstat, __WALL); + gdb_assert (lwpid > 0); + + lwp = find_lwp_pid (pid_to_ptid (lwpid)); + + if (!WIFSTOPPED (wstat) || WSTOPSIG (wstat) != SIGSTOP) + { + lwp->status_pending_p = 1; + lwp->status_pending = wstat; + } + + initial_thread->last_resume_kind = resume_continue; + + async_file_mark (); + + gdb_assert (proc->tdesc != NULL); + } + return 0; } @@ -1089,7 +1243,7 @@ struct counter static int second_thread_of_pid_p (struct inferior_list_entry *entry, void *args) { - struct counter *counter = args; + struct counter *counter = (struct counter *) args; if (ptid_get_pid (entry->id) == counter->pid) { @@ -1123,13 +1277,12 @@ linux_kill_one_lwp (struct lwp_info *lwp) ptrace(CONT, pid, 0,0) and just resumes the tracee. A better alternative is to kill with SIGKILL. We only need one SIGKILL per process, not one for each thread. But since we still support - linuxthreads, and we also support debugging programs using raw - clone without CLONE_THREAD, we send one for each thread. For - years, we used PTRACE_KILL only, so we're being a bit paranoid - about some old kernels where PTRACE_KILL might work better - (dubious if there are any such, but that's why it's paranoia), so - we try SIGKILL first, PTRACE_KILL second, and so we're fine - everywhere. */ + support debugging programs using raw clone without CLONE_THREAD, + we send one for each thread. For years, we used PTRACE_KILL + only, so we're being a bit paranoid about some old kernels where + PTRACE_KILL might work better (dubious if there are any such, but + that's why it's paranoia), so we try SIGKILL first, PTRACE_KILL + second, and so we're fine everywhere. */ errno = 0; kill_lwp (pid, SIGKILL); @@ -1344,16 +1497,14 @@ get_detach_signal (struct thread_info *thread) } } -static int -linux_detach_one_lwp (struct inferior_list_entry *entry, void *args) +/* Detach from LWP. */ + +static void +linux_detach_one_lwp (struct lwp_info *lwp) { - struct thread_info *thread = (struct thread_info *) entry; - struct lwp_info *lwp = get_thread_lwp (thread); - int pid = * (int *) args; + struct thread_info *thread = get_lwp_thread (lwp); int sig; - - if (ptid_get_pid (entry->id) != pid) - return 0; + int lwpid; /* If there is a pending SIGSTOP, get rid of it. */ if (lwp->stop_expected) @@ -1366,22 +1517,94 @@ linux_detach_one_lwp (struct inferior_list_entry *entry, void *args) lwp->stop_expected = 0; } - /* Flush any pending changes to the process's registers. */ - regcache_invalidate_thread (thread); - /* Pass on any pending signal for this thread. */ sig = get_detach_signal (thread); - /* Finally, let it resume. */ - if (the_low_target.prepare_to_resume != NULL) - the_low_target.prepare_to_resume (lwp); - if (ptrace (PTRACE_DETACH, lwpid_of (thread), (PTRACE_TYPE_ARG3) 0, + /* Preparing to resume may try to write registers, and fail if the + lwp is zombie. If that happens, ignore the error. We'll handle + it below, when detach fails with ESRCH. */ + TRY + { + /* Flush any pending changes to the process's registers. */ + regcache_invalidate_thread (thread); + + /* Finally, let it resume. */ + if (the_low_target.prepare_to_resume != NULL) + the_low_target.prepare_to_resume (lwp); + } + CATCH (ex, RETURN_MASK_ERROR) + { + if (!check_ptrace_stopped_lwp_gone (lwp)) + throw_exception (ex); + } + END_CATCH + + lwpid = lwpid_of (thread); + if (ptrace (PTRACE_DETACH, lwpid, (PTRACE_TYPE_ARG3) 0, (PTRACE_TYPE_ARG4) (long) sig) < 0) - error (_("Can't detach %s: %s"), - target_pid_to_str (ptid_of (thread)), - strerror (errno)); + { + int save_errno = errno; + + /* We know the thread exists, so ESRCH must mean the lwp is + zombie. This can happen if one of the already-detached + threads exits the whole thread group. In that case we're + still attached, and must reap the lwp. */ + if (save_errno == ESRCH) + { + int ret, status; + + ret = my_waitpid (lwpid, &status, __WALL); + if (ret == -1) + { + warning (_("Couldn't reap LWP %d while detaching: %s"), + lwpid, strerror (errno)); + } + else if (!WIFEXITED (status) && !WIFSIGNALED (status)) + { + warning (_("Reaping LWP %d while detaching " + "returned unexpected status 0x%x"), + lwpid, status); + } + } + else + { + error (_("Can't detach %s: %s"), + target_pid_to_str (ptid_of (thread)), + strerror (save_errno)); + } + } + else if (debug_threads) + { + debug_printf ("PTRACE_DETACH (%s, %s, 0) (OK)\n", + target_pid_to_str (ptid_of (thread)), + strsignal (sig)); + } delete_lwp (lwp); +} + +/* Callback for find_inferior. Detaches from non-leader threads of a + given process. */ + +static int +linux_detach_lwp_callback (struct inferior_list_entry *entry, void *args) +{ + struct thread_info *thread = (struct thread_info *) entry; + struct lwp_info *lwp = get_thread_lwp (thread); + int pid = *(int *) args; + int lwpid = lwpid_of (thread); + + /* Skip other processes. */ + if (ptid_get_pid (entry->id) != pid) + return 0; + + /* We don't actually detach from the thread group leader just yet. + If the thread group exits, we must reap the zombie clone lwps + before we're able to reap the leader. */ + if (ptid_get_pid (entry->id) == lwpid) + return 0; + + linux_detach_one_lwp (lwp); return 0; } @@ -1389,6 +1612,7 @@ static int linux_detach (int pid) { struct process_info *process; + struct lwp_info *main_lwp; process = find_process_pid (pid); if (process == NULL) @@ -1412,7 +1636,13 @@ linux_detach (int pid) /* Stabilize threads (move out of jump pads). */ stabilize_threads (); - find_inferior (&all_threads, linux_detach_one_lwp, &pid); + /* Detach from the clone lwps first. If the thread group exits just + while we're detaching, we must reap the clone lwps before we're + able to reap the leader. */ + find_inferior (&all_threads, linux_detach_lwp_callback, &pid); + + main_lwp = find_lwp_pid (pid_to_ptid (pid)); + linux_detach_one_lwp (main_lwp); the_target->mourn (process); @@ -1429,7 +1659,7 @@ delete_lwp_callback (struct inferior_list_entry *entry, void *proc) { struct thread_info *thread = (struct thread_info *) entry; struct lwp_info *lwp = get_thread_lwp (thread); - struct process_info *process = proc; + struct process_info *process = (struct process_info *) proc; if (pid_of (thread) == pid_of (process)) delete_lwp (lwp); @@ -1496,12 +1726,6 @@ thread_still_has_status_pending_p (struct thread_info *thread) if (!lp->status_pending_p) return 0; - /* If we got a `vCont;t', but we haven't reported a stop yet, do - report any status pending the LWP may have. */ - if (thread->last_resume_kind == resume_stop - && thread->last_status.kind != TARGET_WAITKIND_IGNORE) - return 0; - if (thread->last_resume_kind != resume_stop && (lp->stop_reason == TARGET_STOPPED_BY_SW_BREAKPOINT || lp->stop_reason == TARGET_STOPPED_BY_HW_BREAKPOINT)) @@ -1558,6 +1782,26 @@ thread_still_has_status_pending_p (struct thread_info *thread) return 1; } +/* Returns true if LWP is resumed from the client's perspective. */ + +static int +lwp_resumed (struct lwp_info *lwp) +{ + struct thread_info *thread = get_lwp_thread (lwp); + + if (thread->last_resume_kind != resume_stop) + return 1; + + /* Did gdb send us a `vCont;t', but we haven't reported the + corresponding stop to gdb yet? If so, the thread is still + resumed/running from gdb's perspective. */ + if (thread->last_resume_kind == resume_stop + && thread->last_status.kind == TARGET_WAITKIND_IGNORE) + return 1; + + return 0; +} + /* Return 1 if this lwp has an interesting status pending. */ static int status_pending_p_callback (struct inferior_list_entry *entry, void *arg) @@ -1571,6 +1815,9 @@ status_pending_p_callback (struct inferior_list_entry *entry, void *arg) if (!ptid_match (ptid_of (thread), ptid)) return 0; + if (!lwp_resumed (lp)) + return 0; + if (lp->status_pending_p && !thread_still_has_status_pending_p (thread)) { @@ -1737,10 +1984,9 @@ check_zombie_leaders (void) thread execs). */ if (debug_threads) - fprintf (stderr, - "CZL: Thread group leader %d zombie " - "(it exited, or another thread execd).\n", - leader_pid); + debug_printf ("CZL: Thread group leader %d zombie " + "(it exited, or another thread execd).\n", + leader_pid); delete_lwp (leader_lp); } @@ -1836,7 +2082,9 @@ handle_tracepoints (struct lwp_info *lwp) lwp_suspended_decr (lwp); gdb_assert (lwp->suspended == 0); - gdb_assert (!stabilizing_threads || lwp->collecting_fast_tracepoint); + gdb_assert (!stabilizing_threads + || (lwp->collecting_fast_tracepoint + != fast_tpoint_collect_result::not_collecting)); if (tpoint_related_event) { @@ -1848,10 +2096,10 @@ handle_tracepoints (struct lwp_info *lwp) return 0; } -/* Convenience wrapper. Returns true if LWP is presently collecting a - fast tracepoint. */ +/* Convenience wrapper. Returns information about LWP's fast tracepoint + collection status. */ -static int +static fast_tpoint_collect_result linux_fast_tracepoint_collecting (struct lwp_info *lwp, struct fast_tpoint_collect_status *status) { @@ -1859,14 +2107,14 @@ linux_fast_tracepoint_collecting (struct lwp_info *lwp, struct thread_info *thread = get_lwp_thread (lwp); if (the_low_target.get_thread_area == NULL) - return 0; + return fast_tpoint_collect_result::not_collecting; /* Get the thread area address. This is used to recognize which thread is which when tracing with the in-process agent library. We don't read anything from the address, and treat it as opaque; it's the address itself that we assume is unique per-thread. */ if ((*the_low_target.get_thread_area) (lwpid_of (thread), &thread_area) == -1) - return 0; + return fast_tpoint_collect_result::not_collecting; return fast_tracepoint_collecting (thread_area, lwp->stop_pc, status); } @@ -1890,14 +2138,14 @@ maybe_move_out_of_jump_pad (struct lwp_info *lwp, int *wstat) && agent_loaded_p ()) { struct fast_tpoint_collect_status status; - int r; if (debug_threads) debug_printf ("Checking whether LWP %ld needs to move out of the " "jump pad.\n", lwpid_of (current_thread)); - r = linux_fast_tracepoint_collecting (lwp, &status); + fast_tpoint_collect_result r + = linux_fast_tracepoint_collecting (lwp, &status); if (wstat == NULL || (WSTOPSIG (*wstat) != SIGILL @@ -1907,9 +2155,10 @@ maybe_move_out_of_jump_pad (struct lwp_info *lwp, int *wstat) { lwp->collecting_fast_tracepoint = r; - if (r != 0) + if (r != fast_tpoint_collect_result::not_collecting) { - if (r == 1 && lwp->exit_jump_pad_bkpt == NULL) + if (r == fast_tpoint_collect_result::before_insn + && lwp->exit_jump_pad_bkpt == NULL) { /* Haven't executed the original instruction yet. Set breakpoint there, and wait till it's hit, @@ -1935,9 +2184,10 @@ maybe_move_out_of_jump_pad (struct lwp_info *lwp, int *wstat) reporting to GDB. Otherwise, it's an IPA lib bug: just report the signal to GDB, and pray for the best. */ - lwp->collecting_fast_tracepoint = 0; + lwp->collecting_fast_tracepoint + = fast_tpoint_collect_result::not_collecting; - if (r != 0 + if (r != fast_tpoint_collect_result::not_collecting && (status.adjusted_insn_addr <= lwp->stop_pc && lwp->stop_pc < status.adjusted_insn_addr_end)) { @@ -2164,6 +2414,8 @@ linux_low_ptrace_options (int attached) if (report_exec_events) options |= PTRACE_O_TRACEEXEC; + options |= PTRACE_O_TRACESYSGOOD; + return options; } @@ -2235,26 +2487,30 @@ linux_low_filter_event (int lwpid, int wstat) { if (debug_threads) debug_printf ("LLFE: %d exited.\n", lwpid); - if (num_lwps (pid_of (thread)) > 1) - { - /* If there is at least one more LWP, then the exit signal was - not the end of the debugged application and should be - ignored. */ - delete_lwp (child); - return NULL; + if (finish_step_over (child)) + { + /* Unsuspend all other LWPs, and set them back running again. */ + unsuspend_all_lwps (child); } - else + + /* If there is at least one more LWP, then the exit signal was + not the end of the debugged application and should be + ignored, unless GDB wants to hear about thread exits. */ + if (report_thread_events + || last_thread_of_process_p (pid_of (thread))) { - /* This was the last lwp in the process. Since events are - serialized to GDB core, and we can't report this one - right now, but GDB core and the other target layers will - want to be notified about the exit code/signal, leave the - status pending for the next time we're able to report - it. */ + /* Since events are serialized to GDB core, and we can't + report this one right now. Leave the status pending for + the next time we're able to report it. */ mark_lwp_dead (child, wstat); return child; } + else + { + delete_lwp (child); + return NULL; + } } gdb_assert (WIFSTOPPED (wstat)); @@ -2295,8 +2551,23 @@ linux_low_filter_event (int lwpid, int wstat) child->must_set_ptrace_flags = 0; } - /* Be careful to not overwrite stop_pc until - check_stopped_by_breakpoint is called. */ + /* Always update syscall_state, even if it will be filtered later. */ + if (WIFSTOPPED (wstat) && WSTOPSIG (wstat) == SYSCALL_SIGTRAP) + { + child->syscall_state + = (child->syscall_state == TARGET_WAITKIND_SYSCALL_ENTRY + ? TARGET_WAITKIND_SYSCALL_RETURN + : TARGET_WAITKIND_SYSCALL_ENTRY); + } + else + { + /* Almost all other ptrace-stops are known to be outside of system + calls, with further exceptions in handle_extended_wait. */ + child->syscall_state = TARGET_WAITKIND_IGNORE; + } + + /* Be careful to not overwrite stop_pc until save_stop_reason is + called. */ if (WIFSTOPPED (wstat) && WSTOPSIG (wstat) == SIGTRAP && linux_is_extended_waitstatus (wstat)) { @@ -2309,27 +2580,12 @@ linux_low_filter_event (int lwpid, int wstat) } } - /* Check first whether this was a SW/HW breakpoint before checking - watchpoints, because at least s390 can't tell the data address of - hardware watchpoint hits, and returns stopped-by-watchpoint as - long as there's a watchpoint set. */ - if (WIFSTOPPED (wstat) && linux_wstatus_maybe_breakpoint (wstat)) + if (linux_wstatus_maybe_breakpoint (wstat)) { - if (check_stopped_by_breakpoint (child)) + if (save_stop_reason (child)) have_stop_pc = 1; } - /* Note that TRAP_HWBKPT can indicate either a hardware breakpoint - or hardware watchpoint. Check which is which if we got - TARGET_STOPPED_BY_HW_BREAKPOINT. Likewise, we may have single - stepped an instruction that triggered a watchpoint. In that - case, on some architectures (such as x86), instead of - TRAP_HWBKPT, si_code indicates TRAP_TRACE, and we need to check - the debug registers separately. */ - if (WIFSTOPPED (wstat) && WSTOPSIG (wstat) == SIGTRAP - && child->stop_reason != TARGET_STOPPED_BY_SW_BREAKPOINT) - check_stopped_by_watchpoint (child); - if (!have_stop_pc) child->stop_pc = get_pc (child); @@ -2376,6 +2632,22 @@ linux_low_filter_event (int lwpid, int wstat) return child; } +/* Return true if THREAD is doing hardware single step. */ + +static int +maybe_hw_step (struct thread_info *thread) +{ + if (can_hardware_single_step ()) + return 1; + else + { + /* GDBserver must insert single-step breakpoint for software + single step. */ + gdb_assert (has_single_step_breakpoints (thread)); + return 0; + } +} + /* Resume LWPs that are currently stopped without any pending status to report, but are resumed from the core's perspective. */ @@ -2388,10 +2660,12 @@ resume_stopped_resumed_lwps (struct inferior_list_entry *entry) if (lp->stopped && !lp->suspended && !lp->status_pending_p - && thread->last_resume_kind != resume_stop && thread->last_status.kind == TARGET_WAITKIND_IGNORE) { - int step = thread->last_resume_kind == resume_step; + int step = 0; + + if (thread->last_resume_kind == resume_step) + step = maybe_hw_step (thread); if (debug_threads) debug_printf ("RSRL: resuming stopped-resumed LWP %s at %s: step=%d\n", @@ -2432,7 +2706,8 @@ linux_wait_for_event_filtered (ptid_t wait_ptid, ptid_t filter_ptid, if (ptid_equal (filter_ptid, minus_one_ptid) || ptid_is_pid (filter_ptid)) { event_thread = (struct thread_info *) - find_inferior (&all_threads, status_pending_p_callback, &filter_ptid); + find_inferior_in_random (&all_threads, status_pending_p_callback, + &filter_ptid); if (event_thread != NULL) event_child = get_thread_lwp (event_thread); if (debug_threads && event_thread) @@ -2444,7 +2719,8 @@ linux_wait_for_event_filtered (ptid_t wait_ptid, ptid_t filter_ptid, if (stopping_threads == NOT_STOPPING_THREADS && requested_child->status_pending_p - && requested_child->collecting_fast_tracepoint) + && (requested_child->collecting_fast_tracepoint + != fast_tpoint_collect_result::not_collecting)) { enqueue_one_deferred_signal (requested_child, &requested_child->status_pending); @@ -2543,7 +2819,8 @@ linux_wait_for_event_filtered (ptid_t wait_ptid, ptid_t filter_ptid, /* ... and find an LWP with a status to report to the core, if any. */ event_thread = (struct thread_info *) - find_inferior (&all_threads, status_pending_p_callback, &filter_ptid); + find_inferior_in_random (&all_threads, status_pending_p_callback, + &filter_ptid); if (event_thread != NULL) { event_child = get_thread_lwp (event_thread); @@ -2597,18 +2874,6 @@ linux_wait_for_event_filtered (ptid_t wait_ptid, ptid_t filter_ptid, current_thread = event_thread; - /* Check for thread exit. */ - if (! WIFSTOPPED (*wstatp)) - { - gdb_assert (last_thread_of_process_p (pid_of (event_thread))); - - if (debug_threads) - debug_printf ("LWP %d is the last lwp of process. " - "Process %ld exiting.\n", - pid_of (event_thread), lwpid_of (event_thread)); - return lwpid_of (event_thread); - } - return lwpid_of (event_thread); } @@ -2633,7 +2898,7 @@ count_events_callback (struct inferior_list_entry *entry, void *data) { struct thread_info *thread = (struct thread_info *) entry; struct lwp_info *lp = get_thread_lwp (thread); - int *count = data; + int *count = (int *) data; gdb_assert (count != NULL); @@ -2668,7 +2933,7 @@ select_event_lwp_callback (struct inferior_list_entry *entry, void *data) { struct thread_info *thread = (struct thread_info *) entry; struct lwp_info *lp = get_thread_lwp (thread); - int *selector = data; + int *selector = (int *) data; gdb_assert (selector != NULL); @@ -2860,7 +3125,7 @@ linux_stabilize_threads (void) } } - find_inferior (&all_threads, unsuspend_one_lwp, NULL); + unsuspend_all_lwps (NULL); stabilizing_threads = 0; @@ -2878,8 +3143,6 @@ linux_stabilize_threads (void) } } -static void async_file_mark (void); - /* Convenience function that is called when the kernel reports an event that is not passed out to GDB. */ @@ -2895,6 +3158,68 @@ ignore_event (struct target_waitstatus *ourstatus) return null_ptid; } +/* Convenience function that is called when the kernel reports an exit + event. This decides whether to report the event to GDB as a + process exit event, a thread exit event, or to suppress the + event. */ + +static ptid_t +filter_exit_event (struct lwp_info *event_child, + struct target_waitstatus *ourstatus) +{ + struct thread_info *thread = get_lwp_thread (event_child); + ptid_t ptid = ptid_of (thread); + + if (!last_thread_of_process_p (pid_of (thread))) + { + if (report_thread_events) + ourstatus->kind = TARGET_WAITKIND_THREAD_EXITED; + else + ourstatus->kind = TARGET_WAITKIND_IGNORE; + + delete_lwp (event_child); + } + return ptid; +} + +/* Returns 1 if GDB is interested in any event_child syscalls. */ + +static int +gdb_catching_syscalls_p (struct lwp_info *event_child) +{ + struct thread_info *thread = get_lwp_thread (event_child); + struct process_info *proc = get_thread_process (thread); + + return !VEC_empty (int, proc->syscalls_to_catch); +} + +/* Returns 1 if GDB is interested in the event_child syscall. + Only to be called when stopped reason is SYSCALL_SIGTRAP. */ + +static int +gdb_catch_this_syscall_p (struct lwp_info *event_child) +{ + int i, iter; + int sysno; + struct thread_info *thread = get_lwp_thread (event_child); + struct process_info *proc = get_thread_process (thread); + + if (VEC_empty (int, proc->syscalls_to_catch)) + return 0; + + if (VEC_index (int, proc->syscalls_to_catch, 0) == ANY_SYSCALL) + return 1; + + get_syscall_trapinfo (event_child, &sysno); + for (i = 0; + VEC_iterate (int, proc->syscalls_to_catch, i, iter); + i++) + if (iter == sysno) + return 1; + + return 0; +} + /* Wait for process, returns status. */ static ptid_t @@ -2911,6 +3236,7 @@ linux_wait_1 (ptid_t ptid, int report_to_gdb; int trace_event; int in_step_range; + int any_resumed; if (debug_threads) { @@ -2928,6 +3254,18 @@ linux_wait_1 (ptid_t ptid, in_step_range = 0; ourstatus->kind = TARGET_WAITKIND_IGNORE; + /* Find a resumed LWP, if any. */ + if (find_inferior (&all_threads, + status_pending_p_callback, + &minus_one_ptid) != NULL) + any_resumed = 1; + else if ((find_inferior (&all_threads, + not_stopped_callback, + &minus_one_ptid) != NULL)) + any_resumed = 1; + else + any_resumed = 0; + if (ptid_equal (step_over_bkpt, null_ptid)) pid = linux_wait_for_event (ptid, &w, options); else @@ -2938,7 +3276,7 @@ linux_wait_1 (ptid_t ptid, pid = linux_wait_for_event (step_over_bkpt, &w, options & ~WNOHANG); } - if (pid == 0) + if (pid == 0 || (pid == -1 && !any_resumed)) { gdb_assert (target_options & TARGET_WNOHANG); @@ -3000,19 +3338,35 @@ linux_wait_1 (ptid_t ptid, } } + if (ourstatus->kind == TARGET_WAITKIND_EXITED) + return filter_exit_event (event_child, ourstatus); + return ptid_of (current_thread); } - /* If step-over executes a breakpoint instruction, it means a - gdb/gdbserver breakpoint had been planted on top of a permanent - breakpoint. The PC has been adjusted by - check_stopped_by_breakpoint to point at the breakpoint address. - Advance the PC manually past the breakpoint, otherwise the - program would keep trapping the permanent breakpoint forever. */ + /* If step-over executes a breakpoint instruction, in the case of a + hardware single step it means a gdb/gdbserver breakpoint had been + planted on top of a permanent breakpoint, in the case of a software + single step it may just mean that gdbserver hit the reinsert breakpoint. + The PC has been adjusted by save_stop_reason to point at + the breakpoint address. + So in the case of the hardware single step advance the PC manually + past the breakpoint and in the case of software single step advance only + if it's not the single_step_breakpoint we are hitting. + This avoids that a program would keep trapping a permanent breakpoint + forever. */ if (!ptid_equal (step_over_bkpt, null_ptid) - && event_child->stop_reason == TARGET_STOPPED_BY_SW_BREAKPOINT) + && event_child->stop_reason == TARGET_STOPPED_BY_SW_BREAKPOINT + && (event_child->stepping + || !single_step_breakpoint_inserted_here (event_child->stop_pc))) { - unsigned int increment_pc = the_low_target.breakpoint_len; + int increment_pc = 0; + int breakpoint_kind = 0; + CORE_ADDR stop_pc = event_child->stop_pc; + + breakpoint_kind = + the_target->breakpoint_kind_from_current_state (&stop_pc); + the_target->sw_breakpoint_from_kind (breakpoint_kind, &increment_pc); if (debug_threads) { @@ -3058,8 +3412,8 @@ linux_wait_1 (ptid_t ptid, /* We have a SIGTRAP, possibly a step-over dance has just finished. If so, tweak the state machine accordingly, - reinsert breakpoints and delete any reinsert (software - single-step) breakpoints. */ + reinsert breakpoints and delete any single-step + breakpoints. */ step_over_finished = finish_step_over (event_child); /* Now invoke the callbacks of any internal breakpoints there. */ @@ -3072,14 +3426,8 @@ linux_wait_1 (ptid_t ptid, if (bp_explains_trap) { - /* If we stepped or ran into an internal breakpoint, we've - already handled it. So next time we resume (from this - PC), we should step over it. */ if (debug_threads) debug_printf ("Hit a gdbserver breakpoint.\n"); - - if (breakpoint_here (event_child->stop_pc)) - event_child->need_step_over = 1; } } else @@ -3118,24 +3466,28 @@ linux_wait_1 (ptid_t ptid, linux_resume_one_lwp (event_child, 0, 0, NULL); + if (debug_threads) + debug_exit (); return ignore_event (ourstatus); } } - if (event_child->collecting_fast_tracepoint) + if (event_child->collecting_fast_tracepoint + != fast_tpoint_collect_result::not_collecting) { if (debug_threads) debug_printf ("LWP %ld was trying to move out of the jump pad (%d). " "Check if we're already there.\n", lwpid_of (current_thread), - event_child->collecting_fast_tracepoint); + (int) event_child->collecting_fast_tracepoint); trace_event = 1; event_child->collecting_fast_tracepoint = linux_fast_tracepoint_collecting (event_child, NULL); - if (event_child->collecting_fast_tracepoint != 1) + if (event_child->collecting_fast_tracepoint + != fast_tpoint_collect_result::before_insn) { /* No longer need this breakpoint. */ if (event_child->exit_jump_pad_bkpt != NULL) @@ -3162,7 +3514,8 @@ linux_wait_1 (ptid_t ptid, } } - if (event_child->collecting_fast_tracepoint == 0) + if (event_child->collecting_fast_tracepoint + == fast_tpoint_collect_result::not_collecting) { if (debug_threads) debug_printf ("fast tracepoint finished " @@ -3200,6 +3553,25 @@ linux_wait_1 (ptid_t ptid, /* Check whether GDB would be interested in this event. */ + /* Check if GDB is interested in this syscall. */ + if (WIFSTOPPED (w) + && WSTOPSIG (w) == SYSCALL_SIGTRAP + && !gdb_catch_this_syscall_p (event_child)) + { + if (debug_threads) + { + debug_printf ("Ignored syscall for LWP %ld.\n", + lwpid_of (current_thread)); + } + + linux_resume_one_lwp (event_child, event_child->stepping, + 0, NULL); + + if (debug_threads) + debug_exit (); + return ignore_event (ourstatus); + } + /* If GDB is not interested in this signal, don't stop other threads, and don't report it to GDB. Just resume the inferior right away. We do this for threading-related signals as well as @@ -3208,8 +3580,6 @@ linux_wait_1 (ptid_t ptid, stepping - they may require special handling to skip the signal handler. Also never ignore signals that could be caused by a breakpoint. */ - /* FIXME drow/2002-06-09: Get signal numbers from the inferior's - thread library? */ if (WIFSTOPPED (w) && current_thread->last_resume_kind != resume_step && ( @@ -3254,6 +3624,10 @@ linux_wait_1 (ptid_t ptid, linux_resume_one_lwp (event_child, event_child->stepping, WSTOPSIG (w), info_p); } + + if (debug_threads) + debug_exit (); + return ignore_event (ourstatus); } @@ -3322,18 +3696,36 @@ linux_wait_1 (ptid_t ptid, (*the_low_target.set_pc) (regcache, event_child->stop_pc); } - /* We may have finished stepping over a breakpoint. If so, - we've stopped and suspended all LWPs momentarily except the - stepping one. This is where we resume them all again. We're - going to keep waiting, so use proceed, which handles stepping - over the next breakpoint. */ + if (step_over_finished) + { + /* If we have finished stepping over a breakpoint, we've + stopped and suspended all LWPs momentarily except the + stepping one. This is where we resume them all again. + We're going to keep waiting, so use proceed, which + handles stepping over the next breakpoint. */ + unsuspend_all_lwps (event_child); + } + else + { + /* Remove the single-step breakpoints if any. Note that + there isn't single-step breakpoint if we finished stepping + over. */ + if (can_software_single_step () + && has_single_step_breakpoints (current_thread)) + { + stop_all_lwps (0, event_child); + delete_single_step_breakpoints (current_thread); + unstop_all_lwps (0, event_child); + } + } + if (debug_threads) debug_printf ("proceeding all threads.\n"); + proceed_all_lwps (); - if (step_over_finished) - unsuspend_all_lwps (event_child); + if (debug_threads) + debug_exit (); - proceed_all_lwps (); return ignore_event (ourstatus); } @@ -3341,12 +3733,11 @@ linux_wait_1 (ptid_t ptid, { if (event_child->waitstatus.kind != TARGET_WAITKIND_IGNORE) { - char *str; + std::string str + = target_waitstatus_to_string (&event_child->waitstatus); - str = target_waitstatus_to_string (&event_child->waitstatus); debug_printf ("LWP %ld: extended event with waitstatus %s\n", - lwpid_of (get_lwp_thread (event_child)), str); - xfree (str); + lwpid_of (get_lwp_thread (event_child)), str.c_str ()); } if (current_thread->last_resume_kind == resume_step) { @@ -3365,29 +3756,71 @@ linux_wait_1 (ptid_t ptid, /* Alright, we're going to report a stop. */ - if (!stabilizing_threads) + /* Remove single-step breakpoints. */ + if (can_software_single_step ()) { - /* In all-stop, stop all threads. */ - if (!non_stop) - stop_all_lwps (0, NULL); + /* Remove single-step breakpoints or not. It it is true, stop all + lwps, so that other threads won't hit the breakpoint in the + staled memory. */ + int remove_single_step_breakpoints_p = 0; - /* If we're not waiting for a specific LWP, choose an event LWP - from among those that have had events. Giving equal priority - to all LWPs that have had events helps prevent - starvation. */ - if (ptid_equal (ptid, minus_one_ptid)) + if (non_stop) { - event_child->status_pending_p = 1; - event_child->status_pending = w; + remove_single_step_breakpoints_p + = has_single_step_breakpoints (current_thread); + } + else + { + /* In all-stop, a stop reply cancels all previous resume + requests. Delete all single-step breakpoints. */ + struct inferior_list_entry *inf, *tmp; - select_event_lwp (&event_child); + ALL_INFERIORS (&all_threads, inf, tmp) + { + struct thread_info *thread = (struct thread_info *) inf; - /* current_thread and event_child must stay in sync. */ - current_thread = get_lwp_thread (event_child); + if (has_single_step_breakpoints (thread)) + { + remove_single_step_breakpoints_p = 1; + break; + } + } + } - event_child->status_pending_p = 0; - w = event_child->status_pending; + if (remove_single_step_breakpoints_p) + { + /* If we remove single-step breakpoints from memory, stop all lwps, + so that other threads won't hit the breakpoint in the staled + memory. */ + stop_all_lwps (0, event_child); + + if (non_stop) + { + gdb_assert (has_single_step_breakpoints (current_thread)); + delete_single_step_breakpoints (current_thread); + } + else + { + struct inferior_list_entry *inf, *tmp; + + ALL_INFERIORS (&all_threads, inf, tmp) + { + struct thread_info *thread = (struct thread_info *) inf; + + if (has_single_step_breakpoints (thread)) + delete_single_step_breakpoints (thread); + } + } + + unstop_all_lwps (0, event_child); } + } + + if (!stabilizing_threads) + { + /* In all-stop, stop all threads. */ + if (!non_stop) + stop_all_lwps (0, NULL); if (step_over_finished) { @@ -3413,6 +3846,25 @@ linux_wait_1 (ptid_t ptid, } } + /* If we're not waiting for a specific LWP, choose an event LWP + from among those that have had events. Giving equal priority + to all LWPs that have had events helps prevent + starvation. */ + if (ptid_equal (ptid, minus_one_ptid)) + { + event_child->status_pending_p = 1; + event_child->status_pending = w; + + select_event_lwp (&event_child); + + /* current_thread and event_child must stay in sync. */ + current_thread = get_lwp_thread (event_child); + + event_child->status_pending_p = 0; + w = event_child->status_pending; + } + + /* Stabilize threads (move out of jump pads). */ if (!non_stop) stabilize_threads (); @@ -3431,6 +3883,15 @@ linux_wait_1 (ptid_t ptid, { /* If the reported event is an exit, fork, vfork or exec, let GDB know. */ + + /* Break the unreported fork relationship chain. */ + if (event_child->waitstatus.kind == TARGET_WAITKIND_FORKED + || event_child->waitstatus.kind == TARGET_WAITKIND_VFORKED) + { + event_child->fork_relative->fork_relative = NULL; + event_child->fork_relative = NULL; + } + *ourstatus = event_child->waitstatus; /* Clear the event lwp's waitstatus since we handled it already. */ event_child->waitstatus.kind = TARGET_WAITKIND_IGNORE; @@ -3454,8 +3915,14 @@ linux_wait_1 (ptid_t ptid, } } - if (current_thread->last_resume_kind == resume_stop - && WSTOPSIG (w) == SIGSTOP) + if (WSTOPSIG (w) == SYSCALL_SIGTRAP) + { + get_syscall_trapinfo (event_child, + &ourstatus->value.syscall_number); + ourstatus->kind = event_child->syscall_state; + } + else if (current_thread->last_resume_kind == resume_stop + && WSTOPSIG (w) == SIGSTOP) { /* A thread that has been requested to stop by GDB with vCont;t, and it stopped cleanly, so report as SIG0. The use of @@ -3484,6 +3951,9 @@ linux_wait_1 (ptid_t ptid, debug_exit (); } + if (ourstatus->kind == TARGET_WAITKIND_EXITED) + return filter_exit_event (event_child, ourstatus); + return ptid_of (current_thread); } @@ -3548,27 +4018,17 @@ linux_wait (ptid_t ptid, static int kill_lwp (unsigned long lwpid, int signo) { - /* Use tkill, if possible, in case we are using nptl threads. If tkill - fails, then we are not using nptl threads and we should be using kill. */ - -#ifdef __NR_tkill - { - static int tkill_failed; - - if (!tkill_failed) - { - int ret; - - errno = 0; - ret = syscall (__NR_tkill, lwpid, signo); - if (errno != ENOSYS) - return ret; - tkill_failed = 1; - } - } -#endif + int ret; - return kill (lwpid, signo); + errno = 0; + ret = syscall (__NR_tkill, lwpid, signo); + if (errno == ENOSYS) + { + /* If tkill fails, then we are not using nptl threads, a + configuration we no longer support. */ + perror_with_name (("tkill")); + } + return ret; } void @@ -3739,7 +4199,8 @@ stuck_in_jump_pad_callback (struct inferior_list_entry *entry, void *data) && (gdb_breakpoint_here (lwp->stop_pc) || lwp->stop_reason == TARGET_STOPPED_BY_WATCHPOINT || thread->last_resume_kind == resume_step) - && linux_fast_tracepoint_collecting (lwp, NULL)); + && (linux_fast_tracepoint_collecting (lwp, NULL) + != fast_tpoint_collect_result::not_collecting)); } static void @@ -3862,6 +4323,64 @@ enqueue_pending_signal (struct lwp_info *lwp, int signal, siginfo_t *info) lwp->pending_signals = p_sig; } +/* Install breakpoints for software single stepping. */ + +static void +install_software_single_step_breakpoints (struct lwp_info *lwp) +{ + struct thread_info *thread = get_lwp_thread (lwp); + struct regcache *regcache = get_thread_regcache (thread, 1); + struct cleanup *old_chain = make_cleanup_restore_current_thread (); + + current_thread = thread; + std::vector next_pcs = the_low_target.get_next_pcs (regcache); + + for (CORE_ADDR pc : next_pcs) + set_single_step_breakpoint (pc, current_ptid); + + do_cleanups (old_chain); +} + +/* Single step via hardware or software single step. + Return 1 if hardware single stepping, 0 if software single stepping + or can't single step. */ + +static int +single_step (struct lwp_info* lwp) +{ + int step = 0; + + if (can_hardware_single_step ()) + { + step = 1; + } + else if (can_software_single_step ()) + { + install_software_single_step_breakpoints (lwp); + step = 0; + } + else + { + if (debug_threads) + debug_printf ("stepping is not implemented on this target"); + } + + return step; +} + +/* The signal can be delivered to the inferior if we are not trying to + finish a fast tracepoint collect. Since signal can be delivered in + the step-over, the program may go to signal handler and trap again + after return from the signal handler. We can live with the spurious + double traps. */ + +static int +lwp_signal_can_be_delivered (struct lwp_info *lwp) +{ + return (lwp->collecting_fast_tracepoint + == fast_tpoint_collect_result::not_collecting); +} + /* Resume execution of LWP. If STEP is nonzero, single-step it. If SIGNAL is nonzero, give it that signal. */ @@ -3871,7 +4390,7 @@ linux_resume_one_lwp_throw (struct lwp_info *lwp, { struct thread_info *thread = get_lwp_thread (lwp); struct thread_info *saved_thread; - int fast_tp_collecting; + int ptrace_request; struct process_info *proc = get_thread_process (thread); /* Note that target description may not be initialised @@ -3884,9 +4403,14 @@ linux_resume_one_lwp_throw (struct lwp_info *lwp, if (lwp->stopped == 0) return; - fast_tp_collecting = lwp->collecting_fast_tracepoint; + gdb_assert (lwp->waitstatus.kind == TARGET_WAITKIND_IGNORE); - gdb_assert (!stabilizing_threads || fast_tp_collecting); + fast_tpoint_collect_result fast_tp_collecting + = lwp->collecting_fast_tracepoint; + + gdb_assert (!stabilizing_threads + || (fast_tp_collecting + != fast_tpoint_collect_result::not_collecting)); /* Cancel actions that rely on GDB not changing the PC (e.g., the user used the "jump" command, or "set $pc = foo"). */ @@ -3898,31 +4422,25 @@ linux_resume_one_lwp_throw (struct lwp_info *lwp, } /* If we have pending signals or status, and a new signal, enqueue the - signal. Also enqueue the signal if we are waiting to reinsert a - breakpoint; it will be picked up again below. */ + signal. Also enqueue the signal if it can't be delivered to the + inferior right now. */ if (signal != 0 && (lwp->status_pending_p || lwp->pending_signals != NULL - || lwp->bp_reinsert != 0 - || fast_tp_collecting)) + || !lwp_signal_can_be_delivered (lwp))) { - struct pending_signals *p_sig = XNEW (struct pending_signals); + enqueue_pending_signal (lwp, signal, info); - p_sig->prev = lwp->pending_signals; - p_sig->signal = signal; - if (info == NULL) - memset (&p_sig->info, 0, sizeof (siginfo_t)); - else - memcpy (&p_sig->info, info, sizeof (siginfo_t)); - lwp->pending_signals = p_sig; + /* Postpone any pending signal. It was enqueued above. */ + signal = 0; } if (lwp->status_pending_p) { if (debug_threads) - debug_printf ("Not resuming lwp %ld (%s, signal %d, stop %s);" + debug_printf ("Not resuming lwp %ld (%s, stop %s);" " has pending status\n", - lwpid_of (thread), step ? "step" : "continue", signal, + lwpid_of (thread), step ? "step" : "continue", lwp->stop_expected ? "expected" : "not expected"); return; } @@ -3930,11 +4448,6 @@ linux_resume_one_lwp_throw (struct lwp_info *lwp, saved_thread = current_thread; current_thread = thread; - if (debug_threads) - debug_printf ("Resuming lwp %ld (%s, signal %d, stop %s)\n", - lwpid_of (thread), step ? "step" : "continue", signal, - lwp->stop_expected ? "expected" : "not expected"); - /* This bit needs some thinking about. If we get a signal that we must report while a single-step reinsert is still pending, we often end up resuming the thread. It might be better to @@ -3953,33 +4466,27 @@ linux_resume_one_lwp_throw (struct lwp_info *lwp, if (can_hardware_single_step ()) { - if (fast_tp_collecting == 0) + if (fast_tp_collecting == fast_tpoint_collect_result::not_collecting) { if (step == 0) - fprintf (stderr, "BAD - reinserting but not stepping.\n"); + warning ("BAD - reinserting but not stepping."); if (lwp->suspended) - fprintf (stderr, "BAD - reinserting and suspended(%d).\n", - lwp->suspended); + warning ("BAD - reinserting and suspended(%d).", + lwp->suspended); } - - step = 1; } - /* Postpone any pending signal. It was enqueued above. */ - signal = 0; + step = maybe_hw_step (thread); } - if (fast_tp_collecting == 1) + if (fast_tp_collecting == fast_tpoint_collect_result::before_insn) { if (debug_threads) debug_printf ("lwp %ld wants to get out of fast tracepoint jump pad" " (exit-jump-pad-bkpt)\n", lwpid_of (thread)); - - /* Postpone any pending signal. It was enqueued above. */ - signal = 0; } - else if (fast_tp_collecting == 2) + else if (fast_tp_collecting == fast_tpoint_collect_result::at_insn) { if (debug_threads) debug_printf ("lwp %ld wants to get out of fast tracepoint jump pad" @@ -3994,9 +4501,6 @@ linux_resume_one_lwp_throw (struct lwp_info *lwp, "moving out of jump pad single-stepping" " not implemented on this target"); } - - /* Postpone any pending signal. It was enqueued above. */ - signal = 0; } /* If we have while-stepping actions in this thread set it stepping. @@ -4007,13 +4511,13 @@ linux_resume_one_lwp_throw (struct lwp_info *lwp, address, continue, and carry on catching this while-stepping action only when that breakpoint is hit. A future enhancement. */ - if (thread->while_stepping != NULL - && can_hardware_single_step ()) + if (thread->while_stepping != NULL) { if (debug_threads) debug_printf ("lwp %ld has a while-stepping action -> forcing step.\n", lwpid_of (thread)); - step = 1; + + step = single_step (lwp); } if (proc->tdesc != NULL && the_low_target.get_pc != NULL) @@ -4029,12 +4533,9 @@ linux_resume_one_lwp_throw (struct lwp_info *lwp, } } - /* If we have pending signals, consume one unless we are trying to - reinsert a breakpoint or we're trying to finish a fast tracepoint - collect. */ - if (lwp->pending_signals != NULL - && lwp->bp_reinsert == 0 - && fast_tp_collecting == 0) + /* If we have pending signals, consume one if it can be delivered to + the inferior. */ + if (lwp->pending_signals != NULL && lwp_signal_can_be_delivered (lwp)) { struct pending_signals **p_sig; @@ -4051,13 +4552,25 @@ linux_resume_one_lwp_throw (struct lwp_info *lwp, *p_sig = NULL; } + if (debug_threads) + debug_printf ("Resuming lwp %ld (%s, signal %d, stop %s)\n", + lwpid_of (thread), step ? "step" : "continue", signal, + lwp->stop_expected ? "expected" : "not expected"); + if (the_low_target.prepare_to_resume != NULL) the_low_target.prepare_to_resume (lwp); regcache_invalidate_thread (thread); errno = 0; lwp->stepping = step; - ptrace (step ? PTRACE_SINGLESTEP : PTRACE_CONT, lwpid_of (thread), + if (step) + ptrace_request = PTRACE_SINGLESTEP; + else if (gdb_catching_syscalls_p (lwp)) + ptrace_request = PTRACE_SYSCALL; + else + ptrace_request = PTRACE_CONT; + ptrace (ptrace_request, + lwpid_of (thread), (PTRACE_TYPE_ARG3) 0, /* Coerce to a uintptr_t first to avoid potential gcc warning of coercing an 8 byte integer to a 4 byte pointer. */ @@ -4152,7 +4665,7 @@ linux_set_resume_request (struct inferior_list_entry *entry, void *arg) int ndx; struct thread_resume_array *r; - r = arg; + r = (struct thread_resume_array *) arg; for (ndx = 0; ndx < r->n; ndx++) { @@ -4179,6 +4692,50 @@ linux_set_resume_request (struct inferior_list_entry *entry, void *arg) continue; } + /* Ignore (wildcard) resume requests for already-resumed + threads. */ + if (r->resume[ndx].kind != resume_stop + && thread->last_resume_kind != resume_stop) + { + if (debug_threads) + debug_printf ("already %s LWP %ld at GDB's request\n", + (thread->last_resume_kind + == resume_step) + ? "stepping" + : "continuing", + lwpid_of (thread)); + continue; + } + + /* Don't let wildcard resumes resume fork children that GDB + does not yet know are new fork children. */ + if (lwp->fork_relative != NULL) + { + struct lwp_info *rel = lwp->fork_relative; + + if (rel->status_pending_p + && (rel->waitstatus.kind == TARGET_WAITKIND_FORKED + || rel->waitstatus.kind == TARGET_WAITKIND_VFORKED)) + { + if (debug_threads) + debug_printf ("not resuming LWP %ld: has queued stop reply\n", + lwpid_of (thread)); + continue; + } + } + + /* If the thread has a pending event that has already been + reported to GDBserver core, but GDB has not pulled the + event out of the vStopped queue yet, likewise, ignore the + (wildcard) resume request. */ + if (in_queued_stop_replies (entry->id)) + { + if (debug_threads) + debug_printf ("not resuming LWP %ld: has queued stop reply\n", + lwpid_of (thread)); + continue; + } + lwp->resume = &r->resume[ndx]; thread->last_resume_kind = lwp->resume->kind; @@ -4280,12 +4837,6 @@ need_step_over_p (struct inferior_list_entry *entry, void *dummy) return 0; } - if (!lwp->need_step_over) - { - if (debug_threads) - debug_printf ("Need step over [LWP %ld]? No\n", lwpid_of (thread)); - } - if (lwp->status_pending_p) { if (debug_threads) @@ -4311,8 +4862,20 @@ need_step_over_p (struct inferior_list_entry *entry, void *dummy) "Old stop_pc was 0x%s, PC is now 0x%s\n", lwpid_of (thread), paddress (lwp->stop_pc), paddress (pc)); + return 0; + } + + /* On software single step target, resume the inferior with signal + rather than stepping over. */ + if (can_software_single_step () + && lwp->pending_signals != NULL + && lwp_signal_can_be_delivered (lwp)) + { + if (debug_threads) + debug_printf ("Need step over [LWP %ld]? Ignoring, has pending" + " signals.\n", + lwpid_of (thread)); - lwp->need_step_over = 0; return 0; } @@ -4348,8 +4911,6 @@ need_step_over_p (struct inferior_list_entry *entry, void *dummy) that find_inferior stops looking. */ current_thread = saved_thread; - /* If the step over is cancelled, this is set again. */ - lwp->need_step_over = 0; return 1; } } @@ -4369,18 +4930,10 @@ need_step_over_p (struct inferior_list_entry *entry, void *dummy) of the way. If we let other threads run while we do that, they may pass by the breakpoint location and miss hitting it. To avoid that, a step-over momentarily stops all threads while LWP is - single-stepped while the breakpoint is temporarily uninserted from - the inferior. When the single-step finishes, we reinsert the - breakpoint, and let all threads that are supposed to be running, - run again. - - On targets that don't support hardware single-step, we don't - currently support full software single-stepping. Instead, we only - support stepping over the thread event breakpoint, by asking the - low target where to place a reinsert breakpoint. Since this - routine assumes the breakpoint being stepped over is a thread event - breakpoint, it usually assumes the return address of the current - function is a good enough place to set the reinsert breakpoint. */ + single-stepped by either hardware or software while the breakpoint + is temporarily uninserted from the inferior. When the single-step + finishes, we reinsert the breakpoint, and let all threads that are + supposed to be running, run again. */ static int start_step_over (struct lwp_info *lwp) @@ -4419,16 +4972,7 @@ start_step_over (struct lwp_info *lwp) uninsert_breakpoints_at (pc); uninsert_fast_tracepoint_jumps_at (pc); - if (can_hardware_single_step ()) - { - step = 1; - } - else - { - CORE_ADDR raddr = (*the_low_target.breakpoint_reinsert_addr) (); - set_reinsert_breakpoint (raddr); - step = 0; - } + step = single_step (lwp); current_thread = saved_thread; @@ -4440,7 +4984,7 @@ start_step_over (struct lwp_info *lwp) } /* Finish a step-over. Reinsert the breakpoint we had uninserted in - start_step_over, if still there, and delete any reinsert + start_step_over, if still there, and delete any single-step breakpoints we've set, on non hardware single-step targets. */ static int @@ -4448,9 +4992,13 @@ finish_step_over (struct lwp_info *lwp) { if (lwp->bp_reinsert != 0) { + struct thread_info *saved_thread = current_thread; + if (debug_threads) debug_printf ("Finished step over.\n"); + current_thread = get_lwp_thread (lwp); + /* Reinsert any breakpoint at LWP->BP_REINSERT. Note that there may be no breakpoint to reinsert there by now. */ reinsert_breakpoints_at (lwp->bp_reinsert); @@ -4458,15 +5006,19 @@ finish_step_over (struct lwp_info *lwp) lwp->bp_reinsert = 0; - /* Delete any software-single-step reinsert breakpoints. No - longer needed. We don't have to worry about other threads - hitting this trap, and later not being able to explain it, - because we were stepping over a breakpoint, and we hold all - threads but LWP stopped while doing that. */ + /* Delete any single-step breakpoints. No longer needed. We + don't have to worry about other threads hitting this trap, + and later not being able to explain it, because we were + stepping over a breakpoint, and we hold all threads but + LWP stopped while doing that. */ if (!can_hardware_single_step ()) - delete_reinsert_breakpoints (); + { + gdb_assert (has_single_step_breakpoints (current_thread)); + delete_single_step_breakpoints (current_thread); + } step_over_bkpt = null_ptid; + current_thread = saved_thread; return 1; } else @@ -4524,7 +5076,6 @@ linux_resume_one_thread (struct inferior_list_entry *entry, void *arg) { struct thread_info *thread = (struct thread_info *) entry; struct lwp_info *lwp = get_thread_lwp (thread); - int step; int leave_all_stopped = * (int *) arg; int leave_pending; @@ -4591,38 +5142,35 @@ linux_resume_one_thread (struct inferior_list_entry *entry, void *arg) || lwp->status_pending_p || leave_all_stopped); + /* If we have a new signal, enqueue the signal. */ + if (lwp->resume->sig != 0) + { + siginfo_t info, *info_p; + + /* If this is the same signal we were previously stopped by, + make sure to queue its siginfo. */ + if (WIFSTOPPED (lwp->last_status) + && WSTOPSIG (lwp->last_status) == lwp->resume->sig + && ptrace (PTRACE_GETSIGINFO, lwpid_of (thread), + (PTRACE_TYPE_ARG3) 0, &info) == 0) + info_p = &info; + else + info_p = NULL; + + enqueue_pending_signal (lwp, lwp->resume->sig, info_p); + } + if (!leave_pending) { if (debug_threads) debug_printf ("resuming LWP %ld\n", lwpid_of (thread)); - step = (lwp->resume->kind == resume_step); - linux_resume_one_lwp (lwp, step, lwp->resume->sig, NULL); + proceed_one_lwp (entry, NULL); } else { if (debug_threads) debug_printf ("leaving LWP %ld stopped\n", lwpid_of (thread)); - - /* If we have a new signal, enqueue the signal. */ - if (lwp->resume->sig != 0) - { - struct pending_signals *p_sig = XCNEW (struct pending_signals); - - p_sig->prev = lwp->pending_signals; - p_sig->signal = lwp->resume->sig; - - /* If this is the same signal we were previously stopped by, - make sure to queue its siginfo. We can ignore the return - value of ptrace; if it fails, we'll skip - PTRACE_SETSIGINFO. */ - if (WIFSTOPPED (lwp->last_status) - && WSTOPSIG (lwp->last_status) == lwp->resume->sig) - ptrace (PTRACE_GETSIGINFO, lwpid_of (thread), (PTRACE_TYPE_ARG3) 0, - &p_sig->info); - - lwp->pending_signals = p_sig; - } } thread->last_status.kind = TARGET_WAITKIND_IGNORE; @@ -4692,6 +5240,11 @@ linux_resume (struct thread_resume *resume_info, size_t n) debug_printf ("linux_resume done\n"); debug_exit (); } + + /* We may have events that were pending that can/should be sent to + the client now. Trigger a linux_wait call. */ + if (target_is_async_p ()) + async_file_mark (); } /* This function is called once per thread. We check the thread's @@ -4751,7 +5304,8 @@ proceed_one_lwp (struct inferior_list_entry *entry, void *except) if (thread->last_resume_kind == resume_stop && lwp->pending_signals_to_report == NULL - && lwp->collecting_fast_tracepoint == 0) + && (lwp->collecting_fast_tracepoint + == fast_tpoint_collect_result::not_collecting)) { /* We haven't reported this LWP as stopped yet (otherwise, the last_status.kind check above would catch it, and we wouldn't @@ -4776,14 +5330,23 @@ proceed_one_lwp (struct inferior_list_entry *entry, void *except) if (debug_threads) debug_printf (" stepping LWP %ld, client wants it stepping\n", lwpid_of (thread)); - step = 1; + + /* If resume_step is requested by GDB, install single-step + breakpoints when the thread is about to be actually resumed if + the single-step breakpoints weren't removed. */ + if (can_software_single_step () + && !has_single_step_breakpoints (thread)) + install_software_single_step_breakpoints (lwp); + + step = maybe_hw_step (thread); } else if (lwp->bp_reinsert != 0) { if (debug_threads) debug_printf (" stepping LWP %ld, reinsert set\n", lwpid_of (thread)); - step = 1; + + step = maybe_hw_step (thread); } else step = 0; @@ -4896,7 +5459,7 @@ disable_regset (struct regsets_info *info, struct regset_info *regset) dr_offset = regset - info->regsets; if (info->disabled_regsets == NULL) - info->disabled_regsets = xcalloc (1, info->num_regsets); + info->disabled_regsets = (char *) xcalloc (1, info->num_regsets); info->disabled_regsets[dr_offset] = 1; } @@ -4950,6 +5513,12 @@ regsets_fetch_inferior_registers (struct regsets_info *regsets_info, not "active". This can happen in normal operation, so suppress the warning in this case. */ } + else if (errno == ESRCH) + { + /* At this point, ESRCH should mean the process is + already gone, in which case we simply ignore attempts + to read its registers. */ + } else { char s[256]; @@ -5084,7 +5653,7 @@ linux_register_in_regsets (const struct regs_info *regs_info, int regno) #ifdef HAVE_LINUX_USRREGS -int +static int register_addr (const struct usrregs_info *usrregs, int regnum) { int addr; @@ -5119,7 +5688,7 @@ fetch_register (const struct usrregs_info *usrregs, size = ((register_size (regcache->tdesc, regno) + sizeof (PTRACE_XFER_TYPE) - 1) & -sizeof (PTRACE_XFER_TYPE)); - buf = alloca (size); + buf = (char *) alloca (size); pid = lwpid_of (current_thread); for (i = 0; i < size; i += sizeof (PTRACE_XFER_TYPE)) @@ -5163,7 +5732,7 @@ store_register (const struct usrregs_info *usrregs, size = ((register_size (regcache->tdesc, regno) + sizeof (PTRACE_XFER_TYPE) - 1) & -sizeof (PTRACE_XFER_TYPE)); - buf = alloca (size); + buf = (char *) alloca (size); memset (buf, 0, size); if (the_low_target.collect_ptrace_register) @@ -5246,7 +5815,7 @@ usr_store_inferior_registers (const struct regs_info *regs_info, #endif -void +static void linux_fetch_registers (struct regcache *regcache, int regno) { int use_regsets; @@ -5279,7 +5848,7 @@ linux_fetch_registers (struct regcache *regcache, int regno) } } -void +static void linux_store_registers (struct regcache *regcache, int regno) { int use_regsets; @@ -5312,11 +5881,11 @@ static int linux_read_memory (CORE_ADDR memaddr, unsigned char *myaddr, int len) { int pid = lwpid_of (current_thread); - register PTRACE_XFER_TYPE *buffer; - register CORE_ADDR addr; - register int count; + PTRACE_XFER_TYPE *buffer; + CORE_ADDR addr; + int count; char filename[64]; - register int i; + int i; int ret; int fd; @@ -5400,16 +5969,16 @@ linux_read_memory (CORE_ADDR memaddr, unsigned char *myaddr, int len) static int linux_write_memory (CORE_ADDR memaddr, const unsigned char *myaddr, int len) { - register int i; + int i; /* Round starting address down to longword boundary. */ - register CORE_ADDR addr = memaddr & -(CORE_ADDR) sizeof (PTRACE_XFER_TYPE); + CORE_ADDR addr = memaddr & -(CORE_ADDR) sizeof (PTRACE_XFER_TYPE); /* Round ending address up; get number of longwords that makes. */ - register int count + int count = (((memaddr + len) - addr) + sizeof (PTRACE_XFER_TYPE) - 1) / sizeof (PTRACE_XFER_TYPE); /* Allocate buffer of that many longwords. */ - register PTRACE_XFER_TYPE *buffer = XALLOCAVEC (PTRACE_XFER_TYPE, count); + PTRACE_XFER_TYPE *buffer = XALLOCAVEC (PTRACE_XFER_TYPE, count); int pid = lwpid_of (current_thread); @@ -5493,18 +6062,13 @@ linux_look_up_symbols (void) if (proc->priv->thread_db != NULL) return; - /* If the kernel supports tracing clones, then we don't need to - use the magic thread event breakpoint to learn about - threads. */ - thread_db_init (!linux_supports_traceclone ()); + thread_db_init (); #endif } static void linux_request_interrupt (void) { - extern unsigned long signal_pid; - /* Send a SIGINT to the process group. This acts just like the user typed a ^C on the controlling terminal. */ kill (-signal_pid, SIGINT); @@ -5614,19 +6178,20 @@ linux_supports_stopped_by_hw_breakpoint (void) return USE_SIGTRAP_SIGINFO; } -/* Implement the supports_conditional_breakpoints target_ops - method. */ +/* Implement the supports_hardware_single_step target_ops method. */ static int -linux_supports_conditional_breakpoints (void) +linux_supports_hardware_single_step (void) { - /* GDBserver needs to step over the breakpoint if the condition is - false. GDBserver software single step is too simple, so disable - conditional breakpoints if the target doesn't have hardware single - step. */ return can_hardware_single_step (); } +static int +linux_supports_software_single_step (void) +{ + return can_software_single_step (); +} + static int linux_stopped_by_watchpoint (void) { @@ -5702,7 +6267,7 @@ linux_qxfer_osdata (const char *annex, layout of the inferiors' architecture. */ static void -siginfo_fixup (siginfo_t *siginfo, void *inf_siginfo, int direction) +siginfo_fixup (siginfo_t *siginfo, gdb_byte *inf_siginfo, int direction) { int done = 0; @@ -5726,7 +6291,7 @@ linux_xfer_siginfo (const char *annex, unsigned char *readbuf, { int pid; siginfo_t siginfo; - char inf_siginfo[sizeof (siginfo_t)]; + gdb_byte inf_siginfo[sizeof (siginfo_t)]; if (current_thread == NULL) return -1; @@ -5960,6 +6525,8 @@ linux_supports_agent (void) static int linux_supports_range_stepping (void) { + if (can_software_single_step ()) + return 1; if (*the_low_target.supports_range_stepping == NULL) return 0; @@ -6138,10 +6705,26 @@ linux_read_loadmap (const char *annex, CORE_ADDR offset, #endif /* defined PT_GETDSBT || defined PTRACE_GETFDPIC */ static void -linux_process_qsupported (const char *query) +linux_process_qsupported (char **features, int count) { if (the_low_target.process_qsupported != NULL) - the_low_target.process_qsupported (query); + the_low_target.process_qsupported (features, count); +} + +static int +linux_supports_catch_syscall (void) +{ + return (the_low_target.get_syscall_trapinfo != NULL + && linux_supports_tracesysgood ()); +} + +static int +linux_get_ipa_tdesc_idx (void) +{ + if (the_low_target.get_ipa_tdesc_idx == NULL) + return 0; + + return (*the_low_target.get_ipa_tdesc_idx) (); } static int @@ -6329,7 +6912,7 @@ get_dynamic (const int pid, const int is_elf64) return 0; gdb_assert (num_phdr < 100); /* Basic sanity check. */ - phdr_buf = alloca (num_phdr * phdr_size); + phdr_buf = (unsigned char *) alloca (num_phdr * phdr_size); if (linux_read_memory (phdr_memaddr, phdr_buf, num_phdr * phdr_size)) return 0; @@ -6658,7 +7241,7 @@ linux_qxfer_libraries_svr4 (const char *annex, unsigned char *readbuf, } } - document = xmalloc (allocated); + document = (char *) xmalloc (allocated); strcpy (document, "