1 /* Get Dwarf Frame state for target live PID process.
2 Copyright (C) 2013 Red Hat, Inc.
3 This file is part of elfutils.
5 This file is free software; you can redistribute it and/or modify
6 it under the terms of either
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
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
18 or both in parallel, as here.
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.
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/>. */
30 #include <sys/ptrace.h>
33 #include <sys/syscall.h>
37 # define MAX(a, b) ((a) > (b) ? (a) : (b))
43 /* It is 0 if not used. */
45 /* Valid only if TID_ATTACHED is not zero. */
50 linux_proc_pid_is_stopped (pid_t pid)
54 bool retval, have_state;
56 snprintf (buffer, sizeof (buffer), "/proc/%ld/status", (long) pid);
57 procfile = fopen (buffer, "r");
62 while (fgets (buffer, sizeof (buffer), procfile) != NULL)
63 if (strncmp (buffer, "State:", 6) == 0)
68 retval = (have_state && strstr (buffer, "T (stopped)") != NULL);
74 ptrace_attach (pid_t tid, bool *tid_was_stoppedp)
76 if (ptrace (PTRACE_ATTACH, tid, NULL, NULL) != 0)
78 __libdwfl_seterrno (DWFL_E_ERRNO);
81 *tid_was_stoppedp = linux_proc_pid_is_stopped (tid);
82 if (*tid_was_stoppedp)
84 /* Make sure there is a SIGSTOP signal pending even when the process is
85 already State: T (stopped). Older kernels might fail to generate
86 a SIGSTOP notification in that case in response to our PTRACE_ATTACH
87 above. Which would make the waitpid below wait forever. So emulate
88 it. Since there can only be one SIGSTOP notification pending this is
89 safe. See also gdb/linux-nat.c linux_nat_post_attach_wait. */
90 syscall (__NR_tkill, tid, SIGSTOP);
91 ptrace (PTRACE_CONT, tid, NULL, NULL);
96 if (waitpid (tid, &status, __WALL) != tid || !WIFSTOPPED (status))
98 int saved_errno = errno;
99 ptrace (PTRACE_DETACH, tid, NULL, NULL);
101 __libdwfl_seterrno (DWFL_E_ERRNO);
104 if (WSTOPSIG (status) == SIGSTOP)
106 if (ptrace (PTRACE_CONT, tid, NULL,
107 (void *) (uintptr_t) WSTOPSIG (status)) != 0)
109 int saved_errno = errno;
110 ptrace (PTRACE_DETACH, tid, NULL, NULL);
112 __libdwfl_seterrno (DWFL_E_ERRNO);
120 pid_memory_read (Dwfl *dwfl, Dwarf_Addr addr, Dwarf_Word *result, void *arg)
122 struct pid_arg *pid_arg = arg;
123 pid_t tid = pid_arg->tid_attached;
125 Dwfl_Process *process = dwfl->process;
126 if (ebl_get_elfclass (process->ebl) == ELFCLASS64)
130 *result = ptrace (PTRACE_PEEKDATA, tid, (void *) (uintptr_t) addr, NULL);
132 #else /* SIZEOF_LONG != 8 */
133 /* This should not happen. */
135 #endif /* SIZEOF_LONG != 8 */
138 /* We do not care about reads unaliged to 4 bytes boundary.
139 But 0x...ffc read of 8 bytes could overrun a page. */
140 bool lowered = (addr & 4) != 0;
143 #endif /* SIZEOF_LONG == 8 */
145 *result = ptrace (PTRACE_PEEKDATA, tid, (void *) (uintptr_t) addr, NULL);
149 # if BYTE_ORDER == BIG_ENDIAN
156 #endif /* SIZEOF_LONG == 8 */
157 *result &= 0xffffffff;
162 pid_next_thread (Dwfl *dwfl __attribute__ ((unused)), void *dwfl_arg,
165 struct pid_arg *pid_arg = dwfl_arg;
166 struct dirent *dirent;
167 /* Start fresh on first traversal. */
168 if (*thread_argp == NULL)
169 rewinddir (pid_arg->dir);
173 dirent = readdir (pid_arg->dir);
178 __libdwfl_seterrno (DWFL_E_ERRNO);
184 while (strcmp (dirent->d_name, ".") == 0
185 || strcmp (dirent->d_name, "..") == 0);
188 long tidl = strtol (dirent->d_name, &end, 10);
191 __libdwfl_seterrno (DWFL_E_ERRNO);
195 if (tidl <= 0 || (end && *end) || tid != tidl)
197 __libdwfl_seterrno (DWFL_E_PARSE_PROC);
200 *thread_argp = dwfl_arg;
204 /* Implement the ebl_set_initial_registers_tid setfunc callback. */
207 pid_thread_state_registers_cb (int firstreg, unsigned nregs,
208 const Dwarf_Word *regs, void *arg)
210 Dwfl_Thread *thread = (Dwfl_Thread *) arg;
213 assert (firstreg == -1);
215 INTUSE(dwfl_thread_state_register_pc) (thread, *regs);
219 return INTUSE(dwfl_thread_state_registers) (thread, firstreg, nregs, regs);
223 pid_set_initial_registers (Dwfl_Thread *thread, void *thread_arg)
225 struct pid_arg *pid_arg = thread_arg;
226 assert (pid_arg->tid_attached == 0);
227 pid_t tid = INTUSE(dwfl_thread_tid) (thread);
228 if (! ptrace_attach (tid, &pid_arg->tid_was_stopped))
230 pid_arg->tid_attached = tid;
231 Dwfl_Process *process = thread->process;
232 Ebl *ebl = process->ebl;
233 return ebl_set_initial_registers_tid (ebl, tid,
234 pid_thread_state_registers_cb, thread);
238 pid_detach (Dwfl *dwfl __attribute__ ((unused)), void *dwfl_arg)
240 struct pid_arg *pid_arg = dwfl_arg;
241 closedir (pid_arg->dir);
246 pid_thread_detach (Dwfl_Thread *thread, void *thread_arg)
248 struct pid_arg *pid_arg = thread_arg;
249 pid_t tid = INTUSE(dwfl_thread_tid) (thread);
250 assert (pid_arg->tid_attached == tid);
251 pid_arg->tid_attached = 0;
252 /* This handling is needed only on older Linux kernels such as
253 2.6.32-358.23.2.el6.ppc64. Later kernels such as 3.11.7-200.fc19.x86_64
254 remember the T (stopped) state themselves and no longer need to pass
255 SIGSTOP during PTRACE_DETACH. */
256 ptrace (PTRACE_DETACH, tid, NULL,
257 (void *) (intptr_t) (pid_arg->tid_was_stopped ? SIGSTOP : 0));
260 static const Dwfl_Thread_Callbacks pid_thread_callbacks =
264 pid_set_initial_registers,
271 __libdwfl_attach_state_for_pid (Dwfl *dwfl, pid_t pid)
274 int i = snprintf (dirname, sizeof (dirname), "/proc/%ld/task", (long) pid);
275 assert (i > 0 && i < (ssize_t) sizeof (dirname) - 1);
276 DIR *dir = opendir (dirname);
279 __libdwfl_seterrno (DWFL_E_ERRNO);
282 struct pid_arg *pid_arg = malloc (sizeof *pid_arg);
286 __libdwfl_seterrno (DWFL_E_NOMEM);
290 pid_arg->tid_attached = 0;
291 if (! INTUSE(dwfl_attach_state) (dwfl, NULL, pid, &pid_thread_callbacks,