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>
This commit is contained in:
parent
142b18ddc8
commit
cb9a19fe4a
|
@ -35,16 +35,6 @@ struct inode;
|
||||||
# include <asm/uprobes.h>
|
# include <asm/uprobes.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* flags that denote/change uprobes behaviour */
|
|
||||||
|
|
||||||
/* Have a copy of original instruction */
|
|
||||||
#define UPROBE_COPY_INSN 0x1
|
|
||||||
|
|
||||||
/* Dont run handlers when first register/ last unregister in progress*/
|
|
||||||
#define UPROBE_RUN_HANDLER 0x2
|
|
||||||
/* Can skip singlestep */
|
|
||||||
#define UPROBE_SKIP_SSTEP 0x4
|
|
||||||
|
|
||||||
struct uprobe_consumer {
|
struct uprobe_consumer {
|
||||||
int (*handler)(struct uprobe_consumer *self, struct pt_regs *regs);
|
int (*handler)(struct uprobe_consumer *self, struct pt_regs *regs);
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -78,6 +78,13 @@ static struct mutex uprobes_mmap_mutex[UPROBES_HASH_SZ];
|
||||||
*/
|
*/
|
||||||
static atomic_t uprobe_events = ATOMIC_INIT(0);
|
static atomic_t uprobe_events = ATOMIC_INIT(0);
|
||||||
|
|
||||||
|
/* Have a copy of original instruction */
|
||||||
|
#define UPROBE_COPY_INSN 0x1
|
||||||
|
/* Dont run handlers when first register/ last unregister in progress*/
|
||||||
|
#define UPROBE_RUN_HANDLER 0x2
|
||||||
|
/* Can skip singlestep */
|
||||||
|
#define UPROBE_SKIP_SSTEP 0x4
|
||||||
|
|
||||||
struct uprobe {
|
struct uprobe {
|
||||||
struct rb_node rb_node; /* node in the rb tree */
|
struct rb_node rb_node; /* node in the rb tree */
|
||||||
atomic_t ref;
|
atomic_t ref;
|
||||||
|
@ -563,6 +570,37 @@ static int copy_insn(struct uprobe *uprobe, struct file *filp)
|
||||||
return __copy_insn(mapping, filp, uprobe->arch.insn, bytes, uprobe->offset);
|
return __copy_insn(mapping, filp, uprobe->arch.insn, bytes, uprobe->offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int prepare_uprobe(struct uprobe *uprobe, struct file *file,
|
||||||
|
struct mm_struct *mm, unsigned long vaddr)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
if (uprobe->flags & UPROBE_COPY_INSN)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
ret = copy_insn(uprobe, file);
|
||||||
|
if (ret)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
ret = -ENOTSUPP;
|
||||||
|
if (is_swbp_insn((uprobe_opcode_t *)uprobe->arch.insn))
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
ret = arch_uprobe_analyze_insn(&uprobe->arch, mm, vaddr);
|
||||||
|
if (ret)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
/* write_opcode() assumes we don't cross page boundary */
|
||||||
|
BUG_ON((uprobe->offset & ~PAGE_MASK) +
|
||||||
|
UPROBE_SWBP_INSN_SIZE > PAGE_SIZE);
|
||||||
|
|
||||||
|
smp_wmb(); /* pairs with rmb() in find_active_uprobe() */
|
||||||
|
uprobe->flags |= UPROBE_COPY_INSN;
|
||||||
|
|
||||||
|
out:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
install_breakpoint(struct uprobe *uprobe, struct mm_struct *mm,
|
install_breakpoint(struct uprobe *uprobe, struct mm_struct *mm,
|
||||||
struct vm_area_struct *vma, unsigned long vaddr)
|
struct vm_area_struct *vma, unsigned long vaddr)
|
||||||
|
@ -580,25 +618,9 @@ install_breakpoint(struct uprobe *uprobe, struct mm_struct *mm,
|
||||||
if (!uprobe->consumers)
|
if (!uprobe->consumers)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (!(uprobe->flags & UPROBE_COPY_INSN)) {
|
ret = prepare_uprobe(uprobe, vma->vm_file, mm, vaddr);
|
||||||
ret = copy_insn(uprobe, vma->vm_file);
|
if (ret)
|
||||||
if (ret)
|
return ret;
|
||||||
return ret;
|
|
||||||
|
|
||||||
if (is_swbp_insn((uprobe_opcode_t *)uprobe->arch.insn))
|
|
||||||
return -ENOTSUPP;
|
|
||||||
|
|
||||||
ret = arch_uprobe_analyze_insn(&uprobe->arch, mm, vaddr);
|
|
||||||
if (ret)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
/* write_opcode() assumes we don't cross page boundary */
|
|
||||||
BUG_ON((uprobe->offset & ~PAGE_MASK) +
|
|
||||||
UPROBE_SWBP_INSN_SIZE > PAGE_SIZE);
|
|
||||||
|
|
||||||
smp_wmb(); /* pairs with rmb() in find_active_uprobe() */
|
|
||||||
uprobe->flags |= UPROBE_COPY_INSN;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* set MMF_HAS_UPROBES in advance for uprobe_pre_sstep_notifier(),
|
* set MMF_HAS_UPROBES in advance for uprobe_pre_sstep_notifier(),
|
||||||
|
|
Loading…
Reference in New Issue