Commit e4a9ea5e authored by Steven Rostedt's avatar Steven Rostedt Committed by Steven Rostedt

tracing: Replace trace_event struct array with pointer array

Currently the trace_event structures are placed in the _ftrace_events
section, and at link time, the linker makes one large array of all
the trace_event structures. On boot up, this array is read (much like
the initcall sections) and the events are 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 _ftrace_event 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 _ftrace_event section is also moved into the .init.data section
as it is now only needed at boot up.
Suggested-by: default avatarDavid Miller <davem@davemloft.net>
Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Acked-by: default avatarDavid S. Miller <davem@davemloft.net>
Signed-off-by: default avatarSteven Rostedt <rostedt@goodmis.org>
parent 9ffdc6c3
...@@ -124,7 +124,8 @@ ...@@ -124,7 +124,8 @@
#endif #endif
#ifdef CONFIG_EVENT_TRACING #ifdef CONFIG_EVENT_TRACING
#define FTRACE_EVENTS() VMLINUX_SYMBOL(__start_ftrace_events) = .; \ #define FTRACE_EVENTS() . = ALIGN(8); \
VMLINUX_SYMBOL(__start_ftrace_events) = .; \
*(_ftrace_events) \ *(_ftrace_events) \
VMLINUX_SYMBOL(__stop_ftrace_events) = .; VMLINUX_SYMBOL(__stop_ftrace_events) = .;
#else #else
...@@ -179,9 +180,6 @@ ...@@ -179,9 +180,6 @@
TRACE_PRINTKS() \ TRACE_PRINTKS() \
\ \
STRUCT_ALIGN(); \ STRUCT_ALIGN(); \
FTRACE_EVENTS() \
\
STRUCT_ALIGN(); \
TRACE_SYSCALLS() TRACE_SYSCALLS()
/* /*
...@@ -482,6 +480,7 @@ ...@@ -482,6 +480,7 @@
KERNEL_CTORS() \ KERNEL_CTORS() \
*(.init.rodata) \ *(.init.rodata) \
MCOUNT_REC() \ MCOUNT_REC() \
FTRACE_EVENTS() \
DEV_DISCARD(init.rodata) \ DEV_DISCARD(init.rodata) \
CPU_DISCARD(init.rodata) \ CPU_DISCARD(init.rodata) \
MEM_DISCARD(init.rodata) \ MEM_DISCARD(init.rodata) \
......
...@@ -389,7 +389,7 @@ struct module ...@@ -389,7 +389,7 @@ struct module
unsigned int num_trace_bprintk_fmt; unsigned int num_trace_bprintk_fmt;
#endif #endif
#ifdef CONFIG_EVENT_TRACING #ifdef CONFIG_EVENT_TRACING
struct ftrace_event_call *trace_events; struct ftrace_event_call **trace_events;
unsigned int num_trace_events; unsigned int num_trace_events;
#endif #endif
#ifdef CONFIG_FTRACE_MCOUNT_RECORD #ifdef CONFIG_FTRACE_MCOUNT_RECORD
......
...@@ -128,28 +128,30 @@ extern struct trace_event_functions exit_syscall_print_funcs; ...@@ -128,28 +128,30 @@ extern struct trace_event_functions exit_syscall_print_funcs;
static struct syscall_metadata \ static struct syscall_metadata \
__attribute__((__aligned__(4))) __syscall_meta_##sname; \ __attribute__((__aligned__(4))) __syscall_meta_##sname; \
static struct ftrace_event_call __used \ static struct ftrace_event_call __used \
__attribute__((__aligned__(4))) \
__attribute__((section("_ftrace_events"))) \
event_enter_##sname = { \ event_enter_##sname = { \
.name = "sys_enter"#sname, \ .name = "sys_enter"#sname, \
.class = &event_class_syscall_enter, \ .class = &event_class_syscall_enter, \
.event.funcs = &enter_syscall_print_funcs, \ .event.funcs = &enter_syscall_print_funcs, \
.data = (void *)&__syscall_meta_##sname,\ .data = (void *)&__syscall_meta_##sname,\
}; \ }; \
static struct ftrace_event_call __used \
__attribute__((section("_ftrace_events"))) \
*__event_enter_##sname = &event_enter_##sname; \
__TRACE_EVENT_FLAGS(enter_##sname, TRACE_EVENT_FL_CAP_ANY) __TRACE_EVENT_FLAGS(enter_##sname, TRACE_EVENT_FL_CAP_ANY)
#define SYSCALL_TRACE_EXIT_EVENT(sname) \ #define SYSCALL_TRACE_EXIT_EVENT(sname) \
static struct syscall_metadata \ static struct syscall_metadata \
__attribute__((__aligned__(4))) __syscall_meta_##sname; \ __attribute__((__aligned__(4))) __syscall_meta_##sname; \
static struct ftrace_event_call __used \ static struct ftrace_event_call __used \
__attribute__((__aligned__(4))) \
__attribute__((section("_ftrace_events"))) \
event_exit_##sname = { \ event_exit_##sname = { \
.name = "sys_exit"#sname, \ .name = "sys_exit"#sname, \
.class = &event_class_syscall_exit, \ .class = &event_class_syscall_exit, \
.event.funcs = &exit_syscall_print_funcs, \ .event.funcs = &exit_syscall_print_funcs, \
.data = (void *)&__syscall_meta_##sname,\ .data = (void *)&__syscall_meta_##sname,\
}; \ }; \
static struct ftrace_event_call __used \
__attribute__((section("_ftrace_events"))) \
*__event_exit_##sname = &event_exit_##sname; \
__TRACE_EVENT_FLAGS(exit_##sname, TRACE_EVENT_FL_CAP_ANY) __TRACE_EVENT_FLAGS(exit_##sname, TRACE_EVENT_FL_CAP_ANY)
#define SYSCALL_METADATA(sname, nb) \ #define SYSCALL_METADATA(sname, nb) \
......
...@@ -446,14 +446,16 @@ static inline notrace int ftrace_get_offsets_##call( \ ...@@ -446,14 +446,16 @@ static inline notrace int ftrace_get_offsets_##call( \
* .reg = ftrace_event_reg, * .reg = ftrace_event_reg,
* }; * };
* *
* static struct ftrace_event_call __used * static struct ftrace_event_call event_<call> = {
* __attribute__((__aligned__(4)))
* __attribute__((section("_ftrace_events"))) event_<call> = {
* .name = "<call>", * .name = "<call>",
* .class = event_class_<template>, * .class = event_class_<template>,
* .event = &ftrace_event_type_<call>, * .event = &ftrace_event_type_<call>,
* .print_fmt = print_fmt_<call>, * .print_fmt = print_fmt_<call>,
* }; * };
* // its only safe to use pointers when doing linker tricks to
* // create an array.
* static struct ftrace_event_call __used
* __attribute__((section("_ftrace_events"))) *__event_<call> = &event_<call>;
* *
*/ */
...@@ -579,28 +581,28 @@ static struct ftrace_event_class __used event_class_##call = { \ ...@@ -579,28 +581,28 @@ static struct ftrace_event_class __used event_class_##call = { \
#undef DEFINE_EVENT #undef DEFINE_EVENT
#define DEFINE_EVENT(template, call, proto, args) \ #define DEFINE_EVENT(template, call, proto, args) \
\ \
static struct ftrace_event_call __used \ static struct ftrace_event_call __used event_##call = { \
__attribute__((__aligned__(4))) \
__attribute__((section("_ftrace_events"))) event_##call = { \
.name = #call, \ .name = #call, \
.class = &event_class_##template, \ .class = &event_class_##template, \
.event.funcs = &ftrace_event_type_funcs_##template, \ .event.funcs = &ftrace_event_type_funcs_##template, \
.print_fmt = print_fmt_##template, \ .print_fmt = print_fmt_##template, \
}; }; \
static struct ftrace_event_call __used \
__attribute__((section("_ftrace_events"))) *__event_##call = &event_##call
#undef DEFINE_EVENT_PRINT #undef DEFINE_EVENT_PRINT
#define DEFINE_EVENT_PRINT(template, call, proto, args, print) \ #define DEFINE_EVENT_PRINT(template, call, proto, args, print) \
\ \
static const char print_fmt_##call[] = print; \ static const char print_fmt_##call[] = print; \
\ \
static struct ftrace_event_call __used \ static struct ftrace_event_call __used event_##call = { \
__attribute__((__aligned__(4))) \
__attribute__((section("_ftrace_events"))) event_##call = { \
.name = #call, \ .name = #call, \
.class = &event_class_##template, \ .class = &event_class_##template, \
.event.funcs = &ftrace_event_type_funcs_##call, \ .event.funcs = &ftrace_event_type_funcs_##call, \
.print_fmt = print_fmt_##call, \ .print_fmt = print_fmt_##call, \
} }; \
static struct ftrace_event_call __used \
__attribute__((section("_ftrace_events"))) *__event_##call = &event_##call
#include TRACE_INCLUDE(TRACE_INCLUDE_FILE) #include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
......
...@@ -1284,7 +1284,7 @@ trace_create_file_ops(struct module *mod) ...@@ -1284,7 +1284,7 @@ trace_create_file_ops(struct module *mod)
static void trace_module_add_events(struct module *mod) static void trace_module_add_events(struct module *mod)
{ {
struct ftrace_module_file_ops *file_ops = NULL; struct ftrace_module_file_ops *file_ops = NULL;
struct ftrace_event_call *call, *start, *end; struct ftrace_event_call **call, **start, **end;
start = mod->trace_events; start = mod->trace_events;
end = mod->trace_events + mod->num_trace_events; end = mod->trace_events + mod->num_trace_events;
...@@ -1297,7 +1297,7 @@ static void trace_module_add_events(struct module *mod) ...@@ -1297,7 +1297,7 @@ static void trace_module_add_events(struct module *mod)
return; return;
for_each_event(call, start, end) { for_each_event(call, start, end) {
__trace_add_event_call(call, mod, __trace_add_event_call(*call, mod,
&file_ops->id, &file_ops->enable, &file_ops->id, &file_ops->enable,
&file_ops->filter, &file_ops->format); &file_ops->filter, &file_ops->format);
} }
...@@ -1367,8 +1367,8 @@ static struct notifier_block trace_module_nb = { ...@@ -1367,8 +1367,8 @@ static struct notifier_block trace_module_nb = {
.priority = 0, .priority = 0,
}; };
extern struct ftrace_event_call __start_ftrace_events[]; extern struct ftrace_event_call *__start_ftrace_events[];
extern struct ftrace_event_call __stop_ftrace_events[]; extern struct ftrace_event_call *__stop_ftrace_events[];
static char bootup_event_buf[COMMAND_LINE_SIZE] __initdata; static char bootup_event_buf[COMMAND_LINE_SIZE] __initdata;
...@@ -1384,7 +1384,7 @@ __setup("trace_event=", setup_trace_event); ...@@ -1384,7 +1384,7 @@ __setup("trace_event=", setup_trace_event);
static __init int event_trace_init(void) static __init int event_trace_init(void)
{ {
struct ftrace_event_call *call; struct ftrace_event_call **call;
struct dentry *d_tracer; struct dentry *d_tracer;
struct dentry *entry; struct dentry *entry;
struct dentry *d_events; struct dentry *d_events;
...@@ -1430,7 +1430,7 @@ static __init int event_trace_init(void) ...@@ -1430,7 +1430,7 @@ static __init int event_trace_init(void)
pr_warning("tracing: Failed to allocate common fields"); pr_warning("tracing: Failed to allocate common fields");
for_each_event(call, __start_ftrace_events, __stop_ftrace_events) { for_each_event(call, __start_ftrace_events, __stop_ftrace_events) {
__trace_add_event_call(call, NULL, &ftrace_event_id_fops, __trace_add_event_call(*call, NULL, &ftrace_event_id_fops,
&ftrace_enable_fops, &ftrace_enable_fops,
&ftrace_event_filter_fops, &ftrace_event_filter_fops,
&ftrace_event_format_fops); &ftrace_event_format_fops);
......
...@@ -161,13 +161,13 @@ struct ftrace_event_class event_class_ftrace_##call = { \ ...@@ -161,13 +161,13 @@ struct ftrace_event_class event_class_ftrace_##call = { \
.fields = LIST_HEAD_INIT(event_class_ftrace_##call.fields),\ .fields = LIST_HEAD_INIT(event_class_ftrace_##call.fields),\
}; \ }; \
\ \
struct ftrace_event_call __used \ struct ftrace_event_call __used event_##call = { \
__attribute__((__aligned__(4))) \
__attribute__((section("_ftrace_events"))) event_##call = { \
.name = #call, \ .name = #call, \
.event.type = etype, \ .event.type = etype, \
.class = &event_class_ftrace_##call, \ .class = &event_class_ftrace_##call, \
.print_fmt = print, \ .print_fmt = print, \
}; \ }; \
struct ftrace_event_call __used \
__attribute__((section("_ftrace_events"))) *__event_##call = &event_##call;
#include "trace_entries.h" #include "trace_entries.h"
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment