Fix kernel crash after second instrumentation start 62/124362/5 accepted/tizen/3.0/common/20170508.152943 accepted/tizen/3.0/mobile/20170508.045936 accepted/tizen/3.0/tv/20170508.045950 accepted/tizen/3.0/wearable/20170508.050003 submit/tizen_3.0-common/20170508.080135 submit/tizen_3.0-common/20170508.081301 submit/tizen_3.0-common/20170508.091535 submit/tizen_3.0/20170414.063157 submit/tizen_3.0_common/20170508.091735
authorVyacheslav Cherkashin <v.cherkashin@samsung.com>
Mon, 10 Apr 2017 08:20:54 +0000 (11:20 +0300)
committerVyacheslav Cherkashin <v.cherkashin@samsung.com>
Thu, 13 Apr 2017 12:04:58 +0000 (15:04 +0300)
Change-Id: If6350f807192b6e4fc7612ccc5592dc720f9d99b
Signed-off-by: Vyacheslav Cherkashin <v.cherkashin@samsung.com>
22 files changed:
got_patcher/gt_module.c
nsp/nsp.c
parser/msg_cmd.c
parser/msg_parser.c
parser/msg_parser.h
parser/swap_msg_parser.c
parser/us_inst.c
parser/us_inst.h
uihv/uihv_module.c
us_manager/img/img_file.c
us_manager/img/img_file.h
us_manager/img/img_ip.c
us_manager/img/img_ip.h
us_manager/img/img_proc.c
us_manager/img/img_proc.h
us_manager/pf/pf_group.c
us_manager/pf/pf_group.h
us_manager/probes/probe_info_new.c
us_manager/probes/probe_info_new.h
us_manager/us_manager.c
webprobe/webprobe.c
wsp/wsp.c

