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
42static bool
43linux_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
66bool
67internal_function
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
113static bool
114pid_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
155static pid_t
156pid_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.  */
199static bool
200pid_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
214static bool
215pid_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
230static bool
231pid_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
246static void
247pid_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
254void
255internal_function
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
267static void
268pid_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
278static 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
288int
289dwfl_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}
363INTDEF (dwfl_linux_proc_attach)
364
365struct __libdwfl_pid_arg *
366internal_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
378static pid_t
379pid_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
388static bool
389pid_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
399bool
400internal_function
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
409static bool
410pid_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
420static bool
421pid_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
429static void
430pid_detach (Dwfl *dwfl __attribute__ ((unused)),
431	    void *dwfl_arg __attribute__ ((unused)))
432{
433}
434
435void
436internal_function
437__libdwfl_ptrace_detach (pid_t tid __attribute__ ((unused)),
438			 bool tid_was_stopped __attribute__ ((unused)))
439{
440}
441
442static void
443pid_thread_detach (Dwfl_Thread *thread __attribute__ ((unused)),
444		  void *thread_arg __attribute__ ((unused)))
445{
446}
447
448static 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
458int
459dwfl_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}
465INTDEF (dwfl_linux_proc_attach)
466
467struct __libdwfl_pid_arg *
468internal_function
469__libdwfl_get_pid_arg (Dwfl *dwfl __attribute__ ((unused)))
470{
471  return NULL;
472}
473
474#endif /* ! __linux __ */
475
476