103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes/* Get Dwarf Frame state for target live PID process.
203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes   Copyright (C) 2013, 2014 Red Hat, Inc.
303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes   This file is part of elfutils.
403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes   This file is free software; you can redistribute it and/or modify
603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes   it under the terms of either
703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes     * the GNU Lesser General Public License as published by the Free
903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes       Software Foundation; either version 3 of the License, or (at
1003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes       your option) any later version
1103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
1203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes   or
1303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
1403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes     * the GNU General Public License as published by the Free
1503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes       Software Foundation; either version 2 of the License, or (at
1603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes       your option) any later version
1703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
1803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes   or both in parallel, as here.
1903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
2003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes   elfutils is distributed in the hope that it will be useful, but
2103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes   WITHOUT ANY WARRANTY; without even the implied warranty of
2203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
2303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes   General Public License for more details.
2403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
2503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes   You should have received copies of the GNU General Public License and
2603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes   the GNU Lesser General Public License along with this program.  If
2703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes   not, see <http://www.gnu.org/licenses/>.  */
2803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
2903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#include "libdwflP.h"
3003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#include <sys/ptrace.h>
3103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#include <sys/wait.h>
3203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#include <dirent.h>
3303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#include <sys/syscall.h>
3403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#include <unistd.h>
3503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
3603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#ifndef MAX
3703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes# define MAX(a, b) ((a) > (b) ? (a) : (b))
3803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#endif
3903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
4003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#ifdef __linux__
4103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
4203333823c75a1c1887e923828113a1b0fd12020cElliott Hughesstatic bool
4303333823c75a1c1887e923828113a1b0fd12020cElliott Hugheslinux_proc_pid_is_stopped (pid_t pid)
4403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes{
4503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  char buffer[64];
4603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  FILE *procfile;
4703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  bool retval, have_state;
4803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
4903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  snprintf (buffer, sizeof (buffer), "/proc/%ld/status", (long) pid);
5003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  procfile = fopen (buffer, "r");
5103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  if (procfile == NULL)
5203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    return false;
5303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
5403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  have_state = false;
5503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  while (fgets (buffer, sizeof (buffer), procfile) != NULL)
5603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    if (strncmp (buffer, "State:", 6) == 0)
5703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      {
5803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	have_state = true;
5903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	break;
6003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      }
6103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  retval = (have_state && strstr (buffer, "T (stopped)") != NULL);
6203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  fclose (procfile);
6303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  return retval;
6403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes}
6503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
6603333823c75a1c1887e923828113a1b0fd12020cElliott Hughesbool
6703333823c75a1c1887e923828113a1b0fd12020cElliott Hughesinternal_function
6803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes__libdwfl_ptrace_attach (pid_t tid, bool *tid_was_stoppedp)
6903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes{
7003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  if (ptrace (PTRACE_ATTACH, tid, NULL, NULL) != 0)
7103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    {
7203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      __libdwfl_seterrno (DWFL_E_ERRNO);
7303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      return false;
7403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    }
7503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  *tid_was_stoppedp = linux_proc_pid_is_stopped (tid);
7603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  if (*tid_was_stoppedp)
7703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    {
7803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      /* Make sure there is a SIGSTOP signal pending even when the process is
7903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	 already State: T (stopped).  Older kernels might fail to generate
8003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	 a SIGSTOP notification in that case in response to our PTRACE_ATTACH
8103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	 above.  Which would make the waitpid below wait forever.  So emulate
8203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	 it.  Since there can only be one SIGSTOP notification pending this is
8303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	 safe.  See also gdb/linux-nat.c linux_nat_post_attach_wait.  */
8403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      syscall (__NR_tkill, tid, SIGSTOP);
8503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      ptrace (PTRACE_CONT, tid, NULL, NULL);
8603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    }
8703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  for (;;)
8803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    {
8903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      int status;
9003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      if (waitpid (tid, &status, __WALL) != tid || !WIFSTOPPED (status))
9103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	{
9203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  int saved_errno = errno;
9303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  ptrace (PTRACE_DETACH, tid, NULL, NULL);
9403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  errno = saved_errno;
9503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  __libdwfl_seterrno (DWFL_E_ERRNO);
9603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  return false;
9703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	}
9803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      if (WSTOPSIG (status) == SIGSTOP)
9903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	break;
10003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      if (ptrace (PTRACE_CONT, tid, NULL,
10103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		  (void *) (uintptr_t) WSTOPSIG (status)) != 0)
10203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	{
10303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  int saved_errno = errno;
10403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  ptrace (PTRACE_DETACH, tid, NULL, NULL);
10503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  errno = saved_errno;
10603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  __libdwfl_seterrno (DWFL_E_ERRNO);
10703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  return false;
10803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	}
10903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    }
11003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  return true;
11103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes}
11203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
11303333823c75a1c1887e923828113a1b0fd12020cElliott Hughesstatic bool
11403333823c75a1c1887e923828113a1b0fd12020cElliott Hughespid_memory_read (Dwfl *dwfl, Dwarf_Addr addr, Dwarf_Word *result, void *arg)
11503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes{
11603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  struct __libdwfl_pid_arg *pid_arg = arg;
11703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  pid_t tid = pid_arg->tid_attached;
11803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  assert (tid > 0);
11903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  Dwfl_Process *process = dwfl->process;
12003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  if (ebl_get_elfclass (process->ebl) == ELFCLASS64)
12103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    {
12203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#if SIZEOF_LONG == 8
12303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      errno = 0;
12403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      *result = ptrace (PTRACE_PEEKDATA, tid, (void *) (uintptr_t) addr, NULL);
12503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      return errno == 0;
12603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#else /* SIZEOF_LONG != 8 */
12703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      /* This should not happen.  */
12803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      return false;
12903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#endif /* SIZEOF_LONG != 8 */
13003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    }
13103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#if SIZEOF_LONG == 8
13203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  /* We do not care about reads unaliged to 4 bytes boundary.
13303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes     But 0x...ffc read of 8 bytes could overrun a page.  */
13403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  bool lowered = (addr & 4) != 0;
13503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  if (lowered)
13603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    addr -= 4;
13703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#endif /* SIZEOF_LONG == 8 */
13803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  errno = 0;
13903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  *result = ptrace (PTRACE_PEEKDATA, tid, (void *) (uintptr_t) addr, NULL);
14003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  if (errno != 0)
14103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    return false;
14203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#if SIZEOF_LONG == 8
14303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes# if BYTE_ORDER == BIG_ENDIAN
14403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  if (! lowered)
14503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    *result >>= 32;
14603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes# else
14703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  if (lowered)
14803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    *result >>= 32;
14903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes# endif
15003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#endif /* SIZEOF_LONG == 8 */
15103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  *result &= 0xffffffff;
15203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  return true;
15303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes}
15403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
15503333823c75a1c1887e923828113a1b0fd12020cElliott Hughesstatic pid_t
15603333823c75a1c1887e923828113a1b0fd12020cElliott Hughespid_next_thread (Dwfl *dwfl __attribute__ ((unused)), void *dwfl_arg,
15703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		 void **thread_argp)
15803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes{
15903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  struct __libdwfl_pid_arg *pid_arg = dwfl_arg;
16003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  struct dirent *dirent;
16103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  /* Start fresh on first traversal. */
16203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  if (*thread_argp == NULL)
16303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    rewinddir (pid_arg->dir);
16403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  do
16503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    {
16603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      errno = 0;
16703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      dirent = readdir (pid_arg->dir);
16803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      if (dirent == NULL)
16903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	{
17003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  if (errno != 0)
17103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    {
17203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      __libdwfl_seterrno (DWFL_E_ERRNO);
17303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	      return -1;
17403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    }
17503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  return 0;
17603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	}
17703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    }
17803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  while (strcmp (dirent->d_name, ".") == 0
17903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	 || strcmp (dirent->d_name, "..") == 0);
18003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  char *end;
18103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  errno = 0;
18203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  long tidl = strtol (dirent->d_name, &end, 10);
18303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  if (errno != 0)
18403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    {
18503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      __libdwfl_seterrno (DWFL_E_ERRNO);
18603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      return -1;
18703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    }
18803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  pid_t tid = tidl;
18903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  if (tidl <= 0 || (end && *end) || tid != tidl)
19003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    {
19103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      __libdwfl_seterrno (DWFL_E_PARSE_PROC);
19203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      return -1;
19303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    }
19403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  *thread_argp = dwfl_arg;
19503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  return tid;
19603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes}
19703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
19803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes/* Just checks that the thread id exists.  */
19903333823c75a1c1887e923828113a1b0fd12020cElliott Hughesstatic bool
20003333823c75a1c1887e923828113a1b0fd12020cElliott Hughespid_getthread (Dwfl *dwfl __attribute__ ((unused)), pid_t tid,
20103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	       void *dwfl_arg, void **thread_argp)
20203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes{
20303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  *thread_argp = dwfl_arg;
20403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  if (kill (tid, 0) < 0)
20503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    {
20603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      __libdwfl_seterrno (DWFL_E_ERRNO);
20703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      return false;
20803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    }
20903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  return true;
21003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes}
21103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
21203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes/* Implement the ebl_set_initial_registers_tid setfunc callback.  */
21303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
21403333823c75a1c1887e923828113a1b0fd12020cElliott Hughesstatic bool
21503333823c75a1c1887e923828113a1b0fd12020cElliott Hughespid_thread_state_registers_cb (int firstreg, unsigned nregs,
21603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes			       const Dwarf_Word *regs, void *arg)
21703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes{
21803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  Dwfl_Thread *thread = (Dwfl_Thread *) arg;
21903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  if (firstreg < 0)
22003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    {
22103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      assert (firstreg == -1);
22203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      assert (nregs == 1);
22303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      INTUSE(dwfl_thread_state_register_pc) (thread, *regs);
22403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      return true;
22503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    }
22603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  assert (nregs > 0);
22703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  return INTUSE(dwfl_thread_state_registers) (thread, firstreg, nregs, regs);
22803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes}
22903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
23003333823c75a1c1887e923828113a1b0fd12020cElliott Hughesstatic bool
23103333823c75a1c1887e923828113a1b0fd12020cElliott Hughespid_set_initial_registers (Dwfl_Thread *thread, void *thread_arg)
23203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes{
23303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  struct __libdwfl_pid_arg *pid_arg = thread_arg;
23403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  assert (pid_arg->tid_attached == 0);
23503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  pid_t tid = INTUSE(dwfl_thread_tid) (thread);
23603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  if (! pid_arg->assume_ptrace_stopped
23703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      && ! __libdwfl_ptrace_attach (tid, &pid_arg->tid_was_stopped))
23803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    return false;
23903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  pid_arg->tid_attached = tid;
24003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  Dwfl_Process *process = thread->process;
24103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  Ebl *ebl = process->ebl;
24203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  return ebl_set_initial_registers_tid (ebl, tid,
24303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes					pid_thread_state_registers_cb, thread);
24403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes}
24503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
24603333823c75a1c1887e923828113a1b0fd12020cElliott Hughesstatic void
24703333823c75a1c1887e923828113a1b0fd12020cElliott Hughespid_detach (Dwfl *dwfl __attribute__ ((unused)), void *dwfl_arg)
24803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes{
24903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  struct __libdwfl_pid_arg *pid_arg = dwfl_arg;
25003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  closedir (pid_arg->dir);
25103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  free (pid_arg);
25203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes}
25303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
25403333823c75a1c1887e923828113a1b0fd12020cElliott Hughesvoid
25503333823c75a1c1887e923828113a1b0fd12020cElliott Hughesinternal_function
25603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes__libdwfl_ptrace_detach (pid_t tid, bool tid_was_stopped)
25703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes{
25803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  /* This handling is needed only on older Linux kernels such as
25903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes     2.6.32-358.23.2.el6.ppc64.  Later kernels such as
26003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes     3.11.7-200.fc19.x86_64 remember the T (stopped) state
26103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes     themselves and no longer need to pass SIGSTOP during
26203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes     PTRACE_DETACH.  */
26303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  ptrace (PTRACE_DETACH, tid, NULL,
26403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  (void *) (intptr_t) (tid_was_stopped ? SIGSTOP : 0));
26503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes}
26603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
26703333823c75a1c1887e923828113a1b0fd12020cElliott Hughesstatic void
26803333823c75a1c1887e923828113a1b0fd12020cElliott Hughespid_thread_detach (Dwfl_Thread *thread, void *thread_arg)
26903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes{
27003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  struct __libdwfl_pid_arg *pid_arg = thread_arg;
27103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  pid_t tid = INTUSE(dwfl_thread_tid) (thread);
27203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  assert (pid_arg->tid_attached == tid);
27303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  pid_arg->tid_attached = 0;
27403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  if (! pid_arg->assume_ptrace_stopped)
27503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    __libdwfl_ptrace_detach (tid, pid_arg->tid_was_stopped);
27603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes}
27703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
27803333823c75a1c1887e923828113a1b0fd12020cElliott Hughesstatic const Dwfl_Thread_Callbacks pid_thread_callbacks =
27903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes{
28003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  pid_next_thread,
28103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  pid_getthread,
28203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  pid_memory_read,
28303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  pid_set_initial_registers,
28403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  pid_detach,
28503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  pid_thread_detach,
28603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes};
28703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
28803333823c75a1c1887e923828113a1b0fd12020cElliott Hughesint
28903333823c75a1c1887e923828113a1b0fd12020cElliott Hughesdwfl_linux_proc_attach (Dwfl *dwfl, pid_t pid, bool assume_ptrace_stopped)
29003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes{
29103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  char buffer[36];
29203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  FILE *procfile;
29303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  int err = 0; /* The errno to return and set for dwfl->attcherr.  */
29403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
29503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  /* Make sure to report the actual PID (thread group leader) to
29603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes     dwfl_attach_state.  */
29703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  snprintf (buffer, sizeof (buffer), "/proc/%ld/status", (long) pid);
29803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  procfile = fopen (buffer, "r");
29903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  if (procfile == NULL)
30003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    {
30103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      err = errno;
30203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    fail:
30303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      if (dwfl->process == NULL && dwfl->attacherr == DWFL_E_NOERROR)
30403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	{
30503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  errno = err;
30603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  dwfl->attacherr = __libdwfl_canon_error (DWFL_E_ERRNO);
30703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	}
30803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      return err;
30903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    }
31003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
31103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  char *line = NULL;
31203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  size_t linelen = 0;
31303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  while (getline (&line, &linelen, procfile) >= 0)
31403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    if (strncmp (line, "Tgid:", 5) == 0)
31503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      {
31603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	errno = 0;
31703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	char *endptr;
31803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	long val = strtol (&line[5], &endptr, 10);
31903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	if ((errno == ERANGE && val == LONG_MAX)
32003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    || *endptr != '\n' || val < 0 || val != (pid_t) val)
32103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  pid = 0;
32203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	else
32303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	  pid = (pid_t) val;
32403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	break;
32503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      }
32603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  free (line);
32703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  fclose (procfile);
32803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
32903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  if (pid == 0)
33003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    {
33103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      err = ESRCH;
33203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      goto fail;
33303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    }
33403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
33503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  char dirname[64];
33603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  int i = snprintf (dirname, sizeof (dirname), "/proc/%ld/task", (long) pid);
33703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  assert (i > 0 && i < (ssize_t) sizeof (dirname) - 1);
33803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  DIR *dir = opendir (dirname);
33903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  if (dir == NULL)
34003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    {
34103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      err = errno;
34203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      goto fail;
34303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    }
34403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  struct __libdwfl_pid_arg *pid_arg = malloc (sizeof *pid_arg);
34503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  if (pid_arg == NULL)
34603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    {
34703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      closedir (dir);
34803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      err = ENOMEM;
34903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      goto fail;
35003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    }
35103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  pid_arg->dir = dir;
35203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  pid_arg->tid_attached = 0;
35303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  pid_arg->assume_ptrace_stopped = assume_ptrace_stopped;
35403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  if (! INTUSE(dwfl_attach_state) (dwfl, NULL, pid, &pid_thread_callbacks,
35503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes				   pid_arg))
35603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    {
35703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      closedir (dir);
35803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      free (pid_arg);
35903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      return -1;
36003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    }
36103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  return 0;
36203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes}
36303333823c75a1c1887e923828113a1b0fd12020cElliott HughesINTDEF (dwfl_linux_proc_attach)
36403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
36503333823c75a1c1887e923828113a1b0fd12020cElliott Hughesstruct __libdwfl_pid_arg *
36603333823c75a1c1887e923828113a1b0fd12020cElliott Hughesinternal_function
36703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes__libdwfl_get_pid_arg (Dwfl *dwfl)
36803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes{
36903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  if (dwfl != NULL && dwfl->process != NULL
37003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes      && dwfl->process->callbacks == &pid_thread_callbacks)
37103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes    return (struct __libdwfl_pid_arg *) dwfl->process->callbacks_arg;
37203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
37303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  return NULL;
37403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes}
37503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
37603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#else	/* __linux__ */
37703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
37803333823c75a1c1887e923828113a1b0fd12020cElliott Hughesstatic pid_t
37903333823c75a1c1887e923828113a1b0fd12020cElliott Hughespid_next_thread (Dwfl *dwfl __attribute__ ((unused)),
38003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	         void *dwfl_arg __attribute__ ((unused)),
38103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		 void **thread_argp __attribute__ ((unused)))
38203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes{
38303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  errno = ENOSYS;
38403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  __libdwfl_seterrno (DWFL_E_ERRNO);
38503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  return -1;
38603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes}
38703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
38803333823c75a1c1887e923828113a1b0fd12020cElliott Hughesstatic bool
38903333823c75a1c1887e923828113a1b0fd12020cElliott Hughespid_getthread (Dwfl *dwfl __attribute__ ((unused)),
39003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	       pid_t tid __attribute__ ((unused)),
39103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	       void *dwfl_arg __attribute__ ((unused)),
39203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	       void **thread_argp __attribute__ ((unused)))
39303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes{
39403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  errno = ENOSYS;
39503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  __libdwfl_seterrno (DWFL_E_ERRNO);
39603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  return false;
39703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes}
39803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
39903333823c75a1c1887e923828113a1b0fd12020cElliott Hughesbool
40003333823c75a1c1887e923828113a1b0fd12020cElliott Hughesinternal_function
40103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes__libdwfl_ptrace_attach (pid_t tid __attribute__ ((unused)),
40203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes			 bool *tid_was_stoppedp __attribute__ ((unused)))
40303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes{
40403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  errno = ENOSYS;
40503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  __libdwfl_seterrno (DWFL_E_ERRNO);
40603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  return false;
40703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes}
40803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
40903333823c75a1c1887e923828113a1b0fd12020cElliott Hughesstatic bool
41003333823c75a1c1887e923828113a1b0fd12020cElliott Hughespid_memory_read (Dwfl *dwfl __attribute__ ((unused)),
41103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes                 Dwarf_Addr addr __attribute__ ((unused)),
41203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	         Dwarf_Word *result __attribute__ ((unused)),
41303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	         void *arg __attribute__ ((unused)))
41403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes{
41503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  errno = ENOSYS;
41603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  __libdwfl_seterrno (DWFL_E_ERRNO);
41703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  return false;
41803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes}
41903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
42003333823c75a1c1887e923828113a1b0fd12020cElliott Hughesstatic bool
42103333823c75a1c1887e923828113a1b0fd12020cElliott Hughespid_set_initial_registers (Dwfl_Thread *thread __attribute__ ((unused)),
42203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes			   void *thread_arg __attribute__ ((unused)))
42303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes{
42403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  errno = ENOSYS;
42503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  __libdwfl_seterrno (DWFL_E_ERRNO);
42603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  return false;
42703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes}
42803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
42903333823c75a1c1887e923828113a1b0fd12020cElliott Hughesstatic void
43003333823c75a1c1887e923828113a1b0fd12020cElliott Hughespid_detach (Dwfl *dwfl __attribute__ ((unused)),
43103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes	    void *dwfl_arg __attribute__ ((unused)))
43203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes{
43303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes}
43403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
43503333823c75a1c1887e923828113a1b0fd12020cElliott Hughesvoid
43603333823c75a1c1887e923828113a1b0fd12020cElliott Hughesinternal_function
43703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes__libdwfl_ptrace_detach (pid_t tid __attribute__ ((unused)),
43803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes			 bool tid_was_stopped __attribute__ ((unused)))
43903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes{
44003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes}
44103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
44203333823c75a1c1887e923828113a1b0fd12020cElliott Hughesstatic void
44303333823c75a1c1887e923828113a1b0fd12020cElliott Hughespid_thread_detach (Dwfl_Thread *thread __attribute__ ((unused)),
44403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes		  void *thread_arg __attribute__ ((unused)))
44503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes{
44603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes}
44703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
44803333823c75a1c1887e923828113a1b0fd12020cElliott Hughesstatic const Dwfl_Thread_Callbacks pid_thread_callbacks =
44903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes{
45003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  pid_next_thread,
45103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  pid_getthread,
45203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  pid_memory_read,
45303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  pid_set_initial_registers,
45403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  pid_detach,
45503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  pid_thread_detach,
45603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes};
45703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
45803333823c75a1c1887e923828113a1b0fd12020cElliott Hughesint
45903333823c75a1c1887e923828113a1b0fd12020cElliott Hughesdwfl_linux_proc_attach (Dwfl *dwfl __attribute__ ((unused)),
46003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes			pid_t pid __attribute__ ((unused)),
46103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes			bool assume_ptrace_stopped __attribute__ ((unused)))
46203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes{
46303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  return ENOSYS;
46403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes}
46503333823c75a1c1887e923828113a1b0fd12020cElliott HughesINTDEF (dwfl_linux_proc_attach)
46603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
46703333823c75a1c1887e923828113a1b0fd12020cElliott Hughesstruct __libdwfl_pid_arg *
46803333823c75a1c1887e923828113a1b0fd12020cElliott Hughesinternal_function
46903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes__libdwfl_get_pid_arg (Dwfl *dwfl __attribute__ ((unused)))
47003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes{
47103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes  return NULL;
47203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes}
47303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
47403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#endif /* ! __linux __ */
47503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes
476