1 /* Internal interfaces for the NetBSD code.
3 Copyright (C) 2006-2022 Free Software Foundation, Inc.
5 This file is part of GDB.
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.
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.
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/>. */
20 #include "gdbsupport/common-defs.h"
21 #include "nat/netbsd-nat.h"
22 #include "gdbsupport/common-debug.h"
24 #include <sys/types.h>
25 #include <sys/ptrace.h>
26 #include <sys/sysctl.h>
30 #include "gdbsupport/function-view.h"
35 /* See netbsd-nat.h. */
38 pid_to_exec_file (pid_t pid
)
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)
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.
52 This function assumes internally that the queried process is stopped
53 and the number of threads does not change between two sysctl () calls. */
56 netbsd_thread_lister (const pid_t pid
,
57 gdb::function_view
<bool (const struct kinfo_lwp
*)>
60 int mib
[5] = {CTL_KERN
, KERN_LWP
, pid
, sizeof (struct kinfo_lwp
), 0};
63 if (sysctl (mib
, ARRAY_SIZE (mib
), NULL
, &size
, NULL
, 0) == -1 || size
== 0)
64 perror_with_name (("sysctl"));
66 mib
[4] = size
/ sizeof (size_t);
68 gdb::unique_xmalloc_ptr
<struct kinfo_lwp
[]> kl
69 ((struct kinfo_lwp
*) xcalloc (size
, 1));
71 if (sysctl (mib
, ARRAY_SIZE (mib
), kl
.get (), &size
, NULL
, 0) == -1
73 perror_with_name (("sysctl"));
75 for (size_t i
= 0; i
< size
/ sizeof (struct kinfo_lwp
); i
++)
77 struct kinfo_lwp
*l
= &kl
[i
];
79 /* Return true if the specified thread is alive. */
81 = [] (struct kinfo_lwp
*lwp
)
96 /* Ignore embryonic or demised threads. */
107 /* See netbsd-nat.h. */
110 thread_alive (ptid_t ptid
)
112 pid_t pid
= ptid
.pid ();
113 lwpid_t lwp
= ptid
.lwp ();
116 = [=] (const struct kinfo_lwp
*kl
)
118 return kl
->l_lid
== lwp
;
121 return netbsd_thread_lister (pid
, fn
);
124 /* See netbsd-nat.h. */
127 thread_name (ptid_t ptid
)
129 pid_t pid
= ptid
.pid ();
130 lwpid_t lwp
= ptid
.lwp ();
132 static char buf
[KI_LNAMELEN
] = {};
135 = [=] (const struct kinfo_lwp
*kl
)
137 if (kl
->l_lid
== lwp
)
139 xsnprintf (buf
, sizeof buf
, "%s", kl
->l_name
);
145 if (netbsd_thread_lister (pid
, fn
))
151 /* See netbsd-nat.h. */
154 for_each_thread (pid_t pid
, gdb::function_view
<void (ptid_t
)> callback
)
157 = [=, &callback
] (const struct kinfo_lwp
*kl
)
159 ptid_t ptid
= ptid_t (pid
, kl
->l_lid
, 0);
164 netbsd_thread_lister (pid
, fn
);
167 /* See netbsd-nat.h. */
170 enable_proc_events (pid_t pid
)
174 if (ptrace (PT_GET_EVENT_MASK
, pid
, &events
, sizeof (events
)) == -1)
175 perror_with_name (("ptrace"));
177 events
|= PTRACE_LWP_CREATE
;
178 events
|= PTRACE_LWP_EXIT
;
180 if (ptrace (PT_SET_EVENT_MASK
, pid
, &events
, sizeof (events
)) == -1)
181 perror_with_name (("ptrace"));
184 /* See netbsd-nat.h. */
187 qxfer_siginfo (pid_t pid
, const char *annex
, unsigned char *readbuf
,
188 unsigned const char *writebuf
, CORE_ADDR offset
, int len
)
190 ptrace_siginfo_t psi
;
192 if (offset
> sizeof (siginfo_t
))
195 if (ptrace (PT_GET_SIGINFO
, pid
, &psi
, sizeof (psi
)) == -1)
198 if (offset
+ len
> sizeof (siginfo_t
))
199 len
= sizeof (siginfo_t
) - offset
;
202 memcpy (readbuf
, ((gdb_byte
*) &psi
.psi_siginfo
) + offset
, len
);
205 memcpy (((gdb_byte
*) &psi
.psi_siginfo
) + offset
, writebuf
, len
);
207 if (ptrace (PT_SET_SIGINFO
, pid
, &psi
, sizeof (psi
)) == -1)
213 /* See netbsd-nat.h. */
216 write_memory (pid_t pid
, unsigned const char *writebuf
, CORE_ADDR offset
,
217 size_t len
, size_t *xfered_len
)
219 struct ptrace_io_desc io
;
220 io
.piod_op
= PIOD_WRITE_D
;
223 size_t bytes_written
= 0;
225 /* Zero length write always succeeds. */
230 io
.piod_addr
= (void *)(writebuf
+ bytes_written
);
231 io
.piod_offs
= (void *)(offset
+ bytes_written
);
234 int rv
= ptrace (PT_IO
, pid
, &io
, 0);
237 gdb_assert (errno
!= 0);
240 if (io
.piod_len
== 0)
243 bytes_written
+= io
.piod_len
;
244 io
.piod_len
= len
- bytes_written
;
246 while (bytes_written
< len
);
249 if (xfered_len
!= nullptr)
250 *xfered_len
= bytes_written
;
255 /* See netbsd-nat.h. */
258 read_memory (pid_t pid
, unsigned char *readbuf
, CORE_ADDR offset
,
259 size_t len
, size_t *xfered_len
)
261 struct ptrace_io_desc io
;
262 io
.piod_op
= PIOD_READ_D
;
265 size_t bytes_read
= 0;
267 /* Zero length read always succeeds. */
272 io
.piod_offs
= (void *)(offset
+ bytes_read
);
273 io
.piod_addr
= readbuf
+ bytes_read
;
275 int rv
= ptrace (PT_IO
, pid
, &io
, 0);
278 if (io
.piod_len
== 0)
281 bytes_read
+= io
.piod_len
;
282 io
.piod_len
= len
- bytes_read
;
284 while (bytes_read
< len
);
287 if (xfered_len
!= nullptr)
288 *xfered_len
= bytes_read
;