Handle pending stops from the Windows kernel
[deliverable/binutils-gdb.git] / gdb / nbsd-nat.c
CommitLineData
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
33char *
f6ac5f3d 34nbsd_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
48static bool
49nbsd_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
102bool
103nbsd_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
120const char *
121nbsd_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
148static void
149nbsd_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
170void
171nbsd_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
178void
179nbsd_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
188std::string
189nbsd_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}
This page took 1.320897 seconds and 4 git commands to generate.