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