This is the mail archive of the elfutils-devel@sourceware.org mailing list for the elfutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH] libdwfl: Make dwfl_linux_proc_attach work even without any DwflModules.


On Tue, 2015-09-08 at 14:53 -0700, Roland McGrath wrote:
> I think there might be circumstances when you can't open /proc/PID/exe.
> I'm not sure you want failure to open it or it failing to be a readable
> ELF file to be hard failures.

I think you are right. Probably not much will actually work
if /proc/PID/exe cannot be read. But the user might find and report a
Dwfl_Module that does work for what they need. So I now just silently
ignore when /proc/PID/exe cannot be read and we fall back to the
existing mechanism of using one of the existing Dwfl_Modules (we might
then still fail of course because there is no Dwfl_Module available).

Thanks,

Mark
From ee861a07846f8548c7c4581380ee0799ac165c47 Mon Sep 17 00:00:00 2001
From: Mark Wielaard <mjw@redhat.com>
Date: Mon, 7 Sep 2015 12:52:12 +0200
Subject: [PATCH] libdwfl: Make dwfl_linux_proc_attach work even without any
 Dwfl_Modules.

dwfl_linux_proc_attach depended on a Dwfl_Module with the correct
ELF header already being available. That isn't really necessary since
when we attach we have the main exe ELF file available. Just use that
to make dwfl_linux_proc_attach always work.

Signed-off-by: Mark Wielaard <mjw@redhat.com>
---
 libdwfl/ChangeLog          |   6 +++
 libdwfl/libdwflP.h         |   5 +++
 libdwfl/linux-pid-attach.c |  43 ++++++++++++++++---
 tests/ChangeLog            |   8 ++++
 tests/Makefile.am          |   6 ++-
 tests/dwfl-proc-attach.c   | 101 +++++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 161 insertions(+), 8 deletions(-)
 create mode 100644 tests/dwfl-proc-attach.c

diff --git a/libdwfl/ChangeLog b/libdwfl/ChangeLog
index 3e36aa7..7a4387e 100644
--- a/libdwfl/ChangeLog
+++ b/libdwfl/ChangeLog
@@ -1,3 +1,9 @@
+2015-09-08  Mark Wielaard  <mjw@redhat.com>
+
+	* libdwflP.h (struct __libdwfl_pid_arg): Add elf and elf_fd.
+	* linux-pid-attach.c (pid_detach): Call elf_end and close.
+	(dwfl_linux_proc_attach): Open and save /proc/PID/exe.
+
 2015-08-14  Dodji Seketeli  <dodji@seketeli.org>
 
 	* find-debuginfo.c (find_debuginfo_in_path): Try to locate the
