summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVyacheslav Cherkashin <v.cherkashin@samsung.com>2014-05-28 14:29:50 +0400
committerVyacheslav Cherkashin <v.cherkashin@samsung.com>2014-07-31 08:01:30 -0700
commit3bc5c13d9a5b3d5d697fe6ca01c74e3ba4ca6891 (patch)
tree70cf8078ac7d1597f38579420b09d231ed17c1f6
parent92943d578946dba39396d1488322af7cc8da422e (diff)
downloadswap-modules-3bc5c13d9a5b3d5d697fe6ca01c74e3ba4ca6891.tar.gz
swap-modules-3bc5c13d9a5b3d5d697fe6ca01c74e3ba4ca6891.tar.bz2
swap-modules-3bc5c13d9a5b3d5d697fe6ca01c74e3ba4ca6891.zip
[IMPROVE] x86: create jumper
Change-Id: Ic356826985c26b7397ab19b5996ba4a78fc54208 Signed-off-by: Vyacheslav Cherkashin <v.cherkashin@samsung.com>
-rw-r--r--kprobe/arch/asm-x86/swap_kprobes.c83
-rw-r--r--kprobe/arch/asm-x86/swap_kprobes.h4
2 files changed, 87 insertions, 0 deletions
diff --git a/kprobe/arch/asm-x86/swap_kprobes.c b/kprobe/arch/asm-x86/swap_kprobes.c
index cd96cf2b..f9cf8f61 100644
--- a/kprobe/arch/asm-x86/swap_kprobes.c
+++ b/kprobe/arch/asm-x86/swap_kprobes.c
@@ -1000,6 +1000,89 @@ static void kjump_exit(void)
+/*
+ ******************************************************************************
+ * jumper *
+ ******************************************************************************
+ */
+struct cb_data {
+ unsigned long ret_addr;
+ unsigned long bx;
+
+ jumper_cb_t cb;
+ char data[0];
+};
+
+static unsigned long __used get_bx(struct cb_data *data)
+{
+ return data->bx;
+}
+
+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;
+}
+
+void jump_trampoline(void);
+__asm(
+ "jump_trampoline: \n"
+ "pushf \n"
+ SWAP_SAVE_REGS_STRING
+ "movl %ebx, %eax \n" /* data --> ax */
+ "call get_bx \n"
+ "movl %eax, (%esp) \n" /* restore bx */
+ "movl %ebx, %eax \n" /* data --> ax */
+ "call jump_handler \n"
+ /* move flags to cs */
+ "movl 56(%esp), %edx \n"
+ "movl %edx, 52(%esp) \n"
+ /* replace saved flags with true return address. */
+ "movl %eax, 56(%esp) \n"
+ SWAP_RESTORE_REGS_STRING
+ "popf\n"
+ "ret\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);
+ if (cb_data == NULL)
+ return -ENOMEM;
+
+ /* save data */
+ cb_data->ret_addr = ret_addr;
+ cb_data->cb = cb;
+ cb_data->bx = regs->bx;
+ memcpy(cb_data->data, data, size);
+
+ /* save cb_data to bx */
+ regs->bx = (long)cb_data;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(set_jump_cb);
+
+
+
+
+
/**
* @brief Initializes x86 module deps.
*
diff --git a/kprobe/arch/asm-x86/swap_kprobes.h b/kprobe/arch/asm-x86/swap_kprobes.h
index e8e7e77a..ce6e7a10 100644
--- a/kprobe/arch/asm-x86/swap_kprobes.h
+++ b/kprobe/arch/asm-x86/swap_kprobes.h
@@ -266,6 +266,10 @@ typedef unsigned long (*jumper_cb_t)(void *);
int set_kjump_cb(struct pt_regs *regs, jumper_cb_t cb,
void *data, size_t size);
+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 swap_arch_init_kprobes(void);
void swap_arch_exit_kprobes(void);