summaryrefslogtreecommitdiff
path: root/module
diff options
context:
space:
mode:
authorSoren Sandmann <sandmann@daimi.au.dk>2007-09-17 01:43:07 +0000
committerSøren Sandmann Pedersen <ssp@src.gnome.org>2007-09-17 01:43:07 +0000
commitf1cbdbf27c9c766ae1db854c67dce112703f8a8b (patch)
treedc34f996274ecb458d87013587bb01b6ee4dc225 /module
parent39cb26654a9564306e6eb825e2da8c61fd36c78e (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.c81
-rw-r--r--module/sysprof-module.h12
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 (&current->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