lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20131223143428.GG28878@ghostprotocols.net>
Date:	Mon, 23 Dec 2013 11:34:28 -0300
From:	Arnaldo Carvalho de Melo <acme@...stprotocols.net>
To:	Masami Hiramatsu <masami.hiramatsu.pt@...achi.com>
Cc:	Ingo Molnar <mingo@...nel.org>,
	Peter Zijlstra <peterz@...radead.org>,
	Srikar Dronamraju <srikar@...ux.vnet.ibm.com>,
	David Ahern <dsahern@...il.com>,
	lkml <linux-kernel@...r.kernel.org>,
	"Steven Rostedt (Red Hat)" <rostedt@...dmis.org>,
	Oleg Nesterov <oleg@...hat.com>,
	"David A. Long" <dave.long@...aro.org>, systemtap@...rceware.org,
	yrl.pp-manager.tt@...achi.com, Namhyung Kim <namhyung@...nel.org>
Subject: Re: [PATCH -tip  2/3] perf-probe: Support dwarf on uprobe events

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
> <map__load@...me/fedora/ksrc/linux-2.6/tools/perf/util/map.c:0>
>       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
>         @<map__load+96>
>                 char*   name
>                 struct map*     map
>                 symbol_filter_t filter
>         @<map__find_symbol+112>
>                 char*   name
>                 symbol_filter_t filter
>         @<map__find_symbol_by_name+136>
>                 char*   name
>                 symbol_filter_t filter
>         @<map_groups__find_symbol_by_name+176>
>                 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 <masami.hiramatsu.pt@...achi.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;
> >>  }
> >>
> > 
> 
> 
> -- 
> Masami HIRAMATSU
> IT Management Research Dept. Linux Technology Center
> Hitachi, Ltd., Yokohama Research Laboratory
> E-mail: masami.hiramatsu.pt@...achi.com
> 
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