mirror of
https://github.com/varun-r-mallya/sysprof.git
synced 2025-12-31 20:36:25 +00:00
Use kernel builtin tracer instead of copying everything ourselves.
2008-03-20 Soren Sandmann <sandmann@redhat.com> * module/sysprof-module.c (trace_kernel): Use kernel builtin tracer instead of copying everything ourselves. svn path=/trunk/; revision=401
This commit is contained in:
committed by
Søren Sandmann Pedersen
parent
83fd2bbc31
commit
c2de993836
@ -1,3 +1,8 @@
|
||||
2008-03-20 Soren Sandmann <sandmann@redhat.com>
|
||||
|
||||
* module/sysprof-module.c (trace_kernel): Use kernel builtin
|
||||
tracer instead of copying everything ourselves.
|
||||
|
||||
2008-03-20 Soren Sandmann <sandmann@redhat.com>
|
||||
|
||||
* module/sysprof-module.c: Support for 2.6.24 and newer
|
||||
|
||||
22
collector.c
22
collector.c
@ -143,8 +143,7 @@ add_trace_to_stash (const SysprofStackTrace *trace,
|
||||
g_assert (a == n_addresses);
|
||||
#endif
|
||||
|
||||
stack_stash_add_trace (
|
||||
stash, addrs, a, 1);
|
||||
stack_stash_add_trace (stash, addrs, a, 1);
|
||||
|
||||
if (addrs != addrs_stack)
|
||||
g_free (addrs);
|
||||
@ -195,6 +194,15 @@ collect_traces (Collector *collector)
|
||||
g_print ("-=-\n");
|
||||
}
|
||||
#endif
|
||||
#if 0
|
||||
{
|
||||
int i;
|
||||
g_print ("pid: %d (%d)\n", trace->pid, trace->n_addresses);
|
||||
for (i=0; i < trace->n_kernel_words; ++i)
|
||||
g_print ("rd: %08x\n", trace->kernel_stack[i]);
|
||||
g_print ("-=-\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
add_trace_to_stash (trace, collector->stash);
|
||||
|
||||
@ -403,7 +411,12 @@ lookup_symbol (Process *process, gpointer address,
|
||||
* legitimately be at offset 0.
|
||||
*/
|
||||
if (offset == 0 && !first_addr)
|
||||
{
|
||||
#if 0
|
||||
g_print ("rejecting callback: %s (%p)\n", sym, address);
|
||||
#endif
|
||||
sym = NULL;
|
||||
}
|
||||
|
||||
/* If offset is greater than 4096, then what happened is most
|
||||
* likely that it is the address of something in the gap between the
|
||||
@ -414,7 +427,12 @@ lookup_symbol (Process *process, gpointer address,
|
||||
* is, and act accordingly. Actually, we should look at /proc/modules
|
||||
*/
|
||||
if (offset > 4096)
|
||||
{
|
||||
#if 0
|
||||
g_print ("offset\n");
|
||||
#endif
|
||||
sym = NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@ -30,6 +30,7 @@
|
||||
|
||||
#include <linux/proc_fs.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/stacktrace.h>
|
||||
#include <linux/poll.h>
|
||||
#include <linux/highmem.h>
|
||||
#include <linux/pagemap.h>
|
||||
@ -151,40 +152,84 @@ nt_memcpy (void *dst, void *src, int n_bytes)
|
||||
#endif
|
||||
}
|
||||
|
||||
static struct pt_regs *
|
||||
copy_kernel_stack (struct pt_regs *regs,
|
||||
SysprofStackTrace *trace)
|
||||
/*
|
||||
* The functions backtrace_* are based on oprofile's backtrace.c
|
||||
*
|
||||
* @remark Copyright 2002 OProfile authors
|
||||
* @remark Read the file COPYING
|
||||
*
|
||||
* @author John Levon
|
||||
* @author David Smith
|
||||
*/
|
||||
static void backtrace_warning_symbol(void *data, char *msg,
|
||||
unsigned long symbol)
|
||||
{
|
||||
int n_bytes;
|
||||
char *esp;
|
||||
/* Ignore warnings */
|
||||
}
|
||||
|
||||
static void backtrace_warning(void *data, char *msg)
|
||||
{
|
||||
/* Ignore warnings */
|
||||
}
|
||||
|
||||
struct backtrace_info_t
|
||||
{
|
||||
SysprofStackTrace *trace;
|
||||
int pos;
|
||||
};
|
||||
|
||||
static int backtrace_stack(void *data, char *name)
|
||||
{
|
||||
/* Don't bother with IRQ stacks for now */
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void backtrace_address(void *data, unsigned long addr, int reliable)
|
||||
{
|
||||
struct backtrace_info_t *info = data;
|
||||
|
||||
if (info->pos < SYSPROF_MAX_ADDRESSES && reliable)
|
||||
info->trace->kernel_stack[info->pos++] = (void *)addr;
|
||||
}
|
||||
|
||||
const static struct stacktrace_ops backtrace_ops = {
|
||||
.warning = backtrace_warning,
|
||||
.warning_symbol = backtrace_warning_symbol,
|
||||
.stack = backtrace_stack,
|
||||
.address = backtrace_address,
|
||||
};
|
||||
|
||||
static struct pt_regs *
|
||||
trace_kernel (struct pt_regs *regs,
|
||||
SysprofStackTrace *trace)
|
||||
{
|
||||
struct backtrace_info_t info;
|
||||
char *eos;
|
||||
|
||||
unsigned long stack;
|
||||
unsigned long bp;
|
||||
|
||||
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.
|
||||
info.trace = trace;
|
||||
info.pos = 1;
|
||||
|
||||
stack = (unsigned long) ((char *)regs + sizeof (struct pt_regs));
|
||||
#ifdef CONFIG_FRAME_POINTER
|
||||
/* We can't set it to 0, because then the stack trace will
|
||||
* contain the stack of the timer interrupt
|
||||
*/
|
||||
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) {
|
||||
#if 0
|
||||
nt_memcpy (&(trace->kernel_stack[1]), esp, n_bytes);
|
||||
bp = regs->REG_FRAME_PTR;
|
||||
#else
|
||||
bp = 0;
|
||||
#endif
|
||||
memcpy (&(trace->kernel_stack[1]), esp, n_bytes);
|
||||
|
||||
trace->n_kernel_words += (n_bytes) / sizeof (void *);
|
||||
}
|
||||
|
||||
dump_trace(NULL, regs, stack, bp, &backtrace_ops, &info);
|
||||
|
||||
trace->n_kernel_words = info.pos;
|
||||
|
||||
/* Now trace the user stack */
|
||||
eos = (char *)current->thread.REG_STACK_PTR0 - sizeof (struct pt_regs);
|
||||
|
||||
return (struct pt_regs *)eos;
|
||||
}
|
||||
|
||||
@ -318,7 +363,7 @@ timer_notify (struct pt_regs *regs)
|
||||
trace->n_addresses = 0;
|
||||
|
||||
if (!is_user)
|
||||
regs = copy_kernel_stack (regs, trace);
|
||||
regs = trace_kernel (regs, trace);
|
||||
|
||||
trace->addresses[0] = (void *)regs->REG_INS_PTR;
|
||||
trace->n_addresses = 1;
|
||||
|
||||
@ -25,11 +25,11 @@ typedef struct SysprofStackInfo SysprofStackInfo;
|
||||
typedef struct SysprofMmapArea SysprofMmapArea;
|
||||
|
||||
#define SYSPROF_N_TRACES 64
|
||||
#define SYSPROF_MAX_ADDRESSES 1020 /* to make it three pages wide */
|
||||
#define SYSPROF_MAX_ADDRESSES 126
|
||||
|
||||
struct SysprofStackTrace
|
||||
{
|
||||
void *kernel_stack[1024];
|
||||
void *kernel_stack[SYSPROF_MAX_ADDRESSES];
|
||||
void *addresses[SYSPROF_MAX_ADDRESSES];
|
||||
int n_kernel_words;
|
||||
int n_addresses; /* note: this can be 1 if the process was compiled
|
||||
|
||||
Reference in New Issue
Block a user