[PATCH v2 0/5] tracepoints: Add warnings for unused tracepoints and trace events

Steven Rostedt posted 5 patches 3 months, 4 weeks ago
There is a newer version of this series
include/asm-generic/vmlinux.lds.h  |   1 +
include/linux/tracepoint.h         |  13 ++
kernel/trace/Kconfig               |  31 +++
kernel/trace/trace_events_filter.c |   4 +
kernel/tracepoint.c                |  26 +++
scripts/Makefile                   |   4 +
scripts/sorttable.c                | 444 ++++++++++++++++++++++++++++++-------
7 files changed, 437 insertions(+), 86 deletions(-)
[PATCH v2 0/5] tracepoints: Add warnings for unused tracepoints and trace events
Posted by Steven Rostedt 3 months, 4 weeks ago
Every trace event can take up to 5K of memory in text and meta data regardless
if they are used or not. Trace events should not be created if they are not
used.  Currently there's over a hundred events in the kernel that are defined
but unused, either because their callers were removed without removing the
trace event with it, or a config hides the trace event caller but not the
trace event itself. And in some cases, trace events were simply added but were
never called for whatever reason. The number of unused trace events continues
to grow.

This patch series aims to fix this.

The first patch creates a new section called __tracepoint_check, where all
callers of a tracepoint creates a variable that is placed in this section with
a pointer to the tracepoint they use. Then on boot up, it iterates this
section and will modify the tracepoint's "func" field to a value of 1 (all
tracepoints "func" fields are initialized to NULL and is only set when they
are registered). This takes place before any tracepoint can be registered.

Then each tracepoint is iterated on and if any tracepoint does not have its
"func" field set to 1 a warning is triggerd and every tracepoint that doesn't
have that field set is printed. The "func" field is then reset back to NULL.

The second patch modifies scripts/sorttable.c to read the __tracepoint_check
section. It sorts it, and then reads the __tracepoint_ptr section that has all
compiled in tracepoints. It makes sure that every tracepoint is found in the
check section and if not, it prints a warning message about it. This lists the
missing tracepoints at build time.

The third patch updates sorttable to work for arm64 when compiled with gcc. As
gcc's arm64 build doesn't put addresses in their section but saves them off in
the RELA sections. This mostly takes the work done that was needed to do the
mcount sorting at boot up on arm64.

The forth patch adds EXPORT_TRACEPOINT() to the __tracepoint_check section as
well. There was several locations that adds tracepoints in the kernel proper
that are only used in modules. It was getting quite complex trying to move
things around that I just decided to make any tracepoint in a
EXPORT_TRACEPOINT "used". I'm using the analogy of static and global
functions. An unused static function gets a warning but an unused global one
does not.

The last patch updates the trace_ftrace_test_filter boot up self test. That
selftest creates a trace event to run a bunch of filter tests on it without
actually calling the tracepoint. To quiet the warning, the selftest tracepoint
is called within a if (!trace_<event>_enabled()) section, where it will not be
optimized out, nor will it be called.

This is v2 from: https://lore.kernel.org/linux-trace-kernel/20250529130138.544ffec4@gandalf.local.home/
which was simply the first patch. This version adds the other patches.

Steven Rostedt (5):
      tracepoints: Add verifier that makes sure all defined tracepoints are used
      tracing: sorttable: Add a tracepoint verification check at build time
      tracing: sorttable: Find unused tracepoints for arm64 that uses reloc for address
      tracepoint: Do not warn for unused event that is exported
      tracing: Call trace_ftrace_test_filter() for the event

----
 include/asm-generic/vmlinux.lds.h  |   1 +
 include/linux/tracepoint.h         |  13 ++
 kernel/trace/Kconfig               |  31 +++
 kernel/trace/trace_events_filter.c |   4 +
 kernel/tracepoint.c                |  26 +++
 scripts/Makefile                   |   4 +
 scripts/sorttable.c                | 444 ++++++++++++++++++++++++++++++-------
 7 files changed, 437 insertions(+), 86 deletions(-)
Re: [PATCH v2 0/5] tracepoints: Add warnings for unused tracepoints and trace events
Posted by Randy Dunlap 3 months, 4 weeks ago
Hi,

On 6/12/25 4:58 PM, Steven Rostedt wrote:
> Every trace event can take up to 5K of memory in text and meta data regardless

s/meta data/metadata/ unless you are referring to meta's data.

s/meta data/metadata/ in patches 1 and 2 also.

