2 * @file kprobe/arch/asm-x86/swap_kprobes.h
3 * @author Alexey Gerenkov <a.gerenkov@samsung.com> User-Space Probes initial implementation;
4 * Support x86/ARM/MIPS for both user and kernel spaces.
5 * @author Ekaterina Gorelkina <e.gorelkina@samsung.com>: redesign module for separating core and arch parts
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25 * Copyright (C) IBM Corporation, 2002, 2004
26 * Copyright (C) Samsung Electronics, 2006-2010
28 * @section DESCRIPTION
30 * Arch-dependent kprobes interface for x86 arch.
33 #ifndef _SWAP_ASM_X86_KPROBES_H
34 #define _SWAP_ASM_X86_KPROBES_H
37 #include <linux/version.h>
38 #include <kprobe/swap_kprobes_deps.h>
43 typedef u8 kprobe_opcode_t;
45 #define BREAKPOINT_INSTRUCTION 0xcc
46 #define RELATIVEJUMP_INSTRUCTION 0xe9
48 #define BP_INSN_SIZE 1
49 #define MAX_INSN_SIZE 16
50 #define MAX_STACK_SIZE 64
52 #define MIN_STACK_SIZE(ADDR) (((MAX_STACK_SIZE) < \
53 (((unsigned long)current_thread_info()) \
54 + THREAD_SIZE - (ADDR))) \
56 : (((unsigned long)current_thread_info()) \
57 + THREAD_SIZE - (ADDR)))
59 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25)
61 #define EREG(rg) e##rg
62 #define XREG(rg) x##rg
63 #define ORIG_EAX_REG orig_eax
69 #define ORIG_EAX_REG orig_ax
71 #endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25) */
73 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
74 #define TF_MASK X86_EFLAGS_TF
75 #define IF_MASK X86_EFLAGS_IF
77 #define UPROBES_TRAMP_LEN (MAX_INSN_SIZE+sizeof(kprobe_opcode_t))
78 #define UPROBES_TRAMP_INSN_IDX 0
79 #define UPROBES_TRAMP_RET_BREAK_IDX MAX_INSN_SIZE
80 #define KPROBES_TRAMP_LEN MAX_INSN_SIZE
81 #define KPROBES_TRAMP_INSN_IDX 0
83 static inline unsigned long arch_get_task_pc(struct task_struct *p)
85 /* FIXME: Not implemented yet */
89 static inline void arch_set_task_pc(struct task_struct *p, unsigned long val)
91 /* FIXME: Not implemented yet */
94 static inline struct pt_regs *swap_get_syscall_uregs(unsigned long sp)
96 return NULL; //FIXME currently not implemented for x86
99 static inline unsigned long swap_get_stack_ptr(struct pt_regs *regs)
101 return regs->EREG(sp);
104 static inline unsigned long swap_get_instr_ptr(struct pt_regs *regs)
106 return regs->EREG(ip);
109 static inline void swap_set_instr_ptr(struct pt_regs *regs, unsigned long val)
111 regs->EREG(ip) = val;
114 static inline unsigned long swap_get_ret_addr(struct pt_regs *regs)
116 unsigned long addr = 0;
117 read_proc_vm_atomic(current, regs->EREG(sp), &addr, sizeof(addr));
121 static inline void swap_set_ret_addr(struct pt_regs *regs, unsigned long val)
123 write_proc_vm_atomic(current, regs->EREG(sp), &val, sizeof(val));
126 static inline unsigned long swap_get_arg(struct pt_regs *regs, int num)
128 unsigned long arg = 0;
129 read_proc_vm_atomic(current, regs->EREG(sp) + (1 + num) * 4,
134 static inline void swap_set_arg(struct pt_regs *regs, int num,
137 write_proc_vm_atomic(current, regs->EREG(sp) + (1 + num) * 4,
141 static inline int swap_fp_backtrace(struct task_struct *task,
142 unsigned long *buf, int max_cnt)
145 struct pt_regs *regs;
153 regs = task_pt_regs(task);
154 frame.next = regs->EREG(bp);
155 frame.raddr = swap_get_ret_addr(regs);
157 while (frame.next && i < max_cnt) {
158 if (read_proc_vm_atomic(task, frame.next, &frame, sizeof(frame))
160 buf[i++] = frame.raddr;
169 * @struct prev_kprobe
170 * @brief Stores previous kprobe.
171 * @var prev_kprobe::kp
172 * Pointer to kprobe struct.
173 * @var prev_kprobe::status
178 unsigned long status;
182 * @struct kprobe_ctlblk
183 * @brief Per-cpu kprobe control block.
184 * @var kprobe_ctlblk::kprobe_status
186 * @var kprobe_ctlblk::prev_kprobe
189 struct kprobe_ctlblk {
190 unsigned long kprobe_status;
191 struct prev_kprobe prev_kprobe;
192 struct pt_regs jprobe_saved_regs;
193 unsigned long kprobe_old_eflags;
194 unsigned long kprobe_saved_eflags;
195 unsigned long *jprobe_saved_esp;
196 kprobe_opcode_t jprobes_stack[MAX_STACK_SIZE];
201 * @struct arch_specific_insn
202 * @brief Architecture specific copy of original instruction.
203 * @var arch_specific_insn::insn
204 * Copy of the original instruction.
205 * @var arch_specific_insn::boostable
206 * If this flag is not 0, this kprobe can be boost when its
207 * post_handler and break_handler is not set.
209 struct arch_specific_insn {
210 kprobe_opcode_t *insn;
215 * @brief Entry point.
217 typedef kprobe_opcode_t (*entry_point_t) (unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long);
219 int arch_init_module_deps(void);
222 struct kretprobe_instance;
224 int swap_arch_prepare_kprobe(struct kprobe *p, struct slot_manager *sm);
225 void swap_arch_arm_kprobe(struct kprobe *p);
226 void swap_arch_disarm_kprobe(struct kprobe *p);
227 void swap_arch_prepare_kretprobe(struct kretprobe_instance *ri,
228 struct pt_regs *regs);
229 void swap_kretprobe_trampoline(void);
231 void restore_previous_kprobe(struct kprobe_ctlblk *kcb);
232 int swap_can_boost(kprobe_opcode_t *opcodes);
233 static inline int arch_check_insn(struct arch_specific_insn *ainsn)
238 static inline unsigned long swap_get_karg(struct pt_regs *regs, unsigned long n)
251 * 3 - arguments from registers
252 * 1 - return address saved on top of the stack
254 return *((unsigned long *)kernel_stack_pointer(regs) + n - 2);
257 static inline unsigned long swap_get_sarg(struct pt_regs *regs, unsigned long n)
259 /* 1 - return address saved on top of the stack */
260 return *((unsigned long *)kernel_stack_pointer(regs) + n + 1);
264 typedef unsigned long (*jumper_cb_t)(void *);
266 int set_kjump_cb(struct pt_regs *regs, jumper_cb_t cb,
267 void *data, size_t size);
269 unsigned long get_jump_addr(void);
270 int set_jump_cb(unsigned long ret_addr, struct pt_regs *regs,
271 jumper_cb_t cb, void *data, size_t size);
273 int swap_arch_init_kprobes(void);
274 void swap_arch_exit_kprobes(void);
276 #endif /* _SWAP_ASM_X86_KPROBES_H */