diff options
author | Ingo Molnar <mingo@elte.hu> | 2009-10-23 02:23:20 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2009-10-23 02:23:20 -0400 |
commit | 43315956509ca6913764861ac7dec128b91eb1ec (patch) | |
tree | 60fd5647f150a46e63093a41417c2eef3e776b3d /kernel/trace/trace_syscalls.c | |
parent | 9bf4e7fba8006d19846fec877b6da0616b2772de (diff) | |
parent | 6beba7adbe092e63dfe8d09fbd1e3ec140474a13 (diff) |
Merge branch 'perf/core' into perf/probes
Conflicts:
tools/perf/Makefile
Merge reason:
- fix the conflict
- pick up the pr_*() infrastructure to queue up dependent patch
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'kernel/trace/trace_syscalls.c')
-rw-r--r-- | kernel/trace/trace_syscalls.c | 106 |
1 files changed, 99 insertions, 7 deletions
diff --git a/kernel/trace/trace_syscalls.c b/kernel/trace/trace_syscalls.c index 9ade66389d5a..58b8e5370767 100644 --- a/kernel/trace/trace_syscalls.c +++ b/kernel/trace/trace_syscalls.c | |||
@@ -14,6 +14,69 @@ static int sys_refcount_exit; | |||
14 | static DECLARE_BITMAP(enabled_enter_syscalls, NR_syscalls); | 14 | static DECLARE_BITMAP(enabled_enter_syscalls, NR_syscalls); |
15 | static DECLARE_BITMAP(enabled_exit_syscalls, NR_syscalls); | 15 | static DECLARE_BITMAP(enabled_exit_syscalls, NR_syscalls); |
16 | 16 | ||
17 | extern unsigned long __start_syscalls_metadata[]; | ||
18 | extern unsigned long __stop_syscalls_metadata[]; | ||
19 | |||
20 | static struct syscall_metadata **syscalls_metadata; | ||
21 | |||
22 | static struct syscall_metadata *find_syscall_meta(unsigned long syscall) | ||
23 | { | ||
24 | struct syscall_metadata *start; | ||
25 | struct syscall_metadata *stop; | ||
26 | char str[KSYM_SYMBOL_LEN]; | ||
27 | |||
28 | |||
29 | start = (struct syscall_metadata *)__start_syscalls_metadata; | ||
30 | stop = (struct syscall_metadata *)__stop_syscalls_metadata; | ||
31 | kallsyms_lookup(syscall, NULL, NULL, NULL, str); | ||
32 | |||
33 | for ( ; start < stop; start++) { | ||
34 | /* | ||
35 | * Only compare after the "sys" prefix. Archs that use | ||
36 | * syscall wrappers may have syscalls symbols aliases prefixed | ||
37 | * with "SyS" instead of "sys", leading to an unwanted | ||
38 | * mismatch. | ||
39 | */ | ||
40 | if (start->name && !strcmp(start->name + 3, str + 3)) | ||
41 | return start; | ||
42 | } | ||
43 | return NULL; | ||
44 | } | ||
45 | |||
46 | static struct syscall_metadata *syscall_nr_to_meta(int nr) | ||
47 | { | ||
48 | if (!syscalls_metadata || nr >= NR_syscalls || nr < 0) | ||
49 | return NULL; | ||
50 | |||
51 | return syscalls_metadata[nr]; | ||
52 | } | ||
53 | |||
54 | int syscall_name_to_nr(char *name) | ||
55 | { | ||
56 | int i; | ||
57 | |||
58 | if (!syscalls_metadata) | ||
59 | return -1; | ||
60 | |||
61 | for (i = 0; i < NR_syscalls; i++) { | ||
62 | if (syscalls_metadata[i]) { | ||
63 | if (!strcmp(syscalls_metadata[i]->name, name)) | ||
64 | return i; | ||
65 | } | ||
66 | } | ||
67 | return -1; | ||
68 | } | ||
69 | |||
70 | void set_syscall_enter_id(int num, int id) | ||
71 | { | ||
72 | syscalls_metadata[num]->enter_id = id; | ||
73 | } | ||
74 | |||
75 | void set_syscall_exit_id(int num, int id) | ||
76 | { | ||
77 | syscalls_metadata[num]->exit_id = id; | ||
78 | } | ||
79 | |||
17 | enum print_line_t | 80 | enum print_line_t |
18 | print_syscall_enter(struct trace_iterator *iter, int flags) | 81 | print_syscall_enter(struct trace_iterator *iter, int flags) |
19 | { | 82 | { |
@@ -103,7 +166,8 @@ extern char *__bad_type_size(void); | |||
103 | #define SYSCALL_FIELD(type, name) \ | 166 | #define SYSCALL_FIELD(type, name) \ |
104 | sizeof(type) != sizeof(trace.name) ? \ | 167 | sizeof(type) != sizeof(trace.name) ? \ |
105 | __bad_type_size() : \ | 168 | __bad_type_size() : \ |
106 | #type, #name, offsetof(typeof(trace), name), sizeof(trace.name) | 169 | #type, #name, offsetof(typeof(trace), name), \ |
170 | sizeof(trace.name), is_signed_type(type) | ||
107 | 171 | ||
108 | int syscall_enter_format(struct ftrace_event_call *call, struct trace_seq *s) | 172 | int syscall_enter_format(struct ftrace_event_call *call, struct trace_seq *s) |
109 | { | 173 | { |
@@ -120,7 +184,8 @@ int syscall_enter_format(struct ftrace_event_call *call, struct trace_seq *s) | |||
120 | if (!entry) | 184 | if (!entry) |
121 | return 0; | 185 | return 0; |
122 | 186 | ||
123 | ret = trace_seq_printf(s, "\tfield:%s %s;\toffset:%zu;\tsize:%zu;\n", | 187 | ret = trace_seq_printf(s, "\tfield:%s %s;\toffset:%zu;\tsize:%zu;" |
188 | "\tsigned:%u;\n", | ||
124 | SYSCALL_FIELD(int, nr)); | 189 | SYSCALL_FIELD(int, nr)); |
125 | if (!ret) | 190 | if (!ret) |
126 | return 0; | 191 | return 0; |
@@ -130,8 +195,10 @@ int syscall_enter_format(struct ftrace_event_call *call, struct trace_seq *s) | |||
130 | entry->args[i]); | 195 | entry->args[i]); |
131 | if (!ret) | 196 | if (!ret) |
132 | return 0; | 197 | return 0; |
133 | ret = trace_seq_printf(s, "\toffset:%d;\tsize:%zu;\n", offset, | 198 | ret = trace_seq_printf(s, "\toffset:%d;\tsize:%zu;" |
134 | sizeof(unsigned long)); | 199 | "\tsigned:%u;\n", offset, |
200 | sizeof(unsigned long), | ||
201 | is_signed_type(unsigned long)); | ||
135 | if (!ret) | 202 | if (!ret) |
136 | return 0; | 203 | return 0; |
137 | offset += sizeof(unsigned long); | 204 | offset += sizeof(unsigned long); |
@@ -163,8 +230,10 @@ int syscall_exit_format(struct ftrace_event_call *call, struct trace_seq *s) | |||
163 | struct syscall_trace_exit trace; | 230 | struct syscall_trace_exit trace; |
164 | 231 | ||
165 | ret = trace_seq_printf(s, | 232 | ret = trace_seq_printf(s, |
166 | "\tfield:%s %s;\toffset:%zu;\tsize:%zu;\n" | 233 | "\tfield:%s %s;\toffset:%zu;\tsize:%zu;" |
167 | "\tfield:%s %s;\toffset:%zu;\tsize:%zu;\n", | 234 | "\tsigned:%u;\n" |
235 | "\tfield:%s %s;\toffset:%zu;\tsize:%zu;" | ||
236 | "\tsigned:%u;\n", | ||
168 | SYSCALL_FIELD(int, nr), | 237 | SYSCALL_FIELD(int, nr), |
169 | SYSCALL_FIELD(long, ret)); | 238 | SYSCALL_FIELD(long, ret)); |
170 | if (!ret) | 239 | if (!ret) |
@@ -212,7 +281,7 @@ int syscall_exit_define_fields(struct ftrace_event_call *call) | |||
212 | if (ret) | 281 | if (ret) |
213 | return ret; | 282 | return ret; |
214 | 283 | ||
215 | ret = trace_define_field(call, SYSCALL_FIELD(long, ret), 0, | 284 | ret = trace_define_field(call, SYSCALL_FIELD(long, ret), |
216 | FILTER_OTHER); | 285 | FILTER_OTHER); |
217 | 286 | ||
218 | return ret; | 287 | return ret; |
@@ -375,6 +444,29 @@ struct trace_event event_syscall_exit = { | |||
375 | .trace = print_syscall_exit, | 444 | .trace = print_syscall_exit, |
376 | }; | 445 | }; |
377 | 446 | ||
447 | int __init init_ftrace_syscalls(void) | ||
448 | { | ||
449 | struct syscall_metadata *meta; | ||
450 | unsigned long addr; | ||
451 | int i; | ||
452 | |||
453 | syscalls_metadata = kzalloc(sizeof(*syscalls_metadata) * | ||
454 | NR_syscalls, GFP_KERNEL); | ||
455 | if (!syscalls_metadata) { | ||
456 | WARN_ON(1); | ||
457 | return -ENOMEM; | ||
458 | } | ||
459 | |||
460 | for (i = 0; i < NR_syscalls; i++) { | ||
461 | addr = arch_syscall_addr(i); | ||
462 | meta = find_syscall_meta(addr); | ||
463 | syscalls_metadata[i] = meta; | ||
464 | } | ||
465 | |||
466 | return 0; | ||
467 | } | ||
468 | core_initcall(init_ftrace_syscalls); | ||
469 | |||
378 | #ifdef CONFIG_EVENT_PROFILE | 470 | #ifdef CONFIG_EVENT_PROFILE |
379 | 471 | ||
380 | static DECLARE_BITMAP(enabled_prof_enter_syscalls, NR_syscalls); | 472 | static DECLARE_BITMAP(enabled_prof_enter_syscalls, NR_syscalls); |