From c4598a886ca8c6c208e3c35b647b56de2371616b Mon Sep 17 00:00:00 2001 From: Vyacheslav Cherkashin Date: Sat, 12 Apr 2014 18:21:00 +0400 Subject: [PATCH] [IMPROVE] ARM: create jumper Change-Id: I6db3078573ba35773ca78431d9c6b1d95679231b Signed-off-by: Vyacheslav Cherkashin --- kprobe/arch/asm-arm/dbi_kprobes.c | 81 +++++++++++++++++++++++++++++++++++++++ kprobe/arch/asm-arm/dbi_kprobes.h | 7 ++++ 2 files changed, 88 insertions(+) diff --git a/kprobe/arch/asm-arm/dbi_kprobes.c b/kprobe/arch/asm-arm/dbi_kprobes.c index d4edf4f..f63efca 100644 --- a/kprobe/arch/asm-arm/dbi_kprobes.c +++ b/kprobe/arch/asm-arm/dbi_kprobes.c @@ -514,6 +514,87 @@ void arch_prepare_kretprobe(struct kretprobe_instance *ri, struct pt_regs *regs) *ptr_ret_addr = (unsigned long)&kretprobe_trampoline; } + + + + +/* + ****************************************************************************** + * jumper * + ****************************************************************************** + */ +struct cb_data { + unsigned long ret_addr; + unsigned long r0; + + jumper_cb_t cb; + char data[0]; +}; + +static unsigned long __used get_r0(struct cb_data *data) +{ + return data->r0; +} + +static unsigned long __used jump_handler(struct cb_data *data) +{ + unsigned long ret_addr = data->ret_addr; + + /* call callback */ + data->cb(data->data); + + /* FIXME: potential memory leak, when process kill */ + kfree(data); + + return ret_addr; +} + +/* FIXME: restore condition flags */ +void jump_trampoline(void); +__asm( + "jump_trampoline: \n" + + "push {r0 - r12} \n" + "mov r1, r0 \n" /* data --> r1 */ + "bl get_r0 \n" + "str r0, [sp] \n" /* restore r0 */ + "mov r0, r1 \n" /* data --> r0 */ + "bl jump_handler \n" + "mov lr, r0 \n" + "pop {r0 - r12} \n" + "bx lr \n" +); + +unsigned long get_jump_addr(void) +{ + return (unsigned long)&jump_trampoline; +} +EXPORT_SYMBOL_GPL(get_jump_addr); + +int set_jump_cb(unsigned long ret_addr, struct pt_regs *regs, + jumper_cb_t cb, void *data, size_t size) +{ + struct cb_data *cb_data; + + cb_data = kmalloc(sizeof(*cb_data) + size, GFP_ATOMIC); + + /* save data */ + cb_data->ret_addr = ret_addr; + cb_data->cb = cb; + cb_data->r0 = regs->ARM_r0; + memcpy(cb_data->data, data, size); + + /* save cb_data to r0 */ + regs->ARM_r0 = (long)cb_data; + + return 0; +} +EXPORT_SYMBOL_GPL(set_jump_cb); + + + + + void swap_register_undef_hook(struct undef_hook *hook) { __swap_register_undef_hook(hook); diff --git a/kprobe/arch/asm-arm/dbi_kprobes.h b/kprobe/arch/asm-arm/dbi_kprobes.h index 704ad04..cd7f23b 100644 --- a/kprobe/arch/asm-arm/dbi_kprobes.h +++ b/kprobe/arch/asm-arm/dbi_kprobes.h @@ -530,6 +530,13 @@ static inline unsigned long swap_get_sarg(struct pt_regs *regs, unsigned long n) return swap_get_karg(regs, n); } +/* jumper */ +typedef unsigned long (*jumper_cb_t)(void *); + +unsigned long get_jump_addr(void); +int set_jump_cb(unsigned long ret_addr, struct pt_regs *regs, + jumper_cb_t cb, void *data, size_t size); + int arch_init_kprobes(void); void arch_exit_kprobes(void); -- 2.7.4