GDBserver
linux-ptrace.c
Go to the documentation of this file.
1 /* Linux-specific ptrace manipulation routines.
2  Copyright (C) 2012-2018 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
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 
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 *
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 
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
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 = (gdb_byte *) 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. */
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
338 {
339  int child_pid, ret, status;
340 
341  /* Initialize the options. */
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
383 {
384  int ret;
385 
386  ret = ptrace (PTRACE_SETOPTIONS, child_pid, (PTRACE_TYPE_ARG3) 0,
388 
389  if (ret == 0)
391 }
392 
393 /* Determine if PTRACE_O_TRACEFORK can be used to follow fork
394  events. */
395 
396 static void
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,
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,
414  if (ret == 0)
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)
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. */
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,
480 
481  if (ret == 0)
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)
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. */
506  (PTRACE_TYPE_ARG4) (uintptr_t) options);
507 }
508 
509 /* Disable reporting of all currently supported ptrace events. */
510 
511 void
513 {
514  /* Set the options. */
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)
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
538 {
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
549 {
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
560 {
562 }
563 
564 /* Returns non-zero if PTRACE_O_TRACEVFORKDONE is supported by
565  ptrace, 0 otherwise. */
566 
567 int
569 {
571 }
572 
573 /* Returns non-zero if PTRACE_O_TRACESYSGOOD is supported by ptrace,
574  0 otherwise. */
575 
576 int
578 {
580 }
581 
582 /* Display possible problems on this system. Display them only once per GDB
583  execution. */
584 
585 void
587 {
588  static int warned = 0;
589 
590  if (warned)
591  return;
592  warned = 1;
593 
595 }
596 
597 /* Extract extended ptrace event from wait status. */
598 
599 int
601 {
602  return (wstat >> 16);
603 }
604 
605 /* Determine whether wait status denotes an extended event. */
606 
607 int
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
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 }
static int linux_fork_to_function(gdb_byte *child_stack, int(*function)(void *))
Definition: linux-ptrace.c:264
#define PTRACE_GETEVENTMSG
Definition: linux-ptrace.h:59
static void xfree(T *ptr)
Definition: common-utils.h:54
void warning(const char *fmt,...)
Definition: errors.c:26
int linux_wstatus_maybe_breakpoint(int wstat)
Definition: linux-ptrace.c:616
static void linux_test_for_tracefork(int child_pid)
Definition: linux-ptrace.c:397
int linux_is_extended_waitstatus(int wstat)
Definition: linux-ptrace.c:608
void linux_check_ptrace_features(void)
Definition: linux-ptrace.c:337
#define _(String)
Definition: gdb_locale.h:35
static int ptrace_supports_feature(int ptrace_options)
Definition: linux-ptrace.c:523
PTRACE_TYPE_RET ptrace()
static int supported_ptrace_options
Definition: linux-ptrace.c:33
int linux_proc_pid_is_zombie_nowarn(pid_t pid)
Definition: linux-procfs.c:219
void linux_ptrace_attach_fail_reason(pid_t pid, struct buffer *buffer)
Definition: linux-ptrace.c:40
#define PTRACE_EVENT_FORK
Definition: linux-ptrace.h:71
#define WSTOPSIG
Definition: gdb_wait.h:75
void linux_ptrace_init_warnings(void)
Definition: linux-ptrace.c:586
char * linux_ptrace_attach_fail_reason_string(ptid_t ptid, int err)
Definition: linux-ptrace.c:59
#define WTERMSIG(w)
Definition: gdb_wait.h:71
int linux_supports_traceclone(void)
Definition: linux-ptrace.c:559
void buffer_xml_printf(struct buffer *buffer, const char *format,...)
Definition: buffer.c:76
#define PTRACE_O_TRACEVFORKDONE
Definition: linux-ptrace.h:67
#define PTRACE_O_TRACEVFORK
Definition: linux-ptrace.h:64
Definition: ptid.h:35
int linux_ptrace_get_extended_event(int wstat)
Definition: linux-ptrace.c:600
static int linux_grandchild_function(void *child_stack)
Definition: linux-ptrace.c:302
#define gdb_assert_not_reached(message)
Definition: gdb_assert.h:55
int linux_supports_traceexec(void)
Definition: linux-ptrace.c:548
#define EXTERN_C
Definition: common-defs.h:87
#define PTRACE_O_TRACEFORK
Definition: linux-ptrace.h:63
char * xstrprintf(const char *format,...)
Definition: common-utils.c:107
#define PTRACE_O_TRACEEXEC
Definition: linux-ptrace.h:66
long ptid_get_lwp(const ptid_t &ptid)
Definition: ptid.c:55
int linux_supports_tracefork(void)
Definition: linux-ptrace.c:537
static void linux_ptrace_test_ret_to_nx(void)
Definition: linux-ptrace.c:99
#define errno
Definition: wincecompat.h:24
#define gdb_assert(expr)
Definition: gdb_assert.h:32
#define PTRACE_O_TRACECLONE
Definition: linux-ptrace.h:65
#define WIFSTOPPED(w)
Definition: gdb_wait.h:62
static int linux_child_function(void *child_stack)
Definition: linux-ptrace.c:317
#define buffer_grow_str0(BUFFER, STRING)
Definition: buffer.h:65
static void linux_test_for_tracesysgood(int child_pid)
Definition: linux-ptrace.c:382
bfd_byte gdb_byte
Definition: common-types.h:38
void buffer_init(struct buffer *buffer)
Definition: buffer.c:60
void linux_enable_event_reporting(pid_t pid, int options)
Definition: linux-ptrace.c:491
pid_t linux_proc_get_tracerpid_nowarn(pid_t lwpid)
Definition: linux-procfs.c:66
char * safe_strerror(int)
void linux_disable_event_reporting(pid_t pid)
Definition: linux-ptrace.c:512
#define PTRACE_SETOPTIONS
Definition: linux-ptrace.h:58
int linux_supports_tracevforkdone(void)
Definition: linux-ptrace.c:568
static void linux_test_for_exitkill(int child_pid)
Definition: linux-ptrace.c:474
Definition: buffer.h:23
void perror_with_name(const char *string)
Definition: utils.c:57
PTR xmalloc(size_t size)
Definition: common-utils.c:35
int my_waitpid(int pid, int *status, int flags)
Definition: linux-waitpid.c:80
#define PTRACE_O_TRACESYSGOOD
Definition: linux-ptrace.h:62
#define WIFSIGNALED(w)
Definition: gdb_wait.h:48
#define PTRACE_TYPE_ARG3
Definition: config.h:339
#define PTRACE_TYPE_ARG4
Definition: config.h:342
char * buffer_finish(struct buffer *buffer)
Definition: buffer.c:66
#define PTRACE_O_EXITKILL
Definition: linux-ptrace.h:82
void error(const char *fmt,...)
Definition: errors.c:38
int linux_supports_tracesysgood(void)
Definition: linux-ptrace.c:577