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 | 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> | |
f94b2e03 | 31 | #include <sys/wait.h> |
a2ecbe9f | 32 | |
766062f6 | 33 | /* Return the name of a file that can be opened to get the symbols for |
84c5b489 MK |
34 | the child process identified by PID. */ |
35 | ||
36 | char * | |
f6ac5f3d | 37 | nbsd_nat_target::pid_to_exec_file (int pid) |
84c5b489 | 38 | { |
b4ab256d | 39 | static char buf[PATH_MAX]; |
a2ecbe9f KR |
40 | size_t buflen; |
41 | int mib[4] = {CTL_KERN, KERN_PROC_ARGS, pid, KERN_PROC_PATHNAME}; | |
42 | buflen = sizeof (buf); | |
43 | if (sysctl (mib, ARRAY_SIZE (mib), buf, &buflen, NULL, 0)) | |
44 | return NULL; | |
45 | return buf; | |
84c5b489 | 46 | } |
05f00e22 | 47 | |
b4848d2a KR |
48 | /* Return the current directory for the process identified by PID. */ |
49 | ||
50 | static std::string | |
51 | nbsd_pid_to_cwd (int pid) | |
52 | { | |
53 | char buf[PATH_MAX]; | |
54 | size_t buflen; | |
55 | int mib[4] = {CTL_KERN, KERN_PROC_ARGS, pid, KERN_PROC_CWD}; | |
56 | buflen = sizeof (buf); | |
57 | if (sysctl (mib, ARRAY_SIZE (mib), buf, &buflen, NULL, 0)) | |
58 | return ""; | |
59 | return buf; | |
60 | } | |
61 | ||
06ca5dd4 KR |
62 | /* Return the kinfo_proc2 structure for the process identified by PID. */ |
63 | ||
64 | static bool | |
65 | nbsd_pid_to_kinfo_proc2 (pid_t pid, struct kinfo_proc2 *kp) | |
66 | { | |
67 | gdb_assert (kp != nullptr); | |
68 | ||
69 | size_t size = sizeof (*kp); | |
70 | int mib[6] = {CTL_KERN, KERN_PROC2, KERN_PROC_PID, pid, | |
71 | static_cast<int> (size), 1}; | |
72 | return !sysctl (mib, ARRAY_SIZE (mib), kp, &size, NULL, 0); | |
73 | } | |
74 | ||
49d1d1f5 KR |
75 | /* Return the command line for the process identified by PID. */ |
76 | ||
77 | static gdb::unique_xmalloc_ptr<char[]> | |
78 | nbsd_pid_to_cmdline (int pid) | |
79 | { | |
80 | int mib[4] = {CTL_KERN, KERN_PROC_ARGS, pid, KERN_PROC_ARGV}; | |
81 | ||
82 | size_t size = 0; | |
83 | if (sysctl (mib, ARRAY_SIZE (mib), NULL, &size, NULL, 0) == -1 || size == 0) | |
84 | return nullptr; | |
85 | ||
86 | gdb::unique_xmalloc_ptr<char[]> args (XNEWVAR (char, size)); | |
87 | ||
88 | if (sysctl (mib, ARRAY_SIZE (mib), args.get (), &size, NULL, 0) == -1 | |
89 | || size == 0) | |
90 | return nullptr; | |
91 | ||
92 | /* Arguments are returned as a flattened string with NUL separators. | |
93 | Join the arguments with spaces to form a single string. */ | |
94 | for (size_t i = 0; i < size - 1; i++) | |
95 | if (args[i] == '\0') | |
96 | args[i] = ' '; | |
97 | args[size - 1] = '\0'; | |
98 | ||
99 | return args; | |
100 | } | |
101 | ||
05f00e22 KR |
102 | /* Generic thread (LWP) lister within a specified process. The callback |
103 | parameters is a C++ function that is called for each detected thread. */ | |
104 | ||
105 | static bool | |
106 | nbsd_thread_lister (const pid_t pid, | |
107 | gdb::function_view<bool (const struct kinfo_lwp *)> | |
108 | callback) | |
109 | { | |
110 | int mib[5] = {CTL_KERN, KERN_LWP, pid, sizeof (struct kinfo_lwp), 0}; | |
111 | size_t size; | |
112 | ||
113 | if (sysctl (mib, ARRAY_SIZE (mib), NULL, &size, NULL, 0) == -1 || size == 0) | |
114 | perror_with_name (("sysctl")); | |
115 | ||
116 | mib[4] = size / sizeof (size_t); | |
117 | ||
118 | gdb::unique_xmalloc_ptr<struct kinfo_lwp[]> kl | |
119 | ((struct kinfo_lwp *) xcalloc (size, 1)); | |
120 | ||
121 | if (sysctl (mib, ARRAY_SIZE (mib), kl.get (), &size, NULL, 0) == -1 | |
122 | || size == 0) | |
123 | perror_with_name (("sysctl")); | |
124 | ||
125 | for (size_t i = 0; i < size / sizeof (struct kinfo_lwp); i++) | |
126 | { | |
127 | struct kinfo_lwp *l = &kl[i]; | |
128 | ||
129 | /* Return true if the specified thread is alive. */ | |
130 | auto lwp_alive | |
131 | = [] (struct kinfo_lwp *lwp) | |
132 | { | |
133 | switch (lwp->l_stat) | |
134 | { | |
135 | case LSSLEEP: | |
136 | case LSRUN: | |
137 | case LSONPROC: | |
138 | case LSSTOP: | |
139 | case LSSUSPENDED: | |
140 | return true; | |
141 | default: | |
142 | return false; | |
143 | } | |
144 | }; | |
145 | ||
146 | /* Ignore embryonic or demised threads. */ | |
147 | if (!lwp_alive (l)) | |
148 | continue; | |
149 | ||
150 | if (callback (l)) | |
151 | return true; | |
152 | } | |
153 | ||
154 | return false; | |
155 | } | |
156 | ||
157 | /* Return true if PTID is still active in the inferior. */ | |
158 | ||
159 | bool | |
160 | nbsd_nat_target::thread_alive (ptid_t ptid) | |
161 | { | |
162 | pid_t pid = ptid.pid (); | |
163 | int lwp = ptid.lwp (); | |
164 | ||
165 | auto fn | |
166 | = [&lwp] (const struct kinfo_lwp *kl) | |
167 | { | |
168 | return kl->l_lid == lwp; | |
169 | }; | |
170 | ||
171 | return nbsd_thread_lister (pid, fn); | |
172 | } | |
173 | ||
174 | /* Return the name assigned to a thread by an application. Returns | |
175 | the string in a static buffer. */ | |
176 | ||
177 | const char * | |
178 | nbsd_nat_target::thread_name (struct thread_info *thr) | |
179 | { | |
180 | ptid_t ptid = thr->ptid; | |
181 | pid_t pid = ptid.pid (); | |
182 | int lwp = ptid.lwp (); | |
183 | ||
184 | static char buf[KI_LNAMELEN] = {}; | |
185 | ||
186 | auto fn | |
187 | = [&lwp] (const struct kinfo_lwp *kl) | |
188 | { | |
189 | if (kl->l_lid == lwp) | |
190 | { | |
191 | xsnprintf (buf, sizeof buf, "%s", kl->l_name); | |
192 | return true; | |
193 | } | |
194 | return false; | |
195 | }; | |
196 | ||
197 | if (nbsd_thread_lister (pid, fn)) | |
198 | return buf; | |
199 | else | |
200 | return NULL; | |
201 | } | |
202 | ||
203 | /* Implement the "post_attach" target_ops method. */ | |
204 | ||
205 | static void | |
206 | nbsd_add_threads (nbsd_nat_target *target, pid_t pid) | |
207 | { | |
208 | auto fn | |
209 | = [&target, &pid] (const struct kinfo_lwp *kl) | |
210 | { | |
211 | ptid_t ptid = ptid_t (pid, kl->l_lid, 0); | |
212 | if (!in_thread_list (target, ptid)) | |
213 | { | |
214 | if (inferior_ptid.lwp () == 0) | |
215 | thread_change_ptid (target, inferior_ptid, ptid); | |
216 | else | |
217 | add_thread (target, ptid); | |
218 | } | |
219 | return false; | |
220 | }; | |
221 | ||
222 | nbsd_thread_lister (pid, fn); | |
223 | } | |
224 | ||
117539e6 KR |
225 | /* Enable additional event reporting on new processes. */ |
226 | ||
227 | static void | |
228 | nbsd_enable_proc_events (pid_t pid) | |
229 | { | |
230 | int events; | |
231 | ||
232 | if (ptrace (PT_GET_EVENT_MASK, pid, &events, sizeof (events)) == -1) | |
233 | perror_with_name (("ptrace")); | |
234 | ||
235 | events |= PTRACE_LWP_CREATE; | |
236 | events |= PTRACE_LWP_EXIT; | |
237 | ||
238 | if (ptrace (PT_SET_EVENT_MASK, pid, &events, sizeof (events)) == -1) | |
239 | perror_with_name (("ptrace")); | |
240 | } | |
241 | ||
242 | /* Implement the "post_startup_inferior" target_ops method. */ | |
243 | ||
244 | void | |
245 | nbsd_nat_target::post_startup_inferior (ptid_t ptid) | |
246 | { | |
247 | nbsd_enable_proc_events (ptid.pid ()); | |
248 | } | |
249 | ||
05f00e22 KR |
250 | /* Implement the "post_attach" target_ops method. */ |
251 | ||
252 | void | |
253 | nbsd_nat_target::post_attach (int pid) | |
254 | { | |
117539e6 | 255 | nbsd_enable_proc_events (pid); |
05f00e22 KR |
256 | nbsd_add_threads (this, pid); |
257 | } | |
258 | ||
259 | /* Implement the "update_thread_list" target_ops method. */ | |
260 | ||
261 | void | |
262 | nbsd_nat_target::update_thread_list () | |
263 | { | |
117539e6 | 264 | delete_exited_threads (); |
05f00e22 KR |
265 | } |
266 | ||
267 | /* Convert PTID to a string. */ | |
268 | ||
269 | std::string | |
270 | nbsd_nat_target::pid_to_str (ptid_t ptid) | |
271 | { | |
272 | int lwp = ptid.lwp (); | |
273 | ||
274 | if (lwp != 0) | |
275 | { | |
276 | pid_t pid = ptid.pid (); | |
277 | ||
278 | return string_printf ("LWP %d of process %d", lwp, pid); | |
279 | } | |
280 | ||
281 | return normal_pid_to_str (ptid); | |
282 | } | |
54b8cbd0 KR |
283 | |
284 | /* Retrieve all the memory regions in the specified process. */ | |
285 | ||
286 | static gdb::unique_xmalloc_ptr<struct kinfo_vmentry[]> | |
287 | nbsd_kinfo_get_vmmap (pid_t pid, size_t *size) | |
288 | { | |
289 | int mib[5] = {CTL_VM, VM_PROC, VM_PROC_MAP, pid, | |
290 | sizeof (struct kinfo_vmentry)}; | |
291 | ||
292 | size_t length = 0; | |
293 | if (sysctl (mib, ARRAY_SIZE (mib), NULL, &length, NULL, 0)) | |
294 | { | |
295 | *size = 0; | |
296 | return NULL; | |
297 | } | |
298 | ||
299 | /* Prereserve more space. The length argument is volatile and can change | |
300 | between the sysctl(3) calls as this function can be called against a | |
301 | running process. */ | |
302 | length = length * 5 / 3; | |
303 | ||
304 | gdb::unique_xmalloc_ptr<struct kinfo_vmentry[]> kiv | |
305 | (XNEWVAR (kinfo_vmentry, length)); | |
306 | ||
307 | if (sysctl (mib, ARRAY_SIZE (mib), kiv.get (), &length, NULL, 0)) | |
308 | { | |
309 | *size = 0; | |
310 | return NULL; | |
311 | } | |
312 | ||
313 | *size = length / sizeof (struct kinfo_vmentry); | |
314 | return kiv; | |
315 | } | |
316 | ||
317 | /* Iterate over all the memory regions in the current inferior, | |
318 | calling FUNC for each memory region. OBFD is passed as the last | |
319 | argument to FUNC. */ | |
320 | ||
321 | int | |
322 | nbsd_nat_target::find_memory_regions (find_memory_region_ftype func, | |
323 | void *data) | |
324 | { | |
325 | pid_t pid = inferior_ptid.pid (); | |
326 | ||
327 | size_t nitems; | |
328 | gdb::unique_xmalloc_ptr<struct kinfo_vmentry[]> vmentl | |
329 | = nbsd_kinfo_get_vmmap (pid, &nitems); | |
330 | if (vmentl == NULL) | |
331 | perror_with_name (_("Couldn't fetch VM map entries.")); | |
332 | ||
333 | for (size_t i = 0; i < nitems; i++) | |
334 | { | |
335 | struct kinfo_vmentry *kve = &vmentl[i]; | |
336 | ||
337 | /* Skip unreadable segments and those where MAP_NOCORE has been set. */ | |
338 | if (!(kve->kve_protection & KVME_PROT_READ) | |
339 | || kve->kve_flags & KVME_FLAG_NOCOREDUMP) | |
340 | continue; | |
341 | ||
342 | /* Skip segments with an invalid type. */ | |
343 | switch (kve->kve_type) | |
344 | { | |
345 | case KVME_TYPE_VNODE: | |
346 | case KVME_TYPE_ANON: | |
347 | case KVME_TYPE_SUBMAP: | |
348 | case KVME_TYPE_OBJECT: | |
349 | break; | |
350 | default: | |
351 | continue; | |
352 | } | |
353 | ||
354 | size_t size = kve->kve_end - kve->kve_start; | |
355 | if (info_verbose) | |
356 | { | |
357 | fprintf_filtered (gdb_stdout, | |
358 | "Save segment, %ld bytes at %s (%c%c%c)\n", | |
359 | (long) size, | |
360 | paddress (target_gdbarch (), kve->kve_start), | |
361 | kve->kve_protection & KVME_PROT_READ ? 'r' : '-', | |
362 | kve->kve_protection & KVME_PROT_WRITE ? 'w' : '-', | |
363 | kve->kve_protection & KVME_PROT_EXEC ? 'x' : '-'); | |
364 | } | |
365 | ||
366 | /* Invoke the callback function to create the corefile segment. | |
367 | Pass MODIFIED as true, we do not know the real modification state. */ | |
368 | func (kve->kve_start, size, kve->kve_protection & KVME_PROT_READ, | |
369 | kve->kve_protection & KVME_PROT_WRITE, | |
370 | kve->kve_protection & KVME_PROT_EXEC, 1, data); | |
371 | } | |
372 | return 0; | |
373 | } | |
374 | ||
375 | /* Implement the "info_proc" target_ops method. */ | |
376 | ||
377 | bool | |
378 | nbsd_nat_target::info_proc (const char *args, enum info_proc_what what) | |
379 | { | |
380 | pid_t pid; | |
49d1d1f5 | 381 | bool do_cmdline = false; |
b4848d2a | 382 | bool do_cwd = false; |
51c133d5 | 383 | bool do_exe = false; |
54b8cbd0 | 384 | bool do_mappings = false; |
06ca5dd4 | 385 | bool do_status = false; |
54b8cbd0 KR |
386 | |
387 | switch (what) | |
388 | { | |
1085dfd4 KR |
389 | case IP_MINIMAL: |
390 | do_cmdline = true; | |
391 | do_cwd = true; | |
392 | do_exe = true; | |
393 | break; | |
06ca5dd4 KR |
394 | case IP_STAT: |
395 | case IP_STATUS: | |
396 | do_status = true; | |
397 | break; | |
54b8cbd0 KR |
398 | case IP_MAPPINGS: |
399 | do_mappings = true; | |
400 | break; | |
49d1d1f5 KR |
401 | case IP_CMDLINE: |
402 | do_cmdline = true; | |
403 | break; | |
51c133d5 KR |
404 | case IP_EXE: |
405 | do_exe = true; | |
406 | break; | |
b4848d2a KR |
407 | case IP_CWD: |
408 | do_cwd = true; | |
409 | break; | |
1085dfd4 KR |
410 | case IP_ALL: |
411 | do_cmdline = true; | |
412 | do_cwd = true; | |
413 | do_exe = true; | |
414 | do_mappings = true; | |
06ca5dd4 | 415 | do_status = true; |
1085dfd4 | 416 | break; |
54b8cbd0 KR |
417 | default: |
418 | error (_("Not supported on this target.")); | |
419 | } | |
420 | ||
421 | gdb_argv built_argv (args); | |
422 | if (built_argv.count () == 0) | |
423 | { | |
424 | pid = inferior_ptid.pid (); | |
425 | if (pid == 0) | |
426 | error (_("No current process: you must name one.")); | |
427 | } | |
428 | else if (built_argv.count () == 1 && isdigit (built_argv[0][0])) | |
429 | pid = strtol (built_argv[0], NULL, 10); | |
430 | else | |
431 | error (_("Invalid arguments.")); | |
432 | ||
433 | printf_filtered (_("process %d\n"), pid); | |
434 | ||
49d1d1f5 KR |
435 | if (do_cmdline) |
436 | { | |
437 | gdb::unique_xmalloc_ptr<char[]> cmdline = nbsd_pid_to_cmdline (pid); | |
438 | if (cmdline != nullptr) | |
439 | printf_filtered ("cmdline = '%s'\n", cmdline.get ()); | |
440 | else | |
441 | warning (_("unable to fetch command line")); | |
442 | } | |
b4848d2a KR |
443 | if (do_cwd) |
444 | { | |
445 | std::string cwd = nbsd_pid_to_cwd (pid); | |
446 | if (cwd != "") | |
447 | printf_filtered ("cwd = '%s'\n", cwd.c_str ()); | |
448 | else | |
449 | warning (_("unable to fetch current working directory")); | |
450 | } | |
51c133d5 KR |
451 | if (do_exe) |
452 | { | |
453 | const char *exe = pid_to_exec_file (pid); | |
454 | if (exe != nullptr) | |
455 | printf_filtered ("exe = '%s'\n", exe); | |
456 | else | |
457 | warning (_("unable to fetch executable path name")); | |
458 | } | |
54b8cbd0 KR |
459 | if (do_mappings) |
460 | { | |
461 | size_t nvment; | |
462 | gdb::unique_xmalloc_ptr<struct kinfo_vmentry[]> vmentl | |
463 | = nbsd_kinfo_get_vmmap (pid, &nvment); | |
464 | ||
465 | if (vmentl != nullptr) | |
466 | { | |
467 | int addr_bit = TARGET_CHAR_BIT * sizeof (void *); | |
468 | nbsd_info_proc_mappings_header (addr_bit); | |
469 | ||
470 | struct kinfo_vmentry *kve = vmentl.get (); | |
471 | for (int i = 0; i < nvment; i++, kve++) | |
472 | nbsd_info_proc_mappings_entry (addr_bit, kve->kve_start, | |
473 | kve->kve_end, kve->kve_offset, | |
474 | kve->kve_flags, kve->kve_protection, | |
475 | kve->kve_path); | |
476 | } | |
477 | else | |
478 | warning (_("unable to fetch virtual memory map")); | |
479 | } | |
06ca5dd4 KR |
480 | if (do_status) |
481 | { | |
482 | struct kinfo_proc2 kp; | |
483 | if (!nbsd_pid_to_kinfo_proc2 (pid, &kp)) | |
484 | warning (_("Failed to fetch process information")); | |
485 | else | |
486 | { | |
487 | auto process_status | |
488 | = [] (int8_t stat) | |
489 | { | |
490 | switch (stat) | |
491 | { | |
492 | case SIDL: | |
493 | return "IDL"; | |
494 | case SACTIVE: | |
495 | return "ACTIVE"; | |
496 | case SDYING: | |
497 | return "DYING"; | |
498 | case SSTOP: | |
499 | return "STOP"; | |
500 | case SZOMB: | |
501 | return "ZOMB"; | |
502 | case SDEAD: | |
503 | return "DEAD"; | |
504 | default: | |
505 | return "? (unknown)"; | |
506 | } | |
507 | }; | |
508 | ||
509 | printf_filtered ("Name: %s\n", kp.p_comm); | |
510 | printf_filtered ("State: %s\n", process_status(kp.p_realstat)); | |
511 | printf_filtered ("Parent process: %" PRId32 "\n", kp.p_ppid); | |
512 | printf_filtered ("Process group: %" PRId32 "\n", kp.p__pgid); | |
513 | printf_filtered ("Session id: %" PRId32 "\n", kp.p_sid); | |
514 | printf_filtered ("TTY: %" PRId32 "\n", kp.p_tdev); | |
515 | printf_filtered ("TTY owner process group: %" PRId32 "\n", kp.p_tpgid); | |
516 | printf_filtered ("User IDs (real, effective, saved): " | |
517 | "%" PRIu32 " %" PRIu32 " %" PRIu32 "\n", | |
518 | kp.p_ruid, kp.p_uid, kp.p_svuid); | |
519 | printf_filtered ("Group IDs (real, effective, saved): " | |
520 | "%" PRIu32 " %" PRIu32 " %" PRIu32 "\n", | |
521 | kp.p_rgid, kp.p_gid, kp.p_svgid); | |
522 | ||
523 | printf_filtered ("Groups:"); | |
524 | for (int i = 0; i < kp.p_ngroups; i++) | |
525 | printf_filtered (" %" PRIu32, kp.p_groups[i]); | |
526 | printf_filtered ("\n"); | |
527 | printf_filtered ("Minor faults (no memory page): %" PRIu64 "\n", | |
528 | kp.p_uru_minflt); | |
529 | printf_filtered ("Major faults (memory page faults): %" PRIu64 "\n", | |
530 | kp.p_uru_majflt); | |
531 | printf_filtered ("utime: %" PRIu32 ".%06" PRIu32 "\n", | |
532 | kp.p_uutime_sec, kp.p_uutime_usec); | |
533 | printf_filtered ("stime: %" PRIu32 ".%06" PRIu32 "\n", | |
534 | kp.p_ustime_sec, kp.p_ustime_usec); | |
535 | printf_filtered ("utime+stime, children: %" PRIu32 ".%06" PRIu32 "\n", | |
536 | kp.p_uctime_sec, kp.p_uctime_usec); | |
537 | printf_filtered ("'nice' value: %" PRIu8 "\n", kp.p_nice); | |
538 | printf_filtered ("Start time: %" PRIu32 ".%06" PRIu32 "\n", | |
539 | kp.p_ustart_sec, kp.p_ustart_usec); | |
540 | int pgtok = getpagesize () / 1024; | |
541 | printf_filtered ("Data size: %" PRIuMAX " kB\n", | |
542 | (uintmax_t) kp.p_vm_dsize * pgtok); | |
543 | printf_filtered ("Stack size: %" PRIuMAX " kB\n", | |
544 | (uintmax_t) kp.p_vm_ssize * pgtok); | |
545 | printf_filtered ("Text size: %" PRIuMAX " kB\n", | |
546 | (uintmax_t) kp.p_vm_tsize * pgtok); | |
547 | printf_filtered ("Resident set size: %" PRIuMAX " kB\n", | |
548 | (uintmax_t) kp.p_vm_rssize * pgtok); | |
549 | printf_filtered ("Maximum RSS: %" PRIu64 " kB\n", kp.p_uru_maxrss); | |
550 | printf_filtered ("Pending Signals:"); | |
551 | for (size_t i = 0; i < ARRAY_SIZE (kp.p_siglist.__bits); i++) | |
552 | printf_filtered (" %08" PRIx32, kp.p_siglist.__bits[i]); | |
553 | printf_filtered ("\n"); | |
554 | printf_filtered ("Ignored Signals:"); | |
555 | for (size_t i = 0; i < ARRAY_SIZE (kp.p_sigignore.__bits); i++) | |
556 | printf_filtered (" %08" PRIx32, kp.p_sigignore.__bits[i]); | |
557 | printf_filtered ("\n"); | |
558 | printf_filtered ("Caught Signals:"); | |
559 | for (size_t i = 0; i < ARRAY_SIZE (kp.p_sigcatch.__bits); i++) | |
560 | printf_filtered (" %08" PRIx32, kp.p_sigcatch.__bits[i]); | |
561 | printf_filtered ("\n"); | |
562 | } | |
563 | } | |
54b8cbd0 KR |
564 | |
565 | return true; | |
566 | } | |
f94b2e03 KR |
567 | |
568 | /* Resume execution of a specified PTID, that points to a process or a thread | |
569 | within a process. If one thread is specified, all other threads are | |
570 | suspended. If STEP is nonzero, single-step it. If SIGNAL is nonzero, | |
571 | give it that signal. */ | |
572 | ||
573 | static void | |
574 | nbsd_resume(nbsd_nat_target *target, ptid_t ptid, int step, | |
575 | enum gdb_signal signal) | |
576 | { | |
577 | int request; | |
578 | ||
579 | gdb_assert (minus_one_ptid != ptid); | |
580 | ||
581 | if (ptid.lwp_p ()) | |
582 | { | |
583 | /* If ptid is a specific LWP, suspend all other LWPs in the process. */ | |
584 | inferior *inf = find_inferior_ptid (target, ptid); | |
585 | ||
586 | for (thread_info *tp : inf->non_exited_threads ()) | |
587 | { | |
588 | if (tp->ptid.lwp () == ptid.lwp ()) | |
589 | request = PT_RESUME; | |
590 | else | |
591 | request = PT_SUSPEND; | |
592 | ||
593 | if (ptrace (request, tp->ptid.pid (), NULL, tp->ptid.lwp ()) == -1) | |
594 | perror_with_name (("ptrace")); | |
595 | } | |
596 | } | |
597 | else | |
598 | { | |
599 | /* If ptid is a wildcard, resume all matching threads (they won't run | |
600 | until the process is continued however). */ | |
601 | for (thread_info *tp : all_non_exited_threads (target, ptid)) | |
602 | if (ptrace (PT_RESUME, tp->ptid.pid (), NULL, tp->ptid.lwp ()) == -1) | |
603 | perror_with_name (("ptrace")); | |
604 | } | |
605 | ||
606 | if (step) | |
607 | { | |
608 | for (thread_info *tp : all_non_exited_threads (target, ptid)) | |
609 | if (ptrace (PT_SETSTEP, tp->ptid.pid (), NULL, tp->ptid.lwp ()) == -1) | |
610 | perror_with_name (("ptrace")); | |
611 | } | |
612 | else | |
613 | { | |
614 | for (thread_info *tp : all_non_exited_threads (target, ptid)) | |
615 | if (ptrace (PT_CLEARSTEP, tp->ptid.pid (), NULL, tp->ptid.lwp ()) == -1) | |
616 | perror_with_name (("ptrace")); | |
617 | } | |
618 | ||
619 | if (catch_syscall_enabled () > 0) | |
620 | request = PT_SYSCALL; | |
621 | else | |
622 | request = PT_CONTINUE; | |
623 | ||
624 | /* An address of (void *)1 tells ptrace to continue from | |
625 | where it was. If GDB wanted it to start some other way, we have | |
626 | already written a new program counter value to the child. */ | |
627 | if (ptrace (request, ptid.pid (), (void *)1, gdb_signal_to_host (signal)) == -1) | |
628 | perror_with_name (("ptrace")); | |
629 | } | |
630 | ||
631 | /* Resume execution of thread PTID, or all threads of all inferiors | |
632 | if PTID is -1. If STEP is nonzero, single-step it. If SIGNAL is nonzero, | |
633 | give it that signal. */ | |
634 | ||
635 | void | |
636 | nbsd_nat_target::resume (ptid_t ptid, int step, enum gdb_signal signal) | |
637 | { | |
638 | if (minus_one_ptid != ptid) | |
639 | nbsd_resume (this, ptid, step, signal); | |
640 | else | |
641 | { | |
642 | for (inferior *inf : all_non_exited_inferiors (this)) | |
643 | nbsd_resume (this, ptid_t (inf->pid, 0, 0), step, signal); | |
644 | } | |
645 | } | |
646 | ||
647 | /* Implement a safe wrapper around waitpid(). */ | |
648 | ||
649 | static pid_t | |
650 | nbsd_wait (ptid_t ptid, struct target_waitstatus *ourstatus, int options) | |
651 | { | |
652 | pid_t pid; | |
653 | int status; | |
654 | ||
655 | set_sigint_trap (); | |
656 | ||
657 | do | |
658 | { | |
659 | /* The common code passes WNOHANG that leads to crashes, overwrite it. */ | |
660 | pid = waitpid (ptid.pid (), &status, 0); | |
661 | } | |
662 | while (pid == -1 && errno == EINTR); | |
663 | ||
664 | clear_sigint_trap (); | |
665 | ||
666 | if (pid == -1) | |
667 | perror_with_name (_("Child process unexpectedly missing")); | |
668 | ||
669 | store_waitstatus (ourstatus, status); | |
670 | return pid; | |
671 | } | |
672 | ||
673 | /* Wait for the child specified by PTID to do something. Return the | |
674 | process ID of the child, or MINUS_ONE_PTID in case of error; store | |
675 | the status in *OURSTATUS. */ | |
676 | ||
677 | ptid_t | |
678 | nbsd_nat_target::wait (ptid_t ptid, struct target_waitstatus *ourstatus, | |
679 | int target_options) | |
680 | { | |
681 | pid_t pid = nbsd_wait (ptid, ourstatus, target_options); | |
682 | ptid_t wptid = ptid_t (pid); | |
683 | ||
684 | /* If the child stopped, keep investigating its status. */ | |
685 | if (ourstatus->kind != TARGET_WAITKIND_STOPPED) | |
686 | return wptid; | |
687 | ||
688 | /* Extract the event and thread that received a signal. */ | |
689 | ptrace_siginfo_t psi; | |
690 | if (ptrace (PT_GET_SIGINFO, pid, &psi, sizeof (psi)) == -1) | |
691 | perror_with_name (("ptrace")); | |
692 | ||
693 | /* Pick child's siginfo_t. */ | |
694 | siginfo_t *si = &psi.psi_siginfo; | |
695 | ||
696 | int lwp = psi.psi_lwpid; | |
697 | ||
698 | int signo = si->si_signo; | |
699 | const int code = si->si_code; | |
700 | ||
701 | /* Construct PTID with a specified thread that received the event. | |
702 | If a signal was targeted to the whole process, lwp is 0. */ | |
703 | wptid = ptid_t (pid, lwp, 0); | |
704 | ||
705 | /* Bail out on non-debugger oriented signals.. */ | |
706 | if (signo != SIGTRAP) | |
707 | return wptid; | |
708 | ||
709 | /* Stop examining non-debugger oriented SIGTRAP codes. */ | |
710 | if (code <= SI_USER || code == SI_NOINFO) | |
711 | return wptid; | |
712 | ||
117539e6 KR |
713 | /* Process state for threading events */ |
714 | ptrace_state_t pst = {}; | |
715 | if (code == TRAP_LWP) | |
716 | { | |
717 | if (ptrace (PT_GET_PROCESS_STATE, pid, &pst, sizeof (pst)) == -1) | |
718 | perror_with_name (("ptrace")); | |
719 | } | |
720 | ||
721 | if (code == TRAP_LWP && pst.pe_report_event == PTRACE_LWP_EXIT) | |
722 | { | |
723 | /* If GDB attaches to a multi-threaded process, exiting | |
724 | threads might be skipped during post_attach that | |
725 | have not yet reported their PTRACE_LWP_EXIT event. | |
726 | Ignore exited events for an unknown LWP. */ | |
727 | thread_info *thr = find_thread_ptid (this, wptid); | |
728 | if (thr == nullptr) | |
729 | ourstatus->kind = TARGET_WAITKIND_SPURIOUS; | |
730 | else | |
731 | { | |
732 | ourstatus->kind = TARGET_WAITKIND_THREAD_EXITED; | |
733 | /* NetBSD does not store an LWP exit status. */ | |
734 | ourstatus->value.integer = 0; | |
735 | ||
736 | if (print_thread_events) | |
737 | printf_unfiltered (_("[%s exited]\n"), | |
738 | target_pid_to_str (wptid).c_str ()); | |
739 | delete_thread (thr); | |
740 | } | |
741 | ||
742 | /* The GDB core expects that the rest of the threads are running. */ | |
743 | if (ptrace (PT_CONTINUE, pid, (void *) 1, 0) == -1) | |
744 | perror_with_name (("ptrace")); | |
745 | ||
746 | return wptid; | |
747 | } | |
748 | ||
f94b2e03 KR |
749 | if (in_thread_list (this, ptid_t (pid))) |
750 | thread_change_ptid (this, ptid_t (pid), wptid); | |
751 | ||
117539e6 KR |
752 | if (code == TRAP_LWP && pst.pe_report_event == PTRACE_LWP_CREATE) |
753 | { | |
754 | /* If GDB attaches to a multi-threaded process, newborn | |
755 | threads might be added by nbsd_add_threads that have | |
756 | not yet reported their PTRACE_LWP_CREATE event. Ignore | |
757 | born events for an already-known LWP. */ | |
758 | if (in_thread_list (this, wptid)) | |
759 | ourstatus->kind = TARGET_WAITKIND_SPURIOUS; | |
760 | else | |
761 | { | |
762 | add_thread (this, wptid); | |
763 | ourstatus->kind = TARGET_WAITKIND_THREAD_CREATED; | |
764 | } | |
765 | return wptid; | |
766 | } | |
767 | ||
f94b2e03 KR |
768 | if (code == TRAP_EXEC) |
769 | { | |
770 | ourstatus->kind = TARGET_WAITKIND_EXECD; | |
771 | ourstatus->value.execd_pathname = xstrdup (pid_to_exec_file (pid)); | |
772 | return wptid; | |
773 | } | |
774 | ||
775 | if (code == TRAP_TRACE) | |
776 | { | |
777 | /* Unhandled at this level. */ | |
778 | return wptid; | |
779 | } | |
780 | ||
781 | if (code == TRAP_SCE || code == TRAP_SCX) | |
782 | { | |
783 | int sysnum = si->si_sysnum; | |
784 | ||
785 | if (!catch_syscall_enabled () || !catching_syscall_number (sysnum)) | |
786 | { | |
787 | /* If the core isn't interested in this event, ignore it. */ | |
788 | ourstatus->kind = TARGET_WAITKIND_SPURIOUS; | |
789 | return wptid; | |
790 | } | |
791 | ||
792 | ourstatus->kind = | |
793 | (code == TRAP_SCE) ? TARGET_WAITKIND_SYSCALL_ENTRY : | |
794 | TARGET_WAITKIND_SYSCALL_RETURN; | |
795 | ourstatus->value.syscall_number = sysnum; | |
796 | return wptid; | |
797 | } | |
798 | ||
799 | if (code == TRAP_BRKPT) | |
800 | { | |
801 | /* Unhandled at this level. */ | |
802 | return wptid; | |
803 | } | |
804 | ||
805 | /* Unclassified SIGTRAP event. */ | |
806 | ourstatus->kind = TARGET_WAITKIND_SPURIOUS; | |
807 | return wptid; | |
808 | } | |
809 | ||
810 | /* Implement the "insert_exec_catchpoint" target_ops method. */ | |
811 | ||
812 | int | |
813 | nbsd_nat_target::insert_exec_catchpoint (int pid) | |
814 | { | |
815 | /* Nothing to do. */ | |
816 | return 0; | |
817 | } | |
818 | ||
819 | /* Implement the "remove_exec_catchpoint" target_ops method. */ | |
820 | ||
821 | int | |
822 | nbsd_nat_target::remove_exec_catchpoint (int pid) | |
823 | { | |
824 | /* Nothing to do. */ | |
825 | return 0; | |
826 | } | |
827 | ||
828 | /* Implement the "set_syscall_catchpoint" target_ops method. */ | |
829 | ||
830 | int | |
831 | nbsd_nat_target::set_syscall_catchpoint (int pid, bool needed, | |
832 | int any_count, | |
833 | gdb::array_view<const int> syscall_counts) | |
834 | { | |
835 | /* Ignore the arguments. inf-ptrace.c will use PT_SYSCALL which | |
836 | will catch all system call entries and exits. The system calls | |
837 | are filtered by GDB rather than the kernel. */ | |
838 | return 0; | |
839 | } |