diff options
author | Oleg Nesterov <oleg@redhat.com> | 2012-09-30 14:11:45 -0400 |
---|---|---|
committer | Oleg Nesterov <oleg@redhat.com> | 2012-10-07 15:19:42 -0400 |
commit | cb9a19fe4aa51afa34786bd383e6614fa0083d58 (patch) | |
tree | e85fac9d3a69707cd9c3a98361f5cba845d5d260 /kernel/events/uprobes.c | |
parent | 142b18ddc81439acda4bc4231b291e99fe67d507 (diff) |
uprobes: Introduce prepare_uprobe()
Preparation. Extract the copy_insn/arch_uprobe_analyze_insn code
from install_breakpoint() into the new helper, prepare_uprobe().
And move uprobe->flags defines from uprobes.h to uprobes.c, nobody
else can use them anyway.
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Acked-by: Srikar Dronamraju <srikar@linux.vnet.ibm.com>
Diffstat (limited to 'kernel/events/uprobes.c')
-rw-r--r-- | kernel/events/uprobes.c | 60 |
1 files changed, 41 insertions, 19 deletions
diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c index c718fef28617..4f315fa94c52 100644 --- a/kernel/events/uprobes.c +++ b/kernel/events/uprobes.c | |||
@@ -78,6 +78,13 @@ static struct mutex uprobes_mmap_mutex[UPROBES_HASH_SZ]; | |||
78 | */ | 78 | */ |
79 | static atomic_t uprobe_events = ATOMIC_INIT(0); | 79 | static atomic_t uprobe_events = ATOMIC_INIT(0); |
80 | 80 | ||
81 | /* Have a copy of original instruction */ | ||
82 | #define UPROBE_COPY_INSN 0x1 | ||
83 | /* Dont run handlers when first register/ last unregister in progress*/ | ||
84 | #define UPROBE_RUN_HANDLER 0x2 | ||
85 | /* Can skip singlestep */ | ||
86 | #define UPROBE_SKIP_SSTEP 0x4 | ||
87 | |||
81 | struct uprobe { | 88 | struct uprobe { |
82 | struct rb_node rb_node; /* node in the rb tree */ | 89 | struct rb_node rb_node; /* node in the rb tree */ |
83 | atomic_t ref; | 90 | atomic_t ref; |
@@ -563,6 +570,37 @@ static int copy_insn(struct uprobe *uprobe, struct file *filp) | |||
563 | return __copy_insn(mapping, filp, uprobe->arch.insn, bytes, uprobe->offset); | 570 | return __copy_insn(mapping, filp, uprobe->arch.insn, bytes, uprobe->offset); |
564 | } | 571 | } |
565 | 572 | ||
573 | static int prepare_uprobe(struct uprobe *uprobe, struct file *file, | ||
574 | struct mm_struct *mm, unsigned long vaddr) | ||
575 | { | ||
576 | int ret = 0; | ||
577 | |||
578 | if (uprobe->flags & UPROBE_COPY_INSN) | ||
579 | return ret; | ||
580 | |||
581 | ret = copy_insn(uprobe, file); | ||
582 | if (ret) | ||
583 | goto out; | ||
584 | |||
585 | ret = -ENOTSUPP; | ||
586 | if (is_swbp_insn((uprobe_opcode_t *)uprobe->arch.insn)) | ||
587 | goto out; | ||
588 | |||
589 | ret = arch_uprobe_analyze_insn(&uprobe->arch, mm, vaddr); | ||
590 | if (ret) | ||
591 | goto out; | ||
592 | |||
593 | /* write_opcode() assumes we don't cross page boundary */ | ||
594 | BUG_ON((uprobe->offset & ~PAGE_MASK) + | ||
595 | UPROBE_SWBP_INSN_SIZE > PAGE_SIZE); | ||
596 | |||
597 | smp_wmb(); /* pairs with rmb() in find_active_uprobe() */ | ||
598 | uprobe->flags |= UPROBE_COPY_INSN; | ||
599 | |||
600 | out: | ||
601 | return ret; | ||
602 | } | ||
603 | |||
566 | static int | 604 | static int |
567 | install_breakpoint(struct uprobe *uprobe, struct mm_struct *mm, | 605 | install_breakpoint(struct uprobe *uprobe, struct mm_struct *mm, |
568 | struct vm_area_struct *vma, unsigned long vaddr) | 606 | struct vm_area_struct *vma, unsigned long vaddr) |
@@ -580,25 +618,9 @@ install_breakpoint(struct uprobe *uprobe, struct mm_struct *mm, | |||
580 | if (!uprobe->consumers) | 618 | if (!uprobe->consumers) |
581 | return 0; | 619 | return 0; |
582 | 620 | ||
583 | if (!(uprobe->flags & UPROBE_COPY_INSN)) { | 621 | ret = prepare_uprobe(uprobe, vma->vm_file, mm, vaddr); |
584 | ret = copy_insn(uprobe, vma->vm_file); | 622 | if (ret) |
585 | if (ret) | 623 | return ret; |
586 | return ret; | ||
587 | |||
588 | if (is_swbp_insn((uprobe_opcode_t *)uprobe->arch.insn)) | ||
589 | return -ENOTSUPP; | ||
590 | |||
591 | ret = arch_uprobe_analyze_insn(&uprobe->arch, mm, vaddr); | ||
592 | if (ret) | ||
593 | return ret; | ||
594 | |||
595 | /* write_opcode() assumes we don't cross page boundary */ | ||
596 | BUG_ON((uprobe->offset & ~PAGE_MASK) + | ||
597 | UPROBE_SWBP_INSN_SIZE > PAGE_SIZE); | ||
598 | |||
599 | smp_wmb(); /* pairs with rmb() in find_active_uprobe() */ | ||
600 | uprobe->flags |= UPROBE_COPY_INSN; | ||
601 | } | ||
602 | 624 | ||
603 | /* | 625 | /* |
604 | * set MMF_HAS_UPROBES in advance for uprobe_pre_sstep_notifier(), | 626 | * set MMF_HAS_UPROBES in advance for uprobe_pre_sstep_notifier(), |