[IMPROVE] create slot_manager
[kernel/swap-modules.git] / driver / us_proc_inst.c
index 8d269aa..b14eb70 100644 (file)
 #include "us_proc_inst.h"
 
 #include "../kprobe/dbi_kprobes_deps.h"
-#include "../kprobe/dbi_uprobes.h"
+#include "../uprobe/swap_uprobes.h"
 
-DEFINE_PER_CPU (us_proc_vtp_t *, gpVtp) = NULL;
-DEFINE_PER_CPU (struct pt_regs *, gpCurVtpRegs) = NULL;
+#include "sspt/sspt.h"
+#include "java_inst.h"
+
+#include <dbi_insn_slots.h>
+
+#define mm_read_lock(task, mm, atomic, lock)                   \
+       mm = atomic ? task->active_mm : get_task_mm(task);      \
+       if (mm == NULL) {                                       \
+               /* FIXME: */                                    \
+               panic("ERRR mm_read_lock: mm == NULL\n");       \
+       }                                                       \
+                                                               \
+       if (atomic) {                                           \
+               lock = down_read_trylock(&mm->mmap_sem);        \
+       } else {                                                \
+               lock = 1;                                       \
+               down_read(&mm->mmap_sem);                       \
+       }
+
+#define mm_read_unlock(mm, atomic, lock)                       \
+       if (lock) {                                             \
+               up_read(&mm->mmap_sem);                         \
+       }                                                       \
+                                                               \
+       if (!atomic) {                                          \
+               mmput(mm);                                      \
+       }
 
 #if defined(CONFIG_MIPS)
 #      define ARCH_REG_VAL(regs, idx)  regs->regs[idx]
@@ -33,35 +58,15 @@ DEFINE_PER_CPU (struct pt_regs *, gpCurVtpRegs) = NULL;
 #      warning ARCH_REG_VAL is not implemented for this architecture. FBI will work improperly or even crash!!!
 #endif // ARCH
 
-unsigned long (*dbi_ujprobe_event_pre_handler_custom_p)
-(us_proc_ip_t *, struct pt_regs *) = NULL;
-EXPORT_SYMBOL(dbi_ujprobe_event_pre_handler_custom_p);
-void (*dbi_ujprobe_event_handler_custom_p)(void) = NULL;
-EXPORT_SYMBOL(dbi_ujprobe_event_handler_custom_p);
-int (*dbi_uretprobe_event_handler_custom_p)
-(struct kretprobe_instance *, struct pt_regs *, us_proc_ip_t *) = NULL;
-EXPORT_SYMBOL(dbi_uretprobe_event_handler_custom_p);
-
-unsigned long ujprobe_event_pre_handler (us_proc_ip_t * ip, struct pt_regs *regs);
+unsigned long ujprobe_event_pre_handler (struct us_ip *ip, struct pt_regs *regs);
 void ujprobe_event_handler (unsigned long arg1, unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5, unsigned long arg6);
-int uretprobe_event_handler (struct kretprobe_instance *probe, struct pt_regs *regs, us_proc_ip_t * ip);
+int uretprobe_event_handler(struct uretprobe_instance *probe, struct pt_regs *regs, struct us_ip *ip);
 
-static int register_usprobe (struct task_struct *task, struct mm_struct *mm, us_proc_ip_t * ip, int atomic, kprobe_opcode_t * islot);
-static int unregister_usprobe (struct task_struct *task, us_proc_ip_t * ip, int atomic);
 
 int us_proc_probes;
 
-struct task_inst_info_node {
-       struct list_head      plist;
-       inst_us_proc_t *      task_inst_info;
-       int                   tgid;
-};
-LIST_HEAD(task_inst_info_list);
+LIST_HEAD(proc_probes_list);
 
-#ifdef SLP_APP
-struct dentry *launchpad_daemon_dentry = NULL;
-EXPORT_SYMBOL_GPL(launchpad_daemon_dentry);
-#endif /* SLP_APP */
 
 #ifdef ANDROID_APP
 unsigned long android_app_vma_start = 0;
@@ -69,217 +74,147 @@ unsigned long android_app_vma_end = 0;
 struct dentry *app_process_dentry = NULL;
 #endif /* ANDROID_APP */
 
