52ed3fa374ce6e97f9686bfdf2972010499c6569
[kernel/swap-modules.git] / kprobe / arch / asm-x86 / dbi_kprobes.h
1 #ifndef _SRC_ASM_X86_KPROBES_H
2 #define _SRC_ASM_X86_KPROBES_H
3
4 /*
5  *  Kernel Probes (KProbes)
6  *  include/linux/kprobes.h
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21  *
22  * Copyright (C) IBM Corporation, 2002, 2004
23  */
24
25 /*
26  *  Dynamic Binary Instrumentation Module based on KProbes
27  *  modules/kprobe/arch/asm-x86/dbi_kprobes.c
28  *
29  * This program is free software; you can redistribute it and/or modify
30  * it under the terms of the GNU General Public License as published by
31  * the Free Software Foundation; either version 2 of the License, or
32  * (at your option) any later version.
33  *
34  * This program is distributed in the hope that it will be useful,
35  * but WITHOUT ANY WARRANTY; without even the implied warranty of
36  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
37  * GNU General Public License for more details.
38  *
39  * You should have received a copy of the GNU General Public License
40  * along with this program; if not, write to the Free Software
41  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
42  *
43  * Copyright (C) Samsung Electronics, 2006-2010
44  *
45  * 2008-2009    Alexey Gerenkov <a.gerenkov@samsung.com> User-Space
46  *              Probes initial implementation; Support x86/ARM/MIPS for both user and kernel spaces.
47  * 2010         Ekaterina Gorelkina <e.gorelkina@samsung.com>: redesign module for separating core and arch parts
48  *
49
50  */
51
52 #include <linux/version.h>
53 #include <dbi_kprobes_deps.h>
54
55 typedef u8 kprobe_opcode_t;
56
57 #define BREAKPOINT_INSTRUCTION          0xcc
58 #define RELATIVEJUMP_INSTRUCTION        0xe9
59
60 #define MAX_INSN_SIZE                   16
61 #define MAX_STACK_SIZE                  64
62
63 #define MIN_STACK_SIZE(ADDR)   (((MAX_STACK_SIZE) <                       \
64                         (((unsigned long)current_thread_info())  \
65                          + THREAD_SIZE - (ADDR)))                 \
66                 ? (MAX_STACK_SIZE)                        \
67                 : (((unsigned long)current_thread_info()) \
68                         + THREAD_SIZE - (ADDR)))
69
70 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25)
71
72 #define EREG(rg)                e##rg
73 #define XREG(rg)                x##rg
74 #define ORIG_EAX_REG            orig_eax
75
76 #else
77
78 #define EREG(rg)                rg
79 #define XREG(rg)                rg
80 #define ORIG_EAX_REG            orig_ax
81
82 #endif /*  LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25) */
83
84 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
85 #define TF_MASK                         X86_EFLAGS_TF
86 #define IF_MASK                         X86_EFLAGS_IF
87 #endif
88 #define UPROBES_TRAMP_LEN               (MAX_INSN_SIZE+sizeof(kprobe_opcode_t))
89 #define UPROBES_TRAMP_INSN_IDX          0
90 #define UPROBES_TRAMP_RET_BREAK_IDX     MAX_INSN_SIZE
91 #define KPROBES_TRAMP_LEN               MAX_INSN_SIZE
92 #define KPROBES_TRAMP_INSN_IDX          0
93
94 static inline unsigned long *arch_get_patch_addr(struct task_struct *p,
95                                                  struct pt_regs *regs)
96 {
97         return (unsigned long *)kernel_stack_pointer(regs);
98 }
99
100 static inline unsigned long arch_get_task_pc(struct task_struct *p)
101 {
102         /* FIXME: Not implemented yet */
103         return 0;
104 }
105
106 static inline void arch_set_task_pc(struct task_struct *p, unsigned long val)
107 {
108         /* FIXME: Not implemented yet */
109 }
110
111 static inline struct pt_regs *dbi_get_syscall_uregs(unsigned long sp)
112 {
113         return NULL; //FIXME currently not implemented for x86
114 }
115
116 static inline unsigned long dbi_get_stack_ptr(struct pt_regs *regs)
117 {
118         return regs->EREG(sp);
119 }
120
121 static inline unsigned long dbi_get_instr_ptr(struct pt_regs *regs)
122 {
123         return regs->EREG(ip);
124 }
125
126 static inline void dbi_set_instr_ptr(struct pt_regs *regs, unsigned long val)
127 {
128         regs->EREG(ip) = val;
129 }
130
131 static inline unsigned long dbi_get_ret_addr(struct pt_regs *regs)
132 {
133         unsigned long addr = 0;
134         read_proc_vm_atomic(current, regs->EREG(sp), &addr, sizeof(addr));
135         return addr;
136 }
137
138 static inline void dbi_set_ret_addr(struct pt_regs *regs, unsigned long val)
139 {
140         write_proc_vm_atomic(current, regs->EREG(sp), &val, sizeof(val));
141 }
142
143 static inline unsigned long dbi_get_arg(struct pt_regs *regs, int num)
144 {
145         unsigned long arg = 0;
146         read_proc_vm_atomic(current, regs->EREG(sp) + (1 + num) * 4,
147                         &arg, sizeof(arg));
148         return arg;
149 }
150
151 static inline void dbi_set_arg(struct pt_regs *regs, int num, unsigned long val)
152 {
153         write_proc_vm_atomic(current, regs->EREG(sp) + (1 + num) * 4,
154                         &val, sizeof(val));
155 }
156
157 static inline int dbi_fp_backtrace(struct task_struct *task, unsigned long *buf,
158                 int max_cnt)
159 {
160         int i = 0;
161         struct pt_regs *regs;
162
163         struct {
164                 unsigned long next;
165                 unsigned long raddr;
166         } frame;
167
168
169         regs = task_pt_regs(task);
170         frame.next = regs->EREG(bp);
171         frame.raddr = dbi_get_ret_addr(regs);
172
173         while (frame.next && i < max_cnt) {
174                 if (read_proc_vm_atomic(task, frame.next, &frame, sizeof(frame))
175                                 == sizeof(frame))
176                         buf[i++] = frame.raddr;
177                 else
178                         break;
179         }
180
181         return i;
182 }
183
184 extern int kprobe_exceptions_notify (struct notifier_block *self, unsigned long val, void *data);
185
186 struct prev_kprobe {
187         struct kprobe *kp;
188         unsigned long status;
189 };
190
191 /* per-cpu kprobe control block */
192 struct kprobe_ctlblk {
193         unsigned long kprobe_status;
194         struct prev_kprobe prev_kprobe;
195         struct pt_regs jprobe_saved_regs;
196         unsigned long kprobe_old_eflags;
197         unsigned long kprobe_saved_eflags;
198         unsigned long *jprobe_saved_esp;
199         kprobe_opcode_t jprobes_stack[MAX_STACK_SIZE];
200 };
201
202
203 int kprobe_fault_handler (struct pt_regs *regs, int trapnr);
204
205 /* Architecture specific copy of original instruction */
206 struct arch_specific_insn {
207         /* copy of the original instruction */
208         kprobe_opcode_t *insn;
209         /*
210          * If this flag is not 0, this kprobe can be boost when its
211          * post_handler and break_handler is not set.
212          */
213         int boostable;
214 };
215
216 typedef kprobe_opcode_t (*entry_point_t) (unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long);
217
218 int arch_init_module_deps(void);
219
220 struct slot_manager;
221 struct kretprobe_instance;
222
223 int arch_prepare_kprobe(struct kprobe *p, struct slot_manager *sm);
224 void arch_arm_kprobe(struct kprobe *p);
225 void arch_disarm_kprobe(struct kprobe *p);
226 void arch_prepare_kretprobe(struct kretprobe_instance *ri, struct pt_regs *regs);
227 void kretprobe_trampoline(void);
228
229 void restore_previous_kprobe(struct kprobe_ctlblk *kcb);
230
231 int arch_init_kprobes(void);
232 void arch_exit_kprobes(void);
233
234 #endif /* _SRC_ASM_X86_KPROBES_H */