summaryrefslogtreecommitdiffstats
path: root/runtime/probes/where_func
diff options
context:
space:
mode:
Diffstat (limited to 'runtime/probes/where_func')
-rw-r--r--runtime/probes/where_func/Makefile11
-rw-r--r--runtime/probes/where_func/README19
-rwxr-xr-xruntime/probes/where_func/build16
-rw-r--r--runtime/probes/where_func/kprobe_where_funct.c78
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");