/* Native-dependent code for OpenBSD. Copyright (C) 2012-2023 Free Software Foundation, Inc. This file is part of GDB. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "defs.h" #include "gdbthread.h" #include "inferior.h" #include "target.h" #include #include #include "gdbsupport/gdb_wait.h" #include "inf-ptrace.h" #include "obsd-nat.h" /* OpenBSD 5.2 and later include rthreads which uses a thread model that maps userland threads directly onto kernel threads in a 1:1 fashion. */ std::string obsd_nat_target::pid_to_str (ptid_t ptid) { if (ptid.lwp () != 0) return string_printf ("thread %ld of process %d", ptid.lwp (), ptid.pid ()); return normal_pid_to_str (ptid); } void obsd_nat_target::update_thread_list () { pid_t pid = inferior_ptid.pid (); struct ptrace_thread_state pts; prune_threads (); if (ptrace (PT_GET_THREAD_FIRST, pid, (caddr_t)&pts, sizeof pts) == -1) perror_with_name (("ptrace")); while (pts.pts_tid != -1) { ptid_t ptid = ptid_t (pid, pts.pts_tid, 0); if (!in_thread_list (this, ptid)) { if (inferior_ptid.lwp () == 0) thread_change_ptid (this, inferior_ptid, ptid); else add_thread (this, ptid); } if (ptrace (PT_GET_THREAD_NEXT, pid, (caddr_t)&pts, sizeof pts) == -1) perror_with_name (("ptrace")); } } /* Enable additional event reporting on a new or existing process. */ static void obsd_enable_proc_events (pid_t pid) { ptrace_event_t pe; /* Set the initial event mask. */ memset (&pe, 0, sizeof pe); pe.pe_set_event |= PTRACE_FORK; if (ptrace (PT_SET_EVENT_MASK, pid, (PTRACE_TYPE_ARG3)&pe, sizeof pe) == -1) perror_with_name (("ptrace")); } ptid_t obsd_nat_target::wait (ptid_t ptid, struct target_waitstatus *ourstatus, target_wait_flags options) { ptid_t wptid = inf_ptrace_target::wait (ptid, ourstatus, options); if (ourstatus->kind () == TARGET_WAITKIND_STOPPED) { ptrace_state_t pe; pid_t pid = wptid.pid (); if (ptrace (PT_GET_PROCESS_STATE, pid, (caddr_t)&pe, sizeof pe) == -1) perror_with_name (("ptrace")); wptid = ptid_t (pid, pe.pe_tid, 0); switch (pe.pe_report_event) { case PTRACE_FORK: ourstatus->set_forked (ptid_t (pe.pe_other_pid)); /* Make sure the other end of the fork is stopped too. */ pid_t fpid = waitpid (pe.pe_other_pid, nullptr, 0); if (fpid == -1) perror_with_name (("waitpid")); if (ptrace (PT_GET_PROCESS_STATE, fpid, (caddr_t)&pe, sizeof pe) == -1) perror_with_name (("ptrace")); gdb_assert (pe.pe_report_event == PTRACE_FORK); gdb_assert (pe.pe_other_pid == pid); if (find_inferior_pid (this, fpid) != nullptr) { ourstatus->set_forked (ptid_t (pe.pe_other_pid)); wptid = ptid_t (fpid, pe.pe_tid, 0); } obsd_enable_proc_events (ourstatus->child_ptid ().pid ()); break; } /* Ensure the ptid is updated with an LWP id on the first stop of a process. */ if (!in_thread_list (this, wptid)) { if (in_thread_list (this, ptid_t (pid))) thread_change_ptid (this, ptid_t (pid), wptid); else add_thread (this, wptid); } } return wptid; } void obsd_nat_target::post_attach (int pid) { obsd_enable_proc_events (pid); } /* Implement the virtual inf_ptrace_target::post_startup_inferior method. */ void obsd_nat_target::post_startup_inferior (ptid_t pid) { obsd_enable_proc_events (pid.pid ()); } /* Target hook for follow_fork. */ void obsd_nat_target::follow_fork (inferior *child_inf, ptid_t child_ptid, target_waitkind fork_kind, bool follow_child, bool detach_fork) { inf_ptrace_target::follow_fork (child_inf, child_ptid, fork_kind, follow_child, detach_fork); if (!follow_child && detach_fork) { /* Breakpoints have already been detached from the child by infrun.c. */ if (ptrace (PT_DETACH, child_ptid.pid (), (PTRACE_TYPE_ARG3)1, 0) == -1) perror_with_name (("ptrace")); } } int obsd_nat_target::insert_fork_catchpoint (int pid) { return 0; } int obsd_nat_target::remove_fork_catchpoint (int pid) { return 0; }