blob: 3d0716abd7d46b489fa8a0c0cab9f505edff5b16 [file] [log] [blame]
Jan Kratochvil0b867462013-05-30 14:37:38 +02001/* Get Dwarf Frame state for target live PID process.
2 Copyright (C) 2013 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 "libdwflP.h"
30#include <sys/ptrace.h>
31#include <sys/wait.h>
32#include <dirent.h>
33#include <sys/syscall.h>
34#include <unistd.h>
35
36#ifndef MAX
37# define MAX(a, b) ((a) > (b) ? (a) : (b))
38#endif
39
40struct pid_arg
41{
42 DIR *dir;
43 /* It is 0 if not used. */
44 pid_t tid_attached;
Jan Kratochvil10d7a392013-11-19 15:00:15 +010045 /* Valid only if TID_ATTACHED is not zero. */
46 bool tid_was_stopped;
Jan Kratochvil0b867462013-05-30 14:37:38 +020047};
48
49static bool
50linux_proc_pid_is_stopped (pid_t pid)
51{
52 char buffer[64];
53 FILE *procfile;
54 bool retval, have_state;
55
56 snprintf (buffer, sizeof (buffer), "/proc/%ld/status", (long) pid);
57 procfile = fopen (buffer, "r");
58 if (procfile == NULL)
59 return false;
60
61 have_state = false;
62 while (fgets (buffer, sizeof (buffer), procfile) != NULL)
63 if (strncmp (buffer, "State:", 6) == 0)
64 {
65 have_state = true;
66 break;
67 }
68 retval = (have_state && strstr (buffer, "T (stopped)") != NULL);
69 fclose (procfile);
70 return retval;
71}
72
73static bool
Jan Kratochvil10d7a392013-11-19 15:00:15 +010074ptrace_attach (pid_t tid, bool *tid_was_stoppedp)
Jan Kratochvil0b867462013-05-30 14:37:38 +020075{
76 if (ptrace (PTRACE_ATTACH, tid, NULL, NULL) != 0)
77 {
78 __libdwfl_seterrno (DWFL_E_ERRNO);
79 return false;
80 }
Jan Kratochvil10d7a392013-11-19 15:00:15 +010081 *tid_was_stoppedp = linux_proc_pid_is_stopped (tid);
82 if (*tid_was_stoppedp)
Jan Kratochvil0b867462013-05-30 14:37:38 +020083 {
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);
92 }
93 for (;;)
94 {
95 int status;
96 if (waitpid (tid, &status, __WALL) != tid || !WIFSTOPPED (status))
97 {
98 int saved_errno = errno;
99 ptrace (PTRACE_DETACH, tid, NULL, NULL);
100 errno = saved_errno;
101 __libdwfl_seterrno (DWFL_E_ERRNO);
102 return false;
103 }
104 if (WSTOPSIG (status) == SIGSTOP)
105 break;
106 if (ptrace (PTRACE_CONT, tid, NULL,
107 (void *) (uintptr_t) WSTOPSIG (status)) != 0)
108 {
109 int saved_errno = errno;
110 ptrace (PTRACE_DETACH, tid, NULL, NULL);
111 errno = saved_errno;
112 __libdwfl_seterrno (DWFL_E_ERRNO);
113 return false;
114 }
115 }
116 return true;
117}
118
119static bool
120pid_memory_read (Dwfl *dwfl, Dwarf_Addr addr, Dwarf_Word *result, void *arg)
121{
122 struct pid_arg *pid_arg = arg;
123 pid_t tid = pid_arg->tid_attached;
124 assert (tid > 0);
125 Dwfl_Process *process = dwfl->process;
126 if (ebl_get_elfclass (process->ebl) == ELFCLASS64)
127 {
128#if SIZEOF_LONG == 8
129 errno = 0;
130 *result = ptrace (PTRACE_PEEKDATA, tid, (void *) (uintptr_t) addr, NULL);
131 return errno == 0;
132#else /* SIZEOF_LONG != 8 */
133 /* This should not happen. */
134 return false;
135#endif /* SIZEOF_LONG != 8 */
136 }
137#if 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;
141 if (lowered)
142 addr -= 4;
143#endif /* SIZEOF_LONG == 8 */
144 errno = 0;
145 *result = ptrace (PTRACE_PEEKDATA, tid, (void *) (uintptr_t) addr, NULL);
146 if (errno != 0)
147 return false;
148#if SIZEOF_LONG == 8
149# if BYTE_ORDER == BIG_ENDIAN
150 if (! lowered)
151 *result >>= 32;
152# else
153 if (lowered)
154 *result >>= 32;
155# endif
156#endif /* SIZEOF_LONG == 8 */
157 *result &= 0xffffffff;
158 return true;
159}
160
161static pid_t
162pid_next_thread (Dwfl *dwfl __attribute__ ((unused)), void *dwfl_arg,
163 void **thread_argp)
164{
165 struct pid_arg *pid_arg = dwfl_arg;
166 struct dirent *dirent;
Mark Wielaardc76b2ff2013-12-17 10:37:29 +0100167 /* Start fresh on first traversal. */
168 if (*thread_argp == NULL)
169 rewinddir (pid_arg->dir);
Jan Kratochvil0b867462013-05-30 14:37:38 +0200170 do
171 {
172 errno = 0;
173 dirent = readdir (pid_arg->dir);
174 if (dirent == NULL)
175 {
176 if (errno != 0)
177 {
178 __libdwfl_seterrno (DWFL_E_ERRNO);
179 return -1;
180 }
181 return 0;
182 }
183 }
184 while (strcmp (dirent->d_name, ".") == 0
185 || strcmp (dirent->d_name, "..") == 0);
186 char *end;
187 errno = 0;
188 long tidl = strtol (dirent->d_name, &end, 10);
189 if (errno != 0)
190 {
191 __libdwfl_seterrno (DWFL_E_ERRNO);
192 return -1;
193 }
194 pid_t tid = tidl;
195 if (tidl <= 0 || (end && *end) || tid != tidl)
196 {
197 __libdwfl_seterrno (DWFL_E_PARSE_PROC);
198 return -1;
199 }
200 *thread_argp = dwfl_arg;
201 return tid;
202}
203
204/* Implement the ebl_set_initial_registers_tid setfunc callback. */
205
206static bool
Jan Kratochvil1c1a53b2013-11-14 20:55:41 +0100207pid_thread_state_registers_cb (int firstreg, unsigned nregs,
208 const Dwarf_Word *regs, void *arg)
Jan Kratochvil0b867462013-05-30 14:37:38 +0200209{
210 Dwfl_Thread *thread = (Dwfl_Thread *) arg;
Jan Kratochvil5cbf42a2013-12-15 18:56:17 +0100211 if (firstreg < 0)
212 {
213 assert (firstreg == -1);
214 assert (nregs == 1);
215 INTUSE(dwfl_thread_state_register_pc) (thread, *regs);
216 return true;
217 }
218 assert (nregs > 0);
Jan Kratochvil0b867462013-05-30 14:37:38 +0200219 return INTUSE(dwfl_thread_state_registers) (thread, firstreg, nregs, regs);
220}
221
222static bool
223pid_set_initial_registers (Dwfl_Thread *thread, void *thread_arg)
224{
225 struct pid_arg *pid_arg = thread_arg;
226 assert (pid_arg->tid_attached == 0);
227 pid_t tid = INTUSE(dwfl_thread_tid) (thread);
Jan Kratochvil10d7a392013-11-19 15:00:15 +0100228 if (! ptrace_attach (tid, &pid_arg->tid_was_stopped))
Jan Kratochvil0b867462013-05-30 14:37:38 +0200229 return false;
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);
235}
236
237static void
238pid_detach (Dwfl *dwfl __attribute__ ((unused)), void *dwfl_arg)
239{
240 struct pid_arg *pid_arg = dwfl_arg;
241 closedir (pid_arg->dir);
242 free (pid_arg);
243}
244
245static void
246pid_thread_detach (Dwfl_Thread *thread, void *thread_arg)
247{
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;
Jan Kratochvil10d7a392013-11-19 15:00:15 +0100252 /* 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));
Jan Kratochvil0b867462013-05-30 14:37:38 +0200258}
259
260static const Dwfl_Thread_Callbacks pid_thread_callbacks =
261{
262 pid_next_thread,
263 pid_memory_read,
264 pid_set_initial_registers,
265 pid_detach,
266 pid_thread_detach,
267};
268
269bool
270internal_function
271__libdwfl_attach_state_for_pid (Dwfl *dwfl, pid_t pid)
272{
273 char dirname[64];
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);
277 if (dir == NULL)
278 {
279 __libdwfl_seterrno (DWFL_E_ERRNO);
280 return false;
281 }
282 struct pid_arg *pid_arg = malloc (sizeof *pid_arg);
283 if (pid_arg == NULL)
284 {
285 closedir (dir);
286 __libdwfl_seterrno (DWFL_E_NOMEM);
287 return false;
288 }
289 pid_arg->dir = dir;
290 pid_arg->tid_attached = 0;
Jan Kratochviled782372013-11-14 20:53:20 +0100291 if (! INTUSE(dwfl_attach_state) (dwfl, NULL, pid, &pid_thread_callbacks,
Jan Kratochvil0b867462013-05-30 14:37:38 +0200292 pid_arg))
293 {
294 closedir (dir);
295 free (pid_arg);
296 return false;
297 }
298 return true;
299}