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