Bug 205857

Summary: tracing broken for kernels with CONFIG_GCC_PLUGIN_STRUCTLEAK=y due __attribute__ leak to tracefs formats
Product: Tools Reporter: Ivan Prisyazhnyy (john.koepi)
Component: Trace-cmd/KernelsharkAssignee: Steven Rostedt (rostedt)
Status: RESOLVED CODE_FIX    
Severity: normal CC: john.koepi, rostedt
Priority: P1    
Hardware: All   
OS: Linux   
Kernel Version: 5.x Subsystem:
Regression: No Bisected commit-id:
Attachments: tools lib traceevent: Handle gcc __attribute__(()) in fields

Description Ivan Prisyazhnyy 2019-12-14 15:34:57 UTC
### What

1. `tools/lib/traceevent` can't parse formats with `__attribute__`:

    $ sudo perf record -e syscalls:sys_enter_io_submit -aR
    libtraceevent: No such file or directory
      Error: expected type 4 but read 5

`trace-cmd` fails the same way while reporting.

2. `__attribute__` leaks into syscalls metadata at include/linux/syscalls.h:

    #define SYSCALL_METADATA(sname, nb, ...)

that leads to the leak of the attributes to the `tracefs`
trace events formats.

    $ cat /sys/kernel/debug/tracing/events/syscalls/sys_enter_io_submit/format
    name: sys_enter_io_submit
    ID: 897
    format:
    field:unsigned short common_type; offset:0; size:2; signed:0;
    ...
    field:struct iocb __attribute__((user)) * __attribute__((user)) * iocbpp; offset:32; size:8; signed:0;
                      ^^^                     ^^^
.

### Where

I am a user of Arch Linux. Arch kernels come with `CONFIG_GCC_PLUGIN_STRUCTLEAK=y`. 
This defines `__user __attribute__((user))` that exists already for at least 2 years.

I suppose all kernels since this was introduced and with enabled STRUCTLEAK 
plugin have broken tracing for the syscalls with `__user` arguments.

### Why
 
In kernels built with `CONFIG_GCC_PLUGIN_STRUCTLEAK=y`
definition of macros `__user` differs from the usual one:

If `__CHECKER__` is false at `include/linux/compiler_types.h:28`:

    # ifdef STRUCTLEAK_PLUGIN
    #  define __user __attribute__((user))
    # else
    #  define __user
    # endif

It seems that this fact leads the syscalls metadata macros at
`include/linux/syscalls.h`

    214:#define SYSCALL_DEFINE1(name, ...) SYSCALL_DEFINEx(1, _##name, __VA_ARGS__)
    198:#define SYSCALL_METADATA(sname, nb, ...)

to include GGC attributes extensions (`__attribute__`) into the
syscalls metadata that is then delivered to the `tracefs/syscalls/format`.

This gets syscalls formats to have `__attribute__` inside:

    $ cat /sys/kernel/debug/tracing/events/syscalls/sys_enter_io_submit/format
    name: sys_enter_io_submit
    ID: 897
    format:
    field:unsigned short common_type; offset:0; size:2; signed:0;
    ...
    field:struct iocb __attribute__((user)) * __attribute__((user)) * iocbpp; offset:32; size:8; signed:0;
    ...

traceevent library does not support fields format that contains
GCC `__attribute__`, like in the example above.

This in its turn makes it impossible to use tracing for those syscalls:

    $ sudo perf record -e syscalls:sys_enter_io_submit -aR
    libtraceevent: No such file or directory
      Error: expected type 4 but read 5

Thus, tracing does not work for some syscalls in Arch Linux kernels.
And I suppose for all kernels that built with structleak plugin support.

### Test

https://github.com/sitano/traceevent_attribute
Comment 1 Steven Rostedt 2020-01-30 23:56:21 UTC
Created attachment 287037 [details]
tools lib traceevent: Handle gcc __attribute__(()) in fields

Does this patch fix it for you?
Comment 2 Steven Rostedt 2020-07-08 00:59:24 UTC
Fixed by commit 5ad2bf6dd6f4 ("trace-cmd traceevent: Handle __attribute__((user)) in field names")