aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFrederic Weisbecker <fweisbec@gmail.com>2009-09-19 00:50:42 -0400
committerFrederic Weisbecker <fweisbec@gmail.com>2009-10-14 03:53:56 -0400
commitc44fc770845163f8d9e573f37f92a7b7a7ade14e (patch)
treedac4327b1454b73cefe7ffb2ef28cc67ea878f2b
parent4d8289494a37e19cd7f3beacea9c957ad3debad6 (diff)
tracing: Move syscalls metadata handling from arch to core
Most of the syscalls metadata processing is done from arch. But these operations are mostly generic accross archs. Especially now that we have a common variable name that expresses the number of syscalls supported by an arch: NR_syscalls, the only remaining bits that need to reside in arch is the syscall nr to addr translation. v2: Compare syscalls symbols only after the "sys" prefix so that we avoid spurious mismatches with archs that have syscalls wrappers, in which case syscalls symbols have "SyS" prefixed aliases. (Reported by: Heiko Carstens) Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com> Acked-by: Heiko Carstens <heiko.carstens@de.ibm.com> Cc: Ingo Molnar <mingo@elte.hu> Cc: Steven Rostedt <rostedt@goodmis.org> Cc: Li Zefan <lizf@cn.fujitsu.com> Cc: Masami Hiramatsu <mhiramat@redhat.com> Cc: Jason Baron <jbaron@redhat.com> Cc: Lai Jiangshan <laijs@cn.fujitsu.com> Cc: Martin Schwidefsky <schwidefsky@de.ibm.com> Cc: Paul Mundt <lethal@linux-sh.org>
-rw-r--r--arch/s390/kernel/ftrace.c67
-rw-r--r--arch/x86/kernel/ftrace.c76
-rw-r--r--include/trace/syscall.h2
-rw-r--r--kernel/trace/trace_syscalls.c86
4 files changed, 91 insertions, 140 deletions
diff --git a/arch/s390/kernel/ftrace.c b/arch/s390/kernel/ftrace.c
index 57bdcb1e3cdf..7c5752c3423d 100644
--- a/arch/s390/kernel/ftrace.c
+++ b/arch/s390/kernel/ftrace.c
@@ -206,73 +206,10 @@ out:
206 206
207#ifdef CONFIG_FTRACE_SYSCALLS 207#ifdef CONFIG_FTRACE_SYSCALLS
208 208
209extern unsigned long __start_syscalls_metadata[];
210extern unsigned long __stop_syscalls_metadata[];
211extern unsigned int sys_call_table[]; 209extern unsigned int sys_call_table[];
212 210
213static struct syscall_metadata **syscalls_metadata; 211unsigned long __init arch_syscall_addr(int nr)
214
215struct syscall_metadata *syscall_nr_to_meta(int nr)
216{
217 if (!syscalls_metadata || nr >= NR_syscalls || nr < 0)
218 return NULL;
219
220 return syscalls_metadata[nr];
221}
222
223int syscall_name_to_nr(char *name)
224{
225 int i;
226
227 if (!syscalls_metadata)
228 return -1;
229 for (i = 0; i < NR_syscalls; i++)
230 if (syscalls_metadata[i])
231 if (!strcmp(syscalls_metadata[i]->name, name))
232 return i;
233 return -1;
234}
235
236void set_syscall_enter_id(int num, int id)
237{
238 syscalls_metadata[num]->enter_id = id;
239}
240
241void set_syscall_exit_id(int num, int id)
242{ 212{
243 syscalls_metadata[num]->exit_id = id; 213 return (unsigned long)sys_call_table[nr];
244}
245
246static struct syscall_metadata *find_syscall_meta(unsigned long syscall)
247{
248 struct syscall_metadata *start;
249 struct syscall_metadata *stop;
250 char str[KSYM_SYMBOL_LEN];
251
252 start = (struct syscall_metadata *)__start_syscalls_metadata;
253 stop = (struct syscall_metadata *)__stop_syscalls_metadata;
254 kallsyms_lookup(syscall, NULL, NULL, NULL, str);
255
256 for ( ; start < stop; start++) {
257 if (start->name && !strcmp(start->name + 3, str + 3))
258 return start;
259 }
260 return NULL;
261}
262
263static int __init arch_init_ftrace_syscalls(void)
264{
265 struct syscall_metadata *meta;
266 int i;
267 syscalls_metadata = kzalloc(sizeof(*syscalls_metadata) * NR_syscalls,
268 GFP_KERNEL);
269 if (!syscalls_metadata)
270 return -ENOMEM;
271 for (i = 0; i < NR_syscalls; i++) {
272 meta = find_syscall_meta((unsigned long)sys_call_table[i]);
273 syscalls_metadata[i] = meta;
274 }
275 return 0;
276} 214}
277arch_initcall(arch_init_ftrace_syscalls);
278#endif 215#endif
diff --git a/arch/x86/kernel/ftrace.c b/arch/x86/kernel/ftrace.c
index 25e6f5fc4b1e..5a1b9758fd62 100644
--- a/arch/x86/kernel/ftrace.c
+++ b/arch/x86/kernel/ftrace.c
@@ -470,82 +470,10 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
470 470
471#ifdef CONFIG_FTRACE_SYSCALLS 471#ifdef CONFIG_FTRACE_SYSCALLS
472 472
473extern unsigned long __start_syscalls_metadata[];
474extern unsigned long __stop_syscalls_metadata[];
475extern unsigned long *sys_call_table; 473extern unsigned long *sys_call_table;
476 474
477static struct syscall_metadata **syscalls_metadata; 475unsigned long __init arch_syscall_addr(int nr)
478
479static struct syscall_metadata *find_syscall_meta(unsigned long *syscall)
480{
481 struct syscall_metadata *start;
482 struct syscall_metadata *stop;
483 char str[KSYM_SYMBOL_LEN];
484
485
486 start = (struct syscall_metadata *)__start_syscalls_metadata;
487 stop = (struct syscall_metadata *)__stop_syscalls_metadata;
488 kallsyms_lookup((unsigned long) syscall, NULL, NULL, NULL, str);
489
490 for ( ; start < stop; start++) {
491 if (start->name && !strcmp(start->name, str))
492 return start;
493 }
494 return NULL;
495}
496
497struct syscall_metadata *syscall_nr_to_meta(int nr)
498{
499 if (!syscalls_metadata || nr >= NR_syscalls || nr < 0)
500 return NULL;
501
502 return syscalls_metadata[nr];
503}
504
505int syscall_name_to_nr(char *name)
506{
507 int i;
508
509 if (!syscalls_metadata)
510 return -1;
511
512 for (i = 0; i < NR_syscalls; i++) {
513 if (syscalls_metadata[i]) {
514 if (!strcmp(syscalls_metadata[i]->name, name))
515 return i;
516 }
517 }
518 return -1;
519}
520
521void set_syscall_enter_id(int num, int id)
522{
523 syscalls_metadata[num]->enter_id = id;
524}
525
526void set_syscall_exit_id(int num, int id)
527{ 476{
528 syscalls_metadata[num]->exit_id = id; 477 return (unsigned long)(&sys_call_table)[nr];
529}
530
531static int __init arch_init_ftrace_syscalls(void)
532{
533 int i;
534 struct syscall_metadata *meta;
535 unsigned long **psys_syscall_table = &sys_call_table;
536
537 syscalls_metadata = kzalloc(sizeof(*syscalls_metadata) *
538 NR_syscalls, GFP_KERNEL);
539 if (!syscalls_metadata) {
540 WARN_ON(1);
541 return -ENOMEM;
542 }
543
544 for (i = 0; i < NR_syscalls; i++) {
545 meta = find_syscall_meta(psys_syscall_table[i]);
546 syscalls_metadata[i] = meta;
547 }
548 return 0;
549} 478}
550arch_initcall(arch_init_ftrace_syscalls);
551#endif 479#endif
diff --git a/include/trace/syscall.h b/include/trace/syscall.h
index 5dc283ba5ae0..e972f0a40f8d 100644
--- a/include/trace/syscall.h
+++ b/include/trace/syscall.h
@@ -33,7 +33,7 @@ struct syscall_metadata {
33}; 33};
34 34
35#ifdef CONFIG_FTRACE_SYSCALLS 35#ifdef CONFIG_FTRACE_SYSCALLS
36extern struct syscall_metadata *syscall_nr_to_meta(int nr); 36extern unsigned long arch_syscall_addr(int nr);
37extern int syscall_name_to_nr(char *name); 37extern int syscall_name_to_nr(char *name);
38void set_syscall_enter_id(int num, int id); 38void set_syscall_enter_id(int num, int id);
39void set_syscall_exit_id(int num, int id); 39void set_syscall_exit_id(int num, int id);
diff --git a/kernel/trace/trace_syscalls.c b/kernel/trace/trace_syscalls.c
index 9fbce6c9d2e1..8bda4bff2286 100644
--- a/kernel/trace/trace_syscalls.c
+++ b/kernel/trace/trace_syscalls.c
@@ -14,6 +14,69 @@ static int sys_refcount_exit;
14static DECLARE_BITMAP(enabled_enter_syscalls, NR_syscalls); 14static DECLARE_BITMAP(enabled_enter_syscalls, NR_syscalls);
15static DECLARE_BITMAP(enabled_exit_syscalls, NR_syscalls); 15static DECLARE_BITMAP(enabled_exit_syscalls, NR_syscalls);
16 16
17extern unsigned long __start_syscalls_metadata[];
18extern unsigned long __stop_syscalls_metadata[];
19
20static struct syscall_metadata **syscalls_metadata;
21
22static 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
46static 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
54int 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
70void set_syscall_enter_id(int num, int id)
71{
72 syscalls_metadata[num]->enter_id = id;
73}
74
75void set_syscall_exit_id(int num, int id)
76{
77 syscalls_metadata[num]->exit_id = id;
78}
79
17enum print_line_t 80enum print_line_t
18print_syscall_enter(struct trace_iterator *iter, int flags) 81print_syscall_enter(struct trace_iterator *iter, int flags)
19{ 82{
@@ -375,6 +438,29 @@ struct trace_event event_syscall_exit = {
375 .trace = print_syscall_exit, 438 .trace = print_syscall_exit,
376}; 439};
377 440
441int __init init_ftrace_syscalls(void)
442{
443 struct syscall_metadata *meta;
444 unsigned long addr;
445 int i;
446
447 syscalls_metadata = kzalloc(sizeof(*syscalls_metadata) *
448 NR_syscalls, GFP_KERNEL);
449 if (!syscalls_metadata) {
450 WARN_ON(1);
451 return -ENOMEM;
452 }
453
454 for (i = 0; i < NR_syscalls; i++) {
455 addr = arch_syscall_addr(i);
456 meta = find_syscall_meta(addr);
457 syscalls_metadata[i] = meta;
458 }
459
460 return 0;
461}
462core_initcall(init_ftrace_syscalls);
463
378#ifdef CONFIG_EVENT_PROFILE 464#ifdef CONFIG_EVENT_PROFILE
379 465
380static DECLARE_BITMAP(enabled_prof_enter_syscalls, NR_syscalls); 466static DECLARE_BITMAP(enabled_prof_enter_syscalls, NR_syscalls);