Merge branch 'dev' of 106.109.8.71:/srv/git/dbi into new_dpf
[kernel/swap-modules.git] / kprobe / arch / asm-arm / dbi_kprobes.c
index b30ac1b..99fc4bc 100644 (file)
@@ -53,8 +53,8 @@
 
 #define SUPRESS_BUG_MESSAGES
 
-extern unsigned int *sched_addr;
-extern unsigned int *fork_addr;
+extern unsigned long sched_addr;
+extern unsigned long fork_addr;
 
 extern struct kprobe * per_cpu__current_kprobe;
 extern spinlock_t kretprobe_lock;
@@ -65,9 +65,9 @@ extern struct hlist_head uprobe_insn_pages;
 
 extern unsigned long (*kallsyms_search) (const char *name);
 
-extern struct kprobe *kprobe_running (void);
-extern struct kprobe_ctlblk *get_kprobe_ctlblk (void);
-extern void reset_current_kprobe (void);
+extern struct kprobe *kprobe_running(void);
+extern void reset_current_kprobe(void);
+extern struct kprobe_ctlblk *get_kprobe_ctlblk(void);
 extern struct kprobe * current_kprobe;
 
 extern struct hlist_head kprobe_table[KPROBE_TABLE_SIZE];
@@ -82,7 +82,7 @@ EXPORT_SYMBOL_GPL (swap_sum_hit);
 #define sign_extend(x, signbit) ((x) | (0 - ((x) & (1 << (signbit)))))
 #define branch_displacement(insn) sign_extend(((insn) & 0xffffff) << 2, 25)
 
-static kprobe_opcode_t get_addr_b(kprobe_opcode_t insn, kprobe_opcode_t addr)
+static kprobe_opcode_t get_addr_b(kprobe_opcode_t insn, kprobe_opcode_t *addr)
 {
        // real position less then PC by 8
        return (kprobe_opcode_t)((long)addr + 8 + branch_displacement(insn));
@@ -373,13 +373,13 @@ int prep_pc_dep_insn_execbuf_thumb (kprobe_opcode_t * insns, kprobe_opcode_t ins
        }
 
 //      STRx PC, xxx
-       if ((reg == 15) && THUMB2_INSN_MATCH (STRW, insn)   || \
-                          THUMB2_INSN_MATCH (STRBW, insn)  || \
-                          THUMB2_INSN_MATCH (STRD, insn)   || \
-                          THUMB2_INSN_MATCH (STRHT, insn)  || \
-                          THUMB2_INSN_MATCH (STRT, insn)   || \
-                          THUMB2_INSN_MATCH (STRHW1, insn) || \
-                          THUMB2_INSN_MATCH (STRHW, insn) )
+       if ((reg == 15) && (THUMB2_INSN_MATCH (STRW, insn)   || \
+                           THUMB2_INSN_MATCH (STRBW, insn)  || \
+                           THUMB2_INSN_MATCH (STRD, insn)   || \
+                           THUMB2_INSN_MATCH (STRHT, insn)  || \
+                           THUMB2_INSN_MATCH (STRT, insn)   || \
+                           THUMB2_INSN_MATCH (STRHW1, insn) || \
+                           THUMB2_INSN_MATCH (STRHW, insn) ))
        {
                insns[2] = (insns[2] & 0x0fffffff) | 0xd0000000;
        }
@@ -407,7 +407,6 @@ int prep_pc_dep_insn_execbuf_thumb (kprobe_opcode_t * insns, kprobe_opcode_t ins
 int arch_check_insn_arm (struct arch_specific_insn *ainsn)
 {
        int ret = 0;
-       kprobe_opcode_t *insn;
 
        // check instructions that can change PC by nature
        if (
@@ -461,6 +460,7 @@ int arch_check_insn_thumb (struct arch_specific_insn *ainsn)
                THUMB2_INSN_MATCH (BL, ainsn->insn_thumb[0]) ||
                THUMB_INSN_MATCH (B1, ainsn->insn_thumb[0]) ||
                THUMB_INSN_MATCH (B2, ainsn->insn_thumb[0]) ||
+               THUMB_INSN_MATCH (CBZ, ainsn->insn_thumb[0]) ||
                THUMB2_INSN_MATCH (B1, ainsn->insn_thumb[0]) ||
                THUMB2_INSN_MATCH (B2, ainsn->insn_thumb[0]) ||
                THUMB2_INSN_MATCH (BLX1, ainsn->insn_thumb[0]) ||
@@ -526,7 +526,6 @@ int arch_prepare_kprobe (struct kprobe *p)
     if (!ret)
     {
         p->opcode = *p->addr;
-        p->ainsn.boostable = 1;
         uregs = pc_dep = 0;
 
         // Rn, Rm ,Rd
@@ -550,7 +549,7 @@ int arch_prepare_kprobe (struct kprobe *p)
                         (ARM_INSN_REG_RD (insn[0]) == 15)))
             {
                 pc_dep = 1;
-                DBPRINTF ("Unboostable insn %lx/%p/%d, DPI/LIO/SIO\n", insn[0], p, p->ainsn.boostable);
+                DBPRINTF ("Unboostable insn %lx/%p, DPI/LIO/SIO\n", insn[0], p);
             }
         }
         // Rn, Rm, Rs
@@ -577,7 +576,7 @@ 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, 0);
+            free_insn_slot(&kprobe_insn_pages, NULL, p->ainsn.insn);
             ret = -EFAULT;
         }
         else
