aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/kprobes.c
diff options
context:
space:
mode:
authorSrinivasa Ds <srinivasa@in.ibm.com>2007-02-20 16:57:54 -0500
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-02-20 20:10:14 -0500
commit346fd59bab28093276be102632f72691a2c243fe (patch)
tree6d8c68c246e54b6ff96410873ae24aa3d70ebc2a /kernel/kprobes.c
parentffda9d302267dbb7fc9bc38f6e4c1b3d61a536a9 (diff)
[PATCH] kprobes: list all active probes in the system
This patch lists all active probes in the system by scanning through kprobe_table[]. It takes care of aggregate handlers and prints the type of the probe. Letter "k" for kprobes, "j" for jprobes, "r" for kretprobes. It also lists address of the instruction,its symbolic name(function name + offset) and the module name. One can access this file through /sys/kernel/debug/kprobes/list. Output looks like this ===================== llm40:~/a # cat /sys/kernel/debug/kprobes/list c0169ae3 r sys_read+0x0 c0169ae3 k sys_read+0x0 c01694c8 k vfs_write+0x0 c0167d20 r sys_open+0x0 f8e658a6 k reiserfs_delete_inode+0x0 reiserfs c0120f4a k do_fork+0x0 c0120f4a j do_fork+0x0 c0169b4a r sys_write+0x0 c0169b4a k sys_write+0x0 c0169622 r vfs_read+0x0 ================================= [akpm@linux-foundation.org: cleanup] [ananth@in.ibm.com: sparc build fix] Signed-off-by: Srinivasa DS <srinivasa@in.ibm.com> Cc: Prasanna S Panchamukhi <prasanna@in.ibm.com> Cc: Ananth N Mavinakayanahalli <ananth@in.ibm.com> Cc: Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com> Signed-off-by: Ananth N Mavinakayanahalli <ananth@in.ibm.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'kernel/kprobes.c')
-rw-r--r--kernel/kprobes.c113
1 files changed, 111 insertions, 2 deletions
diff --git a/kernel/kprobes.c b/kernel/kprobes.c
index 6fcf8dd148d0..d25a9ada3f8e 100644
--- a/kernel/kprobes.c
+++ b/kernel/kprobes.c
@@ -39,6 +39,8 @@
39#include <linux/moduleloader.h> 39#include <linux/moduleloader.h>
40#include <linux/kallsyms.h> 40#include <linux/kallsyms.h>
41#include <linux/freezer.h> 41#include <linux/freezer.h>
42#include <linux/seq_file.h>
43#include <linux/debugfs.h>
42#include <asm-generic/sections.h> 44#include <asm-generic/sections.h>
43#include <asm/cacheflush.h> 45#include <asm/cacheflush.h>
44#include <asm/errno.h> 46#include <asm/errno.h>
@@ -778,6 +780,12 @@ int __kprobes register_kretprobe(struct kretprobe *rp)
778 return -ENOSYS; 780 return -ENOSYS;
779} 781}
780 782
783static int __kprobes pre_handler_kretprobe(struct kprobe *p,
784 struct pt_regs *regs)
785{
786 return 0;
787}
788
781#endif /* ARCH_SUPPORTS_KRETPROBES */ 789#endif /* ARCH_SUPPORTS_KRETPROBES */
782 790
783void __kprobes unregister_kretprobe(struct kretprobe *rp) 791void __kprobes unregister_kretprobe(struct kretprobe *rp)
@@ -815,7 +823,109 @@ static int __init init_kprobes(void)
815 return err; 823 return err;
816} 824}
817 825
818__initcall(init_kprobes); 826#ifdef CONFIG_DEBUG_FS
827static void __kprobes report_probe(struct seq_file *pi, struct kprobe *p,
828 const char *sym, int offset,char *modname)
829{
830 char *kprobe_type;
831
832 if (p->pre_handler == pre_handler_kretprobe)
833 kprobe_type = "r";
834 else if (p->pre_handler == setjmp_pre_handler)
835 kprobe_type = "j";
836 else
837 kprobe_type = "k";
838 if (sym)
839 seq_printf(pi, "%p %s %s+0x%x %s\n", p->addr, kprobe_type,
840 sym, offset, (modname ? modname : " "));
841 else
842 seq_printf(pi, "%p %s %p\n", p->addr, kprobe_type, p->addr);
843}
844
845static void __kprobes *kprobe_seq_start(struct seq_file *f, loff_t *pos)
846{
847 return (*pos < KPROBE_TABLE_SIZE) ? pos : NULL;
848}
849
850static void __kprobes *kprobe_seq_next(struct seq_file *f, void *v, loff_t *pos)
851{
852 (*pos)++;
853 if (*pos >= KPROBE_TABLE_SIZE)
854 return NULL;
855 return pos;
856}
857
858static void __kprobes kprobe_seq_stop(struct seq_file *f, void *v)
859{
860 /* Nothing to do */
861}
862
863static int __kprobes show_kprobe_addr(struct seq_file *pi, void *v)
864{
865 struct hlist_head *head;
866 struct hlist_node *node;
867 struct kprobe *p, *kp;
868 const char *sym = NULL;
869 unsigned int i = *(loff_t *) v;
870 unsigned long size, offset = 0;
871 char *modname, namebuf[128];
872
873 head = &kprobe_table[i];
874 preempt_disable();
875 hlist_for_each_entry_rcu(p, node, head, hlist) {
876 sym = kallsyms_lookup((unsigned long)p->addr, &size,
877 &offset, &modname, namebuf);
878 if (p->pre_handler == aggr_pre_handler) {
879 list_for_each_entry_rcu(kp, &p->list, list)
880 report_probe(pi, kp, sym, offset, modname);
881 } else
882 report_probe(pi, p, sym, offset, modname);
883 }
884 preempt_enable();
885 return 0;
886}
887
888static struct seq_operations kprobes_seq_ops = {
889 .start = kprobe_seq_start,
890 .next = kprobe_seq_next,
891 .stop = kprobe_seq_stop,
892 .show = show_kprobe_addr
893};
894
895static int __kprobes kprobes_open(struct inode *inode, struct file *filp)
896{
897 return seq_open(filp, &kprobes_seq_ops);
898}
899
900static struct file_operations debugfs_kprobes_operations = {
901 .open = kprobes_open,
902 .read = seq_read,
903 .llseek = seq_lseek,
904 .release = seq_release,
905};
906
907static int __kprobes debugfs_kprobe_init(void)
908{
909 struct dentry *dir, *file;
910
911 dir = debugfs_create_dir("kprobes", NULL);
912 if (!dir)
913 return -ENOMEM;
914
915 file = debugfs_create_file("list", 0444, dir , 0 ,
916 &debugfs_kprobes_operations);
917 if (!file) {
918 debugfs_remove(dir);
919 return -ENOMEM;
920 }
921
922 return 0;
923}
924
925late_initcall(debugfs_kprobe_init);
926#endif /* CONFIG_DEBUG_FS */
927
928module_init(init_kprobes);
819 929
820EXPORT_SYMBOL_GPL(register_kprobe); 930EXPORT_SYMBOL_GPL(register_kprobe);
821EXPORT_SYMBOL_GPL(unregister_kprobe); 931EXPORT_SYMBOL_GPL(unregister_kprobe);
@@ -824,4 +934,3 @@ EXPORT_SYMBOL_GPL(unregister_jprobe);
824EXPORT_SYMBOL_GPL(jprobe_return); 934EXPORT_SYMBOL_GPL(jprobe_return);
825EXPORT_SYMBOL_GPL(register_kretprobe); 935EXPORT_SYMBOL_GPL(register_kretprobe);
826EXPORT_SYMBOL_GPL(unregister_kretprobe); 936EXPORT_SYMBOL_GPL(unregister_kretprobe);
827