diff --git a/libdwfl/libdwflP.h b/libdwfl/libdwflP.h
index 12ee116..42a2669 100644
--- a/libdwfl/libdwflP.h
+++ b/libdwfl/libdwflP.h
@@ -400,7 +400,12 @@ struct dwfl_arange
    then get the instance through __libdwfl_get_pid_arg.  */
 struct __libdwfl_pid_arg
 {
+  /* /proc/PID/task/.  */
   DIR *dir;
+  /* Elf for /proc/PID/exe.  Set to NULL if it couldn't be opened.  */
+  Elf *elf;
+  /* fd for /proc/PID/exe.  Set to -1 if it couldn't be opened.  */
+  int elf_fd;
   /* It is 0 if not used.  */
   pid_t tid_attached;
   /* Valid only if TID_ATTACHED is not zero.  */
diff --git a/libdwfl/linux-pid-attach.c b/libdwfl/linux-pid-attach.c
index ae71702..4c0f42d 100644
--- a/libdwfl/linux-pid-attach.c
+++ b/libdwfl/linux-pid-attach.c
@@ -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
@@ -26,7 +26,11 @@
    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;
diff --git a/tests/ChangeLog b/tests/ChangeLog
index 99b4d8f..a4a4f9e 100644
--- a/tests/ChangeLog
+++ b/tests/ChangeLog
@@ -1,3 +1,11 @@
+2015-09-08  Mark Wielaard  <mjw@redhat.com>
+
+	* dwfl-proc-attach.c: New test.
+	* Makefile.am (check_PROGRAMS): Add dwfl-proc-attach.
+	(TESTS): Likewise.
+	(dwfl_proc_attach_LDADD): New variable.
+	(dwfl_proc_attach_LDFLAGS): Likewise.
+
 2015-09-04  Chih-Hung Hsieh  <chh@google.com>
 
 	* asm-tst1.c (main): Replace %Z length modifier with %z.
diff --git a/tests/Makefile.am b/tests/Makefile.am
index d04c270..ca2c2d7 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -51,7 +51,7 @@ check_PROGRAMS = arextract arsymtest newfile saridx scnnames sectiondump \
 		  dwfl-report-elf-align varlocs backtrace backtrace-child \
 		  backtrace-data backtrace-dwarf debuglink debugaltlink \
 		  buildid deleted deleted-lib.so aggregate_size vdsosyms \
-		  getsrc_die strptr newdata elfstrtab
+		  getsrc_die strptr newdata elfstrtab dwfl-proc-attach
 
 asm_TESTS = asm-tst1 asm-tst2 asm-tst3 asm-tst4 asm-tst5 \
 	    asm-tst6 asm-tst7 asm-tst8 asm-tst9
@@ -118,7 +118,7 @@ TESTS = run-arextract.sh run-arsymtest.sh newfile test-nlist \
 	run-stack-demangled-test.sh \
 	run-readelf-dwz-multi.sh run-allfcts-multi.sh run-deleted.sh \
 	run-linkmap-cut.sh run-aggregate-size.sh vdsosyms run-readelf-A.sh \
-	run-getsrc-die.sh run-strptr.sh newdata elfstrtab
+	run-getsrc-die.sh run-strptr.sh newdata elfstrtab dwfl-proc-attach
 
 if !BIARCH
 export ELFUTILS_DISABLE_BIARCH = 1
@@ -446,6 +446,8 @@ getsrc_die_LDADD = $(libdw) $(libelf)
 strptr_LDADD = $(libelf)
 newdata_LDADD = $(libelf)
 elfstrtab_LDADD = $(libelf)
+dwfl_proc_attach_LDADD = $(libdw)
+dwfl_proc_attach_LDFLAGS = -pthread
 
 if GCOV
 check: check-am coverage
diff --git a/tests/dwfl-proc-attach.c b/tests/dwfl-proc-attach.c
new file mode 100644
index 0000000..0ba0be2
--- /dev/null
+++ b/tests/dwfl-proc-attach.c
@@ -0,0 +1,101 @@
+/* Test dwfl_linux_proc_attach works without any modules.
+   Copyright (C) 2015 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <error.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/user.h>
+#include <fcntl.h>
+#include <string.h>
+#include ELFUTILS_HEADER(dwfl)
+#include <pthread.h>
+
+#ifndef __linux__
+int
+main (int argc __attribute__ ((unused)), char **argv __attribute__ ((unused)))
+{
+  printf ("dwfl_linux_proc_attach unsupported.\n");
+  return 77;
+}
+#else /* __linux__ */
+
+static pthread_t thread1;
+static pthread_t thread2;
+
+static void *
+sleeper (void* d __attribute__ ((unused)))
+{
+  sleep (60);
+  return NULL;
+}
+
+static char *debuginfo_path = NULL;
+
+static const Dwfl_Callbacks proc_callbacks =
+  {
+    .find_elf = dwfl_linux_proc_find_elf,
+    .find_debuginfo = dwfl_standard_find_debuginfo,
+    .debuginfo_path = &debuginfo_path,
+  };
+
+static int
+thread_callback (Dwfl_Thread *thread, void *thread_arg)
+{
+  int *threads = (int *) thread_arg;
+  pid_t tid = dwfl_thread_tid (thread);
+  printf ("thread tid: %d\n", tid);
+  (*threads)++;
+
+  return DWARF_CB_OK;
+}
+
+int
+main (int argc __attribute__ ((unused)),
+      char **argv __attribute__ ((unused)))
+{
+  /* Create two extra threads to iterate through.  */
+  int err;
+  if ((err = pthread_create (&thread1, NULL, sleeper, NULL)) != 0)
+    error (-1, err, "Couldn't create thread1");
+  if ((err = pthread_create (&thread2, NULL, sleeper, NULL)) != 0)
+    error (-1, err, "Couldn't create thread2");
+
+  Dwfl *dwfl = dwfl_begin (&proc_callbacks);
+  if (dwfl == NULL)
+    error (-1, 0, "dwfl_begin: %s", dwfl_errmsg (-1));
+
+  pid_t pid = getpid ();
+  /* This used to fail, since we don't have any modules yet.  */
+  if (dwfl_linux_proc_attach (dwfl, pid, false) < 0)
+    error (-1, 0, "dwfl_linux_proc_attach pid %d: %s", pid,
+	   dwfl_errmsg (-1));
+
+  /* Did we see all 3 threads?  */
+  int threads = 0;
+  if (dwfl_getthreads (dwfl, thread_callback, &threads) != DWARF_CB_OK)
+    error (-1, 0, "dwfl_getthreads failed: %s", dwfl_errmsg (-1));
+
+  return (threads == 3) ? 0 : -1;
+}
+
+#endif /* __linux__ */
-- 
2.4.3


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]