diff options
author | Vyacheslav Cherkashin <v.cherkashin@samsung.com> | 2014-04-12 18:21:00 +0400 |
---|---|---|
committer | Vyacheslav Cherkashin <v.cherkashin@samsung.com> | 2014-04-21 17:04:57 +0400 |
commit | c4598a886ca8c6c208e3c35b647b56de2371616b (patch) | |
tree | ea2d8b083d517f3e1132f6782005c8151bd0232a /kprobe | |
parent | 4e6453d75e12abc9be72ca0e368579b89c20146c (diff) | |
download | swap-modules-c4598a886ca8c6c208e3c35b647b56de2371616b.tar.gz swap-modules-c4598a886ca8c6c208e3c35b647b56de2371616b.tar.bz2 swap-modules-c4598a886ca8c6c208e3c35b647b56de2371616b.zip |
[IMPROVE] ARM: create jumper
Change-Id: I6db3078573ba35773ca78431d9c6b1d95679231b
Signed-off-by: Vyacheslav Cherkashin <v.cherkashin@samsung.com>
Diffstat (limited to 'kprobe')
-rw-r--r-- | kprobe/arch/asm-arm/dbi_kprobes.c | 81 | ||||
-rw-r--r-- | kprobe/arch/asm-arm/dbi_kprobes.h | 7 |
2 files changed, 88 insertions, 0 deletions
diff --git a/kprobe/arch/asm-arm/dbi_kprobes.c b/kprobe/arch/asm-arm/dbi_kprobes.c index d4edf4fe..f63efca1 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 704ad045..cd7f23bb 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); |