diff options
author | Oleg Nesterov <oleg@redhat.com> | 2012-10-28 12:57:30 -0400 |
---|---|---|
committer | Oleg Nesterov <oleg@redhat.com> | 2012-11-03 12:15:12 -0400 |
commit | 4dc316c64594d1a5ef2d61fba5ae0fe7fe18cdca (patch) | |
tree | 5fb39a6b6f929ae2ddd4ad83e78524065e86cc96 | |
parent | 65b2c8f0e53347583168423de0f32227d8baf01b (diff) |
uprobes/x86: Cleanup the single-stepping code
No functional changes.
Now that default arch_uprobe_enable/disable_step() helpers do nothing,
x86 has no reason to reimplement them. Change arch_uprobe_*_xol() hooks
to do the necessary work and remove the x86-specific hooks.
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Acked-by: Srikar Dronamraju <srikar@linux.vnet.ibm.com>
-rw-r--r-- | arch/x86/kernel/uprobes.c | 54 |
1 files changed, 19 insertions, 35 deletions
diff --git a/arch/x86/kernel/uprobes.c b/arch/x86/kernel/uprobes.c index aafa5557b396..c71025b67462 100644 --- a/arch/x86/kernel/uprobes.c +++ b/arch/x86/kernel/uprobes.c | |||
@@ -478,6 +478,11 @@ int arch_uprobe_pre_xol(struct arch_uprobe *auprobe, struct pt_regs *regs) | |||
478 | regs->ip = current->utask->xol_vaddr; | 478 | regs->ip = current->utask->xol_vaddr; |
479 | pre_xol_rip_insn(auprobe, regs, autask); | 479 | pre_xol_rip_insn(auprobe, regs, autask); |
480 | 480 | ||
481 | autask->saved_tf = !!(regs->flags & X86_EFLAGS_TF); | ||
482 | regs->flags |= X86_EFLAGS_TF; | ||
483 | if (test_tsk_thread_flag(current, TIF_BLOCKSTEP)) | ||
484 | set_task_blockstep(current, false); | ||
485 | |||
481 | return 0; | 486 | return 0; |
482 | } | 487 | } |
483 | 488 | ||
@@ -603,6 +608,16 @@ int arch_uprobe_post_xol(struct arch_uprobe *auprobe, struct pt_regs *regs) | |||
603 | if (auprobe->fixups & UPROBE_FIX_CALL) | 608 | if (auprobe->fixups & UPROBE_FIX_CALL) |
604 | result = adjust_ret_addr(regs->sp, correction); | 609 | result = adjust_ret_addr(regs->sp, correction); |
605 | 610 | ||
611 | /* | ||
612 | * arch_uprobe_pre_xol() doesn't save the state of TIF_BLOCKSTEP | ||
613 | * so we can get an extra SIGTRAP if we do not clear TF. We need | ||
614 | * to examine the opcode to make it right. | ||
615 | */ | ||
616 | if (utask->autask.saved_tf) | ||
617 | send_sig(SIGTRAP, current, 0); | ||
618 | else if (!(auprobe->fixups & UPROBE_FIX_SETF)) | ||
619 | regs->flags &= ~X86_EFLAGS_TF; | ||
620 | |||
606 | return result; | 621 | return result; |
607 | } | 622 | } |
608 | 623 | ||
@@ -647,6 +662,10 @@ void arch_uprobe_abort_xol(struct arch_uprobe *auprobe, struct pt_regs *regs) | |||
647 | current->thread.trap_nr = utask->autask.saved_trap_nr; | 662 | current->thread.trap_nr = utask->autask.saved_trap_nr; |
648 | handle_riprel_post_xol(auprobe, regs, NULL); | 663 | handle_riprel_post_xol(auprobe, regs, NULL); |
649 | instruction_pointer_set(regs, utask->vaddr); | 664 | instruction_pointer_set(regs, utask->vaddr); |
665 | |||
666 | /* clear TF if it was set by us in arch_uprobe_pre_xol() */ | ||
667 | if (!utask->autask.saved_tf) | ||
668 | regs->flags &= ~X86_EFLAGS_TF; | ||
650 | } | 669 | } |
651 | 670 | ||
652 | /* | 671 | /* |
@@ -676,38 +695,3 @@ bool arch_uprobe_skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs) | |||
676 | send_sig(SIGTRAP, current, 0); | 695 | send_sig(SIGTRAP, current, 0); |
677 | return ret; | 696 | return ret; |
678 | } | 697 | } |
679 | |||
680 | void arch_uprobe_enable_step(struct arch_uprobe *auprobe) | ||
681 | { | ||
682 | struct task_struct *task = current; | ||
683 | struct arch_uprobe_task *autask = &task->utask->autask; | ||
684 | struct pt_regs *regs = task_pt_regs(task); | ||
685 | |||
686 | autask->saved_tf = !!(regs->flags & X86_EFLAGS_TF); | ||
687 | |||
688 | regs->flags |= X86_EFLAGS_TF; | ||
689 | if (test_tsk_thread_flag(task, TIF_BLOCKSTEP)) | ||
690 | set_task_blockstep(task, false); | ||
691 | } | ||
692 | |||
693 | void arch_uprobe_disable_step(struct arch_uprobe *auprobe) | ||
694 | { | ||
695 | struct task_struct *task = current; | ||
696 | struct arch_uprobe_task *autask = &task->utask->autask; | ||
697 | bool trapped = (task->utask->state == UTASK_SSTEP_TRAPPED); | ||
698 | struct pt_regs *regs = task_pt_regs(task); | ||
699 | /* | ||
700 | * The state of TIF_BLOCKSTEP was not saved so we can get an extra | ||
701 | * SIGTRAP if we do not clear TF. We need to examine the opcode to | ||
702 | * make it right. | ||
703 | */ | ||
704 | if (unlikely(trapped)) { | ||
705 | if (!autask->saved_tf) | ||
706 | regs->flags &= ~X86_EFLAGS_TF; | ||
707 | } else { | ||
708 | if (autask->saved_tf) | ||
709 | send_sig(SIGTRAP, task, 0); | ||
710 | else if (!(auprobe->fixups & UPROBE_FIX_SETF)) | ||
711 | regs->flags &= ~X86_EFLAGS_TF; | ||
712 | } | ||
713 | } | ||