]> www.infradead.org Git - users/dwmw2/linux.git/commitdiff
perf probe: Replace unacceptable characters when generating event name
authorMasami Hiramatsu (Google) <mhiramat@kernel.org>
Wed, 13 Nov 2024 00:21:21 +0000 (09:21 +0900)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Tue, 10 Dec 2024 18:41:10 +0000 (15:41 -0300)
Replace unacceptable characters with '_' when generating event name from
the probing function name.

This is not for a C program. For the a C program, it will continue to
remove suffixes.

Note that this language checking depends on the debuginfo. So without
the debuginfo, perf probe will always replaces unacceptable characters
with '_'.

For example.

  $ ./perf probe -x cro3 -D \"cro3::cmd::servo::run_show\"
  p:probe_cro3/cro3_cmd_servo_run_show /work/cro3/target/x86_64-unknown-linux-gnu/debug/cro3:0x197530

  $ ./perf probe -x /work/go/example/outyet/main -D 'main.(*Server).poll'
  p:probe_main/main_Server_poll /work/go/example/outyet/main:0x353040

Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Alexander Lobakin <aleksander.lobakin@intel.com>
Cc: Dima Kogan <dima@secretsauce.net>
Cc: Ian Rogers <irogers@google.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Przemek Kitszel <przemyslaw.kitszel@intel.com>
Link: https://lore.kernel.org/r/173145728160.2747044.18089011235495186810.stgit@mhiramat.roam.corp.google.com
[ Removed some extra tabs in the new struct fields ]
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
tools/perf/util/probe-event.c
tools/perf/util/probe-event.h
tools/perf/util/probe-finder.c
tools/perf/util/probe-finder.h

index 6d51a4c98ad7c29e79157db974dd5c281919b254..aa4a3aee677d0c85280e1c94ff51c2f34cac7351 100644 (file)
@@ -2775,7 +2775,7 @@ int show_perf_probe_events(struct strfilter *filter)
 
 static int get_new_event_name(char *buf, size_t len, const char *base,
                              struct strlist *namelist, bool ret_event,
-                             bool allow_suffix)
+                             bool allow_suffix, bool not_C_symname)
 {
        int i, ret;
        char *p, *nbase;
@@ -2786,10 +2786,24 @@ static int get_new_event_name(char *buf, size_t len, const char *base,
        if (!nbase)
                return -ENOMEM;
 
-       /* Cut off the dot suffixes (e.g. .const, .isra) and version suffixes */
-       p = strpbrk(nbase, ".@");
-       if (p && p != nbase)
-               *p = '\0';
+       if (not_C_symname) {
+               /* Replace non-alnum with '_' */
+               char *s, *d;
+
+               s = d = nbase;
+               do {
+                       if (*s && !isalnum(*s)) {
+                               if (d != nbase && *(d - 1) != '_')
+                                       *d++ = '_';
+                       } else
+                               *d++ = *s;
+               } while (*s++);
+       } else {
+               /* Cut off the dot suffixes (e.g. .const, .isra) and version suffixes */
+               p = strpbrk(nbase, ".@");
+               if (p && p != nbase)
+                       *p = '\0';
+       }
 
        /* Try no suffix number */
        ret = e_snprintf(buf, len, "%s%s", nbase, ret_event ? "__return" : "");
@@ -2884,6 +2898,7 @@ static int probe_trace_event__set_name(struct probe_trace_event *tev,
                                       bool allow_suffix)
 {
        const char *event, *group;
+       bool not_C_symname = true;
        char buf[MAX_EVENT_NAME_LEN];
        int ret;
 
@@ -2898,8 +2913,10 @@ static int probe_trace_event__set_name(struct probe_trace_event *tev,
                        (strncmp(pev->point.function, "0x", 2) != 0) &&
                        !strisglob(pev->point.function))
                        event = pev->point.function;
-               else
+               else {
                        event = tev->point.realname;
+                       not_C_symname = !is_known_C_lang(tev->lang);
+               }
        }
        if (pev->group && !pev->sdt)
                group = pev->group;
@@ -2916,7 +2933,8 @@ static int probe_trace_event__set_name(struct probe_trace_event *tev,
 
        /* Get an unused new event name */
        ret = get_new_event_name(buf, sizeof(buf), event, namelist,
-                                tev->point.retprobe, allow_suffix);
+                                tev->point.retprobe, allow_suffix,
+                                not_C_symname);
        if (ret < 0)
                return ret;
 
index 61a5f4ff4e9c6fd4a1f3d3e7612a84ab2d5edfa7..71905ede0207585374f04139688e618dcc0ca67e 100644 (file)
@@ -58,6 +58,7 @@ struct probe_trace_event {
        char                            *group; /* Group name */
        struct probe_trace_point        point;  /* Trace point */
        int                             nargs;  /* Number of args */
+       int                             lang;   /* Dwarf language code */
        bool                            uprobes;        /* uprobes only */
        struct probe_trace_arg          *args;  /* Arguments */
 };
index 7f2ee0cb43ca488ece89853fd723dd8540b19f6a..1e769b68da37fc09a90db4e2bb2fe4c75ce967d7 100644 (file)
 /* Kprobe tracer basic type is up to u64 */
 #define MAX_BASIC_TYPE_BITS    64
 
+bool is_known_C_lang(int lang)
+{
+       switch (lang) {
+       case DW_LANG_C89:
+       case DW_LANG_C:
+       case DW_LANG_C99:
+       case DW_LANG_C11:
+               return true;
+       default:
+               return false;
+       }
+}
+
 /*
  * Probe finder related functions
  */
@@ -1270,6 +1283,8 @@ static int add_probe_trace_event(Dwarf_Die *sc_die, struct probe_finder *pf)
                goto end;
        }
 
+       tev->lang = dwarf_srclang(dwarf_diecu(sc_die, &pf->cu_die, NULL, NULL));
+
        pr_debug("Probe point found: %s+%lu\n", tev->point.symbol,
                 tev->point.offset);
 
index be7b46ea24608441ab6a9a2e361b8d68e1c976fa..dcf6cc1e1cbeaaba27f2a7d732a9b5db14912e6c 100644 (file)
@@ -26,6 +26,9 @@ static inline int is_c_varname(const char *name)
 #include "dwarf-aux.h"
 #include "debuginfo.h"
 
+/* Check the language code is known C */
+bool is_known_C_lang(int lang);
+
 /* Find probe_trace_events specified by perf_probe_event from debuginfo */
 int debuginfo__find_trace_events(struct debuginfo *dbg,
                                 struct perf_probe_event *pev,
@@ -103,6 +106,8 @@ struct line_finder {
        int                     found;
 };
 
+#else
+#define is_known_C_lang(lang) (false)
 #endif /* HAVE_LIBDW_SUPPORT */
 
 #endif /*_PROBE_FINDER_H */