gdb/obsd-nat.c - gdb

Functions defined

Source code

  1. /* Native-dependent code for OpenBSD.

  2.    Copyright (C) 2012-2015 Free Software Foundation, Inc.

  3.    This file is part of GDB.

  4.    This program is free software; you can redistribute it and/or modify
  5.    it under the terms of the GNU General Public License as published by
  6.    the Free Software Foundation; either version 3 of the License, or
  7.    (at your option) any later version.

  8.    This program is distributed in the hope that it will be useful,
  9.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  10.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  11.    GNU General Public License for more details.

  12.    You should have received a copy of the GNU General Public License
  13.    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */

  14. #include "defs.h"
  15. #include "gdbthread.h"
  16. #include "inferior.h"
  17. #include "target.h"

  18. #include <sys/types.h>
  19. #include <sys/ptrace.h>
  20. #include "gdb_wait.h"

  21. #include "inf-child.h"
  22. #include "obsd-nat.h"

  23. /* OpenBSD 5.2 and later include rthreads which uses a thread model
  24.    that maps userland threads directly onto kernel threads in a 1:1
  25.    fashion.  */

  26. #ifdef PT_GET_THREAD_FIRST

  27. static char *
  28. obsd_pid_to_str (struct target_ops *ops, ptid_t ptid)
  29. {
  30.   if (ptid_get_lwp (ptid) != 0)
  31.     {
  32.       static char buf[64];

  33.       xsnprintf (buf, sizeof buf, "thread %ld", ptid_get_lwp (ptid));
  34.       return buf;
  35.     }

  36.   return normal_pid_to_str (ptid);
  37. }

  38. static void
  39. obsd_update_thread_list (struct target_ops *ops)
  40. {
  41.   pid_t pid = ptid_get_pid (inferior_ptid);
  42.   struct ptrace_thread_state pts;

  43.   prune_threads ();

  44.   if (ptrace (PT_GET_THREAD_FIRST, pid, (caddr_t)&pts, sizeof pts) == -1)
  45.     perror_with_name (("ptrace"));

  46.   while (pts.pts_tid != -1)
  47.     {
  48.       ptid_t ptid = ptid_build (pid, pts.pts_tid, 0);

  49.       if (!in_thread_list (ptid))
  50.         {
  51.           if (ptid_get_lwp (inferior_ptid) == 0)
  52.             thread_change_ptid (inferior_ptid, ptid);
  53.           else
  54.             add_thread (ptid);
  55.         }

  56.       if (ptrace (PT_GET_THREAD_NEXT, pid, (caddr_t)&pts, sizeof pts) == -1)
  57.         perror_with_name (("ptrace"));
  58.     }
  59. }

  60. static ptid_t
  61. obsd_wait (struct target_ops *ops,
  62.            ptid_t ptid, struct target_waitstatus *ourstatus, int options)
  63. {
  64.   pid_t pid;
  65.   int status, save_errno;

  66.   do
  67.     {
  68.       set_sigint_trap ();

  69.       do
  70.         {
  71.           pid = waitpid (ptid_get_pid (ptid), &status, 0);
  72.           save_errno = errno;
  73.         }
  74.       while (pid == -1 && errno == EINTR);

  75.       clear_sigint_trap ();

  76.       if (pid == -1)
  77.         {
  78.           fprintf_unfiltered (gdb_stderr,
  79.                               _("Child process unexpectedly missing: %s.\n"),
  80.                               safe_strerror (save_errno));

  81.           /* Claim it exited with unknown signal.  */
  82.           ourstatus->kind = TARGET_WAITKIND_SIGNALLED;
  83.           ourstatus->value.sig = GDB_SIGNAL_UNKNOWN;
  84.           return inferior_ptid;
  85.         }

  86.       /* Ignore terminated detached child processes.  */
  87.       if (!WIFSTOPPED (status) && pid != ptid_get_pid (inferior_ptid))
  88.         pid = -1;
  89.     }
  90.   while (pid == -1);

  91.   ptid = pid_to_ptid (pid);

  92.   if (WIFSTOPPED (status))
  93.     {
  94.       ptrace_state_t pe;
  95.       pid_t fpid;

  96.       if (ptrace (PT_GET_PROCESS_STATE, pid, (caddr_t)&pe, sizeof pe) == -1)
  97.         perror_with_name (("ptrace"));

  98.       switch (pe.pe_report_event)
  99.         {
  100.         case PTRACE_FORK:
  101.           ourstatus->kind = TARGET_WAITKIND_FORKED;
  102.           ourstatus->value.related_pid = pid_to_ptid (pe.pe_other_pid);

  103.           /* Make sure the other end of the fork is stopped too.  */
  104.           fpid = waitpid (pe.pe_other_pid, &status, 0);
  105.           if (fpid == -1)
  106.             perror_with_name (("waitpid"));

  107.           if (ptrace (PT_GET_PROCESS_STATE, fpid,
  108.                       (caddr_t)&pe, sizeof pe) == -1)
  109.             perror_with_name (("ptrace"));

  110.           gdb_assert (pe.pe_report_event == PTRACE_FORK);
  111.           gdb_assert (pe.pe_other_pid == pid);
  112.           if (fpid == ptid_get_pid (inferior_ptid))
  113.             {
  114.               ourstatus->value.related_pid = pid_to_ptid (pe.pe_other_pid);
  115.               return pid_to_ptid (fpid);
  116.             }

  117.           return pid_to_ptid (pid);
  118.         }

  119.       ptid = ptid_build (pid, pe.pe_tid, 0);
  120.       if (!in_thread_list (ptid))
  121.         {
  122.           if (ptid_get_lwp (inferior_ptid) == 0)
  123.             thread_change_ptid (inferior_ptid, ptid);
  124.           else
  125.             add_thread (ptid);
  126.         }
  127.     }

  128.   store_waitstatus (ourstatus, status);
  129.   return ptid;
  130. }

  131. void
  132. obsd_add_target (struct target_ops *t)
  133. {
  134.   /* Override some methods to support threads.  */
  135.   t->to_pid_to_str = obsd_pid_to_str;
  136.   t->to_update_thread_list = obsd_update_thread_list;
  137.   t->to_wait = obsd_wait;
  138.   add_target (t);
  139. }

  140. #else

  141. void
  142. obsd_add_target (struct target_ops *t)
  143. {
  144.   add_target (t);
  145. }

  146. #endif /* PT_GET_THREAD_FIRST */