From 8e4bff4cab0ddac6060645b0715210484d02ff40 Mon Sep 17 00:00:00 2001 From: Yuval Adam <_@yuv.al> Date: Wed, 30 Aug 2017 08:25:59 +0000 Subject: Initial file dump from open source release --- fs/proc/sprd_debug/proc_userstack.c | 169 ++++++++++++++++++++++++++++++++++++ 1 file changed, 169 insertions(+) create mode 100644 fs/proc/sprd_debug/proc_userstack.c (limited to 'fs/proc/sprd_debug/proc_userstack.c') diff --git a/fs/proc/sprd_debug/proc_userstack.c b/fs/proc/sprd_debug/proc_userstack.c new file mode 100644 index 00000000..ef055bb4 --- /dev/null +++ b/fs/proc/sprd_debug/proc_userstack.c @@ -0,0 +1,169 @@ +//#ifdef CONFIG_USERSTACKTRACEG +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#define K(x) ((x) << (PAGE_SHIFT - 10)) + +extern struct meminfo meminfo; +static int show_user_stack(struct seq_file *m, void *v); +//static struct proc_dir_entry* userstack_info; + +static int get_pfn_from_mm(unsigned long address, struct mm_struct *mm) +{ + pgd_t *pgd; + pud_t *pud; + pmd_t *pmd; + pte_t *pte; + int ret = 0; + + pgd = pgd_offset(mm, address); + if (!pgd_present(*pgd)) + return ret; + + pud = pud_offset(pgd, address); + if (!pud_present(*pud)) + return ret; + + pmd = pmd_offset(pud, address); + if (!pmd_present(*pmd)) + return ret; + + pte = pte_offset_map(pmd, address); + + if (!pte_present(*pte)) + return 0; + + return pte_pfn(*pte); +} + +static struct page *user_addr_to_page(unsigned long uaddr, struct task_struct *task) +{ + int pfn; + pfn = get_pfn_from_mm(uaddr, task->mm); + + if (!pfn) + return NULL; + + return pfn_to_page(pfn); +} + +static int show_userstack_of_task(struct task_struct *task, struct seq_file *m, void *v) +{ + unsigned long val; + unsigned long p; + struct vm_area_struct *vma; + unsigned long usersp, kusersp; + unsigned long length = 32*10; + unsigned long *kaddr = NULL; + struct page *page = NULL; + pgoff_t pgoff; + + if (!task->mm) { + seq_printf(m, "pid:%d, it's a kthread, no userstack!\n",task->pid); + return 0; + } + + usersp = task_pt_regs(task)->uregs[13]; + + seq_printf(m, "userstack pid:%d sp:0x%p\n\n", task->pid, (void *)usersp); + + page = user_addr_to_page(usersp, task); + if (!page) { + seq_printf(m, "Sorry, can't find the stack's page!\n"); + return 0; + } + + pgoff = usersp & 0x00000fff; + kaddr = kmap(page); + kusersp = (unsigned long)kaddr + pgoff; + + for (p = kusersp; p < kusersp + length; p += 4) { + vma = NULL; + val = *(unsigned long *)p; + vma = find_vma(task->mm, val); + if (vma) { + struct file *file = vma->vm_file; + struct mm_struct *mm = vma->vm_mm; + + if (val < vma->vm_start) { + seq_printf(m, "%4lx: %08lx \n", p, val); + continue; + } + + if (file) { + char buf[50]; + char *pp = NULL; + + memset(buf, 0, 50); + pp = d_path(&file->f_path, buf, 50); + if (!IS_ERR(pp)) + mangle_path(buf, pp, "\n"); + + seq_printf(m, "%4lx: %08lx %s 0x%p\n", p, val, buf, (void *)vma->vm_start); + } else { + const char *name = arch_vma_name(vma); + if (!name) { + if (vma->vm_start <= mm->start_brk && vma->vm_end >= mm->brk) + seq_printf(m, "%4lx: %08lx [heap]\n", p, val); + else if (vma->vm_start <= mm->start_stack && vma->vm_end >= mm->start_stack) + seq_printf(m, "%4lx: %08lx [stack]\n", p, val); + else + seq_printf(m, "%4lx: %08lx [vdso]\n", p, val); + } else + seq_printf(m, "%4lx: %08lx %s\n", p, val, name); + } + } else + seq_printf(m, "%4lx: %08lx \n", p, val); + } + seq_printf(m, "====================================================\n"); + kunmap(page); + return 0; +} + +static int show_user_stack(struct seq_file *m, void *v) +{ + struct task_struct *g, *p; + seq_printf(m, "=============enter ====show_user_stack===========\n"); + + do_each_thread(g, p) { + task_lock(p); + if (p->state == TASK_UNINTERRUPTIBLE) + show_userstack_of_task(p, m, v); + task_unlock(p); + }while_each_thread(g, p); + + return 0; +} + +static int userstack_proc_open(struct inode* inode, struct file* file) +{ + single_open(file, show_user_stack, NULL); + return 0; +} + + +struct file_operations userstack_info_proc_fops = +{ + .open = userstack_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + -- cgit v1.3.1