blob: e4eb621212c01e39e7ebbca70d78c0ea10047490 [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;
208 return INTUSE(dwfl_thread_state_registers) (thread, firstreg, nregs, regs);
209}
210
211static bool
212pid_set_initial_registers (Dwfl_Thread *thread, void *thread_arg)
213{
214 struct pid_arg *pid_arg = thread_arg;
215 assert (pid_arg->tid_attached == 0);
216 pid_t tid = INTUSE(dwfl_thread_tid) (thread);
Jan Kratochvil10d7a392013-11-19 15:00:15 +0100217 if (! ptrace_attach (tid, &pid_arg->tid_was_stopped))
Jan Kratochvil0b867462013-05-30 14:37:38 +0200218 return false;
219 pid_arg->tid_attached = tid;
220 Dwfl_Process *process = thread->process;
221 Ebl *ebl = process->ebl;
222 return ebl_set_initial_registers_tid (ebl, tid,
223 pid_thread_state_registers_cb, thread);
224}
225
226static void
227pid_detach (Dwfl *dwfl __attribute__ ((unused)), void *dwfl_arg)
228{
229 struct pid_arg *pid_arg = dwfl_arg;
230 closedir (pid_arg->dir);
231 free (pid_arg);
232}
233
234static void
235pid_thread_detach (Dwfl_Thread *thread, void *thread_arg)
236{
237 struct pid_arg *pid_arg = thread_arg;
238 pid_t tid = INTUSE(dwfl_thread_tid) (thread);
239 assert (pid_arg->tid_attached == tid);
240 pid_arg->tid_attached = 0;
Jan Kratochvil10d7a392013-11-19 15:00:15 +0100241 /* This handling is needed only on older Linux kernels such as
242 2.6.32-358.23.2.el6.ppc64. Later kernels such as 3.11.7-200.fc19.x86_64
243 remember the T (stopped) state themselves and no longer need to pass
244 SIGSTOP during PTRACE_DETACH. */
245 ptrace (PTRACE_DETACH, tid, NULL,
246 (void *) (intptr_t) (pid_arg->tid_was_stopped ? SIGSTOP : 0));
Jan Kratochvil0b867462013-05-30 14:37:38 +0200247}
248
249static const Dwfl_Thread_Callbacks pid_thread_callbacks =
250{
251 pid_next_thread,
252 pid_memory_read,
253 pid_set_initial_registers,
254 pid_detach,
255 pid_thread_detach,
256};
257
258bool
259internal_function
260__libdwfl_attach_state_for_pid (Dwfl *dwfl, pid_t pid)
261{
262 char dirname[64];
263 int i = snprintf (dirname, sizeof (dirname), "/proc/%ld/task", (long) pid);
264 assert (i > 0 && i < (ssize_t) sizeof (dirname) - 1);
265 DIR *dir = opendir (dirname);
266 if (dir == NULL)
267 {
268 __libdwfl_seterrno (DWFL_E_ERRNO);
269 return false;
270 }
271 struct pid_arg *pid_arg = malloc (sizeof *pid_arg);
272 if (pid_arg == NULL)
273 {
274 closedir (dir);
275 __libdwfl_seterrno (DWFL_E_NOMEM);
276 return false;
277 }
278 pid_arg->dir = dir;
279 pid_arg->tid_attached = 0;
Jan Kratochviled782372013-11-14 20:53:20 +0100280 if (! INTUSE(dwfl_attach_state) (dwfl, NULL, pid, &pid_thread_callbacks,
Jan Kratochvil0b867462013-05-30 14:37:38 +0200281 pid_arg))
282 {
283 closedir (dir);
284 free (pid_arg);
285 return false;
286 }
287 return true;
288}