> if they are used or not. Trace events should not be created if they are not
> used.  Currently there's over a hundred events in the kernel that are defined
> but unused, either because their callers were removed without removing the
> trace event with it, or a config hides the trace event caller but not the
> trace event itself. And in some cases, trace events were simply added but were
> never called for whatever reason. The number of unused trace events continues
> to grow.
> 
> This patch series aims to fix this.
> 
> The first patch creates a new section called __tracepoint_check, where all
> callers of a tracepoint creates a variable that is placed in this section with
> a pointer to the tracepoint they use. Then on boot up, it iterates this
> section and will modify the tracepoint's "func" field to a value of 1 (all
> tracepoints "func" fields are initialized to NULL and is only set when they
> are registered). This takes place before any tracepoint can be registered.
> 
> Then each tracepoint is iterated on and if any tracepoint does not have its
> "func" field set to 1 a warning is triggerd and every tracepoint that doesn't

triggered

> have that field set is printed. The "func" field is then reset back to NULL.
> 
> The second patch modifies scripts/sorttable.c to read the __tracepoint_check
> section. It sorts it, and then reads the __tracepoint_ptr section that has all
> compiled in tracepoints. It makes sure that every tracepoint is found in the
> check section and if not, it prints a warning message about it. This lists the
> missing tracepoints at build time.
> 
> The third patch updates sorttable to work for arm64 when compiled with gcc. As
> gcc's arm64 build doesn't put addresses in their section but saves them off in
> the RELA sections. This mostly takes the work done that was needed to do the
> mcount sorting at boot up on arm64.
> 
> The forth patch adds EXPORT_TRACEPOINT() to the __tracepoint_check section as

fourth (or are you coding in forth?)

> well. There was several locations that adds tracepoints in the kernel proper
> that are only used in modules. It was getting quite complex trying to move
> things around that I just decided to make any tracepoint in a
> EXPORT_TRACEPOINT "used". I'm using the analogy of static and global
> functions. An unused static function gets a warning but an unused global one
> does not.
> 
> The last patch updates the trace_ftrace_test_filter boot up self test. That
> selftest creates a trace event to run a bunch of filter tests on it without
> actually calling the tracepoint. To quiet the warning, the selftest tracepoint
> is called within a if (!trace_<event>_enabled()) section, where it will not be
> optimized out, nor will it be called.
> 
> This is v2 from: https://lore.kernel.org/linux-trace-kernel/20250529130138.544ffec4@gandalf.local.home/
> which was simply the first patch. This version adds the other patches.
> 
> Steven Rostedt (5):
>       tracepoints: Add verifier that makes sure all defined tracepoints are used
>       tracing: sorttable: Add a tracepoint verification check at build time
>       tracing: sorttable: Find unused tracepoints for arm64 that uses reloc for address
>       tracepoint: Do not warn for unused event that is exported
>       tracing: Call trace_ftrace_test_filter() for the event
> 
> ----
>  include/asm-generic/vmlinux.lds.h  |   1 +
>  include/linux/tracepoint.h         |  13 ++
>  kernel/trace/Kconfig               |  31 +++
>  kernel/trace/trace_events_filter.c |   4 +
>  kernel/tracepoint.c                |  26 +++
>  scripts/Makefile                   |   4 +
>  scripts/sorttable.c                | 444 ++++++++++++++++++++++++++++++-------
>  7 files changed, 437 insertions(+), 86 deletions(-)
> 

thanks.
-- 
~Randy
Re: [PATCH v2 0/5] tracepoints: Add warnings for unused tracepoints and trace events
Posted by Steven Rostedt 3 months, 4 weeks ago
On Thu, 12 Jun 2025 20:20:48 -0700
Randy Dunlap <rdunlap@infradead.org> wrote:

> Hi,
> 
> On 6/12/25 4:58 PM, Steven Rostedt wrote:
> > Every trace event can take up to 5K of memory in text and meta data regardless  
> 
> s/meta data/metadata/ unless you are referring to meta's data.

Oh so I need to give Meta royalties?

> 
> s/meta data/metadata/ in patches 1 and 2 also.

I'll update when I pull them in. Note, the cover letter isn't something
that I put into git. But I'll try to remember to update if I send a v3.

