commit 6a4267cb9967c4f330e40d5aa8d9be265b3c2997 Author: Josh Stone 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 #include #include @@ -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 */