-#ifdef __ANDROID
-struct dentry *libdvm_dentry = NULL;
-/* Defines below are for libdvm.so with md5sum:
- * 5941c87b49198368e7db726c2977bf1d */
-#define LIBDVM_ENTRY 0x30a64
-#define LIBDVM_RETURN 0x30bdc
-#endif /* __ANDROID */
-
-us_proc_otg_ip_t *find_otg_probe(unsigned long addr)
-{
-       us_proc_otg_ip_t *p;
-
-       list_for_each_entry_rcu (p, &otg_us_proc_info, list) {
-               if (p->ip.offset == addr) {
-                       return p;
-               }
-       }
+#ifdef SLP_APP
+static struct dentry *launchpad_daemon_dentry = NULL;
+EXPORT_SYMBOL_GPL(launchpad_daemon_dentry);
+#endif /* SLP_APP */
 
-       return NULL;
+#define print_event(fmt, args...)                                              \
+{                                                                              \
+       char *buf[1024];                                                        \
+       sprintf(buf, fmt, ##args);                                              \
+       pack_event_info(US_PROBE_ID, RECORD_ENTRY, "ds", 0x0badc0de, buf);      \
 }
 
-int add_otg_probe_to_list(unsigned long addr, us_proc_otg_ip_t **pprobe)
+static inline int is_libonly(void)
 {
-       us_proc_otg_ip_t *new_probe;
-       us_proc_otg_ip_t *probe;
-
-       if (pprobe) {
-               *pprobe = NULL;
-       }
-       /* check if such probe does already exist */
-       probe = find_otg_probe(addr);
-       if (probe) {
-               return 1;
-       }
-
-       new_probe = kmalloc(sizeof(us_proc_otg_ip_t), GFP_KERNEL);
-       if (!new_probe) {
-               EPRINTF ("no memory for new probe!");
-               return -ENOMEM;
-       }
-       memset(new_probe,0, sizeof(us_proc_otg_ip_t));
-
-       new_probe->ip.offset = addr;
-       new_probe->ip.jprobe.kp.addr =
-               new_probe->ip.retprobe.kp.addr = (kprobe_opcode_t *)addr;
-       new_probe->ip.jprobe.priv_arg =
-               new_probe->ip.retprobe.priv_arg = new_probe;
-
-       INIT_LIST_HEAD(&new_probe->list);
-       list_add_rcu(&new_probe->list, &otg_us_proc_info);
-
-       if (pprobe) {
-               *pprobe = new_probe;
-       }
-       return 0;
+       return !strcmp(us_proc_info.path,"*");
 }
 
-int remove_otg_probe_from_list(unsigned long addr)
+// is user-space instrumentation
+static inline int is_us_instrumentation(void)
 {
-       us_proc_otg_ip_t *p;
-
-       //check if such probe does exist
-       p = find_otg_probe(addr);
-       if (!p) {
-               /* We do not care about it. Nothing bad. */
-               return 0;
-       }
-
-       list_del_rcu(&p->list);
-
-       kfree (p);
-
-       return 0;
+       return !!us_proc_info.path;
 }
 
-/**
- * Prepare copy of instrumentation data for task
- * in case of library only instrumentation
- */
-
-inst_us_proc_t* copy_task_inst_info (struct task_struct *task, inst_us_proc_t * task_inst_info)
+static unsigned long alloc_user_pages(struct task_struct *task, unsigned long len, unsigned long prot, unsigned long flags)
 {
-       int i, j;
-       kprobe_opcode_t *entry_save;
-       kprobe_pre_entry_handler_t pre_entry_save;
-       kretprobe_handler_t handler_save;
-
-       inst_us_proc_t* copy_info = 0;
-
-       int unres_ips_count = 0, unres_vtps_count = 0;
-
-       copy_info = kmalloc (sizeof (inst_us_proc_t), GFP_ATOMIC);
-       memset ((void *) copy_info, 0, sizeof (inst_us_proc_t));
-
-       copy_info->path = task_inst_info->path;
-       copy_info->m_f_dentry = NULL;
-
-       copy_info->libs_count = task_inst_info->libs_count;
-       copy_info->p_libs =
-               kmalloc (task_inst_info->libs_count * sizeof (us_proc_lib_t), GFP_ATOMIC);
-
-       if (!copy_info->p_libs) {
-               DPRINTF ("No enough memory for copy_info->p_libs");
-               return NULL;
-       }
-       memcpy (copy_info->p_libs, task_inst_info->p_libs,
-                       copy_info->libs_count * sizeof (us_proc_lib_t));
-
-       for (i = 0; i < copy_info->libs_count; i++) {
-               if (copy_info->p_libs[i].ips_count > 0)
-               {
-                       unres_ips_count += copy_info->p_libs[i].ips_count;
+       unsigned long ret = 0;
+       struct task_struct *otask = current;
+       struct mm_struct *mm;
+       int atomic = in_atomic();
 
-                       copy_info->p_libs[i].p_ips =
-                               kmalloc (copy_info->p_libs[i].ips_count * sizeof (us_proc_ip_t), GFP_ATOMIC);
+       mm = atomic ? task->active_mm : get_task_mm (task);
+       if (mm) {
+               if (!atomic) {
+                       if (!down_write_trylock(&mm->mmap_sem)) {
+                               rcu_read_lock();
 
-                       if (!copy_info->p_libs[i].p_ips) {
-                               DPRINTF ("No enough memory for copy_info->p_libs[i].p_ips");
-                               return NULL;
-                       }
+                               up_read(&mm->mmap_sem);
+                               down_write(&mm->mmap_sem);
 
-                       memcpy (copy_info->p_libs[i].p_ips, task_inst_info->p_libs[i].p_ips,
-                                       copy_info->p_libs[i].ips_count * sizeof (us_proc_ip_t));
-                       for (j = 0; j < copy_info->p_libs[i].ips_count; j++) {
-                               // save handlers
-                               entry_save = copy_info->p_libs[i].p_ips[j].jprobe.entry;
-                               pre_entry_save = copy_info->p_libs[i].p_ips[j].jprobe.pre_entry;
-                               handler_save = copy_info->p_libs[i].p_ips[j].retprobe.handler;
-
-                               copy_info->p_libs[i].p_ips[j].installed = 0;
-                               memset(&copy_info->p_libs[i].p_ips[j].jprobe, 0, sizeof(struct jprobe));
-                               memset(&copy_info->p_libs[i].p_ips[j].retprobe, 0, sizeof(struct kretprobe));
-
-                               // restore handlers
-                               copy_info->p_libs[i].p_ips[j].jprobe.entry = entry_save;
-                               copy_info->p_libs[i].p_ips[j].jprobe.pre_entry = pre_entry_save;
-                               copy_info->p_libs[i].p_ips[j].retprobe.handler = handler_save;
+                               rcu_read_unlock();
                        }
-
-                       unres_ips_count += copy_info->p_libs[i].ips_count;
                }
-
-               for (j = 0; j < copy_info->p_libs[i].plt_count; j++)
-               {
-                       copy_info->p_libs[i].p_plt[j].real_func_addr = 0;
+               // FIXME: its seems to be bad decision to replace 'current' pointer temporarily
+               current_thread_info()->task = task;
+               ret = do_mmap_pgoff(NULL, 0, len, prot, flags, 0);
+               current_thread_info()->task = otask;
+               if (!atomic) {
+                       downgrade_write (&mm->mmap_sem);
+                       mmput(mm);
                }
+       } else {
+               printk("proc %d has no mm", task->tgid);
+       }
 
-               if (copy_info->p_libs[i].vtps_count > 0) {
-                       unres_vtps_count += copy_info->p_libs[i].vtps_count;
-
-                       copy_info->p_libs[i].p_vtps =
-                               kmalloc (copy_info->p_libs[i].vtps_count * sizeof (us_proc_vtp_t), GFP_ATOMIC);
+       return ret;
+}
 
-                       if (!copy_info->p_libs[i].p_vtps) {
-                               DPRINTF ("No enough memory for copy_info->p_libs[i].p_vtps");
-                               return NULL;
-                       }
+static void *sm_alloc_us(struct slot_manager *sm)
+{
+       struct task_struct *task = sm->data;
 
-                       memcpy (copy_info->p_libs[i].p_vtps, task_inst_info->p_libs[i].p_vtps,
-                                       copy_info->p_libs[i].vtps_count * sizeof (us_proc_vtp_t));
-                       for (j = 0; j < copy_info->p_libs[i].vtps_count; j++) {
-                               copy_info->p_libs[i].p_vtps[j].installed = 0;
-                               memset (&copy_info->p_libs[i].p_vtps[j].jprobe, 0, sizeof(struct jprobe));
-                       }
-                       unres_vtps_count = copy_info->p_libs[i].vtps_count;
-               }
+       return (void *)alloc_user_pages(task, PAGE_SIZE,
+                                       PROT_EXEC|PROT_READ|PROT_WRITE,
+                                       MAP_ANONYMOUS|MAP_PRIVATE);
+}
 
-               copy_info->p_libs[i].m_f_dentry = task_inst_info->p_libs[i].m_f_dentry;
-               copy_info->p_libs[i].loaded = 0;
+static void sm_free_us(struct slot_manager *sm, void *ptr)
+{
+       struct task_struct *task = sm->data;
 
-               copy_info->p_libs[i].vma_start = 0;
-               copy_info->p_libs[i].vma_end = 0;
+       /*
+        * E. G.: This code provides kernel dump because of rescheduling while atomic.
+        * As workaround, this code was commented. In this case we will have memory leaks
+        * for instrumented process, but instrumentation process should functionate correctly.
+        * Planned that good solution for this problem will be done during redesigning KProbe
+        * for improving supportability and performance.
+        */
+#if 0
+       mm = get_task_mm(task);
+       if (mm) {
+               down_write(&mm->mmap_sem);
+               do_munmap(mm, (unsigned long)(ptr), PAGE_SIZE);
+               up_write(&mm->mmap_sem);
+               mmput(mm);
        }
-       copy_info->unres_ips_count = unres_ips_count;
-       copy_info->unres_vtps_count = unres_vtps_count;
-
-       return copy_info;
+#endif
+       /* FIXME: implement the removal of memory for task */
 }
 
-inst_us_proc_t* get_task_inst_node(struct task_struct *task)
+struct slot_manager *create_sm_us(struct task_struct *task)
 {
-       struct task_inst_info_node *node, *tnode;
+       struct slot_manager *sm = kmalloc(sizeof(*sm), GFP_ATOMIC);
+       sm->slot_size = UPROBES_TRAMP_LEN;
+       sm->alloc = sm_alloc_us;
+       sm->free = sm_free_us;
+       INIT_HLIST_NODE(&sm->page_list);
+       sm->data = task;
+}
 
-       list_for_each_entry_safe(node, tnode, &task_inst_info_list, plist)
-       {
-               if (node && task && node->tgid == task->tgid) {
-                       return node->task_inst_info;
-               }
-       }
-       return NULL;
+void free_sm_us(struct slot_manager *sm)
+{
+       /* FIXME: free */
 }
 
-void put_task_inst_node(struct task_struct *task, inst_us_proc_t *task_inst_info)
+static struct sspt_procs *get_proc_probes_by_task(struct task_struct *task)
 {
-       struct task_inst_info_node * node;
+       struct sspt_procs *procs, *tmp;
 
-       node = kmalloc (sizeof(struct task_inst_info_node), GFP_ATOMIC);
+       if (!is_libonly()) {
+               if (task != current) {
+                       printk("ERROR get_proc_probes_by_task: \'task != current\'\n");
+                       return NULL;
+               }
 
-       node->tgid = task->tgid;
-       node->task_inst_info = task_inst_info;
+               return us_proc_info.pp;
+       }
 
-       list_add_tail (&(node->plist), &task_inst_info_list);
+       list_for_each_entry_safe(procs, tmp, &proc_probes_list, list) {
+               if (procs->tgid == task->tgid) {
+                       return procs;
+               }
+       }
+
+       return NULL;
 }
 
+static void add_proc_probes(struct task_struct *task, struct sspt_procs *procs)
+{
+       list_add_tail(&procs->list, &proc_probes_list);
+}
 
-void clear_task_inst_info(void)
+static struct sspt_procs *get_proc_probes_by_task_or_new(struct task_struct *task)
 {
-       struct list_head *node, *tmp;
+       struct sspt_procs *procs = get_proc_probes_by_task(task);
+       if (procs == NULL) {
+               procs = sspt_procs_copy(us_proc_info.pp, task);
+               procs->sm = create_sm_us(task);
+               add_proc_probes(task, procs);
+       }
 
-       list_for_each_safe(node, tmp, &task_inst_info_list)
-               list_del(node);
+       return procs;
 }
 
 #ifdef SLP_APP
@@ -329,29 +264,43 @@ static int is_android_app_with_dentry(struct vm_area_struct *vma,
 }
 #endif /* ANDROID_APP */
 
-#ifdef __ANDROID
-void find_libdvm_for_task(struct task_struct *task, inst_us_proc_t *info)
+struct dentry *dentry_by_path(const char *path)
 {
-       struct vm_area_struct *vma = NULL;
-       struct mm_struct *mm = NULL;
-
-       mm = get_task_mm(task);
-       if (mm) {
-               vma = mm->mmap;
-               while (vma) {
-                       if (vma->vm_file) {
-                               if (vma->vm_file->f_dentry == libdvm_dentry) {
-                                       info->libdvm_start = vma->vm_start;
-                                       info->libdvm_end = vma->vm_end;
-                                       break;
-                               }
-                       }
-                       vma = vma->vm_next;
-               }
-               mmput(mm);
+       struct dentry *dentry;
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 38)
+       struct path st_path;
+       if (kern_path(path, LOOKUP_FOLLOW, &st_path) != 0) {
+#else /* LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 38) */
+       struct nameidata nd;
+       if (path_lookup(path, LOOKUP_FOLLOW, &nd) != 0) {
+#endif /* LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 38) */
+               EPRINTF("failed to lookup dentry for path %s!", path);
+               return NULL;
        }
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25)
+       dentry = nd.dentry;
+       path_release(&nd);
+#elif LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 38)
+       dentry = nd.path.dentry;
+       path_put(&nd.path);
+#else /* LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 38) */
+       dentry = st_path.dentry;
+       path_put(&st_path);
+#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25) */
+       return dentry;
+}
+
+static int check_vma(struct vm_area_struct *vma)
+{
+#ifndef __ANDROID
+       return vma->vm_file && !(vma->vm_pgoff != 0 || !(vma->vm_flags & VM_EXEC) || (vma->vm_flags & VM_ACCOUNT) ||
+                       !(vma->vm_flags & (VM_WRITE | VM_MAYWRITE)) ||
+                       !(vma->vm_flags & (VM_READ | VM_MAYREAD)));
+#else // __ANDROID
+       return vma->vm_file && !(vma->vm_pgoff != 0 || !(vma->vm_flags & VM_EXEC));
+#endif // __ANDROID
 }
-#endif /* __ANDROID */
 
 static int find_task_by_path (const char *path, struct task_struct **p_task, struct list_head *tids)
 {
@@ -359,23 +308,14 @@ static int find_task_by_path (const char *path, struct task_struct **p_task, str
        struct task_struct *task;
        struct vm_area_struct *vma;
        struct mm_struct *mm;
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 38)
-       struct path s_path;
-#else /* LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 38) */
-       struct nameidata nd;
-#endif /* LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 38) */
+       struct dentry *dentry = dentry_by_path(path);
 
-       *p_task = 0;
+       *p_task = NULL;
 
        /* find corresponding dir entry, this is also check for valid path */
        // TODO: test - try to instrument process with non-existing path
        // TODO: test - try to instrument process  with existing path and delete file just after start
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 38)
-       if (kern_path(us_proc_info.path, LOOKUP_FOLLOW, &s_path) != 0) {
-#else /* LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 38) */
-       if (path_lookup(us_proc_info.path, LOOKUP_FOLLOW, &nd) != 0) {
-#endif /* LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 38) */
-               EPRINTF ("failed to lookup dentry for path %s!", path);
+       if (dentry == NULL) {
                return -EINVAL;
        }
 
@@ -390,16 +330,8 @@ static int find_task_by_path (const char *path, struct task_struct **p_task, str
                        continue;
                vma = mm->mmap;
                while (vma) {
-                       if ((vma->vm_flags & VM_EXECUTABLE) && vma->vm_file) {
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25)
-                               if (vma->vm_file->f_dentry == nd.dentry) {
-#else
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 38)
-                               if (vma->vm_file->f_dentry == s_path.dentry  ) {
-#else /* LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 38) */
-                               if (vma->vm_file->f_dentry == nd.path.dentry  ) {
-#endif /* LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 38) */
-#endif
+                       if (check_vma(vma)) {
+                               if (vma->vm_file->f_dentry == dentry) {
                                        if (!*p_task) {
                                                *p_task = task;
                                                get_task_struct (task);
@@ -408,15 +340,7 @@ static int find_task_by_path (const char *path, struct task_struct **p_task, str
                                }
 #ifdef SLP_APP
                                if (!*p_task) {
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25)
-                                       if (is_slp_app_with_dentry(vma, nd.dentry)) {
-#else
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 38)
-                                       if (is_slp_app_with_dentry(vma, s_path.dentry)) {
-#else /* LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 38) */
-                                       if (is_slp_app_with_dentry(vma, nd.path.dentry)) {
-#endif /* LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 38) */
-#endif
+                                       if (is_slp_app_with_dentry(vma, dentry)) {
                                                *p_task = task;
                                                get_task_struct(task);
                                        }
@@ -424,15 +348,7 @@ static int find_task_by_path (const char *path, struct task_struct **p_task, str
 #endif /* SLP_APP */
 #ifdef ANDROID_APP
                                if (!*p_task) {
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25)
-                                       if (is_android_app_with_dentry(vma, nd.dentry)) {
-#else
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 38)
-                                       if (is_android_app_with_dentry(vma, s_path.dentry)) {
-#else /* LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 38) */
-                                       if (is_android_app_with_dentry(vma, nd.path.dentry)) {
-#endif /* LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 38) */
-#endif
+                                       if (is_android_app_with_dentry(vma, dentry)) {
                                                *p_task = task;
                                                get_task_struct(task);
                                        }
@@ -456,517 +372,76 @@ static int find_task_by_path (const char *path, struct task_struct **p_task, str
                DPRINTF ("pid for %s not found!", path);
        }
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25)
-       path_release (&nd);
-#else
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 38)
-       path_put (&s_path);
-#else /* LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 38) */
-       path_put (&nd.path);
-#endif /* LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 38) */
-#endif
        return 0;
 }
 
+static void set_mapping_file(struct sspt_file *file,
+               const struct sspt_procs *procs,
+               const struct task_struct *task,
+               const struct vm_area_struct *vma);
 
-static void us_vtp_event_pre_handler (us_proc_vtp_t * vtp, struct pt_regs *regs)
+int install_otg_ip(unsigned long addr,
+                       kprobe_pre_entry_handler_t pre_handler,
+                       unsigned long jp_handler,
+                       uretprobe_handler_t rp_handler)
 {
-       __get_cpu_var(gpVtp) = vtp;
-       __get_cpu_var(gpCurVtpRegs) = regs;
-}
+       int ret = 0;
+       struct task_struct *task = current->group_leader;
+       struct mm_struct *mm = task->mm;
 
-static void us_vtp_event_handler (unsigned long arg1, unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5, unsigned long arg6)
-{
-       us_proc_vtp_t *vtp = __get_cpu_var(gpVtp);
-#if !defined(CONFIG_X86)
-       struct pt_regs *regs = __get_cpu_var(gpCurVtpRegs);
-#endif
-       char fmt[4];
-       unsigned long vaddr;
-       long ival;
-       char cval, *sval;
-       us_proc_vtp_data_t *vtp_data;
-unsigned long ll;
-       fmt[0] = 'p';
-       fmt[3] = 0;
-       fmt[2] = 's';
-
-       list_for_each_entry_rcu (vtp_data, &vtp->list, list) {
-               //              DPRINTF ("[%d]proc %s(%d): %lx", nCount++, current->comm, current->pid, vtp->addr);
-               fmt[1] = vtp_data->type;
-               if (vtp_data->reg == -1)
-                       vaddr = vtp_data->off;
-               else
-                       vaddr = ARCH_REG_VAL (regs, vtp_data->reg) + vtp_data->off;
-               //              DPRINTF ("VTP type '%c'", vtp_data->type);
-               switch (vtp_data->type)
-               {
-                       case 'd':
-                       case 'x':
-                       case 'p':
-                               if (read_proc_vm_atomic (current, vaddr, &ival, sizeof (ival)) < sizeof (ival))
-                                       EPRINTF ("failed to read vm of proc %s/%u addr %lu!", current->comm, current->pid, vaddr);
-                               else
-                                       pack_event_info (VTP_PROBE_ID, RECORD_ENTRY, fmt, vtp->jprobe.kp.addr, ival, vtp_data->name);
-                               break;
-                       case 'f':
-                               if (read_proc_vm_atomic (current, vaddr, &ival, sizeof (ival)) < sizeof (ival))
-                                       EPRINTF ("failed to read vm of proc %s/%u addr %lu!", current->comm, current->pid, vaddr);
-                               else
-                                       pack_event_info (VTP_PROBE_ID, RECORD_ENTRY, fmt, vtp->jprobe.kp.addr, ival, vtp_data->name);
-                               break;
-                       case 'c':
-                               if (read_proc_vm_atomic (current, vaddr, &cval, sizeof (cval)) < sizeof (cval))
-                                       EPRINTF ("failed to read vm of proc %s/%u addr %lu!", current->comm, current->pid, vaddr);
-                               else
-                                       pack_event_info (VTP_PROBE_ID, RECORD_ENTRY, fmt, vtp->jprobe.kp.addr, cval, vtp_data->name);
-                               break;
-                       case 's':
-                               if (current->active_mm) {
-                                       struct page *page;
-                                       struct vm_area_struct *vma;
-                                       void *maddr;
-                                       int len;
-                                       if (get_user_pages_atomic (current, current->active_mm, vaddr, 1, 0, 1, &page, &vma) <= 0) {
-                                               EPRINTF ("get_user_pages_atomic failed for proc %s/%u addr %lu!", current->comm, current->pid, vaddr);
-                                               break;
-                                       }
-                                       maddr = kmap_atomic (page, KM_USER0);
-                                       len = strlen (maddr + (vaddr & ~PAGE_MASK));
-                                       sval = kmalloc (len + 1, GFP_KERNEL);
-                                       if (!sval)
-                                               EPRINTF ("failed to alloc memory for string in proc %s/%u addr %lu!", current->comm, current->pid, vaddr);
-                                       else {
-                                               copy_from_user_page (vma, page, vaddr, sval, maddr + (vaddr & ~PAGE_MASK), len + 1);
-                                               pack_event_info (VTP_PROBE_ID, RECORD_ENTRY, fmt, vtp->jprobe.kp.addr, sval,  vtp_data->name);
-                                               kfree (sval);
-                                       }
-                                       kunmap_atomic (maddr, KM_USER0);
-                                       page_cache_release (page);
-                               }
-                               else
-                                       EPRINTF ("task %s/%u has no mm!", current->comm, current->pid);
-                               break;
-                       default:
-                               EPRINTF ("unknown variable type '%c'", vtp_data->type);
-               }
-       }
-       dbi_uprobe_return ();
-}
+       if (mm) {
+               struct vm_area_struct *vma = find_vma(mm, addr);
+               if (vma && (vma->vm_flags & VM_EXEC) &&
+                   vma->vm_file && vma->vm_file->f_dentry) {
+                       unsigned long offset_addr = addr - vma->vm_start;
+                       struct dentry *dentry = vma->vm_file->f_dentry;
+                       char *name = dentry->d_iname;
+                       struct sspt_procs *procs = get_proc_probes_by_task(task);
+                       struct ip_data pd = {
+                                       .offset = offset_addr,
+                                       .pre_handler = pre_handler,
+                                       .jp_handler = jp_handler,
+                                       .rp_handler = rp_handler,
+                                       .flag_retprobe = 1
+                       };
+
+                       struct sspt_file *file = sspt_procs_find_file_or_new(procs, dentry, name);
+                       struct sspt_page *page = sspt_get_page(file, offset_addr);
+                       struct us_ip *ip = sspt_find_ip(page, offset_addr & ~PAGE_MASK);
+
+                       if (!file->loaded) {
+                               set_mapping_file(file, procs, task, vma);
+                               file->loaded = 1;
+                       }
 
-static int install_mapped_ips (struct task_struct *task, inst_us_proc_t* task_inst_info, int atomic)
-{
-       struct vm_area_struct *vma;
-       int i, k, err;
-       unsigned long addr;
-       unsigned int old_ips_count, old_vtps_count;
-       us_proc_otg_ip_t *p;
-       struct task_struct *t;
-       struct mm_struct *mm;
+                       if (ip == NULL) {
+                               // TODO: sspt_procs_find_file_or_new --> sspt_procs_find_file ?!
+                               struct sspt_file *file = sspt_procs_find_file_or_new(procs, dentry, name);
+                               sspt_file_add_ip(file, &pd);
 
-       mm = atomic ? task->active_mm : get_task_mm (task);
-       if (!mm) {
-               return task_inst_info->unres_ips_count + task_inst_info->unres_vtps_count;
-       }
-       old_ips_count = task_inst_info->unres_ips_count;
-       old_vtps_count = task_inst_info->unres_vtps_count;
-       if(!atomic)
-               down_read (&mm->mmap_sem);
-       vma = mm->mmap;
-       while (vma) {
-               // skip non-text section
-#ifndef __ANDROID
-               if (vma->vm_pgoff != 0 || !(vma->vm_flags & VM_EXEC) || !vma->vm_file || (vma->vm_flags & VM_ACCOUNT) ||
-                       !(vma->vm_flags & (VM_WRITE | VM_MAYWRITE)) ||
-                       !(vma->vm_flags & (VM_READ | VM_MAYREAD))) {
-#else // __ANDROID
-               if (vma->vm_pgoff != 0 || !(vma->vm_flags & VM_EXEC) || !vma->vm_file) {
-#endif // __ANDROID
-                       vma = vma->vm_next;
-                       continue;
-               }
-               /**
-                * After process was forked, some time it inherits parent process environment.
-                * We need to renew instrumentation when we detect that process gets own environment.
-                */
-               for (i = 0; i < task_inst_info->libs_count; i++) {
-//                     struct path tmp_path;
-//                     tmp_path.dentry = task_inst_info->p_libs[i].m_f_dentry;
-//                     tmp_path.mnt = task_inst_info->p_libs[i].m_vfs_mount;
-//                     char* p_path = d_path ( &tmp_path, path_buffer, 255 );
-//                     DPRINTF("f_dentry:%x m_f_dentry:%x path:%s", vma->vm_file->f_dentry,
-//                             task_inst_info->p_libs[i].m_f_dentry, p_path );
-
-                       //TODO: test - try to instrument non-existing libs
-                       if (vma->vm_file->f_dentry == task_inst_info->p_libs[i].m_f_dentry) {
-//                             DPRINTF("vm_flags:%x loaded:%x ips_count:%d vtps_count:%d",
-//                                             vma->vm_flags, task_inst_info->p_libs[i].loaded,
-//                                             task_inst_info->p_libs[i].ips_count, task_inst_info->p_libs[i].vtps_count );
-                               if (!task_inst_info->p_libs[i].loaded) {
-//                                     DPRINTF("!VM_EXECUTABLE && !loaded");
-                                       char *p;
-                                       int app_flag = (vma->vm_file->f_dentry == task_inst_info->m_f_dentry);
-                                       DPRINTF ("post dyn lib event %s/%s", current->comm, task_inst_info->p_libs[i].path);
-                                       // if we installed something, post library info for those IPs
-                                       p = strrchr(task_inst_info->p_libs[i].path, '/');
-                                       if(!p)
-                                               p = task_inst_info->p_libs[i].path;
-                                       else
-                                               p++;
-                                       task_inst_info->p_libs[i].loaded = 1;
-                                       task_inst_info->p_libs[i].vma_start = vma->vm_start;
-                                       task_inst_info->p_libs[i].vma_end = vma->vm_end;
-                                       task_inst_info->p_libs[i].vma_flag = vma->vm_flags;
-                                       pack_event_info (DYN_LIB_PROBE_ID, RECORD_ENTRY, "dspdd",
-                                                       task->tgid, p, vma->vm_start, vma->vm_end-vma->vm_start, app_flag);
-                               }
-                               for (k = 0; k < task_inst_info->p_libs[i].ips_count; k++) {
-                                       DPRINTF("ips_count current:%d", k);
-                                       if (!task_inst_info->p_libs[i].p_ips[k].installed) {
-                                               DPRINTF("!installed");
-                                               addr = task_inst_info->p_libs[i].p_ips[k].offset;
-                                               addr += vma->vm_start;
-                                               if (page_present (mm, addr)) {
-                                                       DPRINTF ("pid %d, %s sym is loaded at %lx/%lx.",
-                                                               task->pid, task_inst_info->p_libs[i].path,
-                                                               task_inst_info->p_libs[i].p_ips[k].offset, addr);
-                                                       task_inst_info->p_libs[i].p_ips[k].jprobe.kp.addr = (kprobe_opcode_t *) addr;
-                                                       task_inst_info->p_libs[i].p_ips[k].retprobe.kp.addr = (kprobe_opcode_t *) addr;
-                                                       task_inst_info->p_libs[i].p_ips[k].installed = 1;
-                                                       task_inst_info->unres_ips_count--;
-                                                       err = register_usprobe (task, mm, &task_inst_info->p_libs[i].p_ips[k], atomic, 0);
-                                                       if (err != 0) {
-                                                               DPRINTF ("failed to install IP at %lx/%p. Error %d!",
-                                                                       task_inst_info->p_libs[i].p_ips[k].offset,
-                                                                       task_inst_info->p_libs[i].p_ips[k].jprobe.kp.addr, err);
-                                                       }
-                                               }
-                                       }
-                               }
-                               for (k = 0; k < task_inst_info->p_libs[i].vtps_count; k++) {
-                                       DPRINTF("vtps_count current:%d", k);
-                                       if (!task_inst_info->p_libs[i].p_vtps[k].installed) {
-                                               DPRINTF("!installed");
-                                               addr = task_inst_info->p_libs[i].p_vtps[k].addr;
-                                               if (!(vma->vm_flags & VM_EXECUTABLE))
-                                                       addr += vma->vm_start;
-                                               if (page_present (mm, addr)) {
-                                                       DPRINTF ("pid %d, %s sym is loaded at %lx/%lx.",
-                                                               task->pid, task_inst_info->p_libs[i].path,
-                                                               task_inst_info->p_libs[i].p_ips[k].offset, addr);
-                                                       task_inst_info->p_libs[i].p_vtps[k].jprobe.kp.tgid = task_inst_info->tgid;
-                                                       task_inst_info->p_libs[i].p_vtps[k].jprobe.kp.addr = (kprobe_opcode_t *) addr;
-                                                       task_inst_info->p_libs[i].p_vtps[k].jprobe.entry = (kprobe_opcode_t *) us_vtp_event_handler;
-                                                       task_inst_info->p_libs[i].p_vtps[k].jprobe.pre_entry = (kprobe_pre_entry_handler_t) us_vtp_event_pre_handler;
-                                                       task_inst_info->p_libs[i].p_vtps[k].jprobe.priv_arg = &task_inst_info->p_libs[i].p_vtps[k];
-                                                       task_inst_info->p_libs[i].p_vtps[k].installed = 1;
-                                                       task_inst_info->unres_vtps_count--;
-                                                       err = dbi_register_ujprobe (task, mm, &task_inst_info->p_libs[i].p_vtps[k].jprobe, atomic);
-                                                       if ( err != 0 ) {
-                                                               EPRINTF ("failed to install VTP at %p. Error %d!",
-                                                                               task_inst_info->p_libs[i].p_vtps[k].jprobe.kp.addr, err);
-                                                       }
-                                               }
-                                       }
-                               }
-                       }
-               }
-#ifdef __ANDROID
-               if (is_java_inst_enabled()
-                   && vma->vm_file->f_dentry == libdvm_dentry) {
-                       us_proc_ip_t *entp = &task_inst_info->libdvm_entry_ip;
-                       if (!entp->installed
-                           && task_inst_info->libdvm_start) {
-                               unsigned long addr = LIBDVM_ENTRY + task_inst_info->libdvm_start;
-                               if (page_present(mm, addr)) {
-                                       entp->jprobe.kp.tgid = task->tgid;
-                                       entp->jprobe.pre_entry = ujprobe_event_pre_handler;
-                                       entp->jprobe.entry = ujprobe_event_handler;
-                                       entp->jprobe.priv_arg = entp;
-                                       entp->jprobe.kp.addr = addr;
-                                       entp->retprobe.kp.tgid = task->tgid;
-                                       entp->retprobe.handler = uretprobe_event_handler;
-                                       entp->retprobe.priv_arg = entp;
-                                       entp->retprobe.kp.addr = addr;
-                                       err = register_usprobe(task, mm, entp, atomic, 0);
-                                       if (err != 0) {
-                                               DPRINTF("failed to install IP at %p", addr);
-                                       }
-                               }
-                               entp->installed = 1;
-                       }
-                       us_proc_ip_t *retp = &task_inst_info->libdvm_return_ip;
-                       if (!retp->installed
-                           && task_inst_info->libdvm_start) {
-                               unsigned long addr = LIBDVM_RETURN + task_inst_info->libdvm_start;
+                               /* if addr mapping, that probe install, else it be installed in do_page_fault handler */
                                if (page_present(mm, addr)) {
-                                       retp->jprobe.kp.tgid = task->tgid;
-                                       retp->jprobe.pre_entry = ujprobe_event_pre_handler;
-                                       retp->jprobe.entry = ujprobe_event_handler;
-                                       retp->jprobe.priv_arg = retp;
-                                       retp->jprobe.kp.addr = addr;
-                                       retp->retprobe.kp.tgid = task->tgid;
-                                       retp->retprobe.handler = uretprobe_event_handler;
-                                       retp->retprobe.priv_arg = retp;
-                                       retp->retprobe.kp.addr = addr;
-                                       err = register_usprobe(task, mm, retp, atomic, 0);
-                                       if (err != 0) {
-                                               DPRINTF("failed to install IP at %p", addr);
+                                       ip = sspt_find_ip(page, offset_addr & ~PAGE_MASK);
+                                       sspt_set_ip_addr(ip, page, file);
+
+                                       // TODO: error
+                                       ret = register_usprobe_my(task, ip);
+                                       if (ret == 0) {
+                                               sspt_page_installed(page);
+                                       } else {
+                                               printk("ERROR install_otg_ip: ret=%d\n", ret);
                                        }
                                }
-                               retp->installed = 1;
                        }
-               }
-#endif /* __ANDROID */
-               vma = vma->vm_next;
-       }
-       list_for_each_entry_rcu (p, &otg_us_proc_info, list) {
-               if (p->ip.installed) {
-                       continue;
-               }
-               rcu_read_lock();
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26)
-               t = find_task_by_pid(p->tgid);
-#else
-               t = pid_task(find_pid_ns(p->tgid, &init_pid_ns),
-                            PIDTYPE_PID);
-#endif
-               if (t){
-                       get_task_struct(t);
-               }
-               rcu_read_unlock();
-               if (!t) {
-                       DPRINTF("task for pid %d not found! Dead probe?",
-                                 p->tgid);
-                       continue;
-               }
-               if (!t->active_mm) {
-                       continue;
-               }
-               if (!page_present(t->active_mm, p->ip.offset)) {
-                       DPRINTF("Page isn't present for %p.",
-                               p->ip.offset);
-                       continue;
-               }
-               p->ip.installed = 1;
-               err = register_usprobe(current, t->active_mm,
-                                      &p->ip, atomic, 0);
-               if (err != 0) {
-                       DPRINTF("failed to install IP at %lx/%p. Error %d!",
-                               p->ip.offset,
-                               p->ip.jprobe.kp.addr, err);
-                       return err;
-               }
-               task_inst_info->unres_otg_ips_count--;
-       }
-       if (!atomic) {
-               up_read (&mm->mmap_sem);
-               mmput (mm);
-       }
-       return task_inst_info->unres_ips_count + task_inst_info->unres_vtps_count;
-}
-
-static int install_otg_ip(unsigned long addr,
-                     unsigned long pre_handler,
-                     unsigned long jp_handler,
-                     unsigned long rp_handler)
-{
-       int err;
-       us_proc_otg_ip_t *pprobe;
-       struct mm_struct *mm;
 
-       inst_us_proc_t *task_inst_info = NULL;
-       struct task_struct *task;
-
-       /* Probe preparing */
-       err = add_otg_probe_to_list(addr, &pprobe);
-       if (err) {
-               if (err == 1) {
-                       DPRINTF("OTG probe %p already installed.", addr);
-                       return 0;
-               } else {
-                       DPRINTF("Failed to add new OTG probe, err=%d",err);
-                       return err;
+                       sspt_put_page(page);
                }
        }
-       if (pre_handler) {
-               pprobe->ip.jprobe.pre_entry =
-                       (kprobe_pre_entry_handler_t)pre_handler;
-       } else {
-               pprobe->ip.jprobe.pre_entry =
-                       (kprobe_pre_entry_handler_t)
-                       dbi_ujprobe_event_pre_handler_custom_p;
-
-       }
-       if (jp_handler) {
-               pprobe->ip.jprobe.entry =
-                       (kprobe_opcode_t *)jp_handler;
-       } else {
-               pprobe->ip.jprobe.entry =
-                       (kprobe_opcode_t *)
-                       dbi_ujprobe_event_handler_custom_p;
-       }
-       if (rp_handler) {
-               pprobe->ip.retprobe.handler =
-                       (kretprobe_handler_t)rp_handler;
-       } else {
-               pprobe->ip.retprobe.handler =
-                       (kretprobe_handler_t)
-                       dbi_uretprobe_event_handler_custom_p;
-       }
-
-       mm = get_task_mm(current);
-       if (!page_present(mm, addr)) {
-               DPRINTF("Page isn't present for %p.", addr);
-
-               pprobe->tgid = current->tgid;
-               task = current->group_leader;
 
-               task_inst_info = get_task_inst_node(task);
-               if (!task_inst_info)
-               {
-                       task_inst_info = copy_task_inst_info(task, &us_proc_info);
-                       put_task_inst_node(task, task_inst_info);
-               }
-               us_proc_info.unres_otg_ips_count++;
-               /* Probe will be installed in do_page_fault handler */
-               return 0;
-       }
-       DPRINTF("Page present for %p.", addr);
-
-       /* Probe installing */
-       pprobe->tgid = current->tgid;
-       pprobe->ip.installed = 1;
-       err = register_usprobe(current, mm, &pprobe->ip, 1, 0);
-       if (err != 0) {
-               DPRINTF("failed to install IP at %lx/%p. Error %d!",
-                        addr, pprobe->ip.jprobe.kp.addr, err);
-               return err;
-       }
-       return 0;
+       return ret;
 }
 EXPORT_SYMBOL_GPL(install_otg_ip);
 
-
-static int uninstall_mapped_ips (struct task_struct *task,  inst_us_proc_t* task_inst_info, int atomic)
-{
-       int i, k, err;
-       us_proc_otg_ip_t *p;
-
-       for (i = 0; i < task_inst_info->libs_count; i++)
-       {
-               DPRINTF ("clear lib %s.", task_inst_info->p_libs[i].path);
-               for (k = 0; k < task_inst_info->p_libs[i].ips_count; k++)
-               {
-                       if (task_inst_info->p_libs[i].p_ips[k].installed)
-                       {
-                               DPRINTF ("remove IP at %p.", task_inst_info->p_libs[i].p_ips[k].jprobe.kp.addr);
-                               err = unregister_usprobe (task, &task_inst_info->p_libs[i].p_ips[k], atomic);
-                               if (err != 0)
-                               {
-                                       EPRINTF ("failed to uninstall IP at %p. Error %d!", task_inst_info->p_libs[i].p_ips[k].jprobe.kp.addr, err);
-                                       continue;
-                               }
-                               task_inst_info->unres_ips_count++;
-                               task_inst_info->p_libs[i].p_ips[k].installed = 0;
-                       }
-               }
-               for (k = 0; k < task_inst_info->p_libs[i].vtps_count; k++)
-               {
-                       if (task_inst_info->p_libs[i].p_vtps[k].installed)
-                       {
-                               dbi_unregister_ujprobe (task, &task_inst_info->p_libs[i].p_vtps[k].jprobe, atomic);
-                               task_inst_info->unres_vtps_count++;
-                               task_inst_info->p_libs[i].p_vtps[k].installed = 0;
-                       }
-               }
-               task_inst_info->p_libs[i].loaded = 0;
-       }
-#ifdef __ANDROID
-       if (is_java_inst_enabled()) {
-               us_proc_ip_t *entp = &task_inst_info->libdvm_entry_ip;
-               if (entp->installed) {
-                       unregister_usprobe(task, entp, atomic);
-                       entp->installed = 0;
-               }
-               us_proc_ip_t *retp = &task_inst_info->libdvm_return_ip;
-               if (retp->installed) {
-                       unregister_usprobe(task, retp, atomic);
-                       retp->installed = 0;
-               }
-       }
-#endif /* __ANDROID */
-       list_for_each_entry_rcu (p, &otg_us_proc_info, list) {
-               if (!p->ip.installed) {
-                       continue;
-               }
-               DPRINTF("remove OTG IP at %p.", p->ip.offset);
-               err = unregister_usprobe(task, &p->ip, atomic);
-               if (err != 0) {
-                       EPRINTF("failed to uninstall IP at %p. Error %d!",
-                                p->ip.jprobe.kp.addr, err);
-                       continue;
-               }
-               p->ip.installed = 0;
-       }
-
-       DPRINTF ("Ures IPs  %d.", task_inst_info->unres_ips_count);
-       DPRINTF ("Ures VTPs %d.", task_inst_info->unres_vtps_count);
-       return 0;
-}
-
-void send_sig_jprobe_event_handler (int sig, struct siginfo *info, struct task_struct *t, struct sigpending *signals)
-{
-       int iRet, del = 0;
-       struct task_struct *task;
-       inst_us_proc_t *task_inst_info = NULL;
-
-       //if user-space instrumentation is not set
-       if (!us_proc_info.path)
-           return;
-
-       if (sig != SIGKILL)
-               return;
-
-       if (!strcmp(us_proc_info.path,"*"))
-       {
-               task_inst_info = get_task_inst_node(t);
-               if (task_inst_info)
-               {
-                       iRet = uninstall_mapped_ips (t, task_inst_info, 1);
-                       if (iRet != 0)
-                               EPRINTF ("failed to uninstall IPs (%d)!", iRet);
-                       dbi_unregister_all_uprobes(t, 1);
-                       return;
-               }
-       }
-       else
-       {
-               if (current->tgid != us_proc_info.tgid)
-                       return;
-                       del = 1;
-
-               // look for another process with the same tgid
-               rcu_read_lock ();
-               for_each_process (task)
-               {
-                       if ((task->pid != t->pid) && (task->tgid == us_proc_info.tgid))
-                       {
-                               del = 0;
-                               break;
-                       }
-               }
-               rcu_read_unlock ();
-               if (del)
-               {
-                       DPRINTF ("%s(%d) send_signal SIGKILL for the last target proc %s(%d)",
-                                       current->comm, current->pid, t->comm, t->pid);
-                       iRet = uninstall_mapped_ips (t, &us_proc_info, 1);
-                       if (iRet != 0)
-                               EPRINTF ("failed to uninstall IPs (%d)!", iRet);
-               }
-       }
-}
 static int uninstall_kernel_probe (unsigned long addr, int uflag, int kflag, kernel_probe_t ** pprobe)
 {
        kernel_probe_t *probe = NULL;
@@ -998,15 +473,16 @@ static int uninstall_kernel_probe (unsigned long addr, int uflag, int kflag, ker
        return iRet;
 }
 
+static int uninstall_us_proc_probes(struct task_struct *task, struct sspt_procs *procs, enum US_FLAGS flag);
+
 int deinst_usr_space_proc (void)
 {
        int iRet = 0, found = 0;
-       struct task_struct *task = 0;
-       inst_us_proc_t *task_inst_info = NULL;
+       struct task_struct *task = NULL;
 
-       //if user-space instrumentation is not set
-       if (!us_proc_info.path)
+       if (!is_us_instrumentation()) {
                return 0;
+       }
 
        iRet = uninstall_kernel_probe (pf_addr, US_PROC_PF_INSTLD,
                        0, &pf_probe);
@@ -1033,16 +509,17 @@ int deinst_usr_space_proc (void)
        if (iRet)
                EPRINTF ("uninstall_kernel_probe(do_munmap) result=%d!", iRet);
 
-       if (!strcmp(us_proc_info.path,"*"))
-       {
-               for_each_process (task)
-               {
-                       task_inst_info = get_task_inst_node(task);
-                       if (task_inst_info)
-                       {
-                               iRet = uninstall_mapped_ips (task, task_inst_info, 1);
-                               if (iRet != 0)
-                                       EPRINTF ("failed to uninstall IPs (%d)!", iRet);
+       if (is_libonly()) {
+               struct sspt_procs *procs;
+
+               for_each_process(task)  {
+                       procs = get_proc_probes_by_task(task);
+                       if (procs) {
+                               int ret = uninstall_us_proc_probes(task, procs, US_UNREGS_PROBE);
+                               if (ret) {
+                                       EPRINTF ("failed to uninstall IPs (%d)!", ret);
+                               }
+
                                dbi_unregister_all_uprobes(task, 1);
                        }
                }
@@ -1064,12 +541,16 @@ int deinst_usr_space_proc (void)
                rcu_read_unlock ();
                if (found)
                {
-                       int i;
+                       int i, ret;
                        // uninstall IPs
-                       iRet = uninstall_mapped_ips (task, &us_proc_info, 0);
-                       if (iRet != 0)
-                       EPRINTF ("failed to uninstall IPs %d!", iRet);
+                       ret = uninstall_us_proc_probes(task, us_proc_info.pp, US_UNREGS_PROBE);
+                       if (ret != 0) {
+                               EPRINTF ("failed to uninstall IPs %d!", ret);
+                       }
+
                        put_task_struct (task);
+
+                       printk("### 1 ### dbi_unregister_all_uprobes:\n");
                        dbi_unregister_all_uprobes(task, 1);
                        us_proc_info.tgid = 0;
                        for(i = 0; i < us_proc_info.libs_count; i++)
@@ -1113,42 +594,21 @@ static int install_kernel_probe (unsigned long addr, int uflag, int kflag, kerne
        return 0;
 }
 
-static struct dentry *get_dentry(const char *path)
-{
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 38)
-       struct path st_path;
-       if (kern_path(path, LOOKUP_FOLLOW, &st_path) != 0) {
-#else /* LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 38) */
-       struct nameidata nd;
-       if (path_lookup(path, LOOKUP_FOLLOW, &nd) != 0) {
-#endif /* LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 38) */
-               EPRINTF("failed to lookup dentry for path %s!", path);
-               return NULL;
-       }
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25)
-       return nd.dentry;
-#elif LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 38)
-       return nd.path.dentry;
-#else /* LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 38) */
-       return st_path.dentry;
-#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25) */
-}
+static void install_proc_probes(struct task_struct *task, struct sspt_procs *procs, int atomic);
 
 int inst_usr_space_proc (void)
 {
        int ret, i;
-       struct task_struct *task = 0;
-       inst_us_proc_t *task_inst_info = NULL;
+       struct task_struct *task = NULL;
 
-       //if user-space instrumentation is not set
-       if (!us_proc_info.path)
+       if (!is_us_instrumentation()) {
                return 0;
+       }
 
        DPRINTF("User space instr");
 
 #ifdef SLP_APP
-       launchpad_daemon_dentry = get_dentry("/usr/bin/launchpad_preloading_preinitializing_daemon");
+       launchpad_daemon_dentry = dentry_by_path("/usr/bin/launchpad_preloading_preinitializing_daemon");
        if (launchpad_daemon_dentry == NULL) {
                return -EINVAL;
        }
@@ -1156,7 +616,7 @@ int inst_usr_space_proc (void)
 #endif /* SLP_APP */
 
 #ifdef ANDROID_APP
-       app_process_dentry = get_dentry("/system/bin/app_process");
+       app_process_dentry = dentry_by_path("/system/bin/app_process");
        if (app_process_dentry == NULL) {
                return -EINVAL;
        }
@@ -1165,20 +625,6 @@ int inst_usr_space_proc (void)
        android_app_vma_end = 0;
 #endif /* ANDROID_APP */
 
-#ifdef __ANDROID
-       if (is_java_inst_enabled()) {
-               libdvm_dentry = get_dentry("/system/lib/libdvm.so");
-               if (libdvm_dentry == NULL) {
-                       return -EINVAL;
-               }
-
-               memset(&us_proc_info.libdvm_entry_ip, 0, sizeof(us_proc_ip_t));
-               memset(&us_proc_info.libdvm_return_ip, 0, sizeof(us_proc_ip_t));
-               us_proc_info.libdvm_start = 0;
-               us_proc_info.libdvm_end = 0;
-       }
-#endif /* __ANDROID */
-
        for (i = 0; i < us_proc_info.libs_count; i++) {
                us_proc_info.p_libs[i].loaded = 0;
        }
@@ -1190,32 +636,22 @@ int inst_usr_space_proc (void)
         * 2) if process is not running - make sure that do_page_fault handler is installed
         * */
 
-       if (!strcmp(us_proc_info.path,"*"))
+       if (is_libonly())
        {
-               clear_task_inst_info();
+               // FIXME: clear_task_inst_info();
                for_each_process (task) {
+                       struct sspt_procs *procs;
+
                        if (task->flags & PF_KTHREAD){
                                DPRINTF("ignored kernel thread %d\n",
                                        task->pid);
                                continue;
                        }
 
-                       task_inst_info = get_task_inst_node(task);
-                       if (!task_inst_info) {
-                               task_inst_info =
-                                       copy_task_inst_info(task,
-                                                           &us_proc_info);
-                               put_task_inst_node(task, task_inst_info);
-                       }
+                       procs = get_proc_probes_by_task_or_new(task);
                        DPRINTF("trying process");
-#ifdef __ANDROID
-                       if (is_java_inst_enabled()) {
-                               find_libdvm_for_task(task, task_inst_info);
-                       }
-#endif /* __ANDROID */
-                       install_mapped_ips (task, task_inst_info, 1);
+                       install_proc_probes(task, procs, 1);
                        //put_task_struct (task);
-                       task_inst_info = NULL;
                }
        }
        else
@@ -1225,156 +661,386 @@ int inst_usr_space_proc (void)
                {
                        DPRINTF("task found. installing probes");
                        us_proc_info.tgid = task->pid;
-#ifdef __ANDROID
-                       if (is_java_inst_enabled()) {
-                               find_libdvm_for_task(task, &us_proc_info);
+                       us_proc_info.pp->sm = create_sm_us(task);
+                       install_proc_probes(task, us_proc_info.pp, 0);
+                       put_task_struct (task);
+               }
+       }
+
+       // enable 'do_page_fault' probe to detect when they will be loaded
+       ret = install_kernel_probe (pf_addr, US_PROC_PF_INSTLD, 0, &pf_probe);
+       if (ret != 0)
+       {
+               EPRINTF ("install_kernel_probe(do_page_fault) result=%d!", ret);
+               return ret;
+       }
+       // enable 'do_exit' probe to detect for remove task_struct
+       ret = install_kernel_probe (exit_addr, US_PROC_EXIT_INSTLD, 0, &exit_probe);
+       if (ret != 0)
+       {
+               EPRINTF ("install_kernel_probe(do_exit) result=%d!", ret);
+               return ret;
+       }
+       /* enable 'copy_process' */
+       ret = install_kernel_probe (cp_addr, US_PROC_CP_INSTLD, 0, &cp_probe);
+       if (ret != 0)
+       {
+               EPRINTF ("instpall_kernel_probe(copy_process) result=%d!", ret);
+               return ret;
+       }
+
+       // enable 'mm_release' probe to detect when for remove user space probes
+       ret = install_kernel_probe (mr_addr, US_PROC_MR_INSTLD, 0, &mr_probe);
+       if (ret != 0)
+       {
+               EPRINTF ("install_kernel_probe(mm_release) result=%d!", ret);
+               return ret;
+       }
+
+       // enable 'do_munmap' probe to detect when for remove user space probes
+       ret = install_kernel_probe (unmap_addr, US_PROC_UNMAP_INSTLD, 0, &unmap_probe);
+       if (ret != 0)
+       {
+               EPRINTF ("install_kernel_probe(do_munmap) result=%d!", ret);
+               return ret;
+       }
+       return 0;
+}
+
+#include "../../tools/gpmu/probes/entry_data.h"
+
+void do_page_fault_j_pre_code(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
+{
+       struct task_struct *task = current->group_leader;
+
+       if (task->flags & PF_KTHREAD) {
+               DPRINTF("ignored kernel thread %d\n", task->pid);
+               return;
+       }
+
+       if (is_us_instrumentation()) {
+               swap_put_entry_data((void *)addr, &sa_dpf);
+       }
+}
+EXPORT_SYMBOL_GPL(do_page_fault_j_pre_code);
+
+
+unsigned long imi_sum_time = 0;
+unsigned long imi_sum_hit = 0;
+
+static void set_mapping_file(struct sspt_file *file,
+               const struct sspt_procs *procs,
+               const struct task_struct *task,
+               const struct vm_area_struct *vma)
+{
+       int app_flag = (vma->vm_file->f_dentry == procs->dentry);
+
+       file->vm_start = vma->vm_start;
+       file->vm_end = vma->vm_end;
+
+       pack_event_info(DYN_LIB_PROBE_ID, RECORD_ENTRY, "dspdd",
+                       task->tgid, file->name, vma->vm_start,
+                       vma->vm_end - vma->vm_start, app_flag);
+}
+
+void print_vma(struct mm_struct *mm);
+
+static int register_us_page_probe(struct sspt_page *page,
+               const struct sspt_file *file,
+               struct task_struct *task)
+{
+       int err = 0;
+       struct us_ip *ip;
+
+       spin_lock(&page->lock);
+
+       if (sspt_page_is_install(page)) {
+               printk("page %lx in %s task[tgid=%u, pid=%u] already installed\n",
+                               page->offset, file->dentry->d_iname, task->tgid, task->pid);
+               print_vma(task->mm);
+               goto unlock;
+       }
+
+       sspt_page_assert_install(page);
+       sspt_set_all_ip_addr(page, file);
+
+       list_for_each_entry(ip, &page->ip_list, list) {
+               err = register_usprobe_my(task, ip);
+               if (err != 0) {
+                       //TODO: ERROR
+                       goto unlock;
+               }
+       }
+
+       sspt_page_installed(page);
+
+unlock:
+       spin_unlock(&page->lock);
+
+       return err;
+}
+
+static int unregister_us_page_probe(struct task_struct *task,
+               struct sspt_page *page, enum US_FLAGS flag)
+{
+       int err = 0;
+       struct us_ip *ip;
+
+       spin_lock(&page->lock);
+       if (!sspt_page_is_install(page)) {
+               spin_unlock(&page->lock);
+               return 0;
+       }
+
+       list_for_each_entry(ip, &page->ip_list, list) {
+               err = unregister_usprobe_my(task, ip, flag);
+               if (err != 0) {
+                       //TODO: ERROR
+                       break;
+               }
+       }
+
+       if (flag != US_DISARM) {
+               sspt_page_uninstalled(page);
+       }
+       spin_unlock(&page->lock);
+
+       return err;
+}
+
+static void install_page_probes(unsigned long page_addr, struct task_struct *task, struct sspt_procs *procs, int atomic)
+{
+       int lock;
+       struct mm_struct *mm;
+       struct vm_area_struct *vma;
+
+       mm_read_lock(task, mm, atomic, lock);
+
+       vma = find_vma(mm, page_addr);
+       if (vma && check_vma(vma)) {
+               struct dentry *dentry = vma->vm_file->f_dentry;
+               struct sspt_file *file = sspt_procs_find_file(procs, dentry);
+               if (file) {
+                       struct sspt_page *page;
+                       if (!file->loaded) {
+                               set_mapping_file(file, procs, task, vma);
+                               file->loaded = 1;
+                       }
+
+                       page = sspt_find_page_mapped(file, page_addr);
+                       if (page) {
+                               register_us_page_probe(page, file, task);
+                       }
+               }
+       }
+
+       mm_read_unlock(mm, atomic, lock);
+}
+
+static void install_file_probes(struct task_struct *task, struct mm_struct *mm, struct sspt_file *file)
+{
+       struct sspt_page *page = NULL;
+       struct hlist_node *node = NULL;
+       struct hlist_head *head = NULL;
+       int i, table_size = (1 << file->page_probes_hash_bits);
+
+       for (i = 0; i < table_size; ++i) {
+               head = &file->page_probes_table[i];
+               hlist_for_each_entry_rcu(page, node, head, hlist) {
+                       register_us_page_probe(page, file, task);
+               }
+       }
+}
+
+static void install_proc_probes(struct task_struct *task, struct sspt_procs *procs, int atomic)
+{
+       int lock;
+       struct vm_area_struct *vma;
+       struct mm_struct *mm;
+
+       mm_read_lock(task, mm, atomic, lock);
+
+       for (vma = mm->mmap; vma; vma = vma->vm_next) {
+               if (check_vma(vma)) {
+                       struct dentry *dentry = vma->vm_file->f_dentry;
+                       struct sspt_file *file = sspt_procs_find_file(procs, dentry);
+                       if (file) {
+                               if (!file->loaded) {
+                                       set_mapping_file(file, procs, task, vma);
+                                       file->loaded = 1;
+                               }
+
+                               install_file_probes(task, mm, file);
+                       }
+               }
+       }
+
+       mm_read_unlock(mm, atomic, lock);
+}
+
+static int check_install_pages_in_file(struct task_struct *task, struct sspt_file *file)
+{
+       int i;
+       int table_size = (1 << file->page_probes_hash_bits);
+       struct sspt_page *page;
+       struct hlist_node *node, *tmp;
+       struct hlist_head *head;
+
+       for (i = 0; i < table_size; ++i) {
+               head = &file->page_probes_table[i];
+               hlist_for_each_entry_safe (page, node, tmp, head, hlist) {
+                       if (page->install) {
+                               return 1;
+                       }
+               }
+       }
+
+       return 0;
+}
+
+static int unregister_us_file_probes(struct task_struct *task, struct sspt_file *file, enum US_FLAGS flag)
+{
+       int i, err = 0;
+       int table_size = (1 << file->page_probes_hash_bits);
+       struct sspt_page *page;
+       struct hlist_node *node, *tmp;
+       struct hlist_head *head;
+
+       for (i = 0; i < table_size; ++i) {
+               head = &file->page_probes_table[i];
+               hlist_for_each_entry_safe (page, node, tmp, head, hlist) {
+                       err = unregister_us_page_probe(task, page, flag);
+                       if (err != 0) {
+                               // TODO: ERROR
+                               return err;
                        }
-#endif /* __ANDROID */
-                       install_mapped_ips (task, &us_proc_info, 0);
-                       put_task_struct (task);
                }
        }
 
-       // enable 'do_page_fault' probe to detect when they will be loaded
-       ret = install_kernel_probe (pf_addr, US_PROC_PF_INSTLD, 0, &pf_probe);
-       if (ret != 0)
-       {
-               EPRINTF ("install_kernel_probe(do_page_fault) result=%d!", ret);
-               return ret;
-       }
-       // enable 'do_exit' probe to detect for remove task_struct
-       ret = install_kernel_probe (exit_addr, US_PROC_EXIT_INSTLD, 0, &exit_probe);
-       if (ret != 0)
-       {
-               EPRINTF ("install_kernel_probe(do_exit) result=%d!", ret);
-               return ret;
+       if (flag != US_DISARM) {
+               file->loaded = 0;
        }
-       /* enable 'copy_process' */
-       ret = install_kernel_probe (cp_addr, US_PROC_CP_INSTLD, 0, &cp_probe);
-       if (ret != 0)
-       {
-               EPRINTF ("instpall_kernel_probe(copy_process) result=%d!", ret);
-               return ret;
+
+       return err;
+}
+
+static int uninstall_us_proc_probes(struct task_struct *task, struct sspt_procs *procs, enum US_FLAGS flag)
+{
+       int err = 0;
+       struct sspt_file *file;
+
+       list_for_each_entry_rcu(file, &procs->file_list, list) {
+               err = unregister_us_file_probes(task, file, flag);
+               if (err != 0) {
+                       // TODO:
+                       return err;
+               }
        }
 
-       // enable 'mm_release' probe to detect when for remove user space probes
-       ret = install_kernel_probe (mr_addr, US_PROC_MR_INSTLD, 0, &mr_probe);
-       if (ret != 0)
-       {
-               EPRINTF ("install_kernel_probe(mm_release) result=%d!", ret);
-               return ret;
+       return err;
+}
+
+static pid_t find_proc_by_task(const struct task_struct *task, struct dentry *dentry)
+{
+       struct vm_area_struct *vma;
+       struct mm_struct *mm = task->active_mm;
+       if (mm == NULL) {
+               return 0;
        }
 
-       // enable 'do_munmap' probe to detect when for remove user space probes
-       ret = install_kernel_probe (unmap_addr, US_PROC_UNMAP_INSTLD, 0, &unmap_probe);
-       if (ret != 0)
-       {
-               EPRINTF ("install_kernel_probe(do_munmap) result=%d!", ret);
-               return ret;
+       for (vma = mm->mmap; vma; vma = vma->vm_next) {
+               if (check_vma(vma)) {
+                       if (vma->vm_file->f_dentry == dentry) {
+                               return task->tgid;
+                       }
+#ifdef SLP_APP
+                       if (is_slp_app_with_dentry(vma, dentry)) {
+                               return task->tgid;
+                       }
+#endif /* SLP_APP */
+#ifdef ANDROID_APP
+                       if (is_android_app_with_dentry(vma, dentry)) {
+                               return task->tgid;
+                       }
+#endif /* ANDROID_APP */
+               }
        }
+
        return 0;
 }
 
 void do_page_fault_ret_pre_code (void)
 {
-       struct mm_struct *mm;
-       struct vm_area_struct *vma = 0;
-       inst_us_proc_t *task_inst_info = NULL;
+       struct task_struct *task = current->group_leader;
+       struct mm_struct *mm = task->mm;
+       struct sspt_procs *procs = NULL;
        /*
         * Because process threads have same address space
         * we instrument only group_leader of all this threads
         */
-       struct task_struct *task = current->group_leader;
+       unsigned long addr = 0;
+       int valid_addr;
 
-       //if user-space instrumentation is not set
-       if (!us_proc_info.path)
-               return;
+       // overhead
+       struct timeval imi_tv1;
+       struct timeval imi_tv2;
+#define USEC_IN_SEC_NUM                                1000000
 
        if (task->flags & PF_KTHREAD) {
                DPRINTF("ignored kernel thread %d\n", task->pid);
                return;
        }
 
+       if (!is_us_instrumentation()) {
+               return;
+       }
 
-       if (!strcmp(us_proc_info.path,"*"))
-       {
-               task_inst_info = get_task_inst_node(task);
-               if (!task_inst_info)
-               {
-                       task_inst_info = copy_task_inst_info(task,
-                                                            &us_proc_info);
-                       put_task_inst_node(task, task_inst_info);
-#ifdef __ANDROID
-                       if (is_java_inst_enabled()) {
-                               find_libdvm_for_task(task, task_inst_info);
-                       }
-#endif /* __ANDROID */
-               }
-               install_mapped_ips (task, task_inst_info, 1);
+       addr = (unsigned long)swap_get_entry_data(&sa_dpf);
+
+       if (addr == 0) {
+               printk("WARNING: do_page_fault_ret_pre_code addr = 0\n");
                return;
        }
 
-       task_inst_info = &us_proc_info;
-       //DPRINTF("do_page_fault from proc %d-%d-%d", current->pid, task_inst_info->tgid, task_inst_info->unres_ips_count);
-       if (!is_java_inst_enabled()
-           && (task_inst_info->unres_ips_count + task_inst_info->unres_vtps_count
-               + task_inst_info->unres_otg_ips_count) == 0)
-       {
-               //DPRINTF("do_page_fault: there no unresolved IPs");
+
+
+
+       valid_addr = mm && page_present(mm, addr);
+       if (!valid_addr) {
                return;
        }
 
-       if (task_inst_info->tgid == 0)
-       {
-               mm = task->active_mm;
-               if (mm)
-               {
-//                     down_read (&mm->mmap_sem);
-                       vma = mm->mmap;
-                       while (vma)
-                       {
-                               if ((vma->vm_flags & VM_EXECUTABLE) && vma->vm_file)
-                               {
-                                       if (vma->vm_file->f_dentry == task_inst_info->m_f_dentry)
-                                       {
-                                               break;
-                                       }
-#ifdef SLP_APP
-                                       if (is_slp_app_with_dentry(vma, task_inst_info->m_f_dentry)) {
-                                               break;
-                                       }
-#endif /* SLP_APP */
-#ifdef ANDROID_APP
-                                       if (is_android_app_with_dentry(vma, task_inst_info->m_f_dentry)) {
-                                               break;
-                                       }
-#endif /* ANDROID_APP */
-                               }
-                               vma = vma->vm_next;
+       if (is_libonly()) {
+               procs = get_proc_probes_by_task_or_new(task);
+       } else {
+               // find task
+               if (us_proc_info.tgid == 0) {
+                       pid_t tgid = find_proc_by_task(task, us_proc_info.m_f_dentry);
+                       if (tgid) {
+                               us_proc_info.tgid = gl_nNotifyTgid = tgid;
+
+                               us_proc_info.pp->sm = create_sm_us(task);
+                               /* install probes in already mapped memory */
+                               install_proc_probes(task, us_proc_info.pp, 1);
                        }
-//                     up_read (&mm->mmap_sem);
-//                     mmput (mm);
-               } else {
-                       //                      DPRINTF ("proc %s/%d has no mm", current->comm, current->pid);
                }
-               if (vma)
-               {
-                    DPRINTF ("do_page_fault found target proc %s(%d)", task->comm, task->pid);
-                    task_inst_info->tgid = task->pid;
-                    gl_nNotifyTgid = task->tgid;
+
+               if (us_proc_info.tgid == task->tgid) {
+                       procs = us_proc_info.pp;
                }
        }
-       if (task_inst_info->tgid == task->tgid)
-       {
-               //DPRINTF("do_page_fault from target proc %d", task_inst_info->tgid);
-#ifdef __ANDROID
-               if (is_java_inst_enabled()) {
-                       find_libdvm_for_task(task, &us_proc_info);
-               }
-#endif /* __ANDROID */
-               install_mapped_ips (task, &us_proc_info, 1);
+
+       if (procs) {
+               unsigned long page = addr & PAGE_MASK;
+
+               // overhead
+               do_gettimeofday(&imi_tv1);
+               install_page_probes(page, task, procs, 1);
+               do_gettimeofday(&imi_tv2);
+               imi_sum_hit++;
+               imi_sum_time += ((imi_tv2.tv_sec - imi_tv1.tv_sec) *  USEC_IN_SEC_NUM +
+                               (imi_tv2.tv_usec - imi_tv1.tv_usec));
        }
-       //DPRINTF("do_page_fault from proc %d-%d exit", task->pid, task_inst_info->pid);
 }
 
 EXPORT_SYMBOL_GPL(do_page_fault_ret_pre_code);
@@ -1386,85 +1052,64 @@ void do_exit_probe_pre_code (void)
 }
 EXPORT_SYMBOL_GPL(do_exit_probe_pre_code);
 
-static int check_addr(unsigned long addr, unsigned long start, size_t len)
+void print_vma(struct mm_struct *mm)
 {
-       if ((addr >= start) && (addr < start + (unsigned long)len)) {
-               return 1;
-       }
+       struct vm_area_struct *vma;
+       printk("### print_vma: START\n");\
+       printk("### print_vma: START\n");
 
-       return 0;
+       for (vma = mm->mmap; vma; vma = vma->vm_next) {
+               char *x = vma->vm_flags & VM_EXEC ? "x" : "-";
+               char *r = vma->vm_flags & VM_READ ? "r" : "-";
+               char *w = vma->vm_flags & VM_WRITE ? "w" : "-";
+               char *name = vma->vm_file ? (char *)vma->vm_file->f_dentry->d_iname : "N/A";
+
+               printk("### [%8lx..%8lx] %s%s%s pgoff=\'%8lu\' %s\n",
+                               vma->vm_start, vma->vm_end, x, r, w, vma->vm_pgoff, name);
+       }
+       printk("### print_vma:  END\n");
 }
 
-static int remove_unmap_probes(struct task_struct *task, inst_us_proc_t* task_inst_info, unsigned long start, size_t len)
+static int remove_unmap_probes(struct task_struct *task, struct sspt_procs *procs, unsigned long start, size_t len)
 {
-       int i, k, err;
-       us_proc_otg_ip_t *p;
-       unsigned long addr;
-       const int atomic = 1;
-
-       for (i = 0; i < task_inst_info->libs_count; ++i) {
-               for (k = 0; k < task_inst_info->p_libs[i].ips_count; ++k) {
-                       if (task_inst_info->p_libs[i].p_ips[k].installed) {
-                               addr = task_inst_info->p_libs[i].p_ips[k].jprobe.kp.addr;
-                               if (check_addr(addr, start, len)) {
-                                       err = unregister_usprobe(task, &task_inst_info->p_libs[i].p_ips[k], atomic);
-                                       if (err != 0) {
-                                               EPRINTF("failed to uninstall IP at %p. Error %d!", task_inst_info->p_libs[i].p_ips[k].jprobe.kp.addr, err);
-                                               continue;
-                                       }
-                                       task_inst_info->unres_ips_count++;
-                                       task_inst_info->p_libs[i].p_ips[k].installed = 0;
-                               }
-                       }
-               }
-               for (k = 0; k < task_inst_info->p_libs[i].vtps_count; ++k) {
-                       if (task_inst_info->p_libs[i].p_vtps[k].installed) {
-                               addr = task_inst_info->p_libs[i].p_vtps[k].jprobe.kp.addr;
-                               if (check_addr(addr, start, len)) {
-                                       dbi_unregister_ujprobe(task, &task_inst_info->p_libs[i].p_vtps[k].jprobe, atomic);
-                                       task_inst_info->unres_vtps_count++;
-                                       task_inst_info->p_libs[i].p_vtps[k].installed = 0;
-                               }
-                       }
-               }
+       struct mm_struct *mm = task->mm;
+       struct vm_area_struct *vma;
+
+       if ((start & ~PAGE_MASK) || start > TASK_SIZE || len > TASK_SIZE - start) {
+               return -EINVAL;
        }
-#ifdef __ANDROID
-       if (is_java_inst_enabled()) {
-               us_proc_ip_t *entp = &task_inst_info->libdvm_entry_ip;
-               if (entp->installed) {
-                       addr = entp->jprobe.kp.addr;
-                       if (check_addr(addr, start, len)) {
-                               unregister_usprobe(task, entp, atomic);
-                               entp->installed = 0;
-                       }
-               }
-               us_proc_ip_t *retp = &task_inst_info->libdvm_return_ip;
-               if (retp->installed) {
-                       addr = retp->jprobe.kp.addr;
-                       if (check_addr(addr, start, len)) {
-                               unregister_usprobe(task, retp, atomic);
-                               retp->installed = 0;
-                       }
-               }
+
+       if ((len = PAGE_ALIGN(len)) == 0) {
+               return -EINVAL;
        }
-#endif /* __ANDROID */
-       list_for_each_entry_rcu (p, &otg_us_proc_info, list) {
-               if (!p->ip.installed) {
-                       continue;
-               }
 
-               addr = p->ip.jprobe.kp.addr;
-               if (check_addr(addr, start, len) == 0) {
-                       continue;
-               }
+       vma = find_vma(mm, start);
+       if (vma && check_vma(vma)) {
+               struct sspt_file *file;
+               unsigned long end = start + len;
+               struct dentry *dentry = vma->vm_file->f_dentry;
+
+               file = sspt_procs_find_file(procs, dentry);
+               if (file) {
+                       if (vma->vm_start == start || vma->vm_end == end) {
+                               unregister_us_file_probes(task, file, US_UNREGS_PROBE);
+                               file->loaded = 0;
+                       } else {
+                               unsigned long page_addr;
+                               struct sspt_page *page;
+
+                               for (page_addr = vma->vm_start; page_addr < vma->vm_end; page_addr += PAGE_SIZE) {
+                                       page = sspt_find_page_mapped(file, page_addr);
+                                       if (page) {
+                                               unregister_us_page_probe(task, page, US_UNREGS_PROBE);
+                                       }
+                               }
 
-               err = unregister_usprobe(task, &p->ip, atomic);
-               if (err != 0) {
-                       EPRINTF("failed to uninstall IP at %p. Error %d!",
-                                p->ip.jprobe.kp.addr, err);
-                       continue;
+                               if (check_install_pages_in_file(task, file)) {
+                                       file->loaded = 0;
+                               }
+                       }
                }
-               p->ip.installed = 0;
        }
 
        return 0;
@@ -1472,104 +1117,76 @@ static int remove_unmap_probes(struct task_struct *task, inst_us_proc_t* task_in
 
 void do_munmap_probe_pre_code(struct mm_struct *mm, unsigned long start, size_t len)
 {
-       inst_us_proc_t *task_inst_info = NULL;
+       struct sspt_procs *procs = NULL;
        struct task_struct *task = current;
 
        //if user-space instrumentation is not set
-       if (!us_proc_info.path || task->tgid != task->pid)
+       if (!is_us_instrumentation()) {
                return;
+       }
 
-       if (!strcmp(us_proc_info.path,"*")) {
-               task_inst_info = get_task_inst_node(task);
+       if (is_libonly()) {
+               procs = get_proc_probes_by_task(task);
        } else {
                if (task->tgid == us_proc_info.tgid) {
-                       task_inst_info = &us_proc_info;
+                       procs = us_proc_info.pp;
                }
        }
 
-       if (task_inst_info) {
-               remove_unmap_probes(task, task_inst_info, start, len);
+       if (procs) {
+               if (remove_unmap_probes(task, procs, start, len)) {
+                       printk("ERROR do_munmap: start=%lx, len=%x\n", start, len);
+               }
        }
 }
 EXPORT_SYMBOL_GPL(do_munmap_probe_pre_code);
 
 void mm_release_probe_pre_code(void)
 {
-       int iRet, del = 0;
-       struct task_struct *task;
-       inst_us_proc_t *task_inst_info = NULL;
+       struct task_struct *task = current;
+       struct sspt_procs *procs = NULL;
 
-       //if user-space instrumentation is not set
-       if (!us_proc_info.path || current->tgid != current->pid)
+       if (!is_us_instrumentation() || task->tgid != task->pid) {
                return;
+       }
 
-       if (!strcmp(us_proc_info.path,"*"))
-       {
-               task_inst_info = get_task_inst_node(current);
-               if (task_inst_info)
-               {
-                       iRet = uninstall_mapped_ips (current, task_inst_info, 1);
-                       if (iRet != 0)
-                               EPRINTF ("failed to uninstall IPs (%d)!", iRet);
-                       dbi_unregister_all_uprobes(current, 1);
+       if (is_libonly()) {
+               procs = get_proc_probes_by_task(task);
+       } else {
+               if (task->tgid == us_proc_info.tgid) {
+                       procs = get_proc_probes_by_task(task);
+                       us_proc_info.tgid = 0;
                }
        }
-       else
-       {
-               if (current->tgid != us_proc_info.tgid)
-                       return;
-                       del = 1;
-               // look for another process with the same tgid
-               rcu_read_lock ();
-               for_each_process (task)
-               {
-                       if ((task->pid != current->pid) && (task->tgid == us_proc_info.tgid))
-                       {
-                               del = 0;
-                               break;
-                       }
-               }
-               rcu_read_unlock ();
-               if (del)
-               {
-                       int i;
-                       iRet = uninstall_mapped_ips (current, &us_proc_info, 1);
-                       if (iRet != 0)
-                               EPRINTF ("failed to uninstall IPs (%d)!", iRet);
-                       dbi_unregister_all_uprobes(current, 1);
-                       us_proc_info.tgid = 0;
-                       for(i = 0; i < us_proc_info.libs_count; i++)
-                               us_proc_info.p_libs[i].loaded = 0;
+
+       if (procs) {
+               int ret = uninstall_us_proc_probes(task, procs, US_UNREGS_PROBE);
+               if (ret != 0) {
+                       EPRINTF ("failed to uninstall IPs (%d)!", ret);
                }
+
+               dbi_unregister_all_uprobes(task, 1);
        }
 }
 EXPORT_SYMBOL_GPL(mm_release_probe_pre_code);
 
 
-static void recover_child(struct task_struct *child_task, inst_us_proc_t *parent_iup)
+static void recover_child(struct task_struct *child_task, struct sspt_procs *procs)
 {
-       int i, k;
-       for(i = 0; i < parent_iup->libs_count; ++i)
-       {
-               for(k = 0; k < parent_iup->p_libs[i].ips_count; ++k)
-                       if(parent_iup->p_libs[i].p_ips[k].installed)
-                               arch_disarm_uprobe(&parent_iup->p_libs[i].p_ips[k].jprobe.kp, child_task);
-
-               for(k = 0; k < parent_iup->p_libs[i].vtps_count; ++k)
-                       if(parent_iup->p_libs[i].p_vtps[k].installed)
-                               arch_disarm_uprobe(&parent_iup->p_libs[i].p_vtps[k].jprobe.kp, child_task);
-       }
+       uninstall_us_proc_probes(child_task, procs, US_DISARM);
+       dbi_disarm_urp_inst_for_task(current, child_task);
 }
 
 static void rm_uprobes_child(struct task_struct *new_task)
 {
-       if(!strcmp(us_proc_info.path, "*")) {
-               inst_us_proc_t *task_inst_info = get_task_inst_node(current);
-               if(task_inst_info)
-                       recover_child(new_task, task_inst_info);
+       if (is_libonly()) {
+               struct sspt_procs *procs = get_proc_probes_by_task(current);
+               if(procs) {
+                       recover_child(new_task, procs);
+               }
        } else {
                if(us_proc_info.tgid == current->tgid) {
-                       recover_child(new_task, &us_proc_info);
+                       recover_child(new_task, us_proc_info.pp);
                }
        }
 }
@@ -1583,74 +1200,26 @@ void copy_process_ret_pre_code(struct task_struct *p)
                rm_uprobes_child(p);
 }
 
-
-DEFINE_PER_CPU (us_proc_ip_t *, gpCurIp) = NULL;
+static DEFINE_PER_CPU(struct us_ip *, gpCurIp) = NULL;
 EXPORT_PER_CPU_SYMBOL_GPL(gpCurIp);
-DEFINE_PER_CPU(struct pt_regs *, gpUserRegs) = NULL;
+static DEFINE_PER_CPU(struct pt_regs *, gpUserRegs) = NULL;
 EXPORT_PER_CPU_SYMBOL_GPL(gpUserRegs);
 
-
-unsigned long ujprobe_event_pre_handler (us_proc_ip_t * ip, struct pt_regs *regs)
+unsigned long ujprobe_event_pre_handler(struct us_ip *ip, struct pt_regs *regs)
 {
        __get_cpu_var (gpCurIp) = ip;
        __get_cpu_var (gpUserRegs) = regs;
        return 0;
 }
 
-#ifdef __ANDROID
-int handle_java_event(unsigned long addr)
-{
-       unsigned long start = 0;
-       struct pt_regs *regs = __get_cpu_var(gpUserRegs);
-
-       if (!strcmp(us_proc_info.path, "*")) {
-               /* TODO: some stuff here */
-       } else {
-               start = us_proc_info.libdvm_start;
-       }
-       unsigned long end = us_proc_info.libdvm_end;
-
-       if (addr == start + LIBDVM_ENTRY) {
-               unsigned long *p_met = (unsigned long *)regs->ARM_r0;
-               char *met_name = p_met ? (char *)(p_met[4]) : 0;
-               unsigned long *p_cl = p_met ? (unsigned long *)p_met[0] : 0;
-               char *cl_name = p_cl ? (char *)(p_cl[6]) : 0;
-               if (!cl_name || !met_name) {
-                       EPRINTF("warn: class name or method name null\n");
-               } else {
-                       pack_event_info(JAVA_PROBE_ID, RECORD_ENTRY, "pss", addr, cl_name, met_name);
-               }
-               dbi_uprobe_return ();
-               return 1;
-       }
-
-       if (addr == start + LIBDVM_RETURN) {
-               unsigned long *p_th = (unsigned long *)regs->ARM_r6;
-               unsigned long *p_st = p_th;
-               unsigned long *p_met = p_st ? (unsigned long *)p_st[2] : 0;
-               char *met_name = p_met ? (char *)(p_met[4]) : 0;
-               unsigned long *p_cl = p_met ? (unsigned long *)p_met[0] : 0;
-               char *cl_name = p_cl ? (char *)(p_cl[6]) : 0;
-               if (!cl_name || !met_name) {
-                       EPRINTF("warn: class name or method name null\n");
-               } else {
-                       pack_event_info(JAVA_PROBE_ID, RECORD_RET, "pss", addr, cl_name, met_name);
-               }
-               dbi_uprobe_return ();
-               return 1;
-       }
-
-       return 0;
-}
-#endif /* __ANDROID */
-
 void ujprobe_event_handler (unsigned long arg1, unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5, unsigned long arg6)
 {
-       us_proc_ip_t *ip = __get_cpu_var (gpCurIp);
-       unsigned long addr = (unsigned long)ip->jprobe.kp.addr;
+       struct us_ip *ip = __get_cpu_var(gpCurIp);
+       unsigned long addr = (unsigned long)ip->jprobe.up.kp.addr;
 
 #ifdef __ANDROID
-       if (is_java_inst_enabled() && handle_java_event(addr)) {
+       struct pt_regs *regs = __get_cpu_var(gpUserRegs);
+       if (is_java_inst_enabled() && handle_java_event(regs)) {
                return;
        }
 #endif /* __ANDROID */
@@ -1671,82 +1240,48 @@ void ujprobe_event_handler (unsigned long arg1, unsigned long arg2, unsigned lon
        dbi_uprobe_return ();
 }
 
-void find_plt_address(unsigned long addr)
+static void send_plt(struct us_ip *ip)
 {
-       inst_us_proc_t *task_inst_info = NULL;
-       int i;
-       unsigned real_addr;
-       struct vm_area_struct *vma;
-       us_proc_lib_t *p_lib = NULL;
-       char *szLibPath = NULL;
+       unsigned long addr = (unsigned long)ip->jprobe.up.kp.addr;
+       struct vm_area_struct *vma = find_vma(current->mm, addr);
+
+       if (vma && check_vma(vma)) {
+               char *name = NULL;
+               unsigned long real_addr;
+               unsigned long real_got = current->mm->exe_file == vma->vm_file ?
+                               ip->got_addr :
+                               ip->got_addr + vma->vm_start;
+
+               if (!read_proc_vm_atomic(current, real_got, &real_addr, sizeof(real_addr))) {
+                       printk("Failed to read got %lx at memory address %lx!\n", ip->got_addr, real_got);
+                       return;
+               }
 
-       // Search for library structure to check whether this function plt or not
-       if (strcmp(us_proc_info.path, "*")){
-       // If app lib instrumentation
-               task_inst_info = &us_proc_info;
-       } else {
-       // If lib only instrumentation
-               task_inst_info = get_task_inst_node(current);
-       }
-       if ((task_inst_info != NULL) && (task_inst_info->is_plt != 0)) {
-               for (i = 0; i < task_inst_info->libs_count; i++)
-               {
-                       if ((task_inst_info->p_libs[i].loaded)
-                               && (task_inst_info->p_libs[i].plt_count > 0)
-                               && (addr > task_inst_info->p_libs[i].vma_start)
-                               && (addr < task_inst_info->p_libs[i].vma_end))
-                       {
-                               p_lib = &(task_inst_info->p_libs[i]);
-                               break;
-                       }
+               vma = find_vma(current->mm, real_addr);
+               if (vma && (vma->vm_start <= real_addr) && (vma->vm_end > real_addr)) {
+                       name = vma->vm_file ? vma->vm_file->f_dentry->d_iname : NULL;
+               } else {
+                       printk("Failed to get vma, includes %lx address\n", real_addr);
+                       return;
                }
-               if (p_lib != NULL) {
-                       for (i = 0; i < p_lib->plt_count; i++)
-                       {
-                               if (addr == p_lib->p_plt[i].func_addr + p_lib->vma_start) {
-                                       unsigned long real_got;
-                                       if (p_lib->vma_flag & VM_EXECUTABLE) {
-                                               real_got = p_lib->p_plt[i].got_addr;
-                                       } else {
-                                               real_got = p_lib->p_plt[i].got_addr + p_lib->vma_start;
-                                       }
-                                       if (!read_proc_vm_atomic(current, (unsigned long)(real_got), &real_addr, sizeof(unsigned long))) {
-                                               printk("Failed to read got %p at memory address %p!\n", p_lib->p_plt[i].got_addr, real_got);
-                                               return;
-                                       }
-                                       if (real_addr != p_lib->p_plt[i].real_func_addr) {
-                                               p_lib->p_plt[i].real_func_addr =  real_addr;
-                                               vma = find_vma(current->mm, real_addr);
-                                               if ((vma != NULL) && (vma->vm_start <= real_addr) && (vma->vm_end > real_addr)) {
-                                                       if (vma->vm_file != NULL) {
-                                                               szLibPath = &(vma->vm_file->f_dentry->d_iname);
-                                                       }
-                                               } else {
-                                                       printk("Failed to get vma, includes %x address\n", real_addr);
-                                                       return;
-                                               }
-                                               if (szLibPath) {
-                                                       pack_event_info(PLT_ADDR_PROBE_ID, RECORD_RET, "ppsp", addr, real_addr, szLibPath, real_addr - vma->vm_start);
-                                                       return;
-                                               } else {
-                                                       pack_event_info(PLT_ADDR_PROBE_ID, RECORD_RET, "ppp", addr, real_addr, real_addr - vma->vm_start);
-                                                       return;
-                                               }
-                                       } else {
-                                               return;
-                                       }
-                               }
-                       }
+
+               if (name) {
+                       pack_event_info(PLT_ADDR_PROBE_ID, RECORD_RET, "ppsp", addr, real_addr, name, real_addr - vma->vm_start);
+               } else {
+                       pack_event_info(PLT_ADDR_PROBE_ID, RECORD_RET, "ppp", addr, real_addr, real_addr - vma->vm_start);
                }
        }
 }
 
-int uretprobe_event_handler (struct kretprobe_instance *probe, struct pt_regs *regs, us_proc_ip_t * ip)
+int uretprobe_event_handler(struct uretprobe_instance *probe, struct pt_regs *regs, struct us_ip *ip)
 {
        int retval = regs_return_value(regs);
-       unsigned long addr = (unsigned long)ip->jprobe.kp.addr;
+       unsigned long addr = (unsigned long)ip->jprobe.up.kp.addr;
 
-       find_plt_address(addr);
+       if (ip->got_addr && ip->flag_got == 0) {
+               send_plt(ip);
+               ip->flag_got = 1;
+       }
 
 #if defined(CONFIG_ARM)
        if (ip->offset & 0x01)
@@ -1763,68 +1298,62 @@ int uretprobe_event_handler (struct kretprobe_instance *probe, struct pt_regs *r
        return 0;
 }
 
-static int register_usprobe (struct task_struct *task, struct mm_struct *mm, us_proc_ip_t * ip, int atomic, kprobe_opcode_t * islot)
+int register_usprobe(struct task_struct *task, struct us_ip *ip, int atomic)
 {
        int ret = 0;
-       ip->jprobe.kp.tgid = task->tgid;
-       //ip->jprobe.kp.addr = (kprobe_opcode_t *) addr;
-       if(!ip->jprobe.entry) {
-               if (dbi_ujprobe_event_handler_custom_p != NULL)
-               {
-                       ip->jprobe.entry = (kprobe_opcode_t *) dbi_ujprobe_event_handler_custom_p;
-                       DPRINTF("Set custom event handler for %x\n", ip->offset);
-               }
-               else
-               {
-                       ip->jprobe.entry = (kprobe_opcode_t *) ujprobe_event_handler;
-                       DPRINTF("Set default event handler for %x\n", ip->offset);
-               }
+
+       if (ip->jprobe.entry == NULL) {
+               ip->jprobe.entry = (void *)ujprobe_event_handler;
+               DPRINTF("Set default event handler for %x\n", ip->offset);
        }
-       if(!ip->jprobe.pre_entry) {
-               if (dbi_ujprobe_event_pre_handler_custom_p != NULL)
-               {
-                       ip->jprobe.pre_entry = (kprobe_pre_entry_handler_t) dbi_ujprobe_event_pre_handler_custom_p;
-                       DPRINTF("Set custom pre handler for %x\n", ip->offset);
-               }
-               else
-               {
-                       ip->jprobe.pre_entry = (kprobe_pre_entry_handler_t) ujprobe_event_pre_handler;
-                       DPRINTF("Set default pre handler for %x\n", ip->offset);
-               }
+
+       if (ip->jprobe.pre_entry == NULL) {
+               ip->jprobe.pre_entry = (uprobe_pre_entry_handler_t)ujprobe_event_pre_handler;
+               DPRINTF("Set default pre handler for %x\n", ip->offset);
        }
+
        ip->jprobe.priv_arg = ip;
-       ret = dbi_register_ujprobe (task, mm, &ip->jprobe, atomic);
-       if (ret)
-       {
+       ip->jprobe.up.task = task;
+       ip->jprobe.up.sm = ip->page->file->procs->sm;
+       ret = dbi_register_ujprobe(&ip->jprobe, atomic);
+       if (ret) {
+               if (ret == -ENOEXEC) {
+                       pack_event_info(ERR_MSG_ID, RECORD_ENTRY, "dp",
+                                       0x1,
+                                       ip->jprobe.up.kp.addr);
+               }
                DPRINTF ("dbi_register_ujprobe() failure %d", ret);
                return ret;
        }
 
-       // Mr_Nobody: comment for valencia
-       ip->retprobe.kp.tgid = task->tgid;
-       //ip->retprobe.kp.addr = (kprobe_opcode_t *) addr;
-       if(!ip->retprobe.handler) {
-               if (dbi_uretprobe_event_handler_custom_p != NULL)
-                       ip->retprobe.handler = (kretprobe_handler_t) dbi_uretprobe_event_handler_custom_p;
-               else {
-                       ip->retprobe.handler = (kretprobe_handler_t) uretprobe_event_handler;
-                       //DPRINTF("Failed custom dbi_uretprobe_event_handler_custom_p");
+       if (ip->flag_retprobe) {
+               // Mr_Nobody: comment for valencia
+               if (ip->retprobe.handler == NULL) {
+                       ip->retprobe.handler = (uretprobe_handler_t)uretprobe_event_handler;
+                       DPRINTF("Set default ret event handler for %x\n", ip->offset);
+               }
+
+               ip->retprobe.priv_arg = ip;
+               ip->retprobe.up.task = task;
+               ip->retprobe.up.sm = ip->page->file->procs->sm;
+               ret = dbi_register_uretprobe(&ip->retprobe, atomic);
+               if (ret) {
+                       EPRINTF ("dbi_register_uretprobe() failure %d", ret);
+                       return ret;
                }
        }
-       ip->retprobe.priv_arg = ip;
-       ret = dbi_register_uretprobe (task, mm, &ip->retprobe, atomic);
-       if (ret)
-       {
-               EPRINTF ("dbi_register_uretprobe() failure %d", ret);
-               return ret;
-       }
+
        return 0;
 }
 
-static int unregister_usprobe (struct task_struct *task, us_proc_ip_t * ip, int atomic)
+int unregister_usprobe(struct task_struct *task, struct us_ip *ip, int atomic)
 {
-       dbi_unregister_ujprobe (task, &ip->jprobe, atomic);
-       dbi_unregister_uretprobe (task, &ip->retprobe, atomic);
+       dbi_unregister_ujprobe(&ip->jprobe, atomic);
+
+       if (ip->flag_retprobe) {
+               dbi_unregister_uretprobe(&ip->retprobe, atomic);
+       }
+
        return 0;
 }
 
@@ -1913,76 +1442,42 @@ int dump_backtrace(probe_id_t probe_id, struct task_struct *task,
 }
 EXPORT_SYMBOL_GPL(dump_backtrace);
 
-unsigned long get_ret_addr(struct task_struct *task, us_proc_ip_t *ip)
+struct uretprobe_instance *find_ri(struct task_struct *task, struct us_ip *ip)
 {
-       unsigned long retaddr = 0;
        struct hlist_node *item, *tmp_node;
-       struct kretprobe_instance *ri;
+       struct uretprobe_instance *ri;
 
-       if (ip) {
-               hlist_for_each_safe (item, tmp_node, &ip->retprobe.used_instances) {
-                       ri = hlist_entry (item, struct kretprobe_instance, uflist);
+       if (ip == NULL)
+               return NULL;
 
-                       if (ri->task && ri->task->pid == task->pid &&
-                                       ri->task->tgid == task->tgid)
-                               retaddr = (unsigned long)ri->ret_addr;
-               }
+       hlist_for_each_safe (item, tmp_node, &ip->retprobe.used_instances) {
+               ri = hlist_entry(item, struct uretprobe_instance, uflist);
+
+               if (ri->task && ri->task->pid == task->pid &&
+                               ri->task->tgid == task->tgid)
+                       return ri;
        }
 
-       if (retaddr)
-               return retaddr;
+       return NULL;
+}
+EXPORT_SYMBOL_GPL(find_ri);
+
+unsigned long get_ret_addr(struct task_struct *task, struct us_ip *ip)
+{
+       struct uretprobe_instance *ri = find_ri(task, ip);;
+       if (ri)
+               return (unsigned long)ri->ret_addr;
        else
                return dbi_get_ret_addr(task_pt_regs(task));
 }
 EXPORT_SYMBOL_GPL(get_ret_addr);
 
-/*function call removes all OTG-probes installed in library "lib_to_delete"*/
-void otg_probe_list_clean(char* lib_to_delete)
+unsigned long get_entry_sp(struct task_struct *task, struct us_ip *ip)
 {
-       struct task_struct *task = current->group_leader;
-       struct mm_struct *mm;
-       struct vm_area_struct *vma = 0;
-       char *filename = "";
-       char *buf = "";
-       unsigned long int addr_max = 0;
-       unsigned long int addr_min = 0;
-       int err;
-       us_proc_otg_ip_t *p;
-
-       mm = task->active_mm;
-/*find in process space map file with name "lib_to_delete" and flag VM_EXEC
-and save address borders of this file*/
-       if (mm) {
-               vma = mm->mmap;
-               while (vma) {
-                       if(vma->vm_file) {
-                               if(vma->vm_file->f_dentry) {
-                                       filename = d_path(&vma->vm_file->f_path, buf, 256);
-                                       if((strcmp(lib_to_delete, filename) == 0) && (vma->vm_flags & VM_EXEC)) {
-                                               addr_min = vma->vm_start;
-                                               addr_max = vma->vm_end;
-                                               break;
-                                       }
-                               }
-                       }
-                       vma = vma->vm_next;
-               }
-       }
-/*remove OTG-probe if its address is between addr_min and addr_max*/
-       list_for_each_entry_rcu (p, &otg_us_proc_info, list) {
-               if (!p->ip.installed) {
-                       continue;
-               }
-               if ( ((unsigned long)p->ip.jprobe.kp.addr <  addr_max) &&
-                    ((unsigned long)p->ip.jprobe.kp.addr >= addr_min) ) {
-                       err = unregister_usprobe(task, &p->ip, 1);
-                       if (err != 0) {
-                               EPRINTF("failed to uninstall IP at %p. Error %d!",
-                                        p->ip.jprobe.kp.addr, err);
-                               continue;
-                       }
-                       p->ip.installed = 0;
-               }
-       }
+       struct uretprobe_instance *ri = find_ri(task, ip);
+       if (ri)
+               return (unsigned long)ri->sp;
+       else
+               return dbi_get_stack_ptr(task_pt_regs(task));
 }
-EXPORT_SYMBOL_GPL(otg_probe_list_clean);
+EXPORT_SYMBOL_GPL(get_entry_sp);