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] |