Blame libdwfl/linux-pid-attach.c

Packit 032894
/* Get Dwarf Frame state for target live PID process.
Packit 032894
   Copyright (C) 2013, 2014, 2015, 2018 Red Hat, Inc.
Packit 032894
   This file is part of elfutils.
Packit 032894
Packit 032894
   This file is free software; you can redistribute it and/or modify
Packit 032894
   it under the terms of either
Packit 032894
Packit 032894
     * the GNU Lesser General Public License as published by the Free
Packit 032894
       Software Foundation; either version 3 of the License, or (at
Packit 032894
       your option) any later version
Packit 032894
Packit 032894
   or
Packit 032894
Packit 032894
     * the GNU General Public License as published by the Free
Packit 032894
       Software Foundation; either version 2 of the License, or (at
Packit 032894
       your option) any later version
Packit 032894
Packit 032894
   or both in parallel, as here.
Packit 032894
Packit 032894
   elfutils is distributed in the hope that it will be useful, but
Packit 032894
   WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 032894
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 032894
   General Public License for more details.
Packit 032894
Packit 032894
   You should have received copies of the GNU General Public License and
Packit 032894
   the GNU Lesser General Public License along with this program.  If
Packit 032894
   not, see <http://www.gnu.org/licenses/>.  */
Packit 032894
Packit 032894
#ifdef HAVE_CONFIG_H
Packit 032894
# include <config.h>
Packit 032894
#endif
Packit 032894
Packit 032894
#include "libelfP.h"
Packit 032894
#include "libdwflP.h"
Packit 032894
#include <sys/types.h>
Packit 032894
#include <sys/stat.h>
Packit 032894
#include <fcntl.h>
Packit 032894
#include <dirent.h>
Packit 032894
#include <unistd.h>
Packit 032894
Packit 032894
#ifdef __linux__
Packit 032894
Packit 032894
#include <sys/uio.h>
Packit 032894
#include <sys/ptrace.h>
Packit 032894
#include <sys/syscall.h>
Packit 032894
#include <sys/wait.h>
Packit 032894
Packit 032894
static bool
Packit 032894
linux_proc_pid_is_stopped (pid_t pid)
Packit 032894
{
Packit 032894
  char buffer[64];
Packit 032894
  FILE *procfile;
Packit 032894
  bool retval, have_state;
Packit 032894
Packit 032894
  snprintf (buffer, sizeof (buffer), "/proc/%ld/status", (long) pid);
Packit 032894
  procfile = fopen (buffer, "r");
Packit 032894
  if (procfile == NULL)
Packit 032894
    return false;
Packit 032894
Packit 032894
  have_state = false;
Packit 032894
  while (fgets (buffer, sizeof (buffer), procfile) != NULL)
Packit 032894
    if (strncmp (buffer, "State:", 6) == 0)
Packit 032894
      {
Packit 032894
	have_state = true;
Packit 032894
	break;
Packit 032894
      }
Packit 032894
  retval = (have_state && strstr (buffer, "T (stopped)") != NULL);
Packit 032894
  fclose (procfile);
Packit 032894
  return retval;
Packit 032894
}
Packit 032894
Packit 032894
bool
Packit 032894
internal_function
Packit 032894
__libdwfl_ptrace_attach (pid_t tid, bool *tid_was_stoppedp)
Packit 032894
{
Packit 032894
  if (ptrace (PTRACE_ATTACH, tid, NULL, NULL) != 0)
Packit 032894
    {
Packit 032894
      __libdwfl_seterrno (DWFL_E_ERRNO);
Packit 032894
      return false;
Packit 032894
    }
Packit 032894
  *tid_was_stoppedp = linux_proc_pid_is_stopped (tid);
Packit 032894
  if (*tid_was_stoppedp)
Packit 032894
    {
Packit 032894
      /* Make sure there is a SIGSTOP signal pending even when the process is
Packit 032894
	 already State: T (stopped).  Older kernels might fail to generate
Packit 032894
	 a SIGSTOP notification in that case in response to our PTRACE_ATTACH
Packit 032894
	 above.  Which would make the waitpid below wait forever.  So emulate
Packit 032894
	 it.  Since there can only be one SIGSTOP notification pending this is
Packit 032894
	 safe.  See also gdb/linux-nat.c linux_nat_post_attach_wait.  */
Packit 032894
      syscall (__NR_tkill, tid, SIGSTOP);
Packit 032894
      ptrace (PTRACE_CONT, tid, NULL, NULL);
Packit 032894
    }
Packit 032894
  for (;;)
Packit 032894
    {
Packit 032894
      int status;
Packit 032894
      if (waitpid (tid, &status, __WALL) != tid || !WIFSTOPPED (status))
Packit 032894
	{
Packit 032894
	  int saved_errno = errno;
Packit 032894
	  ptrace (PTRACE_DETACH, tid, NULL, NULL);
Packit 032894
	  errno = saved_errno;
Packit 032894
	  __libdwfl_seterrno (DWFL_E_ERRNO);
Packit 032894
	  return false;
Packit 032894
	}
Packit 032894
      if (WSTOPSIG (status) == SIGSTOP)
Packit 032894
	break;
Packit 032894
      if (ptrace (PTRACE_CONT, tid, NULL,
Packit 032894
		  (void *) (uintptr_t) WSTOPSIG (status)) != 0)
Packit 032894
	{
Packit 032894
	  int saved_errno = errno;
Packit 032894
	  ptrace (PTRACE_DETACH, tid, NULL, NULL);
Packit 032894
	  errno = saved_errno;
Packit 032894
	  __libdwfl_seterrno (DWFL_E_ERRNO);
Packit 032894
	  return false;
Packit 032894
	}
Packit 032894
    }
Packit 032894
  return true;
Packit 032894
}
Packit 032894
Packit 032894
#ifdef HAVE_PROCESS_VM_READV
Packit 032894
/* Note that the result word size depends on the architecture word size.
Packit 032894
   That is sizeof long. */
