Problem description: gcc happily align structures defined statically on 32-byte. Ftrace trace events and Tracepoints both statically define structures into sections (using the "section" attribute), to then assign these to symbols with the linker scripts to iterate the these sections as an array. However, gcc uses different alignments for these structures when they are defined statically and when they are globally visible and/or in an array. Therefore iteration on these arrays sees "holes" of padding. Use the __u64_packed_aligned for type declarations and __u64_aligned for variable definitions to ensure that gcc a) iterates on the correctly aligned type. (type attribute) b) generates the definitions within the sections with the appropriate alignment. (variable attribute) The Ftrace code introduced the "aligned(4)" variable attribute in commit 1473e4417c79f12d91ef91a469699bfa911f510f to try to work around this problem that showed up on x86_64, but it causes unaligned accesses on sparc64, and is generally a bad idea on 64-bit if RCU pointers are contained within the structure. Moreover, it did not use the same attribute as type attribute, which could cause the iteration on the extern array structure not to match the variable definitions for some structure sizes. Fix this by using __u64_packed_aligned as type attribute and __u64_aligned as variable attribute. We should also ensure proper alignment of each Ftrace section in include/asm-generic/vmlinux.lds.h. Moving all STRUCT_ALIGN() for FTRACE_EVENTS() and TRACE_SYSCALLS() into the definitions, so the alignment is only done if these infrastructures are configured in. Use U64_ALIGN instead of STRUCT_ALIGN. Also align TRACE_PRINTKS on U64_ALIGN to make sure the beginning of the section is aligned on pointer size. Signed-off-by: Mathieu Desnoyers CC: David Miller CC: Steven Rostedt CC: Frederic Weisbecker CC: Ingo Molnar --- include/asm-generic/vmlinux.lds.h | 19 ++++++++++--------- include/linux/compiler.h | 6 +++--- include/linux/ftrace_event.h | 2 +- include/linux/syscalls.h | 18 ++++++++---------- include/trace/ftrace.h | 8 ++++---- include/trace/syscall.h | 2 +- kernel/trace/trace.h | 2 +- kernel/trace/trace_export.c | 2 +- 8 files changed, 29 insertions(+), 30 deletions(-) Index: linux-2.6-lttng/include/linux/compiler.h =================================================================== --- linux-2.6-lttng.orig/include/linux/compiler.h +++ linux-2.6-lttng/include/linux/compiler.h @@ -80,7 +80,7 @@ struct ftrace_branch_data { }; unsigned long miss_hit[2]; }; -}; +} __u64_packed_aligned; /* * Note: DISABLE_BRANCH_PROFILING can be used by special lowlevel code @@ -96,7 +96,7 @@ void ftrace_likely_update(struct ftrace_ #define __branch_check__(x, expect) ({ \ int ______r; \ static struct ftrace_branch_data \ - __attribute__((__aligned__(4))) \ + __u64_aligned \ __attribute__((section("_ftrace_annotated_branch"))) \ ______f = { \ .func = __func__, \ @@ -131,7 +131,7 @@ void ftrace_likely_update(struct ftrace_ ({ \ int ______r; \ static struct ftrace_branch_data \ - __attribute__((__aligned__(4))) \ + __u64_aligned \ __attribute__((section("_ftrace_branch"))) \ ______f = { \ .func = __func__, \ Index: linux-2.6-lttng/include/linux/syscalls.h =================================================================== --- linux-2.6-lttng.orig/include/linux/syscalls.h +++ linux-2.6-lttng/include/linux/syscalls.h @@ -126,12 +126,11 @@ extern struct trace_event_functions exit #define SYSCALL_TRACE_ENTER_EVENT(sname) \ static struct syscall_metadata \ - __attribute__((__aligned__(4))) __syscall_meta_##sname; \ + __u64_aligned __syscall_meta_##sname; \ static struct ftrace_event_call \ - __attribute__((__aligned__(4))) event_enter_##sname; \ + __u64_aligned event_enter_##sname; \ static struct ftrace_event_call __used \ - __attribute__((__aligned__(4))) \ - __attribute__((section("_ftrace_events"))) \ + __u64_aligned __attribute__((section("_ftrace_events"))) \ event_enter_##sname = { \ .name = "sys_enter"#sname, \ .class = &event_class_syscall_enter, \ @@ -141,12 +140,11 @@ extern struct trace_event_functions exit #define SYSCALL_TRACE_EXIT_EVENT(sname) \ static struct syscall_metadata \ - __attribute__((__aligned__(4))) __syscall_meta_##sname; \ + __u64_aligned __syscall_meta_##sname; \ static struct ftrace_event_call \ - __attribute__((__aligned__(4))) event_exit_##sname; \ + __u64_aligned event_exit_##sname; \ static struct ftrace_event_call __used \ - __attribute__((__aligned__(4))) \ - __attribute__((section("_ftrace_events"))) \ + __u64_aligned __attribute__((section("_ftrace_events"))) \ event_exit_##sname = { \ .name = "sys_exit"#sname, \ .class = &event_class_syscall_exit, \ @@ -158,7 +156,7 @@ extern struct trace_event_functions exit SYSCALL_TRACE_ENTER_EVENT(sname); \ SYSCALL_TRACE_EXIT_EVENT(sname); \ static struct syscall_metadata __used \ - __attribute__((__aligned__(4))) \ + __u64_aligned \ __attribute__((section("__syscalls_metadata"))) \ __syscall_meta_##sname = { \ .name = "sys"#sname, \ @@ -174,7 +172,7 @@ extern struct trace_event_functions exit SYSCALL_TRACE_ENTER_EVENT(_##sname); \ SYSCALL_TRACE_EXIT_EVENT(_##sname); \ static struct syscall_metadata __used \ - __attribute__((__aligned__(4))) \ + __u64_aligned \ __attribute__((section("__syscalls_metadata"))) \ __syscall_meta__##sname = { \ .name = "sys_"#sname, \ Index: linux-2.6-lttng/include/trace/ftrace.h =================================================================== --- linux-2.6-lttng.orig/include/trace/ftrace.h +++ linux-2.6-lttng/include/trace/ftrace.h @@ -79,7 +79,7 @@ #undef DEFINE_EVENT #define DEFINE_EVENT(template, name, proto, args) \ static struct ftrace_event_call __used \ - __attribute__((__aligned__(4))) event_##name; + __u64_aligned event_##name; #undef DEFINE_EVENT_PRINT #define DEFINE_EVENT_PRINT(template, name, proto, args, print) \ @@ -447,7 +447,7 @@ static inline notrace int ftrace_get_off * }; * * static struct ftrace_event_call __used - * __attribute__((__aligned__(4))) + * __u64_aligned * __attribute__((section("_ftrace_events"))) event_ = { * .name = "", * .class = event_class_