]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/commitdiff
perf probe: Find versioned symbols from map
authorMasami Hiramatsu <mhiramat@kernel.org>
Fri, 8 Dec 2017 16:28:12 +0000 (01:28 +0900)
committerThadeu Lima de Souza Cascardo <cascardo@canonical.com>
Thu, 12 Apr 2018 13:03:08 +0000 (10:03 -0300)
BugLink: http://bugs.launchpad.net/bugs/1763366
[ Upstream commit 4b3a2716dd785fabb9f6ac80c1d53cb29a88169d ]

Commit d80406453ad4 ("perf symbols: Allow user probes on versioned
symbols") allows user to find default versioned symbols (with "@@") in
map. However, it did not enable normal versioned symbol (with "@") for
perf-probe.  E.g.

  =====
  # ./perf probe -x /lib64/libc-2.25.so malloc_get_state
  Failed to find symbol malloc_get_state in /usr/lib64/libc-2.25.so
    Error: Failed to add events.
  =====

This solves above issue by improving perf-probe symbol search function,
as below.

  =====
  # ./perf probe -x /lib64/libc-2.25.so malloc_get_state
  Added new event:
    probe_libc:malloc_get_state (on malloc_get_state in /usr/lib64/libc-2.25.so)

  You can now use it in all perf tools, such as:

  perf record -e probe_libc:malloc_get_state -aR sleep 1

  # ./perf probe -l
    probe_libc:malloc_get_state (on malloc_get_state@GLIBC_2.2.5 in /usr/lib64/libc-2.25.so)
  =====

Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
Reviewed-by: Thomas Richter <tmricht@linux.vnet.ibm.com>
Acked-by: Ravi Bangoria <ravi.bangoria@linux.vnet.ibm.com>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Paul Clarke <pc@us.ibm.com>
Cc: bhargavb <bhargavaramudu@gmail.com>
Cc: linux-rt-users@vger.kernel.org
Link: http://lkml.kernel.org/r/151275049269.24652.1639103455496216255.stgit@devbox
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: Sasha Levin <alexander.levin@microsoft.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Thadeu Lima de Souza Cascardo <cascardo@canonical.com>
tools/perf/arch/powerpc/util/sym-handling.c
tools/perf/util/probe-event.c
tools/perf/util/symbol.c
tools/perf/util/symbol.h

index 9c4e23d8c8cedbf0c6db4c9c13129b197be7938e..53d83d7e6a096a4d49a0b6f0cbfafc15a27866af 100644 (file)
@@ -64,6 +64,14 @@ int arch__compare_symbol_names_n(const char *namea, const char *nameb,
 
        return strncmp(namea, nameb, n);
 }
+
+const char *arch__normalize_symbol_name(const char *name)
+{
+       /* Skip over initial dot */
+       if (name && *name == '.')
+               name++;
+       return name;
+}
 #endif
 
 #if defined(_CALL_ELF) && _CALL_ELF == 2
index b7aaf9b2294d81224993d220c896a2da43fda308..c3cd3488fee79c485ff8a9cfb5b1034c07119376 100644 (file)
@@ -2792,16 +2792,32 @@ static int find_probe_functions(struct map *map, char *name,
        int found = 0;
        struct symbol *sym;
        struct rb_node *tmp;
+       const char *norm, *ver;
+       char *buf = NULL;
 
        if (map__load(map) < 0)
                return 0;
 
        map__for_each_symbol(map, sym, tmp) {
-               if (strglobmatch(sym->name, name)) {
+               norm = arch__normalize_symbol_name(sym->name);
+               if (!norm)
+                       continue;
+
+               /* We don't care about default symbol or not */
+               ver = strchr(norm, '@');
+               if (ver) {
+                       buf = strndup(norm, ver - norm);
+                       if (!buf)
+                               return -ENOMEM;
+                       norm = buf;
+               }
+               if (strglobmatch(norm, name)) {
                        found++;
                        if (syms && found < probe_conf.max_probes)
                                syms[found - 1] = sym;
                }
+               if (buf)
+                       zfree(&buf);
        }
 
        return found;
@@ -2847,7 +2863,7 @@ static int find_probe_trace_events_from_map(struct perf_probe_event *pev,
         * same name but different addresses, this lists all the symbols.
         */
        num_matched_functions = find_probe_functions(map, pp->function, syms);
-       if (num_matched_functions == 0) {
+       if (num_matched_functions <= 0) {
                pr_err("Failed to find symbol %s in %s\n", pp->function,
                        pev->target ? : "kernel");
                ret = -ENOENT;
index 1b67a8639dfeb0e96b794434c9686c9b9aa96190..cc065d4bfafcff9704aecb96b8af462cf7182778 100644 (file)
@@ -94,6 +94,11 @@ static int prefix_underscores_count(const char *str)
        return tail - str;
 }
 
+const char * __weak arch__normalize_symbol_name(const char *name)
+{
+       return name;
+}
+
 int __weak arch__compare_symbol_names(const char *namea, const char *nameb)
 {
        return strcmp(namea, nameb);
index a4f0075b4e5cf285d955ddd1c4a91a4193737768..0563f33c1eb30802a8b609f4612059e099b675c0 100644 (file)
@@ -349,6 +349,7 @@ bool elf__needs_adjust_symbols(GElf_Ehdr ehdr);
 void arch__sym_update(struct symbol *s, GElf_Sym *sym);
 #endif
 
+const char *arch__normalize_symbol_name(const char *name);
 #define SYMBOL_A 0
 #define SYMBOL_B 1