*/
static void prepare_singlestep(struct kp_core *p, struct pt_regs *regs)
{
- int cpu = smp_processor_id();
-
- if (p->ss_addr[cpu]) {
- regs->ARM_pc = p->ss_addr[cpu];
- p->ss_addr[cpu] = 0;
- } else {
- regs->ARM_pc = (unsigned long)p->ainsn.insn;
- }
+ regs->ARM_pc = (unsigned long)p->ainsn.insn;
}
static void save_previous_kp_core(struct kp_core_ctlblk *kcb)
/*
******************************************************************************
- * kjumper *
- ******************************************************************************
- */
-struct kj_cb_data {
- unsigned long ret_addr;
-
- struct pt_regs regs;
-
- jumper_cb_t cb;
- char data[0];
-};
-
-static struct kj_cb_data * __used kjump_handler(struct kj_cb_data *data)
-{
- /* call callback */
- data->cb(data->data);
-
- return data;
-}
-
-/**
- * @brief Trampoline for kjump kprobes.
- *
- * @return Void.
- */
-void kjump_trampoline(void);
-__asm(
- "kjump_trampoline:\n"
-
- "mov r0, r10\n"
- "bl kjump_handler\n"
- "nop\n" /* for kjump_kprobe */
-);
-
-/**
- * @brief Registers callback for kjump probes.
- *
- * @param regs Pointer to CPU registers data.
- * @param cb Kjump probe callback of jumper_cb_t type.
- * @param data Pointer to data that should be saved in kj_cb_data.
- * @param size Size of the data.
- * @return 0.
- */
-int set_kjump_cb(struct pt_regs *regs, jumper_cb_t cb, void *data, size_t size)
-{
- struct kp_core *p;
- struct kj_cb_data *cb_data;
-
- cb_data = kmalloc(sizeof(*cb_data) + size, GFP_ATOMIC);
- if (cb_data == NULL)
- return -ENOMEM;
-
- /* save data */
- if (size)
- memcpy(cb_data->data, data, size);
-
- p = kp_core_running();
- p->ss_addr[smp_processor_id()] = (unsigned long)&kjump_trampoline;
-
- cb_data->ret_addr = (unsigned long)p->ainsn.insn;
- cb_data->cb = cb;
-
- /* save regs */
- memcpy(&cb_data->regs, regs, sizeof(*regs));
-
- /* save cb_data to r10 */
- regs->ARM_r10 = (long)cb_data;
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(set_kjump_cb);
-
-static int kjump_pre_handler(struct kprobe *p, struct pt_regs *regs)
-{
- struct kj_cb_data *data = (struct kj_cb_data *)regs->ARM_r0;
-
- /* restore regs */
- memcpy(regs, &data->regs, sizeof(*regs));
- /* p->ss_addr[smp_processor_id()] = (unsigned long)data->ret_addr; */
-
- /* FIXME: potential memory leak, when process kill */
- kfree(data);
-
- return 0;
-}
-
-static struct kprobe kjump_kprobe = {
- .pre_handler = kjump_pre_handler,
- .addr = (unsigned long)&kjump_trampoline + 2 * 4, /* nop */
-};
-
-static int kjump_init(void)
-{
- int ret;
-
- ret = swap_register_kprobe(&kjump_kprobe);
- if (ret)
- printk(KERN_INFO "ERROR: kjump_init(), ret=%d\n", ret);
-
- return ret;
-}
-
-static void kjump_exit(void)
-{
- swap_unregister_kprobe(&kjump_kprobe);
-}
-
-
-
-
-
-/*
- ******************************************************************************
* jumper *
******************************************************************************
*/
*/
int swap_arch_init_kprobes(void)
{
- int ret;
-
swap_register_undef_hook(&undef_ho_k);
- ret = kjump_init();
- if (ret) {
- swap_unregister_undef_hook(&undef_ho_k);
- return ret;
- }
-
return 0;
}
*/
void swap_arch_exit_kprobes(void)
{
- kjump_exit();
swap_unregister_undef_hook(&undef_ho_k);
}
/* jumper */
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);
/*
******************************************************************************
- * kjumper *
- ******************************************************************************
- */
-struct kj_cb_data {
- struct pt_regs regs;
- struct kp_core *p;
-
- jumper_cb_t cb;
- char data[0];
-};
-
-static struct kj_cb_data * __used kjump_handler(struct kj_cb_data *data)
-{
- /* call callback */
- data->cb(data->data);
-
- return data;
-}
-
-void kjump_trampoline(void);
-void kjump_trampoline_int3(void);
-__asm(
- "kjump_trampoline:\n"
- "call kjump_handler\n"
- "kjump_trampoline_int3:\n"
- "nop\n" /* for restore_regs_kp */
-);
-
-int set_kjump_cb(struct pt_regs *regs, jumper_cb_t cb, void *data, size_t size)
-{
- struct kj_cb_data *cb_data;
-
- cb_data = kmalloc(sizeof(*cb_data) + size, GFP_ATOMIC);
- if (cb_data == NULL)
- return -ENOMEM;
-
- /* save regs */
- cb_data->regs = *regs;
-
- cb_data->p = kp_core_running();
- cb_data->cb = cb;
-
- /* save data */
- if (size)
- memcpy(cb_data->data, data, size);
-
- /* save pointer cb_data at ax */
- regs->ax = (long)cb_data;
-
- /* jump to kjump_trampoline */
- regs->ip = (unsigned long)&kjump_trampoline;
-
- kp_core_running_set(NULL);
-
- return 1;
-}
-EXPORT_SYMBOL_GPL(set_kjump_cb);
-
-static int restore_regs_pre_handler(struct kprobe *kp, struct pt_regs *regs)
-{
- struct kj_cb_data *data = (struct kj_cb_data *)regs->ax;
- struct kp_core *p = data->p;
- struct kp_core_ctlblk *kcb = kp_core_ctlblk();
-
- /* restore regs */
- *regs = data->regs;
-
- /* FIXME: potential memory leak, when process kill */
- kfree(data);
-
- kcb = kp_core_ctlblk();
-
- set_current_kp_core(p, regs, kcb);
- setup_singlestep(p, regs, kcb);
-
- return 1;
-}
-
-static struct kprobe restore_regs_kp = {
- .pre_handler = restore_regs_pre_handler,
- .addr = (unsigned long)&kjump_trampoline_int3, /* nop */
-};
-
-static int kjump_init(void)
-{
- int ret;
-
- ret = swap_register_kprobe(&restore_regs_kp);
- if (ret)
- printk(KERN_INFO "ERROR: kjump_init(), ret=%d\n", ret);
-
- return ret;
-}
-
-static void kjump_exit(void)
-{
- swap_unregister_kprobe(&restore_regs_kp);
-}
-
-
-
-
-
-/*
- ******************************************************************************
* jumper *
******************************************************************************
*/
ret = register_die_notifier(&kprobe_exceptions_nb);
if (ret)
- goto unreg_tdraw;
-
- ret = kjump_init();
- if (ret)
- goto unreg_die;
+ swap_td_raw_unreg(&kp_tdraw);
- return 0;
-
-unreg_die:
- unregister_die_notifier(&kprobe_exceptions_nb);
-unreg_tdraw:
- swap_td_raw_unreg(&kp_tdraw);
return ret;
}
*/
void swap_arch_exit_kprobes(void)
{
- kjump_exit();
unregister_die_notifier(&kprobe_exceptions_nb);
swap_td_raw_unreg(&kp_tdraw);
}
/* jumper */
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);
kprobe_opcode_t opcode;
struct arch_specific_insn ainsn;
-
- unsigned long ss_addr[NR_CPUS];
};
/**