@@ -588,7 +587,7 @@ int arch_prepare_kprobe (struct kprobe *p)
                 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, 0);
+                    free_insn_slot(&kprobe_insn_pages, NULL, p->ainsn.insn);
                     return -EINVAL;
                 }
                 insns[6] = (kprobe_opcode_t) (p->addr + 2);
@@ -604,7 +603,7 @@ int arch_prepare_kprobe (struct kprobe *p)
                     p->ainsn.insn, insns[0], insns[1], insns[2], insns[3], insns[4],
                     insns[5], insns[6], insns[7], insns[8]);
             memcpy (p->ainsn.insn, insns, sizeof(insns));
-            flush_icache_range(p->ainsn.insn, p->ainsn.insn + sizeof(insns));
+            flush_icache_range((long unsigned)p->ainsn.insn, (long unsigned)(p->ainsn.insn) + sizeof(insns));
 #ifdef BOARD_tegra
             flush_cache_all();
 #endif
@@ -612,8 +611,8 @@ int arch_prepare_kprobe (struct kprobe *p)
     }
     else
     {
-        free_insn_slot (&kprobe_insn_pages, NULL, p->ainsn.insn, 0);
-        printk("arch_prepare_kprobe: instruction 0x%x not instrumentation, addr=0x%p\n", insn[0], p->addr);
+        free_insn_slot(&kprobe_insn_pages, NULL, p->ainsn.insn);
+        printk("arch_prepare_kprobe: instruction 0x%lx not instrumentation, addr=0x%p\n", insn[0], p->addr);
     }
 
     return ret;
@@ -652,7 +651,7 @@ int arch_prepare_uprobe (struct kprobe *p, struct task_struct *task, int atomic)
                return -EINVAL;
        }
        if (!read_proc_vm_atomic (task, (unsigned long) p->addr, &insn, MAX_INSN_SIZE * sizeof(kprobe_opcode_t)))
-               panic ("Failed to read memory %p!\n", p->addr);
+               panic ("Failed to read memory task[tgid=%u, comm=%s] %p!\n", task->tgid, task->comm, p->addr);
        p->opcode = insn[0];
        p->ainsn.insn_arm = get_insn_slot(task, atomic);
        if (!p->ainsn.insn_arm) {
@@ -661,7 +660,7 @@ int arch_prepare_uprobe (struct kprobe *p, struct task_struct *task, int atomic)
        }
        ret = arch_copy_trampoline_arm_uprobe(p, task, 1);
        if (ret) {
-               free_insn_slot (&uprobe_insn_pages, task, p->ainsn.insn_arm, 0);
+               free_insn_slot(&uprobe_insn_pages, task, p->ainsn.insn_arm);
                return -EFAULT;
        }
        p->ainsn.insn_thumb = get_insn_slot(task, atomic);
@@ -671,19 +670,19 @@ int arch_prepare_uprobe (struct kprobe *p, struct task_struct *task, int atomic)
        }
        ret = arch_copy_trampoline_thumb_uprobe(p, task, 1);
        if (ret) {
-               free_insn_slot (&uprobe_insn_pages, task, p->ainsn.insn_arm, 0);
-               free_insn_slot (&uprobe_insn_pages, task, p->ainsn.insn_thumb, 0);
+               free_insn_slot(&uprobe_insn_pages, task, p->ainsn.insn_arm);
+               free_insn_slot(&uprobe_insn_pages, task, p->ainsn.insn_thumb);
                return -EFAULT;
        }
        if ((p->safe_arm == -1) && (p->safe_thumb == -1)) {
-               printk("Error in %s at %d: failed arch_copy_trampoline_*_uprobe() (both)\n", __FILE__, __LINE__);
+               printk("Error in %s at %d: failed arch_copy_trampoline_*_uprobe() (both) [tgid=%u, addr=%x, data=%x]\n",
+                               __FILE__, __LINE__, task->tgid, p->addr, p->opcode);
                if (!write_proc_vm_atomic (task, (unsigned long) p->addr, &p->opcode, sizeof (p->opcode)))
                        panic ("Failed to write memory %p!\n", p->addr);
-               free_insn_slot (&uprobe_insn_pages, task, p->ainsn.insn_arm, 0);
-               free_insn_slot (&uprobe_insn_pages, task, p->ainsn.insn_thumb, 0);
+               free_insn_slot(&uprobe_insn_pages, task, p->ainsn.insn_arm);
+               free_insn_slot(&uprobe_insn_pages, task, p->ainsn.insn_thumb);
                return -EFAULT;
        }
-       p->ainsn.boostable = 1;
        return ret;
 }
 
