Commit | Line | Data |
---|---|---|
84c5b489 MK |
1 | /* Native-dependent code for NetBSD. |
2 | ||
b811d2c2 | 3 | Copyright (C) 2006-2020 Free Software Foundation, Inc. |
84c5b489 MK |
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 | |
a9762ec7 | 9 | the Free Software Foundation; either version 3 of the License, or |
84c5b489 MK |
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 | |
a9762ec7 | 18 | along with this program. If not, see <http://www.gnu.org/licenses/>. */ |
84c5b489 MK |
19 | |
20 | #include "defs.h" | |
21 | ||
84c5b489 | 22 | #include "nbsd-nat.h" |
05f00e22 KR |
23 | #include "gdbthread.h" |
24 | #include "inferior.h" | |
84c5b489 | 25 | |
a2ecbe9f KR |
26 | #include <sys/types.h> |
27 | #include <sys/ptrace.h> | |
28 | #include <sys/sysctl.h> | |
29 | ||
766062f6 | 30 | /* Return the name of a file that can be opened to get the symbols for |
84c5b489 MK |
31 | the child process identified by PID. */ |
32 | ||
33 | char * | |
f6ac5f3d | 34 | nbsd_nat_target::pid_to_exec_file (int pid) |
84c5b489 | 35 | { |
b4ab256d | 36 | static char buf[PATH_MAX]; |
a2ecbe9f KR |
37 | size_t buflen; |
38 | int mib[4] = {CTL_KERN, KERN_PROC_ARGS, pid, KERN_PROC_PATHNAME}; | |
39 | buflen = sizeof (buf); | |
40 | if (sysctl (mib, ARRAY_SIZE (mib), buf, &buflen, NULL, 0)) | |
41 | return NULL; | |
42 | return buf; | |
84c5b489 | 43 | } |
05f00e22 KR |
44 | |
45 | /* Generic thread (LWP) lister within a specified process. The callback | |
46 | parameters is a C++ function that is called for each detected thread. */ | |
47 | ||
48 | static bool | |
49 | nbsd_thread_lister (const pid_t pid, | |
50 | gdb::function_view<bool (const struct kinfo_lwp *)> | |
51 | callback) | |
52 | { | |
53 | int mib[5] = {CTL_KERN, KERN_LWP, pid, sizeof (struct kinfo_lwp), 0}; | |
54 | size_t size; | |
55 | ||
56 | if (sysctl (mib, ARRAY_SIZE (mib), NULL, &size, NULL, 0) == -1 || size == 0) | |
57 | perror_with_name (("sysctl")); | |
58 | ||
59 | mib[4] = size / sizeof (size_t); | |
60 | ||
61 | gdb::unique_xmalloc_ptr<struct kinfo_lwp[]> kl | |
62 | ((struct kinfo_lwp *) xcalloc (size, 1)); | |
63 | ||
64 | if (sysctl (mib, ARRAY_SIZE (mib), kl.get (), &size, NULL, 0) == -1 | |
65 | || size == 0) | |
66 | perror_with_name (("sysctl")); | |
67 | ||
68 | for (size_t i = 0; i < size / sizeof (struct kinfo_lwp); i++) | |
69 | { | |
70 | struct kinfo_lwp *l = &kl[i]; | |
71 | ||
72 | /* Return true if the specified thread is alive. */ | |
73 | auto lwp_alive | |
74 | = [] (struct kinfo_lwp *lwp) | |
75 | { | |
76 | switch (lwp->l_stat) | |
77 | { | |
78 | case LSSLEEP: | |
79 | case LSRUN: | |
80 | case LSONPROC: | |
81 | case LSSTOP: | |
82 | case LSSUSPENDED: | |
83 | return true; | |
84 | default: | |
85 | return false; | |
86 | } | |
87 | }; | |
88 | ||
89 | /* Ignore embryonic or demised threads. */ | |
90 | if (!lwp_alive (l)) | |
91 | continue; | |
92 | ||
93 | if (callback (l)) | |
94 | return true; | |
95 | } | |
96 | ||
97 | return false; | |
98 | } | |
99 | ||
100 | /* Return true if PTID is still active in the inferior. */ | |
101 | ||
102 | bool | |
103 | nbsd_nat_target::thread_alive (ptid_t ptid) | |
104 | { | |
105 | pid_t pid = ptid.pid (); | |
106 | int lwp = ptid.lwp (); | |
107 | ||
108 | auto fn | |
109 | = [&lwp] (const struct kinfo_lwp *kl) | |
110 | { | |
111 | return kl->l_lid == lwp; | |
112 | }; | |
113 | ||
114 | return nbsd_thread_lister (pid, fn); | |
115 | } | |
116 | ||
117 | /* Return the name assigned to a thread by an application. Returns | |
118 | the string in a static buffer. */ | |
119 | ||
120 | const char * | |
121 | nbsd_nat_target::thread_name (struct thread_info *thr) | |
122 | { | |
123 | ptid_t ptid = thr->ptid; | |
124 | pid_t pid = ptid.pid (); | |
125 | int lwp = ptid.lwp (); | |
126 | ||
127 | static char buf[KI_LNAMELEN] = {}; | |
128 | ||
129 | auto fn | |
130 | = [&lwp] (const struct kinfo_lwp *kl) | |
131 | { | |
132 | if (kl->l_lid == lwp) | |
133 | { | |
134 | xsnprintf (buf, sizeof buf, "%s", kl->l_name); | |
135 | return true; | |
136 | } | |
137 | return false; | |
138 | }; | |
139 | ||
140 | if (nbsd_thread_lister (pid, fn)) | |
141 | return buf; | |
142 | else | |
143 | return NULL; | |
144 | } | |
145 | ||
146 | /* Implement the "post_attach" target_ops method. */ | |
147 | ||
148 | static void | |
149 | nbsd_add_threads (nbsd_nat_target *target, pid_t pid) | |
150 | { | |
151 | auto fn | |
152 | = [&target, &pid] (const struct kinfo_lwp *kl) | |
153 | { | |
154 | ptid_t ptid = ptid_t (pid, kl->l_lid, 0); | |
155 | if (!in_thread_list (target, ptid)) | |
156 | { | |
157 | if (inferior_ptid.lwp () == 0) | |
158 | thread_change_ptid (target, inferior_ptid, ptid); | |
159 | else | |
160 | add_thread (target, ptid); | |
161 | } | |
162 | return false; | |
163 | }; | |
164 | ||
165 | nbsd_thread_lister (pid, fn); | |
166 | } | |
167 | ||
168 | /* Implement the "post_attach" target_ops method. */ | |
169 | ||
170 | void | |
171 | nbsd_nat_target::post_attach (int pid) | |
172 | { | |
173 | nbsd_add_threads (this, pid); | |
174 | } | |
175 | ||
176 | /* Implement the "update_thread_list" target_ops method. */ | |
177 | ||
178 | void | |
179 | nbsd_nat_target::update_thread_list () | |
180 | { | |
181 | prune_threads (); | |
182 | ||
183 | nbsd_add_threads (this, inferior_ptid.pid ()); | |
184 | } | |
185 | ||
186 | /* Convert PTID to a string. */ | |
187 | ||
188 | std::string | |
189 | nbsd_nat_target::pid_to_str (ptid_t ptid) | |
190 | { | |
191 | int lwp = ptid.lwp (); | |
192 | ||
193 | if (lwp != 0) | |
194 | { | |
195 | pid_t pid = ptid.pid (); | |
196 | ||
197 | return string_printf ("LWP %d of process %d", lwp, pid); | |
198 | } | |
199 | ||
200 | return normal_pid_to_str (ptid); | |
201 | } |