2 * Dynamic Binary Instrumentation Module based on KProbes
3 * modules/kprobe/arch/asm-arm/dbi_kprobes.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 * 2006-2007 Ekaterina Gorelkina <e.gorelkina@samsung.com>: initial implementation for ARM/MIPS
22 * 2008-2009 Alexey Gerenkov <a.gerenkov@samsung.com> User-Space
23 * Probes initial implementation; Support x86.
24 * 2010 Ekaterina Gorelkina <e.gorelkina@samsung.com>: redesign module for separating core and arch parts
25 * 2010-2011 Alexander Shirshikov <a.shirshikov@samsung.com>: initial implementation for Thumb
26 * 2012 Stanislav Andreev <s.andreev@samsung.com>: added time debug profiling support; BUG() message fix
27 * 2012 Stanislav Andreev <s.andreev@samsung.com>: redesign of kprobe functionality -
28 * kprobe_handler() now called via undefined instruction hooks
29 * 2012 Stanislav Andreev <s.andreev@samsung.com>: hash tables search implemented for uprobes
32 #include <linux/module.h>
35 #include "dbi_kprobes.h"
36 #include "trampoline_arm.h"
37 #include <kprobe/dbi_kprobes.h>
39 #include <kprobe/dbi_kdebug.h>
40 #include <kprobe/dbi_insn_slots.h>
41 #include <kprobe/dbi_kprobes_deps.h>
42 #include <ksyms/ksyms.h>
44 #include <asm/cacheflush.h>
45 #include <asm/traps.h>
46 #include <asm/ptrace.h>
47 #include <linux/list.h>
48 #include <linux/hash.h>
50 #define SUPRESS_BUG_MESSAGES
52 extern struct kprobe * per_cpu__current_kprobe;
53 extern struct hlist_head kprobe_table[KPROBE_TABLE_SIZE];
55 static void (*__swap_register_undef_hook)(struct undef_hook *hook);
56 static void (*__swap_unregister_undef_hook)(struct undef_hook *hook);
58 int prep_pc_dep_insn_execbuf(kprobe_opcode_t *insns, kprobe_opcode_t insn, int uregs)
65 for (i = 0; i < 13; i++, reg_mask <<= 1) {
66 if (!(insn & reg_mask))
70 for (i = 0; i < 13; i++) {
71 if ((uregs & 0x1) && (ARM_INSN_REG_RN(insn) == i))
73 if ((uregs & 0x2) && (ARM_INSN_REG_RD(insn) == i))
75 if ((uregs & 0x4) && (ARM_INSN_REG_RS(insn) == i))
77 if ((uregs & 0x8) && (ARM_INSN_REG_RM(insn) == i))
84 DBPRINTF ("there are no free register %x in insn %lx!", uregs, insn);
87 DBPRINTF ("prep_pc_dep_insn_execbuf: using R%d, changing regs %x", i, uregs);
89 // set register to save
90 ARM_INSN_REG_SET_RD(insns[0], i);
91 // set register to load address to
92 ARM_INSN_REG_SET_RD(insns[1], i);
93 // set instruction to execute and patch it
95 ARM_INSN_REG_CLEAR_MR(insn, 15);
96 ARM_INSN_REG_SET_MR(insn, i);
98 if ((uregs & 0x1) && (ARM_INSN_REG_RN(insn) == 15))
99 ARM_INSN_REG_SET_RN(insn, i);
100 if ((uregs & 0x2) && (ARM_INSN_REG_RD(insn) == 15))
101 ARM_INSN_REG_SET_RD(insn, i);
102 if ((uregs & 0x4) && (ARM_INSN_REG_RS(insn) == 15))
103 ARM_INSN_REG_SET_RS(insn, i);
104 if ((uregs & 0x8) && (ARM_INSN_REG_RM(insn) == 15))
105 ARM_INSN_REG_SET_RM(insn, i);
108 insns[UPROBES_TRAMP_INSN_IDX] = insn;
109 // set register to restore
110 ARM_INSN_REG_SET_RD(insns[3], i);
114 EXPORT_SYMBOL_GPL(prep_pc_dep_insn_execbuf);
116 int arch_check_insn_arm(unsigned long insn)
118 /* check instructions that can change PC by nature */
120 /* ARM_INSN_MATCH(UNDEF, insn) || */
121 ARM_INSN_MATCH(AUNDEF, insn) ||
122 ARM_INSN_MATCH(SWI, insn) ||
123 ARM_INSN_MATCH(BREAK, insn) ||
124 ARM_INSN_MATCH(BXJ, insn)) {
126 #ifndef CONFIG_CPU_V7
127 /* check instructions that can write result to PC */
128 } else if ((ARM_INSN_MATCH(DPIS, insn) ||
129 ARM_INSN_MATCH(DPRS, insn) ||
130 ARM_INSN_MATCH(DPI, insn) ||
131 ARM_INSN_MATCH(LIO, insn) ||
132 ARM_INSN_MATCH(LRO, insn)) &&
133 (ARM_INSN_REG_RD(insn) == 15)) {
135 #endif /* CONFIG_CPU_V7 */
136 /* check special instruction loads store multiple registers */
137 } else if ((ARM_INSN_MATCH(LM, insn) || ARM_INSN_MATCH(SM, insn)) &&
138 /* store PC or load to PC */
139 (ARM_INSN_REG_MR(insn, 15) ||
140 /* store/load with PC update */
141 ((ARM_INSN_REG_RN(insn) == 15) && (insn & 0x200000)))) {
148 printk("Bad insn arch_check_insn_arm: %lx\n", insn);
151 EXPORT_SYMBOL_GPL(arch_check_insn_arm);
153 int arch_prepare_kprobe(struct kprobe *p, struct slot_manager *sm)
155 kprobe_opcode_t insns[KPROBES_TRAMP_LEN];
156 int uregs, pc_dep, ret = 0;
157 kprobe_opcode_t insn[MAX_INSN_SIZE];
158 struct arch_specific_insn ainsn;
160 /* insn: must be on special executable page on i386. */
161 p->ainsn.insn = alloc_insn_slot(sm);
165 memcpy(insn, p->addr, MAX_INSN_SIZE * sizeof(kprobe_opcode_t));
166 ainsn.insn_arm = ainsn.insn = insn;
167 ret = arch_check_insn_arm(insn[0]);
169 p->opcode = *p->addr;
173 if (ARM_INSN_MATCH(DPIS, insn[0]) || ARM_INSN_MATCH(LRO, insn[0]) ||
174 ARM_INSN_MATCH(SRO, insn[0])) {
176 if ((ARM_INSN_REG_RN(insn[0]) == 15) || (ARM_INSN_REG_RM(insn[0]) == 15) ||
177 (ARM_INSN_MATCH(SRO, insn[0]) && (ARM_INSN_REG_RD(insn[0]) == 15))) {
178 DBPRINTF ("Unboostable insn %lx, DPIS/LRO/SRO\n", insn[0]);
183 } else if( ARM_INSN_MATCH(DPI, insn[0]) || ARM_INSN_MATCH(LIO, insn[0]) ||
184 ARM_INSN_MATCH(SIO, insn[0])) {
186 if ((ARM_INSN_REG_RN(insn[0]) == 15) || (ARM_INSN_MATCH(SIO, insn[0]) &&
187 (ARM_INSN_REG_RD (insn[0]) == 15))) {
189 DBPRINTF ("Unboostable insn %lx/%p, DPI/LIO/SIO\n", insn[0], p);
192 } else if (ARM_INSN_MATCH(DPRS, insn[0])) {
194 if ((ARM_INSN_REG_RN(insn[0]) == 15) || (ARM_INSN_REG_RM(insn[0]) == 15) ||
195 (ARM_INSN_REG_RS (insn[0]) == 15)) {
197 DBPRINTF ("Unboostable insn %lx, DPRS\n", insn[0]);
200 } else if(ARM_INSN_MATCH(SM, insn[0])) {
202 if (ARM_INSN_REG_MR(insn[0], 15)) {
203 DBPRINTF ("Unboostable insn %lx, SM\n", insn[0]);
208 // check instructions that can write result to SP andu uses PC
209 if (pc_dep && (ARM_INSN_REG_RD(ainsn.insn[0]) == 13)) {
210 free_insn_slot(sm, p->ainsn.insn);
213 if (uregs && pc_dep) {
214 memcpy(insns, pc_dep_insn_execbuf, sizeof(insns));
215 if (prep_pc_dep_insn_execbuf(insns, insn[0], uregs) != 0) {
216 DBPRINTF ("failed to prepare exec buffer for insn %lx!", insn[0]);
217 free_insn_slot(sm, p->ainsn.insn);
220 insns[6] = (kprobe_opcode_t)(p->addr + 2);
222 memcpy(insns, gen_insn_execbuf, sizeof(insns));
223 insns[KPROBES_TRAMP_INSN_IDX] = insn[0];
225 insns[7] = (kprobe_opcode_t)(p->addr + 1);
226 DBPRINTF ("arch_prepare_kprobe: insn %lx", insn[0]);
227 DBPRINTF ("arch_prepare_kprobe: to %p - %lx %lx %lx %lx %lx %lx %lx %lx %lx",
228 p->ainsn.insn, insns[0], insns[1], insns[2], insns[3], insns[4],
229 insns[5], insns[6], insns[7], insns[8]);
230 memcpy(p->ainsn.insn, insns, sizeof(insns));
231 flush_icache_range((long unsigned)p->ainsn.insn, (long unsigned)(p->ainsn.insn) + sizeof(insns));
237 free_insn_slot(sm, p->ainsn.insn);
238 printk("arch_prepare_kprobe: instruction 0x%lx not instrumentation, addr=0x%p\n", insn[0], p->addr);
244 void prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
247 regs->ARM_pc = (unsigned long)p->ss_addr;
250 regs->ARM_pc = (unsigned long)p->ainsn.insn;
253 EXPORT_SYMBOL_GPL(prepare_singlestep);
255 void save_previous_kprobe(struct kprobe_ctlblk *kcb, struct kprobe *p_run)
257 kcb->prev_kprobe.kp = kprobe_running();
258 kcb->prev_kprobe.status = kcb->kprobe_status;
261 void restore_previous_kprobe(struct kprobe_ctlblk *kcb)
263 __get_cpu_var(current_kprobe) = kcb->prev_kprobe.kp;
264 kcb->kprobe_status = kcb->prev_kprobe.status;
267 void set_current_kprobe(struct kprobe *p, struct pt_regs *regs, struct kprobe_ctlblk *kcb)
269 __get_cpu_var(current_kprobe) = p;
270 DBPRINTF ("set_current_kprobe: p=%p addr=%p\n", p, p->addr);
273 static int kprobe_handler(struct pt_regs *regs)
275 struct kprobe *p, *cur;
276 struct kprobe_ctlblk *kcb;
278 kcb = get_kprobe_ctlblk();
279 cur = kprobe_running();
280 p = get_kprobe((void *)regs->ARM_pc);
284 /* Kprobe is pending, so we're recursing. */
285 switch (kcb->kprobe_status) {
286 case KPROBE_HIT_ACTIVE:
287 case KPROBE_HIT_SSDONE:
288 /* A pre- or post-handler probe got us here. */
289 kprobes_inc_nmissed_count(p);
290 save_previous_kprobe(kcb, NULL);
291 set_current_kprobe(p, 0, 0);
292 kcb->kprobe_status = KPROBE_REENTER;
293 prepare_singlestep(p, regs);
294 restore_previous_kprobe(kcb);
297 /* impossible cases */
301 set_current_kprobe(p, 0, 0);
302 kcb->kprobe_status = KPROBE_HIT_ACTIVE;
304 if (!p->pre_handler || !p->pre_handler(p, regs)) {
305 kcb->kprobe_status = KPROBE_HIT_SS;
306 prepare_singlestep(p, regs);
307 reset_current_kprobe();
317 printk("no_kprobe: Not one of ours: let kernel handle it %p\n",
318 (unsigned long *)regs->ARM_pc);
322 int kprobe_trap_handler(struct pt_regs *regs, unsigned int instr)
327 #ifdef SUPRESS_BUG_MESSAGES
328 int swap_oops_in_progress;
329 /* oops_in_progress used to avoid BUG() messages
330 * that slow down kprobe_handler() execution */
331 swap_oops_in_progress = oops_in_progress;
332 oops_in_progress = 1;
335 local_irq_save(flags);
337 ret = kprobe_handler(regs);
338 preempt_enable_no_resched();
339 local_irq_restore(flags);
341 #ifdef SUPRESS_BUG_MESSAGES
342 oops_in_progress = swap_oops_in_progress;
348 int setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
350 struct jprobe *jp = container_of(p, struct jprobe, kp);
351 kprobe_pre_entry_handler_t pre_entry = (kprobe_pre_entry_handler_t)jp->pre_entry;
352 entry_point_t entry = (entry_point_t)jp->entry;
353 pre_entry = (kprobe_pre_entry_handler_t)jp->pre_entry;
356 p->ss_addr = (void *)pre_entry (jp->priv_arg, regs);
360 entry(regs->ARM_r0, regs->ARM_r1, regs->ARM_r2,
361 regs->ARM_r3, regs->ARM_r4, regs->ARM_r5);
369 void dbi_jprobe_return (void)
373 int longjmp_break_handler (struct kprobe *p, struct pt_regs *regs)
377 EXPORT_SYMBOL_GPL(longjmp_break_handler);
379 #ifdef CONFIG_STRICT_MEMORY_RWX
380 extern void mem_text_write_kernel_word(unsigned long *addr, unsigned long word);
383 void arch_arm_kprobe(struct kprobe *p)
385 #ifdef CONFIG_STRICT_MEMORY_RWX
386 mem_text_write_kernel_word(p->addr, BREAKPOINT_INSTRUCTION);
388 *p->addr = BREAKPOINT_INSTRUCTION;
389 flush_icache_range((unsigned long)p->addr, (unsigned long)p->addr + sizeof(kprobe_opcode_t));
393 void arch_disarm_kprobe(struct kprobe *p)
395 #ifdef CONFIG_STRICT_MEMORY_RWX
396 mem_text_write_kernel_word(p->addr, p->opcode);
398 *p->addr = p->opcode;
399 flush_icache_range((unsigned long)p->addr, (unsigned long)p->addr + sizeof(kprobe_opcode_t));
403 void __naked kretprobe_trampoline(void)
405 __asm__ __volatile__ (
406 "stmdb sp!, {r0 - r11} \n\t"
409 "bl trampoline_probe_handler\n\t"
411 "ldmia sp!, {r0 - r11} \n\t"
416 void arch_prepare_kretprobe(struct kretprobe_instance *ri, struct pt_regs *regs)
418 unsigned long *ptr_ret_addr;
420 /* for __switch_to probe */
421 if ((unsigned long)ri->rp->kp.addr == sched_addr) {
422 struct thread_info *tinfo = (struct thread_info *)regs->ARM_r2;
424 ptr_ret_addr = (unsigned long *)&tinfo->cpu_context.pc;
426 ri->task = tinfo->task;
428 ptr_ret_addr = (unsigned long *)®s->ARM_lr;
429 ri->sp = (unsigned long *)regs->ARM_sp;
432 /* Save the return address */
433 ri->ret_addr = (unsigned long *)*ptr_ret_addr;
435 /* Replace the return addr with trampoline addr */
436 *ptr_ret_addr = (unsigned long)&kretprobe_trampoline;
439 void swap_register_undef_hook(struct undef_hook *hook)
441 __swap_register_undef_hook(hook);
443 EXPORT_SYMBOL_GPL(swap_register_undef_hook);
445 void swap_unregister_undef_hook(struct undef_hook *hook)
447 __swap_unregister_undef_hook(hook);
449 EXPORT_SYMBOL_GPL(swap_unregister_undef_hook);
451 // kernel probes hook
452 static struct undef_hook undef_ho_k = {
453 .instr_mask = 0xffffffff,
454 .instr_val = BREAKPOINT_INSTRUCTION,
455 .cpsr_mask = MODE_MASK,
456 .cpsr_val = SVC_MODE,
457 .fn = kprobe_trap_handler
460 int arch_init_kprobes(void)
462 // Register hooks (kprobe_handler)
463 __swap_register_undef_hook = (void *)swap_ksyms("register_undef_hook");
464 if (__swap_register_undef_hook == NULL) {
465 printk("no register_undef_hook symbol found!\n");
469 // Unregister hooks (kprobe_handler)
470 __swap_unregister_undef_hook = (void *)swap_ksyms("unregister_undef_hook");
471 if (__swap_unregister_undef_hook == NULL) {
472 printk("no unregister_undef_hook symbol found!\n");
476 swap_register_undef_hook(&undef_ho_k);
481 void arch_exit_kprobes(void)
483 swap_unregister_undef_hook(&undef_ho_k);
486 /* export symbol for trampoline_arm.h */
487 EXPORT_SYMBOL_GPL(gen_insn_execbuf);
488 EXPORT_SYMBOL_GPL(pc_dep_insn_execbuf);
489 EXPORT_SYMBOL_GPL(b_r_insn_execbuf);
490 EXPORT_SYMBOL_GPL(b_cond_insn_execbuf);
491 EXPORT_SYMBOL_GPL(blx_off_insn_execbuf);