]> git.ipfire.org Git - thirdparty/elfutils.git/commitdiff
Add --core-pattern option to eu-stack jankratochvil/corepattern
authorJan Kratochvil <jan.kratochvil@redhat.com>
Wed, 26 Nov 2014 21:44:18 +0000 (22:44 +0100)
committerJan Kratochvil <jan.kratochvil@redhat.com>
Wed, 26 Nov 2014 21:44:18 +0000 (22:44 +0100)
To backtrace crashed thread from Linux core_pattern handler a special operation
similar to PTRACE_ATTACH needs to be done.  This is implemented as a demo in
eu-stack's core_pattern function invoked by eu-stack's --core-pattern option.

The code of core_pattern function has been suggested by Oleg Nesterov.

src/
2014-11-26  Jan Kratochvil  <jan.kratochvil@redhat.com>

* stack.c: Include sys/ptrace.h and sys/wait.h.
(OPT_CORE_PATTERN, opt_core_pattern, core_pattern): New.
(parse_opt): Handle OPT_CORE_PATTERN.  Check opt_core_pattern option
validity.  Call core_pattern.  Pass it as assume_ptrace_stopped.
(main): Add "core-pattern" to options.

src/ChangeLog
src/stack.c

index 0082e651b7480322479094fd9f16a2fe68297eec..d2c38009f237fe200bfe0bd957b940295deb890e 100644 (file)
@@ -1,3 +1,11 @@
+2014-11-26  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+       * stack.c: Include sys/ptrace.h and sys/wait.h.
+       (OPT_CORE_PATTERN, opt_core_pattern, core_pattern): New.
+       (parse_opt): Handle OPT_CORE_PATTERN.  Check opt_core_pattern option
+       validity.  Call core_pattern.  Pass it as assume_ptrace_stopped.
+       (main): Add "core-pattern" to options.
+
 2014-11-24  Mark Wielaard  <mjw@redhat.com>
 
        * readelf.c (print_debug_line_section): Check line_range is not zero
index c277dfd03f775a53a6d4704b1525aa0adac23522..b446a766e52461c5723874da2c6a423b973936ff 100644 (file)
@@ -26,6 +26,8 @@
 #include <string.h>
 #include <locale.h>
 #include <fcntl.h>
+#include <sys/ptrace.h>
+#include <sys/wait.h>
 #include ELFUTILS_HEADER(dwfl)
 
 #include <dwarf.h>
@@ -39,8 +41,9 @@ ARGP_PROGRAM_VERSION_HOOK_DEF = print_version;
 ARGP_PROGRAM_BUG_ADDRESS_DEF = PACKAGE_BUGREPORT;
 
 /* non-printable argp options.  */
-#define OPT_DEBUGINFO  0x100
-#define OPT_COREFILE   0x101
+#define OPT_DEBUGINFO          0x100
+#define OPT_COREFILE           0x101
+#define OPT_CORE_PATTERN       0x102
 
 static bool show_activation = false;
 static bool show_module = false;
@@ -52,6 +55,7 @@ static bool show_raw = false;
 static bool show_modules = false;
 static bool show_debugname = false;
 static bool show_inlines = false;
+static bool opt_core_pattern = false;
 
 static int maxframes = 256;
 
@@ -476,6 +480,35 @@ print_version (FILE *stream, struct argp_state *state __attribute__ ((unused)))
   fprintf (stream, "stack (%s) %s\n", PACKAGE_NAME, PACKAGE_VERSION);
 }
 
+/* Provide PTRACE_ATTACH like operation compatible with Linux core_pattern
+   handler.  */
+
+static void
+core_pattern (void)
+{
+  if (ptrace (PTRACE_SEIZE, pid, NULL, (void *) (uintptr_t) PTRACE_O_TRACEEXIT)
+      != 0)
+    error (EXIT_BAD, errno, "ptrace (PTRACE_SEIZE, PTRACE_O_TRACEEXIT)");
+  if (close (0) != 0)
+    error (EXIT_BAD, errno, "close (0; core file fd)");
+  int status;
+  pid_t got = waitpid (pid, &status, 0);
+  if (got == -1)
+    error (EXIT_BAD, errno, "waitpid ()");
+  if (got != pid)
+    error (EXIT_BAD, 0, "waitpid () returned %d but %d was expected",
+          got, pid);
+  if (! WIFSTOPPED (status))
+    error (EXIT_BAD, 0,
+          "waitpid () returned status 0x%x but WIFSTOPPED was expected",
+          status);
+  if ((status >> 8) != (SIGTRAP | (PTRACE_EVENT_EXIT << 8)))
+    error (EXIT_BAD, 0,
+          "waitpid () returned status 0x%x but (status >> 8)"
+          " == (SIGTRAP | (PTRACE_EVENT_EXIT << 8)) was expected",
+          status);
+}
+
 static error_t
 parse_opt (int key, char *arg __attribute__ ((unused)),
           struct argp_state *state)
@@ -560,6 +593,10 @@ parse_opt (int key, char *arg __attribute__ ((unused)),
       show_modules = true;
       break;
 
+    case OPT_CORE_PATTERN:
+      opt_core_pattern = true;
+      break;
+
     case ARGP_KEY_END:
       if (core == NULL && exec != NULL)
        argp_error (state,
@@ -573,6 +610,12 @@ parse_opt (int key, char *arg __attribute__ ((unused)),
        argp_error (state,
                    N_("One of -p PID or --core COREFILE should be given."));
 
+      /* Other threads are already dead (WIFSIGNALED) and they cannot be
+         ptraced anymore.  */
+      if (opt_core_pattern == true && show_one_tid == false)
+       argp_error (state,
+                   N_("--core-pattern requires -1"));
+
       if (pid != 0)
        {
          dwfl = dwfl_begin (&proc_callbacks);
@@ -601,7 +644,9 @@ parse_opt (int key, char *arg __attribute__ ((unused)),
 
       if (pid != 0)
        {
-         int err = dwfl_linux_proc_attach (dwfl, pid, false);
+         if (opt_core_pattern)
+           core_pattern ();
+         int err = dwfl_linux_proc_attach (dwfl, pid, opt_core_pattern);
          if (err < 0)
            error (EXIT_BAD, 0, "dwfl_linux_proc_attach pid %d: %s", pid,
                   dwfl_errmsg (-1));
@@ -674,6 +719,10 @@ main (int argc, char **argv)
        N_("Show at most MAXFRAMES per thread (default 256, use 0 for unlimited)"), 0 },
       { "list-modules", 'l', NULL, 0,
        N_("Show module memory map with build-id, elf and debug files detected"), 0 },
+      { "core-pattern", OPT_CORE_PATTERN, NULL, 0,
+       N_("Attach process as Linux core_pattern handler; use --pid=%i; "
+          "core file fd 0 must be owned only by this process (e.g. use shell exec); "
+          "see man 5 core"), 0 },
       { NULL, 0, NULL, 0, NULL, 0 }
     };