All of lore.kernel.org
 help / color / mirror / Atom feed
From: Holger Freyther <automatic+kernel@freyther.de>
To: linux-kernel@vger.kernel.org
Cc: Holger Hans Peter Freyther <holgar+kernel@google.com>
Subject: [RFC 4/6] perf probe: Show variables for C++ functions
Date: Mon, 14 May 2018 12:19:38 +0800	[thread overview]
Message-ID: <20180514041940.96126-5-automatic+kernel@freyther.de> (raw)
In-Reply-To: <20180514041940.96126-1-automatic+kernel@freyther.de>

From: Holger Hans Peter Freyther <holgar+kernel@google.com>

The demangled C++ function name contains spaces and using the generic
argc_split would split the function in the middle. Create a separate
version that counts the number of opening and closing '<', '>' for
templated functions.

$ ./perf probe -x ./foo -V "std::vector<int, std::allocator<int> >::at"
Available variables at std::vector<int, std::allocator<int> >::at
        @<at+0>
                size_type       __n
                vector<int, std::allocator<int> >*      this

Signed-off-by: Holger Hans Peter Freyther <holgar+kernel@google.com>
---
 tools/perf/util/probe-event.c | 20 +++++++++++++--
 tools/perf/util/string.c      | 57 +++++++++++++++++++++++++++++++++++++++++++
 tools/perf/util/string2.h     |  1 +
 3 files changed, 76 insertions(+), 2 deletions(-)

diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index 39a2d47..97d6b6a 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -1407,6 +1407,22 @@ static int parse_perf_probe_event_name(char **arg, struct perf_probe_event *pev)
 	return 0;
 }
 
+/* Split the function name from  @file, :line, %return but be C++ aware */
+static char *split_func_name(char *arg)
+{
+	char *ptr = arg;
+
+	while ((ptr = strpbrk_esc(ptr, ";:+@%"))) {
+		if (ptr[0] == ':' && ptr[1] == ':') {
+			ptr += 2;
+			continue;
+		}
+		return ptr;
+	}
+
+	return NULL;
+}
+
 /* Parse probepoint definition. */
 static int parse_perf_probe_point(char *arg, struct perf_probe_event *pev)
 {
@@ -1486,7 +1502,7 @@ static int parse_perf_probe_point(char *arg, struct perf_probe_event *pev)
 			file_spec = true;
 	}
 
-	ptr = strpbrk_esc(arg, ";:+@%");
+	ptr = split_func_name(arg);
 	if (ptr) {
 		nc = *ptr;
 		*ptr++ = '\0';
@@ -1726,7 +1742,7 @@ int parse_perf_probe_command(const char *cmd, struct perf_probe_event *pev)
 	char **argv;
 	int argc, i, ret = 0;
 
-	argv = argv_split(cmd, &argc);
+	argv = argv_split_cxx(cmd, &argc);
 	if (!argv) {
 		pr_debug("Failed to split arguments.\n");
 		return -ENOMEM;
diff --git a/tools/perf/util/string.c b/tools/perf/util/string.c
index d8bfd0c..bb96fe2 100644
--- a/tools/perf/util/string.c
+++ b/tools/perf/util/string.c
@@ -80,6 +80,23 @@ static const char *skip_arg(const char *cp)
 	return cp;
 }
 
+static const char *skip_arg_cxx(const char *cp)
+{
+	int tmpl = 0;
+
+	while (*cp) {
+		if (tmpl == 0 && isspace(*cp))
+			break;
+		if (*cp == '<')
+			tmpl += 1;
+		if (*cp == '>')
+			tmpl -= 1;
+		cp++;
+	}
+
+	return cp;
+}
+
 static int count_argc(const char *str)
 {
 	int count = 0;
@@ -163,6 +180,46 @@ char **argv_split(const char *str, int *argcp)
 	return NULL;
 }
 
+char **argv_split_cxx(const char *str, int *argcp)
+{
+	int argc = count_argc(str);
+	char **argv = calloc(argc + 1, sizeof(*argv));
+	char **argvp;
+
+	if (argv == NULL)
+		goto out;
+
+	argvp = argv;
+
+	while (*str) {
+		str = skip_sep(str);
+
+		if (*str) {
+			const char *p = str;
+			char *t;
+
+			str = skip_arg_cxx(str);
+
+			t = strndup(p, str-p);
+			if (t == NULL)
+				goto fail;
+			*argvp++ = t;
+		}
+	}
+	if (argcp)
+		*argcp = argvp - argv;
+	*argvp = NULL;
+
+out:
+	return argv;
+
+fail:
+	if (argcp)
+		*argcp = 0;
+	argv_free(argv);
+	return NULL;
+}
+
 /* Character class matching */
 static bool __match_charclass(const char *pat, char c, const char **npat)
 {
diff --git a/tools/perf/util/string2.h b/tools/perf/util/string2.h
index 4c68a09..d32de6f 100644
--- a/tools/perf/util/string2.h
+++ b/tools/perf/util/string2.h
@@ -8,6 +8,7 @@
 
 s64 perf_atoll(const char *str);
 char **argv_split(const char *str, int *argcp);
+char **argv_split_cxx(const char *str, int *argvcp);
 void argv_free(char **argv);
 bool strglobmatch(const char *str, const char *pat);
 bool strglobmatch_nocase(const char *str, const char *pat);
-- 
2.7.4

  parent reply	other threads:[~2018-05-14  4:28 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-05-14  4:19 [RFC 0/6] perf probe: Attempt to improve C++ probing Holger Freyther
2018-05-14  4:19 ` [RFC 1/6] perf probe: Do not exclude mangled C++ funcs Holger Freyther
2018-05-14  4:19 ` [RFC 2/6] perf probe: Parse linerange for C++ functions Holger Freyther
2018-05-14  4:19 ` [RFC 3/6] perf probe: Make listing of C++ functions work Holger Freyther
2018-05-14  4:19 ` Holger Freyther [this message]
2018-05-14  4:19 ` [RFC 5/6] perf probe: Make listing of variables work for C++ functions Holger Freyther
2018-05-14  4:19 ` [RFC 6/6] perf probe: Make it possible to add a C++ uprobe Holger Freyther
2018-05-14 13:08 ` [RFC 0/6] perf probe: Attempt to improve C++ probing Masami Hiramatsu
2018-05-14 13:31 ` Masami Hiramatsu
2018-05-15 14:10   ` Arnaldo Carvalho de Melo

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=20180514041940.96126-5-automatic+kernel@freyther.de \
    --to=automatic+kernel@freyther.de \
    --cc=holgar+kernel@google.com \
    --cc=linux-kernel@vger.kernel.org \
    /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.