> 
> > if they are used or not. Trace events should not be created if they are not
> > used.  Currently there's over a hundred events in the kernel that are defined
> > but unused, either because their callers were removed without removing the
> > trace event with it, or a config hides the trace event caller but not the
> > trace event itself. And in some cases, trace events were simply added but were
> > never called for whatever reason. The number of unused trace events continues
> > to grow.
> > 
> > This patch series aims to fix this.
> > 
> > The first patch creates a new section called __tracepoint_check, where all
> > callers of a tracepoint creates a variable that is placed in this section with
> > a pointer to the tracepoint they use. Then on boot up, it iterates this
> > section and will modify the tracepoint's "func" field to a value of 1 (all
> > tracepoints "func" fields are initialized to NULL and is only set when they
> > are registered). This takes place before any tracepoint can be registered.
> > 
> > Then each tracepoint is iterated on and if any tracepoint does not have its
> > "func" field set to 1 a warning is triggerd and every tracepoint that doesn't  
> 
> triggered

Yes I am!

> 
> > have that field set is printed. The "func" field is then reset back to NULL.
> > 
> > The second patch modifies scripts/sorttable.c to read the __tracepoint_check
> > section. It sorts it, and then reads the __tracepoint_ptr section that has all
> > compiled in tracepoints. It makes sure that every tracepoint is found in the
> > check section and if not, it prints a warning message about it. This lists the
> > missing tracepoints at build time.
> > 
> > The third patch updates sorttable to work for arm64 when compiled with gcc. As
> > gcc's arm64 build doesn't put addresses in their section but saves them off in
> > the RELA sections. This mostly takes the work done that was needed to do the
> > mcount sorting at boot up on arm64.
> > 
> > The forth patch adds EXPORT_TRACEPOINT() to the __tracepoint_check section as  
> 
> fourth (or are you coding in forth?)

oops

-- Steve

> 
> > well. There was several locations that adds tracepoints in the kernel proper
> > that are only used in modules. It was getting quite complex trying to move
> > things around that I just decided to make any tracepoint in a
> > EXPORT_TRACEPOINT "used". I'm using the analogy of static and global
> > functions. An unused static function gets a warning but an unused global one
> > does not.
> > 
> > The last patch updates the trace_ftrace_test_filter boot up self test. That
> > selftest creates a trace event to run a bunch of filter tests on it without
> > actually calling the tracepoint. To quiet the warning, the selftest tracepoint
> > is called within a if (!trace_<event>_enabled()) section, where it will not be
> > optimized out, nor will it be called.
> > 
> > This is v2 from: https://lore.kernel.org/linux-trace-kernel/20250529130138.544ffec4@gandalf.local.home/
> > which was simply the first patch. This version adds the other patches.
> > 
> > Steven Rostedt (5):
> >       tracepoints: Add verifier that makes sure all defined tracepoints are used
> >       tracing: sorttable: Add a tracepoint verification check at build time
> >       tracing: sorttable: Find unused tracepoints for arm64 that uses reloc for address
> >       tracepoint: Do not warn for unused event that is exported
> >       tracing: Call trace_ftrace_test_filter() for the event
> > 
> > ----
> >  include/asm-generic/vmlinux.lds.h  |   1 +
> >  include/linux/tracepoint.h         |  13 ++
> >  kernel/trace/Kconfig               |  31 +++
> >  kernel/trace/trace_events_filter.c |   4 +
> >  kernel/tracepoint.c                |  26 +++
> >  scripts/Makefile                   |   4 +
> >  scripts/sorttable.c                | 444 ++++++++++++++++++++++++++++++-------
> >  7 files changed, 437 insertions(+), 86 deletions(-)
> >   
> 
> thanks.
Re: [PATCH v2 0/5] tracepoints: Add warnings for unused tracepoints and trace events
Posted by Steven Rostedt 3 months, 4 weeks ago
On Thu, 12 Jun 2025 19:58:27 -0400
Steven Rostedt <rostedt@goodmis.org> wrote:

> The third patch updates sorttable to work for arm64 when compiled with gcc. As
> gcc's arm64 build doesn't put addresses in their section but saves them off in
> the RELA sections. This mostly takes the work done that was needed to do the
> mcount sorting at boot up on arm64.

FYI, I built this on every architecture with their default config and
every architecture that supports tracing reported unused events. Mostly
they were the same, but depending on the defconfig it gave different
output.

-- Steve
Re: [PATCH v2 0/5] tracepoints: Add warnings for unused tracepoints and trace events
Posted by Steven Rostedt 3 months, 4 weeks ago
On Thu, 12 Jun 2025 19:58:27 -0400
Steven Rostedt <rostedt@goodmis.org> wrote:

