entry_point_t entry = (entry_point_t)jp->entry;
pre_entry = (kprobe_pre_entry_handler_t)jp->pre_entry;
- if (((unsigned long)p->addr == sched_addr) && sched_rp) {
- struct thread_info *tinfo = (struct thread_info *)regs->ARM_r2;
- patch_suspended_task(sched_rp, tinfo->task, regs);
- }
-
if (pre_entry) {
p->ss_addr = (void *)pre_entry (jp->priv_arg, regs);
}
void arch_prepare_kretprobe(struct kretprobe_instance *ri, struct pt_regs *regs)
{
- ri->ret_addr = (kprobe_opcode_t *)regs->ARM_lr;
- ri->sp = (kprobe_opcode_t *)regs->ARM_sp;
+ unsigned long *ptr_ret_addr;
+
+ /* for __switch_to probe */
+ if ((unsigned long)ri->rp->kp.addr == sched_addr) {
+ struct thread_info *tinfo = (struct thread_info *)regs->ARM_r2;
+
+ ptr_ret_addr = (unsigned long *)&tinfo->cpu_context.pc;
+ ri->sp = NULL;
+ ri->task = tinfo->task;
+ } else {
+ ptr_ret_addr = (unsigned long *)®s->ARM_lr;
+ ri->sp = (unsigned long *)regs->ARM_sp;
+ }
+
+ /* Save the return address */
+ ri->ret_addr = (unsigned long *)*ptr_ret_addr;
/* Replace the return addr with trampoline addr */
- regs->ARM_lr = (unsigned long)&kretprobe_trampoline;
+ *ptr_ret_addr = (unsigned long)&kretprobe_trampoline;
}
void swap_register_undef_hook(struct undef_hook *hook)
unsigned long status;
};
-static inline unsigned long *arch_get_patch_addr(struct task_struct *p,
- struct pt_regs *regs)
-{
- return &task_thread_info(p)->cpu_context.pc;
-}
-
static inline unsigned long arch_get_task_pc(struct task_struct *p)
{
return task_thread_info(p)->cpu_context.pc;
pre_entry = (kprobe_pre_entry_handler_t) jp->pre_entry;
entry = (entry_point_t) jp->entry;
- /* handle __switch_to probe */
- if ((p->addr == sched_addr) && sched_rp) {
- /* FIXME: Actually 2nd parameter is not used for x86 */
- patch_suspended_task(sched_rp, (struct task_struct *)regs->dx, regs);
- }
-
kcb->jprobe_saved_regs = *regs;
kcb->jprobe_saved_esp = ®s->EREG(sp);
addr = (unsigned long)(kcb->jprobe_saved_esp);
void arch_prepare_kretprobe(struct kretprobe_instance *ri, struct pt_regs *regs)
{
- unsigned long *sara = (unsigned long *)®s->EREG(sp);
- ri->ret_addr = (kprobe_opcode_t *)*sara;
- ri->sp = ®s->EREG(sp);
+ unsigned long *ptr_ret_addr;
+
+ /* for __switch_to probe */
+ if ((unsigned long)ri->rp->kp.addr == sched_addr) {
+ ptr_ret_addr = (unsigned long *)kernel_stack_pointer(regs);
+ ri->sp = NULL;
+ ri->task = (struct task_struct *)regs->dx;
+ } else {
+ ptr_ret_addr = (unsigned long *)®s->sp;
+ ri->sp = ®s->sp;
+ }
+
+ /* Save the return address */
+ ri->ret_addr = (unsigned long *)*ptr_ret_addr;
/* Replace the return addr with trampoline addr */
- *sara = (unsigned long)&kretprobe_trampoline;
+ *ptr_ret_addr = (unsigned long)&kretprobe_trampoline;
}
int arch_init_module_deps()
#define KPROBES_TRAMP_LEN MAX_INSN_SIZE
#define KPROBES_TRAMP_INSN_IDX 0
-static inline unsigned long *arch_get_patch_addr(struct task_struct *p,
- struct pt_regs *regs)
-{
- return (unsigned long *)kernel_stack_pointer(regs);
-}
-
static inline unsigned long arch_get_task_pc(struct task_struct *p)
{
/* FIXME: Not implemented yet */
return (int)orig_ret_address;
}
-struct kretprobe *sched_rp;
-
#define SCHED_RP_NR 200
#define COMMON_RP_NR 10
rp->kp.break_handler = NULL;
/* Pre-allocate memory for max kretprobe instances */
- if ((unsigned long)rp->kp.addr == sched_addr) {
- rp->maxactive = SCHED_RP_NR;//max (100, 2 * NR_CPUS);
- rp->kp.pre_handler = NULL; //not needed for __switch_to
- } else if ((unsigned long)rp->kp.addr == exit_addr) {
+ if ((unsigned long)rp->kp.addr == exit_addr) {
rp->kp.pre_handler = NULL; //not needed for do_exit
rp->maxactive = 0;
} else if ((unsigned long)rp->kp.addr == do_group_exit_addr) {
free_rp_inst(rp);
DBPRINTF ("addr=%p, *addr=[%lx %lx %lx]", rp->kp.addr, (unsigned long) (*(rp->kp.addr)), (unsigned long) (*(rp->kp.addr + 1)), (unsigned long) (*(rp->kp.addr + 2)));
- if ((unsigned long)rp->kp.addr == sched_addr) {
- sched_rp = rp;
- }
return ret;
}
/* No race here */
spin_lock_irqsave(&kretprobe_lock, flags);
- if ((unsigned long)rp->kp.addr == sched_addr)
- sched_rp = NULL;
-
while ((ri = get_used_rp_inst (rp)) != NULL) {
if (!dbi_disarm_krp_inst(ri)) {
printk("%s (%d/%d): cannot disarm krp instance (%08lx)\n",
}
EXPORT_SYMBOL_GPL(clone_kretprobe);
-static void inline set_task_trampoline(unsigned long *patch_addr,
- struct kretprobe_instance *ri,
- unsigned long tramp_addr)
-{
- unsigned long pc = *patch_addr;
- if (pc == tramp_addr)
- panic("[%d] %s (%d/%d): pc = %08lx --- [%d] %s (%d/%d)\n",
- task_cpu(ri->task), ri->task->comm, ri->task->tgid,
- ri->task->pid, pc, task_cpu(current), current->comm,
- current->tgid, current->pid);
- ri->ret_addr = (kprobe_opcode_t *)pc;
- *patch_addr = tramp_addr;
-}
-
static void inline rm_task_trampoline(struct task_struct *p, struct kretprobe_instance *ri)
{
arch_set_task_pc(p, (unsigned long)ri->ret_addr);
return retval;
}
-int patch_suspended_task(struct kretprobe *rp,
- struct task_struct *task,
- struct pt_regs *regs)
-{
- struct kretprobe_instance *ri;
- unsigned long flags;
- kprobe_opcode_t *tramp = (kprobe_opcode_t *)&kretprobe_trampoline;
- unsigned long *patch_addr;
-
- spin_lock_irqsave(&kretprobe_lock, flags);
-
- ri = get_free_rp_inst(rp);
- if (!ri)
- return -ENOMEM;
-
- ri->rp = rp;
- ri->task = task;
- ri->sp = NULL;
- patch_addr = arch_get_patch_addr(task, regs);
- set_task_trampoline(patch_addr, ri, (unsigned long)tramp);
- add_rp_inst(ri);
-
- spin_unlock_irqrestore(&kretprobe_lock, flags);
- return 0;
-}
-
static int init_module_deps(void)
{
int ret;
extern struct hlist_head kprobe_table[KPROBE_TABLE_SIZE];
//extern struct hlist_head kretprobe_inst_table[KPROBE_TABLE_SIZE];
extern atomic_t kprobe_count;
-extern struct kretprobe *sched_rp;
extern unsigned long sched_addr;
struct kprobe *kprobe_running (void);
struct kprobe_ctlblk *get_kprobe_ctlblk (void);
void prepare_singlestep(struct kprobe *p, struct pt_regs *regs);
-int patch_suspended_task(struct kretprobe *rp,
- struct task_struct *task,
- struct pt_regs *regs);
#endif /* _DBI_KPROBES_H */