All of lore.kernel.org
 help / color / mirror / Atom feed
From: Alexis Berlemont <alexis.berlemont@gmail.com>
To: linux-kernel@vger.kernel.org
Cc: Alexis Berlemont <alexis.berlemont@gmail.com>,
	peterz@infradead.org, mingo@redhat.com, acme@kernel.org,
	alexander.shishkin@linux.intel.com
Subject: [PATCH v5 2/2] perf probe: add sdt probes arguments into the uprobe cmd string
Date: Wed, 14 Dec 2016 01:07:32 +0100	[thread overview]
Message-ID: <20161214000732.1710-3-alexis.berlemont@gmail.com> (raw)
In-Reply-To: <20161214000732.1710-1-alexis.berlemont@gmail.com>
In-Reply-To: <20161207122610.008da636793d38a39accf29b@kernel.org>

An sdt probe can be associated with arguments but they were not passed
to the user probe tracing interface (uprobe_events); this patch adapts
the sdt argument descriptors according to the uprobe input format.

As the uprobe parser does not support scaled address mode, perf will
skip arguments which cannot be adapted to the uprobe format.

Here are the results:

$ perf buildid-cache -v --add test_sdt
$ perf probe -x test_sdt sdt_libfoo:table_frob
$ perf probe -x test_sdt sdt_libfoo:table_diddle
$ perf record -e sdt_libfoo:table_frob -e sdt_libfoo:table_diddle test_sdt
$ perf script
test_sdt  ...   666.255678:   sdt_libfoo:table_frob: (4004d7) arg0=0 arg1=0
test_sdt  ...   666.255683: sdt_libfoo:table_diddle: (40051a) arg0=0 arg1=0
test_sdt  ...   666.255686:   sdt_libfoo:table_frob: (4004d7) arg0=1 arg1=2
test_sdt  ...   666.255689: sdt_libfoo:table_diddle: (40051a) arg0=3 arg1=4
test_sdt  ...   666.255692:   sdt_libfoo:table_frob: (4004d7) arg0=2 arg1=4
test_sdt  ...   666.255694: sdt_libfoo:table_diddle: (40051a) arg0=6 arg1=8

Signed-off-by: Alexis Berlemont <alexis.berlemont@gmail.com>
---
 tools/perf/arch/x86/util/perf_regs.c |  83 +++++++++++++++++
 tools/perf/util/perf_regs.c          |   6 ++
 tools/perf/util/perf_regs.h          |   6 ++
 tools/perf/util/probe-file.c         | 170 ++++++++++++++++++++++++++++++++++-
 4 files changed, 261 insertions(+), 4 deletions(-)

diff --git a/tools/perf/arch/x86/util/perf_regs.c b/tools/perf/arch/x86/util/perf_regs.c
index c5db14f..09a7f55 100644
--- a/tools/perf/arch/x86/util/perf_regs.c
+++ b/tools/perf/arch/x86/util/perf_regs.c
@@ -1,4 +1,7 @@
+#include <string.h>
+
 #include "../../perf.h"
