mini refactoring kprobes
authorVyacheslav Cherkashin <v.cherkashin@samsung.com>
Wed, 8 Aug 2012 12:26:54 +0000 (16:26 +0400)
committerVyacheslav Cherkashin <v.cherkashin@samsung.com>
Wed, 8 Aug 2012 12:26:54 +0000 (16:26 +0400)
driver/probes_manager.c
kprobe/arch/asm-arm/dbi_kprobes.c
kprobe/arch/asm-mips/dbi_kprobes.c
kprobe/dbi_kprobes.c
kprobe/dbi_kprobes.h
kprobe/dbi_uprobes.c

index c4acba3..2809ab8 100644 (file)
@@ -102,7 +102,7 @@ register_kernel_jprobe (kernel_probe_t * probe)
        {
                return 0;       // probe is already registered
        }
-       result = dbi_register_jprobe (&probe->jprobe, 0);
+       result = dbi_register_jprobe (&probe->jprobe);
        if (result)
        {
                EPRINTF ("register_kernel_jprobe(0x%lx) failure %d", probe->addr, result);
@@ -120,7 +120,7 @@ unregister_kernel_jprobe (kernel_probe_t * probe)
                ((probe == exec_probe) && (us_proc_probes & US_PROC_EXEC_INSTLD))) {
                return 0;       // probe is necessary for user space instrumentation
        }
-       dbi_unregister_jprobe (&probe->jprobe, 0);
+       dbi_unregister_jprobe (&probe->jprobe);
        return 0;
 }
 
@@ -135,7 +135,7 @@ register_kernel_retprobe (kernel_probe_t * probe)
                return 0;       // probe is already registered
        }
 
-       result = dbi_register_kretprobe (&probe->retprobe, 0);
+       result = dbi_register_kretprobe (&probe->retprobe);
        if (result)
        {
                EPRINTF ("register_kernel_retprobe(0x%lx) failure %d", probe->addr, result);
@@ -153,7 +153,7 @@ unregister_kernel_retprobe (kernel_probe_t * probe)
                ((probe == exec_probe) && (us_proc_probes & US_PROC_EXEC_INSTLD))) {
                return 0;       // probe is necessary for user space instrumentation
        }
-       dbi_unregister_kretprobe (&probe->retprobe, 0);
+       dbi_unregister_kretprobe (&probe->retprobe);
        return 0;
 }
 
@@ -363,14 +363,11 @@ remove_probe (unsigned long addr)
 
 DEFINE_PER_CPU (kernel_probe_t *, gpKernProbe) = NULL;
 EXPORT_PER_CPU_SYMBOL_GPL(gpKernProbe);
-DEFINE_PER_CPU(struct pt_regs *, gpKernRegs) = NULL;
-EXPORT_PER_CPU_SYMBOL_GPL(gpKernRegs);
 
 unsigned long
 def_jprobe_event_pre_handler (kernel_probe_t * probe, struct pt_regs *regs)
 {
        __get_cpu_var (gpKernProbe) = probe;
-       __get_cpu_var (gpKernRegs) = regs;
 
        return 0;
 }
index 033809f..0ca494f 100644 (file)
  * 2008-2009    Alexey Gerenkov <a.gerenkov@samsung.com> User-Space
  *              Probes initial implementation; Support x86.
  * 2010         Ekaterina Gorelkina <e.gorelkina@samsung.com>: redesign module for separating core and arch parts
- *
  * 2010-2011    Alexander Shirshikov <a.shirshikov@samsung.com>: initial implementation for Thumb
- * 2012                Stanislav Andreev <s.andreev@samsung.com>: added time debug profiling support; BUG() message fix
- * 2012                Stanislav Andreev <s.andreev@samsung.com>: redesign of kprobe functionality - 
- *             kprobe_handler() now called via undefined instruction hooks
- * 2012                Stanislav Andreev <s.andreev@samsung.com>: hash tables search implemented for uprobes
+ * 2012         Stanislav Andreev <s.andreev@samsung.com>: added time debug profiling support; BUG() message fix
+ * 2012         Stanislav Andreev <s.andreev@samsung.com>: redesign of kprobe functionality -
+ *              kprobe_handler() now called via undefined instruction hooks
+ * 2012         Stanislav Andreev <s.andreev@samsung.com>: hash tables search implemented for uprobes
  */
 
 #include <linux/module.h>
