]> nv-tegra.nvidia Code Review - linux-2.6.git/blobdiff - include/linux/ptrace.h
regulator: tps65090: convert regualtor_init_data as pointer
[linux-2.6.git] / include / linux / ptrace.h
index f98501ba557eea676a827aed770d57b0b4b12c56..800f113bea66382fd16dc28c85eeae34e44761b0 100644 (file)
 #define PTRACE_GETSIGINFO      0x4202
 #define PTRACE_SETSIGINFO      0x4203
 
+/*
+ * Generic ptrace interface that exports the architecture specific regsets
+ * using the corresponding NT_* types (which are also used in the core dump).
+ * Please note that the NT_PRSTATUS note type in a core dump contains a full
+ * 'struct elf_prstatus'. But the user_regset for NT_PRSTATUS contains just the
+ * elf_gregset_t that is the pr_reg field of 'struct elf_prstatus'. For all the
+ * other user_regset flavors, the user_regset layout and the ELF core dump note
+ * payload are exactly the same layout.
+ *
+ * This interface usage is as follows:
+ *     struct iovec iov = { buf, len};
+ *
+ *     ret = ptrace(PTRACE_GETREGSET/PTRACE_SETREGSET, pid, NT_XXX_TYPE, &iov);
+ *
+ * On the successful completion, iov.len will be updated by the kernel,
+ * specifying how much the kernel has written/read to/from the user's iov.buf.
+ */
+#define PTRACE_GETREGSET       0x4204
+#define PTRACE_SETREGSET       0x4205
+
+#define PTRACE_SEIZE           0x4206
+#define PTRACE_INTERRUPT       0x4207
+#define PTRACE_LISTEN          0x4208
+
+/* flags in @data for PTRACE_SEIZE */
+#define PTRACE_SEIZE_DEVEL     0x80000000 /* temp flag for development */
+
 /* options set using PTRACE_SETOPTIONS */
 #define PTRACE_O_TRACESYSGOOD  0x00000001
 #define PTRACE_O_TRACEFORK     0x00000002
@@ -45,6 +72,7 @@
 #define PTRACE_EVENT_EXEC      4
 #define PTRACE_EVENT_VFORK_DONE        5
 #define PTRACE_EVENT_EXIT      6
+#define PTRACE_EVENT_STOP      7
 
 #include <asm/ptrace.h>
 
  * flags.  When the a task is stopped the ptracer owns task->ptrace.
  */
 
+#define PT_SEIZED      0x00010000      /* SEIZE used, enable new behavior */
 #define PT_PTRACED     0x00000001
 #define PT_DTRACE      0x00000002      /* delayed trace (used on m68k, i386) */
 #define PT_TRACESYSGOOD        0x00000004
 #define PT_PTRACE_CAP  0x00000008      /* ptracer can follow suid-exec */
-#define PT_TRACE_FORK  0x00000010
-#define PT_TRACE_VFORK 0x00000020
-#define PT_TRACE_CLONE 0x00000040
-#define PT_TRACE_EXEC  0x00000080
-#define PT_TRACE_VFORK_DONE    0x00000100
-#define PT_TRACE_EXIT  0x00000200
+
+/* PT_TRACE_* event enable flags */
+#define PT_EVENT_FLAG_SHIFT    4
+#define PT_EVENT_FLAG(event)   (1 << (PT_EVENT_FLAG_SHIFT + (event) - 1))
+
+#define PT_TRACE_FORK          PT_EVENT_FLAG(PTRACE_EVENT_FORK)
+#define PT_TRACE_VFORK         PT_EVENT_FLAG(PTRACE_EVENT_VFORK)
+#define PT_TRACE_CLONE         PT_EVENT_FLAG(PTRACE_EVENT_CLONE)
+#define PT_TRACE_EXEC          PT_EVENT_FLAG(PTRACE_EVENT_EXEC)
+#define PT_TRACE_VFORK_DONE    PT_EVENT_FLAG(PTRACE_EVENT_VFORK_DONE)
+#define PT_TRACE_EXIT          PT_EVENT_FLAG(PTRACE_EVENT_EXIT)
 
 #define PT_TRACE_MASK  0x000003f4
 
 #include <linux/sched.h>               /* For struct task_struct.  */
 
 
