2 * Dynamic Binary Instrumentation Module based on KProbes
3 * modules/kprobe/arch/asm-mips/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/ARM/MIPS for both user-space and kernel space.
24 * 2010 Ekaterina Gorelkina <e.gorelkina@samsung.com>: redesign module for separating core and arch parts
25 * 2012 Stanislav Andreev <s.andreev@samsung.com>: added time debug profiling support; BUG() message fix
28 #include "dbi_kprobes.h"
29 #include "../dbi_kprobes.h"
30 #include "../../dbi_kprobes.h"
32 #include "../../dbi_kdebug.h"
33 #include "../../dbi_insn_slots.h"
34 #include "../../dbi_kprobes_deps.h"
35 #include "../../dbi_uprobes.h"
39 #include <linux/time.h>
42 #define SUPRESS_BUG_MESSAGES
44 unsigned int *arr_traps_original;
46 extern unsigned long sched_addr;
48 extern struct kprobe * per_cpu__current_kprobe;
49 extern spinlock_t kretprobe_lock;
50 extern struct kretprobe *sched_rp;
52 extern struct hlist_head kprobe_insn_pages;
53 extern struct hlist_head uprobe_insn_pages;
55 extern struct kprobe *kprobe_running (void);
56 extern struct kprobe_ctlblk *get_kprobe_ctlblk (void);
57 extern void reset_current_kprobe (void);
60 unsigned long swap_sum_time = 0;
61 unsigned long swap_sum_hit = 0;
62 EXPORT_SYMBOL_GPL (swap_sum_time);
63 EXPORT_SYMBOL_GPL (swap_sum_hit);
66 unsigned int arr_traps_template[] = { 0x3c010000, // lui a1 [0]
67 0x24210000, // addiu a1, a1 [1]
68 0x00200008, // jr a1 [2]
74 * Function return probe trampoline:
75 * - init_kprobes() establishes a probepoint here
76 * - When the probed function returns, this probe
77 * causes the handlers to fire
79 void kretprobe_trampoline_holder (void)
81 asm volatile (".global kretprobe_trampoline\n"
82 "kretprobe_trampoline:\n"
88 struct kprobe trampoline_p =
90 .addr = (kprobe_opcode_t *) & kretprobe_trampoline,
91 .pre_handler = trampoline_probe_handler
94 void gen_insn_execbuf(void);
96 void gen_insn_execbuf_holder (void)
98 asm volatile (".global gen_insn_execbuf\n"
100 "nop\n" // original instruction
106 int arch_check_insn (struct arch_specific_insn *ainsn)
110 switch (MIPS_INSN_OPCODE (ainsn->insn[0]))
112 case MIPS_BEQ_OPCODE: //B, BEQ
113 case MIPS_BEQL_OPCODE: //BEQL
114 case MIPS_BNE_OPCODE: //BNE
115 case MIPS_BNEL_OPCODE: //BNEL
116 case MIPS_BGTZ_OPCODE: //BGTZ
117 case MIPS_BGTZL_OPCODE: //BGTZL
118 case MIPS_BLEZ_OPCODE: //BLEZ
119 case MIPS_BLEZL_OPCODE: //BLEZL
120 case MIPS_J_OPCODE: //J
121 case MIPS_JAL_OPCODE: //JAL
122 DBPRINTF ("arch_check_insn: opcode");
125 case MIPS_REGIMM_OPCODE:
126 //BAL, BGEZ, BGEZAL, BGEZALL, BGEZL, BLTZ, BLTZAL, BLTZALL, BLTZL
127 switch (MIPS_INSN_RT (ainsn->insn[0]))
135 case MIPS_BLTZALL_RT:
136 case MIPS_BGEZALL_RT:
137 DBPRINTF ("arch_check_insn: REGIMM opcode\n");
142 //BC1F, BC1FL, BC1T, BC1TL
143 case MIPS_COP1_OPCODE:
144 //BC2F, BC2FL, BC2T, BC2TL
145 case MIPS_COP2_OPCODE:
146 if (MIPS_INSN_RS (ainsn->insn[0]) == MIPS_BC_RS)
148 DBPRINTF ("arch_check_insn: COP1 opcode\n");
152 case MIPS_SPECIAL_OPCODE:
153 //BREAK, JALR, JALR.HB, JR, JR.HB
154 switch (MIPS_INSN_FUNC (ainsn->insn[0]))
158 case MIPS_BREAK_FUNC:
159 case MIPS_SYSCALL_FUNC:
160 DBPRINTF ("arch_check_insn: SPECIAL opcode\n");
169 int arch_prepare_kretprobe (struct kretprobe *p)
171 DBPRINTF("Warrning: arch_prepare_kretprobe is not implemented\n");
175 int arch_prepare_kprobe (struct kprobe *p)
177 kprobe_opcode_t insns[KPROBES_TRAMP_LEN];
182 kprobe_opcode_t insn[MAX_INSN_SIZE];
183 struct arch_specific_insn ainsn;
184 /* insn: must be on special executable page on i386. */
185 p->ainsn.insn = get_insn_slot (NULL, 0);
188 memcpy (insn, p->addr, MAX_INSN_SIZE * sizeof (kprobe_opcode_t));
190 ret = arch_check_insn (&ainsn);
193 p->opcode = *p->addr;
194 p->ainsn.boostable = 0;
195 memcpy (insns, gen_insn_execbuf, sizeof (insns));
196 insns[KPROBES_TRAMP_INSN_IDX] = insn[0];
197 insns[KPROBES_TRAMP_SS_BREAK_IDX] = BREAKPOINT_INSTRUCTION;
198 insns[KPROBES_TRAMP_RET_BREAK_IDX] = UNDEF_INSTRUCTION;
199 DBPRINTF ("arch_prepare_kprobe: insn %lx", insn[0]);
200 DBPRINTF ("arch_prepare_kprobe: to %p - %lx %lx %lx",
201 p->ainsn.insn, insns[0], insns[1], insns[2]);
202 memcpy (p->ainsn.insn, insns, sizeof(insns));
206 free_insn_slot(&kprobe_insn_pages, NULL, p->ainsn.insn);
213 int arch_prepare_uprobe (struct kprobe *p, struct task_struct *task, int atomic)
216 kprobe_opcode_t insns[UPROBES_TRAMP_LEN];
218 if ((unsigned long) p->addr & 0x01)
220 DBPRINTF ("Attempt to register kprobe at an unaligned address");
226 kprobe_opcode_t insn[MAX_INSN_SIZE];
227 struct arch_specific_insn ainsn;
229 if (!read_proc_vm_atomic (task, (unsigned long) p->addr, &insn, MAX_INSN_SIZE * sizeof(kprobe_opcode_t)))
230 panic ("failed to read memory %p!\n", p->addr);
232 ret = arch_check_insn (&ainsn);
236 p->ainsn.insn = get_insn_slot(task, atomic);
239 p->ainsn.boostable = 0;
240 memcpy (insns, gen_insn_execbuf, sizeof (insns));
241 insns[UPROBES_TRAMP_INSN_IDX] = insn[0];
242 insns[UPROBES_TRAMP_SS_BREAK_IDX] = BREAKPOINT_INSTRUCTION;
243 insns[UPROBES_TRAMP_RET_BREAK_IDX] = UNDEF_INSTRUCTION;
244 DBPRINTF ("arch_prepare_uprobe: insn %lx", insn[0]);
245 DBPRINTF ("arch_prepare_uprobe: to %p - %lx %lx %lx",
246 p->ainsn.insn, insns[0], insns[1], insns[2]);
248 if (!write_proc_vm_atomic (task, (unsigned long) p->ainsn.insn, insns, sizeof (insns)))
250 panic("failed to write memory %p!\n", p->ainsn.insn);
251 DBPRINTF ("failed to write insn slot to process memory: insn %p, addr %p, probe %p!", insn, p->ainsn.insn, p->addr);
252 /*printk ("failed to write insn slot to process memory: %p/%d insn %lx, addr %p, probe %p!\n",
253 task, task->pid, insn, p->ainsn.insn, p->addr);*/
254 free_insn_slot(&uprobe_insn_pages, task, p->ainsn.insn);
263 int arch_prepare_uretprobe (struct kretprobe *p, struct task_struct *task)
265 DBPRINTF("Warrning: arch_prepare_uretprobe is not implemented\n");
269 void prepare_singlestep (struct kprobe *p, struct pt_regs *regs)
273 regs->cp0_epc = (unsigned long) p->ss_addr;
277 regs->cp0_epc = (unsigned long) p->ainsn.insn;
281 void save_previous_kprobe (struct kprobe_ctlblk *kcb, struct kprobe *cur_p)
283 if (kcb->prev_kprobe.kp != NULL)
285 panic ("no space to save new probe[]: task = %d/%s, prev %d/%p, current %d/%p, new %d/%p,",
286 current->pid, current->comm, kcb->prev_kprobe.kp->tgid, kcb->prev_kprobe.kp->addr,
287 kprobe_running()->tgid, kprobe_running()->addr, cur_p->tgid, cur_p->addr);
290 kcb->prev_kprobe.kp = kprobe_running ();
291 kcb->prev_kprobe.status = kcb->kprobe_status;
294 void restore_previous_kprobe (struct kprobe_ctlblk *kcb)
296 __get_cpu_var (current_kprobe) = kcb->prev_kprobe.kp;
297 kcb->kprobe_status = kcb->prev_kprobe.status;
298 kcb->prev_kprobe.kp = NULL;
299 kcb->prev_kprobe.status = 0;
302 void set_current_kprobe (struct kprobe *p, struct pt_regs *regs, struct kprobe_ctlblk *kcb)
304 __get_cpu_var (current_kprobe) = p;
305 DBPRINTF ("set_current_kprobe[]: p=%p addr=%p\n", p, p->addr);
308 int kprobe_handler (struct pt_regs *regs)
310 struct kprobe *p = 0;
311 int ret = 0, pid = 0, retprobe = 0, reenter = 0;
312 kprobe_opcode_t *addr = NULL, *ssaddr = 0;
313 struct kprobe_ctlblk *kcb;
314 #ifdef OVERHEAD_DEBUG
315 struct timeval swap_tv1;
316 struct timeval swap_tv2;
318 #ifdef SUPRESS_BUG_MESSAGES
319 int swap_oops_in_progress;
322 /* We're in an interrupt, but this is clear and BUG()-safe. */
324 addr = (kprobe_opcode_t *) regs->cp0_epc;
325 DBPRINTF ("regs->regs[ 31 ] = 0x%lx\n", regs->regs[31]);
327 #ifdef SUPRESS_BUG_MESSAGES
328 // oops_in_progress used to avoid BUG() messages that slow down kprobe_handler() execution
329 swap_oops_in_progress = oops_in_progress;
330 oops_in_progress = 1;
332 #ifdef OVERHEAD_DEBUG
333 #define USEC_IN_SEC_NUM 1000000
334 do_gettimeofday(&swap_tv1);
338 kcb = get_kprobe_ctlblk ();
340 if (user_mode (regs))
342 //DBPRINTF("exception[%lu] from user mode %s/%u addr %p (%lx).", nCount, current->comm, current->pid, addr, regs->uregs[14]);
346 /* Check we're not actually recursing */
347 if (kprobe_running ())
349 DBPRINTF ("lock???");
350 p = get_kprobe(addr, pid);
353 if(!pid && (addr == (kprobe_opcode_t *)kretprobe_trampoline)){
354 save_previous_kprobe (kcb, p);
355 kcb->kprobe_status = KPROBE_REENTER;
359 /* We have reentered the kprobe_handler(), since
360 * another probe was hit while within the handler.
361 * We here save the original kprobes variables and
362 * just single step on the instruction of the new probe
363 * without calling any user handlers.
365 if(!p->ainsn.boostable){
366 save_previous_kprobe (kcb, p);
367 set_current_kprobe (p, regs, kcb);
369 kprobes_inc_nmissed_count (p);
370 prepare_singlestep (p, regs);
371 if(!p->ainsn.boostable)
372 kcb->kprobe_status = KPROBE_REENTER;
373 preempt_enable_no_resched ();
374 #ifdef OVERHEAD_DEBUG
375 do_gettimeofday(&swap_tv2);
377 swap_sum_time += ((swap_tv2.tv_sec - swap_tv1.tv_sec) * USEC_IN_SEC_NUM +
378 (swap_tv2.tv_usec - swap_tv1.tv_usec));
380 #ifdef SUPRESS_BUG_MESSAGES
381 oops_in_progress = swap_oops_in_progress;
388 if(pid) { //we can reenter probe upon uretprobe exception
389 DBPRINTF ("check for UNDEF_INSTRUCTION %p\n", addr);
390 // UNDEF_INSTRUCTION from user space
391 p = get_kprobe_by_insn_slot (addr-UPROBES_TRAMP_RET_BREAK_IDX, pid, current);
393 save_previous_kprobe (kcb, p);
394 kcb->kprobe_status = KPROBE_REENTER;
397 DBPRINTF ("uretprobe %p\n", addr);
401 p = __get_cpu_var (current_kprobe);
402 DBPRINTF ("kprobe_running !!! p = 0x%p p->break_handler = 0x%p", p, p->break_handler);
403 /*if (p->break_handler && p->break_handler(p, regs)) {
404 DBPRINTF("kprobe_running !!! goto ss");
407 DBPRINTF ("unknown uprobe at %p cur at %p/%p\n", addr, p->addr, p->ainsn.insn);
409 ssaddr = p->ainsn.insn + UPROBES_TRAMP_SS_BREAK_IDX;
411 ssaddr = p->ainsn.insn + KPROBES_TRAMP_SS_BREAK_IDX;
414 regs->cp0_epc = (unsigned long) (p->addr + 1);
415 DBPRINTF ("finish step at %p cur at %p/%p, redirect to %lx\n", addr, p->addr, p->ainsn.insn, regs->cp0_epc);
417 if (kcb->kprobe_status == KPROBE_REENTER) {
418 restore_previous_kprobe (kcb);
421 reset_current_kprobe ();
424 DBPRINTF ("kprobe_running !!! goto no");
426 /* If it's not ours, can't be delete race, (we hold lock). */
427 DBPRINTF ("no_kprobe");
433 //if(einsn != UNDEF_INSTRUCTION) {
434 DBPRINTF ("get_kprobe %p-%d", addr, pid);
436 p = get_kprobe(addr, pid);
440 DBPRINTF ("search UNDEF_INSTRUCTION %p\n", addr);
441 // UNDEF_INSTRUCTION from user space
442 p = get_kprobe_by_insn_slot (addr-UPROBES_TRAMP_RET_BREAK_IDX, pid, current);
444 /* Not one of ours: let kernel handle it */
445 DBPRINTF ("no_kprobe");
446 //printk("no_kprobe2 ret = %d\n", ret);
450 DBPRINTF ("uretprobe %p\n", addr);
453 /* Not one of ours: let kernel handle it */
454 DBPRINTF ("no_kprobe");
455 //printk("no_kprobe2 ret = %d\n", ret);
460 set_current_kprobe (p, regs, kcb);
462 kcb->kprobe_status = KPROBE_HIT_ACTIVE;
464 if (retprobe) //(einsn == UNDEF_INSTRUCTION)
465 ret = trampoline_probe_handler (p, regs);
466 else if (p->pre_handler)
468 ret = p->pre_handler (p, regs);
469 if(!p->ainsn.boostable)
470 kcb->kprobe_status = KPROBE_HIT_SS;
471 else if(p->pre_handler != trampoline_probe_handler) {
472 #ifdef SUPRESS_BUG_MESSAGES
475 reset_current_kprobe ();
476 #ifdef SUPRESS_BUG_MESSAGES
477 preempt_enable_no_resched();
484 DBPRINTF ("p->pre_handler[] 1");
485 #ifdef OVERHEAD_DEBUG
486 do_gettimeofday(&swap_tv2);
488 swap_sum_time += ((swap_tv2.tv_sec - swap_tv1.tv_sec) * USEC_IN_SEC_NUM +
489 (swap_tv2.tv_usec - swap_tv1.tv_usec));
491 #ifdef SUPRESS_BUG_MESSAGES
492 oops_in_progress = swap_oops_in_progress;
494 /* handler has already set things up, so skip ss setup */
497 DBPRINTF ("p->pre_handler 0");
500 preempt_enable_no_resched ();
501 #ifdef OVERHEAD_DEBUG
502 do_gettimeofday(&swap_tv2);
504 swap_sum_time += ((swap_tv2.tv_sec - swap_tv1.tv_sec) * USEC_IN_SEC_NUM +
505 (swap_tv2.tv_usec - swap_tv1.tv_usec));
507 #ifdef SUPRESS_BUG_MESSAGES
508 oops_in_progress = swap_oops_in_progress;
513 void patch_suspended_task_ret_addr(struct task_struct *p, struct kretprobe *rp)
515 DBPRINTF("patch_suspended_task_ret_addr is not implemented");
518 int setjmp_pre_handler (struct kprobe *p, struct pt_regs *regs)
520 struct jprobe *jp = container_of (p, struct jprobe, kp);
521 kprobe_pre_entry_handler_t pre_entry;
525 p = __get_cpu_var (current_kprobe);
528 DBPRINTF ("pjp = 0x%p jp->entry = 0x%p", jp, jp->entry);
529 entry = (entry_point_t) jp->entry;
530 pre_entry = (kprobe_pre_entry_handler_t) jp->pre_entry;
532 // DIE("entry NULL", regs)
533 DBPRINTF ("entry = 0x%p jp->entry = 0x%p", entry, jp->entry);
535 //call handler for all kernel probes and user space ones which belong to current tgid
536 if (!p->tgid || (p->tgid == current->tgid))
538 if(!p->tgid && (p->addr == sched_addr) && sched_rp){
539 struct task_struct *p, *g;
542 if(current != &init_task)
543 patch_suspended_task_ret_addr(&init_task, sched_rp);
545 do_each_thread(g, p){
548 patch_suspended_task_ret_addr(p, sched_rp);
549 } while_each_thread(g, p);
553 p->ss_addr = (void *)pre_entry (jp->priv_arg, regs);
555 entry (regs->regs[4], regs->regs[5], regs->regs[6], regs->regs[7], regs->regs[8], regs->regs[9]);
559 dbi_arch_uprobe_return ();
561 dbi_jprobe_return ();
565 dbi_arch_uprobe_return ();
567 prepare_singlestep (p, regs);
573 void dbi_jprobe_return (void)
575 preempt_enable_no_resched();
578 void dbi_arch_uprobe_return (void)
580 preempt_enable_no_resched();
583 int longjmp_break_handler (struct kprobe *p, struct pt_regs *regs)
586 //kprobe_opcode_t insn = BREAKPOINT_INSTRUCTION;
587 kprobe_opcode_t insns[2];
591 insns[0] = BREAKPOINT_INSTRUCTION;
592 insns[1] = p->opcode;
593 //p->opcode = *p->addr;
594 if (read_proc_vm_atomic (current, (unsigned long) (p->addr), &(p->opcode), sizeof (p->opcode)) < sizeof (p->opcode))
596 printk ("ERROR[]: failed to read vm of proc %s/%u addr %p.", current->comm, current->pid, p->addr);
599 //*p->addr = BREAKPOINT_INSTRUCTION;
600 //*(p->addr+1) = p->opcode;
601 if (write_proc_vm_atomic (current, (unsigned long) (p->addr), insns, sizeof (insns)) < sizeof (insns))
603 printk ("ERROR[]: failed to write vm of proc %s/%u addr %p.", current->comm, current->pid, p->addr);
609 DBPRINTF ("p->opcode = 0x%lx *p->addr = 0x%lx p->addr = 0x%p\n", p->opcode, *p->addr, p->addr);
610 *(p->addr + 1) = p->opcode;
611 p->opcode = *p->addr;
612 *p->addr = BREAKPOINT_INSTRUCTION;
613 flush_icache_range ((unsigned int) p->addr, (unsigned int) (((unsigned int) p->addr) + (sizeof (kprobe_opcode_t) * 2)));
616 reset_current_kprobe ();
621 void arch_arm_kprobe (struct kprobe *p)
623 *p->addr = BREAKPOINT_INSTRUCTION;
624 flush_icache_range ((unsigned long) p->addr, (unsigned long) p->addr + sizeof (kprobe_opcode_t));
627 void arch_disarm_kprobe (struct kprobe *p)
629 *p->addr = p->opcode;
630 flush_icache_range ((unsigned long) p->addr, (unsigned long) p->addr + sizeof (kprobe_opcode_t));
633 int trampoline_probe_handler (struct kprobe *p, struct pt_regs *regs)
635 struct kretprobe_instance *ri = NULL;
636 struct hlist_head *head, empty_rp;
637 struct hlist_node *node, *tmp;
638 unsigned long flags, orig_ret_address = 0;
639 unsigned long trampoline_address = (unsigned long) &kretprobe_trampoline;
640 struct kretprobe *crp = NULL;
641 struct kprobe_ctlblk *kcb = get_kprobe_ctlblk ();
646 // in case of user space retprobe trampoline is at the Nth instruction of US tramp
647 trampoline_address = (unsigned long)(p->ainsn.insn + UPROBES_TRAMP_RET_BREAK_IDX);
650 INIT_HLIST_HEAD (&empty_rp);
651 spin_lock_irqsave (&kretprobe_lock, flags);
652 head = kretprobe_inst_table_head (current);
655 * It is possible to have multiple instances associated with a given
656 * task either because an multiple functions in the call path
657 * have a return probe installed on them, and/or more then one
658 * return probe was registered for a target function.
660 * We can handle this because:
661 * - instances are always inserted at the head of the list
662 * - when multiple return probes are registered for the same
663 * function, the first instance's ret_addr will point to the
664 * real return address, and all the rest will point to
665 * kretprobe_trampoline
667 hlist_for_each_entry_safe (ri, node, tmp, head, hlist)
669 if (ri->task != current)
670 /* another task is sharing our hash bucket */
672 if (ri->rp && ri->rp->handler){
673 ri->rp->handler (ri, regs, ri->rp->priv_arg);
677 orig_ret_address = (unsigned long) ri->ret_addr;
678 recycle_rp_inst (ri);
679 if (orig_ret_address != trampoline_address)
681 * This is the real return address. Any other
682 * instances associated with this task are for
683 * other calls deeper on the call stack
687 kretprobe_assert (ri, orig_ret_address, trampoline_address);
688 //BUG_ON(!orig_ret_address || (orig_ret_address == trampoline_address));
689 if (trampoline_address != (unsigned long) &kretprobe_trampoline){
690 if (ri->rp2) BUG_ON (ri->rp2->kp.tgid == 0);
691 if (ri->rp) BUG_ON (ri->rp->kp.tgid == 0);
692 else if (ri->rp2) BUG_ON (ri->rp2->kp.tgid == 0);
694 if ((ri->rp && ri->rp->kp.tgid) || (ri->rp2 && ri->rp2->kp.tgid))
695 BUG_ON (trampoline_address == (unsigned long) &kretprobe_trampoline);
697 regs->regs[31] = orig_ret_address;
698 DBPRINTF ("regs->cp0_epc = 0x%lx", regs->cp0_epc);
699 if (trampoline_address != (unsigned long) &kretprobe_trampoline)
700 regs->cp0_epc = orig_ret_address;
702 regs->cp0_epc = regs->cp0_epc + 4;
703 DBPRINTF ("regs->cp0_epc = 0x%lx", regs->cp0_epc);
704 DBPRINTF ("regs->cp0_status = 0x%lx", regs->cp0_status);
706 if(p){ // ARM, MIPS, X86 user space
707 if (kcb->kprobe_status == KPROBE_REENTER)
708 restore_previous_kprobe (kcb);
710 reset_current_kprobe ();
712 //TODO: test - enter function, delete us retprobe, exit function
713 // for user space retprobes only - deferred deletion
714 if (trampoline_address != (unsigned long) &kretprobe_trampoline)
716 // if we are not at the end of the list and current retprobe should be disarmed
720 /*sprintf(die_msg, "deferred disarm p->addr = %p [%lx %lx %lx]\n",
721 crp->kp.addr, *kaddrs[0], *kaddrs[1], *kaddrs[2]);
722 DIE(die_msg, regs); */
723 // look for other instances for the same retprobe
724 hlist_for_each_entry_continue (ri, node, hlist)
726 if (ri->task != current)
727 continue; /* another task is sharing our hash bucket */
728 if (ri->rp2 == crp) //if instance belong to the same retprobe
732 { // if there are no more instances for this retprobe
734 DBPRINTF ("defered retprobe deletion p->addr = %p", crp->kp.addr);
735 unregister_uprobe (&crp->kp, current, 1);
742 spin_unlock_irqrestore (&kretprobe_lock, flags);
743 hlist_for_each_entry_safe (ri, node, tmp, &empty_rp, hlist)
745 hlist_del (&ri->hlist);
748 preempt_enable_no_resched ();
750 * By returning a non-zero value, we are telling
751 * kprobe_handler() that we don't want the post_handler
752 * to run (and have re-enabled preemption)
757 void __arch_prepare_kretprobe (struct kretprobe *rp, struct pt_regs *regs)
760 struct kretprobe_instance *ri;
762 DBPRINTF ("start\n");
763 //TODO: test - remove retprobe after func entry but before its exit
764 if ((ri = get_free_rp_inst (rp)) != NULL)
769 ri->ret_addr = (kprobe_opcode_t *) regs->regs[31];
771 regs->regs[31] = (unsigned long) (rp->kp.ainsn.insn + UPROBES_TRAMP_RET_BREAK_IDX);
772 else /* Replace the return addr with trampoline addr */
773 regs->regs[31] = (unsigned long) &kretprobe_trampoline;
777 DBPRINTF ("WARNING: missed retprobe %p\n", rp->kp.addr);
782 DECLARE_MOD_CB_DEP(flush_icache_range, \
783 void, unsigned long __user start, unsigned long __user end);
784 DECLARE_MOD_CB_DEP(flush_icache_page, \
785 void, struct vm_area_struct * vma, struct page * page);
786 DECLARE_MOD_CB_DEP(flush_cache_page, \
787 void, struct vm_area_struct * vma, unsigned long page);
789 int asm_init_module_dependencies()
791 INIT_MOD_DEP_CB(flush_icache_range, r4k_flush_icache_range);
792 INIT_MOD_DEP_CB(flush_icache_page, r4k_flush_icache_page);
793 INIT_MOD_DEP_CB(flush_cache_page, r4k_flush_cache_page);
799 int __init arch_init_kprobes (void)
801 unsigned int do_bp_handler;
802 unsigned int kprobe_handler_addr;
804 unsigned int insns_num = 0;
805 unsigned int code_size = 0;
812 if (arch_init_module_dependencies())
814 DBPRINTF ("Unable to init module dependencies\n");
818 do_bp_handler = (unsigned int)swap_ksyms("do_bp");
820 kprobe_handler_addr = (unsigned int) &kprobe_handler;
821 insns_num = sizeof (arr_traps_template) / sizeof (arr_traps_template[0]);
822 code_size = insns_num * sizeof (unsigned int);
823 DBPRINTF ("insns_num = %d\n", insns_num);
824 // Save original code
825 arr_traps_original = kmalloc (code_size, GFP_KERNEL);
826 if (!arr_traps_original)
828 DBPRINTF ("Unable to allocate space for original code of <do_bp>!\n");
831 memcpy (arr_traps_original, (void *) do_bp_handler, code_size);
833 reg_hi = HIWORD (kprobe_handler_addr);
834 reg_lo = LOWORD (kprobe_handler_addr);
835 if (reg_lo >= 0x8000)
837 arr_traps_template[REG_HI_INDEX] |= reg_hi;
838 arr_traps_template[REG_LO_INDEX] |= reg_lo;
841 memcpy ((void *) do_bp_handler, arr_traps_template, code_size);
842 flush_icache_range (do_bp_handler, do_bp_handler + code_size);
843 if((ret = dbi_register_kprobe (&trampoline_p)) != 0){
844 //dbi_unregister_jprobe(&do_exit_p, 0);
849 void __exit dbi_arch_exit_kprobes (void)
851 unsigned int do_bp_handler;
853 unsigned int insns_num = 0;
854 unsigned int code_size = 0;
856 // Get instruction address
857 do_bp_handler = (unsigned int)swap_ksyms("do_undefinstr");
859 //dbi_unregister_jprobe(&do_exit_p, 0);
861 // Replace back the original code
863 insns_num = sizeof (arr_traps_template) / sizeof (arr_traps_template[0]);
864 code_size = insns_num * sizeof (unsigned int);
865 memcpy ((void *) do_bp_handler, arr_traps_original, code_size);
866 flush_icache_range (do_bp_handler, do_bp_handler + code_size);
867 kfree (arr_traps_original);
868 arr_traps_original = NULL;
871 //EXPORT_SYMBOL_GPL (dbi_arch_uprobe_return);
872 //EXPORT_SYMBOL_GPL (dbi_arch_exit_kprobes);