diff --git a/libdwfl/libdwflP.h b/libdwfl/libdwflP.h index 12ee116..e55cc4b 100644 --- a/libdwfl/libdwflP.h +++ b/libdwfl/libdwflP.h @@ -401,6 +401,8 @@ struct dwfl_arange struct __libdwfl_pid_arg { DIR *dir; + Elf *self; + int self_fd; /* It is 0 if not used. */ pid_t tid_attached; /* Valid only if TID_ATTACHED is not zero. */ diff --git a/libdwfl/linux-pid-attach.c b/libdwfl/linux-pid-attach.c index ae71702..7d69ce0 100644 --- a/libdwfl/linux-pid-attach.c +++ b/libdwfl/linux-pid-attach.c @@ -27,6 +27,9 @@ not, see . */ #include "libdwflP.h" +#include +#include +#include #include #include #include @@ -247,6 +250,8 @@ static void pid_detach (Dwfl *dwfl __attribute__ ((unused)), void *dwfl_arg) { struct __libdwfl_pid_arg *pid_arg = dwfl_arg; + elf_end (pid_arg->self); + close (pid_arg->self_fd); closedir (pid_arg->dir); free (pid_arg); } @@ -332,15 +337,32 @@ dwfl_linux_proc_attach (Dwfl *dwfl, pid_t pid, bool assume_ptrace_stopped) goto fail; } - char dirname[64]; - int i = snprintf (dirname, sizeof (dirname), "/proc/%ld/task", (long) pid); - assert (i > 0 && i < (ssize_t) sizeof (dirname) - 1); - DIR *dir = opendir (dirname); + char name[64]; + int i = snprintf (name, sizeof (name), "/proc/%ld/task", (long) pid); + assert (i > 0 && i < (ssize_t) sizeof (name) - 1); + DIR *dir = opendir (name); if (dir == NULL) { err = errno; goto fail; } + i = snprintf (name, sizeof (name), "/proc/%ld/exe", (long) pid); + assert (i > 0 && i < (ssize_t) sizeof (name) - 1); + int fd = open (name, O_RDONLY); + if (fd < 0) + { + err = errno; + goto fail; + } + Elf *self = elf_begin (fd, ELF_C_READ_MMAP, NULL); + if (self == NULL) + { + /* We need to return an errno, so we should really translate the + elf_errno back to an errno, but lets just assume it is ENOMEM. */ + err = ENOMEM; + close (fd); + goto fail; + } struct __libdwfl_pid_arg *pid_arg = malloc (sizeof *pid_arg); if (pid_arg == NULL) { @@ -349,11 +371,15 @@ dwfl_linux_proc_attach (Dwfl *dwfl, pid_t pid, bool assume_ptrace_stopped) goto fail; } pid_arg->dir = dir; + pid_arg->self = self; + pid_arg->self_fd = fd; pid_arg->tid_attached = 0; pid_arg->assume_ptrace_stopped = assume_ptrace_stopped; - if (! INTUSE(dwfl_attach_state) (dwfl, NULL, pid, &pid_thread_callbacks, + if (! INTUSE(dwfl_attach_state) (dwfl, self, pid, &pid_thread_callbacks, pid_arg)) { + elf_end (self); + close (fd); closedir (dir); free (pid_arg); return -1;