[IMPROVE] create slot_manager
[kernel/swap-modules.git] / kprobe / arch / asm-arm / dbi_kprobes.c
index 4a46996..197bc1c 100644 (file)
@@ -162,7 +162,7 @@ int arch_check_insn_arm(struct arch_specific_insn *ainsn)
 }
 EXPORT_SYMBOL_GPL(arch_check_insn_arm);
 
-int arch_prepare_kprobe(struct kprobe *p)
+int arch_prepare_kprobe(struct kprobe *p, struct slot_manager *sm)
 {
        kprobe_opcode_t insns[KPROBES_TRAMP_LEN];
        int uregs, pc_dep, ret = 0;
@@ -170,7 +170,7 @@ int arch_prepare_kprobe(struct kprobe *p)
        struct arch_specific_insn ainsn;
 
        /* insn: must be on special executable page on i386. */
-       p->ainsn.insn = get_insn_slot(NULL, &kprobe_insn_pages, 0);
+       p->ainsn.insn = alloc_insn_slot(sm);
        if (!p->ainsn.insn)
                return -ENOMEM;
 
@@ -219,14 +219,14 @@ int arch_prepare_kprobe(struct kprobe *p)
 
                // check instructions that can write result to SP andu uses PC
                if (pc_dep  && (ARM_INSN_REG_RD(ainsn.insn[0]) == 13)) {
-                       free_insn_slot(&kprobe_insn_pages, NULL, p->ainsn.insn);
+                       free_insn_slot(sm, p->ainsn.insn);
                        ret = -EFAULT;
                } else {
                        if (uregs && pc_dep) {
                                memcpy(insns, pc_dep_insn_execbuf, sizeof(insns));
                                if (prep_pc_dep_insn_execbuf(insns, insn[0], uregs) != 0) {
                                        DBPRINTF ("failed to prepare exec buffer for insn %lx!", insn[0]);
-                                       free_insn_slot(&kprobe_insn_pages, NULL, p->ainsn.insn);
+                                       free_insn_slot(sm, p->ainsn.insn);
                                        return -EINVAL;
                                }
                                insns[6] = (kprobe_opcode_t)(p->addr + 2);
@@ -246,7 +246,7 @@ int arch_prepare_kprobe(struct kprobe *p)
 #endif
                }
        } else {
-               free_insn_slot(&kprobe_insn_pages, NULL, p->ainsn.insn);
+               free_insn_slot(sm, p->ainsn.insn);
                printk("arch_prepare_kprobe: instruction 0x%lx not instrumentation, addr=0x%p\n", insn[0], p->addr);
        }
 
@@ -415,8 +415,6 @@ int trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
        struct kretprobe *crp = NULL;
        struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
 
-       DBPRINTF ("start");
-
        spin_lock_irqsave(&kretprobe_lock, flags);
 
        /*
@@ -460,36 +458,13 @@ int trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
        }
        kretprobe_assert(ri, orig_ret_address, trampoline_address);
 
-       regs->uregs[14] = orig_ret_address;
-       DBPRINTF ("regs->uregs[14] = 0x%lx\n", regs->uregs[14]);
-       DBPRINTF ("regs->uregs[15] = 0x%lx\n", regs->uregs[15]);
+       regs->ARM_lr = orig_ret_address;
+       regs->ARM_pc = orig_ret_address;
 
-       if (trampoline_address != (unsigned long) &kretprobe_trampoline) {
-               regs->uregs[15] = orig_ret_address;
+       if (kcb->kprobe_status == KPROBE_REENTER) {
+               restore_previous_kprobe(kcb);
        } else {
-               if (!thumb_mode( regs )) {
-                       regs->uregs[15] += 4;
-               } else {
-                       regs->uregs[15] += 2;
-               }
-       }
-
-       DBPRINTF ("regs->uregs[15] = 0x%lx\n", regs->uregs[15]);
-
-       if(p) { // ARM, MIPS, X86 user space
-               if (thumb_mode(regs) && !(regs->uregs[14] & 0x01)) {
-                       regs->ARM_cpsr &= 0xFFFFFFDF;
-               } else {
-                       if (user_mode(regs) && (regs->uregs[14] & 0x01)) {
-                               regs->ARM_cpsr |= 0x20;
-                       }
-               }
-
-               if (kcb->kprobe_status == KPROBE_REENTER) {
-                       restore_previous_kprobe(kcb);
-               } else {
-                       reset_current_kprobe();
-               }
+               reset_current_kprobe();
        }
 
        spin_unlock_irqrestore(&kretprobe_lock, flags);
@@ -580,6 +555,7 @@ int arch_init_kprobes(void)
 
 void arch_exit_kprobes(void)
 {
+       dbi_unregister_kprobe(&trampoline_p, NULL);
        swap_unregister_undef_hook(&undef_ho_k);
 }