tracing: Move syscalls metadata handling from arch to core
authorFrederic Weisbecker <fweisbec@gmail.com>
Sat, 19 Sep 2009 04:50:42 +0000 (06:50 +0200)
committerFrederic Weisbecker <fweisbec@gmail.com>
Wed, 14 Oct 2009 07:53:56 +0000 (09:53 +0200)
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>
arch/s390/kernel/ftrace.c
arch/x86/kernel/ftrace.c
include/trace/syscall.h
kernel/trace/trace_syscalls.c

index 57bdcb1e3cdf0391928565dc26118e5272b3a21b..7c5752c3423df171afcc8fed9f651adcebbf9511 100644 (file)
@@ -206,73 +206,10 @@ out:
 
 #ifdef CONFIG_FTRACE_SYSCALLS
 
-extern unsigned long __start_syscalls_metadata[];
-extern unsigned long __stop_syscalls_metadata[];
 extern unsigned int sys_call_table[];
 
-static struct syscall_metadata **syscalls_metadata;
-
-struct syscall_metadata *syscall_nr_to_meta(int nr)
-{
-       if (!syscalls_metadata || nr >= NR_syscalls || nr < 0)
-               return NULL;
-
-       return syscalls_metadata[nr];
-}
-
-int syscall_name_to_nr(char *name)
-{
-       int i;
-
-       if (!syscalls_metadata)
-               return -1;
-       for (i = 0; i < NR_syscalls; i++)
-               if (syscalls_metadata[i])
-                       if (!strcmp(syscalls_metadata[i]->name, name))
-                               return i;
-       return -1;
-}
-
-void set_syscall_enter_id(int num, int id)
-{
-       syscalls_metadata[num]->enter_id = id;
-}
-
-void set_syscall_exit_id(int num, int id)
+unsigned long __init arch_syscall_addr(int nr)
 {
-       syscalls_metadata[num]->exit_id = id;
-}
-
-static struct syscall_metadata *find_syscall_meta(unsigned long syscall)
-{
-       struct syscall_metadata *start;
-       struct syscall_metadata *stop;
-       char str[KSYM_SYMBOL_LEN];
-
-       start = (struct syscall_metadata *)__start_syscalls_metadata;
-       stop = (struct syscall_metadata *)__stop_syscalls_metadata;
-       kallsyms_lookup(syscall, NULL, NULL, NULL, str);
-
-       for ( ; start < stop; start++) {
-               if (start->name && !strcmp(start->name + 3, str + 3))
-                       return start;
-       }
-       return NULL;
-}
-
-static int __init arch_init_ftrace_syscalls(void)
-{
-       struct syscall_metadata *meta;
-       int i;
-       syscalls_metadata = kzalloc(sizeof(*syscalls_metadata) * NR_syscalls,
-                                   GFP_KERNEL);
-       if (!syscalls_metadata)
-               return -ENOMEM;
-       for (i = 0; i < NR_syscalls; i++) {
-               meta = find_syscall_meta((unsigned long)sys_call_table[i]);
-               syscalls_metadata[i] = meta;
-       }
-       return 0;
+       return (unsigned long)sys_call_table[nr];
 }
-arch_initcall(arch_init_ftrace_syscalls);
 #endif
index 25e6f5fc4b1e6f53fa0b57bf1a5444ed32c0a2fb..5a1b9758fd62796f45c9654cd87d55040a525c07 100644 (file)
@@ -470,82 +470,10 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
 
 #ifdef CONFIG_FTRACE_SYSCALLS
 
-extern unsigned long __start_syscalls_metadata[];
-extern unsigned long __stop_syscalls_metadata[];
 extern unsigned long *sys_call_table;
 
-static struct syscall_metadata **syscalls_metadata;
-
-static struct syscall_metadata *find_syscall_meta(unsigned long *syscall)
-{
-       struct syscall_metadata *start;
-       struct syscall_metadata *stop;
-       char str[KSYM_SYMBOL_LEN];
-
-
-       start = (struct syscall_metadata *)__start_syscalls_metadata;
-       stop = (struct syscall_metadata *)__stop_syscalls_metadata;
-       kallsyms_lookup((unsigned long) syscall, NULL, NULL, NULL, str);
-
-       for ( ; start < stop; start++) {
-               if (start->name && !strcmp(start->name, str))
-                       return start;
-       }
-       return NULL;
-}
-
-struct syscall_metadata *syscall_nr_to_meta(int nr)
-{
-       if (!syscalls_metadata || nr >= NR_syscalls || nr < 0)
-               return NULL;
-
-       return syscalls_metadata[nr];
-}
-
-int syscall_name_to_nr(char *name)
-{
-       int i;
-
-       if (!syscalls_metadata)
-               return -1;
-
-       for (i = 0; i < NR_syscalls; i++) {
-               if (syscalls_metadata[i]) {
-                       if (!strcmp(syscalls_metadata[i]->name, name))
-                               return i;
-               }
-       }
-       return -1;
-}
-
-void set_syscall_enter_id(int num, int id)
-{
-       syscalls_metadata[num]->enter_id = id;
-}
-
-void set_syscall_exit_id(int num, int id)
+unsigned long __init arch_syscall_addr(int nr)
 {
-       syscalls_metadata[num]->exit_id = id;
-}
-
-static int __init arch_init_ftrace_syscalls(void)
-{
-       int i;
-       struct syscall_metadata *meta;
-       unsigned long **psys_syscall_table = &sys_call_table;
-
-       syscalls_metadata = kzalloc(sizeof(*syscalls_metadata) *
-                                       NR_syscalls, GFP_KERNEL);
-       if (!syscalls_metadata) {
-               WARN_ON(1);
-               return -ENOMEM;
-       }
-
-       for (i = 0; i < NR_syscalls; i++) {
-               meta = find_syscall_meta(psys_syscall_table[i]);
-               syscalls_metadata[i] = meta;
-       }
-       return 0;
+       return (unsigned long)(&sys_call_table)[nr];
 }
