flush_icache_range((unsigned long)(addr), \
(unsigned long)(addr) + (size))
-static inline long branch_t16_dest(kprobe_opcode_t insn, unsigned int insn_addr)
+static inline long branch_t16_dest(uprobe_opcode_t insn, unsigned int insn_addr)
{
long offset = insn & 0x3ff;
offset -= insn & 0x400;
return insn_addr + 4 + offset * 2;
}
-static inline long branch_cond_t16_dest(kprobe_opcode_t insn,
+static inline long branch_cond_t16_dest(uprobe_opcode_t insn,
unsigned int insn_addr)
{
long offset = insn & 0x7f;
return insn_addr + 4 + offset * 2;
}
-static inline long branch_t32_dest(kprobe_opcode_t insn, unsigned int insn_addr)
+static inline long branch_t32_dest(uprobe_opcode_t insn, unsigned int insn_addr)
{
unsigned int poff = insn & 0x3ff;
unsigned int offset = (insn & 0x07fe0000) >> 17;
return (insn_addr + 4 + (poff << 12) + offset * 4) & ~3;
}
-static inline long cbz_t16_dest(kprobe_opcode_t insn, unsigned int insn_addr)
+static inline long cbz_t16_dest(uprobe_opcode_t insn, unsigned int insn_addr)
{
unsigned int i = (insn & 0x200) >> 3;
unsigned int offset = (insn & 0xf8) >> 2;
}
/* is instruction Thumb2 and NOT a branch, etc... */
-static int is_thumb2(kprobe_opcode_t insn)
+static int is_thumb2(uprobe_opcode_t insn)
{
return ((insn & 0xf800) == 0xe800 ||
(insn & 0xf800) == 0xf000 ||
return ret;
}
-static int prep_pc_dep_insn_execbuf_thumb(kprobe_opcode_t *insns,
- kprobe_opcode_t insn, int uregs)
+static int prep_pc_dep_insn_execbuf_thumb(uprobe_opcode_t *insns,
+ uprobe_opcode_t insn, int uregs)
{
unsigned char mreg = 0;
unsigned char reg = 0;
* @return 0 on success,\n
* negative error code on error.
*/
-int arch_prepare_uprobe(struct uprobe *up)
+int arch_prepare_uprobe(struct uprobe *p)
{
int ret;
- struct kprobe *p = up2kp(up);
- struct task_struct *task = up->task;
+ struct task_struct *task = p->task;
unsigned long vaddr = (unsigned long)p->addr & ~((unsigned long)1);
unsigned long insn;
int thumb_mode = (unsigned long)p->addr & 1;
return ret;
}
- utramp = swap_slot_alloc(up->sm);
+ utramp = swap_slot_alloc(p->sm);
if (utramp == NULL) {
printk(KERN_INFO "Error: swap_slot_alloc failed (%08lx)\n",
vaddr);
return -ENOMEM;
}
- if (!write_proc_vm_atomic(up->task, (unsigned long)utramp, tramp,
+ if (!write_proc_vm_atomic(p->task, (unsigned long)utramp, tramp,
tramp_len)) {
pr_err("failed to write memory tramp=%p!\n", utramp);
- swap_slot_free(up->sm, utramp);
+ swap_slot_free(p->sm, utramp);
return -EINVAL;
}
void arch_opcode_analysis_uretprobe(struct uretprobe *rp)
{
/* Remove retprobe if first insn overwrites lr */
- rp->thumb_noret = !!(THUMB2_INSN_MATCH(BL, rp->up.kp.opcode) ||
- THUMB2_INSN_MATCH(BLX1, rp->up.kp.opcode) ||
- THUMB_INSN_MATCH(BLX2, rp->up.kp.opcode));
+ rp->thumb_noret = !!(THUMB2_INSN_MATCH(BL, rp->up.opcode) ||
+ THUMB2_INSN_MATCH(BLX1, rp->up.opcode) ||
+ THUMB_INSN_MATCH(BLX2, rp->up.opcode));
- rp->arm_noret = !!(ARM_INSN_MATCH(BL, rp->up.kp.opcode) ||
- ARM_INSN_MATCH(BLX1, rp->up.kp.opcode) ||
- ARM_INSN_MATCH(BLX2, rp->up.kp.opcode));
+ rp->arm_noret = !!(ARM_INSN_MATCH(BL, rp->up.opcode) ||
+ ARM_INSN_MATCH(BLX1, rp->up.opcode) ||
+ ARM_INSN_MATCH(BLX2, rp->up.opcode));
}
/**
*/
int arch_prepare_uretprobe(struct uretprobe_instance *ri, struct pt_regs *regs)
{
- ri->ret_addr = (kprobe_opcode_t *)regs->ARM_lr;
- ri->sp = (kprobe_opcode_t *)regs->ARM_sp;
+ ri->ret_addr = (uprobe_opcode_t *)regs->ARM_lr;
+ ri->sp = (uprobe_opcode_t *)regs->ARM_sp;
/* Set flag of current mode */
- ri->sp = (kprobe_opcode_t *)((long)ri->sp | !!thumb_mode(regs));
+ ri->sp = (uprobe_opcode_t *)((long)ri->sp | !!thumb_mode(regs));
if (ri->preload_thumb) {
- regs->ARM_lr = (unsigned long)(ri->rp->up.kp.ainsn.insn) + 0x1b;
+ regs->ARM_lr = (unsigned long)(ri->rp->up.ainsn.insn) + 0x1b;
} else {
if (thumb_mode(regs))
- regs->ARM_lr = (unsigned long)(ri->rp->up.kp.ainsn.insn) + 0x1b;
+ regs->ARM_lr = (unsigned long)(ri->rp->up.ainsn.insn) + 0x1b;
else
- regs->ARM_lr = (unsigned long)(ri->rp->up.kp.ainsn.insn +
+ regs->ARM_lr = (unsigned long)(ri->rp->up.ainsn.insn +
UPROBES_TRAMP_RET_BREAK_IDX);
}
{
/* Understand function mode */
return ((unsigned long)ri->sp & 1) ?
- ((unsigned long)ri->rp->up.kp.ainsn.insn + 0x1b) :
- (unsigned long)(ri->rp->up.kp.ainsn.insn +
+ ((unsigned long)ri->rp->up.ainsn.insn + 0x1b) :
+ (unsigned long)(ri->rp->up.ainsn.insn +
UPROBES_TRAMP_RET_BREAK_IDX);
}
int i, retval;
if (tr == 0) {
- vaddr = (unsigned long)ri->rp->up.kp.addr;
+ vaddr = (unsigned long)ri->rp->up.addr;
tramp = (unsigned long *)arch_tramp_by_ri(ri);
} else {
/* ri - invalid */
/**
* @brief Jump pre-handler.
*
- * @param p Pointer to the kprobe.
+ * @param p Pointer to the uprobe.
* @param regs Pointer to CPU register data.
* @return 0.
*/
-int setjmp_upre_handler(struct kprobe *p, struct pt_regs *regs)
+int setjmp_upre_handler(struct uprobe *p, struct pt_regs *regs)
{
- struct uprobe *up = container_of(p, struct uprobe, kp);
- struct ujprobe *jp = container_of(up, struct ujprobe, up);
+ struct ujprobe *jp = container_of(p, struct ujprobe, up);
- kprobe_pre_entry_handler_t pre_entry =
- (kprobe_pre_entry_handler_t)jp->pre_entry;
+ uprobe_pre_entry_handler_t pre_entry =
+ (uprobe_pre_entry_handler_t)jp->pre_entry;
entry_point_t entry = (entry_point_t)jp->entry;
if (pre_entry) {
- p->ss_addr[smp_processor_id()] = (kprobe_opcode_t *)
+ p->ss_addr[smp_processor_id()] = (uprobe_opcode_t *)
pre_entry(jp->priv_arg, regs);
}
/**
* @brief Gets trampoline address.
*
- * @param p Pointer to the kprobe.
+ * @param p Pointer to the uprobe.
* @param regs Pointer to CPU register data.
* @return Trampoline address.
*/
-unsigned long arch_get_trampoline_addr(struct kprobe *p, struct pt_regs *regs)
+unsigned long arch_get_trampoline_addr(struct uprobe *p, struct pt_regs *regs)
{
return thumb_mode(regs) ?
(unsigned long)(p->ainsn.insn) + 0x1b :
*/
void arch_remove_uprobe(struct uprobe *up)
{
- swap_slot_free(up->sm, up->kp.ainsn.insn);
+ swap_slot_free(up->sm, up->ainsn.insn);
}
int arch_arm_uprobe(struct uprobe *p)
{
int ret;
- unsigned long vaddr = (unsigned long)p->kp.addr & ~((unsigned long)1);
- int thumb_mode = (unsigned long)p->kp.addr & 1;
+ unsigned long vaddr = (unsigned long)p->addr & ~((unsigned long)1);
+ int thumb_mode = (unsigned long)p->addr & 1;
int len = 4 >> thumb_mode; /* if thumb_mode then len = 2 */
unsigned long insn = thumb_mode ? UBP_THUMB : UBP_ARM;
return 0;
}
-void arch_disarm_uprobe(struct kprobe *p, struct task_struct *task)
+void arch_disarm_uprobe(struct uprobe *p, struct task_struct *task)
{
int ret;
static int urp_handler(struct pt_regs *regs, pid_t tgid)
{
- struct kprobe *p;
+ struct uprobe *p;
unsigned long vaddr = regs->ARM_pc;
unsigned long offset_bp = thumb_mode(regs) ?
0x1a :
4 * UPROBES_TRAMP_RET_BREAK_IDX;
unsigned long tramp_addr = vaddr - offset_bp;
- p = get_ukprobe_by_insn_slot((void *)tramp_addr, tgid, regs);
+ p = get_uprobe_by_insn_slot((void *)tramp_addr, tgid, regs);
if (p == NULL) {
printk(KERN_INFO
"no_uprobe: Not one of ours: let kernel handle it %lx\n",
return 0;
}
+/**
+ * @brief Prepares singlestep for current CPU.
+ *
+ * @param p Pointer to kprobe.
+ * @param regs Pointer to CPU registers data.
+ * @return Void.
+ */
+static void arch_prepare_singlestep(struct uprobe *p, struct pt_regs *regs)
+{
+ int cpu = smp_processor_id();
+
+ if (p->ss_addr[cpu]) {
+ regs->ARM_pc = (unsigned long)p->ss_addr[cpu];
+ p->ss_addr[cpu] = NULL;
+ } else {
+ regs->ARM_pc = (unsigned long)p->ainsn.insn;
+ }
+}
/**
* @brief Breakpoint instruction handler.
int uprobe_trap_handler(struct pt_regs *regs, unsigned int instr)
{
int ret = 0;
- struct kprobe *p;
+ struct uprobe *p;
unsigned long flags;
unsigned long vaddr = regs->ARM_pc | !!thumb_mode(regs);
pid_t tgid = current->tgid;
local_irq_save(flags);
preempt_disable();
- p = get_ukprobe((kprobe_opcode_t *)vaddr, tgid);
+ p = get_uprobe((uprobe_opcode_t *)vaddr, tgid);
if (p) {
- struct uprobe *up = kp2up(p);
bool prepare = false;
- if (up->atomic_ctx) {
+ if (p->atomic_ctx) {
if (!p->pre_handler || !p->pre_handler(p, regs))
prepare = true;
} else {
}
if (prepare)
- prepare_singlestep(p, regs);
+ arch_prepare_singlestep(p, regs);
} else {
ret = urp_handler(regs, tgid);
/* check ARM/THUMB mode on correct */
if (ret) {
vaddr ^= 1;
- p = get_ukprobe((kprobe_opcode_t *)vaddr, tgid);
+ p = get_uprobe((uprobe_opcode_t *)vaddr, tgid);
if (p) {
pr_err("invalid mode: thumb=%d addr=%p insn=%08lx\n",
!!thumb_mode(regs), p->addr, p->opcode);