2 * Dynamic Binary Instrumentation Module based on KProbes
3 * modules/uprobe/arch/asm-x86/swap_uprobes.c
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.
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.
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.
19 * Copyright (C) Samsung Electronics, 2006-2010
21 * 2008-2009 Alexey Gerenkov <a.gerenkov@samsung.com> User-Space
22 * Probes initial implementation; Support x86/ARM/MIPS for both user and kernel spaces.
23 * 2010 Ekaterina Gorelkina <e.gorelkina@samsung.com>: redesign module for separating core and arch parts
27 #include <linux/kdebug.h>
28 #include <kprobe/arch/asm/dbi_kprobes.h>
29 #include <uprobe/swap_uprobes.h>
30 #include <uprobe/arch/asm/swap_uprobes.h>
31 #include <kprobe/dbi_insn_slots.h>
33 struct uprobe_ctlblk {
38 static unsigned long trampoline_addr(struct uprobe *up)
40 return (unsigned long)(up->kp.ainsn.insn +
41 UPROBES_TRAMP_RET_BREAK_IDX);
44 static DEFINE_PER_CPU(struct uprobe_ctlblk, ucb) = { 0, NULL };
46 static struct kprobe *get_current_probe(void)
48 return __get_cpu_var(ucb).p;
51 static void set_current_probe(struct kprobe *p)
53 __get_cpu_var(ucb).p = p;
56 static void reset_current_probe(void)
58 set_current_probe(NULL);
61 static void save_current_flags(struct pt_regs *regs)
63 __get_cpu_var(ucb).flags = regs->EREG(flags);
66 static void restore_current_flags(struct pt_regs *regs)
68 regs->EREG(flags) &= ~IF_MASK;
69 regs->EREG(flags) |= __get_cpu_var(ucb).flags & IF_MASK;
72 int arch_prepare_uprobe(struct uprobe *up)
75 struct kprobe *p = up2kp(up);
76 struct task_struct *task = up->task;
77 u8 *tramp = up->atramp.tramp;
79 if (!read_proc_vm_atomic(task, (unsigned long)p->addr,
80 tramp, MAX_INSN_SIZE))
81 panic("failed to read memory %p!\n", p->addr);
83 tramp[UPROBES_TRAMP_RET_BREAK_IDX] = BREAKPOINT_INSTRUCTION;
85 /* TODO: remove dual info */
88 p->ainsn.boostable = can_boost(tramp) ? 0 : -1;
93 int setjmp_upre_handler(struct kprobe *p, struct pt_regs *regs)
95 struct uprobe *up = container_of(p, struct uprobe, kp);
96 struct ujprobe *jp = container_of(up, struct ujprobe, up);
97 kprobe_pre_entry_handler_t pre_entry = (kprobe_pre_entry_handler_t)jp->pre_entry;
98 entry_point_t entry = (entry_point_t)jp->entry;
99 unsigned long args[6];
101 /* FIXME some user space apps crash if we clean interrupt bit */
102 //regs->EREG(flags) &= ~IF_MASK;
103 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18)
104 trace_hardirqs_off();
107 /* read first 6 args from stack */
108 if (!read_proc_vm_atomic(current, regs->EREG(sp) + 4, args, sizeof(args)))
109 panic("failed to read user space func arguments %lx!\n", regs->EREG(sp) + 4);
112 p->ss_addr = (kprobe_opcode_t *)pre_entry(jp->priv_arg, regs);
115 entry(args[0], args[1], args[2], args[3], args[4], args[5]);
117 arch_ujprobe_return();
122 void arch_prepare_uretprobe(struct uretprobe_instance *ri, struct pt_regs *regs)
124 /* Replace the return addr with trampoline addr */
125 unsigned long ra = trampoline_addr(&ri->rp->up);
126 ri->sp = (kprobe_opcode_t *)regs->sp;
128 if (!read_proc_vm_atomic(current, regs->EREG(sp), &(ri->ret_addr), sizeof(ri->ret_addr)))
129 panic("failed to read user space func ra %lx!\n", regs->EREG(sp));
131 if (!write_proc_vm_atomic(current, regs->EREG(sp), &ra, sizeof(ra)))
132 panic("failed to write user space func ra %lx!\n", regs->EREG(sp));
135 int arch_disarm_urp_inst(struct uretprobe_instance *ri,
136 struct task_struct *task)
139 unsigned long ret_addr;
140 unsigned long sp = (unsigned long)ri->sp;
141 unsigned long tramp_addr = trampoline_addr(&ri->rp->up);
142 len = read_proc_vm_atomic(task, sp, &ret_addr, sizeof(ret_addr));
143 if (len != sizeof(ret_addr)) {
144 printk("---> %s (%d/%d): failed to read stack from %08lx\n",
145 task->comm, task->tgid, task->pid, sp);
149 if (tramp_addr == ret_addr) {
150 len = write_proc_vm_atomic(task, sp, &ri->ret_addr,
151 sizeof(ri->ret_addr));
152 if (len != sizeof(ri->ret_addr)) {
153 printk("---> %s (%d/%d): failed to write "
154 "orig_ret_addr to %08lx",
155 task->comm, task->tgid, task->pid, sp);
159 printk("---> %s (%d/%d): trampoline NOT found at sp = %08lx\n",
160 task->comm, task->tgid, task->pid, sp);
167 unsigned long arch_get_trampoline_addr(struct kprobe *p, struct pt_regs *regs)
169 return trampoline_addr(kp2up(p));
172 void arch_set_orig_ret_addr(unsigned long orig_ret_addr, struct pt_regs *regs)
174 regs->EREG(ip) = orig_ret_addr;
177 static void set_user_jmp_op(void *from, void *to)
183 } __attribute__ ((packed)) jop;
185 jop.raddr = (long)(to) - ((long)(from) + 5);
186 jop.op = RELATIVEJUMP_INSTRUCTION;
188 if (!write_proc_vm_atomic(current, (unsigned long)from, &jop, sizeof(jop)))
189 panic("failed to write jump opcode to user space %p!\n", from);
192 static void resume_execution(struct kprobe *p, struct pt_regs *regs, unsigned long flags)
194 unsigned long *tos, tos_dword = 0;
195 unsigned long copy_eip = (unsigned long)p->ainsn.insn;
196 unsigned long orig_eip = (unsigned long)p->addr;
197 kprobe_opcode_t insns[2];
199 regs->EREG(flags) &= ~TF_MASK;
201 tos = (unsigned long *)&tos_dword;
202 if (!read_proc_vm_atomic(current, regs->EREG(sp), &tos_dword, sizeof(tos_dword)))
203 panic("failed to read dword from top of the user space stack %lx!\n", regs->EREG(sp));
205 if (!read_proc_vm_atomic(current, (unsigned long)p->ainsn.insn, insns, 2 * sizeof(kprobe_opcode_t)))
206 panic("failed to read first 2 opcodes of instruction copy from user space %p!\n", p->ainsn.insn);
209 case 0x9c: /* pushfl */
210 *tos &= ~(TF_MASK | IF_MASK);
211 *tos |= flags & (TF_MASK | IF_MASK);
213 case 0xc2: /* iret/ret/lret */
218 case 0xea: /* jmp absolute -- eip is correct */
219 /* eip is already adjusted, no more changes required */
220 p->ainsn.boostable = 1;
222 case 0xe8: /* call relative - Fix return addr */
223 *tos = orig_eip + (*tos - copy_eip);
225 case 0x9a: /* call absolute -- same as call absolute, indirect */
226 *tos = orig_eip + (*tos - copy_eip);
228 if (!write_proc_vm_atomic(current, regs->EREG (sp), &tos_dword, sizeof(tos_dword)))
229 panic("failed to write dword to top of the user space stack %lx!\n", regs->EREG (sp));
233 if ((insns[1] & 0x30) == 0x10) {
235 * call absolute, indirect
236 * Fix return addr; eip is correct.
237 * But this is not boostable
239 *tos = orig_eip + (*tos - copy_eip);
241 if (!write_proc_vm_atomic(current, regs->EREG(sp), &tos_dword, sizeof(tos_dword)))
242 panic("failed to write dword to top of the user space stack %lx!\n", regs->EREG(sp));
245 } else if (((insns[1] & 0x31) == 0x20) || /* jmp near, absolute indirect */
246 ((insns[1] & 0x31) == 0x21)) {
247 /* jmp far, absolute indirect */
248 /* eip is correct. And this is boostable */
249 p->ainsn.boostable = 1;
256 if (!write_proc_vm_atomic(current, regs->EREG(sp), &tos_dword, sizeof(tos_dword)))
257 panic("failed to write dword to top of the user space stack %lx!\n", regs->EREG(sp));
259 if (p->ainsn.boostable == 0) {
260 if ((regs->EREG(ip) > copy_eip) && (regs->EREG(ip) - copy_eip) + 5 < MAX_INSN_SIZE) {
262 * These instructions can be executed directly if it
263 * jumps back to correct address.
265 set_user_jmp_op((void *) regs->EREG(ip), (void *)orig_eip + (regs->EREG(ip) - copy_eip));
266 p->ainsn.boostable = 1;
268 p->ainsn.boostable = -1;
272 regs->EREG(ip) = orig_eip + (regs->EREG(ip) - copy_eip);
278 static int make_trampoline(struct uprobe *up)
280 struct kprobe *p = up2kp(up);
281 struct task_struct *task = up->task;
284 tramp = alloc_insn_slot(up->sm);
286 printk("trampoline out of memory\n");
290 if (!write_proc_vm_atomic(task, (unsigned long)tramp,
292 sizeof(up->atramp.tramp))) {
293 free_insn_slot(up->sm, tramp);
294 panic("failed to write memory %p!\n", tramp);
298 p->ainsn.insn = tramp;
303 static int uprobe_handler(struct pt_regs *regs)
306 kprobe_opcode_t *addr;
307 struct task_struct *task = current;
308 pid_t tgid = task->tgid;
310 save_current_flags(regs);
312 addr = (kprobe_opcode_t *)(regs->EREG(ip) - sizeof(kprobe_opcode_t));
313 p = get_ukprobe(addr, tgid);
316 void *tramp_addr = (void *)addr - UPROBES_TRAMP_RET_BREAK_IDX;
318 p = get_ukprobe_by_insn_slot(tramp_addr, tgid, regs);
320 printk("no_uprobe\n");
324 trampoline_uprobe_handler(p, regs);
327 if (p->ainsn.insn == NULL) {
328 struct uprobe *up = kp2up(p);
336 if (!p->pre_handler || !p->pre_handler(p, regs)) {
337 if (p->ainsn.boostable == 1 && !p->post_handler) {
338 regs->EREG(ip) = (unsigned long)p->ainsn.insn;
342 prepare_singlestep(p, regs);
346 set_current_probe(p);
351 static int post_uprobe_handler(struct pt_regs *regs)
353 struct kprobe *p = get_current_probe();
354 unsigned long flags = __get_cpu_var(ucb).flags;
359 resume_execution(p, regs, flags);
360 restore_current_flags(regs);
362 reset_current_probe();
367 static int uprobe_exceptions_notify(struct notifier_block *self, unsigned long val, void *data)
369 struct die_args *args = (struct die_args *)data;
370 int ret = NOTIFY_DONE;
372 if (args->regs && !user_mode_vm(args->regs))
376 #ifdef CONFIG_KPROBES
381 if (uprobe_handler(args->regs))
385 if (post_uprobe_handler(args->regs))
395 static struct notifier_block uprobe_exceptions_nb = {
396 .notifier_call = uprobe_exceptions_notify,
400 int swap_arch_init_uprobes(void)
402 return register_die_notifier(&uprobe_exceptions_nb);
405 void swap_arch_exit_uprobes(void)
407 unregister_die_notifier(&uprobe_exceptions_nb);