Re: [PATCH v2 4/5] perf-probe: Find versioned symbols from map

From: Thomas-Mich Richter
Date: Fri Dec 08 2017 - 06:09:02 EST


On 12/07/2017 08:21 AM, Masami Hiramatsu wrote:
> Find versioned symbols correctly from map.
> 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@xxxxxxxxxxx in /usr/lib64/libc-2.25.so)
> =====
>
> Signed-off-by: Masami Hiramatsu <mhiramat@xxxxxxxxxx>
> ---
> tools/perf/arch/powerpc/util/sym-handling.c | 8 ++++++++
> tools/perf/util/probe-event.c | 16 +++++++++++++++-
> tools/perf/util/symbol.c | 5 +++++
> tools/perf/util/symbol.h | 1 +
> 4 files changed, 29 insertions(+), 1 deletion(-)
>
> diff --git a/tools/perf/arch/powerpc/util/sym-handling.c b/tools/perf/arch/powerpc/util/sym-handling.c
> index 9c4e23d8c8ce..a3613c8d97b6 100644
> --- a/tools/perf/arch/powerpc/util/sym-handling.c
> +++ b/tools/perf/arch/powerpc/util/sym-handling.c
> @@ -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++;
> + return name;
> +}
> #endif
>
> #if defined(_CALL_ELF) && _CALL_ELF == 2
> diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
> index 959c4d2ef455..94acc5846e2a 100644
> --- a/tools/perf/util/probe-event.c
> +++ b/tools/perf/util/probe-event.c
> @@ -2801,16 +2801,30 @@ 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);

The weak default function arch__normalize_symbol_name() simply returns
its parameter, so norm can be a NULL ptr when parameter sym->name is a
NULL pointer.
However when sym->name is a NULL pointer (or can be one) then the
Powerpc version of arch__normalize_symbol_name() dereferences a NULL
ptr (by checking the symbol's first character is a '.').

> + if (!norm)
> + continue;
> +
> + /* We don't care about default symbol or not */
> + ver = strchr(norm, '@');
> + if (ver) {
> + buf = strndup(norm, ver - norm);
> + norm = buf;

if strndup() returns a NULL pointer (due to lack of memory)
then variable norm is a NULL ptr and strglobmatch() --> __match_glob()
derefenences that NULL pointer (1. parameter).

> + }
> + if (strglobmatch(norm, name)) {
> found++;
> if (syms && found < probe_conf.max_probes)
> syms[found - 1] = sym;
> }
> + if (buf)
> + zfree(&buf);
> }
>
> return found;
> diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
> index 1b67a8639dfe..cc065d4bfafc 100644
> --- a/tools/perf/util/symbol.c
> +++ b/tools/perf/util/symbol.c
> @@ -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);
> diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
> index a4f0075b4e5c..0563f33c1eb3 100644
> --- a/tools/perf/util/symbol.h
> +++ b/tools/perf/util/symbol.h
> @@ -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
>
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-perf-users" in
> the body of a message to majordomo@xxxxxxxxxxxxxxx
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>


--
Thomas Richter, Dept 3303, IBM LTC Boeblingen Germany
--
Vorsitzende des Aufsichtsrats: Martina Koederitz
GeschÃftsfÃhrung: Dirk Wittkopp
Sitz der Gesellschaft: BÃblingen / Registergericht: Amtsgericht Stuttgart, HRB 243294