[FEATURE] New probes interface 55/29555/7
authorAlexander Aksenov <a.aksenov@samsung.com>
Tue, 9 Sep 2014 07:59:57 +0000 (11:59 +0400)
committerAlexander Aksenov <a.aksenov@samsung.com>
Wed, 12 Nov 2014 12:30:50 +0000 (15:30 +0300)
Separates probes from us_manager.
Now all new probe types should register their methods
using special interface declared in us_manager/probes/register_probes.h
To use probes methods, include us_manager/probes/use_probes.h.

Change-Id: I07c7452789b8eec42cd5372ad2b69a5b8d56804b
Signed-off-by: Alexander Aksenov <a.aksenov@samsung.com>
26 files changed:
Kbuild
build.sh
parser/us_inst.c
retprobe/Kbuild [new file with mode: 0644]
retprobe/retprobe.c [new file with mode: 0644]
retprobe/retprobe.h [new file with mode: 0644]
us_manager/Kbuild
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/probes.c [new file with mode: 0644]
us_manager/probes/probes.h [new file with mode: 0644]
us_manager/probes/register_probes.h [new file with mode: 0644]
us_manager/probes/use_probes.h [new file with mode: 0644]
us_manager/sspt/ip.c
us_manager/sspt/ip.h
us_manager/sspt/sspt.h
us_manager/sspt/sspt_debug.h
us_manager/sspt/sspt_file.c
us_manager/sspt/sspt_file.h
us_manager/sspt/sspt_page.c

diff --git a/Kbuild b/Kbuild
index e334a39..40b8f27 100644 (file)
--- a/Kbuild
+++ b/Kbuild
@@ -11,4 +11,5 @@ obj-m := buffer/ \
          ks_features/ \
          sampler/ \
          energy/ \
-         parser/
+         parser/ \
+         retprobe/
index b13e5dd..e824400 100755 (executable)
--- a/build.sh
+++ b/build.sh
@@ -34,6 +34,7 @@ ks_features_dir=${modules_dir}/ks_features
 sampler_dir=${modules_dir}/sampler
 energy_dir=${modules_dir}/energy
 parser_dir=${modules_dir}/parser
+retprobe_dir=${modules_dir}/retprobe
 
 buffer_module_name=swap_buffer.ko
 driver_module_name=swap_driver.ko
@@ -47,6 +48,7 @@ sampler_module_name=swap_sampler.ko
 energy_module_name=swap_energy.ko
 parser_module_name=swap_message_parser.ko
 ksyms_module_name=swap_ksyms.ko
+retprobe_module_name=swap_retprobe.ko
 
 install_dir="/opt/swap/sdk"
 
@@ -69,7 +71,8 @@ ${ks_features_dir}/${ks_features_module_name} \
 ${sampler_dir}/${sampler_module_name} \
 ${energy_dir}/${energy_module_name} \
 ${parser_dir}/${parser_module_name} \
-${ksyms_dir}/${ksyms_module_name}"
+${ksyms_dir}/${ksyms_module_name} \
+${retprobe_dir}/${retprobe_module_name}"
 
 for m in ${modules} ; do
        ${cross_compile}strip -x -g $m
index 4baf1a6..b36edba 100644 (file)
@@ -33,6 +33,8 @@
 #include <linux/errno.h>
 #include <linux/namei.h>
 #include <us_manager/pf/pf_group.h>
+#include <us_manager/probes/probes.h>
+
 #include "msg_parser.h"
 #include "us_inst.h"
 
@@ -72,9 +74,17 @@ static int mod_func_inst(struct func_inst_data *func, struct pf_group *pfg,
 
        switch (mt) {
        case MT_ADD:
-               ret = pf_register_probe(pfg, dentry, func->addr, func->args,
-                                       func->ret_type);
+       {
+               struct probe_info probe_i;
+
+               /* ARM toolchain hates good style initialization of struct with union */
+               probe_i.probe_type = SWAP_RETPROBE;
+               probe_i.rp_i.args = func->args;
+               probe_i.rp_i.ret_type = func->ret_type;
+               probe_i.rp_i.size = 0;
+               ret = pf_register_probe(pfg, dentry, func->addr, &probe_i);
                break;
+       }
        case MT_DEL:
                ret = pf_unregister_probe(pfg, dentry, func->addr);
                break;
diff --git a/retprobe/Kbuild b/retprobe/Kbuild
new file mode 100644 (file)
index 0000000..0c9fefb
--- /dev/null
@@ -0,0 +1,4 @@
+EXTRA_CFLAGS := $(extra_cflags)
+
+obj-m := swap_retprobe.o
+swap_retprobe-y := retprobe.o
diff --git a/retprobe/retprobe.c b/retprobe/retprobe.c
new file mode 100644 (file)
index 0000000..96ba8c4
--- /dev/null
@@ -0,0 +1,143 @@
+/*
+ *  SWAP uprobe manager
+ *  modules/retprobe/retprobe.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Copyright (C) Samsung Electronics, 2014
+ *
+ * 2014         Alexander Aksenov: Probes interface implement
+ *
+ */
+
+#include "retprobe.h"
+#include <us_manager/us_manager.h>
+#include <us_manager/sspt/ip.h>
+#include <us_manager/probes/register_probes.h>
+#include <writer/swap_writer_module.h>
+#include <uprobe/swap_uprobes.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+
+static int retprobe_copy(struct probe_info *dest,
+                        const struct probe_info *source)
+{
+       size_t len;
+
+       memcpy(dest, source, sizeof(*source));
+
+       len = strlen(source->rp_i.args) + 1;
+       dest->rp_i.args = kmalloc(len, GFP_KERNEL);
+       if (dest->rp_i.args == NULL)
+               return -ENOMEM;
+       memcpy(dest->rp_i.args, source->rp_i.args, len);
+
+       return 0;
+}
+
+
+static void retprobe_cleanup(struct probe_info *probe_i)
+{
+       kfree(probe_i->rp_i.args);
+}
+
+
+
+static struct uprobe *retprobe_get_uprobe(struct us_ip *ip)
+{
+       return &ip->retprobe.up;
+}
+
+static int retprobe_register_probe(struct us_ip *ip)
+{
+       return swap_register_uretprobe(&ip->retprobe);
+}
+
+static void retprobe_unregister_probe(struct us_ip *ip, int disarm)
+{
+       __swap_unregister_uretprobe(&ip->retprobe, disarm);
+}
+
+
+static int retprobe_entry_handler(struct uretprobe_instance *ri, struct pt_regs *regs)
+{
+       struct uretprobe *rp = ri->rp;
+
+       if (rp && get_quiet() == QT_OFF) {
+               struct us_ip *ip = container_of(rp, struct us_ip, retprobe);
+               const char *fmt = ip->probe_i.rp_i.args;
+               unsigned long addr = (unsigned long)ip->orig_addr;
+
+               entry_event(fmt, addr, regs, PT_US, PST_NONE);
+       }
+
+       return 0;
+}
+
+static int retprobe_ret_handler(struct uretprobe_instance *ri, struct pt_regs *regs)
+{
+       struct uretprobe *rp = ri->rp;
+
+       if (rp && get_quiet() == QT_OFF) {
+               struct us_ip *ip = container_of(rp, struct us_ip, retprobe);
+               unsigned long addr = (unsigned long)ip->orig_addr;
+               unsigned long ret_addr = (unsigned long)ri->ret_addr;
+
+               exit_event(ip->probe_i.rp_i.ret_type, regs, PT_US, PST_NONE, addr,
+                  ret_addr);
+       }
+
+       return 0;
+}
+
+static void retprobe_init(struct us_ip *ip)
+{
+       ip->retprobe.entry_handler = retprobe_entry_handler;
+       ip->retprobe.handler = retprobe_ret_handler;
+       ip->retprobe.maxactive = 0;
+}
+
+static void retprobe_uninit(struct us_ip *ip)
+{
+       retprobe_cleanup(&ip->probe_i);
+}
+
+
+static struct probe_iface retprobe_iface = {
+       .init = retprobe_init,
+       .uninit = retprobe_uninit,
+       .reg = retprobe_register_probe,
+       .unreg = retprobe_unregister_probe,
+       .get_uprobe = retprobe_get_uprobe,
+       .copy = retprobe_copy,
+       .cleanup = retprobe_cleanup
+};
+
+static int __init retprobe_module_init(void)
+{
+       return swap_register_probe_type(SWAP_RETPROBE, &retprobe_iface);
+}
+
+static void __exit retprobe_module_exit(void)
+{
+       swap_unregister_probe_type(SWAP_RETPROBE);
+}
+
+module_init(retprobe_module_init);
+module_exit(retprobe_module_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("SWAP retprobe");
+MODULE_AUTHOR("Alexander Aksenov <a.aksenov@samsung.com>");
diff --git a/retprobe/retprobe.h b/retprobe/retprobe.h
new file mode 100644 (file)
index 0000000..7a82781
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ *  SWAP uprobe manager
+ *  modules/us_manager/probes/uretprobe.h
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Copyright (C) Samsung Electronics, 2014
+ *
+ * 2014         Alexander Aksenov: Probes interface implement
+ *
+ */
+
+#ifndef __URETPROBE_H__
+#define __URETPROBE_H__
+
+/* Common retprobe info */
+struct retprobe_info {
+       char *args;
+       char ret_type;
+};
+
+#endif /* __URETPROBE_H__ */
index 5e2cc16..c6db3e9 100644 (file)
@@ -8,4 +8,5 @@ swap_us_manager-y := us_manager.o us_slot_manager.o helper.o debugfs_us_manager.
                      sspt/ip.o sspt/sspt_page.o sspt/sspt_file.o sspt/sspt_proc.o \
                      sspt/sspt_feature.o sspt/sspt_filter.o \
                      pf/proc_filters.o pf/pf_group.o \
-                     img/img_proc.o img/img_file.o img/img_ip.o
+                     img/img_proc.o img/img_file.o img/img_ip.o \
+                     probes/probes.o
index 6a2d405..d87a2c0 100644 (file)
@@ -94,12 +94,12 @@ static struct img_ip *find_img_ip(struct img_file *file, unsigned long addr)
  *
  * @param file Pointer to the img_file struct
  * @param addr Function address
- * @param args Function arguments
- * @param ret_type Return type
+ * @param probe_Pointer to a probe_info structure with an information about
+ * the probe.
  * @return Error code
  */
 int img_file_add_ip(struct img_file *file, unsigned long addr,
-                   const char *args, char ret_type)
+                   struct probe_info *probe_i)
 {
        struct img_ip *ip;
 
@@ -109,7 +109,7 @@ int img_file_add_ip(struct img_file *file, unsigned long addr,
                return 0;
        }
 
-       ip = create_img_ip(addr, args, ret_type);
+       ip = create_img_ip(addr, probe_i);
        img_add_ip_by_list(file, ip);
 
        return 0;
index 312313d..5e7977b 100644 (file)
@@ -28,6 +28,8 @@
 
 #include <linux/types.h>
 
+struct probe_info;
+
 /**
  * @struct img_file
  * @breaf Image of file
@@ -42,7 +44,7 @@ struct img_file *create_img_file(struct dentry *dentry);
 void free_img_file(struct img_file *ip);
 
 int img_file_add_ip(struct img_file *file, unsigned long addr,
-                   const char *args, char ret_type);
+                   struct probe_info *probe_i);
 int img_file_del_ip(struct img_file *file, unsigned long addr);
 
 int img_file_empty(struct img_file *file);
index 102d9f0..7b6395a 100644 (file)
 
 
 #include "img_ip.h"
+#include <us_manager/probes/use_probes.h>
 #include <linux/slab.h>
 
 /**
  * @brief Create img_ip struct
  *
  * @param addr Function address
- * @param args Function arguments
- * @param ret_type Return type
+ * @param probe_i Pointer to the probe info data.
  * @return Pointer to the created img_ip struct
  */
-struct img_ip *create_img_ip(unsigned long addr, const char *args,
-                            char ret_type)
+struct img_ip *create_img_ip(unsigned long addr, struct probe_info *probe_i)
 {
        struct img_ip *ip;
-       size_t len;
 
        ip = kmalloc(sizeof(*ip), GFP_KERNEL);
        INIT_LIST_HEAD(&ip->list);
        ip->addr = addr;
 
-       /* copy args */
-       len = strlen(args) + 1;
-       ip->args = kmalloc(len, GFP_KERNEL);
-       memcpy(ip->args, args, len);
-
-       ip->ret_type = ret_type;
+       probe_info_copy(probe_i, &ip->probe_i);
 
        return ip;
 }
@@ -62,7 +55,7 @@ struct img_ip *create_img_ip(unsigned long addr, const char *args,
  */
 void free_img_ip(struct img_ip *ip)
 {
-       kfree(ip->args);
+       probe_info_cleanup(&ip->probe_i);
        kfree(ip);
 }
 
@@ -76,6 +69,8 @@ void free_img_ip(struct img_ip *ip)
 /* debug */
 void img_ip_print(struct img_ip *ip)
 {
-       printk("###            addr=8%lx, args=%s\n", ip->addr, ip->args);
+       if (ip->probe_i.probe_type == SWAP_RETPROBE)
+               printk("###            addr=8%lx, args=%s\n", ip->addr,
+                          ip->probe_i.rp_i.args);
 }
 /* debug */
index a6992f7..cd14722 100644 (file)
@@ -27,6 +27,7 @@
 #define _IMG_IP_H
 
 #include <linux/types.h>
+#include <us_manager/probes/probes.h>
 
 /**
  * @struct img_ip
 struct img_ip {
        struct list_head list;          /**< For img_file */
        unsigned long addr;             /**< Function address */
-       char *args;                     /**< Function arguments */
-       char ret_type;                  /**< Return type */
+       struct probe_info probe_i;      /**< Probe info */
 };
 
-struct img_ip *create_img_ip(unsigned long addr, const char *args,
-                            char ret_type);
+struct img_ip *create_img_ip(unsigned long addr, struct probe_info *probe_i);
 void free_img_ip(struct img_ip *ip);
 
 /* debug */
index ce7749a..71b20d3 100644 (file)
@@ -90,23 +90,22 @@ static struct img_file *find_img_file(struct img_proc *proc, struct dentry *dent
  * @param proc Pointer to the img_proc struct
  * @param dentry Dentry of file
  * @param addr Function address
- * @param args Function address
- * @param ret_type Return type
+ * @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, const char *args, char ret_type)
+                   unsigned long addr, struct probe_info *probe_i)
 {
        int ret;
        struct img_file *file;
 
        file = find_img_file(proc, dentry);
        if (file)
-               return img_file_add_ip(file, addr, args, ret_type);
+               return img_file_add_ip(file, addr, probe_i);
 
        file = create_img_file(dentry);
 
-       ret = img_file_add_ip(file, addr, args, ret_type);
+       ret = img_file_add_ip(file, addr, probe_i);
        if (ret) {
                printk("Cannot add ip to img file\n");
                free_img_file(file);
index a1b71d5..745df84 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/types.h>
 
 struct dentry;
+struct probe_info;
 
 /**
  * @struct img_proc
@@ -41,7 +42,7 @@ struct img_proc *create_img_proc(void);
 void free_img_proc(struct img_proc *proc);
 
 int img_proc_add_ip(struct img_proc *proc, struct dentry *dentry,
-                   unsigned long addr, const char *args, char ret_type);
+                   unsigned long addr, struct probe_info *probe_i);
 int img_proc_del_ip(struct img_proc *proc, struct dentry *dentry, unsigned long addr);
 
 /* debug */
index e5667b0..920c8fc 100644 (file)
@@ -86,8 +86,7 @@ void copy_proc_form_img_to_sspt(struct img_proc *i_proc, struct sspt_proc *proc)
                file = sspt_proc_find_file_or_new(proc, i_file->dentry);
 
                list_for_each_entry(i_ip, &i_file->ip_list, list)
-                       sspt_file_add_ip(file, i_ip->addr, i_ip->args,
-                                        i_ip->ret_type);
+                       sspt_file_add_ip(file, i_ip->addr, &i_ip->probe_i);
        }
 }
 
@@ -345,14 +344,13 @@ void put_pf_group(struct pf_group *pfg)
  * @param pfg Pointer to the pf_group struct
  * @param dentry Dentry of file
  * @param offset Function offset
- * @param args Function arguments
- * @param ret_type Return type
+ * @param probe_info Pointer to the related probe_info struct
  * @return Error code
  */
 int pf_register_probe(struct pf_group *pfg, struct dentry *dentry,
-                     unsigned long offset, const char *args, char ret_type)
+                     unsigned long offset, struct probe_info *probe_i)
 {
-       return img_proc_add_ip(pfg->i_proc, dentry, offset, args, ret_type);
+       return img_proc_add_ip(pfg->i_proc, dentry, offset, probe_i);
 }
 EXPORT_SYMBOL_GPL(pf_register_probe);
 
index 2065768..f69bd0b 100644 (file)
@@ -30,6 +30,7 @@
 struct dentry;
 struct pf_group;
 struct sspt_proc;
+struct probe_info;
 
 struct pf_group *get_pf_group_by_dentry(struct dentry *dentry, void *priv);
 struct pf_group *get_pf_group_by_tgid(pid_t tgid, void *priv);
@@ -38,7 +39,7 @@ struct pf_group *get_pf_group_dumb(void *priv);
 void put_pf_group(struct pf_group *pfg);
 
 int pf_register_probe(struct pf_group *pfg, struct dentry *dentry,
-                     unsigned long offset, const char *args, char ret_type);
+                     unsigned long offset, struct probe_info *probe_i);
 int pf_unregister_probe(struct pf_group *pfg, struct dentry *dentry,
                        unsigned long offset);
 
