diff options
| author | Mark Wielaard <[email protected]> | 2014-03-04 11:27:15 +0100 |
|---|---|---|
| committer | Mark Wielaard <[email protected]> | 2014-03-10 21:29:00 +0100 |
| commit | 4b9e1433d2272f5f68b3227abdd9cf6817a0afd3 (patch) | |
| tree | e783d86e9a1c097adf1aef6d2157034f2b0c3476 /libdwfl/linux-pid-attach.c | |
| parent | f15bcda4137446d4773bb54cb99cc18497e9822c (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.c | 65 |
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; +} |