Packit 032894
static bool
Packit 032894
read_cached_memory (struct __libdwfl_pid_arg *pid_arg,
Packit 032894
		    Dwarf_Addr addr, Dwarf_Word *result)
Packit 032894
{
Packit 032894
  /* Let the ptrace fallback deal with the corner case of the address
Packit 032894
     possibly crossing a page boundery.  */
Packit 032894
  if ((addr & ((Dwarf_Addr)__LIBDWFL_REMOTE_MEM_CACHE_SIZE - 1))
Packit 032894
      > (Dwarf_Addr)__LIBDWFL_REMOTE_MEM_CACHE_SIZE - sizeof (unsigned long))
Packit 032894
    return false;
Packit 032894
Packit 032894
  struct __libdwfl_remote_mem_cache *mem_cache = pid_arg->mem_cache;
Packit 032894
  if (mem_cache == NULL)
Packit 032894
    {
Packit 032894
      size_t mem_cache_size = sizeof (struct __libdwfl_remote_mem_cache);
Packit 032894
      mem_cache = (struct __libdwfl_remote_mem_cache *) malloc (mem_cache_size);
Packit 032894
      if (mem_cache == NULL)
Packit 032894
	return false;
Packit 032894
Packit 032894
      mem_cache->addr = 0;
Packit 032894
      mem_cache->len = 0;
Packit 032894
      pid_arg->mem_cache = mem_cache;
Packit 032894
    }
Packit 032894
Packit 032894
  unsigned char *d;
Packit 032894
  if (addr >= mem_cache->addr && addr - mem_cache->addr < mem_cache->len)
Packit 032894
    {
Packit 032894
      d = &mem_cache->buf[addr - mem_cache->addr];
Packit 032894
      if ((((uintptr_t) d) & (sizeof (unsigned long) - 1)) == 0)
Packit 032894
	*result = *(unsigned long *) d;
Packit 032894
      else
Packit 032894
	memcpy (result, d, sizeof (unsigned long));
Packit 032894
      return true;
Packit 032894
    }
Packit 032894
Packit 032894
  struct iovec local, remote;
Packit 032894
  mem_cache->addr = addr & ~((Dwarf_Addr)__LIBDWFL_REMOTE_MEM_CACHE_SIZE - 1);
Packit 032894
  local.iov_base = mem_cache->buf;
Packit 032894
  local.iov_len = __LIBDWFL_REMOTE_MEM_CACHE_SIZE;
Packit 032894
  remote.iov_base = (void *) (uintptr_t) mem_cache->addr;
Packit 032894
  remote.iov_len = __LIBDWFL_REMOTE_MEM_CACHE_SIZE;
Packit 032894
Packit 032894
  ssize_t res = process_vm_readv (pid_arg->tid_attached,
Packit 032894
				  &local, 1, &remote, 1, 0);
Packit 032894
  if (res != __LIBDWFL_REMOTE_MEM_CACHE_SIZE)
Packit 032894
    {
Packit 032894
      mem_cache->len = 0;
Packit 032894
      return false;
Packit 032894
    }
Packit 032894
Packit 032894
  mem_cache->len = res;
Packit 032894
  d = &mem_cache->buf[addr - mem_cache->addr];
Packit 032894
  if ((((uintptr_t) d) & (sizeof (unsigned long) - 1)) == 0)
Packit 032894
    *result = *(unsigned long *) d;
Packit 032894
  else
Packit 032894
    memcpy (result, d, sizeof (unsigned long));
Packit 032894
  return true;
Packit 032894
}
Packit 032894
#endif /* HAVE_PROCESS_VM_READV */
Packit 032894
Packit 032894
static void
Packit 032894
clear_cached_memory (struct __libdwfl_pid_arg *pid_arg)
Packit 032894
{
Packit 032894
  struct __libdwfl_remote_mem_cache *mem_cache = pid_arg->mem_cache;
Packit 032894
  if (mem_cache != NULL)
Packit 032894
    mem_cache->len = 0;
Packit 032894
}
Packit 032894
Packit 032894
/* Note that the result word size depends on the architecture word size.
Packit 032894
   That is sizeof long. */