diff --git a/us_manager/probes/probes.c b/us_manager/probes/probes.c
new file mode 100644 (file)
index 0000000..52b024f
--- /dev/null
@@ -0,0 +1,229 @@
+/*
+ *  SWAP uprobe manager
+ *  modules/us_manager/probes/probes.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Copyright (C) Samsung Electronics, 2014
+ *
+ * 2014         Alexander Aksenov: Probes interface implement
+ *
+ */
+
+#include "probes.h"
+#include "register_probes.h"
+#include "use_probes.h"
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/module.h>
+
+static struct probe_iface *probes_methods[SWAP_PROBE_MAX_VAL] = { NULL };
+
+/* 1 - correct probe type
+   0 - wrong probe type
+*/
+static inline int correct_probe_type(enum probe_t probe_type)
+{
+       if (probe_type >= SWAP_PROBE_MAX_VAL)
+               return 0;
+
+       return 1;
+}
+
+static inline int methods_exist(enum probe_t probe_type)
+{
+       if (!correct_probe_type(probe_type))
+               return 0;
+
+       if (probes_methods[probe_type] == NULL)
+               return 0;
+
+       return 1;
+}
+
+/**
+ * @brief Calls specified probe type init method.
+ *
+ * @param pi Pointer to the probe_info.
+ * @param ip Pointer to the probe us_ip struct.
+ * @return Void.
+ */
+void probe_info_init(struct probe_info *pi, struct us_ip *ip)
+{
+       enum probe_t probe_type = pi->probe_type;
+
+       if (!methods_exist(probe_type)) {
+               printk(KERN_WARNING "SWAP US_MANAGER: Wrong probe type!\n");
+               return;
+       }
+
+       probes_methods[probe_type]->init(ip);
+}
+
+/**
+ * @brief Calls specified probe type uninit method.
+ *
+ * @param pi Pointer to the probe_info.
+ * @param ip Pointer to the probe us_ip struct.
+ * @return Void.
+ */
+void probe_info_uninit(struct probe_info *pi, struct us_ip *ip)
+{
+       enum probe_t probe_type = pi->probe_type;
+
+       if (!methods_exist(probe_type)) {
+               printk(KERN_WARNING "SWAP US_MANAGER: Wrong probe type!\n");
+               return;
+       }
+
+       probes_methods[probe_type]->uninit(ip);
+}
+
+/**
+ * @brief Calls specified probe type register method.
+ *
+ * @param pi Pointer to the probe_info.
+ * @param ip Pointer to the probe us_ip struct.
+ * @return -EINVAL on wrong probe type, method result otherwise.
+ */
+int probe_info_register(struct probe_info *pi, struct us_ip *ip)
+{
+       enum probe_t probe_type = pi->probe_type;
+
+       if (!methods_exist(probe_type)) {
+               printk(KERN_WARNING "SWAP US_MANAGER: Wrong probe type!\n");
+               return -EINVAL;
+       }
+
+       return probes_methods[probe_type]->reg(ip);
+}
+
+/**
+ * @brief Calls specified probe type unregister method.
+ *
+ * @param pi Pointer to the probe_info.
+ * @param ip Pointer to the probe us_ip struct.
+ * @param disarm Disarm flag.
+ * @return Void.
+ */
+void probe_info_unregister(struct probe_info *pi, struct us_ip *ip, int disarm)
+{
+       enum probe_t probe_type = pi->probe_type;
+
+       if (!methods_exist(probe_type)) {
+               printk(KERN_WARNING "SWAP US_MANAGER: Wrong probe type!\n");
+               return;
+       }
+
+       probes_methods[probe_type]->unreg(ip, disarm);
+}
+
+/**
+ * @brief Calls specified probe type get underlying uprobe method.
+ *
+ * @param pi Pointer to the probe_info.
+ * @param ip Pointer to the probe us_ip struct.
+ * @return Pointer to the uprobe struct, NULL on error.
+ */
+struct uprobe *probe_info_get_uprobe(struct probe_info *pi, struct us_ip *ip)
+{
+       enum probe_t probe_type = pi->probe_type;
+
+       if (!methods_exist(probe_type)) {
+               printk(KERN_WARNING "SWAP US_MANAGER: Wrong probe type!\n");
+               return NULL;
+       }
+
+       return probes_methods[probe_type]->get_uprobe(ip);
+}
+
+/**
+ * @brief Calls specified probe type copy method.
+ *
+ * @param pi Pointer to the source probe_info.
+ * @param dest Pointer to the probe us_ip struct.
+ * @return -EINVAL on error, method result otherwise.
+ */
+int probe_info_copy(const struct probe_info *pi, struct probe_info *dest)
+{
+       enum probe_t probe_type = pi->probe_type;
+
+       if (!methods_exist(probe_type)) {
+               printk(KERN_WARNING "SWAP US_MANAGER: Wrong probe type!\n");
+               return -EINVAL;
+       }
+
+       return probes_methods[probe_type]->copy(dest, pi);
+}
+
+/**
+ * @brief Calls specified probe type cleanup method.
+ *
+ * @param pi Pointer to the source probe_info.
+ * @return Void.
+ */
+void probe_info_cleanup(struct probe_info *pi)
+{
+       enum probe_t probe_type = pi->probe_type;
+
+       if (!methods_exist(probe_type)) {
+               printk(KERN_WARNING "SWAP US_MANAGER: Wrong probe type!\n");
+               return;
+       }
+
+       probes_methods[probe_type]->cleanup(pi);
+}
+
+/**
+ * @brief Registers probe type.
+ *
+ * @param probe_type Number, associated with this probe type.
+ * @param pi Pointer to the probe interface structure
+ * @return 0 on succes, error code on error.
+ */
+int swap_register_probe_type(enum probe_t probe_type, struct probe_iface *pi)
+{
+       if (!correct_probe_type(probe_type)) {
+               printk(KERN_ERR "SWAP US_MANAGER: Wrong probe type!\n");
+               return -EINVAL;
+       }
+
+       if (probes_methods[probe_type] != NULL)
+               printk(KERN_WARNING "SWAP US_MANAGER: Re-registering probe %d\n",
+                  probe_type);
+
+       probes_methods[probe_type] = pi;
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(swap_register_probe_type);
+
+/**
+ * @brief Unregisters probe type.
+ *
+ * @param probe_type Probe type that should be unregistered.
+ * @return Void.
+ */
+void swap_unregister_probe_type(enum probe_t probe_type)
+{
+       if (!correct_probe_type(probe_type)) {
+               printk(KERN_ERR "SWAP US_MANAGER: Wrong probe type!\n");
+               return;
+       }
+
+       probes_methods[probe_type] = NULL;
+}
+EXPORT_SYMBOL_GPL(swap_unregister_probe_type);
diff --git a/us_manager/probes/probes.h b/us_manager/probes/probes.h
new file mode 100644 (file)
index 0000000..4ba8111
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ *  SWAP uprobe manager
+ *  modules/us_manager/probes/probes.h
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Copyright (C) Samsung Electronics, 2014
+ *
+ * 2014         Alexander Aksenov: Probes interface implement
+ *
+ */
+
+
+#ifndef __PROBES_H__
+#define __PROBES_H__
+
+#include <linux/types.h>
+
+#include <retprobe/retprobe.h>       /* TODO Remove */
+
+
+
+/* All probe types. Only us_manager should know about them - it is its own
+ * business to install proper probes on proper places.
+ */
+enum probe_t {
+       SWAP_RETPROBE = 0,          /* Retprobe */
+       SWAP_PROBE_MAX_VAL          /* Probes max value. */
+};
+
+/* Probe info stuct. It contains the whole information about probe. */
+struct probe_info {
+       enum probe_t probe_type;
+       size_t size;
+       /* Union of all SWAP supported probe types */
+       union {
+               struct retprobe_info rp_i;
+       };
+};
+
+#endif /* __PROBES_H__ */
diff --git a/us_manager/probes/register_probes.h b/us_manager/probes/register_probes.h
new file mode 100644 (file)
index 0000000..fb6a244
--- /dev/null
@@ -0,0 +1,21 @@
+#ifndef __REGISTER_PROBES_H__
+#define __REGISTER_PROBES_H__
+
+#include "probes.h"
+
+struct us_ip;
+
+struct probe_iface {
+       void (*init)(struct us_ip *);
+       void (*uninit)(struct us_ip *);
+       int (*reg)(struct us_ip *);
+       void (*unreg)(struct us_ip *, int);
+       struct uprobe *(*get_uprobe)(struct us_ip *);
+       int (*copy)(struct probe_info *, const struct probe_info *);
+       void (*cleanup)(struct probe_info *);
+};
+
+int swap_register_probe_type(enum probe_t probe_type, struct probe_iface *pi);
+void swap_unregister_probe_type(enum probe_t probe_type);
+
+#endif /* __REGISTER_PROBES_H__ */
diff --git a/us_manager/probes/use_probes.h b/us_manager/probes/use_probes.h
new file mode 100644 (file)
index 0000000..80cfb3a
--- /dev/null
@@ -0,0 +1,16 @@
+#ifndef __USE_PROBES_H__
+#define __USE_PROBES_H__
+
+#include "probes.h"
+
+struct us_ip;
+
+void probe_info_init(struct probe_info *pi, struct us_ip *ip);
+void probe_info_uninit(struct probe_info *pi, struct us_ip *ip);
+int probe_info_register(struct probe_info *pi, struct us_ip *ip);
+void probe_info_unregister(struct probe_info *pi, struct us_ip *ip, int disarm);
+struct uprobe *probe_info_get_uprobe(struct probe_info *pi, struct us_ip *ip);
+int probe_info_copy(const struct probe_info *pi, struct probe_info *dest);
+void probe_info_cleanup(struct probe_info *pi);
+
+#endif /* __USE_PROBES_H__ */
index a54353e..0a46b33 100644 (file)
 #include "ip.h"
 #include "sspt_page.h"
 #include "sspt_file.h"
-#include <writer/swap_writer_module.h>
-#include <us_manager/us_manager.h>
-
-
-static int entry_handler(struct uretprobe_instance *ri, struct pt_regs *regs)
-{
-       struct uretprobe *rp = ri->rp;
-
-       if (rp && get_quiet() == QT_OFF) {
-               struct us_ip *ip = container_of(rp, struct us_ip, retprobe);
-               const char *fmt = ip->args;
-               unsigned long addr = (unsigned long)ip->orig_addr;
-
-               entry_event(fmt, addr, regs, PT_US, PST_NONE);
-       }
-
-       return 0;
-}
-
-static int ret_handler(struct uretprobe_instance *ri, struct pt_regs *regs)
-{
-       struct uretprobe *rp = ri->rp;
-
-       if (rp && get_quiet() == QT_OFF) {
-               struct us_ip *ip = container_of(rp, struct us_ip, retprobe);
-               unsigned long addr = (unsigned long)ip->orig_addr;
-               unsigned long ret_addr = (unsigned long)ri->ret_addr;
-
-               exit_event(ip->ret_type, regs, PT_US, PST_NONE, addr, ret_addr);
-       }
-
-       return 0;
-}
+#include <us_manager/probes/use_probes.h>
 
 /**
  * @brief Create us_ip struct
  *
  * @param offset Function offset from the beginning of the page
- * @param args Function arguments
- * @param ret_type Return type
+ * @param probe_i Pointer to the probe data.
  * @return Pointer to the created us_ip struct
  */
-struct us_ip *create_ip(unsigned long offset, const char *args, char ret_type)
+struct us_ip *create_ip(unsigned long offset, const struct probe_info *probe_i)
 {
-       size_t len = strlen(args) + 1;
-       struct us_ip *ip = kmalloc(sizeof(*ip) + len, GFP_ATOMIC);
+       size_t len = probe_i->size;
+       struct us_ip *ip;
 
+       ip = kmalloc(sizeof(*ip) + len, GFP_ATOMIC);
        if (ip != NULL) {
-               memset(ip, 0, sizeof(*ip));
+               memset(ip, 0, sizeof(*ip) + len);
 
                INIT_LIST_HEAD(&ip->list);
                ip->offset = offset;
-               ip->args = (char *)ip + sizeof(*ip);
-               ip->ret_type = ret_type;
-
-               /* copy args */
-               memcpy(ip->args, args, len);
 
-               /* retprobe */
-               ip->retprobe.handler = ret_handler;
-               ip->retprobe.entry_handler = entry_handler;
+               probe_info_copy(probe_i, &ip->probe_i);
+               probe_info_init(&ip->probe_i, ip);
        } else {
                printk("Cannot kmalloc in create_ip function!\n");
        }
@@ -102,5 +64,6 @@ struct us_ip *create_ip(unsigned long offset, const char *args, char ret_type)
  */
 void free_ip(struct us_ip *ip)
 {
+       probe_info_uninit(&ip->probe_i, ip);
        kfree(ip);
 }
index 6ceb3d1..30cee3c 100644 (file)
@@ -26,6 +26,7 @@
 
 #include <linux/list.h>
 #include <uprobe/swap_uprobes.h>
+#include <us_manager/probes/probes.h>
 
 struct sspt_page;
 
@@ -34,19 +35,21 @@ struct sspt_page;
  * @breaf Image of instrumentation pointer for specified process
  */
 struct us_ip {
-       struct list_head list;          /**< For sspt_page */
-       struct sspt_page *page;         /**< Pointer on the page (parent) */
+       struct list_head list;      /**< For sspt_page */
+       struct sspt_page *page;     /**< Pointer on the page (parent) */
+       struct probe_info probe_i;  /**< Probe's data */
 
-       struct uretprobe retprobe;      /**< uretprobe */
-       char *args;                     /**< Function arguments */
-       char ret_type;                  /**< Return type */
-       unsigned long orig_addr;        /**< Function address */
+       unsigned long orig_addr;    /**< Function address */
+       unsigned long offset;       /**< Page offset */
 
-       unsigned long offset;           /**< Page offset */
+       union {
+               struct uretprobe retprobe;
+               struct uprobe uprobe;
+       };
 };
 
 
-struct us_ip *create_ip(unsigned long offset, const char *args, char ret_type);
+struct us_ip *create_ip(unsigned long offset, const struct probe_info *probe_i);
 void free_ip(struct us_ip *ip);
 
 #endif /* __IP__ */
index 5cff091..fc10af0 100644 (file)
@@ -35,6 +35,7 @@
 
 #include <us_manager/us_manager.h>
 #include <us_manager/pf/pf_group.h>
+#include <us_manager/probes/use_probes.h>
 
 
 static inline int check_vma(struct vm_area_struct *vma)
@@ -48,16 +49,23 @@ static inline int check_vma(struct vm_area_struct *vma)
 static inline int sspt_register_usprobe(struct us_ip *ip)
 {
        int ret;
+       struct uprobe *up = NULL;
 
-       /* for retuprobe */
-       ip->retprobe.up.task = ip->page->file->proc->task;
-       ip->retprobe.up.sm = ip->page->file->proc->sm;
+       up = probe_info_get_uprobe(&ip->probe_i, ip);
 
-       ret = swap_register_uretprobe(&ip->retprobe);
+       if (!up) {
+               printk("SWAP US_MANAGER: failed getting uprobe!\n");
+               return -EINVAL;
+       }
+
+       up->task = ip->page->file->proc->task;
+       up->sm = ip->page->file->proc->sm;
+
+       ret = probe_info_register(&ip->probe_i, ip);
        if (ret) {
                struct sspt_file *file = ip->page->file;
                char *name = file->dentry->d_iname;
-               unsigned long addr = (unsigned long)ip->retprobe.up.kp.addr;
+               unsigned long addr = (unsigned long)up->kp.addr;
                unsigned long offset = addr - file->vm_start;
 
                printk("swap_register_uretprobe() failure %d (%s:%lx|%lx)\n",
@@ -67,32 +75,26 @@ static inline int sspt_register_usprobe(struct us_ip *ip)
        return ret;
 }
 
-static inline int do_unregister_usprobe(struct us_ip *ip, int disarm)
-{
-       __swap_unregister_uretprobe(&ip->retprobe, disarm);
-
-       return 0;
-}
-
 static inline int sspt_unregister_usprobe(struct task_struct *task, struct us_ip *ip, enum US_FLAGS flag)
 {
-       int err = 0;
+       struct uprobe *up = NULL;
 
        switch (flag) {
        case US_UNREGS_PROBE:
-               err = do_unregister_usprobe(ip, 1);
+               probe_info_unregister(&ip->probe_i, ip, 1);
                break;
        case US_DISARM:
-               disarm_uprobe(&ip->retprobe.up.kp, task);
+               up = probe_info_get_uprobe(&ip->probe_i, ip);
+               disarm_uprobe(&up->kp, task);
                break;
        case US_UNINSTALL:
-               err = do_unregister_usprobe(ip, 0);
+               probe_info_unregister(&ip->probe_i, ip, 0);
                break;
        default:
                panic("incorrect value flag=%d", flag);
        }
 
-       return err;
+       return 0;
 }
 
 #endif /* __SSPT__ */
index 26f69ce..9081325 100644 (file)
@@ -26,6 +26,7 @@
  */
 
 #include <kprobe/swap_kprobes_deps.h>
+#include <us_manager/probes/probes.h>
 
 static inline void print_jprobe(struct jprobe *jp)
 {
@@ -41,10 +42,14 @@ static inline void print_retprobe(struct uretprobe *rp)
 
 static inline void print_ip(struct us_ip *ip, int i)
 {
-       printk("###       addr[%2d]=%lx, R_addr=%lx\n",
-                               i, (unsigned long)ip->offset,
-                               (unsigned long)ip->retprobe.up.kp.addr);
-       print_retprobe(&ip->retprobe);
+       if (ip->probe_i.probe_type == SWAP_RETPROBE) {
+               struct uretprobe *rp = &ip->retprobe;
+
+               printk("###       addr[%2d]=%lx, R_addr=%lx\n",
+                                       i, (unsigned long)ip->offset,
+                                       (unsigned long)rp->up.kp.addr);
+               print_retprobe(rp);
+       }
 }
 
 static inline void print_page_probes(const struct sspt_page *page)
index c487550..91b0cdf 100644 (file)
@@ -167,12 +167,12 @@ struct sspt_page *sspt_find_page_mapped(struct sspt_file *file, unsigned long pa
  * @return Void
  */
 void sspt_file_add_ip(struct sspt_file *file, unsigned long offset,
-                     const char *args, char ret_type)
+                     struct probe_info *probe_i)
 {
        struct sspt_page *page = sspt_find_page_or_new(file, offset & PAGE_MASK);
 
        // FIXME: delete ip
-       struct us_ip *ip = create_ip(offset, args, ret_type);
+       struct us_ip *ip = create_ip(offset, probe_i);
 
        sspt_add_ip(page, ip);
 }
index ce55c38..e2af552 100644 (file)
@@ -53,7 +53,7 @@ void sspt_file_free(struct sspt_file *file);
 struct sspt_page *sspt_find_page_mapped(struct sspt_file *file,
                                        unsigned long page);
 void sspt_file_add_ip(struct sspt_file *file, unsigned long offset,
-                     const char *args, char ret_type);
+                     struct probe_info *probe_i);
 
 struct sspt_page *sspt_get_page(struct sspt_file *file, unsigned long offset_addr);
 void sspt_put_page(struct sspt_page *page);
index 0c70f26..31369cf 100644 (file)
@@ -26,6 +26,7 @@
 #include "sspt_page.h"
 #include "sspt_file.h"
 #include "ip.h"
+#include <us_manager/probes/use_probes.h>
 #include <linux/slab.h>
 #include <linux/list.h>
 
@@ -141,6 +142,7 @@ int sspt_register_page(struct sspt_page *page, struct sspt_file *file)
        int err = 0;
        struct us_ip *ip, *n;
        struct list_head ip_list_tmp;
+       struct uprobe *up;
        unsigned long addr;
 
        spin_lock(&page->lock);
@@ -161,7 +163,8 @@ int sspt_register_page(struct sspt_page *page, struct sspt_file *file)
                addr = file->vm_start + page->offset + ip->offset;
 
                ip->orig_addr = addr;
-               ip->retprobe.up.kp.addr = (kprobe_opcode_t *)addr;
+               up = probe_info_get_uprobe(&ip->probe_i, ip);
+               up->kp.addr = (kprobe_opcode_t *)addr;
 
                err = sspt_register_usprobe(ip);
                if (err) {