@@ -135,8 +134,6 @@ int prep_pc_dep_insn_execbuf (kprobe_opcode_t * insns, kprobe_opcode_t insn, int
        {
                for (i = 0; i < 13; i++)
                {
-                       //              DBPRINTF("prep_pc_dep_insn_execbuf: check R%d/%d, changing regs %x in %x",
-                       //                              i, ARM_INSN_REG_RN(insn), uregs, insn);
                        if ((uregs & 0x1) && (ARM_INSN_REG_RN (insn) == i))
                                continue;
                        if ((uregs & 0x2) && (ARM_INSN_REG_RD (insn) == i))
@@ -159,7 +156,7 @@ int prep_pc_dep_insn_execbuf (kprobe_opcode_t * insns, kprobe_opcode_t insn, int
        ARM_INSN_REG_SET_RD (insns[0], i);
        // set register to load address to
        ARM_INSN_REG_SET_RD (insns[1], i);
-       // set instruction to execute and patch it 
+       // set instruction to execute and patch it
        if (uregs & 0x10)
        {
                ARM_INSN_REG_CLEAR_MR (insn, 15);
@@ -198,7 +195,7 @@ int prep_pc_dep_insn_execbuf_thumb (kprobe_opcode_t * insns, kprobe_opcode_t ins
                {
                        if (((((unsigned char) insn) & 0xff) >> 3) == 15)
                                reg = (insn & 0xffff) & uregs;
-                       else    
+                       else
                                return 0;
                }else{
                        if (THUMB2_INSN_MATCH (ADR, insn))
@@ -513,124 +510,110 @@ int arch_prepare_kretprobe (struct kretprobe *p)
 int arch_prepare_kprobe (struct kprobe *p)
 {
        kprobe_opcode_t insns[KPROBES_TRAMP_LEN];
-       int uregs, pc_dep;
-       int ret = 0;
-
-       if (!ret)
-       {
-               kprobe_opcode_t insn[MAX_INSN_SIZE];
-               struct arch_specific_insn ainsn;
-               /* insn: must be on special executable page on i386. */
-               p->ainsn.insn = get_insn_slot (NULL, 0);
-               if (!p->ainsn.insn)
-                       return -ENOMEM;
-               memcpy (insn, p->addr, MAX_INSN_SIZE * sizeof (kprobe_opcode_t));
-               ainsn.insn_arm = ainsn.insn = insn;
-               ret = arch_check_insn_arm (&ainsn);
-               if (!ret)
-               {
-                       p->opcode = *p->addr;
-
-                       p->ainsn.boostable = 1;
-                       uregs = pc_dep = 0;
-                       // Rn, Rm ,Rd
-                       if (ARM_INSN_MATCH (DPIS, insn[0]) || ARM_INSN_MATCH (LRO, insn[0]) ||
-                                       ARM_INSN_MATCH (SRO, insn[0]))
-                       {
-
-                               uregs = 0xb;
-                               if ((ARM_INSN_REG_RN (insn[0]) == 15) || (ARM_INSN_REG_RM (insn[0]) == 15) ||
-                                               (ARM_INSN_MATCH (SRO, insn[0]) && (ARM_INSN_REG_RD (insn[0]) == 15)))
-                               {
-
-                                       DBPRINTF ("Unboostable insn %lx, DPIS/LRO/SRO\n", insn[0]);
-                                       pc_dep = 1;
-                               }
-                       }
-                       // Rn ,Rd
-                       else if (ARM_INSN_MATCH (DPI, insn[0]) || ARM_INSN_MATCH (LIO, insn[0]) ||
-                                       ARM_INSN_MATCH (SIO, insn[0]))
-                       {
-
-                               uregs = 0x3;
-                               if ((ARM_INSN_REG_RN (insn[0]) == 15) || (ARM_INSN_MATCH (SIO, insn[0]) &&
-                                                       (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);
-                               }
-                       }
-                       // Rn, Rm, Rs
-                       else if (ARM_INSN_MATCH (DPRS, insn[0]))
-                       {
-
-                               uregs = 0xd;
-                               if ((ARM_INSN_REG_RN (insn[0]) == 15) || (ARM_INSN_REG_RM (insn[0]) == 15) ||
-                                               (ARM_INSN_REG_RS (insn[0]) == 15))
-                               {
-
-                                       pc_dep = 1;
-                                       DBPRINTF ("Unboostable insn %lx, DPRS\n", insn[0]);
-                               }
-                       }
-                       // register list
-                       else if (ARM_INSN_MATCH (SM, insn[0]))
-                       {
-
-                               uregs = 0x10;
-                               if (ARM_INSN_REG_MR (insn[0], 15))
-                               {
-
-                                       DBPRINTF ("Unboostable insn %lx, SM\n", insn[0]);
-                                       pc_dep = 1;
-                               }
-                       }
-                       // check instructions that can write result to SP andu uses PC
-                       if (pc_dep  && (ARM_INSN_REG_RD (ainsn.insn[0]) == 13))
-                       {
-                               static int count;
-                               count++;
-                               //printk ("insn writes result to SP and uses PC: %lx/%d\n", ainsn.insn[0], count);
-                               free_insn_slot (&kprobe_insn_pages, NULL, p->ainsn.insn, 0);
-                               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, 0);
-                                               return -EINVAL;
-                                       }
-                                       //insns[KPROBES_TRAMP_SS_BREAK_IDX] = BREAKPOINT_INSTRUCTION;
-                                       insns[6] = (kprobe_opcode_t) (p->addr + 2);
-                               }
-                               else
-                               {
-                                       memcpy (insns, gen_insn_execbuf, sizeof (insns));
-                                       insns[KPROBES_TRAMP_INSN_IDX] = insn[0];
-                               }
-                               //insns[KPROBES_TRAMP_RET_BREAK_IDX] = UNDEF_INSTRUCTION;
-                               insns[7] = (kprobe_opcode_t) (p->addr + 1);
-                               DBPRINTF ("arch_prepare_kprobe: insn %lx", insn[0]);
-                               DBPRINTF ("arch_prepare_kprobe: to %p - %lx %lx %lx %lx %lx %lx %lx %lx %lx",
-                                               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));
+       int uregs, pc_dep, ret = 0;
+    kprobe_opcode_t insn[MAX_INSN_SIZE];
+    struct arch_specific_insn ainsn;
+
+    /* insn: must be on special executable page on i386. */
+    p->ainsn.insn = get_insn_slot (NULL, 0);
+    if (!p->ainsn.insn)
+        return -ENOMEM;
+
+    memcpy (insn, p->addr, MAX_INSN_SIZE * sizeof (kprobe_opcode_t));
+    ainsn.insn_arm = ainsn.insn = insn;
+    ret = arch_check_insn_arm (&ainsn);
+    if (!ret)
+    {
+        p->opcode = *p->addr;
+        p->ainsn.boostable = 1;
+        uregs = pc_dep = 0;
+
+        // Rn, Rm ,Rd
+        if(ARM_INSN_MATCH (DPIS, insn[0]) || ARM_INSN_MATCH (LRO, insn[0]) ||
+           ARM_INSN_MATCH (SRO, insn[0]))
+        {
+            uregs = 0xb;
+            if( (ARM_INSN_REG_RN (insn[0]) == 15) || (ARM_INSN_REG_RM (insn[0]) == 15) ||
+                (ARM_INSN_MATCH (SRO, insn[0]) && (ARM_INSN_REG_RD (insn[0]) == 15)) )
+            {
+                DBPRINTF ("Unboostable insn %lx, DPIS/LRO/SRO\n", insn[0]);
+                pc_dep = 1;
+            }
+        }
+        // Rn ,Rd
+        else if(ARM_INSN_MATCH (DPI, insn[0]) || ARM_INSN_MATCH (LIO, insn[0]) ||
+                ARM_INSN_MATCH (SIO, insn[0]))
+        {
+            uregs = 0x3;
+            if ((ARM_INSN_REG_RN (insn[0]) == 15) || (ARM_INSN_MATCH (SIO, insn[0]) &&
+                        (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);
+            }
+        }
+        // Rn, Rm, Rs
+        else if(ARM_INSN_MATCH (DPRS, insn[0]))
+        {
+            uregs = 0xd;
+            if ((ARM_INSN_REG_RN (insn[0]) == 15) || (ARM_INSN_REG_RM (insn[0]) == 15) ||
+                (ARM_INSN_REG_RS (insn[0]) == 15))
+            {
+                pc_dep = 1;
+                DBPRINTF ("Unboostable insn %lx, DPRS\n", insn[0]);
+            }
+        }
+        // register list
+        else if(ARM_INSN_MATCH (SM, insn[0]))
+        {
+            uregs = 0x10;
+            if (ARM_INSN_REG_MR (insn[0], 15))
+            {
+                DBPRINTF ("Unboostable insn %lx, SM\n", insn[0]);
+                pc_dep = 1;
+            }
+        }
+        // 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);
+            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, 0);
+                    return -EINVAL;
+                }
+                insns[6] = (kprobe_opcode_t) (p->addr + 2);
+            }
+            else
+            {
+                memcpy (insns, gen_insn_execbuf, sizeof (insns));
+                insns[KPROBES_TRAMP_INSN_IDX] = insn[0];
+            }
+            insns[7] = (kprobe_opcode_t) (p->addr + 1);
+            DBPRINTF ("arch_prepare_kprobe: insn %lx", insn[0]);
+            DBPRINTF ("arch_prepare_kprobe: to %p - %lx %lx %lx %lx %lx %lx %lx %lx %lx",
+                    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));
 #ifdef BOARD_tegra
-                               flush_cache_all();
+            flush_cache_all();
 #endif
-                       }
-               }
-               else
-               {
-                       free_insn_slot (&kprobe_insn_pages, NULL, p->ainsn.insn, 0);
-               }
-       }
+        }
+    }
+    else
+    {
+        free_insn_slot (&kprobe_insn_pages, NULL, p->ainsn.insn, 0);
+    }
+
        return ret;
 }
 
