From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 14819 invoked by alias); 27 Feb 2014 22:43:47 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Received: (qmail 14809 invoked by uid 89); 27 Feb 2014 22:43:46 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.3 required=5.0 tests=AWL,BAYES_00,RP_MATCHES_RCVD autolearn=ham version=3.3.2 X-HELO: glazunov.sibelius.xs4all.nl Received: from sibelius.xs4all.nl (HELO glazunov.sibelius.xs4all.nl) (83.163.83.176) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES256-GCM-SHA384 encrypted) ESMTPS; Thu, 27 Feb 2014 22:43:44 +0000 Received: from glazunov.sibelius.xs4all.nl (kettenis@localhost [127.0.0.1]) by glazunov.sibelius.xs4all.nl (8.14.5/8.14.3) with ESMTP id s1RMhel0005544 for ; Thu, 27 Feb 2014 23:43:40 +0100 (CET) Received: (from kettenis@localhost) by glazunov.sibelius.xs4all.nl (8.14.5/8.14.3/Submit) id s1RMheVq007573; Thu, 27 Feb 2014 23:43:40 +0100 (CET) Date: Thu, 27 Feb 2014 22:43:00 -0000 Message-Id: <201402272243.s1RMheVq007573@glazunov.sibelius.xs4all.nl> From: Mark Kettenis To: gdb-patches@sourceware.org Subject: [PATCH/RFC] Support rthreads on OpenBSD 5.2 and later. X-SW-Source: 2014-02/txt/msg00850.txt.bz2 OpenBSD 5.2 and later has a proper threads implementation based on kernel threads. Debugging support is provided through additional ptrace(2) requests, so this diff extends the generic code in inf-ptrace.c with OpenBSD-specific code to discover additional threads. I intend to commit this in a couple of days as I don't really expect other people to care. But comments are welcome... gdb/ChangeLog: * obsd-nat.h: New file. * obsd-nat.c: New file. --- gdb/obsd-nat.c | 185 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ gdb/obsd-nat.h | 25 ++++++++ 2 files changed, 210 insertions(+) create mode 100644 gdb/obsd-nat.c create mode 100644 gdb/obsd-nat.h diff --git a/gdb/obsd-nat.c b/gdb/obsd-nat.c new file mode 100644 index 0000000..c17a565 --- /dev/null +++ b/gdb/obsd-nat.c @@ -0,0 +1,185 @@ +/* Native-dependent code for OpenBSD. + + Copyright (C) 2012-2014 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include "defs.h" +#include "gdbthread.h" +#include "inferior.h" +#include "target.h" + +#include "gdb_assert.h" +#include +#include +#include + +#include "inf-child.h" +#include "obsd-nat.h" + +/* OpenBSD 5.2 and later include rthreads which uses a thread model + that maps userlan threads directly onto kernel threads in a 1:1 + fashion. */ + +#ifdef PT_GET_THREAD_FIRST + +static char * +obsd_pid_to_str (struct target_ops *ops, ptid_t ptid) +{ + if (ptid_get_lwp (ptid) != 0) + { + static char buf[64]; + + xsnprintf (buf, sizeof buf, "thread %ld", ptid_get_lwp (ptid)); + return buf; + } + + return normal_pid_to_str (ptid); +} + +static void +obsd_find_new_threads (struct target_ops *ops) +{ + pid_t pid = ptid_get_pid (inferior_ptid); + struct ptrace_thread_state pts; + + if (ptrace(PT_GET_THREAD_FIRST, pid, (caddr_t)&pts, sizeof pts) == -1) + perror_with_name (("ptrace")); + + while (pts.pts_tid != -1) + { + ptid_t ptid = ptid_build (pid, pts.pts_tid, 0); + + if (!in_thread_list (ptid)) + { + if (ptid_get_lwp (inferior_ptid) == 0) + thread_change_ptid (inferior_ptid, ptid); + else + add_thread (ptid); + } + + if (ptrace(PT_GET_THREAD_NEXT, pid, (caddr_t)&pts, sizeof pts) == -1) + perror_with_name (("ptrace")); + } +} + +static ptid_t +obsd_wait (struct target_ops *ops, + ptid_t ptid, struct target_waitstatus *ourstatus, int options) +{ + pid_t pid; + int status, save_errno; + + do + { + set_sigint_trap (); + + do + { + pid = waitpid (ptid_get_pid (ptid), &status, 0); + save_errno = errno; + } + while (pid == -1 && errno == EINTR); + + clear_sigint_trap (); + + if (pid == -1) + { + fprintf_unfiltered (gdb_stderr, + _("Child process unexpectedly missing: %s.\n"), + safe_strerror (save_errno)); + + /* Claim it exited with unknown signal. */ + ourstatus->kind = TARGET_WAITKIND_SIGNALLED; + ourstatus->value.sig = GDB_SIGNAL_UNKNOWN; + return inferior_ptid; + } + + /* Ignore terminated detached child processes. */ + if (!WIFSTOPPED (status) && pid != ptid_get_pid (inferior_ptid)) + pid = -1; + } + while (pid == -1); + + ptid = pid_to_ptid (pid); + + if (WIFSTOPPED (status)) + { + ptrace_state_t pe; + pid_t fpid; + + if (ptrace (PT_GET_PROCESS_STATE, pid, (caddr_t)&pe, sizeof pe) == -1) + perror_with_name (("ptrace")); + + switch (pe.pe_report_event) + { + case PTRACE_FORK: + ourstatus->kind = TARGET_WAITKIND_FORKED; + ourstatus->value.related_pid = pid_to_ptid (pe.pe_other_pid); + + /* Make sure the other end of the fork is stopped too. */ + fpid = waitpid (pe.pe_other_pid, &status, 0); + if (fpid == -1) + perror_with_name (("waitpid")); + + if (ptrace (PT_GET_PROCESS_STATE, fpid, + (caddr_t)&pe, sizeof pe) == -1) + perror_with_name (("ptrace")); + + gdb_assert (pe.pe_report_event == PTRACE_FORK); + gdb_assert (pe.pe_other_pid == pid); + if (fpid == ptid_get_pid (inferior_ptid)) + { + ourstatus->value.related_pid = pid_to_ptid (pe.pe_other_pid); + return pid_to_ptid (fpid); + } + + return pid_to_ptid (pid); + } + + ptid = ptid_build (pid, pe.pe_tid, 0); + if (!in_thread_list (ptid)) + { + if (ptid_get_lwp (inferior_ptid) == 0) + thread_change_ptid (inferior_ptid, ptid); + else + add_thread (ptid); + } + } + + store_waitstatus (ourstatus, status); + return ptid; +} + +void +obsd_add_target (struct target_ops *t) +{ + /* Override some methods to support threads. */ + t->to_pid_to_str = obsd_pid_to_str; + t->to_find_new_threads = obsd_find_new_threads; + t->to_wait = obsd_wait; + add_target (t); +} + +#else + +void +obsd_add_target (struct target_ops *t) +{ + add_target (t); +} + +#endif /* PT_GET_THREAD_FIRST */ diff --git a/gdb/obsd-nat.h b/gdb/obsd-nat.h new file mode 100644 index 0000000..ad021fc --- /dev/null +++ b/gdb/obsd-nat.h @@ -0,0 +1,25 @@ +/* Native-dependent code for OpenBSD. + + Copyright (C) 2014 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifndef OBSD_NAT_H +#define OBSD_NAT_H + +extern void obsd_add_target (struct target_ops *); + +#endif /* obsd-nat.h */ -- 1.8.5.3