This is the mail archive of the
systemtap@sourceware.org
mailing list for the systemtap project.
ia64 kprobes on syscalls
- From: jes at trained-monkey dot org (Jes Sorensen)
- To: systemtap at sourceware dot org
- Date: Fri, 24 Feb 2006 04:54:47 -0500
- Subject: ia64 kprobes on syscalls
Hi,
I am trying to use kprobes to monitor system calls on ia64. However I am
not exactly having a lot of luck with it ;( I tried a couple of
approaches so far and they all seem to result in the kernel exploding
quickly.
First attempt was to add probes directly to the syscall entry code. Now
I am trying to add it to the sys_foo functions instead by walking the
sys_call_table, but it seems to have the same problem.
Has anyone done this successfully on ia64? Is it supposed to work? I was
speaking to Suparna who said there were some systemtap scripts to do
this, so I a presume it has at least been working at some point for the
x86?
I've attached a simple test case below if anyone wishes to comment upon
it (or tell me why I am utterly stupid ;) Ignore the fact that this
thing is leaking struct kprobe's left right and center.
Cheers,
Jes
Index: linux-2.6/arch/ia64/Kconfig.debug
===================================================================
--- linux-2.6.orig/arch/ia64/Kconfig.debug
+++ linux-2.6/arch/ia64/Kconfig.debug
@@ -2,6 +2,9 @@
source "lib/Kconfig.debug"
+config IA64_SYSCALL_PROBES
+ tristate "Enable syscall probe hack"
+
choice
prompt "Physical memory granularity"
default IA64_GRANULE_64MB
Index: linux-2.6/arch/ia64/kernel/Makefile
===================================================================
--- linux-2.6.orig/arch/ia64/kernel/Makefile
+++ linux-2.6/arch/ia64/kernel/Makefile
@@ -30,6 +30,7 @@
obj-$(CONFIG_KPROBES) += kprobes.o jprobes.o
obj-$(CONFIG_IA64_UNCACHED_ALLOCATOR) += uncached.o
mca_recovery-y += mca_drv.o mca_drv_asm.o
+obj-$(CONFIG_IA64_SYSCALL_PROBES) += syscall-probes.o
# The gate DSO image is built using a special linker script.
targets += gate.so gate-syms.o
Index: linux-2.6/arch/ia64/kernel/ia64_ksyms.c
===================================================================
--- linux-2.6.orig/arch/ia64/kernel/ia64_ksyms.c
+++ linux-2.6/arch/ia64/kernel/ia64_ksyms.c
@@ -108,3 +108,6 @@
extern char ia64_ivt[];
EXPORT_SYMBOL(ia64_ivt);
+
+extern unsigned long sys_call_table[];
+EXPORT_SYMBOL(sys_call_table);
Index: linux-2.6/arch/ia64/kernel/syscall-probes.c
===================================================================
--- /dev/null
+++ linux-2.6/arch/ia64/kernel/syscall-probes.c
@@ -0,0 +1,88 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/uio.h>
+#include <linux/kprobes.h>
+#include <linux/kallsyms.h>
+#include <asm/unistd.h>
+
+static int count;
+
+
+static int
+syscall_enter_pre_handler(struct kprobe *probe, struct pt_regs *regs)
+{
+ if (count++ < 25)
+ printk(KERN_DEBUG "syscall me harder! r15\n");
+
+ return 0;
+}
+
+static int probe_fault_handler(struct kprobe *probe,
+ struct pt_regs *regs, int trap)
+{
+ printk(KERN_DEBUG "probe_fault_handler: addr %p, trap %i\n",
+ probe->addr, trap);
+ return 0;
+}
+
+extern unsigned long sys_call_table[];
+
+static int install_syscall_enter_probe(void)
+{
+ int ret, i, j;
+ struct kprobe *p;
+
+ printk(KERN_DEBUG "installing syscall_enter probe!\n");
+
+ for (i = 1, j = 0; i < NR_syscalls; i++) {
+ /*
+ * entry 0 is always a ni_syscall
+ */
+ if (sys_call_table[i] != sys_call_table[0]) {
+ p = kmalloc(sizeof(struct kprobe), GFP_KERNEL);
+ BUG_ON(!p);
+
+ p->pre_handler = syscall_enter_pre_handler;
+ p->fault_handler = probe_fault_handler;
+ p->addr = (void *)sys_call_table[i];
+
+ ret = register_kprobe(p);
+ if (ret)
+ BUG();
+ j++;
+ }
+ }
+
+
+ printk(KERN_DEBUG "installed %i syscall probes\n", j);
+ return ret;
+}
+
+
+static int init_syscall_probes(void)
+{
+ /* kprobes */
+ install_syscall_enter_probe();
+ return 0;
+};
+
+static void exit_syscall_probes(void)
+{
+#if 0
+ unregister_kprobe(&syscall_enter_probe);
+ printk(KERN_DEBUG "syscall probe be gone!\n");
+#endif
+};
+
+
+module_init(init_syscall_probes);
+module_exit(exit_syscall_probes);
+
+MODULE_LICENSE("GPL");