Branch data Line data Source code
1 : : /* Get Dwarf Frame state for target live PID process.
2 : : Copyright (C) 2013, 2014, 2015, 2018, 2025 Red Hat, Inc.
3 : : This file is part of elfutils.
4 : :
5 : : This file is free software; you can redistribute it and/or modify
6 : : it under the terms of either
7 : :
8 : : * the GNU Lesser General Public License as published by the Free
9 : : Software Foundation; either version 3 of the License, or (at
10 : : your option) any later version
11 : :
12 : : or
13 : :
14 : : * the GNU General Public License as published by the Free
15 : : Software Foundation; either version 2 of the License, or (at
16 : : your option) any later version
17 : :
18 : : or both in parallel, as here.
19 : :
20 : : elfutils is distributed in the hope that it will be useful, but
21 : : WITHOUT ANY WARRANTY; without even the implied warranty of
22 : : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23 : : General Public License for more details.
24 : :
25 : : You should have received copies of the GNU General Public License and
26 : : the GNU Lesser General Public License along with this program. If
27 : : not, see <http://www.gnu.org/licenses/>. */
28 : :
29 : : #ifdef HAVE_CONFIG_H
30 : : # include <config.h>
31 : : #endif
32 : :
33 : : #include <system.h>
34 : :
35 : : #include "libelfP.h"
36 : : #include "libdwflP.h"
37 : : #include <sys/types.h>
38 : : #include <sys/stat.h>
39 : : #include <fcntl.h>
40 : : #include <dirent.h>
41 : :
42 : : #ifdef __linux__
43 : :
44 : : #include <sys/uio.h>
45 : : #include <sys/ptrace.h>
46 : : #include <sys/syscall.h>
47 : : #include <sys/wait.h>
48 : :
49 : : static bool
50 : 14 : linux_proc_pid_is_stopped (pid_t pid)
51 : : {
52 : 14 : char buffer[64];
53 : 14 : FILE *procfile;
54 : 14 : bool retval, have_state;
55 : :
56 : 14 : snprintf (buffer, sizeof (buffer), "/proc/%ld/status", (long) pid);
57 : 14 : procfile = fopen (buffer, "r");
58 [ + - ]: 14 : if (procfile == NULL)
59 : : return false;
60 : :
61 : 42 : have_state = false;
62 [ + - ]: 42 : while (fgets (buffer, sizeof (buffer), procfile) != NULL)
63 [ + + ]: 42 : if (startswith (buffer, "State:"))
64 : : {
65 : : have_state = true;
66 : : break;
67 : : }
68 [ + - + - ]: 14 : retval = (have_state && strstr (buffer, "T (stopped)") != NULL);
69 : 14 : fclose (procfile);
70 : 14 : return retval;
71 : : }
72 : :
73 : : bool
74 : : internal_function
75 : 16 : __libdwfl_ptrace_attach (pid_t tid, bool *tid_was_stoppedp)
76 : : {
77 [ + + ]: 16 : if (ptrace (PTRACE_ATTACH, tid, NULL, NULL) != 0)
78 : : {
79 : 2 : __libdwfl_seterrno (DWFL_E_ERRNO);
80 : 2 : return false;
81 : : }
82 : 14 : *tid_was_stoppedp = linux_proc_pid_is_stopped (tid);
83 [ - + ]: 14 : if (*tid_was_stoppedp)
84 : : {
85 : : /* Make sure there is a SIGSTOP signal pending even when the process is
86 : : already State: T (stopped). Older kernels might fail to generate
87 : : a SIGSTOP notification in that case in response to our PTRACE_ATTACH
88 : : above. Which would make the waitpid below wait forever. So emulate
89 : : it. Since there can only be one SIGSTOP notification pending this is
90 : : safe. See also gdb/linux-nat.c linux_nat_post_attach_wait. */
91 : 0 : syscall (__NR_tkill, tid, SIGSTOP);
92 : 0 : ptrace (PTRACE_CONT, tid, NULL, NULL);
93 : : }
94 : 14 : for (;;)
95 : 0 : {
96 : 14 : int status;
97 [ + - - + ]: 14 : if (waitpid (tid, &status, __WALL) != tid || !WIFSTOPPED (status))
98 : : {
99 : 0 : int saved_errno = errno;
100 : 0 : ptrace (PTRACE_DETACH, tid, NULL, NULL);
101 : 0 : errno = saved_errno;
102 : 0 : __libdwfl_seterrno (DWFL_E_ERRNO);
103 : 0 : return false;
104 : : }
105 [ - + ]: 14 : if (WSTOPSIG (status) == SIGSTOP)
106 : : break;
107 [ # # ]: 0 : if (ptrace (PTRACE_CONT, tid, NULL,
108 : 0 : (void *) (uintptr_t) WSTOPSIG (status)) != 0)
109 : : {
110 : 0 : int saved_errno = errno;
111 : 0 : ptrace (PTRACE_DETACH, tid, NULL, NULL);
112 : 0 : errno = saved_errno;
113 : 0 : __libdwfl_seterrno (DWFL_E_ERRNO);
114 : 0 : return false;
115 : : }
116 : : }
117 : 14 : return true;
118 : : }
119 : :
120 : : #ifdef HAVE_PROCESS_VM_READV
121 : : /* Note that the result word size depends on the architecture word size.
122 : : That is sizeof long. */
123 : : static bool
124 : 130 : read_cached_memory (struct __libdwfl_pid_arg *pid_arg,
125 : : Dwarf_Addr addr, Dwarf_Word *result)
126 : : {
127 : : /* Let the ptrace fallback deal with the corner case of the address
128 : : possibly crossing a page boundary. */
129 [ - + ]: 130 : if ((addr & ((Dwarf_Addr)__LIBDWFL_REMOTE_MEM_CACHE_SIZE - 1))
130 : : > (Dwarf_Addr)__LIBDWFL_REMOTE_MEM_CACHE_SIZE - sizeof (unsigned long))
131 : : return false;
132 : :
133 : 130 : struct __libdwfl_remote_mem_cache *mem_cache = pid_arg->mem_cache;
134 [ + + ]: 130 : if (mem_cache == NULL)
135 : : {
136 : 6 : size_t mem_cache_size = sizeof (struct __libdwfl_remote_mem_cache);
137 : 6 : mem_cache = malloc (mem_cache_size);
138 [ - + ]: 6 : if (mem_cache == NULL)
139 : : return false;
140 : :
141 : 6 : mem_cache->addr = 0;
142 : 6 : mem_cache->len = 0;
143 : 6 : pid_arg->mem_cache = mem_cache;
144 : : }
145 : :
146 : 130 : unsigned char *d;
147 [ + + + + ]: 130 : if (addr >= mem_cache->addr && addr - mem_cache->addr < mem_cache->len)
148 : : {
149 : 121 : d = &mem_cache->buf[addr - mem_cache->addr];
150 [ + - ]: 121 : if ((((uintptr_t) d) & (sizeof (unsigned long) - 1)) == 0)
151 : 121 : *result = *(unsigned long *) d;
152 : : else
153 : 0 : memcpy (result, d, sizeof (unsigned long));
154 : 121 : return true;
155 : : }
156 : :
157 : 9 : struct iovec local, remote;
158 : 9 : mem_cache->addr = addr & ~((Dwarf_Addr)__LIBDWFL_REMOTE_MEM_CACHE_SIZE - 1);
159 : 9 : local.iov_base = mem_cache->buf;
160 : 9 : local.iov_len = __LIBDWFL_REMOTE_MEM_CACHE_SIZE;
161 : 9 : remote.iov_base = (void *) (uintptr_t) mem_cache->addr;
162 : 9 : remote.iov_len = __LIBDWFL_REMOTE_MEM_CACHE_SIZE;
163 : :
164 : 9 : ssize_t res = process_vm_readv (pid_arg->tid_attached,
165 : : &local, 1, &remote, 1, 0);
166 [ - + ]: 9 : if (res != __LIBDWFL_REMOTE_MEM_CACHE_SIZE)
167 : : {
168 : 0 : mem_cache->len = 0;
169 : 0 : return false;
170 : : }
171 : :
172 : 9 : mem_cache->len = res;
173 : 9 : d = &mem_cache->buf[addr - mem_cache->addr];
174 [ + - ]: 9 : if ((((uintptr_t) d) & (sizeof (unsigned long) - 1)) == 0)
175 : 9 : *result = *(unsigned long *) d;
176 : : else
177 : 0 : memcpy (result, d, sizeof (unsigned long));
178 : : return true;
179 : : }
180 : : #endif /* HAVE_PROCESS_VM_READV */
181 : :
182 : : static void
183 : 6 : clear_cached_memory (struct __libdwfl_pid_arg *pid_arg)
184 : : {
185 : 6 : struct __libdwfl_remote_mem_cache *mem_cache = pid_arg->mem_cache;
186 : 6 : if (mem_cache != NULL)
187 : 6 : mem_cache->len = 0;
188 : : }
189 : :
190 : : /* Note that the result word size depends on the architecture word size.
191 : : That is sizeof long. */
192 : : static bool
193 : 130 : pid_memory_read (Dwfl *dwfl, Dwarf_Addr addr, Dwarf_Word *result, void *arg)
194 : : {
195 : 130 : struct __libdwfl_pid_arg *pid_arg = arg;
196 : 130 : pid_t tid = pid_arg->tid_attached;
197 : 130 : Dwfl_Process *process = dwfl->process;
198 [ - + ]: 130 : assert (tid > 0);
199 : :
200 : : #ifdef HAVE_PROCESS_VM_READV
201 [ + - ]: 130 : if (read_cached_memory (pid_arg, addr, result))
202 : : {
203 : : #if SIZEOF_LONG == 8
204 : : # if BYTE_ORDER == BIG_ENDIAN
205 : : if (ebl_get_elfclass (process->ebl) == ELFCLASS32)
206 : : *result >>= 32;
207 : : # endif
208 : : #endif
209 : : return true;
210 : : }
211 : : #endif
212 : :
213 [ # # ]: 0 : if (ebl_get_elfclass (process->ebl) == ELFCLASS64)
214 : : {
215 : : #if SIZEOF_LONG == 8
216 : 0 : errno = 0;
217 : 0 : *result = ptrace (PTRACE_PEEKDATA, tid, (void *) (uintptr_t) addr, NULL);
218 : 0 : return errno == 0;
219 : : #else /* SIZEOF_LONG != 8 */
220 : : /* This should not happen. */
221 : : return false;
222 : : #endif /* SIZEOF_LONG != 8 */
223 : : }
224 : : #if SIZEOF_LONG == 8
225 : : /* We do not care about reads unaliged to 4 bytes boundary.
226 : : But 0x...ffc read of 8 bytes could overrun a page. */
227 : 0 : bool lowered = (addr & 4) != 0;
228 [ # # ]: 0 : if (lowered)
229 : 0 : addr -= 4;
230 : : #endif /* SIZEOF_LONG == 8 */
231 : 0 : errno = 0;
232 : 0 : *result = ptrace (PTRACE_PEEKDATA, tid, (void *) (uintptr_t) addr, NULL);
233 [ # # ]: 0 : if (errno != 0)
234 : : return false;
235 : : #if SIZEOF_LONG == 8
236 : : # if BYTE_ORDER == BIG_ENDIAN
237 : : if (! lowered)
238 : : *result >>= 32;
239 : : # else
240 [ # # ]: 0 : if (lowered)
241 : 0 : *result >>= 32;
242 : : # endif
243 : : #endif /* SIZEOF_LONG == 8 */
244 : 0 : *result &= 0xffffffff;
245 : 0 : return true;
246 : : }
247 : :
248 : : static pid_t
249 : 20 : pid_next_thread (Dwfl *dwfl __attribute__ ((unused)), void *dwfl_arg,
250 : : void **thread_argp)
251 : : {
252 : 20 : struct __libdwfl_pid_arg *pid_arg = dwfl_arg;
253 : 20 : struct dirent *dirent;
254 : : /* Start fresh on first traversal. */
255 [ + + ]: 20 : if (*thread_argp == NULL)
256 : 8 : rewinddir (pid_arg->dir);
257 : 36 : do
258 : : {
259 : 36 : errno = 0;
260 : 36 : dirent = readdir (pid_arg->dir);
261 [ + + ]: 36 : if (dirent == NULL)
262 : : {
263 [ - + ]: 6 : if (errno != 0)
264 : : {
265 : 0 : __libdwfl_seterrno (DWFL_E_ERRNO);
266 : 0 : return -1;
267 : : }
268 : : return 0;
269 : : }
270 : : }
271 : 30 : while (strcmp (dirent->d_name, ".") == 0
272 [ + + + + ]: 30 : || strcmp (dirent->d_name, "..") == 0);
273 : 14 : char *end;
274 : 14 : errno = 0;
275 : 14 : long tidl = strtol (dirent->d_name, &end, 10);
276 [ - + ]: 14 : if (errno != 0)
277 : : {
278 : 0 : __libdwfl_seterrno (DWFL_E_ERRNO);
279 : 0 : return -1;
280 : : }
281 : 14 : pid_t tid = tidl;
282 [ + - + - : 14 : if (tidl <= 0 || (end && *end) || tid != tidl)
+ - - + ]
283 : : {
284 : 0 : __libdwfl_seterrno (DWFL_E_PARSE_PROC);
285 : 0 : return -1;
286 : : }
287 : 14 : *thread_argp = dwfl_arg;
288 : 14 : return tid;
289 : : }
290 : :
291 : : /* Just checks that the thread id exists. */
292 : : static bool
293 : 0 : pid_getthread (Dwfl *dwfl __attribute__ ((unused)), pid_t tid,
294 : : void *dwfl_arg, void **thread_argp)
295 : : {
296 : 0 : *thread_argp = dwfl_arg;
297 [ # # ]: 0 : if (kill (tid, 0) < 0)
298 : : {
299 : 0 : __libdwfl_seterrno (DWFL_E_ERRNO);
300 : 0 : return false;
301 : : }
302 : : return true;
303 : : }
304 : :
305 : : static bool
306 : 8 : pid_set_initial_registers (Dwfl_Thread *thread, void *thread_arg)
307 : : {
308 : 8 : struct __libdwfl_pid_arg *pid_arg = thread_arg;
309 [ - + ]: 8 : assert (pid_arg->tid_attached == 0);
310 : 8 : pid_t tid = INTUSE(dwfl_thread_tid) (thread);
311 [ + + ]: 8 : if (! pid_arg->assume_ptrace_stopped
312 [ + - ]: 2 : && ! __libdwfl_ptrace_attach (tid, &pid_arg->tid_was_stopped))
313 : : return false;
314 : 8 : pid_arg->tid_attached = tid;
315 : 8 : Dwfl_Process *process = thread->process;
316 : 8 : Ebl *ebl = process->ebl;
317 : 8 : return ebl_set_initial_registers_tid (ebl, tid,
318 : : __libdwfl_set_initial_registers_thread, thread);
319 : : }
320 : :
321 : : static void
322 : 26 : pid_detach (Dwfl *dwfl __attribute__ ((unused)), void *dwfl_arg)
323 : : {
324 : 26 : struct __libdwfl_pid_arg *pid_arg = dwfl_arg;
325 : 26 : elf_end (pid_arg->elf);
326 : 26 : free (pid_arg->mem_cache);
327 : 26 : close (pid_arg->elf_fd);
328 : 26 : closedir (pid_arg->dir);
329 : 26 : free (pid_arg);
330 : 26 : }
331 : :
332 : : void
333 : : internal_function
334 : 14 : __libdwfl_ptrace_detach (pid_t tid, bool tid_was_stopped)
335 : : {
336 : : /* This handling is needed only on older Linux kernels such as
337 : : 2.6.32-358.23.2.el6.ppc64. Later kernels such as
338 : : 3.11.7-200.fc19.x86_64 remember the T (stopped) state
339 : : themselves and no longer need to pass SIGSTOP during
340 : : PTRACE_DETACH. */
341 [ + - ]: 28 : ptrace (PTRACE_DETACH, tid, NULL,
342 : : (void *) (intptr_t) (tid_was_stopped ? SIGSTOP : 0));
343 : 14 : }
344 : :
345 : : static void
346 : 6 : pid_thread_detach (Dwfl_Thread *thread, void *thread_arg)
347 : : {
348 : 6 : struct __libdwfl_pid_arg *pid_arg = thread_arg;
349 : 6 : pid_t tid = INTUSE(dwfl_thread_tid) (thread);
350 [ - + ]: 6 : assert (pid_arg->tid_attached == tid);
351 : 6 : pid_arg->tid_attached = 0;
352 [ + - ]: 6 : clear_cached_memory (pid_arg);
353 [ + + ]: 6 : if (! pid_arg->assume_ptrace_stopped)
354 : 2 : __libdwfl_ptrace_detach (tid, pid_arg->tid_was_stopped);
355 : 6 : }
356 : :
357 : : static const Dwfl_Thread_Callbacks pid_thread_callbacks =
358 : : {
359 : : pid_next_thread,
360 : : pid_getthread,
361 : : pid_memory_read,
362 : : pid_set_initial_registers,
363 : : pid_detach,
364 : : pid_thread_detach,
365 : : };
366 : :
367 : : int
368 : 28 : dwfl_linux_proc_attach (Dwfl *dwfl, pid_t pid, bool assume_ptrace_stopped)
369 : : {
370 : 28 : char buffer[36];
371 : 28 : FILE *procfile;
372 : 28 : int err = 0; /* The errno to return and set for dwfl->attcherr. */
373 : :
374 : : /* Make sure to report the actual PID (thread group leader) to
375 : : dwfl_attach_state. */
376 : 28 : snprintf (buffer, sizeof (buffer), "/proc/%ld/status", (long) pid);
377 : 28 : procfile = fopen (buffer, "r");
378 [ - + ]: 28 : if (procfile == NULL)
379 : : {
380 : 0 : err = errno;
381 : 0 : fail:
382 [ # # # # ]: 0 : if (dwfl->process == NULL && dwfl->attacherr == DWFL_E_NOERROR)
383 : : {
384 : 0 : errno = err;
385 : 0 : dwfl->attacherr = __libdwfl_canon_error (DWFL_E_ERRNO);
386 : : }
387 : 0 : return err;
388 : : }
389 : :
390 : 28 : char *line = NULL;
391 : 28 : size_t linelen = 0;
392 [ + - ]: 112 : while (getline (&line, &linelen, procfile) >= 0)
393 [ + + ]: 112 : if (startswith (line, "Tgid:"))
394 : : {
395 : 28 : errno = 0;
396 : 28 : char *endptr;
397 : 28 : long val = strtol (&line[5], &endptr, 10);
398 [ - + - - ]: 28 : if ((errno == ERANGE && val == LONG_MAX)
399 [ - + - + : 28 : || *endptr != '\n' || val < 0 || val != (pid_t) val)
- + ]
400 : : pid = 0;
401 : : else
402 : 28 : pid = (pid_t) val;
403 : 28 : break;
404 : : }
405 : 28 : free (line);
406 : 28 : fclose (procfile);
407 : :
408 [ - + ]: 28 : if (pid == 0)
409 : : {
410 : 0 : err = ESRCH;
411 : 0 : goto fail;
412 : : }
413 : :
414 : 28 : char name[64];
415 [ - + ]: 28 : int i = snprintf (name, sizeof (name), "/proc/%ld/task", (long) pid);
416 [ - + ]: 28 : if (i <= 0 || i >= (ssize_t) sizeof (name) - 1)
417 : : {
418 : 0 : errno = -ENOMEM;
419 : 0 : goto fail;
420 : : }
421 : 28 : DIR *dir = opendir (name);
422 [ - + ]: 28 : if (dir == NULL)
423 : : {
424 : 0 : err = errno;
425 : 0 : goto fail;
426 : : }
427 : :
428 : 28 : Elf *elf;
429 [ - + ]: 28 : i = snprintf (name, sizeof (name), "/proc/%ld/exe", (long) pid);
430 [ - + ]: 28 : assert (i > 0 && i < (ssize_t) sizeof (name) - 1);
431 : 28 : int elf_fd = open (name, O_RDONLY);
432 [ + - ]: 28 : if (elf_fd >= 0)
433 : : {
434 : 28 : elf = elf_begin (elf_fd, ELF_C_READ_MMAP, NULL);
435 [ - + ]: 28 : if (elf == NULL)
436 : : {
437 : : /* Just ignore, dwfl_attach_state will fall back to trying
438 : : to associate the Dwfl with one of the existing DWfl_Module
439 : : ELF images (to know the machine/class backend to use). */
440 : 0 : close (elf_fd);
441 : 0 : elf_fd = -1;
442 : : }
443 : : }
444 : : else
445 : : elf = NULL;
446 : 28 : struct __libdwfl_pid_arg *pid_arg = malloc (sizeof *pid_arg);
447 [ - + ]: 28 : if (pid_arg == NULL)
448 : : {
449 : 0 : elf_end (elf);
450 : 0 : close (elf_fd);
451 : 0 : closedir (dir);
452 : 0 : err = ENOMEM;
453 : 0 : goto fail;
454 : : }
455 : 28 : pid_arg->dir = dir;
456 : 28 : pid_arg->elf = elf;
457 : 28 : pid_arg->elf_fd = elf_fd;
458 : 28 : pid_arg->mem_cache = NULL;
459 : 28 : pid_arg->tid_attached = 0;
460 : 28 : pid_arg->assume_ptrace_stopped = assume_ptrace_stopped;
461 [ - + ]: 28 : if (! INTUSE(dwfl_attach_state) (dwfl, elf, pid, &pid_thread_callbacks,
462 : : pid_arg))
463 : : {
464 : 0 : elf_end (elf);
465 : 0 : close (elf_fd);
466 : 0 : closedir (dir);
467 : 0 : free (pid_arg);
468 : 0 : return -1;
469 : : }
470 : : return 0;
471 : : }
472 : : INTDEF (dwfl_linux_proc_attach)
473 : :
474 : : struct __libdwfl_pid_arg *
475 : : internal_function
476 : 16 : __libdwfl_get_pid_arg (Dwfl *dwfl)
477 : : {
478 [ + - + - ]: 16 : if (dwfl != NULL && dwfl->process != NULL
479 [ + - ]: 16 : && dwfl->process->callbacks == &pid_thread_callbacks)
480 : 16 : return (struct __libdwfl_pid_arg *) dwfl->process->callbacks_arg;
481 : :
482 : : return NULL;
483 : : }
484 : :
485 : : #else /* __linux__ */
486 : :
487 : : bool
488 : : internal_function
489 : : __libdwfl_ptrace_attach (pid_t tid __attribute__ ((unused)),
490 : : bool *tid_was_stoppedp __attribute__ ((unused)))
491 : : {
492 : : errno = ENOSYS;
493 : : __libdwfl_seterrno (DWFL_E_ERRNO);
494 : : return false;
495 : : }
496 : :
497 : : void
498 : : internal_function
499 : : __libdwfl_ptrace_detach (pid_t tid __attribute__ ((unused)),
500 : : bool tid_was_stopped __attribute__ ((unused)))
501 : : {
502 : : }
503 : :
504 : : int
505 : : dwfl_linux_proc_attach (Dwfl *dwfl __attribute__ ((unused)),
506 : : pid_t pid __attribute__ ((unused)),
507 : : bool assume_ptrace_stopped __attribute__ ((unused)))
508 : : {
509 : : return ENOSYS;
510 : : }
511 : : INTDEF (dwfl_linux_proc_attach)
512 : :
513 : : struct __libdwfl_pid_arg *
514 : : internal_function
515 : : __libdwfl_get_pid_arg (Dwfl *dwfl __attribute__ ((unused)))
516 : : {
517 : : return NULL;
518 : : }
519 : :
520 : : #endif /* ! __linux __ */
521 : :
|