This is the mail archive of the systemtap@sources.redhat.com mailing list for the systemtap project.
Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
---|---|---|
Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |
Other format: | [Raw text] |
1) it does not return a negative code or void 2) high traffic
--- linux-2.6.10.acc/include/linux/kprobes.h 2005-03-10 16:06:45.611716998 -0800 +++ linux-2.6.10.works/include/linux/kprobes.h 2005-03-09 15:43:20.000000000 -0800 @@ -41,7 +41,7 @@ unsigned long flags); typedef int (*kprobe_fault_handler_t) (struct kprobe *, struct pt_regs *, int trapnr); -typedef int (*rprobe_handler_t) (struct kprobe *, struct pt_regs *); +typedef int (*rprobe_handler_t) (struct rprobe_instance *, struct pt_regs *); struct kprobe { struct hlist_node hlist; --- linux-2.6.10.acc/kernel/kprobes.c 2005-03-10 16:06:45.613716967 -0800 +++ linux-2.6.10.works/kernel/kprobes.c 2005-03-10 14:34:41.000000000 -0800 @@ -124,7 +124,7 @@ hlist_add_head(&ri->hlist, &rprobe_inst_table[hash_ptr(ri->stack_addr, RPROBE_HASH_BITS)]); } -int register_kprobe(struct kprobe *p) +int _register_kprobe(struct kprobe *p) { int ret = 0; unsigned long flags; @@ -151,10 +151,20 @@ return ret; } +int register_kprobe(struct kprobe *p) +{ + p->rp = NULL; + return _register_kprobe(p); +} + void unregister_kprobe(struct kprobe *p) { unsigned long flags; spin_lock_irqsave(&kprobe_lock, flags); + if (get_kprobe(p->addr) == NULL) { + spin_unlock_irqrestore(&kprobe_lock, flags); + return; + } arch_remove_kprobe(p); *p->addr = p->opcode; hlist_del(&p->hlist); @@ -162,11 +172,19 @@ (unsigned long) p->addr + sizeof(kprobe_opcode_t)); if (p->rp != NULL) { - /* Also clean up rprobe */ if (p->rp->num_ri_running != 0) { + int i; + struct rprobe *rp; + struct rprobe_instance *ri; /* Flag to tell the last running rprobe to clean up */ p->rp->unregistering = 1; - } else { + rp = kmalloc(sizeof(struct rprobe), GFP_KERNEL); + memcpy(rp, p->rp, sizeof(struct rprobe)); + for (i = 0 ; i < p->rp->maxactive; i++) { + ri = p->rp->instances + i; + ri->rp = rp; + } + } else { kfree(p->rp->instances); } } @@ -234,7 +252,7 @@ /* Establish function entry probe point */ /* todo: we need to deal with probe that has been registered */ - if((ret = register_kprobe(p)) != 0) { + if((ret = _register_kprobe(p)) != 0) { kfree(rp->instances); return ret; } --- linux-2.6.10.acc/arch/i386/kernel/kprobes.c 2005-03-10 16:06:45.633716665 -0800 +++ linux-2.6.10.works/arch/i386/kernel/kprobes.c 2005-03-10 15:41:34.000000000 -0800 @@ -196,8 +196,7 @@ return 0; } if (ri->rp && !ri->rp->unregistering) { - - return ri->rp->handler(p, regs); + return ri->rp->handler(ri, regs); } return 0; } @@ -271,7 +270,7 @@ * the unregister */ kfree(ri->rp->instances); - ri->rp->unregistering = 0; + kfree(ri->rp); } else { /* put ri obj back to free list */ list_add(&ri->list, &ri->rp->free_instances);
--- linux-2.6.10/include/linux/kprobes.h 2004-12-24 13:34:27.000000000 -0800 +++ linux-2.6.10.works/include/linux/kprobes.h 2005-03-09 15:43:20.000000000 -0800 @@ -34,12 +34,15 @@ struct kprobe; struct pt_regs; +struct rprobe_instance; typedef int (*kprobe_pre_handler_t) (struct kprobe *, struct pt_regs *); typedef int (*kprobe_break_handler_t) (struct kprobe *, struct pt_regs *); typedef void (*kprobe_post_handler_t) (struct kprobe *, struct pt_regs *, unsigned long flags); typedef int (*kprobe_fault_handler_t) (struct kprobe *, struct pt_regs *, int trapnr); +typedef int (*rprobe_handler_t) (struct rprobe_instance *, struct pt_regs *); + struct kprobe { struct hlist_node hlist; @@ -65,6 +68,9 @@ /* copy of the original instruction */ struct arch_specific_insn ainsn; + + /* point to rprobe */ + struct rprobe *rp; }; /* @@ -82,6 +88,26 @@ kprobe_opcode_t *entry; /* probe handling code to jump to */ }; +struct rprobe { + rprobe_handler_t handler; + kprobe_fault_handler_t fault_handler; + int maxactive; + int nmissed; + int num_ri_running; + int unregistering; + struct kprobe *kprobe; + struct rprobe_instance *instances; /* allocated memory */ + struct list_head free_instances; +}; + +struct rprobe_instance { + struct list_head list; + struct hlist_node hlist; + struct rprobe *rp; + void *ret_addr; + void *stack_addr; +}; + #ifdef CONFIG_KPROBES /* Locks kprobe: irq must be disabled */ void lock_kprobes(void); @@ -94,9 +120,12 @@ return kprobe_cpu == smp_processor_id(); } +asmlinkage void rprobe_trampoline(void) __asm__("rprobe_trampoline"); + extern int arch_prepare_kprobe(struct kprobe *p); extern void arch_remove_kprobe(struct kprobe *p); extern void show_registers(struct pt_regs *regs); +extern int trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs); /* Get the kprobe at this addr (if any). Must have called lock_kprobes */ struct kprobe *get_kprobe(void *addr); @@ -109,6 +138,15 @@ void unregister_jprobe(struct jprobe *p); void jprobe_return(void); +int register_erprobe(struct kprobe *p, struct rprobe *rp); +int register_jrprobe(struct jprobe *p, struct rprobe *rp); + +struct rprobe_instance *get_free_rinst(struct rprobe *rp); +struct rprobe_instance *get_rinst(void *sara); +void add_rprobe_inst_to_hash(struct rprobe_instance *ri); + +void test_erprobe(void); +int test_erprobe2(int a, int b, int c, char *str); #else static inline int kprobe_running(void) { @@ -131,5 +169,13 @@ static inline void jprobe_return(void) { } +static inline int register_erprobe(struct kprobe *p, struct rprobe *rp) +{ + return -ENOSYS; +} +static inline int register_jrprobe(struct jprobe *p, struct rprobe *rp) +{ + return -ENOSYS; +} #endif #endif /* _LINUX_KPROBES_H */ --- linux-2.6.10/kernel/kprobes.c 2004-12-24 13:35:59.000000000 -0800 +++ linux-2.6.10.works/kernel/kprobes.c 2005-03-10 14:34:41.000000000 -0800 @@ -42,6 +42,11 @@ static struct hlist_head kprobe_table[KPROBE_TABLE_SIZE]; +#define RPROBE_HASH_BITS KPROBE_HASH_BITS + +#define RPROBE_INST_TABLE_SIZE KPROBE_TABLE_SIZE +static struct hlist_head rprobe_inst_table[RPROBE_INST_TABLE_SIZE]; + unsigned int kprobe_cpu = NR_CPUS; static spinlock_t kprobe_lock = SPIN_LOCK_UNLOCKED; @@ -58,6 +63,24 @@ spin_unlock(&kprobe_lock); } +struct kprobe trampoline_p = { + .addr = (kprobe_opcode_t *) &rprobe_trampoline, + .pre_handler = trampoline_probe_handler, + .rp = NULL +}; + +static void init_rprobe(void) +{ + int i; + + /* Register a probe point at the rprobe trampoline */ + register_kprobe(&trampoline_p); + + /* Allocate rprobe instances table */ + for (i = 0; i < RPROBE_INST_TABLE_SIZE; i++) + INIT_HLIST_HEAD(&rprobe_inst_table[i]); +} + /* You have to be holding the kprobe_lock */ struct kprobe *get_kprobe(void *addr) { @@ -73,7 +96,35 @@ return NULL; } -int register_kprobe(struct kprobe *p) +struct rprobe_instance * get_free_rinst(struct rprobe *rp) +{ + if (list_empty(&rp->free_instances)) { + return NULL; + } + return (struct rprobe_instance *) rp->free_instances.next; +} + +struct rprobe_instance *get_rinst(void *sara) +{ + struct hlist_head *head; + struct hlist_node *node; + + head = &rprobe_inst_table[hash_ptr(sara, RPROBE_HASH_BITS)]; + hlist_for_each(node, head) { + struct rprobe_instance *ri = hlist_entry(node, + struct rprobe_instance, hlist); + if (ri->stack_addr == sara) + return ri; + } + return NULL; +} + +void add_rprobe_inst_to_hash(struct rprobe_instance *ri) +{ + hlist_add_head(&ri->hlist, &rprobe_inst_table[hash_ptr(ri->stack_addr, RPROBE_HASH_BITS)]); +} + +int _register_kprobe(struct kprobe *p) { int ret = 0; unsigned long flags; @@ -100,15 +151,43 @@ return ret; } +int register_kprobe(struct kprobe *p) +{ + p->rp = NULL; + return _register_kprobe(p); +} + void unregister_kprobe(struct kprobe *p) { unsigned long flags; spin_lock_irqsave(&kprobe_lock, flags); + if (get_kprobe(p->addr) == NULL) { + spin_unlock_irqrestore(&kprobe_lock, flags); + return; + } arch_remove_kprobe(p); *p->addr = p->opcode; hlist_del(&p->hlist); flush_icache_range((unsigned long) p->addr, (unsigned long) p->addr + sizeof(kprobe_opcode_t)); + + if (p->rp != NULL) { + if (p->rp->num_ri_running != 0) { + int i; + struct rprobe *rp; + struct rprobe_instance *ri; + /* Flag to tell the last running rprobe to clean up */ + p->rp->unregistering = 1; + rp = kmalloc(sizeof(struct rprobe), GFP_KERNEL); + memcpy(rp, p->rp, sizeof(struct rprobe)); + for (i = 0 ; i < p->rp->maxactive; i++) { + ri = p->rp->instances + i; + ri->rp = rp; + } + } else { + kfree(p->rp->instances); + } + } spin_unlock_irqrestore(&kprobe_lock, flags); } @@ -131,6 +210,79 @@ unregister_kprobe(&jp->kp); } +int register_erprobe(struct kprobe *p, struct rprobe *rp) +{ + int ret = 0; + static int rprobe_init_setup = 0; + struct rprobe_instance *inst; + int maxinst, i; + + if (rprobe_init_setup == 0) { + init_rprobe(); + rprobe_init_setup = 1; + } + /* Pre-allocate memory for max rprobe instances */ + if (rp->maxactive > 0) { + maxinst = rp->maxactive; + } else { +#ifdef CONFIG_PREEMPT + maxinst = max(10, 2 * NR_CPUS); +#else + maxinst = NR_CPUS; +#endif + } + rp->instances = kmalloc(maxinst * sizeof(struct rprobe_instance), + GFP_KERNEL); + if (rp->instances == NULL) { + return -ENOMEM; + } + + INIT_LIST_HEAD(&rp->free_instances); + /* Put all rprobe_instance object on the free list */ + for (i = 0; i < maxinst; i++) { + inst = rp->instances + i; + list_add(&inst->list, &rp->free_instances); + } + rp->num_ri_running = 0; + rp->nmissed = 0; + rp->unregistering = 0; + rp->kprobe = p; + p->rp = rp; + + /* Establish function entry probe point */ + /* todo: we need to deal with probe that has been registered */ + + if((ret = _register_kprobe(p)) != 0) { + kfree(rp->instances); + return ret; + } + return ret; +} + +int register_jrprobe(struct jprobe *jp, struct rprobe *rp) +{ + + jp->kp.pre_handler = setjmp_pre_handler; + jp->kp.break_handler = longjmp_break_handler; + + return register_erprobe(&jp->kp, rp); +} + +/* Just for testing - remove when done */ +void test_erprobe() +{ + int a,b,c; + a=15; + b=10; + c=20; + printk("test_erprobe invoked: a=%d, b=%d, c=%d.\n", a,b,c); +} +int test_erprobe2(int a, int b, int c, char *str) +{ + printk("test_erprobe2 invoked: a=%d, b=%d, c=%d, str=%s.\n", a,b,c, str); + return 1; +} + static int __init init_kprobes(void) { int i, err = 0; @@ -139,11 +291,12 @@ /* initialize all list heads */ for (i = 0; i < KPROBE_TABLE_SIZE; i++) INIT_HLIST_HEAD(&kprobe_table[i]); - + err = register_die_notifier(&kprobe_exceptions_nb); return err; } + __initcall(init_kprobes); EXPORT_SYMBOL_GPL(register_kprobe); @@ -151,3 +304,7 @@ EXPORT_SYMBOL_GPL(register_jprobe); EXPORT_SYMBOL_GPL(unregister_jprobe); EXPORT_SYMBOL_GPL(jprobe_return); +EXPORT_SYMBOL_GPL(register_erprobe); +EXPORT_SYMBOL_GPL(register_jrprobe); +EXPORT_SYMBOL_GPL(test_erprobe); +EXPORT_SYMBOL_GPL(test_erprobe2); --- linux-2.6.10/arch/i386/kernel/kprobes.c 2004-12-24 13:34:33.000000000 -0800 +++ linux-2.6.10.works/arch/i386/kernel/kprobes.c 2005-03-10 15:41:34.000000000 -0800 @@ -143,11 +143,38 @@ if (is_IF_modifier(p->opcode)) kprobe_saved_eflags &= ~IF_MASK; + if (p->rp != NULL) { + /* + * Get a rprobe instance off the free list and populate it + * with the return addr, stack addr, and rp. + */ + struct rprobe_instance *ri; + unsigned long *sara = (unsigned long *)®s->esp; + + if ((ri = get_free_rinst(p->rp)) != NULL) { + INIT_HLIST_NODE(&ri->hlist); + ri->rp = p->rp; + ri->stack_addr = sara; + ri->ret_addr = (void *) *sara; + /* Add probe instance in hash */ + add_rprobe_inst_to_hash(ri); + /* Replace the return addr with trampoline addr */ + *sara = (unsigned long) &rprobe_trampoline; + /* + * Remove obj in free list - + * will add it back when resume execution + */ + list_del(&ri->list); + p->rp->num_ri_running++; + } else { + p->rp->nmissed++; + } + } + if (p->pre_handler(p, regs)) { /* handler has already set things up, so skip ss setup */ return 1; } - ss_probe: prepare_singlestep(p, regs); kprobe_status = KPROBE_HIT_SS; @@ -157,6 +184,22 @@ preempt_enable_no_resched(); return ret; } +/* + * Called when we hit the probe point at rprobe_trampoline + */ +int trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) +{ + struct rprobe_instance *ri; + unsigned long *sara = (unsigned long *)(®s->esp - 1); + + if ((ri = get_rinst(sara)) == NULL) { + return 0; + } + if (ri->rp && !ri->rp->unregistering) { + return ri->rp->handler(ri, regs); + } + return 0; +} /* * Called after single-stepping. p->addr is the address of the @@ -210,6 +253,31 @@ case 0xea: /* jmp absolute -- eip is correct */ next_eip = regs->eip; break; + case 0x90: /* nop */ + /* Check to make sure this is from the trampoline probe */ + if (orig_eip == (unsigned long) rprobe_trampoline) { + struct rprobe_instance *ri; + unsigned long *sara = tos - 1; /* RA already popped */ + ri = get_rinst(sara); + if (ri != NULL) { + next_eip = (unsigned long)ri->ret_addr; + hlist_del(&ri->hlist); + ri->rp->num_ri_running--; + if (ri->rp->num_ri_running == 0 && + ri->rp->unregistering == 1) { + /* This is the last running ri during + * unregister, free memory to complete + * the unregister + */ + kfree(ri->rp->instances); + kfree(ri->rp); + } else { + /* put ri obj back to free list */ + list_add(&ri->list, &ri->rp->free_instances); + } + } + } + break; default: break; } --- linux-2.6.10/arch/i386/kernel/entry.S 2004-12-24 13:34:27.000000000 -0800 +++ linux-2.6.10.works/arch/i386/kernel/entry.S 2005-03-04 11:33:50.000000000 -0800 @@ -140,6 +140,12 @@ .previous +#ifdef CONFIG_KPROBES +ENTRY(rprobe_trampoline) + nop +/* NOT REACHED */ +#endif + ENTRY(ret_from_fork) pushl %eax call schedule_tail
#!/bin/sh KERNEl_SRC=/home/nguyhien/sandbox/dprobes/linux-2.6.10.works SYS_CALLS="sys_restart_syscall \ sys_exit \ -sys_fork \ sys_read \ sys_write \ -sys_open \ -sys_close \ sys_waitpid \ sys_creat \ sys_link \ sys_unlink \ -sys_execve \ sys_chdir \ -sys_time \ sys_mknod \ sys_chmod \ sys_lchown16 \ sys_stat \ sys_lseek \ -sys_getpid \ sys_mount \ sys_oldumount \ sys_setuid16 \ -sys_getuid16 \ sys_stime \ sys_ptrace \ -sys_alarm \ sys_fstat \ sys_pause \ -sys_utime \ sys_access \ sys_nice \ sys_sync \ sys_kill \ sys_rename \ sys_mkdir \ sys_rmdir \ sys_dup \ sys_pipe \ sys_times \ sys_brk \ sys_setgid16 \ -sys_getgid16 \ -sys_signal \ -sys_geteuid16 \ -sys_getegid16 \ sys_acct \ sys_umount \ sys_ioctl \ sys_fcntl \ sys_setpgid \ sys_olduname \ sys_umask \ sys_chroot \ sys_ustat \ sys_dup2 \ -sys_getppid \ -sys_getpgrp \ sys_setsid \ sys_sigaction \ sys_sgetmask \ sys_ssetmask \ sys_setreuid16 \ sys_setregid16 \ sys_sigsuspend \ sys_sigpending \ sys_sethostname \ sys_setrlimit \ sys_old_getrlimit \ sys_getrusage \ sys_gettimeofday \ sys_settimeofday \ sys_getgroups16 \ sys_setgroups16 \ old_select \ sys_symlink \ sys_lstat \ sys_readlink \ sys_uselib \ sys_swapon \ sys_reboot \ old_readdir \ -old_mmap \ sys_munmap \ sys_truncate \ sys_ftruncate \ sys_fchmod \ sys_fchown16 \ sys_getpriority \ sys_setpriority \ sys_statfs \ sys_fstatfs \ sys_ioperm \ sys_socketcall \ sys_syslog \ sys_setitimer \ sys_getitimer \ sys_newstat \ sys_newlstat \ sys_newfstat \ sys_uname \ sys_iopl \ sys_vhangup \ sys_vm86old \ sys_wait4 \ sys_swapoff \ sys_sysinfo \ sys_ipc \ sys_fsync \ -sys_sigreturn \ sys_clone \ sys_setdomainname \ sys_newuname \ sys_modify_ldt \ sys_adjtimex \ sys_mprotect \ sys_sigprocmask \ -sys_init_module \ -sys_delete_module \ sys_quotactl \ sys_getpgid \ sys_fchdir \ sys_bdflush \ sys_sysfs \ sys_personality \ sys_setfsuid16 \ sys_setfsgid16 \ sys_llseek \ sys_getdents \ -sys_select \ sys_flock \ sys_msync \ sys_readv \ sys_writev \ -sys_getsid \ sys_fdatasync \ sys_sysctl \ sys_mlock \ sys_munlock \ sys_mlockall \ sys_munlockall \ sys_sched_setparam \ sys_sched_getparam \ sys_sched_setscheduler \ sys_sched_getscheduler \ sys_sched_yield \ sys_sched_get_priority_max \ sys_sched_get_priority_min \ sys_sched_rr_get_interval \ sys_nanosleep \ sys_mremap \ sys_setresuid16 \ -sys_getresuid16 \ sys_vm86 \ sys_poll \ sys_nfsservctl \ sys_setresgid16 \ -sys_getresgid16 \ sys_prctl \ -sys_rt_sigreturn \ sys_rt_sigaction \ sys_rt_sigprocmask \ -sys_rt_sigpending \ -sys_rt_sigtimedwait \ sys_rt_sigqueueinfo \ -sys_rt_sigsuspend \ sys_pread64 \ sys_pwrite64 \ sys_chown16 \ sys_getcwd \ sys_capget \ sys_capset \ sys_sigaltstack \ sys_sendfile \ -sys_vfork \ sys_getrlimit \ -sys_mmap2 \ sys_truncate64 \ sys_ftruncate64 \ -sys_stat64 \ sys_lstat64 \ sys_fstat64 \ sys_lchown \ sys_getuid \ sys_getgid \ sys_geteuid \ sys_getegid \ sys_setreuid \ sys_setregid \ sys_getgroups \ sys_setgroups \ sys_fchown \ sys_setresuid \ sys_getresuid \ sys_setresgid \ sys_getresgid \ sys_chown \ sys_setuid \ sys_setgid \ sys_setfsuid \ sys_setfsgid \ sys_pivot_root \ sys_mincore \ sys_madvise \ sys_getdents64 \ sys_fcntl64 \ -sys_gettid \ sys_readahead \ sys_setxattr \ sys_lsetxattr \ sys_fsetxattr \ sys_getxattr \ sys_lgetxattr \ sys_fgetxattr \ sys_listxattr \ sys_llistxattr \ sys_flistxattr \ sys_removexattr \ sys_lremovexattr \ sys_fremovexattr \ sys_tkill \ sys_sendfile64 \ sys_futex \ sys_sched_setaffinity \ sys_sched_getaffinity \ sys_set_thread_area \ sys_get_thread_area \ sys_io_setup \ sys_io_destroy \ sys_io_getevents \ sys_io_submit \ sys_io_cancel \ sys_fadvise64 \ sys_exit_group \ sys_lookup_dcookie \ sys_epoll_create \ sys_epoll_ctl \ sys_epoll_wait \ sys_remap_file_pages \ sys_set_tid_address \ sys_timer_create \ sys_timer_settime \ sys_timer_gettime \ sys_timer_getoverrun \ sys_timer_delete \ sys_clock_settime \ sys_clock_gettime \ sys_clock_getres \ sys_clock_nanosleep \ sys_statfs64 \ sys_fstatfs64 \ sys_tgkill \ sys_utimes \ sys_fadvise64_64 \ -sys_mbind \ -sys_get_mempolicy \ -sys_set_mempolicy \ -sys_mq_open \ -sys_mq_unlink \ -sys_mq_timedsend \ -sys_mq_timedreceive \ -sys_mq_notify \ -sys_mq_getsetattr \ -sys_waitid \ -sys_add_key \ -sys_request_key \ -sys_keyctl" cp sys_rprobe.t sys_rprobe.c for sys_call in $SYS_CALLS; do sys_call_entry_addr=`cat /proc/kallsyms | grep " ${sys_call}$" | awk '{print $1}'` echo "${sys_call} : ${sys_call_entry_addr}" if [ "${sys_call_entry_addr}X" = "X" ]; then continue fi # echo $sys_call_entry_addr jprobe_init="\/\* ${sys_call} \*\/\n\t{\n\t.kp.addr = (kprobe_opcode_t *) 0x${sys_call_entry_addr},\n\t.entry = (kprobe_opcode_t *) inst_sys_call\n\t},\n\t\/\*<jprobe>\*\/" name_addr_init="{\n\t.name=\"${sys_call}\",\n\t.addr=0x${sys_call_entry_addr}\n\t},\n\t\/\*<nameaddr>\*\/" cat sys_rprobe.c | sed "s/\/\*<jprobe>\*\//${jprobe_init}/" | sed "s/\/\*<nameaddr>\*\//${name_addr_init}/" > tmp_rp1.tmp cp tmp_rp1.tmp sys_rprobe.c done echo "obj-m := sys_rprobe.o" > Makefile make -C $KERNEl_SRC M=`pwd` modules
Attachment:
sys_rprobe.t
Description: Troff document
Attachment:
loadtestrprobe.sh
Description: Bourne shell script
#include <linux/module.h> #include <linux/kprobes.h> static unsigned long entryaddr; module_param(entryaddr, ulong, 0); MODULE_PARM_DESC(addr, "\nfunction entry address.\n"); int inst_test_erprobe2 (void) { printk("test_eprobe2 entry handler\n"); jprobe_return(); return 0; } int rp_handler(struct rprobe_instance *ri, struct pt_regs *regs) { printk("rprobe handler: p->addr=0x%p\n", ri->rp->kprobe->addr); printk("return code is stored in eax=0x%lx\n", regs->eax); return 0; } static struct jprobe jp = { .entry = (kprobe_opcode_t *) inst_test_erprobe2, }; static struct rprobe rp = { .handler = rp_handler, .maxactive = 1, .nmissed = 0 }; static int init_testrp(void) { if (entryaddr == 0 ) { printk("Need to input an function entry address as parameter.\n"); return -EINVAL; } jp.kp.addr = (kprobe_opcode_t *) entryaddr; register_jrprobe(&jp, &rp); printk("exit probe init: instrumentation is enabled...\n"); return 0; } static void cleanup_testrp(void) { unregister_jprobe(&jp); printk("exit probe cleanup.\n"); } module_init(init_testrp); module_exit(cleanup_testrp); MODULE_LICENSE("GPL");
Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
---|---|---|
Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |