summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Aksenov <a.aksenov@samsung.com>2014-09-09 11:59:57 +0400
committerAlexander Aksenov <a.aksenov@samsung.com>2014-11-12 15:30:50 +0300
commitf71aa99c316e5aebdee03adc74e6b87b14bfd502 (patch)
tree525f441047d6aa54695f5f045da90588447e28cb
parent10433d40881fb6e6c3129b2a1d731c0492eb11f9 (diff)
downloadswap-modules-f71aa99c316e5aebdee03adc74e6b87b14bfd502.tar.gz
swap-modules-f71aa99c316e5aebdee03adc74e6b87b14bfd502.tar.bz2
swap-modules-f71aa99c316e5aebdee03adc74e6b87b14bfd502.zip
[FEATURE] New probes interface
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>
-rw-r--r--Kbuild3
-rwxr-xr-xbuild.sh5
-rw-r--r--parser/us_inst.c14
-rw-r--r--retprobe/Kbuild4
-rw-r--r--retprobe/retprobe.c143
-rw-r--r--retprobe/retprobe.h34
-rw-r--r--us_manager/Kbuild3
-rw-r--r--us_manager/img/img_file.c8
-rw-r--r--us_manager/img/img_file.h4
-rw-r--r--us_manager/img/img_ip.c21
-rw-r--r--us_manager/img/img_ip.h7
-rw-r--r--us_manager/img/img_proc.c9
-rw-r--r--us_manager/img/img_proc.h3
-rw-r--r--us_manager/pf/pf_group.c10
-rw-r--r--us_manager/pf/pf_group.h3
-rw-r--r--us_manager/probes/probes.c229
-rw-r--r--us_manager/probes/probes.h53
-rw-r--r--us_manager/probes/register_probes.h21
-rw-r--r--us_manager/probes/use_probes.h16
-rw-r--r--us_manager/sspt/ip.c57
-rw-r--r--us_manager/sspt/ip.h19
-rw-r--r--us_manager/sspt/sspt.h36
-rw-r--r--us_manager/sspt/sspt_debug.h13
-rw-r--r--us_manager/sspt/sspt_file.c4
-rw-r--r--us_manager/sspt/sspt_file.h2
-rw-r--r--us_manager/sspt/sspt_page.c5
26 files changed, 606 insertions, 120 deletions
diff --git a/Kbuild b/Kbuild
index e334a390..40b8f272 100644
--- a/Kbuild
+++ b/Kbuild
@@ -11,4 +11,5 @@ obj-m := buffer/ \
ks_features/ \
sampler/ \
energy/ \
- parser/
+ parser/ \
+ retprobe/
diff --git a/build.sh b/build.sh
index b13e5dd7..e8244007 100755
--- 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
diff --git a/parser/us_inst.c b/parser/us_inst.c
index 4baf1a66..b36edbab 100644
--- a/parser/us_inst.c
+++ b/parser/us_inst.c
@@ -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
index 00000000..0c9fefbd
--- /dev/null
+++ b/retprobe/Kbuild
@@ -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
index 00000000..96ba8c46
--- /dev/null
+++ b/retprobe/retprobe.c
@@ -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
index 00000000..7a82781d
--- /dev/null
+++ b/retprobe/retprobe.h
@@ -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__ */
diff --git a/us_manager/Kbuild b/us_manager/Kbuild
index 5e2cc16c..c6db3e99 100644
--- a/us_manager/Kbuild
+++ b/us_manager/Kbuild
@@ -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
diff --git a/us_manager/img/img_file.c b/us_manager/img/img_file.c
index 6a2d4052..d87a2c08 100644
--- a/us_manager/img/img_file.c
+++ b/us_manager/img/img_file.c
@@ -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;
diff --git a/us_manager/img/img_file.h b/us_manager/img/img_file.h
index 312313da..5e7977b7 100644
--- a/us_manager/img/img_file.h
+++ b/us_manager/img/img_file.h
@@ -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);
diff --git a/us_manager/img/img_ip.c b/us_manager/img/img_ip.c
index 102d9f08..7b6395a2 100644
--- a/us_manager/img/img_ip.c
+++ b/us_manager/img/img_ip.c
@@ -24,32 +24,25 @@
#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 */
diff --git a/us_manager/img/img_ip.h b/us_manager/img/img_ip.h
index a6992f75..cd147225 100644
--- a/us_manager/img/img_ip.h
+++ b/us_manager/img/img_ip.h
@@ -27,6 +27,7 @@
#define _IMG_IP_H
#include <linux/types.h>
+#include <us_manager/probes/probes.h>
/**
* @struct img_ip
@@ -35,12 +36,10 @@
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 */
diff --git a/us_manager/img/img_proc.c b/us_manager/img/img_proc.c
index ce7749ae..71b20d35 100644
--- a/us_manager/img/img_proc.c
+++ b/us_manager/img/img_proc.c
@@ -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);
diff --git a/us_manager/img/img_proc.h b/us_manager/img/img_proc.h
index a1b71d58..745df840 100644
--- a/us_manager/img/img_proc.h
+++ b/us_manager/img/img_proc.h
@@ -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 */
diff --git a/us_manager/pf/pf_group.c b/us_manager/pf/pf_group.c
index e5667b00..920c8fcf 100644
--- a/us_manager/pf/pf_group.c
+++ b/us_manager/pf/pf_group.c
@@ -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);
diff --git a/us_manager/pf/pf_group.h b/us_manager/pf/pf_group.h
index 20657683..f69bd0b9 100644
--- a/us_manager/pf/pf_group.h
+++ b/us_manager/pf/pf_group.h
@@ -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
index 00000000..52b024f7
--- /dev/null
+++ b/us_manager/probes/probes.c
@@ -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
index 00000000..4ba81112
--- /dev/null
+++ b/us_manager/probes/probes.h
@@ -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
index 00000000..fb6a244c
--- /dev/null
+++ b/us_manager/probes/register_probes.h
@@ -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
index 00000000..80cfb3a3
--- /dev/null
+++ b/us_manager/probes/use_probes.h
@@ -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__ */
diff --git a/us_manager/sspt/ip.c b/us_manager/sspt/ip.c
index a54353ea..0a46b33c 100644
--- a/us_manager/sspt/ip.c
+++ b/us_manager/sspt/ip.c
@@ -26,67 +26,29 @@
#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);
}
diff --git a/us_manager/sspt/ip.h b/us_manager/sspt/ip.h
index 6ceb3d1c..30cee3cc 100644
--- a/us_manager/sspt/ip.h
+++ b/us_manager/sspt/ip.h
@@ -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__ */
diff --git a/us_manager/sspt/sspt.h b/us_manager/sspt/sspt.h
index 5cff0915..fc10af0a 100644
--- a/us_manager/sspt/sspt.h
+++ b/us_manager/sspt/sspt.h
@@ -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__ */
diff --git a/us_manager/sspt/sspt_debug.h b/us_manager/sspt/sspt_debug.h
index 26f69cef..9081325a 100644
--- a/us_manager/sspt/sspt_debug.h
+++ b/us_manager/sspt/sspt_debug.h
@@ -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)
diff --git a/us_manager/sspt/sspt_file.c b/us_manager/sspt/sspt_file.c
index c4875503..91b0cdf1 100644
--- a/us_manager/sspt/sspt_file.c
+++ b/us_manager/sspt/sspt_file.c
@@ -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);
}
diff --git a/us_manager/sspt/sspt_file.h b/us_manager/sspt/sspt_file.h
index ce55c38a..e2af5523 100644
--- a/us_manager/sspt/sspt_file.h
+++ b/us_manager/sspt/sspt_file.h
@@ -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);
diff --git a/us_manager/sspt/sspt_page.c b/us_manager/sspt/sspt_page.c
index 0c70f26d..31369cf3 100644
--- a/us_manager/sspt/sspt_page.c
+++ b/us_manager/sspt/sspt_page.c
@@ -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) {