-arch_initcall(arch_init_ftrace_syscalls);
 #endif
index 5dc283ba5ae07dd14fe29a0cee8611c7a0a7e937..e972f0a40f8d02af648863793adb7e8383673f7b 100644 (file)
@@ -33,7 +33,7 @@ struct syscall_metadata {
 };
 
 #ifdef CONFIG_FTRACE_SYSCALLS
-extern struct syscall_metadata *syscall_nr_to_meta(int nr);
+extern unsigned long arch_syscall_addr(int nr);
 extern int syscall_name_to_nr(char *name);
 void set_syscall_enter_id(int num, int id);
 void set_syscall_exit_id(int num, int id);
index 9fbce6c9d2e14610762039f0e484ca1509790c6d..8bda4bff2286644a68d601bbb6af7c0938673be4 100644 (file)
@@ -14,6 +14,69 @@ static int sys_refcount_exit;
 static DECLARE_BITMAP(enabled_enter_syscalls, NR_syscalls);
 static DECLARE_BITMAP(enabled_exit_syscalls, NR_syscalls);
 
+extern unsigned long __start_syscalls_metadata[];
+extern unsigned long __stop_syscalls_metadata[];
+
+static struct syscall_metadata **syscalls_metadata;
+
+static struct syscall_metadata *find_syscall_meta(unsigned long syscall)
+{
+       struct syscall_metadata *start;
+       struct syscall_metadata *stop;
+       char str[KSYM_SYMBOL_LEN];
+
+
+       start = (struct syscall_metadata *)__start_syscalls_metadata;
+       stop = (struct syscall_metadata *)__stop_syscalls_metadata;
+       kallsyms_lookup(syscall, NULL, NULL, NULL, str);
+
+       for ( ; start < stop; start++) {
+               /*
+                * Only compare after the "sys" prefix. Archs that use
+                * syscall wrappers may have syscalls symbols aliases prefixed
+                * with "SyS" instead of "sys", leading to an unwanted
+                * mismatch.
+                */
+               if (start->name && !strcmp(start->name + 3, str + 3))
+                       return start;
+       }
+       return NULL;
+}
+
+static struct syscall_metadata *syscall_nr_to_meta(int nr)
+{
+       if (!syscalls_metadata || nr >= NR_syscalls || nr < 0)
+               return NULL;
+
+       return syscalls_metadata[nr];
+}
+
+int syscall_name_to_nr(char *name)
+{
+       int i;
+
+       if (!syscalls_metadata)
+               return -1;
+
+       for (i = 0; i < NR_syscalls; i++) {
+               if (syscalls_metadata[i]) {
+                       if (!strcmp(syscalls_metadata[i]->name, name))
+                               return i;
+               }
+       }
+       return -1;
+}
+
+void set_syscall_enter_id(int num, int id)
+{
+       syscalls_metadata[num]->enter_id = id;
+}
+
+void set_syscall_exit_id(int num, int id)
+{
+       syscalls_metadata[num]->exit_id = id;
+}
+
 enum print_line_t
 print_syscall_enter(struct trace_iterator *iter, int flags)
 {
@@ -375,6 +438,29 @@ struct trace_event event_syscall_exit = {
        .trace                  = print_syscall_exit,
 };
 
+int __init init_ftrace_syscalls(void)
+{
+       struct syscall_metadata *meta;
+       unsigned long addr;
+       int i;
+
+       syscalls_metadata = kzalloc(sizeof(*syscalls_metadata) *
+                                       NR_syscalls, GFP_KERNEL);
+       if (!syscalls_metadata) {
+               WARN_ON(1);
+               return -ENOMEM;
+       }
+
+       for (i = 0; i < NR_syscalls; i++) {
+               addr = arch_syscall_addr(i);
+               meta = find_syscall_meta(addr);
+               syscalls_metadata[i] = meta;
+       }
+
+       return 0;
+}
+core_initcall(init_ftrace_syscalls);
+
 #ifdef CONFIG_EVENT_PROFILE
 
 static DECLARE_BITMAP(enabled_prof_enter_syscalls, NR_syscalls);