All of lore.kernel.org
 help / color / mirror / Atom feed
From: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
To: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: Ingo Molnar <mingo@kernel.org>,
	Srikar Dronamraju <srikar@linux.vnet.ibm.com>,
	David Ahern <dsahern@gmail.com>,
	lkml <linux-kernel@vger.kernel.org>,
	"Steven Rostedt (Red Hat)" <rostedt@goodmis.org>,
	Oleg Nesterov <oleg@redhat.com>,
	"David A. Long" <dave.long@linaro.org>,
	systemtap@sourceware.org, yrl.pp-manager.tt@hitachi.com,
	Namhyung Kim <namhyung@kernel.org>
Subject: Re: [PATCH -tip  2/3] perf-probe: Support dwarf on uprobe events
Date: Fri, 20 Dec 2013 15:01:54 -0300	[thread overview]
Message-ID: <20131220180154.GB28878@ghostprotocols.net> (raw)
In-Reply-To: <20131220100259.7169.57512.stgit@kbuild-fedora.novalocal>

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?

Showing output from commands when new features are implemented can speed
up the process of having it used :-)

- Arnaldo
 
> Signed-off-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
> ---
>  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;
>  }
> 

  reply	other threads:[~2013-12-20 18:02 UTC|newest]

Thread overview: 22+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-12-20 10:02 [PATCH -tip 0/3] perf-probe: Dwarf support for uprobes Masami Hiramatsu
2013-12-20 10:02 ` [PATCH -tip 1/3] [CLEANUP] perf-probe: Expand given path to absolute path Masami Hiramatsu
2013-12-20 18:00   ` Arnaldo Carvalho de Melo
2013-12-22 21:35     ` Masami Hiramatsu
2013-12-23 14:28       ` Arnaldo Carvalho de Melo
2013-12-24  6:51         ` Masami Hiramatsu
2013-12-23  6:17   ` Namhyung Kim
2013-12-23 10:46     ` Masami Hiramatsu
2013-12-20 10:02 ` [PATCH -tip 2/3] perf-probe: Support dwarf on uprobe events Masami Hiramatsu
2013-12-20 18:01   ` Arnaldo Carvalho de Melo [this message]
2013-12-22 21:39     ` Masami Hiramatsu
2013-12-23 14:34       ` Arnaldo Carvalho de Melo
2013-12-24  1:03         ` Masami Hiramatsu
2013-12-20 10:03 ` [PATCH -tip 3/3] perf-probe: Use the actual address as a hint for uprobes Masami Hiramatsu
2013-12-20 18:03   ` Arnaldo Carvalho de Melo
2013-12-22 21:54     ` Masami Hiramatsu
2013-12-23  7:46       ` Namhyung Kim
2013-12-23 10:50         ` Masami Hiramatsu
2013-12-24  7:54           ` Namhyung Kim
2013-12-24  8:27             ` Masami Hiramatsu
2013-12-24  8:46               ` Namhyung Kim
2013-12-24 15:03                 ` Masami Hiramatsu

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20131220180154.GB28878@ghostprotocols.net \
    --to=acme@ghostprotocols.net \
    --cc=dave.long@linaro.org \
    --cc=dsahern@gmail.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=masami.hiramatsu.pt@hitachi.com \
    --cc=mingo@kernel.org \
    --cc=namhyung@kernel.org \
    --cc=oleg@redhat.com \
    --cc=rostedt@goodmis.org \
    --cc=srikar@linux.vnet.ibm.com \
    --cc=systemtap@sourceware.org \
    --cc=yrl.pp-manager.tt@hitachi.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.