-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/dcache.h>
-#include <linux/mm_types.h>
-#include <linux/fs.h>
-#include <linux/err.h>
-#include <asm/ptrace.h>
-#include <asm/uaccess.h>
-#include "swap_msg.h"
-
-/* FIXME: "../.." */
-#include "../../buffer/swap_buffer_module.h"
-
-enum MSG_ID {
- MSG_PROC_INFO = 0x2002,
- MSG_ERROR = 0x2005,
- MSG_SAMPLE = 0x2006,
- MSG_FUNCTION_ENTRY = 0x2010,
- MSG_FUNCTION_EXIT = 0x2011,
- MSG_CONTEXT_SWITCH_ENTRY = 0x2012,
- MSG_CONTEXT_SWITCH_EXIT = 0x2013
-};
-
-static char *cpu_buf[NR_CPUS];
-
-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 0;
-}
-
-void uninit_msg(void)
-{
- int i;
-
- for (i = 0; i < NR_CPUS; ++i)
- kfree(cpu_buf[i]);
-}
-
-static char *get_current_buf(void)
-{
- return cpu_buf[task_cpu(current)];
-}
-
-static inline u64 timespec2time(struct timespec *ts)
-{
- return ((u64)ts->tv_nsec) << 32 | ts->tv_sec;
-}
-
-
-
-
-
-/* ============================================================================
- * = BASIC MESSAGE FORMAT =
- * ============================================================================
- */
-
-struct basic_msg_fmt {
- u32 msg_id;
- u32 seq_number;
- u64 time;
- u32 len;
- char payload[0];
-} __attribute__((packed));
-
-#if 0 /* debug */
-static void print_hex(char *ptr, int len)
-{
- int i;
-
- printk("print_hex:\n");
- for (i = 0; i < len; ++i) {
- printk("[%x] [%3d]=%2x\n", &ptr[i], i, ptr[i]);
- }
-}
-#endif
-
-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);
-
- swap_buffer_write(bmf->len + sizeof(*bmf), buf);
-}
-
-static char* pack_basic_msg_fmt(char *buf, enum MSG_ID id)
-{
- struct basic_msg_fmt *bmf = (struct basic_msg_fmt *)buf;
- struct timespec ts;
-
- getnstimeofday(&ts);
-
- bmf->msg_id = id;
- bmf->time = timespec2time(&ts);
-
- return bmf->payload;
-}
-
-
-
-
-
-/* ============================================================================
- * = PROCESS INFO =
- * ============================================================================
- */
-
-struct proc_info {
- u32 pid;
- u64 start_time;
- u64 low_addr;
- u64 high_addr;
- u32 app_type;
- u32 bin_type;
- char bin_path[0];
-} __attribute__((packed));
-
-struct proc_info_part {
- u32 lib_cnt;
- char libs[0];
-} __attribute__((packed));
-
-struct lib_obj {
- u64 low_addr;
- u64 high_addr;
- char lib_path[0];
-} __attribute__((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;
- struct file *file;
-
- lo->low_addr = vma->vm_start;
- lo->high_addr = vma->vm_end;
-
- return pack_path(lo->lib_path, vma->vm_file);
-}
-
-/* FIXME: check_vma()*/
-#include "../../us_manager/sspt/sspt.h"
-static char *pack_proc_info_part(char *bin_path, struct mm_struct *mm)
-{
- struct proc_info_part *pip;
- struct vm_area_struct *vma;
- char *lib_obj, *end_path = NULL;
- int lib_cnt = 0;
-
- end_path = pack_path(bin_path, mm->exe_file);
-
- pip = (struct proc_info_part *)end_path;
- lib_obj = pip->libs;
-
- down_write(&mm->mmap_sem);
- for (vma = mm->mmap; vma; vma = vma->vm_next) {
- if (check_vma(vma)) {
- lib_obj = pack_lib_obj(lib_obj, vma);
- ++lib_cnt;
- }
- }
- up_write(&mm->mmap_sem);
-
- pip->lib_cnt = lib_cnt;
- return lib_obj;
-}
-
-static char *pack_proc_info(char *payload, struct task_struct *task)
-{
- struct proc_info *pi = (struct proc_info *)payload;
-
- pi->pid = task->tgid;
-
- /* FIXME: */
- pi->start_time = timespec2time(&task->start_time);
- pi->low_addr = 2;
- pi->high_addr = 3;
- pi->app_type = 4;
- pi->bin_type = 5;
-
- return pack_proc_info_part(pi->bin_path, task->mm);
-}
-
-void proc_info_msg(struct task_struct *task)
-{
- char *buf, *payload, *buf_end;
-
- buf = get_current_buf();
- payload = pack_basic_msg_fmt(buf, MSG_PROC_INFO);
- buf_end = pack_proc_info(payload, task);
-
- set_len_msg(buf, buf_end);
-}
-
-
-
-
-
-/* ============================================================================
- * = SAMPLE =
- * ============================================================================
- */
-
-struct sample {
- u32 pid;
- u32 tid;
- u64 pc_addr;
-} __attribute__((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->tid = task->pid;
- s->pc_addr = regs->ARM_pc;
-
- return payload + sizeof(*s);
-}
-
-void sample_msg(struct pt_regs *regs)
-{
- char *buf, *payload, *buf_end;
-
- buf = get_current_buf();
- payload = pack_basic_msg_fmt(buf, MSG_SAMPLE);
- buf_end = pack_sample(payload, regs);
-
- set_len_msg(buf, buf_end);
-}
-
-
-
-
-
-/* ============================================================================
- * = ENTRY =
- * ============================================================================
- */
-
-struct msg_func_entry {
- u64 pc_addr;
- u64 caller_pc_addr;
- u16 probe_type;
- u16 probe_sub_type;
- u32 pid;
- u32 tid;
- u32 cpu_num;
- u32 cnt_args;
- char args[0];
-} __attribute__((packed));
-
-static char *pack_msg_func_entry(char *payload, const char *fmt, struct pt_regs *regs,
- enum PROBE_TYPE pt, enum PROBE_SUB_TYPE pst)
-{
- 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 = task_cpu(task);
- mfe->pc_addr = regs->ARM_pc;
- mfe->caller_pc_addr = regs->ARM_lr;
- mfe->probe_type = pt;
- mfe->probe_sub_type = pst;
- mfe->cnt_args = strlen(fmt);
-
- return payload + sizeof(*mfe);
-}
-
-static int get_args(unsigned long args[], int cnt, struct pt_regs *regs)
-{
- int i, arg_in_regs;
-
- arg_in_regs = cnt < 3 ? cnt : 3;
- switch (arg_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;
- }
-
- /* FIXME: cnt > 4 */
- for (i = 4; i < cnt; ++i) {
- args[i] = 0;
- }
-
- return 0;
-}
-
-static int pack_args(char *buf, int len, const char *fmt, struct pt_regs *regs)
-{
- enum { args_cnt = 16 };
- char *buf_old = buf;
- unsigned long arg, args[args_cnt];
- u32 *tmp_u32;
- u64 *tmp_u64;
- int i, cnt;
-
- cnt = strlen(fmt);
-
- /* FIXME: when the number of arguments is greater than args_cnt */
- cnt = cnt < args_cnt ? cnt : args_cnt;
- get_args(args, cnt, regs);
-
- for (i = 0; i < cnt; ++i) {
- if (len < 2)
- return -ENOMEM;
-
- arg = args[i];
- *buf = fmt[i];
- buf += 1;
- len -= 1;
-
- switch (fmt[i]) {
- case 'c': /* 1 byte(char) */
- if (len < 1)
- return -ENOMEM;
- *buf = (char)arg;
- buf += 1;
- len -= 1;
- break;
-
- case 'd': /* 4 byte(int) */
- if (len < 4)
- return -ENOMEM;
- tmp_u32 = buf;
- *tmp_u32 = arg;
- buf += 4;
- len -= 4;
- break;
-
- case 'x': /* 8 byte(long) */
- case 'p': /* 8 byte(pointer) */
- if (len < 8)
- return -ENOMEM;
- tmp_u64 = buf;
- *tmp_u64 = (u64)arg;
- buf += 8;
- len -= 8;
- break;
-// case 'f': /* 4 byte(float) */
-// break;
-// case 'w': /* 8 byte(double) */
-// 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 *)arg;
- 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 + 1;
- len -= ret + 1;
- }
- break;
- default:
- return -EINVAL;
- }
- }
-
- return buf - buf_old;
-}
-
-void entry_event(const char *fmt, struct pt_regs *regs,
- enum PROBE_TYPE pt, enum PROBE_SUB_TYPE pst)
-{
- 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, regs, pt, pst);
-
- /* FIXME: len = 1024 */
- ret = pack_args(args, 1024, fmt, regs);
- if (ret < 0) {
- printk("ERROR: !!!!!\n");
- return;
- }
-
- buf_end = args + ret;
-
- set_len_msg(buf, buf_end);
-}
-EXPORT_SYMBOL_GPL(entry_event);
-
-
-
-
-
-/* ============================================================================
- * = EXIT =
- * ============================================================================
- */
-
-struct msg_func_exit {
- u32 pid;
- u32 tid;
- u64 pc_addr;
- u32 cpu_num;
- u64 ret_val;
-} __attribute__((packed));
-
-static char *pack_msg_func_exit(char *payload, struct pt_regs *regs)
-{
- struct msg_func_exit *mfe = (struct msg_func_exit *)payload;
- struct task_struct *task = current;
-
- mfe->pid = task->tgid;
- mfe->tid = task->pid;
- mfe->cpu_num = task_cpu(task);
- mfe->pc_addr = regs->ARM_pc;
- mfe->ret_val = regs->ARM_r0;
-
- return payload + sizeof(*mfe);
-}
-
-void exit_event(struct pt_regs *regs)
-{
- char *buf, *payload, *buf_end;
-
- buf = get_current_buf();
- payload = pack_basic_msg_fmt(buf, MSG_FUNCTION_EXIT);
- buf_end = pack_msg_func_exit(payload, regs);
- set_len_msg(buf, buf_end);
-}
-EXPORT_SYMBOL_GPL(exit_event);
-
-
-
-
-
-/* ============================================================================
- * = CONTEXT SWITCH =
- * ============================================================================
- */
-
-struct msg_context_switch {
- u64 pc_addr;
- u32 pid;
- u32 tid;
- u32 cpu_num;
-} __attribute__((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 = regs->ARM_pc;
- mcs->pid = task->tgid;
- mcs->tid = task->pid;
- mcs->cpu_num = task_cpu(task);
-
- return payload + sizeof(*mcs);
-}
-
-static void context_switch(struct pt_regs *regs, enum MSG_ID id)
-{
- char *buf, *payload, *buf_end;
-
- 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);
-}
-
-void switch_entry(struct pt_regs *regs)
-{
- context_switch(regs, MSG_CONTEXT_SWITCH_ENTRY);
-}
-
-void switch_exit(struct pt_regs *regs)
-{
- context_switch(regs, MSG_CONTEXT_SWITCH_EXIT);
-}
-
-
-
-
-
-/* ============================================================================
- * = ERROR =
- * ============================================================================
- */
-
-struct msg_err {
- char msg[0];
-} __attribute__((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;
-}
-
-void error_msg(const char *fmt, ...)
-{
- char *buf, *payload, *buf_end;
- va_list args;
-
- 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);
-}