2 * uprobe/arch/asm-x86/swap_uprobes.c
3 * @author Alexey Gerenkov <a.gerenkov@samsung.com> User-Space Probes initial
4 * implementation; Support x86/ARM/MIPS for both user and kernel spaces.
5 * @author Ekaterina Gorelkina <e.gorelkina@samsung.com>: redesign module for
6 * separating core and arch parts
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26 * Copyright (C) Samsung Electronics, 2006-2010
28 * @section DESCRIPTION
30 * Arch-dependent uprobe interface implementation for x86.
34 #include <linux/kdebug.h>
36 #include <kprobe/swap_slots.h>
37 #include <uprobe/swap_uprobes.h>
39 #include "swap_uprobes.h"
43 * @struct uprobe_ctlblk
44 * @brief Uprobe control block
46 struct uprobe_ctlblk {
47 unsigned long flags; /**< Flags */
48 struct kprobe *p; /**< Pointer to the uprobe's kprobe */
51 static unsigned long trampoline_addr(struct uprobe *up)
53 return (unsigned long)(up->kp.ainsn.insn +
54 UPROBES_TRAMP_RET_BREAK_IDX);
57 static DEFINE_PER_CPU(struct uprobe_ctlblk, ucb) = { 0, NULL };
59 static struct kprobe *get_current_probe(void)
61 return __get_cpu_var(ucb).p;
64 static void set_current_probe(struct kprobe *p)
66 __get_cpu_var(ucb).p = p;
69 static void reset_current_probe(void)
71 set_current_probe(NULL);
74 static void save_current_flags(struct pt_regs *regs)
76 __get_cpu_var(ucb).flags = regs->EREG(flags);
79 static void restore_current_flags(struct pt_regs *regs)
81 regs->EREG(flags) &= ~IF_MASK;
82 regs->EREG(flags) |= __get_cpu_var(ucb).flags & IF_MASK;
86 * @brief Prepares uprobe for x86.
88 * @param up Pointer to the uprobe.
89 * @return 0 on success,\n
92 int arch_prepare_uprobe(struct uprobe *up)
94 struct kprobe *p = up2kp(up);
95 struct task_struct *task = up->task;
96 u8 *tramp = up->atramp.tramp;
97 enum { call_relative_opcode = 0xe8 };
99 if (!read_proc_vm_atomic(task, (unsigned long)p->addr,
100 tramp, MAX_INSN_SIZE)) {
101 printk("failed to read memory %p!\n", p->addr);
104 /* TODO: this is a workaround */
105 if (tramp[0] == call_relative_opcode) {
106 printk(KERN_INFO "cannot install probe: 1st instruction is call\n");
110 tramp[UPROBES_TRAMP_RET_BREAK_IDX] = BREAKPOINT_INSTRUCTION;
112 /* TODO: remove dual info */
113 p->opcode = tramp[0];
115 p->ainsn.boostable = swap_can_boost(tramp) ? 0 : -1;
117 p->ainsn.insn = swap_slot_alloc(up->sm);
118 if (p->ainsn.insn == NULL) {
119 printk(KERN_INFO "trampoline out of memory\n");
123 if (!write_proc_vm_atomic(task, (unsigned long)p->ainsn.insn,
124 tramp, sizeof(up->atramp.tramp))) {
125 swap_slot_free(up->sm, p->ainsn.insn);
126 printk("failed to write memory %p!\n", tramp);
134 * @brief Jump pre-handler.
136 * @param p Pointer to the uprobe's kprobe.
137 * @param regs Pointer to CPU register data.
140 int setjmp_upre_handler(struct kprobe *p, struct pt_regs *regs)
142 struct uprobe *up = container_of(p, struct uprobe, kp);
143 struct ujprobe *jp = container_of(up, struct ujprobe, up);
144 kprobe_pre_entry_handler_t pre_entry =
145 (kprobe_pre_entry_handler_t)jp->pre_entry;
146 entry_point_t entry = (entry_point_t)jp->entry;
147 unsigned long args[6];
149 /* FIXME some user space apps crash if we clean interrupt bit */
150 /* regs->EREG(flags) &= ~IF_MASK; */
151 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18)
152 trace_hardirqs_off();
155 /* read first 6 args from stack */
156 if (!read_proc_vm_atomic(current, regs->EREG(sp) + 4,
158 printk("failed to read user space func arguments %lx!\n",
162 p->ss_addr[smp_processor_id()] = (kprobe_opcode_t *)
163 pre_entry(jp->priv_arg, regs);
166 entry(args[0], args[1], args[2], args[3], args[4], args[5]);
168 arch_ujprobe_return();
174 * @brief Prepares uretprobe for x86.
176 * @param ri Pointer to the uretprobe instance.
177 * @param regs Pointer to CPU register data.
180 int arch_prepare_uretprobe(struct uretprobe_instance *ri, struct pt_regs *regs)
182 /* Replace the return addr with trampoline addr */
183 unsigned long ra = trampoline_addr(&ri->rp->up);
184 ri->sp = (kprobe_opcode_t *)regs->sp;
186 if (!read_proc_vm_atomic(current, regs->EREG(sp), &(ri->ret_addr),
187 sizeof(ri->ret_addr))) {
188 printk("failed to read user space func ra %lx addr=%p!\n",
189 regs->EREG(sp), ri->rp->up.kp.addr);
193 if (!write_proc_vm_atomic(current, regs->EREG(sp), &ra, sizeof(ra))) {
194 printk("failed to write user space func ra %lx!\n", regs->EREG(sp));
198 add_uprobe_table(&ri->rp->up.kp);
204 * @brief Disarms uretprobe on x86 arch.
206 * @param ri Pointer to the uretprobe instance.
207 * @param task Pointer to the task for which the probe.
208 * @return 0 on success,\n
209 * negative error code on error.
211 int arch_disarm_urp_inst(struct uretprobe_instance *ri,
212 struct task_struct *task)
215 unsigned long ret_addr;
216 unsigned long sp = (unsigned long)ri->sp;
217 unsigned long tramp_addr = trampoline_addr(&ri->rp->up);
218 len = read_proc_vm_atomic(task, sp, &ret_addr, sizeof(ret_addr));
219 if (len != sizeof(ret_addr)) {
220 printk(KERN_INFO "---> %s (%d/%d): failed to read stack from %08lx\n",
221 task->comm, task->tgid, task->pid, sp);
225 if (tramp_addr == ret_addr) {
226 len = write_proc_vm_atomic(task, sp, &ri->ret_addr,
227 sizeof(ri->ret_addr));
228 if (len != sizeof(ri->ret_addr)) {
229 printk(KERN_INFO "---> %s (%d/%d): failed to write "
230 "orig_ret_addr to %08lx",
231 task->comm, task->tgid, task->pid, sp);
235 printk(KERN_INFO "---> %s (%d/%d): trampoline NOT found at sp = %08lx\n",
236 task->comm, task->tgid, task->pid, sp);
244 * @brief Gets trampoline address.
246 * @param p Pointer to the uprobe's kprobe.
247 * @param regs Pointer to CPU register data.
248 * @return Trampoline address.
250 unsigned long arch_get_trampoline_addr(struct kprobe *p, struct pt_regs *regs)
252 return trampoline_addr(kp2up(p));
256 * @brief Restores return address.
258 * @param orig_ret_addr Original return address.
259 * @param regs Pointer to CPU register data.
262 void arch_set_orig_ret_addr(unsigned long orig_ret_addr, struct pt_regs *regs)
264 regs->EREG(ip) = orig_ret_addr;
268 * @brief Removes uprobe.
270 * @param up Pointer to the target uprobe.
273 void arch_remove_uprobe(struct uprobe *up)
275 struct kprobe *p = up2kp(up);
277 swap_slot_free(up->sm, p->ainsn.insn);
280 static void set_user_jmp_op(void *from, void *to)
282 struct __arch_jmp_op {
287 jop.raddr = (long)(to) - ((long)(from) + 5);
288 jop.op = RELATIVEJUMP_INSTRUCTION;
290 if (!write_proc_vm_atomic(current, (unsigned long)from, &jop,
292 printk("failed to write jump opcode to user space %p\n", from);
295 static void resume_execution(struct kprobe *p,
296 struct pt_regs *regs,
299 unsigned long *tos, tos_dword = 0;
300 unsigned long copy_eip = (unsigned long)p->ainsn.insn;
301 unsigned long orig_eip = (unsigned long)p->addr;
302 kprobe_opcode_t insns[2];
304 regs->EREG(flags) &= ~TF_MASK;
306 tos = (unsigned long *)&tos_dword;
307 if (!read_proc_vm_atomic(current, regs->EREG(sp), &tos_dword,
308 sizeof(tos_dword))) {
309 printk("failed to read dword from top of the user space stack "
310 "%lx!\n", regs->EREG(sp));
314 if (!read_proc_vm_atomic(current, (unsigned long)p->ainsn.insn, insns,
315 2 * sizeof(kprobe_opcode_t))) {
316 printk("failed to read first 2 opcodes of instruction copy "
317 "from user space %p!\n", p->ainsn.insn);
322 case 0x9c: /* pushfl */
323 *tos &= ~(TF_MASK | IF_MASK);
324 *tos |= flags & (TF_MASK | IF_MASK);
326 case 0xc2: /* iret/ret/lret */
331 case 0xea: /* jmp absolute -- eip is correct */
332 /* eip is already adjusted, no more changes required */
333 p->ainsn.boostable = 1;
335 case 0xe8: /* call relative - Fix return addr */
336 *tos = orig_eip + (*tos - copy_eip);
338 case 0x9a: /* call absolute -- same as call absolute, indirect */
339 *tos = orig_eip + (*tos - copy_eip);
341 if (!write_proc_vm_atomic(current,
344 sizeof(tos_dword))) {
345 printk("failed to write dword to top of the"
346 " user space stack %lx!\n", regs->EREG(sp));
352 if ((insns[1] & 0x30) == 0x10) {
354 * call absolute, indirect
355 * Fix return addr; eip is correct.
356 * But this is not boostable
358 *tos = orig_eip + (*tos - copy_eip);
360 if (!write_proc_vm_atomic(current, regs->EREG(sp),
362 sizeof(tos_dword))) {
363 printk("failed to write dword to top of the "
364 "user space stack %lx!\n",
370 } else if (((insns[1] & 0x31) == 0x20) || /* jmp near, absolute
372 ((insns[1] & 0x31) == 0x21)) {
373 /* jmp far, absolute indirect */
374 /* eip is correct. And this is boostable */
375 p->ainsn.boostable = 1;
379 if (insns[1] == 0xc3)
380 /* repz ret special handling: no more changes */
387 if (!write_proc_vm_atomic(current, regs->EREG(sp), &tos_dword,
388 sizeof(tos_dword))) {
389 printk("failed to write dword to top of the user space stack "
390 "%lx!\n", regs->EREG(sp));
394 if (p->ainsn.boostable == 0) {
395 if ((regs->EREG(ip) > copy_eip) && (regs->EREG(ip) - copy_eip) +
398 * These instructions can be executed directly if it
399 * jumps back to correct address.
401 set_user_jmp_op((void *) regs->EREG(ip),
403 (regs->EREG(ip) - copy_eip));
404 p->ainsn.boostable = 1;
406 p->ainsn.boostable = -1;
410 regs->EREG(ip) = orig_eip + (regs->EREG(ip) - copy_eip);
416 static int uprobe_handler(struct pt_regs *regs)
419 kprobe_opcode_t *addr;
420 struct task_struct *task = current;
421 pid_t tgid = task->tgid;
423 save_current_flags(regs);
425 addr = (kprobe_opcode_t *)(regs->EREG(ip) - sizeof(kprobe_opcode_t));
426 p = get_ukprobe(addr, tgid);
429 void *tramp_addr = (void *)addr - UPROBES_TRAMP_RET_BREAK_IDX;
431 p = get_ukprobe_by_insn_slot(tramp_addr, tgid, regs);
433 printk(KERN_INFO "no_uprobe\n");
437 trampoline_uprobe_handler(p, regs);
440 if (!p->pre_handler || !p->pre_handler(p, regs)) {
442 if (p->ainsn.boostable == 1 && !p->post_handler) {
443 if (p->ss_addr[smp_processor_id()]) {
444 regs->EREG(ip) = (unsigned long)p->ss_addr[smp_processor_id()];
445 p->ss_addr[smp_processor_id()] = NULL;
447 regs->EREG(ip) = (unsigned long)p->ainsn.insn;
452 prepare_singlestep(p, regs);
456 set_current_probe(p);
461 static int post_uprobe_handler(struct pt_regs *regs)
463 struct kprobe *p = get_current_probe();
464 unsigned long flags = __get_cpu_var(ucb).flags;
469 resume_execution(p, regs, flags);
470 restore_current_flags(regs);
472 reset_current_probe();
477 static int uprobe_exceptions_notify(struct notifier_block *self,
478 unsigned long val, void *data)
480 struct die_args *args = (struct die_args *)data;
481 int ret = NOTIFY_DONE;
483 if (args->regs == NULL || !user_mode_vm(args->regs))
487 #ifdef CONFIG_KPROBES
492 if (uprobe_handler(args->regs))
496 if (post_uprobe_handler(args->regs))
506 static struct notifier_block uprobe_exceptions_nb = {
507 .notifier_call = uprobe_exceptions_notify,
512 * @brief Registers notify.
514 * @return register_die_notifier result.
516 int swap_arch_init_uprobes(void)
518 return register_die_notifier(&uprobe_exceptions_nb);
522 * @brief Unregisters notify.
526 void swap_arch_exit_uprobes(void)
528 unregister_die_notifier(&uprobe_exceptions_nb);