Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
tracehook.h
Go to the documentation of this file.
1 /*
2  * Tracing hooks
3  *
4  * Copyright (C) 2008-2009 Red Hat, Inc. All rights reserved.
5  *
6  * This copyrighted material is made available to anyone wishing to use,
7  * modify, copy, or redistribute it subject to the terms and conditions
8  * of the GNU General Public License v.2.
9  *
10  * This file defines hook entry points called by core code where
11  * user tracing/debugging support might need to do something. These
12  * entry points are called tracehook_*(). Each hook declared below
13  * has a detailed kerneldoc comment giving the context (locking et
14  * al) from which it is called, and the meaning of its return value.
15  *
16  * Each function here typically has only one call site, so it is ok
17  * to have some nontrivial tracehook_*() inlines. In all cases, the
18  * fast path when no tracing is enabled should be very short.
19  *
20  * The purpose of this file and the tracehook_* layer is to consolidate
21  * the interface that the kernel core and arch code uses to enable any
22  * user debugging or tracing facility (such as ptrace). The interfaces
23  * here are carefully documented so that maintainers of core and arch
24  * code do not need to think about the implementation details of the
25  * tracing facilities. Likewise, maintainers of the tracing code do not
26  * need to understand all the calling core or arch code in detail, just
27  * documented circumstances of each call, such as locking conditions.
28  *
29  * If the calling core code changes so that locking is different, then
30  * it is ok to change the interface documented here. The maintainer of
31  * core code changing should notify the maintainers of the tracing code
32  * that they need to work out the change.
33  *
34  * Some tracehook_*() inlines take arguments that the current tracing
35  * implementations might not necessarily use. These function signatures
36  * are chosen to pass in all the information that is on hand in the
37  * caller and might conceivably be relevant to a tracer, so that the
38  * core code won't have to be updated when tracing adds more features.
39  * If a call site changes so that some of those parameters are no longer
40  * already on hand without extra work, then the tracehook_* interface
41  * can change so there is no make-work burden on the core code. The
42  * maintainer of core code changing should notify the maintainers of the
43  * tracing code that they need to work out the change.
44  */
45 
46 #ifndef _LINUX_TRACEHOOK_H
47 #define _LINUX_TRACEHOOK_H 1
48 
49 #include <linux/sched.h>
50 #include <linux/ptrace.h>
51 #include <linux/security.h>
52 #include <linux/task_work.h>
53 struct linux_binprm;
54 
55 /*
56  * ptrace report for syscall entry and exit looks identical.
57  */
58 static inline int ptrace_report_syscall(struct pt_regs *regs)
59 {
60  int ptrace = current->ptrace;
61 
62  if (!(ptrace & PT_PTRACED))
63  return 0;
64 
65  ptrace_notify(SIGTRAP | ((ptrace & PT_TRACESYSGOOD) ? 0x80 : 0));
66 
67  /*
68  * this isn't the same as continuing with a signal, but it will do
69  * for normal use. strace only continues with a signal if the
70  * stopping signal is not SIGTRAP. -brl
71  */
72  if (current->exit_code) {
73  send_sig(current->exit_code, current, 1);
74  current->exit_code = 0;
75  }
76 
77  return fatal_signal_pending(current);
78 }
79 
99 static inline __must_check int tracehook_report_syscall_entry(
100  struct pt_regs *regs)
101 {
102  return ptrace_report_syscall(regs);
103 }
104 
122 static inline void tracehook_report_syscall_exit(struct pt_regs *regs, int step)
123 {
124  if (step) {
125  siginfo_t info;
126  user_single_step_siginfo(current, regs, &info);
127  force_sig_info(SIGTRAP, &info, current);
128  return;
129  }
130 
131  ptrace_report_syscall(regs);
132 }
133 
149 static inline void tracehook_signal_handler(int sig, siginfo_t *info,
150  const struct k_sigaction *ka,
151  struct pt_regs *regs, int stepping)
152 {
153  if (stepping)
155 }
156 
166 static inline void set_notify_resume(struct task_struct *task)
167 {
168 #ifdef TIF_NOTIFY_RESUME
169  if (!test_and_set_tsk_thread_flag(task, TIF_NOTIFY_RESUME))
170  kick_process(task);
171 #endif
172 }
173 
187 static inline void tracehook_notify_resume(struct pt_regs *regs)
188 {
189  /*
190  * The caller just cleared TIF_NOTIFY_RESUME. This barrier
191  * pairs with task_work_add()->set_notify_resume() after
192  * hlist_add_head(task->task_works);
193  */
195  if (unlikely(current->task_works))
196  task_work_run();
197 }
198 
199 #endif /* <linux/tracehook.h> */