linux-pid-attach.c revision 19108019192ab273c53ae324be448d29dac806ca
10b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil/* Get Dwarf Frame state for target live PID process.
20b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil   Copyright (C) 2013 Red Hat, Inc.
30b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil   This file is part of elfutils.
40b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil
50b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil   This file is free software; you can redistribute it and/or modify
60b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil   it under the terms of either
70b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil
80b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil     * the GNU Lesser General Public License as published by the Free
90b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil       Software Foundation; either version 3 of the License, or (at
100b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil       your option) any later version
110b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil
120b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil   or
130b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil
140b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil     * the GNU General Public License as published by the Free
150b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil       Software Foundation; either version 2 of the License, or (at
160b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil       your option) any later version
170b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil
180b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil   or both in parallel, as here.
190b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil
200b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil   elfutils is distributed in the hope that it will be useful, but
210b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil   WITHOUT ANY WARRANTY; without even the implied warranty of
220b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
230b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil   General Public License for more details.
240b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil
250b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil   You should have received copies of the GNU General Public License and
260b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil   the GNU Lesser General Public License along with this program.  If
270b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil   not, see <http://www.gnu.org/licenses/>.  */
280b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil
290b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil#include "libdwflP.h"
300b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil#include <sys/ptrace.h>
310b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil#include <sys/wait.h>
320b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil#include <dirent.h>
330b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil#include <sys/syscall.h>
340b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil#include <unistd.h>
350b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil
360b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil#ifndef MAX
370b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil# define MAX(a, b) ((a) > (b) ? (a) : (b))
380b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil#endif
390b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil
400b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvilstruct pid_arg
410b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil{
420b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil  DIR *dir;
430b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil  /* It is 0 if not used.  */
440b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil  pid_t tid_attached;
4510d7a39aa2a509c16edd205c94b365ff1696f4fbJan Kratochvil  /* Valid only if TID_ATTACHED is not zero.  */
4610d7a39aa2a509c16edd205c94b365ff1696f4fbJan Kratochvil  bool tid_was_stopped;
4719108019192ab273c53ae324be448d29dac806caMark Wielaard  /* True if threads are ptrace stopped by caller.  */
4819108019192ab273c53ae324be448d29dac806caMark Wielaard  bool assume_ptrace_stopped;
490b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil};
500b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil
510b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvilstatic bool
520b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvillinux_proc_pid_is_stopped (pid_t pid)
530b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil{
540b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil  char buffer[64];
550b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil  FILE *procfile;
560b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil  bool retval, have_state;
570b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil
580b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil  snprintf (buffer, sizeof (buffer), "/proc/%ld/status", (long) pid);
590b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil  procfile = fopen (buffer, "r");
600b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil  if (procfile == NULL)
610b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil    return false;
620b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil
630b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil  have_state = false;
640b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil  while (fgets (buffer, sizeof (buffer), procfile) != NULL)
650b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil    if (strncmp (buffer, "State:", 6) == 0)
660b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil      {
670b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil	have_state = true;
680b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil	break;
690b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil      }
700b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil  retval = (have_state && strstr (buffer, "T (stopped)") != NULL);
710b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil  fclose (procfile);
720b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil  return retval;
730b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil}
740b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil
750b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvilstatic bool
7610d7a39aa2a509c16edd205c94b365ff1696f4fbJan Kratochvilptrace_attach (pid_t tid, bool *tid_was_stoppedp)
770b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil{
780b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil  if (ptrace (PTRACE_ATTACH, tid, NULL, NULL) != 0)
790b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil    {
800b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil      __libdwfl_seterrno (DWFL_E_ERRNO);
810b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil      return false;
820b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil    }
8310d7a39aa2a509c16edd205c94b365ff1696f4fbJan Kratochvil  *tid_was_stoppedp = linux_proc_pid_is_stopped (tid);
8410d7a39aa2a509c16edd205c94b365ff1696f4fbJan Kratochvil  if (*tid_was_stoppedp)
850b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil    {
860b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil      /* Make sure there is a SIGSTOP signal pending even when the process is
870b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil	 already State: T (stopped).  Older kernels might fail to generate
880b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil	 a SIGSTOP notification in that case in response to our PTRACE_ATTACH
890b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil	 above.  Which would make the waitpid below wait forever.  So emulate
900b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil	 it.  Since there can only be one SIGSTOP notification pending this is
910b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil	 safe.  See also gdb/linux-nat.c linux_nat_post_attach_wait.  */
920b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil      syscall (__NR_tkill, tid, SIGSTOP);
930b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil      ptrace (PTRACE_CONT, tid, NULL, NULL);
940b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil    }
950b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil  for (;;)
960b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil    {
970b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil      int status;
980b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil      if (waitpid (tid, &status, __WALL) != tid || !WIFSTOPPED (status))
990b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil	{
1000b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil	  int saved_errno = errno;
1010b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil	  ptrace (PTRACE_DETACH, tid, NULL, NULL);
1020b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil	  errno = saved_errno;
1030b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil	  __libdwfl_seterrno (DWFL_E_ERRNO);
1040b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil	  return false;
1050b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil	}
1060b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil      if (WSTOPSIG (status) == SIGSTOP)
1070b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil	break;
1080b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil      if (ptrace (PTRACE_CONT, tid, NULL,
1090b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil		  (void *) (uintptr_t) WSTOPSIG (status)) != 0)
1100b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil	{
1110b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil	  int saved_errno = errno;
1120b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil	  ptrace (PTRACE_DETACH, tid, NULL, NULL);
1130b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil	  errno = saved_errno;
1140b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil	  __libdwfl_seterrno (DWFL_E_ERRNO);
1150b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil	  return false;
1160b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil	}
1170b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil    }
1180b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil  return true;
1190b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil}
1200b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil
1210b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvilstatic bool
1220b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvilpid_memory_read (Dwfl *dwfl, Dwarf_Addr addr, Dwarf_Word *result, void *arg)
1230b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil{
1240b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil  struct pid_arg *pid_arg = arg;
1250b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil  pid_t tid = pid_arg->tid_attached;
1260b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil  assert (tid > 0);
1270b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil  Dwfl_Process *process = dwfl->process;
1280b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil  if (ebl_get_elfclass (process->ebl) == ELFCLASS64)
1290b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil    {
1300b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil#if SIZEOF_LONG == 8
1310b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil      errno = 0;
1320b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil      *result = ptrace (PTRACE_PEEKDATA, tid, (void *) (uintptr_t) addr, NULL);
1330b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil      return errno == 0;
1340b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil#else /* SIZEOF_LONG != 8 */
1350b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil      /* This should not happen.  */
1360b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil      return false;
1370b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil#endif /* SIZEOF_LONG != 8 */
1380b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil    }
1390b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil#if SIZEOF_LONG == 8
1400b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil  /* We do not care about reads unaliged to 4 bytes boundary.
1410b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil     But 0x...ffc read of 8 bytes could overrun a page.  */
1420b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil  bool lowered = (addr & 4) != 0;
1430b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil  if (lowered)
1440b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil    addr -= 4;
1450b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil#endif /* SIZEOF_LONG == 8 */
1460b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil  errno = 0;
1470b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil  *result = ptrace (PTRACE_PEEKDATA, tid, (void *) (uintptr_t) addr, NULL);
1480b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil  if (errno != 0)
1490b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil    return false;
1500b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil#if SIZEOF_LONG == 8
1510b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil# if BYTE_ORDER == BIG_ENDIAN
1520b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil  if (! lowered)
1530b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil    *result >>= 32;
1540b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil# else
1550b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil  if (lowered)
1560b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil    *result >>= 32;
1570b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil# endif
1580b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil#endif /* SIZEOF_LONG == 8 */
1590b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil  *result &= 0xffffffff;
1600b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil  return true;
1610b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil}
1620b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil
1630b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvilstatic pid_t
1640b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvilpid_next_thread (Dwfl *dwfl __attribute__ ((unused)), void *dwfl_arg,
1650b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil		 void **thread_argp)
1660b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil{
1670b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil  struct pid_arg *pid_arg = dwfl_arg;
1680b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil  struct dirent *dirent;
169c76b2ff3eebc04c628ea7475c7ea0abb6cf0ff0dMark Wielaard  /* Start fresh on first traversal. */
170c76b2ff3eebc04c628ea7475c7ea0abb6cf0ff0dMark Wielaard  if (*thread_argp == NULL)
171c76b2ff3eebc04c628ea7475c7ea0abb6cf0ff0dMark Wielaard    rewinddir (pid_arg->dir);
1720b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil  do
1730b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil    {
1740b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil      errno = 0;
1750b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil      dirent = readdir (pid_arg->dir);
1760b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil      if (dirent == NULL)
1770b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil	{
1780b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil	  if (errno != 0)
1790b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil	    {
1800b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil	      __libdwfl_seterrno (DWFL_E_ERRNO);
1810b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil	      return -1;
1820b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil	    }
1830b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil	  return 0;
1840b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil	}
1850b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil    }
1860b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil  while (strcmp (dirent->d_name, ".") == 0
1870b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil	 || strcmp (dirent->d_name, "..") == 0);
1880b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil  char *end;
1890b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil  errno = 0;
1900b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil  long tidl = strtol (dirent->d_name, &end, 10);
1910b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil  if (errno != 0)
1920b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil    {
1930b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil      __libdwfl_seterrno (DWFL_E_ERRNO);
1940b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil      return -1;
1950b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil    }
1960b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil  pid_t tid = tidl;
1970b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil  if (tidl <= 0 || (end && *end) || tid != tidl)
1980b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil    {
1990b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil      __libdwfl_seterrno (DWFL_E_PARSE_PROC);
2000b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil      return -1;
2010b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil    }
2020b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil  *thread_argp = dwfl_arg;
2030b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil  return tid;
2040b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil}
2050b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil
206e962ec3bcbe8eccdcded36aaafee7bec41fa1bc4Mark Wielaard/* Just checks that the thread id exists.  */
207e962ec3bcbe8eccdcded36aaafee7bec41fa1bc4Mark Wielaardstatic bool
208e962ec3bcbe8eccdcded36aaafee7bec41fa1bc4Mark Wielaardpid_getthread (Dwfl *dwfl __attribute__ ((unused)), pid_t tid,
209e962ec3bcbe8eccdcded36aaafee7bec41fa1bc4Mark Wielaard	       void *dwfl_arg, void **thread_argp)
210e962ec3bcbe8eccdcded36aaafee7bec41fa1bc4Mark Wielaard{
211e962ec3bcbe8eccdcded36aaafee7bec41fa1bc4Mark Wielaard  *thread_argp = dwfl_arg;
212e962ec3bcbe8eccdcded36aaafee7bec41fa1bc4Mark Wielaard  if (kill (tid, 0) < 0)
213e962ec3bcbe8eccdcded36aaafee7bec41fa1bc4Mark Wielaard    {
214e962ec3bcbe8eccdcded36aaafee7bec41fa1bc4Mark Wielaard      __libdwfl_seterrno (DWFL_E_ERRNO);
215e962ec3bcbe8eccdcded36aaafee7bec41fa1bc4Mark Wielaard      return false;
216e962ec3bcbe8eccdcded36aaafee7bec41fa1bc4Mark Wielaard    }
217e962ec3bcbe8eccdcded36aaafee7bec41fa1bc4Mark Wielaard  return true;
218e962ec3bcbe8eccdcded36aaafee7bec41fa1bc4Mark Wielaard}
219e962ec3bcbe8eccdcded36aaafee7bec41fa1bc4Mark Wielaard
2200b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil/* Implement the ebl_set_initial_registers_tid setfunc callback.  */
2210b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil
2220b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvilstatic bool
2231c1a53b657ef31b168928925884c01a7e4bcaf0cJan Kratochvilpid_thread_state_registers_cb (int firstreg, unsigned nregs,
2241c1a53b657ef31b168928925884c01a7e4bcaf0cJan Kratochvil			       const Dwarf_Word *regs, void *arg)
2250b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil{
2260b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil  Dwfl_Thread *thread = (Dwfl_Thread *) arg;
2275cbf42aaf47195e2c41171786371d55b253a7667Jan Kratochvil  if (firstreg < 0)
2285cbf42aaf47195e2c41171786371d55b253a7667Jan Kratochvil    {
2295cbf42aaf47195e2c41171786371d55b253a7667Jan Kratochvil      assert (firstreg == -1);
2305cbf42aaf47195e2c41171786371d55b253a7667Jan Kratochvil      assert (nregs == 1);
2315cbf42aaf47195e2c41171786371d55b253a7667Jan Kratochvil      INTUSE(dwfl_thread_state_register_pc) (thread, *regs);
2325cbf42aaf47195e2c41171786371d55b253a7667Jan Kratochvil      return true;
2335cbf42aaf47195e2c41171786371d55b253a7667Jan Kratochvil    }
2345cbf42aaf47195e2c41171786371d55b253a7667Jan Kratochvil  assert (nregs > 0);
2350b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil  return INTUSE(dwfl_thread_state_registers) (thread, firstreg, nregs, regs);
2360b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil}
2370b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil
2380b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvilstatic bool
2390b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvilpid_set_initial_registers (Dwfl_Thread *thread, void *thread_arg)
2400b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil{
2410b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil  struct pid_arg *pid_arg = thread_arg;
2420b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil  assert (pid_arg->tid_attached == 0);
2430b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil  pid_t tid = INTUSE(dwfl_thread_tid) (thread);
24419108019192ab273c53ae324be448d29dac806caMark Wielaard  if (! pid_arg->assume_ptrace_stopped
24519108019192ab273c53ae324be448d29dac806caMark Wielaard      && ! ptrace_attach (tid, &pid_arg->tid_was_stopped))
2460b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil    return false;
2470b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil  pid_arg->tid_attached = tid;
2480b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil  Dwfl_Process *process = thread->process;
2490b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil  Ebl *ebl = process->ebl;
2500b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil  return ebl_set_initial_registers_tid (ebl, tid,
2510b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil					pid_thread_state_registers_cb, thread);
2520b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil}
2530b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil
2540b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvilstatic void
2550b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvilpid_detach (Dwfl *dwfl __attribute__ ((unused)), void *dwfl_arg)
2560b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil{
2570b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil  struct pid_arg *pid_arg = dwfl_arg;
2580b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil  closedir (pid_arg->dir);
2590b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil  free (pid_arg);
2600b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil}
2610b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil
2620b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvilstatic void
2630b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvilpid_thread_detach (Dwfl_Thread *thread, void *thread_arg)
2640b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil{
2650b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil  struct pid_arg *pid_arg = thread_arg;
2660b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil  pid_t tid = INTUSE(dwfl_thread_tid) (thread);
2670b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil  assert (pid_arg->tid_attached == tid);
2680b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil  pid_arg->tid_attached = 0;
26919108019192ab273c53ae324be448d29dac806caMark Wielaard  if (! pid_arg->assume_ptrace_stopped)
27019108019192ab273c53ae324be448d29dac806caMark Wielaard    {
27119108019192ab273c53ae324be448d29dac806caMark Wielaard      /* This handling is needed only on older Linux kernels such as
27219108019192ab273c53ae324be448d29dac806caMark Wielaard         2.6.32-358.23.2.el6.ppc64.  Later kernels such as
27319108019192ab273c53ae324be448d29dac806caMark Wielaard         3.11.7-200.fc19.x86_64 remember the T (stopped) state
27419108019192ab273c53ae324be448d29dac806caMark Wielaard         themselves and no longer need to pass SIGSTOP during
27519108019192ab273c53ae324be448d29dac806caMark Wielaard         PTRACE_DETACH.  */
27619108019192ab273c53ae324be448d29dac806caMark Wielaard      ptrace (PTRACE_DETACH, tid, NULL,
27719108019192ab273c53ae324be448d29dac806caMark Wielaard	      (void *) (intptr_t) (pid_arg->tid_was_stopped ? SIGSTOP : 0));
27819108019192ab273c53ae324be448d29dac806caMark Wielaard    }
2790b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil}
2800b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil
2810b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvilstatic const Dwfl_Thread_Callbacks pid_thread_callbacks =
2820b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil{
2830b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil  pid_next_thread,
284e962ec3bcbe8eccdcded36aaafee7bec41fa1bc4Mark Wielaard  pid_getthread,
2850b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil  pid_memory_read,
2860b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil  pid_set_initial_registers,
2870b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil  pid_detach,
2880b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil  pid_thread_detach,
2890b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil};
2900b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil
29119108019192ab273c53ae324be448d29dac806caMark Wielaardint
29219108019192ab273c53ae324be448d29dac806caMark Wielaarddwfl_linux_proc_attach (Dwfl *dwfl, pid_t pid, bool assume_ptrace_stopped)
2930b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil{
29497bbf9b7ca002aab236bf750aba699d81f7985f7Mark Wielaard  char buffer[36];
29597bbf9b7ca002aab236bf750aba699d81f7985f7Mark Wielaard  FILE *procfile;
29697bbf9b7ca002aab236bf750aba699d81f7985f7Mark Wielaard
29797bbf9b7ca002aab236bf750aba699d81f7985f7Mark Wielaard  /* Make sure to report the actual PID (thread group leader) to
29897bbf9b7ca002aab236bf750aba699d81f7985f7Mark Wielaard     dwfl_attach_state.  */
29997bbf9b7ca002aab236bf750aba699d81f7985f7Mark Wielaard  snprintf (buffer, sizeof (buffer), "/proc/%ld/status", (long) pid);
30097bbf9b7ca002aab236bf750aba699d81f7985f7Mark Wielaard  procfile = fopen (buffer, "r");
30197bbf9b7ca002aab236bf750aba699d81f7985f7Mark Wielaard  if (procfile == NULL)
30219108019192ab273c53ae324be448d29dac806caMark Wielaard    return errno;
30397bbf9b7ca002aab236bf750aba699d81f7985f7Mark Wielaard
30497bbf9b7ca002aab236bf750aba699d81f7985f7Mark Wielaard  char *line = NULL;
30597bbf9b7ca002aab236bf750aba699d81f7985f7Mark Wielaard  size_t linelen = 0;
30697bbf9b7ca002aab236bf750aba699d81f7985f7Mark Wielaard  while (getline (&line, &linelen, procfile) >= 0)
30797bbf9b7ca002aab236bf750aba699d81f7985f7Mark Wielaard    if (strncmp (line, "Tgid:", 5) == 0)
30897bbf9b7ca002aab236bf750aba699d81f7985f7Mark Wielaard      {
30997bbf9b7ca002aab236bf750aba699d81f7985f7Mark Wielaard        pid = atoi (&line[5]);
31097bbf9b7ca002aab236bf750aba699d81f7985f7Mark Wielaard        break;
31197bbf9b7ca002aab236bf750aba699d81f7985f7Mark Wielaard      }
31297bbf9b7ca002aab236bf750aba699d81f7985f7Mark Wielaard  free (line);
31397bbf9b7ca002aab236bf750aba699d81f7985f7Mark Wielaard  fclose (procfile);
31497bbf9b7ca002aab236bf750aba699d81f7985f7Mark Wielaard
31597bbf9b7ca002aab236bf750aba699d81f7985f7Mark Wielaard  if (pid == 0)
31619108019192ab273c53ae324be448d29dac806caMark Wielaard    return ESRCH;
31797bbf9b7ca002aab236bf750aba699d81f7985f7Mark Wielaard
3180b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil  char dirname[64];
3190b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil  int i = snprintf (dirname, sizeof (dirname), "/proc/%ld/task", (long) pid);
3200b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil  assert (i > 0 && i < (ssize_t) sizeof (dirname) - 1);
3210b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil  DIR *dir = opendir (dirname);
3220b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil  if (dir == NULL)
32319108019192ab273c53ae324be448d29dac806caMark Wielaard    return errno;
3240b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil  struct pid_arg *pid_arg = malloc (sizeof *pid_arg);
3250b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil  if (pid_arg == NULL)
3260b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil    {
3270b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil      closedir (dir);
32819108019192ab273c53ae324be448d29dac806caMark Wielaard      return ENOMEM;
3290b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil    }
3300b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil  pid_arg->dir = dir;
3310b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil  pid_arg->tid_attached = 0;
33219108019192ab273c53ae324be448d29dac806caMark Wielaard  pid_arg->assume_ptrace_stopped = assume_ptrace_stopped;
333ed78237ef7c31fb1d7dc80e2c2e07484e1216727Jan Kratochvil  if (! INTUSE(dwfl_attach_state) (dwfl, NULL, pid, &pid_thread_callbacks,
3340b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil				   pid_arg))
3350b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil    {
3360b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil      closedir (dir);
3370b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil      free (pid_arg);
33819108019192ab273c53ae324be448d29dac806caMark Wielaard      return -1;
3390b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil    }
34019108019192ab273c53ae324be448d29dac806caMark Wielaard  return 0;
3410b867460075c9f02cb305abc91a0e12b90017583Jan Kratochvil}
34219108019192ab273c53ae324be448d29dac806caMark WielaardINTDEF (dwfl_linux_proc_attach)
343