d805b892404e2d3dc0e67bd9573bcad8cc96c523
[deliverable/binutils-gdb.git] / gdb / nat / netbsd-nat.c
1 /* Internal interfaces for the NetBSD code.
2
3 Copyright (C) 2006-2020 Free Software Foundation, Inc.
4
5 This file is part of GDB.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
19
20 #include "gdbsupport/common-defs.h"
21 #include "nat/netbsd-nat.h"
22 #include "gdbsupport/common-debug.h"
23
24 #include <sys/types.h>
25 #include <sys/ptrace.h>
26 #include <sys/sysctl.h>
27
28 #include <cstring>
29
30 #include "gdbsupport/function-view.h"
31
32 namespace netbsd_nat
33 {
34
35 /* See netbsd-nat.h. */
36
37 const char *
38 pid_to_exec_file (pid_t pid)
39 {
40 static char buf[PATH_MAX];
41 int mib[4] = {CTL_KERN, KERN_PROC_ARGS, pid, KERN_PROC_PATHNAME};
42 size_t buflen = sizeof (buf);
43 if (::sysctl (mib, ARRAY_SIZE (mib), buf, &buflen, NULL, 0) != 0)
44 return NULL;
45 return buf;
46 }
47
48 /* Generic thread (LWP) lister within a specified PID. The CALLBACK
49 parameters is a C++ function that is called for each detected thread.
50 When the CALLBACK function returns true, the iteration is interrupted.
51
52 This function assumes internally that the queried process is stopped
53 and the number of threads does not change between two sysctl () calls. */
54
55 static bool
56 netbsd_thread_lister (const pid_t pid,
57 gdb::function_view<bool (const struct kinfo_lwp *)>
58 callback)
59 {
60 int mib[5] = {CTL_KERN, KERN_LWP, pid, sizeof (struct kinfo_lwp), 0};
61 size_t size;
62
63 if (sysctl (mib, ARRAY_SIZE (mib), NULL, &size, NULL, 0) == -1 || size == 0)
64 perror_with_name (("sysctl"));
65
66 mib[4] = size / sizeof (size_t);
67
68 gdb::unique_xmalloc_ptr<struct kinfo_lwp[]> kl
69 ((struct kinfo_lwp *) xcalloc (size, 1));
70
71 if (sysctl (mib, ARRAY_SIZE (mib), kl.get (), &size, NULL, 0) == -1
72 || size == 0)
73 perror_with_name (("sysctl"));
74
75 for (size_t i = 0; i < size / sizeof (struct kinfo_lwp); i++)
76 {
77 struct kinfo_lwp *l = &kl[i];
78
79 /* Return true if the specified thread is alive. */
80 auto lwp_alive
81 = [] (struct kinfo_lwp *lwp)
82 {
83 switch (lwp->l_stat)
84 {
85 case LSSLEEP:
86 case LSRUN:
87 case LSONPROC:
88 case LSSTOP:
89 case LSSUSPENDED:
90 return true;
91 default:
92 return false;
93 }
94 };
95
96 /* Ignore embryonic or demised threads. */
97 if (!lwp_alive (l))
98 continue;
99
100 if (callback (l))
101 return true;
102 }
103
104 return false;
105 }
106
107 /* See netbsd-nat.h. */
108
109 bool
110 thread_alive (ptid_t ptid)
111 {
112 pid_t pid = ptid.pid ();
113 lwpid_t lwp = ptid.lwp ();
114
115 auto fn
116 = [=] (const struct kinfo_lwp *kl)
117 {
118 return kl->l_lid == lwp;
119 };
120
121 return netbsd_thread_lister (pid, fn);
122 }
123
124 /* See netbsd-nat.h. */
125
126 const char *
127 thread_name (ptid_t ptid)
128 {
129 pid_t pid = ptid.pid ();
130 lwpid_t lwp = ptid.lwp ();
131
132 static char buf[KI_LNAMELEN] = {};
133
134 auto fn
135 = [=] (const struct kinfo_lwp *kl)
136 {
137 if (kl->l_lid == lwp)
138 {
139 xsnprintf (buf, sizeof buf, "%s", kl->l_name);
140 return true;
141 }
142 return false;
143 };
144
145 if (netbsd_thread_lister (pid, fn))
146 return buf;
147 else
148 return NULL;
149 }
150
151 /* See netbsd-nat.h. */
152
153 void
154 for_each_thread (pid_t pid, gdb::function_view<void (ptid_t)> callback)
155 {
156 auto fn
157 = [=, &callback] (const struct kinfo_lwp *kl)
158 {
159 ptid_t ptid = ptid_t (pid, kl->l_lid, 0);
160 callback (ptid);
161 return false;
162 };
163
164 netbsd_thread_lister (pid, fn);
165 }
166
167 /* See netbsd-nat.h. */
168
169 void
170 enable_proc_events (pid_t pid)
171 {
172 int events;
173
174 if (ptrace (PT_GET_EVENT_MASK, pid, &events, sizeof (events)) == -1)
175 perror_with_name (("ptrace"));
176
177 events |= PTRACE_LWP_CREATE;
178 events |= PTRACE_LWP_EXIT;
179
180 if (ptrace (PT_SET_EVENT_MASK, pid, &events, sizeof (events)) == -1)
181 perror_with_name (("ptrace"));
182 }
183
184 }
This page took 0.034094 seconds and 3 git commands to generate.