summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Kratochvil <jan.kratochvil@redhat.com>2013-11-19 15:00:15 +0100
committerJan Kratochvil <jan.kratochvil@redhat.com>2013-11-19 15:00:15 +0100
commit10d7a39aa2a509c16edd205c94b365ff1696f4fb (patch)
tree0acef2e0db248e0f1a4abc3724337174265ec62d
parentdb35c87a85aa651b8ea3ed19689c53cefc28e313 (diff)
downloadelfutils-10d7a39aa2a509c16edd205c94b365ff1696f4fb.tar.gz
Compatibility with older kernels such as RHEL-6.
Signed-off-by: Jan Kratochvil <jan.kratochvil@redhat.com>
-rw-r--r--libdwfl/ChangeLog8
-rw-r--r--libdwfl/linux-pid-attach.c16
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 =