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