Packit 032894
static bool
Packit 032894
pid_memory_read (Dwfl *dwfl, Dwarf_Addr addr, Dwarf_Word *result, void *arg)
Packit 032894
{
Packit 032894
  struct __libdwfl_pid_arg *pid_arg = arg;
Packit 032894
  pid_t tid = pid_arg->tid_attached;
Packit 032894
  assert (tid > 0);
Packit 032894
Packit 032894
#ifdef HAVE_PROCESS_VM_READV
Packit 032894
  if (read_cached_memory (pid_arg, addr, result))
Packit 032894
    return true;
Packit 032894
#endif
Packit 032894
Packit 032894
  Dwfl_Process *process = dwfl->process;
Packit 032894
  if (ebl_get_elfclass (process->ebl) == ELFCLASS64)
Packit 032894
    {
Packit 032894
#if SIZEOF_LONG == 8
Packit 032894
      errno = 0;
Packit 032894
      *result = ptrace (PTRACE_PEEKDATA, tid, (void *) (uintptr_t) addr, NULL);
Packit 032894
      return errno == 0;
Packit 032894
#else /* SIZEOF_LONG != 8 */
Packit 032894
      /* This should not happen.  */
Packit 032894
      return false;
Packit 032894
#endif /* SIZEOF_LONG != 8 */
Packit 032894
    }
Packit 032894
#if SIZEOF_LONG == 8
Packit 032894
  /* We do not care about reads unaliged to 4 bytes boundary.
Packit 032894
     But 0x...ffc read of 8 bytes could overrun a page.  */
Packit 032894
  bool lowered = (addr & 4) != 0;
Packit 032894
  if (lowered)
Packit 032894
    addr -= 4;
Packit 032894
#endif /* SIZEOF_LONG == 8 */
Packit 032894
  errno = 0;
Packit 032894
  *result = ptrace (PTRACE_PEEKDATA, tid, (void *) (uintptr_t) addr, NULL);
Packit 032894
  if (errno != 0)
Packit 032894
    return false;
Packit 032894
#if SIZEOF_LONG == 8
Packit 032894
# if BYTE_ORDER == BIG_ENDIAN
Packit 032894
  if (! lowered)
Packit 032894
    *result >>= 32;
Packit 032894
# else
Packit 032894
  if (lowered)
Packit 032894
    *result >>= 32;
Packit 032894
# endif
Packit 032894
#endif /* SIZEOF_LONG == 8 */
Packit 032894
  *result &= 0xffffffff;
Packit 032894
  return true;
Packit 032894
}
Packit 032894
Packit 032894
static pid_t
Packit 032894
pid_next_thread (Dwfl *dwfl __attribute__ ((unused)), void *dwfl_arg,
Packit 032894
		 void **thread_argp)
