diff options
author | Oleg Nesterov <oleg@redhat.com> | 2014-04-05 15:06:10 -0400 |
---|---|---|
committer | Oleg Nesterov <oleg@redhat.com> | 2014-04-17 15:58:22 -0400 |
commit | d241006354c550c7d22f304e2fdf90137fb8eaab (patch) | |
tree | 2494931597f4033b265f74763f5b851692a7da3a | |
parent | 7ba6db2d688bdf83049a18c8e55b2d1e58e8b0bc (diff) |
uprobes/x86: Emulate nop's using ops->emulate()
Finally we can kill the ugly (and very limited) code in __skip_sstep().
Just change branch_setup_xol_ops() to treat "nop" as jmp to the next insn.
Thanks to lib/insn.c, it is clever enough. OPCODE1() == 0x90 includes
"(rep;)+ nop;" at least, and (afaics) much more.
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Reviewed-by: Jim Keniston <jkenisto@us.ibm.com>
-rw-r--r-- | arch/x86/kernel/uprobes.c | 20 |
1 files changed, 1 insertions, 19 deletions
diff --git a/arch/x86/kernel/uprobes.c b/arch/x86/kernel/uprobes.c index c3baeaacf1b6..f3c4212f3819 100644 --- a/arch/x86/kernel/uprobes.c +++ b/arch/x86/kernel/uprobes.c | |||
@@ -478,6 +478,7 @@ static int branch_setup_xol_ops(struct arch_uprobe *auprobe, struct insn *insn) | |||
478 | switch (OPCODE1(insn)) { | 478 | switch (OPCODE1(insn)) { |
479 | case 0xeb: /* jmp 8 */ | 479 | case 0xeb: /* jmp 8 */ |
480 | case 0xe9: /* jmp 32 */ | 480 | case 0xe9: /* jmp 32 */ |
481 | case 0x90: /* prefix* + nop; same as jmp with .offs = 0 */ | ||
481 | break; | 482 | break; |
482 | default: | 483 | default: |
483 | return -ENOSYS; | 484 | return -ENOSYS; |
@@ -710,29 +711,10 @@ void arch_uprobe_abort_xol(struct arch_uprobe *auprobe, struct pt_regs *regs) | |||
710 | regs->flags &= ~X86_EFLAGS_TF; | 711 | regs->flags &= ~X86_EFLAGS_TF; |
711 | } | 712 | } |
712 | 713 | ||
713 | /* | ||
714 | * Skip these instructions as per the currently known x86 ISA. | ||
715 | * rep=0x66*; nop=0x90 | ||
716 | */ | ||
717 | static bool __skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs) | 714 | static bool __skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs) |
718 | { | 715 | { |
719 | int i; | ||
720 | |||
721 | if (auprobe->ops->emulate) | 716 | if (auprobe->ops->emulate) |
722 | return auprobe->ops->emulate(auprobe, regs); | 717 | return auprobe->ops->emulate(auprobe, regs); |
723 | |||
724 | /* TODO: move this code into ->emulate() hook */ | ||
725 | for (i = 0; i < MAX_UINSN_BYTES; i++) { | ||
726 | if (auprobe->insn[i] == 0x66) | ||
727 | continue; | ||
728 | |||
729 | if (auprobe->insn[i] == 0x90) { | ||
730 | regs->ip += i + 1; | ||
731 | return true; | ||
732 | } | ||
733 | |||
734 | break; | ||
735 | } | ||
736 | return false; | 718 | return false; |
737 | } | 719 | } |
738 | 720 | ||