diff options
Diffstat (limited to 'runtime/probes/where_func')
-rw-r--r-- | runtime/probes/where_func/Makefile | 11 | ||||
-rw-r--r-- | runtime/probes/where_func/README | 19 | ||||
-rwxr-xr-x | runtime/probes/where_func/build | 16 | ||||
-rw-r--r-- | runtime/probes/where_func/kprobe_where_funct.c | 78 |
4 files changed, 124 insertions, 0 deletions
diff --git a/runtime/probes/where_func/Makefile b/runtime/probes/where_func/Makefile new file mode 100644 index 00000000..1e6b9d2e --- /dev/null +++ b/runtime/probes/where_func/Makefile @@ -0,0 +1,11 @@ +# Makefile +# +# +# make -C path/to/kernel/src M=`pwd` modules STP_RUNTIME=path_to_systemtap_rt + +CFLAGS += -I $(STP_RUNTIME) -D KALLSYMS_LOOKUP_NAME=$(KALLSYMS_LOOKUP_NAME) \ + -D KALLSYMS_LOOKUP=$(KALLSYMS_LOOKUP) +obj-m := kprobe_where_funct.o + +clean: + /bin/rm -rf *.o *.ko *~ *.mod.c .*.cmd .tmp_versions diff --git a/runtime/probes/where_func/README b/runtime/probes/where_func/README new file mode 100644 index 00000000..0df3d719 --- /dev/null +++ b/runtime/probes/where_func/README @@ -0,0 +1,19 @@ +This is a silly little instrumentation routine to instrument functions +entry by name. It makes use of the SystemTap runime libraries break +down the number of times the function by caller. It also uses +__print_symbol to map the address back to locations in functions. + +By default it instruments schedule(). + +The instrumentation module is built by having the kernel that is going +to be instrumented currently on the machine and doing "./build" + +The instrumentation is inserted as root with: + +/sbin/insmod kprobe_funct_where.ko funct_name=function_name + +The instrumentation is removed as root with: + +/sbin/rmmod kprobe_funct_where + +-Will Cohen diff --git a/runtime/probes/where_func/build b/runtime/probes/where_func/build new file mode 100755 index 00000000..3713f08a --- /dev/null +++ b/runtime/probes/where_func/build @@ -0,0 +1,16 @@ +#!/bin/bash + +KVERSION=`uname -r` +echo $KVERSION +KALLSYMS_LOOKUP_NAME=`grep " kallsyms_lookup_name" /boot/System.map-$KVERSION |awk '{print $1}'` +KALLSYMS_LOOKUP=`grep " kallsyms_lookup$" /boot/System.map-$KVERSION |awk '{print $1}'` + +make V=1 -C /lib/modules/`uname -r`/build M=`pwd` modules \ + KALLSYMS_LOOKUP_NAME=0x$KALLSYMS_LOOKUP_NAME \ + KALLSYMS_LOOKUP=0x$KALLSYMS_LOOKUP \ + STP_RUNTIME=`pwd`/../.. + + + + + diff --git a/runtime/probes/where_func/kprobe_where_funct.c b/runtime/probes/where_func/kprobe_where_funct.c new file mode 100644 index 00000000..f90f71bc --- /dev/null +++ b/runtime/probes/where_func/kprobe_where_funct.c @@ -0,0 +1,78 @@ +/* kprobe_where_funct.c + this is a simple module to get information about calls to a function that is passed as a module option + Will Cohen +*/ + +#define HASH_TABLE_BITS 8 +#define HASH_TABLE_SIZE (1<<HASH_TABLE_BITS) +#define BUCKETS 16 /* largest histogram width */ + +#include "runtime.h" +#include "io.c" +#include "map.c" +#include "probes.c" + +MODULE_DESCRIPTION("SystemTap probe: where_func"); +MODULE_AUTHOR("Will Cohen and Martin Hunt"); + +static char default_name[] = "schedule"; +static char *funct_name = default_name; +module_param(funct_name, charp, 0); +MODULE_PARM_DESC(funct_name, "function entry name.\n"); + +static int count_funct = 0; + +MAP funct_locations; + +static int inst_funct(struct kprobe *p, struct pt_regs *regs) +{ + long ret_addr = cur_ret_addr(regs); + ++count_funct; + _stp_map_key_long(funct_locations, ret_addr); + _stp_map_add_int64(funct_locations, 1); + return 0; +} + +/*For each probe you need to allocate a kprobe structure*/ +static struct kprobe kp[] = { + { + .addr = default_name, + .pre_handler = inst_funct, + } +}; +#define MAX_KPROBES (sizeof(kp)/sizeof(struct kprobe)) + +int init_module(void) +{ + int ret; + + funct_locations = _stp_map_new(1000, INT64); + + if (funct_name) + kp[0].addr = funct_name; + + ret = _stp_register_kprobes (kp, MAX_KPROBES); + + return ret; +} + +void cleanup_module(void) +{ + struct map_node_int64 *ptr; + + _stp_unregister_kprobes (kp, MAX_KPROBES); + + dlog("%s() called %d times.\n", funct_name, count_funct); + dlog("NUM\tCaller Addr\tCaller Name\n", funct_name); + + /* now walk the hash table and print out all the information */ + foreach(funct_locations, ptr) { + _stp_print_buf_init(); + _stp_print_symbol("%s\n", key1int(ptr)); + dlog("%lld\t0x%p\t(%s)\n", ptr->val, key1int(ptr), _stp_pbuf); + } + + _stp_map_del(funct_locations); +} + +MODULE_LICENSE("GPL"); |