Packit 032894
{
Packit 032894
  struct __libdwfl_pid_arg *pid_arg = dwfl_arg;
Packit 032894
  struct dirent *dirent;
Packit 032894
  /* Start fresh on first traversal. */
Packit 032894
  if (*thread_argp == NULL)
Packit 032894
    rewinddir (pid_arg->dir);
Packit 032894
  do
Packit 032894
    {
Packit 032894
      errno = 0;
Packit 032894
      dirent = readdir (pid_arg->dir);
Packit 032894
      if (dirent == NULL)
Packit 032894
	{
Packit 032894
	  if (errno != 0)
Packit 032894
	    {
Packit 032894
	      __libdwfl_seterrno (DWFL_E_ERRNO);
Packit 032894
	      return -1;
Packit 032894
	    }
Packit 032894
	  return 0;
Packit 032894
	}
Packit 032894
    }
Packit 032894
  while (strcmp (dirent->d_name, ".") == 0
Packit 032894
	 || strcmp (dirent->d_name, "..") == 0);
Packit 032894
  char *end;
Packit 032894
  errno = 0;
Packit 032894
  long tidl = strtol (dirent->d_name, &end, 10);
Packit 032894
  if (errno != 0)
Packit 032894
    {
Packit 032894
      __libdwfl_seterrno (DWFL_E_ERRNO);
Packit 032894
      return -1;
Packit 032894
    }
Packit 032894
  pid_t tid = tidl;
Packit 032894
  if (tidl <= 0 || (end && *end) || tid != tidl)
Packit 032894
    {
Packit 032894
      __libdwfl_seterrno (DWFL_E_PARSE_PROC);
Packit 032894
      return -1;
Packit 032894
    }
Packit 032894
  *thread_argp = dwfl_arg;
Packit 032894
  return tid;
Packit 032894
}
Packit 032894
Packit 032894
/* Just checks that the thread id exists.  */
Packit 032894
static bool
Packit 032894
pid_getthread (Dwfl *dwfl __attribute__ ((unused)), pid_t tid,
Packit 032894
	       void *dwfl_arg, void **thread_argp)
Packit 032894
{
Packit 032894
  *thread_argp = dwfl_arg;
Packit 032894
  if (kill (tid, 0) < 0)
Packit 032894
    {
Packit 032894
      __libdwfl_seterrno (DWFL_E_ERRNO);
Packit 032894
      return false;
Packit 032894
    }
Packit 032894
  return true;
Packit 032894
}
Packit 032894
Packit 032894
/* Implement the ebl_set_initial_registers_tid setfunc callback.  */
Packit 032894
Packit 032894
static bool
Packit 032894
pid_thread_state_registers_cb (int firstreg, unsigned nregs,
Packit 032894
			       const Dwarf_Word *regs, void *arg)
