[IMPROVE] handling '__switch_to' retprobe
authorVyacheslav Cherkashin <v.cherkashin@samsung.com>
Fri, 16 Aug 2013 17:55:03 +0000 (21:55 +0400)
committerVyacheslav Cherkashin <v.cherkashin@samsung.com>
Fri, 16 Aug 2013 17:55:03 +0000 (21:55 +0400)
kprobe/arch/asm-arm/dbi_kprobes.c
kprobe/arch/asm-arm/dbi_kprobes.h
kprobe/arch/asm-x86/dbi_kprobes.c
kprobe/arch/asm-x86/dbi_kprobes.h
kprobe/dbi_kprobes.c
kprobe/dbi_kprobes.h

index 399df62..df16592 100644 (file)
@@ -357,11 +357,6 @@ int setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
        entry_point_t entry = (entry_point_t)jp->entry;
        pre_entry = (kprobe_pre_entry_handler_t)jp->pre_entry;
 
-       if (((unsigned long)p->addr == sched_addr) && sched_rp) {
-               struct thread_info *tinfo = (struct thread_info *)regs->ARM_r2;
-               patch_suspended_task(sched_rp, tinfo->task, regs);
-       }
-
        if (pre_entry) {
                p->ss_addr = (void *)pre_entry (jp->priv_arg, regs);
        }
@@ -413,11 +408,25 @@ void __naked kretprobe_trampoline(void)
 
 void arch_prepare_kretprobe(struct kretprobe_instance *ri, struct pt_regs *regs)
 {
-       ri->ret_addr = (kprobe_opcode_t *)regs->ARM_lr;
-       ri->sp = (kprobe_opcode_t *)regs->ARM_sp;
+       unsigned long *ptr_ret_addr;
+
+       /* for __switch_to probe */
+       if ((unsigned long)ri->rp->kp.addr == sched_addr) {
+               struct thread_info *tinfo = (struct thread_info *)regs->ARM_r2;
+
+               ptr_ret_addr = (unsigned long *)&tinfo->cpu_context.pc;
+               ri->sp = NULL;
+               ri->task = tinfo->task;
+       } else {
+               ptr_ret_addr = (unsigned long *)&regs->ARM_lr;
+               ri->sp = (unsigned long *)regs->ARM_sp;
+       }
+
+       /* Save the return address */
+       ri->ret_addr = (unsigned long *)*ptr_ret_addr;
 
        /* Replace the return addr with trampoline addr */
-       regs->ARM_lr = (unsigned long)&kretprobe_trampoline;
+       *ptr_ret_addr = (unsigned long)&kretprobe_trampoline;
 }
 
 void swap_register_undef_hook(struct undef_hook *hook)
index 013e85f..b22f728 100644 (file)
@@ -68,12 +68,6 @@ struct prev_kprobe {
        unsigned long status;
 };
 
