blob: 6be578bbc9127ebca6b53a53df1bfc6c3893cf3d [file] [log] [blame]
Jan Kratochvil0b867462013-05-30 14:37:38 +02001/* Get Dwarf Frame state for target live PID process.
Mark Wielaard4b9e1432014-03-04 11:27:15 +01002 Copyright (C) 2013, 2014 Red Hat, Inc.
Jan Kratochvil0b867462013-05-30 14:37:38 +02003 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
Jan Kratochvil0b867462013-05-30 14:37:38 +020040
41static bool
42linux_proc_pid_is_stopped (pid_t pid)
43{
44 char buffer[64];
45 FILE *procfile;
46 bool retval, have_state;
47
48 snprintf (buffer, sizeof (buffer), "/proc/%ld/status", (long) pid);
49 procfile = fopen (buffer, "r");
50 if (procfile == NULL)
51 return false;
52
53 have_state = false;
54 while (fgets (buffer, sizeof (buffer), procfile) != NULL)
55 if (strncmp (buffer, "State:", 6) == 0)
56 {
57 have_state = true;
58 break;
59 }
60 retval = (have_state && strstr (buffer, "T (stopped)") != NULL);
61 fclose (procfile);
62 return retval;
63}
64
Mark Wielaard4b9e1432014-03-04 11:27:15 +010065bool
66internal_function
67__libdwfl_ptrace_attach (pid_t tid, bool *tid_was_stoppedp)
Jan Kratochvil0b867462013-05-30 14:37:38 +020068{
69 if (ptrace (PTRACE_ATTACH, tid, NULL, NULL) != 0)
70 {
71 __libdwfl_seterrno (DWFL_E_ERRNO);
72 return false;
73 }
Jan Kratochvil10d7a392013-11-19 15:00:15 +010074 *tid_was_stoppedp = linux_proc_pid_is_stopped (tid);
75 if (*tid_was_stoppedp)
Jan Kratochvil0b867462013-05-30 14:37:38 +020076 {
77 /* Make sure there is a SIGSTOP signal pending even when the process is
78 already State: T (stopped). Older kernels might fail to generate
79 a SIGSTOP notification in that case in response to our PTRACE_ATTACH
80 above. Which would make the waitpid below wait forever. So emulate
81 it. Since there can only be one SIGSTOP notification pending this is
82 safe. See also gdb/linux-nat.c linux_nat_post_attach_wait. */
83 syscall (__NR_tkill, tid, SIGSTOP);
84 ptrace (PTRACE_CONT, tid, NULL, NULL);
85 }
86 for (;;)
87 {
88 int status;
89 if (waitpid (tid, &status, __WALL) != tid || !WIFSTOPPED (status))
90 {
91 int saved_errno = errno;
92 ptrace (PTRACE_DETACH, tid, NULL, NULL);
93 errno = saved_errno;
94 __libdwfl_seterrno (DWFL_E_ERRNO);
95 return false;
96 }
97 if (WSTOPSIG (status) == SIGSTOP)
98 break;
99 if (ptrace (PTRACE_CONT, tid, NULL,
100 (void *) (uintptr_t) WSTOPSIG (status)) != 0)
101 {
102 int saved_errno = errno;
103 ptrace (PTRACE_DETACH, tid, NULL, NULL);
104 errno = saved_errno;
105 __libdwfl_seterrno (DWFL_E_ERRNO);
106 return false;
107 }
108 }
109 return true;
110}
111
112static bool
113pid_memory_read (Dwfl *dwfl, Dwarf_Addr addr, Dwarf_Word *result, void *arg)
114{
Mark Wielaard4b9e1432014-03-04 11:27:15 +0100115 struct __libdwfl_pid_arg *pid_arg = arg;
Jan Kratochvil0b867462013-05-30 14:37:38 +0200116 pid_t tid = pid_arg->tid_attached;
117 assert (tid > 0);
118 Dwfl_Process *process = dwfl->process;
119 if (ebl_get_elfclass (process->ebl) == ELFCLASS64)
120 {
121#if SIZEOF_LONG == 8
122 errno = 0;
123 *result = ptrace (PTRACE_PEEKDATA, tid, (void *) (uintptr_t) addr, NULL);
124 return errno == 0;
125#else /* SIZEOF_LONG != 8 */
126 /* This should not happen. */
127 return false;
128#endif /* SIZEOF_LONG != 8 */
129 }
130#if SIZEOF_LONG == 8
131 /* We do not care about reads unaliged to 4 bytes boundary.
132 But 0x...ffc read of 8 bytes could overrun a page. */
133 bool lowered = (addr & 4) != 0;
134 if (lowered)
135 addr -= 4;
136#endif /* SIZEOF_LONG == 8 */
137 errno = 0;
138 *result = ptrace (PTRACE_PEEKDATA, tid, (void *) (uintptr_t) addr, NULL);
139 if (errno != 0)
140 return false;
141#if SIZEOF_LONG == 8
142# if BYTE_ORDER == BIG_ENDIAN
143 if (! lowered)
144 *result >>= 32;
145# else
146 if (lowered)
147 *result >>= 32;
148# endif
149#endif /* SIZEOF_LONG == 8 */
150 *result &= 0xffffffff;
151 return true;
152}
153
154static pid_t
155pid_next_thread (Dwfl *dwfl __attribute__ ((unused)), void *dwfl_arg,
156 void **thread_argp)
157{
Mark Wielaard4b9e1432014-03-04 11:27:15 +0100158 struct __libdwfl_pid_arg *pid_arg = dwfl_arg;
Jan Kratochvil0b867462013-05-30 14:37:38 +0200159 struct dirent *dirent;
Mark Wielaardc76b2ff2013-12-17 10:37:29 +0100160 /* Start fresh on first traversal. */
161 if (*thread_argp == NULL)
162 rewinddir (pid_arg->dir);
Jan Kratochvil0b867462013-05-30 14:37:38 +0200163 do
164 {
165 errno = 0;
166 dirent = readdir (pid_arg->dir);
167 if (dirent == NULL)
168 {
169 if (errno != 0)
170 {
171 __libdwfl_seterrno (DWFL_E_ERRNO);
172 return -1;
173 }
174 return 0;
175 }
176 }
177 while (strcmp (dirent->d_name, ".") == 0
178 || strcmp (dirent->d_name, "..") == 0);
179 char *end;
180 errno = 0;
181 long tidl = strtol (dirent->d_name, &end, 10);
182 if (errno != 0)
183 {
184 __libdwfl_seterrno (DWFL_E_ERRNO);
185 return -1;
186 }
187 pid_t tid = tidl;
188 if (tidl <= 0 || (end && *end) || tid != tidl)
189 {
190 __libdwfl_seterrno (DWFL_E_PARSE_PROC);
191 return -1;
192 }
193 *thread_argp = dwfl_arg;
194 return tid;
195}
196
Mark Wielaarde962ec32013-12-20 10:09:12 +0100197/* Just checks that the thread id exists. */
198static bool
199pid_getthread (Dwfl *dwfl __attribute__ ((unused)), pid_t tid,
200 void *dwfl_arg, void **thread_argp)
201{
202 *thread_argp = dwfl_arg;
203 if (kill (tid, 0) < 0)
204 {
205 __libdwfl_seterrno (DWFL_E_ERRNO);
206 return false;
207 }
208 return true;
209}
210
Jan Kratochvil0b867462013-05-30 14:37:38 +0200211/* Implement the ebl_set_initial_registers_tid setfunc callback. */
212
213static bool
Jan Kratochvil1c1a53b2013-11-14 20:55:41 +0100214pid_thread_state_registers_cb (int firstreg, unsigned nregs,
215 const Dwarf_Word *regs, void *arg)
Jan Kratochvil0b867462013-05-30 14:37:38 +0200216{
217 Dwfl_Thread *thread = (Dwfl_Thread *) arg;
Jan Kratochvil5cbf42a2013-12-15 18:56:17 +0100218 if (firstreg < 0)
219 {
220 assert (firstreg == -1);
221 assert (nregs == 1);
222 INTUSE(dwfl_thread_state_register_pc) (thread, *regs);
223 return true;
224 }
225 assert (nregs > 0);
Jan Kratochvil0b867462013-05-30 14:37:38 +0200226 return INTUSE(dwfl_thread_state_registers) (thread, firstreg, nregs, regs);
227}
228
229static bool
230pid_set_initial_registers (Dwfl_Thread *thread, void *thread_arg)
231{
Mark Wielaard4b9e1432014-03-04 11:27:15 +0100232 struct __libdwfl_pid_arg *pid_arg = thread_arg;
Jan Kratochvil0b867462013-05-30 14:37:38 +0200233 assert (pid_arg->tid_attached == 0);
234 pid_t tid = INTUSE(dwfl_thread_tid) (thread);
Mark Wielaard19108012013-12-30 22:00:57 +0100235 if (! pid_arg->assume_ptrace_stopped
Mark Wielaard4b9e1432014-03-04 11:27:15 +0100236 && ! __libdwfl_ptrace_attach (tid, &pid_arg->tid_was_stopped))
Jan Kratochvil0b867462013-05-30 14:37:38 +0200237 return false;
238 pid_arg->tid_attached = tid;
239 Dwfl_Process *process = thread->process;
240 Ebl *ebl = process->ebl;
241 return ebl_set_initial_registers_tid (ebl, tid,
242 pid_thread_state_registers_cb, thread);
243}
244
245static void
246pid_detach (Dwfl *dwfl __attribute__ ((unused)), void *dwfl_arg)
247{
Mark Wielaard4b9e1432014-03-04 11:27:15 +0100248 struct __libdwfl_pid_arg *pid_arg = dwfl_arg;
Jan Kratochvil0b867462013-05-30 14:37:38 +0200249 closedir (pid_arg->dir);
250 free (pid_arg);
251}
252
Mark Wielaard4b9e1432014-03-04 11:27:15 +0100253void
254internal_function
255__libdwfl_ptrace_detach (pid_t tid, bool tid_was_stopped)
256{
257 /* This handling is needed only on older Linux kernels such as
258 2.6.32-358.23.2.el6.ppc64. Later kernels such as
259 3.11.7-200.fc19.x86_64 remember the T (stopped) state
260 themselves and no longer need to pass SIGSTOP during
261 PTRACE_DETACH. */
262 ptrace (PTRACE_DETACH, tid, NULL,
263 (void *) (intptr_t) (tid_was_stopped ? SIGSTOP : 0));
264}
265
Jan Kratochvil0b867462013-05-30 14:37:38 +0200266static void
267pid_thread_detach (Dwfl_Thread *thread, void *thread_arg)
268{
Mark Wielaard4b9e1432014-03-04 11:27:15 +0100269 struct __libdwfl_pid_arg *pid_arg = thread_arg;
Jan Kratochvil0b867462013-05-30 14:37:38 +0200270 pid_t tid = INTUSE(dwfl_thread_tid) (thread);
271 assert (pid_arg->tid_attached == tid);
272 pid_arg->tid_attached = 0;
Mark Wielaard19108012013-12-30 22:00:57 +0100273 if (! pid_arg->assume_ptrace_stopped)
Mark Wielaard4b9e1432014-03-04 11:27:15 +0100274 __libdwfl_ptrace_detach (tid, pid_arg->tid_was_stopped);
Jan Kratochvil0b867462013-05-30 14:37:38 +0200275}
276
277static const Dwfl_Thread_Callbacks pid_thread_callbacks =
278{
279 pid_next_thread,
Mark Wielaarde962ec32013-12-20 10:09:12 +0100280 pid_getthread,
Jan Kratochvil0b867462013-05-30 14:37:38 +0200281 pid_memory_read,
282 pid_set_initial_registers,
283 pid_detach,
284 pid_thread_detach,
285};
286
Mark Wielaard19108012013-12-30 22:00:57 +0100287int
288dwfl_linux_proc_attach (Dwfl *dwfl, pid_t pid, bool assume_ptrace_stopped)
Jan Kratochvil0b867462013-05-30 14:37:38 +0200289{
Mark Wielaard97bbf9b2013-12-23 14:20:06 +0100290 char buffer[36];
291 FILE *procfile;
292
293 /* Make sure to report the actual PID (thread group leader) to
294 dwfl_attach_state. */
295 snprintf (buffer, sizeof (buffer), "/proc/%ld/status", (long) pid);
296 procfile = fopen (buffer, "r");
297 if (procfile == NULL)
Mark Wielaard19108012013-12-30 22:00:57 +0100298 return errno;
Mark Wielaard97bbf9b2013-12-23 14:20:06 +0100299
300 char *line = NULL;
301 size_t linelen = 0;
302 while (getline (&line, &linelen, procfile) >= 0)
303 if (strncmp (line, "Tgid:", 5) == 0)
304 {
Mark Wielaard68de4422014-01-02 21:17:18 +0100305 errno = 0;
306 char *endptr;
307 long val = strtol (&line[5], &endptr, 10);
308 if ((errno == ERANGE && val == LONG_MAX)
309 || *endptr != '\n' || val < 0 || val != (pid_t) val)
310 pid = 0;
311 else
312 pid = (pid_t) val;
313 break;
Mark Wielaard97bbf9b2013-12-23 14:20:06 +0100314 }
315 free (line);
316 fclose (procfile);
317
318 if (pid == 0)
Mark Wielaard19108012013-12-30 22:00:57 +0100319 return ESRCH;
Mark Wielaard97bbf9b2013-12-23 14:20:06 +0100320
Jan Kratochvil0b867462013-05-30 14:37:38 +0200321 char dirname[64];
322 int i = snprintf (dirname, sizeof (dirname), "/proc/%ld/task", (long) pid);
323 assert (i > 0 && i < (ssize_t) sizeof (dirname) - 1);
324 DIR *dir = opendir (dirname);
325 if (dir == NULL)
Mark Wielaard19108012013-12-30 22:00:57 +0100326 return errno;
Mark Wielaard4b9e1432014-03-04 11:27:15 +0100327 struct __libdwfl_pid_arg *pid_arg = malloc (sizeof *pid_arg);
Jan Kratochvil0b867462013-05-30 14:37:38 +0200328 if (pid_arg == NULL)
329 {
330 closedir (dir);
Mark Wielaard19108012013-12-30 22:00:57 +0100331 return ENOMEM;
Jan Kratochvil0b867462013-05-30 14:37:38 +0200332 }
333 pid_arg->dir = dir;
334 pid_arg->tid_attached = 0;
Mark Wielaard19108012013-12-30 22:00:57 +0100335 pid_arg->assume_ptrace_stopped = assume_ptrace_stopped;
Jan Kratochviled782372013-11-14 20:53:20 +0100336 if (! INTUSE(dwfl_attach_state) (dwfl, NULL, pid, &pid_thread_callbacks,
Jan Kratochvil0b867462013-05-30 14:37:38 +0200337 pid_arg))
338 {
339 closedir (dir);
340 free (pid_arg);
Mark Wielaard19108012013-12-30 22:00:57 +0100341 return -1;
Jan Kratochvil0b867462013-05-30 14:37:38 +0200342 }
Mark Wielaard19108012013-12-30 22:00:57 +0100343 return 0;
Jan Kratochvil0b867462013-05-30 14:37:38 +0200344}
Mark Wielaard19108012013-12-30 22:00:57 +0100345INTDEF (dwfl_linux_proc_attach)
Mark Wielaard4b9e1432014-03-04 11:27:15 +0100346
347struct __libdwfl_pid_arg *
348internal_function
349__libdwfl_get_pid_arg (Dwfl *dwfl)
350{
351 if (dwfl != NULL && dwfl->process != NULL
352 && dwfl->process->callbacks == &pid_thread_callbacks)
353 return (struct __libdwfl_pid_arg *) dwfl->process->callbacks_arg;
354
355 return NULL;
356}