aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteven Rostedt <srostedt@redhat.com>2011-02-02 17:06:09 -0500
committerSteven Rostedt <rostedt@goodmis.org>2011-02-03 09:29:06 -0500
commit3d56e331b6537671c66f1b510bed0f1e0331dfc8 (patch)
tree80145576e1b9e701b7a2270c6a09798ed6b783c3
parent654986462939cd7ec18f276c6379a334dac106a7 (diff)
tracing: Replace syscall_meta_data struct array with pointer array
Currently the syscall_meta structures for the syscall tracepoints are placed in the __syscall_metadata section, and at link time, the linker makes one large array of all these syscall metadata structures. On boot up, this array is read (much like the initcall sections) and the syscall data is processed. The problem is that there is no guarantee that gcc will place complex structures nicely together in an array format. Two structures in the same file may be placed awkwardly, because gcc has no clue that they are suppose to be in an array. A hack was used previous to force the alignment to 4, to pack the structures together. But this caused alignment issues with other architectures (sparc). Instead of packing the structures into an array, the structures' addresses are now put into the __syscall_metadata section. As pointers are always the natural alignment, gcc should always pack them tightly together (otherwise initcall, extable, etc would also fail). By having the pointers to the structures in the section, we can still iterate the trace_events without causing unnecessary alignment problems with other architectures, or depending on the current behaviour of gcc that will likely change in the future just to tick us kernel developers off a little more. The __syscall_metadata section is also moved into the .init.data section as it is now only needed at boot up. Suggested-by: David Miller <davem@davemloft.net> Acked-by: David S. Miller <davem@davemloft.net> Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
-rw-r--r--include/asm-generic/vmlinux.lds.h9
-rw-r--r--include/linux/syscalls.h18
-rw-r--r--kernel/trace/trace_syscalls.c19
3 files changed, 23 insertions, 23 deletions
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 57b1b6811b61..fe77e3395b40 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -141,7 +141,8 @@
141#endif 141#endif
142 142
143#ifdef CONFIG_FTRACE_SYSCALLS 143#ifdef CONFIG_FTRACE_SYSCALLS
144#define TRACE_SYSCALLS() VMLINUX_SYMBOL(__start_syscalls_metadata) = .; \ 144#define TRACE_SYSCALLS() . = ALIGN(8); \
145 VMLINUX_SYMBOL(__start_syscalls_metadata) = .; \
145 *(__syscalls_metadata) \ 146 *(__syscalls_metadata) \
146 VMLINUX_SYMBOL(__stop_syscalls_metadata) = .; 147 VMLINUX_SYMBOL(__stop_syscalls_metadata) = .;
147#else 148#else
@@ -175,10 +176,7 @@
175 VMLINUX_SYMBOL(__stop___verbose) = .; \ 176 VMLINUX_SYMBOL(__stop___verbose) = .; \
176 LIKELY_PROFILE() \ 177 LIKELY_PROFILE() \
177 BRANCH_PROFILE() \ 178 BRANCH_PROFILE() \
178 TRACE_PRINTKS() \ 179 TRACE_PRINTKS()
179 \
180 STRUCT_ALIGN(); \
181 TRACE_SYSCALLS()
182 180
183/* 181/*
184 * Data section helpers 182 * Data section helpers
@@ -483,6 +481,7 @@
483 *(.init.rodata) \ 481 *(.init.rodata) \
484 MCOUNT_REC() \ 482 MCOUNT_REC() \
485 FTRACE_EVENTS() \ 483 FTRACE_EVENTS() \
484 TRACE_SYSCALLS() \
486 DEV_DISCARD(init.rodata) \ 485 DEV_DISCARD(init.rodata) \
487 CPU_DISCARD(init.rodata) \ 486 CPU_DISCARD(init.rodata) \
488 MEM_DISCARD(init.rodata) \ 487 MEM_DISCARD(init.rodata) \
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
index 45508fec366d..98664db1be47 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h
@@ -125,8 +125,7 @@ extern struct trace_event_functions enter_syscall_print_funcs;
125extern struct trace_event_functions exit_syscall_print_funcs; 125extern struct trace_event_functions exit_syscall_print_funcs;
126 126
127#define SYSCALL_TRACE_ENTER_EVENT(sname) \ 127#define SYSCALL_TRACE_ENTER_EVENT(sname) \
128 static struct syscall_metadata \ 128 static struct syscall_metadata __syscall_meta_##sname; \
129 __attribute__((__aligned__(4))) __syscall_meta_##sname; \
130 static struct ftrace_event_call __used \ 129 static struct ftrace_event_call __used \
131 event_enter_##sname = { \ 130 event_enter_##sname = { \
132 .name = "sys_enter"#sname, \ 131 .name = "sys_enter"#sname, \
@@ -140,8 +139,7 @@ extern struct trace_event_functions exit_syscall_print_funcs;
140 __TRACE_EVENT_FLAGS(enter_##sname, TRACE_EVENT_FL_CAP_ANY) 139 __TRACE_EVENT_FLAGS(enter_##sname, TRACE_EVENT_FL_CAP_ANY)
141 140
142#define SYSCALL_TRACE_EXIT_EVENT(sname) \ 141#define SYSCALL_TRACE_EXIT_EVENT(sname) \
143 static struct syscall_metadata \ 142 static struct syscall_metadata __syscall_meta_##sname; \
144 __attribute__((__aligned__(4))) __syscall_meta_##sname; \
145 static struct ftrace_event_call __used \ 143 static struct ftrace_event_call __used \
146 event_exit_##sname = { \ 144 event_exit_##sname = { \
147 .name = "sys_exit"#sname, \ 145 .name = "sys_exit"#sname, \
@@ -158,8 +156,6 @@ extern struct trace_event_functions exit_syscall_print_funcs;
158 SYSCALL_TRACE_ENTER_EVENT(sname); \ 156 SYSCALL_TRACE_ENTER_EVENT(sname); \
159 SYSCALL_TRACE_EXIT_EVENT(sname); \ 157 SYSCALL_TRACE_EXIT_EVENT(sname); \
160 static struct syscall_metadata __used \ 158 static struct syscall_metadata __used \
161 __attribute__((__aligned__(4))) \
162 __attribute__((section("__syscalls_metadata"))) \
163 __syscall_meta_##sname = { \ 159 __syscall_meta_##sname = { \
164 .name = "sys"#sname, \ 160 .name = "sys"#sname, \
165 .nb_args = nb, \ 161 .nb_args = nb, \
@@ -168,14 +164,15 @@ extern struct trace_event_functions exit_syscall_print_funcs;
168 .enter_event = &event_enter_##sname, \ 164 .enter_event = &event_enter_##sname, \
169 .exit_event = &event_exit_##sname, \ 165 .exit_event = &event_exit_##sname, \
170 .enter_fields = LIST_HEAD_INIT(__syscall_meta_##sname.enter_fields), \ 166 .enter_fields = LIST_HEAD_INIT(__syscall_meta_##sname.enter_fields), \
171 }; 167 }; \
168 static struct syscall_metadata __used \
169 __attribute__((section("__syscalls_metadata"))) \
170 *__p_syscall_meta_##sname = &__syscall_meta_##sname;
172 171
173#define SYSCALL_DEFINE0(sname) \ 172#define SYSCALL_DEFINE0(sname) \
174 SYSCALL_TRACE_ENTER_EVENT(_##sname); \ 173 SYSCALL_TRACE_ENTER_EVENT(_##sname); \
175 SYSCALL_TRACE_EXIT_EVENT(_##sname); \ 174 SYSCALL_TRACE_EXIT_EVENT(_##sname); \
176 static struct syscall_metadata __used \ 175 static struct syscall_metadata __used \
177 __attribute__((__aligned__(4))) \
178 __attribute__((section("__syscalls_metadata"))) \
179 __syscall_meta__##sname = { \ 176 __syscall_meta__##sname = { \
180 .name = "sys_"#sname, \ 177 .name = "sys_"#sname, \
181 .nb_args = 0, \ 178 .nb_args = 0, \
@@ -183,6 +180,9 @@ extern struct trace_event_functions exit_syscall_print_funcs;
183 .exit_event = &event_exit__##sname, \ 180 .exit_event = &event_exit__##sname, \
184 .enter_fields = LIST_HEAD_INIT(__syscall_meta__##sname.enter_fields), \ 181 .enter_fields = LIST_HEAD_INIT(__syscall_meta__##sname.enter_fields), \
185 }; \ 182 }; \
183 static struct syscall_metadata __used \
184 __attribute__((section("__syscalls_metadata"))) \
185 *__p_syscall_meta_##sname = &__syscall_meta__##sname; \
186 asmlinkage long sys_##sname(void) 186 asmlinkage long sys_##sname(void)
187#else 187#else
188#define SYSCALL_DEFINE0(name) asmlinkage long sys_##name(void) 188#define SYSCALL_DEFINE0(name) asmlinkage long sys_##name(void)
diff --git a/kernel/trace/trace_syscalls.c b/kernel/trace/trace_syscalls.c
index b706529b4fc7..5c9fe08d2093 100644
--- a/kernel/trace/trace_syscalls.c
+++ b/kernel/trace/trace_syscalls.c
@@ -55,20 +55,21 @@ struct ftrace_event_class event_class_syscall_exit = {
55 .raw_init = init_syscall_trace, 55 .raw_init = init_syscall_trace,
56}; 56};
57 57
58extern unsigned long __start_syscalls_metadata[]; 58extern struct syscall_metadata *__start_syscalls_metadata[];
59extern unsigned long __stop_syscalls_metadata[]; 59extern struct syscall_metadata *__stop_syscalls_metadata[];
60 60
61static struct syscall_metadata **syscalls_metadata; 61static struct syscall_metadata **syscalls_metadata;
62 62
63static struct syscall_metadata *find_syscall_meta(unsigned long syscall) 63static __init struct syscall_metadata *
64find_syscall_meta(unsigned long syscall)
64{ 65{
65 struct syscall_metadata *start; 66 struct syscall_metadata **start;
66 struct syscall_metadata *stop; 67 struct syscall_metadata **stop;
67 char str[KSYM_SYMBOL_LEN]; 68 char str[KSYM_SYMBOL_LEN];
68 69
69 70
70 start = (struct syscall_metadata *)__start_syscalls_metadata; 71 start = __start_syscalls_metadata;
71 stop = (struct syscall_metadata *)__stop_syscalls_metadata; 72 stop = __stop_syscalls_metadata;
72 kallsyms_lookup(syscall, NULL, NULL, NULL, str); 73 kallsyms_lookup(syscall, NULL, NULL, NULL, str);
73 74
74 for ( ; start < stop; start++) { 75 for ( ; start < stop; start++) {
@@ -78,8 +79,8 @@ static struct syscall_metadata *find_syscall_meta(unsigned long syscall)
78 * with "SyS" instead of "sys", leading to an unwanted 79 * with "SyS" instead of "sys", leading to an unwanted
79 * mismatch. 80 * mismatch.
80 */ 81 */
81 if (start->name && !strcmp(start->name + 3, str + 3)) 82 if ((*start)->name && !strcmp((*start)->name + 3, str + 3))
82 return start; 83 return *start;
83 } 84 }
84 return NULL; 85 return NULL;
85} 86}