On Mon, Mar 01, 2021 at 11:08:15PM +0900, Masami Hiramatsu wrote:

> +static void kprobe_emulate_jmp(struct kprobe *p, struct pt_regs *regs)
> +{
> +     unsigned long ip = regs->ip - INT3_INSN_SIZE + p->ainsn.size;
> +
> +     ip += p->ainsn.rel32;
> +     int3_emulate_jmp(regs, ip);
> +}
> +NOKPROBE_SYMBOL(kprobe_emulate_jmp);

Would it make sense to have this be something like:

static void kprobe_emulate_jmp(struct kprobe *p, struct pt_regs *regs, bool 
cond)
{
        unsigned long ip = regs->ip - INT3_INSN_SIZE + p->ainsn.size;

        if (cond)
                ip += p->ainsn.rel32;
        int3_emulate_jmp(regs, ip);
}

> +static void kprobe_emulate_jcc(struct kprobe *p, struct pt_regs *regs)
> +{
> +     bool invert = p->ainsn.jcc.type & 1;
> +     bool match;
> +
> +     if (p->ainsn.jcc.type < 0xc) {
> +             match = regs->flags & jcc_mask[p->ainsn.jcc.type >> 1];
> +     } else {
> +             match = ((regs->flags & X86_EFLAGS_SF) >> X86_EFLAGS_SF_BIT) ^
> +                     ((regs->flags & X86_EFLAGS_OF) >> X86_EFLAGS_OF_BIT);
> +             if (p->ainsn.jcc.type >= 0xe)
> +                     match = match && (regs->flags & X86_EFLAGS_ZF);
> +     }
> +     if ((match && !invert) || (!match && invert))
> +             kprobe_emulate_jmp(p, regs);
> +     else
> +             regs->ip = regs->ip - INT3_INSN_SIZE + p->ainsn.size;

Then you can do:

        kprobe_emulate_jmp(p, regs, match);

> +}
> +NOKPROBE_SYMBOL(kprobe_emulate_jcc);
> +
> +static void kprobe_emulate_loop(struct kprobe *p, struct pt_regs *regs)
> +{
> +     bool match;
> +
> +     if (p->ainsn.loop.type != 3) {  /* LOOP* */
> +             if (p->ainsn.loop.asize == 32)
> +                     match = ((*(u32 *)&regs->cx)--) != 0;
> +#ifdef CONFIG_X86_64
> +             else if (p->ainsn.loop.asize == 64)
> +                     match = ((*(u64 *)&regs->cx)--) != 0;
> +#endif
> +             else
> +                     match = ((*(u16 *)&regs->cx)--) != 0;
> +     } else {                        /* JCXZ */
> +             if (p->ainsn.loop.asize == 32)
> +                     match = *(u32 *)(&regs->cx) == 0;
> +#ifdef CONFIG_X86_64
> +             else if (p->ainsn.loop.asize == 64)
> +                     match = *(u64 *)(&regs->cx) == 0;
> +#endif
> +             else
> +                     match = *(u16 *)(&regs->cx) == 0;
> +     }
> +
> +     if (p->ainsn.loop.type == 0)    /* LOOPNE */
> +             match = match && !(regs->flags & X86_EFLAGS_ZF);
> +     else if (p->ainsn.loop.type == 1)       /* LOOPE */
> +             match = match && (regs->flags & X86_EFLAGS_ZF);
> +
> +     if (match)
> +             kprobe_emulate_jmp(p, regs);
> +     else
> +             regs->ip = regs->ip - INT3_INSN_SIZE + p->ainsn.size;

and here.

> +}
> +NOKPROBE_SYMBOL(kprobe_emulate_loop);

Reply via email to