linux-ptrace.c revision 1.10 1 1.1 christos /* Linux-specific ptrace manipulation routines.
2 1.9 christos Copyright (C) 2012-2024 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 "linux-ptrace.h"
20 1.1 christos #include "linux-procfs.h"
21 1.1 christos #include "linux-waitpid.h"
22 1.5 christos #ifdef HAVE_SYS_PROCFS_H
23 1.4 christos #include <sys/procfs.h>
24 1.5 christos #endif
25 1.10 christos #include "gdbsupport/eintr.h"
26 1.1 christos
27 1.3 christos /* Stores the ptrace options supported by the running kernel.
28 1.3 christos A value of -1 means we did not check for features yet. A value
29 1.3 christos of 0 means there are no supported features. */
30 1.3 christos static int supported_ptrace_options = -1;
31 1.1 christos
32 1.6 christos /* Find all possible reasons we could fail to attach PID and return these
33 1.6 christos as a string. An empty string is returned if we didn't find any reason. */
34 1.1 christos
35 1.6 christos std::string
36 1.6 christos linux_ptrace_attach_fail_reason (pid_t pid)
37 1.1 christos {
38 1.6 christos pid_t tracerpid = linux_proc_get_tracerpid_nowarn (pid);
39 1.6 christos std::string result;
40 1.1 christos
41 1.1 christos if (tracerpid > 0)
42 1.6 christos string_appendf (result,
43 1.6 christos _("process %d is already traced by process %d"),
44 1.6 christos (int) pid, (int) tracerpid);
45 1.1 christos
46 1.1 christos if (linux_proc_pid_is_zombie_nowarn (pid))
47 1.6 christos string_appendf (result,
48 1.6 christos _("process %d is a zombie - the process has already "
49 1.6 christos "terminated"),
50 1.6 christos (int) pid);
51 1.6 christos
52 1.6 christos return result;
53 1.1 christos }
54 1.1 christos
55 1.1 christos /* See linux-ptrace.h. */
56 1.1 christos
57 1.6 christos std::string
58 1.1 christos linux_ptrace_attach_fail_reason_string (ptid_t ptid, int err)
59 1.1 christos {
60 1.6 christos long lwpid = ptid.lwp ();
61 1.6 christos std::string reason = linux_ptrace_attach_fail_reason (lwpid);
62 1.6 christos
63 1.6 christos if (!reason.empty ())
64 1.6 christos return string_printf ("%s (%d), %s", safe_strerror (err), err,
65 1.6 christos reason.c_str ());
66 1.1 christos else
67 1.6 christos return string_printf ("%s (%d)", safe_strerror (err), err);
68 1.1 christos }
69 1.1 christos
70 1.1 christos #if defined __i386__ || defined __x86_64__
71 1.1 christos
72 1.1 christos /* Address of the 'ret' instruction in asm code block below. */
73 1.9 christos extern "C" void linux_ptrace_test_ret_to_nx_instr (void);
74 1.1 christos
75 1.1 christos #include <sys/reg.h>
76 1.1 christos #include <sys/mman.h>
77 1.1 christos #include <signal.h>
78 1.1 christos
79 1.1 christos #endif /* defined __i386__ || defined __x86_64__ */
80 1.1 christos
81 1.6 christos /* Kill CHILD. WHO is used to report warnings. */
82 1.6 christos
83 1.6 christos static void
84 1.6 christos kill_child (pid_t child, const char *who)
85 1.6 christos {
86 1.6 christos pid_t got_pid;
87 1.6 christos int kill_status;
88 1.6 christos
89 1.6 christos if (kill (child, SIGKILL) != 0)
90 1.6 christos {
91 1.6 christos warning (_("%s: failed to kill child pid %ld %s"),
92 1.6 christos who, (long) child, safe_strerror (errno));
93 1.6 christos return;
94 1.6 christos }
95 1.6 christos
96 1.6 christos errno = 0;
97 1.6 christos got_pid = my_waitpid (child, &kill_status, 0);
98 1.6 christos if (got_pid != child)
99 1.6 christos {
100 1.6 christos warning (_("%s: "
101 1.6 christos "kill waitpid returned %ld: %s"),
102 1.6 christos who, (long) got_pid, safe_strerror (errno));
103 1.6 christos return;
104 1.6 christos }
105 1.6 christos if (!WIFSIGNALED (kill_status))
106 1.6 christos {
107 1.6 christos warning (_("%s: "
108 1.6 christos "kill status %d is not WIFSIGNALED!"),
109 1.6 christos who, kill_status);
110 1.6 christos return;
111 1.6 christos }
112 1.6 christos }
113 1.6 christos
114 1.1 christos /* Test broken off-trunk Linux kernel patchset for NX support on i386. It was
115 1.1 christos removed in Fedora kernel 88fa1f0332d188795ed73d7ac2b1564e11a0b4cd.
116 1.1 christos
117 1.1 christos Test also x86_64 arch for PaX support. */
118 1.1 christos
119 1.1 christos static void
120 1.1 christos linux_ptrace_test_ret_to_nx (void)
121 1.1 christos {
122 1.1 christos #if defined __i386__ || defined __x86_64__
123 1.1 christos pid_t child, got_pid;
124 1.1 christos gdb_byte *return_address, *pc;
125 1.1 christos long l;
126 1.6 christos int status;
127 1.4 christos elf_gregset_t regs;
128 1.1 christos
129 1.4 christos return_address
130 1.4 christos = (gdb_byte *) mmap (NULL, 2, PROT_READ | PROT_WRITE,
131 1.1 christos MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
132 1.1 christos if (return_address == MAP_FAILED)
133 1.1 christos {
134 1.1 christos warning (_("linux_ptrace_test_ret_to_nx: Cannot mmap: %s"),
135 1.3 christos safe_strerror (errno));
136 1.1 christos return;
137 1.1 christos }
138 1.1 christos
139 1.1 christos /* Put there 'int3'. */
140 1.1 christos *return_address = 0xcc;
141 1.1 christos
142 1.1 christos child = fork ();
143 1.1 christos switch (child)
144 1.1 christos {
145 1.1 christos case -1:
146 1.1 christos warning (_("linux_ptrace_test_ret_to_nx: Cannot fork: %s"),
147 1.3 christos safe_strerror (errno));
148 1.1 christos return;
149 1.1 christos
150 1.1 christos case 0:
151 1.1 christos l = ptrace (PTRACE_TRACEME, 0, (PTRACE_TYPE_ARG3) NULL,
152 1.1 christos (PTRACE_TYPE_ARG4) NULL);
153 1.1 christos if (l != 0)
154 1.1 christos warning (_("linux_ptrace_test_ret_to_nx: Cannot PTRACE_TRACEME: %s"),
155 1.3 christos safe_strerror (errno));
156 1.1 christos else
157 1.1 christos {
158 1.1 christos #if defined __i386__
159 1.1 christos asm volatile ("pushl %0;"
160 1.1 christos ".globl linux_ptrace_test_ret_to_nx_instr;"
161 1.1 christos "linux_ptrace_test_ret_to_nx_instr:"
162 1.1 christos "ret"
163 1.6 christos : : "r" (return_address) : "memory");
164 1.1 christos #elif defined __x86_64__
165 1.1 christos asm volatile ("pushq %0;"
166 1.1 christos ".globl linux_ptrace_test_ret_to_nx_instr;"
167 1.1 christos "linux_ptrace_test_ret_to_nx_instr:"
168 1.1 christos "ret"
169 1.1 christos : : "r" ((uint64_t) (uintptr_t) return_address)
170 1.6 christos : "memory");
171 1.1 christos #else
172 1.1 christos # error "!__i386__ && !__x86_64__"
173 1.1 christos #endif
174 1.1 christos gdb_assert_not_reached ("asm block did not terminate");
175 1.1 christos }
176 1.1 christos
177 1.1 christos _exit (1);
178 1.1 christos }
179 1.1 christos
180 1.1 christos errno = 0;
181 1.10 christos got_pid = gdb::waitpid (child, &status, 0);
182 1.1 christos if (got_pid != child)
183 1.1 christos {
184 1.1 christos warning (_("linux_ptrace_test_ret_to_nx: waitpid returned %ld: %s"),
185 1.3 christos (long) got_pid, safe_strerror (errno));
186 1.1 christos return;
187 1.1 christos }
188 1.1 christos
189 1.1 christos if (WIFSIGNALED (status))
190 1.1 christos {
191 1.1 christos if (WTERMSIG (status) != SIGKILL)
192 1.1 christos warning (_("linux_ptrace_test_ret_to_nx: WTERMSIG %d is not SIGKILL!"),
193 1.1 christos (int) WTERMSIG (status));
194 1.1 christos else
195 1.1 christos warning (_("Cannot call inferior functions, Linux kernel PaX "
196 1.1 christos "protection forbids return to non-executable pages!"));
197 1.1 christos return;
198 1.1 christos }
199 1.1 christos
200 1.1 christos if (!WIFSTOPPED (status))
201 1.1 christos {
202 1.1 christos warning (_("linux_ptrace_test_ret_to_nx: status %d is not WIFSTOPPED!"),
203 1.1 christos status);
204 1.6 christos kill_child (child, "linux_ptrace_test_ret_to_nx");
205 1.1 christos return;
206 1.1 christos }
207 1.1 christos
208 1.1 christos /* We may get SIGSEGV due to missing PROT_EXEC of the return_address. */
209 1.1 christos if (WSTOPSIG (status) != SIGTRAP && WSTOPSIG (status) != SIGSEGV)
210 1.1 christos {
211 1.1 christos warning (_("linux_ptrace_test_ret_to_nx: "
212 1.1 christos "WSTOPSIG %d is neither SIGTRAP nor SIGSEGV!"),
213 1.1 christos (int) WSTOPSIG (status));
214 1.6 christos kill_child (child, "linux_ptrace_test_ret_to_nx");
215 1.1 christos return;
216 1.1 christos }
217 1.1 christos
218 1.4 christos if (ptrace (PTRACE_GETREGS, child, (PTRACE_TYPE_ARG3) 0,
219 1.4 christos (PTRACE_TYPE_ARG4) ®s) < 0)
220 1.4 christos {
221 1.4 christos warning (_("linux_ptrace_test_ret_to_nx: Cannot PTRACE_GETREGS: %s"),
222 1.4 christos safe_strerror (errno));
223 1.4 christos }
224 1.1 christos #if defined __i386__
225 1.4 christos pc = (gdb_byte *) (uintptr_t) regs[EIP];
226 1.1 christos #elif defined __x86_64__
227 1.4 christos pc = (gdb_byte *) (uintptr_t) regs[RIP];
228 1.1 christos #else
229 1.1 christos # error "!__i386__ && !__x86_64__"
230 1.1 christos #endif
231 1.1 christos
232 1.6 christos kill_child (child, "linux_ptrace_test_ret_to_nx");
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.4 christos linux_fork_to_function (gdb_byte *child_stack, int (*function) (void *))
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.6 christos child_stack = (gdb_byte *) 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 parent process forks a child. The child allows itself to
304 1.1 christos be traced by its parent. */
305 1.1 christos
306 1.4 christos static int
307 1.4 christos linux_child_function (void *child_stack)
308 1.1 christos {
309 1.1 christos ptrace (PTRACE_TRACEME, 0, (PTRACE_TYPE_ARG3) 0, (PTRACE_TYPE_ARG4) 0);
310 1.1 christos kill (getpid (), SIGSTOP);
311 1.1 christos
312 1.9 christos /* This code is only reachable by the child (grandchild's parent)
313 1.1 christos process. */
314 1.1 christos _exit (0);
315 1.1 christos }
316 1.1 christos
317 1.1 christos static void linux_test_for_exitkill (int child_pid);
318 1.1 christos
319 1.1 christos /* Determine ptrace features available on this target. */
320 1.1 christos
321 1.3 christos void
322 1.1 christos linux_check_ptrace_features (void)
323 1.1 christos {
324 1.1 christos int child_pid, ret, status;
325 1.1 christos
326 1.8 christos /* Initialize the options. We consider that these options are always
327 1.8 christos supported. */
328 1.8 christos supported_ptrace_options
329 1.8 christos = (PTRACE_O_TRACESYSGOOD
330 1.8 christos | PTRACE_O_TRACECLONE
331 1.8 christos | PTRACE_O_TRACEFORK
332 1.8 christos | PTRACE_O_TRACEVFORK
333 1.8 christos | PTRACE_O_TRACEVFORKDONE
334 1.8 christos | PTRACE_O_TRACEEXEC);
335 1.1 christos
336 1.1 christos /* Fork a child so we can do some testing. The child will call
337 1.1 christos linux_child_function and will get traced. The child will
338 1.1 christos eventually fork a grandchild so we can test fork event
339 1.1 christos reporting. */
340 1.1 christos child_pid = linux_fork_to_function (NULL, linux_child_function);
341 1.1 christos
342 1.1 christos ret = my_waitpid (child_pid, &status, 0);
343 1.1 christos if (ret == -1)
344 1.1 christos perror_with_name (("waitpid"));
345 1.1 christos else if (ret != child_pid)
346 1.1 christos error (_("linux_check_ptrace_features: waitpid: unexpected result %d."),
347 1.1 christos ret);
348 1.1 christos if (! WIFSTOPPED (status))
349 1.1 christos error (_("linux_check_ptrace_features: waitpid: unexpected status %d."),
350 1.1 christos status);
351 1.1 christos
352 1.1 christos linux_test_for_exitkill (child_pid);
353 1.1 christos
354 1.6 christos /* Kill child_pid. */
355 1.6 christos kill_child (child_pid, "linux_check_ptrace_features");
356 1.1 christos }
357 1.1 christos
358 1.1 christos /* Determine if PTRACE_O_EXITKILL can be used. */
359 1.1 christos
360 1.1 christos static void
361 1.1 christos linux_test_for_exitkill (int child_pid)
362 1.1 christos {
363 1.1 christos int ret;
364 1.1 christos
365 1.1 christos ret = ptrace (PTRACE_SETOPTIONS, child_pid, (PTRACE_TYPE_ARG3) 0,
366 1.1 christos (PTRACE_TYPE_ARG4) PTRACE_O_EXITKILL);
367 1.1 christos
368 1.1 christos if (ret == 0)
369 1.3 christos supported_ptrace_options |= PTRACE_O_EXITKILL;
370 1.1 christos }
371 1.1 christos
372 1.1 christos /* Enable reporting of all currently supported ptrace events.
373 1.3 christos OPTIONS is a bit mask of extended features we want enabled,
374 1.3 christos if supported by the kernel. PTRACE_O_TRACECLONE is always
375 1.3 christos enabled, if supported. */
376 1.1 christos
377 1.1 christos void
378 1.3 christos linux_enable_event_reporting (pid_t pid, int options)
379 1.1 christos {
380 1.1 christos /* Check if we have initialized the ptrace features for this
381 1.1 christos target. If not, do it now. */
382 1.3 christos if (supported_ptrace_options == -1)
383 1.1 christos linux_check_ptrace_features ();
384 1.1 christos
385 1.3 christos /* We always want clone events. */
386 1.3 christos options |= PTRACE_O_TRACECLONE;
387 1.3 christos
388 1.3 christos /* Filter out unsupported options. */
389 1.3 christos options &= supported_ptrace_options;
390 1.1 christos
391 1.1 christos /* Set the options. */
392 1.1 christos ptrace (PTRACE_SETOPTIONS, pid, (PTRACE_TYPE_ARG3) 0,
393 1.3 christos (PTRACE_TYPE_ARG4) (uintptr_t) options);
394 1.1 christos }
395 1.1 christos
396 1.1 christos /* Disable reporting of all currently supported ptrace events. */
397 1.1 christos
398 1.1 christos void
399 1.1 christos linux_disable_event_reporting (pid_t pid)
400 1.1 christos {
401 1.1 christos /* Set the options. */
402 1.1 christos ptrace (PTRACE_SETOPTIONS, pid, (PTRACE_TYPE_ARG3) 0, 0);
403 1.1 christos }
404 1.1 christos
405 1.1 christos /* Display possible problems on this system. Display them only once per GDB
406 1.1 christos execution. */
407 1.1 christos
408 1.1 christos void
409 1.1 christos linux_ptrace_init_warnings (void)
410 1.1 christos {
411 1.1 christos static int warned = 0;
412 1.1 christos
413 1.1 christos if (warned)
414 1.1 christos return;
415 1.1 christos warned = 1;
416 1.1 christos
417 1.1 christos linux_ptrace_test_ret_to_nx ();
418 1.1 christos }
419 1.1 christos
420 1.1 christos /* Extract extended ptrace event from wait status. */
421 1.1 christos
422 1.1 christos int
423 1.1 christos linux_ptrace_get_extended_event (int wstat)
424 1.1 christos {
425 1.1 christos return (wstat >> 16);
426 1.1 christos }
427 1.1 christos
428 1.1 christos /* Determine whether wait status denotes an extended event. */
429 1.1 christos
430 1.1 christos int
431 1.1 christos linux_is_extended_waitstatus (int wstat)
432 1.1 christos {
433 1.1 christos return (linux_ptrace_get_extended_event (wstat) != 0);
434 1.1 christos }
435 1.3 christos
436 1.3 christos /* Return true if the event in LP may be caused by breakpoint. */
437 1.3 christos
438 1.3 christos int
439 1.3 christos linux_wstatus_maybe_breakpoint (int wstat)
440 1.3 christos {
441 1.3 christos return (WIFSTOPPED (wstat)
442 1.3 christos && (WSTOPSIG (wstat) == SIGTRAP
443 1.3 christos /* SIGILL and SIGSEGV are also treated as traps in case a
444 1.3 christos breakpoint is inserted at the current PC. */
445 1.3 christos || WSTOPSIG (wstat) == SIGILL
446 1.3 christos || WSTOPSIG (wstat) == SIGSEGV));
447 1.3 christos }
448