Hey, it appears to not crash
authorSøren Sandmann Pedersen <ssp@src.gnome.org>
Fri, 29 Oct 2004 22:27:30 +0000 (22:27 +0000)
committerSøren Sandmann Pedersen <ssp@src.gnome.org>
Fri, 29 Oct 2004 22:27:30 +0000 (22:27 +0000)
sysprof-module.c
sysprof.c

index 462e1e2..ad07eab 100644 (file)
 #include <linux/proc_fs.h>
 #include <asm/uaccess.h>
 #include <linux/poll.h>
+#include <linux/highmem.h>
 
 #include "sysprof-module.h"
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Soeren Sandmann (sandmann@daimi.au.dk)");
 
-#define SAMPLES_PER_SECOND (100)
+#define SAMPLES_PER_SECOND (10)
 #define INTERVAL (HZ / SAMPLES_PER_SECOND)
 #define N_TRACES 256
 
@@ -89,49 +90,132 @@ add_timeout(unsigned int interval,
  * The portable part of the driver starts here
  */
 
+static int
+read_task_address (struct task_struct *task, unsigned long address, int *result)
+{
+       unsigned long page_addr = address & PAGE_MASK;
+       int found;
+       struct page *page;
+       void *kaddr;
+       int res;
+
+       if (!task || !task->mm)
+               return 0;
+
+       found = get_user_pages (task, task->mm, page_addr, 1, 0, 0, &page, NULL);
+
+       if (!found)
+               return 0;
+
+       kaddr = kmap_atomic (page, KM_SOFTIRQ0);
+       
+       res = ((int *)kaddr)[(address - page_addr) / 4];
+
+       kunmap_atomic (page, KM_SOFTIRQ0);
+       
+       *result = res;
+       
+       return 1;
+}
+
+typedef struct StackFrame StackFrame;
+struct StackFrame {
+       unsigned long next;
+       unsigned long return_address;
+};
+
+static int
+read_frame (struct task_struct *task, unsigned long addr, StackFrame *frame)
+{
+       if (!addr || !frame)
+               return 0;
+
+       frame->next = 0;
+       frame->return_address = 0;
+       
+       if (!read_task_address (task, addr, (int *)&(frame->next)))
+               return 0;
+
+       if (!read_task_address (task, addr + 4, (int *)&(frame->return_address)))
+               return 0;
+
+       return 1;
+}
+
 static void
 generate_stack_trace(struct task_struct *task,
                     SysprofStackTrace *trace)
 {
-#define START_OF_STACK 0xBFFFFFFF 
-       
-       typedef struct StackFrame StackFrame;
-       struct StackFrame {
-               StackFrame *next;
-               void *return_address;
-       };
-       
-       StackFrame *frame;
+#ifdef NOT_ON_4G4G     /* FIXME: What is the symbol really called? */
+#  define START_OF_STACK 0xBFFFFFFF
+#else
+#  define START_OF_STACK 0xFF000000
+#endif
+       struct pt_regs *regs = ((struct pt_regs *) (THREAD_SIZE + (unsigned long) task->thread_info)) - 1;
+       StackFrame frame;
+       unsigned long addr;
        int i;
        
-       struct pt_regs *regs = ((struct pt_regs *) (THREAD_SIZE + (unsigned long) task->thread_info)) - 1;
        memset(trace, 0, sizeof (SysprofStackTrace));
        
        trace->pid = task->pid;
        trace->truncated = 0;
        
        trace->addresses[0] = (void *)regs->eip;
+
        i = 1;
-       frame = (StackFrame *)regs->ebp;
+
+       addr = regs->ebp;
+
+#if 0
+       printk (KERN_ALERT "in generate\n");
+#endif
+#if 0
+       read_frame (task, addr, &frame);
+#endif
+       while (i < SYSPROF_MAX_ADDRESSES && read_frame (task, addr, &frame)) {
+               trace->addresses[i++] = (void *)frame.return_address;
+               
+               addr = frame.next;
+       }
+
+#if 0
+       printk (KERN_ALERT "done (frame.next = %p)\n", frame.next);
+#endif
+              
+#if 0
+       
+       read_frame (task, regs->ebp, &frame);
        
-       while (frame && i < SYSPROF_MAX_ADDRESSES &&
+       while (i < SYSPROF_MAX_ADDRESSES &&
               (long)frame < (long)START_OF_STACK &&
               (long)frame >= regs->esp) {
                void *next = NULL;
+
+               printk(KERN_ALERT "esp: %lx\n", regs->esp);
+               printk(KERN_ALERT "ebp: %lx\n", regs->ebp);
                
                if (verify_area(VERIFY_READ, frame, sizeof(StackFrame)) == 0) {
                        void *return_address;
                        
-                       __get_user (return_address, &(frame->return_address));
-                       __get_user (next, &(frame->next));
+                       read_task_address (task, (unsigned long)return_address, (int *)&(frame->return_address));
+                       read_task_address (task, (unsigned long)next, (int *)&(frame->next));
+                                          
                        trace->addresses[i++] = return_address;
                        
                        if ((long)next <= (long)frame)
                                next = NULL;
+                       else
+                               printk(KERN_ALERT "bad next\n");
                }
+               else
+                       printk(KERN_ALERT "couldn't verify\n");
                
                frame = next;
+               if (frame == NULL)
+                       printk(KERN_ALERT "frame %d is null\n", i);
        }
+#endif
        
        trace->n_addresses = i;
        if (i == SYSPROF_MAX_ADDRESSES)
@@ -155,13 +239,13 @@ do_generate (void *data)
        for_each_process (p)
                if (p == task)
                        goto go_ahead;
-
-go_ahead:
-       generate_stack_trace (task, head);
-
+       return;
+       
+ go_ahead:
+       generate_stack_trace(task, head);
        if (head++ == &stack_traces[N_TRACES - 1])
                head = &stack_traces[0];
-       
+                            
        wake_up (&wait_for_trace);
 }
 
@@ -220,9 +304,10 @@ procfile_read(char *buffer,
              int *eof,
              void *data)
 {
+#if 0
        if (buffer_len < sizeof (SysprofStackTrace)) 
                return -ENOMEM;
-       
+#endif
        wait_event_interruptible (wait_for_trace, head != tail);
        *buffer_location = (char *)tail;
        if (tail++ == &stack_traces[N_TRACES - 1])
index 312f909..b5f527c 100644 (file)
--- a/sysprof.c
+++ b/sysprof.c
@@ -106,9 +106,15 @@ on_read (gpointer data)
     Application *app = data;
     SysprofStackTrace trace;
     int rd;
+    int i;
     
     rd = read (app->input_fd, &trace, sizeof (trace));
 
+    g_print ("pid: %d\n", trace.pid);
+    for (i=0; i < trace.n_addresses; ++i)
+       g_print ("rd: %08x\n", trace.addresses[i]);
+    g_print ("-=-\n");
+
     if (rd > 0 && app->profiling && !app->generating_profile)
     {
        Process *process = process_get_from_pid (trace.pid);