@@ -695,27 +694,29 @@ int arch_prepare_uretprobe (struct kretprobe *p, struct task_struct *task)
 
 void prepare_singlestep (struct kprobe *p, struct pt_regs *regs)
 {
-       if(p->ss_addr)
-       {
-               regs->uregs[15] = (unsigned long) p->ss_addr;
+       if (p->ss_addr) {
+               regs->ARM_pc = (unsigned long)p->ss_addr;
                p->ss_addr = NULL;
+       } else {
+               regs->ARM_pc = (unsigned long)p->ainsn.insn;
        }
-       else
-               regs->uregs[15] = (unsigned long) p->ainsn.insn;
 }
 
-void save_previous_kprobe (struct kprobe_ctlblk *kcb, struct kprobe *cur_p)
+void save_previous_kprobe(struct kprobe_ctlblk *kcb, struct kprobe *p_run)
 {
-       if (kcb->prev_kprobe.kp != NULL)
-       {
+       if (p_run == NULL) {
+               panic("arm_save_previous_kprobe: p_run == NULL\n");
+       }
+
+       if (kcb->prev_kprobe.kp != NULL) {
                DBPRINTF ("no space to save new probe[]: task = %d/%s", current->pid, current->comm);
        }
 
-       kcb->prev_kprobe.kp = kprobe_running ();
+       kcb->prev_kprobe.kp = p_run;
        kcb->prev_kprobe.status = kcb->kprobe_status;
 }
 
-void restore_previous_kprobe (struct kprobe_ctlblk *kcb)
+void restore_previous_kprobe(struct kprobe_ctlblk *kcb)
 {
        set_current_kprobe(kcb->prev_kprobe.kp, NULL, NULL);
        kcb->kprobe_status = kcb->prev_kprobe.status;
@@ -723,9 +724,9 @@ void restore_previous_kprobe (struct kprobe_ctlblk *kcb)
        kcb->prev_kprobe.status = 0;
 }
 
-void set_current_kprobe (struct kprobe *p, struct pt_regs *regs, struct kprobe_ctlblk *kcb)
+void set_current_kprobe(struct kprobe *p, struct pt_regs *regs, struct kprobe_ctlblk *kcb)
 {
-       __get_cpu_var (current_kprobe) = p;
+       __get_cpu_var(current_kprobe) = p;
        DBPRINTF ("set_current_kprobe: p=%p addr=%p\n", p, p->addr);
 }
 
@@ -770,7 +771,7 @@ int arch_copy_trampoline_arm_uprobe (struct kprobe *p, struct task_struct *task,
                                (ARM_INSN_REG_RD (insn[0]) == 15)))
                {
                        pc_dep = 1;
-                       DBPRINTF ("Unboostable insn %lx/%p/%d, DPI/LIO/SIO\n", insn[0], p, p->ainsn.boostable);
+                       DBPRINTF ("Unboostable insn %lx/%p, DPI/LIO/SIO\n", insn[0], p);
                }
        }
        // Rn, Rm, Rs
