Imported Upstream version 0.165
[platform/upstream/elfutils.git] / libdwfl / linux-pid-attach.c
index ae71702..4c0f42d 100644 (file)
@@ -1,5 +1,5 @@
 /* Get Dwarf Frame state for target live PID process.
-   Copyright (C) 2013, 2014 Red Hat, Inc.
+   Copyright (C) 2013, 2014, 2015 Red Hat, Inc.
    This file is part of elfutils.
 
    This file is free software; you can redistribute it and/or modify
    the GNU Lesser General Public License along with this program.  If
    not, see <http://www.gnu.org/licenses/>.  */
 
+#include "libelfP.h"
 #include "libdwflP.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
 #include <sys/ptrace.h>
 #include <sys/wait.h>
 #include <dirent.h>
@@ -247,6 +251,8 @@ static void
 pid_detach (Dwfl *dwfl __attribute__ ((unused)), void *dwfl_arg)
 {
   struct __libdwfl_pid_arg *pid_arg = dwfl_arg;
+  elf_end (pid_arg->elf);
+  close (pid_arg->elf_fd);
   closedir (pid_arg->dir);
   free (pid_arg);
 }
@@ -332,28 +338,53 @@ dwfl_linux_proc_attach (Dwfl *dwfl, pid_t pid, bool assume_ptrace_stopped)
       goto fail;
     }
 
-  char dirname[64];
-  int i = snprintf (dirname, sizeof (dirname), "/proc/%ld/task", (long) pid);
-  assert (i > 0 && i < (ssize_t) sizeof (dirname) - 1);
-  DIR *dir = opendir (dirname);
+  char name[64];
+  int i = snprintf (name, sizeof (name), "/proc/%ld/task", (long) pid);
+  assert (i > 0 && i < (ssize_t) sizeof (name) - 1);
+  DIR *dir = opendir (name);
   if (dir == NULL)
     {
       err = errno;
       goto fail;
     }
+
+  Elf *elf;
+  i = snprintf (name, sizeof (name), "/proc/%ld/exe", (long) pid);
+  assert (i > 0 && i < (ssize_t) sizeof (name) - 1);
+  int elf_fd = open (name, O_RDONLY);
+  if (elf_fd >= 0)
+    {
+      elf = elf_begin (elf_fd, ELF_C_READ_MMAP, NULL);
+      if (elf == NULL)
+       {
+         /* Just ignore, dwfl_attach_state will fall back to trying
+            to associate the Dwfl with one of the existing DWfl_Module
+            ELF images (to know the machine/class backend to use).  */
+         close (elf_fd);
+         elf_fd = -1;
+       }
+    }
+  else
+    elf = NULL;
   struct __libdwfl_pid_arg *pid_arg = malloc (sizeof *pid_arg);
   if (pid_arg == NULL)
     {
+      elf_end (elf);
+      close (elf_fd);
       closedir (dir);
       err = ENOMEM;
       goto fail;
     }
   pid_arg->dir = dir;
+  pid_arg->elf = elf;
+  pid_arg->elf_fd = elf_fd;
   pid_arg->tid_attached = 0;
   pid_arg->assume_ptrace_stopped = assume_ptrace_stopped;
-  if (! INTUSE(dwfl_attach_state) (dwfl, NULL, pid, &pid_thread_callbacks,
+  if (! INTUSE(dwfl_attach_state) (dwfl, elf, pid, &pid_thread_callbacks,
                                   pid_arg))
     {
+      elf_end (elf);
+      close (elf_fd);
       closedir (dir);
       free (pid_arg);
       return -1;