Index: dist/gdb/nbsd-nat.c =================================================================== RCS file: /cvsroot/src/external/gpl3/gdb/dist/gdb/nbsd-nat.c,v retrieving revision 1.6 diff -u -r1.6 nbsd-nat.c --- dist/gdb/nbsd-nat.c 23 Jun 2018 03:15:55 -0000 1.6 +++ dist/gdb/nbsd-nat.c 2 May 2019 21:23:29 -0000 @@ -45,7 +45,6 @@ static char buf[PATH_MAX]; char name[PATH_MAX]; -#ifdef KERN_PROC_PATHNAME size_t buflen; int mib[4]; @@ -56,7 +55,6 @@ buflen = sizeof buf; if (sysctl (mib, 4, buf, &buflen, NULL, 0) == 0) return buf; -#endif xsnprintf (name, PATH_MAX, "/proc/%d/exe", pid); len = readlink (name, buf, PATH_MAX - 1); @@ -131,79 +129,6 @@ return 0; } -#ifdef KERN_PROC_AUXV -static enum target_xfer_status (*super_xfer_partial) (struct target_ops *ops, - enum target_object object, - const char *annex, - gdb_byte *readbuf, - const gdb_byte *writebuf, - ULONGEST offset, - ULONGEST len, - ULONGEST *xfered_len); - -/* Implement the "to_xfer_partial target_ops" method. */ - -static enum target_xfer_status -nbsd_xfer_partial (struct target_ops *ops, enum target_object object, - const char *annex, gdb_byte *readbuf, - const gdb_byte *writebuf, - ULONGEST offset, ULONGEST len, ULONGEST *xfered_len) -{ - pid_t pid = ptid_get_pid (inferior_ptid); - - switch (object) - { - case TARGET_OBJECT_AUXV: - { - struct cleanup *cleanup = make_cleanup (null_cleanup, NULL); - unsigned char *buf; - size_t buflen; - int mib[4]; - - if (writebuf != NULL) - return TARGET_XFER_E_IO; - mib[0] = CTL_KERN; - mib[1] = KERN_PROC; - mib[2] = KERN_PROC_AUXV; - mib[3] = pid; - if (offset == 0) - { - buf = readbuf; - buflen = len; - } - else - { - buflen = offset + len; - buf = XCNEWVEC (unsigned char, buflen); - cleanup = make_cleanup (xfree, buf); - } - if (sysctl (mib, 4, buf, &buflen, NULL, 0) == 0) - { - if (offset != 0) - { - if (buflen > offset) - { - buflen -= offset; - memcpy (readbuf, buf + offset, buflen); - } - else - buflen = 0; - } - do_cleanups (cleanup); - *xfered_len = buflen; - return (buflen == 0) ? TARGET_XFER_EOF : TARGET_XFER_OK; - } - do_cleanups (cleanup); - return TARGET_XFER_E_IO; - } - default: - return super_xfer_partial (ops, object, annex, readbuf, writebuf, offset, - len, xfered_len); - } -} -#endif - -#ifdef PT_LWPINFO static int debug_nbsd_lwp; static void (*super_resume) (struct target_ops *, @@ -222,27 +147,6 @@ fprintf_filtered (file, _("Debugging of NetBSD lwp module is %s.\n"), value); } -#if defined(TDP_RFPPWAIT) || defined(HAVE_STRUCT_PTRACE_LWPINFO_PL_TDNAME) -/* Fetch the external variant of the kernel's internal process - structure for the process PID into KP. */ - -static void -nbsd_fetch_kinfo_proc (pid_t pid, struct kinfo_proc *kp) -{ - size_t len; - int mib[4]; - - len = sizeof *kp; - mib[0] = CTL_KERN; - mib[1] = KERN_PROC; - mib[2] = KERN_PROC_PID; - mib[3] = pid; - if (sysctl (mib, 4, kp, &len, NULL, 0) == -1) - perror_with_name (("sysctl")); -} -#endif - - /* Return true if PTID is still active in the inferior. */ static int @@ -256,10 +160,6 @@ if (ptrace (PT_LWPINFO, ptid_get_pid (ptid), (caddr_t) &pl, sizeof pl) == -1) return 0; -#ifdef PL_FLAG_EXITED - if (pl.pl_flags & PL_FLAG_EXITED) - return 0; -#endif } return 1; @@ -286,32 +186,50 @@ return normal_pid_to_str (ptid); } -#ifdef HAVE_STRUCT_PTRACE_LWPINFO_PL_TDNAME /* Return the name assigned to a thread by an application. Returns the string in a static buffer. */ static const char * nbsd_thread_name (struct target_ops *self, struct thread_info *thr) { - struct ptrace_lwpinfo pl; - struct kinfo_proc kp; + struct kinfo_lwp *kl; pid_t pid = ptid_get_pid (thr->ptid); lwpid_t lwp = ptid_get_lwp (thr->ptid); - static char buf[sizeof pl.pl_tdname + 1]; + static char buf[KI_LNAMELEN]; + int mib[5]; + size_t i, nlwps; + size_t size; + + mib[0] = CTL_KERN; + mib[1] = KERN_LWP; + mib[2] = pid; + mib[3] = sizeof(struct kinfo_lwp); + mib[4] = 0; + + if (sysctl(mib, 5, NULL, &size, NULL, 0) == -1 || size == 0) + perror_with_name (("sysctl")); + + mib[4] = size / sizeof(size_t); + + kl = (struct kinfo_lwp *) xmalloc (size); + if (kl == NULL) + perror_with_name (("malloc")); + + if (sysctl(mib, 5, kl, &size, NULL, 0) == -1 || size == 0) + perror_with_name (("sysctl")); + + nlwps = size / sizeof(struct kinfo_lwp); + buf[0] = '\0'; + for (i = 0; i < nlwps; i++) { + if (kl[i].l_lid == lwp) { + xsnprintf (buf, sizeof buf, "%s", kl[i].l_name); + break; + } + } + xfree(kl); - /* Note that ptrace_lwpinfo returns the process command in pl_tdname - if a name has not been set explicitly. Return a NULL name in - that case. */ - nbsd_fetch_kinfo_proc (pid, &kp); - pl.pl_lwpid = lwp; - if (ptrace (PT_LWPINFO, pid, (caddr_t) &pl, sizeof pl) == -1) - perror_with_name (("ptrace")); - if (strcmp (kp.ki_comm, pl.pl_tdname) == 0) - return NULL; - xsnprintf (buf, sizeof buf, "%s", pl.pl_tdname); return buf; } -#endif /* Enable additional event reporting on new processes. @@ -329,34 +247,19 @@ static void nbsd_enable_proc_events (pid_t pid) { -#ifdef PT_GET_EVENT_MASK int events; if (ptrace (PT_GET_EVENT_MASK, pid, (PTRACE_TYPE_ARG3)&events, sizeof (events)) == -1) perror_with_name (("ptrace")); events |= PTRACE_FORK; -#ifdef PTRACE_LWP - events |= PTRACE_LWP; -#endif -#ifdef notyet -#ifdef PTRACE_VFORK events |= PTRACE_VFORK; -#endif -#endif + events |= PTRACE_VFORK_DONE; + events |= PTRACE_LWP_CREATE; + events |= PTRACE_LWP_EXIT; if (ptrace (PT_SET_EVENT_MASK, pid, (PTRACE_TYPE_ARG3)&events, sizeof (events)) == -1) perror_with_name (("ptrace")); -#else -#ifdef TDP_RFPPWAIT - if (ptrace (PT_FOLLOW_FORK, pid, (PTRACE_TYPE_ARG3)0, 1) == -1) - perror_with_name (("ptrace")); -#endif -#ifdef PT_LWP_EVENTS - if (ptrace (PT_LWP_EVENTS, pid, (PTRACE_TYPE_ARG3)0, 1) == -1) - perror_with_name (("ptrace")); -#endif -#endif } /* Add threads for any new LWPs in a process. @@ -371,7 +274,6 @@ int val; struct ptrace_lwpinfo pl; -// gdb_assert (!in_thread_list (pid_to_ptid (pid))); pl.pl_lwpid = 0; while ((val = ptrace (PT_LWPINFO, pid, (void *)&pl, sizeof(pl))) != -1 && pl.pl_lwpid != 0) @@ -387,50 +289,11 @@ static void nbsd_update_thread_list (struct target_ops *ops) { -#ifdef PT_LWP_EVENTS - /* With support for thread events, threads are added/deleted from the - list as events are reported, so just try deleting exited threads. */ - delete_exited_threads (); -#else prune_threads (); nbsd_add_threads (ptid_get_pid (inferior_ptid)); -#endif } -#ifdef TDP_RFPPWAIT -/* - To catch fork events, PT_FOLLOW_FORK is set on every traced process - to enable stops on returns from fork or vfork. Note that both the - parent and child will always stop, even if system call stops are not - enabled. - - After a fork, both the child and parent process will stop and report - an event. However, there is no guarantee of order. If the parent - reports its stop first, then nbsd_wait explicitly waits for the new - child before returning. If the child reports its stop first, then - the event is saved on a list and ignored until the parent's stop is - reported. nbsd_wait could have been changed to fetch the parent PID - of the new child and used that to wait for the parent explicitly. - However, if two threads in the parent fork at the same time, then - the wait on the parent might return the "wrong" fork event. - - The initial version of PT_FOLLOW_FORK did not set PL_FLAG_CHILD for - the new child process. This flag could be inferred by treating any - events for an unknown pid as a new child. - - In addition, the initial version of PT_FOLLOW_FORK did not report a - stop event for the parent process of a vfork until after the child - process executed a new program or exited. The kernel was changed to - defer the wait for exit or exec of the child until after posting the - stop event shortly after the change to introduce PL_FLAG_CHILD. - This could be worked around by reporting a vfork event when the - child event posted and ignoring the subsequent event from the - parent. - - This implementation requires both of these fixes for simplicity's - sake. FreeBSD versions newer than 9.1 contain both fixes. -*/ struct nbsd_fork_info { @@ -479,58 +342,6 @@ return null_ptid; } -#ifndef PTRACE_VFORK -static struct nbsd_fork_info *nbsd_pending_vfork_done; - -/* Record a pending vfork done event. */ - -static void -nbsd_add_vfork_done (ptid_t pid) -{ - struct nbsd_fork_info *info = XCNEW (struct nbsd_fork_info); - - info->ptid = pid; - info->next = nbsd_pending_vfork_done; - nbsd_pending_vfork_done = info; -} - -/* Check for a pending vfork done event for a specific PID. */ - -static int -nbsd_is_vfork_done_pending (pid_t pid) -{ - struct nbsd_fork_info *info; - - for (info = nbsd_pending_vfork_done; info != NULL; info = info->next) - { - if (ptid_get_pid (info->ptid) == pid) - return 1; - } - return 0; -} - -/* Check for a pending vfork done event. If one is found, remove it - from the list and return the PTID. */ - -static ptid_t -nbsd_next_vfork_done (void) -{ - struct nbsd_fork_info *info; - ptid_t ptid; - - if (nbsd_pending_vfork_done != NULL) - { - info = nbsd_pending_vfork_done; - nbsd_pending_vfork_done = info->next; - ptid = info->ptid; - xfree (info); - return ptid; - } - return null_ptid; -} -#endif -#endif - /* Implement the "to_resume" target_ops method. */ static void @@ -561,22 +372,118 @@ wptid = super_wait (ops, ptid, ourstatus, target_options); if (ourstatus->kind == TARGET_WAITKIND_STOPPED) { - struct ptrace_lwpinfo pl; - pid_t pid; + ptrace_state_t pst, child_pst; + ptrace_siginfo_t psi, child_psi; int status; + pid_t pid, child, wchild; + ptid_t child_ptid; + pid = ptid_get_pid (wptid); // Find the lwp that caused the wait status change - pl.pl_lwpid = 0; - do { - if (ptrace (PT_LWPINFO, pid, (caddr_t) &pl, sizeof pl) == -1) - perror_with_name (("ptrace")); - if (pl.pl_event == PL_EVENT_SIGNAL) - break; - } while (pl.pl_lwpid != 0); - if (pl.pl_lwpid != 0) - wptid = ptid_build (pid, pl.pl_lwpid, 0); - if (!in_thread_list (wptid)) - add_thread (wptid); + if (ptrace(PT_GET_SIGINFO, pid, &psi, sizeof(psi)) == -1) + perror_with_name (("ptrace")); + + thread_change_ptid (pid_to_ptid (pid), wptid); + + switch (psi.psi_siginfo.si_signo) { + case SIGTRAP: + switch (psi.psi_siginfo.si_code) { + case TRAP_BRKPT: +// lp->stop_reason = TARGET_STOPPED_BY_SW_BREAKPOINT; + break; + case TRAP_DBREG: +// if (hardware_breakpoint_inserted_here_p (get_regcache_aspace (regcache), pc)) +// lp->stop_reason = TARGET_STOPPED_BY_HW_BREAKPOINT; +// else +// lp->stop_reason = TARGET_STOPPED_BY_WATCHPOINT; + break; + case TRAP_TRACE: +// lp->stop_reason = TARGET_STOPPED_BY_SINGLE_STEP; + break; + case TRAP_SCE: + ourstatus->kind = TARGET_WAITKIND_SYSCALL_ENTRY; +// ourstatus->value.syscall_number = 0; + break; + case TRAP_SCX: + ourstatus->kind = TARGET_WAITKIND_SYSCALL_RETURN; +// ourstatus->value.syscall_number = 0; + break; + case TRAP_EXEC: + ourstatus->kind = TARGET_WAITKIND_EXECD; + ourstatus->value.execd_pathname = xstrdup(nbsd_pid_to_exec_file (NULL, pid)); + break; + case TRAP_LWP: + case TRAP_CHLD: + if (ptrace(PT_GET_PROCESS_STATE, pid, &pst, sizeof(pst)) == -1) + perror_with_name (("ptrace")); + switch (pst.pe_report_event) { + case PTRACE_FORK: + case PTRACE_VFORK: + if (pst.pe_report_event == PTRACE_FORK) + ourstatus->kind = TARGET_WAITKIND_FORKED; + else + ourstatus->kind = TARGET_WAITKIND_VFORKED; + child = pst.pe_other_pid; + wchild = waitpid (child, &status, 0); + + if (wchild == -1) + perror_with_name (("waitpid")); + + gdb_assert (wchild == child); + + if (!WIFSTOPPED(status)) { + /* Abnormal situation (SIGKILLed?).. bail out */ + ourstatus->kind = TARGET_WAITKIND_SPURIOUS; + return wptid; + } + + if (ptrace(PT_GET_SIGINFO, child, &child_psi, sizeof(child_psi)) == -1) + perror_with_name (("ptrace")); + + if (child_psi.psi_siginfo.si_signo != SIGTRAP) { + /* Abnormal situation.. bail out */ + ourstatus->kind = TARGET_WAITKIND_SPURIOUS; + return wptid; + } + + if (child_psi.psi_siginfo.si_code != TRAP_CHLD) { + /* Abnormal situation.. bail out */ + ourstatus->kind = TARGET_WAITKIND_SPURIOUS; + return wptid; + } + + child_ptid = ptid_build(child, child_psi.psi_lwpid, 0); + nbsd_enable_proc_events (ptid_get_pid (child_ptid)); + ourstatus->value.related_pid = child_ptid; + break; + case PTRACE_VFORK_DONE: + ourstatus->kind = TARGET_WAITKIND_VFORK_DONE; + break; + case PTRACE_LWP_CREATE: + wptid = ptid_build (pid, pst.pe_lwp, 0); + if (in_thread_list (wptid)) { + /* Newborn reported after attach? */ + ourstatus->kind = TARGET_WAITKIND_SPURIOUS; + return wptid; + } + add_thread (wptid); + ourstatus->kind = TARGET_WAITKIND_THREAD_CREATED; + break; + case PTRACE_LWP_EXIT: + wptid = ptid_build (pid, pst.pe_lwp, 0); + if (!in_thread_list (wptid)) { + /* Dead child reported after attach? */ + ourstatus->kind = TARGET_WAITKIND_SPURIOUS; + return wptid; + } + delete_thread (wptid); + ourstatus->kind = TARGET_WAITKIND_THREAD_EXITED; + break; + } + break; + } + break; + } if (debug_nbsd_lwp) fprintf_unfiltered (gdb_stdlog, @@ -589,7 +496,6 @@ return wptid; } -#ifdef TDP_RFPPWAIT /* Target hook for follow_fork. On entry and at return inferior_ptid is the ptid of the followed inferior. */ @@ -635,7 +541,6 @@ { return 0; } -#endif /* Implement the "to_post_startup_inferior" target_ops method. */ @@ -654,10 +559,6 @@ nbsd_add_threads (pid); } -#ifdef PL_FLAG_EXEC -/* If the FreeBSD kernel supports PL_FLAG_EXEC, then traced processes - will always stop after exec. */ - static int nbsd_insert_exec_catchpoint (struct target_ops *self, int pid) { @@ -669,9 +570,7 @@ { return 0; } -#endif -#ifdef HAVE_STRUCT_PTRACE_LWPINFO_PL_SYSCALL_CODE static int nbsd_set_syscall_catchpoint (struct target_ops *self, int pid, int needed, int any_count, int table_size, int *table) @@ -682,24 +581,15 @@ are filtered by GDB rather than the kernel. */ return 0; } -#endif -#endif void nbsd_nat_add_target (struct target_ops *t) { t->to_pid_to_exec_file = nbsd_pid_to_exec_file; t->to_find_memory_regions = nbsd_find_memory_regions; -#ifdef KERN_PROC_AUXV - super_xfer_partial = t->to_xfer_partial; - t->to_xfer_partial = nbsd_xfer_partial; -#endif -#ifdef PT_LWPINFO t->to_thread_alive = nbsd_thread_alive; t->to_pid_to_str = nbsd_pid_to_str; -#ifdef HAVE_STRUCT_PTRACE_LWPINFO_PL_TDNAME t->to_thread_name = nbsd_thread_name; -#endif t->to_update_thread_list = nbsd_update_thread_list; t->to_has_thread_control = tc_schedlock; super_resume = t->to_resume; @@ -708,21 +598,14 @@ t->to_wait = nbsd_wait; t->to_post_startup_inferior = nbsd_post_startup_inferior; t->to_post_attach = nbsd_post_attach; -#ifdef TDP_RFPPWAIT t->to_follow_fork = nbsd_follow_fork; t->to_insert_fork_catchpoint = nbsd_insert_fork_catchpoint; t->to_remove_fork_catchpoint = nbsd_remove_fork_catchpoint; t->to_insert_vfork_catchpoint = nbsd_insert_vfork_catchpoint; t->to_remove_vfork_catchpoint = nbsd_remove_vfork_catchpoint; -#endif -#ifdef PL_FLAG_EXEC t->to_insert_exec_catchpoint = nbsd_insert_exec_catchpoint; t->to_remove_exec_catchpoint = nbsd_remove_exec_catchpoint; -#endif -#ifdef HAVE_STRUCT_PTRACE_LWPINFO_PL_SYSCALL_CODE t->to_set_syscall_catchpoint = nbsd_set_syscall_catchpoint; -#endif -#endif add_target (t); } @@ -732,7 +615,6 @@ void _initialize_nbsd_nat (void) { -#ifdef PT_LWPINFO add_setshow_boolean_cmd ("nbsd-lwp", class_maintenance, &debug_nbsd_lwp, _("\ Set debugging of NetBSD lwp module."), _("\ @@ -741,5 +623,4 @@ NULL, &show_nbsd_lwp_debug, &setdebuglist, &showdebuglist); -#endif }