diff options
author | Jan Kratochvil <jan.kratochvil@redhat.com> | 2013-11-19 15:00:15 +0100 |
---|---|---|
committer | Jan Kratochvil <jan.kratochvil@redhat.com> | 2013-11-19 15:00:15 +0100 |
commit | 10d7a39aa2a509c16edd205c94b365ff1696f4fb (patch) | |
tree | 0acef2e0db248e0f1a4abc3724337174265ec62d | |
parent | db35c87a85aa651b8ea3ed19689c53cefc28e313 (diff) | |
download | elfutils-10d7a39aa2a509c16edd205c94b365ff1696f4fb.tar.gz |
Compatibility with older kernels such as RHEL-6.
Signed-off-by: Jan Kratochvil <jan.kratochvil@redhat.com>
-rw-r--r-- | libdwfl/ChangeLog | 8 | ||||
-rw-r--r-- | libdwfl/linux-pid-attach.c | 16 |
2 files changed, 20 insertions, 4 deletions
diff --git a/libdwfl/ChangeLog b/libdwfl/ChangeLog index ca328ded..67ae84ad 100644 --- a/libdwfl/ChangeLog +++ b/libdwfl/ChangeLog @@ -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. diff --git a/libdwfl/linux-pid-attach.c b/libdwfl/linux-pid-attach.c index ca821446..e4eb6212 100644 --- a/libdwfl/linux-pid-attach.c +++ b/libdwfl/linux-pid-attach.c @@ -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 = |