summaryrefslogtreecommitdiffstats
path: root/libdwfl/linux-pid-attach.c
diff options
context:
space:
mode:
authorMark Wielaard <[email protected]>2014-03-04 11:27:15 +0100
committerMark Wielaard <[email protected]>2014-03-10 21:29:00 +0100
commit4b9e1433d2272f5f68b3227abdd9cf6817a0afd3 (patch)
treee783d86e9a1c097adf1aef6d2157034f2b0c3476 /libdwfl/linux-pid-attach.c
parentf15bcda4137446d4773bb54cb99cc18497e9822c (diff)
libdwfl: dwfl_linux_proc_find_elf use elf_from_remote_memory for (deleted).
If a module has a "(deleted)" main ELF file, then try to read it from remote memory if the Dwfl has process state attached by reusing the ptrace mechanism from linux-pid-attach. Signed-off-by: Mark Wielaard <[email protected]>
Diffstat (limited to 'libdwfl/linux-pid-attach.c')
-rw-r--r--libdwfl/linux-pid-attach.c65
1 files changed, 36 insertions, 29 deletions
diff --git a/libdwfl/linux-pid-attach.c b/libdwfl/linux-pid-attach.c
index 58d6942f..6be578bb 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 Red Hat, Inc.
+ Copyright (C) 2013, 2014 Red Hat, Inc.
This file is part of elfutils.
This file is free software; you can redistribute it and/or modify
@@ -37,16 +37,6 @@
# define MAX(a, b) ((a) > (b) ? (a) : (b))
#endif
-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;
- /* True if threads are ptrace stopped by caller. */
- bool assume_ptrace_stopped;
-};
static bool
linux_proc_pid_is_stopped (pid_t pid)
@@ -72,8 +62,9 @@ linux_proc_pid_is_stopped (pid_t pid)
return retval;
}
-static bool
-ptrace_attach (pid_t tid, bool *tid_was_stoppedp)
+bool
+internal_function
+__libdwfl_ptrace_attach (pid_t tid, bool *tid_was_stoppedp)
{
if (ptrace (PTRACE_ATTACH, tid, NULL, NULL) != 0)
{
@@ -121,7 +112,7 @@ ptrace_attach (pid_t tid, bool *tid_was_stoppedp)
static bool
pid_memory_read (Dwfl *dwfl, Dwarf_Addr addr, Dwarf_Word *result, void *arg)
{
- struct pid_arg *pid_arg = arg;
+ struct __libdwfl_pid_arg *pid_arg = arg;
pid_t tid = pid_arg->tid_attached;
assert (tid > 0);
Dwfl_Process *process = dwfl->process;
@@ -164,7 +155,7 @@ static pid_t
pid_next_thread (Dwfl *dwfl __attribute__ ((unused)), void *dwfl_arg,
void **thread_argp)
{
- struct pid_arg *pid_arg = dwfl_arg;
+ struct __libdwfl_pid_arg *pid_arg = dwfl_arg;
struct dirent *dirent;
/* Start fresh on first traversal. */
if (*thread_argp == NULL)
@@ -238,11 +229,11 @@ pid_thread_state_registers_cb (int firstreg, unsigned nregs,
static bool
pid_set_initial_registers (Dwfl_Thread *thread, void *thread_arg)
{
- struct pid_arg *pid_arg = thread_arg;
+ struct __libdwfl_pid_arg *pid_arg = thread_arg;
assert (pid_arg->tid_attached == 0);
pid_t tid = INTUSE(dwfl_thread_tid) (thread);
if (! pid_arg->assume_ptrace_stopped
- && ! ptrace_attach (tid, &pid_arg->tid_was_stopped))
+ && ! __libdwfl_ptrace_attach (tid, &pid_arg->tid_was_stopped))
return false;
pid_arg->tid_attached = tid;
Dwfl_Process *process = thread->process;
@@ -254,28 +245,33 @@ pid_set_initial_registers (Dwfl_Thread *thread, void *thread_arg)
static void
pid_detach (Dwfl *dwfl __attribute__ ((unused)), void *dwfl_arg)
{
- struct pid_arg *pid_arg = dwfl_arg;
+ struct __libdwfl_pid_arg *pid_arg = dwfl_arg;
closedir (pid_arg->dir);
free (pid_arg);
}
+void
+internal_function
+__libdwfl_ptrace_detach (pid_t tid, bool tid_was_stopped)
+{
+ /* 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) (tid_was_stopped ? SIGSTOP : 0));
+}
+
static void
pid_thread_detach (Dwfl_Thread *thread, void *thread_arg)
{
- struct pid_arg *pid_arg = thread_arg;
+ struct __libdwfl_pid_arg *pid_arg = thread_arg;
pid_t tid = INTUSE(dwfl_thread_tid) (thread);
assert (pid_arg->tid_attached == tid);
pid_arg->tid_attached = 0;
if (! pid_arg->assume_ptrace_stopped)
- {
- /* 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));
- }
+ __libdwfl_ptrace_detach (tid, pid_arg->tid_was_stopped);
}
static const Dwfl_Thread_Callbacks pid_thread_callbacks =
@@ -328,7 +324,7 @@ dwfl_linux_proc_attach (Dwfl *dwfl, pid_t pid, bool assume_ptrace_stopped)
DIR *dir = opendir (dirname);
if (dir == NULL)
return errno;
- struct pid_arg *pid_arg = malloc (sizeof *pid_arg);
+ struct __libdwfl_pid_arg *pid_arg = malloc (sizeof *pid_arg);
if (pid_arg == NULL)
{
closedir (dir);
@@ -347,3 +343,14 @@ dwfl_linux_proc_attach (Dwfl *dwfl, pid_t pid, bool assume_ptrace_stopped)
return 0;
}
INTDEF (dwfl_linux_proc_attach)
+
+struct __libdwfl_pid_arg *
+internal_function
+__libdwfl_get_pid_arg (Dwfl *dwfl)
+{
+ if (dwfl != NULL && dwfl->process != NULL
+ && dwfl->process->callbacks == &pid_thread_callbacks)
+ return (struct __libdwfl_pid_arg *) dwfl->process->callbacks_arg;
+
+ return NULL;
+}