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