Line data Source code
1 : /* Get Dwarf Frame state for target live PID process.
2 : Copyright (C) 2013, 2014, 2015 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 "libelfP.h"
34 : #include "libdwflP.h"
35 : #include <sys/types.h>
36 : #include <sys/stat.h>
37 : #include <fcntl.h>
38 : #include <sys/wait.h>
39 : #include <dirent.h>
40 : #include <unistd.h>
41 :
42 : #ifdef __linux__
43 :
44 : #include <sys/ptrace.h>
45 : #include <sys/syscall.h>
46 :
47 : static bool
48 3 : linux_proc_pid_is_stopped (pid_t pid)
49 : {
50 : char buffer[64];
51 : FILE *procfile;
52 : bool retval, have_state;
53 :
54 6 : snprintf (buffer, sizeof (buffer), "/proc/%ld/status", (long) pid);
55 3 : procfile = fopen (buffer, "r");
56 3 : if (procfile == NULL)
57 : return false;
58 :
59 : have_state = false;
60 9 : while (fgets (buffer, sizeof (buffer), procfile) != NULL)
61 9 : if (strncmp (buffer, "State:", 6) == 0)
62 : {
63 : have_state = true;
64 : break;
65 : }
66 3 : retval = (have_state && strstr (buffer, "T (stopped)") != NULL);
67 3 : fclose (procfile);
68 3 : return retval;
69 : }
70 :
71 : bool
72 : internal_function
73 4 : __libdwfl_ptrace_attach (pid_t tid, bool *tid_was_stoppedp)
74 : {
75 4 : if (ptrace (PTRACE_ATTACH, tid, NULL, NULL) != 0)
76 : {
77 1 : __libdwfl_seterrno (DWFL_E_ERRNO);
78 1 : return false;
79 : }
80 3 : *tid_was_stoppedp = linux_proc_pid_is_stopped (tid);
81 3 : if (*tid_was_stoppedp)
82 : {
83 : /* Make sure there is a SIGSTOP signal pending even when the process is
84 : already State: T (stopped). Older kernels might fail to generate
85 : a SIGSTOP notification in that case in response to our PTRACE_ATTACH
86 : above. Which would make the waitpid below wait forever. So emulate
87 : it. Since there can only be one SIGSTOP notification pending this is
88 : safe. See also gdb/linux-nat.c linux_nat_post_attach_wait. */
89 0 : syscall (__NR_tkill, tid, SIGSTOP);
90 0 : ptrace (PTRACE_CONT, tid, NULL, NULL);
91 : }
92 : for (;;)
93 0 : {
94 : int status;
95 3 : if (waitpid (tid, &status, __WALL) != tid || !WIFSTOPPED (status))
96 : {
97 0 : int saved_errno = errno;
98 0 : ptrace (PTRACE_DETACH, tid, NULL, NULL);
99 0 : errno = saved_errno;
100 0 : __libdwfl_seterrno (DWFL_E_ERRNO);
101 0 : return false;
102 : }
103 3 : if (WSTOPSIG (status) == SIGSTOP)
104 : break;
105 0 : if (ptrace (PTRACE_CONT, tid, NULL,
106 0 : (void *) (uintptr_t) WSTOPSIG (status)) != 0)
107 : {
108 0 : int saved_errno = errno;
109 0 : ptrace (PTRACE_DETACH, tid, NULL, NULL);
110 0 : errno = saved_errno;
111 0 : __libdwfl_seterrno (DWFL_E_ERRNO);
112 0 : return false;
113 : }
114 : }
115 3 : return true;
116 : }
117 :
118 : static bool
119 92 : pid_memory_read (Dwfl *dwfl, Dwarf_Addr addr, Dwarf_Word *result, void *arg)
120 : {
121 92 : struct __libdwfl_pid_arg *pid_arg = arg;
122 92 : pid_t tid = pid_arg->tid_attached;
123 92 : assert (tid > 0);
124 92 : Dwfl_Process *process = dwfl->process;
125 92 : if (ebl_get_elfclass (process->ebl) == ELFCLASS64)
126 : {
127 : #if SIZEOF_LONG == 8
128 34 : errno = 0;
129 34 : *result = ptrace (PTRACE_PEEKDATA, tid, (void *) (uintptr_t) addr, NULL);
130 34 : return errno == 0;
131 : #else /* SIZEOF_LONG != 8 */
132 : /* This should not happen. */
133 : return false;
134 : #endif /* SIZEOF_LONG != 8 */
135 : }
136 : #if SIZEOF_LONG == 8
137 : /* We do not care about reads unaliged to 4 bytes boundary.
138 : But 0x...ffc read of 8 bytes could overrun a page. */
139 58 : bool lowered = (addr & 4) != 0;
140 58 : if (lowered)
141 30 : addr -= 4;
142 : #endif /* SIZEOF_LONG == 8 */
143 58 : errno = 0;
144 58 : *result = ptrace (PTRACE_PEEKDATA, tid, (void *) (uintptr_t) addr, NULL);
145 58 : if (errno != 0)
146 : return false;
147 : #if SIZEOF_LONG == 8
148 : # if BYTE_ORDER == BIG_ENDIAN
149 : if (! lowered)
150 : *result >>= 32;
151 : # else
152 58 : if (lowered)
153 30 : *result >>= 32;
154 : # endif
155 : #endif /* SIZEOF_LONG == 8 */
156 58 : *result &= 0xffffffff;
157 58 : return true;
158 : }
159 :
160 : static pid_t
161 13 : pid_next_thread (Dwfl *dwfl __attribute__ ((unused)), void *dwfl_arg,
162 : void **thread_argp)
163 : {
164 13 : struct __libdwfl_pid_arg *pid_arg = dwfl_arg;
165 : struct dirent *dirent;
166 : /* Start fresh on first traversal. */
167 13 : if (*thread_argp == NULL)
168 5 : rewinddir (pid_arg->dir);
169 : do
170 : {
171 23 : errno = 0;
172 23 : dirent = readdir (pid_arg->dir);
173 23 : if (dirent == NULL)
174 : {
175 4 : if (errno != 0)
176 : {
177 0 : __libdwfl_seterrno (DWFL_E_ERRNO);
178 0 : return -1;
179 : }
180 : return 0;
181 : }
182 : }
183 19 : while (strcmp (dirent->d_name, ".") == 0
184 19 : || strcmp (dirent->d_name, "..") == 0);
185 : char *end;
186 9 : errno = 0;
187 9 : long tidl = strtol (dirent->d_name, &end, 10);
188 9 : if (errno != 0)
189 : {
190 0 : __libdwfl_seterrno (DWFL_E_ERRNO);
191 0 : return -1;
192 : }
193 9 : pid_t tid = tidl;
194 9 : if (tidl <= 0 || (end && *end) || tid != tidl)
195 : {
196 0 : __libdwfl_seterrno (DWFL_E_PARSE_PROC);
197 0 : return -1;
198 : }
199 9 : *thread_argp = dwfl_arg;
200 9 : return tid;
201 : }
202 :
203 : /* Just checks that the thread id exists. */
204 : static bool
205 0 : pid_getthread (Dwfl *dwfl __attribute__ ((unused)), pid_t tid,
206 : void *dwfl_arg, void **thread_argp)
207 : {
208 0 : *thread_argp = dwfl_arg;
209 0 : if (kill (tid, 0) < 0)
210 : {
211 0 : __libdwfl_seterrno (DWFL_E_ERRNO);
212 0 : return false;
213 : }
214 : return true;
215 : }
216 :
217 : /* Implement the ebl_set_initial_registers_tid setfunc callback. */
218 :
219 : static bool
220 6 : pid_thread_state_registers_cb (int firstreg, unsigned nregs,
221 : const Dwarf_Word *regs, void *arg)
222 : {
223 6 : Dwfl_Thread *thread = (Dwfl_Thread *) arg;
224 6 : if (firstreg < 0)
225 : {
226 0 : assert (firstreg == -1);
227 0 : assert (nregs == 1);
228 0 : INTUSE(dwfl_thread_state_register_pc) (thread, *regs);
229 0 : return true;
230 : }
231 6 : assert (nregs > 0);
232 6 : return INTUSE(dwfl_thread_state_registers) (thread, firstreg, nregs, regs);
233 : }
234 :
235 : static bool
236 6 : pid_set_initial_registers (Dwfl_Thread *thread, void *thread_arg)
237 : {
238 6 : struct __libdwfl_pid_arg *pid_arg = thread_arg;
239 6 : assert (pid_arg->tid_attached == 0);
240 6 : pid_t tid = INTUSE(dwfl_thread_tid) (thread);
241 6 : if (! pid_arg->assume_ptrace_stopped
242 1 : && ! __libdwfl_ptrace_attach (tid, &pid_arg->tid_was_stopped))
243 : return false;
244 6 : pid_arg->tid_attached = tid;
245 6 : Dwfl_Process *process = thread->process;
246 6 : Ebl *ebl = process->ebl;
247 6 : return ebl_set_initial_registers_tid (ebl, tid,
248 : pid_thread_state_registers_cb, thread);
249 : }
250 :
251 : static void
252 9 : pid_detach (Dwfl *dwfl __attribute__ ((unused)), void *dwfl_arg)
253 : {
254 9 : struct __libdwfl_pid_arg *pid_arg = dwfl_arg;
255 9 : elf_end (pid_arg->elf);
256 9 : close (pid_arg->elf_fd);
257 9 : closedir (pid_arg->dir);
258 9 : free (pid_arg);
259 9 : }
260 :
261 : void
262 : internal_function
263 2 : __libdwfl_ptrace_detach (pid_t tid, bool tid_was_stopped)
264 : {
265 : /* This handling is needed only on older Linux kernels such as
266 : 2.6.32-358.23.2.el6.ppc64. Later kernels such as
267 : 3.11.7-200.fc19.x86_64 remember the T (stopped) state
268 : themselves and no longer need to pass SIGSTOP during
269 : PTRACE_DETACH. */
270 3 : ptrace (PTRACE_DETACH, tid, NULL,
271 : (void *) (intptr_t) (tid_was_stopped ? SIGSTOP : 0));
272 2 : }
273 :
274 : static void
275 5 : pid_thread_detach (Dwfl_Thread *thread, void *thread_arg)
276 : {
277 5 : struct __libdwfl_pid_arg *pid_arg = thread_arg;
278 5 : pid_t tid = INTUSE(dwfl_thread_tid) (thread);
279 5 : assert (pid_arg->tid_attached == tid);
280 5 : pid_arg->tid_attached = 0;
281 5 : if (! pid_arg->assume_ptrace_stopped)
282 1 : __libdwfl_ptrace_detach (tid, pid_arg->tid_was_stopped);
283 5 : }
284 :
285 : static const Dwfl_Thread_Callbacks pid_thread_callbacks =
286 : {
287 : pid_next_thread,
288 : pid_getthread,
289 : pid_memory_read,
290 : pid_set_initial_registers,
291 : pid_detach,
292 : pid_thread_detach,
293 : };
294 :
295 : int
296 12 : dwfl_linux_proc_attach (Dwfl *dwfl, pid_t pid, bool assume_ptrace_stopped)
297 : {
298 : char buffer[36];
299 : FILE *procfile;
300 12 : int err = 0; /* The errno to return and set for dwfl->attcherr. */
301 :
302 : /* Make sure to report the actual PID (thread group leader) to
303 : dwfl_attach_state. */
304 24 : snprintf (buffer, sizeof (buffer), "/proc/%ld/status", (long) pid);
305 12 : procfile = fopen (buffer, "r");
306 12 : if (procfile == NULL)
307 : {
308 0 : err = errno;
309 0 : fail:
310 0 : if (dwfl->process == NULL && dwfl->attacherr == DWFL_E_NOERROR)
311 : {
312 0 : errno = err;
313 0 : dwfl->attacherr = __libdwfl_canon_error (DWFL_E_ERRNO);
314 : }
315 : return err;
316 : }
317 :
318 12 : char *line = NULL;
319 12 : size_t linelen = 0;
320 60 : while (getline (&line, &linelen, procfile) >= 0)
321 48 : if (strncmp (line, "Tgid:", 5) == 0)
322 : {
323 12 : errno = 0;
324 : char *endptr;
325 12 : long val = strtol (&line[5], &endptr, 10);
326 12 : if ((errno == ERANGE && val == LONG_MAX)
327 12 : || *endptr != '\n' || val < 0 || val != (pid_t) val)
328 : pid = 0;
329 : else
330 12 : pid = (pid_t) val;
331 : break;
332 : }
333 12 : free (line);
334 12 : fclose (procfile);
335 :
336 12 : if (pid == 0)
337 : {
338 : err = ESRCH;
339 : goto fail;
340 : }
341 :
342 : char name[64];
343 24 : int i = snprintf (name, sizeof (name), "/proc/%ld/task", (long) pid);
344 12 : assert (i > 0 && i < (ssize_t) sizeof (name) - 1);
345 12 : DIR *dir = opendir (name);
346 12 : if (dir == NULL)
347 : {
348 0 : err = errno;
349 0 : goto fail;
350 : }
351 :
352 : Elf *elf;
353 24 : i = snprintf (name, sizeof (name), "/proc/%ld/exe", (long) pid);
354 12 : assert (i > 0 && i < (ssize_t) sizeof (name) - 1);
355 12 : int elf_fd = open (name, O_RDONLY);
356 12 : if (elf_fd >= 0)
357 : {
358 12 : elf = elf_begin (elf_fd, ELF_C_READ_MMAP, NULL);
359 12 : if (elf == NULL)
360 : {
361 : /* Just ignore, dwfl_attach_state will fall back to trying
362 : to associate the Dwfl with one of the existing DWfl_Module
363 : ELF images (to know the machine/class backend to use). */
364 0 : close (elf_fd);
365 0 : elf_fd = -1;
366 : }
367 : }
368 : else
369 : elf = NULL;
370 12 : struct __libdwfl_pid_arg *pid_arg = malloc (sizeof *pid_arg);
371 12 : if (pid_arg == NULL)
372 : {
373 0 : elf_end (elf);
374 0 : close (elf_fd);
375 0 : closedir (dir);
376 0 : err = ENOMEM;
377 0 : goto fail;
378 : }
379 12 : pid_arg->dir = dir;
380 12 : pid_arg->elf = elf;
381 12 : pid_arg->elf_fd = elf_fd;
382 12 : pid_arg->tid_attached = 0;
383 12 : pid_arg->assume_ptrace_stopped = assume_ptrace_stopped;
384 12 : if (! INTUSE(dwfl_attach_state) (dwfl, elf, pid, &pid_thread_callbacks,
385 : pid_arg))
386 : {
387 0 : elf_end (elf);
388 0 : close (elf_fd);
389 0 : closedir (dir);
390 0 : free (pid_arg);
391 0 : return -1;
392 : }
393 : return 0;
394 : }
395 : INTDEF (dwfl_linux_proc_attach)
396 :
397 : struct __libdwfl_pid_arg *
398 : internal_function
399 5 : __libdwfl_get_pid_arg (Dwfl *dwfl)
400 : {
401 5 : if (dwfl != NULL && dwfl->process != NULL
402 5 : && dwfl->process->callbacks == &pid_thread_callbacks)
403 5 : return (struct __libdwfl_pid_arg *) dwfl->process->callbacks_arg;
404 :
405 : return NULL;
406 : }
407 :
408 : #else /* __linux__ */
409 :
410 : bool
411 : internal_function
412 : __libdwfl_ptrace_attach (pid_t tid __attribute__ ((unused)),
413 : bool *tid_was_stoppedp __attribute__ ((unused)))
414 : {
415 : errno = ENOSYS;
416 : __libdwfl_seterrno (DWFL_E_ERRNO);
417 : return false;
418 : }
419 :
420 : void
421 : internal_function
422 : __libdwfl_ptrace_detach (pid_t tid __attribute__ ((unused)),
423 : bool tid_was_stopped __attribute__ ((unused)))
424 : {
425 : }
426 :
427 : int
428 : dwfl_linux_proc_attach (Dwfl *dwfl __attribute__ ((unused)),
429 : pid_t pid __attribute__ ((unused)),
430 : bool assume_ptrace_stopped __attribute__ ((unused)))
431 : {
432 : return ENOSYS;
433 : }
434 : INTDEF (dwfl_linux_proc_attach)
435 :
436 : struct __libdwfl_pid_arg *
437 : internal_function
438 : __libdwfl_get_pid_arg (Dwfl *dwfl __attribute__ ((unused)))
439 : {
440 : return NULL;
441 : }
442 :
443 : #endif /* ! __linux __ */
444 :
|