aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOleg Nesterov <oleg@redhat.com>2014-04-05 15:06:10 -0400
committerOleg Nesterov <oleg@redhat.com>2014-04-17 15:58:22 -0400
commitd241006354c550c7d22f304e2fdf90137fb8eaab (patch)
tree2494931597f4033b265f74763f5b851692a7da3a
parent7ba6db2d688bdf83049a18c8e55b2d1e58e8b0bc (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.c20
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 */
717static bool __skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs) 714static 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