diff options
-rw-r--r-- | arch/x86/kernel/ftrace.c | 10 | ||||
-rw-r--r-- | include/linux/syscalls.h | 22 | ||||
-rw-r--r-- | include/trace/syscall.h | 8 | ||||
-rw-r--r-- | kernel/trace/trace.h | 6 | ||||
-rw-r--r-- | kernel/trace/trace_syscalls.c | 26 |
5 files changed, 52 insertions, 20 deletions
diff --git a/arch/x86/kernel/ftrace.c b/arch/x86/kernel/ftrace.c index 0d93d409b8d2..3cff1214e176 100644 --- a/arch/x86/kernel/ftrace.c +++ b/arch/x86/kernel/ftrace.c | |||
@@ -516,6 +516,16 @@ int syscall_name_to_nr(char *name) | |||
516 | return -1; | 516 | return -1; |
517 | } | 517 | } |
518 | 518 | ||
519 | void set_syscall_enter_id(int num, int id) | ||
520 | { | ||
521 | syscalls_metadata[num]->enter_id = id; | ||
522 | } | ||
523 | |||
524 | void set_syscall_exit_id(int num, int id) | ||
525 | { | ||
526 | syscalls_metadata[num]->exit_id = id; | ||
527 | } | ||
528 | |||
519 | static int __init arch_init_ftrace_syscalls(void) | 529 | static int __init arch_init_ftrace_syscalls(void) |
520 | { | 530 | { |
521 | int i; | 531 | int i; |
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h index 5e5b4d33a31c..ce4b01c658eb 100644 --- a/include/linux/syscalls.h +++ b/include/linux/syscalls.h | |||
@@ -116,13 +116,20 @@ struct perf_counter_attr; | |||
116 | 116 | ||
117 | #define SYSCALL_TRACE_ENTER_EVENT(sname) \ | 117 | #define SYSCALL_TRACE_ENTER_EVENT(sname) \ |
118 | static struct ftrace_event_call event_enter_##sname; \ | 118 | static struct ftrace_event_call event_enter_##sname; \ |
119 | struct trace_event enter_syscall_print_##sname = { \ | ||
120 | .trace = print_syscall_enter, \ | ||
121 | }; \ | ||
119 | static int init_enter_##sname(void) \ | 122 | static int init_enter_##sname(void) \ |
120 | { \ | 123 | { \ |
121 | int num; \ | 124 | int num, id; \ |
122 | num = syscall_name_to_nr("sys"#sname); \ | 125 | num = syscall_name_to_nr("sys"#sname); \ |
123 | if (num < 0) \ | 126 | if (num < 0) \ |
124 | return -ENOSYS; \ | 127 | return -ENOSYS; \ |
125 | register_ftrace_event(&event_syscall_enter); \ | 128 | id = register_ftrace_event(&enter_syscall_print_##sname);\ |
129 | if (!id) \ | ||
130 | return -ENODEV; \ | ||
131 | event_enter_##sname.id = id; \ | ||
132 | set_syscall_enter_id(num, id); \ | ||
126 | INIT_LIST_HEAD(&event_enter_##sname.fields); \ | 133 | INIT_LIST_HEAD(&event_enter_##sname.fields); \ |
127 | init_preds(&event_enter_##sname); \ | 134 | init_preds(&event_enter_##sname); \ |
128 | return 0; \ | 135 | return 0; \ |
@@ -142,13 +149,20 @@ struct perf_counter_attr; | |||
142 | 149 | ||
143 | #define SYSCALL_TRACE_EXIT_EVENT(sname) \ | 150 | #define SYSCALL_TRACE_EXIT_EVENT(sname) \ |
144 | static struct ftrace_event_call event_exit_##sname; \ | 151 | static struct ftrace_event_call event_exit_##sname; \ |
152 | struct trace_event exit_syscall_print_##sname = { \ | ||
153 | .trace = print_syscall_exit, \ | ||
154 | }; \ | ||
145 | static int init_exit_##sname(void) \ | 155 | static int init_exit_##sname(void) \ |
146 | { \ | 156 | { \ |
147 | int num; \ | 157 | int num, id; \ |
148 | num = syscall_name_to_nr("sys"#sname); \ | 158 | num = syscall_name_to_nr("sys"#sname); \ |
149 | if (num < 0) \ | 159 | if (num < 0) \ |
150 | return -ENOSYS; \ | 160 | return -ENOSYS; \ |
151 | register_ftrace_event(&event_syscall_exit); \ | 161 | id = register_ftrace_event(&exit_syscall_print_##sname);\ |
162 | if (!id) \ | ||
163 | return -ENODEV; \ | ||
164 | event_exit_##sname.id = id; \ | ||
165 | set_syscall_exit_id(num, id); \ | ||
152 | INIT_LIST_HEAD(&event_exit_##sname.fields); \ | 166 | INIT_LIST_HEAD(&event_exit_##sname.fields); \ |
153 | init_preds(&event_exit_##sname); \ | 167 | init_preds(&event_exit_##sname); \ |
154 | return 0; \ | 168 | return 0; \ |
diff --git a/include/trace/syscall.h b/include/trace/syscall.h index 73fb8b4a9955..df628404241a 100644 --- a/include/trace/syscall.h +++ b/include/trace/syscall.h | |||
@@ -32,23 +32,31 @@ DECLARE_TRACE_WITH_CALLBACK(syscall_exit, | |||
32 | * @nb_args: number of parameters it takes | 32 | * @nb_args: number of parameters it takes |
33 | * @types: list of types as strings | 33 | * @types: list of types as strings |
34 | * @args: list of args as strings (args[i] matches types[i]) | 34 | * @args: list of args as strings (args[i] matches types[i]) |
35 | * @enter_id: associated ftrace enter event id | ||
36 | * @exit_id: associated ftrace exit event id | ||
35 | */ | 37 | */ |
36 | struct syscall_metadata { | 38 | struct syscall_metadata { |
37 | const char *name; | 39 | const char *name; |
38 | int nb_args; | 40 | int nb_args; |
39 | const char **types; | 41 | const char **types; |
40 | const char **args; | 42 | const char **args; |
43 | int enter_id; | ||
44 | int exit_id; | ||
41 | }; | 45 | }; |
42 | 46 | ||
43 | #ifdef CONFIG_FTRACE_SYSCALLS | 47 | #ifdef CONFIG_FTRACE_SYSCALLS |
44 | extern struct syscall_metadata *syscall_nr_to_meta(int nr); | 48 | extern struct syscall_metadata *syscall_nr_to_meta(int nr); |
45 | extern int syscall_name_to_nr(char *name); | 49 | extern int syscall_name_to_nr(char *name); |
50 | void set_syscall_enter_id(int num, int id); | ||
51 | void set_syscall_exit_id(int num, int id); | ||
46 | extern struct trace_event event_syscall_enter; | 52 | extern struct trace_event event_syscall_enter; |
47 | extern struct trace_event event_syscall_exit; | 53 | extern struct trace_event event_syscall_exit; |
48 | extern int reg_event_syscall_enter(void *ptr); | 54 | extern int reg_event_syscall_enter(void *ptr); |
49 | extern void unreg_event_syscall_enter(void *ptr); | 55 | extern void unreg_event_syscall_enter(void *ptr); |
50 | extern int reg_event_syscall_exit(void *ptr); | 56 | extern int reg_event_syscall_exit(void *ptr); |
51 | extern void unreg_event_syscall_exit(void *ptr); | 57 | extern void unreg_event_syscall_exit(void *ptr); |
58 | enum print_line_t print_syscall_enter(struct trace_iterator *iter, int flags); | ||
59 | enum print_line_t print_syscall_exit(struct trace_iterator *iter, int flags); | ||
52 | #endif | 60 | #endif |
53 | 61 | ||
54 | #endif /* _TRACE_SYSCALL_H */ | 62 | #endif /* _TRACE_SYSCALL_H */ |
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h index d682357e4b1f..300ef788c976 100644 --- a/kernel/trace/trace.h +++ b/kernel/trace/trace.h | |||
@@ -34,8 +34,6 @@ enum trace_type { | |||
34 | TRACE_GRAPH_ENT, | 34 | TRACE_GRAPH_ENT, |
35 | TRACE_USER_STACK, | 35 | TRACE_USER_STACK, |
36 | TRACE_HW_BRANCHES, | 36 | TRACE_HW_BRANCHES, |
37 | TRACE_SYSCALL_ENTER, | ||
38 | TRACE_SYSCALL_EXIT, | ||
39 | TRACE_KMEM_ALLOC, | 37 | TRACE_KMEM_ALLOC, |
40 | TRACE_KMEM_FREE, | 38 | TRACE_KMEM_FREE, |
41 | TRACE_POWER, | 39 | TRACE_POWER, |
@@ -319,10 +317,6 @@ extern void __ftrace_bad_type(void); | |||
319 | TRACE_KMEM_ALLOC); \ | 317 | TRACE_KMEM_ALLOC); \ |
320 | IF_ASSIGN(var, ent, struct kmemtrace_free_entry, \ | 318 | IF_ASSIGN(var, ent, struct kmemtrace_free_entry, \ |
321 | TRACE_KMEM_FREE); \ | 319 | TRACE_KMEM_FREE); \ |
322 | IF_ASSIGN(var, ent, struct syscall_trace_enter, \ | ||
323 | TRACE_SYSCALL_ENTER); \ | ||
324 | IF_ASSIGN(var, ent, struct syscall_trace_exit, \ | ||
325 | TRACE_SYSCALL_EXIT); \ | ||
326 | __ftrace_bad_type(); \ | 320 | __ftrace_bad_type(); \ |
327 | } while (0) | 321 | } while (0) |
328 | 322 | ||
diff --git a/kernel/trace/trace_syscalls.c b/kernel/trace/trace_syscalls.c index c7ae25ee95d8..e58a9c11ba85 100644 --- a/kernel/trace/trace_syscalls.c +++ b/kernel/trace/trace_syscalls.c | |||
@@ -36,14 +36,18 @@ print_syscall_enter(struct trace_iterator *iter, int flags) | |||
36 | struct syscall_metadata *entry; | 36 | struct syscall_metadata *entry; |
37 | int i, ret, syscall; | 37 | int i, ret, syscall; |
38 | 38 | ||
39 | trace_assign_type(trace, ent); | 39 | trace = (typeof(trace))ent; |
40 | |||
41 | syscall = trace->nr; | 40 | syscall = trace->nr; |
42 | |||
43 | entry = syscall_nr_to_meta(syscall); | 41 | entry = syscall_nr_to_meta(syscall); |
42 | |||
44 | if (!entry) | 43 | if (!entry) |
45 | goto end; | 44 | goto end; |
46 | 45 | ||
46 | if (entry->enter_id != ent->type) { | ||
47 | WARN_ON_ONCE(1); | ||
48 | goto end; | ||
49 | } | ||
50 | |||
47 | ret = trace_seq_printf(s, "%s(", entry->name); | 51 | ret = trace_seq_printf(s, "%s(", entry->name); |
48 | if (!ret) | 52 | if (!ret) |
49 | return TRACE_TYPE_PARTIAL_LINE; | 53 | return TRACE_TYPE_PARTIAL_LINE; |
@@ -78,16 +82,20 @@ print_syscall_exit(struct trace_iterator *iter, int flags) | |||
78 | struct syscall_metadata *entry; | 82 | struct syscall_metadata *entry; |
79 | int ret; | 83 | int ret; |
80 | 84 | ||
81 | trace_assign_type(trace, ent); | 85 | trace = (typeof(trace))ent; |
82 | |||
83 | syscall = trace->nr; | 86 | syscall = trace->nr; |
84 | |||
85 | entry = syscall_nr_to_meta(syscall); | 87 | entry = syscall_nr_to_meta(syscall); |
88 | |||
86 | if (!entry) { | 89 | if (!entry) { |
87 | trace_seq_printf(s, "\n"); | 90 | trace_seq_printf(s, "\n"); |
88 | return TRACE_TYPE_HANDLED; | 91 | return TRACE_TYPE_HANDLED; |
89 | } | 92 | } |
90 | 93 | ||
94 | if (entry->exit_id != ent->type) { | ||
95 | WARN_ON_ONCE(1); | ||
96 | return TRACE_TYPE_UNHANDLED; | ||
97 | } | ||
98 | |||
91 | ret = trace_seq_printf(s, "%s -> 0x%lx\n", entry->name, | 99 | ret = trace_seq_printf(s, "%s -> 0x%lx\n", entry->name, |
92 | trace->ret); | 100 | trace->ret); |
93 | if (!ret) | 101 | if (!ret) |
@@ -114,7 +122,7 @@ void ftrace_syscall_enter(struct pt_regs *regs, long id) | |||
114 | 122 | ||
115 | size = sizeof(*entry) + sizeof(unsigned long) * sys_data->nb_args; | 123 | size = sizeof(*entry) + sizeof(unsigned long) * sys_data->nb_args; |
116 | 124 | ||
117 | event = trace_current_buffer_lock_reserve(TRACE_SYSCALL_ENTER, size, | 125 | event = trace_current_buffer_lock_reserve(sys_data->enter_id, size, |
118 | 0, 0); | 126 | 0, 0); |
119 | if (!event) | 127 | if (!event) |
120 | return; | 128 | return; |
@@ -142,7 +150,7 @@ void ftrace_syscall_exit(struct pt_regs *regs, long ret) | |||
142 | if (!sys_data) | 150 | if (!sys_data) |
143 | return; | 151 | return; |
144 | 152 | ||
145 | event = trace_current_buffer_lock_reserve(TRACE_SYSCALL_EXIT, | 153 | event = trace_current_buffer_lock_reserve(sys_data->exit_id, |
146 | sizeof(*entry), 0, 0); | 154 | sizeof(*entry), 0, 0); |
147 | if (!event) | 155 | if (!event) |
148 | return; | 156 | return; |
@@ -239,10 +247,8 @@ void unreg_event_syscall_exit(void *ptr) | |||
239 | 247 | ||
240 | struct trace_event event_syscall_enter = { | 248 | struct trace_event event_syscall_enter = { |
241 | .trace = print_syscall_enter, | 249 | .trace = print_syscall_enter, |
242 | .type = TRACE_SYSCALL_ENTER | ||
243 | }; | 250 | }; |
244 | 251 | ||
245 | struct trace_event event_syscall_exit = { | 252 | struct trace_event event_syscall_exit = { |
246 | .trace = print_syscall_exit, | 253 | .trace = print_syscall_exit, |
247 | .type = TRACE_SYSCALL_EXIT | ||
248 | }; | 254 | }; |