blob: 45a0732d16ef0dfef3707fe84873b114ec66d0d1 [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;
167 do
168 {
169 errno = 0;
170 dirent = readdir (pid_arg->dir);
171 if (dirent == NULL)
172 {
173 if (errno != 0)
174 {
175 __libdwfl_seterrno (DWFL_E_ERRNO);
176 return -1;
177 }
178 return 0;
179 }
180 }
181 while (strcmp (dirent->d_name, ".") == 0
182 || strcmp (dirent->d_name, "..") == 0);
183 char *end;
184 errno = 0;
185 long tidl = strtol (dirent->d_name, &end, 10);
186 if (errno != 0)
187 {
188 __libdwfl_seterrno (DWFL_E_ERRNO);
189 return -1;
190 }
191 pid_t tid = tidl;
192 if (tidl <= 0 || (end && *end) || tid != tidl)
193 {
194 __libdwfl_seterrno (DWFL_E_PARSE_PROC);
195 return -1;
196 }
197 *thread_argp = dwfl_arg;
198 return tid;
199}
200
201/* Implement the ebl_set_initial_registers_tid setfunc callback. */
202
203static bool
Jan Kratochvil1c1a53b2013-11-14 20:55:41 +0100204pid_thread_state_registers_cb (int firstreg, unsigned nregs,
205 const Dwarf_Word *regs, void *arg)
Jan Kratochvil0b867462013-05-30 14:37:38 +0200206{
207 Dwfl_Thread *thread = (Dwfl_Thread *) arg;
Jan Kratochvil5cbf42a2013-12-15 18:56:17 +0100208 if (firstreg < 0)
209 {
210 assert (firstreg == -1);
211 assert (nregs == 1);
212 INTUSE(dwfl_thread_state_register_pc) (thread, *regs);
213 return true;
214 }
215 assert (nregs > 0);
Jan Kratochvil0b867462013-05-30 14:37:38 +0200216 return INTUSE(dwfl_thread_state_registers) (thread, firstreg, nregs, regs);
217}
218
219static bool
220pid_set_initial_registers (Dwfl_Thread *thread, void *thread_arg)
221{
222 struct pid_arg *pid_arg = thread_arg;
223 assert (pid_arg->tid_attached == 0);
224 pid_t tid = INTUSE(dwfl_thread_tid) (thread);
Jan Kratochvil10d7a392013-11-19 15:00:15 +0100225 if (! ptrace_attach (tid, &pid_arg->tid_was_stopped))
Jan Kratochvil0b867462013-05-30 14:37:38 +0200226 return false;
227 pid_arg->tid_attached = tid;
228 Dwfl_Process *process = thread->process;
229 Ebl *ebl = process->ebl;
230 return ebl_set_initial_registers_tid (ebl, tid,
231 pid_thread_state_registers_cb, thread);
232}
233
234static void
235pid_detach (Dwfl *dwfl __attribute__ ((unused)), void *dwfl_arg)
236{
237 struct pid_arg *pid_arg = dwfl_arg;
238 closedir (pid_arg->dir);
239 free (pid_arg);
240}
241
242static void
243pid_thread_detach (Dwfl_Thread *thread, void *thread_arg)
244{
245 struct pid_arg *pid_arg = thread_arg;
246 pid_t tid = INTUSE(dwfl_thread_tid) (thread);
247 assert (pid_arg->tid_attached == tid);
248 pid_arg->tid_attached = 0;
Jan Kratochvil10d7a392013-11-19 15:00:15 +0100249 /* This handling is needed only on older Linux kernels such as
250 2.6.32-358.23.2.el6.ppc64. Later kernels such as 3.11.7-200.fc19.x86_64
251 remember the T (stopped) state themselves and no longer need to pass
252 SIGSTOP during PTRACE_DETACH. */
253 ptrace (PTRACE_DETACH, tid, NULL,
254 (void *) (intptr_t) (pid_arg->tid_was_stopped ? SIGSTOP : 0));
Jan Kratochvil0b867462013-05-30 14:37:38 +0200255}
256
257static const Dwfl_Thread_Callbacks pid_thread_callbacks =
258{
259 pid_next_thread,
260 pid_memory_read,
261 pid_set_initial_registers,
262 pid_detach,
263 pid_thread_detach,
264};
265
266bool
267internal_function
268__libdwfl_attach_state_for_pid (Dwfl *dwfl, pid_t pid)
269{
270 char dirname[64];
271 int i = snprintf (dirname, sizeof (dirname), "/proc/%ld/task", (long) pid);
272 assert (i > 0 && i < (ssize_t) sizeof (dirname) - 1);
273 DIR *dir = opendir (dirname);
274 if (dir == NULL)
275 {
276 __libdwfl_seterrno (DWFL_E_ERRNO);
277 return false;
278 }
279 struct pid_arg *pid_arg = malloc (sizeof *pid_arg);
280 if (pid_arg == NULL)
281 {
282 closedir (dir);
283 __libdwfl_seterrno (DWFL_E_NOMEM);
284 return false;
285 }
286 pid_arg->dir = dir;
287 pid_arg->tid_attached = 0;
Jan Kratochviled782372013-11-14 20:53:20 +0100288 if (! INTUSE(dwfl_attach_state) (dwfl, NULL, pid, &pid_thread_callbacks,
Jan Kratochvil0b867462013-05-30 14:37:38 +0200289 pid_arg))
290 {
291 closedir (dir);
292 free (pid_arg);
293 return false;
294 }
295 return true;
296}