[FEATURE] FBI porting 60/38860/10
authorVitaliy Cherepanov <v.cherepanov@samsung.com>
Mon, 17 Nov 2014 13:37:09 +0000 (16:37 +0300)
committerVitaliy Cherepanov <v.cherepanov@samsung.com>
Fri, 15 May 2015 09:32:02 +0000 (12:32 +0300)
Change-Id: Ia0453593cf0d32c32a7b536ffaedf184b0445f32
Signed-off-by: Vitaliy Cherepanov <v.cherepanov@samsung.com>
14 files changed:
Kbuild
build.sh
fbiprobe/Kbuild [new file with mode: 0644]
fbiprobe/fbi_msg.c [new file with mode: 0644]
fbiprobe/fbi_msg.h [new file with mode: 0644]
fbiprobe/fbi_probe_module.h [new file with mode: 0644]
fbiprobe/fbiprobe.c [new file with mode: 0644]
fbiprobe/fbiprobe.h [new file with mode: 0644]
fbiprobe/regs.h [new file with mode: 0644]
packaging/swap-modules.spec
parser/msg_parser.c
us_manager/probes/probes.h
writer/swap_msg.h
writer/swap_writer_module.c

diff --git a/Kbuild b/Kbuild
index e632be9..cbf9dac 100644 (file)
--- a/Kbuild
+++ b/Kbuild
@@ -16,4 +16,5 @@ obj-m := master/ \
          retprobe/ \
          webprobe/ \
          task_data/ \
-         preload/
+         preload/ \
+         fbiprobe/
index d4194b2..94a50ed 100755 (executable)
--- a/build.sh
+++ b/build.sh
@@ -38,6 +38,7 @@ retprobe_dir=${modules_dir}/retprobe
 webprobe_dir=${modules_dir}/webprobe
 task_data_dir=${modules_dir}/task_data
 preload_dir=${modules_dir}/preload
+fbiprobe_dir=${modules_dir}/fbiprobe
 
 buffer_module_name=swap_buffer.ko
 driver_module_name=swap_driver.ko
@@ -55,6 +56,7 @@ retprobe_module_name=swap_retprobe.ko
 webprobe_module_name=swap_webprobe.ko
 task_data_module_name=swap_task_data.ko
 preload_module_name=swap_preload.ko
+fbiprobe_module_name=swap_fbiprobe.ko
 
 install_dir="/opt/swap/sdk"
 
@@ -81,7 +83,8 @@ ${ksyms_dir}/${ksyms_module_name} \
 ${retprobe_dir}/${retprobe_module_name} \
 ${webprobe_dir}/${webprobe_module_name} \
 ${task_data_dir}/${task_data_module_name} \
-${preload_dir}/${preload_module_name}"
+${preload_dir}/${preload_module_name} \
+${fbiprobe_dir}/${fbiprobe_module_name}"
 
 for m in ${modules} ; do
        ${cross_compile}strip -x -g $m
