All of lore.kernel.org
 help / color / mirror / Atom feed
From: "acme@kernel.org" <acme@kernel.org>
To: "Wangnan (F)" <wangnan0@huawei.com>
Cc: "平松雅巳 / HIRAMATU,MASAMI" <masami.hiramatsu.pt@hitachi.com>,
	"mingo@redhat.com" <mingo@redhat.com>,
	"namhyung@kernel.org" <namhyung@kernel.org>,
	"pi3orama@163.com" <pi3orama@163.com>,
	"linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org>
Subject: Re: [PATCH 2/2] perf probe: Support probing at absolute address
Date: Wed, 26 Aug 2015 10:02:23 -0300	[thread overview]
Message-ID: <20150826130223.GN19203@kernel.org> (raw)
In-Reply-To: <55DD269A.7030408@huawei.com>

Em Wed, Aug 26, 2015 at 10:38:18AM +0800, Wangnan (F) escreveu:
> 
> On 2015/8/26 8:02, 平松雅巳 / HIRAMATU,MASAMI wrote:
> >>From: Wang Nan [mailto:wangnan0@huawei.com]
> >>
> >>It should be useful to allow 'perf probe' probe at absolute offset of
> >>a target. For example, when (u)probing at a instruction of a shared
> >>object in a embedded system where debuginfo is not avaliable but we
> >>know the offset of that instruction by manually digging.
> >>
> >>This patch enables following perf probe command syntax:
> >>
> >>  # perf probe +0xffffffff811e6615
> >>
> >>And
> >>
> >>  # perf probe /lib/x86_64-linux-gnu/libc-2.19.so +0xeb860
> >Why do we need "+" for the absolute address?
> >It seems that we can do it if we find that the given probe point
> >starts with "0x".
> >
> >Thanks,
> 
> I will change 2/2 as you suggection.
> 
> However, we can only ensure that in kernel side symbol never leading
> with '0x'. Although I don't think symbol leading with 0x is useful,
> it is still possible for a userspace program compiled and linked by
> a language other than C produces such symbol. '+' helps us separate
> address and function name semantically, make us don't rely on assumption
> on function names. If in future we do meet '0x' symbols, I think we still
> need the '+' syntax back. But we can do it at that time.

Agreed, I also think that using '+' is better, but will not dwell on
this so as to make progress :-)

- Arnaldo
 