Packit 032894
{
Packit 032894
  Dwfl_Thread *thread = (Dwfl_Thread *) arg;
Packit 032894
  if (firstreg < 0)
Packit 032894
    {
Packit 032894
      assert (firstreg == -1);
Packit 032894
      assert (nregs == 1);
Packit 032894
      INTUSE(dwfl_thread_state_register_pc) (thread, *regs);
Packit 032894
      return true;
Packit 032894
    }
Packit 032894
  assert (nregs > 0);
Packit 032894
  return INTUSE(dwfl_thread_state_registers) (thread, firstreg, nregs, regs);
Packit 032894
}
Packit 032894
Packit 032894
static bool
Packit 032894
pid_set_initial_registers (Dwfl_Thread *thread, void *thread_arg)
Packit 032894
{
Packit 032894
  struct __libdwfl_pid_arg *pid_arg = thread_arg;
Packit 032894
  assert (pid_arg->tid_attached == 0);
Packit 032894
  pid_t tid = INTUSE(dwfl_thread_tid) (thread);
Packit 032894
  if (! pid_arg->assume_ptrace_stopped
Packit 032894
      && ! __libdwfl_ptrace_attach (tid, &pid_arg->tid_was_stopped))
Packit 032894
    return false;
Packit 032894
  pid_arg->tid_attached = tid;
Packit 032894
  Dwfl_Process *process = thread->process;
Packit 032894
  Ebl *ebl = process->ebl;
Packit 032894
  return ebl_set_initial_registers_tid (ebl, tid,
Packit 032894
					pid_thread_state_registers_cb, thread);
Packit 032894
}
Packit 032894
Packit 032894
static void
Packit 032894
pid_detach (Dwfl *dwfl __attribute__ ((unused)), void *dwfl_arg)
Packit 032894
{
Packit 032894
  struct __libdwfl_pid_arg *pid_arg = dwfl_arg;
Packit 032894
  elf_end (pid_arg->elf);
Packit 032894
  free (pid_arg->mem_cache);
Packit 032894
  close (pid_arg->elf_fd);
Packit 032894
  closedir (pid_arg->dir);
Packit 032894
  free (pid_arg);
Packit 032894
}
Packit 032894
Packit 032894
void
Packit 032894
internal_function
Packit 032894
__libdwfl_ptrace_detach (pid_t tid, bool tid_was_stopped)
Packit 032894
{
Packit 032894
  /* This handling is needed only on older Linux kernels such as
Packit 032894
     2.6.32-358.23.2.el6.ppc64.  Later kernels such as
Packit 032894
     3.11.7-200.fc19.x86_64 remember the T (stopped) state
Packit 032894
     themselves and no longer need to pass SIGSTOP during
Packit 032894
     PTRACE_DETACH.  */
Packit 032894
  ptrace (PTRACE_DETACH, tid, NULL,
Packit 032894
	  (void *) (intptr_t) (tid_was_stopped ? SIGSTOP : 0));
Packit 032894
}
Packit 032894
Packit 032894
static void
Packit 032894
pid_thread_detach (Dwfl_Thread *thread, void *thread_arg)
Packit 032894
{
Packit 032894
  struct __libdwfl_pid_arg *pid_arg = thread_arg;
Packit 032894
  pid_t tid = INTUSE(dwfl_thread_tid) (thread);
Packit 032894
  assert (pid_arg->tid_attached == tid);
Packit 032894
  pid_arg->tid_attached = 0;
Packit 032894
  clear_cached_memory (pid_arg);
Packit 032894
  if (! pid_arg->assume_ptrace_stopped)
Packit 032894
    __libdwfl_ptrace_detach (tid, pid_arg->tid_was_stopped);
Packit 032894
}
Packit 032894
Packit 032894
static const Dwfl_Thread_Callbacks pid_thread_callbacks =
Packit 032894
{
Packit 032894
  pid_next_thread,
Packit 032894
  pid_getthread,
Packit 032894
  pid_memory_read,
Packit 032894
  pid_set_initial_registers,
Packit 032894
  pid_detach,
Packit 032894
  pid_thread_detach,
Packit 032894
};
Packit 032894
Packit 032894
int
Packit 032894
dwfl_linux_proc_attach (Dwfl *dwfl, pid_t pid, bool assume_ptrace_stopped)
Packit 032894
{
Packit 032894
  char buffer[36];
Packit 032894
  FILE *procfile;
Packit 032894
  int err = 0; /* The errno to return and set for dwfl->attcherr.  */
Packit 032894
Packit 032894
  /* Make sure to report the actual PID (thread group leader) to
Packit 032894
     dwfl_attach_state.  */
Packit 032894
  snprintf (buffer, sizeof (buffer), "/proc/%ld/status", (long) pid);
Packit 032894
  procfile = fopen (buffer, "r");
Packit 032894
  if (procfile == NULL)
Packit 032894
    {
Packit 032894
      err = errno;
Packit 032894
    fail:
Packit 032894
      if (dwfl->process == NULL && dwfl->attacherr == DWFL_E_NOERROR)
Packit 032894
	{
Packit 032894
	  errno = err;
Packit 032894
	  dwfl->attacherr = __libdwfl_canon_error (DWFL_E_ERRNO);
Packit 032894
	}
Packit 032894
      return err;
Packit 032894
    }
Packit 032894
Packit 032894
  char *line = NULL;
Packit 032894
  size_t linelen = 0;
Packit 032894
  while (getline (&line, &linelen, procfile) >= 0)
Packit 032894
    if (strncmp (line, "Tgid:", 5) == 0)
Packit 032894
      {
Packit 032894
	errno = 0;
Packit 032894
	char *endptr;
Packit 032894
	long val = strtol (&line[5], &endptr, 10);
Packit 032894
	if ((errno == ERANGE && val == LONG_MAX)
Packit 032894
	    || *endptr != '\n' || val < 0 || val != (pid_t) val)
Packit 032894
	  pid = 0;
Packit 032894
	else
Packit 032894
	  pid = (pid_t) val;
Packit 032894
	break;
Packit 032894
      }
Packit 032894
  free (line);
Packit 032894
  fclose (procfile);
Packit 032894
Packit 032894
  if (pid == 0)
Packit 032894
    {
Packit 032894
      err = ESRCH;
Packit 032894
      goto fail;
Packit 032894
    }
Packit 032894
Packit 032894
  char name[64];
Packit 032894
  int i = snprintf (name, sizeof (name), "/proc/%ld/task", (long) pid);
Packit 032894
  assert (i > 0 && i < (ssize_t) sizeof (name) - 1);
Packit 032894
  DIR *dir = opendir (name);
Packit 032894
  if (dir == NULL)
Packit 032894
    {
Packit 032894
      err = errno;
Packit 032894
      goto fail;
Packit 032894
    }
Packit 032894
Packit 032894
  Elf *elf;
Packit 032894
  i = snprintf (name, sizeof (name), "/proc/%ld/exe", (long) pid);
Packit 032894
  assert (i > 0 && i < (ssize_t) sizeof (name) - 1);
Packit 032894
  int elf_fd = open (name, O_RDONLY);
Packit 032894
  if (elf_fd >= 0)
Packit 032894
    {
Packit 032894
      elf = elf_begin (elf_fd, ELF_C_READ_MMAP, NULL);
Packit 032894
      if (elf == NULL)
Packit 032894
	{
Packit 032894
	  /* Just ignore, dwfl_attach_state will fall back to trying
Packit 032894
	     to associate the Dwfl with one of the existing DWfl_Module
Packit 032894
	     ELF images (to know the machine/class backend to use).  */
Packit 032894
	  close (elf_fd);
Packit 032894
	  elf_fd = -1;
Packit 032894
	}
Packit 032894
    }
Packit 032894
  else
Packit 032894
    elf = NULL;
Packit 032894
  struct __libdwfl_pid_arg *pid_arg = malloc (sizeof *pid_arg);
Packit 032894
  if (pid_arg == NULL)
Packit 032894
    {
Packit 032894
      elf_end (elf);
Packit 032894
      close (elf_fd);
Packit 032894
      closedir (dir);
Packit 032894
      err = ENOMEM;
Packit 032894
      goto fail;
Packit 032894
    }
Packit 032894
  pid_arg->dir = dir;
Packit 032894
  pid_arg->elf = elf;
Packit 032894
  pid_arg->elf_fd = elf_fd;
Packit 032894
  pid_arg->mem_cache = NULL;
Packit 032894
  pid_arg->tid_attached = 0;
Packit 032894
  pid_arg->assume_ptrace_stopped = assume_ptrace_stopped;
Packit 032894
  if (! INTUSE(dwfl_attach_state) (dwfl, elf, pid, &pid_thread_callbacks,
Packit 032894
				   pid_arg))
Packit 032894
    {
Packit 032894
      elf_end (elf);
Packit 032894
      close (elf_fd);
Packit 032894
      closedir (dir);
Packit 032894
      free (pid_arg);
Packit 032894
      return -1;
Packit 032894
    }
Packit 032894
  return 0;
Packit 032894
}
Packit 032894
INTDEF (dwfl_linux_proc_attach)
Packit 032894
Packit 032894
struct __libdwfl_pid_arg *
Packit 032894
internal_function
Packit 032894
__libdwfl_get_pid_arg (Dwfl *dwfl)
Packit 032894
{
Packit 032894
  if (dwfl != NULL && dwfl->process != NULL
Packit 032894
      && dwfl->process->callbacks == &pid_thread_callbacks)
Packit 032894
    return (struct __libdwfl_pid_arg *) dwfl->process->callbacks_arg;
Packit 032894
Packit 032894
  return NULL;
Packit 032894
}
Packit 032894
Packit 032894
#else	/* __linux__ */
Packit 032894
Packit 032894
bool
Packit 032894
internal_function
Packit 032894
__libdwfl_ptrace_attach (pid_t tid __attribute__ ((unused)),
Packit 032894
			 bool *tid_was_stoppedp __attribute__ ((unused)))
