blob: 21ff4b99ec1a7b155c8480827c497b9860dcfb95 [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;
Mark Wielaard19108012013-12-30 22:00:57 +010047 /* True if threads are ptrace stopped by caller. */
48 bool assume_ptrace_stopped;
Jan Kratochvil0b867462013-05-30 14:37:38 +020049};
50
51static bool
52linux_proc_pid_is_stopped (pid_t pid)
53{
54 char buffer[64];
55 FILE *procfile;
56 bool retval, have_state;
57
58 snprintf (buffer, sizeof (buffer), "/proc/%ld/status", (long) pid);
59 procfile = fopen (buffer, "r");
60 if (procfile == NULL)
61 return false;
62
63 have_state = false;
64 while (fgets (buffer, sizeof (buffer), procfile) != NULL)
65 if (strncmp (buffer, "State:", 6) == 0)
66 {
67 have_state = true;
68 break;
69 }
70 retval = (have_state && strstr (buffer, "T (stopped)") != NULL);
71 fclose (procfile);
72 return retval;
73}
74
75static bool
Jan Kratochvil10d7a392013-11-19 15:00:15 +010076ptrace_attach (pid_t tid, bool *tid_was_stoppedp)
Jan Kratochvil0b867462013-05-30 14:37:38 +020077{
78 if (ptrace (PTRACE_ATTACH, tid, NULL, NULL) != 0)
79 {
80 __libdwfl_seterrno (DWFL_E_ERRNO);
81 return false;
82 }
Jan Kratochvil10d7a392013-11-19 15:00:15 +010083 *tid_was_stoppedp = linux_proc_pid_is_stopped (tid);
84 if (*tid_was_stoppedp)
Jan Kratochvil0b867462013-05-30 14:37:38 +020085 {
86 /* Make sure there is a SIGSTOP signal pending even when the process is
87 already State: T (stopped). Older kernels might fail to generate
88 a SIGSTOP notification in that case in response to our PTRACE_ATTACH
89 above. Which would make the waitpid below wait forever. So emulate
90 it. Since there can only be one SIGSTOP notification pending this is
91 safe. See also gdb/linux-nat.c linux_nat_post_attach_wait. */
92 syscall (__NR_tkill, tid, SIGSTOP);
93 ptrace (PTRACE_CONT, tid, NULL, NULL);
94 }
95 for (;;)
96 {
97 int status;
98 if (waitpid (tid, &status, __WALL) != tid || !WIFSTOPPED (status))
99 {
100 int saved_errno = errno;
101 ptrace (PTRACE_DETACH, tid, NULL, NULL);
102 errno = saved_errno;
103 __libdwfl_seterrno (DWFL_E_ERRNO);
104 return false;
105 }
106 if (WSTOPSIG (status) == SIGSTOP)
107 break;
108 if (ptrace (PTRACE_CONT, tid, NULL,
109 (void *) (uintptr_t) WSTOPSIG (status)) != 0)
110 {
111 int saved_errno = errno;
112 ptrace (PTRACE_DETACH, tid, NULL, NULL);
113 errno = saved_errno;
114 __libdwfl_seterrno (DWFL_E_ERRNO);
115 return false;
116 }
117 }
118 return true;
119}
120
121static bool
122pid_memory_read (Dwfl *dwfl, Dwarf_Addr addr, Dwarf_Word *result, void *arg)
123{
124 struct pid_arg *pid_arg = arg;
125 pid_t tid = pid_arg->tid_attached;
126 assert (tid > 0);
127 Dwfl_Process *process = dwfl->process;
128 if (ebl_get_elfclass (process->ebl) == ELFCLASS64)
129 {
130#if SIZEOF_LONG == 8
131 errno = 0;
132 *result = ptrace (PTRACE_PEEKDATA, tid, (void *) (uintptr_t) addr, NULL);
133 return errno == 0;
134#else /* SIZEOF_LONG != 8 */
135 /* This should not happen. */
136 return false;
137#endif /* SIZEOF_LONG != 8 */
138 }
139#if SIZEOF_LONG == 8
140 /* We do not care about reads unaliged to 4 bytes boundary.
141 But 0x...ffc read of 8 bytes could overrun a page. */
142 bool lowered = (addr & 4) != 0;
143 if (lowered)
144 addr -= 4;
145#endif /* SIZEOF_LONG == 8 */
146 errno = 0;
147 *result = ptrace (PTRACE_PEEKDATA, tid, (void *) (uintptr_t) addr, NULL);
148 if (errno != 0)
149 return false;
150#if SIZEOF_LONG == 8
151# if BYTE_ORDER == BIG_ENDIAN
152 if (! lowered)
153 *result >>= 32;
154# else
155 if (lowered)
156 *result >>= 32;
157# endif
158#endif /* SIZEOF_LONG == 8 */
159 *result &= 0xffffffff;
160 return true;
161}
162
163static pid_t
164pid_next_thread (Dwfl *dwfl __attribute__ ((unused)), void *dwfl_arg,
165 void **thread_argp)
166{
167 struct pid_arg *pid_arg = dwfl_arg;
168 struct dirent *dirent;
Mark Wielaardc76b2ff2013-12-17 10:37:29 +0100169 /* Start fresh on first traversal. */
170 if (*thread_argp == NULL)
171 rewinddir (pid_arg->dir);
Jan Kratochvil0b867462013-05-30 14:37:38 +0200172 do
173 {
174 errno = 0;
175 dirent = readdir (pid_arg->dir);
176 if (dirent == NULL)
177 {
178 if (errno != 0)
179 {
180 __libdwfl_seterrno (DWFL_E_ERRNO);
181 return -1;
182 }
183 return 0;
184 }
185 }
186 while (strcmp (dirent->d_name, ".") == 0
187 || strcmp (dirent->d_name, "..") == 0);
188 char *end;
189 errno = 0;
190 long tidl = strtol (dirent->d_name, &end, 10);
191 if (errno != 0)
192 {
193 __libdwfl_seterrno (DWFL_E_ERRNO);
194 return -1;
195 }
196 pid_t tid = tidl;
197 if (tidl <= 0 || (end && *end) || tid != tidl)
198 {
199 __libdwfl_seterrno (DWFL_E_PARSE_PROC);
200 return -1;
201 }
202 *thread_argp = dwfl_arg;
203 return tid;
204}
205
Mark Wielaarde962ec32013-12-20 10:09:12 +0100206/* Just checks that the thread id exists. */
207static bool
208pid_getthread (Dwfl *dwfl __attribute__ ((unused)), pid_t tid,
209 void *dwfl_arg, void **thread_argp)
210{
211 *thread_argp = dwfl_arg;
212 if (kill (tid, 0) < 0)
213 {
214 __libdwfl_seterrno (DWFL_E_ERRNO);
215 return false;
216 }
217 return true;
218}
219
Jan Kratochvil0b867462013-05-30 14:37:38 +0200220/* Implement the ebl_set_initial_registers_tid setfunc callback. */
221
222static bool
Jan Kratochvil1c1a53b2013-11-14 20:55:41 +0100223pid_thread_state_registers_cb (int firstreg, unsigned nregs,
224 const Dwarf_Word *regs, void *arg)
Jan Kratochvil0b867462013-05-30 14:37:38 +0200225{
226 Dwfl_Thread *thread = (Dwfl_Thread *) arg;
Jan Kratochvil5cbf42a2013-12-15 18:56:17 +0100227 if (firstreg < 0)
228 {
229 assert (firstreg == -1);
230 assert (nregs == 1);
231 INTUSE(dwfl_thread_state_register_pc) (thread, *regs);
232 return true;
233 }
234 assert (nregs > 0);
Jan Kratochvil0b867462013-05-30 14:37:38 +0200235 return INTUSE(dwfl_thread_state_registers) (thread, firstreg, nregs, regs);
236}
237
238static bool
239pid_set_initial_registers (Dwfl_Thread *thread, void *thread_arg)
240{
241 struct pid_arg *pid_arg = thread_arg;
242 assert (pid_arg->tid_attached == 0);
243 pid_t tid = INTUSE(dwfl_thread_tid) (thread);
Mark Wielaard19108012013-12-30 22:00:57 +0100244 if (! pid_arg->assume_ptrace_stopped
245 && ! ptrace_attach (tid, &pid_arg->tid_was_stopped))
Jan Kratochvil0b867462013-05-30 14:37:38 +0200246 return false;
247 pid_arg->tid_attached = tid;
248 Dwfl_Process *process = thread->process;
249 Ebl *ebl = process->ebl;
250 return ebl_set_initial_registers_tid (ebl, tid,
251 pid_thread_state_registers_cb, thread);
252}
253
254static void
255pid_detach (Dwfl *dwfl __attribute__ ((unused)), void *dwfl_arg)
256{
257 struct pid_arg *pid_arg = dwfl_arg;
258 closedir (pid_arg->dir);
259 free (pid_arg);
260}
261
262static void
263pid_thread_detach (Dwfl_Thread *thread, void *thread_arg)
264{
265 struct pid_arg *pid_arg = thread_arg;
266 pid_t tid = INTUSE(dwfl_thread_tid) (thread);
267 assert (pid_arg->tid_attached == tid);
268 pid_arg->tid_attached = 0;
Mark Wielaard19108012013-12-30 22:00:57 +0100269 if (! pid_arg->assume_ptrace_stopped)
270 {
271 /* This handling is needed only on older Linux kernels such as
272 2.6.32-358.23.2.el6.ppc64. Later kernels such as
273 3.11.7-200.fc19.x86_64 remember the T (stopped) state
274 themselves and no longer need to pass SIGSTOP during
275 PTRACE_DETACH. */
276 ptrace (PTRACE_DETACH, tid, NULL,
277 (void *) (intptr_t) (pid_arg->tid_was_stopped ? SIGSTOP : 0));
278 }
Jan Kratochvil0b867462013-05-30 14:37:38 +0200279}
280
281static const Dwfl_Thread_Callbacks pid_thread_callbacks =
282{
283 pid_next_thread,
Mark Wielaarde962ec32013-12-20 10:09:12 +0100284 pid_getthread,
Jan Kratochvil0b867462013-05-30 14:37:38 +0200285 pid_memory_read,
286 pid_set_initial_registers,
287 pid_detach,
288 pid_thread_detach,
289};
290
Mark Wielaard19108012013-12-30 22:00:57 +0100291int
292dwfl_linux_proc_attach (Dwfl *dwfl, pid_t pid, bool assume_ptrace_stopped)
Jan Kratochvil0b867462013-05-30 14:37:38 +0200293{
Mark Wielaard97bbf9b2013-12-23 14:20:06 +0100294 char buffer[36];
295 FILE *procfile;
296
297 /* Make sure to report the actual PID (thread group leader) to
298 dwfl_attach_state. */
299 snprintf (buffer, sizeof (buffer), "/proc/%ld/status", (long) pid);
300 procfile = fopen (buffer, "r");
301 if (procfile == NULL)
Mark Wielaard19108012013-12-30 22:00:57 +0100302 return errno;
Mark Wielaard97bbf9b2013-12-23 14:20:06 +0100303
304 char *line = NULL;
305 size_t linelen = 0;
306 while (getline (&line, &linelen, procfile) >= 0)
307 if (strncmp (line, "Tgid:", 5) == 0)
308 {
309 pid = atoi (&line[5]);
310 break;
311 }
312 free (line);
313 fclose (procfile);
314
315 if (pid == 0)
Mark Wielaard19108012013-12-30 22:00:57 +0100316 return ESRCH;
Mark Wielaard97bbf9b2013-12-23 14:20:06 +0100317
Jan Kratochvil0b867462013-05-30 14:37:38 +0200318 char dirname[64];
319 int i = snprintf (dirname, sizeof (dirname), "/proc/%ld/task", (long) pid);
320 assert (i > 0 && i < (ssize_t) sizeof (dirname) - 1);
321 DIR *dir = opendir (dirname);
322 if (dir == NULL)
Mark Wielaard19108012013-12-30 22:00:57 +0100323 return errno;
Jan Kratochvil0b867462013-05-30 14:37:38 +0200324 struct pid_arg *pid_arg = malloc (sizeof *pid_arg);
325 if (pid_arg == NULL)
326 {
327 closedir (dir);
Mark Wielaard19108012013-12-30 22:00:57 +0100328 return ENOMEM;
Jan Kratochvil0b867462013-05-30 14:37:38 +0200329 }
330 pid_arg->dir = dir;
331 pid_arg->tid_attached = 0;
Mark Wielaard19108012013-12-30 22:00:57 +0100332 pid_arg->assume_ptrace_stopped = assume_ptrace_stopped;
Jan Kratochviled782372013-11-14 20:53:20 +0100333 if (! INTUSE(dwfl_attach_state) (dwfl, NULL, pid, &pid_thread_callbacks,
Jan Kratochvil0b867462013-05-30 14:37:38 +0200334 pid_arg))
335 {
336 closedir (dir);
337 free (pid_arg);
Mark Wielaard19108012013-12-30 22:00:57 +0100338 return -1;
Jan Kratochvil0b867462013-05-30 14:37:38 +0200339 }
Mark Wielaard19108012013-12-30 22:00:57 +0100340 return 0;
Jan Kratochvil0b867462013-05-30 14:37:38 +0200341}
Mark Wielaard19108012013-12-30 22:00:57 +0100342INTDEF (dwfl_linux_proc_attach)