@@ -823,7 +806,7 @@ int arch_copy_trampoline_arm_uprobe (struct kprobe *p, struct task_struct *task,
                memcpy (insns, pc_dep_insn_execbuf, sizeof (insns));
                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!", 
+                       printk("Error in %s at %d: failed to prepare exec buffer for insn %lx!",
                                insn[0], __FILE__, __LINE__);
                        p->safe_arm = -1;
                        // TODO: move free to later phase
@@ -906,10 +889,10 @@ int arch_copy_trampoline_thumb_uprobe (struct kprobe *p, struct task_struct *tas
                        THUMB2_INSN_MATCH (LDRHW, insn[0]) || THUMB2_INSN_MATCH (LDRHW1, insn[0]) ||
                        THUMB2_INSN_MATCH (LDRWL, insn[0])) && THUMB2_INSN_REG_RN(insn[0]) == 15) ||
                        THUMB2_INSN_MATCH (LDREX, insn[0]) ||
-                       ((THUMB2_INSN_MATCH (STRW, insn[0]) || THUMB2_INSN_MATCH (STRBW, insn[0]) || 
-                               THUMB2_INSN_MATCH (STRHW, insn[0]) || THUMB2_INSN_MATCH (STRHW1, insn[0])) && 
+                       ((THUMB2_INSN_MATCH (STRW, insn[0]) || THUMB2_INSN_MATCH (STRBW, insn[0]) ||
+                               THUMB2_INSN_MATCH (STRHW, insn[0]) || THUMB2_INSN_MATCH (STRHW1, insn[0])) &&
                                (THUMB2_INSN_REG_RN(insn[0]) == 15 || THUMB2_INSN_REG_RT(insn[0]) == 15)) ||
-                       ((THUMB2_INSN_MATCH (STRT, insn[0]) || THUMB2_INSN_MATCH (STRHT, insn[0])) && 
+                       ((THUMB2_INSN_MATCH (STRT, insn[0]) || THUMB2_INSN_MATCH (STRHT, insn[0])) &&
                                (THUMB2_INSN_REG_RN(insn[0]) == 15 || THUMB2_INSN_REG_RT(insn[0]) == 15)) )
        {
                uregs = 0xf000;         // Rt 12-15
@@ -971,7 +954,7 @@ int arch_copy_trampoline_thumb_uprobe (struct kprobe *p, struct task_struct *tas
                memcpy (insns, pc_dep_insn_execbuf_thumb, 18 * 2);
                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!", 
+                       printk("Error in %s at %d: failed to prepare exec buffer for insn %lx!",
                                insn[0], __FILE__, __LINE__);
                        p->safe_thumb = -1;
                        //free_insn_slot (&uprobe_insn_pages, task, p->ainsn.insn_thumb, 0);
@@ -1137,7 +1120,7 @@ int kprobe_handler (struct pt_regs *regs)
 #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_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
@@ -1148,7 +1131,7 @@ int kprobe_handler (struct pt_regs *regs)
                }
                else
                {
-                       if(pid) { //we can reenter probe upon uretprobe exception   
+                       if(pid) { //we can reenter probe upon uretprobe exception
                                DBPRINTF ("check for UNDEF_INSTRUCTION %p\n", addr);
                                // UNDEF_INSTRUCTION from user space
 
@@ -1171,7 +1154,7 @@ int kprobe_handler (struct pt_regs *regs)
                                /*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)
                                        ssaddr = p->ainsn.insn + UPROBES_TRAMP_SS_BREAK_IDX;
@@ -1265,7 +1248,7 @@ int kprobe_handler (struct pt_regs *regs)
 #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_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
@@ -1280,7 +1263,7 @@ no_kprobe:
 #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_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
@@ -1293,7 +1276,7 @@ no_kprobe_live:
 #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_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
@@ -1371,7 +1354,7 @@ int setjmp_pre_handler (struct kprobe *p, struct pt_regs *regs)
 
        //call handler for all kernel probes and user space ones which belong to current tgid
        if (!p->tgid || (p->tgid == current->tgid))
-       {               
+       {
                if(!p->tgid && ((unsigned int)p->addr == sched_addr) && sched_rp){
                        struct task_struct *p, *g;
                        rcu_read_lock();
@@ -1510,7 +1493,7 @@ int trampoline_probe_handler (struct kprobe *p, struct pt_regs *regs)
        /*
         * It is possible to have multiple instances associated with a given
         * task either because an multiple functions in the call path
-        * have a return probe installed on them, and/or more then one 
+        * have a return probe installed on them, and/or more then one
         * return probe was registered for a target function.
         *
         * We can handle this because:
@@ -1751,7 +1734,7 @@ int __init arch_init_kprobes (void)
        do_kpro(&undef_ho_k);
        do_kpro(&undef_ho_u);
        do_kpro(&undef_ho_u_t);
-       if ((ret = dbi_register_kprobe (&trampoline_p, 0)) != 0) {
+       if ((ret = dbi_register_kprobe (&trampoline_p)) != 0) {
                //dbi_unregister_jprobe(&do_exit_p, 0);
                return ret;
        }
index 6358741..b537746 100644 (file)
@@ -841,7 +841,7 @@ int __init arch_init_kprobes (void)
        // Insert new code
        memcpy ((void *) do_bp_handler, arr_traps_template, code_size); 
        flush_icache_range (do_bp_handler, do_bp_handler + code_size); 
-       if((ret = dbi_register_kprobe (&trampoline_p, 0)) != 0){
+       if((ret = dbi_register_kprobe (&trampoline_p)) != 0){
                //dbi_unregister_jprobe(&do_exit_p, 0);
                return ret;
        }
index 669c548..8eeae24 100644 (file)
@@ -44,9 +44,8 @@
  * 2006-2007    Ekaterina Gorelkina <e.gorelkina@samsung.com>: initial implementation for ARM and MIPS
  * 2008-2009    Alexey Gerenkov <a.gerenkov@samsung.com> User-Space
  *              Probes initial implementation; Support x86/ARM/MIPS for both user and kernel spaces.
- * 2010         Ekaterina Gorelkina <e.gorelkina@samsung.com>: redesign module for separating core and arch parts 
+ * 2010         Ekaterina Gorelkina <e.gorelkina@samsung.com>: redesign module for separating core and arch parts
  *
-
  */
 
 #include "dbi_kprobes.h"
@@ -73,7 +72,6 @@
 
 extern unsigned int *sched_addr;
 extern unsigned int *fork_addr;
-
 extern struct hlist_head kprobe_insn_pages;
 
 extern unsigned long (*kallsyms_search) (const char *name);
@@ -99,13 +97,13 @@ void kretprobe_assert (struct kretprobe_instance *ri, unsigned long orig_ret_add
 
 
 /* We have preemption disabled.. so it is safe to use __ versions */
-static inline 
+static inline
 void set_kprobe_instance (struct kprobe *kp)
 {
        __get_cpu_var (kprobe_instance) = kp;
 }
 
-static inline 
+static inline
 void reset_kprobe_instance (void)
 {
        __get_cpu_var (kprobe_instance) = NULL;
@@ -174,7 +172,7 @@ struct kprobe *get_kprobe (void *addr, int tgid, struct task_struct *ctask)
  * Aggregate handlers for multiple kprobes support - these handlers
  * take care of invoking the individual kprobe handlers on p->list
  */
-static 
+static
 int aggr_pre_handler (struct kprobe *p, struct pt_regs *regs)
 {
        struct kprobe *kp;
@@ -194,7 +192,7 @@ int aggr_pre_handler (struct kprobe *p, struct pt_regs *regs)
        return 0;
 }
 
-static 
+static
 void aggr_post_handler (struct kprobe *p, struct pt_regs *regs, unsigned long flags)
 {
        struct kprobe *kp;
@@ -208,10 +206,9 @@ void aggr_post_handler (struct kprobe *p, struct pt_regs *regs, unsigned long fl
                        reset_kprobe_instance ();
                }
        }
-       return;
 }
 
-static 
+static
 int aggr_fault_handler (struct kprobe *p, struct pt_regs *regs, int trapnr)
 {
        struct kprobe *cur = __get_cpu_var (kprobe_instance);
@@ -228,7 +225,7 @@ int aggr_fault_handler (struct kprobe *p, struct pt_regs *regs, int trapnr)
        return 0;
 }
 
-static 
+static
 int aggr_break_handler (struct kprobe *p, struct pt_regs *regs)
 {
        struct kprobe *cur = __get_cpu_var (kprobe_instance);
@@ -359,7 +356,7 @@ void free_rp_inst (struct kretprobe *rp)
 /*
  * Keep all fields in the kprobe consistent
  */
-static inline 
+static inline
 void copy_kprobe (struct kprobe *old_p, struct kprobe *p)
 {
        memcpy (&p->opcode, &old_p->opcode, sizeof (kprobe_opcode_t));
@@ -419,7 +416,7 @@ inline void dbi_hlist_replace_rcu (struct hlist_node *old, struct hlist_node *ne
  * Fill in the required fields of the "manager kprobe". Replace the
  * earlier kprobe in the hlist with the manager kprobe
  */
-static inline 
+static inline
 void add_aggr_kprobe (struct kprobe *ap, struct kprobe *p)
 {
        copy_kprobe (p, ap);
@@ -477,132 +474,80 @@ int register_aggr_kprobe (struct kprobe *old_p, struct kprobe *p)
        return ret;
 }
 
-static 
-int __dbi_register_kprobe (struct kprobe *p, unsigned long called_from, int atomic)
-{
-       struct kprobe *old_p;
-       //      struct module *probed_mod;
-       int ret = 0;
-       /*
-        * If we have a symbol_name argument look it up,
-        * and add it to the address.  That way the addr
-        * field can either be global or relative to a symbol.
-        */
-       if (p->symbol_name)
-       {
-               if (p->addr)
-                       return -EINVAL;
-               p->addr = (unsigned int) kallsyms_search (p->symbol_name);
-       }
-
-       if (!p->addr)
-               return -EINVAL;
-       DBPRINTF ("p->addr = 0x%p\n", p->addr);
-       p->addr = (kprobe_opcode_t *) (((char *) p->addr) + p->offset);
-       DBPRINTF ("p->addr = 0x%p p = 0x%p\n", p->addr, p);
-
-       /*      if ((!kernel_text_address((unsigned long) p->addr)) ||
-               in_kprobes_functions((unsigned long) p->addr))
-               return -EINVAL;*/
+int dbi_register_kprobe (struct kprobe *p)
+{
+    struct kprobe *old_p;
+    int ret = 0;
+    /*
+     * If we have a symbol_name argument look it up,
+     * and add it to the address.  That way the addr
+     * field can either be global or relative to a symbol.
+     */
+    if (p->symbol_name)
+    {
+        if (p->addr)
+            return -EINVAL;
+        p->addr = (unsigned int) kallsyms_search (p->symbol_name);
+    }
+
+    if (!p->addr)
+        return -EINVAL;
+    DBPRINTF ("p->addr = 0x%p\n", p->addr);
+    p->addr = (kprobe_opcode_t *) (((char *) p->addr) + p->offset);
+    DBPRINTF ("p->addr = 0x%p p = 0x%p\n", p->addr, p);
 
 #ifdef KPROBES_PROFILE
-       p->start_tm.tv_sec = p->start_tm.tv_usec = 0;
-       p->hnd_tm_sum.tv_sec = p->hnd_tm_sum.tv_usec = 0;
-       p->count = 0;
+    p->start_tm.tv_sec = p->start_tm.tv_usec = 0;
+    p->hnd_tm_sum.tv_sec = p->hnd_tm_sum.tv_usec = 0;
+    p->count = 0;
 #endif
-       p->mod_refcounted = 0;
-       //p->proc_prio = 0;
-       //p->proc_sched = 0;    
-       //p->spid = -1;
-       //p->irq = 0;
-       //p->task_flags = 0;
-       /*
-       // Check are we probing a module
-       if ((probed_mod = module_text_address((unsigned long) p->addr))) {
-       struct module *calling_mod = module_text_address(called_from);
-       // We must allow modules to probe themself and
-       // in this case avoid incrementing the module refcount,
-       // so as to allow unloading of self probing modules.
-       //
-       if (calling_mod && (calling_mod != probed_mod)) {
-       if (unlikely(!try_module_get(probed_mod)))
-       return -EINVAL;
-       p->mod_refcounted = 1;
-       } else
-       probed_mod = NULL;
-       }
-        */
-       p->nmissed = 0;
-       //      mutex_lock(&kprobe_mutex);
-       old_p = get_kprobe (p->addr, 0, NULL);
-       if (old_p)
-       {
-               ret = register_aggr_kprobe (old_p, p);
-               if (!ret)
-                       atomic_inc (&kprobe_count);
-               goto out;
-       }
-
-       if ((ret = arch_prepare_kprobe (p)) != 0)
-               goto out;
-
-       DBPRINTF ("before out ret = 0x%x\n", ret);
-
-       INIT_HLIST_NODE (&p->hlist);
-       hlist_add_head_rcu (&p->hlist, &kprobe_table[hash_ptr (p->addr, KPROBE_HASH_BITS)]);
-
-       /*      if (atomic_add_return(1, &kprobe_count) == \
-               (ARCH_INACTIVE_KPROBE_COUNT + 1))
-               register_page_fault_notifier(&kprobe_page_fault_nb);*/
-
-       arch_arm_kprobe (p);
+    p->mod_refcounted = 0;
+    p->nmissed = 0;
+
+    old_p = get_kprobe (p->addr, 0, NULL);
+    if (old_p)
+    {
+        ret = register_aggr_kprobe (old_p, p);
+        if (!ret)
+            atomic_inc (&kprobe_count);
+        goto out;
+    }
+
+    if ((ret = arch_prepare_kprobe (p)) != 0)
+        goto out;
+
+    DBPRINTF ("before out ret = 0x%x\n", ret);
+    INIT_HLIST_NODE (&p->hlist);
+    hlist_add_head_rcu (&p->hlist, &kprobe_table[hash_ptr (p->addr, KPROBE_HASH_BITS)]);
+    arch_arm_kprobe (p);
 
 out:
-       //      mutex_unlock(&kprobe_mutex);
-       /*
-          if (ret && probed_mod)
-          module_put(probed_mod);
-        */
-       DBPRINTF ("out ret = 0x%x\n", ret);
-
-       return ret;
+    DBPRINTF ("out ret = 0x%x\n", ret);
+    return ret;
 }
 
-
-int dbi_register_kprobe (struct kprobe *p, int atomic)
+void dbi_unregister_kprobe (struct kprobe *p, struct task_struct *task)
 {
-       return __dbi_register_kprobe (p, (unsigned long) __builtin_return_address (0), atomic);
-}
-
-void dbi_unregister_kprobe (struct kprobe *p, struct task_struct *task, int atomic)
-{
-       //      struct module *mod;
        struct kprobe *old_p, *list_p;
-       int cleanup_p, pid = 0;
-
-       //      mutex_lock(&kprobe_mutex);
-
-       pid = p->tgid;
+       int cleanup_p, pid = p->tgid;
 
        old_p = get_kprobe (p->addr, pid, NULL);
        DBPRINTF ("dbi_unregister_kprobe p=%p old_p=%p", p, old_p);
        if (unlikely (!old_p))
-       {
-               //              mutex_unlock(&kprobe_mutex);
                return;
-       }
+
        if (p != old_p)
        {
-               list_for_each_entry_rcu (list_p, &old_p->list, list) 
+               list_for_each_entry_rcu (list_p, &old_p->list, list)
                        if (list_p == p)
                                /* kprobe p is a valid probe */
                                goto valid_p;
-               //              mutex_unlock(&kprobe_mutex);
                return;
        }
+
 valid_p:
        DBPRINTF ("dbi_unregister_kprobe valid_p");
-       if ((old_p == p) || ((old_p->pre_handler == aggr_pre_handler) && 
+       if ((old_p == p) || ((old_p->pre_handler == aggr_pre_handler) &&
                                (p->list.next == &old_p->list) && (p->list.prev == &old_p->list)))
        {
                /* Only probe on the hash list */
@@ -620,14 +565,7 @@ valid_p:
                cleanup_p = 0;
        }
        DBPRINTF ("dbi_unregister_kprobe cleanup_p=%d", cleanup_p);
-       //      mutex_unlock(&kprobe_mutex);
 
-       //      synchronize_sched();
-       /*
-          if (p->mod_refcounted &&
-          (mod = module_text_address((unsigned long)p->addr)))
-          module_put(mod);
-        */
        if (cleanup_p)
        {
                if (p != old_p)
@@ -639,7 +577,6 @@ valid_p:
        }
        else
        {
-               ///             mutex_lock(&kprobe_mutex);
                if (p->break_handler)
                        old_p->break_handler = NULL;
                if (p->post_handler)
@@ -655,32 +592,21 @@ valid_p:
                        if (cleanup_p == 0)
                                old_p->post_handler = NULL;
                }
-               //              mutex_unlock(&kprobe_mutex);
        }
-
-       /* Call unregister_page_fault_notifier()
-        * if no probes are active
-        */
-       //      mutex_lock(&kprobe_mutex);
-       /*      if (atomic_add_return(-1, &kprobe_count) == \
-               ARCH_INACTIVE_KPROBE_COUNT)
-               unregister_page_fault_notifier(&kprobe_page_fault_nb);*/
-       //      mutex_unlock(&kprobe_mutex);
-       return;
 }
 
-int dbi_register_jprobe (struct jprobe *jp, int atomic)
+int dbi_register_jprobe (struct jprobe *jp)
 {
        /* Todo: Verify probepoint is a function entry point */
        jp->kp.pre_handler = setjmp_pre_handler;
        jp->kp.break_handler = longjmp_break_handler;
 
-       return __dbi_register_kprobe (&jp->kp, (unsigned long) __builtin_return_address (0), atomic);
+       return dbi_register_kprobe (&jp->kp);
 }
 
-void dbi_unregister_jprobe (struct jprobe *jp, int atomic)
+void dbi_unregister_jprobe (struct jprobe *jp)
 {
-       dbi_unregister_kprobe (&jp->kp, 0, atomic);
+       dbi_unregister_kprobe (&jp->kp, 0);
 }
 
 /*
@@ -746,12 +672,11 @@ int alloc_nodes_kretprobe(struct kretprobe *rp)
      return 0;
 }
 
-int dbi_register_kretprobe (struct kretprobe *rp, int atomic)
+int dbi_register_kretprobe (struct kretprobe *rp)
 {
        int ret = 0;
        struct kretprobe_instance *inst;
        int i;
-       int priority = atomic ? GFP_ATOMIC : GFP_KERNEL;
        DBPRINTF ("START");
 
        rp->kp.pre_handler = pre_handler_kretprobe;
@@ -776,7 +701,7 @@ int dbi_register_kretprobe (struct kretprobe *rp, int atomic)
        INIT_HLIST_HEAD (&rp->free_instances);
        for (i = 0; i < rp->maxactive; i++)
        {
-               inst = kmalloc (sizeof (struct kretprobe_instance), priority);
+               inst = kmalloc (sizeof (struct kretprobe_instance), GFP_KERNEL);
                if (inst == NULL)
                {
                        free_rp_inst (rp);
@@ -789,7 +714,7 @@ int dbi_register_kretprobe (struct kretprobe *rp, int atomic)
        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)));
        rp->nmissed = 0;
        /* Establish function entry probe point */
-       if ((ret = __dbi_register_kprobe (&rp->kp, (unsigned long) __builtin_return_address (0), atomic)) != 0)
+       if ((ret = dbi_register_kprobe (&rp->kp)) != 0)
                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)));
@@ -799,12 +724,12 @@ int dbi_register_kretprobe (struct kretprobe *rp, int atomic)
        return ret;
 }
 
-void dbi_unregister_kretprobe (struct kretprobe *rp, int atomic)
+void dbi_unregister_kretprobe (struct kretprobe *rp)
 {
        unsigned long flags;
        struct kretprobe_instance *ri;
 
-       dbi_unregister_kprobe (&rp->kp, 0, atomic);
+       dbi_unregister_kprobe (&rp->kp, 0);
 
        if((unsigned int)rp->kp.addr == sched_addr)
                sched_rp = NULL;
index a0a500b..2e7bbe0 100644 (file)
  * 2006-2007    Ekaterina Gorelkina <e.gorelkina@samsung.com>: initial implementation for ARM and MIPS
  * 2008-2009    Alexey Gerenkov <a.gerenkov@samsung.com> User-Space
  *              Probes initial implementation; Support x86/ARM/MIPS for both user and kernel spaces.
- * 2010         Ekaterina Gorelkina <e.gorelkina@samsung.com>: redesign module for separating core and arch parts 
+ * 2010         Ekaterina Gorelkina <e.gorelkina@samsung.com>: redesign module for separating core and arch parts
  *
-
  */
 
 
-
 #include <linux/version.h>     // LINUX_VERSION_CODE, KERNEL_VERSION()
-
-//#include <linux/list.h>
 #include <linux/notifier.h>
-//#include <linux/smp.h>
 #include <linux/percpu.h>
 #include <linux/spinlock.h>
 #include <linux/rcupdate.h>
@@ -234,8 +229,8 @@ struct kprobe *get_kprobe_by_insn_slot (void *addr, int tgid, struct task_struct
 struct hlist_head *kretprobe_inst_table_head (void *hash_key);
 
 
-int dbi_register_kprobe (struct kprobe *p, int atomic);
-void dbi_unregister_kprobe (struct kprobe *p, struct task_struct *task, int atomic);
+int dbi_register_kprobe (struct kprobe *p);
+void dbi_unregister_kprobe (struct kprobe *p, struct task_struct *task);
 
 int register_aggr_kprobe (struct kprobe *old_p, struct kprobe *p);
 int pre_handler_kretprobe (struct kprobe *p, struct pt_regs *regs);
@@ -243,8 +238,8 @@ int pre_handler_kretprobe (struct kprobe *p, struct pt_regs *regs);
 int setjmp_pre_handler (struct kprobe *, struct pt_regs *);
 int longjmp_break_handler (struct kprobe *, struct pt_regs *);
 
-int dbi_register_jprobe (struct jprobe *p, int atomic);
-void dbi_unregister_jprobe (struct jprobe *p, int atomic);
+int dbi_register_jprobe (struct jprobe *p);
+void dbi_unregister_jprobe (struct jprobe *p);
 void dbi_jprobe_return (void);
 void dbi_jprobe_return_end (void);
 
@@ -253,10 +248,10 @@ struct kretprobe_instance * get_used_rp_inst (struct kretprobe *rp);
 
 
 int alloc_nodes_kretprobe(struct kretprobe *rp);
-int dbi_register_kretprobe (struct kretprobe *rp, int atomic);
-void dbi_unregister_kretprobe (struct kretprobe *rp, int atomic);
+int dbi_register_kretprobe (struct kretprobe *rp);
+void dbi_unregister_kretprobe (struct kretprobe *rp);
 
-void kretprobe_assert (struct kretprobe_instance *ri, 
+void kretprobe_assert (struct kretprobe_instance *ri,
                unsigned long orig_ret_address, unsigned long trampoline_address);
 
 
index d2bf5bf..d69cd8b 100644 (file)
@@ -139,7 +139,7 @@ out:
 
 void unregister_uprobe (struct kprobe *p, struct task_struct *task, int atomic)
 {
-       dbi_unregister_kprobe (p, task, atomic);
+       dbi_unregister_kprobe (p, task);
 }