* [PATCH v9 0/4] tracepoints: Add warnings for unused tracepoints and trace events
@ 2025-10-15 20:38 Steven Rostedt
2025-10-15 20:38 ` [PATCH v9 1/4] sorttable: Move ELF parsing into scripts/elf-parse.[ch] Steven Rostedt
` (3 more replies)
0 siblings, 4 replies; 15+ messages in thread
From: Steven Rostedt @ 2025-10-15 20:38 UTC (permalink / raw)
To: linux-kernel, linux-trace-kernel, linux-kbuild
Cc: Masami Hiramatsu, Mark Rutland, Mathieu Desnoyers, Andrew Morton,
Arnd Bergmann, Masahiro Yamada, Nathan Chancellor, Nicolas Schier,
Nick Desaulniers, Catalin Marinas, Linus Torvalds, Randy Dunlap,
Stephen Rothwell
Every trace event can take up to 5K of memory in text and metadata regardless
if they are used or not. Trace events should not be created if they are not
used. Currently there's several 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 moves the elf parsing out of sorttable.c so that it can be
used by other tooling.
The second patch creates a new program to run during build called
tracepoint-update (note this may be extended to do other tracepoint
modifications in the future). It also creates a new section called
__tracepoint_check, where all callers of a tracepoint creates a variable
that is placed in this section with the name of the tracepoint they use.
The scripts/tracepoint-update.c is used to find tracepoints that are defined
but not used which would mean they would not be in the __tracepoint_check
section. It sorts the names from that section, and then reads the
__tracepoint_strings section that has all compiled in tracepoint names. 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 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 triggers warnings when a module defines a tracepoint but
does not use it.
Instead of hiding this behind a config option, where allmodconfig can
cause the warnings to trigger, and we don't want current warnings
to suddenly appear. Have the warnings trigger by a new make command line:
make UT=1
This will enable the unused tracepoints warnings. Now this should not
be an issue to upstream before all warnings are removed. When all current
warnings are removed, we can then make this the default option where
it will always cause the build to warn if there's a unused tracepoint
defined.
Changes since v8: https://lore.kernel.org/linux-trace-kernel/20250828203555.783399758@kernel.org/
- Instead of hiding the unused tracepoint warnings behind a config
option, which means allmodconfig will trigger it, make it a
make command line option. Now to enable the warnings, on must run
make UT=1
- Trigger warnings for modules as well as built in unused tracepoints.
Steven Rostedt (4):
sorttable: Move ELF parsing into scripts/elf-parse.[ch]
tracing: Add a tracepoint verification check at build time
tracepoint: Do not warn for unused event that is exported
tracing: Add warnings for unused tracepoints for modules
----
Makefile | 15 ++
include/asm-generic/vmlinux.lds.h | 1 +
include/linux/tracepoint.h | 13 ++
scripts/Makefile | 6 +
scripts/Makefile.modfinal | 7 +
scripts/elf-parse.c | 198 ++++++++++++++++
scripts/elf-parse.h | 305 ++++++++++++++++++++++++
scripts/link-vmlinux.sh | 7 +
scripts/sorttable.c | 477 +++-----------------------------------
scripts/tracepoint-update.c | 239 +++++++++++++++++++
10 files changed, 825 insertions(+), 443 deletions(-)
create mode 100644 scripts/elf-parse.c
create mode 100644 scripts/elf-parse.h
create mode 100644 scripts/tracepoint-update.c
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH v9 1/4] sorttable: Move ELF parsing into scripts/elf-parse.[ch]
2025-10-15 20:38 [PATCH v9 0/4] tracepoints: Add warnings for unused tracepoints and trace events Steven Rostedt
@ 2025-10-15 20:38 ` Steven Rostedt
2025-10-15 20:38 ` [PATCH v9 2/4] tracing: Add a tracepoint verification check at build time Steven Rostedt
` (2 subsequent siblings)
3 siblings, 0 replies; 15+ messages in thread
From: Steven Rostedt @ 2025-10-15 20:38 UTC (permalink / raw)
To: linux-kernel, linux-trace-kernel, linux-kbuild
Cc: Masami Hiramatsu, Mark Rutland, Mathieu Desnoyers, Andrew Morton,
Arnd Bergmann, Masahiro Yamada, Nathan Chancellor, Nicolas Schier,
Nick Desaulniers, Catalin Marinas, Linus Torvalds, Randy Dunlap,
Stephen Rothwell
From: Steven Rostedt <rostedt@goodmis.org>
In order to share the elf parsing that is in sorttable.c so that other
programs could use the same code, move it into elf-parse.c and
elf-parse.h.
Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
---
scripts/Makefile | 3 +
scripts/elf-parse.c | 198 ++++++++++++++++++
scripts/elf-parse.h | 305 ++++++++++++++++++++++++++++
scripts/sorttable.c | 477 ++++----------------------------------------
4 files changed, 540 insertions(+), 443 deletions(-)
create mode 100644 scripts/elf-parse.c
create mode 100644 scripts/elf-parse.h
diff --git a/scripts/Makefile b/scripts/Makefile
index 46f860529df5..f19624b3ed92 100644
--- a/scripts/Makefile
+++ b/scripts/Makefile
@@ -12,6 +12,8 @@ hostprogs-always-$(CONFIG_SYSTEM_EXTRA_CERTIFICATE) += insert-sys-cert
hostprogs-always-$(CONFIG_RUST_KERNEL_DOCTESTS) += rustdoc_test_builder
hostprogs-always-$(CONFIG_RUST_KERNEL_DOCTESTS) += rustdoc_test_gen
+sorttable-objs := sorttable.o elf-parse.o
+
ifneq ($(or $(CONFIG_X86_64),$(CONFIG_X86_32)),)
always-$(CONFIG_RUST) += target.json
filechk_rust_target = $< < include/config/auto.conf
@@ -25,6 +27,7 @@ generate_rust_target-rust := y
rustdoc_test_builder-rust := y
rustdoc_test_gen-rust := y
+HOSTCFLAGS_elf-parse.o = -I$(srctree)/tools/include
HOSTCFLAGS_sorttable.o = -I$(srctree)/tools/include
HOSTLDLIBS_sorttable = -lpthread
HOSTCFLAGS_asn1_compiler.o = -I$(srctree)/include
diff --git a/scripts/elf-parse.c b/scripts/elf-parse.c
new file mode 100644
index 000000000000..99869ff91a8c
--- /dev/null
+++ b/scripts/elf-parse.c
@@ -0,0 +1,198 @@
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include "elf-parse.h"
+
+struct elf_funcs elf_parser;
+
+/*
+ * Get the whole file as a programming convenience in order to avoid
+ * malloc+lseek+read+free of many pieces. If successful, then mmap
+ * avoids copying unused pieces; else just read the whole file.
+ * Open for both read and write.
+ */
+static void *map_file(char const *fname, size_t *size)
+{
+ int fd;
+ struct stat sb;
+ void *addr = NULL;
+
+ fd = open(fname, O_RDWR);
+ if (fd < 0) {
+ perror(fname);
+ return NULL;
+ }
+ if (fstat(fd, &sb) < 0) {
+ perror(fname);
+ goto out;
+ }
+ if (!S_ISREG(sb.st_mode)) {
+ fprintf(stderr, "not a regular file: %s\n", fname);
+ goto out;
+ }
+
+ addr = mmap(0, sb.st_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
+ if (addr == MAP_FAILED) {
+ fprintf(stderr, "Could not mmap file: %s\n", fname);
+ goto out;
+ }
+
+ *size = sb.st_size;
+
+out:
+ close(fd);
+ return addr;
+}
+
+static int elf_parse(const char *fname, void *addr, uint32_t types)
+{
+ Elf_Ehdr *ehdr = addr;
+ uint16_t type;
+
+ switch (ehdr->e32.e_ident[EI_DATA]) {
+ case ELFDATA2LSB:
+ elf_parser.r = rle;
+ elf_parser.r2 = r2le;
+ elf_parser.r8 = r8le;
+ elf_parser.w = wle;
+ elf_parser.w8 = w8le;
+ break;
+ case ELFDATA2MSB:
+ elf_parser.r = rbe;
+ elf_parser.r2 = r2be;
+ elf_parser.r8 = r8be;
+ elf_parser.w = wbe;
+ elf_parser.w8 = w8be;
+ break;
+ default:
+ fprintf(stderr, "unrecognized ELF data encoding %d: %s\n",
+ ehdr->e32.e_ident[EI_DATA], fname);
+ return -1;
+ }
+
+ if (memcmp(ELFMAG, ehdr->e32.e_ident, SELFMAG) != 0 ||
+ ehdr->e32.e_ident[EI_VERSION] != EV_CURRENT) {
+ fprintf(stderr, "unrecognized ELF file %s\n", fname);
+ return -1;
+ }
+
+ type = elf_parser.r2(&ehdr->e32.e_type);
+ if (!((1 << type) & types)) {
+ fprintf(stderr, "Invalid ELF type file %s\n", fname);
+ return -1;
+ }
+
+ switch (ehdr->e32.e_ident[EI_CLASS]) {
+ case ELFCLASS32: {
+ elf_parser.ehdr_shoff = ehdr32_shoff;
+ elf_parser.ehdr_shentsize = ehdr32_shentsize;
+ elf_parser.ehdr_shstrndx = ehdr32_shstrndx;
+ elf_parser.ehdr_shnum = ehdr32_shnum;
+ elf_parser.shdr_addr = shdr32_addr;
+ elf_parser.shdr_offset = shdr32_offset;
+ elf_parser.shdr_link = shdr32_link;
+ elf_parser.shdr_size = shdr32_size;
+ elf_parser.shdr_name = shdr32_name;
+ elf_parser.shdr_type = shdr32_type;
+ elf_parser.shdr_entsize = shdr32_entsize;
+ elf_parser.sym_type = sym32_type;
+ elf_parser.sym_name = sym32_name;
+ elf_parser.sym_value = sym32_value;
+ elf_parser.sym_shndx = sym32_shndx;
+ elf_parser.rela_offset = rela32_offset;
+ elf_parser.rela_info = rela32_info;
+ elf_parser.rela_addend = rela32_addend;
+ elf_parser.rela_write_addend = rela32_write_addend;
+
+ if (elf_parser.r2(&ehdr->e32.e_ehsize) != sizeof(Elf32_Ehdr) ||
+ elf_parser.r2(&ehdr->e32.e_shentsize) != sizeof(Elf32_Shdr)) {
+ fprintf(stderr,
+ "unrecognized ET_EXEC/ET_DYN file: %s\n", fname);
+ return -1;
+ }
+
+ }
+ break;
+ case ELFCLASS64: {
+ elf_parser.ehdr_shoff = ehdr64_shoff;
+ elf_parser.ehdr_shentsize = ehdr64_shentsize;
+ elf_parser.ehdr_shstrndx = ehdr64_shstrndx;
+ elf_parser.ehdr_shnum = ehdr64_shnum;
+ elf_parser.shdr_addr = shdr64_addr;
+ elf_parser.shdr_offset = shdr64_offset;
+ elf_parser.shdr_link = shdr64_link;
+ elf_parser.shdr_size = shdr64_size;
+ elf_parser.shdr_name = shdr64_name;
+ elf_parser.shdr_type = shdr64_type;
+ elf_parser.shdr_entsize = shdr64_entsize;
+ elf_parser.sym_type = sym64_type;
+ elf_parser.sym_name = sym64_name;
+ elf_parser.sym_value = sym64_value;
+ elf_parser.sym_shndx = sym64_shndx;
+ elf_parser.rela_offset = rela64_offset;
+ elf_parser.rela_info = rela64_info;
+ elf_parser.rela_addend = rela64_addend;
+ elf_parser.rela_write_addend = rela64_write_addend;
+
+ if (elf_parser.r2(&ehdr->e64.e_ehsize) != sizeof(Elf64_Ehdr) ||
+ elf_parser.r2(&ehdr->e64.e_shentsize) != sizeof(Elf64_Shdr)) {
+ fprintf(stderr,
+ "unrecognized ET_EXEC/ET_DYN file: %s\n",
+ fname);
+ return -1;
+ }
+
+ }
+ break;
+ default:
+ fprintf(stderr, "unrecognized ELF class %d %s\n",
+ ehdr->e32.e_ident[EI_CLASS], fname);
+ return -1;
+ }
+ return 0;
+}
+
+int elf_map_machine(void *addr)
+{
+ Elf_Ehdr *ehdr = addr;
+
+ return elf_parser.r2(&ehdr->e32.e_machine);
+}
+
+int elf_map_long_size(void *addr)
+{
+ Elf_Ehdr *ehdr = addr;
+
+ return ehdr->e32.e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
+}
+
+void *elf_map(char const *fname, size_t *size, uint32_t types)
+{
+ void *addr;
+ int ret;
+
+ addr = map_file(fname, size);
+ if (!addr)
+ return NULL;
+
+ ret = elf_parse(fname, addr, types);
+ if (ret < 0) {
+ elf_unmap(addr, *size);
+ return NULL;
+ }
+
+ return addr;
+}
+
+void elf_unmap(void *addr, size_t size)
+{
+ munmap(addr, size);
+}
diff --git a/scripts/elf-parse.h b/scripts/elf-parse.h
new file mode 100644
index 000000000000..f4411e03069d
--- /dev/null
+++ b/scripts/elf-parse.h
@@ -0,0 +1,305 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+#ifndef _SCRIPTS_ELF_PARSE_H
+#define _SCRIPTS_ELF_PARSE_H
+
+#include <elf.h>
+
+#include <tools/be_byteshift.h>
+#include <tools/le_byteshift.h>
+
+typedef union {
+ Elf32_Ehdr e32;
+ Elf64_Ehdr e64;
+} Elf_Ehdr;
+
+typedef union {
+ Elf32_Shdr e32;
+ Elf64_Shdr e64;
+} Elf_Shdr;
+
+typedef union {
+ Elf32_Sym e32;
+ Elf64_Sym e64;
+} Elf_Sym;
+
+typedef union {
+ Elf32_Rela e32;
+ Elf64_Rela e64;
+} Elf_Rela;
+
+struct elf_funcs {
+ int (*compare_extable)(const void *a, const void *b);
+ uint64_t (*ehdr_shoff)(Elf_Ehdr *ehdr);
+ uint16_t (*ehdr_shstrndx)(Elf_Ehdr *ehdr);
+ uint16_t (*ehdr_shentsize)(Elf_Ehdr *ehdr);
+ uint16_t (*ehdr_shnum)(Elf_Ehdr *ehdr);
+ uint64_t (*shdr_addr)(Elf_Shdr *shdr);
+ uint64_t (*shdr_offset)(Elf_Shdr *shdr);
+ uint64_t (*shdr_size)(Elf_Shdr *shdr);
+ uint64_t (*shdr_entsize)(Elf_Shdr *shdr);
+ uint32_t (*shdr_link)(Elf_Shdr *shdr);
+ uint32_t (*shdr_name)(Elf_Shdr *shdr);
+ uint32_t (*shdr_type)(Elf_Shdr *shdr);
+ uint8_t (*sym_type)(Elf_Sym *sym);
+ uint32_t (*sym_name)(Elf_Sym *sym);
+ uint64_t (*sym_value)(Elf_Sym *sym);
+ uint16_t (*sym_shndx)(Elf_Sym *sym);
+ uint64_t (*rela_offset)(Elf_Rela *rela);
+ uint64_t (*rela_info)(Elf_Rela *rela);
+ uint64_t (*rela_addend)(Elf_Rela *rela);
+ void (*rela_write_addend)(Elf_Rela *rela, uint64_t val);
+ uint32_t (*r)(const uint32_t *);
+ uint16_t (*r2)(const uint16_t *);
+ uint64_t (*r8)(const uint64_t *);
+ void (*w)(uint32_t, uint32_t *);
+ void (*w8)(uint64_t, uint64_t *);
+};
+
+extern struct elf_funcs elf_parser;
+
+static inline uint64_t ehdr64_shoff(Elf_Ehdr *ehdr)
+{
+ return elf_parser.r8(&ehdr->e64.e_shoff);
+}
+
+static inline uint64_t ehdr32_shoff(Elf_Ehdr *ehdr)
+{
+ return elf_parser.r(&ehdr->e32.e_shoff);
+}
+
+static inline uint64_t ehdr_shoff(Elf_Ehdr *ehdr)
+{
+ return elf_parser.ehdr_shoff(ehdr);
+}
+
+#define EHDR_HALF(fn_name) \
+static inline uint16_t ehdr64_##fn_name(Elf_Ehdr *ehdr) \
+{ \
+ return elf_parser.r2(&ehdr->e64.e_##fn_name); \
+} \
+ \
+static inline uint16_t ehdr32_##fn_name(Elf_Ehdr *ehdr) \
+{ \
+ return elf_parser.r2(&ehdr->e32.e_##fn_name); \
+} \
+ \
+static inline uint16_t ehdr_##fn_name(Elf_Ehdr *ehdr) \
+{ \
+ return elf_parser.ehdr_##fn_name(ehdr); \
+}
+
+EHDR_HALF(shentsize)
+EHDR_HALF(shstrndx)
+EHDR_HALF(shnum)
+
+#define SHDR_WORD(fn_name) \
+static inline uint32_t shdr64_##fn_name(Elf_Shdr *shdr) \
+{ \
+ return elf_parser.r(&shdr->e64.sh_##fn_name); \
+} \
+ \
+static inline uint32_t shdr32_##fn_name(Elf_Shdr *shdr) \
+{ \
+ return elf_parser.r(&shdr->e32.sh_##fn_name); \
+} \
+ \
+static inline uint32_t shdr_##fn_name(Elf_Shdr *shdr) \
+{ \
+ return elf_parser.shdr_##fn_name(shdr); \
+}
+
+#define SHDR_ADDR(fn_name) \
+static inline uint64_t shdr64_##fn_name(Elf_Shdr *shdr) \
+{ \
+ return elf_parser.r8(&shdr->e64.sh_##fn_name); \
+} \
+ \
+static inline uint64_t shdr32_##fn_name(Elf_Shdr *shdr) \
+{ \
+ return elf_parser.r(&shdr->e32.sh_##fn_name); \
+} \
+ \
+static inline uint64_t shdr_##fn_name(Elf_Shdr *shdr) \
+{ \
+ return elf_parser.shdr_##fn_name(shdr); \
+}
+
+#define SHDR_WORD(fn_name) \
+static inline uint32_t shdr64_##fn_name(Elf_Shdr *shdr) \
+{ \
+ return elf_parser.r(&shdr->e64.sh_##fn_name); \
+} \
+ \
+static inline uint32_t shdr32_##fn_name(Elf_Shdr *shdr) \
+{ \
+ return elf_parser.r(&shdr->e32.sh_##fn_name); \
+} \
+static inline uint32_t shdr_##fn_name(Elf_Shdr *shdr) \
+{ \
+ return elf_parser.shdr_##fn_name(shdr); \
+}
+
+SHDR_ADDR(addr)
+SHDR_ADDR(offset)
+SHDR_ADDR(size)
+SHDR_ADDR(entsize)
+
+SHDR_WORD(link)
+SHDR_WORD(name)
+SHDR_WORD(type)
+
+#define SYM_ADDR(fn_name) \
+static inline uint64_t sym64_##fn_name(Elf_Sym *sym) \
+{ \
+ return elf_parser.r8(&sym->e64.st_##fn_name); \
+} \
+ \
+static inline uint64_t sym32_##fn_name(Elf_Sym *sym) \
+{ \
+ return elf_parser.r(&sym->e32.st_##fn_name); \
+} \
+ \
+static inline uint64_t sym_##fn_name(Elf_Sym *sym) \
+{ \
+ return elf_parser.sym_##fn_name(sym); \
+}
+
+#define SYM_WORD(fn_name) \
+static inline uint32_t sym64_##fn_name(Elf_Sym *sym) \
+{ \
+ return elf_parser.r(&sym->e64.st_##fn_name); \
+} \
+ \
+static inline uint32_t sym32_##fn_name(Elf_Sym *sym) \
+{ \
+ return elf_parser.r(&sym->e32.st_##fn_name); \
+} \
+ \
+static inline uint32_t sym_##fn_name(Elf_Sym *sym) \
+{ \
+ return elf_parser.sym_##fn_name(sym); \
+}
+
+#define SYM_HALF(fn_name) \
+static inline uint16_t sym64_##fn_name(Elf_Sym *sym) \
+{ \
+ return elf_parser.r2(&sym->e64.st_##fn_name); \
+} \
+ \
+static inline uint16_t sym32_##fn_name(Elf_Sym *sym) \
+{ \
+ return elf_parser.r2(&sym->e32.st_##fn_name); \
+} \
+ \
+static inline uint16_t sym_##fn_name(Elf_Sym *sym) \
+{ \
+ return elf_parser.sym_##fn_name(sym); \
+}
+
+static inline uint8_t sym64_type(Elf_Sym *sym)
+{
+ return ELF64_ST_TYPE(sym->e64.st_info);
+}
+
+static inline uint8_t sym32_type(Elf_Sym *sym)
+{
+ return ELF32_ST_TYPE(sym->e32.st_info);
+}
+
+static inline uint8_t sym_type(Elf_Sym *sym)
+{
+ return elf_parser.sym_type(sym);
+}
+
+SYM_ADDR(value)
+SYM_WORD(name)
+SYM_HALF(shndx)
+
+#define __maybe_unused __attribute__((__unused__))
+
+#define RELA_ADDR(fn_name) \
+static inline uint64_t rela64_##fn_name(Elf_Rela *rela) \
+{ \
+ return elf_parser.r8((uint64_t *)&rela->e64.r_##fn_name); \
+} \
+ \
+static inline uint64_t rela32_##fn_name(Elf_Rela *rela) \
+{ \
+ return elf_parser.r((uint32_t *)&rela->e32.r_##fn_name); \
+} \
+ \
+static inline uint64_t __maybe_unused rela_##fn_name(Elf_Rela *rela) \
+{ \
+ return elf_parser.rela_##fn_name(rela); \
+}
+
+RELA_ADDR(offset)
+RELA_ADDR(info)
+RELA_ADDR(addend)
+
+static inline void rela64_write_addend(Elf_Rela *rela, uint64_t val)
+{
+ elf_parser.w8(val, (uint64_t *)&rela->e64.r_addend);
+}
+
+static inline void rela32_write_addend(Elf_Rela *rela, uint64_t val)
+{
+ elf_parser.w(val, (uint32_t *)&rela->e32.r_addend);
+}
+
+static inline uint32_t rbe(const uint32_t *x)
+{
+ return get_unaligned_be32(x);
+}
+
+static inline uint16_t r2be(const uint16_t *x)
+{
+ return get_unaligned_be16(x);
+}
+
+static inline uint64_t r8be(const uint64_t *x)
+{
+ return get_unaligned_be64(x);
+}
+
+static inline uint32_t rle(const uint32_t *x)
+{
+ return get_unaligned_le32(x);
+}
+
+static inline uint16_t r2le(const uint16_t *x)
+{
+ return get_unaligned_le16(x);
+}
+
+static inline uint64_t r8le(const uint64_t *x)
+{
+ return get_unaligned_le64(x);
+}
+
+static inline void wbe(uint32_t val, uint32_t *x)
+{
+ put_unaligned_be32(val, x);
+}
+
+static inline void wle(uint32_t val, uint32_t *x)
+{
+ put_unaligned_le32(val, x);
+}
+
+static inline void w8be(uint64_t val, uint64_t *x)
+{
+ put_unaligned_be64(val, x);
+}
+
+static inline void w8le(uint64_t val, uint64_t *x)
+{
+ put_unaligned_le64(val, x);
+}
+
+void *elf_map(char const *fname, size_t *size, uint32_t types);
+void elf_unmap(void *addr, size_t size);
+int elf_map_machine(void *addr);
+int elf_map_long_size(void *addr);
+
+#endif /* _SCRIPTS_ELF_PARSE_H */
diff --git a/scripts/sorttable.c b/scripts/sorttable.c
index deed676bfe38..e8ed11c680c6 100644
--- a/scripts/sorttable.c
+++ b/scripts/sorttable.c
@@ -21,10 +21,8 @@
*/
#include <sys/types.h>
-#include <sys/mman.h>
#include <sys/stat.h>
#include <getopt.h>
-#include <elf.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
@@ -34,8 +32,7 @@
#include <errno.h>
#include <pthread.h>
-#include <tools/be_byteshift.h>
-#include <tools/le_byteshift.h>
+#include "elf-parse.h"
#ifndef EM_ARCOMPACT
#define EM_ARCOMPACT 93
@@ -65,335 +62,8 @@
#define EM_LOONGARCH 258
#endif
-typedef union {
- Elf32_Ehdr e32;
- Elf64_Ehdr e64;
-} Elf_Ehdr;
-
-typedef union {
- Elf32_Shdr e32;
- Elf64_Shdr e64;
-} Elf_Shdr;
-
-typedef union {
- Elf32_Sym e32;
- Elf64_Sym e64;
-} Elf_Sym;
-
-typedef union {
- Elf32_Rela e32;
- Elf64_Rela e64;
-} Elf_Rela;
-
-static uint32_t (*r)(const uint32_t *);
-static uint16_t (*r2)(const uint16_t *);
-static uint64_t (*r8)(const uint64_t *);
-static void (*w)(uint32_t, uint32_t *);
-static void (*w8)(uint64_t, uint64_t *);
typedef void (*table_sort_t)(char *, int);
-static struct elf_funcs {
- int (*compare_extable)(const void *a, const void *b);
- uint64_t (*ehdr_shoff)(Elf_Ehdr *ehdr);
- uint16_t (*ehdr_shstrndx)(Elf_Ehdr *ehdr);
- uint16_t (*ehdr_shentsize)(Elf_Ehdr *ehdr);
- uint16_t (*ehdr_shnum)(Elf_Ehdr *ehdr);
- uint64_t (*shdr_addr)(Elf_Shdr *shdr);
- uint64_t (*shdr_offset)(Elf_Shdr *shdr);
- uint64_t (*shdr_size)(Elf_Shdr *shdr);
- uint64_t (*shdr_entsize)(Elf_Shdr *shdr);
- uint32_t (*shdr_link)(Elf_Shdr *shdr);
- uint32_t (*shdr_name)(Elf_Shdr *shdr);
- uint32_t (*shdr_type)(Elf_Shdr *shdr);
- uint8_t (*sym_type)(Elf_Sym *sym);
- uint32_t (*sym_name)(Elf_Sym *sym);
- uint64_t (*sym_value)(Elf_Sym *sym);
- uint16_t (*sym_shndx)(Elf_Sym *sym);
- uint64_t (*rela_offset)(Elf_Rela *rela);
- uint64_t (*rela_info)(Elf_Rela *rela);
- uint64_t (*rela_addend)(Elf_Rela *rela);
- void (*rela_write_addend)(Elf_Rela *rela, uint64_t val);
-} e;
-
-static uint64_t ehdr64_shoff(Elf_Ehdr *ehdr)
-{
- return r8(&ehdr->e64.e_shoff);
-}
-
-static uint64_t ehdr32_shoff(Elf_Ehdr *ehdr)
-{
- return r(&ehdr->e32.e_shoff);
-}
-
-static uint64_t ehdr_shoff(Elf_Ehdr *ehdr)
-{
- return e.ehdr_shoff(ehdr);
-}
-
-#define EHDR_HALF(fn_name) \
-static uint16_t ehdr64_##fn_name(Elf_Ehdr *ehdr) \
-{ \
- return r2(&ehdr->e64.e_##fn_name); \
-} \
- \
-static uint16_t ehdr32_##fn_name(Elf_Ehdr *ehdr) \
-{ \
- return r2(&ehdr->e32.e_##fn_name); \
-} \
- \
-static uint16_t ehdr_##fn_name(Elf_Ehdr *ehdr) \
-{ \
- return e.ehdr_##fn_name(ehdr); \
-}
-
-EHDR_HALF(shentsize)
-EHDR_HALF(shstrndx)
-EHDR_HALF(shnum)
-
-#define SHDR_WORD(fn_name) \
-static uint32_t shdr64_##fn_name(Elf_Shdr *shdr) \
-{ \
- return r(&shdr->e64.sh_##fn_name); \
-} \
- \
-static uint32_t shdr32_##fn_name(Elf_Shdr *shdr) \
-{ \
- return r(&shdr->e32.sh_##fn_name); \
-} \
- \
-static uint32_t shdr_##fn_name(Elf_Shdr *shdr) \
-{ \
- return e.shdr_##fn_name(shdr); \
-}
-
-#define SHDR_ADDR(fn_name) \
-static uint64_t shdr64_##fn_name(Elf_Shdr *shdr) \
-{ \
- return r8(&shdr->e64.sh_##fn_name); \
-} \
- \
-static uint64_t shdr32_##fn_name(Elf_Shdr *shdr) \
-{ \
- return r(&shdr->e32.sh_##fn_name); \
-} \
- \
-static uint64_t shdr_##fn_name(Elf_Shdr *shdr) \
-{ \
- return e.shdr_##fn_name(shdr); \
-}
-
-#define SHDR_WORD(fn_name) \
-static uint32_t shdr64_##fn_name(Elf_Shdr *shdr) \
-{ \
- return r(&shdr->e64.sh_##fn_name); \
-} \
- \
-static uint32_t shdr32_##fn_name(Elf_Shdr *shdr) \
-{ \
- return r(&shdr->e32.sh_##fn_name); \
-} \
-static uint32_t shdr_##fn_name(Elf_Shdr *shdr) \
-{ \
- return e.shdr_##fn_name(shdr); \
-}
-
-SHDR_ADDR(addr)
-SHDR_ADDR(offset)
-SHDR_ADDR(size)
-SHDR_ADDR(entsize)
-
-SHDR_WORD(link)
-SHDR_WORD(name)
-SHDR_WORD(type)
-
-#define SYM_ADDR(fn_name) \
-static uint64_t sym64_##fn_name(Elf_Sym *sym) \
-{ \
- return r8(&sym->e64.st_##fn_name); \
-} \
- \
-static uint64_t sym32_##fn_name(Elf_Sym *sym) \
-{ \
- return r(&sym->e32.st_##fn_name); \
-} \
- \
-static uint64_t sym_##fn_name(Elf_Sym *sym) \
-{ \
- return e.sym_##fn_name(sym); \
-}
-
-#define SYM_WORD(fn_name) \
-static uint32_t sym64_##fn_name(Elf_Sym *sym) \
-{ \
- return r(&sym->e64.st_##fn_name); \
-} \
- \
-static uint32_t sym32_##fn_name(Elf_Sym *sym) \
-{ \
- return r(&sym->e32.st_##fn_name); \
-} \
- \
-static uint32_t sym_##fn_name(Elf_Sym *sym) \
-{ \
- return e.sym_##fn_name(sym); \
-}
-
-#define SYM_HALF(fn_name) \
-static uint16_t sym64_##fn_name(Elf_Sym *sym) \
-{ \
- return r2(&sym->e64.st_##fn_name); \
-} \
- \
-static uint16_t sym32_##fn_name(Elf_Sym *sym) \
-{ \
- return r2(&sym->e32.st_##fn_name); \
-} \
- \
-static uint16_t sym_##fn_name(Elf_Sym *sym) \
-{ \
- return e.sym_##fn_name(sym); \
-}
-
-static uint8_t sym64_type(Elf_Sym *sym)
-{
- return ELF64_ST_TYPE(sym->e64.st_info);
-}
-
-static uint8_t sym32_type(Elf_Sym *sym)
-{
- return ELF32_ST_TYPE(sym->e32.st_info);
-}
-
-static uint8_t sym_type(Elf_Sym *sym)
-{
- return e.sym_type(sym);
-}
-
-SYM_ADDR(value)
-SYM_WORD(name)
-SYM_HALF(shndx)
-
-#define __maybe_unused __attribute__((__unused__))
-
-#define RELA_ADDR(fn_name) \
-static uint64_t rela64_##fn_name(Elf_Rela *rela) \
-{ \
- return r8((uint64_t *)&rela->e64.r_##fn_name); \
-} \
- \
-static uint64_t rela32_##fn_name(Elf_Rela *rela) \
-{ \
- return r((uint32_t *)&rela->e32.r_##fn_name); \
-} \
- \
-static uint64_t __maybe_unused rela_##fn_name(Elf_Rela *rela) \
-{ \
- return e.rela_##fn_name(rela); \
-}
-
-RELA_ADDR(offset)
-RELA_ADDR(info)
-RELA_ADDR(addend)
-
-static void rela64_write_addend(Elf_Rela *rela, uint64_t val)
-{
- w8(val, (uint64_t *)&rela->e64.r_addend);
-}
-
-static void rela32_write_addend(Elf_Rela *rela, uint64_t val)
-{
- w(val, (uint32_t *)&rela->e32.r_addend);
-}
-
-/*
- * Get the whole file as a programming convenience in order to avoid
- * malloc+lseek+read+free of many pieces. If successful, then mmap
- * avoids copying unused pieces; else just read the whole file.
- * Open for both read and write.
- */
-static void *mmap_file(char const *fname, size_t *size)
-{
- int fd;
- struct stat sb;
- void *addr = NULL;
-
- fd = open(fname, O_RDWR);
- if (fd < 0) {
- perror(fname);
- return NULL;
- }
- if (fstat(fd, &sb) < 0) {
- perror(fname);
- goto out;
- }
- if (!S_ISREG(sb.st_mode)) {
- fprintf(stderr, "not a regular file: %s\n", fname);
- goto out;
- }
-
- addr = mmap(0, sb.st_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
- if (addr == MAP_FAILED) {
- fprintf(stderr, "Could not mmap file: %s\n", fname);
- goto out;
- }
-
- *size = sb.st_size;
-
-out:
- close(fd);
- return addr;
-}
-
-static uint32_t rbe(const uint32_t *x)
-{
- return get_unaligned_be32(x);
-}
-
-static uint16_t r2be(const uint16_t *x)
-{
- return get_unaligned_be16(x);
-}
-
-static uint64_t r8be(const uint64_t *x)
-{
- return get_unaligned_be64(x);
-}
-
-static uint32_t rle(const uint32_t *x)
-{
- return get_unaligned_le32(x);
-}
-
-static uint16_t r2le(const uint16_t *x)
-{
- return get_unaligned_le16(x);
-}
-
-static uint64_t r8le(const uint64_t *x)
-{
- return get_unaligned_le64(x);
-}
-
-static void wbe(uint32_t val, uint32_t *x)
-{
- put_unaligned_be32(val, x);
-}
-
-static void wle(uint32_t val, uint32_t *x)
-{
- put_unaligned_le32(val, x);
-}
-
-static void w8be(uint64_t val, uint64_t *x)
-{
- put_unaligned_be64(val, x);
-}
-
-static void w8le(uint64_t val, uint64_t *x)
-{
- put_unaligned_le64(val, x);
-}
-
/*
* Move reserved section indices SHN_LORESERVE..SHN_HIRESERVE out of
* the way to -256..-1, to avoid conflicting with real section
@@ -415,13 +85,13 @@ static inline unsigned int get_secindex(unsigned int shndx,
return SPECIAL(shndx);
if (shndx != SHN_XINDEX)
return shndx;
- return r(&symtab_shndx_start[sym_offs]);
+ return elf_parser.r(&symtab_shndx_start[sym_offs]);
}
static int compare_extable_32(const void *a, const void *b)
{
- Elf32_Addr av = r(a);
- Elf32_Addr bv = r(b);
+ Elf32_Addr av = elf_parser.r(a);
+ Elf32_Addr bv = elf_parser.r(b);
if (av < bv)
return -1;
@@ -430,18 +100,15 @@ static int compare_extable_32(const void *a, const void *b)
static int compare_extable_64(const void *a, const void *b)
{
- Elf64_Addr av = r8(a);
- Elf64_Addr bv = r8(b);
+ Elf64_Addr av = elf_parser.r8(a);
+ Elf64_Addr bv = elf_parser.r8(b);
if (av < bv)
return -1;
return av > bv;
}
-static int compare_extable(const void *a, const void *b)
-{
- return e.compare_extable(a, b);
-}
+static int (*compare_extable)(const void *a, const void *b);
static inline void *get_index(void *start, int entsize, int index)
{
@@ -577,7 +244,7 @@ static int (*compare_values)(const void *a, const void *b);
/* Only used for sorting mcount table */
static void rela_write_addend(Elf_Rela *rela, uint64_t val)
{
- e.rela_write_addend(rela, val);
+ elf_parser.rela_write_addend(rela, val);
}
struct func_info {
@@ -792,9 +459,9 @@ static int fill_addrs(void *ptr, uint64_t size, void *addrs)
for (; ptr < end; ptr += long_size, addrs += long_size, count++) {
if (long_size == 4)
- *(uint32_t *)ptr = r(addrs);
+ *(uint32_t *)ptr = elf_parser.r(addrs);
else
- *(uint64_t *)ptr = r8(addrs);
+ *(uint64_t *)ptr = elf_parser.r8(addrs);
}
return count;
}
@@ -805,9 +472,9 @@ static void replace_addrs(void *ptr, uint64_t size, void *addrs)
for (; ptr < end; ptr += long_size, addrs += long_size) {
if (long_size == 4)
- w(*(uint32_t *)ptr, addrs);
+ elf_parser.w(*(uint32_t *)ptr, addrs);
else
- w8(*(uint64_t *)ptr, addrs);
+ elf_parser.w8(*(uint64_t *)ptr, addrs);
}
}
@@ -1111,7 +778,7 @@ static int do_sort(Elf_Ehdr *ehdr,
sym_value(sort_needed_sym) - shdr_addr(sort_needed_sec);
/* extable has been sorted, clear the flag */
- w(0, sort_needed_loc);
+ elf_parser.w(0, sort_needed_loc);
rc = 0;
out:
@@ -1155,8 +822,8 @@ static int do_sort(Elf_Ehdr *ehdr,
static int compare_relative_table(const void *a, const void *b)
{
- int32_t av = (int32_t)r(a);
- int32_t bv = (int32_t)r(b);
+ int32_t av = (int32_t)elf_parser.r(a);
+ int32_t bv = (int32_t)elf_parser.r(b);
if (av < bv)
return -1;
@@ -1175,7 +842,7 @@ static void sort_relative_table(char *extab_image, int image_size)
*/
while (i < image_size) {
uint32_t *loc = (uint32_t *)(extab_image + i);
- w(r(loc) + i, loc);
+ elf_parser.w(elf_parser.r(loc) + i, loc);
i += 4;
}
@@ -1185,7 +852,7 @@ static void sort_relative_table(char *extab_image, int image_size)
i = 0;
while (i < image_size) {
uint32_t *loc = (uint32_t *)(extab_image + i);
- w(r(loc) - i, loc);
+ elf_parser.w(elf_parser.r(loc) - i, loc);
i += 4;
}
}
@@ -1197,8 +864,8 @@ static void sort_relative_table_with_data(char *extab_image, int image_size)
while (i < image_size) {
uint32_t *loc = (uint32_t *)(extab_image + i);
- w(r(loc) + i, loc);
- w(r(loc + 1) + i + 4, loc + 1);
+ elf_parser.w(elf_parser.r(loc) + i, loc);
+ elf_parser.w(elf_parser.r(loc + 1) + i + 4, loc + 1);
/* Don't touch the fixup type or data */
i += sizeof(uint32_t) * 3;
@@ -1210,8 +877,8 @@ static void sort_relative_table_with_data(char *extab_image, int image_size)
while (i < image_size) {
uint32_t *loc = (uint32_t *)(extab_image + i);
- w(r(loc) - i, loc);
- w(r(loc + 1) - (i + 4), loc + 1);
+ elf_parser.w(elf_parser.r(loc) - i, loc);
+ elf_parser.w(elf_parser.r(loc + 1) - (i + 4), loc + 1);
/* Don't touch the fixup type or data */
i += sizeof(uint32_t) * 3;
@@ -1223,35 +890,7 @@ static int do_file(char const *const fname, void *addr)
Elf_Ehdr *ehdr = addr;
table_sort_t custom_sort = NULL;
- switch (ehdr->e32.e_ident[EI_DATA]) {
- case ELFDATA2LSB:
- r = rle;
- r2 = r2le;
- r8 = r8le;
- w = wle;
- w8 = w8le;
- break;
- case ELFDATA2MSB:
- r = rbe;
- r2 = r2be;
- r8 = r8be;
- w = wbe;
- w8 = w8be;
- break;
- default:
- fprintf(stderr, "unrecognized ELF data encoding %d: %s\n",
- ehdr->e32.e_ident[EI_DATA], fname);
- return -1;
- }
-
- if (memcmp(ELFMAG, ehdr->e32.e_ident, SELFMAG) != 0 ||
- (r2(&ehdr->e32.e_type) != ET_EXEC && r2(&ehdr->e32.e_type) != ET_DYN) ||
- ehdr->e32.e_ident[EI_VERSION] != EV_CURRENT) {
- fprintf(stderr, "unrecognized ET_EXEC/ET_DYN file %s\n", fname);
- return -1;
- }
-
- switch (r2(&ehdr->e32.e_machine)) {
+ switch (elf_map_machine(ehdr)) {
case EM_AARCH64:
#ifdef MCOUNT_SORT_ENABLED
sort_reloc = true;
@@ -1281,85 +920,37 @@ static int do_file(char const *const fname, void *addr)
break;
default:
fprintf(stderr, "unrecognized e_machine %d %s\n",
- r2(&ehdr->e32.e_machine), fname);
+ elf_parser.r2(&ehdr->e32.e_machine), fname);
return -1;
}
- switch (ehdr->e32.e_ident[EI_CLASS]) {
- case ELFCLASS32: {
- struct elf_funcs efuncs = {
- .compare_extable = compare_extable_32,
- .ehdr_shoff = ehdr32_shoff,
- .ehdr_shentsize = ehdr32_shentsize,
- .ehdr_shstrndx = ehdr32_shstrndx,
- .ehdr_shnum = ehdr32_shnum,
- .shdr_addr = shdr32_addr,
- .shdr_offset = shdr32_offset,
- .shdr_link = shdr32_link,
- .shdr_size = shdr32_size,
- .shdr_name = shdr32_name,
- .shdr_type = shdr32_type,
- .shdr_entsize = shdr32_entsize,
- .sym_type = sym32_type,
- .sym_name = sym32_name,
- .sym_value = sym32_value,
- .sym_shndx = sym32_shndx,
- .rela_offset = rela32_offset,
- .rela_info = rela32_info,
- .rela_addend = rela32_addend,
- .rela_write_addend = rela32_write_addend,
- };
-
- e = efuncs;
+ switch (elf_map_long_size(addr)) {
+ case 4:
+ compare_extable = compare_extable_32,
long_size = 4;
extable_ent_size = 8;
- if (r2(&ehdr->e32.e_ehsize) != sizeof(Elf32_Ehdr) ||
- r2(&ehdr->e32.e_shentsize) != sizeof(Elf32_Shdr)) {
+ if (elf_parser.r2(&ehdr->e32.e_ehsize) != sizeof(Elf32_Ehdr) ||
+ elf_parser.r2(&ehdr->e32.e_shentsize) != sizeof(Elf32_Shdr)) {
fprintf(stderr,
"unrecognized ET_EXEC/ET_DYN file: %s\n", fname);
return -1;
}
- }
break;
- case ELFCLASS64: {
- struct elf_funcs efuncs = {
- .compare_extable = compare_extable_64,
- .ehdr_shoff = ehdr64_shoff,
- .ehdr_shentsize = ehdr64_shentsize,
- .ehdr_shstrndx = ehdr64_shstrndx,
- .ehdr_shnum = ehdr64_shnum,
- .shdr_addr = shdr64_addr,
- .shdr_offset = shdr64_offset,
- .shdr_link = shdr64_link,
- .shdr_size = shdr64_size,
- .shdr_name = shdr64_name,
- .shdr_type = shdr64_type,
- .shdr_entsize = shdr64_entsize,
- .sym_type = sym64_type,
- .sym_name = sym64_name,
- .sym_value = sym64_value,
- .sym_shndx = sym64_shndx,
- .rela_offset = rela64_offset,
- .rela_info = rela64_info,
- .rela_addend = rela64_addend,
- .rela_write_addend = rela64_write_addend,
- };
-
- e = efuncs;
+ case 8:
+ compare_extable = compare_extable_64,
long_size = 8;
extable_ent_size = 16;
- if (r2(&ehdr->e64.e_ehsize) != sizeof(Elf64_Ehdr) ||
- r2(&ehdr->e64.e_shentsize) != sizeof(Elf64_Shdr)) {
+ if (elf_parser.r2(&ehdr->e64.e_ehsize) != sizeof(Elf64_Ehdr) ||
+ elf_parser.r2(&ehdr->e64.e_shentsize) != sizeof(Elf64_Shdr)) {
fprintf(stderr,
"unrecognized ET_EXEC/ET_DYN file: %s\n",
fname);
return -1;
}
- }
break;
default:
fprintf(stderr, "unrecognized ELF class %d %s\n",
@@ -1398,7 +989,7 @@ int main(int argc, char *argv[])
/* Process each file in turn, allowing deep failure. */
for (i = optind; i < argc; i++) {
- addr = mmap_file(argv[i], &size);
+ addr = elf_map(argv[i], &size, (1 << ET_EXEC) | (1 << ET_DYN));
if (!addr) {
++n_error;
continue;
@@ -1407,7 +998,7 @@ int main(int argc, char *argv[])
if (do_file(argv[i], addr))
++n_error;
- munmap(addr, size);
+ elf_unmap(addr, size);
}
return !!n_error;
--
2.51.0
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH v9 2/4] tracing: Add a tracepoint verification check at build time
2025-10-15 20:38 [PATCH v9 0/4] tracepoints: Add warnings for unused tracepoints and trace events Steven Rostedt
2025-10-15 20:38 ` [PATCH v9 1/4] sorttable: Move ELF parsing into scripts/elf-parse.[ch] Steven Rostedt
@ 2025-10-15 20:38 ` Steven Rostedt
2025-10-15 23:12 ` Nathan Chancellor
2025-10-17 20:15 ` Nicolas Schier
2025-10-15 20:38 ` [PATCH v9 3/4] tracepoint: Do not warn for unused event that is exported Steven Rostedt
2025-10-15 20:38 ` [PATCH v9 4/4] tracing: Add warnings for unused tracepoints for modules Steven Rostedt
3 siblings, 2 replies; 15+ messages in thread
From: Steven Rostedt @ 2025-10-15 20:38 UTC (permalink / raw)
To: linux-kernel, linux-trace-kernel, linux-kbuild
Cc: Masami Hiramatsu, Mark Rutland, Mathieu Desnoyers, Andrew Morton,
Arnd Bergmann, Masahiro Yamada, Nathan Chancellor, Nicolas Schier,
Nick Desaulniers, Catalin Marinas, Linus Torvalds, Randy Dunlap,
Stephen Rothwell
From: Steven Rostedt <rostedt@goodmis.org>
If a tracepoint is defined via DECLARE_TRACE() or TRACE_EVENT() but never
called (via the trace_<tracepoint>() function), its metadata is still
around in memory and not discarded.
When created via TRACE_EVENT() the situation is worse because the
TRACE_EVENT() creates metadata that can be around 5k per trace event.
Having unused trace events causes several thousand of wasted bytes.
Add a verifier that injects a string of the name of the tracepoint it
calls that is added to the discarded section "__tracepoint_check".
For every builtin tracepoint, its name (which is saved in the in-memory
section "__tracepoint_strings") will have its name also in the
"__tracepoint_check" section if it is used.
Add a new program that is run on build called tracepoint-update. This is
executed on the vmlinux.o before the __tracepoint_check section is
discarded (the section is discarded before vmlinux is created). This
program will create an array of each string in the __tracepoint_check
section and then sort it. Then it will walk the strings in the
__tracepoint_strings section and do a binary search to check if its name
is in the __tracepoint_check section. If it is not, then it is unused and
a warning is printed.
Note, this currently only handles tracepoints that are builtin and not in
modules.
Enabling this currently with a given config produces:
warning: tracepoint 'sched_move_numa' is unused.
warning: tracepoint 'sched_stick_numa' is unused.
warning: tracepoint 'sched_swap_numa' is unused.
warning: tracepoint 'pelt_hw_tp' is unused.
warning: tracepoint 'pelt_irq_tp' is unused.
warning: tracepoint 'rcu_preempt_task' is unused.
warning: tracepoint 'rcu_unlock_preempted_task' is unused.
warning: tracepoint 'xdp_bulk_tx' is unused.
warning: tracepoint 'xdp_redirect_map' is unused.
warning: tracepoint 'xdp_redirect_map_err' is unused.
warning: tracepoint 'vma_mas_szero' is unused.
warning: tracepoint 'vma_store' is unused.
warning: tracepoint 'hugepage_set_pmd' is unused.
warning: tracepoint 'hugepage_set_pud' is unused.
warning: tracepoint 'hugepage_update_pmd' is unused.
warning: tracepoint 'hugepage_update_pud' is unused.
warning: tracepoint 'block_rq_remap' is unused.
warning: tracepoint 'xhci_dbc_handle_event' is unused.
warning: tracepoint 'xhci_dbc_handle_transfer' is unused.
warning: tracepoint 'xhci_dbc_gadget_ep_queue' is unused.
warning: tracepoint 'xhci_dbc_alloc_request' is unused.
warning: tracepoint 'xhci_dbc_free_request' is unused.
warning: tracepoint 'xhci_dbc_queue_request' is unused.
warning: tracepoint 'xhci_dbc_giveback_request' is unused.
warning: tracepoint 'tcp_ao_wrong_maclen' is unused.
warning: tracepoint 'tcp_ao_mismatch' is unused.
warning: tracepoint 'tcp_ao_key_not_found' is unused.
warning: tracepoint 'tcp_ao_rnext_request' is unused.
warning: tracepoint 'tcp_ao_synack_no_key' is unused.
warning: tracepoint 'tcp_ao_snd_sne_update' is unused.
warning: tracepoint 'tcp_ao_rcv_sne_update' is unused.
Some of the above is totally unused but others are not used due to their
"trace_" functions being inside configs, in which case, the defined
tracepoints should also be inside those same configs. Others are
architecture specific but defined in generic code, where they should
either be moved to the architecture or be surrounded by #ifdef for the
architectures they are for.
This tool could be updated to process modules in the future.
I'd like to thank Mathieu Desnoyers for suggesting using strings instead
of pointers, as using pointers in vmlinux.o required handling relocations
and it required implementing almost a full feature linker to do so.
To enable this check, run the build with: make UT=1
Link: https://lore.kernel.org/all/20250528114549.4d8a5e03@gandalf.local.home/
Suggested-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> # for using strings instead of pointers
Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
---
Changes since v8: https://lore.kernel.org/20250828203741.401496225@kernel.org
- Instead of using a config option to enable this, enable it via: make UT=1
This will allow it to go into linux-next without triggering all the
current warnings but also allow people to find and fix current unused
tracepoints.
Makefile | 15 ++
include/asm-generic/vmlinux.lds.h | 1 +
include/linux/tracepoint.h | 11 ++
scripts/Makefile | 3 +
scripts/link-vmlinux.sh | 7 +
scripts/tracepoint-update.c | 232 ++++++++++++++++++++++++++++++
6 files changed, 269 insertions(+)
create mode 100644 scripts/tracepoint-update.c
diff --git a/Makefile b/Makefile
index 17cfa11ca716..a3141890f38f 100644
--- a/Makefile
+++ b/Makefile
@@ -157,6 +157,20 @@ endif
export KBUILD_EXTRA_WARN
+# To check for unused tracepoints (tracepoints that are defined but never
+# called), run with:
+#
+# make UT=1
+#
+# Each unused tracepoints can take up to 5KB of memory in the running kernel.
+# It is best to remove any that are not used.
+
+ifeq ("$(origin UT)", "command line")
+ WARN_ON_UNUSED_TRACEPOINTS := $(UT)
+endif
+
+export WARN_ON_UNUSED_TRACEPOINTS
+
# Kbuild will save output files in the current working directory.
# This does not need to match to the root of the kernel source tree.
#
@@ -1772,6 +1786,7 @@ help:
@echo ' c: extra checks in the configuration stage (Kconfig)'
@echo ' e: warnings are being treated as errors'
@echo ' Multiple levels can be combined with W=12 or W=123'
+ @echo ' make UT=1 [targets] Warn if a tracepoint is defined but not used.
@$(if $(dtstree), \
echo ' make CHECK_DTBS=1 [targets] Check all generated dtb files against schema'; \
echo ' This can be applied both to "dtbs" and to individual "foo.dtb" targets' ; \
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 8a9a2e732a65..08ca759fb992 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -1048,6 +1048,7 @@ defined(CONFIG_AUTOFDO_CLANG) || defined(CONFIG_PROPELLER_CLANG)
*(.no_trim_symbol) \
/* ld.bfd warns about .gnu.version* even when not emitted */ \
*(.gnu.version*) \
+ *(__tracepoint_check)
#define DISCARDS \
/DISCARD/ : { \
diff --git a/include/linux/tracepoint.h b/include/linux/tracepoint.h
index 826ce3f8e1f8..1e53d3626c78 100644
--- a/include/linux/tracepoint.h
+++ b/include/linux/tracepoint.h
@@ -221,6 +221,15 @@ static inline struct tracepoint *tracepoint_ptr_deref(tracepoint_ptr_t *p)
__do_trace_##name(args); \
}
+/*
+ * When a tracepoint is used, it's name is added to the __tracepoint_check
+ * section. This section is only used at build time to make sure all
+ * defined tracepoints are used. It is discarded after the build.
+ */
+# define TRACEPOINT_CHECK(name) \
+ static const char __used __section("__tracepoint_check") __trace_check[] = \
+ #name;
+
/*
* Make sure the alignment of the structure in the __tracepoints section will
* not add unwanted padding between the beginning of the section and the
@@ -270,6 +279,7 @@ static inline struct tracepoint *tracepoint_ptr_deref(tracepoint_ptr_t *p)
__DECLARE_TRACE_COMMON(name, PARAMS(proto), PARAMS(args), PARAMS(data_proto)) \
static inline void __do_trace_##name(proto) \
{ \
+ TRACEPOINT_CHECK(name) \
if (cond) { \
guard(preempt_notrace)(); \
__DO_TRACE_CALL(name, TP_ARGS(args)); \
@@ -289,6 +299,7 @@ static inline struct tracepoint *tracepoint_ptr_deref(tracepoint_ptr_t *p)
__DECLARE_TRACE_COMMON(name, PARAMS(proto), PARAMS(args), PARAMS(data_proto)) \
static inline void __do_trace_##name(proto) \
{ \
+ TRACEPOINT_CHECK(name) \
guard(rcu_tasks_trace)(); \
__DO_TRACE_CALL(name, TP_ARGS(args)); \
} \
diff --git a/scripts/Makefile b/scripts/Makefile
index f19624b3ed92..0941e5ce7b57 100644
--- a/scripts/Makefile
+++ b/scripts/Makefile
@@ -11,8 +11,10 @@ hostprogs-always-$(CONFIG_MODULE_SIG_FORMAT) += sign-file
hostprogs-always-$(CONFIG_SYSTEM_EXTRA_CERTIFICATE) += insert-sys-cert
hostprogs-always-$(CONFIG_RUST_KERNEL_DOCTESTS) += rustdoc_test_builder
hostprogs-always-$(CONFIG_RUST_KERNEL_DOCTESTS) += rustdoc_test_gen
+hostprogs-always-$(CONFIG_TRACEPOINTS) += tracepoint-update
sorttable-objs := sorttable.o elf-parse.o
+tracepoint-update-objs := tracepoint-update.o elf-parse.o
ifneq ($(or $(CONFIG_X86_64),$(CONFIG_X86_32)),)
always-$(CONFIG_RUST) += target.json
@@ -27,6 +29,7 @@ generate_rust_target-rust := y
rustdoc_test_builder-rust := y
rustdoc_test_gen-rust := y
+HOSTCFLAGS_tracepoint-update.o = -I$(srctree)/tools/include
HOSTCFLAGS_elf-parse.o = -I$(srctree)/tools/include
HOSTCFLAGS_sorttable.o = -I$(srctree)/tools/include
HOSTLDLIBS_sorttable = -lpthread
diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh
index 433849ff7529..d304029fa6da 100755
--- a/scripts/link-vmlinux.sh
+++ b/scripts/link-vmlinux.sh
@@ -208,6 +208,13 @@ kallsymso=
strip_debug=
generate_map=
+# Use "make UT=1" to trigger warnings on unused tracepoints
+case "${WARN_ON_UNUSED_TRACEPOINTS}" in
+*1*)
+ ${objtree}/scripts/tracepoint-update vmlinux.o
+ ;;
+esac
+
if is_enabled CONFIG_KALLSYMS; then
true > .tmp_vmlinux0.syms
kallsyms .tmp_vmlinux0.syms .tmp_vmlinux0.kallsyms
diff --git a/scripts/tracepoint-update.c b/scripts/tracepoint-update.c
new file mode 100644
index 000000000000..6ec30f39d0ad
--- /dev/null
+++ b/scripts/tracepoint-update.c
@@ -0,0 +1,232 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <getopt.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <pthread.h>
+
+#include "elf-parse.h"
+
+static Elf_Shdr *check_data_sec;
+static Elf_Shdr *tracepoint_data_sec;
+
+static inline void *get_index(void *start, int entsize, int index)
+{
+ return start + (entsize * index);
+}
+
+static int compare_strings(const void *a, const void *b)
+{
+ const char *av = *(const char **)a;
+ const char *bv = *(const char **)b;
+
+ return strcmp(av, bv);
+}
+
+struct elf_tracepoint {
+ Elf_Ehdr *ehdr;
+ const char **array;
+ int count;
+};
+
+#define REALLOC_SIZE (1 << 10)
+#define REALLOC_MASK (REALLOC_SIZE - 1)
+
+static int add_string(const char *str, const char ***vals, int *count)
+{
+ const char **array = *vals;
+
+ if (!(*count & REALLOC_MASK)) {
+ int size = (*count) + REALLOC_SIZE;
+
+ array = realloc(array, sizeof(char *) * size);
+ if (!array) {
+ fprintf(stderr, "Failed memory allocation\n");
+ return -1;
+ }
+ *vals = array;
+ }
+
+ array[(*count)++] = str;
+ return 0;
+}
+
+/**
+ * for_each_shdr_str - iterator that reads strings that are in an ELF section.
+ * @len: "int" to hold the length of the current string
+ * @ehdr: A pointer to the ehdr of the ELF file
+ * @sec: The section that has the strings to iterate on
+ *
+ * This is a for loop that iterates over all the nul terminated strings
+ * that are in a given ELF section. The variable "str" will hold
+ * the current string for each iteration and the passed in @len will
+ * contain the strlen() of that string.
+ */
+#define for_each_shdr_str(len, ehdr, sec) \
+ for (const char *str = (void *)(ehdr) + shdr_offset(sec), \
+ *end = str + shdr_size(sec); \
+ len = strlen(str), str < end; \
+ str += (len) + 1)
+
+
+static void make_trace_array(struct elf_tracepoint *etrace)
+{
+ Elf_Ehdr *ehdr = etrace->ehdr;
+ const char **vals = NULL;
+ int count = 0;
+ int len;
+
+ etrace->array = NULL;
+
+ /*
+ * The __tracepoint_check section is filled with strings of the
+ * names of tracepoints (in tracepoint_strings). Create an array
+ * that points to each string and then sort the array.
+ */
+ for_each_shdr_str(len, ehdr, check_data_sec) {
+ if (!len)
+ continue;
+ if (add_string(str, &vals, &count) < 0)
+ return;
+ }
+
+ /* If CONFIG_TRACEPOINT_VERIFY_USED is not set, there's nothing to do */
+ if (!count)
+ return;
+
+ qsort(vals, count, sizeof(char *), compare_strings);
+
+ etrace->array = vals;
+ etrace->count = count;
+}
+
+static int find_event(const char *str, void *array, size_t size)
+{
+ return bsearch(&str, array, size, sizeof(char *), compare_strings) != NULL;
+}
+
+static void check_tracepoints(struct elf_tracepoint *etrace)
+{
+ Elf_Ehdr *ehdr = etrace->ehdr;
+ int len;
+
+ if (!etrace->array)
+ return;
+
+ /*
+ * The __tracepoints_strings section holds all the names of the
+ * defined tracepoints. If any of them are not in the
+ * __tracepoint_check_section it means they are not used.
+ */
+ for_each_shdr_str(len, ehdr, tracepoint_data_sec) {
+ if (!len)
+ continue;
+ if (!find_event(str, etrace->array, etrace->count)) {
+ fprintf(stderr, "warning: tracepoint '%s' is unused.\n", str);
+ }
+ }
+
+ free(etrace->array);
+}
+
+static void *tracepoint_check(struct elf_tracepoint *etrace)
+{
+ make_trace_array(etrace);
+ check_tracepoints(etrace);
+
+ return NULL;
+}
+
+static int process_tracepoints(void *addr, char const *const fname)
+{
+ struct elf_tracepoint etrace = {0};
+ Elf_Ehdr *ehdr = addr;
+ Elf_Shdr *shdr_start;
+ Elf_Shdr *string_sec;
+ const char *secstrings;
+ unsigned int shnum;
+ unsigned int shstrndx;
+ int shentsize;
+ int idx;
+ int done = 2;
+
+ shdr_start = (Elf_Shdr *)((char *)ehdr + ehdr_shoff(ehdr));
+ shentsize = ehdr_shentsize(ehdr);
+
+ shstrndx = ehdr_shstrndx(ehdr);
+ if (shstrndx == SHN_XINDEX)
+ shstrndx = shdr_link(shdr_start);
+ string_sec = get_index(shdr_start, shentsize, shstrndx);
+ secstrings = (const char *)ehdr + shdr_offset(string_sec);
+
+ shnum = ehdr_shnum(ehdr);
+ if (shnum == SHN_UNDEF)
+ shnum = shdr_size(shdr_start);
+
+ for (int i = 0; done && i < shnum; i++) {
+ Elf_Shdr *shdr = get_index(shdr_start, shentsize, i);
+
+ idx = shdr_name(shdr);
+
+ /* locate the __tracepoint_check in vmlinux */
+ if (!strcmp(secstrings + idx, "__tracepoint_check")) {
+ check_data_sec = shdr;
+ done--;
+ }
+
+ /* locate the __tracepoints_ptrs section in vmlinux */
+ if (!strcmp(secstrings + idx, "__tracepoints_strings")) {
+ tracepoint_data_sec = shdr;
+ done--;
+ }
+ }
+
+ if (!check_data_sec) {
+ fprintf(stderr, "no __tracepoint_check in file: %s\n", fname);
+ return -1;
+ }
+
+ if (!tracepoint_data_sec) {
+ fprintf(stderr, "no __tracepoint_strings in file: %s\n", fname);
+ return -1;
+ }
+
+ etrace.ehdr = ehdr;
+ tracepoint_check(&etrace);
+ return 0;
+}
+
+int main(int argc, char *argv[])
+{
+ int n_error = 0;
+ size_t size = 0;
+ void *addr = NULL;
+
+ if (argc < 2) {
+ fprintf(stderr, "usage: tracepoint-update vmlinux...\n");
+ return 0;
+ }
+
+ /* Process each file in turn, allowing deep failure. */
+ for (int i = 1; i < argc; i++) {
+ addr = elf_map(argv[i], &size, 1 << ET_REL);
+ if (!addr) {
+ ++n_error;
+ continue;
+ }
+
+ if (process_tracepoints(addr, argv[i]))
+ ++n_error;
+
+ elf_unmap(addr, size);
+ }
+
+ return !!n_error;
+}
--
2.51.0
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH v9 3/4] tracepoint: Do not warn for unused event that is exported
2025-10-15 20:38 [PATCH v9 0/4] tracepoints: Add warnings for unused tracepoints and trace events Steven Rostedt
2025-10-15 20:38 ` [PATCH v9 1/4] sorttable: Move ELF parsing into scripts/elf-parse.[ch] Steven Rostedt
2025-10-15 20:38 ` [PATCH v9 2/4] tracing: Add a tracepoint verification check at build time Steven Rostedt
@ 2025-10-15 20:38 ` Steven Rostedt
2025-10-15 20:38 ` [PATCH v9 4/4] tracing: Add warnings for unused tracepoints for modules Steven Rostedt
3 siblings, 0 replies; 15+ messages in thread
From: Steven Rostedt @ 2025-10-15 20:38 UTC (permalink / raw)
To: linux-kernel, linux-trace-kernel, linux-kbuild
Cc: Masami Hiramatsu, Mark Rutland, Mathieu Desnoyers, Andrew Morton,
Arnd Bergmann, Masahiro Yamada, Nathan Chancellor, Nicolas Schier,
Nick Desaulniers, Catalin Marinas, Linus Torvalds, Randy Dunlap,
Stephen Rothwell
From: Steven Rostedt <rostedt@goodmis.org>
There are a few generic events that may only be used by modules. They are
defined and then set with EXPORT_TRACEPOINT*(). Mark events that are
exported as being used, even though they still waste memory in the kernel
proper.
Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
---
include/linux/tracepoint.h | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/include/linux/tracepoint.h b/include/linux/tracepoint.h
index 1e53d3626c78..8a56f3278b1b 100644
--- a/include/linux/tracepoint.h
+++ b/include/linux/tracepoint.h
@@ -227,8 +227,8 @@ static inline struct tracepoint *tracepoint_ptr_deref(tracepoint_ptr_t *p)
* defined tracepoints are used. It is discarded after the build.
*/
# define TRACEPOINT_CHECK(name) \
- static const char __used __section("__tracepoint_check") __trace_check[] = \
- #name;
+ static const char __used __section("__tracepoint_check") \
+ __trace_check_##name[] = #name;
/*
* Make sure the alignment of the structure in the __tracepoints section will
@@ -382,10 +382,12 @@ static inline struct tracepoint *tracepoint_ptr_deref(tracepoint_ptr_t *p)
__DEFINE_TRACE_EXT(_name, NULL, PARAMS(_proto), PARAMS(_args));
#define EXPORT_TRACEPOINT_SYMBOL_GPL(name) \
+ TRACEPOINT_CHECK(name) \
EXPORT_SYMBOL_GPL(__tracepoint_##name); \
EXPORT_SYMBOL_GPL(__traceiter_##name); \
EXPORT_STATIC_CALL_GPL(tp_func_##name)
#define EXPORT_TRACEPOINT_SYMBOL(name) \
+ TRACEPOINT_CHECK(name) \
EXPORT_SYMBOL(__tracepoint_##name); \
EXPORT_SYMBOL(__traceiter_##name); \
EXPORT_STATIC_CALL(tp_func_##name)
--
2.51.0
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH v9 4/4] tracing: Add warnings for unused tracepoints for modules
2025-10-15 20:38 [PATCH v9 0/4] tracepoints: Add warnings for unused tracepoints and trace events Steven Rostedt
` (2 preceding siblings ...)
2025-10-15 20:38 ` [PATCH v9 3/4] tracepoint: Do not warn for unused event that is exported Steven Rostedt
@ 2025-10-15 20:38 ` Steven Rostedt
2025-10-15 23:19 ` Nathan Chancellor
2025-10-16 10:54 ` kernel test robot
3 siblings, 2 replies; 15+ messages in thread
From: Steven Rostedt @ 2025-10-15 20:38 UTC (permalink / raw)
To: linux-kernel, linux-trace-kernel, linux-kbuild
Cc: Masami Hiramatsu, Mark Rutland, Mathieu Desnoyers, Andrew Morton,
Arnd Bergmann, Masahiro Yamada, Nathan Chancellor, Nicolas Schier,
Nick Desaulniers, Catalin Marinas, Linus Torvalds, Randy Dunlap,
Stephen Rothwell
From: Steven Rostedt <rostedt@goodmis.org>
If a modules has TRACE_EVENT() but does not use it, add a warning about it
at build time.
Currently, the build must be made by adding "UT=1" to the make command
line in order for this to trigger.
Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
---
scripts/Makefile.modfinal | 7 +++++++
scripts/tracepoint-update.c | 7 +++++++
2 files changed, 14 insertions(+)
diff --git a/scripts/Makefile.modfinal b/scripts/Makefile.modfinal
index 542ba462ed3e..6f909979af91 100644
--- a/scripts/Makefile.modfinal
+++ b/scripts/Makefile.modfinal
@@ -28,6 +28,12 @@ ccflags-remove-y := $(CC_FLAGS_CFI)
.module-common.o: $(srctree)/scripts/module-common.c FORCE
$(call if_changed_rule,cc_o_c)
+ifneq ($(WARN_ON_UNUSED_TRACEPOINTS),"")
+cmd_check_tracepoint = ${objtree}/scripts/tracepoint-update $<;
+else
+cmd_check_tracepoint =
+endif
+
quiet_cmd_ld_ko_o = LD [M] $@
cmd_ld_ko_o = \
$(LD) -r $(KBUILD_LDFLAGS) \
@@ -57,6 +63,7 @@ if_changed_except = $(if $(call newer_prereqs_except,$(2))$(cmd-check), \
ifdef CONFIG_DEBUG_INFO_BTF_MODULES
+$(if $(newer-prereqs),$(call cmd,btf_ko))
endif
+ +$(call cmd,check_tracepoint)
targets += $(modules:%.o=%.ko) $(modules:%.o=%.mod.o) .module-common.o
diff --git a/scripts/tracepoint-update.c b/scripts/tracepoint-update.c
index 6ec30f39d0ad..7e068de9c7f1 100644
--- a/scripts/tracepoint-update.c
+++ b/scripts/tracepoint-update.c
@@ -188,6 +188,13 @@ static int process_tracepoints(void *addr, char const *const fname)
}
}
+ /*
+ * Modules may not have either section. But if it has one section,
+ * it should have both of them.
+ */
+ if (!check_data_sec && !tracepoint_data_sec)
+ return 0;
+
if (!check_data_sec) {
fprintf(stderr, "no __tracepoint_check in file: %s\n", fname);
return -1;
--
2.51.0
^ permalink raw reply related [flat|nested] 15+ messages in thread
* Re: [PATCH v9 2/4] tracing: Add a tracepoint verification check at build time
2025-10-15 20:38 ` [PATCH v9 2/4] tracing: Add a tracepoint verification check at build time Steven Rostedt
@ 2025-10-15 23:12 ` Nathan Chancellor
2025-10-15 23:14 ` Steven Rostedt
2025-10-17 20:15 ` Nicolas Schier
1 sibling, 1 reply; 15+ messages in thread
From: Nathan Chancellor @ 2025-10-15 23:12 UTC (permalink / raw)
To: Steven Rostedt
Cc: linux-kernel, linux-trace-kernel, linux-kbuild, Masami Hiramatsu,
Mark Rutland, Mathieu Desnoyers, Andrew Morton, Arnd Bergmann,
Masahiro Yamada, Nicolas Schier, Nick Desaulniers,
Catalin Marinas, Linus Torvalds, Randy Dunlap, Stephen Rothwell
Hi Steve,
The kbuild portions of this seem fine, as they mirror existing patterns.
On Wed, Oct 15, 2025 at 04:38:44PM -0400, Steven Rostedt wrote:
> diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
> index 8a9a2e732a65..08ca759fb992 100644
> --- a/include/asm-generic/vmlinux.lds.h
> +++ b/include/asm-generic/vmlinux.lds.h
> @@ -1048,6 +1048,7 @@ defined(CONFIG_AUTOFDO_CLANG) || defined(CONFIG_PROPELLER_CLANG)
> *(.no_trim_symbol) \
> /* ld.bfd warns about .gnu.version* even when not emitted */ \
> *(.gnu.version*) \
> + *(__tracepoint_check)
Please add a trailing slash like the other lines so that one does not
need to be added when someone else needs to grow this macro (also helps
with 'git blame').
Cheers,
Nathan
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v9 2/4] tracing: Add a tracepoint verification check at build time
2025-10-15 23:12 ` Nathan Chancellor
@ 2025-10-15 23:14 ` Steven Rostedt
0 siblings, 0 replies; 15+ messages in thread
From: Steven Rostedt @ 2025-10-15 23:14 UTC (permalink / raw)
To: Nathan Chancellor
Cc: Steven Rostedt, linux-kernel, linux-trace-kernel, linux-kbuild,
Masami Hiramatsu, Mark Rutland, Mathieu Desnoyers, Andrew Morton,
Arnd Bergmann, Masahiro Yamada, Nicolas Schier, Nick Desaulniers,
Catalin Marinas, Linus Torvalds, Randy Dunlap, Stephen Rothwell
On Wed, 15 Oct 2025 16:12:19 -0700
Nathan Chancellor <nathan@kernel.org> wrote:
> Hi Steve,
>
> The kbuild portions of this seem fine, as they mirror existing patterns.
>
> On Wed, Oct 15, 2025 at 04:38:44PM -0400, Steven Rostedt wrote:
> > diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
> > index 8a9a2e732a65..08ca759fb992 100644
> > --- a/include/asm-generic/vmlinux.lds.h
> > +++ b/include/asm-generic/vmlinux.lds.h
> > @@ -1048,6 +1048,7 @@ defined(CONFIG_AUTOFDO_CLANG) || defined(CONFIG_PROPELLER_CLANG)
> > *(.no_trim_symbol) \
> > /* ld.bfd warns about .gnu.version* even when not emitted */ \
> > *(.gnu.version*) \
> > + *(__tracepoint_check)
>
> Please add a trailing slash like the other lines so that one does not
> need to be added when someone else needs to grow this macro (also helps
> with 'git blame').
Sure thing! Thanks for looking at these patches!
-- Steve
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v9 4/4] tracing: Add warnings for unused tracepoints for modules
2025-10-15 20:38 ` [PATCH v9 4/4] tracing: Add warnings for unused tracepoints for modules Steven Rostedt
@ 2025-10-15 23:19 ` Nathan Chancellor
2025-10-17 20:22 ` Nicolas Schier
2025-10-21 19:57 ` Steven Rostedt
2025-10-16 10:54 ` kernel test robot
1 sibling, 2 replies; 15+ messages in thread
From: Nathan Chancellor @ 2025-10-15 23:19 UTC (permalink / raw)
To: Steven Rostedt
Cc: linux-kernel, linux-trace-kernel, linux-kbuild, Masami Hiramatsu,
Mark Rutland, Mathieu Desnoyers, Andrew Morton, Arnd Bergmann,
Masahiro Yamada, Nicolas Schier, Nick Desaulniers,
Catalin Marinas, Linus Torvalds, Randy Dunlap, Stephen Rothwell
Hi Steve,
On Wed, Oct 15, 2025 at 04:38:46PM -0400, Steven Rostedt wrote:
> diff --git a/scripts/Makefile.modfinal b/scripts/Makefile.modfinal
> index 542ba462ed3e..6f909979af91 100644
> --- a/scripts/Makefile.modfinal
> +++ b/scripts/Makefile.modfinal
> @@ -28,6 +28,12 @@ ccflags-remove-y := $(CC_FLAGS_CFI)
> .module-common.o: $(srctree)/scripts/module-common.c FORCE
> $(call if_changed_rule,cc_o_c)
>
> +ifneq ($(WARN_ON_UNUSED_TRACEPOINTS),"")
Drop the "", nowhere else in Kbuild appears to do this.
> +cmd_check_tracepoint = ${objtree}/scripts/tracepoint-update $<;
Please use $(objtree) to be consistent with the rest of Kbuild.
> +else
> +cmd_check_tracepoint =
> +endif
> +
> quiet_cmd_ld_ko_o = LD [M] $@
> cmd_ld_ko_o = \
> $(LD) -r $(KBUILD_LDFLAGS) \
> @@ -57,6 +63,7 @@ if_changed_except = $(if $(call newer_prereqs_except,$(2))$(cmd-check), \
> ifdef CONFIG_DEBUG_INFO_BTF_MODULES
> +$(if $(newer-prereqs),$(call cmd,btf_ko))
> endif
> + +$(call cmd,check_tracepoint)
>
> targets += $(modules:%.o=%.ko) $(modules:%.o=%.mod.o) .module-common.o
>
> diff --git a/scripts/tracepoint-update.c b/scripts/tracepoint-update.c
> index 6ec30f39d0ad..7e068de9c7f1 100644
> --- a/scripts/tracepoint-update.c
> +++ b/scripts/tracepoint-update.c
> @@ -188,6 +188,13 @@ static int process_tracepoints(void *addr, char const *const fname)
> }
> }
>
> + /*
> + * Modules may not have either section. But if it has one section,
> + * it should have both of them.
> + */
> + if (!check_data_sec && !tracepoint_data_sec)
> + return 0;
> +
This feels like it could be its own patch but I guess it does not make
much sense without enablement. It might be worth calling this out a bit
more in the commit message.
> if (!check_data_sec) {
> fprintf(stderr, "no __tracepoint_check in file: %s\n", fname);
> return -1;
> --
> 2.51.0
>
>
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v9 4/4] tracing: Add warnings for unused tracepoints for modules
2025-10-15 20:38 ` [PATCH v9 4/4] tracing: Add warnings for unused tracepoints for modules Steven Rostedt
2025-10-15 23:19 ` Nathan Chancellor
@ 2025-10-16 10:54 ` kernel test robot
1 sibling, 0 replies; 15+ messages in thread
From: kernel test robot @ 2025-10-16 10:54 UTC (permalink / raw)
To: Steven Rostedt, linux-kernel, linux-trace-kernel, linux-kbuild
Cc: oe-kbuild-all, Masami Hiramatsu, Mark Rutland, Mathieu Desnoyers,
Andrew Morton, Linux Memory Management List, Arnd Bergmann,
Masahiro Yamada, Nathan Chancellor, Nicolas Schier,
Nick Desaulniers, Catalin Marinas, Randy Dunlap
Hi Steven,
kernel test robot noticed the following build errors:
[auto build test ERROR on akpm-mm/mm-everything]
[also build test ERROR on linus/master v6.18-rc1 next-20251015]
[cannot apply to trace/for-next arnd-asm-generic/master]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Steven-Rostedt/sorttable-Move-ELF-parsing-into-scripts-elf-parse-ch/20251016-044008
base: https://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm.git mm-everything
patch link: https://lore.kernel.org/r/20251015203924.731213165%40kernel.org
patch subject: [PATCH v9 4/4] tracing: Add warnings for unused tracepoints for modules
config: microblaze-defconfig (https://download.01.org/0day-ci/archive/20251016/202510161811.9iIH3K15-lkp@intel.com/config)
compiler: microblaze-linux-gcc (GCC) 15.1.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20251016/202510161811.9iIH3K15-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202510161811.9iIH3K15-lkp@intel.com/
All errors (new ones prefixed by >>):
>> /bin/bash: line 1: ./scripts/tracepoint-update: No such file or directory
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v9 2/4] tracing: Add a tracepoint verification check at build time
2025-10-15 20:38 ` [PATCH v9 2/4] tracing: Add a tracepoint verification check at build time Steven Rostedt
2025-10-15 23:12 ` Nathan Chancellor
@ 2025-10-17 20:15 ` Nicolas Schier
2025-10-21 19:47 ` Steven Rostedt
1 sibling, 1 reply; 15+ messages in thread
From: Nicolas Schier @ 2025-10-17 20:15 UTC (permalink / raw)
To: Steven Rostedt
Cc: linux-kernel, linux-trace-kernel, linux-kbuild, Masami Hiramatsu,
Mark Rutland, Mathieu Desnoyers, Andrew Morton, Arnd Bergmann,
Masahiro Yamada, Nathan Chancellor, Nick Desaulniers,
Catalin Marinas, Linus Torvalds, Randy Dunlap, Stephen Rothwell
On Wed, Oct 15, 2025 at 04:38:44PM -0400, Steven Rostedt wrote:
> From: Steven Rostedt <rostedt@goodmis.org>
>
> If a tracepoint is defined via DECLARE_TRACE() or TRACE_EVENT() but never
> called (via the trace_<tracepoint>() function), its metadata is still
> around in memory and not discarded.
>
> When created via TRACE_EVENT() the situation is worse because the
> TRACE_EVENT() creates metadata that can be around 5k per trace event.
> Having unused trace events causes several thousand of wasted bytes.
>
> Add a verifier that injects a string of the name of the tracepoint it
> calls that is added to the discarded section "__tracepoint_check".
> For every builtin tracepoint, its name (which is saved in the in-memory
> section "__tracepoint_strings") will have its name also in the
> "__tracepoint_check" section if it is used.
>
> Add a new program that is run on build called tracepoint-update. This is
> executed on the vmlinux.o before the __tracepoint_check section is
> discarded (the section is discarded before vmlinux is created). This
> program will create an array of each string in the __tracepoint_check
> section and then sort it. Then it will walk the strings in the
> __tracepoint_strings section and do a binary search to check if its name
> is in the __tracepoint_check section. If it is not, then it is unused and
> a warning is printed.
>
> Note, this currently only handles tracepoints that are builtin and not in
> modules.
>
> Enabling this currently with a given config produces:
>
> warning: tracepoint 'sched_move_numa' is unused.
> warning: tracepoint 'sched_stick_numa' is unused.
> warning: tracepoint 'sched_swap_numa' is unused.
> warning: tracepoint 'pelt_hw_tp' is unused.
> warning: tracepoint 'pelt_irq_tp' is unused.
> warning: tracepoint 'rcu_preempt_task' is unused.
> warning: tracepoint 'rcu_unlock_preempted_task' is unused.
> warning: tracepoint 'xdp_bulk_tx' is unused.
> warning: tracepoint 'xdp_redirect_map' is unused.
> warning: tracepoint 'xdp_redirect_map_err' is unused.
> warning: tracepoint 'vma_mas_szero' is unused.
> warning: tracepoint 'vma_store' is unused.
> warning: tracepoint 'hugepage_set_pmd' is unused.
> warning: tracepoint 'hugepage_set_pud' is unused.
> warning: tracepoint 'hugepage_update_pmd' is unused.
> warning: tracepoint 'hugepage_update_pud' is unused.
> warning: tracepoint 'block_rq_remap' is unused.
> warning: tracepoint 'xhci_dbc_handle_event' is unused.
> warning: tracepoint 'xhci_dbc_handle_transfer' is unused.
> warning: tracepoint 'xhci_dbc_gadget_ep_queue' is unused.
> warning: tracepoint 'xhci_dbc_alloc_request' is unused.
> warning: tracepoint 'xhci_dbc_free_request' is unused.
> warning: tracepoint 'xhci_dbc_queue_request' is unused.
> warning: tracepoint 'xhci_dbc_giveback_request' is unused.
> warning: tracepoint 'tcp_ao_wrong_maclen' is unused.
> warning: tracepoint 'tcp_ao_mismatch' is unused.
> warning: tracepoint 'tcp_ao_key_not_found' is unused.
> warning: tracepoint 'tcp_ao_rnext_request' is unused.
> warning: tracepoint 'tcp_ao_synack_no_key' is unused.
> warning: tracepoint 'tcp_ao_snd_sne_update' is unused.
> warning: tracepoint 'tcp_ao_rcv_sne_update' is unused.
>
> Some of the above is totally unused but others are not used due to their
> "trace_" functions being inside configs, in which case, the defined
> tracepoints should also be inside those same configs. Others are
> architecture specific but defined in generic code, where they should
> either be moved to the architecture or be surrounded by #ifdef for the
> architectures they are for.
>
> This tool could be updated to process modules in the future.
>
> I'd like to thank Mathieu Desnoyers for suggesting using strings instead
> of pointers, as using pointers in vmlinux.o required handling relocations
> and it required implementing almost a full feature linker to do so.
>
> To enable this check, run the build with: make UT=1
>
> Link: https://lore.kernel.org/all/20250528114549.4d8a5e03@gandalf.local.home/
>
> Suggested-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> # for using strings instead of pointers
> Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
> ---
> Changes since v8: https://lore.kernel.org/20250828203741.401496225@kernel.org
>
> - Instead of using a config option to enable this, enable it via: make UT=1
> This will allow it to go into linux-next without triggering all the
> current warnings but also allow people to find and fix current unused
> tracepoints.
>
> Makefile | 15 ++
> include/asm-generic/vmlinux.lds.h | 1 +
> include/linux/tracepoint.h | 11 ++
> scripts/Makefile | 3 +
> scripts/link-vmlinux.sh | 7 +
> scripts/tracepoint-update.c | 232 ++++++++++++++++++++++++++++++
> 6 files changed, 269 insertions(+)
> create mode 100644 scripts/tracepoint-update.c
>
> diff --git a/Makefile b/Makefile
> index 17cfa11ca716..a3141890f38f 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -157,6 +157,20 @@ endif
>
> export KBUILD_EXTRA_WARN
>
> +# To check for unused tracepoints (tracepoints that are defined but never
> +# called), run with:
> +#
> +# make UT=1
> +#
> +# Each unused tracepoints can take up to 5KB of memory in the running kernel.
> +# It is best to remove any that are not used.
> +
> +ifeq ("$(origin UT)", "command line")
> + WARN_ON_UNUSED_TRACEPOINTS := $(UT)
> +endif
> +
> +export WARN_ON_UNUSED_TRACEPOINTS
Is there a special reason why you chose to introduce a new command-line
variable instead of extending KBUILD_EXTRA_WARN / W ?
Kind regards,
Nicolas
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v9 4/4] tracing: Add warnings for unused tracepoints for modules
2025-10-15 23:19 ` Nathan Chancellor
@ 2025-10-17 20:22 ` Nicolas Schier
2025-10-21 19:48 ` Steven Rostedt
2025-10-21 19:57 ` Steven Rostedt
1 sibling, 1 reply; 15+ messages in thread
From: Nicolas Schier @ 2025-10-17 20:22 UTC (permalink / raw)
To: Steven Rostedt
Cc: Nathan Chancellor, linux-kernel, linux-trace-kernel, linux-kbuild,
Masami Hiramatsu, Mark Rutland, Mathieu Desnoyers, Andrew Morton,
Arnd Bergmann, Masahiro Yamada, Nick Desaulniers, Catalin Marinas,
Linus Torvalds, Randy Dunlap, Stephen Rothwell
On Wed, Oct 15, 2025 at 04:19:28PM -0700, Nathan Chancellor wrote:
> Hi Steve,
>
> On Wed, Oct 15, 2025 at 04:38:46PM -0400, Steven Rostedt wrote:
> > diff --git a/scripts/Makefile.modfinal b/scripts/Makefile.modfinal
> > index 542ba462ed3e..6f909979af91 100644
> > --- a/scripts/Makefile.modfinal
> > +++ b/scripts/Makefile.modfinal
> > @@ -28,6 +28,12 @@ ccflags-remove-y := $(CC_FLAGS_CFI)
> > .module-common.o: $(srctree)/scripts/module-common.c FORCE
> > $(call if_changed_rule,cc_o_c)
> >
> > +ifneq ($(WARN_ON_UNUSED_TRACEPOINTS),"")
>
> Drop the "", nowhere else in Kbuild appears to do this.
>
> > +cmd_check_tracepoint = ${objtree}/scripts/tracepoint-update $<;
>
> Please use $(objtree) to be consistent with the rest of Kbuild.
>
> > +else
> > +cmd_check_tracepoint =
> > +endif
The else part is not required, cp. definition of e.g. cmd_checkdoc in
scripts/Makefile.build.
Kind regards
Nicolas
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v9 2/4] tracing: Add a tracepoint verification check at build time
2025-10-17 20:15 ` Nicolas Schier
@ 2025-10-21 19:47 ` Steven Rostedt
2025-10-21 21:21 ` Nicolas Schier
0 siblings, 1 reply; 15+ messages in thread
From: Steven Rostedt @ 2025-10-21 19:47 UTC (permalink / raw)
To: Nicolas Schier
Cc: Steven Rostedt, linux-kernel, linux-trace-kernel, linux-kbuild,
Masami Hiramatsu, Mark Rutland, Mathieu Desnoyers, Andrew Morton,
Arnd Bergmann, Masahiro Yamada, Nathan Chancellor,
Nick Desaulniers, Catalin Marinas, Linus Torvalds, Randy Dunlap,
Stephen Rothwell
On Fri, 17 Oct 2025 22:15:20 +0200
Nicolas Schier <nsc@kernel.org> wrote:
> > +# To check for unused tracepoints (tracepoints that are defined but never
> > +# called), run with:
> > +#
> > +# make UT=1
> > +#
> > +# Each unused tracepoints can take up to 5KB of memory in the running kernel.
> > +# It is best to remove any that are not used.
> > +
> > +ifeq ("$(origin UT)", "command line")
> > + WARN_ON_UNUSED_TRACEPOINTS := $(UT)
> > +endif
> > +
> > +export WARN_ON_UNUSED_TRACEPOINTS
>
> Is there a special reason why you chose to introduce a new command-line
> variable instead of extending KBUILD_EXTRA_WARN / W ?
Honestly, I didn't think about using KBUILD_EXTRA_WARN. I also want this
option to go away after we remove the current unused tracepoints so that
any new ones will always cause a warning.
The only reason not to make it always warn is because I don't want to add
warnings for the existing code. I'm working on having outreachy projects to
remove the currently unused tracepoints. Once that is done, then this
option is going to go away and the build will always warn on unused
tracepoints.
I thought it might be easier to remove it without any issues if it's a new
command line that goes away in the future.
Looking at EXTRA_WARN, it appears to be for basic issues with the code and
adds new C compiler warning flags. This isn't exactly the same.
If you think it makes sense to extend EXTRA_WARN, I can still go ahead and
do that.
-- Steve
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v9 4/4] tracing: Add warnings for unused tracepoints for modules
2025-10-17 20:22 ` Nicolas Schier
@ 2025-10-21 19:48 ` Steven Rostedt
0 siblings, 0 replies; 15+ messages in thread
From: Steven Rostedt @ 2025-10-21 19:48 UTC (permalink / raw)
To: Nicolas Schier
Cc: Steven Rostedt, Nathan Chancellor, linux-kernel,
linux-trace-kernel, linux-kbuild, Masami Hiramatsu, Mark Rutland,
Mathieu Desnoyers, Andrew Morton, Arnd Bergmann, Masahiro Yamada,
Nick Desaulniers, Catalin Marinas, Linus Torvalds, Randy Dunlap,
Stephen Rothwell
On Fri, 17 Oct 2025 22:22:32 +0200
Nicolas Schier <nsc@kernel.org> wrote:
> On Wed, Oct 15, 2025 at 04:19:28PM -0700, Nathan Chancellor wrote:
> > Hi Steve,
> >
> > On Wed, Oct 15, 2025 at 04:38:46PM -0400, Steven Rostedt wrote:
> > > diff --git a/scripts/Makefile.modfinal b/scripts/Makefile.modfinal
> > > index 542ba462ed3e..6f909979af91 100644
> > > --- a/scripts/Makefile.modfinal
> > > +++ b/scripts/Makefile.modfinal
> > > @@ -28,6 +28,12 @@ ccflags-remove-y := $(CC_FLAGS_CFI)
> > > .module-common.o: $(srctree)/scripts/module-common.c FORCE
> > > $(call if_changed_rule,cc_o_c)
> > >
> > > +ifneq ($(WARN_ON_UNUSED_TRACEPOINTS),"")
> >
> > Drop the "", nowhere else in Kbuild appears to do this.
> >
> > > +cmd_check_tracepoint = ${objtree}/scripts/tracepoint-update $<;
> >
> > Please use $(objtree) to be consistent with the rest of Kbuild.
> >
> > > +else
> > > +cmd_check_tracepoint =
> > > +endif
>
> The else part is not required, cp. definition of e.g. cmd_checkdoc in
> scripts/Makefile.build.
Thanks, will do.
-- Steve
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v9 4/4] tracing: Add warnings for unused tracepoints for modules
2025-10-15 23:19 ` Nathan Chancellor
2025-10-17 20:22 ` Nicolas Schier
@ 2025-10-21 19:57 ` Steven Rostedt
1 sibling, 0 replies; 15+ messages in thread
From: Steven Rostedt @ 2025-10-21 19:57 UTC (permalink / raw)
To: Nathan Chancellor
Cc: Steven Rostedt, linux-kernel, linux-trace-kernel, linux-kbuild,
Masami Hiramatsu, Mark Rutland, Mathieu Desnoyers, Andrew Morton,
Arnd Bergmann, Masahiro Yamada, Nicolas Schier, Nick Desaulniers,
Catalin Marinas, Linus Torvalds, Randy Dunlap, Stephen Rothwell
On Wed, 15 Oct 2025 16:19:28 -0700
Nathan Chancellor <nathan@kernel.org> wrote:
> Hi Steve,
>
> On Wed, Oct 15, 2025 at 04:38:46PM -0400, Steven Rostedt wrote:
> > diff --git a/scripts/Makefile.modfinal b/scripts/Makefile.modfinal
> > index 542ba462ed3e..6f909979af91 100644
> > --- a/scripts/Makefile.modfinal
> > +++ b/scripts/Makefile.modfinal
> > @@ -28,6 +28,12 @@ ccflags-remove-y := $(CC_FLAGS_CFI)
> > .module-common.o: $(srctree)/scripts/module-common.c FORCE
> > $(call if_changed_rule,cc_o_c)
> >
> > +ifneq ($(WARN_ON_UNUSED_TRACEPOINTS),"")
>
> Drop the "", nowhere else in Kbuild appears to do this.
>
> > +cmd_check_tracepoint = ${objtree}/scripts/tracepoint-update $<;
>
> Please use $(objtree) to be consistent with the rest of Kbuild.
OK for both.
>
> > +else
> > +cmd_check_tracepoint =
> > +endif
> > +
> > quiet_cmd_ld_ko_o = LD [M] $@
> > cmd_ld_ko_o = \
> > $(LD) -r $(KBUILD_LDFLAGS) \
> > @@ -57,6 +63,7 @@ if_changed_except = $(if $(call newer_prereqs_except,$(2))$(cmd-check), \
> > ifdef CONFIG_DEBUG_INFO_BTF_MODULES
> > +$(if $(newer-prereqs),$(call cmd,btf_ko))
> > endif
> > + +$(call cmd,check_tracepoint)
> >
> > targets += $(modules:%.o=%.ko) $(modules:%.o=%.mod.o) .module-common.o
> >
> > diff --git a/scripts/tracepoint-update.c b/scripts/tracepoint-update.c
> > index 6ec30f39d0ad..7e068de9c7f1 100644
> > --- a/scripts/tracepoint-update.c
> > +++ b/scripts/tracepoint-update.c
> > @@ -188,6 +188,13 @@ static int process_tracepoints(void *addr, char const *const fname)
> > }
> > }
> >
> > + /*
> > + * Modules may not have either section. But if it has one section,
> > + * it should have both of them.
> > + */
> > + if (!check_data_sec && !tracepoint_data_sec)
> > + return 0;
> > +
>
> This feels like it could be its own patch but I guess it does not make
> much sense without enablement. It might be worth calling this out a bit
> more in the commit message.
>
It was found during debugging. I could make this a separate patch in
preparation for this patch.
-- Steve
> > if (!check_data_sec) {
> > fprintf(stderr, "no __tracepoint_check in file: %s\n", fname);
> > return -1;
> > --
> > 2.51.0
> >
> >
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v9 2/4] tracing: Add a tracepoint verification check at build time
2025-10-21 19:47 ` Steven Rostedt
@ 2025-10-21 21:21 ` Nicolas Schier
0 siblings, 0 replies; 15+ messages in thread
From: Nicolas Schier @ 2025-10-21 21:21 UTC (permalink / raw)
To: Steven Rostedt
Cc: Steven Rostedt, linux-kernel, linux-trace-kernel, linux-kbuild,
Masami Hiramatsu, Mark Rutland, Mathieu Desnoyers, Andrew Morton,
Arnd Bergmann, Masahiro Yamada, Nathan Chancellor,
Nick Desaulniers, Catalin Marinas, Linus Torvalds, Randy Dunlap,
Stephen Rothwell
On Tue, Oct 21, 2025 at 03:47:37PM -0400, Steven Rostedt wrote:
> On Fri, 17 Oct 2025 22:15:20 +0200
> Nicolas Schier <nsc@kernel.org> wrote:
>
> > > +# To check for unused tracepoints (tracepoints that are defined but never
> > > +# called), run with:
> > > +#
> > > +# make UT=1
> > > +#
> > > +# Each unused tracepoints can take up to 5KB of memory in the running kernel.
> > > +# It is best to remove any that are not used.
> > > +
> > > +ifeq ("$(origin UT)", "command line")
> > > + WARN_ON_UNUSED_TRACEPOINTS := $(UT)
> > > +endif
> > > +
> > > +export WARN_ON_UNUSED_TRACEPOINTS
> >
> > Is there a special reason why you chose to introduce a new command-line
> > variable instead of extending KBUILD_EXTRA_WARN / W ?
>
> Honestly, I didn't think about using KBUILD_EXTRA_WARN. I also want this
> option to go away after we remove the current unused tracepoints so that
> any new ones will always cause a warning.
>
> The only reason not to make it always warn is because I don't want to add
> warnings for the existing code. I'm working on having outreachy projects to
> remove the currently unused tracepoints. Once that is done, then this
> option is going to go away and the build will always warn on unused
> tracepoints.
>
> I thought it might be easier to remove it without any issues if it's a new
> command line that goes away in the future.
>
> Looking at EXTRA_WARN, it appears to be for basic issues with the code and
> adds new C compiler warning flags. This isn't exactly the same.
>
> If you think it makes sense to extend EXTRA_WARN, I can still go ahead and
> do that.
thanks for clarification! For completeness: KBUILD_EXTRA_WARN is also
used for non-C related checks (cp. scripts/misc-check).
I somehow missed that UT= shall exist temporarily only - if this is
still the plan, I don't see a strong reason to put to much work into
integration in KBUILD_EXTRA_WARN.
Kind regards
Nicolas
^ permalink raw reply [flat|nested] 15+ messages in thread
end of thread, other threads:[~2025-10-21 21:21 UTC | newest]
Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-10-15 20:38 [PATCH v9 0/4] tracepoints: Add warnings for unused tracepoints and trace events Steven Rostedt
2025-10-15 20:38 ` [PATCH v9 1/4] sorttable: Move ELF parsing into scripts/elf-parse.[ch] Steven Rostedt
2025-10-15 20:38 ` [PATCH v9 2/4] tracing: Add a tracepoint verification check at build time Steven Rostedt
2025-10-15 23:12 ` Nathan Chancellor
2025-10-15 23:14 ` Steven Rostedt
2025-10-17 20:15 ` Nicolas Schier
2025-10-21 19:47 ` Steven Rostedt
2025-10-21 21:21 ` Nicolas Schier
2025-10-15 20:38 ` [PATCH v9 3/4] tracepoint: Do not warn for unused event that is exported Steven Rostedt
2025-10-15 20:38 ` [PATCH v9 4/4] tracing: Add warnings for unused tracepoints for modules Steven Rostedt
2025-10-15 23:19 ` Nathan Chancellor
2025-10-17 20:22 ` Nicolas Schier
2025-10-21 19:48 ` Steven Rostedt
2025-10-21 19:57 ` Steven Rostedt
2025-10-16 10:54 ` kernel test robot
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).