diff options
author | Oleg Nesterov <oleg@redhat.com> | 2014-04-25 12:53:32 -0400 |
---|---|---|
committer | Oleg Nesterov <oleg@redhat.com> | 2014-04-30 13:10:40 -0400 |
commit | 83cd591485e558ab70aed45ce7261ce3f5ee8746 (patch) | |
tree | 7ab3da68050aaeba3646426a3a7db3947d3bf673 /arch | |
parent | 1dc76e6eacef271230d9ff6fd0f91824bda03f44 (diff) |
uprobes/x86: Cleanup the usage of UPROBE_FIX_IP/UPROBE_FIX_CALL
Now that UPROBE_FIX_IP/UPROBE_FIX_CALL are mutually exclusive we can
use a single "fix_ip_or_call" enum instead of 2 fix_* booleans. This
way the logic looks more understandable and clean to me.
While at it, join "case 0xea" with other "ip is correct" ret/lret cases.
Also change default_post_xol_op() to use "else if" for the same reason.
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/x86/kernel/uprobes.c | 27 |
1 files changed, 11 insertions, 16 deletions
diff --git a/arch/x86/kernel/uprobes.c b/arch/x86/kernel/uprobes.c index 5bcce852628a..d2792e884d54 100644 --- a/arch/x86/kernel/uprobes.c +++ b/arch/x86/kernel/uprobes.c | |||
@@ -424,10 +424,9 @@ static int default_post_xol_op(struct arch_uprobe *auprobe, struct pt_regs *regs | |||
424 | long correction = (long)(utask->vaddr - utask->xol_vaddr); | 424 | long correction = (long)(utask->vaddr - utask->xol_vaddr); |
425 | 425 | ||
426 | handle_riprel_post_xol(auprobe, regs, &correction); | 426 | handle_riprel_post_xol(auprobe, regs, &correction); |
427 | if (auprobe->def.fixups & UPROBE_FIX_IP) | 427 | if (auprobe->def.fixups & UPROBE_FIX_IP) { |
428 | regs->ip += correction; | 428 | regs->ip += correction; |
429 | 429 | } else if (auprobe->def.fixups & UPROBE_FIX_CALL) { | |
430 | if (auprobe->def.fixups & UPROBE_FIX_CALL) { | ||
431 | regs->sp += sizeof_long(); | 430 | regs->sp += sizeof_long(); |
432 | if (push_ret_address(regs, utask->vaddr + auprobe->def.ilen)) | 431 | if (push_ret_address(regs, utask->vaddr + auprobe->def.ilen)) |
433 | return -ERESTART; | 432 | return -ERESTART; |
@@ -623,7 +622,7 @@ static int branch_setup_xol_ops(struct arch_uprobe *auprobe, struct insn *insn) | |||
623 | int arch_uprobe_analyze_insn(struct arch_uprobe *auprobe, struct mm_struct *mm, unsigned long addr) | 622 | int arch_uprobe_analyze_insn(struct arch_uprobe *auprobe, struct mm_struct *mm, unsigned long addr) |
624 | { | 623 | { |
625 | struct insn insn; | 624 | struct insn insn; |
626 | bool fix_ip = true, fix_call = false; | 625 | u8 fix_ip_or_call = UPROBE_FIX_IP; |
627 | int ret; | 626 | int ret; |
628 | 627 | ||
629 | ret = uprobe_init_insn(auprobe, &insn, is_64bit_mm(mm)); | 628 | ret = uprobe_init_insn(auprobe, &insn, is_64bit_mm(mm)); |
@@ -647,21 +646,20 @@ int arch_uprobe_analyze_insn(struct arch_uprobe *auprobe, struct mm_struct *mm, | |||
647 | case 0xcb: | 646 | case 0xcb: |
648 | case 0xc2: | 647 | case 0xc2: |
649 | case 0xca: | 648 | case 0xca: |
650 | fix_ip = false; | 649 | case 0xea: /* jmp absolute -- ip is correct */ |
650 | fix_ip_or_call = 0; | ||
651 | break; | 651 | break; |
652 | case 0x9a: /* call absolute - Fix return addr, not ip */ | 652 | case 0x9a: /* call absolute - Fix return addr, not ip */ |
653 | fix_call = true; | 653 | fix_ip_or_call = UPROBE_FIX_CALL; |
654 | fix_ip = false; | ||
655 | break; | ||
656 | case 0xea: /* jmp absolute -- ip is correct */ | ||
657 | fix_ip = false; | ||
658 | break; | 654 | break; |
659 | case 0xff: | 655 | case 0xff: |
660 | switch (MODRM_REG(&insn)) { | 656 | switch (MODRM_REG(&insn)) { |
661 | case 2: case 3: /* call or lcall, indirect */ | 657 | case 2: case 3: /* call or lcall, indirect */ |
662 | fix_call = true; | 658 | fix_ip_or_call = UPROBE_FIX_CALL; |
659 | break; | ||
663 | case 4: case 5: /* jmp or ljmp, indirect */ | 660 | case 4: case 5: /* jmp or ljmp, indirect */ |
664 | fix_ip = false; | 661 | fix_ip_or_call = 0; |
662 | break; | ||
665 | } | 663 | } |
666 | /* fall through */ | 664 | /* fall through */ |
667 | default: | 665 | default: |
@@ -669,10 +667,7 @@ int arch_uprobe_analyze_insn(struct arch_uprobe *auprobe, struct mm_struct *mm, | |||
669 | } | 667 | } |
670 | 668 | ||
671 | auprobe->def.ilen = insn.length; | 669 | auprobe->def.ilen = insn.length; |
672 | if (fix_ip) | 670 | auprobe->def.fixups |= fix_ip_or_call; |
673 | auprobe->def.fixups |= UPROBE_FIX_IP; | ||
674 | if (fix_call) | ||
675 | auprobe->def.fixups |= UPROBE_FIX_CALL; | ||
676 | 671 | ||
677 | auprobe->ops = &default_xol_ops; | 672 | auprobe->ops = &default_xol_ops; |
678 | return 0; | 673 | return 0; |