]> Gentwo Git Trees - linux/.git/commitdiff
tracing: Add an option to show symbols in _text+offset for function profiler
authorMasami Hiramatsu (Google) <mhiramat@kernel.org>
Fri, 31 Oct 2025 02:46:20 +0000 (11:46 +0900)
committerMasami Hiramatsu (Google) <mhiramat@kernel.org>
Tue, 4 Nov 2025 12:44:18 +0000 (21:44 +0900)
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

Link: https://lore.kernel.org/all/176187878064.994619.8878296550240416558.stgit@devnote2/
Suggested-by: Steven Rostedt (Google) <rostedt@goodmis.org>
Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
kernel/trace/ftrace.c
kernel/trace/trace.c
kernel/trace/trace.h

index 42bd2ba68a821935871f549889fe073ef7ed11ab..ab601cd9638b44fb10c267af4d2e0c008a381bdc 100644 (file)
@@ -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)) {
+               unsigned 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+%#lx", 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
index 14e8703a6a53a8270af23eb7c8ded9d9eee692e5..e5f186daf00701a40fbef761efbc47f1335e7c45 100644 (file)
@@ -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 \
@@ -11291,7 +11292,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;
 }
index 8c99136619bf3dd1551d8c86d73c0fd76966f829..7d8f4bd9facd0eea231fe1ff901dea08f382affc 100644 (file)
@@ -1359,6 +1359,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_BIT       -1
+#endif
+
 /*
  * trace_iterator_flags is an enumeration that defines bit
  * positions into trace_flags that controls the output.
@@ -1397,7 +1405,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