> Every trace event can take up to 5K of memory in text and meta data regardless
> if they are used or not. Trace events should not be created if they are not
> used.  Currently there's over a hundred events in the kernel that are defined
> but unused, either because their callers were removed without removing the
> trace event with it, or a config hides the trace event caller but not the
> trace event itself. And in some cases, trace events were simply added but were
> never called for whatever reason. The number of unused trace events continues
> to grow.

Now it's been a while since I looked at the actual sizes, so I decided
to see what they are again.

So I created a trace header with 10 events (attached file), that had this:

TRACE_EVENT(size_event_1,
        TP_PROTO(struct size_event_struct *A, struct size_event_struct *B),
        TP_ARGS(A, B),
        TP_STRUCT__entry(
                __field(        unsigned long,  Aa)
                __field(        unsigned long,  Ab)
                __field(        unsigned long,  Ba)
                __field(        unsigned long,  Bb)
        ),
        TP_fast_assign(
                __entry->Aa = A->a;
                __entry->Ab = A->b;
                __entry->Ba = B->a;
                __entry->Bb = B->b;
        ),
        TP_printk("Aa=%ld Ab=%ld Ba=%ld Bb=%ld",
                __entry->Aa, __entry->Ab, __entry->Ba, __entry->Bb)
);

And I created 9 more by just renaming the event name (size_event_2, etc).

I also looked at how well DEFINE_EVENT() works (note a TRACE_EVENT()
macro is just a DECLARE_EVENT_CLASS() followed by a DEFINE_EVENT() with
the same name as the class, so I could use the first TRACE_EVENT as a
class and the first event).

DEFINE_EVENT(size_event_1, size_event_2,
        TP_PROTO(struct size_event_struct *A, struct size_event_struct *B),
        TP_ARGS(A, B));

The module is simply:

echo '#include <linux/module.h>

#define CREATE_TRACE_POINTS
#include "size_events.h"

static __init int size_init(void)
{
        return 0;
}

static __exit void size_exit(void)
{
}

module_init(size_init);
module_exit(size_exit);

MODULE_AUTHOR("Steven Rostedt");
MODULE_DESCRIPTION("Test the size of trace event");
MODULE_LICENSE("GPL");' > event-mod.c

The results are (renaming the module to what they did):

   text    data     bss     dec     hex filename
    629    1440       0    2069     815 no-events.ko
  44837   15424       0   60261    eb65 trace-events.ko
  11495    8064       0   19559    4c67 define-events.ko

With no events, the size is 2069.
With full trace events it jumped to 60261
With One DECLARE_EVENT_CLASS() and 9 DEFINE_EVENT(), it changed to 19559

That means each TRACE_EVENT() is approximately 5819 bytes.
  (60261 - 2069) / 10

And each DEFINE_EVENT() is approximately 1296 bytes.
  ((19559 - 2069) - 5819) / 9

Now I do have a bit of debugging options enabled which could cause this
to bloat even more. But yeah, trace events do take up a bit of memory.

-- Steve
Re: [PATCH v2 0/5] tracepoints: Add warnings for unused tracepoints and trace events
Posted by Steven Rostedt 3 months, 4 weeks ago
On Fri, 13 Jun 2025 10:28:34 -0400
Steven Rostedt <rostedt@goodmis.org> wrote:

> And each DEFINE_EVENT() is approximately 1296 bytes.
>   ((19559 - 2069) - 5819) / 9

Interesting enough, just raw tracepoints are not much better. I updated
the header file (attached) to have 10 of these, and compiled that.

DECLARE_TRACE(size_event_1,
        TP_PROTO(struct size_event_struct *A, struct size_event_struct *B),
        TP_ARGS(A, B));

The result is:

   text    data     bss     dec     hex filename
    629    1440       0    2069     815 no-events.ko
  44837   15424       0   60261    eb65 trace-events.ko
  11495    8064       0   19559    4c67 define-events.ko
  10865    4408       0   15273    3ba9 declare-trace.ko

Where each DECLARE_TRACE() ends up being 1320 bytes.
  (15273 - 2069) / 10

This is slightly bigger than a DEFINE_EVENT(), but that's also because
the DEFINE_EVENT() shares some of the tracepoint creation in the
DECLARE_EVENT_CLASS(), where as that work is done fully in the
DECLARE_TRACE().

-- Steve