#include <buffer/swap_buffer_module.h>
#include <buffer/swap_buffer_errors.h>
#include <buffer/buffer_description.h>
-#include <writer/swap_writer_module.h>
#include "driver_defs.h"
#include "swap_driver_errors.h"
obj-m := swap_ks_features.o
swap_ks_features-y := ks_features.o \
ks_map.o \
- file_ops.o
+ file_ops.o \
+ ksf_msg.o
*/
+#include "ksf_msg.h"
#include "syscall_list.h"
-#include <linux/mutex.h>
+
/**
* @struct feature
* Syscalls count.
* @var feature::feature_list
* Pointer to feature's syscall list.
- * @var feature::sub_type
+ * @var feature::type
* Featue subtype.
* @var feature::enable
* Is feature enable.
struct feature {
size_t cnt;
enum syscall_id *feature_list;
- int sub_type;
+ enum probe_t type;
unsigned enable:1;
};
* @def CREATE_FEATURE
* Feature initialization.
*/
-#define CREATE_FEATURE(x, subtype) \
+#define CREATE_FEATURE(x, _type) \
{ \
.cnt = sizeof(x) / sizeof(enum syscall_id), \
.feature_list = x, \
- .sub_type = subtype, \
+ .type = _type, \
.enable = 0 \
}
static struct feature features[] = {
- CREATE_FEATURE(id_none, PST_NONE),
- CREATE_FEATURE(id_file, PST_KS_FILE),
- CREATE_FEATURE(id_ipc, PST_KS_IPC),
- CREATE_FEATURE(id_process, PST_KS_PROCESS),
- CREATE_FEATURE(id_signal, PST_KS_SIGNAL),
- CREATE_FEATURE(id_net, PST_KS_NETWORK),
- CREATE_FEATURE(id_desc, PST_KS_DESC)
+ CREATE_FEATURE(id_none, PT_KS_NONE),
+ CREATE_FEATURE(id_file, PT_KS_FILE),
+ CREATE_FEATURE(id_ipc, PT_KS_IPC),
+ CREATE_FEATURE(id_process, PT_KS_PROCESS),
+ CREATE_FEATURE(id_signal, PT_KS_SIGNAL),
+ CREATE_FEATURE(id_net, PT_KS_NETWORK),
+ CREATE_FEATURE(id_desc, PT_KS_DESC)
};
/**
#include <linux/fs.h>
#include <kprobe/swap_kprobes.h>
#include <writer/event_filter.h>
-#include <writer/swap_writer_module.h>
#include "ks_map.h"
+#include "ksf_msg.h"
#include "file_ops.h"
#define FOPS_PREFIX "[FILE_OPS] "
/* path buffer size */
enum { PATH_LEN = 512 };
-/* event subtypes: the same as for IO probes */
-enum {
- FOPS_OPEN = 0,
- FOPS_CLOSE = 1,
- FOPS_READ_BEGIN = 2,
- FOPS_READ_END = 3,
- FOPS_READ = FOPS_READ_BEGIN,
- FOPS_WRITE_BEGIN = 4,
- FOPS_WRITE_END = 5,
- FOPS_WRITE = FOPS_WRITE_BEGIN,
- FOPS_DIRECTORY = 6,
- FOPS_PERMS = 7,
- FOPS_OTHER = 8,
- FOPS_SEND = 9,
- FOPS_RECV = 10,
- FOPS_OPTION = 11,
- FOPS_MANAGE = 12,
- FOPS_LOCK_START = 14, /* 13 */
- FOPS_LOCK_END = 15,
- FOPS_LOCK_RELEASE = 16
-};
-
struct file_probe {
int id;
const char *args;
if (fops_fcheck(current, file) == 0) {
char *buf = fops_path_buf();
- custom_entry_event(F_ADDR(rp), regs, PT_FILE,
- fprobe->subtype, "Sx",
- fops_fpath(file, buf, PATH_LEN),
- (u64)fd);
+ ksf_msg_file_entry(fd, fprobe->subtype,
+ fops_fpath(file, buf, PATH_LEN));
+
priv->dentry = file->f_dentry;
} else {
priv->dentry = NULL;
struct kretprobe *rp = ri->rp;
struct file_private *priv = (struct file_private *)ri->data;
- if (rp && priv->dentry) {
- struct file_probe *fprobe = to_file_probe(rp);
-
- custom_exit_event(F_ADDR(rp), R_ADDR(ri), regs,
- PT_FILE, fprobe->subtype, "x");
- }
+ if (rp && priv->dentry)
+ ksf_msg_file_exit(regs, 'x');
return 0;
}
if (fops_fcheck(current, file) == 0) {
char *buf = fops_path_buf();
+ const char *path = fops_fpath(file, buf, PATH_LEN);
- custom_entry_event(F_ADDR(rp), regs, PT_FILE,
- fprobe->subtype, "Sxs",
- fops_fpath(file, buf, PATH_LEN),
- (u64)fd, priv->name);
- custom_exit_event(F_ADDR(rp), R_ADDR(ri), regs,
- PT_FILE, fprobe->subtype, "x");
+ ksf_msg_file_entry_open(fd, fprobe->subtype,
+ path, priv->name);
+ ksf_msg_file_exit(regs, 'x');
}
if (file)
filepath = fops_fpath(file, buf, PATH_LEN);
if (lock_arg_init(fprobe->id, regs, &arg) == 0) {
- subtype = (arg.type == F_UNLCK ?
- FOPS_LOCK_RELEASE :
- FOPS_LOCK_START);
-
- custom_entry_event(F_ADDR(rp), regs, PT_FILE,
- subtype, "Sxddxx",
- filepath, (u64)fd,
- arg.type, arg.whence,
- arg.start, arg.len);
+ subtype = arg.type == F_UNLCK ?
+ FOPS_LOCK_RELEASE :
+ FOPS_LOCK_START;
+ ksf_msg_file_entry_lock(fd, subtype, filepath,
+ arg.type, arg.whence,
+ arg.start, arg.len);
} else {
- custom_entry_event(F_ADDR(rp), regs, PT_FILE,
- subtype, "Sx",
- filepath, (u64)fd);
+ ksf_msg_file_entry(fd, subtype, filepath);
}
priv->dentry = file->f_dentry;
struct kretprobe *rp = ri->rp;
struct flock_private *priv = (struct flock_private *)ri->data;
- if (rp && priv->dentry) {
- int subtype;
- if (priv->subtype == FOPS_LOCK_START)
- subtype = FOPS_LOCK_END;
- else
- subtype = priv->subtype;
-
- custom_exit_event(F_ADDR(rp), R_ADDR(ri), regs,
- PT_FILE, subtype, "x");
- }
+ if (rp && priv->dentry)
+ ksf_msg_file_exit(regs, 'x');
return 0;
}
#include <ksyms/ksyms.h>
#include <kprobe/swap_kprobes.h>
#include <master/swap_initializer.h>
-#include <writer/swap_writer_module.h>
#include <writer/event_filter.h>
+#include "ksf_msg.h"
#include "ks_features.h"
#include "syscall_list.h"
#include "features_data.c"
#include "file_ops.h"
+
/**
* @struct ks_probe
* @brief Kernel-space probe. Struct used as a container of syscall probes.
* Installed probes counter.
* @var ks_probe::args
* Pointer to args format string.
- * @var ks_probe::sub_type
+ * @var ks_probe::type
* Probe sub type.
*/
struct ks_probe {
struct kretprobe rp;
int counter;
char *args;
- int sub_type;
+ int type;
};
#define CREATE_RP(name) \
.rp = CREATE_RP(name), \
.counter = 0, \
.args = #args__, \
- .sub_type = PST_NONE \
+ .type = PT_KS_NONE \
}
static struct ks_probe ksp[] = {
if (rp && check_event(current)) {
struct ks_probe *ksp = container_of(rp, struct ks_probe, rp);
const char *fmt = ksp->args;
- unsigned long addr = (unsigned long)ksp->rp.kp.addr;
- int sub_type = ksp->sub_type;
+ const unsigned long addr = (unsigned long)ksp->rp.kp.addr;
+ enum probe_t type = ksp->type;
- entry_event(fmt, addr, regs, PT_KS, sub_type);
+ ksf_msg_entry(regs, addr, type, fmt);
}
return 0;
if (rp && check_event(current)) {
struct ks_probe *ksp = container_of(rp, struct ks_probe, rp);
- unsigned long func_addr = (unsigned long)rp->kp.addr;
- unsigned long ret_addr = (unsigned long)ri->ret_addr;
- int sub_type = ksp->sub_type;
+ const unsigned long func_addr = (unsigned long)rp->kp.addr;
+ const unsigned long ret_addr = (unsigned long)ri->ret_addr;
+ enum probe_t type = ksp->type;
- exit_event('x', regs, PT_KS, sub_type, func_addr, ret_addr);
+ ksf_msg_exit(regs, func_addr, ret_addr, type, 'x');
}
return 0;
struct pt_regs *regs)
{
if (check_event(current))
- switch_entry(regs);
+ ksf_switch_entry(regs);
return 0;
}
struct pt_regs *regs)
{
if (check_event(current))
- switch_exit(regs);
+ ksf_switch_exit(regs);
return 0;
}
static void set_pst(struct feature *f, size_t id)
{
- ksp[id].sub_type |= f->sub_type;
+ ksp[id].type |= f->type;
}
static void unset_pst(struct feature *f, size_t id)
{
- ksp[id].sub_type &= !f->sub_type;
+ ksp[id].type &= !f->type;
}
static void do_uninstall_features(struct feature *f, size_t i)
--- /dev/null
+/*
+ * 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, 2015
+ *
+ * 2015 Vyacheslav Cherkashin <v.cherkashin@samsung.com>
+ *
+ */
+
+
+#include <linux/sched.h>
+#include <writer/swap_msg.h>
+#include <writer/kernel_operations.h>
+#include "ksf_msg.h"
+
+
+#define KSF_PREFIX KERN_INFO "[KSF] "
+
+
+
+
+
+/* ============================================================================
+ * = MSG_SYSCALL_* (ENTRY/EXIT) =
+ * ============================================================================
+ */
+struct msg_sys_header {
+ u32 pid;
+ u32 tid;
+ u32 probe_type;
+ u64 pc_addr;
+ u64 caller_pc_addr;
+ u32 cpu_num;
+} __packed;
+
+struct msg_sys_entry {
+ struct msg_sys_header h;
+ u32 cnt_args;
+ char args[0];
+} __packed;
+
+struct msg_sys_exit {
+ struct msg_sys_header h;
+ char ret_val[0];
+} __packed;
+
+
+static void pack_header(struct msg_sys_header *h, unsigned long func_addr,
+ unsigned long ret_addr, enum probe_t type)
+{
+ struct task_struct *task = current;
+
+ h->pid = task->tgid;
+ h->tid = task->pid;
+ h->probe_type = (u32)type;
+ h->pc_addr = func_addr;
+ h->caller_pc_addr = ret_addr;
+ h->cpu_num = smp_processor_id();
+}
+
+static void pack_entry_header(struct msg_sys_entry *e, struct pt_regs *regs,
+ unsigned long func_addr, enum probe_t type,
+ const char *fmt)
+{
+ pack_header(&e->h, func_addr, get_regs_ret_func(regs), type);
+ e->cnt_args = strlen(fmt);
+}
+
+static void pack_exit_header(struct msg_sys_exit *e, unsigned long func_addr,
+ unsigned long ret_addr, enum probe_t type)
+{
+ pack_header(&e->h, func_addr, ret_addr, type);
+}
+
+void ksf_msg_entry(struct pt_regs *regs, unsigned long func_addr,
+ enum probe_t type, const char *fmt)
+{
+ int ret;
+ struct swap_msg *m;
+ struct msg_sys_entry *ent;
+ size_t size;
+
+ m = swap_msg_get(MSG_SYSCALL_ENTRY);
+
+ ent = swap_msg_payload(m);
+ pack_entry_header(ent, regs, func_addr, type, fmt);
+
+ size = swap_msg_size(m) - sizeof(*ent);
+ ret = swap_msg_pack_args(ent->args, size, fmt, regs);
+ if (ret < 0) {
+ printk(KSF_PREFIX "ERROR: arguments packing, ret=%d\n", ret);
+ goto put_msg;
+ }
+
+ swap_msg_flush(m, sizeof(*ent) + ret);
+
+put_msg:
+ swap_msg_put(m);
+}
+
+void ksf_msg_exit(struct pt_regs *regs, unsigned long func_addr,
+ unsigned long ret_addr, enum probe_t type, char ret_type)
+{
+ int ret;
+ struct swap_msg *m;
+ struct msg_sys_exit *ext;
+ size_t size;
+
+ m = swap_msg_get(MSG_SYSCALL_EXIT);
+
+ ext = swap_msg_payload(m);
+ pack_exit_header(ext, func_addr, ret_addr, type);
+
+ size = swap_msg_size(m) - sizeof(*ext);
+ ret = swap_msg_pack_ret_val(ext->ret_val, size, ret_type, regs);
+ if (ret < 0) {
+ printk(KSF_PREFIX "ERROR: ret value packing, ret=%d\n", ret);
+ goto put_msg;
+ }
+
+ swap_msg_flush(m, sizeof(*ext) + ret);
+
+put_msg:
+ swap_msg_put(m);
+}
+
+
+
+
+
+/* ============================================================================
+ * = MSG_FILE_FUNCTION_* (ENTRY/EXIT) =
+ * ============================================================================
+ */
+struct msg_file_entry {
+ u32 pid;
+ u32 tid;
+ u32 fd;
+ u32 event_type;
+ char file_path[0];
+} __packed;
+
+enum file_info {
+ FI_GENIRAL = 0,
+ FI_OPEN = 1,
+ FI_LOCK = 2
+};
+
+static int pack_file_entry_head(void *data, size_t size, enum file_info info,
+ int fd, enum file_api_t api, const char *path)
+{
+ struct msg_file_entry *ent = (struct msg_file_entry *)data;
+ struct task_struct *task = current;
+ size_t len, old_size = size;
+
+ ent->pid = task->tgid;
+ ent->tid = task->pid;
+ ent->fd = fd;
+ ent->event_type = api;
+
+ size -= sizeof(*ent);
+ len = strlen(path);
+ if (size < len + 1)
+ return -ENOMEM;
+
+ memcpy(ent->file_path, path, len);
+ ent->file_path[len] = '\0';
+
+ size -= len + 1;
+ data += old_size - size;
+
+ if (size < 4)
+ return -ENOMEM;
+
+ *((u32 *)data) = (u32)info;
+ size -= 4;
+
+ return old_size - size;
+}
+
+
+
+void ksf_msg_file_entry(int fd, enum file_api_t api, const char *path)
+{
+ int ret;
+ void *p;
+ size_t size;
+ struct swap_msg *m;
+
+ m = swap_msg_get(MSG_FILE_FUNCTION_ENTRY);
+ p = swap_msg_payload(m);
+ size = swap_msg_size(m);
+
+ ret = pack_file_entry_head(p, size, FI_GENIRAL, fd, api, path);
+ if (ret < 0) {
+ printk(KSF_PREFIX "buffer is too small\n");
+ goto put_msg;
+ }
+
+ swap_msg_flush(m, ret);
+
+put_msg:
+ swap_msg_put(m);
+}
+
+void ksf_msg_file_entry_open(int fd, enum file_api_t api, const char *path,
+ const char __user *ofile)
+{
+ long n;
+ int ret;
+ void *p;
+ size_t size;
+ struct swap_msg *m;
+
+ m = swap_msg_get(MSG_FILE_FUNCTION_ENTRY);
+ p = swap_msg_payload(m);
+ size = swap_msg_size(m);
+
+ ret = pack_file_entry_head(p, size, FI_OPEN, fd, api, path);
+ if (ret < 0) {
+ printk(KSF_PREFIX "buffer is too small\n");
+ goto put_msg;
+ }
+
+ size -= ret;
+ p += ret;
+
+ n = strncpy_from_user(p, ofile, size);
+ if (n < 0) {
+ printk(KSF_PREFIX "cannot copy ofile\n");
+ swap_msg_put(m);
+ }
+
+ swap_msg_flush(m, ret + n + 1);
+
+put_msg:
+ swap_msg_put(m);
+}
+
+struct lock_arg {
+ u32 type;
+ u32 whence;
+ u64 start;
+ u64 len;
+} __packed;
+
+void ksf_msg_file_entry_lock(int fd, enum file_api_t api, const char *path,
+ int type, int whence, s64 start, s64 len)
+{
+ int ret;
+ void *p;
+ size_t size;
+ struct swap_msg *m;
+ struct lock_arg *arg;
+
+ m = swap_msg_get(MSG_FILE_FUNCTION_ENTRY);
+ p = swap_msg_payload(m);
+ size = swap_msg_size(m);
+
+ ret = pack_file_entry_head(p, size, FI_LOCK, fd, api, path);
+ if (ret < 0) {
+ printk(KSF_PREFIX "buffer is too small\n");
+ goto put_msg;
+ }
+
+ size -= ret;
+ p += ret;
+
+ if (size < sizeof(*arg)) {
+ printk(KSF_PREFIX "buffer is too small\n");
+ goto put_msg;
+ }
+
+ arg = (struct lock_arg *)p;
+ arg->type = (u32)type;
+ arg->whence = (u32)whence;
+ arg->start = (u64)start;
+ arg->len = (u64)len;
+
+ swap_msg_flush(m, ret + sizeof(*arg));
+
+put_msg:
+ swap_msg_put(m);
+}
+
+
+struct msg_file_exit {
+ u32 pid;
+ u32 tid;
+ char ret_val[0];
+} __packed;
+
+void ksf_msg_file_exit(struct pt_regs *regs, char ret_type)
+{
+ struct task_struct *task = current;
+ int ret;
+ struct swap_msg *m;
+ struct msg_file_exit *ext;
+ size_t size;
+
+ m = swap_msg_get(MSG_FILE_FUNCTION_EXIT);
+
+ ext = swap_msg_payload(m);
+ ext->pid = task->tgid;
+ ext->tid = task->pid;
+
+ size = swap_msg_size(m) - sizeof(*ext);
+ ret = swap_msg_pack_ret_val(ext->ret_val, size, ret_type, regs);
+ if (ret < 0) {
+ printk(KSF_PREFIX "ERROR: ret value packing, ret=%d\n", ret);
+ goto put_msg;
+ }
+
+ swap_msg_flush(m, sizeof(*ext) + ret);
+
+put_msg:
+ swap_msg_put(m);
+}
+
+
+
+
+
+/* ============================================================================
+ * = MSG_FILE_FUNCTION_* (ENTRY/EXIT) =
+ * ============================================================================
+ */
+struct msg_context_switch {
+ u64 pc_addr;
+ u32 pid;
+ u32 tid;
+ u32 cpu_num;
+} __packed;
+
+static void context_switch(struct pt_regs *regs, enum swap_msg_id id)
+{
+ struct task_struct *task = current;
+ struct swap_msg *m;
+ struct msg_context_switch *mcs;
+ void *p;
+
+ m = swap_msg_get(id);
+ p = swap_msg_payload(m);
+
+ mcs = p;
+ mcs->pc_addr = 0;
+ mcs->pid = task->tgid;
+ mcs->tid = task->pid;
+ mcs->cpu_num = smp_processor_id();
+
+ swap_msg_flush(m, sizeof(*mcs));
+ swap_msg_put(m);
+}
+
+void ksf_switch_entry(struct pt_regs *regs)
+{
+ context_switch(regs, MSG_CONTEXT_SWITCH_ENTRY);
+}
+
+void ksf_switch_exit(struct pt_regs *regs)
+{
+ context_switch(regs, MSG_CONTEXT_SWITCH_EXIT);
+}
--- /dev/null
+/*
+ * 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, 2015
+ *
+ * 2015 Vyacheslav Cherkashin <v.cherkashin@samsung.com>
+ *
+ */
+
+
+#ifndef _KSF_MSG_H
+#define _KSF_MSG_H
+
+
+enum probe_t {
+ PT_KS_NONE = 0x00,
+ PT_KS_FILE = 0x01,
+ PT_KS_IPC = 0x02,
+ PT_KS_PROCESS = 0x04,
+ PT_KS_SIGNAL = 0x08,
+ PT_KS_NETWORK = 0x10,
+ PT_KS_DESC = 0x20
+};
+
+
+enum file_api_t {
+ FOPS_OPEN = 0,
+ FOPS_CLOSE = 1,
+ FOPS_READ_BEGIN = 2,
+ FOPS_READ_END = 3,
+ FOPS_READ = FOPS_READ_BEGIN,
+ FOPS_WRITE_BEGIN = 4,
+ FOPS_WRITE_END = 5,
+ FOPS_WRITE = FOPS_WRITE_BEGIN,
+ FOPS_DIRECTORY = 6,
+ FOPS_PERMS = 7,
+ FOPS_OTHER = 8,
+ FOPS_SEND = 9,
+ FOPS_RECV = 10,
+ FOPS_OPTION = 11,
+ FOPS_MANAGE = 12,
+ FOPS_LOCK_START = 14, /* 13 */
+ FOPS_LOCK_END = 15,
+ FOPS_LOCK_RELEASE = 16
+};
+
+
+struct pt_regs;
+
+
+void ksf_msg_entry(struct pt_regs *regs, unsigned long func_addr,
+ enum probe_t type, const char *fmt);
+void ksf_msg_exit(struct pt_regs *regs, unsigned long func_addr,
+ unsigned long ret_addr, enum probe_t type, char ret_type);
+
+void ksf_msg_file_entry(int fd, enum file_api_t api, const char *path);
+void ksf_msg_file_entry_open(int fd, enum file_api_t api, const char *path,
+ const char __user *ofile);
+void ksf_msg_file_entry_lock(int fd, enum file_api_t api, const char *path,
+ int type, int whence, s64 start, s64 len);
+void ksf_msg_file_exit(struct pt_regs *regs, char ret_type);
+
+void ksf_switch_entry(struct pt_regs *regs);
+void ksf_switch_exit(struct pt_regs *regs);
+
+
+#endif /* _KSF_MSG_H */
#include <linux/types.h>
+#include <linux/sched.h>
#include <linux/module.h>
#include <ks_features/ks_features.h>
#include <us_manager/us_manager.h>
#include "features.h"
#include "msg_parser.h"
+#include <writer/swap_msg.h>
#include <writer/event_filter.h>
-#include <writer/swap_writer_module.h>
#include <sampler/swap_sampler_module.h>
#include <energy/energy.h>
}
+
+
+
+struct sample {
+ u32 pid;
+ u64 pc_addr;
+ u32 tid;
+ u32 cpu_num;
+} __packed;
+
+static void sample_msg(struct pt_regs *regs)
+{
+ struct swap_msg *m;
+ struct sample *s;
+ struct task_struct *task = current;
+
+ m = swap_msg_get(MSG_SAMPLE);
+
+ s = swap_msg_payload(m);
+ s->pid = task->tgid;
+ s->pc_addr = instruction_pointer(regs);
+ s->tid = task->pid;
+ s->cpu_num = smp_processor_id();
+
+ swap_msg_flush(m, sizeof(*s));
+ swap_msg_put(m);
+}
+
static void sampler_cb(struct pt_regs *regs)
{
if (check_event(current))
#include <linux/errno.h>
#include <linux/delay.h>
#include <linux/module.h>
-#include <writer/swap_writer_module.h>
#include "msg_parser.h"
#include "msg_buf.h"
#include "features.h"
#include "parser_defs.h"
#include "us_inst.h"
+#include <writer/swap_msg.h>
#include <us_manager/us_manager.h>
+
static int wrt_launcher_port;
static int set_config(struct conf_data *conf)
struct us_inst_data *us_inst;
struct conf_data conf;
- reset_seq_num();
- reset_discarded();
+ swap_msg_seq_num_reset();
+ swap_msg_discard_reset();
us_inst = create_us_inst_data(mb);
if (us_inst == NULL)
{
int ret = 0;
struct conf_data conf;
- unsigned int discarded;
+ int discarded;
if (!is_end_mb(mb)) {
print_err("to long message, remained=%u", remained_mb(mb));
if (ret)
printk(KERN_INFO "Cannot set config, ret = %d\n", ret);
- discarded = get_discarded_count();
+ discarded = swap_msg_discard_get();
printk(KERN_INFO "discarded messages: %d\n", discarded);
- reset_discarded();
+ swap_msg_discard_reset();
return ret;
}
#include <us_manager/us_manager.h>
#include <us_manager/probes/register_probes.h>
#include <us_manager/sspt/sspt_page.h>
-#include <writer/swap_writer_module.h>
#include <uprobe/swap_uprobes.h>
#include <us_manager/sspt/ip.h>
#include "preload_probe.h"
EXTRA_CFLAGS := $(extra_cflags)
obj-m := swap_retprobe.o
-swap_retprobe-y := retprobe.o
+swap_retprobe-y := \
+ retprobe.o \
+ rp_msg.o
#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>
+#include "rp_msg.h"
+
static int retprobe_copy(struct probe_info *dest,
const struct probe_info *source)
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;
+ const unsigned long func_addr = (unsigned long)ip->orig_addr;
- entry_event(fmt, addr, regs, PT_US, PST_NONE);
+ rp_msg_entry(regs, func_addr, fmt);
}
return 0;
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;
+ const unsigned long func_addr = (unsigned long)ip->orig_addr;
+ const unsigned long ret_addr = (unsigned long)ri->ret_addr;
+ const char ret_type = ip->probe_i.rp_i.ret_type;
- exit_event(ip->probe_i.rp_i.ret_type, regs, PT_US, PST_NONE, addr,
- ret_addr);
+ rp_msg_exit(regs, func_addr, ret_type, ret_addr);
}
return 0;
--- /dev/null
+/*
+ * 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, 2015
+ *
+ * 2015 Vyacheslav Cherkashin <v.cherkashin@samsung.com>
+ *
+ */
+
+
+#include <linux/sched.h>
+#include <writer/swap_msg.h>
+#include <writer/kernel_operations.h>
+#include "rp_msg.h"
+
+
+#define RP_PREFIX KERN_INFO "[RP] "
+
+
+struct msg_entry {
+ u32 pid;
+ u32 tid;
+ u64 pc_addr;
+ u64 caller_pc_addr;
+ u32 cpu_num;
+ u32 cnt_args;
+ char args[0];
+} __packed;
+
+struct msg_exit {
+ u32 pid;
+ u32 tid;
+ u64 pc_addr;
+ u64 caller_pc_addr;
+ u32 cpu_num;
+ char ret_val[0];
+} __packed;
+
+
+void rp_msg_entry(struct pt_regs *regs, unsigned long func_addr,
+ const char *fmt)
+{
+ int ret;
+ struct task_struct *task = current;
+ struct swap_msg *m;
+ struct msg_entry *ent;
+ void *p;
+ size_t size;
+
+ m = swap_msg_get(MSG_FUNCTION_ENTRY);
+ p = swap_msg_payload(m);
+
+ ent = p;
+ ent->pid = task->tgid;
+ ent->tid = task->pid;
+ ent->pc_addr = func_addr;
+ ent->caller_pc_addr = get_regs_ret_func(regs);
+ ent->cpu_num = smp_processor_id();
+ ent->cnt_args = strlen(fmt);
+
+ size = swap_msg_size(m);
+ ret = swap_msg_pack_args(p + sizeof(*ent), size - sizeof(*ent),
+ fmt, regs);
+ if (ret < 0) {
+ printk(RP_PREFIX "ERROR: arguments packing, ret=%d\n", ret);
+ goto put_msg;
+ }
+
+ swap_msg_flush(m, sizeof(*ent) + ret);
+
+put_msg:
+ swap_msg_put(m);
+}
+
+void rp_msg_exit(struct pt_regs *regs, unsigned long func_addr,
+ char ret_type, unsigned long ret_addr)
+{
+ int ret;
+ struct task_struct *task = current;
+ struct swap_msg *m;
+ struct msg_exit *ext;
+ void *p;
+ size_t size;
+
+ m = swap_msg_get(MSG_FUNCTION_EXIT);
+ p = swap_msg_payload(m);
+
+ ext = p;
+ ext->pid = task->tgid;
+ ext->tid = task->pid;
+ ext->pc_addr = func_addr;
+ ext->caller_pc_addr = ret_addr;
+ ext->cpu_num = smp_processor_id();
+
+ size = swap_msg_size(m);
+ ret = swap_msg_pack_ret_val(p + sizeof(*ext), size - sizeof(*ext),
+ ret_type, regs);
+ if (ret < 0) {
+ printk(RP_PREFIX "ERROR: return value packing, ret=%d\n", ret);
+ goto put_msg;
+ }
+
+ swap_msg_flush(m, sizeof(*ext) + ret);
+
+put_msg:
+ swap_msg_put(m);
+}
--- /dev/null
+/*
+ * 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, 2015
+ *
+ * 2015 Vyacheslav Cherkashin <v.cherkashin@samsung.com>
+ *
+ */
+
+
+#ifndef _RP_MSG_H
+#define _RP_MSG_H
+
+
+struct pt_regs;
+
+
+void rp_msg_entry(struct pt_regs *regs, unsigned long func_addr,
+ const char *fmt);
+void rp_msg_exit(struct pt_regs *regs, unsigned long func_addr,
+ char ret_type, unsigned long ret_addr);
+
+
+#endif /* _RP_MSG_H */
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 \
- probes/probes.o
+ probes/probes.o \
+ usm_msg.o
#include <kprobe/swap_kprobes_deps.h>
#include <ksyms/ksyms.h>
#include <writer/kernel_operations.h>
-#include <writer/swap_writer_module.h>
#include "us_slot_manager.h"
#include "sspt/sspt.h"
+#include "usm_msg.h"
#include "helper.h"
struct task_struct;
sspt_proc_insert_files(proc, &head);
- proc_unmap_msg(start, end);
+ usm_msg_unmap(start, end);
}
}
struct task_struct *task;
task = current->group_leader;
- if (is_kthread(task) ||
- get_regs_ret_val(regs))
+ if (is_kthread(task) || regs_return_value(regs))
goto out;
remove_unmap_probes(task, (struct unmap_data *)ri->data);
if (is_kthread(task))
return 0;
- start_addr = (unsigned long)get_regs_ret_val(regs);
+ start_addr = regs_return_value(regs);
if (IS_ERR_VALUE(start_addr))
return 0;
vma = find_vma_intersection(task->mm, start_addr, start_addr + 1);
if (vma && check_vma(vma))
- pcoc_map_msg(vma);
+ usm_msg_map(vma);
return 0;
}
#include <linux/slab.h>
#include <linux/list.h>
#include "proc_filters.h"
+#include <us_manager/usm_msg.h>
#include <us_manager/img/img_proc.h>
#include <us_manager/img/img_file.h>
#include <us_manager/img/img_ip.h>
#include <us_manager/sspt/sspt_proc.h>
#include <us_manager/helper.h>
-#include <writer/swap_writer_module.h>
struct pf_group {
struct list_head list;
}
down_write(&task->mm->mmap_sem);
- proc_info_msg(task, dentry);
+ usm_msg_info(task, dentry);
sspt_proc_install(proc);
up_write(&task->mm->mmap_sem);
}
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/list.h>
+#include <us_manager/usm_msg.h>
#include <us_manager/us_slot_manager.h>
-#include <writer/swap_writer_module.h>
static LIST_HEAD(proc_probes_list);
sspt_destroy_feature(proc->feature);
- terminate_msg(proc->task);
+ usm_msg_term(proc->task);
free_sm_us(proc->sm);
kfree(proc);
}
#include "helper.h"
#include "us_manager.h"
#include "debugfs_us_manager.h"
-
#include <writer/event_filter.h>
#include <master/swap_initializer.h>
-/* FIXME: move /un/init_msg() elsewhere and remove this include */
-#include <writer/swap_writer_module.h> /* for /un/init_msg() */
-
-
static DEFINE_MUTEX(mutex_inst);
static enum status_type status = ST_OFF;
int ret;
ret = init_us_filter();
- if (ret)
- return ret;
-
- ret = init_msg(32*1024); /* TODO: move to writer */
- if (ret)
- exit_us_filter();
return ret;
}
if (status == ST_ON)
do_usm_stop();
- uninit_msg();
exit_us_filter();
}
--- /dev/null
+/*
+ * 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, 2015
+ *
+ * 2015 Vyacheslav Cherkashin <v.cherkashin@samsung.com>
+ *
+ */
+
+
+#include <linux/fs.h>
+#include <linux/sched.h>
+#include <linux/dcache.h>
+
+#include <writer/swap_msg.h>
+#include <us_manager/sspt/sspt.h> /* ... check_vma() */
+
+
+#define USM_PREFIX KERN_INFO "[USM] "
+
+
+struct kmem_info {
+ const char *name;
+ unsigned long start;
+ unsigned long end;
+};
+
+static void kmem_info_fill(struct kmem_info *info, struct mm_struct *mm)
+{
+#if defined(CONFIG_ARM)
+ info->name = "[vectors]"
+ info->start = CONFIG_VECTORS_BASE;
+ info->end = CONFIG_VECTORS_BASE + PAGE_SIZE;
+#elif defined(CONFIG_X86_32)
+ unsigned long vdso;
+ struct vm_area_struct *vma_vdso;
+
+ vdso = (unsigned long)mm->context.vdso;
+ vma_vdso = find_vma_intersection(mm, vdso, vdso + 1);
+ if (vma_vdso) {
+ info->name = "[vdso]";
+ info->start = vma_vdso->vm_start;
+ info->end = vma_vdso->vm_end;
+ } else {
+ printk(USM_PREFIX "Cannot get VDSO mapping\n");
+
+ info->name = NULL;
+ info->start = 0;
+ info->end = 0;
+ }
+#endif /* CONFIG_arch */
+}
+
+
+static int pack_path(void *data, size_t size, struct file *file)
+{
+ enum { TMP_BUF_LEN = 512 };
+ char tmp_buf[TMP_BUF_LEN];
+ const char NA[] = "N/A";
+ const char *filename;
+ size_t len = sizeof(NA);
+
+ if (file == NULL) {
+ filename = NA;
+ goto cp2buf;
+ }
+
+ filename = d_path(&file->f_path, tmp_buf, TMP_BUF_LEN);
+ if (IS_ERR_OR_NULL(filename)) {
+ filename = NA;
+ goto cp2buf;
+ }
+
+ len = strlen(filename) + 1;
+
+cp2buf:
+ if (size < len)
+ return -ENOMEM;
+
+ memcpy(data, filename, len);
+ return len;
+}
+
+
+
+
+
+/* ============================================================================
+ * = MSG_PROCESS_INFO =
+ * ============================================================================
+ */
+struct proc_info_top {
+ u32 pid;
+ char comm[0];
+} __packed;
+
+struct proc_info_bottom {
+ u32 ppid;
+ u64 start_time;
+ u64 low_addr;
+ u64 high_addr;
+ char bin_path[0];
+} __packed;
+
+struct lib_obj {
+ u64 low_addr;
+ u64 high_addr;
+ char lib_path[0];
+} __packed;
+
+static int pack_lib_obj(void *data, size_t size, struct vm_area_struct *vma)
+{
+ int ret;
+ struct lib_obj *obj = (struct lib_obj *)data;
+
+ if (size < sizeof(*obj))
+ return -ENOMEM;
+
+ obj->low_addr = vma->vm_start;
+ obj->high_addr = vma->vm_end;
+ size -= sizeof(*obj);
+
+ ret = pack_path(obj->lib_path, size, vma->vm_file);
+ if (ret < 0)
+ return ret;
+
+ return ret + sizeof(*obj);
+}
+
+static int pack_shared_kmem(void *data, size_t size, struct mm_struct *mm)
+{
+ struct lib_obj *obj = (struct lib_obj *)data;
+ struct kmem_info info;
+ size_t name_len, obj_size;
+
+ if (size < sizeof(*obj))
+ return -ENOMEM;
+
+ kmem_info_fill(&info, mm);
+
+ if (info.name == NULL)
+ return 0;
+
+ obj->low_addr = (u64)info.start;
+ obj->high_addr = (u64)info.end;
+
+ name_len = strlen(info.name) + 1;
+ obj_size = sizeof(*obj) + name_len;
+ if (size < obj_size)
+ return -ENOMEM;
+
+ memcpy(obj->lib_path, info.name, name_len);
+
+ return obj_size;
+}
+
+static int pack_libs(void *data, size_t size, struct mm_struct *mm)
+{
+ int ret;
+ struct vm_area_struct *vma;
+ u32 *lib_cnt = (u32 *)data;
+ const size_t old_size = size;
+
+ if (size < sizeof(*lib_cnt))
+ return -ENOMEM;
+
+ /* packing libraries count */
+ *lib_cnt = 0;
+ data += sizeof(*lib_cnt);
+ size -= sizeof(*lib_cnt);
+
+ /* packing libraries */
+ for (vma = mm->mmap; vma; vma = vma->vm_next) {
+ if (check_vma(vma)) {
+ ret = pack_lib_obj(data, size, vma);
+ if (ret < 0)
+ return ret;
+
+ data += ret;
+ size -= ret;
+ ++(*lib_cnt);
+ }
+ }
+
+ /* packing shared kernel memory */
+ ret = pack_shared_kmem(data, size, mm);
+ if (ret < 0)
+ return ret;
+
+ *lib_cnt += !!ret;
+ size -= ret;
+
+ return old_size - size;
+}
+
+static struct vm_area_struct *find_vma_exe_by_dentry(struct mm_struct *mm,
+ struct dentry *dentry)
+{
+ struct vm_area_struct *vma;
+
+ for (vma = mm->mmap; vma; vma = vma->vm_next) {
+ if (vma->vm_file && (vma->vm_flags & VM_EXEC) &&
+ (vma->vm_file->f_dentry == dentry))
+ goto out;
+ }
+
+ vma = NULL;
+out:
+
+ return vma;
+}
+
+static int pack_proc_info_top(void *data, size_t size,
+ struct task_struct *task)
+{
+ struct proc_info_top *pit = (struct proc_info_top *)data;
+
+ if (size < sizeof(*pit) + sizeof(task->comm))
+ return -ENOMEM;
+
+ pit->pid = task->tgid;
+ get_task_comm(pit->comm, task);
+
+ return sizeof(*pit) + strlen(pit->comm) + 1;
+}
+
+static int pack_proc_info_bottom(void *data, size_t size,
+ struct task_struct *task,
+ struct dentry *dentry)
+{
+ struct proc_info_bottom *pib = (struct proc_info_bottom *)data;
+ struct vm_area_struct *vma = find_vma_exe_by_dentry(task->mm, dentry);
+ struct timespec boot_time;
+ struct timespec start_time;
+ int ret;
+
+ if (size < sizeof(*pib))
+ return -ENOMEM;
+
+ getboottime(&boot_time);
+ start_time = timespec_add(boot_time, task->real_start_time);
+
+ pib->ppid = task->real_parent->tgid;
+ pib->start_time = swap_msg_spec2time(&start_time);
+
+ if (vma) {
+ pib->low_addr = vma->vm_start;
+ pib->high_addr = vma->vm_end;
+ ret = pack_path(pib->bin_path, size, vma->vm_file);
+ } else {
+ pib->low_addr = 0;
+ pib->high_addr = 0;
+ ret = pack_path(pib->bin_path, size, NULL);
+ }
+
+ if (ret < 0)
+ return ret;
+
+ return sizeof(*pib) + ret;
+}
+
+static int pack_proc_info(void *data, size_t size, struct task_struct *task,
+ struct dentry *dentry)
+{
+ int ret;
+ const size_t old_size = size;
+
+ ret = pack_proc_info_top(data, size, task);
+ if (ret < 0)
+ return ret;
+
+ data += ret;
+ size -= ret;
+
+ ret = pack_proc_info_bottom(data, size, task, dentry);
+ if (ret < 0)
+ return ret;
+
+ data += ret;
+ size -= ret;
+
+ ret = pack_libs(data, size, task->mm);
+ if (ret < 0)
+ return ret;
+
+ return old_size - size + ret;
+}
+
+/* Called with down\up\_read(&task->mm->mmap_sem). */
+void usm_msg_info(struct task_struct *task, struct dentry *dentry)
+{
+ int ret;
+ struct swap_msg *m;
+ void *p;
+ size_t size;
+
+ m = swap_msg_get(MSG_PROC_INFO);
+ p = swap_msg_payload(m);
+ size = swap_msg_size(m);
+
+ ret = pack_proc_info(p, size, task, dentry);
+ if (ret < 0) {
+ printk(USM_PREFIX "ERROR: message process info packing, "
+ "ret=%d\n", ret);
+ goto put_msg;
+ }
+
+ swap_msg_flush(m, ret);
+
+put_msg:
+ swap_msg_put(m);
+}
+
+
+
+
+
+/* ============================================================================
+ * = MSG_TERMINATE =
+ * ============================================================================
+ */
+struct proc_terminate {
+ u32 pid;
+} __packed;
+
+void usm_msg_term(struct task_struct *task)
+{
+ struct swap_msg *m;
+ struct proc_terminate *term;
+
+ m = swap_msg_get(MSG_TERMINATE);
+
+ term = swap_msg_payload(m);
+ term->pid = task->pid;
+
+ swap_msg_flush(m, sizeof(*term));
+ swap_msg_put(m);
+}
+
+
+
+
+
+/* ============================================================================
+ * = MSG_PROCESS_MAP =
+ * ============================================================================
+ */
+struct proc_map {
+ u32 pid;
+ u64 low_addr;
+ u64 high_addr;
+ char bin_path[0];
+} __packed;
+
+static int pack_proc_map(void *data, size_t size, struct vm_area_struct *vma)
+{
+ struct proc_map *map = (struct proc_map *)data;
+ int ret;
+
+ map->pid = current->tgid;
+ map->low_addr = vma->vm_start;
+ map->high_addr = vma->vm_end;
+
+ ret = pack_path(map->bin_path, size - sizeof(*map), vma->vm_file);
+ if (ret < 0)
+ return ret;
+
+ return ret + sizeof(*map);
+}
+
+void usm_msg_map(struct vm_area_struct *vma)
+{
+ int ret;
+ struct swap_msg *m;
+ void *p;
+ size_t size;
+
+ m = swap_msg_get(MSG_PROC_MAP);
+ p = swap_msg_payload(m);
+ size = swap_msg_size(m);
+
+ ret = pack_proc_map(p, size, vma);
+ if (ret < 0) {
+ printk(USM_PREFIX "ERROR: message process mapping packing, "
+ "ret=%d\n", ret);
+ goto put_msg;
+ }
+
+ swap_msg_flush(m, ret);
+
+put_msg:
+ swap_msg_put(m);
+}
+
+
+
+
+
+/* ============================================================================
+ * = MSG_PROCESS_UNMAP =
+ * ============================================================================
+ */
+struct proc_unmap {
+ u32 pid;
+ u64 low_addr;
+ u64 high_addr;
+} __packed;
+
+void usm_msg_unmap(unsigned long start, unsigned long end)
+{
+ struct swap_msg *m;
+ struct proc_unmap *unmap;
+
+ m = swap_msg_get(MSG_PROC_UNMAP);
+
+ unmap = swap_msg_payload(m);
+ unmap->pid = current->tgid;
+ unmap->low_addr = (u64)start;
+ unmap->high_addr = (u64)end;
+
+ swap_msg_flush(m, sizeof(*unmap));
+ swap_msg_put(m);
+}
+
+
+
+
+
+/* ============================================================================
+ * = MSG_PROCESS_COMM =
+ * ============================================================================
+ */
+struct proc_comm {
+ u32 pid;
+ char comm[0];
+} __packed;
+
+void usm_msg_comm(struct task_struct *task)
+{
+ struct swap_msg *m;
+ struct proc_comm *c;
+
+ m = swap_msg_get(MSG_PROC_COMM);
+
+ c = swap_msg_payload(m);
+ c->pid = task->tgid;
+ get_task_comm(c->comm, task);
+
+ swap_msg_flush(m, sizeof(*c) + strlen(c->comm) + 1);
+ swap_msg_put(m);
+}
--- /dev/null
+/*
+ * 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, 2015
+ *
+ * 2015 Vyacheslav Cherkashin <v.cherkashin@samsung.com>
+ *
+ */
+
+
+#ifndef _USM_MSG_H
+#define _USM_MSG_H
+
+
+struct dentry;
+struct task_struct;
+struct vm_area_struct;
+
+
+void usm_msg_info(struct task_struct *task, struct dentry *dentry);
+void usm_msg_term(struct task_struct *task);
+void usm_msg_map(struct vm_area_struct *vma);
+void usm_msg_unmap(unsigned long start, unsigned long end);
+void usm_msg_comm(struct task_struct *task);
+
+
+#endif /* _USM_MSG_H */
obj-m := swap_webprobe.o
swap_webprobe-y := webprobe.o \
webprobe_debugfs.o \
- webprobe_prof.o
+ webprobe_prof.o \
+ web_msg.o
--- /dev/null
+/*
+ * 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, 2015
+ *
+ * 2015 Vyacheslav Cherkashin <v.cherkashin@samsung.com>
+ *
+ */
+
+
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/stddef.h>
+#include <linux/uaccess.h>
+#include <writer/swap_msg.h>
+#include <writer/event_filter.h>
+#include <swap-asm/swap_uprobes.h>
+
+
+#define WEB_PREFIX KERN_INFO "[WEB_PROF] "
+
+/* TODO: develop method for obtaining this data during build... */
+/* location: webkit2-efl-123997_0.11.113/Source/WTF/wtf/text/StringImpl.h:70 */
+struct MStringImpl {
+ unsigned m_refCount;
+ unsigned m_length;
+ union {
+ const unsigned char *m_data8;
+ const unsigned short *m_data16;
+ };
+ union {
+ void *m_buffer;
+ struct MStringImpl *m_substringBuffer;
+ unsigned short *m_copyData16;
+ };
+ unsigned m_hashAndFlags;
+};
+
+/* location: webkit2-efl-123997_0.11.113/Source/JavaScriptCore/profiler/
+ * CallIdentifier.h:36
+ */
+struct MCallIdentifier {
+ struct MStringImpl *m_name;
+ struct MStringImpl *m_url;
+ unsigned m_lineNumber;
+};
+
+enum {
+ OFFSET_NAME = offsetof(struct MCallIdentifier, m_name),
+ OFFSET_URL = offsetof(struct MCallIdentifier, m_url),
+ OFFSET_LNUM = offsetof(struct MCallIdentifier, m_lineNumber)
+};
+
+
+static int pack_web_string(void *data, size_t size,
+ struct MStringImpl __user *str_imp)
+{
+ int ret;
+ char __user *str;
+ unsigned len;
+ char __user **pstr;
+ unsigned __user *plen;
+
+ pstr = (void __user *)str_imp + offsetof(struct MStringImpl, m_data8);
+ plen = (void __user *)str_imp + offsetof(struct MStringImpl, m_length);
+
+ if (get_user(str, pstr) ||
+ get_user(len, plen)) {
+ printk(WEB_PREFIX "%s: cannot read user memory\n", __func__);
+ return -EPERM;
+ }
+
+ if (size < len + 1) {
+ printk(WEB_PREFIX "function name is very long(len=%u)\n", len);
+ return -ENOMEM;
+ }
+
+ ret = strncpy_from_user(data, str, len);
+ if (ret < 0) {
+ printk(WEB_PREFIX "%s: cannot read user memory\n", __func__);
+ return ret;
+ }
+
+ ((char *)data)[ret] = '\0';
+
+ return ret + 1;
+}
+
+
+void web_msg_entry(struct pt_regs *regs)
+{
+ int ret;
+ struct swap_msg *m;
+ void *p;
+ long t_name, t_url;
+ unsigned lnum;
+ size_t pack_size = 0, size;
+ struct MCallIdentifier *call_id;
+ struct task_struct *task = current;
+
+ if (!check_event(task))
+ return;
+
+ call_id = (void *)swap_get_uarg(regs, 2);
+ if (get_user(t_name, (long *)((long)call_id + OFFSET_NAME)) ||
+ get_user(t_url, (long *)((long)call_id + OFFSET_URL)) ||
+ get_user(lnum, (unsigned *)((long)call_id + OFFSET_LNUM))) {
+ printk(WEB_PREFIX "%s: cannot read user memory\n", __func__);
+ return;
+ }
+
+ m = swap_msg_get(MSG_WEB_FUNCTION_ENTRY);
+ p = swap_msg_payload(m);
+ size = swap_msg_size(m);
+
+ /* Pack message */
+ /* PID */
+ *(u32 *)p = task->tgid;
+ p += sizeof(u32);
+ /* TID */
+ *(u32 *)p = task->pid;
+ p += sizeof(u32);
+ /* Line number (in source file) */
+ *(u32 *)p = lnum;
+ p += sizeof(u32);
+
+ size -= 3 * sizeof(u32);
+ pack_size += 3 * sizeof(u32);
+
+ /* Function name */
+ ret = pack_web_string(p, size, (struct MStringImpl *)t_name);
+ if (ret < 0)
+ goto put_msg;
+
+ size -= ret;
+ pack_size += ret;
+
+ /* URL (source file) */
+ ret = pack_web_string(p, size, (struct MStringImpl *)t_url);
+ if (ret < 0)
+ goto put_msg;
+
+ swap_msg_flush(m, pack_size + ret);
+
+put_msg:
+ swap_msg_put(m);
+}
+
+void web_msg_exit(struct pt_regs *regs)
+{
+ int ret;
+ struct swap_msg *m;
+ void *p;
+ long t_name;
+ size_t pack_size = 0, size;
+ struct MCallIdentifier *call_id;
+ struct task_struct *task = current;
+
+ if (!check_event(task))
+ return;
+
+ call_id = (void *)swap_get_uarg(regs, 2);
+ if (get_user(t_name, (long *)((long)call_id + OFFSET_NAME))) {
+ printk(WEB_PREFIX "%s: cannot read user memory\n", __func__);
+ return;
+ }
+
+ m = swap_msg_get(MSG_WEB_FUNCTION_EXIT);
+ p = swap_msg_payload(m);
+ size = swap_msg_size(m);
+
+ /* PID */
+ *(u32 *)p = task->tgid;
+ p += sizeof(u32);
+
+ /* TID */
+ *(u32 *)p = task->pid;
+ p += sizeof(u32);
+
+ size -= 2 * sizeof(u32);
+ pack_size += 2 * sizeof(u32);
+
+ /* Function name */
+ ret = pack_web_string(p, size, (struct MStringImpl *)t_name);
+ if (ret < 0)
+ goto put_msg;
+
+ swap_msg_flush(m, pack_size + ret);
+
+put_msg:
+ swap_msg_put(m);
+}
--- /dev/null
+/*
+ * 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, 2015
+ *
+ * 2015 Vyacheslav Cherkashin <v.cherkashin@samsung.com>
+ *
+ */
+
+
+#ifndef _WEB_MSG_H
+#define _WEB_MSG_H
+
+
+struct pt_regs;
+
+
+void web_msg_entry(struct pt_regs *regs);
+void web_msg_exit(struct pt_regs *regs);
+
+
+#endif /* _WEB_MSG_H */
#include <us_manager/sspt/ip.h>
#include <us_manager/probes/register_probes.h>
#include <us_manager/sspt/sspt.h>
-#include <writer/swap_writer_module.h>
#include <uprobe/swap_uprobes.h>
#include <parser/msg_cmd.h>
#include <linux/module.h>
#include "webprobe_debugfs.h"
#include "webprobe_prof.h"
+#include "web_msg.h"
static unsigned long inspserver_addr_local;
if (addr == web_prof_addr(WILL_EXECUTE) &&
d == web_prof_lib_dentry()) {
willexecute_addr_local = ip->orig_addr;
- return entry_web_event(addr, regs);
+ web_msg_entry(regs);
} else if (addr == web_prof_addr(DID_EXECUTE) &&
d == web_prof_lib_dentry()) {
didexecute_addr_local = ip->orig_addr;
- return exit_web_event(addr, regs);
+ web_msg_exit(regs);
}
}
obj-m := swap_writer.o
swap_writer-y := swap_writer_module.o \
debugfs_writer.o \
- event_filter.o
+ event_filter.o \
+ swap_msg.o
-swap_writer-$(CONFIG_ARM) += kernel_operations_arm.o
-swap_writer-$(CONFIG_X86) += kernel_operations_x86.o
#include <asm/uaccess.h>
#include <master/swap_debugfs.h>
#include <master/swap_initializer.h>
-#include "swap_writer_module.h"
+#include "swap_msg.h"
#include "event_filter.h"
goto put_buf;
}
- ret = raw_msg(buf, count);
+ ret = swap_msg_raw(buf, count);
put_buf:
put_current_buf();
#define __KERNEL_OPERATIONS_H__
#include <linux/kernel.h>
+#include <linux/uaccess.h>
#include <asm/ptrace.h>
/* MESSAGES */
#endif /* CONFIG_arch */
-int get_args(unsigned long args[], int cnt, struct pt_regs *regs);
-
-/* Returns shared kernel memory area name if it is found, otherwise - NULL */
-const char *get_shared_kmem(struct mm_struct *mm, unsigned long *start,
- unsigned long *end);
-
#endif /* __KERNEL_OPERATIONS_H__ */
+++ /dev/null
-/**
- * writer/kernel_operations_arm.c
- * @author Alexander Aksenov <a.aksenov@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, 2013
- *
- * @section DESCRIPTION
- *
- * ARM arch-dependent operations.
- */
-
-#include <asm/ptrace.h>
-#include <asm/uaccess.h>
-#include <asm/page.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <generated/autoconf.h>
-
-#include "kernel_operations.h"
-
-
-/* ======================= ARGS ========================== */
-
-/**
- * @brief Returns arg values.
- *
- * @param[out] args Pointer to array where argument values should be stored/
- * @param cnt Arguments count.
- * @param regs Pointer to register data.
- * @return 0.
- */
-int get_args(unsigned long args[], int cnt, struct pt_regs *regs)
-{
- /* All args, except first 4, are passed on the stack */
- enum { stack_args = 4 };
- int i, args_in_regs;
-
- args_in_regs = cnt < 3 ? cnt : 3;
-
- /* Get first 4 args from registers */
- switch (args_in_regs) {
- case 3:
- args[3] = regs->ARM_r3;
- case 2:
- args[2] = regs->ARM_r2;
- case 1:
- args[1] = regs->ARM_r1;
- case 0:
- args[0] = regs->ARM_r0;
- }
-
- /* Get other args from stack */
- for (i = stack_args; i < cnt; ++i) {
- unsigned long *args_in_sp = (unsigned long *)regs->ARM_sp +
- i - stack_args;
- if (get_user(args[i], args_in_sp))
- printk(KERN_INFO "failed to dereference a pointer, addr=%p\n",
- args_in_sp);
- }
-
- return 0;
-}
-
-
-/* ================== KERNEL SHARED MEM ===================== */
-
-/* CONFIG_VECTORS_BASE used to handle both MMU and non-MMU cases.
- * According to docs (Documentation/arm/memory.txt) all vector addresses
- * are fixed and vectors are always equal to one page, so,
- * end = start + PAGE_SIZE
- * */
-
-/**
- * @brief Gets shared kernel memory addresses.
- *
- * @param mm Pointer to process mm_struct.
- * @param[out] start Pointer to the variable where the first shared mem
- * address should be put.
- * @param[out] end Pointer to the variable where the last shared mem
- * address should be put.
- * @return Pointer to the string with shared mem area name.
- */
-const char *get_shared_kmem(struct mm_struct *mm,
- unsigned long *start,
- unsigned long *end)
-{
- *start = CONFIG_VECTORS_BASE;
- *end = CONFIG_VECTORS_BASE + PAGE_SIZE;
-
- return "[vectors]";
-}
+++ /dev/null
-/**
- * writer/kernel_operations_x86.c
- * @author Alexander Aksenov <a.aksenov@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, 2013
- *
- * @section DESCRIPTION
- *
- * X86 arch-dependent operations.
- */
-
-#include <asm/ptrace.h>
-#include <asm/uaccess.h>
-#include <asm/elf.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/mm.h>
-
-#include "kernel_operations.h"
-
-
-/* ======================= ARGS ========================== */
-
-/**
- * @brief Returns arg values.
- *
- * @param[out] args Pointer to array where argument values should be stored/
- * @param cnt Arguments count.
- * @param regs Pointer to register data.
- * @return 0.
- */
-int get_args(unsigned long args[], int cnt, struct pt_regs *regs)
-{
- int i, stack_args = 0;
-
- /* If we're in kernel mode on x86, get arguments from bx, cx, dx, si,
- * di, bp
- */
- if (!user_mode(regs)) {
- int args_in_regs;
- args_in_regs = cnt < 5 ? cnt : 5;
- stack_args = 6;
-
- switch (args_in_regs) {
- case 5:
- args[5] = regs->bp;
- case 4:
- args[4] = regs->di;
- case 3:
- args[3] = regs->si;
- case 2:
- args[2] = regs->dx;
- case 1:
- args[1] = regs->cx;
- case 0:
- args[0] = regs->bx;
- }
- }
-
- /* Get other args from stack */
- for (i = stack_args; i < cnt; ++i) {
- unsigned long *args_in_sp = (unsigned long *)regs->sp +
- 1 + i - stack_args;
- if (get_user(args[i], args_in_sp))
- printk(KERN_INFO "failed to dereference a pointer, addr=%p\n",
- args_in_sp);
- }
-
- return 0;
-}
-
-
-/* ================== KERNEL SHARED MEM ===================== */
-
-/**
- * @brief Gets shared kernel memory addresses.
- *
- * @param mm Pointer to process mm_struct.
- * @param[out] start Pointer to the variable where the first shared mem
- * address should be put.
- * @param[out] end Pointer to the variable where the last shared mem
- * address should be put.
- * @return Pointer to the string with shared mem area name.
- */
-const char *get_shared_kmem(struct mm_struct *mm, unsigned long *start,
- unsigned long *end)
-{
- unsigned long vdso;
- struct vm_area_struct *vma_vdso;
-
- vdso = (unsigned long)mm->context.vdso;
- vma_vdso = find_vma_intersection(mm, vdso, vdso + 1);
-
- if (vma_vdso == NULL) {
- print_err("Cannot get VDSO mapping\n");
- return NULL;
- }
-
- *start = vma_vdso->vm_start;
- *end = vma_vdso->vm_end;
-
- return "[vdso]";
-}
--- /dev/null
+/*
+ * 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, 2015
+ *
+ * 2015 Vyacheslav Cherkashin <v.cherkashin@samsung.com>
+ *
+ */
+
+
+#include <linux/slab.h>
+#include <linux/sched.h>
+#include <linux/ctype.h>
+#include <linux/errno.h>
+#include <linux/atomic.h>
+#include <buffer/swap_buffer_module.h>
+#include <swap-asm/swap_kprobes.h>
+#include <swap-asm/swap_uprobes.h>
+#include "swap_msg.h"
+
+
+#define MSG_PREFIX KERN_INFO "[SWAP_MSG] "
+
+
+struct swap_msg {
+ u32 msg_id;
+ u32 seq_num;
+ u64 time;
+ u32 len;
+ char payload[0];
+} __packed;
+
+
+static char *cpu_buf[NR_CPUS];
+static atomic_t seq_num = ATOMIC_INIT(-1);
+static atomic_t discarded = ATOMIC_INIT(0);
+
+
+int swap_msg_init(void)
+{
+ size_t i;
+ const size_t end = ((size_t) 0) - 1;
+
+ for (i = 0; i < NR_CPUS; ++i) {
+ cpu_buf[i] = kmalloc(SWAP_MSG_BUF_SIZE, GFP_KERNEL);
+ if (cpu_buf[i] == NULL)
+ goto no_mem;
+ }
+
+ return 0;
+
+no_mem:
+ --i;
+ for (; i != end; --i)
+ kfree(cpu_buf[i]);
+
+ return -ENOMEM;
+}
+
+void swap_msg_exit(void)
+{
+ int i;
+
+ for (i = 0; i < NR_CPUS; ++i)
+ kfree(cpu_buf[i]);
+}
+
+void swap_msg_seq_num_reset(void)
+{
+ atomic_set(&seq_num, -1);
+}
+EXPORT_SYMBOL_GPL(swap_msg_seq_num_reset);
+
+void swap_msg_discard_reset(void)
+{
+ atomic_set(&discarded, 0);
+}
+EXPORT_SYMBOL_GPL(swap_msg_discard_reset);
+
+int swap_msg_discard_get(void)
+{
+ return atomic_read(&discarded);
+}
+EXPORT_SYMBOL_GPL(swap_msg_discard_get);
+
+
+u64 swap_msg_timespec2time(struct timespec *ts)
+{
+ return ((u64)ts->tv_nsec) << 32 | ts->tv_sec;
+}
+
+
+
+
+
+struct swap_msg *swap_msg_get(enum swap_msg_id id)
+{
+ struct timespec ts;
+ struct swap_msg *m;
+
+ getnstimeofday(&ts);
+
+ m = (struct swap_msg *)cpu_buf[get_cpu()];
+
+ m->msg_id = (u32)id;
+ m->seq_num = atomic_inc_return(&seq_num);
+ m->time = swap_msg_spec2time(&ts);
+
+ return m;
+}
+EXPORT_SYMBOL_GPL(swap_msg_get);
+
+int swap_msg_flush(struct swap_msg *m, size_t size)
+{
+ if (unlikely(size >= SWAP_MSG_PAYLOAD_SIZE))
+ return -ENOMEM;
+
+ m->len = size;
+
+ if (swap_buffer_write(m, SWAP_MSG_PRIV_DATA + size)) {
+ atomic_inc(&discarded);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(swap_msg_flush);
+
+void swap_msg_put(struct swap_msg *m)
+{
+ put_cpu();
+}
+EXPORT_SYMBOL_GPL(swap_msg_put);
+
+
+
+
+
+
+static unsigned long get_arg(struct pt_regs *regs, unsigned long n)
+{
+ return user_mode(regs) ?
+ swap_get_uarg(regs, n) : /* US argument */
+ swap_get_sarg(regs, n); /* sys_call argument */
+}
+
+int swap_msg_pack_args(char *buf, int len,
+ const char *fmt, struct pt_regs *regs)
+{
+ char *buf_old = buf;
+ u32 *tmp_u32;
+ u64 *tmp_u64;
+ int i, /* the index of the argument */
+ fmt_i, /* format index */
+ fmt_len; /* the number of parameters, in format */
+
+ fmt_len = strlen(fmt);
+
+ for (i = 0, fmt_i = 0; fmt_i < fmt_len; ++i, ++fmt_i) {
+ if (len < 2)
+ return -ENOMEM;
+
+ *buf = fmt[fmt_i];
+ buf += 1;
+ len -= 1;
+
+ switch (fmt[fmt_i]) {
+ case 'b': /* 1 byte(bool) */
+ if (len < 1)
+ return -ENOMEM;
+ *buf = (char)!!get_arg(regs, i);
+ buf += 1;
+ len -= 1;
+ break;
+ case 'c': /* 1 byte(char) */
+ if (len < 1)
+ return -ENOMEM;
+ *buf = (char)get_arg(regs, i);
+ buf += 1;
+ len -= 1;
+ break;
+ case 'f': /* 4 byte(float) */
+ case 'd': /* 4 byte(int) */
+ if (len < 4)
+ return -ENOMEM;
+ tmp_u32 = (u32 *)buf;
+ *tmp_u32 = (u32)get_arg(regs, i);
+ buf += 4;
+ len -= 4;
+ break;
+ case 'x': /* 8 byte(long) */
+ case 'p': /* 8 byte(pointer) */
+ if (len < 8)
+ return -ENOMEM;
+ tmp_u64 = (u64 *)buf;
+ *tmp_u64 = (u64)get_arg(regs, i);
+ buf += 8;
+ len -= 8;
+ break;
+ case 'w': /* 8 byte(double) */
+ if (len < 8)
+ return -ENOMEM;
+ tmp_u64 = (u64 *)buf;
+ *tmp_u64 = get_arg(regs, i);
+ ++i;
+ *tmp_u64 |= (u64)get_arg(regs, i) << 32;
+ buf += 8;
+ len -= 8;
+ break;
+ case 's': /* string end with '\0' */
+ {
+ enum { max_str_len = 512 };
+ const char __user *user_s;
+ int len_s, ret;
+
+ user_s = (const char __user *)get_arg(regs, i);
+ len_s = strnlen_user(user_s, max_str_len);
+ if (len < len_s)
+ return -ENOMEM;
+
+ ret = strncpy_from_user(buf, user_s, len_s);
+ if (ret < 0)
+ return -EFAULT;
+
+ buf[ret] = '\0';
+
+ buf += ret + 1;
+ len -= ret + 1;
+ }
+ break;
+ default:
+ return -EINVAL;
+ }
+ }
+
+ return buf - buf_old;
+}
+EXPORT_SYMBOL_GPL(swap_msg_pack_args);
+
+int swap_msg_pack_ret_val(char *buf, int len,
+ char ret_type, struct pt_regs *regs)
+{
+ const char *buf_old = buf;
+ u32 *tmp_u32;
+ u64 *tmp_u64;
+
+ *buf = ret_type;
+ ++buf;
+
+ switch (ret_type) {
+ case 'b': /* 1 byte(bool) */
+ if (len < 1)
+ return -ENOMEM;
+ *buf = (char)!!regs_return_value(regs);
+ ++buf;
+ break;
+ case 'c': /* 1 byte(char) */
+ if (len < 1)
+ return -ENOMEM;
+ *buf = (char)regs_return_value(regs);
+ ++buf;
+ break;
+ case 'd': /* 4 byte(int) */
+ if (len < 4)
+ return -ENOMEM;
+ tmp_u32 = (u32 *)buf;
+ *tmp_u32 = regs_return_value(regs);
+ buf += 4;
+ break;
+ case 'x': /* 8 byte(long) */
+ case 'p': /* 8 byte(pointer) */
+ if (len < 8)
+ return -ENOMEM;
+ tmp_u64 = (u64 *)buf;
+ *tmp_u64 = (u64)regs_return_value(regs);
+ buf += 8;
+ break;
+ case 's': /* string end with '\0' */
+ {
+ enum { max_str_len = 512 };
+ const char __user *user_s;
+ int len_s, ret;
+
+ user_s = (const char __user *)regs_return_value(regs);
+ len_s = strnlen_user(user_s, max_str_len);
+ if (len < len_s)
+ return -ENOMEM;
+
+ ret = strncpy_from_user(buf, user_s, len_s);
+ if (ret < 0)
+ return -EFAULT;
+
+ buf[ret] = '\0';
+ buf += ret + 1;
+ }
+ break;
+ case 'n':
+ case 'v':
+ break;
+ case 'f': /* 4 byte(float) */
+ if (len < 4)
+ return -ENOMEM;
+ tmp_u32 = (u32 *)buf;
+ *tmp_u32 = swap_get_urp_float(regs);
+ buf += 4;
+ break;
+ case 'w': /* 8 byte(double) */
+ if (len < 8)
+ return -ENOMEM;
+ tmp_u64 = (u64 *)buf;
+ *tmp_u64 = swap_get_urp_double(regs);
+ buf += 8;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return buf - buf_old;
+}
+EXPORT_SYMBOL_GPL(swap_msg_pack_ret_val);
+
+
+
+
+
+int swap_msg_raw(void *data, size_t size)
+{
+ struct swap_msg *m = (struct swap_msg *)data;
+
+ if (sizeof(*m) > size) {
+ printk(MSG_PREFIX "ERROR: message RAW small size=%u\n", size);
+ return -EINVAL;
+ }
+
+ if (m->len + sizeof(*m) != size) {
+ printk(MSG_PREFIX "ERROR: message RAW wrong format\n");
+ return -EINVAL;
+ }
+
+ m->seq_num = atomic_inc_return(&seq_num);
+
+ /* TODO: What should be returned?! When message was discarded. */
+ if (swap_buffer_write(m, size))
+ atomic_inc(&discarded);
+
+ return size;
+}
+EXPORT_SYMBOL_GPL(swap_msg_raw);
+
+void swap_msg_error(const char *fmt, ...)
+{
+ int ret;
+ struct swap_msg *m;
+ void *p;
+ size_t size;
+ va_list args;
+
+ m = swap_msg_get(MSG_ERROR);
+ p = swap_msg_payload(m);
+ size = swap_msg_size(m);
+
+ va_start(args, fmt);
+ ret = vsnprintf(p, size, fmt, args);
+ va_end(args);
+
+ if (ret <= 0) {
+ printk(MSG_PREFIX "ERROR: msg error packing, ret=%d\n", ret);
+ goto put_msg;
+ }
+
+ swap_msg_flush(m, ret + 1);
+
+put_msg:
+ swap_msg_put(m);
+}
+EXPORT_SYMBOL_GPL(swap_msg_error);
--- /dev/null
+/*
+ * 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, 2015
+ *
+ * 2015 Vyacheslav Cherkashin <v.cherkashin@samsung.com>
+ *
+ */
+
+
+#ifndef _SWAP_MSG_H
+#define _SWAP_MSG_H
+
+
+#include <linux/time.h>
+#include <linux/types.h>
+
+
+enum swap_msg_id {
+ MSG_PROC_INFO = 0x0001,
+ MSG_TERMINATE = 0x0002,
+ MSG_ERROR = 0x0003,
+ MSG_SAMPLE = 0x0004,
+ MSG_FUNCTION_ENTRY = 0x0008,
+ MSG_FUNCTION_EXIT = 0x0009,
+ MSG_SYSCALL_ENTRY = 0x000a,
+ MSG_SYSCALL_EXIT = 0x000b,
+ MSG_FILE_FUNCTION_ENTRY = 0x000c,
+ MSG_FILE_FUNCTION_EXIT = 0x000d,
+ MSG_CONTEXT_SWITCH_ENTRY = 0x0010,
+ MSG_CONTEXT_SWITCH_EXIT = 0x0011,
+ MSG_PROC_MAP = 0x0012,
+ MSG_PROC_UNMAP = 0x0013,
+ MSG_PROC_COMM = 0x0014,
+ MSG_WEB_FUNCTION_ENTRY = 0x0015,
+ MSG_WEB_FUNCTION_EXIT = 0x0016
+};
+
+enum {
+ SWAP_MSG_PRIV_DATA = 20,
+ SWAP_MSG_BUF_SIZE = 32 * 1024,
+ SWAP_MSG_PAYLOAD_SIZE = SWAP_MSG_BUF_SIZE - SWAP_MSG_PRIV_DATA
+};
+
+
+struct swap_msg;
+
+
+static inline u64 swap_msg_spec2time(struct timespec *ts)
+{
+ return ((u64)ts->tv_nsec) << 32 | ts->tv_sec;
+}
+
+struct swap_msg *swap_msg_get(enum swap_msg_id id);
+int swap_msg_flush(struct swap_msg *m, size_t size);
+void swap_msg_put(struct swap_msg *m);
+
+static inline void *swap_msg_payload(struct swap_msg *m)
+{
+ return (void *)m + SWAP_MSG_PRIV_DATA;
+}
+
+static inline size_t swap_msg_size(struct swap_msg *m)
+{
+ return (size_t)SWAP_MSG_PAYLOAD_SIZE;
+}
+
+
+int swap_msg_pack_args(char *buf, int len,
+ const char *fmt, struct pt_regs *regs);
+int swap_msg_pack_ret_val(char *buf, int len,
+ char ret_type, struct pt_regs *regs);
+
+
+int swap_msg_raw(void *buf, size_t size);
+void swap_msg_error(const char *fmt, ...);
+
+void swap_msg_seq_num_reset(void);
+void swap_msg_discard_reset(void);
+int swap_msg_discard_get(void);
+
+int swap_msg_init(void);
+void swap_msg_exit(void);
+
+
+#endif /* _SWAP_MSG_H */
* Packing and writing data.
*/
-#include <linux/types.h>
-#include <linux/ctype.h>
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/dcache.h>
-#include <linux/mm.h>
-#include <linux/mm_types.h>
-#include <linux/fs.h>
-#include <linux/err.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-
-#include <asm/uaccess.h>
+#include <linux/module.h>
#include <master/swap_initializer.h>
-#include <buffer/swap_buffer_module.h>
-#include <buffer/swap_buffer_errors.h>
-
-#include <swap-asm/swap_kprobes.h>
-#include <swap-asm/swap_uprobes.h>
-
-#include "swap_writer_module.h"
-#include "swap_writer_errors.h"
-#include "kernel_operations.h"
-#include "debugfs_writer.h"
+#include "swap_msg.h"
#include "event_filter.h"
+#include "debugfs_writer.h"
-/**
- * @enum MSG_ID
- * @brief Supported message IDs.
- */
-enum MSG_ID {
- MSG_PROC_INFO = 0x0001, /**< Process info */
- MSG_TERMINATE = 0x0002, /**< Terminate */
- MSG_ERROR = 0x0003, /**< Error */
- MSG_SAMPLE = 0x0004, /**< Sampler event */
- MSG_FUNCTION_ENTRY = 0x0008, /**< Function entry */
- MSG_FUNCTION_EXIT = 0x0009, /**< Function return */
- MSG_CONTEXT_SWITCH_ENTRY = 0x0010, /**< Context switch entry */
- MSG_CONTEXT_SWITCH_EXIT = 0x0011, /**< Context switch exit */
- MSG_PROC_MAP = 0x0012, /**< Process map */
- MSG_PROC_UNMAP = 0x0013, /**< Process unmap */
- MSG_PROC_COMM = 0x0014, /**< Process comm */
- MSG_WEB_FUNCTION_ENTRY = 0x0015, /**< Web function entry */
- MSG_WEB_FUNCTION_EXIT = 0x0016 /**< Web function exit */
-};
-
-static char *cpu_buf[NR_CPUS];
-static u32 seq_num;
-static unsigned int discarded;
-
-/**
- * @brief Initializes new message.
- *
- * @param buf_size Message buffer size.
- * @return Success.
- */
-int init_msg(size_t buf_size)
-{
- int i;
-
- for (i = 0; i < NR_CPUS; ++i)
- cpu_buf[i] = kmalloc(buf_size, GFP_KERNEL);
-
- return E_SW_SUCCESS;
-}
-EXPORT_SYMBOL_GPL(init_msg);
-
-/**
- * @brief Uninitializes message.
- *
- * @return Void.
- */
-void uninit_msg(void)
-{
- int i;
-
- for (i = 0; i < NR_CPUS; ++i)
- kfree(cpu_buf[i]);
-}
-EXPORT_SYMBOL_GPL(uninit_msg);
-
-/**
- * @brief Sets discarded events count to 0.
- *
- * @return Void.
- */
-void reset_discarded(void)
-{
- discarded = 0;
-}
-EXPORT_SYMBOL_GPL(reset_discarded);
-
-/**
- * @brief Sets events sequence number to 0.
- *
- * @return Void.
- */
-void reset_seq_num(void)
-{
- seq_num = 0;
-}
-EXPORT_SYMBOL_GPL(reset_seq_num);
-
-/**
- * @brief Gets discarded events count.
- *
- * @return Discarded events count.
- */
-unsigned int get_discarded_count(void)
-{
- return discarded;
-}
-EXPORT_SYMBOL_GPL(get_discarded_count);
-
-static inline char *get_current_buf(void)
-{
- return cpu_buf[get_cpu()];
-}
-
-static inline void put_current_buf(void)
-{
- put_cpu();
-}
-
-static inline u64 timespec2time(struct timespec *ts)
-{
- return ((u64)ts->tv_nsec) << 32 | ts->tv_sec;
-}
-
-/* ============================================================================
- * = BASIC MESSAGE FORMAT =
- * ============================================================================
- */
-
-/**
- * @struct basic_msg_fmt
- * @brief Basic message.
- */
-struct basic_msg_fmt {
- u32 msg_id; /**< Message ID */
- u32 seq_number; /**< Sequence number */
- u64 time; /**< Message time */
- u32 len; /**< Message length */
- char payload[0]; /**< Message itself */
-} __packed;
-
-#if 0 /* debug */
-static void print_hex(char *ptr, int len)
-{
- int i;
-
- printk(KERN_INFO "print_hex:\n");
- for (i = 0; i < len; ++i)
- printk(KERN_INFO "[%x] [%3d]=%2x\n", &ptr[i], i, ptr[i]);
-}
-#endif
-
-static int write_to_buffer(void *data)
-{
- int result;
- struct basic_msg_fmt *bmf = (struct basic_msg_fmt *)data;
-
- result = swap_buffer_write(bmf, bmf->len + sizeof(*bmf));
- if (result < 0)
- discarded++;
-
- return result;
-}
-
-static void set_len_msg(char *buf, char *end)
-{
- struct basic_msg_fmt *bmf = (struct basic_msg_fmt *)buf;
- bmf->len = end - buf - sizeof(*bmf);
-}
-
-static inline void set_seq_num(struct basic_msg_fmt *bmf)
-{
- bmf->seq_number = seq_num;
- seq_num++;
-}
-
-static inline void set_time(struct basic_msg_fmt *bmf)
-{
- struct timespec ts;
-
- getnstimeofday(&ts);
- bmf->time = timespec2time(&ts);
-}
-
-static char *pack_basic_msg_fmt(char *buf, enum MSG_ID id)
-{
- struct basic_msg_fmt *bmf = (struct basic_msg_fmt *)buf;
-
- set_time(bmf);
- set_seq_num(bmf);
- bmf->msg_id = id;
-
- return bmf->payload;
-}
-
-
-
-
-
-/* ============================================================================
- * = PROCESS INFO =
- * ============================================================================
- */
-
-/**
- * @struct proc_info_top
- * @brief Top proc info part.
- */
-struct proc_info_top {
- u32 pid; /**< Process PID */
- char comm[0]; /**< Message */
-} __packed;
-
-/**
- * @struct proc_info_bottom
- * @brief Bottom proc info part.
- */
-struct proc_info_bottom {
- u32 ppid; /**< Parent PID */
- u32 start_sec; /**< Start time sec */
- u32 start_nsec; /**< Start time nsec */
- u64 low_addr; /**< Low address */
- u64 high_addr; /**< High address */
- char bin_path[0]; /**< Binary path */
-} __packed;
-
-/**
- * @struct proc_info_part
- * @brief Process info part.
- */
-struct proc_info_part {
- u32 lib_cnt; /**< Library count */
- char libs[0]; /**< Libraries */
-} __packed;
-
-/**
- * @struct lib_obj
- * @brief Library object.
- */
-struct lib_obj {
- u64 low_addr; /**< Low library address */
- u64 high_addr; /**< High library address */
- char lib_path[0]; /**< Library path */
-} __packed;
-
-static char *pack_path(char *buf, struct file *file)
-{
- enum { TMP_BUF_LEN = 512 };
- char tmp_buf[TMP_BUF_LEN];
- char NA[] = "N/A";
- char *filename;
- size_t len;
-
- if (file == NULL)
- return strcpy(buf, NA) + sizeof(NA);
-
- filename = d_path(&file->f_path, tmp_buf, TMP_BUF_LEN);
- if (IS_ERR_OR_NULL(filename))
- return strcpy(buf, NA) + sizeof(NA);
-
- len = strlen(filename) + 1;
- memcpy(buf, filename, len);
-
- return buf + len;
-}
-
-static char *pack_lib_obj(char *lib_obj, struct vm_area_struct *vma)
-{
- struct lib_obj *lo = (struct lib_obj *)lib_obj;
-
- lo->low_addr = vma->vm_start;
- lo->high_addr = vma->vm_end;
-
- return pack_path(lo->lib_path, vma->vm_file);
-}
-
-/* FIXME: check_vma()*/
-static int check_vma(struct vm_area_struct *vma)
-{
- return vma->vm_file &&
- !(vma->vm_pgoff != 0 ||
- !(vma->vm_flags & VM_EXEC) ||
- !(vma->vm_flags & (VM_READ | VM_MAYREAD)));
-}
-
-static struct vm_area_struct *find_vma_exe_by_dentry(struct mm_struct *mm,
- struct dentry *dentry)
-{
- struct vm_area_struct *vma;
-
- for (vma = mm->mmap; vma; vma = vma->vm_next) {
- if (vma->vm_file && (vma->vm_flags & VM_EXEC) &&
- (vma->vm_file->f_dentry == dentry))
- goto out;
- }
-
- vma = NULL;
-out:
-
- return vma;
-}
-
-static char *pack_shared_kmem(char *lib_obj,
- struct mm_struct *mm,
- u32 *lib_cnt_p)
-{
- struct lib_obj *so = (struct lib_obj *)lib_obj;
- char *so_obj;
- unsigned long start = 0, end = 0;
-
- const char *kmem_name = get_shared_kmem(mm, &start, &end);
- size_t name_len;
-
- if (kmem_name == NULL)
- return lib_obj;
-
- name_len = strlen(kmem_name) + 1;
- so->low_addr = (u64)start;
- so->high_addr = (u64)end;
- memcpy(so->lib_path, kmem_name, name_len);
- (*lib_cnt_p)++;
- so_obj = so->lib_path + name_len;
-
- return so_obj;
-}
-
-static char *pack_libs(char *lib_obj, struct mm_struct *mm, u32 *lib_cnt_p)
-{
- struct vm_area_struct *vma;
-
- for (vma = mm->mmap; vma; vma = vma->vm_next) {
- if (check_vma(vma)) {
- lib_obj = pack_lib_obj(lib_obj, vma);
- ++(*lib_cnt_p);
- }
- }
-
- return lib_obj;
-}
-
-static char *pack_proc_info_part(char *end_path, struct mm_struct *mm)
-{
- struct proc_info_part *pip;
- char *lib_obj;
- u32 *lib_cnt_p;
-
- pip = (struct proc_info_part *)end_path;
- pip->lib_cnt = 0;
- lib_obj = pip->libs;
- lib_cnt_p = &pip->lib_cnt;
-
- lib_obj = pack_libs(lib_obj, mm, lib_cnt_p);
- lib_obj = pack_shared_kmem(lib_obj, mm, lib_cnt_p);
-
- return lib_obj;
-}
-
-static char *pack_comm(char *buf, struct task_struct *task)
-{
- get_task_comm(buf, task);
-
- return buf + strlen(buf) + 1;
-}
-
-static char *pack_proc_info_top(char *data, struct task_struct *task)
-{
- struct proc_info_top *pit = (struct proc_info_top *)data;
-
- pit->pid = task->tgid;
-
- return pack_comm(pit->comm, task);
-}
-
-static char *pack_proc_info_bottom(char *data, struct task_struct *task,
- struct dentry *dentry)
-{
- struct proc_info_bottom *pib = (struct proc_info_bottom *)data;
- struct vm_area_struct *vma = find_vma_exe_by_dentry(task->mm, dentry);
- struct timespec boot_time;
- struct timespec start_time;
- char *end_path = NULL;
-
- getboottime(&boot_time);
- start_time = timespec_add(boot_time, task->real_start_time);
-
- pib->ppid = task->real_parent->tgid;
- pib->start_sec = (u32)start_time.tv_sec;
- pib->start_nsec = (u32)start_time.tv_nsec;
-
- if (vma) {
- pib->low_addr = vma->vm_start;
- pib->high_addr = vma->vm_end;
- end_path = pack_path(pib->bin_path, vma->vm_file);
- } else {
- pib->low_addr = 0;
- pib->high_addr = 0;
- end_path = pack_path(pib->bin_path, NULL);
- }
- return pack_proc_info_part(end_path, task->mm);
-}
-
-static char *pack_proc_info(char *payload, struct task_struct *task,
- struct dentry *dentry)
-{
- payload = pack_proc_info_top(payload, task);
- return pack_proc_info_bottom(payload, task, dentry);
-}
-
-/**
- * @brief Packs and writes process info message. Called with
- * down\up\_read(&task->mm->mmap_sem).
- *
- * @param task Pointer to the target task_struct.
- * @param dentry Pointer to the task dentry.
- * @return Written data size on success, negative error code on error.
- */
-int proc_info_msg(struct task_struct *task, struct dentry *dentry)
+static int core_init(void)
{
- char *buf, *payload, *buf_end;
int ret;
- buf = get_current_buf();
- payload = pack_basic_msg_fmt(buf, MSG_PROC_INFO);
- buf_end = pack_proc_info(payload, task, dentry);
-
- set_len_msg(buf, buf_end);
+ ret = swap_msg_init();
+ if (ret)
+ return ret;
- ret = write_to_buffer(buf);
- put_current_buf();
+ ret = event_filter_init();
+ if (ret)
+ swap_msg_exit();
return ret;
}
-EXPORT_SYMBOL_GPL(proc_info_msg);
-
-
-
-
-
-/* ============================================================================
- * = PROCESS TERMINATE =
- * ============================================================================
- */
-
-/**
- * @struct proc_terminate
- * @brief Terminate message struct.
- */
-struct proc_terminate {
- u32 pid; /**< Process ID */
-} __packed;
-
-static char *pack_proc_terminate(char *payload, struct task_struct *task)
-{
- struct proc_terminate *pt = (struct proc_terminate *)payload;
-
- pt->pid = task->pid;
- return payload + sizeof(*pt);
-}
-
-/**
- * @brief Packs and writes terminate message.
- *
- * @param task Target task_struct.
- * @return Void.
- */
-void terminate_msg(struct task_struct *task)
-{
- char *buf, *payload, *buf_end;
-
- buf = get_current_buf();
- payload = pack_basic_msg_fmt(buf, MSG_TERMINATE);
- buf_end = pack_proc_terminate(payload, task);
-
- set_len_msg(buf, buf_end);
-
- write_to_buffer(buf);
- put_current_buf();
-}
-EXPORT_SYMBOL_GPL(terminate_msg);
-
-
-
-
-
-/* ============================================================================
- * = PROCESS MAP =
- * ============================================================================
- */
-
-/**
- * @struct proc_map
- * @brief Process mapping info.
- */
-struct proc_map {
- u32 pid; /**< Process ID */
- u64 low_addr; /**< Low address */
- u64 high_addr; /**< High address */
- char bin_path[0]; /**< Binary path */
-} __packed;
-
-static char *pack_proc_map(char *payload, struct vm_area_struct *vma)
-{
- struct proc_map *pm = (struct proc_map *)payload;
-
- pm->pid = current->tgid;
- pm->low_addr = vma->vm_start;
- pm->high_addr = vma->vm_end;
-
- return pack_path(pm->bin_path, vma->vm_file);
-}
-
-/**
- * @brief Packs and writes process map message.
- *
- * @param vma Target memory area.
- * @return Void.
- */
-void pcoc_map_msg(struct vm_area_struct *vma)
-{
- char *buf, *payload, *buf_end;
-
- buf = get_current_buf();
- payload = pack_basic_msg_fmt(buf, MSG_PROC_MAP);
- buf_end = pack_proc_map(payload, vma);
-
- set_len_msg(buf, buf_end);
-
- write_to_buffer(buf);
- put_current_buf();
-}
-EXPORT_SYMBOL_GPL(pcoc_map_msg);
-
-
-
-
-
-/* ============================================================================
- * = PROCESS UNMAP =
- * ============================================================================
- */
-
-/**
- * @struct proc_unmap
- * @brief Process mapping info.
- */
-struct proc_unmap {
- u32 pid; /**< Process ID */
- u64 low_addr; /**< Low address */
- u64 high_addr; /**< High address */
-} __packed;
-
-static char *pack_proc_unmap(char *payload, unsigned long start,
- unsigned long end)
-{
- struct proc_unmap *pum = (struct proc_unmap *)payload;
-
- pum->pid = current->tgid;
- pum->low_addr = start;
- pum->high_addr = end;
-
- return payload + sizeof(*pum);
-}
-
-/**
- * @brief Packs and writes process unmap message.
- *
- * @param start Unmapping area low address.
- * @param end Unmapping area high address.
- * @return Void.
- */
-void proc_unmap_msg(unsigned long start, unsigned long end)
-{
- char *buf, *payload, *buf_end;
-
- buf = get_current_buf();
- payload = pack_basic_msg_fmt(buf, MSG_PROC_UNMAP);
- buf_end = pack_proc_unmap(payload, start, end);
-
- set_len_msg(buf, buf_end);
-
- write_to_buffer(buf);
- put_current_buf();
-}
-EXPORT_SYMBOL_GPL(proc_unmap_msg);
-
-
-
-
-
-/* ============================================================================
- * = PROCESS COMM =
- * ============================================================================
- */
-
-/**
- * @struct proc_comm
- * @brief Comm message info.
- */
-struct proc_comm {
- u32 pid; /**< Process ID */
- char comm[0]; /**< Comm */
-} __packed;
-
-static char *pack_proc_comm(char *data, struct task_struct *task)
-{
- struct proc_comm *pcomm = (struct proc_comm *)data;
-
- pcomm->pid = task->tgid;
-
- return pack_comm(pcomm->comm, task);
-}
-/**
- * @brief Packs and writes process comm message.
- *
- * @param task Target task_struct.
- * @return Void.
- */
-void proc_comm_msg(struct task_struct *task)
+static void core_exit(void)
{
- char *buf, *payload, *buf_end;
-
- buf = get_current_buf();
- payload = pack_basic_msg_fmt(buf, MSG_PROC_COMM);
- buf_end = pack_proc_comm(payload, task);
-
- set_len_msg(buf, buf_end);
-
- write_to_buffer(buf);
- put_current_buf();
+ event_filter_exit();
+ swap_msg_exit();
}
-EXPORT_SYMBOL_GPL(proc_comm_msg);
-
-
-
-
-
-/* ============================================================================
- * = SAMPLE =
- * ============================================================================
- */
-
-/**
- * @struct sample
- * @brief Sampler event info.
- */
-struct sample {
- u32 pid; /**< Process ID */
- u64 pc_addr; /**< Instruction pointer address */
- u32 tid; /**< Thread ID */
- u32 cpu_num; /**< CPU number */
-} __packed;
-
-static char *pack_sample(char *payload, struct pt_regs *regs)
-{
- struct sample *s = (struct sample *)payload;
- struct task_struct *task = current;
-
- s->pid = task->tgid;
- s->pc_addr = get_regs_ip(regs);
- s->tid = task->pid;
- s->cpu_num = smp_processor_id();
-
- return payload + sizeof(*s);
-}
-
-/**
- * @brief Packs and writes sample message.
- *
- * @param regs Pointer to CPU register data.
- * @return Written data size on success, negative error code on error.
- */
-int sample_msg(struct pt_regs *regs)
-{
- char *buf, *payload, *buf_end;
- int ret;
-
- buf = get_current_buf();
- payload = pack_basic_msg_fmt(buf, MSG_SAMPLE);
- buf_end = pack_sample(payload, regs);
-
- set_len_msg(buf, buf_end);
-
- ret = write_to_buffer(buf);
- put_current_buf();
-
- return ret;
-}
-EXPORT_SYMBOL_GPL(sample_msg);
-
-
-
-
-/* ============================================================================
- * = ENTRY =
- * ============================================================================
- */
-
-/**
- * @struct msg_func_entry
- * @brief Entry event info.
- */
-struct msg_func_entry {
- u32 pid; /**< Process ID */
- u32 tid; /**< Thread ID */
- u16 probe_type; /**< Probe type */
- u16 probe_sub_type; /**< Probe subtype */
- u64 pc_addr; /**< Instruction pointer address. */
- u64 caller_pc_addr; /**< Return address */
- u32 cpu_num; /**< CPU number */
- u32 cnt_args; /**< Count of args */
- char args[0]; /**< Args format string */
-} __packed;
-
-static char *pack_msg_func_entry(char *payload, const char *fmt,
- unsigned long func_addr, struct pt_regs *regs,
- enum PROBE_TYPE pt, int sub_type)
-{
- struct msg_func_entry *mfe = (struct msg_func_entry *)payload;
- struct task_struct *task = current;
-
- mfe->pid = task->tgid;
- mfe->tid = task->pid;
- mfe->cpu_num = smp_processor_id();
- mfe->pc_addr = func_addr;
- mfe->caller_pc_addr = get_regs_ret_func(regs);
- mfe->probe_type = pt;
- mfe->probe_sub_type = sub_type;
- mfe->cnt_args = strlen(fmt);
-
- return payload + sizeof(*mfe);
-}
-
-static unsigned long get_arg(struct pt_regs *regs, unsigned long n)
-{
- return user_mode(regs) ?
- swap_get_uarg(regs, n) : /* US argument */
- swap_get_sarg(regs, n); /* sys_call argument */
-}
-
-static int pack_args(char *buf, int len, const char *fmt, struct pt_regs *regs)
-{
- char *buf_old = buf;
- u32 *tmp_u32;
- u64 *tmp_u64;
- int i, /* the index of the argument */
- fmt_i, /* format index */
- fmt_len; /* the number of parameters, in format */
-
- fmt_len = strlen(fmt);
-
- for (i = 0, fmt_i = 0; fmt_i < fmt_len; ++i, ++fmt_i) {
- if (len < 2)
- return -ENOMEM;
-
- *buf = fmt[fmt_i];
- buf += 1;
- len -= 1;
-
- switch (fmt[fmt_i]) {
- case 'b': /* 1 byte(bool) */
- *buf = (char)!!get_arg(regs, i);
- buf += 1;
- len -= 1;
- break;
- case 'c': /* 1 byte(char) */
- *buf = (char)get_arg(regs, i);
- buf += 1;
- len -= 1;
- break;
- case 'f': /* 4 byte(float) */
- case 'd': /* 4 byte(int) */
- if (len < 4)
- return -ENOMEM;
- tmp_u32 = (u32 *)buf;
- *tmp_u32 = (u32)get_arg(regs, i);
- buf += 4;
- len -= 4;
- break;
- case 'x': /* 8 byte(long) */
- case 'p': /* 8 byte(pointer) */
- if (len < 8)
- return -ENOMEM;
- tmp_u64 = (u64 *)buf;
- *tmp_u64 = (u64)get_arg(regs, i);
- buf += 8;
- len -= 8;
- break;
- case 'w': /* 8 byte(double) */
- if (len < 8)
- return -ENOMEM;
- tmp_u64 = (u64 *)buf;
- *tmp_u64 = get_arg(regs, i);
- ++i;
- *tmp_u64 |= (u64)get_arg(regs, i) << 32;
- buf += 8;
- len -= 8;
- break;
- case 's': /* string end with '\0' */
- {
- enum { max_str_len = 512 };
- const char __user *user_s;
- int len_s, ret;
-
- user_s = (const char __user *)get_arg(regs, i);
- len_s = strnlen_user(user_s, max_str_len);
- if (len < len_s)
- return -ENOMEM;
-
- ret = strncpy_from_user(buf, user_s, len_s);
- if (ret < 0)
- return -EFAULT;
-
- buf[ret] = '\0';
-
- buf += ret + 1;
- len -= ret + 1;
- }
- break;
- default:
- return -EINVAL;
- }
- }
-
- return buf - buf_old;
-}
-
-/**
- * @brief Packs and writes entry event message.
- *
- * @param fmt Arguments format string.
- * @param func_addr Function address.
- * @param regs CPU register data.
- * @param pt Probe type.
- * @param sub_type Probe sub type.
- * @return Written data size on success, negative error code on error.
- */
-int entry_event(const char *fmt, unsigned long func_addr, struct pt_regs *regs,
- enum PROBE_TYPE pt, int sub_type)
-{
- char *buf, *payload, *args, *buf_end;
- int ret;
-
- buf = get_current_buf();
- payload = pack_basic_msg_fmt(buf, MSG_FUNCTION_ENTRY);
- args = pack_msg_func_entry(payload, fmt, func_addr,
- regs, pt, sub_type);
-
- /* FIXME: len = 1024 */
- ret = pack_args(args, 1024, fmt, regs);
- if (ret < 0) {
- printk(KERN_INFO "ERROR: !!!!!\n");
- goto put_buf;
- }
-
- buf_end = args + ret;
-
- set_len_msg(buf, buf_end);
-
- ret = write_to_buffer(buf);
-
-put_buf:
- put_current_buf();
-
- return ret;
-}
-EXPORT_SYMBOL_GPL(entry_event);
-
-
-
-
-
-/* ============================================================================
- * = EXIT =
- * ============================================================================
- */
-
-/**
- * @struct msg_func_exit
- * @brief Exit event message info.
- */
-struct msg_func_exit {
- u32 pid; /**< PID */
- u32 tid; /**< TID */
- u16 probe_type; /**< Probe type */
- u16 probe_sub_type; /**< Probe subtype */
- u64 pc_addr; /**< Instruction pointer */
- u64 caller_pc_addr; /**< Return address */
- u32 cpu_num; /**< CPU number */
- char ret_val[0]; /**< Return value */
-} __packed;
-
-static int pack_msg_ret_val(char *buf, int len, char ret_type,
- struct pt_regs *regs)
-{
- const char *buf_old = buf;
- u32 *tmp_u32;
- u64 *tmp_u64;
-
- *buf = ret_type;
- ++buf;
-
- switch (ret_type) {
- case 'b': /* 1 byte(bool) */
- if (len < 1)
- return -ENOMEM;
- *buf = (char)!!get_regs_ret_val(regs);
- ++buf;
- break;
- case 'c': /* 1 byte(char) */
- if (len < 1)
- return -ENOMEM;
- *buf = (char)get_regs_ret_val(regs);
- ++buf;
- break;
- case 'd': /* 4 byte(int) */
- if (len < 4)
- return -ENOMEM;
- tmp_u32 = (u32 *)buf;
- *tmp_u32 = get_regs_ret_val(regs);
- buf += 4;
- break;
- case 'x': /* 8 byte(long) */
- case 'p': /* 8 byte(pointer) */
- if (len < 8)
- return -ENOMEM;
- tmp_u64 = (u64 *)buf;
- *tmp_u64 = (u64)get_regs_ret_val(regs);
- buf += 8;
- break;
- case 's': /* string end with '\0' */
- {
- enum { max_str_len = 512 };
- const char __user *user_s;
- int len_s, ret;
-
- user_s = (const char __user *)get_regs_ret_val(regs);
- len_s = strnlen_user(user_s, max_str_len);
- if (len < len_s)
- return -ENOMEM;
-
- ret = strncpy_from_user(buf, user_s, len_s);
- if (ret < 0)
- return -EFAULT;
-
- buf[ret] = '\0';
- buf += ret + 1;
- }
- break;
- case 'n':
- case 'v':
- break;
- case 'f': /* 4 byte(float) */
- if (len < 4)
- return -ENOMEM;
- tmp_u32 = (u32 *)buf;
- *tmp_u32 = swap_get_urp_float(regs);
- buf += 4;
- break;
- case 'w': /* 8 byte(double) */
- if (len < 8)
- return -ENOMEM;
- tmp_u64 = (u64 *)buf;
- *tmp_u64 = swap_get_urp_double(regs);
- buf += 8;
- break;
- default:
- return -EINVAL;
- }
-
- return buf - buf_old;
-}
-
-
-static int pack_msg_func_exit(char *buf, int len, char ret_type,
- struct pt_regs *regs, int pt, int sub_type,
- unsigned long func_addr, unsigned long ret_addr)
-{
- struct msg_func_exit *mfe = (struct msg_func_exit *)buf;
- struct task_struct *task = current;
- int ret;
-
- mfe->pid = task->tgid;
- mfe->tid = task->pid;
- mfe->probe_type = pt;
- mfe->probe_sub_type = sub_type;
- mfe->cpu_num = smp_processor_id();
- mfe->pc_addr = func_addr;
- mfe->caller_pc_addr = ret_addr;
-
- ret = pack_msg_ret_val(mfe->ret_val, len, ret_type, regs);
- if (ret < 0) {
- printk(KERN_INFO "ERROR: packing MSG_FUNCTION_EXIT (ret=%d)\n",
- ret);
- return ret;
- }
-
- return sizeof(*mfe) + ret;
-}
-
-/**
- * @brief Packs and writes exit event.
- *
- * @param ret_type Return value type.
- * @param regs CPU register data.
- * @param sub_type Event subtype.
- * @param func_addr Function address.
- * @param ret_addr Return address.
- * @return Written data size on success, negative error code on error.
- */
-int exit_event(char ret_type, struct pt_regs *regs, int pt, int sub_type,
- unsigned long func_addr, unsigned long ret_addr)
-{
- char *buf, *payload, *buf_end;
- int ret;
-
- buf = get_current_buf();
- payload = pack_basic_msg_fmt(buf, MSG_FUNCTION_EXIT);
- /* FIXME: len=1024 */
- ret = pack_msg_func_exit(payload, 1024, ret_type, regs, pt, sub_type,
- func_addr, ret_addr);
- if (ret < 0)
- goto put_buf;
-
- buf_end = payload + ret;
- set_len_msg(buf, buf_end);
-
- ret = write_to_buffer(buf);
-
-put_buf:
- put_current_buf();
-
- return ret;
-}
-EXPORT_SYMBOL_GPL(exit_event);
-
-
-
-
-
-/* ============================================================================
- * = CONTEXT SWITCH =
- * ============================================================================
- */
-
-/*
- * @struct msg_context_switch
- * @brief Context switch message info.
- */
-struct msg_context_switch {
- u64 pc_addr; /**< Instruction pointer */
- u32 pid; /**< PID */
- u32 tid; /**< TID */
- u32 cpu_num; /**< CPU number */
-} __packed;
-
-static char *pack_msg_context_switch(char *payload, struct pt_regs *regs)
-{
- struct msg_context_switch *mcs = (struct msg_context_switch *)payload;
- struct task_struct *task = current;
-
- mcs->pc_addr = 0;
- mcs->pid = task->tgid;
- mcs->tid = task->pid;
- mcs->cpu_num = smp_processor_id();
-
- return payload + sizeof(*mcs);
-}
-
-static int context_switch(struct pt_regs *regs, enum MSG_ID id)
-{
- char *buf, *payload, *buf_end;
- int ret;
-
- buf = get_current_buf();
- payload = pack_basic_msg_fmt(buf, id);
- buf_end = pack_msg_context_switch(payload, regs);
- set_len_msg(buf, buf_end);
-
- ret = write_to_buffer(buf);
- put_current_buf();
-
- return ret;
-}
-
-/**
- * @brief Packs and writes context switch entry message.
- *
- * @param regs CPU register data.
- * @return Written data size on success, negative error code on error.
- */
-int switch_entry(struct pt_regs *regs)
-{
- return context_switch(regs, MSG_CONTEXT_SWITCH_ENTRY);
-}
-EXPORT_SYMBOL_GPL(switch_entry);
-
-/**
- * @brief Packs and writes context switch exit message.
- *
- * @param regs CPU register data.
- * @return Written data size on success, negative error code on error.
- */
-int switch_exit(struct pt_regs *regs)
-{
- return context_switch(regs, MSG_CONTEXT_SWITCH_EXIT);
-}
-EXPORT_SYMBOL_GPL(switch_exit);
-
-
-
-
-/* ============================================================================
- * = ERROR =
- * ============================================================================
- */
-
-/**
- * @struct msg_err
- * @brief Error message info.
- */
-struct msg_err {
- char msg[0]; /**< Error message string */
-} __packed;
-
-static char *pack_msg_err(char *payload, const char *fmt, va_list args)
-{
- struct msg_err *me = (struct msg_err *)payload;
- int ret;
-
- ret = vsprintf(me->msg, fmt, args);
- if (ret < 0)
- return payload;
-
- return payload + sizeof(*me) + ret + 1;
-}
-
-/**
- * @brief Packs and writes error message.
- *
- * @param fmt Error string format
- * @return Written data size on success, negative error code on error.
- */
-int error_msg(const char *fmt, ...)
-{
- char *buf, *payload, *buf_end;
- va_list args;
- int ret;
-
- buf = get_current_buf();
- payload = pack_basic_msg_fmt(buf, MSG_ERROR);
-
- va_start(args, fmt);
- buf_end = pack_msg_err(payload, fmt, args);
- va_end(args);
-
- set_len_msg(buf, buf_end);
-
- ret = write_to_buffer(buf);
- put_current_buf();
-
- return ret;
-}
-EXPORT_SYMBOL_GPL(error_msg);
-
-
-
-
-
-/* ============================================================================
- * = MESSAGES FROM USER SPACE =
- * ============================================================================
- */
-
-/**
- * @brief Interface for writing messages from user space directly.
- *
- * @param buf Pointer to message.
- * @param len Message len.
- * @return len
- */
-int raw_msg(char *buf, size_t len)
-{
- struct basic_msg_fmt *bmf = (struct basic_msg_fmt *)buf;
-
- if (sizeof(*bmf) > len)
- return -EINVAL;
-
- if (bmf->len + sizeof(*bmf) != len)
- return -EINVAL;
-
- set_seq_num(bmf);
- write_to_buffer(buf);
-
- return len;
-}
-
-
-
-/* ============================================================================
- * = CUSTOM EVENT =
- * ============================================================================
- */
-
-static int pack_custom_event(char *buf, int len, const char *fmt, va_list args)
-{
- enum { max_str_len = 512 };
- const char *p;
- char *buf_orig = buf;
-
- for (p = fmt; *p != '\0'; p++) {
- char ch = *p;
-
- if (len < 1)
- return -ENOMEM;
-
- *buf = tolower(ch);
- buf += 1;
- len -= 1;
-
- switch (ch) {
- case 'b': /* 1 byte(bool) */
- if (len < 1)
- return -ENOMEM;
- *buf = !!(char)va_arg(args, int);
- buf += 1;
- len -= 1;
- break;
- case 'c': /* 1 byte(char) */
- if (len < 1)
- return -ENOMEM;
- *buf = (char)va_arg(args, int);
- buf += 1;
- len -= 1;
- break;
- case 'f': /* 4 byte(float) */
- case 'd': /* 4 byte(int) */
- if (len < 4)
- return -ENOMEM;
- *(u32 *)buf = va_arg(args, u32);
- buf += 4;
- len -= 4;
- break;
- case 'x': /* 8 byte(long) */
- case 'w': /* 8 byte(double) */
- if (len < 8)
- return -ENOMEM;
- *(u64 *)buf = va_arg(args, u64);
- buf += 8;
- len -= 8;
- break;
- case 'p': /* 8 byte(pointer) */
- if (len < 8)
- return -ENOMEM;
- *(u64 *)buf = va_arg(args, unsigned long);
- buf += 8;
- len -= 8;
- break;
- case 's': /* userspace string with '\0' terminating byte */
- {
- const char __user *str;
- int len_s, n;
-
- str = va_arg(args, const char __user *);
- /* strnlen_user includes '\0' in its return value */
- len_s = strnlen_user(str, max_str_len);
- if (len < len_s)
- return -ENOMEM;
- /* strncpy_from_user returns the length of the copied
- * string (without '\0') */
- n = strncpy_from_user(buf, str, len_s - 1);
- if (n < 0)
- return n;
- buf[n] = '\0';
-
- buf += n + 1;
- len -= n + 1;
- break;
- }
- case 'S': /* kernelspace string with '\0' terminating byte */
- {
- const char *str;
- int len_s;
-
- str = va_arg(args, const char *);
- len_s = strnlen(str, max_str_len);
- if (len < len_s + 1) /* + '\0' */
- return -ENOMEM;
- strncpy(buf, str, len_s);
- buf[len_s] = '\0';
-
- buf += len_s + 1;
- len -= len_s + 1;
- break;
- }
- case 'a': /* userspace byte array (len + ptr) */
- {
- const void __user *ptr;
- u32 len_p, n;
-
- len_p = va_arg(args, u32);
- if (len < sizeof(len_p) + len_p)
- return -ENOMEM;
- *(u32 *)buf = len_p;
- buf += sizeof(len_p);
- len -= sizeof(len_p);
-
- ptr = va_arg(args, const void __user *);
- n = copy_from_user(buf, ptr, len_p);
- if (n < len_p)
- return -EFAULT;
- buf += len_p;
- len -= len_p;
- break;
- }
- case 'A': /* kernelspace byte array (len + ptr) */
- {
- const void *ptr;
- u32 len_p;
-
- /* array size */
- len_p = va_arg(args, u32);
- if (len < sizeof(len_p) + len_p)
- return -ENOMEM;
- *(u32 *)buf = len_p;
- buf += sizeof(len_p);
- len -= sizeof(len_p);
-
- /* byte array */
- ptr = va_arg(args, const void *);
- memcpy(buf, ptr, len_p);
- buf += len_p;
- len -= len_p;
- break;
- }
- default:
- return -EINVAL;
- }
- }
-
- return buf - buf_orig;
-}
-
-enum { max_custom_event_size = 2048 };
-
-/**
- * @brief Packs and writes custom entry event.
- *
- * @param func_addr Function address.
- * @param regs CPU register data.
- * @param type Probe type.
- * @param sub_type Probe sub type.
- * @param fmt Format string.
- * @return Written data size on success, negative error code on error.
- */
-int custom_entry_event(unsigned long func_addr, struct pt_regs *regs,
- int pt, int sub_type, const char *fmt, ...)
-{
- char *buf, *payload, *args, *buf_end;
- va_list vargs;
- int ret;
-
- buf = get_current_buf();
- payload = pack_basic_msg_fmt(buf, MSG_FUNCTION_ENTRY);
- args = pack_msg_func_entry(payload, fmt, func_addr,
- regs, pt, sub_type);
-
- va_start(vargs, fmt);
- ret = pack_custom_event(args, max_custom_event_size, fmt, vargs);
- va_end(vargs);
-
- if (ret < 0)
- goto put_buf;
-
- buf_end = args + ret;
- set_len_msg(buf, buf_end);
- ret = write_to_buffer(buf);
-
-put_buf:
- put_current_buf();
-
- return ret;
-}
-EXPORT_SYMBOL_GPL(custom_entry_event);
-
-/* TODO currently this function is a simple wrapper. it will be refactored when
- * protocol changes are applied */
-
-/**
- * @brief Packs and writes custom exit event.
- *
- * @param func_addr Function address.
- * @param ret_addr Return address.
- * @param regs CPU register data.
- * @param fmt Format string.
- * @return Written data size on success, negative error code on error.
- */
-int custom_exit_event(unsigned long func_addr, unsigned long ret_addr,
- struct pt_regs *regs, int pt, int sub_type,
- const char *fmt, ...)
-{
- char *buf, *payload, *buf_end;
- int ret;
-
- buf = get_current_buf();
- payload = pack_basic_msg_fmt(buf, MSG_FUNCTION_EXIT);
- ret = pack_msg_func_exit(payload, max_custom_event_size,
- fmt[0], regs, pt, sub_type,
- func_addr, ret_addr);
- if (ret < 0)
- goto put_buf;
-
- buf_end = payload + ret;
- set_len_msg(buf, buf_end);
-
- ret = write_to_buffer(buf);
-
-put_buf:
- put_current_buf();
-
- return ret;
-}
-EXPORT_SYMBOL_GPL(custom_exit_event);
-
-
-
-
-
-/* ============================================================================
- * = WEB APP EVENT =
- * ============================================================================
- */
-
-/* TODO: develop method for obtaining this data during build... */
-/* location: webkit2-efl-123997_0.11.113/Source/WTF/wtf/text/StringImpl.h:70 */
-struct MStringImpl {
- unsigned m_refCount;
- unsigned m_length;
- union {
- const unsigned char *m_data8;
- const unsigned short *m_data16;
- };
- union {
- void *m_buffer;
- struct MStringImpl *m_substringBuffer;
- unsigned short *m_copyData16;
- };
- unsigned m_hashAndFlags;
-};
-
-/* location: webkit2-efl-123997_0.11.113/Source/JavaScriptCore/profiler/
- * CallIdentifier.h:36
- */
-struct MCallIdentifier {
- struct MStringImpl *m_name;
- struct MStringImpl *m_url;
- unsigned m_lineNumber;
-};
-
-int entry_web_event(unsigned long func_addr, struct pt_regs *regs)
-{
- char *buf, *pl;
- long t;
- int ret = 0, n, lnum;
- struct MCallIdentifier *callIdentifier;
- struct {
- const char *str;
- int len;
- } m_name, m_url;
- struct task_struct *task = current;
-
- if (!check_event(current))
- return 0;
-
- callIdentifier = (void *)swap_get_uarg(regs, 2);
-
- if (get_user(t, (int *)&callIdentifier->m_name) ||
- get_user(m_name.str, &((struct MStringImpl *)t)->m_data8) ||
- get_user(m_name.len, &((struct MStringImpl *)t)->m_length) ||
- get_user(t, (int *)&callIdentifier->m_url) ||
- get_user(m_url.str, &((struct MStringImpl *)t)->m_data8) ||
- get_user(m_url.len, &((struct MStringImpl *)t)->m_length) ||
- get_user(lnum, (int *)&callIdentifier->m_lineNumber)) {
- print_err("%s: cannot read user memory\n", __func__);
- return 0;
- }
-
- buf = get_current_buf();
- pl = pack_basic_msg_fmt(buf, MSG_WEB_FUNCTION_ENTRY);
-
- /* Pack message */
- /* PID */
- *(u32 *)pl = task->tgid;
- pl += sizeof(u32);
- /* TID */
- *(u32 *)pl = task->pid;
- pl += sizeof(u32);
- /* Line number (in source file) */
- *(u32 *)pl = lnum;
- pl += sizeof(u32);
- /* Function name */
- n = strncpy_from_user(pl, m_name.str, m_name.len);
- if (n < 0) {
- print_err("%s: cannot read user memory (function name)\n",
- __func__);
- goto put_current_buf_return;
- } else {
- pl[n] = '\0';
- pl += n + 1;
- }
- /* URL (source file) */
- n = strncpy_from_user(pl, m_url.str, m_url.len);
- if (n < 0) {
- print_err("%s: cannot read user memory (url)\n", __func__);
- goto put_current_buf_return;
- } else {
- pl[n] = '\0';
- pl += n + 1;
- }
-
- set_len_msg(buf, pl);
- ret = write_to_buffer(buf);
-
-put_current_buf_return:
- put_current_buf();
- return ret;
-}
-EXPORT_SYMBOL_GPL(entry_web_event);
-
-int exit_web_event(unsigned long func_addr, struct pt_regs *regs)
-{
- char *buf, *pl;
- long t;
- int ret = 0, n;
- struct MCallIdentifier *callIdentifier;
- struct {
- const char *str;
- int len;
- } m_name;
- struct task_struct *task = current;
-
- if (!check_event(current))
- return 0;
-
- callIdentifier = (void *)swap_get_uarg(regs, 2);
-
- if (get_user(t, (int *)&callIdentifier->m_name) ||
- get_user(m_name.str, &((struct MStringImpl *)t)->m_data8) ||
- get_user(m_name.len, &((struct MStringImpl *)t)->m_length)) {
- print_err("%s: cannot read user memory\n", __func__);
- return 0;
- }
-
- buf = get_current_buf();
- pl = pack_basic_msg_fmt(buf, MSG_WEB_FUNCTION_EXIT);
-
- /* Pack message */
- /* PID */
- *(u32 *)pl = task->tgid;
- pl += sizeof(u32);
- /* TID */
- *(u32 *)pl = task->pid;
- pl += sizeof(u32);
- /* Function name */
- n = strncpy_from_user(pl, m_name.str, m_name.len);
- if (n < 0) {
- print_err("%s: cannot read user memory (function name)\n",
- __func__);
- goto put_current_buf_return;
- } else {
- pl[n] = '\0';
- pl += n + 1;
- }
-
- set_len_msg(buf, pl);
- ret = write_to_buffer(buf);
-
-put_current_buf_return:
- put_current_buf();
- return ret;
-}
-EXPORT_SYMBOL_GPL(exit_web_event);
-
-
-
-
-SWAP_LIGHT_INIT_MODULE(NULL, event_filter_init, event_filter_exit,
+SWAP_LIGHT_INIT_MODULE(NULL, core_init, core_exit,
init_debugfs_writer, exit_debugfs_writer);
MODULE_LICENSE("GPL");
+++ /dev/null
-/**
- * @file writer/swap_writer_module.h
- * @author Alexander Aksenov <a.aksenov@samsung.com>
- * @author Vyacheslav Cherkashin
- *
- * @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, 2013
- *
- * @section DESCRIPTION
- *
- * Write module interface defenition.
- */
-
-#ifndef _SWAP_MSG_H
-#define _SWAP_MSG_H
-
-#include <linux/types.h>
-
-/**
- * @enum PROBE_TYPE
- * @brief Probe types.
- */
-enum PROBE_TYPE {
- PT_US = 1, /**< User probe */
- PT_KS = 3 /**< Kernel probe */
-};
-
-/**
- * @enum PROBE_SUB_TYPE
- * @brief Probe sub types.
- */
-enum PROBE_SUB_TYPE {
- PST_NONE = 0x00, /**< Common */
- PST_KS_FILE = 0x01, /**< File feature */
- PST_KS_IPC = 0x02, /**< Ipc feature */
- PST_KS_PROCESS = 0x04, /**< Process feature */
- PST_KS_SIGNAL = 0x08, /**< Signal feature */
- PST_KS_NETWORK = 0x10, /**< Network feature */
- PST_KS_DESC = 0x20 /**< Desc feature */
-};
-
-struct pt_regs;
-struct dentry;
-struct task_struct;
-struct vm_area_struct;
-
-int init_msg(size_t buf_size);
-void uninit_msg(void);
-
-void reset_discarded(void);
-unsigned int get_discarded_count(void);
-void reset_seq_num(void);
-
-int proc_info_msg(struct task_struct *task, struct dentry *dentry);
-void terminate_msg(struct task_struct *task);
-void pcoc_map_msg(struct vm_area_struct *vma);
-void proc_unmap_msg(unsigned long start, unsigned long end);
-void proc_comm_msg(struct task_struct *task);
-int sample_msg(struct pt_regs *regs);
-
-int entry_event(const char *fmt, unsigned long func_addr, struct pt_regs *regs,
- enum PROBE_TYPE pt, int sub_type);
-int exit_event(char ret_type, struct pt_regs *regs, int pt, int sub_type,
- unsigned long func_addr, unsigned long ret_addr);
-
-int entry_web_event(unsigned long func_addr, struct pt_regs *regs);
-int exit_web_event(unsigned long func_addr, struct pt_regs *regs);
-
-int switch_entry(struct pt_regs *regs);
-int switch_exit(struct pt_regs *regs);
-
-int error_msg(const char *fmt, ...);
-
-int raw_msg(char *buf, size_t len);
-
-int custom_entry_event(unsigned long func_addr, struct pt_regs *regs,
- int pt, int sub_type, const char *fmt, ...);
-int custom_exit_event(unsigned long func_addr, unsigned long ret_addr,
- struct pt_regs *regs, int pt, int sub_type,
- const char *fmt, ...);
-
-#endif /* _SWAP_MSG_H */