xref: /netbsd/external/gpl3/gdb/dist/gdb/obsd-nat.c (revision 1424dfb3)
126a53354Schristos /* Native-dependent code for OpenBSD.
226a53354Schristos 
3*1424dfb3Schristos    Copyright (C) 2012-2020 Free Software Foundation, Inc.
426a53354Schristos 
526a53354Schristos    This file is part of GDB.
626a53354Schristos 
726a53354Schristos    This program is free software; you can redistribute it and/or modify
826a53354Schristos    it under the terms of the GNU General Public License as published by
926a53354Schristos    the Free Software Foundation; either version 3 of the License, or
1026a53354Schristos    (at your option) any later version.
1126a53354Schristos 
1226a53354Schristos    This program is distributed in the hope that it will be useful,
1326a53354Schristos    but WITHOUT ANY WARRANTY; without even the implied warranty of
1426a53354Schristos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1526a53354Schristos    GNU General Public License for more details.
1626a53354Schristos 
1726a53354Schristos    You should have received a copy of the GNU General Public License
1826a53354Schristos    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
1926a53354Schristos 
2026a53354Schristos #include "defs.h"
2126a53354Schristos #include "gdbthread.h"
2226a53354Schristos #include "inferior.h"
2326a53354Schristos #include "target.h"
2426a53354Schristos 
2526a53354Schristos #include <sys/types.h>
2626a53354Schristos #include <sys/ptrace.h>
27*1424dfb3Schristos #include "gdbsupport/gdb_wait.h"
2826a53354Schristos 
2926a53354Schristos #include "inf-child.h"
3026a53354Schristos #include "obsd-nat.h"
3126a53354Schristos 
3226a53354Schristos /* OpenBSD 5.2 and later include rthreads which uses a thread model
3326a53354Schristos    that maps userland threads directly onto kernel threads in a 1:1
3426a53354Schristos    fashion.  */
3526a53354Schristos 
3626a53354Schristos #ifdef PT_GET_THREAD_FIRST
3726a53354Schristos 
38*1424dfb3Schristos std::string
pid_to_str(ptid_t ptid)3907163879Schristos obsd_nat_target::pid_to_str (ptid_t ptid)
4026a53354Schristos {
4107163879Schristos   if (ptid.lwp () != 0)
42*1424dfb3Schristos     return string_printf ("thread %ld", ptid.lwp ());
4326a53354Schristos 
4426a53354Schristos   return normal_pid_to_str (ptid);
4526a53354Schristos }
4626a53354Schristos 
4707163879Schristos void
update_thread_list()4807163879Schristos obsd_nat_target::update_thread_list ()
4926a53354Schristos {
5007163879Schristos   pid_t pid = inferior_ptid.pid ();
5126a53354Schristos   struct ptrace_thread_state pts;
5226a53354Schristos 
5326a53354Schristos   prune_threads ();
5426a53354Schristos 
5526a53354Schristos   if (ptrace (PT_GET_THREAD_FIRST, pid, (caddr_t)&pts, sizeof pts) == -1)
5626a53354Schristos     perror_with_name (("ptrace"));
5726a53354Schristos 
5826a53354Schristos   while (pts.pts_tid != -1)
5926a53354Schristos     {
6007163879Schristos       ptid_t ptid = ptid_t (pid, pts.pts_tid, 0);
6126a53354Schristos 
62*1424dfb3Schristos       if (!in_thread_list (this, ptid))
6326a53354Schristos 	{
6407163879Schristos 	  if (inferior_ptid.lwp () == 0)
65*1424dfb3Schristos 	    thread_change_ptid (this, inferior_ptid, ptid);
6626a53354Schristos 	  else
67*1424dfb3Schristos 	    add_thread (this, ptid);
6826a53354Schristos 	}
6926a53354Schristos 
7026a53354Schristos       if (ptrace (PT_GET_THREAD_NEXT, pid, (caddr_t)&pts, sizeof pts) == -1)
7126a53354Schristos 	perror_with_name (("ptrace"));
7226a53354Schristos     }
7326a53354Schristos }
7426a53354Schristos 
7507163879Schristos ptid_t
wait(ptid_t ptid,struct target_waitstatus * ourstatus,int options)7607163879Schristos obsd_nat_target::wait (ptid_t ptid, struct target_waitstatus *ourstatus,
7707163879Schristos 		       int options)
7826a53354Schristos {
7926a53354Schristos   pid_t pid;
8026a53354Schristos   int status, save_errno;
8126a53354Schristos 
8226a53354Schristos   do
8326a53354Schristos     {
8426a53354Schristos       set_sigint_trap ();
8526a53354Schristos 
8626a53354Schristos       do
8726a53354Schristos 	{
8807163879Schristos 	  pid = waitpid (ptid.pid (), &status, 0);
8926a53354Schristos 	  save_errno = errno;
9026a53354Schristos 	}
9126a53354Schristos       while (pid == -1 && errno == EINTR);
9226a53354Schristos 
9326a53354Schristos       clear_sigint_trap ();
9426a53354Schristos 
9526a53354Schristos       if (pid == -1)
9626a53354Schristos 	{
9726a53354Schristos 	  fprintf_unfiltered (gdb_stderr,
9826a53354Schristos 			      _("Child process unexpectedly missing: %s.\n"),
9926a53354Schristos 			      safe_strerror (save_errno));
10026a53354Schristos 
10126a53354Schristos 	  /* Claim it exited with unknown signal.  */
10226a53354Schristos 	  ourstatus->kind = TARGET_WAITKIND_SIGNALLED;
10326a53354Schristos 	  ourstatus->value.sig = GDB_SIGNAL_UNKNOWN;
10426a53354Schristos 	  return inferior_ptid;
10526a53354Schristos 	}
10626a53354Schristos 
10726a53354Schristos       /* Ignore terminated detached child processes.  */
10807163879Schristos       if (!WIFSTOPPED (status) && pid != inferior_ptid.pid ())
10926a53354Schristos 	pid = -1;
11026a53354Schristos     }
11126a53354Schristos   while (pid == -1);
11226a53354Schristos 
11307163879Schristos   ptid = ptid_t (pid);
11426a53354Schristos 
11526a53354Schristos   if (WIFSTOPPED (status))
11626a53354Schristos     {
11726a53354Schristos       ptrace_state_t pe;
11826a53354Schristos       pid_t fpid;
11926a53354Schristos 
12026a53354Schristos       if (ptrace (PT_GET_PROCESS_STATE, pid, (caddr_t)&pe, sizeof pe) == -1)
12126a53354Schristos 	perror_with_name (("ptrace"));
12226a53354Schristos 
12326a53354Schristos       switch (pe.pe_report_event)
12426a53354Schristos 	{
12526a53354Schristos 	case PTRACE_FORK:
12626a53354Schristos 	  ourstatus->kind = TARGET_WAITKIND_FORKED;
12707163879Schristos 	  ourstatus->value.related_pid = ptid_t (pe.pe_other_pid);
12826a53354Schristos 
12926a53354Schristos 	  /* Make sure the other end of the fork is stopped too.  */
13026a53354Schristos 	  fpid = waitpid (pe.pe_other_pid, &status, 0);
13126a53354Schristos 	  if (fpid == -1)
13226a53354Schristos 	    perror_with_name (("waitpid"));
13326a53354Schristos 
13426a53354Schristos 	  if (ptrace (PT_GET_PROCESS_STATE, fpid,
13526a53354Schristos 		      (caddr_t)&pe, sizeof pe) == -1)
13626a53354Schristos 	    perror_with_name (("ptrace"));
13726a53354Schristos 
13826a53354Schristos 	  gdb_assert (pe.pe_report_event == PTRACE_FORK);
13926a53354Schristos 	  gdb_assert (pe.pe_other_pid == pid);
14007163879Schristos 	  if (fpid == inferior_ptid.pid ())
14126a53354Schristos 	    {
14207163879Schristos 	      ourstatus->value.related_pid = ptid_t (pe.pe_other_pid);
14307163879Schristos 	      return ptid_t (fpid);
14426a53354Schristos 	    }
14526a53354Schristos 
14607163879Schristos 	  return ptid_t (pid);
14726a53354Schristos 	}
14826a53354Schristos 
14907163879Schristos       ptid = ptid_t (pid, pe.pe_tid, 0);
150*1424dfb3Schristos       if (!in_thread_list (this, ptid))
15126a53354Schristos 	{
15207163879Schristos 	  if (inferior_ptid.lwp () == 0)
153*1424dfb3Schristos 	    thread_change_ptid (this, inferior_ptid, ptid);
15426a53354Schristos 	  else
155*1424dfb3Schristos 	    add_thread (this, ptid);
15626a53354Schristos 	}
15726a53354Schristos     }
15826a53354Schristos 
15926a53354Schristos   store_waitstatus (ourstatus, status);
16026a53354Schristos   return ptid;
16126a53354Schristos }
16226a53354Schristos 
16326a53354Schristos #endif /* PT_GET_THREAD_FIRST */
164*1424dfb3Schristos 
165*1424dfb3Schristos #ifdef PT_GET_PROCESS_STATE
166*1424dfb3Schristos 
167*1424dfb3Schristos void
post_attach(int pid)168*1424dfb3Schristos obsd_nat_target::post_attach (int pid)
169*1424dfb3Schristos {
170*1424dfb3Schristos   ptrace_event_t pe;
171*1424dfb3Schristos 
172*1424dfb3Schristos   /* Set the initial event mask.  */
173*1424dfb3Schristos   memset (&pe, 0, sizeof pe);
174*1424dfb3Schristos   pe.pe_set_event |= PTRACE_FORK;
175*1424dfb3Schristos   if (ptrace (PT_SET_EVENT_MASK, pid,
176*1424dfb3Schristos 	      (PTRACE_TYPE_ARG3)&pe, sizeof pe) == -1)
177*1424dfb3Schristos     perror_with_name (("ptrace"));
178*1424dfb3Schristos }
179*1424dfb3Schristos 
180*1424dfb3Schristos void
post_startup_inferior(ptid_t pid)181*1424dfb3Schristos obsd_nat_target::post_startup_inferior (ptid_t pid)
182*1424dfb3Schristos {
183*1424dfb3Schristos   ptrace_event_t pe;
184*1424dfb3Schristos 
185*1424dfb3Schristos   /* Set the initial event mask.  */
186*1424dfb3Schristos   memset (&pe, 0, sizeof pe);
187*1424dfb3Schristos   pe.pe_set_event |= PTRACE_FORK;
188*1424dfb3Schristos   if (ptrace (PT_SET_EVENT_MASK, pid.pid (),
189*1424dfb3Schristos 	      (PTRACE_TYPE_ARG3)&pe, sizeof pe) == -1)
190*1424dfb3Schristos     perror_with_name (("ptrace"));
191*1424dfb3Schristos }
192*1424dfb3Schristos 
193*1424dfb3Schristos /* Target hook for follow_fork.  On entry and at return inferior_ptid is
194*1424dfb3Schristos    the ptid of the followed inferior.  */
195*1424dfb3Schristos 
196*1424dfb3Schristos bool
follow_fork(bool follow_child,bool detach_fork)197*1424dfb3Schristos obsd_nat_target::follow_fork (bool follow_child, bool detach_fork)
198*1424dfb3Schristos {
199*1424dfb3Schristos   if (!follow_child)
200*1424dfb3Schristos     {
201*1424dfb3Schristos       struct thread_info *tp = inferior_thread ();
202*1424dfb3Schristos       pid_t child_pid = tp->pending_follow.value.related_pid.pid ();
203*1424dfb3Schristos 
204*1424dfb3Schristos       /* Breakpoints have already been detached from the child by
205*1424dfb3Schristos 	 infrun.c.  */
206*1424dfb3Schristos 
207*1424dfb3Schristos       if (ptrace (PT_DETACH, child_pid, (PTRACE_TYPE_ARG3)1, 0) == -1)
208*1424dfb3Schristos 	perror_with_name (("ptrace"));
209*1424dfb3Schristos     }
210*1424dfb3Schristos 
211*1424dfb3Schristos   return false;
212*1424dfb3Schristos }
213*1424dfb3Schristos 
214*1424dfb3Schristos int
insert_fork_catchpoint(int pid)215*1424dfb3Schristos obsd_nat_target::insert_fork_catchpoint (int pid)
216*1424dfb3Schristos {
217*1424dfb3Schristos   return 0;
218*1424dfb3Schristos }
219*1424dfb3Schristos 
220*1424dfb3Schristos int
remove_fork_catchpoint(int pid)221*1424dfb3Schristos obsd_nat_target::remove_fork_catchpoint (int pid)
222*1424dfb3Schristos {
223*1424dfb3Schristos   return 0;
224*1424dfb3Schristos }
225*1424dfb3Schristos 
226*1424dfb3Schristos #endif /* PT_GET_PROCESS_STATE */
227