12b144498SSrikar Dronamraju #ifndef _LINUX_UPROBES_H 22b144498SSrikar Dronamraju #define _LINUX_UPROBES_H 32b144498SSrikar Dronamraju /* 47b2d81d4SIngo Molnar * User-space Probes (UProbes) 52b144498SSrikar Dronamraju * 62b144498SSrikar Dronamraju * This program is free software; you can redistribute it and/or modify 72b144498SSrikar Dronamraju * it under the terms of the GNU General Public License as published by 82b144498SSrikar Dronamraju * the Free Software Foundation; either version 2 of the License, or 92b144498SSrikar Dronamraju * (at your option) any later version. 102b144498SSrikar Dronamraju * 112b144498SSrikar Dronamraju * This program is distributed in the hope that it will be useful, 122b144498SSrikar Dronamraju * but WITHOUT ANY WARRANTY; without even the implied warranty of 132b144498SSrikar Dronamraju * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 142b144498SSrikar Dronamraju * GNU General Public License for more details. 152b144498SSrikar Dronamraju * 162b144498SSrikar Dronamraju * You should have received a copy of the GNU General Public License 172b144498SSrikar Dronamraju * along with this program; if not, write to the Free Software 182b144498SSrikar Dronamraju * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 192b144498SSrikar Dronamraju * 2035aa621bSIngo Molnar * Copyright (C) IBM Corporation, 2008-2012 212b144498SSrikar Dronamraju * Authors: 222b144498SSrikar Dronamraju * Srikar Dronamraju 232b144498SSrikar Dronamraju * Jim Keniston 2435aa621bSIngo Molnar * Copyright (C) 2011-2012 Red Hat, Inc., Peter Zijlstra <pzijlstr@redhat.com> 252b144498SSrikar Dronamraju */ 262b144498SSrikar Dronamraju 272b144498SSrikar Dronamraju #include <linux/errno.h> 282b144498SSrikar Dronamraju #include <linux/rbtree.h> 2932473431SOleg Nesterov #include <linux/types.h> 302b144498SSrikar Dronamraju 312b144498SSrikar Dronamraju struct vm_area_struct; 32d4b3b638SSrikar Dronamraju struct mm_struct; 33d4b3b638SSrikar Dronamraju struct inode; 343820b4d2SDavid A. Long struct notifier_block; 3572e6ae28SVictor Kamensky struct page; 360326f5a9SSrikar Dronamraju 37da1816b1SOleg Nesterov #define UPROBE_HANDLER_REMOVE 1 38da1816b1SOleg Nesterov #define UPROBE_HANDLER_MASK 1 39da1816b1SOleg Nesterov 40ded49c55SAnton Arapov #define MAX_URETPROBE_DEPTH 64 41ded49c55SAnton Arapov 428a7f2fa0SOleg Nesterov enum uprobe_filter_ctx { 438a7f2fa0SOleg Nesterov UPROBE_FILTER_REGISTER, 448a7f2fa0SOleg Nesterov UPROBE_FILTER_UNREGISTER, 458a7f2fa0SOleg Nesterov UPROBE_FILTER_MMAP, 468a7f2fa0SOleg Nesterov }; 478a7f2fa0SOleg Nesterov 482b144498SSrikar Dronamraju struct uprobe_consumer { 492b144498SSrikar Dronamraju int (*handler)(struct uprobe_consumer *self, struct pt_regs *regs); 50ea024870SAnton Arapov int (*ret_handler)(struct uprobe_consumer *self, 51ea024870SAnton Arapov unsigned long func, 52ea024870SAnton Arapov struct pt_regs *regs); 538a7f2fa0SOleg Nesterov bool (*filter)(struct uprobe_consumer *self, 548a7f2fa0SOleg Nesterov enum uprobe_filter_ctx ctx, 558a7f2fa0SOleg Nesterov struct mm_struct *mm); 562b144498SSrikar Dronamraju 572b144498SSrikar Dronamraju struct uprobe_consumer *next; 582b144498SSrikar Dronamraju }; 592b144498SSrikar Dronamraju 602b144498SSrikar Dronamraju #ifdef CONFIG_UPROBES 61c912dae6SOleg Nesterov #include <asm/uprobes.h> 62c912dae6SOleg Nesterov 630326f5a9SSrikar Dronamraju enum uprobe_task_state { 640326f5a9SSrikar Dronamraju UTASK_RUNNING, 650326f5a9SSrikar Dronamraju UTASK_SSTEP, 660326f5a9SSrikar Dronamraju UTASK_SSTEP_ACK, 670326f5a9SSrikar Dronamraju UTASK_SSTEP_TRAPPED, 680326f5a9SSrikar Dronamraju }; 690326f5a9SSrikar Dronamraju 700326f5a9SSrikar Dronamraju /* 710326f5a9SSrikar Dronamraju * uprobe_task: Metadata of a task while it singlesteps. 720326f5a9SSrikar Dronamraju */ 730326f5a9SSrikar Dronamraju struct uprobe_task { 740326f5a9SSrikar Dronamraju enum uprobe_task_state state; 7532473431SOleg Nesterov 7632473431SOleg Nesterov union { 7732473431SOleg Nesterov struct { 780326f5a9SSrikar Dronamraju struct arch_uprobe_task autask; 7932473431SOleg Nesterov unsigned long vaddr; 8032473431SOleg Nesterov }; 8132473431SOleg Nesterov 8232473431SOleg Nesterov struct { 8332473431SOleg Nesterov struct callback_head dup_xol_work; 8432473431SOleg Nesterov unsigned long dup_xol_addr; 8532473431SOleg Nesterov }; 8632473431SOleg Nesterov }; 8732473431SOleg Nesterov 8832473431SOleg Nesterov struct uprobe *active_uprobe; 8932473431SOleg Nesterov unsigned long xol_vaddr; 900326f5a9SSrikar Dronamraju 910dfd0eb8SAnton Arapov struct return_instance *return_instances; 92ded49c55SAnton Arapov unsigned int depth; 930326f5a9SSrikar Dronamraju }; 940326f5a9SSrikar Dronamraju 95*97da8976SOleg Nesterov struct return_instance { 96*97da8976SOleg Nesterov struct uprobe *uprobe; 97*97da8976SOleg Nesterov unsigned long func; 98*97da8976SOleg Nesterov unsigned long orig_ret_vaddr; /* original return address */ 99*97da8976SOleg Nesterov bool chained; /* true, if instance is nested */ 100*97da8976SOleg Nesterov 101*97da8976SOleg Nesterov struct return_instance *next; /* keep as stack */ 102*97da8976SOleg Nesterov }; 103*97da8976SOleg Nesterov 104c912dae6SOleg Nesterov struct xol_area; 105d4b3b638SSrikar Dronamraju 106d4b3b638SSrikar Dronamraju struct uprobes_state { 107d4b3b638SSrikar Dronamraju struct xol_area *xol_area; 108d4b3b638SSrikar Dronamraju }; 109647c42dfSOleg Nesterov 110271a9c35SBjorn Helgaas extern int set_swbp(struct arch_uprobe *aup, struct mm_struct *mm, unsigned long vaddr); 111271a9c35SBjorn Helgaas extern int set_orig_insn(struct arch_uprobe *aup, struct mm_struct *mm, unsigned long vaddr); 112271a9c35SBjorn Helgaas extern bool is_swbp_insn(uprobe_opcode_t *insn); 113271a9c35SBjorn Helgaas extern bool is_trap_insn(uprobe_opcode_t *insn); 114271a9c35SBjorn Helgaas extern unsigned long uprobe_get_swbp_addr(struct pt_regs *regs); 115b02ef20aSOleg Nesterov extern unsigned long uprobe_get_trap_addr(struct pt_regs *regs); 116f72d41faSOleg Nesterov extern int uprobe_write_opcode(struct mm_struct *mm, unsigned long vaddr, uprobe_opcode_t); 117e3343e6aSSrikar Dronamraju extern int uprobe_register(struct inode *inode, loff_t offset, struct uprobe_consumer *uc); 118bdf8647cSOleg Nesterov extern int uprobe_apply(struct inode *inode, loff_t offset, struct uprobe_consumer *uc, bool); 119e3343e6aSSrikar Dronamraju extern void uprobe_unregister(struct inode *inode, loff_t offset, struct uprobe_consumer *uc); 1207b2d81d4SIngo Molnar extern int uprobe_mmap(struct vm_area_struct *vma); 121cbc91f71SSrikar Dronamraju extern void uprobe_munmap(struct vm_area_struct *vma, unsigned long start, unsigned long end); 12232cdba1eSOleg Nesterov extern void uprobe_start_dup_mmap(void); 12332cdba1eSOleg Nesterov extern void uprobe_end_dup_mmap(void); 124f8ac4ec9SOleg Nesterov extern void uprobe_dup_mmap(struct mm_struct *oldmm, struct mm_struct *newmm); 1250326f5a9SSrikar Dronamraju extern void uprobe_free_utask(struct task_struct *t); 1263ab67966SOleg Nesterov extern void uprobe_copy_process(struct task_struct *t, unsigned long flags); 1270326f5a9SSrikar Dronamraju extern int uprobe_post_sstep_notifier(struct pt_regs *regs); 1280326f5a9SSrikar Dronamraju extern int uprobe_pre_sstep_notifier(struct pt_regs *regs); 1290326f5a9SSrikar Dronamraju extern void uprobe_notify_resume(struct pt_regs *regs); 1300326f5a9SSrikar Dronamraju extern bool uprobe_deny_signal(void); 131c2d3f25dSRalf Baechle extern bool arch_uprobe_skip_sstep(struct arch_uprobe *aup, struct pt_regs *regs); 132d4b3b638SSrikar Dronamraju extern void uprobe_clear_state(struct mm_struct *mm); 1333820b4d2SDavid A. Long extern int arch_uprobe_analyze_insn(struct arch_uprobe *aup, struct mm_struct *mm, unsigned long addr); 1343820b4d2SDavid A. Long extern int arch_uprobe_pre_xol(struct arch_uprobe *aup, struct pt_regs *regs); 1353820b4d2SDavid A. Long extern int arch_uprobe_post_xol(struct arch_uprobe *aup, struct pt_regs *regs); 1363820b4d2SDavid A. Long extern bool arch_uprobe_xol_was_trapped(struct task_struct *tsk); 1373820b4d2SDavid A. Long extern int arch_uprobe_exception_notify(struct notifier_block *self, unsigned long val, void *data); 1383820b4d2SDavid A. Long extern void arch_uprobe_abort_xol(struct arch_uprobe *aup, struct pt_regs *regs); 1393820b4d2SDavid A. Long extern unsigned long arch_uretprobe_hijack_return_addr(unsigned long trampoline_vaddr, struct pt_regs *regs); 140*97da8976SOleg Nesterov extern bool arch_uretprobe_is_alive(struct return_instance *ret, struct pt_regs *regs); 141271a9c35SBjorn Helgaas extern bool arch_uprobe_ignore(struct arch_uprobe *aup, struct pt_regs *regs); 142271a9c35SBjorn Helgaas extern void arch_uprobe_copy_ixol(struct page *page, unsigned long vaddr, 14372e6ae28SVictor Kamensky void *src, unsigned long len); 1440326f5a9SSrikar Dronamraju #else /* !CONFIG_UPROBES */ 145d4b3b638SSrikar Dronamraju struct uprobes_state { 146d4b3b638SSrikar Dronamraju }; 147b02ef20aSOleg Nesterov 148b02ef20aSOleg Nesterov #define uprobe_get_trap_addr(regs) instruction_pointer(regs) 149b02ef20aSOleg Nesterov 1507b2d81d4SIngo Molnar static inline int 151e3343e6aSSrikar Dronamraju uprobe_register(struct inode *inode, loff_t offset, struct uprobe_consumer *uc) 1522b144498SSrikar Dronamraju { 1532b144498SSrikar Dronamraju return -ENOSYS; 1542b144498SSrikar Dronamraju } 155bdf8647cSOleg Nesterov static inline int 156bdf8647cSOleg Nesterov uprobe_apply(struct inode *inode, loff_t offset, struct uprobe_consumer *uc, bool add) 157bdf8647cSOleg Nesterov { 158bdf8647cSOleg Nesterov return -ENOSYS; 159bdf8647cSOleg Nesterov } 1607b2d81d4SIngo Molnar static inline void 161e3343e6aSSrikar Dronamraju uprobe_unregister(struct inode *inode, loff_t offset, struct uprobe_consumer *uc) 1622b144498SSrikar Dronamraju { 1632b144498SSrikar Dronamraju } 1647b2d81d4SIngo Molnar static inline int uprobe_mmap(struct vm_area_struct *vma) 1652b144498SSrikar Dronamraju { 1662b144498SSrikar Dronamraju return 0; 1672b144498SSrikar Dronamraju } 168cbc91f71SSrikar Dronamraju static inline void 169cbc91f71SSrikar Dronamraju uprobe_munmap(struct vm_area_struct *vma, unsigned long start, unsigned long end) 170682968e0SSrikar Dronamraju { 171682968e0SSrikar Dronamraju } 17232cdba1eSOleg Nesterov static inline void uprobe_start_dup_mmap(void) 17332cdba1eSOleg Nesterov { 17432cdba1eSOleg Nesterov } 17532cdba1eSOleg Nesterov static inline void uprobe_end_dup_mmap(void) 17632cdba1eSOleg Nesterov { 17732cdba1eSOleg Nesterov } 178f8ac4ec9SOleg Nesterov static inline void 179f8ac4ec9SOleg Nesterov uprobe_dup_mmap(struct mm_struct *oldmm, struct mm_struct *newmm) 180f8ac4ec9SOleg Nesterov { 181f8ac4ec9SOleg Nesterov } 1820326f5a9SSrikar Dronamraju static inline void uprobe_notify_resume(struct pt_regs *regs) 1830326f5a9SSrikar Dronamraju { 1840326f5a9SSrikar Dronamraju } 1850326f5a9SSrikar Dronamraju static inline bool uprobe_deny_signal(void) 1860326f5a9SSrikar Dronamraju { 1870326f5a9SSrikar Dronamraju return false; 1880326f5a9SSrikar Dronamraju } 1890326f5a9SSrikar Dronamraju static inline void uprobe_free_utask(struct task_struct *t) 1900326f5a9SSrikar Dronamraju { 1910326f5a9SSrikar Dronamraju } 1923ab67966SOleg Nesterov static inline void uprobe_copy_process(struct task_struct *t, unsigned long flags) 1930326f5a9SSrikar Dronamraju { 1940326f5a9SSrikar Dronamraju } 195d4b3b638SSrikar Dronamraju static inline void uprobe_clear_state(struct mm_struct *mm) 196d4b3b638SSrikar Dronamraju { 197d4b3b638SSrikar Dronamraju } 1980326f5a9SSrikar Dronamraju #endif /* !CONFIG_UPROBES */ 1992b144498SSrikar Dronamraju #endif /* _LINUX_UPROBES_H */ 200