@@ -809,7 +810,7 @@ int arch_copy_trampoline_arm_uprobe (struct kprobe *p, struct task_struct *task,
                if (prep_pc_dep_insn_execbuf (insns, insn[0], uregs) != 0)
                {
                        printk("Error in %s at %d: failed to prepare exec buffer for insn %lx!",
-                               insn[0], __FILE__, __LINE__);
+                               __FILE__, __LINE__, insn[0]);
                        p->safe_arm = -1;
                        // TODO: move free to later phase
                        //free_insn_slot (&uprobe_insn_pages, task, p->ainsn.insn_arm, 0);
@@ -915,7 +916,7 @@ int arch_copy_trampoline_thumb_uprobe (struct kprobe *p, struct task_struct *tas
                uregs = 0xf000; // Rd 12-15
                pc_dep = 1;
        }
-       else if (THUMB2_INSN_MATCH (STRD, insn[0]) && (THUMB2_INSN_REG_RN(insn[0] == 15) || THUMB2_INSN_REG_RT(insn[0] == 15) || THUMB2_INSN_REG_RT2(insn[0]) == 15))
+       else if (THUMB2_INSN_MATCH(STRD, insn[0]) && ((THUMB2_INSN_REG_RN(insn[0]) == 15) || (THUMB2_INSN_REG_RT(insn[0]) == 15) || THUMB2_INSN_REG_RT2(insn[0]) == 15))
        {
                uregs = 0xff00;         // Rt 12-15, Rt2 8-11
                pc_dep = 1;
@@ -957,7 +958,7 @@ int arch_copy_trampoline_thumb_uprobe (struct kprobe *p, struct task_struct *tas
                if (prep_pc_dep_insn_execbuf_thumb (insns, insn[0], uregs) != 0)
                {
                        printk("Error in %s at %d: failed to prepare exec buffer for insn %lx!",
-                               insn[0], __FILE__, __LINE__);
+                               __FILE__, __LINE__, insn[0]);
                        p->safe_thumb = -1;
                        //free_insn_slot (&uprobe_insn_pages, task, p->ainsn.insn_thumb, 0);
                        //return -EINVAL;
@@ -969,12 +970,12 @@ int arch_copy_trampoline_thumb_uprobe (struct kprobe *p, struct task_struct *tas
                if (!isThumb2(insn[0]))
                {
                        addr = ((unsigned int)p->addr) + 2;
-                       *((unsigned short*)insns + 16) = addr & 0x0000ffff | 0x1;
+                       *((unsigned short*)insns + 16) = (addr & 0x0000ffff) | 0x1;
                        *((unsigned short*)insns + 17) = addr >> 16;
                }
                else {
                        addr = ((unsigned int)p->addr) + 4;
-                       *((unsigned short*)insns + 16) = addr & 0x0000ffff | 0x1;
+                       *((unsigned short*)insns + 16) = (addr & 0x0000ffff) | 0x1;
                        *((unsigned short*)insns + 17) = addr >> 16;
                }
        }
@@ -985,13 +986,13 @@ int arch_copy_trampoline_thumb_uprobe (struct kprobe *p, struct task_struct *tas
                {
                        addr = ((unsigned int)p->addr) + 2;
                        *((unsigned short*)insns + 2) = insn[0];
-                       *((unsigned short*)insns + 16) = addr & 0x0000ffff | 0x1;
+                       *((unsigned short*)insns + 16) = (addr & 0x0000ffff) | 0x1;
                        *((unsigned short*)insns + 17) = addr >> 16;
                }
                else {
                        addr = ((unsigned int)p->addr) + 4;
                        insns[1] = insn[0];
-                       *((unsigned short*)insns + 16) = addr & 0x0000ffff | 0x1;
+                       *((unsigned short*)insns + 16) = (addr & 0x0000ffff) | 0x1;
                        *((unsigned short*)insns + 17) = addr >> 16;
                }
        }
@@ -1005,146 +1006,121 @@ int arch_copy_trampoline_thumb_uprobe (struct kprobe *p, struct task_struct *tas
        return 0;
 }
 
+static int check_validity_insn(struct kprobe *p, struct pt_regs *regs, struct task_struct *task)
+{
+       struct kprobe *kp;
+
+       if (unlikely(thumb_mode(regs))) {
+               if (p->safe_thumb != -1) {
+                       p->ainsn.insn = p->ainsn.insn_thumb;
+                       list_for_each_entry_rcu(kp, &p->list, list) {
+                               kp->ainsn.insn = p->ainsn.insn_thumb;
+                       }
+               } else {
+                       printk("Error in %s at %d: we are in thumb mode (!) and check instruction was fail \
+                               (%0lX instruction at %p address)!\n", __FILE__, __LINE__, p->opcode, p->addr);
+                       // Test case when we do our actions on already running application
+                       arch_disarm_uprobe(p, task);
+                       return -1;
+               }
+       } else {
+               if (p->safe_arm != -1) {
+                       p->ainsn.insn = p->ainsn.insn_arm;
+                       list_for_each_entry_rcu(kp, &p->list, list) {
+                               kp->ainsn.insn = p->ainsn.insn_arm;
+                       }
+               } else {
+                       printk("Error in %s at %d: we are in arm mode (!) and check instruction was fail \
+                               (%0lX instruction at %p address)!\n", __FILE__, __LINE__, p->opcode, p->addr);
+                       // Test case when we do our actions on already running application
+                       arch_disarm_uprobe(p, task);
+                       return -1;
+               }
+       }
+
+       return 0;
+}
+
+static int kprobe_trap_handler(struct pt_regs *regs, unsigned int instr)
+{
+       int ret;
+        unsigned long flags;
+        local_irq_save(flags);
+        ret = kprobe_handler(regs);
+        local_irq_restore(flags);
+        return ret;
+}
 
-int kprobe_handler (struct pt_regs *regs)
+int kprobe_handler(struct pt_regs *regs)
 {
-       struct kprobe *p = 0;
-       int ret = 0, pid = 0, retprobe = 0, reenter = 0;
-       kprobe_opcode_t *addr = NULL, *ssaddr = 0;
+       int err_out = 0;
+       char *msg_out = NULL;
+       unsigned long user_m = user_mode(regs);
+       pid_t tgid = (user_m) ? current->tgid : 0;
+       kprobe_opcode_t *addr = (kprobe_opcode_t *) (regs->ARM_pc);
+
+       struct kprobe *p = NULL, *p_run = NULL;
+       int ret = 0, retprobe = 0, reenter = 0;
+       kprobe_opcode_t *ssaddr = 0;
        struct kprobe_ctlblk *kcb;
-       int i = 0;
-#ifdef OVERHEAD_DEBUG
-       struct timeval swap_tv1;
-       struct timeval swap_tv2;
-#endif
-#ifdef SUPRESS_BUG_MESSAGES
-       int swap_oops_in_progress;
-#endif
-       struct hlist_head *head;
-       struct hlist_node *node;
-       struct kprobe *pop, *retVal = NULL;
-       struct kprobe *kp;
 
 #ifdef SUPRESS_BUG_MESSAGES
+       int swap_oops_in_progress;
        // oops_in_progress used to avoid BUG() messages that slow down kprobe_handler() execution
        swap_oops_in_progress = oops_in_progress;
        oops_in_progress = 1;
 #endif
 #ifdef OVERHEAD_DEBUG
+       struct timeval swap_tv1;
+       struct timeval swap_tv2;
 #define USEC_IN_SEC_NUM                                1000000
        do_gettimeofday(&swap_tv1);
 #endif
        preempt_disable();
-       addr = (kprobe_opcode_t *) (regs->uregs[15]);
-       if (user_mode(regs))
-       {
-               head = &kprobe_table[hash_ptr (addr, KPROBE_HASH_BITS)];
-               hlist_for_each_entry_rcu (pop, node, head, hlist) {
-                       /*
-                        * Searching occurred probe by
-                        * instruction address and task_struct
-                        */
-                       if (pop->addr == addr) {
-                               if (pop->tgid == current->tgid) {
-                                   retVal = pop;
-                                   break;
-                               }
-                       }
-               }
-       }
-       if (retVal) {
-               if (unlikely(thumb_mode(regs))) {
-                       if (pop->safe_thumb != -1) {
-                               pop->ainsn.insn = pop->ainsn.insn_thumb;
-                               list_for_each_entry_rcu (kp, &pop->list, list) {
-                                       kp->ainsn.insn = pop->ainsn.insn_thumb;
-                               }
-                       }
-                       else {
-                               printk("Error in %s at %d: we are in thumb mode (!) and check instruction was fail \
-                                       (%0X instruction at %p address)!\n", __FILE__, __LINE__, pop->opcode, pop->addr);
-                               // Test case when we do our actions on already running application
-                               arch_disarm_uprobe (pop, current);
-                               goto no_kprobe_live;
-                       }
-               }
-               else {
-                       if (pop->safe_arm != -1) {
-                               pop->ainsn.insn = pop->ainsn.insn_arm;
-                               list_for_each_entry_rcu (kp, &pop->list, list) {
-                                       kp->ainsn.insn = pop->ainsn.insn_arm;
-                               }
-                       }
-                       else {
-                               printk("Error in %s at %d: we are in arm mode (!) and check instruction was fail \
-                                       (%0X instruction at %p address)!\n", __FILE__, __LINE__, pop->opcode, pop->addr );
-                               // Test case when we do our actions on already running application
-                               arch_disarm_uprobe (pop, current);
-                               goto no_kprobe_live;
-                       }
-               }
+
+//     printk("### kprobe_handler: task[tgid=%u (%s)] addr=%p\n", tgid, current->comm, addr);
+       p = get_kprobe(addr, tgid);
+
+       if (user_m && p && (check_validity_insn(p, regs, current) != 0)) {
+               goto no_kprobe_live;
        }
+
        /* We're in an interrupt, but this is clear and BUG()-safe. */
        kcb = get_kprobe_ctlblk ();
-       if (user_mode (regs))
-       {
-               //DBPRINTF("exception[%lu] from user mode %s/%u addr %p (%lx).", nCount, current->comm, current->pid, addr, regs->uregs[14]);
-               pid = current->tgid;
-       }
+
        /* Check we're not actually recursing */
-       // TODO: handling of recursion is disabled
-       if (0 && kprobe_running ())
+       // TODO: event is not saving in trace
+       p_run = kprobe_running();
+       if (p_run)
        {
-               DBPRINTF ("lock???");
-               p = get_kprobe (addr, pid, current);
+               DBPRINTF("lock???");
                if (p)
                {
-                       if(!pid && (addr == (kprobe_opcode_t *)kretprobe_trampoline)){
-                               save_previous_kprobe (kcb, p);
+                       if (!tgid && (addr == (kprobe_opcode_t *)kretprobe_trampoline)) {
+                               save_previous_kprobe(kcb, p_run);
                                kcb->kprobe_status = KPROBE_REENTER;
                                reenter = 1;
-                       }
-                       else {
+                       } else {
                                /* We have reentered the kprobe_handler(), since
                                 * another probe was hit while within the handler.
                                 * We here save the original kprobes variables and
                                 * just single step on the instruction of the new probe
                                 * without calling any user handlers.
                                 */
-                               if(!p->ainsn.boostable){
-                                       save_previous_kprobe (kcb, p);
-                                       set_current_kprobe (p, regs, kcb);
-                               }
                                kprobes_inc_nmissed_count (p);
                                prepare_singlestep (p, regs);
-                               if(!p->ainsn.boostable)
-                                       kcb->kprobe_status = KPROBE_REENTER;
-                               preempt_enable_no_resched ();
-#ifdef OVERHEAD_DEBUG
-                               do_gettimeofday(&swap_tv2);
-                               swap_sum_hit++;
-                               swap_sum_time += ((swap_tv2.tv_sec - swap_tv1.tv_sec) * USEC_IN_SEC_NUM +
-                                       (swap_tv2.tv_usec - swap_tv1.tv_usec));
-#endif
-#ifdef SUPRESS_BUG_MESSAGES
-                               oops_in_progress = swap_oops_in_progress;
-#endif
-                               return 0;
+
+                               err_out = 0;
+                               goto out;
                        }
-               }
-               else
-               {
-                       if(pid) { //we can reenter probe upon uretprobe exception
+               } else {
+                       if(tgid) { //we can reenter probe upon uretprobe exception
                                DBPRINTF ("check for UNDEF_INSTRUCTION %p\n", addr);
                                // UNDEF_INSTRUCTION from user space
 
-                               if (!thumb_mode ( regs ))
-                                       p = get_kprobe_by_insn_slot_arm (addr-UPROBES_TRAMP_RET_BREAK_IDX, pid, current);
-                               else
-                                       p = get_kprobe_by_insn_slot_thumb ((unsigned long)addr - 0x1a, pid, current);
-
+                               p = get_kprobe_by_insn_slot(addr, tgid, regs);
                                if (p) {
-                                       save_previous_kprobe (kcb, p);
+                                       save_previous_kprobe(kcb, p_run);
                                        kcb->kprobe_status = KPROBE_REENTER;
                                        reenter = 1;
                                        retprobe = 1;
@@ -1152,26 +1128,24 @@ int kprobe_handler (struct pt_regs *regs)
                                }
                        }
                        if(!p) {
-                               p = kprobe_running();
+                               p = p_run;
                                DBPRINTF ("kprobe_running !!! p = 0x%p p->break_handler = 0x%p", p, p->break_handler);
                                /*if (p->break_handler && p->break_handler(p, regs)) {
                                  DBPRINTF("kprobe_running !!! goto ss");
                                  goto ss_probe;
                                  } */
                                DBPRINTF ("unknown uprobe at %p cur at %p/%p\n", addr, p->addr, p->ainsn.insn);
-                               if(pid)
+                               if (tgid)
                                        ssaddr = p->ainsn.insn + UPROBES_TRAMP_SS_BREAK_IDX;
                                else
                                        ssaddr = p->ainsn.insn + KPROBES_TRAMP_SS_BREAK_IDX;
-                               if (addr == ssaddr)
-                               {
-                                       regs->uregs[15] = (unsigned long) (p->addr + 1);
-                                       DBPRINTF ("finish step at %p cur at %p/%p, redirect to %lx\n", addr, p->addr, p->ainsn.insn, regs->uregs[15]);
+                               if (addr == ssaddr) {
+                                       regs->ARM_pc = (unsigned long) (p->addr + 1);
+                                       DBPRINTF ("finish step at %p cur at %p/%p, redirect to %lx\n", addr, p->addr, p->ainsn.insn, regs->ARM_pc);
                                        if (kcb->kprobe_status == KPROBE_REENTER) {
-                                               restore_previous_kprobe (kcb);
-                                       }
-                                       else {
-                                               reset_current_kprobe ();
+                                               restore_previous_kprobe(kcb);
+                                       } else {
+                                               reset_current_kprobe();
                                        }
                                }
                                DBPRINTF ("kprobe_running !!! goto no");
@@ -1182,21 +1156,13 @@ int kprobe_handler (struct pt_regs *regs)
                        }
                }
        }
-       if (!p)
-       {
-               p = get_kprobe (addr, pid, current);
-       }
-       if (!p)
-       {
-               if(pid) {
+
+       if (!p) {
+               if (tgid) {
                        DBPRINTF ("search UNDEF_INSTRUCTION %p\n", addr);
                        // UNDEF_INSTRUCTION from user space
 
-                       if (!thumb_mode ( regs ))
-                               p = get_kprobe_by_insn_slot_arm (addr-UPROBES_TRAMP_RET_BREAK_IDX, pid, current);
-                       else
-                               p = get_kprobe_by_insn_slot_thumb ((unsigned long)addr - 0x1a, pid, current);
-
+                       p = get_kprobe_by_insn_slot(addr, tgid, regs);
                        if (!p) {
                                /* Not one of ours: let kernel handle it */
                                DBPRINTF ("no_kprobe");
@@ -1204,78 +1170,52 @@ int kprobe_handler (struct pt_regs *regs)
                        }
                        retprobe = 1;
                        DBPRINTF ("uretprobe %p\n", addr);
-               }
-               else {
+               } else {
                        /* Not one of ours: let kernel handle it */
                        DBPRINTF ("no_kprobe");
                        goto no_kprobe;
                }
        }
        // restore opcode for thumb app
-       if (user_mode( regs ) && thumb_mode( regs ))
-       {
-               if (!isThumb2(p->opcode))
-               {
+       if (user_mode( regs ) && thumb_mode( regs )) {
+               if (!isThumb2(p->opcode)) {
                        unsigned long tmp = p->opcode >> 16;
                        write_proc_vm_atomic(current, (unsigned long)((unsigned short*)p->addr + 1), &tmp, 2);
-               }else{
-                       unsigned long tmp = p->opcode;
-                       write_proc_vm_atomic(current, (unsigned long)((unsigned short*)p->addr), &tmp, 4);
+
+                       // "2*sizeof(kprobe_opcode_t)" - strange. Should be "sizeof(kprobe_opcode_t)", need to test
+                       flush_icache_range((unsigned int) p->addr, ((unsigned int)p->addr) + (2 * sizeof(kprobe_opcode_t)));
                }
-               flush_icache_range ((unsigned int) p->addr, (unsigned int) (((unsigned int) p->addr) + (sizeof (kprobe_opcode_t) * 2)));
        }
-       set_current_kprobe (p, regs, kcb);
+       set_current_kprobe(p, NULL, NULL);
        if(!reenter)
                kcb->kprobe_status = KPROBE_HIT_ACTIVE;
-       if (retprobe)           //(einsn == UNDEF_INSTRUCTION)
+       if (retprobe) {         //(einsn == UNDEF_INSTRUCTION)
                ret = trampoline_probe_handler (p, regs);
-       else if (p->pre_handler)
-       {
+       } else if (p->pre_handler) {
                ret = p->pre_handler (p, regs);
-               if(!p->ainsn.boostable)
-                       kcb->kprobe_status = KPROBE_HIT_SS;
-               else if(p->pre_handler != trampoline_probe_handler) {
-#ifdef SUPRESS_BUG_MESSAGES
-                       preempt_disable();
-#endif
+               if(p->pre_handler != trampoline_probe_handler) {
                        reset_current_kprobe();
-#ifdef SUPRESS_BUG_MESSAGES
-                       preempt_enable_no_resched();
-#endif
                }
        }
-       if (ret)
-       {
-               DBPRINTF ("p->pre_handler 1");
+
+       if (ret) {
                /* handler has already set things up, so skip ss setup */
-#ifdef OVERHEAD_DEBUG
-               do_gettimeofday(&swap_tv2);
-               swap_sum_hit++;
-               swap_sum_time += ((swap_tv2.tv_sec - swap_tv1.tv_sec) * USEC_IN_SEC_NUM +
-                       (swap_tv2.tv_usec - swap_tv1.tv_usec));
-#endif
-#ifdef SUPRESS_BUG_MESSAGES
-               oops_in_progress = swap_oops_in_progress;
-#endif
-               return 0;
+               err_out = 0;
+               goto out;
        }
-       DBPRINTF ("p->pre_handler 0");
 
 no_kprobe:
-       preempt_enable_no_resched ();
-#ifdef OVERHEAD_DEBUG
-       do_gettimeofday(&swap_tv2);
-       swap_sum_hit++;
-       swap_sum_time += ((swap_tv2.tv_sec - swap_tv1.tv_sec) *  USEC_IN_SEC_NUM +
-               (swap_tv2.tv_usec - swap_tv1.tv_usec));
-#endif
-#ifdef SUPRESS_BUG_MESSAGES
-       oops_in_progress = swap_oops_in_progress;
-#endif
-       printk("no_kprobe\n");
-       return 1;               // return with death
+       msg_out = "no_kprobe\n";
+       err_out = 1;            // return with death
+       goto out;
+
 no_kprobe_live:
-       preempt_enable_no_resched ();
+       msg_out = "no_kprobe live\n";
+       err_out = 0;            // ok - life is life
+       goto out;
+
+out:
+       preempt_enable_no_resched();
 #ifdef OVERHEAD_DEBUG
        do_gettimeofday(&swap_tv2);
        swap_sum_hit++;
@@ -1285,8 +1225,12 @@ no_kprobe_live:
 #ifdef SUPRESS_BUG_MESSAGES
        oops_in_progress = swap_oops_in_progress;
 #endif
-       printk("no_kprobe live\n");
-       return 0;               // ok - life is life
+
+       if(msg_out) {
+               printk(msg_out);
+       }
+
+       return err_out;
 }
 
 int setjmp_pre_handler (struct kprobe *p, struct pt_regs *regs)
@@ -1296,7 +1240,7 @@ int setjmp_pre_handler (struct kprobe *p, struct pt_regs *regs)
        entry_point_t entry;
 
 # ifdef REENTER
-       p = kprobe_running();
+//     p = kprobe_running(regs);
 # endif
 
        DBPRINTF ("pjp = 0x%p jp->entry = 0x%p", jp, jp->entry);
@@ -1334,12 +1278,10 @@ int setjmp_pre_handler (struct kprobe *p, struct pt_regs *regs)
 
 void dbi_jprobe_return (void)
 {
-       preempt_enable_no_resched();
 }
 
 void dbi_arch_uprobe_return (void)
 {
-       preempt_enable_no_resched();
 }
 
 int longjmp_break_handler (struct kprobe *p, struct pt_regs *regs)
@@ -1376,7 +1318,7 @@ int longjmp_break_handler (struct kprobe *p, struct pt_regs *regs)
                flush_icache_range ((unsigned int) p->addr, (unsigned int) (((unsigned int) p->addr) + (sizeof (kprobe_opcode_t) * 2)));
        }
 
-       reset_current_kprobe ();
+       reset_current_kprobe();
 
 #endif //REENTER
 
@@ -1400,7 +1342,7 @@ void arch_disarm_kprobe (struct kprobe *p)
 int trampoline_probe_handler (struct kprobe *p, struct pt_regs *regs)
 {
        struct kretprobe_instance *ri = NULL;
-       struct hlist_head *head, empty_rp;
+       struct hlist_head *head;
        struct hlist_node *node, *tmp;
        unsigned long flags, orig_ret_address = 0;
        unsigned long trampoline_address = (unsigned long) &kretprobe_trampoline;
@@ -1418,7 +1360,6 @@ int trampoline_probe_handler (struct kprobe *p, struct pt_regs *regs)
                        trampoline_address = (unsigned long)(p->ainsn.insn) + 0x1b;
        }
 
-       INIT_HLIST_HEAD (&empty_rp);
        spin_lock_irqsave (&kretprobe_lock, flags);
 
        /*
@@ -1491,11 +1432,6 @@ int trampoline_probe_handler (struct kprobe *p, struct pt_regs *regs)
        DBPRINTF ("regs->uregs[15] = 0x%lx\n", regs->uregs[15]);
 
        if(p){ // ARM, MIPS, X86 user space
-               if (kcb->kprobe_status == KPROBE_REENTER)
-                       restore_previous_kprobe (kcb);
-               else
-                       reset_current_kprobe ();
-
                if (thumb_mode( regs ) && !(regs->uregs[14] & 0x01))
                {
                        regs->ARM_cpsr &= 0xFFFFFFDF;
@@ -1531,14 +1467,15 @@ int trampoline_probe_handler (struct kprobe *p, struct pt_regs *regs)
                                }
 
                                if (!node)
-                               {       // if there are no more instances for this retprobe
+                               {
+                                       // if there are no more instances for this retprobe
                                        // delete retprobe
+                                       struct kprobe *is_p = &crp->kp;
                                        DBPRINTF ("defered retprobe deletion p->addr = %p", crp->kp.addr);
                                        /*
                                          If there is no any retprobe instances of this retprobe
                                          we can free the resources related to the probe.
                                         */
-                                       struct kprobe *is_p = &crp->kp;
                                        if (!(hlist_unhashed(&is_p->is_hlist_arm))) {
                                                hlist_del_rcu(&is_p->is_hlist_arm);
                                        }
@@ -1551,16 +1488,16 @@ int trampoline_probe_handler (struct kprobe *p, struct pt_regs *regs)
                                hlist_del(current_node);
                        }
                }
-       }
 
-       hlist_for_each_entry_safe (ri, node, tmp, &empty_rp, hlist)
-       {
-               hlist_del (&ri->hlist);
-               kfree (ri);
+               if (kcb->kprobe_status == KPROBE_REENTER) {
+                       restore_previous_kprobe(kcb);
+               } else {
+                       reset_current_kprobe();
+               }
        }
+
        spin_unlock_irqrestore (&kretprobe_lock, flags);
 
-       preempt_enable_no_resched ();
        /*
         * By returning a non-zero value, we are telling
         * kprobe_handler() that we don't want the post_handler
@@ -1608,10 +1545,6 @@ int asm_init_module_dependencies()
        return 0;
 }
 
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 38)
-typedef unsigned long (* in_gate_area_fp_t)(unsigned long);
-in_gate_area_fp_t in_gate_area_fp;
-#endif /* LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 38) */
 
 void (* do_kpro)(struct undef_hook *);
 void (* undo_kpro)(struct undef_hook *);
@@ -1622,7 +1555,7 @@ struct undef_hook undef_ho_k = {
     .instr_val = BREAKPOINT_INSTRUCTION,
     .cpsr_mask = MODE_MASK,
     .cpsr_val  = SVC_MODE,
-    .fn                = kprobe_handler,
+    .fn                = kprobe_trap_handler
 };
 
 // userspace probes hook (arm)
@@ -1631,7 +1564,7 @@ struct undef_hook undef_ho_u = {
     .instr_val = BREAKPOINT_INSTRUCTION,
     .cpsr_mask = MODE_MASK,
     .cpsr_val  = USR_MODE,
-    .fn                = kprobe_handler,
+    .fn                = kprobe_trap_handler
 };
 
 // userspace probes hook (thumb)
@@ -1640,7 +1573,7 @@ struct undef_hook undef_ho_u_t = {
     .instr_val = BREAKPOINT_INSTRUCTION & 0x0000ffff,
     .cpsr_mask = MODE_MASK,
     .cpsr_val  = USR_MODE,
-    .fn                = kprobe_handler,
+    .fn                = kprobe_trap_handler
 };
 
 int __init arch_init_kprobes (void)
@@ -1654,14 +1587,6 @@ int __init arch_init_kprobes (void)
                return -1;
        }
 
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 38)
-       in_gate_area_fp = (in_gate_area_fp_t)kallsyms_search("in_gate_area_no_mm");
-       if (!in_gate_area_fp) {
-               DBPRINTF("no in_gate_area symbol found!");
-                return -1;
-        }
-#endif /* LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 38) */
-
        do_bp_handler = (unsigned int) kallsyms_search ("do_undefinstr");
        if (do_bp_handler == 0) {
                DBPRINTF("no do_undefinstr symbol found!");
@@ -1669,11 +1594,19 @@ int __init arch_init_kprobes (void)
         }
        arr_traps_template[NOTIFIER_CALL_CHAIN_INDEX] = arch_construct_brunch ((unsigned int)kprobe_handler, do_bp_handler + NOTIFIER_CALL_CHAIN_INDEX * 4, 1);
        // Register hooks (kprobe_handler)
-       do_kpro = kallsyms_search ("register_undef_hook");
+       do_kpro = (void *)kallsyms_search ("register_undef_hook");
        if (do_kpro == 0) {
                printk("no register_undef_hook symbol found!\n");
                 return -1;
         }
+
+        // Unregister hooks (kprobe_handler)
+        undo_kpro = (void *)kallsyms_search ("unregister_undef_hook");
+        if (undo_kpro == 0) {
+                printk("no unregister_undef_hook symbol found!\n");
+                return -1;
+        }
+
        do_kpro(&undef_ho_k);
        do_kpro(&undef_ho_u);
        do_kpro(&undef_ho_u_t);
@@ -1686,12 +1619,6 @@ int __init arch_init_kprobes (void)
 
 void __exit dbi_arch_exit_kprobes (void)
 {
-       // Unregister hooks (kprobe_handler)
-       undo_kpro = kallsyms_search ("unregister_undef_hook");
-       if (undo_kpro == 0) {
-               printk("no unregister_undef_hook symbol found!\n");
-                return -1;
-        }
        undo_kpro(&undef_ho_u_t);
        undo_kpro(&undef_ho_u);
        undo_kpro(&undef_ho_k);