]> git.ipfire.org Git - thirdparty/elfutils.git/commitdiff
Compatibility with older kernels such as RHEL-6.
authorJan Kratochvil <jan.kratochvil@redhat.com>
Tue, 19 Nov 2013 14:00:15 +0000 (15:00 +0100)
committerJan Kratochvil <jan.kratochvil@redhat.com>
Tue, 19 Nov 2013 14:00:15 +0000 (15:00 +0100)
Signed-off-by: Jan Kratochvil <jan.kratochvil@redhat.com>
libdwfl/ChangeLog
libdwfl/linux-pid-attach.c

index ca328ded7742b3b27778941f9618a5bcd83f5013..67ae84add80dce7ea24eda29cfe6aa55ca060bf3 100644 (file)
@@ -1,3 +1,11 @@
+2013-11-19  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+       Compatibility with older kernels such as RHEL-6.
+       * linux-pid-attach.c (struct pid_arg): New field tid_was_stopped.
+       (ptrace_attach): New parameter tid_was_stoppedp.  Set it.
+       (pid_set_initial_registers): Pass tid_was_stopped.
+       (pid_thread_detach): Use tid_was_stopped.
+
 2013-11-18  Josh Stone  <jistone@redhat.com>
 
        * dwfl_module_getdwarf.c (find_aux_address_sync): New function.
index ca8214467184838cb5cd229fbc5bc052203c9616..e4eb621212c01e39e7ebbca70d78c0ea10047490 100644 (file)
@@ -42,6 +42,8 @@ struct pid_arg
   DIR *dir;
   /* It is 0 if not used.  */
   pid_t tid_attached;
+  /* Valid only if TID_ATTACHED is not zero.  */
+  bool tid_was_stopped;
 };
 
 static bool
@@ -69,14 +71,15 @@ linux_proc_pid_is_stopped (pid_t pid)
 }
 
 static bool
-ptrace_attach (pid_t tid)
+ptrace_attach (pid_t tid, bool *tid_was_stoppedp)
 {
   if (ptrace (PTRACE_ATTACH, tid, NULL, NULL) != 0)
     {
       __libdwfl_seterrno (DWFL_E_ERRNO);
       return false;
     }
-  if (linux_proc_pid_is_stopped (tid))
+  *tid_was_stoppedp = linux_proc_pid_is_stopped (tid);
+  if (*tid_was_stoppedp)
     {
       /* Make sure there is a SIGSTOP signal pending even when the process is
         already State: T (stopped).  Older kernels might fail to generate
@@ -211,7 +214,7 @@ pid_set_initial_registers (Dwfl_Thread *thread, void *thread_arg)
   struct pid_arg *pid_arg = thread_arg;
   assert (pid_arg->tid_attached == 0);
   pid_t tid = INTUSE(dwfl_thread_tid) (thread);
-  if (! ptrace_attach (tid))
+  if (! ptrace_attach (tid, &pid_arg->tid_was_stopped))
     return false;
   pid_arg->tid_attached = tid;
   Dwfl_Process *process = thread->process;
@@ -235,7 +238,12 @@ pid_thread_detach (Dwfl_Thread *thread, void *thread_arg)
   pid_t tid = INTUSE(dwfl_thread_tid) (thread);
   assert (pid_arg->tid_attached == tid);
   pid_arg->tid_attached = 0;
-  ptrace (PTRACE_DETACH, tid, NULL, NULL);
+  /* This handling is needed only on older Linux kernels such as
+     2.6.32-358.23.2.el6.ppc64.  Later kernels such as 3.11.7-200.fc19.x86_64
+     remember the T (stopped) state themselves and no longer need to pass
+     SIGSTOP during PTRACE_DETACH.  */
+  ptrace (PTRACE_DETACH, tid, NULL,
+         (void *) (intptr_t) (pid_arg->tid_was_stopped ? SIGSTOP : 0));
 }
 
 static const Dwfl_Thread_Callbacks pid_thread_callbacks =