From: Masami Hiramatsu (Google) <mhiramat@kernel.org>
Function profiler shows the hit count of each function using its symbol
name. However, there are some same-name local symbols, which we can not
distinguish.
To solve this issue, this introduces an option to show the symbols
in "_text+OFFSET" format. This can avoid exposing the random shift of
KASLR. The functions in modules are shown as "MODNAME+OFFSET" where the
offset is from ".text".
E.g. for the kernel text symbols, specify vmlinux and the output to
addr2line, you can find the actual function and source info;
$ addr2line -fie vmlinux _text+3078208
__balance_callbacks
kernel/sched/core.c:5064
for modules, specify the module file and .text+OFFSET;
$ addr2line -fie samples/trace_events/trace-events-sample.ko .text+8224
do_simple_thread_func
samples/trace_events/trace-events-sample.c:23
Suggested-by: Steven Rostedt (Google) <rostedt@goodmis.org>
Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
---
Changes in v2:
- Define a dummy TRACE_ITER_PROF_TEXT_OFFSET if CONFIG_FUNCTION_PROFILER=n.
---
kernel/trace/ftrace.c | 26 +++++++++++++++++++++++++-
kernel/trace/trace.c | 5 +++--
kernel/trace/trace.h | 11 ++++++++++-
3 files changed, 38 insertions(+), 4 deletions(-)
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
index 00b76d450a89..d4802bb93793 100644
--- a/kernel/trace/ftrace.c
+++ b/kernel/trace/ftrace.c
@@ -534,7 +534,9 @@ static int function_stat_headers(struct seq_file *m)
static int function_stat_show(struct seq_file *m, void *v)
{
+ struct trace_array *tr = trace_get_global_array();
struct ftrace_profile *rec = v;
+ const char *refsymbol = NULL;
char str[KSYM_SYMBOL_LEN];
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
static struct trace_seq s;
@@ -554,7 +556,29 @@ static int function_stat_show(struct seq_file *m, void *v)
return 0;
#endif
- kallsyms_lookup(rec->ip, NULL, NULL, NULL, str);
+ if (tr->trace_flags & TRACE_ITER_PROF_TEXT_OFFSET) {
+ long offset;
+
+ if (core_kernel_text(rec->ip)) {
+ refsymbol = "_text";
+ offset = rec->ip - (unsigned long)_text;
+ } else {
+ struct module *mod;
+
+ guard(rcu)();
+ mod = __module_text_address(rec->ip);
+ if (mod) {
+ refsymbol = mod->name;
+ /* Calculate offset from module's text entry address. */
+ offset = rec->ip - (unsigned long)mod->mem[MOD_TEXT].base;
+ }
+ }
+ if (refsymbol)
+ snprintf(str, sizeof(str), " %s%+ld", refsymbol, offset);
+ }
+ if (!refsymbol)
+ kallsyms_lookup(rec->ip, NULL, NULL, NULL, str);
+
seq_printf(m, " %-30.30s %10lu", str, rec->counter);
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index 2b3fe0a30c7d..9f254c290bcd 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -522,7 +522,8 @@ EXPORT_SYMBOL_GPL(unregister_ftrace_export);
/* trace_options that are only supported by global_trace */
#define TOP_LEVEL_TRACE_FLAGS (TRACE_ITER_PRINTK | \
- TRACE_ITER_PRINTK_MSGONLY | TRACE_ITER_RECORD_CMD)
+ TRACE_ITER_PRINTK_MSGONLY | TRACE_ITER_RECORD_CMD | \
+ TRACE_ITER_PROF_TEXT_OFFSET)
/* trace_flags that are default zero for instances */
#define ZEROED_TRACE_FLAGS \
@@ -11106,7 +11107,7 @@ __init static int tracer_alloc_buffers(void)
#ifdef CONFIG_FUNCTION_TRACER
/* Used to set module cached ftrace filtering at boot up */
-__init struct trace_array *trace_get_global_array(void)
+struct trace_array *trace_get_global_array(void)
{
return &global_trace;
}
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h
index caec534072e7..3d034dd753c6 100644
--- a/kernel/trace/trace.h
+++ b/kernel/trace/trace.h
@@ -1353,6 +1353,14 @@ extern int trace_get_user(struct trace_parser *parser, const char __user *ubuf,
# define STACK_FLAGS
#endif
+#ifdef CONFIG_FUNCTION_PROFILER
+# define PROFILER_FLAGS \
+ C(PROF_TEXT_OFFSET, "prof-text-offset"),
+#else
+# define PROFILER_FLAGS
+# define TRACE_ITER_PROF_TEXT_OFFSET 0UL
+#endif
+
/*
* trace_iterator_flags is an enumeration that defines bit
* positions into trace_flags that controls the output.
@@ -1391,7 +1399,8 @@ extern int trace_get_user(struct trace_parser *parser, const char __user *ubuf,
FUNCTION_FLAGS \
FGRAPH_FLAGS \
STACK_FLAGS \
- BRANCH_FLAGS
+ BRANCH_FLAGS \
+ PROFILER_FLAGS
/*
* By defining C, we can make TRACE_FLAGS a list of bit names
Hi Masami,
kernel test robot noticed the following build errors:
[auto build test ERROR on trace/for-next]
[also build test ERROR on linus/master v6.18-rc1 next-20251017]
[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/Masami-Hiramatsu-Google/tracing-Allow-tracer-to-add-more-than-32-options/20251018-004104
base: https://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace for-next
patch link: https://lore.kernel.org/r/176071775059.175601.3827350589430991963.stgit%40devnote2
patch subject: [PATCH v4 2/2] tracing: Add an option to show symbols in _text+offset for function profiler
config: x86_64-rhel-9.4 (https://download.01.org/0day-ci/archive/20251018/202510181934.DYd8mdHX-lkp@intel.com/config)
compiler: gcc-14 (Debian 14.2.0-19) 14.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20251018/202510181934.DYd8mdHX-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/202510181934.DYd8mdHX-lkp@intel.com/
All errors (new ones prefixed by >>):
In file included from kernel/trace/trace_output.h:6,
from kernel/trace/ftrace.c:45:
>> kernel/trace/trace.h:1434:34: error: enumerator value outside the range of underlying type
1434 | #define C(a, b) TRACE_ITER_##a = (1 << TRACE_ITER_##a##_BIT)
| ^
kernel/trace/trace.h:1369:17: note: in expansion of macro 'C'
1369 | C(PROF_TEXT_OFFSET, "prof-text-offset"),
| ^
kernel/trace/trace.h:1414:17: note: in expansion of macro 'PROFILER_FLAGS'
1414 | PROFILER_FLAGS
| ^~~~~~~~~~~~~~
kernel/trace/trace.h:1436:40: note: in expansion of macro 'TRACE_FLAGS'
1436 | enum trace_iterator_flags : uint64_t { TRACE_FLAGS };
| ^~~~~~~~~~~
--
In file included from kernel/trace/trace_probe.h:31,
from kernel/trace/bpf_trace.c:35:
>> kernel/trace/trace.h:1434:34: error: enumerator value outside the range of underlying type
1434 | #define C(a, b) TRACE_ITER_##a = (1 << TRACE_ITER_##a##_BIT)
| ^
kernel/trace/trace.h:1369:17: note: in expansion of macro 'C'
1369 | C(PROF_TEXT_OFFSET, "prof-text-offset"),
| ^
kernel/trace/trace.h:1414:17: note: in expansion of macro 'PROFILER_FLAGS'
1414 | PROFILER_FLAGS
| ^~~~~~~~~~~~~~
kernel/trace/trace.h:1436:40: note: in expansion of macro 'TRACE_FLAGS'
1436 | enum trace_iterator_flags : uint64_t { TRACE_FLAGS };
| ^~~~~~~~~~~
kernel/trace/bpf_trace.c: In function '____bpf_trace_printk':
kernel/trace/bpf_trace.c:378:9: warning: function '____bpf_trace_printk' might be a candidate for 'gnu_printf' format attribute [-Wsuggest-attribute=format]
378 | ret = bstr_printf(data.buf, MAX_BPRINTF_BUF, fmt, data.bin_args);
| ^~~
kernel/trace/bpf_trace.c: In function '____bpf_trace_vprintk':
kernel/trace/bpf_trace.c:434:9: warning: function '____bpf_trace_vprintk' might be a candidate for 'gnu_printf' format attribute [-Wsuggest-attribute=format]
434 | ret = bstr_printf(data.buf, MAX_BPRINTF_BUF, fmt, data.bin_args);
| ^~~
kernel/trace/bpf_trace.c: In function '____bpf_seq_printf':
kernel/trace/bpf_trace.c:476:9: warning: function '____bpf_seq_printf' might be a candidate for 'gnu_printf' format attribute [-Wsuggest-attribute=format]
476 | seq_bprintf(m, fmt, data.bin_args);
| ^~~~~~~~~~~
--
In file included from kernel/trace/rv/rv.h:9,
from kernel/trace/rv/rv.c:151:
>> kernel/trace/rv/../trace.h:1434:34: error: enumerator value outside the range of underlying type
1434 | #define C(a, b) TRACE_ITER_##a = (1 << TRACE_ITER_##a##_BIT)
| ^
kernel/trace/rv/../trace.h:1369:17: note: in expansion of macro 'C'
1369 | C(PROF_TEXT_OFFSET, "prof-text-offset"),
| ^
kernel/trace/rv/../trace.h:1414:17: note: in expansion of macro 'PROFILER_FLAGS'
1414 | PROFILER_FLAGS
| ^~~~~~~~~~~~~~
kernel/trace/rv/../trace.h:1436:40: note: in expansion of macro 'TRACE_FLAGS'
1436 | enum trace_iterator_flags : uint64_t { TRACE_FLAGS };
| ^~~~~~~~~~~
vim +1434 kernel/trace/trace.h
a3418a364ec3c8 Steven Rostedt (Red Hat 2015-09-29 1428)
a3418a364ec3c8 Steven Rostedt (Red Hat 2015-09-29 1429) /*
a3418a364ec3c8 Steven Rostedt (Red Hat 2015-09-29 1430) * By redefining C, we can make TRACE_FLAGS a list of masks that
a3418a364ec3c8 Steven Rostedt (Red Hat 2015-09-29 1431) * use the bits as defined above.
a3418a364ec3c8 Steven Rostedt (Red Hat 2015-09-29 1432) */
a3418a364ec3c8 Steven Rostedt (Red Hat 2015-09-29 1433) #undef C
a3418a364ec3c8 Steven Rostedt (Red Hat 2015-09-29 @1434) #define C(a, b) TRACE_ITER_##a = (1 << TRACE_ITER_##a##_BIT)
a3418a364ec3c8 Steven Rostedt (Red Hat 2015-09-29 1435)
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
© 2016 - 2026 Red Hat, Inc.