diff options
author | Oleg Nesterov <oleg@redhat.com> | 2014-03-31 13:38:09 -0400 |
---|---|---|
committer | Oleg Nesterov <oleg@redhat.com> | 2014-04-17 15:58:18 -0400 |
commit | 34e7317d6ae8f6111ac449444f22e14f4a14ebfd (patch) | |
tree | 06a98d253f4c9de9ae8f4af73209727ec2a1589e /arch/x86/kernel/uprobes.c | |
parent | d20737c07a1063d681fe9fb86f3da369da1edab7 (diff) |
uprobes/x86: move the UPROBE_FIX_{RIP,IP,CALL} code at the end of pre/post hooks
No functional changes. Preparation to simplify the review of the next
change. Just reorder the code in arch_uprobe_pre/post_xol() functions
so that UPROBE_FIX_{RIP_*,IP,CALL} logic goes to the end.
Also change arch_uprobe_pre_xol() to use utask instead of autask, to
make the code more symmetrical with arch_uprobe_post_xol().
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Reviewed-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Reviewed-by: Jim Keniston <jkenisto@us.ibm.com>
Acked-by: Srikar Dronamraju <srikar@linux.vnet.ibm.com>
Diffstat (limited to 'arch/x86/kernel/uprobes.c')
-rw-r--r-- | arch/x86/kernel/uprobes.c | 30 |
1 files changed, 14 insertions, 16 deletions
diff --git a/arch/x86/kernel/uprobes.c b/arch/x86/kernel/uprobes.c index c52c30fa7871..3bb4198aa588 100644 --- a/arch/x86/kernel/uprobes.c +++ b/arch/x86/kernel/uprobes.c | |||
@@ -474,19 +474,18 @@ int arch_uprobe_analyze_insn(struct arch_uprobe *auprobe, struct mm_struct *mm, | |||
474 | */ | 474 | */ |
475 | int arch_uprobe_pre_xol(struct arch_uprobe *auprobe, struct pt_regs *regs) | 475 | int arch_uprobe_pre_xol(struct arch_uprobe *auprobe, struct pt_regs *regs) |
476 | { | 476 | { |
477 | struct arch_uprobe_task *autask; | 477 | struct uprobe_task *utask = current->utask; |
478 | 478 | ||
479 | autask = ¤t->utask->autask; | 479 | regs->ip = utask->xol_vaddr; |
480 | autask->saved_trap_nr = current->thread.trap_nr; | 480 | utask->autask.saved_trap_nr = current->thread.trap_nr; |
481 | current->thread.trap_nr = UPROBE_TRAP_NR; | 481 | current->thread.trap_nr = UPROBE_TRAP_NR; |
482 | regs->ip = current->utask->xol_vaddr; | ||
483 | pre_xol_rip_insn(auprobe, regs, autask); | ||
484 | 482 | ||
485 | autask->saved_tf = !!(regs->flags & X86_EFLAGS_TF); | 483 | utask->autask.saved_tf = !!(regs->flags & X86_EFLAGS_TF); |
486 | regs->flags |= X86_EFLAGS_TF; | 484 | regs->flags |= X86_EFLAGS_TF; |
487 | if (test_tsk_thread_flag(current, TIF_BLOCKSTEP)) | 485 | if (test_tsk_thread_flag(current, TIF_BLOCKSTEP)) |
488 | set_task_blockstep(current, false); | 486 | set_task_blockstep(current, false); |
489 | 487 | ||
488 | pre_xol_rip_insn(auprobe, regs, &utask->autask); | ||
490 | return 0; | 489 | return 0; |
491 | } | 490 | } |
492 | 491 | ||
@@ -560,22 +559,13 @@ bool arch_uprobe_xol_was_trapped(struct task_struct *t) | |||
560 | */ | 559 | */ |
561 | int arch_uprobe_post_xol(struct arch_uprobe *auprobe, struct pt_regs *regs) | 560 | int arch_uprobe_post_xol(struct arch_uprobe *auprobe, struct pt_regs *regs) |
562 | { | 561 | { |
563 | struct uprobe_task *utask; | 562 | struct uprobe_task *utask = current->utask; |
564 | long correction; | 563 | long correction; |
565 | int result = 0; | 564 | int result = 0; |
566 | 565 | ||
567 | WARN_ON_ONCE(current->thread.trap_nr != UPROBE_TRAP_NR); | 566 | WARN_ON_ONCE(current->thread.trap_nr != UPROBE_TRAP_NR); |
568 | 567 | ||
569 | utask = current->utask; | ||
570 | current->thread.trap_nr = utask->autask.saved_trap_nr; | 568 | current->thread.trap_nr = utask->autask.saved_trap_nr; |
571 | correction = (long)(utask->vaddr - utask->xol_vaddr); | ||
572 | handle_riprel_post_xol(auprobe, regs, &correction); | ||
573 | if (auprobe->fixups & UPROBE_FIX_IP) | ||
574 | regs->ip += correction; | ||
575 | |||
576 | if (auprobe->fixups & UPROBE_FIX_CALL) | ||
577 | result = adjust_ret_addr(regs->sp, correction); | ||
578 | |||
579 | /* | 569 | /* |
580 | * arch_uprobe_pre_xol() doesn't save the state of TIF_BLOCKSTEP | 570 | * arch_uprobe_pre_xol() doesn't save the state of TIF_BLOCKSTEP |
581 | * so we can get an extra SIGTRAP if we do not clear TF. We need | 571 | * so we can get an extra SIGTRAP if we do not clear TF. We need |
@@ -586,6 +576,14 @@ int arch_uprobe_post_xol(struct arch_uprobe *auprobe, struct pt_regs *regs) | |||
586 | else if (!(auprobe->fixups & UPROBE_FIX_SETF)) | 576 | else if (!(auprobe->fixups & UPROBE_FIX_SETF)) |
587 | regs->flags &= ~X86_EFLAGS_TF; | 577 | regs->flags &= ~X86_EFLAGS_TF; |
588 | 578 | ||
579 | correction = (long)(utask->vaddr - utask->xol_vaddr); | ||
580 | handle_riprel_post_xol(auprobe, regs, &correction); | ||
581 | if (auprobe->fixups & UPROBE_FIX_IP) | ||
582 | regs->ip += correction; | ||
583 | |||
584 | if (auprobe->fixups & UPROBE_FIX_CALL) | ||
585 | result = adjust_ret_addr(regs->sp, correction); | ||
586 | |||
589 | return result; | 587 | return result; |
590 | } | 588 | } |
591 | 589 | ||