-extern long arch_ptrace(struct task_struct *child, long request, long addr, long data);
-extern struct task_struct *ptrace_get_task_struct(pid_t pid);
-extern int ptrace_traceme(void);
+extern long arch_ptrace(struct task_struct *child, long request,
+                       unsigned long addr, unsigned long data);
 extern int ptrace_readdata(struct task_struct *tsk, unsigned long src, char __user *dst, int len);
 extern int ptrace_writedata(struct task_struct *tsk, char __user *src, unsigned long dst, int len);
-extern int ptrace_attach(struct task_struct *tsk);
-extern int ptrace_detach(struct task_struct *, unsigned int);
 extern void ptrace_disable(struct task_struct *);
-extern int ptrace_check_attach(struct task_struct *task, int kill);
-extern int ptrace_request(struct task_struct *child, long request, long addr, long data);
+extern int ptrace_check_attach(struct task_struct *task, bool ignore_state);
+extern int ptrace_request(struct task_struct *child, long request,
+                         unsigned long addr, unsigned long data);
 extern void ptrace_notify(int exit_code);
 extern void __ptrace_link(struct task_struct *child,
                          struct task_struct *new_parent);
 extern void __ptrace_unlink(struct task_struct *child);
-extern void ptrace_untrace(struct task_struct *child);
-extern int ptrace_may_attach(struct task_struct *task);
-extern int __ptrace_may_attach(struct task_struct *task);
+extern void exit_ptrace(struct task_struct *tracer);
+#define PTRACE_MODE_READ   1
+#define PTRACE_MODE_ATTACH 2
+/* Returns 0 on success, -errno on denial. */
+extern int __ptrace_may_access(struct task_struct *task, unsigned int mode);
+/* Returns true on success, false on denial. */
+extern bool ptrace_may_access(struct task_struct *task, unsigned int mode);
 
 static inline int ptrace_reparented(struct task_struct *child)
 {
-       return child->real_parent != child->parent;
-}
-static inline void ptrace_link(struct task_struct *child,
-                              struct task_struct *new_parent)
-{
-       if (unlikely(child->ptrace))
-               __ptrace_link(child, new_parent);
+       return !same_thread_group(child->real_parent, child->parent);
 }
+
 static inline void ptrace_unlink(struct task_struct *child)
 {
        if (unlikely(child->ptrace))
                __ptrace_unlink(child);
 }
 