> Thank you.
> 
> 
> >>In the above example, we don't need a anchor symbol, so it is possible
> >>to compute absolute addresses using other methods and then use
> >>'perf probe' to create the probing points.
> >>
> >>Signed-off-by: Wang Nan <wangnan0@huawei.com>
> >>Cc: Arnaldo Carvalho de Melo <acme@kernel.org>
> >>Cc: Ingo Molnar <mingo@redhat.com>
> >>Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
> >>Cc: Namhyung Kim <namhyung@kernel.org>
> >>---
> >>  tools/perf/util/probe-event.c  | 144 +++++++++++++++++++++++++++++++++++++----
> >>  tools/perf/util/probe-event.h  |   3 +
> >>  tools/perf/util/probe-finder.c |  21 +-----
> >>  3 files changed, 138 insertions(+), 30 deletions(-)
> >>
> >>diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
> >>index 6c7e538..59de69a4 100644
> >>--- a/tools/perf/util/probe-event.c
> >>+++ b/tools/perf/util/probe-event.c
> >>@@ -1194,9 +1194,13 @@ static int parse_perf_probe_point(char *arg, struct perf_probe_event *pev)
> >>  		*ptr++ = '\0';
> >>  	}
> >>
> >>-	tmp = strdup(arg);
> >>-	if (tmp == NULL)
> >>-		return -ENOMEM;
> >>+	if (arg[0] == '\0')
> >>+		tmp = NULL;
> >>+	else {
> >>+		tmp = strdup(arg);
> >>+		if (tmp == NULL)
> >>+			return -ENOMEM;
> >>+	}
> >>
> >>  	if (file_spec)
> >>  		pp->file = tmp;
> >>@@ -1283,11 +1287,6 @@ static int parse_perf_probe_point(char *arg, struct perf_probe_event *pev)
> >>  		return -EINVAL;
> >>  	}
> >>
> >>-	if (pp->offset && !pp->function) {
> >>-		semantic_error("Offset requires an entry function.\n");
> >>-		return -EINVAL;
> >>-	}
> >>-
> >>  	if (pp->retprobe && !pp->function) {
> >>  		semantic_error("Return probe requires an entry function.\n");
> >>  		return -EINVAL;
> >>@@ -1299,6 +1298,11 @@ static int parse_perf_probe_point(char *arg, struct perf_probe_event *pev)
> >>  		return -EINVAL;
> >>  	}
> >>
> >>+	if (!pp->function && !pp->offset && !pp->file) {
> >>+		semantic_error("Absolute address should not be zero.\n");
> >>+		return -EINVAL;
> >>+	}
> >>+
> >>  	pr_debug("symbol:%s file:%s line:%d offset:%lu return:%d lazy:%s\n",
> >>  		 pp->function, pp->file, pp->line, pp->offset, pp->retprobe,
> >>  		 pp->lazy_line);
> >>@@ -1609,7 +1613,7 @@ error:
> >>  static char *synthesize_perf_probe_point(struct perf_probe_point *pp)
> >>  {
> >>  	char *buf, *tmp;
> >>-	char offs[32] = "", line[32] = "", file[32] = "";
> >>+	char offs[32] = "", line[32] = "", file[32] = "", addr[32] = "";
> >>  	int ret, len;
> >>
> >>  	buf = zalloc(MAX_CMDLEN);
> >>@@ -1622,6 +1626,11 @@ static char *synthesize_perf_probe_point(struct perf_probe_point *pp)
> >>  		if (ret <= 0)
> >>  			goto error;
> >>  	}
> >>+	if (!pp->function) {
> >>+		ret = e_snprintf(addr, 32, "0x%lx", pp->offset);
> >>+		if (ret <= 0)
> >>+			goto error;
> >>+	}
> >>  	if (pp->line) {
> >>  		ret = e_snprintf(line, 32, ":%d", pp->line);
> >>  		if (ret <= 0)
> >>@@ -1639,9 +1648,11 @@ static char *synthesize_perf_probe_point(struct perf_probe_point *pp)
> >>  			goto error;
> >>  	}
> >>
> >>-	if (pp->function)
> >>-		ret = e_snprintf(buf, MAX_CMDLEN, "%s%s%s%s%s", pp->function,
> >>-				 offs, pp->retprobe ? "%return" : "", line,
> >>+	if (pp->function || pp->offset)
> >>+		ret = e_snprintf(buf, MAX_CMDLEN, "%s%s%s%s%s",
> >>+				 pp->function ? : addr,
> >>+				 pp->function ? offs : "",
> >>+				 pp->retprobe ? "%return" : "", line,
> >>  				 file);
> >>  	else
> >>  		ret = e_snprintf(buf, MAX_CMDLEN, "%s%s", file, line);
> >>@@ -1786,6 +1797,11 @@ char *synthesize_probe_trace_command(struct probe_trace_event *tev)
> >>  	if (tev->uprobes)
> >>  		ret = e_snprintf(buf + len, MAX_CMDLEN - len, "%s:0x%lx",
> >>  				 tp->module, tp->address);
> >>+	else if (tp->symbol[0] == '0' && tp->symbol[1] == 'x')
> >>+		/* Absolute address. See try_to_find_absolute_address() */
> >>+		ret = e_snprintf(buf + len, MAX_CMDLEN - len, "%s%s0x%lx",
> >>+				 tp->module ?: "", tp->module ? ":" : "",
> >>+				 tp->address);
> >>  	else
> >>  		ret = e_snprintf(buf + len, MAX_CMDLEN - len, "%s%s%s+%lu",
> >>  				 tp->module ?: "", tp->module ? ":" : "",
> >>@@ -2572,6 +2588,87 @@ err_out:
> >>  	goto out;
> >>  }
> >>
> >>+static int try_to_find_absolute_address(struct perf_probe_event *pev,
> >>+					struct probe_trace_event **tevs)
> >>+{
> >>+	struct perf_probe_point *pp = &pev->point;
> >>+	struct probe_trace_event *tev;
> >>+	struct probe_trace_point *tp;
> >>+	int i, err;
> >>+
> >>+	if (perf_probe_event_need_dwarf(pev) || pev->point.function)
> >>+		return -EINVAL;
> >>+
> >>+	/*
> >>+	 * This is 'perf probe /lib/libc.so +0xabcd'. Try to probe at
> >>+	 * absolute address.
> >>+	 *
> >>+	 * Only one tev can be generated by this.
> >>+	 */
> >>+	*tevs = zalloc(sizeof(*tev));
> >>+	if (!*tevs)
> >>+		return -ENOMEM;
> >>+
> >>+	tev = *tevs;
> >>+	tp = &tev->point;
> >>+
> >>+	/*
> >>+	 * Don't use tp->offset, use address directly, because
> >>+	 * in synthesize_probe_trace_command() address cannot be
> >>+	 * zero.
> >>+	 */
> >>+	tp->address = pev->point.offset;
> >>+	tp->retprobe = pp->retprobe;
> >>+	tev->uprobes = pev->uprobes;
> >>+
> >>+	err = -ENOMEM;
> >>+	/* Give it a '0x' leading symbol name */
> >>+	if (asprintf(&tp->symbol, "0x%lx", tp->address) < 0)
> >>+		goto errout;
> >>+
> >>+	/* For kprobe, check range */
> >>+	if ((!tev->uprobes) &&
> >>+	    (kprobe_warn_out_range(tev->point.symbol,
> >>+				   tev->point.address))) {
> >>+		err = -EACCES;
> >>+		goto errout;
> >>+	}
> >>+
> >>+	if (asprintf(&tp->realname, "abs_%lx", tp->address) < 0)
> >>+		goto errout;
> >>+
> >>+	if (pev->target) {
> >>+		tp->module = strdup(pev->target);
> >>+		if (!tp->module)
> >>+			goto errout;
> >>+	}
> >>+
> >>+	if (tev->group) {
> >>+		tev->group = strdup(pev->group);
> >>+		if (!tev->group)
> >>+			goto errout;
> >>+	}
> >>+
> >>+	if (pev->event) {
> >>+		tev->event = strdup(pev->event);
> >>+		if (!tev->event)
> >>+			goto errout;
> >>+	}
> >>+
> >>+	tev->nargs = pev->nargs;
> >>+	for (i = 0; i < tev->nargs; i++)
> >>+		copy_to_probe_trace_arg(&tev->args[i], &pev->args[i]);
> >>+
> >>+	return 1;
> >>+
> >>+errout:
> >>+	if (*tevs) {
> >>+		clear_probe_trace_events(*tevs, 1);
> >>+		*tevs = NULL;
> >>+	}
> >>+	return err;
> >>+}
> >>+
> >>  bool __weak arch__prefers_symtab(void) { return false; }
> >>
> >>  static int convert_to_probe_trace_events(struct perf_probe_event *pev,
> >>@@ -2588,6 +2685,10 @@ static int convert_to_probe_trace_events(struct perf_probe_event *pev,
> >>  		}
> >>  	}
> >>
> >>+	ret = try_to_find_absolute_address(pev, tevs);
> >>+	if (ret > 0)
> >>+		return ret;
> >>+
> >>  	if (arch__prefers_symtab() && !perf_probe_event_need_dwarf(pev)) {
> >>  		ret = find_probe_trace_events_from_map(pev, tevs);
> >>  		if (ret > 0)
> >>@@ -2758,3 +2859,22 @@ end:
> >>  	return ret;
> >>  }
> >>
> >>+int copy_to_probe_trace_arg(struct probe_trace_arg *tvar,
> >>+			    struct perf_probe_arg *pvar)
> >>+{
> >>+	tvar->value = strdup(pvar->var);
> >>+	if (tvar->value == NULL)
> >>+		return -ENOMEM;
> >>+	if (pvar->type) {
> >>+		tvar->type = strdup(pvar->type);
> >>+		if (tvar->type == NULL)
> >>+			return -ENOMEM;
> >>+	}
> >>+	if (pvar->name) {
> >>+		tvar->name = strdup(pvar->name);
> >>+		if (tvar->name == NULL)
> >>+			return -ENOMEM;
> >>+	} else
> >>+		tvar->name = NULL;
> >>+	return 0;
> >>+}
> >>diff --git a/tools/perf/util/probe-event.h b/tools/perf/util/probe-event.h
> >>index 83ee95e..174a3cf 100644
> >>--- a/tools/perf/util/probe-event.h
> >>+++ b/tools/perf/util/probe-event.h
> >>@@ -156,4 +156,7 @@ int e_snprintf(char *str, size_t size, const char *format, ...)
> >>  /* Maximum index number of event-name postfix */
> >>  #define MAX_EVENT_INDEX	1024
> >>
> >>+int copy_to_probe_trace_arg(struct probe_trace_arg *tvar,
> >>+			    struct perf_probe_arg *pvar);
> >>+
> >>  #endif /*_PROBE_EVENT_H */
> >>diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
> >>index 7b80f8c..29c43c068 100644
> >>--- a/tools/perf/util/probe-finder.c
> >>+++ b/tools/perf/util/probe-finder.c
> >>@@ -553,24 +553,9 @@ static int find_variable(Dwarf_Die *sc_die, struct probe_finder *pf)
> >>  	char buf[32], *ptr;
> >>  	int ret = 0;
> >>
> >>-	if (!is_c_varname(pf->pvar->var)) {
> >>-		/* Copy raw parameters */
> >>-		pf->tvar->value = strdup(pf->pvar->var);
> >>-		if (pf->tvar->value == NULL)
> >>-			return -ENOMEM;
> >>-		if (pf->pvar->type) {
> >>-			pf->tvar->type = strdup(pf->pvar->type);
> >>-			if (pf->tvar->type == NULL)
> >>-				return -ENOMEM;
> >>-		}
> >>-		if (pf->pvar->name) {
> >>-			pf->tvar->name = strdup(pf->pvar->name);
> >>-			if (pf->tvar->name == NULL)
> >>-				return -ENOMEM;
> >>-		} else
> >>-			pf->tvar->name = NULL;
> >>-		return 0;
> >>-	}
> >>+	/* Copy raw parameters */
> >>+	if (!is_c_varname(pf->pvar->var))
> >>+		return copy_to_probe_trace_arg(pf->tvar, pf->pvar);
> >>
> >>  	if (pf->pvar->name)
> >>  		pf->tvar->name = strdup(pf->pvar->name);
> >>--
> >>1.8.3.4
> 

  parent reply	other threads:[~2015-08-26 13:02 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-08-25 13:27 [PATCH 1/2] perf probe: Prevent segfault when reading probe point with absolute address Wang Nan
2015-08-25 13:27 ` [PATCH 2/2] perf probe: Support probing at " Wang Nan
2015-08-26  0:02   ` 平松雅巳 / HIRAMATU,MASAMI
2015-08-26  2:38     ` Wangnan (F)
2015-08-26  9:02       ` 平松雅巳 / HIRAMATU,MASAMI
2015-08-26 13:02       ` acme [this message]
2015-08-26 13:19         ` Wangnan (F)
2015-08-26 13:32           ` Arnaldo Carvalho de Melo
2015-08-26 13:00     ` acme
2015-08-25 15:32 ` [PATCH 1/2] perf probe: Prevent segfault when reading probe point with " Arnaldo Carvalho de Melo
2015-08-26  0:08 ` 平松雅巳 / HIRAMATU,MASAMI
2015-08-28  6:40 ` [tip:perf/core] " tip-bot for Wang Nan

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=20150826130223.GN19203@kernel.org \
    --to=acme@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=masami.hiramatsu.pt@hitachi.com \
    --cc=mingo@redhat.com \
    --cc=namhyung@kernel.org \
    --cc=pi3orama@163.com \
    --cc=wangnan0@huawei.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.