From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 7119 invoked by alias); 23 Dec 2013 14:34:32 -0000 Mailing-List: contact systemtap-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Post: List-Help: , Sender: systemtap-owner@sourceware.org Received: (qmail 7110 invoked by uid 89); 23 Dec 2013 14:34:31 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.6 required=5.0 tests=BAYES_00,FREEMAIL_FROM,RCVD_IN_DNSWL_LOW,SPF_PASS autolearn=ham version=3.3.2 X-HELO: mail-qc0-f181.google.com Received: from mail-qc0-f181.google.com (HELO mail-qc0-f181.google.com) (209.85.216.181) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES128-SHA encrypted) ESMTPS; Mon, 23 Dec 2013 14:34:29 +0000 Received: by mail-qc0-f181.google.com with SMTP id e9so4817109qcy.26 for ; Mon, 23 Dec 2013 06:34:27 -0800 (PST) X-Received: by 10.224.80.4 with SMTP id r4mr42643105qak.69.1387809267609; Mon, 23 Dec 2013 06:34:27 -0800 (PST) Received: from zoo.ghostprotocols.net (177.207.140.17.dynamic.adsl.gvt.net.br. [177.207.140.17]) by mx.google.com with ESMTPSA id r5sm30765988qaj.13.2013.12.23.06.34.23 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 23 Dec 2013 06:34:26 -0800 (PST) Received: by zoo.ghostprotocols.net (Postfix, from userid 1000) id 8E1FA1E10DC; Mon, 23 Dec 2013 11:34:28 -0300 (BRT) Date: Mon, 23 Dec 2013 14:34:00 -0000 From: Arnaldo Carvalho de Melo To: Masami Hiramatsu Cc: Ingo Molnar , Peter Zijlstra , Srikar Dronamraju , David Ahern , lkml , "Steven Rostedt (Red Hat)" , Oleg Nesterov , "David A. Long" , systemtap@sourceware.org, yrl.pp-manager.tt@hitachi.com, Namhyung Kim Subject: Re: [PATCH -tip 2/3] perf-probe: Support dwarf on uprobe events Message-ID: <20131223143428.GG28878@ghostprotocols.net> References: <20131220100255.7169.19384.stgit@kbuild-fedora.novalocal> <20131220100259.7169.57512.stgit@kbuild-fedora.novalocal> <20131220180154.GB28878@ghostprotocols.net> <52B75C04.6000404@hitachi.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <52B75C04.6000404@hitachi.com> X-Url: http://acmel.wordpress.com User-Agent: Mutt/1.5.21 (2010-09-15) X-SW-Source: 2013-q4/txt/msg00491.txt.bz2 Em Mon, Dec 23, 2013 at 06:39:16AM +0900, Masami Hiramatsu escreveu: > (2013/12/21 3:01), Arnaldo Carvalho de Melo wrote: > > Em Fri, Dec 20, 2013 at 10:02:59AM +0000, Masami Hiramatsu escreveu: > >> Support dwarf(debuginfo) based operations for uprobe events. > >> With this change, perf probe can analyze debuginfo of user > >> application binary to set up new uprobe event. > >> This allows perf-probe --add/--line works with -x option. > >> (Actually, --vars has already accepted -x option) > > > > Can you provide an example? > > > > OK, here is the examples from 0/3. :) Pleasn readnthis message: http://lkml.kernel.org/r/20131218141125.GT21999@twins.programming.kicks-ass.net It is unrelated to this code being discussed in this thread, but provides another request for having better patch descriptions and to have relevant discussion in the corresponding patch, not just on "0/N". > Or, should I better put this into the patch description too? Sure thing, please! > For example) > - Shows the probe-able lines of the given function The above line would be more clear as: "The following command shows the probe-able lines of a given user space function, something that so far was only available in the 'perf probe' tool for kernel space functions:" - Arnaldo > ---- > # ./perf probe -x perf --line map__load > > 0 int map__load(struct map *map, symbol_filter_t filter) > 1 { > 2 const char *name = map->dso->long_name; > int nr; > > 5 if (dso__loaded(map->dso, map->type)) > 6 return 0; > > 8 nr = dso__load(map->dso, map, filter); > 9 if (nr < 0) { > 10 if (map->dso->has_build_id) { > ---- > > - Shows the available variables of the given line > ---- > # ./perf probe -x perf --vars map__load:8 > Available variables at map__load:8 > @ > char* name > struct map* map > symbol_filter_t filter > @ > char* name > symbol_filter_t filter > @ > char* name > symbol_filter_t filter > @ > char* name > struct map* map > symbol_filter_t filter > ---- > > - Set a probe with available vars on the given line > ---- > # ./perf probe -x perf --add 'map__load:8 $vars' > > Added new events: > probe_perf:map__load (on map__load:8 with $vars) > probe_perf:map__load_1 (on map__load:8 with $vars) > probe_perf:map__load_2 (on map__load:8 with $vars) > probe_perf:map__load_3 (on map__load:8 with $vars) > > You can now use it in all perf tools, such as: > > perf record -e probe_perf:map__load_3 -aR sleep 1 > ---- > > > Showing output from commands when new features are implemented can speed > > up the process of having it used :-) > > > > - Arnaldo > > > >> Signed-off-by: Masami Hiramatsu > >> --- > >> tools/perf/builtin-probe.c | 2 > >> tools/perf/util/probe-event.c | 230 +++++++++++++++++++++++++++-------------- > >> 2 files changed, 155 insertions(+), 77 deletions(-) > >> > >> diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c > >> index b40d064..7fc566a 100644 > >> --- a/tools/perf/builtin-probe.c > >> +++ b/tools/perf/builtin-probe.c > >> @@ -420,7 +420,7 @@ int cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused) > >> } > >> > >> #ifdef HAVE_DWARF_SUPPORT > >> - if (params.show_lines && !params.uprobes) { > >> + if (params.show_lines) { > >> if (params.mod_events) { > >> pr_err(" Error: Don't use --line with" > >> " --add/--del.\n"); > >> diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c > >> index 05be5de..e27cecb 100644 > >> --- a/tools/perf/util/probe-event.c > >> +++ b/tools/perf/util/probe-event.c > >> @@ -186,6 +186,90 @@ static int init_user_exec(void) > >> return ret; > >> } > >> > >> +static const char *__target_symbol; > >> +static struct symbol *__result_sym; > >> + > >> +static int filter_target_symbol(struct map *map __maybe_unused, > >> + struct symbol *sym) > >> +{ > >> + if (strcmp(__target_symbol, sym->name) == 0) { > >> + __result_sym = sym; > >> + return 0; > >> + } > >> + return 1; > >> +} > >> + > >> +/* Find the offset of the symbol in the executable binary */ > >> +static int find_symbol_offset(const char *exec, const char *function, > >> + unsigned long *offs) > >> +{ > >> + struct symbol *sym; > >> + struct map *map = NULL; > >> + int ret = -EINVAL; > >> + > >> + if (!offs) > >> + return -EINVAL; > >> + > >> + map = dso__new_map(exec); > >> + if (!map) { > >> + pr_warning("Cannot find appropriate DSO for %s.\n", exec); > >> + goto out; > >> + } > >> + pr_debug("Search %s in %s\n", function, exec); > >> + __target_symbol = function; > >> + __result_sym = NULL; > >> + if (map__load(map, filter_target_symbol)) { > >> + pr_err("Failed to find %s in %s.\n", function, exec); > >> + goto out; > >> + } > >> + sym = __result_sym; > >> + if (!sym) { > >> + pr_warning("Cannot find %s in DSO %s\n", function, exec); > >> + goto out; > >> + } > >> + > >> + *offs = (map->start > sym->start) ? map->start : 0; > >> + *offs += sym->start + map->pgoff; > >> + ret = 0; > >> +out: > >> + if (map) { > >> + dso__delete(map->dso); > >> + map__delete(map); > >> + } > >> + return ret; > >> +} > >> + > >> +static int convert_exec_to_group(const char *exec, char **result) > >> +{ > >> + char *ptr1, *ptr2, *exec_copy; > >> + char buf[64]; > >> + int ret; > >> + > >> + exec_copy = strdup(exec); > >> + if (!exec_copy) > >> + return -ENOMEM; > >> + > >> + ptr1 = basename(exec_copy); > >> + if (!ptr1) { > >> + ret = -EINVAL; > >> + goto out; > >> + } > >> + > >> + ptr2 = strpbrk(ptr1, "-._"); > >> + if (ptr2) > >> + *ptr2 = '\0'; > >> + ret = e_snprintf(buf, 64, "%s_%s", PERFPROBE_GROUP, ptr1); > >> + if (ret < 0) > >> + goto out; > >> + > >> + *result = strdup(buf); > >> + ret = *result ? 0 : -ENOMEM; > >> + > >> +out: > >> + free(exec_copy); > >> + return ret; > >> +} > >> + > >> static int convert_to_perf_probe_point(struct probe_trace_point *tp, > >> struct perf_probe_point *pp) > >> { > >> @@ -261,6 +345,45 @@ static int kprobe_convert_to_perf_probe(struct probe_trace_point *tp, > >> return 0; > >> } > >> > >> +static int add_exec_to_probe_trace_events(struct probe_trace_event *tevs, > >> + int ntevs, const char *exec, > >> + const char *group) > >> +{ > >> + int i, ret = 0; > >> + unsigned long offset; > >> + char buf[32]; > >> + > >> + if (!exec) > >> + return 0; > >> + > >> + for (i = 0; i < ntevs && ret >= 0; i++) { > >> + /* Get proper offset */ > >> + ret = find_symbol_offset(exec, tevs[i].point.symbol, &offset); > >> + if (ret < 0) > >> + break; > >> + offset += tevs[i].point.offset; > >> + tevs[i].point.offset = 0; > >> + free(tevs[i].point.symbol); > >> + ret = e_snprintf(buf, 32, "0x%lx", offset); > >> + if (ret < 0) > >> + break; > >> + tevs[i].point.module = strdup(exec); > >> + tevs[i].point.symbol = strdup(buf); > >> + if (!tevs[i].point.symbol || !tevs[i].point.module) { > >> + ret = -ENOMEM; > >> + break; > >> + } > >> + /* Replace group name if not given */ > >> + if (!group) { > >> + free(tevs[i].group); > >> + ret = convert_exec_to_group(exec, &tevs[i].group); > >> + } > >> + tevs[i].uprobes = true; > >> + } > >> + > >> + return ret; > >> +} > >> + > >> static int add_module_to_probe_trace_events(struct probe_trace_event *tevs, > >> int ntevs, const char *module) > >> { > >> @@ -305,15 +428,6 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev, > >> struct debuginfo *dinfo; > >> int ntevs, ret = 0; > >> > >> - if (pev->uprobes) { > >> - if (need_dwarf) { > >> - pr_warning("Debuginfo-analysis is not yet supported" > >> - " with -x/--exec option.\n"); > >> - return -ENOSYS; > >> - } > >> - return convert_name_to_addr(pev, target); > >> - } > >> - > >> dinfo = open_debuginfo(target); > >> > >> if (!dinfo) { > >> @@ -332,9 +446,14 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev, > >> > >> if (ntevs > 0) { /* Succeeded to find trace events */ > >> pr_debug("find %d probe_trace_events.\n", ntevs); > >> - if (target) > >> - ret = add_module_to_probe_trace_events(*tevs, ntevs, > >> - target); > >> + if (target) { > >> + if (pev->uprobes) > >> + ret = add_exec_to_probe_trace_events(*tevs, > >> + ntevs, target, pev->group); > >> + else > >> + ret = add_module_to_probe_trace_events(*tevs, > >> + ntevs, target); > >> + } > >> return ret < 0 ? ret : ntevs; > >> } > >> > >> @@ -654,9 +773,6 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev, > >> return -ENOSYS; > >> } > >> > >> - if (pev->uprobes) > >> - return convert_name_to_addr(pev, target); > >> - > >> return 0; > >> } > >> > >> @@ -1916,11 +2032,26 @@ static int convert_to_probe_trace_events(struct perf_probe_event *pev, > >> int ret = 0, i; > >> struct probe_trace_event *tev; > >> > >> + if (pev->uprobes) > >> + if (!pev->group) { > >> + ret = convert_exec_to_group(target, &pev->group); > >> + if (ret != 0) { > >> + pr_warning("Failed to make group name.\n"); > >> + return ret; > >> + } > >> + } > >> + > >> /* Convert perf_probe_event with debuginfo */ > >> ret = try_to_find_probe_trace_events(pev, tevs, max_tevs, target); > >> if (ret != 0) > >> return ret; /* Found in debuginfo or got an error */ > >> > >> + if (pev->uprobes) { > >> + ret = convert_name_to_addr(pev, target); > >> + if (ret < 0) > >> + return ret; > >> + } > >> + > >> /* Allocate trace event buffer */ > >> tev = *tevs = zalloc(sizeof(struct probe_trace_event)); > >> if (tev == NULL) > >> @@ -2279,88 +2410,35 @@ int show_available_funcs(const char *target, struct strfilter *_filter, > >> static int convert_name_to_addr(struct perf_probe_event *pev, const char *exec) > >> { > >> struct perf_probe_point *pp = &pev->point; > >> - struct symbol *sym; > >> - struct map *map = NULL; > >> - char *function = NULL; > >> int ret = -EINVAL; > >> - unsigned long long vaddr = 0; > >> + unsigned long vaddr = 0; > >> > >> if (!pp->function) { > >> pr_warning("No function specified for uprobes"); > >> goto out; > >> } > >> > >> - function = strdup(pp->function); > >> - if (!function) { > >> - pr_warning("Failed to allocate memory by strdup.\n"); > >> - ret = -ENOMEM; > >> - goto out; > >> - } > >> - > >> - map = dso__new_map(exec); > >> - if (!map) { > >> - pr_warning("Cannot find appropriate DSO for %s.\n", exec); > >> - goto out; > >> - } > >> - available_func_filter = strfilter__new(function, NULL); > >> - if (map__load(map, filter_available_functions)) { > >> - pr_err("Failed to load map.\n"); > >> - goto out; > >> - } > >> - > >> - sym = map__find_symbol_by_name(map, function, NULL); > >> - if (!sym) { > >> - pr_warning("Cannot find %s in DSO %s\n", function, exec); > >> + ret = find_symbol_offset(exec, pp->function, &vaddr); > >> + if (ret < 0) > >> goto out; > >> - } > >> > >> - if (map->start > sym->start) > >> - vaddr = map->start; > >> - vaddr += sym->start + pp->offset + map->pgoff; > >> + vaddr += pp->offset; > >> pp->offset = 0; > >> > >> if (!pev->event) { > >> - pev->event = function; > >> - function = NULL; > >> - } > >> - if (!pev->group) { > >> - char *ptr1, *ptr2, *exec_copy; > >> - > >> - pev->group = zalloc(sizeof(char *) * 64); > >> - exec_copy = strdup(exec); > >> - if (!exec_copy) { > >> - ret = -ENOMEM; > >> - pr_warning("Failed to copy exec string.\n"); > >> - goto out; > >> - } > >> + pev->event = pp->function; > >> + } else > >> + free(pp->function); > >> > >> - ptr1 = strdup(basename(exec_copy)); > >> - if (ptr1) { > >> - ptr2 = strpbrk(ptr1, "-._"); > >> - if (ptr2) > >> - *ptr2 = '\0'; > >> - e_snprintf(pev->group, 64, "%s_%s", PERFPROBE_GROUP, > >> - ptr1); > >> - free(ptr1); > >> - } > >> - free(exec_copy); > >> - } > >> - free(pp->function); > >> pp->function = zalloc(sizeof(char *) * MAX_PROBE_ARGS); > >> if (!pp->function) { > >> ret = -ENOMEM; > >> pr_warning("Failed to allocate memory by zalloc.\n"); > >> goto out; > >> } > >> - e_snprintf(pp->function, MAX_PROBE_ARGS, "0x%llx", vaddr); > >> + e_snprintf(pp->function, MAX_PROBE_ARGS, "0x%lx", vaddr); > >> ret = 0; > >> > >> out: > >> - if (map) { > >> - dso__delete(map->dso); > >> - map__delete(map); > >> - } > >> - if (function) > >> - free(function); > >> return ret; > >> } > >> > > > > > -- > Masami HIRAMATSU > IT Management Research Dept. Linux Technology Center > Hitachi, Ltd., Yokohama Research Laboratory > E-mail: masami.hiramatsu.pt@hitachi.com >