1 /* Get Dwarf Frame state for target live PID process.
2    Copyright (C) 2013, 2014 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 
40 #ifdef __linux__
41 
42 static bool
linux_proc_pid_is_stopped(pid_t pid)43 linux_proc_pid_is_stopped (pid_t pid)
44 {
45   char buffer[64];
46   FILE *procfile;
47   bool retval, have_state;
48 
49   snprintf (buffer, sizeof (buffer), "/proc/%ld/status", (long) pid);
50   procfile = fopen (buffer, "r");
51   if (procfile == NULL)
52     return false;
53 
54   have_state = false;
55   while (fgets (buffer, sizeof (buffer), procfile) != NULL)
56     if (strncmp (buffer, "State:", 6) == 0)
57       {
58 	have_state = true;
59 	break;
60       }
61   retval = (have_state && strstr (buffer, "T (stopped)") != NULL);
62   fclose (procfile);
63   return retval;
64 }
65 
66 bool
67 internal_function
__libdwfl_ptrace_attach(pid_t tid,bool * tid_was_stoppedp)68 __libdwfl_ptrace_attach (pid_t tid, bool *tid_was_stoppedp)
69 {
70   if (ptrace (PTRACE_ATTACH, tid, NULL, NULL) != 0)
71     {
72       __libdwfl_seterrno (DWFL_E_ERRNO);
73       return false;
74     }
75   *tid_was_stoppedp = linux_proc_pid_is_stopped (tid);
76   if (*tid_was_stoppedp)
77     {
78       /* Make sure there is a SIGSTOP signal pending even when the process is
79 	 already State: T (stopped).  Older kernels might fail to generate
80 	 a SIGSTOP notification in that case in response to our PTRACE_ATTACH
81 	 above.  Which would make the waitpid below wait forever.  So emulate
82 	 it.  Since there can only be one SIGSTOP notification pending this is
83 	 safe.  See also gdb/linux-nat.c linux_nat_post_attach_wait.  */
84       syscall (__NR_tkill, tid, SIGSTOP);
85       ptrace (PTRACE_CONT, tid, NULL, NULL);
86     }
87   for (;;)
88     {
89       int status;
90       if (waitpid (tid, &status, __WALL) != tid || !WIFSTOPPED (status))
91 	{
92 	  int saved_errno = errno;
93 	  ptrace (PTRACE_DETACH, tid, NULL, NULL);
94 	  errno = saved_errno;
95 	  __libdwfl_seterrno (DWFL_E_ERRNO);
96 	  return false;
97 	}
98       if (WSTOPSIG (status) == SIGSTOP)
99 	break;
100       if (ptrace (PTRACE_CONT, tid, NULL,
101 		  (void *) (uintptr_t) WSTOPSIG (status)) != 0)
102 	{
103 	  int saved_errno = errno;
104 	  ptrace (PTRACE_DETACH, tid, NULL, NULL);
105 	  errno = saved_errno;
106 	  __libdwfl_seterrno (DWFL_E_ERRNO);
107 	  return false;
108 	}
109     }
110   return true;
111 }
112 
113 static bool
pid_memory_read(Dwfl * dwfl,Dwarf_Addr addr,Dwarf_Word * result,void * arg)114 pid_memory_read (Dwfl *dwfl, Dwarf_Addr addr, Dwarf_Word *result, void *arg)
115 {
116   struct __libdwfl_pid_arg *pid_arg = arg;
117   pid_t tid = pid_arg->tid_attached;
118   assert (tid > 0);
119   Dwfl_Process *process = dwfl->process;
120   if (ebl_get_elfclass (process->ebl) == ELFCLASS64)
121     {
122 #if SIZEOF_LONG == 8
123       errno = 0;
124       *result = ptrace (PTRACE_PEEKDATA, tid, (void *) (uintptr_t) addr, NULL);
125       return errno == 0;
126 #else /* SIZEOF_LONG != 8 */
127       /* This should not happen.  */
128       return false;
129 #endif /* SIZEOF_LONG != 8 */
130     }
131 #if SIZEOF_LONG == 8
132   /* We do not care about reads unaliged to 4 bytes boundary.
133      But 0x...ffc read of 8 bytes could overrun a page.  */
134   bool lowered = (addr & 4) != 0;
135   if (lowered)
136     addr -= 4;
137 #endif /* SIZEOF_LONG == 8 */
138   errno = 0;
139   *result = ptrace (PTRACE_PEEKDATA, tid, (void *) (uintptr_t) addr, NULL);
140   if (errno != 0)
141     return false;
142 #if SIZEOF_LONG == 8
143 # if BYTE_ORDER == BIG_ENDIAN
144   if (! lowered)
145     *result >>= 32;
146 # else
147   if (lowered)
148     *result >>= 32;
149 # endif
150 #endif /* SIZEOF_LONG == 8 */
151   *result &= 0xffffffff;
152   return true;
153 }
154 
155 static pid_t
pid_next_thread(Dwfl * dwfl,void * dwfl_arg,void ** thread_argp)156 pid_next_thread (Dwfl *dwfl __attribute__ ((unused)), void *dwfl_arg,
157 		 void **thread_argp)
158 {
159   struct __libdwfl_pid_arg *pid_arg = dwfl_arg;
160   struct dirent *dirent;
161   /* Start fresh on first traversal. */
162   if (*thread_argp == NULL)
163     rewinddir (pid_arg->dir);
164   do
165     {
166       errno = 0;
167       dirent = readdir (pid_arg->dir);
168       if (dirent == NULL)
169 	{
170 	  if (errno != 0)
171 	    {
172 	      __libdwfl_seterrno (DWFL_E_ERRNO);
173 	      return -1;
174 	    }
175 	  return 0;
176 	}
177     }
178   while (strcmp (dirent->d_name, ".") == 0
179 	 || strcmp (dirent->d_name, "..") == 0);
180   char *end;
181   errno = 0;
182   long tidl = strtol (dirent->d_name, &end, 10);
183   if (errno != 0)
184     {
185       __libdwfl_seterrno (DWFL_E_ERRNO);
186       return -1;
187     }
188   pid_t tid = tidl;
189   if (tidl <= 0 || (end && *end) || tid != tidl)
190     {
191       __libdwfl_seterrno (DWFL_E_PARSE_PROC);
192       return -1;
193     }
194   *thread_argp = dwfl_arg;
195   return tid;
196 }
197 
198 /* Just checks that the thread id exists.  */
199 static bool
pid_getthread(Dwfl * dwfl,pid_t tid,void * dwfl_arg,void ** thread_argp)200 pid_getthread (Dwfl *dwfl __attribute__ ((unused)), pid_t tid,
201 	       void *dwfl_arg, void **thread_argp)
202 {
203   *thread_argp = dwfl_arg;
204   if (kill (tid, 0) < 0)
205     {
206       __libdwfl_seterrno (DWFL_E_ERRNO);
207       return false;
208     }
209   return true;
210 }
211 
212 /* Implement the ebl_set_initial_registers_tid setfunc callback.  */
213 
214 static bool
pid_thread_state_registers_cb(int firstreg,unsigned nregs,const Dwarf_Word * regs,void * arg)215 pid_thread_state_registers_cb (int firstreg, unsigned nregs,
216 			       const Dwarf_Word *regs, void *arg)
217 {
218   Dwfl_Thread *thread = (Dwfl_Thread *) arg;
219   if (firstreg < 0)
220     {
221       assert (firstreg == -1);
222       assert (nregs == 1);
223       INTUSE(dwfl_thread_state_register_pc) (thread, *regs);
224       return true;
225     }
226   assert (nregs > 0);
227   return INTUSE(dwfl_thread_state_registers) (thread, firstreg, nregs, regs);
228 }
229 
230 static bool
pid_set_initial_registers(Dwfl_Thread * thread,void * thread_arg)231 pid_set_initial_registers (Dwfl_Thread *thread, void *thread_arg)
232 {
233   struct __libdwfl_pid_arg *pid_arg = thread_arg;
234   assert (pid_arg->tid_attached == 0);
235   pid_t tid = INTUSE(dwfl_thread_tid) (thread);
236   if (! pid_arg->assume_ptrace_stopped
237       && ! __libdwfl_ptrace_attach (tid, &pid_arg->tid_was_stopped))
238     return false;
239   pid_arg->tid_attached = tid;
240   Dwfl_Process *process = thread->process;
241   Ebl *ebl = process->ebl;
242   return ebl_set_initial_registers_tid (ebl, tid,
243 					pid_thread_state_registers_cb, thread);
244 }
245 
246 static void
pid_detach(Dwfl * dwfl,void * dwfl_arg)247 pid_detach (Dwfl *dwfl __attribute__ ((unused)), void *dwfl_arg)
248 {
249   struct __libdwfl_pid_arg *pid_arg = dwfl_arg;
250   closedir (pid_arg->dir);
251   free (pid_arg);
252 }
253 
254 void
255 internal_function
__libdwfl_ptrace_detach(pid_t tid,bool tid_was_stopped)256 __libdwfl_ptrace_detach (pid_t tid, bool tid_was_stopped)
257 {
258   /* This handling is needed only on older Linux kernels such as
259      2.6.32-358.23.2.el6.ppc64.  Later kernels such as
260      3.11.7-200.fc19.x86_64 remember the T (stopped) state
261      themselves and no longer need to pass SIGSTOP during
262      PTRACE_DETACH.  */
263   ptrace (PTRACE_DETACH, tid, NULL,
264 	  (void *) (intptr_t) (tid_was_stopped ? SIGSTOP : 0));
265 }
266 
267 static void
pid_thread_detach(Dwfl_Thread * thread,void * thread_arg)268 pid_thread_detach (Dwfl_Thread *thread, void *thread_arg)
269 {
270   struct __libdwfl_pid_arg *pid_arg = thread_arg;
271   pid_t tid = INTUSE(dwfl_thread_tid) (thread);
272   assert (pid_arg->tid_attached == tid);
273   pid_arg->tid_attached = 0;
274   if (! pid_arg->assume_ptrace_stopped)
275     __libdwfl_ptrace_detach (tid, pid_arg->tid_was_stopped);
276 }
277 
278 static const Dwfl_Thread_Callbacks pid_thread_callbacks =
279 {
280   pid_next_thread,
281   pid_getthread,
282   pid_memory_read,
283   pid_set_initial_registers,
284   pid_detach,
285   pid_thread_detach,
286 };
287 
288 int
dwfl_linux_proc_attach(Dwfl * dwfl,pid_t pid,bool assume_ptrace_stopped)289 dwfl_linux_proc_attach (Dwfl *dwfl, pid_t pid, bool assume_ptrace_stopped)
290 {
291   char buffer[36];
292   FILE *procfile;
293   int err = 0; /* The errno to return and set for dwfl->attcherr.  */
294 
295   /* Make sure to report the actual PID (thread group leader) to
296      dwfl_attach_state.  */
297   snprintf (buffer, sizeof (buffer), "/proc/%ld/status", (long) pid);
298   procfile = fopen (buffer, "r");
299   if (procfile == NULL)
300     {
301       err = errno;
302     fail:
303       if (dwfl->process == NULL && dwfl->attacherr == DWFL_E_NOERROR)
304 	{
305 	  errno = err;
306 	  dwfl->attacherr = __libdwfl_canon_error (DWFL_E_ERRNO);
307 	}
308       return err;
309     }
310 
311   char *line = NULL;
312   size_t linelen = 0;
313   while (getline (&line, &linelen, procfile) >= 0)
314     if (strncmp (line, "Tgid:", 5) == 0)
315       {
316 	errno = 0;
317 	char *endptr;
318 	long val = strtol (&line[5], &endptr, 10);
319 	if ((errno == ERANGE && val == LONG_MAX)
320 	    || *endptr != '\n' || val < 0 || val != (pid_t) val)
321 	  pid = 0;
322 	else
323 	  pid = (pid_t) val;
324 	break;
325       }
326   free (line);
327   fclose (procfile);
328 
329   if (pid == 0)
330     {
331       err = ESRCH;
332       goto fail;
333     }
334 
335   char dirname[64];
336   int i = snprintf (dirname, sizeof (dirname), "/proc/%ld/task", (long) pid);
337   assert (i > 0 && i < (ssize_t) sizeof (dirname) - 1);
338   DIR *dir = opendir (dirname);
339   if (dir == NULL)
340     {
341       err = errno;
342       goto fail;
343     }
344   struct __libdwfl_pid_arg *pid_arg = malloc (sizeof *pid_arg);
345   if (pid_arg == NULL)
346     {
347       closedir (dir);
348       err = ENOMEM;
349       goto fail;
350     }
351   pid_arg->dir = dir;
352   pid_arg->tid_attached = 0;
353   pid_arg->assume_ptrace_stopped = assume_ptrace_stopped;
354   if (! INTUSE(dwfl_attach_state) (dwfl, NULL, pid, &pid_thread_callbacks,
355 				   pid_arg))
356     {
357       closedir (dir);
358       free (pid_arg);
359       return -1;
360     }
361   return 0;
362 }
INTDEF(dwfl_linux_proc_attach)363 INTDEF (dwfl_linux_proc_attach)
364 
365 struct __libdwfl_pid_arg *
366 internal_function
367 __libdwfl_get_pid_arg (Dwfl *dwfl)
368 {
369   if (dwfl != NULL && dwfl->process != NULL
370       && dwfl->process->callbacks == &pid_thread_callbacks)
371     return (struct __libdwfl_pid_arg *) dwfl->process->callbacks_arg;
372 
373   return NULL;
374 }
375 
376 #else	/* __linux__ */
377 
378 static pid_t
pid_next_thread(Dwfl * dwfl,void * dwfl_arg,void ** thread_argp)379 pid_next_thread (Dwfl *dwfl __attribute__ ((unused)),
380 	         void *dwfl_arg __attribute__ ((unused)),
381 		 void **thread_argp __attribute__ ((unused)))
382 {
383   errno = ENOSYS;
384   __libdwfl_seterrno (DWFL_E_ERRNO);
385   return -1;
386 }
387 
388 static bool
pid_getthread(Dwfl * dwfl,pid_t tid,void * dwfl_arg,void ** thread_argp)389 pid_getthread (Dwfl *dwfl __attribute__ ((unused)),
390 	       pid_t tid __attribute__ ((unused)),
391 	       void *dwfl_arg __attribute__ ((unused)),
392 	       void **thread_argp __attribute__ ((unused)))
393 {
394   errno = ENOSYS;
395   __libdwfl_seterrno (DWFL_E_ERRNO);
396   return false;
397 }
398 
399 bool
400 internal_function
__libdwfl_ptrace_attach(pid_t tid,bool * tid_was_stoppedp)401 __libdwfl_ptrace_attach (pid_t tid __attribute__ ((unused)),
402 			 bool *tid_was_stoppedp __attribute__ ((unused)))
403 {
404   errno = ENOSYS;
405   __libdwfl_seterrno (DWFL_E_ERRNO);
406   return false;
407 }
408 
409 static bool
pid_memory_read(Dwfl * dwfl,Dwarf_Addr addr,Dwarf_Word * result,void * arg)410 pid_memory_read (Dwfl *dwfl __attribute__ ((unused)),
411                  Dwarf_Addr addr __attribute__ ((unused)),
412 	         Dwarf_Word *result __attribute__ ((unused)),
413 	         void *arg __attribute__ ((unused)))
414 {
415   errno = ENOSYS;
416   __libdwfl_seterrno (DWFL_E_ERRNO);
417   return false;
418 }
419 
420 static bool
pid_set_initial_registers(Dwfl_Thread * thread,void * thread_arg)421 pid_set_initial_registers (Dwfl_Thread *thread __attribute__ ((unused)),
422 			   void *thread_arg __attribute__ ((unused)))
423 {
424   errno = ENOSYS;
425   __libdwfl_seterrno (DWFL_E_ERRNO);
426   return false;
427 }
428 
429 static void
pid_detach(Dwfl * dwfl,void * dwfl_arg)430 pid_detach (Dwfl *dwfl __attribute__ ((unused)),
431 	    void *dwfl_arg __attribute__ ((unused)))
432 {
433 }
434 
435 void
436 internal_function
__libdwfl_ptrace_detach(pid_t tid,bool tid_was_stopped)437 __libdwfl_ptrace_detach (pid_t tid __attribute__ ((unused)),
438 			 bool tid_was_stopped __attribute__ ((unused)))
439 {
440 }
441 
442 static void
pid_thread_detach(Dwfl_Thread * thread,void * thread_arg)443 pid_thread_detach (Dwfl_Thread *thread __attribute__ ((unused)),
444 		  void *thread_arg __attribute__ ((unused)))
445 {
446 }
447 
448 static const Dwfl_Thread_Callbacks pid_thread_callbacks =
449 {
450   pid_next_thread,
451   pid_getthread,
452   pid_memory_read,
453   pid_set_initial_registers,
454   pid_detach,
455   pid_thread_detach,
456 };
457 
458 int
dwfl_linux_proc_attach(Dwfl * dwfl,pid_t pid,bool assume_ptrace_stopped)459 dwfl_linux_proc_attach (Dwfl *dwfl __attribute__ ((unused)),
460 			pid_t pid __attribute__ ((unused)),
461 			bool assume_ptrace_stopped __attribute__ ((unused)))
462 {
463   return ENOSYS;
464 }
INTDEF(dwfl_linux_proc_attach)465 INTDEF (dwfl_linux_proc_attach)
466 
467 struct __libdwfl_pid_arg *
468 internal_function
469 __libdwfl_get_pid_arg (Dwfl *dwfl __attribute__ ((unused)))
470 {
471   return NULL;
472 }
473 
474 #endif /* ! __linux __ */
475 
476