+#include "../../util/util.h"
 #include "../../util/perf_regs.h"
 
 const struct sample_reg sample_reg_masks[] = {
@@ -26,3 +29,83 @@ const struct sample_reg sample_reg_masks[] = {
 #endif
 	SMPL_REG_END
 };
+
+struct sdt_name_reg {
+	const char *sdt_name;
+	const char *uprobe_name;
+};
+#define SDT_NAME_REG(n, m) {.sdt_name = "%" #n, .uprobe_name = "%" #m}
+#define SDT_NAME_REG_END {.sdt_name = NULL, .uprobe_name = NULL}
+
+static const struct sdt_name_reg sdt_reg_renamings[] = {
+	SDT_NAME_REG(eax, ax),
+	SDT_NAME_REG(rax, ax),
+	SDT_NAME_REG(ebx, bx),
+	SDT_NAME_REG(rbx, bx),
+	SDT_NAME_REG(ecx, cx),
+	SDT_NAME_REG(rcx, cx),
+	SDT_NAME_REG(edx, dx),
+	SDT_NAME_REG(rdx, dx),
+	SDT_NAME_REG(esi, si),
+	SDT_NAME_REG(rsi, si),
+	SDT_NAME_REG(edi, di),
+	SDT_NAME_REG(rdi, di),
+	SDT_NAME_REG(ebp, bp),
+	SDT_NAME_REG(rbp, bp),
+	SDT_NAME_REG_END,
+};
+
+int sdt_rename_register(char **pdesc, char *old_name)
+{
+	const struct sdt_name_reg *rnames = sdt_reg_renamings;
+	char *new_desc, *old_desc = *pdesc;
+	size_t prefix_len, sdt_len, uprobe_len, old_desc_len, offset;
+	int ret = -1;
+
+	while (ret != 0 && rnames->sdt_name != NULL) {
+		sdt_len = strlen(rnames->sdt_name);
+		ret = strncmp(old_name, rnames->sdt_name, sdt_len);
+		rnames += !!ret;
+	}
+
+	if (rnames->sdt_name == NULL)
+		return 0;
+
+	sdt_len = strlen(rnames->sdt_name);
+	uprobe_len = strlen(rnames->uprobe_name);
+	old_desc_len = strlen(old_desc) + 1;
+
+	new_desc = zalloc(old_desc_len + uprobe_len - sdt_len);
+	if (new_desc == NULL)
+		return -1;
+
+	/* Copy the chars before the register name (at least '%') */
+	prefix_len = old_name - old_desc;
+	memcpy(new_desc, old_desc, prefix_len);
+
+	/* Copy the new register name */
+	memcpy(new_desc + prefix_len, rnames->uprobe_name, uprobe_len);
+
+	/* Copy the chars after the register name (if need be) */
+	offset = prefix_len + sdt_len;
+	if (offset < old_desc_len) {
+		/*
+		 * The orginal register name can be suffixed by 'b',
+		 * 'w' or 'd' to indicate its size; so, we need to
+		 * skip this char if we met one.
+		 */
+		char sfx = old_desc[offset];
+
+		if (sfx == 'b' || sfx == 'w'  || sfx == 'd')
+			offset++;
+	}
+
+	if (offset < old_desc_len)
+		memcpy(new_desc + prefix_len + uprobe_len,
+			old_desc + offset, old_desc_len - offset);
+
+	free(old_desc);
+	*pdesc = new_desc;
+
+	return 0;
+}
diff --git a/tools/perf/util/perf_regs.c b/tools/perf/util/perf_regs.c
index c4023f2..a37e593 100644
--- a/tools/perf/util/perf_regs.c
+++ b/tools/perf/util/perf_regs.c
@@ -6,6 +6,12 @@ const struct sample_reg __weak sample_reg_masks[] = {
 	SMPL_REG_END
 };
 
+int __weak sdt_rename_register(char **pdesc __maybe_unused,
+			char *old_name __maybe_unused)
+{
+	return 0;
+}
+
 #ifdef HAVE_PERF_REGS_SUPPORT
 int perf_reg_value(u64 *valp, struct regs_dump *regs, int id)
 {
diff --git a/tools/perf/util/perf_regs.h b/tools/perf/util/perf_regs.h
index 679d6e4..7544a15 100644
--- a/tools/perf/util/perf_regs.h
+++ b/tools/perf/util/perf_regs.h
@@ -15,6 +15,12 @@ struct sample_reg {
 
 extern const struct sample_reg sample_reg_masks[];
 
+/*
+ * The table sdt_reg_renamings is used for adjusting gcc/gas-generated
+ * registers before filling the uprobe tracer interface.
+ */
+int sdt_rename_register(char **pdesc, char *old_name);
+
 #ifdef HAVE_PERF_REGS_SUPPORT
 #include <perf_regs.h>
 
diff --git a/tools/perf/util/probe-file.c b/tools/perf/util/probe-file.c
index 436b647..d8a169e 100644
--- a/tools/perf/util/probe-file.c
+++ b/tools/perf/util/probe-file.c
@@ -27,6 +27,7 @@
 #include "probe-event.h"
 #include "probe-file.h"
 #include "session.h"
+#include "perf_regs.h"
 
 #define MAX_CMDLEN 256
 
@@ -687,6 +688,166 @@ static unsigned long long sdt_note__get_addr(struct sdt_note *note)
 		 : (unsigned long long)note->addr.a64[0];
 }
 
+static const char * const type_to_suffix[] = {
+	":s64", "", "", "", ":s32", "", ":s16", ":s8",
+	"", ":u8", ":u16", "", ":u32", "", "", "", ":u64"
+};
+
+static int synthesize_sdt_probe_arg(struct strbuf *buf, int i, const char *arg)
+{
+	char *tmp, *desc = strdup(arg);
+	const char *prefix = "", *suffix = "";
+	int ret = -1;
+
+	if (desc == NULL) {
+		pr_debug4("Allocation error\n");
+		return ret;
+	}
+
+	tmp = strchr(desc, '@');
+	if (tmp) {
+		long type_idx;
+		/*
+		 * Isolate the string number and convert it into a
+		 * binary value; this will be an index to get suffix
+		 * of the uprobe name (defining the type)
+		 */
+		tmp[0] = '\0';
+		type_idx = strtol(desc, NULL, 10);
+		/* Check that the conversion went OK */
+		if (type_idx == LONG_MIN || type_idx == LONG_MAX) {
+			pr_debug4("Failed to parse sdt type\n");
+			goto error;
+		}
+		/* Check that the converted value is OK */
+		if (type_idx < -8 || type_idx > 8) {
+			pr_debug4("Failed to get a valid sdt type\n");
+			goto error;
+		}
+		suffix = type_to_suffix[type_idx + 8];
+		/* Get rid of the sdt prefix which is now useless */
+		tmp++;
+		memmove(desc, tmp, strlen(tmp) + 1);
+	}
+
+	/*
+	 * The uprobe tracer format does not support all the
+	 * addressing modes (notably: in x86 the scaled mode); so, we
+	 * detect ',' characters, if there is just one, there is no
+	 * use converting the sdt arg into a uprobe one.
+	 */
+	if (strchr(desc, ',')) {
+		pr_debug4("Skipping unsupported SDT argument; %s\n", desc);
+		goto out;
+	}
+
+	/*
+	 * If the argument addressing mode is indirect, we must check
+	 * a few things...
+	 */
+	tmp = strchr(desc, '(');
+	if (tmp) {
+		int j;
+
+		/*
+		 * ...if the addressing mode is indirect with a
+		 * positive offset (ex.: "1608(%ax)"), we need to add
+		 * a '+' prefix so as to be compliant with uprobe
+		 * format.
+		 */
+		if (desc[0] != '+' && desc[0] != '-')
+			prefix = "+";
+
+		/*
+		 * ...or if the addressing mode is indirect with a symbol
+		 * as offset, the argument will not be supported by
+		 * the uprobe tracer format; so, let's skip this one.
+		 */
+		for (j = 0; j < tmp - desc; j++) {
+			if (desc[j] != '+' && desc[j] != '-' &&
+				!isdigit(desc[j])) {
+				pr_debug4("Skipping unsupported SDT argument; "
+					"%s\n", desc);
+				goto out;
+			}
+		}
+	}
+
+	/*
+	 * The uprobe tracer format does not support constants; if we
+	 * find one in the current argument, let's skip the argument.
+	 */
+	if (strchr(desc, '$')) {
+		pr_debug4("Skipping unsupported SDT argument; %s\n", desc);
+		goto out;
+	}
+
+	/*
+	 * The uprobe parser does not support all gas register names;
+	 * so, we have to replace them (ex. for x86_64: %rax -> %ax);
+	 * the loop below looks for the register names (starting with
+	 * a '%' and tries to perform the needed renamings.
+	 */
+	tmp = strchr(desc, '%');
+	while (tmp) {
+		size_t offset = tmp - desc;
+
+		ret = sdt_rename_register(&desc, desc + offset);
+		if (ret < 0)
+			goto error;
+
+		/*
+		 * The desc pointer might have changed; so, let's not
+		 * try to reuse tmp for next lookup
+		 */
+		tmp = strchr(desc + offset + 1, '%');
+	}
+
+	if (strbuf_addf(buf, " arg%d=%s%s%s", i + 1, prefix, desc, suffix) < 0)
+		goto error;
+
+out:
+	ret = 0;
+error:
+	free(desc);
+	return ret;
+}
+
+static char *synthesize_sdt_probe_command(struct sdt_note *note,
+					const char *pathname,
+					const char *sdtgrp)
+{
+	struct strbuf buf;
+	char *ret = NULL, **args;
+	int i, args_count;
+
+	if (strbuf_init(&buf, 32) < 0)
+		return NULL;
+
+	if (strbuf_addf(&buf, "p:%s/%s %s:0x%llx",
+				sdtgrp, note->name, pathname,
+				sdt_note__get_addr(note)) < 0)
+		goto error;
+
+	if (!note->args)
+		goto out;
+
+	if (note->args) {
+		args = argv_split(note->args, &args_count);
+
+		for (i = 0; i < args_count; ++i) {
+			if (synthesize_sdt_probe_arg(&buf, i, args[i]) < 0)
+				goto error;
+		}
+	}
+
+out:
+	ret = strbuf_detach(&buf, NULL);
+error:
+	strbuf_release(&buf);
+	return ret;
+}
+
 int probe_cache__scan_sdt(struct probe_cache *pcache, const char *pathname)
 {
 	struct probe_cache_entry *entry = NULL;
@@ -723,11 +884,12 @@ int probe_cache__scan_sdt(struct probe_cache *pcache, const char *pathname)
 			entry->pev.group = strdup(sdtgrp);
 			list_add_tail(&entry->node, &pcache->entries);
 		}
-		ret = asprintf(&buf, "p:%s/%s %s:0x%llx",
-				sdtgrp, note->name, pathname,
-				sdt_note__get_addr(note));
-		if (ret < 0)
+		buf = synthesize_sdt_probe_command(note, pathname, sdtgrp);
+		if (!buf) {
+			ret = -ENOMEM;
 			break;
+		}
+
 		strlist__add(entry->tevlist, buf);
 		free(buf);
 		entry = NULL;
-- 
2.10.2

  parent reply	other threads:[~2016-12-14  0:12 UTC|newest]

Thread overview: 77+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-11-16 23:55 [PATCH 0/2] perf: add support of SDT probes arguments Alexis Berlemont
2016-11-16 23:56 ` [PATCH 1/2] perf sdt: add scanning of sdt probles arguments Alexis Berlemont
2016-11-16 23:56 ` [PATCH 2/2] perf probe: add sdt probes arguments into the uprobe cmd string Alexis Berlemont
2016-11-17  9:04   ` Hemant Kumar
2016-11-18 23:56     ` [PATCH v2 0/2] " Alexis Berlemont
2016-11-18 23:56     ` [PATCH v2 1/2] perf sdt: add scanning of sdt probles arguments Alexis Berlemont
2016-11-25 14:40       ` Arnaldo Carvalho de Melo
2016-11-26  0:58         ` [PATCH v4 0/2] perf probe: add sdt probes arguments into the uprobe cmd string Alexis Berlemont
2016-12-05 23:42           ` Alexis Berlemont
2016-12-06 14:45             ` Arnaldo Carvalho de Melo
2016-11-26  0:58         ` [PATCH v4 1/2] perf sdt: add scanning of sdt probles arguments Alexis Berlemont
2016-12-07  2:44           ` Masami Hiramatsu
2016-11-26  0:58         ` [PATCH v4 2/2] perf probe: add sdt probes arguments into the uprobe cmd string Alexis Berlemont
2016-12-07  3:26           ` Masami Hiramatsu
2016-12-09 15:14             ` Arnaldo Carvalho de Melo
2016-12-10 10:00               ` Masami Hiramatsu
2016-12-14  0:07             ` [PATCH v5 0/2] " Alexis Berlemont
2016-12-14  7:36               ` Ingo Molnar
2017-01-23 11:23                 ` Ravi Bangoria
2017-02-22 22:41                   ` Alexis Berlemont
2017-01-24  6:58                 ` Ravi Bangoria
2017-01-24  8:22                   ` Ingo Molnar
2017-01-24  8:36                     ` Ravi Bangoria
2017-02-02 11:11               ` [PATCH 0/5] perf/sdt: Argument support for x86 and powepc Ravi Bangoria
2017-02-02 11:11                 ` [PATCH 1/5] perf/sdt: Show proper hint Ravi Bangoria
2017-02-02 13:40                   ` Ingo Molnar
2017-02-02 16:20                     ` Arnaldo Carvalho de Melo
2017-02-03 10:26                       ` [PATCH v2] " Ravi Bangoria
2017-02-03 15:18                         ` Arnaldo Carvalho de Melo
2017-02-07  7:53                           ` Ingo Molnar
2017-02-07 15:50                             ` Arnaldo Carvalho de Melo
2017-02-07  8:00                           ` Ingo Molnar
2017-02-16 10:16                           ` [RFC] perf/sdt: Directly record SDT event with 'perf record' Ravi Bangoria
2017-02-20  7:08                             ` Ingo Molnar
2017-02-20  8:21                               ` Ravi Bangoria
2017-02-20  8:42                                 ` Ingo Molnar
2017-02-20 11:01                                   ` Ravi Bangoria
2017-02-20 14:11                                     ` Arnaldo Carvalho de Melo
2017-02-23  8:13                                       ` Ravi Bangoria
2017-02-23 12:48                                         ` Arnaldo Carvalho de Melo
2017-02-07  1:13                         ` [PATCH v2] perf/sdt: Show proper hint Masami Hiramatsu
2017-02-10  7:44                         ` [tip:perf/core] perf sdt: Show proper hint when event not yet in place via 'perf probe' tip-bot for Ravi Bangoria
2017-02-02 11:11                 ` [PATCH 2/5] perf/sdt/x86: Add renaming logic for rNN and other registers Ravi Bangoria
2017-02-07  3:11                   ` Masami Hiramatsu
2017-03-21 14:08                     ` Arnaldo Carvalho de Melo
2017-03-24 18:45                   ` [tip:perf/core] perf sdt x86: " tip-bot for Ravi Bangoria
2017-02-02 11:11                 ` [PATCH 3/5] perf/sdt/x86: Move OP parser to tools/perf/arch/x86/ Ravi Bangoria
2017-02-07  3:11                   ` Masami Hiramatsu
2017-02-07  5:22                     ` Ravi Bangoria
2017-03-21 14:10                       ` Arnaldo Carvalho de Melo
2017-03-21 23:00                         ` Masami Hiramatsu
2017-03-22 11:22                           ` Arnaldo Carvalho de Melo
2017-03-21 14:55                   ` Masami Hiramatsu
2017-02-02 11:11                 ` [PATCH 4/5] perf/sdt/powerpc: Add argument support Ravi Bangoria
2017-02-02 11:11                 ` [PATCH 5/5] perf/probe: Change MAX_CMDLEN Ravi Bangoria
2017-02-07  1:40                   ` Masami Hiramatsu
2017-02-07  5:45                     ` [PATCH v2] " Ravi Bangoria
2017-03-21  5:19                       ` Masami Hiramatsu
2017-03-21 13:37                         ` Arnaldo Carvalho de Melo
2017-03-24 18:43                       ` [tip:perf/core] perf probe: " tip-bot for Ravi Bangoria
2017-02-07  2:55                 ` [PATCH 0/5] perf/sdt: Argument support for x86 and powepc Masami Hiramatsu
2017-03-06  7:53                   ` Ravi Bangoria
2017-03-06 13:42                     ` Masami Hiramatsu
2017-03-21  5:08               ` [PATCH v5 0/2] perf probe: add sdt probes arguments into the uprobe cmd string Masami Hiramatsu
2016-12-14  0:07             ` [PATCH v5 1/2] perf sdt: add scanning of sdt probles arguments Alexis Berlemont
2017-03-06 13:39               ` Masami Hiramatsu
2017-03-21 13:52                 ` Arnaldo Carvalho de Melo
2017-03-24 18:44               ` [tip:perf/core] perf sdt: Add scanning of sdt probes arguments tip-bot for Alexis Berlemont
2016-12-14  0:07             ` Alexis Berlemont [this message]
2017-01-24  8:50               ` [PATCH v5 2/2] perf probe: add sdt probes arguments into the uprobe cmd string Ravi Bangoria
2017-03-06 17:23               ` Masami Hiramatsu
2017-03-24 18:44               ` [tip:perf/core] perf probe: Add " tip-bot for Alexis Berlemont
2016-11-18 23:56     ` [PATCH v2 2/2] perf probe: add " Alexis Berlemont
2016-11-21 10:25       ` Hemant Kumar
2016-11-24 23:13         ` [PATCH v3 0/2] " Alexis Berlemont
2016-11-24 23:13         ` [PATCH v3 1/2] perf sdt: add scanning of sdt probles arguments Alexis Berlemont
2016-11-24 23:13         ` [PATCH v3 2/2] perf probe: add sdt probes arguments into the uprobe cmd string Alexis Berlemont

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=20161214000732.1710-3-alexis.berlemont@gmail.com \
    --to=alexis.berlemont@gmail.com \
    --cc=acme@kernel.org \
    --cc=alexander.shishkin@linux.intel.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mingo@redhat.com \
    --cc=peterz@infradead.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.