204 lines
6.4 KiB
Diff
204 lines
6.4 KiB
Diff
|
commit 6a4267cb9967c4f330e40d5aa8d9be265b3c2997
|
||
|
Author: Josh Stone <jistone@redhat.com>
|
||
|
Date: Fri Oct 12 14:45:55 2012 -0700
|
||
|
|
||
|
PR14712 backport for release-2.0
|
||
|
|
||
|
529c7ea Fix for kernels without VM_EXECUTABLE
|
||
|
3df148c Fix the include order so vma tracking works
|
||
|
1f13ff7 Correct the bug number in a comment
|
||
|
|
||
|
diff --git a/runtime/linux/task_finder.c b/runtime/linux/task_finder.c
|
||
|
index 2b1e22f..e2e575a 100644
|
||
|
--- a/runtime/linux/task_finder.c
|
||
|
+++ b/runtime/linux/task_finder.c
|
||
|
@@ -26,6 +26,7 @@
|
||
|
#include "syscall.h"
|
||
|
#include "utrace_compatibility.h"
|
||
|
#include "task_finder_map.c"
|
||
|
+#include "task_finder_vma.c"
|
||
|
|
||
|
static LIST_HEAD(__stp_task_finder_list);
|
||
|
|
||
|
@@ -440,7 +441,7 @@ __stp_task_finder_cleanup(void)
|
||
|
static char *
|
||
|
__stp_get_mm_path(struct mm_struct *mm, char *buf, int buflen)
|
||
|
{
|
||
|
- struct vm_area_struct *vma;
|
||
|
+ struct file *vm_file;
|
||
|
char *rc = NULL;
|
||
|
|
||
|
// The down_read() function can sleep, so we'll call
|
||
|
@@ -451,17 +452,12 @@ __stp_get_mm_path(struct mm_struct *mm, char *buf, int buflen)
|
||
|
return ERR_PTR(-ENOENT);
|
||
|
}
|
||
|
|
||
|
- vma = mm->mmap;
|
||
|
- while (vma) {
|
||
|
- if ((vma->vm_flags & VM_EXECUTABLE) && vma->vm_file)
|
||
|
- break;
|
||
|
- vma = vma->vm_next;
|
||
|
- }
|
||
|
- if (vma) {
|
||
|
+ vm_file = stap_find_exe_file(mm);
|
||
|
+ if (vm_file) {
|
||
|
#ifdef STAPCONF_DPATH_PATH
|
||
|
- rc = d_path(&(vma->vm_file->f_path), buf, buflen);
|
||
|
+ rc = d_path(&(vm_file->f_path), buf, buflen);
|
||
|
#else
|
||
|
- rc = d_path(vma->vm_file->f_dentry, vma->vm_file->f_vfsmnt,
|
||
|
+ rc = d_path(vm_file->f_dentry, vm_file->f_vfsmnt,
|
||
|
buf, buflen);
|
||
|
#endif
|
||
|
}
|
||
|
diff --git a/runtime/linux/task_finder2.c b/runtime/linux/task_finder2.c
|
||
|
index 680b428..27ba2d2 100644
|
||
|
--- a/runtime/linux/task_finder2.c
|
||
|
+++ b/runtime/linux/task_finder2.c
|
||
|
@@ -11,6 +11,7 @@
|
||
|
#endif
|
||
|
#include "syscall.h"
|
||
|
#include "task_finder_map.c"
|
||
|
+#include "task_finder_vma.c"
|
||
|
|
||
|
static LIST_HEAD(__stp_task_finder_list);
|
||
|
|
||
|
@@ -425,7 +426,7 @@ __stp_task_finder_cleanup(void)
|
||
|
static char *
|
||
|
__stp_get_mm_path(struct mm_struct *mm, char *buf, int buflen)
|
||
|
{
|
||
|
- struct vm_area_struct *vma;
|
||
|
+ struct file *vm_file;
|
||
|
char *rc = NULL;
|
||
|
|
||
|
// The down_read() function can sleep, so we'll call
|
||
|
@@ -436,17 +437,12 @@ __stp_get_mm_path(struct mm_struct *mm, char *buf, int buflen)
|
||
|
return ERR_PTR(-ENOENT);
|
||
|
}
|
||
|
|
||
|
- vma = mm->mmap;
|
||
|
- while (vma) {
|
||
|
- if ((vma->vm_flags & VM_EXECUTABLE) && vma->vm_file)
|
||
|
- break;
|
||
|
- vma = vma->vm_next;
|
||
|
- }
|
||
|
- if (vma) {
|
||
|
+ vm_file = stap_find_exe_file(mm);
|
||
|
+ if (vm_file) {
|
||
|
#ifdef STAPCONF_DPATH_PATH
|
||
|
- rc = d_path(&(vma->vm_file->f_path), buf, buflen);
|
||
|
+ rc = d_path(&(vm_file->f_path), buf, buflen);
|
||
|
#else
|
||
|
- rc = d_path(vma->vm_file->f_dentry, vma->vm_file->f_vfsmnt,
|
||
|
+ rc = d_path(vm_file->f_dentry, vm_file->f_vfsmnt,
|
||
|
buf, buflen);
|
||
|
#endif
|
||
|
}
|
||
|
diff --git a/runtime/linux/uprobes-common.c b/runtime/linux/uprobes-common.c
|
||
|
index 64b62cc..cdfb5a6 100644
|
||
|
--- a/runtime/linux/uprobes-common.c
|
||
|
+++ b/runtime/linux/uprobes-common.c
|
||
|
@@ -77,13 +77,10 @@ static int stap_uprobe_change_plus (struct task_struct *tsk, unsigned long reloc
|
||
|
|
||
|
sdt_sem_pid = (sups->return_p ? sup->urp.u.pid : sup->up.pid);
|
||
|
if (sups->sdt_sem_offset && (sdt_sem_pid != tsk->tgid || sup->sdt_sem_address == 0)) {
|
||
|
- /* If the probe is in the executable itself, the offset *is* the address. */
|
||
|
- if (vm_flags & VM_EXECUTABLE) {
|
||
|
- sup->sdt_sem_address = relocation + sups->sdt_sem_offset;
|
||
|
- }
|
||
|
- else {
|
||
|
- sup->sdt_sem_address = (relocation - offset) + sups->sdt_sem_offset;
|
||
|
- }
|
||
|
+ /* If the probe is in an ET_EXEC binary, then the sdt_sem_offset already
|
||
|
+ * is a real address. But stap_uprobe_process_found calls us in this
|
||
|
+ * case with relocation=offset=0, so we don't have to worry about it. */
|
||
|
+ sup->sdt_sem_address = (relocation - offset) + sups->sdt_sem_offset;
|
||
|
} /* sdt_sem_offset */
|
||
|
if (slotted_p) {
|
||
|
struct stap_uprobe *sup = & stap_uprobes[i];
|
||
|
diff --git a/runtime/linux/uprobes-inode.c b/runtime/linux/uprobes-inode.c
|
||
|
index 578123c..9d4d867 100644
|
||
|
--- a/runtime/linux/uprobes-inode.c
|
||
|
+++ b/runtime/linux/uprobes-inode.c
|
||
|
@@ -406,9 +406,14 @@ stapiu_change_plus(struct stapiu_target* target, struct task_struct *task,
|
||
|
if (!p->tgid) {
|
||
|
p->tgid = task->tgid;
|
||
|
p->relocation = relocation;
|
||
|
- p->base = relocation;
|
||
|
- if (!(vm_flags & VM_EXECUTABLE))
|
||
|
- p->base -= offset;
|
||
|
+
|
||
|
+ /* The base is used for relocating semaphores. If the
|
||
|
+ * probe is in an ET_EXEC binary, then that offset
|
||
|
+ * already is a real address. But stapiu_process_found
|
||
|
+ * calls us in this case with relocation=offset=0, so
|
||
|
+ * we don't have to worry about it. */
|
||
|
+ p->base = relocation - offset;
|
||
|
+
|
||
|
list_add(&p->target_process, &target->processes);
|
||
|
break;
|
||
|
}
|
||
|
@@ -491,7 +496,7 @@ static struct inode *
|
||
|
stapiu_get_task_inode(struct task_struct *task)
|
||
|
{
|
||
|
struct mm_struct *mm;
|
||
|
- struct vm_area_struct *vma;
|
||
|
+ struct file* vm_file;
|
||
|
struct inode *inode = NULL;
|
||
|
|
||
|
// Grab the inode associated with the task.
|
||
|
@@ -507,15 +512,9 @@ stapiu_get_task_inode(struct task_struct *task)
|
||
|
}
|
||
|
|
||
|
down_read(&mm->mmap_sem);
|
||
|
- vma = mm->mmap;
|
||
|
- while (vma) {
|
||
|
- if ((vma->vm_flags & VM_EXECUTABLE) && vma->vm_file
|
||
|
- && vma->vm_file->f_path.dentry != NULL) {
|
||
|
- inode = vma->vm_file->f_path.dentry->d_inode;
|
||
|
- break;
|
||
|
- }
|
||
|
- vma = vma->vm_next;
|
||
|
- }
|
||
|
+ vm_file = stap_find_exe_file(mm);
|
||
|
+ if (vm_file && vm_file->f_path.dentry)
|
||
|
+ inode = vm_file->f_path.dentry->d_inode;
|
||
|
|
||
|
up_read(&mm->mmap_sem);
|
||
|
return inode;
|
||
|
diff --git a/runtime/task_finder_vma.c b/runtime/task_finder_vma.c
|
||
|
index 7c872ba..0db35a0 100644
|
||
|
--- a/runtime/task_finder_vma.c
|
||
|
+++ b/runtime/task_finder_vma.c
|
||
|
@@ -1,3 +1,6 @@
|
||
|
+#ifndef TASK_FINDER_VMA_C
|
||
|
+#define TASK_FINDER_VMA_C
|
||
|
+
|
||
|
#include <linux/list.h>
|
||
|
#include <linux/jhash.h>
|
||
|
#include <linux/spinlock.h>
|
||
|
@@ -371,3 +374,23 @@ stap_drop_vma_maps(struct task_struct *tsk)
|
||
|
write_unlock_irqrestore(&__stp_tf_vma_lock, flags);
|
||
|
return 0;
|
||
|
}
|
||
|
+
|
||
|
+/* Find the main executable for this mm.
|
||
|
+ * NB: mmap_sem should be held already. */
|
||
|
+static struct file*
|
||
|
+stap_find_exe_file(struct mm_struct* mm)
|
||
|
+{
|
||
|
+ /* VM_EXECUTABLE was killed in kernel commit e9714acf, but in kernels
|
||
|
+ * that new we can just use mm->exe_file anyway. (PR14712) */
|
||
|
+#ifdef VM_EXECUTABLE
|
||
|
+ struct vm_area_struct *vma;
|
||
|
+ for (vma = mm->mmap; vma; vma = vma->vm_next)
|
||
|
+ if ((vma->vm_flags & VM_EXECUTABLE) && vma->vm_file)
|
||
|
+ return vma->vm_file;
|
||
|
+ return NULL;
|
||
|
+#else
|
||
|
+ return mm->exe_file;
|
||
|
+#endif
|
||
|
+}
|
||
|
+
|
||
|
+#endif /* TASK_FINDER_VMA_C */
|