-static inline unsigned long *arch_get_patch_addr(struct task_struct *p,
-                                                struct pt_regs *regs)
-{
-       return &task_thread_info(p)->cpu_context.pc;
-}
-
 static inline unsigned long arch_get_task_pc(struct task_struct *p)
 {
        return task_thread_info(p)->cpu_context.pc;
index 2353ff9..5993561 100644 (file)
@@ -521,12 +521,6 @@ int setjmp_pre_handler (struct kprobe *p, struct pt_regs *regs)
        pre_entry = (kprobe_pre_entry_handler_t) jp->pre_entry;
        entry = (entry_point_t) jp->entry;
 
-       /* handle __switch_to probe */
-       if ((p->addr == sched_addr) && sched_rp) {
-               /* FIXME: Actually 2nd parameter is not used for x86 */
-               patch_suspended_task(sched_rp, (struct task_struct *)regs->dx, regs);
-       }
-
        kcb->jprobe_saved_regs = *regs;
        kcb->jprobe_saved_esp = &regs->EREG(sp);
        addr = (unsigned long)(kcb->jprobe_saved_esp);
@@ -867,12 +861,23 @@ static __used void *trampoline_probe_handler_x86(struct pt_regs *regs)
 
 void arch_prepare_kretprobe(struct kretprobe_instance *ri, struct pt_regs *regs)
 {
-       unsigned long *sara = (unsigned long *)&regs->EREG(sp);
-       ri->ret_addr = (kprobe_opcode_t *)*sara;
-       ri->sp = &regs->EREG(sp);
+       unsigned long *ptr_ret_addr;
+
+       /* for __switch_to probe */
+       if ((unsigned long)ri->rp->kp.addr == sched_addr) {
+               ptr_ret_addr = (unsigned long *)kernel_stack_pointer(regs);
+               ri->sp = NULL;
+               ri->task = (struct task_struct *)regs->dx;
+       } else {
+               ptr_ret_addr = (unsigned long *)&regs->sp;
+               ri->sp = &regs->sp;
+       }
+
+       /* Save the return address */
+       ri->ret_addr = (unsigned long *)*ptr_ret_addr;
 
        /* Replace the return addr with trampoline addr */
-       *sara = (unsigned long)&kretprobe_trampoline;
+       *ptr_ret_addr = (unsigned long)&kretprobe_trampoline;
 }
 
 int arch_init_module_deps()
index 52c7f84..8463020 100644 (file)
@@ -91,12 +91,6 @@ typedef u8 kprobe_opcode_t;
 #define KPROBES_TRAMP_LEN              MAX_INSN_SIZE
 #define KPROBES_TRAMP_INSN_IDX          0
 
-static inline unsigned long *arch_get_patch_addr(struct task_struct *p,
-                                                struct pt_regs *regs)
-{
-       return (unsigned long *)kernel_stack_pointer(regs);
-}
-
 static inline unsigned long arch_get_task_pc(struct task_struct *p)
 {
        /* FIXME: Not implemented yet */
index e078166..3fa8499 100644 (file)
@@ -723,8 +723,6 @@ int trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
        return (int)orig_ret_address;
 }
 
-struct kretprobe *sched_rp;
-
 #define SCHED_RP_NR 200
 #define COMMON_RP_NR 10
 
@@ -775,10 +773,7 @@ int dbi_register_kretprobe(struct kretprobe *rp)
        rp->kp.break_handler = NULL;
 
        /* Pre-allocate memory for max kretprobe instances */
-       if ((unsigned long)rp->kp.addr == sched_addr) {
-               rp->maxactive = SCHED_RP_NR;//max (100, 2 * NR_CPUS);
-               rp->kp.pre_handler = NULL; //not needed for __switch_to
-       } else if ((unsigned long)rp->kp.addr == exit_addr) {
+       if ((unsigned long)rp->kp.addr == exit_addr) {
                rp->kp.pre_handler = NULL; //not needed for do_exit
                rp->maxactive = 0;
        } else if ((unsigned long)rp->kp.addr == do_group_exit_addr) {
@@ -816,9 +811,6 @@ int dbi_register_kretprobe(struct kretprobe *rp)
                free_rp_inst(rp);
 
        DBPRINTF ("addr=%p, *addr=[%lx %lx %lx]", rp->kp.addr, (unsigned long) (*(rp->kp.addr)), (unsigned long) (*(rp->kp.addr + 1)), (unsigned long) (*(rp->kp.addr + 2)));
-       if ((unsigned long)rp->kp.addr == sched_addr) {
-               sched_rp = rp;
-       }
 
        return ret;
 }
@@ -835,9 +827,6 @@ void dbi_unregister_kretprobe(struct kretprobe *rp)
        /* No race here */
        spin_lock_irqsave(&kretprobe_lock, flags);
 
-       if ((unsigned long)rp->kp.addr == sched_addr)
-               sched_rp = NULL;
-
        while ((ri = get_used_rp_inst (rp)) != NULL) {
                if (!dbi_disarm_krp_inst(ri)) {
                        printk("%s (%d/%d): cannot disarm krp instance (%08lx)\n",
@@ -881,20 +870,6 @@ struct kretprobe *clone_kretprobe(struct kretprobe *rp)
 }
 EXPORT_SYMBOL_GPL(clone_kretprobe);
 
-static void inline set_task_trampoline(unsigned long *patch_addr,
-                                      struct kretprobe_instance *ri,
-                                      unsigned long tramp_addr)
-{
-       unsigned long pc = *patch_addr;
-       if (pc == tramp_addr)
-               panic("[%d] %s (%d/%d): pc = %08lx --- [%d] %s (%d/%d)\n",
-                     task_cpu(ri->task), ri->task->comm, ri->task->tgid,
-                     ri->task->pid, pc, task_cpu(current), current->comm,
-                     current->tgid, current->pid);
-       ri->ret_addr = (kprobe_opcode_t *)pc;
-       *patch_addr = tramp_addr;
-}
-
 static void inline rm_task_trampoline(struct task_struct *p, struct kretprobe_instance *ri)
 {
        arch_set_task_pc(p, (unsigned long)ri->ret_addr);
@@ -952,32 +927,6 @@ static int dbi_disarm_krp_inst(struct kretprobe_instance *ri)
        return retval;
 }
 
-int patch_suspended_task(struct kretprobe *rp,
-                        struct task_struct *task,
-                        struct pt_regs *regs)
-{
-       struct kretprobe_instance *ri;
-       unsigned long flags;
-       kprobe_opcode_t *tramp = (kprobe_opcode_t *)&kretprobe_trampoline;
-       unsigned long *patch_addr;
-
-       spin_lock_irqsave(&kretprobe_lock, flags);
-
-       ri = get_free_rp_inst(rp);
-       if (!ri)
-               return -ENOMEM;
-
-       ri->rp = rp;
-       ri->task = task;
-       ri->sp = NULL;
-       patch_addr = arch_get_patch_addr(task, regs);
-       set_task_trampoline(patch_addr, ri, (unsigned long)tramp);
-       add_rp_inst(ri);
-
-       spin_unlock_irqrestore(&kretprobe_lock, flags);
-       return 0;
-}
-
 static int init_module_deps(void)
 {
        int ret;
index 460375a..7622740 100644 (file)
@@ -284,7 +284,6 @@ extern spinlock_t kretprobe_lock;
 extern struct hlist_head kprobe_table[KPROBE_TABLE_SIZE];
 //extern struct hlist_head kretprobe_inst_table[KPROBE_TABLE_SIZE];
 extern atomic_t kprobe_count;
-extern struct kretprobe *sched_rp;
 extern unsigned long sched_addr;
 
 struct kprobe *kprobe_running (void);
@@ -292,9 +291,6 @@ void reset_current_kprobe (void);
 struct kprobe_ctlblk *get_kprobe_ctlblk (void);
 
 void prepare_singlestep(struct kprobe *p, struct pt_regs *regs);
-int patch_suspended_task(struct kretprobe *rp,
-                        struct task_struct *task,
-                        struct pt_regs *regs);
 
 #endif /* _DBI_KPROBES_H */