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