Packit 032894
{
Packit 032894
  errno = ENOSYS;
Packit 032894
  __libdwfl_seterrno (DWFL_E_ERRNO);
Packit 032894
  return false;
Packit 032894
}
Packit 032894
Packit 032894
void
Packit 032894
internal_function
Packit 032894
__libdwfl_ptrace_detach (pid_t tid __attribute__ ((unused)),
Packit 032894
			 bool tid_was_stopped __attribute__ ((unused)))
Packit 032894
{
Packit 032894
}
Packit 032894
Packit 032894
int
Packit 032894
dwfl_linux_proc_attach (Dwfl *dwfl __attribute__ ((unused)),
Packit 032894
			pid_t pid __attribute__ ((unused)),
Packit 032894
			bool assume_ptrace_stopped __attribute__ ((unused)))
Packit 032894
{
Packit 032894
  return ENOSYS;
Packit 032894
}
Packit 032894
INTDEF (dwfl_linux_proc_attach)
Packit 032894
Packit 032894
struct __libdwfl_pid_arg *
Packit 032894
internal_function
Packit 032894
__libdwfl_get_pid_arg (Dwfl *dwfl __attribute__ ((unused)))
Packit 032894
{
Packit 032894
  return NULL;
Packit 032894
}
Packit 032894
Packit 032894
#endif /* ! __linux __ */
Packit 032894