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