index fd9257c..662e295 100644 (file)
@@ -27,6 +27,7 @@ enum task_id_t {
 
 struct l_probe_el {
        struct list_head list;
+
        struct pf_group *pfg;
        enum task_id_t task_id;
        union {
@@ -34,6 +35,10 @@ struct l_probe_el {
                struct dentry *dentry;
                char *id;
        };
+
+       struct probe_new p_fixup;
+       struct probe_new p_reloc;
+       struct probe_new p_init;
 };
 
 struct bin_data_t {
@@ -369,29 +374,27 @@ static struct probe_desc pin_pinit = MAKE_URPROBE(pthread_init_eh,
 
 static int _register_probe_el_no_lock(struct l_probe_el *l_probe)
 {
-       struct probe_new p_fixup;
-       struct probe_new p_reloc;
-       struct probe_new p_init;
        int ret;
 
-       p_fixup.desc = &pin_fixup;
-       p_fixup.offset = _linker_fixup.off;
-
-       ret = pin_register(&p_fixup, l_probe->pfg, _linker_fixup.dentry);
+       /* register 'fix_up' */
+       l_probe->p_fixup.desc = &pin_fixup;
+       l_probe->p_fixup.offset = _linker_fixup.off;
+       ret = pin_register(&l_probe->p_fixup, l_probe->pfg,
+                          _linker_fixup.dentry);
        if (ret != 0) {
                printk(GT_PREFIX "Error register linker fixup probe. "
                                 "Linker dentry %s, "
                                 "dl_fixup() offset = 0x%lx\n",
                                 _linker_fixup.dentry->d_name.name,
                                 _linker_fixup.off);
-
                return ret;
        }
 
-       p_reloc.desc = &pin_reloc;
-       p_reloc.offset = _linker_reloc.off;
-
-       ret = pin_register(&p_reloc, l_probe->pfg, _linker_reloc.dentry);
+       /* register 'reloc' */
+       l_probe->p_reloc.desc = &pin_reloc;
+       l_probe->p_reloc.offset = _linker_reloc.off;
+       ret = pin_register(&l_probe->p_reloc, l_probe->pfg,
+                          _linker_reloc.dentry);
        if (ret != 0) {
                printk(GT_PREFIX "Error register linker reloc probe. "
                                  "Linker dentry %s, "
@@ -402,10 +405,11 @@ static int _register_probe_el_no_lock(struct l_probe_el *l_probe)
                goto reg_probe_el_fail;
        }
 
-       p_init.desc = &pin_pinit;
-       p_init.offset = _pthread_init.off;
-
-       ret = pin_register(&p_init, l_probe->pfg, _pthread_init.dentry);
+       /* register 'init' */
+       l_probe->p_init.desc = &pin_pinit;
+       l_probe->p_init.offset = _pthread_init.off;
+       ret = pin_register(&l_probe->p_init, l_probe->pfg,
+                          _pthread_init.dentry);
        if (ret != 0) {
                printk(GT_PREFIX "Error register pthread minimal init. "
                                 "Pthread dentry %s, "
@@ -419,59 +423,19 @@ static int _register_probe_el_no_lock(struct l_probe_el *l_probe)
        return 0;
 
 reg_probe_pthread_fail:
-       pin_unregister(&p_reloc, l_probe->pfg, _linker_reloc.dentry);
+       pin_unregister(&l_probe->p_reloc, l_probe->pfg);
 
 reg_probe_el_fail:
-       pin_unregister(&p_fixup, l_probe->pfg, _linker_fixup.dentry);
+       pin_unregister(&l_probe->p_fixup, l_probe->pfg);
 
        return ret;
 }
 
 static int _unregister_probe_el_no_lock(struct l_probe_el *l_probe)
 {
-       struct probe_new p_fixup;
-       struct probe_new p_reloc;
-       struct probe_new p_init;
-       int ret;
-
-       p_init.desc = &pin_pinit;
-       p_init.offset = _pthread_init.off;
-
-       ret = pin_unregister(&p_init, l_probe->pfg, _pthread_init.dentry);
-       if (ret != 0) {
-               printk(GT_PREFIX "Error unregister pthread minimal init. "
-                                "Pthread dentry %s, "
-                                "__pthread_minimal_init() offset = 0x%lx\n",
-                                _pthread_init.dentry->d_name.name,
-                                _pthread_init.off);
-               return ret;
-       }
-
-       p_reloc.desc = &pin_reloc;
-       p_reloc.offset = _linker_reloc.off;
-
-       ret = pin_unregister(&p_reloc, l_probe->pfg, _linker_reloc.dentry);
-       if (ret != 0) {
-               printk(GT_PREFIX "Error unregister linker reloc probe. "
-                                "Linker dentry %s, "
-                                "dl_fixup() offset = 0x%lx\n",
-                                _linker_reloc.dentry->d_name.name,
-                                _linker_reloc.off);
-               return ret;
-       }
-
-       p_fixup.desc = &pin_fixup;
-       p_fixup.offset = _linker_fixup.off;
-
-       ret = pin_unregister(&p_fixup, l_probe->pfg, _linker_fixup.dentry);
-       if (ret != 0) {
-               printk(GT_PREFIX "Error unregister linker fixup probe. "
-                                "Linker dentry %s, "
-                                "dl_fixup() offset = 0x%lx\n",
-                                _linker_fixup.dentry->d_name.name,
-                                _linker_fixup.off);
-               return ret;
-       }
+       pin_unregister(&l_probe->p_init, l_probe->pfg);
+       pin_unregister(&l_probe->p_reloc, l_probe->pfg);
+       pin_unregister(&l_probe->p_fixup, l_probe->pfg);
 
        return 0;
 }
index 8319997..d1bd5a0 100644 (file)
--- a/nsp/nsp.c
+++ b/nsp/nsp.c
@@ -335,17 +335,17 @@ static int nsp_data_inst(struct nsp_data *data)
        return 0;
 
 ur_elm_run:
-       pin_unregister(&p_elm_run, pfg, libcapi_dentry);
+       pin_unregister(&p_elm_run, pfg);
 ur_ac_init:
-       pin_unregister(&p_ac_init, pfg, libcapi_dentry);
+       pin_unregister(&p_ac_init, pfg);
 ur_ac_efl_main:
-       pin_unregister(&p_ac_efl_main, pfg, libappcore_dentry);
+       pin_unregister(&p_ac_efl_main, pfg);
 ur_main:
-       pin_unregister(&data->p_main, pfg, data->app_dentry);
+       pin_unregister(&data->p_main, pfg);
 ur_dlopen:
-       pin_unregister(&p_dlopen, pfg, lpad_dentry);
+       pin_unregister(&p_dlopen, pfg);
 ur_dlsym:
-       pin_unregister(&p_dlsym, pfg, lpad_dentry);
+       pin_unregister(&p_dlsym, pfg);
 put_g:
        put_pf_group(pfg);
        return ret;
@@ -355,13 +355,13 @@ static void nsp_data_uninst(struct nsp_data *data)
 {
        struct pf_group *pfg = data->pfg;
 
-       pin_unregister(&p_do_app, pfg, libappcore_dentry);
-       pin_unregister(&p_elm_run, pfg, libcapi_dentry);
-       pin_unregister(&p_ac_init, pfg, libcapi_dentry);
-       pin_unregister(&p_ac_efl_main, pfg, libappcore_dentry);
-       pin_unregister(&data->p_main, pfg, data->app_dentry);
-       pin_unregister(&p_dlopen, pfg, lpad_dentry);
-       pin_unregister(&p_dlsym, pfg, lpad_dentry);
+       pin_unregister(&p_do_app, pfg);
+       pin_unregister(&p_elm_run, pfg);
+       pin_unregister(&p_ac_init, pfg);
+       pin_unregister(&p_ac_efl_main, pfg);
+       pin_unregister(&data->p_main, pfg);
+       pin_unregister(&p_dlopen, pfg);
+       pin_unregister(&p_dlsym, pfg);
        put_pf_group(pfg);
 
        data->pfg = NULL;
index b0ff1c5..24a290a 100644 (file)
@@ -40,7 +40,6 @@
 #include <us_manager/us_manager.h>
 
 
-static LIST_HEAD(app_inst_head);
 static int wrt_launcher_port;
 
 static int set_config(struct conf_data *conf)
@@ -77,42 +76,37 @@ int msg_keep_alive(struct msg_buf *mb)
 int msg_start(struct msg_buf *mb)
 {
        int ret = 0;
-       u32 cnt;
        struct conf_data conf;
+       LIST_HEAD(app_head);
 
        swap_msg_seq_num_reset();
        swap_msg_discard_reset();
 
-       cnt = create_us_inst_data(mb, &app_inst_head);
-       if (!cnt)
+       if (!create_us_inst_data(mb, &app_head))
                return -EINVAL;
 
        if (!is_end_mb(mb)) {
-               print_err("to long message, remained=%u", remained_mb(mb));
-               ret = -EINVAL;
-               goto free_us_inst;
+               pr_info("To long message, remained=%u", remained_mb(mb));
+               destroy_us_inst_data(&app_head);
+               return -EINVAL;
        }
 
-       ret = mod_us_inst(&app_inst_head, MT_ADD);
+       ret = app_list_reg(&app_head);
        if (ret) {
-               printk(KERN_INFO "Cannot mod us inst, ret = %d\n", ret);
-               ret = -EINVAL;
-               goto free_us_inst;
+               pr_info("Cannot mod us inst, ret = %d\n", ret);
+               return ret;
        }
 
        ret = usm_start();
-       if (ret)
-               goto free_us_inst;
+       if (ret) {
+               app_list_unreg_all();
+               return ret;
+       }
 
        restore_config(&conf);
        set_config(&conf);
 
-       return ret;
-
-free_us_inst:
-       destroy_us_inst_data(&app_inst_head);
-
-       return ret;
+       return 0;
 }
 
 /**
@@ -136,7 +130,7 @@ int msg_stop(struct msg_buf *mb)
        if (ret)
                return ret;
 
-       pfg_put_all();
+       app_list_unreg_all();
 
        conf.use_features0 = 0;
        conf.use_features1 = 0;
@@ -148,8 +142,6 @@ int msg_stop(struct msg_buf *mb)
        printk(KERN_INFO "discarded messages: %d\n", discarded);
        swap_msg_discard_reset();
 
-       destroy_us_inst_data(&app_inst_head);
-
        return ret;
 }
 
@@ -196,40 +188,18 @@ free_conf_data:
  */
 int msg_swap_inst_add(struct msg_buf *mb)
 {
-       int ret = 0;
-       u32 cnt;
-       struct app_inst_data *src, *n;
-       struct list_head app_head;
+       LIST_HEAD(app_head);
 
-       INIT_LIST_HEAD(&app_head);
-       cnt = create_us_inst_data(mb, &app_head);
-       if (!cnt)
+       if (!create_us_inst_data(mb, &app_head))
                return -EINVAL;
 
        if (!is_end_mb(mb)) {
-               print_err("to long message, remained=%u", remained_mb(mb));
-               ret = -EINVAL;
-               goto free_us_inst;
-       }
-
-       list_for_each_entry_safe(src, n, &app_head, list) {
-               struct app_inst_data *dst;
-
-               dst = app_inst_data_find(&app_inst_head, src);
-               if (dst) {
-                       app_inst_data_splice(dst, src);
-               } else {
-                       list_del(&src->list);
-                       list_add_tail(&src->list, &app_inst_head);
-               }
+               pr_info("To long message, remained=%u", remained_mb(mb));
+               destroy_us_inst_data(&app_head);
+               return -EINVAL;
        }
 
-       ret = mod_us_inst(&app_inst_head, MT_ADD);
-
-free_us_inst:
-       destroy_us_inst_data(&app_head);
-
-       return ret;
+       return app_list_reg(&app_head);
 }
 
 /**
@@ -240,41 +210,19 @@ free_us_inst:
  */
 int msg_swap_inst_remove(struct msg_buf *mb)
 {
-       int ret = 0;
-       u32 cnt;
-       struct list_head app_head;
-       struct app_inst_data *src, *n;
+       LIST_HEAD(app_head);
 
        INIT_LIST_HEAD(&app_head);
-       cnt =  create_us_inst_data(mb, &app_head);
-       if (!cnt)
+       if (!create_us_inst_data(mb, &app_head))
                return -EINVAL;
 
        if (!is_end_mb(mb)) {
-               print_err("to long message, remained=%u", remained_mb(mb));
-               ret = -EINVAL;
-               goto free_us_inst;
-       }
-
-       list_for_each_entry_safe(src, n, &app_inst_head, list) {
-               struct app_inst_data *dst;
-
-               dst = app_inst_data_find(&app_head, src);
-               if (dst) {
-                       app_inst_data_move(dst, src);
-                       if (list_empty(&src->f_head) &&
-                           list_empty(&src->l_head)) {
-                               destroy_app_inst_data(src);
-                       }
-               }
+               pr_info("To long message, remained=%u", remained_mb(mb));
+               destroy_us_inst_data(&app_head);
+               return -EINVAL;
        }
 
-       ret = mod_us_inst(&app_head, MT_DEL);
-
-free_us_inst:
-       destroy_us_inst_data(&app_head);
-
-       return ret;
+       return app_list_unreg(&app_head);
 }
 
 void set_wrt_launcher_port(int port)
index 415d0bb..1b6a302 100644 (file)
  */
 
 /**
- * @brief Creates and fills app_info_data struct.
+ * @brief Creates and fills pr_app_info struct.
  *
  * @param mb Pointer to the message buffer.
  * @param ai Pointer to the target app_inst_data.
  * @return 0 on success, error code on error.
  */
-int create_app_info(struct msg_buf *mb, struct app_inst_data *ai)
+struct pr_app_info *pr_app_info_create(struct msg_buf *mb)
 {
        int ret;
+       struct pr_app_info *app_info;
        u32 app_type;
-       char *ta_id, *exec_path;
+       char *str_id, *exec_path;
 
-       print_parse_debug("app_info:\n");
+       app_info = kmalloc(sizeof(*app_info), GFP_KERNEL);
+       if (!app_info)
+               return ERR_PTR(-ENOMEM);
 
+       print_parse_debug("app_info:\n");
        print_parse_debug("type:");
        ret = get_u32(mb, &app_type);
        if (ret) {
                print_err("failed to read target application type\n");
-               return -EINVAL;
+               goto free_app_info;
        }
 
        print_parse_debug("id:");
-       ret = get_string(mb, &ta_id);
+       ret = get_string(mb, &str_id);
        if (ret) {
                print_err("failed to read target application ID\n");
-               return -EINVAL;
+               goto free_app_info;
        }
 
        print_parse_debug("exec path:");
        ret = get_string(mb, &exec_path);
        if (ret) {
                print_err("failed to read executable path\n");
-               goto free_ta_id;
+               goto free_id;
        }
 
        switch (app_type) {
        case AT_TIZEN_NATIVE_APP:
        case AT_TIZEN_WEB_APP:
        case AT_COMMON_EXEC:
-               ai->tgid = 0;
+               app_info->tgid = 0;
                break;
        case AT_PID: {
                u32 tgid = 0;
 
-               if (*ta_id != '\0') {
-                       ret = kstrtou32(ta_id, 10, &tgid);
+               if (*str_id != '\0') {
+                       ret = kstrtou32(str_id, 10, &tgid);
                        if (ret) {
                                print_err("converting string to PID, "
-                                         "str='%s'\n", ta_id);
+                                         "str='%s'\n", str_id);
                                goto free_exec_path;
                        }
                }
 
-               ai->tgid = tgid;
+               app_info->tgid = tgid;
                break;
        }
        default:
@@ -105,19 +109,44 @@ int create_app_info(struct msg_buf *mb, struct app_inst_data *ai)
                goto free_exec_path;
        }
 
-       ai->type = (enum APP_TYPE)app_type;
-       ai->id = ta_id;
-       ai->path = exec_path;
+       app_info->type = (enum APP_TYPE)app_type;
+       app_info->id = str_id;
+       app_info->path = exec_path;
 
-       return 0;
+       return app_info;
 
 free_exec_path:
        put_string(exec_path);
+free_id:
+       put_string(str_id);
+free_app_info:
+       kfree(app_info);
+       return ERR_PTR(ret);
+}
 
-free_ta_id:
-       put_string(ta_id);
+void pr_app_info_free(struct pr_app_info *app_info)
+{
+       put_string(app_info->path);
+       put_string(app_info->id);
+       kfree(app_info);
+}
 
-       return -EINVAL;
+int pr_app_info_cmp(struct pr_app_info *app0, struct pr_app_info *app1)
+{
+       print_parse_debug("app0: %d, %d, %s, %s\n",
+                         app0->type, app0->tgid, app0->id, app0->path);
+
+       print_parse_debug("app1: %d, %d, %s, %s\n",
+                         app1->type, app1->tgid, app1->id, app1->path);
+
+       if ((app0->type == app1->type) &&
+           (app0->tgid == app1->tgid) &&
+           !strcmp(app0->id, app1->id) &&
+           !strcmp(app0->path, app1->path)) {
+               return 0;
+       }
+
+       return 1;
 }
 
 
@@ -257,6 +286,27 @@ free_args:
 }
 
 /**
+ * @brief Retprobe data cleanup.
+ *
+ * @param pi Pointer to the probe_info comprising retprobe.
+ * @return Void.
+ */
+void put_retprobe(struct probe_info *pi)
+{
+       put_string(pi->rp_i.args);
+}
+
+static int cmp_retprobe(struct probe_info *p0, struct probe_info *p1)
+{
+       if (p0->rp_i.ret_type == p1->rp_i.ret_type &&
+           !strcmp(p0->rp_i.args, p1->rp_i.args)) {
+               return 0;
+       }
+
+       return 1;
+}
+
+/**
  * @brief Gets webprobe data and puts it to the probe_info struct.
  *
  * @param mb Pointer to the message buffer.
@@ -270,15 +320,9 @@ int get_webprobe(struct msg_buf *mb, struct probe_desc *pd)
        return 0;
 }
 
-/**
- * @brief Retprobe data cleanup.
- *
- * @param pi Pointer to the probe_info comprising retprobe.
- * @return Void.
- */
-void put_retprobe(struct probe_info *pi)
+static int cmp_webprobe(struct probe_info *p0, struct probe_info *p1)
 {
-       put_string(pi->rp_i.args);
+       return 0;
 }
 
 /**
@@ -322,6 +366,16 @@ void put_preload_probe(struct probe_info *pi)
 {
 }
 
+static int cmp_preload_probe(struct probe_info *p0, struct probe_info *p1)
+{
+       if (p0->pl_i.handler == p1->pl_i.handler &&
+           p0->pl_i.flags == p1->pl_i.flags) {
+               return 0;
+       }
+
+       return 1;
+}
+
 /**
  * @brief Gets preload get_caller and puts it to the probe_info struct.
  *
@@ -347,6 +401,11 @@ void put_get_caller_probe(struct probe_info *pi)
 {
 }
 
+static int cmp_get_caller_probe(struct probe_info *p0, struct probe_info *p1)
+{
+       return 0;
+}
+
 /**
  * @brief Gets preload get_call_type and puts it to the probe_info struct.
  *
@@ -371,6 +430,12 @@ void put_get_call_type_probe(struct probe_info *pi)
 {
 }
 
+static int cmp_get_caller_type_probe(struct probe_info *p0,
+                                    struct probe_info *p1)
+{
+       return 0;
+}
+
 /**
  * @brief Gets preload write_msg and puts it to the probe_info struct.
  *
@@ -395,8 +460,10 @@ void put_write_msg_probe(struct probe_info *pi)
 {
 }
 
-
-
+static int cmp_write_msg_probe(struct probe_info *p0, struct probe_info *p1)
+{
+       return 0;
+}
 
 /**
  * @brief Gets FBI probe data and puts it to the probe_info struct.
@@ -525,12 +592,19 @@ err:
  */
 void put_fbi_probe(struct probe_info *pi)
 {
+       /* FIXME: memory leak (vars) */
        return;
 }
 
+static int cmp_fbi_probe(struct probe_info *p0, struct probe_info *p1)
+{
+       /* TODO: to implement */
+       return 0;
+}
+
 
 /* ============================================================================
- * ==                               FUNC_INST                                ==
+ * ==                                 PROBE                                  ==
  * ============================================================================
  */
 
@@ -541,217 +615,271 @@ void put_fbi_probe(struct probe_info *pi)
  * @return Pointer to the filled func_inst_data struct on success;\n
  * 0 on error.
  */
-struct func_inst_data *create_func_inst_data(struct msg_buf *mb)
+struct pr_probe_desc *pr_probe_desc_create(struct msg_buf *mb)
 {
-       struct func_inst_data *fi;
-       struct probe_desc *pd;
+       int ret = -EINVAL;
+       struct pr_probe_desc *probe;
+       int (*get_probe)(struct msg_buf *mb, struct probe_desc *pd);
        u64 addr;
        u8 type;
 
        print_parse_debug("func addr:");
        if (get_u64(mb, &addr)) {
                print_err("failed to read data function address\n");
-               return NULL;
+               return ERR_PTR(-EINVAL);
        }
 
        print_parse_debug("probe type:");
        if (get_u8(mb, &type)) {
                print_err("failed to read data probe type\n");
-               return NULL;
+               return ERR_PTR(-EINVAL);
        }
 
-       fi = kmalloc(sizeof(*fi), GFP_KERNEL);
-       if (fi == NULL) {
+       probe = kmalloc(sizeof(*probe), GFP_KERNEL);
+       if (!probe) {
                print_err("out of memory\n");
-               return NULL;
+               return ERR_PTR(-ENOMEM);
        }
-       INIT_LIST_HEAD(&fi->list);
-       fi->registered = 0;
-
-       pd = &fi->p_desc;
+       INIT_LIST_HEAD(&probe->list);
 
        switch (type) {
        case SWAP_RETPROBE:
-               if (get_retprobe(mb, pd) != 0)
-                       goto err;
+               get_probe = get_retprobe;
                break;
        case SWAP_WEBPROBE:
-               if (get_webprobe(mb, pd) != 0)
-                       goto err;
+               get_probe = get_webprobe;
                break;
        case SWAP_PRELOAD_PROBE:
-               if (get_preload_probe(mb, pd) != 0)
-                       goto err;
+               get_probe = get_preload_probe;
                break;
        case SWAP_GET_CALLER:
-               if (get_get_caller_probe(mb, pd) != 0)
-                       goto err;
+               get_probe = get_get_caller_probe;
                break;
        case SWAP_GET_CALL_TYPE:
-               if (get_get_call_type_probe(mb, pd) != 0)
-                       goto err;
+               get_probe = get_get_call_type_probe;
                break;
        case SWAP_FBIPROBE:
-               if (get_fbi_probe(mb, pd) != 0)
-                       goto err;
+               get_probe = get_fbi_probe;
                break;
        case SWAP_WRITE_MSG:
-               if (get_write_msg_probe(mb, pd) != 0)
-                       goto err;
+               get_probe = get_write_msg_probe;
                break;
        default:
                printk(KERN_WARNING "SWAP PARSER: Wrong probe type %d!\n",
                       type);
+               ret = -EINVAL;
                goto err;
        }
 
-       fi->addr = addr;
-       return fi;
-err:
+       ret = get_probe(mb, &probe->p_desc);
+       if (ret)
+               goto err;
+
+       probe->addr = addr;
+       return probe;
 
-       kfree(fi);
-       return NULL;
+err:
+       kfree(probe);
+       return ERR_PTR(ret);
 }
 
+
 /**
  * @brief func_inst_data cleanup.
  *
  * @param fi Pointer to the target func_inst_data.
  * @return Void.
  */
-void destroy_func_inst_data(struct func_inst_data *fi)
+void pr_probe_desc_free(struct pr_probe_desc *probe)
 {
-       switch (fi->p_desc.type) {
+       switch (probe->p_desc.type) {
        case SWAP_RETPROBE:
-               put_retprobe(&(fi->p_desc.info));
+               put_retprobe(&(probe->p_desc.info));
                break;
        case SWAP_WEBPROBE:
                break;
        case SWAP_PRELOAD_PROBE:
-               put_preload_probe(&(fi->p_desc.info));
+               put_preload_probe(&(probe->p_desc.info));
                break;
        case SWAP_GET_CALLER:
-               put_get_caller_probe(&(fi->p_desc.info));
+               put_get_caller_probe(&(probe->p_desc.info));
                break;
        case SWAP_GET_CALL_TYPE:
-               put_get_call_type_probe(&(fi->p_desc.info));
+               put_get_call_type_probe(&(probe->p_desc.info));
                break;
        case SWAP_FBIPROBE:
-               put_fbi_probe(&(fi->p_desc.info));
+               put_fbi_probe(&(probe->p_desc.info));
                break;
        case SWAP_WRITE_MSG:
-               put_write_msg_probe(&(fi->p_desc.info));
+               put_write_msg_probe(&(probe->p_desc.info));
                break;
        default:
-               printk(KERN_WARNING "SWAP PARSER: Wrong probe type %d!\n",
-                  fi->p_desc.type);
+               pr_err("SWAP PARSER: Wrong probe type %d!\n",
+                      probe->p_desc.type);
        }
 
-       kfree(fi);
+       kfree(probe);
 }
 
-/**
- * @brief func_inst_data find.
- *
- * @param head Pointer to the list head with func_inst_data.
- * @param func Pointer to the func_inst_data looking for.
- * @return Pointer to the found func_inst_data struct on success;\n
- * NULL on error.
- */
-struct func_inst_data *func_inst_data_find(struct list_head *head,
-                                          struct func_inst_data *func)
+int probe_inst_info_cmp(struct pr_probe_desc *p0, struct pr_probe_desc *p1)
 {
-       struct func_inst_data *f;
+       enum probe_t type;
+       int (*cmp_probe)(struct probe_info *p0, struct probe_info *p1);
+
+       if (p0->addr != p1->addr &&
+           p0->p_desc.type != p1->p_desc.type)
+               return 1;
 
-       list_for_each_entry(f, head, list) {
-               if (func->addr == f->addr)
-                       return f;
+       type = p0->p_desc.type;
+       switch (type) {
+       case SWAP_RETPROBE:
+               cmp_probe = cmp_retprobe;
+               break;
+       case SWAP_WEBPROBE:
+               cmp_probe = cmp_webprobe;
+               break;
+       case SWAP_PRELOAD_PROBE:
+               cmp_probe = cmp_preload_probe;
+               break;
+       case SWAP_GET_CALLER:
+               cmp_probe = cmp_get_caller_probe;
+               break;
+       case SWAP_GET_CALL_TYPE:
+               cmp_probe = cmp_get_caller_type_probe;
+               break;
+       case SWAP_FBIPROBE:
+               cmp_probe = cmp_fbi_probe;
+               break;
+       case SWAP_WRITE_MSG:
+               cmp_probe = cmp_write_msg_probe;
+               break;
+       default:
+               pr_err("SWAP PARSER: Wrong probe type %d!\n", type);
+               return 1;
        }
 
-       return NULL;
+       return cmp_probe(&p0->p_desc.info, &p1->p_desc.info);
 }
 
-/**
- * @brief func_inst_data lists splice
- *
- * @param dst Pointer to the destination list head.
- * @param src Pointer to the source list head.
- * @return u32 count of spliced elements.
- */
-u32 func_inst_data_splice(struct list_head *dst,
-                         struct list_head *src)
+static struct pr_bin_info *pr_bin_info_create(const char *path)
 {
-       struct func_inst_data *f, *n, *s;
-       u32 cnt = 0;
-
-       list_for_each_entry_safe(f, n, src, list) {
-               s = func_inst_data_find(dst, f);
-               if (s) {
-                       printk(KERN_WARNING "duplicate func probe\n");
-                       continue;
-               }
+       struct pr_bin_info *info;
 
-               list_del(&f->list);
-               list_add_tail(&f->list, dst);
-               cnt++;
+       info = kmalloc(sizeof(*info), GFP_KERNEL);
+       if (!info)
+               return ERR_PTR(-ENOMEM);
+
+       info->path = kstrdup(path, GFP_KERNEL);
+       if (!info->path) {
+               kfree(info);
+               return ERR_PTR(-ENOMEM);
        }
 
-       return cnt;
+       return info;
 }
 
-/**
- * @brief func_inst_data move from one list to another
- *
- * @param dst Pointer to the destination list head.
- * @param src Pointer to the source list head.
- * @return u32 Counter of moved elements.
- */
-u32 func_inst_data_move(struct list_head *dst,
-                       struct list_head *src)
+static void pr_bin_info_free(struct pr_bin_info *info)
 {
-       struct func_inst_data *f, *n, *s;
-       u32 cnt = 0;
-
-       list_for_each_entry_safe(f, n, src, list) {
-               s = func_inst_data_find(dst, f);
-               if (s) {
-                       print_parse_debug("move func 0x%016llX\n", f->addr);
-                       list_del(&f->list);
-                       list_del(&s->list);
-                       destroy_func_inst_data(s);
-                       list_add_tail(&f->list, dst);
-                       cnt++;
-               }
+       kfree(info->path);
+       kfree(info);
+}
+
+
+struct pr_bin_desc *pr_bin_desc_create(const char *path,
+                                      struct list_head *probe_list)
+{
+       struct pr_bin_desc *bin;
+
+       bin = kmalloc(sizeof(*bin), GFP_KERNEL);
+       if (!bin)
+               return ERR_PTR(-ENOMEM);
+
+       bin->info = pr_bin_info_create(path);
+       if (IS_ERR(bin->info)) {
+               long err = PTR_ERR(bin->info);
+
+               kfree(bin);
+               return ERR_PTR(err);
        }
 
-       return cnt;
+       INIT_LIST_HEAD(&bin->list);
+       INIT_LIST_HEAD(&bin->probe_head);
+       list_splice_init(probe_list, &bin->probe_head);
+
+       return bin;
 }
 
+void pr_bin_desc_free(struct pr_bin_desc *bin)
+{
+       struct pr_probe_desc *p, *n;
 
+       list_for_each_entry_safe(p, n, &bin->probe_head, list) {
+               list_del(&p->list);
+               pr_probe_desc_free(p);
+       }
 
-/* ============================================================================
- * ==                               LIB_INST                                 ==
- * ============================================================================
- */
+       pr_bin_info_free(bin->info);
+       kfree(bin);
+}
 
-/**
- * @brief Creates and fills lib_inst_data struct.
- *
- * @param mb Pointer to the message buffer.
- * @return Pointer to the filled lib_inst_data struct on success;\n
- * 0 on error.
- */
-struct lib_inst_data *create_lib_inst_data(struct msg_buf *mb)
+int pr_bin_info_cmp(struct pr_bin_info *b0, struct pr_bin_info *b1)
+{
+       return strcmp(b0->path, b1->path);
+}
+
+
+static void pr_probe_desc_list_free(struct list_head *head)
+{
+       struct pr_probe_desc *probe, *n;
+
+       list_for_each_entry_safe(probe, n, head, list) {
+               list_del(&probe->list);
+               pr_probe_desc_free(probe);
+       }
+}
+
+static int pr_probe_desc_list_create(struct msg_buf *mb, struct list_head *head)
+{
+       u32 i, cnt;
+
+       if (get_u32(mb, &cnt)) {
+               print_err("failed to read count of functions\n");
+               return -EINVAL;
+       }
+
+       print_parse_debug("probe count:%d", cnt);
+       if (remained_mb(mb) / MIN_SIZE_FUNC_INST < cnt) {
+               print_err("to match count of probes(%u)\n", cnt);
+               return -EINVAL;
+       }
+
+       for (i = 0; i < cnt; ++i) {
+               struct pr_probe_desc *probe;
+
+               print_parse_debug("probe #%d:\n", i + 1);
+               probe = pr_probe_desc_create(mb);
+               if (IS_ERR(probe)) {
+                       pr_probe_desc_list_free(head);
+                       return PTR_ERR(probe);
+               }
+
+               list_add(&probe->list, head);
+       }
+
+       return cnt;
+}
+
+
+struct pr_bin_desc *bin_info_by_lib(struct msg_buf *mb)
 {
-       struct lib_inst_data *li;
-       struct func_inst_data *fi, *fin;
+       u32 cnt;
        char *path;
-       u32 cnt, i = 0;
+       struct pr_bin_desc *bin = ERR_PTR(-EINVAL);
 
        print_parse_debug("bin path:");
        if (get_string(mb, &path)) {
                print_err("failed to read path of binary\n");
-               return NULL;
+               return bin;
        }
 
        print_parse_debug("func count:");
@@ -765,138 +893,72 @@ struct lib_inst_data *create_lib_inst_data(struct msg_buf *mb)
                goto free_path;
        }
 
-       li = kmalloc(sizeof(*li), GFP_KERNEL);
-       if (li == NULL) {
-               print_err("out of memory\n");
-               goto free_path;
-       }
-       INIT_LIST_HEAD(&li->list);
-       INIT_LIST_HEAD(&li->f_head);
-
        if (cnt) {
+               u32 i;
+               LIST_HEAD(probe_head);
+
                for (i = 0; i < cnt; ++i) {
+                       struct pr_probe_desc *probe;
                        print_parse_debug("func #%d:\n", i + 1);
-                       fi = create_func_inst_data(mb);
-                       if (fi == NULL)
-                               goto free_func;
-                       list_add_tail(&fi->list, &li->f_head);
-               }
-       }
-
-       li->path = path;
-       li->cnt_func = cnt;
+                       probe = pr_probe_desc_create(mb);
+                       if (IS_ERR(probe)) {
+                               /* set error to 'bin' */
+                               bin = ERR_PTR(PTR_ERR(probe));
+                               pr_probe_desc_list_free(&probe_head);
+                               goto free_path;
+                       }
 
-       return li;
+                       list_add(&probe->list, &probe_head);
+               }
 
-free_func:
-       list_for_each_entry_safe(fi, fin, &li->f_head, list) {
-               list_del(&fi->list);
-               destroy_func_inst_data(fi);
+               bin = pr_bin_desc_create(path, &probe_head);
+               if (IS_ERR(bin))
+                       pr_probe_desc_list_free(&probe_head);
        }
-       kfree(li);
 
 free_path:
        put_string(path);
-
-       return NULL;
+       return bin;
 }
 
-/**
- * @brief lib_inst_data cleanup.
- *
- * @param li Pointer to the target lib_inst_data.
- * @return Void.
- */
-void destroy_lib_inst_data(struct lib_inst_data *li)
-{
-       struct func_inst_data *fi, *fin;
 
-       list_for_each_entry_safe(fi, fin, &li->f_head, list) {
-               list_del(&fi->list);
-               destroy_func_inst_data(fi);
-       }
 
-       put_string(li->path);
-       kfree(li);
-}
 
-/**
- * @brief lib_inst_data find.
- *
- * @param head Pointer to the list head with lib_inst_data.
- * @param lib Pointer to the lib_inst_data looking for.
- * @return Pointer to the found lib_inst_data struct on success;\n
- * NULL on error.
- */
-struct lib_inst_data *lib_inst_data_find(struct list_head *head,
-                                        struct lib_inst_data *lib)
+void bin_info_list_free(struct list_head *head)
 {
-       struct lib_inst_data *l;
+       struct pr_bin_desc *bin, *n;
 
-       list_for_each_entry(l, head, list) {
-               if (!strcmp(l->path, lib->path))
-                       return l;
+       list_for_each_entry_safe(bin, n, head, list) {
+               list_del(&bin->list);
+               pr_bin_desc_free(bin);
        }
-
-       return NULL;
 }
 
-/**
- * @brief lib_inst_data lists splice
- *
- * @param dst Pointer to the destination list head.
- * @param src Pointer to the source list head.
- * @return u32 count of spliced elements.
- */
-u32 lib_inst_data_splice(struct list_head *dst, struct list_head *src)
+int bin_info_list_create(struct msg_buf *mb, struct list_head *head)
 {
-       struct lib_inst_data *l, *n, *s;
-       u32 cnt = 0;
-
-       list_for_each_entry_safe(l, n, src, list) {
-               s = lib_inst_data_find(dst, l);
+       u32 i, cnt;
 
-               if (s) {
-                       print_parse_debug("update lib %s\n", s->path);
-                       s->cnt_func += func_inst_data_splice(&s->f_head,
-                                                            &l->f_head);
-
-               } else {
-                       print_parse_debug("add new lib %s\n", s->path);
-
-                       list_del(&l->list);
-                       list_add_tail(&l->list, dst);
-                       cnt++;
-               }
+       if (get_u32(mb, &cnt)) {
+               print_err("failed to read count of binaries\n");
+               return -EINVAL;
        }
+       print_parse_debug("bin count:i%d", cnt);
 
-       return cnt;
-}
+       if (remained_mb(mb) / MIN_SIZE_LIB_INST < cnt) {
+               print_err("to match count of binaries(%u)\n", cnt);
+               return -EINVAL;
+       }
 
-/**
- * @brief lib_inst_data move from one list to another
- *
- * @param dst Pointer to the destination list head.
- * @param src Pointer to the source list head.
- * @return u32 Counter of moved elements.
- */
-u32 lib_inst_data_move(struct list_head *dst, struct list_head *src)
-{
-       struct lib_inst_data *l, *n, *s;
-       u32 cnt = 0;
-
-       list_for_each_entry_safe(l, n, src, list) {
-               s = lib_inst_data_find(dst, l);
-
-               if (s) {
-                       print_parse_debug("update lib %s\n", s->path);
-                       l->cnt_func -= func_inst_data_move(&s->f_head,
-                                                            &l->f_head);
-                       if (list_empty(&l->f_head)) {
-                               list_del(&l->list);
-                               destroy_lib_inst_data(l);
-                               cnt++;
-                       }
+       for (i = 0; i < cnt; ++i) {
+               struct pr_bin_desc *bin;
+
+               print_parse_debug("bin #%d:\n", i_lib + 1);
+               bin = bin_info_by_lib(mb);
+               if (IS_ERR(bin)) {
+                       bin_info_list_free(head);
+                       return PTR_ERR(bin);
+               } else if (bin) {
+                       list_add(&bin->list, head);
                }
        }
 
@@ -905,202 +967,90 @@ u32 lib_inst_data_move(struct list_head *dst, struct list_head *src)
 
 
 /* ============================================================================
- * ==                               APP_INST                                 ==
+ * ==                                 APP                                    ==
  * ============================================================================
  */
 
 /**
- * @brief Creates and fills app_inst_data struct.
+ * @brief Creates and fills pr_app_desc struct.
  *
  * @param mb Pointer to the message buffer.
  * @return Pointer to the filled app_inst_data struct on success;\n
  * 0 on error.
  */
-struct app_inst_data *create_app_inst_data(struct msg_buf *mb)
+struct pr_app_desc *pr_app_desc_create(struct msg_buf *mb)
 {
-       struct app_inst_data *app_inst;
-       struct func_inst_data *func, *func_n;
-       struct lib_inst_data *lib, *lib_n;
-       u32 cnt_func, i_func = 0, cnt_lib, i_lib = 0;
-
-       app_inst = kmalloc(sizeof(*app_inst), GFP_KERNEL);
-       if (app_inst == NULL) {
-               print_err("out of memory\n");
-               return NULL;
+       int cnt_probe, cnt_bin, ret = -EINVAL;
+       struct pr_app_info *app_info;
+       struct pr_app_desc *app;
+       LIST_HEAD(probe_head);
+       LIST_HEAD(bin_head);
+
+       app = kmalloc(sizeof(*app), GFP_KERNEL);
+       if (!app) {
+               print_err("%s: Out of memory\n", __func__);
+               return ERR_PTR(-ENOMEM);
        }
 
-       INIT_LIST_HEAD(&app_inst->list);
-       INIT_LIST_HEAD(&app_inst->f_head);
-       INIT_LIST_HEAD(&app_inst->l_head);
-
-       if (create_app_info(mb, app_inst))
-               goto err;
-
-       if (get_u32(mb, &cnt_func)) {
-               print_err("failed to read count of functions\n");
-               goto free_app_inst;
-       }
-       print_parse_debug("func count:%d", cnt_func);
-
-       if (remained_mb(mb) / MIN_SIZE_FUNC_INST < cnt_func) {
-               print_err("to match count of functions(%u)\n", cnt_func);
+       app_info = pr_app_info_create(mb);
+       if (IS_ERR(app_info)) {
+               ret = PTR_ERR(app_info);
                goto free_app_inst;
        }
 
-       if (cnt_func) {
-               for (i_func = 0; i_func < cnt_func; ++i_func) {
-                       print_parse_debug("func #%d:\n", i_func + 1);
-                       func = create_func_inst_data(mb);
-                       if (func == NULL)
-                               goto free_func;
-                       list_add_tail(&func->list, &app_inst->f_head);
+       app->info = app_info;
+       app->pfg = NULL;
+       INIT_LIST_HEAD(&app->list);
+       INIT_LIST_HEAD(&app->bin_head);
+
+       cnt_probe = pr_probe_desc_list_create(mb, &probe_head);
+       if (cnt_probe < 0) {
+               ret = cnt_probe;
+               goto free_app_info;
+       } else if (cnt_probe) {
+               struct pr_bin_desc *bin;
+
+               bin = pr_bin_desc_create(app_info->path, &probe_head);
+               if (IS_ERR(bin)) {
+                       pr_probe_desc_list_free(&probe_head);
+                       ret = PTR_ERR(bin);
+                       goto free_app_info;
                }
-       }
-
-       if (get_u32(mb, &cnt_lib)) {
-               print_err("failed to read count of libraries\n");
-               goto free_func;
-       }
-       print_parse_debug("lib count:i%d", cnt_lib);
-
-       if (remained_mb(mb) / MIN_SIZE_LIB_INST < cnt_lib) {
-               print_err("to match count of libraries(%u)\n", cnt_lib);
-               goto free_func;
-       }
-
-       if (cnt_lib) {
-               for (i_lib = 0; i_lib < cnt_lib; ++i_lib) {
-                       print_parse_debug("lib #%d:\n", i_lib + 1);
-                       lib = create_lib_inst_data(mb);
-                       if (lib == NULL)
-                               goto free_lib;
 
-                       list_add_tail(&lib->list, &app_inst->l_head);
-               }
+               /* add pr_bin_desc */
+               list_add(&bin->list, &app->bin_head);
        }
 
-       app_inst->cnt_func = cnt_func;
-       app_inst->cnt_lib = cnt_lib;
-
-       return app_inst;
-
-free_lib:
-       list_for_each_entry_safe(lib, lib_n, &app_inst->l_head, list) {
-               list_del(&lib->list);
-               destroy_lib_inst_data(lib);
+       cnt_bin = bin_info_list_create(mb, &app->bin_head);
+       if (cnt_probe < 0) {
+               ret = cnt_bin;
+               goto free_bins;
        }
 
-free_func:
-       list_for_each_entry_safe(func, func_n, &app_inst->f_head, list) {
-               list_del(&func->list);
-               destroy_func_inst_data(func);
-       }
+       return app;
 
+free_bins:
+       bin_info_list_free(&app->bin_head);
+free_app_info:
+       pr_app_info_free(app_info);
 free_app_inst:
-       put_string(app_inst->path);
-       put_string(app_inst->id);
-
-err:
-       kfree(app_inst);
-
-       return NULL;
+       kfree(app);
+       return ERR_PTR(ret);
 }
 
 /**
- * @brief app_inst_data cleanup.
+ * @brief pr_app_desc cleanup.
  *
  * @param ai Pointer to the target app_inst_data.
  * @return Void.
  */
-void destroy_app_inst_data(struct app_inst_data *ai)
+void pr_app_desc_free(struct pr_app_desc *app)
 {
-       struct func_inst_data *func, *func_n;
-       struct lib_inst_data *lib, *lib_n;
-
-       list_for_each_entry_safe(lib, lib_n, &ai->l_head, list) {
-               list_del(&lib->list);
-               destroy_lib_inst_data(lib);
-       }
-
-       list_for_each_entry_safe(func, func_n, &ai->f_head, list) {
-               list_del(&func->list);
-               destroy_func_inst_data(func);
-       }
-
-       put_string(ai->path);
-       put_string(ai->id);
-
-       kfree(ai);
+       bin_info_list_free(&app->bin_head);
+       pr_app_info_free(app->info);
+       kfree(app);
 }
 
-/**
- * @brief find app_inst_data.
- *
- * @param head Pointer to the list head with app_inst_data.
- * @param ai Pointer to the target app_inst_data.
- * @return Pointer to the target app_inst_data.
- */
-struct app_inst_data *app_inst_data_find(struct list_head *head,
-                                        struct app_inst_data *ai)
-{
-       struct app_inst_data *p;
-
-       list_for_each_entry(p, head, list) {
-
-               print_parse_debug("app1: %d, %d, %s, %s\n",
-                               p->type, p->tgid, p->id, p->path);
-
-               print_parse_debug("app2: %d, %d, %s, %s\n",
-                               ai->type, ai->tgid, ai->id, ai->path);
-
-               if ((p->type == ai->type) &&
-                   (p->tgid == ai->tgid) &&
-                   !strcmp(p->id, ai->id) &&
-                   !strcmp(p->path, ai->path)) {
-                       return p;
-               }
-       }
-
-       return NULL;
-}
-
-/**
- * @brief app_inst_data splice
- *
- * @param dst Pointer to the destination app_inst_data.
- * @param src Pointer to the source app_inst_data..
- * @return void.
- */
-void app_inst_data_splice(struct app_inst_data *dst,
-                         struct app_inst_data *src)
-{
-       print_parse_debug("find app, splice func and lib to %s\n",
-                                       dst->path);
-
-       dst->cnt_func += func_inst_data_splice(&dst->f_head, &src->f_head);
-       dst->cnt_lib += lib_inst_data_splice(&dst->l_head, &src->l_head);
-
-       return;
-}
-
-/**
- * @brief app_inst_data move from one to another
- *
- * @param dst Pointer to the destination app_inst_data.
- * @param src Pointer to the source app_inst_data.
- * @return void.
- */
-void app_inst_data_move(struct app_inst_data *dst,
-                       struct app_inst_data *src)
-{
-       print_parse_debug("find app, delete func and lib from %s\n",
-                       dst->path);
-
-       dst->cnt_func -= func_inst_data_move(&dst->f_head, &src->f_head);
-       dst->cnt_lib -= lib_inst_data_move(&dst->l_head, &src->l_head);
-
-       return;
-}
 
 /* ============================================================================
  * ==                                US_INST                                 ==
@@ -1117,8 +1067,7 @@ void app_inst_data_move(struct app_inst_data *dst,
 u32 create_us_inst_data(struct msg_buf *mb,
                        struct list_head *head)
 {
-       struct app_inst_data *ai, *n;
-       u32 cnt, i = 0;
+       u32 cnt, i;
 
        print_parse_debug("us_inst_data:\n");
 
@@ -1134,22 +1083,20 @@ u32 create_us_inst_data(struct msg_buf *mb,
        }
 
        for (i = 0; i < cnt; ++i) {
+               struct pr_app_desc *app;
+
                print_parse_debug("app #%d:\n", i + 1);
-               ai = create_app_inst_data(mb);
-               if (ai == NULL)
+               app = pr_app_desc_create(mb);
+               if (IS_ERR(app))
                        goto err;
 
-               list_add_tail(&ai->list, head);
+               list_add_tail(&app->list, head);
        }
 
        return cnt;
 
 err:
-       list_for_each_entry_safe(ai, n, head, list) {
-               list_del(&ai->list);
-               destroy_app_inst_data(ai);
-       }
-
+       destroy_us_inst_data(head);
        return 0;
 }
 
@@ -1161,9 +1108,10 @@ err:
  */
 void destroy_us_inst_data(struct list_head *head)
 {
-       struct app_inst_data *ai, *n;
-       list_for_each_entry_safe(ai, n, head, list) {
-               list_del(&ai->list);
-               destroy_app_inst_data(ai);
+       struct pr_app_desc *app, *n;
+
+       list_for_each_entry_safe(app, n, head, list) {
+               list_del(&app->list);
+               pr_app_desc_free(app);
        }
 }
index cd16327..9620e65 100644 (file)
@@ -35,6 +35,7 @@
 #include <linux/types.h>
 #include <us_manager/probes/probes.h>
 
+struct img_ip;
 struct msg_buf;
 
 /**
@@ -56,17 +57,6 @@ enum {
 };
 
 /**
- * @struct app_info_data
- * @brief Basic application information.
- */
-struct app_info_data {
-       enum APP_TYPE app_type;     /**< Application type. */
-       pid_t tgid;                 /**< Application PID. */
-       char *app_id;               /**< Application ID */
-       char *exec_path;            /**< Application execution path. */
-};
-
-/**
  * @struct conf_data
  * @brief Configuration struct.
  */
@@ -78,44 +68,69 @@ struct conf_data {
 };
 
 /**
- * @struct func_inst_data
- * @brief Application and library functions to set probes.
+ * @brief The pr_app_info struct
  */
-struct func_inst_data {
-       struct list_head list;
-       u64 addr;                   /**< Function address. */
-       struct probe_desc p_desc;   /**< Probe info. */
-       int registered;
+struct pr_app_info {
+       enum APP_TYPE type;     /**< Application type. */
+       pid_t tgid;             /**< Application PID. */
+       char *id;               /**< Application ID */
+       char *path;             /**< Application execution path. */
+};
+
+/**
+ * @brief The pr_bin_info struct
+ */
+struct pr_bin_info {
+       char *path;
 };
 
 /**
- * @struct lib_inst_data
- * @brief Library struct.
+ * @brief The pr_app_desc struct
  */
-struct lib_inst_data {
+struct pr_app_desc {
        struct list_head list;
-       char *path;                 /**< Library path. */
-       u32 cnt_func;               /**< Function probes count in this library. */
-       struct list_head f_head;    /**< List head of func_inst_data */
+
+       struct pr_app_info *info;
+       struct pf_group *pfg;
+       struct list_head bin_head;
 };
 
 /**
- * @struct app_inst_data
- * @brief Application struct.
+ * @brief The pr_bin_desc struct
  */
-struct app_inst_data {
+struct pr_bin_desc {
+       struct list_head list;
+
+       struct pr_bin_info *info;
+
+       struct list_head probe_head;
+};
+
+struct pr_probe_desc {
        struct list_head list;
-       enum APP_TYPE type;                /**< Application type. */
-       pid_t tgid;                        /**< Application PID. */
-       char *id;                          /**< Application ID */
-       char *path;                        /**< Application execution path. */
-       struct list_head f_head;           /**< List head of func_inst_data */
-       struct list_head l_head;           /**< List head of lib_inst_data */
-       u32 cnt_func;                      /**< Function probes count in app. */
-       u32 cnt_lib;                       /**< Libs count. */
+
+       /* register info */
+       u64 addr;
+       struct probe_desc p_desc;
+
+       /* unregister info */
+       struct img_ip *ip;
 };
 
-int create_app_info(struct msg_buf *mb, struct app_inst_data *ai);
+
+struct pr_app_info *pr_app_info_create(struct msg_buf *mb);
+void pr_app_info_free(struct pr_app_info *app_info);
+int pr_app_info_cmp(struct pr_app_info *app0, struct pr_app_info *app1);
+
+struct pr_bin_desc *pr_bin_desc_create(const char *path,
+                                      struct list_head *probe_list);
+void pr_bin_desc_free(struct pr_bin_desc *bin);
+
+int pr_bin_info_cmp(struct pr_bin_info *b0, struct pr_bin_info *b1);
+
+struct pr_probe_desc *pr_probe_desc_create(struct msg_buf *mb);
+void pr_probe_desc_free(struct pr_probe_desc *probe_info);
+int probe_inst_info_cmp(struct pr_probe_desc *p0, struct pr_probe_desc *p1);
 
 struct conf_data *create_conf_data(struct msg_buf *mb);
 void destroy_conf_data(struct conf_data *conf);
@@ -123,44 +138,26 @@ void destroy_conf_data(struct conf_data *conf);
 void save_config(const struct conf_data *conf);
 void restore_config(struct conf_data *conf);
 
-struct func_inst_data *create_func_inst_data(struct msg_buf *mb);
-void destroy_func_inst_data(struct func_inst_data *func_inst);
-
-struct lib_inst_data *create_lib_inst_data(struct msg_buf *mb);
-void destroy_lib_inst_data(struct lib_inst_data *lib_inst);
-
-struct app_inst_data *create_app_inst_data(struct msg_buf *mb);
-void destroy_app_inst_data(struct app_inst_data *app_inst);
-struct app_inst_data *app_inst_data_find(struct list_head *head,
-                                        struct app_inst_data *ai);
-void app_inst_data_move(struct app_inst_data *dst,
-                         struct app_inst_data *src);
-void app_inst_data_splice(struct app_inst_data *dst,
-                         struct app_inst_data *src);
+struct pr_app_desc *pr_app_desc_create(struct msg_buf *mb);
+void pr_app_desc_free(struct pr_app_desc *app);
 
 u32 create_us_inst_data(struct msg_buf *mb, struct list_head *head);
 void destroy_us_inst_data(struct list_head *head);
 
 
-/* empty functions for calculating size fields in structures */
-struct func_inst_data make_func_inst_data(void);
-struct lib_inst_data make_lib_inst_data(void);
-struct app_inst_data make_app_inst_data(void);
-struct us_inst_data make_us_inst_data(void);
-
 /**
  * @brief Constant defenitions.
  */
 enum {
        MIN_SIZE_STRING = 1,
-       MIN_SIZE_FUNC_INST = sizeof(make_func_inst_data().addr) +
+       MIN_SIZE_FUNC_INST = 8 /* address size */ +
                             MIN_SIZE_STRING,
        MIN_SIZE_LIB_INST = MIN_SIZE_STRING +
-                           sizeof(make_lib_inst_data().cnt_func),
+                           4 /* lib counter */,
        MIN_SIZE_APP_INFO = SIZE_APP_TYPE + MIN_SIZE_STRING + MIN_SIZE_STRING,
        MIN_SIZE_APP_INST = MIN_SIZE_APP_INFO +
-                           sizeof(make_app_inst_data().cnt_func) +
-                           sizeof(make_app_inst_data().cnt_lib)
+                           4 /* probe counter */ +
+                           4 /* lib counter */,
 };
 
 #endif /* _MSG_PARSER_H */
index 0f7e394..a8b4c28 100644 (file)
@@ -158,7 +158,7 @@ static int reg_msg_handler(void)
 static void unreg_msg_handler(void)
 {
        set_msg_handler(NULL);
-       pfg_put_all();
+       app_list_unreg_all();
 }
 
 static int once(void)
index f9293da..3af2994 100644 (file)
 #include "usm_msg.h"
 
 
-struct pfg_item {
-       struct list_head list;
-       struct pf_group *pfg;
-};
-
-
-static LIST_HEAD(pfg_item_list);
-static DEFINE_SPINLOCK(pfg_item_lock);
-
-
 static struct pfg_msg_cb msg_cb = {
        .msg_info = usm_msg_info,
        .msg_status_info = usm_msg_status_info,
@@ -59,247 +49,377 @@ static struct pfg_msg_cb msg_cb = {
        .msg_unmap = usm_msg_unmap
 };
 
-static struct pfg_item *pfg_item_create(struct pf_group *pfg)
-{
-       int ret;
-       struct pfg_item *item;
-
-       ret = pfg_msg_cb_set(pfg, &msg_cb);
-       if (ret)
-               return ERR_PTR(ret);
 
-       item = kmalloc(sizeof(*item), GFP_KERNEL);
-       if (item == NULL)
-               return ERR_PTR(-ENOMEM);
-
-       INIT_LIST_HEAD(&item->list);
-       item->pfg = pfg;
-
-       return item;
-}
-
-static void pfg_item_free(struct pfg_item *item)
+static int probe_inst_reg(struct pr_probe_desc *probe, struct pf_group *pfg,
+                         struct dentry *dentry)
 {
-       pfg_msg_cb_reset(item->pfg);
-       kfree(item);
-}
-
-/* called with pfg_item_lock held */
-static bool pfg_check(struct pf_group *pfg)
-{
-       struct pfg_item *item;
-
-       list_for_each_entry(item, &pfg_item_list, list) {
-               if (item->pfg == pfg)
-                       return true;
-       }
+       probe->ip = pf_register_probe(pfg, dentry, probe->addr, &probe->p_desc);
+       if (IS_ERR(probe->ip))
+               return PTR_ERR(probe->ip);
 
-       return false;
+       return 0;
 }
 
-static int pfg_add(struct pf_group *pfg)
+static void probe_inst_unreg(struct pr_probe_desc *probe, struct pf_group *pfg)
 {
-       bool already;
-
-       spin_lock(&pfg_item_lock);
-       already = pfg_check(pfg);
-       spin_unlock(&pfg_item_lock);
-
-       if (already) {
-               put_pf_group(pfg);
-       } else {
-               struct pfg_item *item;
-
-               item = pfg_item_create(pfg);
-               if (IS_ERR(item))
-                       return PTR_ERR(item);
-
-               spin_lock(&pfg_item_lock);
-               list_add(&item->list, &pfg_item_list);
-               spin_unlock(&pfg_item_lock);
-       }
-
-       return 0;
+       pf_unregister_probe(pfg, probe->ip);
 }
 
-void pfg_put_all(void)
+static void do_bin_inst_unreg(struct list_head *head, struct pf_group *pfg)
 {
-       LIST_HEAD(tmp_list);
-       struct pfg_item *item, *n;
-
-       spin_lock(&pfg_item_lock);
-       list_splice_init(&pfg_item_list, &tmp_list);
-       spin_unlock(&pfg_item_lock);
+       struct pr_probe_desc *probe;
 
-       list_for_each_entry_safe(item, n, &tmp_list, list) {
-               struct pf_group *pfg = item->pfg;
-
-               list_del(&item->list);
-               pfg_item_free(item);
-               put_pf_group(pfg);
+       list_for_each_entry(probe, head, list) {
+               probe_inst_unreg(probe, pfg);
        }
 }
 
-static int mod_func_inst(struct func_inst_data *func, struct pf_group *pfg,
-                        struct dentry *dentry, enum MOD_TYPE mt)
+static void bin_inst_unreg(struct pr_bin_desc *bin, struct pf_group *pfg)
 {
-       int ret = 0;
-
-       switch (mt) {
-       case MT_ADD:
-               if (func->registered == 0) {
-                       ret = pf_register_probe(pfg, dentry, func->addr,
-                                               &func->p_desc);
-                       if (!ret)
-                               func->registered = 1;
-               }
-               break;
-       case MT_DEL:
-               if (func->registered == 1) {
-                       ret = pf_unregister_probe(pfg, dentry, func->addr,
-                                                 &func->p_desc);
-                       if (!ret)
-                               func->registered = 0;
-               }
-               break;
-       default:
-               printk(KERN_INFO "ERROR: mod_type=0x%x\n", mt);
-               ret = -EINVAL;
-       }
-
-       return ret;
+       do_bin_inst_unreg(&bin->probe_head, pfg);
 }
 
-static int mod_lib_inst(struct lib_inst_data *lib, struct pf_group *pfg,
-                       enum MOD_TYPE mt)
+static int bin_inst_reg(struct pr_bin_desc *bin, struct pf_group *pfg)
 {
-       struct func_inst_data *func;
-       int ret = 0;
+       struct pr_probe_desc *probe, *n;
        struct dentry *dentry;
+       LIST_HEAD(reg_head);
 
-       dentry = dentry_by_path(lib->path);
+       dentry = dentry_by_path(bin->info->path);
        if (dentry == NULL) {
-               printk(KERN_INFO "Cannot get dentry by path %s\n", lib->path);
+               pr_warn("Cannot get dentry by path %s\n", bin->info->path);
                return -EINVAL;
        }
 
-       list_for_each_entry(func, &lib->f_head, list) {
-               ret = mod_func_inst(func, pfg, dentry, mt);
-               if (ret) {
-                       printk(KERN_INFO "Cannot mod func inst, ret = %d\n",
-                              ret);
+       list_for_each_entry_safe(probe, n, &bin->probe_head, list) {
+               int ret;
+
+               ret = probe_inst_reg(probe, pfg, dentry);
+               if (!ret) {
+                       list_move(&probe->list, &reg_head);
+               } else {
+                       do_bin_inst_unreg(&reg_head, pfg);
                        return ret;
                }
        }
 
-       return ret;
+       list_splice(&reg_head, &bin->probe_head);
+       return 0;
 }
 
-static int get_pfg_by_app_info(struct app_inst_data *ai,
-                              struct pf_group **pfg)
+static struct pf_group *get_pfg_by_app_info(struct pr_app_info *app)
 {
+       struct pf_group *pfg = ERR_PTR(-EINVAL);
        struct dentry *dentry;
 
-       dentry = dentry_by_path(ai->path);
+       dentry = dentry_by_path(app->path);
        if (dentry == NULL)
-               return -EINVAL;
+               return pfg;
 
-       switch (ai->type) {
+       switch (app->type) {
        case AT_PID:
-               if (ai->tgid == 0) {
-                       if (ai->path[0] == '\0')
-                               *pfg = get_pf_group_dumb(dentry);
+               if (app->tgid == 0) {
+                       if (app->path[0] == '\0')
+                               pfg = get_pf_group_dumb(dentry);
                        else
                                goto pf_dentry;
-               } else
-                       *pfg = get_pf_group_by_tgid(ai->tgid, dentry);
+               } else {
+                       pfg = get_pf_group_by_tgid(app->tgid, dentry);
+               }
                break;
        case AT_TIZEN_WEB_APP:
-               *pfg = get_pf_group_by_comm(ai->id, dentry);
+               pfg = get_pf_group_by_comm(app->id, dentry);
                break;
        case AT_TIZEN_NATIVE_APP:
        case AT_COMMON_EXEC:
  pf_dentry:
-               *pfg = get_pf_group_by_dentry(dentry, dentry);
+               pfg = get_pf_group_by_dentry(dentry, dentry);
                break;
        default:
-               printk(KERN_INFO "ERROR: app_type=0x%x\n", ai->type);
-               return -EINVAL;
+               pr_info("ERROR: app_type=0x%x\n", app->type);
+               break;
        }
 
-       return 0;
+       if (!pfg)
+               pfg = ERR_PTR(-ENOMEM);
+
+       if (!IS_ERR(pfg)) {
+               /* TODO: move to other location and chack return value */
+               pfg_msg_cb_set(pfg, &msg_cb);
+       }
+
+       return pfg;
+}
+
+static void do_us_app_inst_unreg(struct pr_app_desc *app,
+                                struct list_head *head)
+{
+       struct pr_bin_desc *bin;
+
+       list_for_each_entry(bin, head, list) {
+               bin_inst_unreg(bin, app->pfg);
+       }
+       put_pf_group(app->pfg);
+       app->pfg = NULL;
+}
+
+static void us_app_inst_unreg(struct pr_app_desc *app)
+{
+       do_us_app_inst_unreg(app, &app->bin_head);
 }
 
-static int mod_us_app_inst(struct app_inst_data *app_inst, enum MOD_TYPE mt)
+static int us_app_inst_reg(struct pr_app_desc *app)
 {
-       int ret;
        struct pf_group *pfg;
-       struct dentry *dentry;
-       struct func_inst_data *func;
-       struct lib_inst_data *lib;
+       struct pr_bin_desc *bin, *n;
+       LIST_HEAD(reg_head);
+
+       pfg = get_pfg_by_app_info(app->info);
+       if (IS_ERR(pfg))
+               return PTR_ERR(pfg);
+
+       app->pfg = pfg;
+       list_for_each_entry_safe(bin, n, &app->bin_head, list) {
+               int ret;
+
+               ret = bin_inst_reg(bin, app->pfg);
+               if (!ret) {
+                       list_move(&bin->list, &reg_head);
+               } else {
+                       do_us_app_inst_unreg(app, &reg_head);
+                       return ret;
+               }
+       }
+
+       list_splice(&reg_head, &app->bin_head);
+       return 0;
+}
+
+
+static struct pr_probe_desc *find_probe(struct list_head *head,
+                                       struct pr_probe_desc *probe)
+{
+       struct pr_probe_desc *p;
+
+       list_for_each_entry(p, head, list) {
+               if (!probe_inst_info_cmp(probe, p))
+                       return p;
+       }
 
-       ret = get_pfg_by_app_info(app_inst, &pfg);
-       if (ret) {
-               printk(KERN_INFO "Cannot get pfg by app info, ret = %d\n", ret);
-               return ret;
+       return NULL;
+}
+
+static struct pr_bin_desc *find_bin(struct list_head *head,
+                                   struct pr_bin_info *info)
+{
+       struct pr_bin_desc *bin;
+
+       list_for_each_entry(bin, head, list) {
+               if (!pr_bin_info_cmp(bin->info, info))
+                       return bin;
+       }
+
+       return NULL;
+}
+
+static struct pr_app_desc *find_app(struct list_head *head,
+                                   struct pr_app_info *app_info)
+{
+       struct pr_app_desc *app;
+
+       list_for_each_entry(app, head, list) {
+               if (!pr_app_info_cmp(app->info, app_info))
+                       return app;
        }
 
-       ret = pfg_add(pfg);
-       if (ret) {
-               put_pf_group(pfg);
-               printk(KERN_INFO "Cannot pfg_add, ret=%d\n", ret);
-               return ret;
+       return NULL;
+}
+
+static void us_probe_get_equal_elements(struct list_head *probe_head,
+                                       struct list_head *test_probe_head,
+                                       struct list_head *out_probe_head)
+{
+       struct pr_probe_desc *test_probe, *n;
+
+       list_for_each_entry_safe(test_probe, n, test_probe_head, list) {
+               struct pr_probe_desc *probe;
+
+               probe = find_probe(probe_head, test_probe);
+               if (probe) {
+                       list_move(&probe->list, out_probe_head);
+
+                       /* remove probe */
+                       list_del(&test_probe->list);
+                       pr_probe_desc_free(test_probe);
+               } else {
+                       return;
+               }
        }
+}
 
-       list_for_each_entry(func, &app_inst->f_head, list) {
-               /* TODO: */
-               dentry = dentry_by_path(app_inst->path);
-               if (dentry == NULL) {
-                       printk(KERN_INFO "Cannot find dentry by path %s\n",
-                              app_inst->path);
-                       return -EINVAL;
+static void us_bin_get_equal_elements(struct list_head *bin_head,
+                                     struct list_head *test_bin_head,
+                                     struct list_head *out_bin_head)
+{
+       struct pr_bin_desc *test_bin, *n;
+
+       list_for_each_entry_safe(test_bin, n, test_bin_head, list) {
+               struct pr_bin_desc *bin;
+               LIST_HEAD(out_probe_head);
+
+               bin = find_bin(bin_head, test_bin->info);
+               if (!bin)
+                       return;
+
+               us_probe_get_equal_elements(&bin->probe_head,
+                                           &test_bin->probe_head,
+                                           &out_probe_head);
+
+               /* check all probes found */
+               if (list_empty(&test_bin->probe_head)) {
+                       list_move(&test_bin->list, out_bin_head);
+                       list_splice(&out_probe_head, &test_bin->probe_head);
+               } else {
+                       list_splice(&out_probe_head, &bin->probe_head);
                }
+       }
+}
 
-               ret = mod_func_inst(func, pfg, dentry, mt);
-               if (ret) {
-                       printk(KERN_INFO "Cannot mod func inst, ret = %d\n",
-                              ret);
-                       return ret;
+static void us_app_get_equal_elements(struct list_head *app_head,
+                                     struct list_head *test_app_head,
+                                     struct list_head *out_app_head)
+{
+       struct pr_app_desc *test_app, *n;
+
+       list_for_each_entry_safe(test_app, n, test_app_head, list) {
+               struct pr_app_desc *app;
+               LIST_HEAD(out_bin_head);
+
+               app = find_app(app_head, test_app->info);
+               if (!app)
+                       return;
+
+               us_bin_get_equal_elements(&app->bin_head,
+                                         &test_app->bin_head,
+                                         &out_bin_head);
+
+               /* check all bins found */
+               if (list_empty(&test_app->bin_head)) {
+                       list_move(&test_app->list, out_app_head);
+                       list_splice(&out_bin_head, &test_app->bin_head);
+               } else {
+                       list_splice(&out_bin_head, &app->bin_head);
                }
        }
+}
 
-       list_for_each_entry(lib, &app_inst->l_head, list) {
-               ret = mod_lib_inst(lib, pfg, mt);
-               if (ret) {
-                       printk(KERN_INFO "Cannot mod lib inst, ret = %d\n",
-                              ret);
-                       return ret;
+
+static void bin_list_splice(struct list_head *list, struct list_head *head)
+{
+       struct pr_bin_desc *new_bin, *n;
+
+       list_for_each_entry_safe(new_bin, n, list, list) {
+               struct pr_bin_desc *bin;
+
+               bin = find_bin(head, new_bin->info);
+               if (bin) {
+                       list_splice_init(&new_bin->probe_head,
+                                        &bin->probe_head);
+
+                       list_del(&new_bin->list);
+                       pr_bin_desc_free(new_bin);
+               } else {
+                       list_move(&new_bin->list, head);
+               }
+       }
+}
+
+static void app_list_splice(struct list_head *list, struct list_head *head)
+{
+       struct pr_app_desc *new_app, *n;
+
+       list_for_each_entry_safe(new_app, n, list, list) {
+               struct pr_app_desc *app;
+
+               app = find_app(head, new_app->info);
+               if (app) {
+                       bin_list_splice(&new_app->bin_head, &app->bin_head);
+
+                       list_del(&new_app->list);
+                       put_pf_group(app->pfg);
+                       pr_app_desc_free(new_app);
+               } else {
+                       list_move(&new_app->list, head);
                }
        }
+}
+
+static void app_list_free(struct list_head *head)
+{
+       struct pr_app_desc *app, *n;
+
+       list_for_each_entry_safe(app, n, head, list) {
+               list_del(&app->list);
+               pr_app_desc_free(app);
+       }
+}
+
+static void do_app_list_unreg(struct list_head *head)
+{
+       struct pr_app_desc *app;
+
+       list_for_each_entry(app, head, list) {
+               us_app_inst_unreg(app);
+       }
+}
+
+
+
+static LIST_HEAD(app_head);
+
+/* After call the 'head' list is empty, do not free it. */
+int app_list_unreg(struct list_head *head)
+{
+       LIST_HEAD(out_app_head);
+
+       us_app_get_equal_elements(&app_head, head, &out_app_head);
+
+       /* check all apps found */
+       if (!list_empty(head)) {
+               app_list_splice(&out_app_head, &app_head);
+               return -EINVAL;
+       }
 
+       do_app_list_unreg(&out_app_head);
+       app_list_free(&out_app_head);
        return 0;
 }
 
-/**
- * @brief Registers probes.
- *
- * @param us_inst Pointer to the target us_inst_data struct.
- * @param mt Modificator, indicates whether we install or remove probes.
- * @return 0 on suceess, error code on error.
- */
-int mod_us_inst(struct list_head *head, enum MOD_TYPE mt)
+/* After call the 'head' list is empty, do not free it. */
+int app_list_reg(struct list_head *head)
 {
-       int ret;
-       struct app_inst_data *ai;
-
-       list_for_each_entry(ai, head, list) {
-               ret = mod_us_app_inst(ai,  mt);
-               if (ret) {
-                       printk(KERN_INFO "Cannot mod us app inst, ret = %d\n",
-                              ret);
+       LIST_HEAD(reg_head);
+       struct pr_app_desc *app, *n;
+
+       list_for_each_entry_safe(app, n, head, list) {
+               int ret;
+
+               ret = us_app_inst_reg(app);
+               if (!ret) {
+                       list_move(&app->list, &reg_head);
+               } else {
+                       do_app_list_unreg(&reg_head);
+                       list_move(&reg_head, head);
+                       app_list_free(head);
                        return ret;
                }
        }
 
+       app_list_splice(&reg_head, &app_head);
        return 0;
 }
+
+void app_list_unreg_all(void)
+{
+       WARN_ON(app_list_unreg(&app_head));
+}
index 3ba3907..9db9e1f 100644 (file)
 #ifndef _US_INST_H
 #define _US_INST_H
 
-/**
- * @enum MOD_TYPE
- * @brief Type of mod_us_inst behaviour. */
-enum MOD_TYPE {
-       MT_ADD,             /**< Add probes. */
-       MT_DEL              /**< Remove probes. */
-};
-
-int mod_us_inst(struct list_head *head, enum MOD_TYPE mt);
-void pfg_put_all(void);
+int app_list_reg(struct list_head *head);
+int app_list_unreg(struct list_head *head);
+void app_list_unreg_all(void);
 
 #endif /* _US_INST_H */
index dc6b501..a31e9e7 100644 (file)
@@ -209,11 +209,7 @@ int uihv_disable(void)
                goto out;
        }
 
-       ret = pin_unregister(&__ui_data.p_main, __ui_data.pfg,
-                            __ui_data.app_dentry);
-       if (ret)
-               goto out;
-
+       pin_unregister(&__ui_data.p_main, __ui_data.pfg);
        put_pf_group(__ui_data.pfg);
        __ui_data.pfg = NULL;
        __ui_data.enable = false;
index b90ef0a..e5165d9 100644 (file)
 
 #include "img_file.h"
 #include "img_ip.h"
+#include <linux/err.h>
 #include <linux/slab.h>
 #include <linux/dcache.h>
+#include <linux/atomic.h>
+
+
+static atomic_t file_counter = ATOMIC_INIT(0);
 
 
 static void img_del_ip_by_list(struct img_ip *ip);
@@ -44,8 +49,9 @@ struct img_file *img_file_create(struct dentry *dentry)
        file = kmalloc(sizeof(*file), GFP_ATOMIC);
        if (file == NULL) {
                pr_err("%s: failed to allocate memory\n", __func__);
-               return NULL;
+               return ERR_PTR(-ENOMEM);
        }
+       atomic_inc(&file_counter);
 
        file->dentry = dentry;
        INIT_LIST_HEAD(&file->list);
@@ -72,6 +78,7 @@ static void img_file_free(struct img_file *file)
                img_ip_put(ip);
        }
 
+       atomic_dec(&file_counter);
        kfree(file);
 }
 
@@ -97,24 +104,8 @@ void img_file_put(struct img_file *file)
 {
        if (atomic_dec_and_test(&file->use))
                img_file_free(file);
-
-       return;
 }
 
-/* called with mutex_[lock/unlock](&file->ips.mtx) */
-static struct img_ip *find_img_ip(struct img_file *file, unsigned long addr,
-                                 struct probe_desc *pd)
-{
-       struct img_ip *ip;
-
-       list_for_each_entry(ip, &file->ips.head, list) {
-               if ((ip->addr == addr) &&
-                   (ip->desc == pd))
-                       return ip;
-       }
-
-       return NULL;
-}
 
 /**
  * @brief Add instrumentation pointer
@@ -125,30 +116,20 @@ static struct img_ip *find_img_ip(struct img_file *file, unsigned long addr,
  * the probe.
  * @return Error code
  */
-int img_file_add_ip(struct img_file *file, unsigned long addr,
-                   struct probe_desc *pd)
+struct img_ip *img_file_add_ip(struct img_file *file, unsigned long addr,
+                              struct probe_desc *pd)
 {
-       int ret = 0;
        struct img_ip *ip;
 
-       mutex_lock(&file->ips.mtx);
-       ip = find_img_ip(file, addr, pd);
-       if (ip) {
-               /* ip already exists in img */
-               goto unlock;
-       }
-
-       ip = img_ip_create(addr, pd);
-       if (ip == NULL) {
-               ret = -ENOMEM;
-               goto unlock;
-       }
+       ip = img_ip_create(addr, pd, file);
+       if (IS_ERR(ip))
+               return ip;
 
+       mutex_lock(&file->ips.mtx);
        img_add_ip_by_list(file, ip);
-
-unlock:
        mutex_unlock(&file->ips.mtx);
-       return ret;
+
+       return ip;
 }
 
 /**
@@ -158,27 +139,14 @@ unlock:
  * @param addr Function address
  * @return Error code
  */
-int img_file_del_ip(struct img_file *file, unsigned long addr,
-                   struct probe_desc *pd)
+void img_file_del_ip(struct img_file *file, struct img_ip *ip)
 {
-       struct img_ip *ip;
-
        mutex_lock(&file->ips.mtx);
-       ip = find_img_ip(file, addr, pd);
-       if (ip == NULL) {
-               printk(KERN_INFO "Warning: no ip found in img, addr = %lx\n",
-                      addr);
-               mutex_unlock(&file->ips.mtx);
-               return -EINVAL;
-       }
-
        img_del_ip_by_list(ip);
        mutex_unlock(&file->ips.mtx);
 
        img_ip_clean(ip);
        img_ip_put(ip);
-
-       return 0;
 }
 
 /**
@@ -194,6 +162,11 @@ int img_file_empty(struct img_file *file)
        return list_empty(&file->ips.head);
 }
 
+bool img_file_is_unloadable(void)
+{
+       return !(atomic_read(&file_counter) + !img_ip_is_unloadable());
+}
+
 /**
  * @brief For debug
  *
index df79909..e84bcaa 100644 (file)
@@ -53,12 +53,12 @@ struct img_file *img_file_create(struct dentry *dentry);
 void img_file_get(struct img_file *file);
 void img_file_put(struct img_file *file);
 
-int img_file_add_ip(struct img_file *file, unsigned long addr,
-                   struct probe_desc *pd);
-int img_file_del_ip(struct img_file *file, unsigned long addr,
-                   struct probe_desc *pd);
+struct img_ip *img_file_add_ip(struct img_file *file, unsigned long addr,
+                              struct probe_desc *pd);
+void img_file_del_ip(struct img_file *file, struct img_ip *ip);
 
 int img_file_empty(struct img_file *file);
+bool img_file_is_unloadable(void);
 
 /* debug */
 void img_file_print(struct img_file *file);
index c0caf1b..da7f6e2 100644 (file)
 
 
 #include "img_ip.h"
+#include "img_file.h"
 #include <us_manager/probes/use_probes.h>
 #include <us_manager/sspt/sspt.h>
 #include <us_manager/sspt/sspt_ip.h>
 #include <linux/slab.h>
+#include <linux/atomic.h>
+
+
+static atomic_t ip_counter = ATOMIC_INIT(0);
 
 /**
  * @brief Create img_ip struct
  * @param probe_i Pointer to the probe info data.
  * @return Pointer to the created img_ip struct
  */
-struct img_ip *img_ip_create(unsigned long addr, struct probe_desc *pd)
+struct img_ip *img_ip_create(unsigned long addr, struct probe_desc *pd,
+                            struct img_file *file)
 {
        struct img_ip *ip;
 
        ip = kmalloc(sizeof(*ip), GFP_KERNEL);
        if (!ip)
-               return NULL;
+               return ERR_PTR(-ENOMEM);
+       atomic_inc(&ip_counter);
 
        INIT_LIST_HEAD(&ip->list);
        kref_init(&ip->ref);
@@ -50,6 +57,7 @@ struct img_ip *img_ip_create(unsigned long addr, struct probe_desc *pd)
        INIT_LIST_HEAD(&ip->sspt.head);
        ip->addr = addr;
        ip->desc = pd;
+       ip->file = file;
 
        return ip;
 }
@@ -59,6 +67,8 @@ static void img_ip_release(struct kref *ref)
        struct img_ip *ip = container_of(ref, struct img_ip, ref);
 
        WARN_ON(!list_empty(&ip->sspt.head));
+
+       atomic_dec(&ip_counter);
        kfree(ip);
 }
 
@@ -109,6 +119,11 @@ void img_ip_unlock(struct img_ip *ip)
        mutex_unlock(&ip->sspt.mtx);
 }
 
+bool img_ip_is_unloadable(void)
+{
+       return !atomic_read(&ip_counter);
+}
+
 /**
  * @brief For debug
  *
index 402ffe8..b68c943 100644 (file)
@@ -32,6 +32,7 @@
 
 
 struct sspt_ip;
+struct img_file;
 struct probe_desc;
 
 /**
@@ -41,6 +42,7 @@ struct probe_desc;
 struct img_ip {
        /* img_file */
        struct list_head list;          /**< List for img_file */
+       struct img_file *file;          /**< Pointer on the file (parent) */
 
        struct kref ref;
 
@@ -54,7 +56,8 @@ struct img_ip {
        struct probe_desc *desc;        /**< Probe info */
 };
 
-struct img_ip *img_ip_create(unsigned long addr, struct probe_desc *info);
+struct img_ip *img_ip_create(unsigned long addr, struct probe_desc *info,
+                            struct img_file *file);
 void img_ip_clean(struct img_ip *ip);
 void img_ip_get(struct img_ip *ip);
 void img_ip_put(struct img_ip *ip);
@@ -63,6 +66,8 @@ void img_ip_add_ip(struct img_ip *ip, struct sspt_ip *sspt_ip);
 void img_ip_lock(struct img_ip *ip);
 void img_ip_unlock(struct img_ip *ip);
 
+bool img_ip_is_unloadable(void);
+
 /* debug */
 void img_ip_print(struct img_ip *ip);
 /* debug */
index 5051424..1d4db97 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/slab.h>
 #include <linux/list.h>
 #include <linux/mutex.h>
+#include <linux/atomic.h>
 #include <us_manager/sspt/sspt_proc.h>
 #include <us_manager/sspt/sspt_file.h>
 #include "img_ip.h"
@@ -42,6 +43,8 @@ struct img_proc {
 };
 
 
+static atomic_t proc_counter = ATOMIC_INIT(0);
+
 static void img_del_file_by_list(struct img_file *file);
 
 /**
@@ -55,6 +58,7 @@ struct img_proc *img_proc_create(void)
 
        proc = kmalloc(sizeof(*proc), GFP_ATOMIC);
        if (proc) {
+               atomic_inc(&proc_counter);
                INIT_LIST_HEAD(&proc->files.head);
                mutex_init(&proc->files.mtx);
        }
@@ -79,6 +83,7 @@ void img_proc_free(struct img_proc *proc)
        }
        mutex_unlock(&proc->files.mtx);
 
+       atomic_dec(&proc_counter);
        kfree(proc);
 }
 
@@ -117,31 +122,27 @@ static struct img_file *img_file_find(struct img_proc *proc,
  * @param probe_i Pointer to a probe_info struct related with the probe
  * @return Error code
  */
-int img_proc_add_ip(struct img_proc *proc, struct dentry *dentry,
-                   unsigned long addr, struct probe_desc *pd)
+struct img_ip *img_proc_add_ip(struct img_proc *proc, struct dentry *dentry,
+                              unsigned long addr, struct probe_desc *pd)
 {
-       int ret;
        struct img_file *file;
 
        mutex_lock(&proc->files.mtx);
        file = img_file_find(proc, dentry);
-
        if (!file) {
                file = img_file_create(dentry);
-               if (!file) {
+               if (IS_ERR(file)) {
                        mutex_unlock(&proc->files.mtx);
-                       return -ENOMEM;
+
+                       /* handle type cast */
+                       return ERR_PTR(PTR_ERR(file));
                }
 
                img_add_file_by_list(proc, file);
        }
        mutex_unlock(&proc->files.mtx);
 
-       ret = img_file_add_ip(file, addr, pd);
-       if (ret)
-               printk(KERN_INFO "Cannot add ip to img file\n");
-
-       return ret;
+       return img_file_add_ip(file, addr, pd);
 }
 
 /**
@@ -152,26 +153,17 @@ int img_proc_add_ip(struct img_proc *proc, struct dentry *dentry,
  * @param args Function address
  * @return Error code
  */
-int img_proc_del_ip(struct img_proc *proc,
-                   struct dentry *dentry,
-                   unsigned long addr,
-                   struct probe_desc *pd)
+void img_proc_del_ip(struct img_proc *proc, struct img_ip *ip)
 {
-       int ret = -EINVAL;
-       struct img_file *file;
+       struct img_file *file = ip->file;
 
        mutex_lock(&proc->files.mtx);
-       file = img_file_find(proc, dentry);
-       if (file) {
-               ret = img_file_del_ip(file, addr, pd);
-               if (img_file_empty(file)) {
-                       img_del_file_by_list(file);
-                       img_file_put(file);
-               }
+       img_file_del_ip(file, ip);
+       if (img_file_empty(file)) {
+               img_del_file_by_list(file);
+               img_file_put(file);
        }
        mutex_unlock(&proc->files.mtx);
-
-       return ret;
 }
 
 void img_proc_copy_to_sspt(struct img_proc *i_proc, struct sspt_proc *proc)
@@ -194,6 +186,11 @@ void img_proc_copy_to_sspt(struct img_proc *i_proc, struct sspt_proc *proc)
        mutex_unlock(&i_proc->files.mtx);
 }
 
+bool img_proc_is_unloadable(void)
+{
+       return !(atomic_read(&proc_counter) + !img_file_is_unloadable());
+}
+
 /**
  * @brief For debug
  *
index 730fea0..c9f0fc3 100644 (file)
@@ -35,12 +35,12 @@ struct probe_desc;
 struct img_proc *img_proc_create(void);
 void img_proc_free(struct img_proc *proc);
 
-int img_proc_add_ip(struct img_proc *proc, struct dentry *dentry,
-                   unsigned long addr, struct probe_desc *pd);
-int img_proc_del_ip(struct img_proc *proc, struct dentry *dentry,
-                   unsigned long addri, struct probe_desc *pd);
+struct img_ip *img_proc_add_ip(struct img_proc *proc, struct dentry *dentry,
+                              unsigned long addr, struct probe_desc *pd);
+void img_proc_del_ip(struct img_proc *proc, struct img_ip *ip);
 
 void img_proc_copy_to_sspt(struct img_proc *i_proc, struct sspt_proc *proc);
+bool img_proc_is_unloadable(void);
 
 /* debug */
 void img_proc_print(struct img_proc *proc);
index 38cfb85..6470414 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/list.h>
 #include <linux/namei.h>
 #include <linux/mman.h>
+#include <linux/atomic.h>
 #include <linux/spinlock.h>
 #include "pf_group.h"
 #include "proc_filters.h"
@@ -58,6 +59,8 @@ struct pl_struct {
 };
 
 
+static atomic_t pfg_counter = ATOMIC_INIT(0);
+
 static LIST_HEAD(pfg_list);
 static DECLARE_RWSEM(pfg_list_sem);
 
@@ -120,6 +123,7 @@ static struct pf_group *pfg_create(void)
        pfg->msg_cb = NULL;
        atomic_set(&pfg->usage, 1);
 
+       atomic_inc(&pfg_counter);
        return pfg;
 
 create_pfg_fail:
@@ -140,9 +144,15 @@ static void pfg_free(struct pf_group *pfg)
                free_pl_struct(pl);
        }
 
+       atomic_dec(&pfg_counter);
        kfree(pfg);
 }
 
+bool pfg_is_unloadable(void)
+{
+       return !(atomic_read(&pfg_counter) + !img_proc_is_unloadable());
+}
+
 static int pfg_add_proc(struct pf_group *pfg, struct sspt_proc *proc)
 {
        struct pl_struct *pls;
@@ -449,10 +459,10 @@ EXPORT_SYMBOL_GPL(put_pf_group);
  * @param dentry Dentry of file
  * @param offset Function offset
  * @param probe_info Pointer to the related probe_info struct
- * @return Error code
+ * @return pointer to the img_ip struct or error
  */
-int pf_register_probe(struct pf_group *pfg, struct dentry *dentry,
-                     unsigned long offset, struct probe_desc *pd)
+struct img_ip *pf_register_probe(struct pf_group *pfg, struct dentry *dentry,
+                                unsigned long offset, struct probe_desc *pd)
 {
        return img_proc_add_ip(pfg->i_proc, dentry, offset, pd);
 }
@@ -462,14 +472,13 @@ EXPORT_SYMBOL_GPL(pf_register_probe);
  * @brief Unregister prober from pf_grpup struct
  *
  * @param pfg Pointer to the pf_group struct
- * @param dentry Dentry of file
- * @param offset Function offset
- * @return Error code
+ * @param ip Pointer to the img_ip struct
+ * @return Void
  */
-int pf_unregister_probe(struct pf_group *pfg, struct dentry *dentry,
-                       unsigned long offset, struct probe_desc *pd)
+void pf_unregister_probe(struct pf_group *pfg, struct img_ip *ip)
 {
-       return img_proc_del_ip(pfg->i_proc, dentry, offset, pd);
+       WARN(IS_ERR_OR_NULL(ip), "invalid img_ip");
+       img_proc_del_ip(pfg->i_proc, ip);
 }
 EXPORT_SYMBOL_GPL(pf_unregister_probe);
 
index 3c170fa..b09d840 100644 (file)
@@ -27,6 +27,7 @@
 
 #include <linux/types.h>
 
+struct img_ip;
 struct dentry;
 struct pf_group;
 struct sspt_proc;
@@ -50,15 +51,15 @@ struct pf_group *get_pf_group_by_tgid(pid_t tgid, void *priv);
 struct pf_group *get_pf_group_by_comm(char *comm, void *priv);
 struct pf_group *get_pf_group_dumb(void *priv);
 void put_pf_group(struct pf_group *pfg);
+bool pfg_is_unloadable(void);
 
 int pfg_msg_cb_set(struct pf_group *pfg, struct pfg_msg_cb *msg_cb);
 void pfg_msg_cb_reset(struct pf_group *pfg);
 struct pfg_msg_cb *pfg_msg_cb_get(struct pf_group *pfg);
 
-int pf_register_probe(struct pf_group *pfg, struct dentry *dentry,
-                     unsigned long offset, struct probe_desc *pd);
-int pf_unregister_probe(struct pf_group *pfg, struct dentry *dentry,
-                       unsigned long offset, struct probe_desc *pd);
+struct img_ip *pf_register_probe(struct pf_group *pfg, struct dentry *dentry,
+                            unsigned long offset, struct probe_desc *pd);
+void pf_unregister_probe(struct pf_group *pfg, struct img_ip *ip);
 
 void install_all(void);
 void uninstall_all(void);
index fa4712a..9640c75 100644 (file)
@@ -83,31 +83,24 @@ static int uprobe_handler(struct uprobe *p, struct pt_regs *regs)
 int pin_register(struct probe_new *probe, struct pf_group *pfg,
                 struct dentry *dentry)
 {
-       int ret;
-       ret = pf_register_probe(pfg, dentry, probe->offset, probe->desc);
-       if (ret) {
-               printk(KERN_ERR "%s: register probe failed (%d)\n",
-                               __FUNCTION__, ret);
-               return ret;
+       struct img_ip *ip;
+
+       ip = pf_register_probe(pfg, dentry, probe->offset, probe->desc);
+       if (IS_ERR(ip)) {
+               pr_err("%s: register probe failed\n", __func__);
+               return PTR_ERR(ip);
        }
 
+       probe->priv = ip;
        return 0;
 }
 EXPORT_SYMBOL_GPL(pin_register);
 
-int pin_unregister(struct probe_new *probe, struct pf_group *pfg,
-                  struct dentry *dentry)
+void pin_unregister(struct probe_new *probe, struct pf_group *pfg)
 {
-       int ret;
+       struct img_ip *ip = probe->priv;
 
-       ret = pf_unregister_probe(pfg, dentry, probe->offset, probe->desc);
-       if (ret) {
-               printk(KERN_ERR "%s: unregister probe failed (%d)\n",
-                               __FUNCTION__, ret);
-               return ret;
-       }
-
-       return 0;
+       pf_unregister_probe(pfg, ip);
 }
 EXPORT_SYMBOL_GPL(pin_unregister);
 
index 8df6947..978bfe9 100644 (file)
@@ -55,8 +55,12 @@ struct probe_info_new {
 };
 
 struct probe_new {
+       /* reg data */
        unsigned long offset;
        struct probe_desc *desc;
+
+       /* unreg data */
+       void *priv;
 };
 
 
@@ -81,8 +85,7 @@ struct probe_info_otg {
 
 int pin_register(struct probe_new *probe, struct pf_group *pfg,
                 struct dentry *dentry);
-int pin_unregister(struct probe_new *probe, struct pf_group *pfg,
-                  struct dentry *dentry);
+void pin_unregister(struct probe_new *probe, struct pf_group *pfg);
 
 
 int pin_init(void);
index 8ea1041..8559832 100644 (file)
@@ -277,6 +277,8 @@ static void exit_us_manager(void)
        exit_us_filter();
        pin_exit();
        sspt_proc_uninit();
+
+       WARN_ON(!pfg_is_unloadable());
 }
 
 SWAP_LIGHT_INIT_MODULE(usm_once, init_us_manager, exit_us_manager,
index d3d7620..c88dbf6 100644 (file)
@@ -45,6 +45,10 @@ struct web_prof_data {
        struct pf_group *pfg;
        u64 inspserver_addr;
        u64 tick_addr;
+
+       struct probe_new inspserver_probe;
+       struct probe_new tick_probe;
+
        bool enable;
 };
 
@@ -55,18 +59,12 @@ static struct web_prof_data *web_data;
 /* function tick handler */
 static int tick_handler(struct uprobe *p, struct pt_regs *regs);
 static struct probe_desc pin_tick_handler = MAKE_UPROBE(tick_handler);
-static struct probe_new tick_probe = {
-       .desc = &pin_tick_handler
-};
 
 /* function inspector port */
 static int insport_rhandler(struct uretprobe_instance *ri,
                            struct pt_regs *regs);
 static struct probe_desc pin_insport_rhandler =
                                MAKE_URPROBE(NULL, insport_rhandler, 0);
-static struct probe_new insport_probe = {
-       .desc = &pin_insport_rhandler
-};
 
 static int insport_rhandler(struct uretprobe_instance *ri,
                            struct pt_regs *regs)
@@ -151,28 +149,31 @@ bool web_prof_enabled(void)
 
 static void __web_prof_disable(struct web_prof_data *data)
 {
-       pin_unregister(&tick_probe, data->pfg, data->lib_dentry);
-       pin_unregister(&insport_probe, data->pfg, data->lib_dentry);
+       pin_unregister(&data->tick_probe, data->pfg);
+       pin_unregister(&data->inspserver_probe, data->pfg);
 }
 
 static int __web_prof_enable(struct web_prof_data *data)
 {
        int ret;
 
-       tick_probe.offset = data->tick_addr;
-       ret = pin_register(&tick_probe, data->pfg, data->lib_dentry);
+       data->tick_probe.offset = (unsigned long)data->tick_addr;
+       data->tick_probe.desc = &pin_tick_handler;
+       ret = pin_register(&data->tick_probe, data->pfg, data->lib_dentry);
        if (ret)
                goto fail0;
 
-       insport_probe.offset = data->inspserver_addr;
-       ret = pin_register(&insport_probe, data->pfg, data->lib_dentry);
+       data->inspserver_probe.offset = (unsigned long)data->inspserver_addr;
+       data->inspserver_probe.desc = &pin_insport_rhandler;
+       ret = pin_register(&data->inspserver_probe, data->pfg,
+                          data->lib_dentry);
        if (ret)
                goto fail1;
 
        return 0;
 
 fail1:
-       pin_unregister(&tick_probe, data->pfg, data->lib_dentry);
+       pin_unregister(&data->tick_probe, data->pfg);
 fail0:
        return ret;
 }
index 6e87139..66b8cbe 100644 (file)
--- a/wsp/wsp.c
+++ b/wsp/wsp.c
@@ -197,22 +197,6 @@ static bool wsp_is_addr_init(void)
        return true;
 }
 
-static int wsp_probe_register(struct pf_group *pfg, struct dentry *dentry,
-                             struct wsp_probe *wsp_probe)
-{
-       struct probe_new *probe_new = &wsp_probe->probe;
-
-       return pin_register(probe_new, pfg, dentry);
-}
-
-static void wsp_probe_unregister(struct pf_group *pfg, struct dentry *dentry,
-                                struct wsp_probe *wsp_probe)
-{
-       struct probe_new *probe_new = &wsp_probe->probe;
-
-       pin_unregister(probe_new, pfg, dentry);
-}
-
 static int wsp_bin_register(struct pf_group *pfg, struct wsp_bin *bin)
 {
        int i, ret;
@@ -227,7 +211,7 @@ static int wsp_bin_register(struct pf_group *pfg, struct wsp_bin *bin)
        for (i = 0; i < bin->cnt; ++i) {
                struct wsp_probe *p = &bin->probe_array[i];
 
-               ret = wsp_probe_register(pfg, dentry, p);
+               ret = pin_register(&p->probe, pfg, dentry);
                if (ret) {
                        pr_err("failed to register WSP probe (%lx:%d)\n",
                               p->probe.offset, ret);
@@ -252,7 +236,7 @@ static void wsp_bin_unregister(struct pf_group *pfg, struct wsp_bin *bin)
        for (i = 0; i < bin->cnt; ++i) {
                struct wsp_probe *p = &bin->probe_array[i];
 
-               wsp_probe_unregister(pfg, dentry, p);
+               pin_unregister(&p->probe, pfg);
        }
 }