3f7e0689294f16f36cf56d64dd1679fb585fec7c
[kernel/swap-modules.git] / us_manager / us_def_handler.c
1 /*
2  *  SWAP uprobe manager
3  *  modules/us_manager/us_def_handler.c
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18  *
19  * Copyright (C) Samsung Electronics, 2013
20  *
21  * 2013  Vyacheslav Cherkashin: SWAP us_manager implement
22  *
23  */
24
25 #include <linux/module.h>
26 #include <asm/percpu.h>
27 #include <swap_uprobes.h>
28 #include <sspt/ip.h>
29 #include <dbi_kprobes_deps.h>
30 #include <sspt/sspt.h>
31 #include <writer/swap_writer_module.h>
32
33 DEFINE_PER_CPU(struct us_ip *, gpCurIp) = NULL;
34 EXPORT_PER_CPU_SYMBOL_GPL(gpCurIp);
35 DEFINE_PER_CPU(struct pt_regs *, gpUserRegs) = NULL;
36 EXPORT_PER_CPU_SYMBOL_GPL(gpUserRegs);
37
38 unsigned long ujprobe_event_pre_handler(struct us_ip *ip, struct pt_regs *regs)
39 {
40         __get_cpu_var(gpCurIp) = ip;
41         __get_cpu_var(gpUserRegs) = regs;
42
43         return 0;
44 }
45 EXPORT_SYMBOL_GPL(ujprobe_event_pre_handler);
46
47 void ujprobe_event_handler(unsigned long arg0, unsigned long arg1,
48                            unsigned long arg2, unsigned long arg3,
49                            unsigned long arg4, unsigned long arg5)
50 {
51         struct us_ip *ip = __get_cpu_var(gpCurIp);
52         struct us_ip *regs = __get_cpu_var(gpUserRegs);
53         unsigned long addr = (unsigned long)ip->jprobe.up.kp.addr;
54
55 #if defined(CONFIG_ARM)
56         addr = ip->offset & 0x01 ? addr | 0x01 : addr;
57 #endif
58
59         entry_event(ip->jprobe.args, regs, PT_US, PST_NONE);
60
61         swap_ujprobe_return();
62 }
63 EXPORT_SYMBOL_GPL(ujprobe_event_handler);
64
65 static void send_plt(struct us_ip *ip)
66 {
67         unsigned long addr = (unsigned long)ip->jprobe.up.kp.addr;
68         struct vm_area_struct *vma = find_vma(current->mm, addr);
69
70         if (vma && check_vma(vma)) {
71                 char *name = NULL;
72                 unsigned long real_addr;
73                 unsigned long real_got = current->mm->exe_file == vma->vm_file ?
74                                          ip->got_addr :
75                                          ip->got_addr + vma->vm_start;
76
77                 if (!read_proc_vm_atomic(current, real_got, &real_addr, sizeof(real_addr))) {
78                         printk("Failed to read got %lx at memory address %lx!\n", ip->got_addr, real_got);
79                         return;
80                 }
81
82                 vma = find_vma(current->mm, real_addr);
83                 if (vma && (vma->vm_start <= real_addr) && (vma->vm_end > real_addr)) {
84                         name = vma->vm_file ? vma->vm_file->f_dentry->d_iname : NULL;
85                 } else {
86                         printk("Failed to get vma, includes %lx address\n", real_addr);
87                         return;
88                 }
89
90 //              if (name)
91 //                      pack_event_info(PLT_ADDR_PROBE_ID, RECORD_RET, "ppsp",
92 //                                      addr, real_addr, name,
93 //                                      real_addr - vma->vm_start);
94 //              else
95 //                      pack_event_info(PLT_ADDR_PROBE_ID, RECORD_RET, "ppp",
96 //                                      addr, real_addr,
97 //                                      real_addr - vma->vm_start);
98         }
99 }
100
101 int uretprobe_event_handler(struct uretprobe_instance *probe,
102                             struct pt_regs *regs)
103 {
104         int retval = regs_return_value(regs);
105         struct us_ip *ip = container_of(probe->rp, struct us_ip, retprobe);
106         unsigned long addr = (unsigned long)ip->jprobe.up.kp.addr;
107
108         if (ip->got_addr && ip->flag_got == 0) {
109                 send_plt(ip);
110                 ip->flag_got = 1;
111         }
112
113 #if defined(CONFIG_ARM)
114         addr = ip->offset & 0x01 ? addr | 0x01 : addr;
115 #endif
116
117         exit_event(regs, addr);
118
119         return 0;
120 }
121 EXPORT_SYMBOL_GPL(uretprobe_event_handler);