diff --git a/fbiprobe/Kbuild b/fbiprobe/Kbuild
new file mode 100644 (file)
index 0000000..94a0906
--- /dev/null
@@ -0,0 +1,4 @@
+EXTRA_CFLAGS := $(extra_cflags)
+
+obj-m := swap_fbiprobe.o
+swap_fbiprobe-y := fbiprobe.o
diff --git a/fbiprobe/fbi_msg.c b/fbiprobe/fbi_msg.c
new file mode 100644 (file)
index 0000000..3c3a236
--- /dev/null
@@ -0,0 +1,76 @@
+/**
+ * fbiprobe/fbi_msg.c
+ * @author Vitaliy Cherepanov <v.cherepanov@samsung.com>
+ *
+ * @section LICENSE
+ *
+ * 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.
+ *
+ * @section COPYRIGHT
+ *
+ * Copyright (C) Samsung Electronics, 2015
+ *
+ * @section DESCRIPTION
+ *
+ * Packing and writing data.
+ */
+
+
+#include <linux/types.h>
+
+#include <writer/swap_msg.h>
+
+struct msg_fbi {
+       u32 var_id;
+       u32 size;
+       char var_data[0];
+} __packed;
+
+
+static char *pack_fbi_info(char *payload, unsigned long var_id, size_t size,
+                          char *msg_buf)
+{
+       struct msg_fbi *fbi_m = (struct msg_fbi *)payload;
+
+       fbi_m->var_id = var_id;
+       fbi_m->size = size;
+       if (size != 0) {
+               /* FIXME Possible out of buffer! */
+               memcpy(&fbi_m->var_data, msg_buf, size);
+       }
+
+       /*
+        * If size is 0 that mean we cannot get data for this probe.
+        * But we pack it like error code
+        */
+
+       return payload + sizeof(struct msg_fbi) + size;
+}
+
+void fbi_msg(unsigned long var_id, size_t size, char *msg_buf)
+{
+       struct swap_msg *m;
+       void *p;
+       void *buf_end;
+
+       m = swap_msg_get(MSG_FBI);
+       p = swap_msg_payload(m);
+
+       buf_end = pack_fbi_info(p, var_id, size, msg_buf);
+
+       swap_msg_flush(m, buf_end - p);
+
+       swap_msg_put(m);
+}
diff --git a/fbiprobe/fbi_msg.h b/fbiprobe/fbi_msg.h
new file mode 100644 (file)
index 0000000..69fd209
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * @file fbiprobe/fbi_msg.h
+ *
+ * @author Vitaliy Cherepanov <v.cherepanov@samsung.com>
+ *
+ * @section LICENSE
+ *
+ * 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.
+ *
+ * @section COPYRIGHT
+ *
+ * Copyright (C) Samsung Electronics, 2014
+ *
+ * @section DESCRIPTION
+ *
+ * Function body instrumetation
+ *
+ */
+
+#ifndef __FBI_MSG_H__
+#define __FBI_MSG_H__
+
+#include <linux/types.h>
+
+void fbi_msg(unsigned long var_id, size_t size, char *msg_buf);
+
+#endif /* __FBI_MSG_H__ */
diff --git a/fbiprobe/fbi_probe_module.h b/fbiprobe/fbi_probe_module.h
new file mode 100644 (file)
index 0000000..cac6f4a
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ * @file fbiprobe/fbi_probe.h
+ *
+ * @author Alexander Aksenov <a.aksenov@samsung.com>
+ * @author Vitaliy Cherepanov <v.cherepanov@samsung.com>
+ *
+ * @section LICENSE
+ *
+ * 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.
+ *
+ * @section COPYRIGHT
+ *
+ * Copyright (C) Samsung Electronics, 2014
+ *
+ * 2014 Alexander Aksenov : FBI implement
+ * 2014 Vitaliy Cherepanov: FBI implement, portage
+ *
+ * @section DESCRIPTION
+ *
+ * Function body instrumentation.
+ *
+ */
+
+#ifndef __FBI_PROBE_MODULE_H__
+#define __FBI_PROBE_MODULE_H__
+
+#include <linux/kernel.h>
+
+/* MESSAGES */
+
+#define MODULE_NAME "SWAP_FBI_PROBE"
+
+/* FBI_DEBUG_ON:
+ * val | DEBUG | MSG | WARN | ERR | CRITICAL|
+ * ----+-------+-----+------+-----+---------|
+ * 0   | OFF   | OFF | OFF  | OFF | OFF     |
+ * 1   | OFF   | OFF | OFF  | OFF | ON      |
+ * 2   | OFF   | OFF | OFF  | ON  | ON      |
+ * 3   | OFF   | OFF | ON   | ON  | ON      |
+ * 4   | OFF   | ON  | ON   | ON  | ON      |
+ * 5   | ON    | ON  | ON   | ON  | ON      |
+ */
+
+#define FBI_DEBUG_LEVEL 3
+
+/** Prints debug message.*/
+#if (FBI_DEBUG_LEVEL >= 5)
+#define print_debug(msg, args...) \
+       printk(KERN_DEBUG MODULE_NAME " DEBUG : " msg, ##args)
+#else
+#define print_debug(msg, args...)
+#endif
+
+/** Prints info message.*/
+#if (FBI_DEBUG_LEVEL >= 4)
+#define print_msg(msg, args...)   \
+       printk(KERN_INFO MODULE_NAME " : " msg, ##args)
+#else
+#define print_msg(msg, args...)
+#endif
+
+/** Prints warning message.*/
+#if (FBI_DEBUG_LEVEL >= 3)
+#define print_warn(msg, args...)  \
+       printk(KERN_WARNING MODULE_NAME " WARNING : " msg, ##args)
+#else
+#define print_warn(msg, args...)
+#endif
+
+/** Prints error message.*/
+#if (FBI_DEBUG_LEVEL >= 2)
+#define print_err(msg, args...)   \
+       printk(KERN_ERR MODULE_NAME " ERROR : " msg, ##args)
+#else
+#define print_err(msg, args...)
+#endif
+
+/** Prints critical error message.*/
+#if (FBI_DEBUG_LEVEL >= 1)
+#define print_crit(msg, args...)  \
+       printk(KERN_CRIT MODULE_NAME " CRITICAL : " msg, ##args)
+#else
+#define print_crit(msg, args...)
+#endif
+
+#endif /* __FBI_PROBE_MODULE_H__ */
diff --git a/fbiprobe/fbiprobe.c b/fbiprobe/fbiprobe.c
new file mode 100644 (file)
index 0000000..d37e4c0
--- /dev/null
@@ -0,0 +1,352 @@
+/*
+ * @file fbiprobe/fbi_probe.c
+ *
+ * @author Alexander Aksenov <a.aksenov@samsung.com>
+ * @author Vitaliy Cherepanov <v.cherepanov@samsung.com>
+ *
+ * @section LICENSE
+ *
+ * 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.
+ *
+ * @section COPYRIGHT
+ *
+ * Copyright (C) Samsung Electronics, 2014
+ *
+ * 2014 Alexander Aksenov : FBI implement
+ * 2014 Vitaliy Cherepanov: FBI implement, portage
+ *
+ * @section DESCRIPTION
+ *
+ * Function body instrumetation
+ *
+ */
+
+#include "fbiprobe.h"
+#include "fbi_probe_module.h"
+#include "fbi_msg.h"
+#include "regs.h"
+
+#include <us_manager/us_manager.h>
+#include <us_manager/probes/probes.h>
+#include <us_manager/probes/register_probes.h>
+
+#include <uprobe/swap_uprobes.h>
+#include <us_manager/sspt/ip.h>
+
+#include <kprobe/swap_kprobes_deps.h>
+#include <linux/module.h>
+
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/dcache.h>
+#include <linux/mm_types.h>
+
+#include <us_manager/sspt/sspt_page.h>
+#include <us_manager/sspt/sspt_file.h>
+
+#define DIRECT_ADDR (0xFF)
+#define MAX_STRING_LEN (512)
+
+/* you shoud free allocated data buffer */
+static char *fbi_probe_alloc_and_read_from_addr(const struct fbi_info *fbi_i,
+                                               unsigned long addr,
+                                               uint32_t *size)
+{
+       uint8_t i, j;
+       char *buf = NULL;
+       struct fbi_step *step;
+
+       *size = 0;
+
+       /* get final variable address */
+       step = fbi_i->steps;
+       for (i = 0; i != fbi_i->steps_count; i++) {
+               /* dereference */
+               for (j = 0; j != step->ptr_order; j++) {
+                       unsigned long new_addr;
+                       /* equel to: addr = *addr */
+                       if (!read_proc_vm_atomic(current, addr, &new_addr, sizeof(new_addr))) {
+                               print_warn("Wrong read! (0x%lx) step #%d ptr_order #%d\n",
+                                          addr, i + 1, j + 1);
+                               goto fail_exit;
+                       }
+                       addr = new_addr;
+               }
+
+               /* offset */
+               addr += step->data_offset;
+               step++;
+       }
+
+       /* calculate data size */
+       if (fbi_i->data_size == 0) {
+               /*
+                * that mean variable is string and
+                * we need to calculate string length
+                */
+
+               *size = strnlen_user((const char __user *)addr, MAX_STRING_LEN);
+               if (*size == 0) {
+                       print_warn("Cannot get string from 0x%lx\n", addr);
+                       goto fail_exit;
+               }
+       } else {
+               /* else use size from fbi struct */
+               *size = fbi_i->data_size;
+       }
+
+       buf = kmalloc(*size, GFP_KERNEL);
+       if (buf == NULL) {
+               print_warn("Not enough memory\n");
+               goto size_0;
+       }
+
+       if (!read_proc_vm_atomic(current, addr, buf, *size)) {
+               print_warn("Error reading data at 0x%lx, task %d\n",
+                          addr, current->pid);
+               goto free_buf;
+       }
+
+       if (fbi_i->data_size == 0) {
+               /*
+                * that mean variable is string and
+                * we need to add terminate '\0'
+                */
+               buf[*size - 1] = '\0';
+       }
+
+       return buf;
+
+free_buf:
+       kfree(buf);
+       buf = NULL;
+size_0:
+       *size = 0;
+fail_exit:
+       return NULL;
+
+}
+
+static int fbi_probe_get_data_from_reg(const struct fbi_info *fbi_i,
+                                      struct pt_regs *regs)
+{
+       unsigned long *reg_ptr;
+
+       reg_ptr = get_ptr_by_num(regs, fbi_i->reg_n);
+       if (reg_ptr == NULL) {
+               print_err("fbi_probe_get_data_from_reg: Wrong register number!\n");
+               return 0;
+       }
+
+       fbi_msg(fbi_i->var_id, fbi_i->data_size, (char *)reg_ptr);
+
+       return 0;
+}
+
+static int fbi_probe_get_data_from_ptrs(const struct fbi_info *fbi_i,
+                                       struct pt_regs *regs)
+{
+       unsigned long *reg_ptr;
+       unsigned long addr;
+       uint32_t size = 0;
+       void *buf;
+
+       reg_ptr = get_ptr_by_num(regs, fbi_i->reg_n);
+       if (reg_ptr == NULL) {
+               print_err("fbi_probe_get_data_from_ptrs: Wrong register number!\n");
+               return 0;
+       }
+
+       addr = *reg_ptr + fbi_i->reg_offset;
+
+       buf = fbi_probe_alloc_and_read_from_addr(fbi_i, addr, &size);
+       if (buf != NULL) {
+               fbi_msg(fbi_i->var_id, size, buf);
+               kfree(buf);
+       }
+
+       return 0;
+}
+
+static struct vm_area_struct *find_vma_exe_by_dentry(struct mm_struct *mm,
+                                                    struct dentry *dentry)
+{
+       struct vm_area_struct *vma;
+
+       /* FIXME: down_write(&mm->mmap_sem); up_write(&mm->mmap_sem); */
+       /* TODO FILTER vma */
+       for (vma = mm->mmap; vma; vma = vma->vm_next) {
+               if (vma->vm_file &&
+                  (vma->vm_file->f_dentry == dentry))
+                       /* found */
+                       goto exit;
+       }
+
+       /* not found */
+       vma = NULL;
+exit:
+       return vma;
+}
+
+static int fbi_probe_get_data_from_direct_addr(const struct fbi_info *fbi_i,
+                                              struct us_ip *ip,
+                                              struct pt_regs *regs)
+{
+       struct vm_area_struct *vma;
+       unsigned long addr;
+       uint32_t size = 0;
+       char *buf;
+
+       /* register offset is global address */
+       vma = find_vma_exe_by_dentry(current->mm, ip->page->file->dentry);
+       if (vma == NULL) {
+               print_warn("cannot locate dentry\n");
+               goto exit;
+       }
+
+       addr = vma->vm_start + fbi_i->reg_offset;
+
+       print_debug("DIRECT_ADDR reg_offset = %llx\n", fbi_i->reg_offset);
+       print_debug("DIRECT_ADDR vm_start   = %lx\n", vma->vm_start);
+       print_debug("DIRECT_ADDR res_addr   = %lx\n", addr);
+
+       buf = fbi_probe_alloc_and_read_from_addr(fbi_i, addr, &size);
+       if (buf != NULL) {
+               fbi_msg(fbi_i->var_id, size, buf);
+               kfree(buf);
+       } else {
+               print_warn("get data by direct addr failed (0x%lx :0x%llx)\n",
+                          addr, fbi_i->reg_offset);
+       }
+exit:
+       return 0;
+}
+
+static int fbi_probe_handler(struct kprobe *p, struct pt_regs *regs)
+{
+       struct uprobe *up = container_of(p, struct uprobe, kp);
+       struct us_ip *ip = container_of(up, struct us_ip, uprobe);
+       struct fbi_info *fbi_i = &ip->probe_i.fbi_i;
+
+       if (ip->probe_i.probe_type != SWAP_FBIPROBE) {
+               /* How this can occure? Doesn't matter, just print and go */
+               print_err("Not FBI probe in FBI handler!\n");
+               return 0;
+       }
+
+       if (fbi_i->reg_n == DIRECT_ADDR)
+               return fbi_probe_get_data_from_direct_addr(fbi_i, ip, regs);
+       else if (fbi_i->steps_count == 0)
+               return fbi_probe_get_data_from_reg(fbi_i, regs);
+       else
+               return fbi_probe_get_data_from_ptrs(fbi_i, regs);
+
+       return 0;
+}
+
+/* FBI probe interfaces */
+void fbi_probe_cleanup(struct probe_info *probe_i)
+{
+       struct fbi_step *steps;
+       steps = probe_i->fbi_i.steps;
+       if (steps != NULL) {
+               kfree(steps);
+               probe_i->fbi_i.steps = NULL;
+               probe_i->fbi_i.steps_count = 0;
+       }
+}
+
+void fbi_probe_init(struct us_ip *ip)
+{
+       ip->uprobe.kp.pre_handler = (kprobe_pre_handler_t)fbi_probe_handler;
+}
+
+void fbi_probe_uninit(struct us_ip *ip)
+{
+       if (ip != NULL)
+               fbi_probe_cleanup(&ip->probe_i);
+}
+
+static int fbi_probe_register_probe(struct us_ip *ip)
+{
+       return swap_register_uprobe(&ip->uprobe);
+}
+
+static void fbi_probe_unregister_probe(struct us_ip *ip, int disarm)
+{
+       __swap_unregister_uprobe(&ip->uprobe, disarm);
+}
+
+static struct uprobe *fbi_probe_get_uprobe(struct us_ip *ip)
+{
+       return &ip->uprobe;
+}
+
+int fbi_probe_copy(struct probe_info *dest, const struct probe_info *source)
+{
+       uint8_t steps_count;
+       size_t steps_size;
+       struct fbi_step *steps_source;
+       struct fbi_step *steps_dest = NULL;
+
+       steps_source = source->fbi_i.steps;
+       steps_count = source->fbi_i.steps_count;
+       steps_size = sizeof(*steps_source) * steps_count;
+
+       memcpy(dest, source, sizeof(*source));
+       if (steps_size != 0 && steps_source != NULL) {
+               steps_dest = kmalloc(steps_size, GFP_KERNEL);
+               if (steps_dest == NULL) {
+                       print_err("can not alloc data\n");
+                       return -ENOMEM;
+               }
+
+               memcpy(steps_dest, steps_source, steps_size);
+       }
+       dest->fbi_i.steps = steps_dest;
+       return 0;
+}
+
+/* Register */
+static struct probe_iface fbi_probe_iface = {
+       .init = fbi_probe_init,
+       .uninit = fbi_probe_uninit,
+       .reg = fbi_probe_register_probe,
+       .unreg = fbi_probe_unregister_probe,
+       .get_uprobe = fbi_probe_get_uprobe,
+       .copy = fbi_probe_copy,
+       .cleanup = fbi_probe_cleanup
+};
+
+static int __init fbiprobe_module_init(void)
+{
+       int ret = 0;
+       ret = swap_register_probe_type(SWAP_FBIPROBE, &fbi_probe_iface);
+       print_debug("Init done. Result=%d\n", ret);
+       return ret;
+}
+
+static void __exit fbiprobe_module_exit(void)
+{
+       swap_unregister_probe_type(SWAP_FBIPROBE);
+}
+
+module_init(fbiprobe_module_init);
+module_exit(fbiprobe_module_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("SWAP fbiprobe");
+MODULE_AUTHOR("Alexander Aksenov <a.aksenov@samsung.com>; Vitaliy Cherepanov <v.cherepanov@samsung.com>");
+
diff --git a/fbiprobe/fbiprobe.h b/fbiprobe/fbiprobe.h
new file mode 100644 (file)
index 0000000..fbd8359
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * @file fbi_probe/fbi_probe.h
+ *
+ * @author Alexander Aksenov <a.aksenov@samsung.com>
+ * @author Vitaliy Cherepanov <v.cherepanov@samsung.com>
+ *
+ * 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.
+ *
+ * @section COPYRIGHT
+ *
+ * Copyright (C) Samsung Electronics, 2014
+ *
+ * 2014 Alexander Aksenov : FBI implement
+ * 2014 Vitaliy Cherepanov: FBI implement, portage
+ *
+ * @section DESCRIPTION
+ *
+ * Function body instrumentation.
+ *
+ */
+
+#ifndef __FBI_PROBE_H__
+#define __FBI_PROBE_H__
+
+#include <linux/types.h>
+
+/* FBI step */
+struct fbi_step {
+       uint8_t ptr_order;         /* Specifies what is located on the address:
+                                   * ptr_order = 0  -  variable
+                                   * ptr_order = 1  -  pointer to variable
+                                   * ptr_order = 2  -  pointer to pointer
+                                   * etc. */
+
+       uint64_t data_offset;
+} __packed;
+
+/* FBI info */
+struct fbi_info {
+       /* Variable position is evaluated by the following rule:
+        * var_position = *(pointer_to_register) - reg_offset
+        * It is expected that the offset is not null only when we're taking
+        * var value from stack.
+        */
+       uint64_t var_id;           /* Variable identifier. Used to specify var */
+       uint64_t reg_offset;       /* Offset relative to the registers value
+                                   * address, specified with reg_n */
+       uint8_t reg_n;             /* Register number. Hope times of cpu
+                                   * with more than 2 million ones are very far from us */
+       uint32_t data_size;        /* Data size to be read */
+
+       uint8_t steps_count;       /* Count of steps to extract variable value */
+       struct fbi_step *steps;    /* extract steps */
+};
+
+#endif /* __FBI_PROBE_H__ */
diff --git a/fbiprobe/regs.h b/fbiprobe/regs.h
new file mode 100644 (file)
index 0000000..d73e950
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * @file fbiprobe/fbi_probe.h
+ *
+ * @author Aleksandr Aksenov <a.aksenov@samsung.com>
+ * @author Vitaliy Cherepanov <v.cherepanov@samsung.com>
+ *
+ * @section LICENSE
+ *
+ * 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.
+ *
+ * @section COPYRIGHT
+ *
+ * Copyright (C) Samsung Electronics, 2014
+ *
+ * 2014 Alexander Aksenov : FBI implement
+ * 2014 Vitaliy Cherepanov: FBI portage
+ *
+ * @section DESCRIPTION
+ *
+ * Function body instrumetation
+ *
+ */
+
+#ifndef __REGS_H__
+#define __REGS_H__
+
+#include <asm/ptrace.h>
+
+#include "fbi_probe_module.h"
+/* This function is used to compare register number and its name on x86 arch.
+ * For ARM it is dumb.
+ * List of registers and their nums on x86:
+ * ax       0
+ * bx       1
+ * cx       2
+ * dx       3
+ * si       4
+ * di       5
+ * bp       6
+ * sp       7
+ */
+
+#if defined(CONFIG_X86)
+
+static inline unsigned long *get_ptr_by_num(struct pt_regs *regs,
+                                           unsigned char reg_num)
+{
+       unsigned long *reg = NULL;
+       if (reg_num < sizeof(struct pt_regs) / sizeof(regs->ax))
+               reg = (unsigned long *)regs;
+
+       return &reg[reg_num];
+}
+
+#elif defined(CONFIG_ARM)
+
+static inline unsigned long *get_ptr_by_num(struct pt_regs *regs,
+                                           unsigned char reg_num)
+{
+       return &regs->uregs[reg_num];
+}
+
+#endif /* CONFIG_arch */
+
+#endif /* __REGS_H__ */
index b3dd375..a7af233 100755 (executable)
@@ -47,6 +47,7 @@ install -m 666 retprobe/swap_retprobe.ko -t %{buildroot}/opt/swap/sdk
 install -m 666 webprobe/swap_webprobe.ko -t %{buildroot}/opt/swap/sdk
 install -m 666 task_data/swap_task_data.ko -t %{buildroot}/opt/swap/sdk
 install -m 666 preload/swap_preload.ko -t %{buildroot}/opt/swap/sdk
+install -m 666 fbiprobe/swap_fbiprobe.ko -t %{buildroot}/opt/swap/sdk
 
 %files
 %defattr(-,root,root)
@@ -67,3 +68,4 @@ install -m 666 preload/swap_preload.ko -t %{buildroot}/opt/swap/sdk
 /opt/swap/sdk/swap_webprobe.ko
 /opt/swap/sdk/swap_task_data.ko
 /opt/swap/sdk/swap_preload.ko
+/opt/swap/sdk/swap_fbiprobe.ko
index 3860447..4f0108f 100644 (file)
@@ -1,7 +1,8 @@
 /**
  * parser/msg_parser.c
+ *
  * @author Vyacheslav Cherkashin
- * @author Vitaliy Cherepanov
+ * @author Vitaliy Cherepanov <v.cherepanov@samsung.com>
  *
  * @sectionLICENSE
  *
@@ -424,6 +425,102 @@ void put_get_call_type_probe(struct probe_info *pi)
 
 
 
+/**
+ * @brief Gets FBI probe data and puts it to the probe_info struct.
+ *
+ * @param mb Pointer to the message buffer.
+ * @param pi Pointer to the probe_info struct.
+ * @return 0 on success, error code on error.
+ */
+int get_fbi_probe(struct msg_buf *mb, struct probe_info *pi)
+{
+       u64 var_id;
+       u64 reg_offset;
+       u8 reg_n;
+       u32 data_size;
+       u8 steps_count, i;
+       struct fbi_step *steps = NULL;
+
+       print_parse_debug("var ID:");
+       if (get_u64(mb, &var_id)) {
+               print_err("failed to read var ID\n");
+               return -EINVAL;
+       }
+
+       print_parse_debug("register offset:");
+       if (get_u64(mb, &reg_offset)) {
+               print_err("failed to read register offset\n");
+               return -EINVAL;
+       }
+
+       print_parse_debug("register number:");
+       if (get_u8(mb, &reg_n)) {
+               print_err("failed to read number of the register\n");
+               return -EINVAL;
+       }
+
+       print_parse_debug("data size:");
+       if (get_u32(mb, &data_size)) {
+               print_err("failed to read data size\n");
+               return -EINVAL;
+       }
+
+       print_parse_debug("steps count:");
+       if (get_u8(mb, &steps_count)) {
+               print_err("failed to read steps count\n");
+               return -EINVAL;
+       }
+
+       if (steps_count > 0) {
+               steps = kmalloc(steps_count * sizeof(pi->fbi_i.steps[0]),
+                               GFP_KERNEL);
+               if (steps == NULL)
+                       return -ENOMEM;
+
+               for (i = 0; i != steps_count; i++) {
+                       print_parse_debug("steps #%d ptr_order:", i);
+                       if (get_u8(mb, &(steps[i].ptr_order))) {
+                               print_err("failed to read pointer order(step #%d)\n",
+                                         i);
+                               goto free_steps;
+                       }
+                       print_parse_debug("steps #%d data_offset:", i);
+                       if (get_u64(mb, &(steps[i].data_offset))){
+                               print_err("failed to read offset (steps #%d)\n",
+                                         i);
+                               goto free_steps;
+                       }
+               }
+       }
+
+       pi->probe_type = SWAP_FBIPROBE;
+       pi->fbi_i.reg_n = reg_n;
+       pi->fbi_i.reg_offset = reg_offset;
+       pi->fbi_i.data_size = data_size;
+       pi->fbi_i.var_id = var_id;
+       pi->fbi_i.steps_count = steps_count;
+       pi->fbi_i.steps = steps;
+       pi->size = 0;
+
+       return 0;
+
+free_steps:
+       kfree(steps);
+       return -EINVAL;
+}
+
+/**
+ * @brief FBI probe data cleanup.
+ *
+ * @param pi Pointer to the probe_info comprising FBI probe.
+ * @return Void.
+ */
+void put_fbi_probe(struct probe_info *pi)
+{
+       return;
+}
+
+
 /* ============================================================================
  * ==                               FUNC_INST                                ==
  * ============================================================================
@@ -483,6 +580,10 @@ struct func_inst_data *create_func_inst_data(struct msg_buf *mb)
                if (get_get_call_type_probe(mb, &(fi->probe_i)) != 0)
                        goto free_func_inst;
                break;
+       case SWAP_FBIPROBE:
+               if (get_fbi_probe(mb, &(fi->probe_i)) != 0)
+                       goto free_func_inst;
+               break;
        default:
                printk(KERN_WARNING "SWAP PARSER: Wrong probe type %d!\n",
                       type);
@@ -520,6 +621,9 @@ void destroy_func_inst_data(struct func_inst_data *fi)
        case SWAP_GET_CALL_TYPE:
                put_get_call_type_probe(&(fi->probe_i));
                break;
+       case SWAP_FBIPROBE:
+               put_fbi_probe(&(fi->probe_i));
+               break;
        default:
                printk(KERN_WARNING "SWAP PARSER: Wrong probe type %d!\n",
                   fi->probe_i.probe_type);
index 13c3c4f..988bfe8 100644 (file)
@@ -2,6 +2,11 @@
  *  SWAP uprobe manager
  *  modules/us_manager/probes/probes.h
  *
+ * @author Alexander Aksenov <a.aksenov@samsung.com>
+ * @author Vitaliy Cherepanov <v.cherepanov@samsung.com>
+ *
+ * @section LICENSE
+ *
  * 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
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  *
+ * @section COPYRIGHT
+ *
  * Copyright (C) Samsung Electronics, 2014
  *
- * 2014         Alexander Aksenov: Probes interface implement
+ * 2014 Alexander Aksenov : Probes interface implement
+ * 2014 Vitaliy Cherepanov: Portage
  *
  */
 
@@ -30,6 +38,7 @@
 
 #include <preload/preload_probe.h>   /* TODO Remove */
 #include <retprobe/retprobe.h>       /* TODO Remove */
+#include <fbiprobe/fbiprobe.h>       /* TODO Remove */
 
 
 
@@ -38,6 +47,7 @@
  */
 enum probe_t {
        SWAP_RETPROBE = 0,          /* Retprobe */
+       SWAP_FBIPROBE = 1,          /* FBI probe */
        SWAP_PRELOAD_PROBE = 2,     /* Preload probe */
        SWAP_WEBPROBE = 3,          /* Webprobe */
        SWAP_GET_CALLER = 4,        /* Get caller probe. Supports preload */
@@ -52,6 +62,7 @@ struct probe_info {
        /* Union of all SWAP supported probe types */
        union {
                struct retprobe_info rp_i;
+               struct fbi_info fbi_i;
                struct preload_info pl_i;
                struct get_caller_info gc_i;
                struct get_call_type_info gct_i;
index c3c3488..288caec 100644 (file)
@@ -45,7 +45,8 @@ enum swap_msg_id {
        MSG_PROC_UNMAP                  = 0x0013,
        MSG_PROC_COMM                   = 0x0014,
        MSG_WEB_FUNCTION_ENTRY          = 0x0015,
-       MSG_WEB_FUNCTION_EXIT           = 0x0016
+       MSG_WEB_FUNCTION_EXIT           = 0x0016,
+       MSG_FBI                         = 0x0020
 };
 
 enum {
index e120b3a..f945a81 100644 (file)
@@ -1,6 +1,7 @@
 /**
  * writer/swap_writer_module.c
  * @author Alexander Aksenov <a.aksenov@samsung.com>
+ * @author Vitaliy Cherepanov <v.cherepanov@samsung.com>
  * @author Vyacheslav Cherkashin
  *
  * @section LICENSE