-int generic_ptrace_peekdata(struct task_struct *tsk, long addr, long data);
-int generic_ptrace_pokedata(struct task_struct *tsk, long addr, long data);
+int generic_ptrace_peekdata(struct task_struct *tsk, unsigned long addr,
+                           unsigned long data);
+int generic_ptrace_pokedata(struct task_struct *tsk, unsigned long addr,
+                           unsigned long data);
+
+/**
+ * ptrace_parent - return the task that is tracing the given task
+ * @task: task to consider
+ *
+ * Returns %NULL if no one is tracing @task, or the &struct task_struct
+ * pointer to its tracer.
+ *
+ * Must called under rcu_read_lock().  The pointer returned might be kept
+ * live only by RCU.  During exec, this may be called with task_lock() held
+ * on @task, still held from when check_unsafe_exec() was called.
+ */
+static inline struct task_struct *ptrace_parent(struct task_struct *task)
+{
+       if (unlikely(task->ptrace))
+               return rcu_dereference(task->parent);
+       return NULL;
+}
+
+/**
+ * ptrace_event_enabled - test whether a ptrace event is enabled
+ * @task: ptracee of interest
+ * @event: %PTRACE_EVENT_* to test
+ *
+ * Test whether @event is enabled for ptracee @task.
+ *
+ * Returns %true if @event is enabled, %false otherwise.
+ */
+static inline bool ptrace_event_enabled(struct task_struct *task, int event)
+{
+       return task->ptrace & PT_EVENT_FLAG(event);
+}
+
+/**
+ * ptrace_event - possibly stop for a ptrace event notification
+ * @event:     %PTRACE_EVENT_* value to report
+ * @message:   value for %PTRACE_GETEVENTMSG to return
+ *
+ * Check whether @event is enabled and, if so, report @event and @message
+ * to the ptrace parent.
+ *
+ * Called without locks.
+ */
+static inline void ptrace_event(int event, unsigned long message)
+{
+       if (unlikely(ptrace_event_enabled(current, event))) {
+               current->ptrace_message = message;
+               ptrace_notify((event << 8) | SIGTRAP);
+       } else if (event == PTRACE_EVENT_EXEC && unlikely(current->ptrace)) {
+               /* legacy EXEC report via SIGTRAP */
+               send_sig(SIGTRAP, current, 0);
+       }
+}
+
+/**
+ * ptrace_init_task - initialize ptrace state for a new child
+ * @child:             new child task
+ * @ptrace:            true if child should be ptrace'd by parent's tracer
+ *
+ * This is called immediately after adding @child to its parent's children
+ * list.  @ptrace is false in the normal case, and true to ptrace @child.
+ *
+ * Called with current's siglock and write_lock_irq(&tasklist_lock) held.
+ */
+static inline void ptrace_init_task(struct task_struct *child, bool ptrace)
+{
+       INIT_LIST_HEAD(&child->ptrace_entry);
+       INIT_LIST_HEAD(&child->ptraced);
+#ifdef CONFIG_HAVE_HW_BREAKPOINT
+       atomic_set(&child->ptrace_bp_refcnt, 1);
+#endif
+       child->jobctl = 0;
+       child->ptrace = 0;
+       child->parent = child->real_parent;
+
+       if (unlikely(ptrace) && current->ptrace) {
+               child->ptrace = current->ptrace;
+               __ptrace_link(child, current->parent);
+
+               if (child->ptrace & PT_SEIZED)
+                       task_set_jobctl_pending(child, JOBCTL_TRAP_STOP);
+               else
+                       sigaddset(&child->pending.signal, SIGSTOP);
+
+               set_tsk_thread_flag(child, TIF_SIGPENDING);
+       }
+}
+
+/**
+ * ptrace_release_task - final ptrace-related cleanup of a zombie being reaped
+ * @task:      task in %EXIT_DEAD state
+ *
+ * Called with write_lock(&tasklist_lock) held.
+ */
+static inline void ptrace_release_task(struct task_struct *task)
+{
+       BUG_ON(!list_empty(&task->ptraced));
+       ptrace_unlink(task);
+       BUG_ON(!list_empty(&task->ptrace_entry));
+}
 
 #ifndef force_successful_syscall_return
 /*
@@ -178,6 +311,9 @@ static inline void user_enable_single_step(struct task_struct *task)
 static inline void user_disable_single_step(struct task_struct *task)
 {
 }
+#else
+extern void user_enable_single_step(struct task_struct *);
+extern void user_disable_single_step(struct task_struct *);
 #endif /* arch_has_single_step */
 
 #ifndef arch_has_block_step
@@ -205,8 +341,22 @@ static inline void user_enable_block_step(struct task_struct *task)
 {
        BUG();                  /* This can never be called.  */
 }
+#else
+extern void user_enable_block_step(struct task_struct *);
 #endif /* arch_has_block_step */
 
+#ifdef ARCH_HAS_USER_SINGLE_STEP_INFO
+extern void user_single_step_siginfo(struct task_struct *tsk,
+                               struct pt_regs *regs, siginfo_t *info);
+#else
+static inline void user_single_step_siginfo(struct task_struct *tsk,
+                               struct pt_regs *regs, siginfo_t *info)
+{
+       memset(info, 0, sizeof(*info));
+       info->si_signo = SIGTRAP;
+}
+#endif
+
 #ifndef arch_ptrace_stop_needed
 /**
  * arch_ptrace_stop_needed - Decide whether arch_ptrace_stop() should be called
@@ -242,6 +392,17 @@ static inline void user_enable_block_step(struct task_struct *task)
 #define arch_ptrace_stop(code, info)           do { } while (0)
 #endif
 
-#endif
+extern int task_current_syscall(struct task_struct *target, long *callno,
+                               unsigned long args[6], unsigned int maxargs,
+                               unsigned long *sp, unsigned long *pc);
+
+#ifdef CONFIG_HAVE_HW_BREAKPOINT
+extern int ptrace_get_breakpoints(struct task_struct *tsk);
+extern void ptrace_put_breakpoints(struct task_struct *tsk);
+#else
+static inline void ptrace_put_breakpoints(struct task_struct *tsk) { }
+#endif /* CONFIG_HAVE_HW_BREAKPOINT */
+
+#endif /* __KERNEL */
 
 #endif