When displaying ranges, ignore duplicate offsets.
[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 23#include "gdbthread.h"
54b8cbd0 24#include "nbsd-tdep.h"
05f00e22 25#include "inferior.h"
54b8cbd0 26#include "gdbarch.h"
84c5b489 27
a2ecbe9f
KR
28#include <sys/types.h>
29#include <sys/ptrace.h>
30#include <sys/sysctl.h>
31
766062f6 32/* Return the name of a file that can be opened to get the symbols for
84c5b489
MK
33 the child process identified by PID. */
34
35char *
f6ac5f3d 36nbsd_nat_target::pid_to_exec_file (int pid)
84c5b489 37{
b4ab256d 38 static char buf[PATH_MAX];
a2ecbe9f
KR
39 size_t buflen;
40 int mib[4] = {CTL_KERN, KERN_PROC_ARGS, pid, KERN_PROC_PATHNAME};
41 buflen = sizeof (buf);
42 if (sysctl (mib, ARRAY_SIZE (mib), buf, &buflen, NULL, 0))
43 return NULL;
44 return buf;
84c5b489 45}
05f00e22 46
b4848d2a
KR
47/* Return the current directory for the process identified by PID. */
48
49static std::string
50nbsd_pid_to_cwd (int pid)
51{
52 char buf[PATH_MAX];
53 size_t buflen;
54 int mib[4] = {CTL_KERN, KERN_PROC_ARGS, pid, KERN_PROC_CWD};
55 buflen = sizeof (buf);
56 if (sysctl (mib, ARRAY_SIZE (mib), buf, &buflen, NULL, 0))
57 return "";
58 return buf;
59}
60
06ca5dd4
KR
61/* Return the kinfo_proc2 structure for the process identified by PID. */
62
63static bool
64nbsd_pid_to_kinfo_proc2 (pid_t pid, struct kinfo_proc2 *kp)
65{
66 gdb_assert (kp != nullptr);
67
68 size_t size = sizeof (*kp);
69 int mib[6] = {CTL_KERN, KERN_PROC2, KERN_PROC_PID, pid,
70 static_cast<int> (size), 1};
71 return !sysctl (mib, ARRAY_SIZE (mib), kp, &size, NULL, 0);
72}
73
49d1d1f5
KR
74/* Return the command line for the process identified by PID. */
75
76static gdb::unique_xmalloc_ptr<char[]>
77nbsd_pid_to_cmdline (int pid)
78{
79 int mib[4] = {CTL_KERN, KERN_PROC_ARGS, pid, KERN_PROC_ARGV};
80
81 size_t size = 0;
82 if (sysctl (mib, ARRAY_SIZE (mib), NULL, &size, NULL, 0) == -1 || size == 0)
83 return nullptr;
84
85 gdb::unique_xmalloc_ptr<char[]> args (XNEWVAR (char, size));
86
87 if (sysctl (mib, ARRAY_SIZE (mib), args.get (), &size, NULL, 0) == -1
88 || size == 0)
89 return nullptr;
90
91 /* Arguments are returned as a flattened string with NUL separators.
92 Join the arguments with spaces to form a single string. */
93 for (size_t i = 0; i < size - 1; i++)
94 if (args[i] == '\0')
95 args[i] = ' ';
96 args[size - 1] = '\0';
97
98 return args;
99}
100
05f00e22
KR
101/* Generic thread (LWP) lister within a specified process. The callback
102 parameters is a C++ function that is called for each detected thread. */
103
104static bool
105nbsd_thread_lister (const pid_t pid,
106 gdb::function_view<bool (const struct kinfo_lwp *)>
107 callback)
108{
109 int mib[5] = {CTL_KERN, KERN_LWP, pid, sizeof (struct kinfo_lwp), 0};
110 size_t size;
111
112 if (sysctl (mib, ARRAY_SIZE (mib), NULL, &size, NULL, 0) == -1 || size == 0)
113 perror_with_name (("sysctl"));
114
115 mib[4] = size / sizeof (size_t);
116
117 gdb::unique_xmalloc_ptr<struct kinfo_lwp[]> kl
118 ((struct kinfo_lwp *) xcalloc (size, 1));
119
120 if (sysctl (mib, ARRAY_SIZE (mib), kl.get (), &size, NULL, 0) == -1
121 || size == 0)
122 perror_with_name (("sysctl"));
123
124 for (size_t i = 0; i < size / sizeof (struct kinfo_lwp); i++)
125 {
126 struct kinfo_lwp *l = &kl[i];
127
128 /* Return true if the specified thread is alive. */
129 auto lwp_alive
130 = [] (struct kinfo_lwp *lwp)
131 {
132 switch (lwp->l_stat)
133 {
134 case LSSLEEP:
135 case LSRUN:
136 case LSONPROC:
137 case LSSTOP:
138 case LSSUSPENDED:
139 return true;
140 default:
141 return false;
142 }
143 };
144
145 /* Ignore embryonic or demised threads. */
146 if (!lwp_alive (l))
147 continue;
148
149 if (callback (l))
150 return true;
151 }
152
153 return false;
154}
155
156/* Return true if PTID is still active in the inferior. */
157
158bool
159nbsd_nat_target::thread_alive (ptid_t ptid)
160{
161 pid_t pid = ptid.pid ();
162 int lwp = ptid.lwp ();
163
164 auto fn
165 = [&lwp] (const struct kinfo_lwp *kl)
166 {
167 return kl->l_lid == lwp;
168 };
169
170 return nbsd_thread_lister (pid, fn);
171}
172
173/* Return the name assigned to a thread by an application. Returns
174 the string in a static buffer. */
175
176const char *
177nbsd_nat_target::thread_name (struct thread_info *thr)
178{
179 ptid_t ptid = thr->ptid;
180 pid_t pid = ptid.pid ();
181 int lwp = ptid.lwp ();
182
183 static char buf[KI_LNAMELEN] = {};
184
185 auto fn
186 = [&lwp] (const struct kinfo_lwp *kl)
187 {
188 if (kl->l_lid == lwp)
189 {
190 xsnprintf (buf, sizeof buf, "%s", kl->l_name);
191 return true;
192 }
193 return false;
194 };
195
196 if (nbsd_thread_lister (pid, fn))
197 return buf;
198 else
199 return NULL;
200}
201
202/* Implement the "post_attach" target_ops method. */
203
204static void
205nbsd_add_threads (nbsd_nat_target *target, pid_t pid)
206{
207 auto fn
208 = [&target, &pid] (const struct kinfo_lwp *kl)
209 {
210 ptid_t ptid = ptid_t (pid, kl->l_lid, 0);
211 if (!in_thread_list (target, ptid))
212 {
213 if (inferior_ptid.lwp () == 0)
214 thread_change_ptid (target, inferior_ptid, ptid);
215 else
216 add_thread (target, ptid);
217 }
218 return false;
219 };
220
221 nbsd_thread_lister (pid, fn);
222}
223
224/* Implement the "post_attach" target_ops method. */
225
226void
227nbsd_nat_target::post_attach (int pid)
228{
229 nbsd_add_threads (this, pid);
230}
231
232/* Implement the "update_thread_list" target_ops method. */
233
234void
235nbsd_nat_target::update_thread_list ()
236{
237 prune_threads ();
238
239 nbsd_add_threads (this, inferior_ptid.pid ());
240}
241
242/* Convert PTID to a string. */
243
244std::string
245nbsd_nat_target::pid_to_str (ptid_t ptid)
246{
247 int lwp = ptid.lwp ();
248
249 if (lwp != 0)
250 {
251 pid_t pid = ptid.pid ();
252
253 return string_printf ("LWP %d of process %d", lwp, pid);
254 }
255
256 return normal_pid_to_str (ptid);
257}
54b8cbd0
KR
258
259/* Retrieve all the memory regions in the specified process. */
260
261static gdb::unique_xmalloc_ptr<struct kinfo_vmentry[]>
262nbsd_kinfo_get_vmmap (pid_t pid, size_t *size)
263{
264 int mib[5] = {CTL_VM, VM_PROC, VM_PROC_MAP, pid,
265 sizeof (struct kinfo_vmentry)};
266
267 size_t length = 0;
268 if (sysctl (mib, ARRAY_SIZE (mib), NULL, &length, NULL, 0))
269 {
270 *size = 0;
271 return NULL;
272 }
273
274 /* Prereserve more space. The length argument is volatile and can change
275 between the sysctl(3) calls as this function can be called against a
276 running process. */
277 length = length * 5 / 3;
278
279 gdb::unique_xmalloc_ptr<struct kinfo_vmentry[]> kiv
280 (XNEWVAR (kinfo_vmentry, length));
281
282 if (sysctl (mib, ARRAY_SIZE (mib), kiv.get (), &length, NULL, 0))
283 {
284 *size = 0;
285 return NULL;
286 }
287
288 *size = length / sizeof (struct kinfo_vmentry);
289 return kiv;
290}
291
292/* Iterate over all the memory regions in the current inferior,
293 calling FUNC for each memory region. OBFD is passed as the last
294 argument to FUNC. */
295
296int
297nbsd_nat_target::find_memory_regions (find_memory_region_ftype func,
298 void *data)
299{
300 pid_t pid = inferior_ptid.pid ();
301
302 size_t nitems;
303 gdb::unique_xmalloc_ptr<struct kinfo_vmentry[]> vmentl
304 = nbsd_kinfo_get_vmmap (pid, &nitems);
305 if (vmentl == NULL)
306 perror_with_name (_("Couldn't fetch VM map entries."));
307
308 for (size_t i = 0; i < nitems; i++)
309 {
310 struct kinfo_vmentry *kve = &vmentl[i];
311
312 /* Skip unreadable segments and those where MAP_NOCORE has been set. */
313 if (!(kve->kve_protection & KVME_PROT_READ)
314 || kve->kve_flags & KVME_FLAG_NOCOREDUMP)
315 continue;
316
317 /* Skip segments with an invalid type. */
318 switch (kve->kve_type)
319 {
320 case KVME_TYPE_VNODE:
321 case KVME_TYPE_ANON:
322 case KVME_TYPE_SUBMAP:
323 case KVME_TYPE_OBJECT:
324 break;
325 default:
326 continue;
327 }
328
329 size_t size = kve->kve_end - kve->kve_start;
330 if (info_verbose)
331 {
332 fprintf_filtered (gdb_stdout,
333 "Save segment, %ld bytes at %s (%c%c%c)\n",
334 (long) size,
335 paddress (target_gdbarch (), kve->kve_start),
336 kve->kve_protection & KVME_PROT_READ ? 'r' : '-',
337 kve->kve_protection & KVME_PROT_WRITE ? 'w' : '-',
338 kve->kve_protection & KVME_PROT_EXEC ? 'x' : '-');
339 }
340
341 /* Invoke the callback function to create the corefile segment.
342 Pass MODIFIED as true, we do not know the real modification state. */
343 func (kve->kve_start, size, kve->kve_protection & KVME_PROT_READ,
344 kve->kve_protection & KVME_PROT_WRITE,
345 kve->kve_protection & KVME_PROT_EXEC, 1, data);
346 }
347 return 0;
348}
349
350/* Implement the "info_proc" target_ops method. */
351
352bool
353nbsd_nat_target::info_proc (const char *args, enum info_proc_what what)
354{
355 pid_t pid;
49d1d1f5 356 bool do_cmdline = false;
b4848d2a 357 bool do_cwd = false;
51c133d5 358 bool do_exe = false;
54b8cbd0 359 bool do_mappings = false;
06ca5dd4 360 bool do_status = false;
54b8cbd0
KR
361
362 switch (what)
363 {
1085dfd4
KR
364 case IP_MINIMAL:
365 do_cmdline = true;
366 do_cwd = true;
367 do_exe = true;
368 break;
06ca5dd4
KR
369 case IP_STAT:
370 case IP_STATUS:
371 do_status = true;
372 break;
54b8cbd0
KR
373 case IP_MAPPINGS:
374 do_mappings = true;
375 break;
49d1d1f5
KR
376 case IP_CMDLINE:
377 do_cmdline = true;
378 break;
51c133d5
KR
379 case IP_EXE:
380 do_exe = true;
381 break;
b4848d2a
KR
382 case IP_CWD:
383 do_cwd = true;
384 break;
1085dfd4
KR
385 case IP_ALL:
386 do_cmdline = true;
387 do_cwd = true;
388 do_exe = true;
389 do_mappings = true;
06ca5dd4 390 do_status = true;
1085dfd4 391 break;
54b8cbd0
KR
392 default:
393 error (_("Not supported on this target."));
394 }
395
396 gdb_argv built_argv (args);
397 if (built_argv.count () == 0)
398 {
399 pid = inferior_ptid.pid ();
400 if (pid == 0)
401 error (_("No current process: you must name one."));
402 }
403 else if (built_argv.count () == 1 && isdigit (built_argv[0][0]))
404 pid = strtol (built_argv[0], NULL, 10);
405 else
406 error (_("Invalid arguments."));
407
408 printf_filtered (_("process %d\n"), pid);
409
49d1d1f5
KR
410 if (do_cmdline)
411 {
412 gdb::unique_xmalloc_ptr<char[]> cmdline = nbsd_pid_to_cmdline (pid);
413 if (cmdline != nullptr)
414 printf_filtered ("cmdline = '%s'\n", cmdline.get ());
415 else
416 warning (_("unable to fetch command line"));
417 }
b4848d2a
KR
418 if (do_cwd)
419 {
420 std::string cwd = nbsd_pid_to_cwd (pid);
421 if (cwd != "")
422 printf_filtered ("cwd = '%s'\n", cwd.c_str ());
423 else
424 warning (_("unable to fetch current working directory"));
425 }
51c133d5
KR
426 if (do_exe)
427 {
428 const char *exe = pid_to_exec_file (pid);
429 if (exe != nullptr)
430 printf_filtered ("exe = '%s'\n", exe);
431 else
432 warning (_("unable to fetch executable path name"));
433 }
54b8cbd0
KR
434 if (do_mappings)
435 {
436 size_t nvment;
437 gdb::unique_xmalloc_ptr<struct kinfo_vmentry[]> vmentl
438 = nbsd_kinfo_get_vmmap (pid, &nvment);
439
440 if (vmentl != nullptr)
441 {
442 int addr_bit = TARGET_CHAR_BIT * sizeof (void *);
443 nbsd_info_proc_mappings_header (addr_bit);
444
445 struct kinfo_vmentry *kve = vmentl.get ();
446 for (int i = 0; i < nvment; i++, kve++)
447 nbsd_info_proc_mappings_entry (addr_bit, kve->kve_start,
448 kve->kve_end, kve->kve_offset,
449 kve->kve_flags, kve->kve_protection,
450 kve->kve_path);
451 }
452 else
453 warning (_("unable to fetch virtual memory map"));
454 }
06ca5dd4
KR
455 if (do_status)
456 {
457 struct kinfo_proc2 kp;
458 if (!nbsd_pid_to_kinfo_proc2 (pid, &kp))
459 warning (_("Failed to fetch process information"));
460 else
461 {
462 auto process_status
463 = [] (int8_t stat)
464 {
465 switch (stat)
466 {
467 case SIDL:
468 return "IDL";
469 case SACTIVE:
470 return "ACTIVE";
471 case SDYING:
472 return "DYING";
473 case SSTOP:
474 return "STOP";
475 case SZOMB:
476 return "ZOMB";
477 case SDEAD:
478 return "DEAD";
479 default:
480 return "? (unknown)";
481 }
482 };
483
484 printf_filtered ("Name: %s\n", kp.p_comm);
485 printf_filtered ("State: %s\n", process_status(kp.p_realstat));
486 printf_filtered ("Parent process: %" PRId32 "\n", kp.p_ppid);
487 printf_filtered ("Process group: %" PRId32 "\n", kp.p__pgid);
488 printf_filtered ("Session id: %" PRId32 "\n", kp.p_sid);
489 printf_filtered ("TTY: %" PRId32 "\n", kp.p_tdev);
490 printf_filtered ("TTY owner process group: %" PRId32 "\n", kp.p_tpgid);
491 printf_filtered ("User IDs (real, effective, saved): "
492 "%" PRIu32 " %" PRIu32 " %" PRIu32 "\n",
493 kp.p_ruid, kp.p_uid, kp.p_svuid);
494 printf_filtered ("Group IDs (real, effective, saved): "
495 "%" PRIu32 " %" PRIu32 " %" PRIu32 "\n",
496 kp.p_rgid, kp.p_gid, kp.p_svgid);
497
498 printf_filtered ("Groups:");
499 for (int i = 0; i < kp.p_ngroups; i++)
500 printf_filtered (" %" PRIu32, kp.p_groups[i]);
501 printf_filtered ("\n");
502 printf_filtered ("Minor faults (no memory page): %" PRIu64 "\n",
503 kp.p_uru_minflt);
504 printf_filtered ("Major faults (memory page faults): %" PRIu64 "\n",
505 kp.p_uru_majflt);
506 printf_filtered ("utime: %" PRIu32 ".%06" PRIu32 "\n",
507 kp.p_uutime_sec, kp.p_uutime_usec);
508 printf_filtered ("stime: %" PRIu32 ".%06" PRIu32 "\n",
509 kp.p_ustime_sec, kp.p_ustime_usec);
510 printf_filtered ("utime+stime, children: %" PRIu32 ".%06" PRIu32 "\n",
511 kp.p_uctime_sec, kp.p_uctime_usec);
512 printf_filtered ("'nice' value: %" PRIu8 "\n", kp.p_nice);
513 printf_filtered ("Start time: %" PRIu32 ".%06" PRIu32 "\n",
514 kp.p_ustart_sec, kp.p_ustart_usec);
515 int pgtok = getpagesize () / 1024;
516 printf_filtered ("Data size: %" PRIuMAX " kB\n",
517 (uintmax_t) kp.p_vm_dsize * pgtok);
518 printf_filtered ("Stack size: %" PRIuMAX " kB\n",
519 (uintmax_t) kp.p_vm_ssize * pgtok);
520 printf_filtered ("Text size: %" PRIuMAX " kB\n",
521 (uintmax_t) kp.p_vm_tsize * pgtok);
522 printf_filtered ("Resident set size: %" PRIuMAX " kB\n",
523 (uintmax_t) kp.p_vm_rssize * pgtok);
524 printf_filtered ("Maximum RSS: %" PRIu64 " kB\n", kp.p_uru_maxrss);
525 printf_filtered ("Pending Signals:");
526 for (size_t i = 0; i < ARRAY_SIZE (kp.p_siglist.__bits); i++)
527 printf_filtered (" %08" PRIx32, kp.p_siglist.__bits[i]);
528 printf_filtered ("\n");
529 printf_filtered ("Ignored Signals:");
530 for (size_t i = 0; i < ARRAY_SIZE (kp.p_sigignore.__bits); i++)
531 printf_filtered (" %08" PRIx32, kp.p_sigignore.__bits[i]);
532 printf_filtered ("\n");
533 printf_filtered ("Caught Signals:");
534 for (size_t i = 0; i < ARRAY_SIZE (kp.p_sigcatch.__bits); i++)
535 printf_filtered (" %08" PRIx32, kp.p_sigcatch.__bits[i]);
536 printf_filtered ("\n");
537 }
538 }
54b8cbd0
KR
539
540 return true;
541}
This page took 1.21895 seconds and 4 git commands to generate.