Home | History | Annotate | Line # | Download | only in nat
linux-ptrace.c revision 1.5
      1 /* Linux-specific ptrace manipulation routines.
      2    Copyright (C) 2012-2017 Free Software Foundation, Inc.
      3 
      4    This file is part of GDB.
      5 
      6    This program is free software; you can redistribute it and/or modify
      7    it under the terms of the GNU General Public License as published by
      8    the Free Software Foundation; either version 3 of the License, or
      9    (at your option) any later version.
     10 
     11    This program is distributed in the hope that it will be useful,
     12    but WITHOUT ANY WARRANTY; without even the implied warranty of
     13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     14    GNU General Public License for more details.
     15 
     16    You should have received a copy of the GNU General Public License
     17    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
     18 
     19 #include "common-defs.h"
     20 #include "linux-ptrace.h"
     21 #include "linux-procfs.h"
     22 #include "linux-waitpid.h"
     23 #include "buffer.h"
     24 #include "gdb_wait.h"
     25 #include "gdb_ptrace.h"
     26 #ifdef HAVE_SYS_PROCFS_H
     27 #include <sys/procfs.h>
     28 #endif
     29 
     30 /* Stores the ptrace options supported by the running kernel.
     31    A value of -1 means we did not check for features yet.  A value
     32    of 0 means there are no supported features.  */
     33 static int supported_ptrace_options = -1;
     34 
     35 /* Find all possible reasons we could fail to attach PID and append
     36    these as strings to the already initialized BUFFER.  '\0'
     37    termination of BUFFER must be done by the caller.  */
     38 
     39 void
     40 linux_ptrace_attach_fail_reason (pid_t pid, struct buffer *buffer)
     41 {
     42   pid_t tracerpid;
     43 
     44   tracerpid = linux_proc_get_tracerpid_nowarn (pid);
     45   if (tracerpid > 0)
     46     buffer_xml_printf (buffer, _("process %d is already traced "
     47 				 "by process %d"),
     48 		       (int) pid, (int) tracerpid);
     49 
     50   if (linux_proc_pid_is_zombie_nowarn (pid))
     51     buffer_xml_printf (buffer, _("process %d is a zombie "
     52 				 "- the process has already terminated"),
     53 		       (int) pid);
     54 }
     55 
     56 /* See linux-ptrace.h.  */
     57 
     58 char *
     59 linux_ptrace_attach_fail_reason_string (ptid_t ptid, int err)
     60 {
     61   static char *reason_string;
     62   struct buffer buffer;
     63   char *warnings;
     64   long lwpid = ptid_get_lwp (ptid);
     65 
     66   xfree (reason_string);
     67 
     68   buffer_init (&buffer);
     69   linux_ptrace_attach_fail_reason (lwpid, &buffer);
     70   buffer_grow_str0 (&buffer, "");
     71   warnings = buffer_finish (&buffer);
     72   if (warnings[0] != '\0')
     73     reason_string = xstrprintf ("%s (%d), %s",
     74 				safe_strerror (err), err, warnings);
     75   else
     76     reason_string = xstrprintf ("%s (%d)",
     77 				safe_strerror (err), err);
     78   xfree (warnings);
     79   return reason_string;
     80 }
     81 
     82 #if defined __i386__ || defined __x86_64__
     83 
     84 /* Address of the 'ret' instruction in asm code block below.  */
     85 EXTERN_C void linux_ptrace_test_ret_to_nx_instr (void);
     86 
     87 #include <sys/reg.h>
     88 #include <sys/mman.h>
     89 #include <signal.h>
     90 
     91 #endif /* defined __i386__ || defined __x86_64__ */
     92 
     93 /* Test broken off-trunk Linux kernel patchset for NX support on i386.  It was
     94    removed in Fedora kernel 88fa1f0332d188795ed73d7ac2b1564e11a0b4cd.
     95 
     96    Test also x86_64 arch for PaX support.  */
     97 
     98 static void
     99 linux_ptrace_test_ret_to_nx (void)
    100 {
    101 #if defined __i386__ || defined __x86_64__
    102   pid_t child, got_pid;
    103   gdb_byte *return_address, *pc;
    104   long l;
    105   int status, kill_status;
    106   elf_gregset_t regs;
    107 
    108   return_address
    109     = (gdb_byte *) mmap (NULL, 2, PROT_READ | PROT_WRITE,
    110 			 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
    111   if (return_address == MAP_FAILED)
    112     {
    113       warning (_("linux_ptrace_test_ret_to_nx: Cannot mmap: %s"),
    114 	       safe_strerror (errno));
    115       return;
    116     }
    117 
    118   /* Put there 'int3'.  */
    119   *return_address = 0xcc;
    120 
    121   child = fork ();
    122   switch (child)
    123     {
    124     case -1:
    125       warning (_("linux_ptrace_test_ret_to_nx: Cannot fork: %s"),
    126 	       safe_strerror (errno));
    127       return;
    128 
    129     case 0:
    130       l = ptrace (PTRACE_TRACEME, 0, (PTRACE_TYPE_ARG3) NULL,
    131 		  (PTRACE_TYPE_ARG4) NULL);
    132       if (l != 0)
    133 	warning (_("linux_ptrace_test_ret_to_nx: Cannot PTRACE_TRACEME: %s"),
    134 		 safe_strerror (errno));
    135       else
    136 	{
    137 #if defined __i386__
    138 	  asm volatile ("pushl %0;"
    139 			".globl linux_ptrace_test_ret_to_nx_instr;"
    140 			"linux_ptrace_test_ret_to_nx_instr:"
    141 			"ret"
    142 			: : "r" (return_address) : "%esp", "memory");
    143 #elif defined __x86_64__
    144 	  asm volatile ("pushq %0;"
    145 			".globl linux_ptrace_test_ret_to_nx_instr;"
    146 			"linux_ptrace_test_ret_to_nx_instr:"
    147 			"ret"
    148 			: : "r" ((uint64_t) (uintptr_t) return_address)
    149 			: "%rsp", "memory");
    150 #else
    151 # error "!__i386__ && !__x86_64__"
    152 #endif
    153 	  gdb_assert_not_reached ("asm block did not terminate");
    154 	}
    155 
    156       _exit (1);
    157     }
    158 
    159   errno = 0;
    160   got_pid = waitpid (child, &status, 0);
    161   if (got_pid != child)
    162     {
    163       warning (_("linux_ptrace_test_ret_to_nx: waitpid returned %ld: %s"),
    164 	       (long) got_pid, safe_strerror (errno));
    165       return;
    166     }
    167 
    168   if (WIFSIGNALED (status))
    169     {
    170       if (WTERMSIG (status) != SIGKILL)
    171 	warning (_("linux_ptrace_test_ret_to_nx: WTERMSIG %d is not SIGKILL!"),
    172 		 (int) WTERMSIG (status));
    173       else
    174 	warning (_("Cannot call inferior functions, Linux kernel PaX "
    175 		   "protection forbids return to non-executable pages!"));
    176       return;
    177     }
    178 
    179   if (!WIFSTOPPED (status))
    180     {
    181       warning (_("linux_ptrace_test_ret_to_nx: status %d is not WIFSTOPPED!"),
    182 	       status);
    183       return;
    184     }
    185 
    186   /* We may get SIGSEGV due to missing PROT_EXEC of the return_address.  */
    187   if (WSTOPSIG (status) != SIGTRAP && WSTOPSIG (status) != SIGSEGV)
    188     {
    189       warning (_("linux_ptrace_test_ret_to_nx: "
    190 		 "WSTOPSIG %d is neither SIGTRAP nor SIGSEGV!"),
    191 	       (int) WSTOPSIG (status));
    192       return;
    193     }
    194 
    195   if (ptrace (PTRACE_GETREGS, child, (PTRACE_TYPE_ARG3) 0,
    196 	      (PTRACE_TYPE_ARG4) &regs) < 0)
    197     {
    198       warning (_("linux_ptrace_test_ret_to_nx: Cannot PTRACE_GETREGS: %s"),
    199 	       safe_strerror (errno));
    200     }
    201 #if defined __i386__
    202   pc = (gdb_byte *) (uintptr_t) regs[EIP];
    203 #elif defined __x86_64__
    204   pc = (gdb_byte *) (uintptr_t) regs[RIP];
    205 #else
    206 # error "!__i386__ && !__x86_64__"
    207 #endif
    208 
    209   kill (child, SIGKILL);
    210   ptrace (PTRACE_KILL, child, (PTRACE_TYPE_ARG3) NULL,
    211 	  (PTRACE_TYPE_ARG4) NULL);
    212 
    213   errno = 0;
    214   got_pid = waitpid (child, &kill_status, 0);
    215   if (got_pid != child)
    216     {
    217       warning (_("linux_ptrace_test_ret_to_nx: "
    218 		 "PTRACE_KILL waitpid returned %ld: %s"),
    219 	       (long) got_pid, safe_strerror (errno));
    220       return;
    221     }
    222   if (!WIFSIGNALED (kill_status))
    223     {
    224       warning (_("linux_ptrace_test_ret_to_nx: "
    225 		 "PTRACE_KILL status %d is not WIFSIGNALED!"),
    226 	       status);
    227       return;
    228     }
    229 
    230   /* + 1 is there as x86* stops after the 'int3' instruction.  */
    231   if (WSTOPSIG (status) == SIGTRAP && pc == return_address + 1)
    232     {
    233       /* PASS */
    234       return;
    235     }
    236 
    237   /* We may get SIGSEGV due to missing PROT_EXEC of the RETURN_ADDRESS page.  */
    238   if (WSTOPSIG (status) == SIGSEGV && pc == return_address)
    239     {
    240       /* PASS */
    241       return;
    242     }
    243 
    244   if ((void (*) (void)) pc != &linux_ptrace_test_ret_to_nx_instr)
    245     warning (_("linux_ptrace_test_ret_to_nx: PC %p is neither near return "
    246 	       "address %p nor is the return instruction %p!"),
    247 	     pc, return_address, &linux_ptrace_test_ret_to_nx_instr);
    248   else
    249     warning (_("Cannot call inferior functions on this system - "
    250 	       "Linux kernel with broken i386 NX (non-executable pages) "
    251 	       "support detected!"));
    252 #endif /* defined __i386__ || defined __x86_64__ */
    253 }
    254 
    255 /* Helper function to fork a process and make the child process call
    256    the function FUNCTION, passing CHILD_STACK as parameter.
    257 
    258    For MMU-less targets, clone is used instead of fork, and
    259    CHILD_STACK is used as stack space for the cloned child.  If NULL,
    260    stack space is allocated via malloc (and subsequently passed to
    261    FUNCTION).  For MMU targets, CHILD_STACK is ignored.  */
    262 
    263 static int
    264 linux_fork_to_function (gdb_byte *child_stack, int (*function) (void *))
    265 {
    266   int child_pid;
    267 
    268   /* Sanity check the function pointer.  */
    269   gdb_assert (function != NULL);
    270 
    271 #if defined(__UCLIBC__) && defined(HAS_NOMMU)
    272 #define STACK_SIZE 4096
    273 
    274     if (child_stack == NULL)
    275       child_stack = xmalloc (STACK_SIZE * 4);
    276 
    277     /* Use CLONE_VM instead of fork, to support uClinux (no MMU).  */
    278 #ifdef __ia64__
    279       child_pid = __clone2 (function, child_stack, STACK_SIZE,
    280 			    CLONE_VM | SIGCHLD, child_stack + STACK_SIZE * 2);
    281 #else /* !__ia64__ */
    282       child_pid = clone (function, child_stack + STACK_SIZE,
    283 			 CLONE_VM | SIGCHLD, child_stack + STACK_SIZE * 2);
    284 #endif /* !__ia64__ */
    285 #else /* !defined(__UCLIBC) && defined(HAS_NOMMU) */
    286   child_pid = fork ();
    287 
    288   if (child_pid == 0)
    289     function (NULL);
    290 #endif /* defined(__UCLIBC) && defined(HAS_NOMMU) */
    291 
    292   if (child_pid == -1)
    293     perror_with_name (("fork"));
    294 
    295   return child_pid;
    296 }
    297 
    298 /* A helper function for linux_check_ptrace_features, called after
    299    the child forks a grandchild.  */
    300 
    301 static int
    302 linux_grandchild_function (void *child_stack)
    303 {
    304   /* Free any allocated stack.  */
    305   xfree (child_stack);
    306 
    307   /* This code is only reacheable by the grandchild (child's child)
    308      process.  */
    309   _exit (0);
    310 }
    311 
    312 /* A helper function for linux_check_ptrace_features, called after
    313    the parent process forks a child.  The child allows itself to
    314    be traced by its parent.  */
    315 
    316 static int
    317 linux_child_function (void *child_stack)
    318 {
    319   ptrace (PTRACE_TRACEME, 0, (PTRACE_TYPE_ARG3) 0, (PTRACE_TYPE_ARG4) 0);
    320   kill (getpid (), SIGSTOP);
    321 
    322   /* Fork a grandchild.  */
    323   linux_fork_to_function ((gdb_byte *) child_stack, linux_grandchild_function);
    324 
    325   /* This code is only reacheable by the child (grandchild's parent)
    326      process.  */
    327   _exit (0);
    328 }
    329 
    330 static void linux_test_for_tracesysgood (int child_pid);
    331 static void linux_test_for_tracefork (int child_pid);
    332 static void linux_test_for_exitkill (int child_pid);
    333 
    334 /* Determine ptrace features available on this target.  */
    335 
    336 void
    337 linux_check_ptrace_features (void)
    338 {
    339   int child_pid, ret, status;
    340 
    341   /* Initialize the options.  */
    342   supported_ptrace_options = 0;
    343 
    344   /* Fork a child so we can do some testing.  The child will call
    345      linux_child_function and will get traced.  The child will
    346      eventually fork a grandchild so we can test fork event
    347      reporting.  */
    348   child_pid = linux_fork_to_function (NULL, linux_child_function);
    349 
    350   ret = my_waitpid (child_pid, &status, 0);
    351   if (ret == -1)
    352     perror_with_name (("waitpid"));
    353   else if (ret != child_pid)
    354     error (_("linux_check_ptrace_features: waitpid: unexpected result %d."),
    355 	   ret);
    356   if (! WIFSTOPPED (status))
    357     error (_("linux_check_ptrace_features: waitpid: unexpected status %d."),
    358 	   status);
    359 
    360   linux_test_for_tracesysgood (child_pid);
    361 
    362   linux_test_for_tracefork (child_pid);
    363 
    364   linux_test_for_exitkill (child_pid);
    365 
    366   /* Clean things up and kill any pending children.  */
    367   do
    368     {
    369       ret = ptrace (PTRACE_KILL, child_pid, (PTRACE_TYPE_ARG3) 0,
    370 		    (PTRACE_TYPE_ARG4) 0);
    371       if (ret != 0)
    372 	warning (_("linux_check_ptrace_features: failed to kill child"));
    373       my_waitpid (child_pid, &status, 0);
    374     }
    375   while (WIFSTOPPED (status));
    376 }
    377 
    378 /* Determine if PTRACE_O_TRACESYSGOOD can be used to catch
    379    syscalls.  */
    380 
    381 static void
    382 linux_test_for_tracesysgood (int child_pid)
    383 {
    384   int ret;
    385 
    386   ret = ptrace (PTRACE_SETOPTIONS, child_pid, (PTRACE_TYPE_ARG3) 0,
    387 		(PTRACE_TYPE_ARG4) PTRACE_O_TRACESYSGOOD);
    388 
    389   if (ret == 0)
    390     supported_ptrace_options |= PTRACE_O_TRACESYSGOOD;
    391 }
    392 
    393 /* Determine if PTRACE_O_TRACEFORK can be used to follow fork
    394    events.  */
    395 
    396 static void
    397 linux_test_for_tracefork (int child_pid)
    398 {
    399   int ret, status;
    400   long second_pid;
    401 
    402   /* First, set the PTRACE_O_TRACEFORK option.  If this fails, we
    403      know for sure that it is not supported.  */
    404   ret = ptrace (PTRACE_SETOPTIONS, child_pid, (PTRACE_TYPE_ARG3) 0,
    405 		(PTRACE_TYPE_ARG4) PTRACE_O_TRACEFORK);
    406 
    407   if (ret != 0)
    408     return;
    409 
    410   /* Check if the target supports PTRACE_O_TRACEVFORKDONE.  */
    411   ret = ptrace (PTRACE_SETOPTIONS, child_pid, (PTRACE_TYPE_ARG3) 0,
    412 		(PTRACE_TYPE_ARG4) (PTRACE_O_TRACEFORK
    413 				    | PTRACE_O_TRACEVFORKDONE));
    414   if (ret == 0)
    415     supported_ptrace_options |= PTRACE_O_TRACEVFORKDONE;
    416 
    417   /* Setting PTRACE_O_TRACEFORK did not cause an error, however we
    418      don't know for sure that the feature is available; old
    419      versions of PTRACE_SETOPTIONS ignored unknown options.
    420      Therefore, we attach to the child process, use PTRACE_SETOPTIONS
    421      to enable fork tracing, and let it fork.  If the process exits,
    422      we assume that we can't use PTRACE_O_TRACEFORK; if we get the
    423      fork notification, and we can extract the new child's PID, then
    424      we assume that we can.
    425 
    426      We do not explicitly check for vfork tracing here.  It is
    427      assumed that vfork tracing is available whenever fork tracing
    428      is available.  */
    429   ret = ptrace (PTRACE_CONT, child_pid, (PTRACE_TYPE_ARG3) 0,
    430 		(PTRACE_TYPE_ARG4) 0);
    431   if (ret != 0)
    432     warning (_("linux_test_for_tracefork: failed to resume child"));
    433 
    434   ret = my_waitpid (child_pid, &status, 0);
    435 
    436   /* Check if we received a fork event notification.  */
    437   if (ret == child_pid && WIFSTOPPED (status)
    438       && linux_ptrace_get_extended_event (status) == PTRACE_EVENT_FORK)
    439     {
    440       /* We did receive a fork event notification.  Make sure its PID
    441 	 is reported.  */
    442       second_pid = 0;
    443       ret = ptrace (PTRACE_GETEVENTMSG, child_pid, (PTRACE_TYPE_ARG3) 0,
    444 		    (PTRACE_TYPE_ARG4) &second_pid);
    445       if (ret == 0 && second_pid != 0)
    446 	{
    447 	  int second_status;
    448 
    449 	  /* We got the PID from the grandchild, which means fork
    450 	     tracing is supported.  */
    451 	  supported_ptrace_options |= PTRACE_O_TRACECLONE;
    452 	  supported_ptrace_options |= (PTRACE_O_TRACEFORK
    453 				       | PTRACE_O_TRACEVFORK
    454 				       | PTRACE_O_TRACEEXEC);
    455 
    456 	  /* Do some cleanup and kill the grandchild.  */
    457 	  my_waitpid (second_pid, &second_status, 0);
    458 	  ret = ptrace (PTRACE_KILL, second_pid, (PTRACE_TYPE_ARG3) 0,
    459 			(PTRACE_TYPE_ARG4) 0);
    460 	  if (ret != 0)
    461 	    warning (_("linux_test_for_tracefork: "
    462 		       "failed to kill second child"));
    463 	  my_waitpid (second_pid, &status, 0);
    464 	}
    465     }
    466   else
    467     warning (_("linux_test_for_tracefork: unexpected result from waitpid "
    468 	     "(%d, status 0x%x)"), ret, status);
    469 }
    470 
    471 /* Determine if PTRACE_O_EXITKILL can be used.  */
    472 
    473 static void
    474 linux_test_for_exitkill (int child_pid)
    475 {
    476   int ret;
    477 
    478   ret = ptrace (PTRACE_SETOPTIONS, child_pid, (PTRACE_TYPE_ARG3) 0,
    479 		(PTRACE_TYPE_ARG4) PTRACE_O_EXITKILL);
    480 
    481   if (ret == 0)
    482     supported_ptrace_options |= PTRACE_O_EXITKILL;
    483 }
    484 
    485 /* Enable reporting of all currently supported ptrace events.
    486    OPTIONS is a bit mask of extended features we want enabled,
    487    if supported by the kernel.  PTRACE_O_TRACECLONE is always
    488    enabled, if supported.  */
    489 
    490 void
    491 linux_enable_event_reporting (pid_t pid, int options)
    492 {
    493   /* Check if we have initialized the ptrace features for this
    494      target.  If not, do it now.  */
    495   if (supported_ptrace_options == -1)
    496     linux_check_ptrace_features ();
    497 
    498   /* We always want clone events.  */
    499   options |= PTRACE_O_TRACECLONE;
    500 
    501   /* Filter out unsupported options.  */
    502   options &= supported_ptrace_options;
    503 
    504   /* Set the options.  */
    505   ptrace (PTRACE_SETOPTIONS, pid, (PTRACE_TYPE_ARG3) 0,
    506 	  (PTRACE_TYPE_ARG4) (uintptr_t) options);
    507 }
    508 
    509 /* Disable reporting of all currently supported ptrace events.  */
    510 
    511 void
    512 linux_disable_event_reporting (pid_t pid)
    513 {
    514   /* Set the options.  */
    515   ptrace (PTRACE_SETOPTIONS, pid, (PTRACE_TYPE_ARG3) 0, 0);
    516 }
    517 
    518 /* Returns non-zero if PTRACE_OPTIONS is contained within
    519    SUPPORTED_PTRACE_OPTIONS, therefore supported.  Returns 0
    520    otherwise.  */
    521 
    522 static int
    523 ptrace_supports_feature (int ptrace_options)
    524 {
    525   if (supported_ptrace_options == -1)
    526     linux_check_ptrace_features ();
    527 
    528   return ((supported_ptrace_options & ptrace_options) == ptrace_options);
    529 }
    530 
    531 /* Returns non-zero if PTRACE_EVENT_FORK is supported by ptrace,
    532    0 otherwise.  Note that if PTRACE_EVENT_FORK is supported so is
    533    PTRACE_EVENT_CLONE, PTRACE_EVENT_EXEC and PTRACE_EVENT_VFORK,
    534    since they were all added to the kernel at the same time.  */
    535 
    536 int
    537 linux_supports_tracefork (void)
    538 {
    539   return ptrace_supports_feature (PTRACE_O_TRACEFORK);
    540 }
    541 
    542 /* Returns non-zero if PTRACE_EVENT_EXEC is supported by ptrace,
    543    0 otherwise.  Note that if PTRACE_EVENT_FORK is supported so is
    544    PTRACE_EVENT_CLONE, PTRACE_EVENT_FORK and PTRACE_EVENT_VFORK,
    545    since they were all added to the kernel at the same time.  */
    546 
    547 int
    548 linux_supports_traceexec (void)
    549 {
    550   return ptrace_supports_feature (PTRACE_O_TRACEEXEC);
    551 }
    552 
    553 /* Returns non-zero if PTRACE_EVENT_CLONE is supported by ptrace,
    554    0 otherwise.  Note that if PTRACE_EVENT_CLONE is supported so is
    555    PTRACE_EVENT_FORK, PTRACE_EVENT_EXEC and PTRACE_EVENT_VFORK,
    556    since they were all added to the kernel at the same time.  */
    557 
    558 int
    559 linux_supports_traceclone (void)
    560 {
    561   return ptrace_supports_feature (PTRACE_O_TRACECLONE);
    562 }
    563 
    564 /* Returns non-zero if PTRACE_O_TRACEVFORKDONE is supported by
    565    ptrace, 0 otherwise.  */
    566 
    567 int
    568 linux_supports_tracevforkdone (void)
    569 {
    570   return ptrace_supports_feature (PTRACE_O_TRACEVFORKDONE);
    571 }
    572 
    573 /* Returns non-zero if PTRACE_O_TRACESYSGOOD is supported by ptrace,
    574    0 otherwise.  */
    575 
    576 int
    577 linux_supports_tracesysgood (void)
    578 {
    579   return ptrace_supports_feature (PTRACE_O_TRACESYSGOOD);
    580 }
    581 
    582 /* Display possible problems on this system.  Display them only once per GDB
    583    execution.  */
    584 
    585 void
    586 linux_ptrace_init_warnings (void)
    587 {
    588   static int warned = 0;
    589 
    590   if (warned)
    591     return;
    592   warned = 1;
    593 
    594   linux_ptrace_test_ret_to_nx ();
    595 }
    596 
    597 /* Extract extended ptrace event from wait status.  */
    598 
    599 int
    600 linux_ptrace_get_extended_event (int wstat)
    601 {
    602   return (wstat >> 16);
    603 }
    604 
    605 /* Determine whether wait status denotes an extended event.  */
    606 
    607 int
    608 linux_is_extended_waitstatus (int wstat)
    609 {
    610   return (linux_ptrace_get_extended_event (wstat) != 0);
    611 }
    612 
    613 /* Return true if the event in LP may be caused by breakpoint.  */
    614 
    615 int
    616 linux_wstatus_maybe_breakpoint (int wstat)
    617 {
    618   return (WIFSTOPPED (wstat)
    619 	  && (WSTOPSIG (wstat) == SIGTRAP
    620 	      /* SIGILL and SIGSEGV are also treated as traps in case a
    621 		 breakpoint is inserted at the current PC.  */
    622 	      || WSTOPSIG (wstat) == SIGILL
    623 	      || WSTOPSIG (wstat) == SIGSEGV));
    624 }
    625