diff options
author | Soren Sandmann <sandmann@daimi.au.dk> | 2007-09-17 01:43:07 +0000 |
---|---|---|
committer | Søren Sandmann Pedersen <ssp@src.gnome.org> | 2007-09-17 01:43:07 +0000 |
commit | f1cbdbf27c9c766ae1db854c67dce112703f8a8b (patch) | |
tree | dc34f996274ecb458d87013587bb01b6ee4dc225 /module | |
parent | 39cb26654a9564306e6eb825e2da8c61fd36c78e (diff) |
Add support for looking up kernel symbols from /proc/kallsyms
2007-09-16 Soren Sandmann <sandmann@daimi.au.dk>
* process.c (process_lookup_kernel_symbol): Add support for
looking up kernel symbols from /proc/kallsyms
* sysprof-text.c (dump_data): Print note that the file is being
saved.
* module/sysprof-module.[ch] (timer_notify): Send a copy of the
kernel stack to userspace.
* collector.c: Do kernel symbol lookups.
svn path=/trunk/; revision=372
Diffstat (limited to 'module')
-rw-r--r-- | module/sysprof-module.c | 81 | ||||
-rw-r--r-- | module/sysprof-module.h | 12 |
2 files changed, 45 insertions, 48 deletions
diff --git a/module/sysprof-module.c b/module/sysprof-module.c index 59b7910..d2f5ab5 100644 --- a/module/sysprof-module.c +++ b/module/sysprof-module.c @@ -106,6 +106,12 @@ read_frame (void *frame_pointer, StackFrame *frame) DEFINE_PER_CPU(int, n_samples); +static int +minimum (int a, int b) +{ + return a > b ? b : a; +} + #ifdef OLD_PROFILE static int timer_notify(struct notifier_block * self, unsigned long val, void * data) #else @@ -123,9 +129,6 @@ timer_notify (struct pt_regs *regs) StackFrame frame; int result; static atomic_t in_timer_notify = ATOMIC_INIT(1); -#if 0 - int stacksize; -#endif int n; n = ++get_cpu_var(n_samples); @@ -135,7 +138,6 @@ timer_notify (struct pt_regs *regs) return 0; /* 0: locked, 1: unlocked */ - if (!atomic_dec_and_test(&in_timer_notify)) goto out; @@ -150,58 +152,51 @@ timer_notify (struct pt_regs *regs) memset(trace, 0, sizeof (SysprofStackTrace)); trace->pid = current->pid; - + + trace->n_kernel_words = 0; + trace->n_addresses = 0; + i = 0; if (!is_user) { - trace->addresses[i++] = (void *)0x01; - regs = (void *)current->thread.REG_STACK_PTR0 - sizeof (struct pt_regs); + int n_bytes; + char *esp; + char *eos; + + trace->kernel_stack[0] = (void *)regs->REG_INS_PTR; + trace->n_kernel_words = 1; + + /* The timer interrupt happened in kernel mode. When this + * happens the registers are pushed on the stack, _except_ + * esp. So we can't use regs->esp to copy the stack pointer. + * Instead we use the fact that the regs pointer itself + * points to the stack. + */ + esp = (char *)regs + sizeof (struct pt_regs); + eos = (char *)current->thread.REG_STACK_PTR0 - sizeof (struct pt_regs); + + n_bytes = minimum ((char *)eos - esp, + sizeof (trace->kernel_stack)); + + if (n_bytes > 0) { + memcpy (&(trace->kernel_stack[1]), esp, n_bytes); + + trace->n_kernel_words += (n_bytes) / sizeof (void *); + } + + /* Now trace the user stack */ + regs = (struct pt_regs *)eos; } + i = 0; trace->addresses[i++] = (void *)regs->REG_INS_PTR; frame_pointer = (void *)regs->REG_FRAME_PTR; - - { -#if 0 - /* In principle we should use get_task_mm() but - * that will use task_lock() leading to deadlock - * if somebody already has the lock - */ - if (spin_is_locked (¤t->alloc_lock)) - printk ("alreadylocked\n"); - { - struct mm_struct *mm = current->mm; - if (mm) - { - printk (KERN_ALERT "stack size: %d (%d)\n", - mm->start_stack - regs->REG_STACK_PTR, - current->pid); - - stacksize = mm->start_stack - regs->REG_STACK_PTR; - } - else - stacksize = 1; - } -#endif -#if 0 - else - printk (KERN_ALERT "could not lock on %d\n", current->pid); -#endif - } -#if 0 - if (stacksize < 100000) - goto out; -#endif - while (((result = read_frame (frame_pointer, &frame)) == 0) && i < SYSPROF_MAX_ADDRESSES && (unsigned long)frame_pointer >= regs->REG_STACK_PTR) { -#if 0 - printk ("frame pointer: %p (retaddr: %p)\n", frame_pointer, frame.return_address); -#endif trace->addresses[i++] = (void *)frame.return_address; frame_pointer = (StackFrame *)frame.next; } diff --git a/module/sysprof-module.h b/module/sysprof-module.h index 9b7e4df..d92886d 100644 --- a/module/sysprof-module.h +++ b/module/sysprof-module.h @@ -25,16 +25,18 @@ typedef struct SysprofStackInfo SysprofStackInfo; typedef struct SysprofMmapArea SysprofMmapArea; #define SYSPROF_N_TRACES 64 -#define SYSPROF_MAX_ADDRESSES 1021 /* to make it one page wide */ +#define SYSPROF_MAX_ADDRESSES 1020 /* to make it three pages wide */ struct SysprofStackTrace { + void *kernel_stack[1024]; + void *addresses[SYSPROF_MAX_ADDRESSES]; + int n_kernel_words; + int n_addresses; /* note: this can be 1 if the process was compiled + * with -fomit-frame-pointer or is otherwise weird + */ int pid; /* -1 if in kernel */ int truncated; - int n_addresses; /* note: this can be 1 if the process was compiled - * with -fomit-frame-pointer or is otherwise weird - */ - void *addresses[SYSPROF_MAX_ADDRESSES]; }; struct SysprofMmapArea |